Ejemplo n.º 1
0
    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument('name',
                            required=True,
                            type=str,
                            help=ErrorMessage.PARAM_FORMAT_ERROR.value.format(
                                'name', 'Empty'))
        parser.add_argument('config',
                            required=True,
                            type=dict,
                            help=ErrorMessage.PARAM_FORMAT_ERROR.value.format(
                                'config', 'Empty'))
        parser.add_argument('comment')
        data = parser.parse_args()
        name = data['name']
        config = data['config']
        comment = data['comment']

        if Project.query.filter_by(name=name).first() is not None:
            raise InvalidArgumentException(
                details=ErrorMessage.NAME_CONFLICT.value.format(name))

        if config.get('participants') is None:
            raise InvalidArgumentException(
                details=ErrorMessage.PARAM_FORMAT_ERROR.value.format(
                    'participants', 'Empty'))
        if len(config.get('participants')) != 1:
            # TODO: remove limit after operator supports multiple participants
            raise InvalidArgumentException(
                details='Currently not support multiple participants.')

        certificates = {}
        for participant in config.get('participants'):
            if 'name' not in participant.keys() or \
                'url' not in participant.keys() or \
                'domain_name' not in participant.keys():
                raise InvalidArgumentException(
                    details=ErrorMessage.PARAM_FORMAT_ERROR.value.format(
                        'participants', 'Participant must have name, '
                        'domain_name and url.'))
            domain_name = participant.get('domain_name')
            if participant.get('certificates') is not None:
                current_cert = parse_certificates(
                    participant.get('certificates'))
                # check validation
                for file_name in _CERTIFICATE_FILE_NAMES:
                    if current_cert.get(file_name) is None:
                        raise InvalidArgumentException(
                            details=ErrorMessage.PARAM_FORMAT_ERROR.value.
                            format('certificates', '{} not existed'.format(
                                file_name)))
                certificates[domain_name] = {'certs': current_cert}
                participant.pop('certificates')

                # create add on
                try:
                    k8s_client = get_client()
                    for domain_name, certificate in certificates.items():
                        create_add_on(k8s_client, domain_name,
                                      participant.get('url'), current_cert)
                except RuntimeError as e:
                    raise InvalidArgumentException(details=str(e))

        new_project = Project()
        # generate token
        # If users send a token, then use it instead.
        # If `token` is None, generate a new one by uuid.
        config['name'] = name
        token = config.get('token', uuid4().hex)
        config['token'] = token

        # check format of config
        try:
            new_project.set_config(ParseDict(config, ProjectProto()))
        except Exception as e:
            raise InvalidArgumentException(
                details=ErrorMessage.PARAM_FORMAT_ERROR.value.format(
                    'config', e))
        new_project.set_certificate(
            ParseDict({'domain_name_to_cert': certificates},
                      CertificateStorage()))
        new_project.name = name
        new_project.token = token
        new_project.comment = comment

        try:
            new_project = db.session.merge(new_project)
            db.session.commit()
        except Exception as e:
            raise InvalidArgumentException(details=str(e))

        return {'data': new_project.to_dict()}
Ejemplo n.º 2
0
    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument('name',
                            required=True,
                            type=str,
                            help=ErrorMessage.PARAM_FORMAT_ERROR.value.format(
                                'name', 'Empty'))
        parser.add_argument('config',
                            required=True,
                            type=dict,
                            help=ErrorMessage.PARAM_FORMAT_ERROR.value.format(
                                'config', 'Empty'))
        parser.add_argument('comment')
        data = parser.parse_args()
        name = data['name']
        config = data['config']
        comment = data['comment']

        if Project.query.filter_by(name=name).first() is not None:
            raise InvalidArgumentException(
                details=ErrorMessage.NAME_CONFLICT.value.format(name))

        if config.get('participants') is None:
            raise InvalidArgumentException(
                details=ErrorMessage.PARAM_FORMAT_ERROR.value.format(
                    'participants', 'Empty'))
        if len(config.get('participants')) != 1:
            # TODO: remove limit after operator supports multiple participants
            raise InvalidArgumentException(
                details='Currently not support multiple participants.')

        # exact configuration from variables
        # TODO: one custom host for one participant
        custom_host = None
        for variable in config.get('variables', []):
            if variable.get('name') == 'CUSTOM_HOST':
                custom_host = variable.get('value')

        # parse participant
        certificates = {}
        for participant in config.get('participants'):
            if 'name' not in participant.keys() or \
                'url' not in participant.keys() or \
                'domain_name' not in participant.keys():
                raise InvalidArgumentException(
                    details=ErrorMessage.PARAM_FORMAT_ERROR.value.format(
                        'participants', 'Participant must have name, '
                        'domain_name and url.'))
            if re.match(_URL_REGEX, participant.get('url')) is None:
                raise InvalidArgumentException('URL pattern is wrong')
            domain_name = participant.get('domain_name')
            # Grpc spec
            participant['grpc_spec'] = {
                'authority': '{}-client-auth.com'.format(domain_name[:-4])
            }
            if participant.get('certificates') is not None:
                current_cert = parse_certificates(
                    participant.get('certificates'))
                success, err = verify_certificates(current_cert)
                if not success:
                    raise InvalidArgumentException(err)
                certificates[domain_name] = {'certs': current_cert}
            if 'certificates' in participant.keys():
                participant.pop('certificates')

        new_project = Project()
        # generate token
        # If users send a token, then use it instead.
        # If `token` is None, generate a new one by uuid.
        config['name'] = name
        token = config.get('token', uuid4().hex)
        config['token'] = token

        # check format of config
        try:
            new_project.set_config(ParseDict(config, ProjectProto()))
        except Exception as e:
            raise InvalidArgumentException(
                details=ErrorMessage.PARAM_FORMAT_ERROR.value.format(
                    'config', e))
        new_project.set_certificate(
            ParseDict({'domain_name_to_cert': certificates},
                      CertificateStorage()))
        new_project.name = name
        new_project.token = token
        new_project.comment = comment

        # create add on
        for participant in new_project.get_config().participants:
            if participant.domain_name in\
                new_project.get_certificate().domain_name_to_cert.keys():
                _create_add_on(
                    participant,
                    new_project.get_certificate().domain_name_to_cert[
                        participant.domain_name], custom_host)
        try:
            new_project = db.session.merge(new_project)
            db.session.commit()
        except Exception as e:
            raise InvalidArgumentException(details=str(e))

        return {'data': new_project.to_dict()}
Ejemplo n.º 3
0
    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument('name',
                            required=True,
                            type=str,
                            help=ErrorMessage.PARAM_FORMAT_ERROR.value.format(
                                'name', 'Empty'))
        parser.add_argument('config',
                            required=True,
                            type=dict,
                            help=ErrorMessage.PARAM_FORMAT_ERROR.value.format(
                                'config', 'Empty'))
        parser.add_argument('comment')

        data = parser.parse_args()
        name = data['name']
        config = data['config']
        comment = data['comment']

        if Project.query.filter_by(name=name).first() is not None:
            abort(HTTPStatus.BAD_REQUEST,
                  message=ErrorMessage.NAME_CONFLICT.value.format(name))

        if config.get('participants') is None:
            abort(HTTPStatus.BAD_REQUEST,
                  message=ErrorMessage.PARAM_FORMAT_ERROR.value.format(
                      'participants', 'Empty'))
        elif len(config.get('participants')) != 1:
            # TODO: remove limit in schema after operator supports multiple participants
            abort(HTTPStatus.BAD_REQUEST,
                  message='Currently not support multiple participants.')

        certificates = {}
        for domain_name, participant in config.get('participants').items():
            if 'name' not in participant.keys(
            ) or 'url' not in participant.keys():
                abort(HTTPStatus.BAD_REQUEST,
                      message=ErrorMessage.PARAM_FORMAT_ERROR.value.format(
                          'participants',
                          'Participant must have name and url.'))
            if participant.get('certificates') is not None:
                current_cert = _parse_certificates(
                    participant.get('certificates'))
                # check validation
                for file_name in _CERTIFICATE_FILE_NAMES:
                    if current_cert.get(file_name) is None:
                        abort(HTTPStatus.BAD_REQUEST,
                              message=ErrorMessage.PARAM_FORMAT_ERROR.value.
                              format('certificates',
                                     '{} not existed'.format(file_name)))
                certificates[domain_name] = participant.get('certificates')
                participant['domain_name'] = domain_name
                participant.pop('certificates')
            # format participant to proto structure
            # TODO: fill other fields
            participant['grpc_spec'] = {'url': participant.get('url')}
            participant.pop('url')

        new_project = Project()
        # generate token
        # If users send a token, then use it instead.
        # If `token` is None, generate a new one by uuid.
        token = config.get('token', uuid4().hex)
        config['token'] = token

        # check format of config
        try:
            new_project.set_config(ParseDict(config, ProjectProto()))
        except Exception as e:
            abort(HTTPStatus.BAD_REQUEST,
                  message=ErrorMessage.PARAM_FORMAT_ERROR.value.format(
                      'config', e))
        new_project.set_certificate(
            ParseDict({'certificate': certificates}, Certificate()))
        new_project.name = name
        new_project.token = token
        new_project.comment = comment

        # following operations will change the state of k8s and db
        try:
            # TODO: singleton k8s client
            k8s_client = K8sClient()
            for domain_name, certificate in certificates.items():
                _create_add_on(k8s_client, domain_name, certificate)

            db.session.add(new_project)
            db.session.commit()
        except Exception as e:
            abort(HTTPStatus.INTERNAL_SERVER_ERROR, msg=e)

        return {'data': new_project.to_dict()}