def delete(self, request): """ :param request: :return: """ if self.jira_client is None: try: self.jira_client = init_jira_client() except Exception as exc: logger.warn('Could not log into Jira, skip it') return Response(STATUS_OK) wh = self.jira_client.get_ax_webhook() if not wh: logger.warn('No webhook on Jira server, ignore it') return Response(STATUS_OK) # Delete ingress try: logger.info('Deleting ingress for Jira webhook %s', wh['url']) axsys_client.delete_ingress(urlparse(wh['url']).netloc) except Exception as exc: logger.error('Failed to delete ingress for webhook: %s', str(exc)) raise AXApiInternalError('Failed to delete ingress for webhook', str(exc)) else: logger.info('Successfully deleted ingress for webhook') # Delete webhook try: self.jira_client.delete_ax_webhook() except Exception as exc: logger.exception(exc) raise AXApiInternalError('Fail to delete jira webhooks', detail=str(exc)) return Response(STATUS_OK)
def delete_webhook(): jira_client = Gateway.init_jira_client(gateway.axops_client) wh = jira_client.get_ax_webhook() if not wh: logger.warning('No webhook on Jira server, ignore it') return jsonify({}) # Delete ingress try: logger.info('Deleting ingress for Jira webhook %s', wh['url']) gateway.axsys_client.delete_ingress(urlparse(wh['url']).netloc) except Exception as exc: logger.error('Failed to delete ingress for webhook: %s', str(exc)) raise AXApiInternalError('Failed to delete ingress for webhook', str(exc)) else: logger.info('Successfully deleted ingress for webhook') # Delete webhook try: jira_client.delete_ax_webhook() except Exception as exc: logger.exception(exc) raise AXApiInternalError('Fail to delete jira webhooks', detail=str(exc)) return jsonify({})
def _put_file(repo, branch, path): """Put a file in s3. :param repo: :param branch: :param path: :return: """ _, vendor, repo_owner, repo_name = parse_repo(repo) workspace = '{}/{}/{}/{}'.format(BASE_DIR, vendor, repo_owner, repo_name) if not os.path.isdir(workspace): raise AXApiInvalidParam('Invalid repository', 'Invalid repository ({})'.format(repo)) try: logger.info( 'Extracting file content from repository (repo: %s, branch: %s, path: %s) ...', repo, branch, path) git_client = GitClient(path=workspace, read_only=True) files = git_client.get_files(branch=branch, subdir=path, binary_mode=True) except Exception as e: message = 'Failed to extract file content' detail = '{}: {}'.format(message, str(e)) logger.error(detail) raise AXApiInternalError(message, detail) else: if len(files) == 0: raise AXApiInvalidParam( 'Unable to locate file with given information') file_content = files[0]['content'] logger.info('Successfully extracted file content') try: # Cluster name id always has the form <cluster_name>-<36_bytes_long_cluster_id> cluster_name, cluster_id = CLUSTER_NAME_ID[:-37], CLUSTER_NAME_ID[-36:] key = '{cluster_name}/{cluster_id}/{vendor}/{repo_owner}/{repo_name}/{branch}/{path}'.format( cluster_name=cluster_name, cluster_id=cluster_id, vendor=vendor, repo_owner=repo_owner, repo_name=repo_name, branch=branch, path=path) logger.info('Uploading file content to s3 (bucket: %s, key: %s) ...', S3_BUCKET_NAME, key) response = s3_bucket.Object(key).put(Body=file_content) etag = response.get('ETag') if etag: etag = json.loads(etag) except Exception as e: message = 'Failed to upload file content' detail = '{}: {}'.format(message, str(e)) logger.error(detail) raise AXApiInternalError(message, detail) else: logger.info('Successfully uploaded file content') return {'bucket': S3_BUCKET_NAME, 'key': key, 'etag': etag}
def delete_webhook(self, vendor, repo): """Delete webhook :param vendor: :param repo: :returns: """ # Delete webhook try: logger.info('Deleting webhook (repo: %s) ...', repo) self.scm_clients[vendor].delete_webhook(repo) except AXApiAuthFailed as e: logger.error('Invalid credential supplied') detail = { 'repo': repo, 'error': 'Invalid credential supplied:' + str(e) } self.event_notification_client.send_message_to_notification_center(CODE_JOB_CI_WEBHOOK_DELETION_FAILURE, detail=detail) raise AXApiInvalidParam('User authentication failed', detail=str(e)) except AXApiForbiddenReq as e: logger.error('Supplied credential is valid but having insufficient permission') detail = { 'repo': repo, 'error': 'Supplied credential is valid but having insufficient permission:' + str(e) } self.event_notification_client.send_message_to_notification_center(CODE_JOB_CI_WEBHOOK_DELETION_FAILURE, detail=detail) raise AXApiInvalidParam('User has insufficient permission', detail=str(e)) except Exception as e: logger.error('Failed to delete webhook: %s', e) detail = { 'repo': repo, 'error': 'Failed to delete webhook:' + str(e) } self.event_notification_client.send_message_to_notification_center(CODE_JOB_CI_WEBHOOK_DELETION_FAILURE, detail=detail) raise AXApiInternalError('Failed to delete webhook', str(e)) else: logger.info('Successfully deleted webhook (repo: %s)', repo) # Delete ELB try: if not self.has_webhook(repo): logger.info('Deleting ELB for webhook ...') self.axsys_client.delete_webhook() except Exception as e: logger.error('Failed to delete ELB for webhook: %s', str(e)) detail = {'repo': repo, 'error': 'Failed to delete ELB for webhook' + str(e) } self.event_notification_client.send_message_to_notification_center(CODE_JOB_CI_ELB_DELETION_FAILURE, detail=detail) raise AXApiInternalError('Failed to delete ELB for webhook', str(e)) else: logger.info('Successfully deleted ELB for webhook') return {}
def _delete_file(repo, branch, path): """Delete a file from s3. :param repo: :param branch: :param path: :return: """ _, vendor, repo_owner, repo_name = Gateway.parse_repo(repo) try: cluster_name, cluster_id = Gateway.CLUSTER_NAME_ID[: -37], Gateway.CLUSTER_NAME_ID[ -36:] key = '{cluster_name}/{cluster_id}/{vendor}/{repo_owner}/{repo_name}/{branch}/{path}'.format( cluster_name=cluster_name, cluster_id=cluster_id, vendor=vendor, repo_owner=repo_owner, repo_name=repo_name, branch=branch, path=path) logger.info('Deleting file from s3 (bucket: %s, key: %s) ...', Gateway.S3_BUCKET_NAME, key) Gateway.s3_bucket.Object(key).delete() except Exception as e: message = 'Failed to delete file' detail = '{}: {}'.format(message, str(e)) logger.error(detail) raise AXApiInternalError(message, detail) else: logger.info('Successfully deleted file') return {'bucket': Gateway.S3_BUCKET_NAME, 'key': key}
def update_security_group(self, ip, port, target, add_or_remove=True): """Add/remove security group :param ip: in the form of '0.0.0.0/0'. :param port: :param target: :param add_or_remove: true for add, false for remove :returns: """ try: payload = { 'target': target, 'action': 'enable' if add_or_remove else 'disable', 'port': port, 'ip_ranges': [ip] } return self._axmon_client.put('/v1/security_groups', data=json.dumps(payload), value_only=True) except HTTPError as e: logger.error('Failed to add security group (%s)', str(e)) status_code = e.response.status_code if 400 <= status_code < 500 and status_code != 404: error = AXApiInvalidParam else: error = AXApiInternalError error_payload = e.response.json() raise error(message=error_payload.get('message', ''), detail=error_payload.get('detail', '')) except Exception as e: message = 'Failed to add security group' detail = 'Failed to add security group ({})'.format(str(e)) logger.error(detail) raise AXApiInternalError(message=message, detail=detail)
def purge_branches(self, repo, branch=None): """Purge branch heads. :param repo: :param branch: :return: """ if not repo: raise AXApiInvalidParam('Missing required parameter', 'Missing required parameter (repo)') logger.info('Purging branch heads (repo: %s, branch: %s) ...', repo, branch) try: if not branch: self.axdb_client.purge_branch_heads(repo) else: self.axdb_client.purge_branch_head(repo, branch) except Exception as e: message = 'Unable to purge branch heads' detail = 'Unable to purge branch heads (repo: {}, branch: {}): {}'.format( repo, branch, str(e)) logger.error(detail) raise AXApiInternalError(message, detail) else: logger.info('Successfully purged branch heads')
def reports(): """Report build/test status to source control tool.""" payload = get_json() logger.info('Received reporting request (payload: %s)', payload) report_id = payload.get('id') repo = payload.get('repo') if not report_id: raise AXApiInvalidParam('Missing required parameters', detail='Required parameters (id)') try: if not repo: cache = gateway.redis_client.get(report_id, decoder=json.loads) repo = cache['repo'] vendor = gateway.axops_client.get_tool(repo)['type'] if vendor not in gateway.scm_clients.keys(): raise AXApiInvalidParam( 'Invalid parameter values', detail='Unsupported type ({})'.format(vendor)) result = gateway.scm_clients[vendor].upload_job_result(payload) if result == -1: logger.info( 'GitHub does not support status report for the non-sha commits. Skip.' ) except Exception as e: logger.error('Failed to report status: %s', e) gateway.event_notification_client.send_message_to_notification_center( CODE_JOB_CI_STATUS_REPORTING_FAILURE, detail=payload) raise AXApiInternalError('Failed to report status', detail=str(e)) else: logger.info('Successfully reported status') return jsonify(result)
def put(self, request, pk=None): """ :param request: :param pk: :return: """ if self.jira_client is None: self.jira_client = init_jira_client() projects = request.data.get('projects', None) logger.info('Received jira webhook update request ...') # Update webhook try: if projects: logger.info('Filtered projects are: %s', projects) if type(projects) == str: projects = json.loads(projects) else: logger.info('No project filter') projects = None self.jira_client.update_ax_webhook(projects) except Exception as exc: logger.exception(exc) raise AXApiInternalError('Fail to update jira webhooks', detail=str(exc)) else: logger.info('Successfully updated Jira webhook') return Response(STATUS_OK)
def _verify_elb(hostname): try: logger.info('Verifying ELB (%s) ...', hostname) ip = socket.gethostbyname(hostname) logger.info('Successfully resolved ELB (%s) to IP (%s)', hostname, ip) except Exception as e: logger.error('ELB not ready: %s', str(e)) raise AXApiInternalError('ELB not ready', str(e))
def create_webhook(): payload = get_json() logger.info('Received jira webhook creation request, %s', payload) url = payload.get('url', None) username = payload.get('username', None) password = payload.get('password', None) webhook = payload.get('webhook', None) projects = payload.get('projects', None) # Create ingress try: dnsname = urlparse(webhook).netloc logger.info('Creating ingress for Jira webhook %s', dnsname) gateway.axsys_client.create_ingress(dnsname) except Exception as exc: logger.error('Failed to create ingress for webhook: %s', str(exc)) raise AXApiInternalError('Failed to create ingress for webhook', str(exc)) else: logger.info('Successfully created ingress for webhook') # Create webhook jira_client = Gateway.init_jira_client(gateway.axops_client, url=url, username=username, password=password) try: if projects: logger.info('Filtered projects are: %s', projects) if type(projects) == str: projects = json.loads(projects) else: logger.info('No project filter') projects = None wh = jira_client.create_ax_webhook(webhook, projects=projects) except Exception as exc: logger.exception(exc) raise AXApiInternalError('Fail to create Jira webhooks', detail=str(exc)) return jsonify(wh.json())
def test_project(): payload = get_json() url = payload.get('url', '').lower() username = payload.get('username', None) password = payload.get('password', None) logger.info('Received request (url: %s, username: %s, password: ******)', url, username) assert all([url, username, password]), \ AXApiInvalidParam('Missing required parameters', detail='Required parameters (username, password, url)') try: Gateway.init_jira_client(url, username, password) except requests.exceptions.ConnectionError as exc: raise AXApiInternalError('Invalid URL', detail=str(exc)) except jira.exceptions.JIRAError as exc: raise AXApiInternalError('Invalid authentication', detail=str(exc)) except Exception as exc: raise AXApiInternalError('Failed to connect to JIRA', detail=str(exc)) else: return jsonify({})
def events(self, request): """Create a DevOps event. :param request: :return: """ payload, headers = request.data, request.META try: logger.info('Translating SCM event ...') events = EventTranslator.translate(payload, headers) except Exception as e: logger.error('Failed to translate event: %s', e) # Todo Tianhe Issue: #330 comment out for now because it is distracting # event_notification_client.send_message_to_notification_center(CODE_JOB_CI_EVENT_TRANSLATE_FAILURE, # detail={ # 'payload': payload, # 'error': str(e) # }) raise AXApiInternalError('Failed to translate event', detail=str(e)) else: logger.info('Successfully translated event') kafka_client = ProducerClient() successful_events = [] for event in events: if event['type'] == AxEventTypes.PING: logger.info( 'Received a PING event, skipping service creation ...') continue else: try: logger.info('Creating AX event ...\n%s', AxPrettyPrinter().pformat(event)) key = '{}_{}_{}'.format(event['repo'], event['branch'], event['commit']) kafka_client.send(AxSettings.TOPIC_DEVOPS_CI_EVENT, key=key, value=event, timeout=120) except Exception as e: event_notification_client.send_message_to_notification_center( CODE_JOB_CI_EVENT_CREATION_FAILURE, detail={ 'event_type': event.get('type', 'UNKNOWN'), 'error': str(e) }) logger.warning('Failed to create AX event: %s', e) else: logger.info('Successfully created AX event') successful_events.append(event) kafka_client.close() return Response(successful_events)
def create_jira_event(): checked_fields = ('description', 'project', 'status', 'summary', 'Key') delete_event = 'jira:issue_deleted' update_event = 'jira:issue_updated' payload = get_json() try: logger.info('Translating JIRA event ...') event = translate_jira_issue_event(payload) except Exception as exc: logger.error('Failed to translate event: %s', exc) raise AXApiInternalError('Failed to translate event', detail=str(exc)) else: logger.info('Successfully translated event: %s', event) try: if event['type'] == delete_event: logger.info('The following Jira field(s) get updated: %s', event['changed_fields']) if event['status_category_id'] == 3: logger.info('Jira issue %s is closed', event['id']) logger.info('Delete Jira on AXDB %s', event['id']) gateway.axops_client.delete_jira_issue(event['id']) elif event['changed_fields'] and any(f in event['changed_fields'] for f in checked_fields): logger.info('Update Jira content on AXDB ...') gateway.axops_client.update_jira_issue(event['axdb_content']) else: logger.info('No Jira content need to be updated') elif event['type'] == update_event: logger.info('Delete Jira on AXDB %s', event['id']) gateway.axops_client.delete_jira_issue(event['id']) else: logger.warning('Not supported event: (%s), ignore it', event['type']) except Exception as exc: raise AXApiInternalError('Failed to update JIRA content on AXDB', detail=str(exc)) else: return jsonify({})
def events(request): """Create a JIRA webhook event. :param request: :return: """ checked_fields =('description', 'project', 'status', 'summary', 'Key') payload = request.data try: logger.info('Translating JIRA event ...') event = translate_jira_issue_event(payload) except Exception as exc: logger.error('Failed to translate event: %s', exc) raise AXApiInternalError('Failed to translate event', detail=str(exc)) else: logger.info('Successfully translated event: %s', event) try: if event['type'] == UPDATE_EVENT: logger.info('The following Jira field(s) get updated: %s', event['changed_fields']) if event['status_category_id'] == 3: logger.info('Jira issue %s is closed', event['id']) logger.info('Delete Jira on AXDB %s', event['id']) axops_client.delete_jira_issue(event['id']) elif event['changed_fields'] and any(f in event['changed_fields'] for f in checked_fields): logger.info('Update Jira content on AXDB ...') axops_client.update_jira_issue(event['axdb_content']) else: logger.info('No Jira content need to be updated') elif event['type'] == DELETE_EVENT: logger.info('Delete Jira on AXDB %s', event['id']) axops_client.delete_jira_issue(event['id']) else: logger.warn('Not supported event: (%s), ignore it', event['type']) except Exception as exc: raise AXApiInternalError('Failed to update JIRA content on AXDB', detail=str(exc)) else: return Response(STATUS_OK)
def yamls(self, request): """Update YAML contents (i.e. policy, template). :param request: :return: """ vendor = request.data.get('type') repo = request.data.get('repo') branch = request.data.get('branch') if not all([vendor, repo, branch]): raise AXApiInvalidParam( 'Missing required parameters', detail='Required parameters (type, repo, branch)') if vendor not in self.scm_clients.keys(): raise AXApiInvalidParam( 'Invalid parameter values', detail='Unsupported type ({})'.format(vendor)) try: # The arrival of events may not always be in the natural order of commits. For # example, the user may resent an old event from UI of source control tool. In # this case, we may update the YAML contents to an older version. To avoid this, # we guarantee that every YAML update will only update the content to the latest # version on a branch. More specifically, whenever we receive an event, we extract # the repo and branch information, and find the HEAD of the branch. Then, we use # the commit of HEAD to retrieve the YAML content, and update policies/templates # correspondingly. scm_client = self.scm_clients[vendor] commit = scm_client.get_branch_head(repo, branch) yaml_files = scm_client.get_yamls(repo, commit) logger.info('Updating YAML contents (policy/template) ...') axops_client.update_yamls(repo, branch, commit, yaml_files) except Exception as e: if 'Branch not found' in e.message: logger.info('No need to update YAML contents') return Response() else: logger.error('Failed to update YAML contents: %s', e) event_notification_client.send_message_to_notification_center( CODE_JOB_CI_YAML_UPDATE_FAILURE, detail={ 'vendor': vendor, 'repo': repo, 'branch': branch, 'error': str(e) }) raise AXApiInternalError('Failed to update YAML contents', str(e)) else: logger.info('Successfully updated YAML contents') return Response()
def create(self, request): """ :param request: :return: """ logger.info('Received jira webhook creation request') url = request.data.get('url', None) username = request.data.get('username', None) password = request.data.get('password', None) webhook = request.data.get('webhook', None) projects = request.data.get('projects', None) # Create ingress try: dnsname = urlparse(webhook).netloc logger.info('Creating ingress for Jira webhook %s', dnsname) axsys_client.create_ingress(dnsname) except Exception as exc: logger.error('Failed to create ingress for webhook: %s', str(exc)) raise AXApiInternalError('Failed to create ingress for webhook', str(exc)) else: logger.info('Successfully created ingress for webhook') # Create webhook self.jira_client = init_jira_client(url=url, username=username, password=password) try: if projects: logger.info('Filtered projects are: %s', projects) if type(projects) == str: projects = json.loads(projects) else: logger.info('No project filter') projects = None wh = self.jira_client.create_ax_webhook(webhook, projects=projects) except Exception as exc: logger.exception(exc) raise AXApiInternalError('Fail to create jira webhooks', detail=str(exc)) return Response(wh.json())
def test(self, request): """Test connection to Jira server. :param request: :return: """ url = request.data.get('url', '').lower() username = request.data.get('username', None) password = request.data.get('password', None) logger.info('Received request (url: %s, username: %s, password: ******)', url, username) assert all([url, username, password]), \ AXApiInvalidParam('Missing required parameters', detail='Required parameters (username, password, url)') try: init_jira_client(url, username, password) except requests.exceptions.ConnectionError as exc: raise AXApiInternalError('Invalid URL', detail=str(exc)) except jira.exceptions.JIRAError as exc: raise AXApiInternalError('Invalid authentication', detail=str(exc)) except Exception as exc: raise AXApiInternalError('Failed to connect to JIRA', detail=str(exc)) else: return Response(STATUS_OK)
def add_comment(issue_id): jira_client = Gateway.init_jira_client(gateway.axops_client) payload = get_json() comment = payload.get('comment', None) user = payload.get('user', None) if not comment: raise AXApiInvalidParam('Require Comment message info') if not user: raise AXApiInvalidParam('Require Commenter info') try: jira_client.add_issue_comment(issue_id, comment, commenter=user) except Exception as exc: raise AXApiInternalError('Failed to add comment', detail=str(exc)) return jsonify({})
def match_patterns(patterns, string): """Match branch. :param patterns: :param string: :return: """ for pattern in patterns: try: match = re.match(pattern, string) except Exception as e: logger.error('Failed to match pattern (pattern: %s, string: %s): %s', pattern, string, e) raise AXApiInternalError('Failed to match pattern', detail=str(e)) else: if match: return True return False
def delete_webhook(self): """Delete webhook""" try: self._axmon_client.delete('/v1/webhook') except HTTPError as e: logger.error('Failed to delete webhook: %s', str(e)) status_code = e.response.status_code if 400 <= status_code < 500 and status_code != 404: error = AXApiInvalidParam else: error = AXApiInternalError error_payload = e.response.json() raise error(message=error_payload.get('message', ''), detail=error_payload.get('detail', '')) except Exception as e: message = 'Failed to delete webhook' detail = 'Failed to delete webhook ({})'.format(str(e)) logger.error(detail) raise AXApiInternalError(message=message, detail=detail)
def _download_artifact(params): """Download an artifact :param params: :returns: """ if 'artifact_id' in params: _params = {'artifact_id': params['artifact_id']} elif 'service_instance_id' in params: if 'name' in params: _params = { 'service_instance_id': params['service_instance_id'], 'name': params['name'] } elif 'retention_tags' in params and params['retention_tags'] == RETENTION_TAG_USER_LOG: _params = { 'service_instance_id': params['service_instance_id'], 'retention_tags': params['retention_tags'] } elif 'retention_tags' in params and params['retention_tags'] != RETENTION_TAG_USER_LOG: raise AXApiInvalidParam('Invalid parameter value', 'Can only download {} artifacts when "name" is not supplied'.format(RETENTION_TAG_USER_LOG)) else: raise AXApiInvalidParam('Missing required parameter', 'Must supply either "name" or "retention_tags" when supplying "service_instance_id"') elif 'workflow_id' in params: if 'full_path' not in params or 'name' not in params: raise AXApiInvalidParam('Missing required parameter', 'Must supply both "full_path" and "name" when supplying "workflow_id"') _params = { 'workflow_id': params['workflow_id'], 'full_path': params['full_path'], 'name': params['name'] } else: raise AXApiInvalidParam('Missing required parameter', 'Must supply "artifact_id", "service_instance_id", or "workflow_id"') location, content = artifact_manager.download_artifact_by_query(**_params) if location: return redirect(location, code=302) if content: return Response(content) else: raise AXApiInternalError('Internal Error')
def create(self, request): """ :param request: :return: """ if self.jira_client is None: self.jira_client = init_jira_client() logger.info('Received jira issue creation request (%s)', request.data) project = request.data.get('project', None) summary = request.data.get('summary', None) issuetype = request.data.get('issuetype', None) reporter = request.data.get('reporter', None) description = request.data.get('description', None) # optional if project is None: raise AXApiInvalidParam('Missing required parameters: Project', detail='Missing required parameters, Project') if summary is None: raise AXApiInvalidParam('Missing required parameters: Summary', detail='Missing required parameters, Summary') if issuetype is None: raise AXApiInvalidParam('Missing required parameters: Issuetype', detail='Missing required parameters, Issuetype') if reporter is None: raise AXApiInvalidParam('Missing required parameters: Reporter', detail='Missing required parameters, Reporter') try: issue_obj = self.jira_client.create_issue(project, summary, issuetype=issuetype, reporter=reporter, description=description) except jira.exceptions.JIRAError as exc: raise AXApiInternalError('Invalid Parameters', detail=str(exc)) else: issue_dict = copy.deepcopy(issue_obj.raw['fields']) issue_dict['url'] = issue_obj.self issue_dict['id'] = issue_obj.id issue_dict['key'] = issue_obj.key return Response(issue_dict)
def addcomment(self, request, pk=None): """ :param request: :param pk: :return: """ if self.jira_client is None: self.jira_client = init_jira_client() comment = request.data.get('comment', None) user = request.data.get('user', None) if not comment: raise AXApiInvalidParam('Require Comment message info') if not user: raise AXApiInvalidParam('Require Commenter info') try: self.jira_client.add_issue_comment(pk, comment, commenter=user) except Exception as exc: raise AXApiInternalError('Failed to add comment', detail=str(exc)) return Response(STATUS_OK)
def modify_webhook(): jira_client = Gateway.init_jira_client(gateway.axops_client) payload = get_json() projects = payload.get('projects', None) logger.info('Received jira webhook update request, %s', payload) # Update webhook try: if projects: logger.info('Filtered projects are: %s', projects) if type(projects) == str: projects = json.loads(projects) else: logger.info('No project filter') projects = None jira_client.update_ax_webhook(projects) except Exception as exc: logger.exception(exc) raise AXApiInternalError('Fail to update jira webhooks', detail=str(exc)) else: logger.info('Successfully updated Jira webhook') return jsonify({})
def create_issue(): jira_client = Gateway.init_jira_client(gateway.axops_client) payload = get_json() logger.info('Received Jira issue creation request (%s)', payload) project = payload.get('project', None) summary = payload.get('summary', None) issuetype = payload.get('issuetype', None) reporter = payload.get('reporter', None) description = payload.get('description', None) # optional if project is None: raise AXApiInvalidParam('Missing required parameters: Project', detail='Missing required parameters, Project') if summary is None: raise AXApiInvalidParam('Missing required parameters: Summary', detail='Missing required parameters, Summary') if issuetype is None: raise AXApiInvalidParam( 'Missing required parameters: Issuetype', detail='Missing required parameters, Issuetype') if reporter is None: raise AXApiInvalidParam('Missing required parameters: Reporter', detail='Missing required parameters, Reporter') try: issue_obj = jira_client.create_issue(project, summary, issuetype=issuetype, reporter=reporter, description=description) except jira.exceptions.JIRAError as exc: raise AXApiInternalError('Invalid Parameters', detail=str(exc)) else: issue_dict = copy.deepcopy(issue_obj.raw['fields']) issue_dict['url'] = issue_obj.self issue_dict['id'] = issue_obj.id issue_dict['key'] = issue_obj.key return jsonify(issue_dict)
def test(self, request): """Test connection to SCM server. :param request: :return: """ scm_type = request.data.get('type', '').lower() url = request.data.get('url', '').lower() username = request.data.get('username', None) password = request.data.get('password', None) logger.info( 'Received request (type: %s, url: %s, username: %s, password: ******)', scm_type, url, username) if not scm_type: raise AXApiInvalidParam('Missing required parameters', detail='Required parameters (type)') if scm_type not in SUPPORTED_TYPES: raise AXApiInvalidParam( 'Invalid parameter values', detail='Unsupported type ({})'.format(scm_type)) if scm_type == TYPE_GIT: assert url, AXApiInvalidParam( 'Missing required parameters', detail='Require parameter (url) when type is {}'.format( TYPE_GIT)) else: assert all([username, password]), AXApiInvalidParam( 'Missing required parameters', detail='Required parameters (username, password, url)') try: repos = self.get_repos(scm_type, url, username, password) except Exception as e: logger.warning('Failed to get repositories: %s', e) raise AXApiInternalError('Failed to get repositories', detail=str(e)) else: return Response({'repos': repos})
def create_webhook(self, ip_range, external_port, internal_port): """Create webhook :param ip_range: :param external_port: :param internal_port: :returns: """ try: payload = { 'port_spec': [{ 'name': 'webhook', 'port': external_port, 'targetPort': internal_port }], 'ip_ranges': ip_range } return self._axmon_client.put('/v1/webhook', data=json.dumps(payload), value_only=True) except HTTPError as e: logger.error('Failed to create webhook: %s', str(e)) status_code = e.response.status_code if 400 <= status_code < 500 and status_code != 404: error = AXApiInvalidParam else: error = AXApiInternalError error_payload = e.response.json() raise error(message=error_payload.get('message', ''), detail=error_payload.get('detail', '')) except Exception as e: message = 'Failed to create webhook' detail = 'Failed to create webhook ({})'.format(str(e)) logger.error(detail) raise AXApiInternalError(message=message, detail=detail)
def test(): """Test connection to SCM server.""" payload = get_json() scm_type = payload.get('type', '').lower() url = payload.get('url', '').lower() username = payload.get('username', None) password = payload.get('password', None) logger.info( 'Received request (type: %s, url: %s, username: %s, password: ******)', scm_type, url, username) if not scm_type: raise AXApiInvalidParam('Missing required parameters', detail='Required parameters (type)') if scm_type not in SUPPORTED_TYPES: raise AXApiInvalidParam( 'Invalid parameter values', detail='Unsupported type ({})'.format(scm_type)) if scm_type == ScmVendors.GIT: assert url, AXApiInvalidParam( 'Missing required parameters', detail='Require parameter (url) when type is {}'.format( ScmVendors.GIT)) else: assert all([username, password]), AXApiInvalidParam( 'Missing required parameters', detail='Required parameters (username, password, url)') try: repos = gateway.get_repos(scm_type=scm_type, url=url, username=username, password=password) except Exception as e: logger.warning('Failed to get repositories: %s', e) raise AXApiInternalError('Failed to get repositories', detail=str(e)) else: return jsonify({'repos': repos})
def create_webhook(self, vendor, repo): """Create webhook :param vendor: :param repo: :returns: """ @retry(wait_fixed=5000, stop_max_delay=20 * 60 * 1000) def _verify_elb(hostname): try: logger.info('Verifying ELB (%s) ...', hostname) ip = socket.gethostbyname(hostname) logger.info('Successfully resolved ELB (%s) to IP (%s)', hostname, ip) except Exception as e: logger.error('ELB not ready: %s', str(e)) raise AXApiInternalError('ELB not ready', str(e)) ip_range = self.scm_clients[vendor].get_webhook_whitelist() # Create ELB payload = {'ip_range': ip_range, 'external_port': 8443, 'internal_port': 8087} try: logger.info('Creating ELB for webhook ...') result = self.axsys_client.create_webhook(**payload) except Exception as e: logger.error('Failed to create ELB for webhook: %s', str(e)) self.event_notification_client.send_message_to_notification_center(CODE_JOB_CI_ELB_CREATION_FAILURE, detail=payload) raise AXApiInternalError('Failed to create ELB for webhook', str(e)) else: logger.info('Successfully created ELB for webhook') # Verify ELB hostname = result['hostname'] try: _verify_elb(hostname) except Exception as e: logger.error('Timed out on waiting for ELB to be available: %s', str(e)) self.event_notification_client.send_message_to_notification_center(CODE_JOB_CI_ELB_VERIFICATION_TIMEOUT, detail={'hostname': hostname}) raise AXApiInternalError('Timed out on waiting for ELB to be available: %s' % str(e)) # Create webhook try: logger.info('Creating webhook (repo: %s) ...', repo) self.scm_clients[vendor].create_webhook(repo) except AXApiAuthFailed as e: logger.error('Invalid credential supplied') detail = { 'repo': repo, 'error': 'Invalid credential supplied:' + str(e) } self.event_notification_client.send_message_to_notification_center(CODE_JOB_CI_WEBHOOK_CREATION_FAILURE, detail=detail) raise AXApiInvalidParam('User authentication failed', detail=str(e)) except AXApiForbiddenReq as e: logger.error('Supplied credential is valid but having insufficient permission') detail = { 'repo': repo, 'error': 'Supplied credential is valid but having insufficient permission:' + str(e) } self.event_notification_client.send_message_to_notification_center(CODE_JOB_CI_WEBHOOK_CREATION_FAILURE, detail=detail) raise AXApiInvalidParam('User has insufficient permission', detail=str(e)) except Exception as e: logger.error('Failed to configure webhook: %s', e) detail = { 'repo': repo, 'error': 'Failed to configure webhook:' + str(e) } self.event_notification_client.send_message_to_notification_center(CODE_JOB_CI_WEBHOOK_CREATION_FAILURE, detail=detail) raise AXApiInternalError('Failed to configure webhook', str(e)) else: logger.info('Successfully created webhook (repo: %s)', repo) return {}