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()}
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()}
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()}