Example #1
0
    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)
Example #2
0
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({})
Example #3
0
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}
Example #4
0
    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 {}
Example #5
0
    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}
Example #6
0
    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)
Example #7
0
    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')
Example #8
0
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)
Example #9
0
    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)
Example #10
0
 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))
Example #11
0
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())
Example #12
0
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({})
Example #13
0
    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)
Example #14
0
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({})
Example #15
0
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)
Example #16
0
    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()
Example #17
0
    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())
Example #18
0
    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)
Example #19
0
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({})
Example #20
0
    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
Example #21
0
 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)
Example #22
0
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')
Example #23
0
    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)
Example #24
0
    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)
Example #25
0
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({})
Example #26
0
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)
Example #27
0
    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})
Example #28
0
    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)
Example #29
0
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})
Example #30
0
    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 {}