def current_user_get(): """ユーザー情報取得 user info get Returns: Response: HTTP Respose """ app_name = multi_lang.get_text("EP020-0001", "ユーザー情報:") exec_stat = multi_lang.get_text("EP020-0017", "取得") error_detail = "" try: globals.logger.debug('#' * 50) globals.logger.debug('CALL {}'.format( inspect.currentframe().f_code.co_name)) globals.logger.debug('#' * 50) ret_user = user_get() return jsonify({"result": "200", "info": ret_user}), 200 except common.UserException as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail) except Exception as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail)
def get_workspace_members_cdexec(workspace_id): """ワークスペース CD実行メンバー情報取得 workspace cdexec members get Returns: Response: HTTP Respose """ app_name = multi_lang.get_text("EP020-0003", "ワークスペース情報:") exec_stat = multi_lang.get_text("EP020-0018", "CD実行メンバー一覧取得") error_detail = "" try: globals.logger.debug('#' * 50) globals.logger.debug('CALL {}'.format(inspect.currentframe().f_code.co_name)) globals.logger.debug('#' * 50) # 権限「オーナー変更」保有しているユーザーを抽出する # Extract users who have the authority "change owner" rows = api_service_common.get_workspace_members_by_role(workspace_id, const.ROLE_WS_ROLE_CD_EXECUTE[0].format(workspace_id)) return jsonify({"result": "200", "rows": rows}), 200 except common.UserException as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail) except Exception as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail)
def get_ci_pipeline_result_logs(workspace_id, taskrun_name): app_name = "TEKTONタスク実行ログ:" exec_stat = "情報取得" error_detail = "" try: globals.logger.debug('#' * 50) globals.logger.debug('CALL {}'.format(inspect.currentframe().f_code.co_name)) globals.logger.debug('#' * 50) # Get Query Parameter latest = request.args.get('latest', default='False') # ヘッダ情報 post_headers = { 'Content-Type': 'application/json', } # epoch-control-tekton-api の呼び先設定 api_url_tekton = "{}://{}:{}/workspace/{}/tekton/taskrun/{}/logs".format( os.environ["EPOCH_CONTROL_TEKTON_PROTOCOL"], os.environ["EPOCH_CONTROL_TEKTON_HOST"], os.environ["EPOCH_CONTROL_TEKTON_PORT"], workspace_id, taskrun_name) # TEKTONタスク実行ログ情報取得 exec_stat = "taskrunログ情報取得" request_response = requests.get(api_url_tekton, params={"latest": latest}) ret = json.loads(request_response.text) if request_response.status_code != 200: if "errorDetail" in ret: error_detail = ret["errorDetail"] else: error_detail = "" raise common.UserException(error_detail) ret_status = 200 response = { "result": ret_status, "log" : ret["log"], } # 戻り値をそのまま返却 return jsonify(response), ret_status except common.UserException as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail) except Exception as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail)
def get_users(): """ユーザー情報一覧取得 user info list get Returns: Response: HTTP Respose """ app_name = multi_lang.get_text("EP020-0001", "ユーザー情報:") exec_stat = multi_lang.get_text("EP020-0002", "一覧取得") error_detail = "" try: globals.logger.debug('#' * 50) globals.logger.debug('CALL {}'.format(inspect.currentframe().f_code.co_name)) globals.logger.debug('#' * 50) api_url = "{}://{}:{}/{}/user".format(os.environ['EPOCH_EPAI_API_PROTOCOL'], os.environ['EPOCH_EPAI_API_HOST'], os.environ['EPOCH_EPAI_API_PORT'], os.environ["EPOCH_EPAI_REALM_NAME"], ) # # get users - ユーザー取得 # response = requests.get(api_url) if response.status_code != 200 and response.status_code != 404: error_detail = multi_lang.get_text("EP020-0008", "ユーザー情報の取得に失敗しました") raise common.UserException("{} Error user get status:{}".format(inspect.currentframe().f_code.co_name, response.status_code)) users = json.loads(response.text) # globals.logger.debug(f"users:{users}") ret_users = [] for user in users["rows"]: ret_user = { "user_id": user["id"], "username": user["username"], } ret_users.append(ret_user) rows = ret_users return jsonify({"result": "200", "rows": rows}), 200 except common.UserException as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail) except Exception as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail)
def get_repositories(registry): app_name = "ワークスペース情報:" exec_stat = "DockerHub container images取得" error_detail = "" try: globals.logger.debug('#' * 50) globals.logger.debug('CALL {}'.format(inspect.currentframe().f_code.co_name)) globals.logger.debug('#' * 50) # Get Dockerhub TOKEN token = get_token(request.headers["username"], request.headers["password"]) if token is None: return jsonify({"result": "401"}), 401 # Dockerhub Request parameters api_headers = { 'Authorization': 'Bearer {}'.format(token), } api_url = api_base_url + api_path["get_tags"].format(registry) rows = [] while True: globals.logger.debug('CALL {}'.format(api_url)) api_response = requests.get( api_url, headers=api_headers) if api_response.status_code != 200: return jsonify({"result": api_response.status_code}), api_response.status_code api_response_json = json.loads(api_response.text) for result in api_response_json["results"]: row = { "name": registry, "url": link_url.format(registry), "tag": result["name"], "tag_last_pushed": result["tag_last_pushed"], "full_size": result["full_size"] } rows.append(row) if api_response_json["next"] is None: break else: api_url = api_response_json["next"] return jsonify({"result": 200, "rows": rows}), 200 except common.UserException as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail) except Exception as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail)
def get_cd_operations(workspace_id): """get cd-operations list Returns: Response: HTTP Respose """ app_name = "ワークスペース情報:" exec_stat = "Operation情報取得" error_detail = "" try: globals.logger.debug('#' * 50) globals.logger.debug('CALL {}'.format( inspect.currentframe().f_code.co_name)) globals.logger.debug('#' * 50) # ワークスペースアクセス情報取得 access_info = api_access_info.get_access_info(workspace_id) # namespaceの取得 namespace = common.get_namespace_name(workspace_id) ita_restapi_endpoint = "http://{}.{}.svc:{}/default/menu/07_rest_api_ver1.php".format( EPOCH_ITA_HOST, namespace, EPOCH_ITA_PORT) ita_user = access_info['ITA_USER'] ita_pass = access_info['ITA_PASSWORD'] # HTTPヘッダの生成 filter_headers = { 'host': EPOCH_ITA_HOST + ':' + EPOCH_ITA_PORT, 'Content-Type': 'application/json', 'Authorization': base64.b64encode( (ita_user + ':' + ita_pass).encode()), 'X-Command': 'FILTER', } # # オペレーションの取得 # opelist_resp = requests.post(ita_restapi_endpoint + '?no=' + ite_menu_operation, headers=filter_headers) globals.logger.debug('---- Operation ----') globals.logger.debug(opelist_resp.text) if common.is_json_format(opelist_resp.text): opelist_json = json.loads(opelist_resp.text) else: error_detail = "Operation情報取得失敗" raise common.UserException(error_detail) rows = opelist_json # 正常終了 ret_status = 200 # 戻り値をそのまま返却 return jsonify({"result": ret_status, "rows": rows}), ret_status except common.UserException as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail) except Exception as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail)
def create_github_webhooks(workspace_id): """webhooks 設定 Args: workspace_id (int): ワークスペースID Returns: Response: HTTP Respose """ app_name = "ワークスペース情報:" exec_stat = "GitHub WebHooks設定" error_detail = "" apache_path = '/api/listener/{}'.format(workspace_id) try: globals.logger.debug('#' * 50) globals.logger.debug('CALL {}'.format( inspect.currentframe().f_code.co_name)) globals.logger.debug('#' * 50) # 引数で指定されたCD環境を取得 request_json = json.loads(request.data) request_ci_confg = request_json["ci_config"] # パイプライン数分繰り返し for pipeline in request_ci_confg["pipelines"]: git_repos = re.sub( '\\.git$', '', re.sub('^https?://[^/][^/]*/', '', pipeline["git_repositry"]["url"])) web_hooks_url = pipeline["webhooks_url"] + ':' + os.environ[ 'EPOCH_WEBHOOK_PORT'] + apache_path token = request_ci_confg["pipelines_common"]["git_repositry"][ "token"] # GitHubへPOST送信 # ヘッダ情報 post_headers = { 'Authorization': 'token ' + token, 'Accept': 'application/vnd.github.v3+json', } # 引数をJSON形式で構築 post_data = json.dumps({ "config": { "url": web_hooks_url, "content_type": "json", "secret": "", "insecure_ssl": "1", "token": "token", "digest": "digest", } }) # hooksのPOST送信 globals.logger.debug('- github.webhooks setting to git') globals.logger.debug('- https_proxy:{}, http_proxy:{}'.format( os.environ['HTTPS_PROXY'], os.environ['HTTP_PROXY'])) globals.logger.debug('- request URL:' + github_webhook_base_url + git_repos + github_webhook_base_hooks) globals.logger.debug('- webhook URL :' + web_hooks_url) request_response = requests.post(github_webhook_base_url + git_repos + github_webhook_base_hooks, headers=post_headers, data=post_data) globals.logger.debug('- response headers') globals.logger.debug(request_response.headers) globals.logger.debug('- response body') globals.logger.debug(request_response.text) # 成功(201) または、Webhook URLの重複(422)のステータスコードが返ってきた場合、コード200を返し後続の処理を実行する if request_response.status_code == 201 or request_response.status_code == 422: ret_status = 200 # 戻り値をそのまま返却 return jsonify({"result": ret_status}), ret_status except common.UserException as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail) except Exception as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail)
def create_ita(workspace_id): """IT-Automation Pod Create Args: workspace_id (int): workspace id Returns: Response: HTTP Respose """ app_name = "ワークスペース情報:" exec_stat = "IT-Automation環境構築" error_detail = "" try: globals.logger.debug('#' * 50) globals.logger.debug('CALL {}'.format( inspect.currentframe().f_code.co_name)) globals.logger.debug('#' * 50) # namespace定義 name = common.get_namespace_name(workspace_id) globals.logger.debug("ita-pod create start") # templateの展開 with tempfile.TemporaryDirectory() as tempdir: file_name = 'ita_install.yaml' yaml_param = { "HTTP_PROXY": os.environ.get("EPOCH_HTTP_PROXY"), "HTTPS_PROXY": os.environ.get("EPOCH_HTTPS_PROXY"), "NO_PROXY": os.environ.get("EPOCH_HOSTNAME"), } yaml_text = render_template(file_name, param=yaml_param) # yaml一時ファイル生成 path_yamlfile = '{}/{}'.format(tempdir, file_name) with open(path_yamlfile, mode='w') as fp: fp.write(yaml_text) # kubectl実行 try: result_kubectl = subprocess.check_output( ['kubectl', 'apply', '-f', path_yamlfile, '-n', name], stderr=subprocess.STDOUT) globals.logger.debug( 'COMMAAND SUCCEED: kubectl apply -f {}\n{}'.format( path_yamlfile, result_kubectl.decode('utf-8'))) except subprocess.CalledProcessError as e: globals.logger.error('COMMAND ERROR RETURN:{}\n{}'.format( e.returncode, e.output.decode('utf-8'))) exec_detail = "IT-AutomationのPodが生成できません。環境を確認してください。" raise common.UserException(exec_detail) except Exception: raise # 対象となるdeploymentを定義 # deployments = [ "deployment/ita-worker" ] # envs = [ # "HTTP_PROXY=" + os.environ['EPOCH_HTTP_PROXY'], # "HTTPS_PROXY=" + os.environ['EPOCH_HTTPS_PROXY'], # "http_proxy=" + os.environ['EPOCH_HTTP_PROXY'], # "https_proxy=" + os.environ['EPOCH_HTTPS_PROXY'] # ] # exec_detail = "環境変数[PROXY]を確認してください" # for deployment_name in deployments: # for env_name in envs: # # 環境変数の設定 # try: # result_kubectl = subprocess.check_output(["kubectl","set","env",deployment_name,"-n",name,env_name],stderr=subprocess.STDOUT) # globals.logger.debug('COMMAAND SUCCEED: kubectl set env {}\n{}'.format(deployment_name, result_kubectl.decode('utf-8'))) # except subprocess.CalledProcessError as e: # globals.logger.error('COMMAND ERROR RETURN:{}\n{}'.format(e.returncode, e.output.decode('utf-8'))) # exec_detail = "{}の環境変数[PROXY]の設定ができません。環境を確認してください。".format(deployment_name) # raise common.UserException(exec_detail) # except Exception: # raise exec_detail = "" # 正常終了 ret_status = 200 # 戻り値をそのまま返却 return jsonify({"result": ret_status}), ret_status except common.UserException as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail) except Exception as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail)
def post_manifest_parameter(workspace_id): """manifest パラメータ登録 manifest parameter registration Args: workspace_id (int): workspace ID Returns: Response: HTTP Respose """ app_name = "ワークスペース情報:" exec_stat = "manifestパラメータ登録" error_detail = "" try: globals.logger.debug('#' * 50) globals.logger.debug('CALL {}'.format( inspect.currentframe().f_code.co_name)) globals.logger.debug('#' * 50) # ヘッダ情報 post header info. post_headers = { 'Content-Type': 'application/json', } # 引数をJSON形式で受け取りそのまま引数に設定 Receive the argument in JSON format and set it as it is post_data = request.json.copy() # send put (workspace data update) apiInfo = "{}://{}:{}".format( os.environ['EPOCH_RS_WORKSPACE_PROTOCOL'], os.environ['EPOCH_RS_WORKSPACE_HOST'], os.environ['EPOCH_RS_WORKSPACE_PORT']) globals.logger.debug( "workspace put call: worksapce_id:{}".format(workspace_id)) request_response = requests.put( "{}/workspace/{}/manifestParameter".format(apiInfo, workspace_id), headers=post_headers, data=json.dumps(post_data)) # エラーの際は処理しない if request_response.status_code != 200: globals.logger.error("call rs workspace error:{}".format( request_response.status_code)) error_detail = "ワークスペース情報更新失敗" raise common.UserException(error_detail) # ヘッダ情報 post_headers = { 'Content-Type': 'application/json', } # 引数をJSON形式で受け取りそのまま引数に設定 Receive the argument in JSON format and set it as it is post_data = request.json.copy() # 呼び出すapiInfoは、環境変数より取得 apiInfo = "{}://{}:{}".format(os.environ["EPOCH_CONTROL_ITA_PROTOCOL"], os.environ["EPOCH_CONTROL_ITA_HOST"], os.environ["EPOCH_CONTROL_ITA_PORT"]) globals.logger.debug("apiInfo:" + apiInfo) # Manifestパラメータ設定(ITA) globals.logger.debug( "ita/manifestParameter post call: worksapce_id:{}".format( workspace_id)) request_response = requests.post( "{}/workspace/{}/it-automation/manifest/parameter".format( apiInfo, workspace_id), headers=post_headers, data=json.dumps(post_data)) # globals.logger.debug("ita/manifestParameter:response:" + request_response.text.encode().decode('unicode-escape')) ret = json.loads(request_response.text) #ret = request_response.text # globals.logger.debug(ret["result"]) if request_response.status_code != 200: globals.logger.error("call ita/manifestParameter error:{}".format( request_response.status_code)) error_detail = "IT-Automation パラメータ登録失敗" raise common.UserException(error_detail) # 正常終了 normal return code ret_status = 200 return jsonify({"result": ret_status}), ret_status except common.UserException as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail) except Exception as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail)
def get_manifest_template_list(workspace_id): """manifest テンプレート登録 manifest template registration Args: workspace_id (int): workspace ID Returns: Response: HTTP Respose """ app_name = "ワークスペース情報:" exec_stat = "manifestテンプレート取得" error_detail = "" try: globals.logger.debug('#' * 50) globals.logger.debug('CALL {}'.format( inspect.currentframe().f_code.co_name)) globals.logger.debug('#' * 50) resourceProtocol = os.environ['EPOCH_RS_WORKSPACE_PROTOCOL'] resourceHost = os.environ['EPOCH_RS_WORKSPACE_HOST'] resourcePort = os.environ['EPOCH_RS_WORKSPACE_PORT'] apiurl = "{}://{}:{}/workspace/{}/manifests".format( resourceProtocol, resourceHost, resourcePort, workspace_id) # ヘッダ情報 headers = { 'Content-Type': 'application/json', } # GET送信(作成) response = requests.get(apiurl, headers=headers) globals.logger.debug("get_manifests return --------------------") globals.logger.debug(json.loads(response.text)) globals.logger.debug("--------------------") if response.status_code == 200 and common.is_json_format( response.text): # 200(正常)かつ、レスポンスデータがJSON形式の場合は、後続の処理を実行 pass elif response.status_code == 404: error_detail = 'manifest template data not found' raise common.UserException(error_detail) elif response.status_code != 200: # 200(正常), 404(not found) 以外の応答の場合 error_detail = 'CALL responseAPI Error' raise common.UserException(error_detail) ret_manifests = json.loads(response.text) rows = ret_manifests["rows"] # 正常終了 normal return code ret_status = 200 return jsonify({"result": ret_status, "rows": rows}), ret_status except common.UserException as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail) except Exception as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail)
def settings_manifest_parameter(workspace_id): """manifest parameter setting Returns: Response: HTTP Respose """ app_name = "ワークスペース情報:" exec_stat = "実行環境取得" error_detail = "" try: globals.logger.debug('#' * 50) globals.logger.debug('CALL {}'.format( inspect.currentframe().f_code.co_name)) globals.logger.debug('#' * 50) # パラメータ情報(JSON形式) prameter save payload = request.json.copy() # ワークスペースアクセス情報取得 access_info = api_access_info.get_access_info(workspace_id) # namespaceの取得 namespace = common.get_namespace_name(workspace_id) ita_restapi_endpoint = "http://{}.{}.svc:{}/default/menu/07_rest_api_ver1.php".format( EPOCH_ITA_HOST, namespace, EPOCH_ITA_PORT) ita_user = access_info['ITA_USER'] ita_pass = access_info['ITA_PASSWORD'] # HTTPヘッダの生成 filter_headers = { 'host': EPOCH_ITA_HOST + ':' + EPOCH_ITA_PORT, 'Content-Type': 'application/json', 'Authorization': base64.b64encode( (ita_user + ':' + ita_pass).encode()), 'X-Command': 'FILTER', } edit_headers = { 'host': EPOCH_ITA_HOST + ':' + EPOCH_ITA_PORT, 'Content-Type': 'application/json', 'Authorization': base64.b64encode( (ita_user + ':' + ita_pass).encode()), 'X-Command': 'EDIT', } # globals.logger.debug(payload) # # オペレーションの取得 # opelist_resp = requests.post(ita_restapi_endpoint + '?no=' + ite_menu_operation, headers=filter_headers) opelist_json = json.loads(opelist_resp.text) globals.logger.debug('---- Operation ----') # logger.debug(opelist_resp.text) # logger.debug(opelist_json) # 項目位置の取得 column_indexes_opelist = column_indexes( column_names_opelist, opelist_json['resultdata']['CONTENTS']['BODY'][0]) globals.logger.debug('---- Operation Index ----') # logger.debug(column_indexes_opelist) # # マニフェスト環境パラメータの取得 # content = {"1": {"NORMAL": "0"}} maniparam_resp = requests.post(ita_restapi_endpoint + '?no=' + ita_menu_manifest_param, headers=filter_headers, data=json.dumps(content)) maniparam_json = json.loads(maniparam_resp.text) globals.logger.debug('---- Current Manifest Parameters ----') # logger.debug(maniparam_resp.text) globals.logger.debug(maniparam_json) # 項目位置の取得 column_indexes_maniparam = column_indexes( column_names_manifest_param, maniparam_json['resultdata']['CONTENTS']['BODY'][0]) globals.logger.debug('---- Manifest Parameters Index ----') # logger.debug(column_indexes_maniparam) # Responseデータの初期化 response = { "result": "200", } globals.logger.debug("opelist:{}".format( opelist_json['resultdata']['CONTENTS']['BODY'])) # マニフェスト環境パラメータのデータ成型 maniparam_edit = [] for environment in payload['ci_config']['environments']: idx_ope = -1 # cd_configの同一環境情報からgit_urlを取得する Get git_url from the same environment information in cd_config for cd_environment in payload['cd_config']['environments']: if environment['environment_id'] == cd_environment[ 'environment_id']: globals.logger.debug("git_url:{}".format( cd_environment['git_repositry']['url'])) idx_ope = search_opration( opelist_json['resultdata']['CONTENTS']['BODY'], column_indexes_opelist, cd_environment['git_repositry']['url']) # ITAからオペレーション(=環境)が取得できなければ異常 if idx_ope == -1: error_detail = "CD環境が設定されていません。" raise common.UserException(error_detail) req_maniparam_operation_id = opelist_json['resultdata'][ 'CONTENTS']['BODY'][idx_ope][ column_indexes_common['record_no']] for idx_manifile, row_manifile in enumerate( environment['manifests']): image = None image_tag = None param01 = None param02 = None param03 = None param04 = None param05 = None param06 = None param07 = None param08 = None param09 = None param10 = None param11 = None param12 = None param13 = None param14 = None param15 = None param16 = None param17 = None param18 = None param19 = None param20 = None # parameters成型 for key, value in row_manifile['parameters'].items(): if key == 'image': image = value elif key == 'image_tag': image_tag = value elif key == 'param01': param01 = value elif key == 'param02': param02 = value elif key == 'param03': param03 = value elif key == 'param04': param04 = value elif key == 'param05': param05 = value elif key == 'param06': param06 = value elif key == 'param07': param07 = value elif key == 'param08': param08 = value elif key == 'param09': param09 = value elif key == 'param10': param10 = value elif key == 'param11': param11 = value elif key == 'param12': param12 = value elif key == 'param13': param13 = value elif key == 'param14': param14 = value elif key == 'param15': param15 = value elif key == 'param16': param16 = value elif key == 'param17': param17 = value elif key == 'param18': param18 = value elif key == 'param19': param19 = value elif key == 'param20': param20 = value # 既存データ確認 maniparam_id = -1 for idx_maniparam, row_maniparam in enumerate( maniparam_json['resultdata']['CONTENTS']['BODY']): current_maniparam_operation_id = row_maniparam[ column_indexes_maniparam['operation_id']] current_maniparam_include_index = row_maniparam[ column_indexes_maniparam['indexes']] if current_maniparam_operation_id == req_maniparam_operation_id and \ current_maniparam_include_index == str(idx_manifile + 1): maniparam_id = row_maniparam[ column_indexes_common['record_no']] break if maniparam_id == -1: # 追加処理データの設定 maniparam_edit.append({ str(column_indexes_common['method']): param_value_method_entry, str(column_indexes_maniparam['host']): param_value_host, str(column_indexes_maniparam['operation']): format_opration_info( opelist_json['resultdata']['CONTENTS']['BODY'] [idx_ope], column_indexes_opelist), str(column_indexes_maniparam['indexes']): idx_manifile + 1, str(column_indexes_maniparam['image']): image, str(column_indexes_maniparam['image_tag']): image_tag, str(column_indexes_maniparam['param01']): param01, str(column_indexes_maniparam['param02']): param02, str(column_indexes_maniparam['param03']): param03, str(column_indexes_maniparam['param04']): param04, str(column_indexes_maniparam['param05']): param05, str(column_indexes_maniparam['param06']): param06, str(column_indexes_maniparam['param07']): param07, str(column_indexes_maniparam['param08']): param08, str(column_indexes_maniparam['param09']): param09, str(column_indexes_maniparam['param10']): param10, str(column_indexes_maniparam['param11']): param11, str(column_indexes_maniparam['param12']): param12, str(column_indexes_maniparam['param13']): param13, str(column_indexes_maniparam['param14']): param14, str(column_indexes_maniparam['param15']): param15, str(column_indexes_maniparam['param16']): param16, str(column_indexes_maniparam['param17']): param17, str(column_indexes_maniparam['param18']): param18, str(column_indexes_maniparam['param19']): param19, str(column_indexes_maniparam['param20']): param20, str(column_indexes_maniparam['template_name']): '"{{ TPF_epoch_template_yaml' + str(idx_manifile + 1) + ' }}"', }) globals.logger.debug( '---- Manifest Parameters Item(Add) ----') globals.logger.debug(maniparam_edit[len(maniparam_edit) - 1]) else: # 更新処理 maniparam_edit.append({ str(column_indexes_common['method']): param_value_method_update, str(column_indexes_common['record_no']): maniparam_id, str(column_indexes_maniparam['host']): maniparam_json['resultdata']['CONTENTS']['BODY'] [idx_maniparam][column_indexes_maniparam['host']], str(column_indexes_maniparam['operation']): maniparam_json['resultdata']['CONTENTS']['BODY'] [idx_maniparam][column_indexes_maniparam['operation']], str(column_indexes_maniparam['indexes']): maniparam_json['resultdata']['CONTENTS']['BODY'] [idx_maniparam][column_indexes_maniparam['indexes']], str(column_indexes_maniparam['image']): image, str(column_indexes_maniparam['image_tag']): image_tag, str(column_indexes_maniparam['param01']): param01, str(column_indexes_maniparam['param02']): param02, str(column_indexes_maniparam['param03']): param03, str(column_indexes_maniparam['param04']): param04, str(column_indexes_maniparam['param05']): param05, str(column_indexes_maniparam['param06']): param06, str(column_indexes_maniparam['param07']): param07, str(column_indexes_maniparam['param08']): param08, str(column_indexes_maniparam['param09']): param09, str(column_indexes_maniparam['param10']): param10, str(column_indexes_maniparam['param11']): param11, str(column_indexes_maniparam['param12']): param12, str(column_indexes_maniparam['param13']): param13, str(column_indexes_maniparam['param14']): param14, str(column_indexes_maniparam['param15']): param15, str(column_indexes_maniparam['param16']): param16, str(column_indexes_maniparam['param17']): param17, str(column_indexes_maniparam['param18']): param18, str(column_indexes_maniparam['param19']): param19, str(column_indexes_maniparam['param20']): param20, str(column_indexes_maniparam['template_name']): maniparam_json['resultdata']['CONTENTS']['BODY'] [idx_maniparam][ column_indexes_maniparam['template_name']], str(column_indexes_maniparam['lastupdate']): maniparam_json['resultdata']['CONTENTS']['BODY'] [idx_maniparam][ column_indexes_maniparam['lastupdate']], }) globals.logger.debug( '---- Manifest Parameters Item(Update) ----') globals.logger.debug(maniparam_edit[len(maniparam_edit) - 1]) globals.logger.debug('---- Deleting Manifest Parameters Setting ----') # 既存データをすべて廃止する for idx_maniparam, row_maniparam in enumerate( maniparam_json['resultdata']['CONTENTS']['BODY']): # 1行目無視する if idx_maniparam == 0: continue flgExists = False for idx_edit, row_edit in enumerate(maniparam_edit): # 該当するrecord_noがあれば、チェックする if str(column_indexes_common['record_no']) in row_edit: if row_edit[str( column_indexes_common['record_no'] )] == row_maniparam[column_indexes_common['record_no']]: flgExists = True break # 該当するレコードがない場合は、廃止として追加する if not flgExists: # 削除用のデータ設定 maniparam_edit.append({ str(column_indexes_common['method']): param_value_method_delete, str(column_indexes_common['record_no']): row_maniparam[column_indexes_common['record_no']], str(column_indexes_maniparam['lastupdate']): row_maniparam[column_indexes_maniparam['lastupdate']], }) globals.logger.debug('---- Updating Manifest Parameters ----') # globals.logger.debug(json.dumps(maniparam_edit)) manuparam_edit_resp = requests.post(ita_restapi_endpoint + '?no=' + ita_menu_manifest_param, headers=edit_headers, data=json.dumps(maniparam_edit)) maniparam_json = json.loads(manuparam_edit_resp.text) globals.logger.debug('---- Manifest Parameters Post Response ----') # logger.debug(manuparam_edit_resp.text) # globals.logger.debug(maniparam_json) if maniparam_json["status"] != "SUCCEED" or maniparam_json[ "resultdata"]["LIST"]["NORMAL"]["error"]["ct"] != 0: raise common.UserException( manuparam_edit_resp.text.encode().decode('unicode-escape')) # 正常終了 ret_status = 200 # 戻り値をそのまま返却 return jsonify({"result": ret_status}), ret_status except common.UserException as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail) except Exception as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail)
def settings_git_environment(workspace_id): """git environment setting Args: workspace_id (int): workspace ID Returns: Response: HTTP Respose """ app_name = "ワークスペース情報:" exec_stat = "IT-Automation git情報設定" error_detail = "" try: globals.logger.debug('#' * 50) globals.logger.debug('CALL {}'.format( inspect.currentframe().f_code.co_name)) globals.logger.debug('#' * 50) # パラメータ情報(JSON形式) prameter save payload = request.json.copy() # ワークスペースアクセス情報取得 access_info = api_access_info.get_access_info(workspace_id) # namespaceの取得 namespace = common.get_namespace_name(workspace_id) ita_restapi_endpoint = "http://{}.{}.svc:{}/default/menu/07_rest_api_ver1.php".format( EPOCH_ITA_HOST, namespace, EPOCH_ITA_PORT) ita_user = access_info['ITA_USER'] ita_pass = access_info['ITA_PASSWORD'] # HTTPヘッダの生成 filter_headers = { 'host': EPOCH_ITA_HOST + ':' + EPOCH_ITA_PORT, 'Content-Type': 'application/json', 'Authorization': base64.b64encode( (ita_user + ':' + ita_pass).encode()), 'X-Command': 'FILTER', } edit_headers = { 'host': EPOCH_ITA_HOST + ':' + EPOCH_ITA_PORT, 'Content-Type': 'application/json', 'Authorization': base64.b64encode( (ita_user + ':' + ita_pass).encode()), 'X-Command': 'EDIT', } # # オペレーションの取得 # opelist_resp = requests.post(ita_restapi_endpoint + '?no=' + ite_menu_operation, headers=filter_headers) opelist_json = json.loads(opelist_resp.text) globals.logger.debug('---- Operation ----') #logger.debug(opelist_resp.text.encode().decode('unicode-escape')) # globals.logger.debug(opelist_resp.text) # 項目位置の取得 column_indexes_opelist = column_indexes( column_names_opelist, opelist_json['resultdata']['CONTENTS']['BODY'][0]) globals.logger.debug('---- Operation Index ----') # globals.logger.debug(column_indexes_opelist) # # オペレーションの追加処理 # opelist_edit = [] for idx_req, row_req in enumerate( payload['cd_config']['environments']): if search_opration(opelist_json['resultdata']['CONTENTS']['BODY'], column_indexes_opelist, row_req['git_repositry']['url']) == -1: # オペレーションになければ、追加データを設定 opelist_edit.append({ str(column_indexes_common['method']): param_value_method_entry, str(column_indexes_opelist['operation_name']): param_value_operation_name_prefix + row_req['git_repositry']['url'], str(column_indexes_opelist['operation_date']): param_value_operation_date, str(column_indexes_opelist['remarks']): row_req['git_repositry']['url'], }) if len(opelist_edit) > 0: # # オペレーションの追加がある場合 # ope_add_resp = requests.post(ita_restapi_endpoint + '?no=' + ite_menu_operation, headers=edit_headers, data=json.dumps(opelist_edit)) globals.logger.debug('---- ope_add_resp ----') #logger.debug(ope_add_resp.text.encode().decode('unicode-escape')) globals.logger.debug(ope_add_resp.text) # 追加後再取得(オペレーションIDが決定する) opelist_resp = requests.post(ita_restapi_endpoint + '?no=' + ite_menu_operation, headers=filter_headers) opelist_json = json.loads(opelist_resp.text) globals.logger.debug('---- Operation ----') #logger.debug(opelist_resp.text.encode().decode('unicode-escape')) # # Git環境情報の取得 # gitlist_resp = requests.post(ita_restapi_endpoint + '?no=' + ita_menu_gitenv_param, headers=filter_headers) gitlist_json = json.loads(gitlist_resp.text) globals.logger.debug('---- Git Environments ----') #logger.debug(gitlist_resp.text.encode().decode('unicode-escape')) #logger.debug(gitlist_resp.text) # 項目位置の取得 column_indexes_gitlist = column_indexes( column_names_gitlist, gitlist_json['resultdata']['CONTENTS']['BODY'][0]) globals.logger.debug('---- Git Environments Index ----') # logger.debug(column_indexes_gitlist) # Responseデータの初期化 response = {"items": []} # Git環境情報の追加・更新 gitlist_edit = [] for idx_req, row_req in enumerate( payload['cd_config']['environments']): idx_git = search_gitlist( gitlist_json['resultdata']['CONTENTS']['BODY'], column_indexes_gitlist, row_req['git_repositry']['url']) if idx_git == -1: # リストになければ、追加データを設定 # 追加対象のURLのオペレーション idx_ope = search_opration( opelist_json['resultdata']['CONTENTS']['BODY'], column_indexes_opelist, row_req['git_repositry']['url']) # 追加処理データの設定 gitlist_edit.append({ str(column_indexes_common['method']): param_value_method_entry, str(column_indexes_gitlist['host']): param_value_host, str(column_indexes_gitlist['operation_id']): opelist_json['resultdata']['CONTENTS']['BODY'][idx_ope][ column_indexes_opelist['operation_id']], str(column_indexes_gitlist['operation']): format_opration_info( opelist_json['resultdata']['CONTENTS']['BODY'] [idx_ope], column_indexes_opelist), str(column_indexes_gitlist['git_url']): row_req['git_repositry']['url'], str(column_indexes_gitlist['git_user']): payload['cd_config']['environments_common'] ['git_repositry']['user'], str(column_indexes_gitlist['git_password']): payload['cd_config']['environments_common'] ['git_repositry']['token'], }) # レスポンスデータの設定 response["items"].append({ 'operation_id': opelist_json['resultdata']['CONTENTS']['BODY'][idx_ope][ column_indexes_opelist['operation_id']], 'git_url': row_req['git_repositry']['url'], 'git_user': payload['cd_config']['environments_common'] ['git_repositry']['user'], 'git_password': payload['cd_config']['environments_common'] ['git_repositry']['token'], }) else: # リストにあれば、更新データを設定 gitlist_edit.append({ str(column_indexes_common['method']): param_value_method_update, str(column_indexes_common['record_no']): gitlist_json['resultdata']['CONTENTS']['BODY'][idx_git][ column_indexes_common['record_no']], str(column_indexes_gitlist['host']): gitlist_json['resultdata']['CONTENTS']['BODY'][idx_git][ column_indexes_gitlist['host']], str(column_indexes_gitlist['operation']): gitlist_json['resultdata']['CONTENTS']['BODY'][idx_git][ column_indexes_gitlist['operation']], str(column_indexes_gitlist['git_url']): row_req['git_repositry']['url'], str(column_indexes_gitlist['git_user']): payload['cd_config']['environments_common'] ['git_repositry']['user'], str(column_indexes_gitlist['git_password']): payload['cd_config']['environments_common'] ['git_repositry']['token'], str(column_indexes_gitlist['lastupdate']): gitlist_json['resultdata']['CONTENTS']['BODY'][idx_git][ column_indexes_gitlist['lastupdate']], }) # レスポンスデータの設定 response["items"].append({ 'operation_id': gitlist_json['resultdata']['CONTENTS']['BODY'][idx_git][ column_indexes_gitlist['operation_id']], 'git_url': row_req['git_repositry']['url'], 'git_user': payload['cd_config']['environments_common'] ['git_repositry']['user'], 'git_password': payload['cd_config']['environments_common'] ['git_repositry']['token'], }) globals.logger.debug('---- Git Environments Post ----') #logger.debug(json.dumps(gitlist_edit).encode().decode('unicode-escape')) # logger.debug(json.dumps(gitlist_edit)) gitlist_edit_resp = requests.post(ita_restapi_endpoint + '?no=' + ita_menu_gitenv_param, headers=edit_headers, data=json.dumps(gitlist_edit)) globals.logger.debug('---- Git Environments Post Response ----') #logger.debug(gitlist_edit_resp.text.encode().decode('unicode-escape')) # globals.logger.debug(gitlist_edit_resp.text) # 正常終了 ret_status = 200 # 戻り値をそのまま返却 return jsonify({ "result": ret_status, "rows": response["items"] }), ret_status except common.UserException as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail) except Exception as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail)
def get_workspace_members(workspace_id): """ワークスペース該当メンバー情報取得 workspace members get Returns: Response: HTTP Respose """ app_name = multi_lang.get_text("EP020-0003", "ワークスペース情報:") exec_stat = multi_lang.get_text("EP020-0004", "メンバー一覧取得") error_detail = "" try: globals.logger.debug('#' * 50) globals.logger.debug('CALL {}'.format(inspect.currentframe().f_code.co_name)) globals.logger.debug('#' * 50) roles = const.ALL_ROLES stock_user_id = [] ret_users = [] for role in roles: # workspace 参照権限のあるユーザーをすべて取得する Get all users with read permission # 子のロールでは取得できないので割り当てたロールで取得する # Since it cannot be acquired by the child role, it is acquired by the assigned role. api_url = "{}://{}:{}/{}/client/epoch-system/roles/{}/users".format(os.environ['EPOCH_EPAI_API_PROTOCOL'], os.environ['EPOCH_EPAI_API_HOST'], os.environ['EPOCH_EPAI_API_PORT'], os.environ["EPOCH_EPAI_REALM_NAME"], role.format(workspace_id) ) # # get users - ユーザー取得 # response = requests.get(api_url) if response.status_code != 200 and response.status_code != 404: error_detail = multi_lang.get_text("EP020-0008", "ユーザー情報の取得に失敗しました") raise common.UserException("{} Error user get status:{}".format(inspect.currentframe().f_code.co_name, response.status_code)) users = json.loads(response.text) # globals.logger.debug(f"users:{users}") for user in users["rows"]: # すでに同じユーザーがいた場合は処理しない If the same user already exists, it will not be processed # if len(stock_user_id) > 0: if user["user_id"] in stock_user_id: continue # 取得したユーザーのロールを取得 Get the role of the acquired user api_url = "{}://{}:{}/{}/user/{}/roles/epoch-system".format(os.environ['EPOCH_EPAI_API_PROTOCOL'], os.environ['EPOCH_EPAI_API_HOST'], os.environ['EPOCH_EPAI_API_PORT'], os.environ["EPOCH_EPAI_REALM_NAME"], user["user_id"] ) # # get user role - ユーザーロール情報取得 # response = requests.get(api_url) if response.status_code != 200: error_detail = multi_lang.get_text("EP020-0009", "ユーザーロール情報の取得に失敗しました") raise common.UserException("{} Error user role get status:{}".format(inspect.currentframe().f_code.co_name, response.status_code)) ret_roles = json.loads(response.text) # globals.logger.debug(f"roles:{ret_roles}") set_role_kind = [] # 取得したすべてのロールから絞り込む Narrow down from all acquired roles for get_role in ret_roles["rows"]: kind = common.get_role_kind(get_role["name"]) # 該当のロールのみチェック Check only the corresponding role if kind is not None: ex_role = re.match("ws-({}|\d+)-(.+)", get_role["name"]) globals.logger.debug("role_workspace_id:{} kind:{}".format(ex_role[1], ex_role[2])) # 該当のワークスペースのみの絞り込み Narrow down only the applicable workspace if ex_role[1] == str(workspace_id): set_role_kind.append( { "kind" : kind } ) ret_user = { "user_id": user["user_id"], "username": user["user_name"], "roles": set_role_kind } ret_users.append(ret_user) stock_user_id.append(user["user_id"]) # globals.logger.debug(f"users:{ret_users}") rows = ret_users return jsonify({"result": "200", "rows": rows}), 200 except common.UserException as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail) except Exception as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail)
def leave_workspace(workspace_id): """Exit from a member of the workspace - ワークスペースのメンバーから抜けます Args: workspace_id (int): workspace ID Returns: Response: HTTP Respose """ app_name = multi_lang.get_text("EP020-0001", "ワークスペース情報:") exec_stat = multi_lang.get_text("EP020-0010", "退去") error_detail = "" try: globals.logger.debug('#' * 50) globals.logger.debug('CALL {} workspace_id [{}]'.format(inspect.currentframe().f_code.co_name, workspace_id)) globals.logger.debug('#' * 50) # ヘッダ情報 header info post_header = { 'Content-Type': 'application/json', } api_info_epai = "{}://{}:{}".format(os.environ["EPOCH_EPAI_API_PROTOCOL"], os.environ["EPOCH_EPAI_API_HOST"], os.environ["EPOCH_EPAI_API_PORT"]) realm_name = "exastroplatform" # ユーザIDの取得 get user id user_id = common.get_current_user(request.headers) # 指定のワークスペースIDに対する、オーナーロールのユーザ一覧を取得 Get a list of owner role users for the specified workspace ID response = requests.get("{}/{}/client/epoch-system/roles/{}/users".format(api_info_epai, realm_name, const.ROLE_WS_OWNER[0].format(workspace_id)), headers=post_header) users = json.loads(response.text) globals.logger.debug(type(users["rows"])) globals.logger.debug(users["rows"]) owner_check = False # 自身がオーナーかどうか確認 Check if you are the owner for user in users["rows"]: if user["user_id"] == user_id: owner_check = True break if owner_check: # 自身がオーナの場合、他のオーナーがいるかチェック If you are the owner, check if there are other owners if len(users["rows"]) == 1: # ログイン者が唯一のオーナーの時は退去できない Can't move out when the login person is the only owner return jsonify({"result": "400", "reason": multi_lang.get_text("EP020-0014", "あなた以外のオーナーがいないので退去できません")}), 400 response = requests.get("{}/{}/user/{}/roles/epoch-system".format(api_info_epai, realm_name, user_id), headers=post_header) user_roles = json.loads(response.text) roles = [] for role in user_roles["rows"]: if "ws-{}".format(workspace_id) in role["name"]: roles.append( { "name" : role["name"] } ) post_data = { "roles" : roles } globals.logger.debug("post_data : " + json.dumps(post_data)) # 自分自身のワークスペースに関するロールを全て削除 - Delete all roles related to your own workspace response = requests.delete("{}/{}/user/{}/roles/epoch-system".format(api_info_epai, realm_name, user_id), headers=post_header, data=json.dumps(post_data)) if response.status_code != 200: error_detail = multi_lang.get_text("EP020-0011", "ユーザクライアントロールの削除に失敗しました") return jsonify({"result": "400", "reason": multi_lang.get_text("EP020-0015", "ワークスペースからの退去に失敗しました")}), 400 # ロールの更新日を現在時刻に変更 - Change the update date of the role to the current time api_info = "{}://{}:{}/workspace/{}".format(os.environ["EPOCH_RS_WORKSPACE_PROTOCOL"], os.environ["EPOCH_RS_WORKSPACE_HOST"], os.environ["EPOCH_RS_WORKSPACE_PORT"], workspace_id) # 現在時刻を設定はrs_workspace側で処理 The current time is set on the rs_workspace side post_data = { 'role_update_at' : '' } response = requests.patch(api_info, headers=post_header, data=json.dumps(post_data)) if response.status_code != 200: error_detail = multi_lang.get_text("EP020-0012", "ロール更新日の変更に失敗しました") return jsonify({"result": "400", "reason": multi_lang.get_text("EP020-0015", "ワークスペースからの退去に失敗しました")}), 400 return jsonify({"result": "200"}), 200 except common.UserException as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail) except Exception as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail)
def merge_workspace_members(workspace_id): """ワークスペース該当メンバー登録 workspace member registration Request: json { "rows": [ { "user_id": "", "roles": [ { "kind": "", } ] }, ], "role_update_at": "", } Returns: Response: HTTP Respose """ app_name = multi_lang.get_text("EP020-0003", "ワークスペース情報:") exec_stat = multi_lang.get_text("EP020-0005", "メンバー登録") error_detail = "" return_code = 500 try: globals.logger.debug('#' * 50) globals.logger.debug('CALL {}'.format(inspect.currentframe().f_code.co_name)) globals.logger.debug('#' * 50) # 引数はJSON形式 Arguments are in JSON format req_json = request.json.copy() # ヘッダ情報 header info. post_headers = { 'Content-Type': 'application/json', } # workspace get api_url = "{}://{}:{}/workspace/{}".format(os.environ['EPOCH_RS_WORKSPACE_PROTOCOL'], os.environ['EPOCH_RS_WORKSPACE_HOST'], os.environ['EPOCH_RS_WORKSPACE_PORT'], workspace_id) response = requests.get(api_url, headers=post_headers) if response.status_code == 200 and common.is_json_format(response.text): # 取得したワークスペース情報を退避 Save the acquired workspace information ret = json.loads(response.text) ws_row = ret["rows"][0] elif response.status_code == 404: return_code = 400 error_detail = multi_lang.get_text("EP000-0022", "更新対象(workspace)がありません", "workspace") # 情報取得できない場合はエラー Error if information cannot be obtained raise common.UserException("{} not found workspace !".format(inspect.currentframe().f_code.co_name)) else: if response.status_code == 500 and common.is_json_format(response.text): # 戻り値がJsonの場合は、値を取得 If the return value is Json, get the value ret = json.loads(response.text) # 詳細エラーがある場合は詳細を設定 Set details if there are detailed errors if ret["errorDetail"] is not None: error_detail = ret["errorDetail"] raise common.UserException("{} Error get workspace db status:{}".format(inspect.currentframe().f_code.co_name, response.status_code)) globals.logger.debug("Exclusive check") globals.logger.debug("db[{}] update[{}]".format(str(ws_row["role_update_at"]), req_json["role_update_at"])) # 排他チェック:ロール更新日時が一致しているかチェックする # Exclusive check: Check if the role update datetime match if str(ws_row["role_update_at"]) != req_json["role_update_at"]: return_code = 400 error_detail = multi_lang.get_text("EP000-0023", "対象の情報(workspace)が他で更新されたため、更新できません\n画面更新後、再度情報を入力・選択して実行してください", "workspace") raise common.UserException("{} update exclusive check error".format(inspect.currentframe().f_code.co_name)) ret_status = response.status_code # ログインユーザーの情報取得 Get login user information user_id = common.get_current_user(request.headers) api_url = "{}://{}:{}/{}/user/{}".format(os.environ['EPOCH_EPAI_API_PROTOCOL'], os.environ['EPOCH_EPAI_API_HOST'], os.environ['EPOCH_EPAI_API_PORT'], os.environ["EPOCH_EPAI_REALM_NAME"], user_id ) # # get users - ユーザー取得 # response = requests.get(api_url) if response.status_code != 200 and response.status_code != 404: error_detail = multi_lang.get_text("EP020-0008", "ユーザー情報の取得に失敗しました") raise common.UserException("{} Error user get status:{}".format(inspect.currentframe().f_code.co_name, response.status_code)) users = json.loads(response.text) # globals.logger.debug(f"users:{users}") # 取得したユーザーのロールを取得 # Get the role of the acquired user api_url = "{}://{}:{}/{}/user/{}/roles/epoch-system".format(os.environ['EPOCH_EPAI_API_PROTOCOL'], os.environ['EPOCH_EPAI_API_HOST'], os.environ['EPOCH_EPAI_API_PORT'], os.environ["EPOCH_EPAI_REALM_NAME"], user_id ) # # get user role - ユーザーロール情報取得 # response = requests.get(api_url) if response.status_code != 200: error_detail = multi_lang.get_text("EP020-0009", "ユーザーロール情報の取得に失敗しました") globals.logger.debug(error_detail) raise common.UserException("{} Error user role get status:{}".format(inspect.currentframe().f_code.co_name, response.status_code)) ret_roles = json.loads(response.text) # globals.logger.debug(f"roles:{ret_roles}") bool_owener_role = False # オーナーロール設定可能権限かどうかチェックする # Check if the owner role can be set for get_role in ret_roles["rows"]: # globals.logger.debug('role:{}'.format(get_role["name"])) # ロールがあればチェックOK # Check OK if there is a roll if get_role["name"] == const.ROLE_WS_ROLE_OWNER_ROLE_SETTING[0].format(workspace_id): bool_owener_role = True break # 権限「オーナー変更」保有しているユーザーを抽出する # Extract users who have the authority "change owner" owener_users = api_service_common.get_workspace_members_by_role(workspace_id, const.ROLE_WS_ROLE_OWNER_ROLE_SETTING[0].format(workspace_id)) # globals.logger.debug(f"owener_users{owener_users}") owener_users_id_array = [] # チェック用に配列化 # Arranged for checking for user in owener_users: owener_users_id_array.append(user["user_id"]) # オーナーロール変更以外がオーナーロールありに変更したかチェック # Check if other than the owner role change has changed to have an owner role if not bool_owener_role: bool_auth_error = False for row in req_json["rows"]: globals.logger.debug(f"req_row:{row}") bool_owner_update = False for role in row["roles"]: # オーナー更新ありのフラグをONにする # Turn on the flag with owner update globals.logger.debug("owener_check({}):({})".format(common.get_role_name(role["kind"]), const.ROLE_WS_OWNER[0])) if common.get_role_name(role["kind"]) == const.ROLE_WS_OWNER[0]: bool_owner_update = True # オーナーロールの変更がある場合、権限がないのでエラーとする # If there is a change in the owner role, it will be an error because you do not have the authority. if common.get_role_name(role["kind"]) == const.ROLE_WS_OWNER[0] and \ row["user_id"] not in owener_users_id_array: bool_auth_error = True break # オーナーありのユーザーからオーナー権限を削除した際は権限がないのでエラーとする # If you delete the owner authority from a user who has an owner, you will get an error because you do not have the authority. if not bool_owner_update and row["user_id"] in owener_users_id_array: bool_auth_error = True break # 権限エラーの場合は、処理を抜ける # In case of permission error, exit the process if bool_auth_error: break # 権限エラー # Permission error if bool_auth_error: # ログイン者が唯一のオーナーの時は退去できない # Can't move out when the login person is the only owner error_detail = multi_lang.get_text("EP020-0024", "オーナー権限を変更することはできません") raise common.AuthException(error_detail) else: # オーナーロール変更ありのユーザーが、オーナーロール変更した際、オーナーロールのユーザーが残るかどうか # Check if a user with an owner role change has a user change with an owner role change owner_add_cnt = 0 owner_del_cnt = 0 for row in req_json["rows"]: bool_owner_update = False for role in row["roles"]: # オーナー更新ありのフラグをONにする # Turn on the flag with owner update if common.get_role_name(role["kind"]) == const.ROLE_WS_OWNER[0]: bool_owner_update = True break # オーナーありのユーザーからオーナー権限を削除した件数をカウント # Count the number of cases where the owner authority is deleted from the owner-owned user if not bool_owner_update and row["user_id"] in owener_users_id_array: owner_del_cnt += 1 # 新規オーナーかチェックする # Check if you are a new owner elif bool_owner_update and row["user_id"] not in owener_users_id_array: owner_add_cnt += 1 # オーナーが0人となる場合はエラーとする # If the number of owners is 0, an error will occur. if (len(owener_users) - owner_del_cnt) == 0 and owner_add_cnt == 0: # ログイン者が唯一のオーナーの時は退去できない # Can't move out when the login person is the only owner error_detail = multi_lang.get_text("EP020-0025", "最低1人以上のオーナーは必要です") raise common.AuthException(error_detail) for row in req_json["rows"]: # 登録前にすべてのroleを削除する # Delete all roles before registration roles = const.ALL_ROLES # # ロールの制御のurl - role control url # api_url = "{}://{}:{}/{}/user/{}/roles/epoch-system".format(os.environ['EPOCH_EPAI_API_PROTOCOL'], os.environ['EPOCH_EPAI_API_HOST'], os.environ['EPOCH_EPAI_API_PORT'], os.environ["EPOCH_EPAI_REALM_NAME"], row["user_id"], ) del_roles = [] for role in roles: del_role = { "name": role.format(workspace_id), } del_roles.append(del_role) post_data = { "roles" : del_roles } # # delete workspace role - ワークスペース ロールの削除 # response = requests.delete(api_url, headers=post_headers, data=json.dumps(post_data)) if response.status_code != 200: error_detail = multi_lang.get_text("EP020-0006", "ロールの削除に失敗しました") raise common.UserException("{} Error user role delete status:{}".format(inspect.currentframe().f_code.co_name, response.status_code)) # 登録するroleの情報を編集 # Edit the information of the role to be registered add_roles = [] for role in row["roles"]: add_role = { "name": common.get_role_name(role["kind"]).format(workspace_id), "enabled": True, } add_roles.append(add_role) post_data = { "roles" : add_roles } # # append workspace role - ワークスペース ロールの付与 # response = requests.post(api_url, headers=post_headers, data=json.dumps(post_data)) if response.status_code != 200: error_detail = multi_lang.get_text("EP020-0007", "ロールの登録に失敗しました") globals.logger.debug(error_detail) raise common.UserException("{} Error user role add status:{}".format(inspect.currentframe().f_code.co_name, response.status_code)) # # logs output - ログ出力 # post_data = { "action" : "role update", "role_update_user_id" : row["user_id"], "role_update_user_roles" : add_roles, } api_url = "{}://{}:{}/workspace/{}/member/{}/logs/{}".format(os.environ['EPOCH_RS_LOGS_PROTOCOL'], os.environ['EPOCH_RS_LOGS_HOST'], os.environ['EPOCH_RS_LOGS_PORT'], workspace_id, users["info"]["username"], const.LOG_KIND_UPDATE ) response = requests.post(api_url, headers=post_headers, data=json.dumps(post_data)) if response.status_code != 200: error_detail = multi_lang.get_text("EP020-0023", "ログ出力に失敗しました") globals.logger.debug(error_detail) raise common.UserException("{} Error log output status:{}".format(inspect.currentframe().f_code.co_name, response.status_code)) # # workspace info. Roll update date update - ワークスペース情報 ロール更新日の更新 # post_data = { "role_update_at" : "", } globals.logger.debug("role datetime update Start") api_url = "{}://{}:{}/workspace/{}".format(os.environ['EPOCH_RS_WORKSPACE_PROTOCOL'], os.environ['EPOCH_RS_WORKSPACE_HOST'], os.environ['EPOCH_RS_WORKSPACE_PORT'], workspace_id) response = requests.patch(api_url, headers=post_headers, data=json.dumps(post_data)) if response.status_code != 200: error_detail = multi_lang.get_text("EP000-0024", "対象の情報({})を更新できませんでした", "workspace") globals.logger.debug(error_detail) raise common.UserException("{} Error workspace-db update status:{}".format(inspect.currentframe().f_code.co_name, response.status_code)) globals.logger.debug("role datetime update Succeed!") return jsonify({"result": "200"}), 200 except common.AuthException as e: return jsonify({"result": 400, "errorDetail": error_detail}), 400 except common.UserException as e: return common.user_error_to_message(e, app_name + exec_stat, error_detail, return_code) except Exception as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail)
def create_argocd(workspace_id): """ Create pod argocd - ArgoCD Pod 作成 Args: workspace_id (int): workspace id Returns: Response: HTTP Respose """ app_name = multi_lang.get_text("EP035-0001", "ワークスペース情報:") exec_stat = multi_lang.get_text("EP035-0002", "ArgoCD環境構築") error_detail = "" try: globals.logger.debug('#' * 50) globals.logger.debug('CALL {}'.format( inspect.currentframe().f_code.co_name)) globals.logger.debug('#' * 50) ret_status = 200 template_dir = os.path.dirname( os.path.abspath(__file__)) + "/templates" # argocd apply pod create globals.logger.debug('apply : argocd_install_v2_1_1.yaml') stdout_cd = subprocess.check_output([ "kubectl", "apply", "-n", workspace_namespace(workspace_id), "-f", (template_dir + "/argocd_install_v2_1_1.yaml") ], stderr=subprocess.STDOUT) # globals.logger.debug(stdout_cd.decode('utf-8')) # # argocd apply rolebinding # with tempfile.TemporaryDirectory() as tempdir: # テンプレートファイルからyamlの生成 yamltext = render_template('argocd_rolebinding.yaml', param={ "workspace_id": workspace_id, "workspace_namespace": workspace_namespace(workspace_id), }) path_yamlfile = '{}/{}'.format(tempdir, "argocd_rolebinding.yaml") with open(path_yamlfile, mode='w') as fp: fp.write(yamltext) # yamlの適用 globals.logger.debug('apply : argocd_rolebinding.yaml') stdout_cd = subprocess.check_output([ "kubectl", "apply", "-n", workspace_namespace(workspace_id), "-f", path_yamlfile ], stderr=subprocess.STDOUT) # globals.logger.debug(stdout_cd.decode('utf-8')) # # パスワードの初期化 # # Access情報の取得 access_data = get_access_info(workspace_id) argo_password = access_data['ARGOCD_PASSWORD'] salt = bcrypt.gensalt(rounds=10, prefix=b'2a') password = argo_password.encode("ascii") argoLogin = bcrypt.hashpw(password, salt).decode("ascii") datenow = datetime.now( pytz.timezone('Asia/Tokyo')).strftime('%Y-%m-%dT%H:%M:%S%z') pdata = '{"stringData": { "admin.password": "******", "admin.passwordMtime": "\'' + datenow + '\'" }}' globals.logger.debug('patch argocd-secret :') stdout_cd = subprocess.check_output([ "kubectl", "-n", workspace_namespace(workspace_id), "patch", "secret", "argocd-secret", "-p", pdata ], stderr=subprocess.STDOUT) # globals.logger.debug(stdout_cd.decode('utf-8')) # # PROXY setting # # 対象となるdeploymentを定義 deployments = [ "deployment/argocd-server", "deployment/argocd-dex-server", "deployment/argocd-redis", "deployment/argocd-repo-server" ] # Proxyの設定値 envs = [ "HTTP_PROXY=" + os.environ['EPOCH_HTTP_PROXY'], "HTTPS_PROXY=" + os.environ['EPOCH_HTTPS_PROXY'], "http_proxy=" + os.environ['EPOCH_HTTP_PROXY'], "https_proxy=" + os.environ['EPOCH_HTTPS_PROXY'], "NO_PROXY=" + os.environ['EPOCH_ARGOCD_NO_PROXY'], "no_proxy=" + os.environ['EPOCH_ARGOCD_NO_PROXY'] ] # PROXYの設定を反映 for deployment_name in deployments: for env_name in envs: # 環境変数の設定 # globals.logger.debug('set env : {} {}'.format(deployment_name, env_name)) stdout_cd = subprocess.check_output([ "kubectl", "set", "env", deployment_name, "-n", workspace_namespace(workspace_id), env_name ], stderr=subprocess.STDOUT) # globals.logger.debug(stdout_cd.decode('utf-8')) # 戻り値をそのまま返却 return jsonify({"result": ret_status}), ret_status except common.UserException as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail) except Exception as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail)
def argocd_settings(workspace_id): """Setting argocd - ArgoCD設定 Args: workspace_id (int): workspace id Returns: Response: HTTP Respose """ app_name = multi_lang.get_text("EP035-0001", "ワークスペース情報:") exec_stat = multi_lang.get_text("EP035-0004", "ArgoCD設定") error_detail = "" try: # ワークスペースアクセス情報取得 access_data = get_access_info(workspace_id) argo_host = 'argocd-server.epoch-ws-{}.svc'.format(workspace_id) argo_id = access_data['ARGOCD_USER'] argo_password = access_data['ARGOCD_PASSWORD'] # 引数で指定されたCD環境を取得 request_json = json.loads(request.data) request_ci_env = request_json["ci_config"]["environments"] request_cd_env = request_json["cd_config"]["environments"] gitUsername = request_json["cd_config"]["environments_common"][ "git_repositry"]["user"] gitPassword = request_json["cd_config"]["environments_common"][ "git_repositry"]["token"] housing = request_json["cd_config"]["environments_common"][ "git_repositry"]["housing"] # # argocd login # globals.logger.debug("argocd login :"******"argocd", "login", argo_host, "--insecure", "--username", argo_id, "--password", argo_password ], stderr=subprocess.STDOUT) globals.logger.debug(stdout_cd.decode('utf-8')) # # repo setting # # リポジトリ情報の一覧を取得する globals.logger.debug("argocd repo list :") stdout_cd = subprocess.check_output( ["argocd", "repo", "list", "-o", "json"], stderr=subprocess.STDOUT) globals.logger.debug(stdout_cd.decode('utf-8')) # 設定済みのリポジトリ情報をクリア repo_list = json.loads(stdout_cd) for repo in repo_list: globals.logger.debug("argocd repo rm [repo] {} :".format( repo['repo'])) stdout_cd = subprocess.check_output( ["argocd", "repo", "rm", repo['repo']], stderr=subprocess.STDOUT) globals.logger.debug(stdout_cd.decode('utf-8')) # 環境群数分処理を実行 for env in request_cd_env: env_name = env["name"] gitUrl = env["git_repositry"]["url"] exec_stat = multi_lang.get_text("EP035-0005", "ArgoCD設定 - リポジトリ作成") error_detail = multi_lang.get_text("EP035-0006", "IaCリポジトリの設定内容を確認してください") # レポジトリの情報を追加 globals.logger.debug("argocd repo add :") if housing == "inner": stdout_cd = subprocess.check_output([ "argocd", "repo", "add", "--insecure-ignore-host-key", gitUrl, "--username", gitUsername, "--password", gitPassword ], stderr=subprocess.STDOUT) else: stdout_cd = subprocess.check_output([ "argocd", "repo", "add", gitUrl, "--username", gitUsername, "--password", gitPassword ], stderr=subprocess.STDOUT) globals.logger.debug(stdout_cd.decode('utf-8')) # # app setting # # アプリケーション情報の一覧を取得する globals.logger.debug("argocd app list :") stdout_cd = subprocess.check_output( ["argocd", "app", "list", "-o", "json"], stderr=subprocess.STDOUT) globals.logger.debug(stdout_cd.decode('utf-8')) # アプリケーション情報を削除する app_list = json.loads(stdout_cd) for app in app_list: globals.logger.debug('argocd app delete [app] {} :'.format( app['metadata']['name'])) stdout_cd = subprocess.check_output( ["argocd", "app", "delete", app['metadata']['name'], "-y"], stderr=subprocess.STDOUT) # アプリケーションが消えるまでWaitする globals.logger.debug("wait : argocd app list clean") for i in range(WAIT_APPLICATION_DELETE): # アプリケーションの一覧を取得し、結果が0件になるまでWaitする stdout_cd = subprocess.check_output( ["argocd", "app", "list", "-o", "json"], stderr=subprocess.STDOUT) app_list = json.loads(stdout_cd) if len(app_list) == 0: break time.sleep(1) # 1秒ごとに確認 # 環境群数分処理を実行 for env in request_cd_env: argo_app_name = get_argo_app_name(workspace_id, env['environment_id']) cluster = env["deploy_destination"]["cluster_url"] namespace = env["deploy_destination"]["namespace"] gitUrl = env["git_repositry"]["url"] # namespaceの存在チェック ret = common.get_namespace(namespace) if ret is None: # 存在しない(None)ならnamespace作成 ret = common.create_namespace(namespace) if ret is None: # namespaceの作成で失敗(None)が返ってきた場合はエラー error_detail = 'create namespace処理に失敗しました' raise common.UserException(error_detail) exec_stat = multi_lang.get_text("EP035-0007", "ArgoCD設定 - アプリケーション作成") error_detail = multi_lang.get_text("EP035-0008", "ArgoCDの入力内容を確認してください") # argocd app create catalogue \ # --repo [repogitory URL] \ # --path ./ \ # --dest-server https://kubernetes.default.svc \ # --dest-namespace [namespace] \ # --auto-prune \ # --sync-policy automated # アプリケーション作成 globals.logger.debug("argocd app create :") stdout_cd = subprocess.check_output([ "argocd", "app", "create", argo_app_name, "--repo", gitUrl, "--path", "./", "--dest-server", cluster, "--dest-namespace", namespace, "--auto-prune", "--sync-policy", "automated", ], stderr=subprocess.STDOUT) globals.logger.debug(stdout_cd.decode('utf-8')) ret_status = 200 # 戻り値をそのまま返却 return jsonify({"result": ret_status}), ret_status except common.UserException as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail) except Exception as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail)
def settings_manifest_templates(workspace_id): """manifest templates setting Returns: Response: HTTP Respose """ app_name = "ワークスペース情報:" exec_stat = "manifestテンプレートファイル登録" error_detail = "" try: globals.logger.debug('#' * 50) globals.logger.debug('CALL {}'.format( inspect.currentframe().f_code.co_name)) globals.logger.debug('#' * 50) # パラメータ情報(JSON形式) prameter save payload = request.json.copy() # ワークスペースアクセス情報取得 access_info = api_access_info.get_access_info(workspace_id) # namespaceの取得 namespace = common.get_namespace_name(workspace_id) ita_restapi_endpoint = "http://{}.{}.svc:{}/default/menu/07_rest_api_ver1.php".format( EPOCH_ITA_HOST, namespace, EPOCH_ITA_PORT) ita_user = access_info['ITA_USER'] ita_pass = access_info['ITA_PASSWORD'] # HTTPヘッダの生成 filter_headers = { 'host': EPOCH_ITA_HOST + ':' + EPOCH_ITA_PORT, 'Content-Type': 'application/json', 'Authorization': base64.b64encode( (ita_user + ':' + ita_pass).encode()), 'X-Command': 'FILTER', } edit_headers = { 'host': EPOCH_ITA_HOST + ':' + EPOCH_ITA_PORT, 'Content-Type': 'application/json', 'Authorization': base64.b64encode( (ita_user + ':' + ita_pass).encode()), 'X-Command': 'EDIT', } # # マニフェストテンプレートの取得 # content = { "1": { "NORMAL": "0" }, "3": { "NORMAL": "TPF_epoch_template_yaml" }, } manitpl_resp = requests.post(ita_restapi_endpoint + '?no=' + ita_menu_manifest_template, headers=filter_headers, data=json.dumps(content)) manitpl_json = json.loads(manitpl_resp.text) globals.logger.debug('---- Current Manifest Templates ----') # logger.debug(manitpl_resp.text) # globals.logger.debug(manitpl_json) req_data = payload['manifests'] mani_req_len = len(req_data) mani_ita_len = manitpl_json['resultdata']['CONTENTS']['RECORD_LENGTH'] max_loop_cnt = max(mani_req_len, mani_ita_len) globals.logger.debug("max_loop_cnt: " + str(max_loop_cnt)) ita_data = manitpl_json['resultdata']['CONTENTS']["BODY"] ita_data.pop(0) # globals.logger.debug(ita_data) edit_data = {"UPLOAD_FILE": []} tpl_cnt = 0 for i in range(max_loop_cnt): # ITAを廃止 if i > mani_req_len - 1: tmp_data = [] for j, item in enumerate(ita_data[i]): if j == 0: tmp_data.append('廃止') else: tmp_data.append(item) edit_data[str(i)] = tmp_data # ITAに新規登録する elif i > mani_ita_len - 1: tpl_cnt += 1 tmp_data = {} tmp_data['0'] = "登録" tmp_data['3'] = "TPF_epoch_template_yaml" + str(tpl_cnt) tmp_data['4'] = req_data[i]["file_name"] tmp_data['5'] = "VAR_image:\n"\ "VAR_image_tag:\n"\ "VAR_param01:\n"\ "VAR_param02:\n"\ "VAR_param03:\n"\ "VAR_param04:\n"\ "VAR_param05:\n"\ "VAR_param06:\n"\ "VAR_param07:\n"\ "VAR_param08:\n"\ "VAR_param09:\n"\ "VAR_param10:\n"\ "VAR_param11:\n"\ "VAR_param12:\n"\ "VAR_param13:\n"\ "VAR_param14:\n"\ "VAR_param15:\n"\ "VAR_param16:\n"\ "VAR_param17:\n"\ "VAR_param18:\n"\ "VAR_param19:\n"\ "VAR_param20:" edit_data[str(i)] = tmp_data edit_data["UPLOAD_FILE"].append({ "4": base64.b64encode( req_data[i]["file_text"].encode()).decode() }) # ITAを更新する else: tpl_cnt += 1 tmp_data = ita_data[i] tmp_data[0] = "更新" tmp_data[3] = "TPF_epoch_template_yaml" + str(tpl_cnt) tmp_data[4] = req_data[i]["file_name"] tmp_data[5] = "VAR_image:\n"\ "VAR_image_tag:\n"\ "VAR_param01:\n"\ "VAR_param02:\n"\ "VAR_param03:\n"\ "VAR_param04:\n"\ "VAR_param05:\n"\ "VAR_param06:\n"\ "VAR_param07:\n"\ "VAR_param08:\n"\ "VAR_param09:\n"\ "VAR_param10:\n"\ "VAR_param11:\n"\ "VAR_param12:\n"\ "VAR_param13:\n"\ "VAR_param14:\n"\ "VAR_param15:\n"\ "VAR_param16:\n"\ "VAR_param17:\n"\ "VAR_param18:\n"\ "VAR_param19:\n"\ "VAR_param20:" edit_data[str(i)] = tmp_data edit_data["UPLOAD_FILE"].append({ "4": base64.b64encode( req_data[i]["file_text"].encode()).decode() }) # globals.logger.debug(edit_data) # ITAへREST実行 manutemplate_edit_resp = requests.post(ita_restapi_endpoint + '?no=' + ita_menu_manifest_template, headers=edit_headers, data=json.dumps(edit_data)) # manitemplate_json = json.loads(manutemplate_edit_resp.text) # globals.logger.debug(manitemplate_json) # 正常終了 ret_status = 200 # 戻り値をそのまま返却 return jsonify({"result": ret_status}), ret_status except common.UserException as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail) except Exception as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail)
def post_manifest_template(workspace_id): """manifest テンプレート登録 manifest template registration Args: workspace_id (int): workspace ID Returns: Response: HTTP Respose """ app_name = "ワークスペース情報:" exec_stat = "manifestテンプレート登録" error_detail = "" try: globals.logger.debug('#' * 50) globals.logger.debug('CALL {}'.format( inspect.currentframe().f_code.co_name)) globals.logger.debug('#' * 50) # ファイルの存在チェック exists file check if 'manifest_files' not in request.files: error_detail = "アップロードファイルがありません" globals.logger.debug('upload file not found') raise common.UserException(error_detail) apiInfo = "{}://{}:{}".format( os.environ['EPOCH_RS_WORKSPACE_PROTOCOL'], os.environ['EPOCH_RS_WORKSPACE_HOST'], os.environ['EPOCH_RS_WORKSPACE_PORT']) # ヘッダ情報 post_headers = { 'Content-Type': 'application/json', } # データ情報(追加用) post_data_add = {"manifests": []} # データ情報(更新用) post_data_upd = {"manifests": []} # RsWorkspace API呼び出し(全件取得) response = requests.get("{}/workspace/{}/manifests".format( apiInfo, workspace_id), headers=post_headers) # 戻り値が正常値以外の場合は、処理を終了 if response.status_code != 200: error_detail = "manifestテンプレート情報取得失敗" globals.logger.debug("CALL responseAPI /manifests Error") raise common.UserException(error_detail) ret_manifests = json.loads(response.text) globals.logger.debug("get Filedata ------------------ S") globals.logger.debug(ret_manifests["rows"]) globals.logger.debug("get Filedata ------------------ E") # 送信されたマニフェストファイル数分処理する for manifest_file in request.files.getlist('manifest_files'): file_text = '' # ↓ 2重改行になっているので、変更するかも ↓ for line in manifest_file: file_text += line.decode('utf-8') # ファイル情報(manifest_data) manifest_data = { "file_name": manifest_file.filename, "file_text": file_text } # 同一ファイルがあるかファイルIDを取得 file_id = common.get_file_id(ret_manifests["rows"], manifest_file.filename) # 同一ファイル名が登録されている場合は、更新とする if not file_id: # データ登録情報(manifest_dataと結合) post_data_add['manifests'].append(manifest_data) else: manifest_data["file_id"] = file_id # データ更新情報(manifest_dataと結合) post_data_upd['manifests'].append(manifest_data) globals.logger.debug("post_data_add ------------------ S") globals.logger.debug(post_data_add) globals.logger.debug("post_data_add ------------------ E") globals.logger.debug("post_data_upd ------------------ S") globals.logger.debug(post_data_upd) globals.logger.debug("post_data_upd ------------------ E") # RsWorkspace API呼び出し(削除) # response = requests.delete( apiInfo + "/workspace/" + str(workspace_id) + "/manifests", headers=post_headers) # 更新は1件ずつ実施 for upd in post_data_upd['manifests']: # JSON形式に変換 post_data = json.dumps(upd) # RsWorkspace API呼び出し(更新) response = requests.put("{}/workspace/{}/manifests/{}".format( apiInfo, workspace_id, upd["file_id"]), headers=post_headers, data=post_data) # JSON形式に変換 post_data = json.dumps(post_data_add) # RsWorkspace API呼び出し(登録) response = requests.post("{}/workspace/{}/manifests".format( apiInfo, workspace_id), headers=post_headers, data=post_data) # ITA呼び出し globals.logger.debug("CALL ita_registration Start") response = ita_registration(workspace_id) globals.logger.debug("CALL ita_registration End response:") globals.logger.debug(response) # 正常終了 normal return code ret_status = 200 return jsonify({"result": ret_status, "rows": response}), ret_status except common.UserException as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail) except Exception as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail)
def get_git_commits(workspace_id): """Get git commit history - gitコミット履歴取得 Args: workspace_id (int): workspace ID Returns: Response: HTTP Respose """ app_name = "ワークスペース情報:" exec_stat = "CIパイプラインgit履歴取得" error_detail = "" try: globals.logger.debug('#' * 50) globals.logger.debug('CALL {}'.format(inspect.currentframe().f_code.co_name)) globals.logger.debug('#' * 50) # workspace get api_url = "{}://{}:{}/workspace/{}".format(os.environ['EPOCH_RS_WORKSPACE_PROTOCOL'], os.environ['EPOCH_RS_WORKSPACE_HOST'], os.environ['EPOCH_RS_WORKSPACE_PORT'], workspace_id) response = requests.get(api_url) if response.status_code != 200: error_detail = multi_lang.get_text("EP020-0013", "ワークスペース情報の取得に失敗しました") globals.logger.debug(error_detail) raise common.UserException(error_detail) # 取得したワークスペース情報を退避 Save the acquired workspace information ret = json.loads(response.text) # 取得したworkspace情報をパラメータとして受け渡す Pass the acquired workspace information as a parameter workspace_info = ret["rows"][0] git_token = workspace_info["ci_config"]["pipelines_common"]["git_repositry"]["token"] git_user = workspace_info["ci_config"]["pipelines_common"]["git_repositry"]["user"] # ヘッダ情報 header info. post_headers_in_token = { 'private-token': git_token, 'Content-Type': 'application/json', } rows = [] # パイプライン数分処理する Process for a few minutes in the pipelines for pipeline in workspace_info["ci_config"]["pipelines"]: git_url = pipeline["git_repositry"]["url"] if workspace_info["ci_config"]["pipelines_common"]["git_repositry"]["housing"] == const.HOUSING_INNER: # EPOCH内レジストリ ブランチの一覧取得 Get a list of registry branches in EPOCH api_url = "{}://{}:{}/branches?git_url={}".format(os.environ['EPOCH_CONTROL_INSIDE_GITLAB_PROTOCOL'], os.environ['EPOCH_CONTROL_INSIDE_GITLAB_HOST'], os.environ['EPOCH_CONTROL_INSIDE_GITLAB_PORT'], urllib.parse.quote(git_url)) response = requests.get(api_url, headers=post_headers_in_token) if response.status_code != 200: raise common.UserException("git branches get error:[{}]".format(response.status_code)) ret_git_branches = json.loads(response.text) # ブランチごとにcommit情報を取得する # Get commit information for each branch for branch_row in ret_git_branches["rows"]: # EPOCH内レジストリ Registry in EPOCH api_url = "{}://{}:{}/commits?git_url={}&branch={}".format(os.environ['EPOCH_CONTROL_INSIDE_GITLAB_PROTOCOL'], os.environ['EPOCH_CONTROL_INSIDE_GITLAB_HOST'], os.environ['EPOCH_CONTROL_INSIDE_GITLAB_PORT'], urllib.parse.quote(git_url), urllib.parse.quote(branch_row["name"])) response = requests.get(api_url, headers=post_headers_in_token) if response.status_code != 200: raise common.UserException("git commit get error:[{}]".format(response.status_code)) ret_git_commit = json.loads(response.text) # 取得した情報数分処理する # Process for the number of acquired information for git_row in ret_git_commit["rows"]: web_url = git_row["web_url"] base_url = re.search('^https?://[^/][^/]*/',git_url).group() web_url = web_url.replace("https://gitlab.gitlab.svc/", base_url) # web_url = web_url.replace("https://gitlab.gitlab.svc/", git_url.match("(https?://[^/]+/)")) row = { "git_url": git_url, "repository": "{}/{}".format(git_user, re.search('([^/]+?)(?=.git)', git_url).group()), "branch": branch_row["name"], "commit_id": git_row["id"], "name": git_row["committer_name"], "date": git_row["committed_date"], "message": git_row["message"], "html_url": web_url, } rows.append(row) else: # GitHub branches get api_url = "{}://{}:{}/branches?git_url={}".format(os.environ['EPOCH_CONTROL_GITHUB_PROTOCOL'], os.environ['EPOCH_CONTROL_GITHUB_HOST'], os.environ['EPOCH_CONTROL_GITHUB_PORT'], urllib.parse.quote(git_url)) response = requests.get(api_url, headers=post_headers_in_token) if response.status_code != 200: raise common.UserException("git branches get error:[{}]".format(response.status_code)) ret_git_branches = json.loads(response.text) # ブランチごとにcommit情報を取得する # Get commit information for each branch for branch_row in ret_git_branches["rows"]: # GitHub commit get api_url = "{}://{}:{}/commits?git_url={}&branch={}".format(os.environ['EPOCH_CONTROL_GITHUB_PROTOCOL'], os.environ['EPOCH_CONTROL_GITHUB_HOST'], os.environ['EPOCH_CONTROL_GITHUB_PORT'], urllib.parse.quote(git_url), urllib.parse.quote(branch_row["name"])) response = requests.get(api_url, headers=post_headers_in_token) if response.status_code != 200: raise common.UserException("git commit get error:[{}]".format(response.status_code)) ret_git_commit = json.loads(response.text) # globals.logger.debug("rows:[{}]".format(ret_git_commit["rows"])) # 取得した情報数分処理する # Process for the number of acquired information for git_row in ret_git_commit["rows"]: row = { "git_url": git_url, "repository": "{}/{}".format(git_user, re.search('([^/]+?)(?=.git)', git_url).group()), "branch": branch_row["name"], "commit_id": git_row["sha"], "name": git_row["commit"]["committer"]["name"], "date": git_row["commit"]["committer"]["date"], "message": git_row["commit"]["message"], "html_url": git_row["html_url"], } rows.append(row) response = { "result":"200", "rows" : rows, } ret_status = 200 return jsonify(response), ret_status except common.UserException as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail) except Exception as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail)
def delete_manifest_template(workspace_id, file_id): """manifest テンプレート削除 manifest template delete Args: workspace_id (int): workspace ID file_id (int): file ID Returns: Response: HTTP Respose """ app_name = "ワークスペース情報:" exec_stat = "manifestテンプレート削除" error_detail = "" try: globals.logger.debug('#' * 50) globals.logger.debug('CALL {}'.format( inspect.currentframe().f_code.co_name)) globals.logger.debug('#' * 50) # ヘッダ情報 headers = { 'Content-Type': 'application/json', } # DELETE送信(作成) resourceProtocol = os.environ['EPOCH_RS_WORKSPACE_PROTOCOL'] resourceHost = os.environ['EPOCH_RS_WORKSPACE_HOST'] resourcePort = os.environ['EPOCH_RS_WORKSPACE_PORT'] apiurl = "{}://{}:{}/workspace/{}/manifests/{}".format( resourceProtocol, resourceHost, resourcePort, workspace_id, file_id) response = requests.delete(apiurl, headers=headers) if response.status_code == 200 and common.is_json_format( response.text): # 200(正常)かつ、レスポンスデータがJSON形式の場合は、後続の処理を実行 pass elif response.status_code == 404: # manifestデータが見つからない(404)場合 error_detail = 'manifest template data not found' raise common.UserException(error_detail) elif response.status_code != 200: # 200(正常), 404(not found) 以外の応答の場合 error_detail = 'CALL responseAPI Error' raise common.UserException(error_detail) # ITA呼び出し globals.logger.debug("CALL ita_registration Start") response = ita_registration(workspace_id) globals.logger.debug("CALL ita_registration End response:") globals.logger.debug(response) # 正常終了 normal return code ret_status = 200 return jsonify({"result": ret_status, "rows": response}), ret_status except common.UserException as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail) except Exception as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail)
def post_ci_pipeline(workspace_id): """CIパイプライン情報設定 Args: workspace_id (int): workspace ID Returns: Response: HTTP Respose """ app_name = "ワークスペース情報:" exec_stat = "CIパイプライン情報設定" error_detail = "" try: globals.logger.debug('#' * 50) globals.logger.debug('CALL {}'.format(inspect.currentframe().f_code.co_name)) globals.logger.debug('#' * 50) # ヘッダ情報 post_headers = { 'Content-Type': 'application/json', } # # 引数をJSON形式で受け取りそのまま引数に設定 # post_data = request.json.copy() # workspace get api_url = "{}://{}:{}/workspace/{}".format(os.environ['EPOCH_RS_WORKSPACE_PROTOCOL'], os.environ['EPOCH_RS_WORKSPACE_HOST'], os.environ['EPOCH_RS_WORKSPACE_PORT'], workspace_id) response = requests.get(api_url) if response.status_code != 200: error_detail = multi_lang.get_test("EP020-0013", "ワークスペース情報の取得に失敗しました") globals.logger.debug(error_detail) raise common.UserException(error_detail) # 取得したワークスペース情報を退避 Save the acquired workspace information ret = json.loads(response.text) # 取得したworkspace情報をパラメータとして受け渡す Pass the acquired workspace information as a parameter post_data = ret["rows"][0] # ワークスペース状態の取得 Get workspace status api_url = "{}://{}:{}/workspace/{}/status".format(os.environ['EPOCH_RS_WORKSPACE_PROTOCOL'], os.environ['EPOCH_RS_WORKSPACE_HOST'], os.environ['EPOCH_RS_WORKSPACE_PORT'], workspace_id) response = requests.get(api_url) if response.status_code != 200: error_detail = multi_lang.get_test("EP020-0026", "ワークスペース状態情報の取得に失敗しました") globals.logger.debug(error_detail) raise common.UserException(error_detail) # 取得したワークスペース状態を退避 Save the acquired workspace status get_workspace_status = json.loads(response.text) # 更新で使用する項目のみを展開する Expand only the items used in the update workspace_status = { const.STATUS_CI_SETTING : get_workspace_status[const.STATUS_CI_SETTING] } # 前回の結果が正常終了しているかチェックする # Be sure to execute CI settings except OK if workspace_status[const.STATUS_CI_SETTING] == const.STATUS_OK: # 更新前ワークスペース情報取得 Get workspace before update api_url = "{}://{}:{}/workspace/{}/before".format(os.environ['EPOCH_RS_WORKSPACE_PROTOCOL'], os.environ['EPOCH_RS_WORKSPACE_HOST'], os.environ['EPOCH_RS_WORKSPACE_PORT'], workspace_id) response = requests.get(api_url) if response.status_code == 200: # 取得したワークスペース情報を退避 Save the acquired workspace information ret = json.loads(response.text) # 取得したworkspace情報をパラメータとして受け渡す Pass the acquired workspace information as a parameter before_data = ret["rows"][0] elif response.status_code == 404: before_data = None elif response.status_code != 200: error_detail = multi_lang.get_test("EP020-0013", "ワークスペース情報の取得に失敗しました") globals.logger.debug(error_detail) raise common.UserException(error_detail) else: # OK以外は、必ずCI設定を実行 # Be sure to execute CI settings except OK before_data = None ci_config_json_after = post_data["ci_config"].copy() if before_data is not None: ci_config_json_before = before_data["ci_config"].copy() # environmentsの情報は比較に必要ないのでJsonから削除 # The environment information is not needed for comparison, so delete it from Json if "environments" in ci_config_json_after: ci_config_json_after.pop("environments") if before_data is not None: if "environments" in ci_config_json_before: ci_config_json_before.pop("environments") ci_config_str_after = json.dumps(ci_config_json_after) if before_data is not None: ci_config_str_before = json.dumps(ci_config_json_before) else: ci_config_str_before = None # 更新前、更新後が一致しない場合にCIパイプラインの設定を行なう # Set up the CI pipeline when the pre-update and post-update do not match if ci_config_str_after != ci_config_str_before: globals.logger.debug("changed ci_config parameter!") # 実行前はNGで更新 Update with NG before execution workspace_status[const.STATUS_CI_SETTING] = const.STATUS_NG # workspace 状態更新 workspace status update api_url = "{}://{}:{}/workspace/{}/status".format(os.environ['EPOCH_RS_WORKSPACE_PROTOCOL'], os.environ['EPOCH_RS_WORKSPACE_HOST'], os.environ['EPOCH_RS_WORKSPACE_PORT'], workspace_id) response = requests.put(api_url, headers=post_headers, data=json.dumps(workspace_status)) if response.status_code != 200: error_detail = multi_lang.get_test("EP020-0027", "ワークスペース状態情報の更新に失敗しました") globals.logger.debug(error_detail) raise common.UserException(error_detail) # epoch-control-inside-gitlab-api の呼び先設定 api_url_gitlab = "{}://{}:{}/workspace/{}/gitlab".format(os.environ["EPOCH_CONTROL_INSIDE_GITLAB_PROTOCOL"], os.environ["EPOCH_CONTROL_INSIDE_GITLAB_HOST"], os.environ["EPOCH_CONTROL_INSIDE_GITLAB_PORT"], workspace_id) # epoch-control-github-api の呼び先設定 api_url_github = "{}://{}:{}/workspace/{}/github/webhooks".format(os.environ["EPOCH_CONTROL_GITHUB_PROTOCOL"], os.environ["EPOCH_CONTROL_GITHUB_HOST"], os.environ["EPOCH_CONTROL_GITHUB_PORT"], workspace_id) # epoch-control-tekton-api の呼び先設定 api_url_tekton = "{}://{}:{}/workspace/{}/tekton/pipeline".format(os.environ["EPOCH_CONTROL_TEKTON_PROTOCOL"], os.environ["EPOCH_CONTROL_TEKTON_HOST"], os.environ["EPOCH_CONTROL_TEKTON_PORT"], workspace_id) # パイプライン設定(GitLab Create Project) # request_body = json.loads(request.data) request_body = post_data git_projects = [] # アプリケーションコード if request_body['ci_config']['pipelines_common']['git_repositry']['housing'] == 'inner': for pipeline_ap in request_body['ci_config']['pipelines']: ap_data = { 'git_repositry': { 'user': request_body['ci_config']['pipelines_common']['git_repositry']['user'], 'token': request_body['ci_config']['pipelines_common']['git_repositry']['token'], 'url': pipeline_ap['git_repositry']['url'], } } git_projects.append(ap_data) # IaC # if request_body['cd_config']['environments_common']['git_repositry']['housing'] == 'inner': # for pipeline_iac in request_body['cd_config']['environments']: # ap_data = { # 'git_repositry': { # 'user': request_body['cd_config']['environments_common']['git_repositry']['user'], # 'token': request_body['cd_config']['environments_common']['git_repositry']['token'], # 'url': pipeline_iac['git_repositry']['url'], # } # } # git_projects.append(ap_data) for proj_data in git_projects: # gitlab/repos post送信 response = requests.post('{}/repos'.format(api_url_gitlab), headers=post_headers, data=json.dumps(proj_data)) globals.logger.debug("post gitlab/repos response:{}".format(response.text)) if response.status_code != 200 and response.status_code != 201: error_detail = 'gitlab/repos post処理に失敗しました' raise common.UserException(error_detail) if request_body['ci_config']['pipelines_common']['git_repositry']['housing'] == 'outer': # github/webhooks post送信 response = requests.post( api_url_github, headers=post_headers, data=json.dumps(post_data)) globals.logger.debug("post github/webhooks response:{}".format(response.text)) if response.status_code != 200: error_detail = 'github/webhooks post処理に失敗しました' raise common.UserException(error_detail) else: # パイプライン設定(GitLab webhooks) for pipeline_ap in request_body['ci_config']['pipelines']: ap_data = { 'git_repositry': { 'user': request_body['ci_config']['pipelines_common']['git_repositry']['user'], 'token': request_body['ci_config']['pipelines_common']['git_repositry']['token'], 'url': pipeline_ap['git_repositry']['url'], }, 'webhooks_url': pipeline_ap['webhooks_url'], } response = requests.post('{}/webhooks'.format(api_url_gitlab), headers=post_headers, data=json.dumps(ap_data)) globals.logger.debug("post gitlab/webhooks response:{}".format(response.text)) if response.status_code != 200 and response.status_code != 201: error_detail = 'gitlab/webhooks post処理に失敗しました' raise common.UserException(error_detail) # listener post送信 response = requests.post(api_url_tekton, headers=post_headers, data=json.dumps(post_data)) globals.logger.debug("post tekton/pipeline response:{}".format(response.text)) if response.status_code != 200: error_detail = 'tekton/pipeline post処理に失敗しました' raise common.UserException(error_detail) # 実行後はOKで更新 Update with OK after execution workspace_status[const.STATUS_CI_SETTING] = const.STATUS_OK # workspace 状態更新 workspace status update api_url = "{}://{}:{}/workspace/{}/status".format(os.environ['EPOCH_RS_WORKSPACE_PROTOCOL'], os.environ['EPOCH_RS_WORKSPACE_HOST'], os.environ['EPOCH_RS_WORKSPACE_PORT'], workspace_id) response = requests.put(api_url, headers=post_headers, data=json.dumps(workspace_status)) if response.status_code != 200: error_detail = multi_lang.get_test("EP020-0027", "ワークスペース状態情報の更新に失敗しました") globals.logger.debug(error_detail) raise common.UserException(error_detail) ret_status = 200 # 戻り値をそのまま返却 return jsonify({"result": ret_status}), ret_status except common.UserException as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail) except Exception as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail)
def get_git_hooks(workspace_id): """Get webhook history - webhook履歴取得 Args: workspace_id (int): workspace ID Returns: Response: HTTP Respose """ app_name = "ワークスペース情報:" exec_stat = "CIパイプラインwebhook履歴取得" error_detail = "" try: globals.logger.debug('#' * 50) globals.logger.debug('CALL {}'.format(inspect.currentframe().f_code.co_name)) globals.logger.debug('#' * 50) # workspace get api_url = "{}://{}:{}/workspace/{}".format(os.environ['EPOCH_RS_WORKSPACE_PROTOCOL'], os.environ['EPOCH_RS_WORKSPACE_HOST'], os.environ['EPOCH_RS_WORKSPACE_PORT'], workspace_id) response = requests.get(api_url) if response.status_code != 200: error_detail = multi_lang.get_text("EP020-0013", "ワークスペース情報の取得に失敗しました") globals.logger.debug(error_detail) raise common.UserException(error_detail) # 取得したワークスペース情報を退避 Save the acquired workspace information ret = json.loads(response.text) # 取得したworkspace情報をパラメータとして受け渡す Pass the acquired workspace information as a parameter workspace_info = ret["rows"][0] git_token = workspace_info["ci_config"]["pipelines_common"]["git_repositry"]["token"] git_user = workspace_info["ci_config"]["pipelines_common"]["git_repositry"]["user"] # ヘッダ情報 header info. post_headers_in_token = { 'private-token': git_token, 'Content-Type': 'application/json', } rows = [] # パイプライン数分処理する Process for a few minutes in the pipelines for pipeline in workspace_info["ci_config"]["pipelines"]: git_url = pipeline["git_repositry"]["url"] # GitHubのみ対応 Only compatible with GitHub if workspace_info["cd_config"]["environments_common"]["git_repositry"]["housing"] == const.HOUSING_OUTER: # GitHub hooks get api_url = "{}://{}:{}/hooks?git_url={}".format(os.environ['EPOCH_CONTROL_GITHUB_PROTOCOL'], os.environ['EPOCH_CONTROL_GITHUB_HOST'], os.environ['EPOCH_CONTROL_GITHUB_PORT'], urllib.parse.quote(git_url)) response = requests.get(api_url, headers=post_headers_in_token) if response.status_code != 200: raise common.UserException("git hooks get error:[{}]".format(response.status_code)) ret_git_hooks = json.loads(response.text) # globals.logger.debug("rows:[{}]".format(ret_git_hooks["rows"])) # 取得した情報数分処理する # Process for the number of acquired information for hooks_row in ret_git_hooks["rows"]: # GitHub hooks get api_url = "{}://{}:{}/hooks/{}/deliveries?git_url={}".format(os.environ['EPOCH_CONTROL_GITHUB_PROTOCOL'], os.environ['EPOCH_CONTROL_GITHUB_HOST'], os.environ['EPOCH_CONTROL_GITHUB_PORT'], hooks_row["id"], urllib.parse.quote(git_url)) response = requests.get(api_url, headers=post_headers_in_token) if response.status_code != 200: raise common.UserException("git deliveries get error:[{}]".format(response.status_code)) ret_git_deliveries = json.loads(response.text) # globals.logger.debug("deliveries:[{}]".format(ret_git_deliveries["rows"])) # 取得した情報数分処理する # Process for the number of acquired information for deliveries_row in ret_git_deliveries["rows"]: # event push only if deliveries_row["event"].lower() == "push": row = { "git_url": git_url, "repository": "{}/{}".format(git_user, re.search('([^/]+?)(?=.git)', git_url).group()), "branch": "", "url": hooks_row["config"]["url"], "date": deliveries_row["delivered_at"], "status": deliveries_row["status"], "status_code": deliveries_row["status_code"], "event": deliveries_row["event"], } rows.append(row) response = { "result":"200", "rows" : rows, } ret_status = 200 return jsonify(response), ret_status except common.UserException as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail) except Exception as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail)
def get_registry(workspace_id): """Get container registry information - コンテナレジストリ情報取得 Args: workspace_id (int): workspace ID Returns: Response: HTTP Respose """ app_name = multi_lang.get_text("EP020-0003", "ワークスペース情報:") exec_stat = multi_lang.get_text("EP020-0074", "CIパイプライン コンテナレジストリ情報取得") error_detail = "" try: globals.logger.debug('#' * 50) globals.logger.debug('CALL {}'.format(inspect.currentframe().f_code.co_name)) globals.logger.debug('#' * 50) # Workspace information acquisition URL - ワークスペース情報取得URL api_url = "{}://{}:{}/workspace/{}".format(os.environ['EPOCH_RS_WORKSPACE_PROTOCOL'], os.environ['EPOCH_RS_WORKSPACE_HOST'], os.environ['EPOCH_RS_WORKSPACE_PORT'], workspace_id) # Get Workspace information ― ワークスペース情報取得 response = requests.get(api_url) workspace_json = json.loads(response.text) if response.status_code != 200: error_detail = multi_lang.get_text("EP020-0089", "ワークスペース情報の取得に失敗しました") globals.logger.debug(error_detail) raise common.UserException(error_detail) git_user = workspace_json["rows"][0]["ci_config"]["pipelines_common"]["git_repositry"]["user"] # Request header for getting container registry information # コンテナレジストリ情報取得用 リクエストヘッダ request_headers = { 'Content-Type': 'application/json', 'username': workspace_json["rows"][0]["ci_config"]["pipelines_common"]["container_registry"]["user"], 'password': workspace_json["rows"][0]["ci_config"]["pipelines_common"]["container_registry"]["password"] } # CI result information acquisition URL - CI結果情報取得URL api_url = "{}://{}:{}/workspace/{}/tekton/task".format(os.environ['EPOCH_RS_CI_RESULT_PROTOCOL'], os.environ['EPOCH_RS_CI_RESULT_HOST'], os.environ['EPOCH_RS_CI_RESULT_PORT'], workspace_id) # Get CI result information ― CI結果情報取得 response = requests.get(api_url) ci_result_json = json.loads(response.text) if response.status_code != 200: error_detail = multi_lang.get_text("EP020-0088", "CI結果情報の取得に失敗しました") globals.logger.debug(error_detail) raise common.UserException(error_detail) rows = [] # Extract the repository information from the acquired CI result information and format it # 取得したCI結果情報の内、リポジトリ情報を抜き出して整形 for ci_result in ci_result_json["rows"]: # Container registry information acquisition URL - コンテナレジストリ情報取得URL api_url = "{}://{}:{}/registry/{}".format(os.environ['EPOCH_CONTROL_DOCKERHUB_PROTOCOL'], os.environ['EPOCH_CONTROL_DOCKERHUB_HOST'], os.environ['EPOCH_CONTROL_DOCKERHUB_PORT'], ci_result["container_registry_image"]) # Get container registry information - コンテナレジストリ情報取得 response = requests.post(api_url, headers=request_headers) registry_json = json.loads(response.text) if response.status_code != 200: error_detail = multi_lang.get_text("EP020-0075", "コンテナレジストリ情報の取得に失敗しました") globals.logger.debug(error_detail) raise common.UserException(error_detail) for registry in registry_json["rows"]: # Merge repository information with repository information that matches the registry name and image tag # レジストリ名とイメージタグが一致する、リポジトリ情報と、レジストリ情報をマージする if ci_result["container_registry_image"] in registry["name"] \ and ci_result["container_registry_image_tag"] in registry["tag"]: rows.append( { "registry": registry, "repository": { "name": "{}/{}".format(git_user, re.search('([^/]+?)(?=.git)', ci_result["git_repository_url"]).group()), "url": ci_result["git_repository_url"], "branch": ci_result["git_branch"] } } ) ret_status = 200 return jsonify({ "return": ret_status, "rows": rows }), ret_status except common.UserException as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail) except Exception as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail)
def settings_ita(workspace_id): """IT-Automation 設定 Args: workspace_id (int): workspace id Returns: Response: HTTP Respose """ app_name = "ワークスペース情報:" exec_stat = "IT-Automation初期設定" error_detail = "" try: globals.logger.debug('#' * 50) globals.logger.debug('CALL {}'.format( inspect.currentframe().f_code.co_name)) globals.logger.debug('#' * 50) ita_db_name = "ita_db" ita_db_user = "******" ita_db_password = "******" # パラメータ情報(JSON形式) payload = request.json.copy() # ワークスペースアクセス情報取得 access_info = api_access_info.get_access_info(workspace_id) # namespaceの取得 namespace = common.get_namespace_name(workspace_id) # *-*-*-* podが立ち上がるのを待つ *-*-*-* start_time = time.time() while True: globals.logger.debug("waiting for ita pod up...") # PodがRunningになったら終了 if is_ita_pod_running(namespace): break # timeout current_time = time.time() if (current_time - start_time) > WAIT_SEC_ITA_POD_UP: globals.logger.debug( "ITA pod start Time out S:{} sec:{}".format( start_time, (current_time - start_time))) error_detail = "IT-Automation 初期設定でタイムアウトしました。再度、実行してください。" raise common.UserException(error_detail) time.sleep(1) # *-*-*-* podが立ち上がるのを待つ *-*-*-* start_time = time.time() while True: globals.logger.debug("waiting for ita mariaDB up...") # PodがRunningになったら終了 if is_ita_mysql_running(namespace, ita_db_user, ita_db_password): break # timeout current_time = time.time() if (current_time - start_time) > WAIT_SEC_ITA_POD_UP: globals.logger.debug( "ITA mariaDB start Time out S:{} sec:{}".format( start_time, (current_time - start_time))) error_detail = "IT-Automation 初期設定でタイムアウトしました。再度、実行してください。" raise common.UserException(error_detail) time.sleep(1) # *-*-*-* パスワード更新済み判定とする *-*-*-* # command = "mysql -u %s -p%s %s < /app/epoch/tmp/ita_table_update.sql" % (ita_db_user, ita_db_password, ita_db_name) command = "mysql -u %s -p%s %s -e'UPDATE A_ACCOUNT_LIST SET PW_LAST_UPDATE_TIME = \"2999-12-31 23:59:58\" WHERE USER_ID = 1;'" % ( ita_db_user, ita_db_password, ita_db_name) stdout_ita = subprocess.check_output([ "kubectl", "exec", "-i", "-n", namespace, "deployment/it-automation", "--", "bash", "-c", command ], stderr=subprocess.STDOUT) # *-*-*-* 認証情報準備 *-*-*-* host = "{}.{}.svc:{}".format(EPOCH_ITA_HOST, namespace, EPOCH_ITA_PORT) user_id = access_info["ITA_USER"] user_init_pass = "******" user_pass = access_info["ITA_PASSWORD"] # パスワード暗号化 init_auth = base64.b64encode((user_id + ':' + user_init_pass).encode()) auth = base64.b64encode((user_id + ':' + user_pass).encode()) # すでに1度でもインポート済みの場合は、処理しない ret_is_import = is_already_imported(host, auth, init_auth) if ret_is_import == 200: globals.logger.debug("ITA initialize Imported.(success)") # 正常終了 ret_status = 200 # 戻り値をそのまま返却 return jsonify({"result": ret_status}), ret_status # 一度もインポートしていないときに処理する if ret_is_import == 0: # *-*-*-* インポート実行(初期パスワードで実行) *-*-*-* task_id = import_process(host, init_auth) # *-*-*-* インポート結果確認 *-*-*-* globals.logger.debug('---- monitoring import dialog ----') # POST送信する # ヘッダ情報 header = { 'host': host, 'Content-Type': 'application/json', 'Authorization': init_auth, 'X-Command': 'FILTER', } # 実行パラメータ設定 data = {"2": {"LIST": [task_id]}} # json文字列に変換("utf-8"形式に自動エンコードされる) json_data = json.dumps(data) start_time = time.time() while True: globals.logger.debug("monitoring...") time.sleep(3) # timeout current_time = time.time() if (current_time - start_time) > WAIT_SEC_ITA_IMPORT: globals.logger.debug("ITA menu import Time out") error_detail = "IT-Automation 初期設定でタイムアウトしました。再度、実行してください。" raise common.UserException(error_detail) # リクエスト送信 dialog_response = requests.post( 'http://' + host + '/default/menu/07_rest_api_ver1.php?no=2100000213', headers=header, data=json_data) if dialog_response.status_code != 200: globals.logger.error("no=2100000213 error:{}".format( dialog_response.status_code)) globals.logger.error(dialog_response.text) error_detail = "IT-Automation 初期設定が失敗しました。再度、実行してください。" # タイミングによって500応答が返されるため継続 # raise common.UserException(error_detail) continue # ファイルがあるメニューのため、response.textをデバッグ出力すると酷い目にあう # print(dialog_response.text) dialog_resp_data = json.loads(dialog_response.text) if dialog_resp_data["status"] != "SUCCEED" or dialog_resp_data[ "resultdata"]["CONTENTS"]["RECORD_LENGTH"] != 1: globals.logger.error("no=2100000213 status:{}".format( dialog_resp_data["status"])) globals.logger.error(dialog_response.text) error_detail = "IT-Automation 初期設定が失敗しました。再度、実行してください。" raise common.UserException(error_detail) record = dialog_resp_data["resultdata"]["CONTENTS"]["BODY"][1] globals.logger.debug(json.dumps(record)) if record[3] == u"完了(異常)": error_detail = "IT-Automation ITAのメニューインポートに失敗しました。" raise common.UserException(error_detail) if record[3] == u"完了": break error_detail = "IT-Automation 初期設定のパスワード初期化に失敗しました。" # *-*-*-* パスワード変更 *-*-*-* command = "mysql -u {} -p{} {} -e'UPDATE A_ACCOUNT_LIST".format(ita_db_user, ita_db_password, ita_db_name) + \ " SET PASSWORD = \"{}\"".format(hashlib.md5((user_pass).encode()).hexdigest()) + \ " WHERE USER_ID = 1;'" stdout_ita = subprocess.check_output([ "kubectl", "exec", "-i", "-n", namespace, "deployment/it-automation", "--", "bash", "-c", command ], stderr=subprocess.STDOUT) error_detail = "IT-Automation 初期設定のユーザー情報生成に失敗しました。" # *-*-*-* EPOCHユーザー更新 *-*-*-* command = "mysql -u {} -p{} {} -e'UPDATE A_ACCOUNT_LIST".format(ita_db_user, ita_db_password, ita_db_name) + \ " SET USERNAME = \"{}\"".format(access_info["ITA_EPOCH_USER"]) + \ " , PASSWORD = \"{}\"".format(hashlib.md5((access_info["ITA_EPOCH_PASSWORD"]).encode()).hexdigest()) + \ " , PW_LAST_UPDATE_TIME = \"2999-12-31 23:59:58\"" + \ " WHERE USER_ID = 2;'" stdout_ita = subprocess.check_output([ "kubectl", "exec", "-i", "-n", namespace, "deployment/it-automation", "--", "bash", "-c", command ], stderr=subprocess.STDOUT) # 正常終了 ret_status = 200 # 戻り値をそのまま返却 return jsonify({"result": ret_status}), ret_status except common.UserException as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail) except Exception as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail)
def get_ci_pipeline_result(workspace_id): """Get CI pipeline results (CIパイプライン結果取得) Args: workspace_id (int): WORKSPACE ID Returns: Response: HTTP Respose """ app_name = "ワークスペース情報:" exec_stat = "CIパイプライン結果取得" error_detail = "" try: globals.logger.debug('#' * 50) globals.logger.debug('CALL {}'.format(inspect.currentframe().f_code.co_name)) globals.logger.debug('#' * 50) # Get Query Parameter latest = request.args.get('latest', default='False') # ヘッダ情報 post_headers = { 'Content-Type': 'application/json', } # epoch-control-tekton-api の呼び先設定 api_url_tekton = "{}://{}:{}/workspace/{}/tekton/pipelinerun".format(os.environ["EPOCH_CONTROL_TEKTON_PROTOCOL"], os.environ["EPOCH_CONTROL_TEKTON_HOST"], os.environ["EPOCH_CONTROL_TEKTON_PORT"], workspace_id) # TEKTONパイプライン情報取得 exec_stat = "pipelinerun情報取得" request_response = requests.get(api_url_tekton, params={"latest": latest}) ret = json.loads(request_response.text) if request_response.status_code != 200: if "errorDetail" in ret: exec_detail = ret["errorDetail"] else: exec_detail = "" raise common.UserException(error_detail) rows = [] # globals.logger.debug(f'rows:{ret["rows"]}') for row in ret["rows"]: tasks = [] if row is None: continue if not "tasks" in row: continue for task in row["tasks"]: # globals.logger.debug(f'tasks:{task}') # taskにログがある場合のみ取得 # Get only if task has a log if "taskrun_name" in task: taskrun_name = task["taskrun_name"] # epoch-control-tekton-api の呼び先設定 api_url_tekton = "{}://{}:{}/workspace/{}/tekton/taskrun/{}/logs".format( os.environ["EPOCH_CONTROL_TEKTON_PROTOCOL"], os.environ["EPOCH_CONTROL_TEKTON_HOST"], os.environ["EPOCH_CONTROL_TEKTON_PORT"], workspace_id, taskrun_name) # TEKTONタスク実行ログ情報取得 exec_stat = "taskrunログ情報取得" request_response = requests.get(api_url_tekton, params={"latest": latest}) ret = json.loads(request_response.text) if request_response.status_code != 200: if "errorDetail" in ret: error_detail = ret["errorDetail"] else: error_detail = "" raise common.UserException(error_detail) # 取得したログをtaskの"log"として追加 # Add the acquired log as "log" of task task["log"] = ret["log"] tasks.append(task) # 成形したtaskの情報を上書き # Overwrite the information of the molded task row["tasks"] = tasks rows.append(row) # globals.logger.debug(f'rows:{rows}') ret_status = 200 response = { "result": ret_status, "rows" : rows, } # 戻り値をそのまま返却 return jsonify(response), ret_status except common.UserException as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail) except Exception as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail)
def get_github_webhooks(workspace_id): """webhooks 取得 Args: workspace_id (int): ワークスペースID Returns: Response: HTTP Respose """ app_name = "ワークスペース情報:" exec_stat = "GitHub WebHooks取得" error_detail = "" try: globals.logger.debug('#' * 50) globals.logger.debug('CALL {}'.format( inspect.currentframe().f_code.co_name)) globals.logger.debug('#' * 50) # 引数で指定されたCD環境を取得 request_json = json.loads(request.data) request_ci_confg = request_json["ci_config"] # パイプライン数分繰り返し for pipeline in request_ci_confg["pipelines"]: git_repos = re.sub( '\\.git$', '', re.sub('^https?://[^/][^/]*/', '', pipeline["git_repositry"]["url"])) token = request_ci_confg["pipelines_common"]["git_repositry"][ "token"] # GitHubへGET送信 # ヘッダ情報 request_headers = { 'Authorization': 'token ' + token, 'Accept': 'application/vnd.github.v3+json', } globals.logger.debug(git_repos) # GETリクエスト送信 request_response = requests.get(github_webhook_base_url + git_repos + github_webhook_base_hooks, headers=request_headers) ret_status = request_response.status_code if ret_status == '200': rows = request_response.text else: rows = [] # 戻り値をそのまま返却 return jsonify({"result": ret_status, "rows": rows}), ret_status except common.UserException as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail) except Exception as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail)
def cd_execute(workspace_id): """cd execute Returns: Response: HTTP Respose """ app_name = "ワークスペース情報:" exec_stat = "CD実行" error_detail = "" try: globals.logger.debug('#' * 50) globals.logger.debug('CALL {}'.format( inspect.currentframe().f_code.co_name)) globals.logger.debug('#' * 50) # パラメータ情報(JSON形式) prameter save payload = request.json.copy() # ワークスペースアクセス情報取得 get workspace access info. access_info = api_access_info.get_access_info(workspace_id) # namespaceの取得 get namespace namespace = common.get_namespace_name(workspace_id) ita_restapi_endpoint = "http://{}.{}.svc:{}/default/menu/07_rest_api_ver1.php".format( EPOCH_ITA_HOST, namespace, EPOCH_ITA_PORT) ita_user = access_info['ITA_USER'] ita_pass = access_info['ITA_PASSWORD'] operation_id = payload["operation_id"] conductor_class_no = payload["conductor_class_no"] preserve_datetime = payload["preserve_datetime"] # POST送信する # HTTPヘッダの生成 filter_headers = { 'host': EPOCH_ITA_HOST + ':' + EPOCH_ITA_PORT, 'Content-Type': 'application/json', 'Authorization': base64.b64encode( (ita_user + ':' + ita_pass).encode()), 'X-Command': 'EXECUTE', } # 実行パラメータ設定 data = { "CONDUCTOR_CLASS_NO": conductor_class_no, "OPERATION_ID": operation_id, "PRESERVE_DATETIME": preserve_datetime, } # json文字列に変換("utf-8"形式に自動エンコードされる) json_data = json.dumps(data) # リクエスト送信 exec_response = requests.post(ita_restapi_endpoint + '?no=' + ite_menu_conductor_exec, headers=filter_headers, data=json_data) if exec_response.status_code != 200: globals.logger.error(exec_response.text) error_detail = multi_lang.get_text( "EP034-0001", "CD実行の呼び出しに失敗しました status:{0}".format( exec_response.status_code), exec_response.status_code) raise common.UserException(error_detail) globals.logger.debug("-------------------------") globals.logger.debug("response:") globals.logger.debug(exec_response.text) globals.logger.debug("-------------------------") resp_data = json.loads(exec_response.text) if resp_data["status"] != "SUCCEED": globals.logger.error("no={} status:{}".format( ite_menu_conductor_exec, resp_data["status"])) error_detail = multi_lang.get_text( "EP034-0002", "CD実行の呼び出しに失敗しました ita-status:{0} resultdata:{1}".format( resp_data["status"], resp_data["resultdata"]), resp_data["status"], resp_data["resultdata"]) raise common.UserException(error_detail) if resp_data["status"] != "SUCCEED": globals.logger.error("no={} status:{}".format( ite_menu_conductor_exec, resp_data["status"])) error_detail = multi_lang.get_text( "EP034-0002", "CD実行の呼び出しに失敗しました ita-status:{0} resultdata:{1}".format( resp_data["status"], resp_data["resultdata"]), resp_data["status"], resp_data["resultdata"]) raise common.UserException(error_detail) # 戻り値が"000"以外の場合は、エラーを返す # If the return value is other than "000", an error is returned. if resp_data["resultdata"]["RESULTCODE"] != "000": globals.logger.error("RESULTCODE error: resultdata:{}".format( resp_data["resultdata"])) error_detail = resp_data["resultdata"]["RESULTINFO"] raise common.UserException(error_detail) # 作業IDを退避 cd_result_id = resp_data["resultdata"]["CONDUCTOR_INSTANCE_ID"] # 正常終了 ret_status = 200 # 戻り値をそのまま返却 return jsonify({ "result": ret_status, "cd_result_id": cd_result_id }), ret_status except common.UserException as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail) except Exception as e: return common.server_error_to_message(e, app_name + exec_stat, error_detail)