def test_post_project(self, mock_verify_certificates): mock_verify_certificates.return_value = (True, '') name = 'test-post-project' config = { 'participants': [{ 'name': 'test-post-participant', 'domain_name': 'fl-test-post.com', 'url': '127.0.0.1:32443', 'certificates': self.TEST_CERTIFICATES }], 'variables': [{ 'name': 'test-post', 'value': 'test' }] } comment = 'test post project' create_response = self.post_helper('/api/v2/projects', data={ 'name': name, 'config': config, 'comment': comment }) self.assertEqual(create_response.status_code, HTTPStatus.OK) created_project = json.loads(create_response.data).get('data') queried_project = Project.query.filter_by(name=name).first() self.assertEqual(created_project, queried_project.to_dict()) mock_verify_certificates.assert_called_once_with( parse_certificates(self.TEST_CERTIFICATES))
def setUp(self): super().setUp() with open(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'test.tar.gz'), 'rb') as file: self.TEST_CERTIFICATES = str(b64encode(file.read()), encoding='utf-8') self.default_project = Project() self.default_project.name = 'test-self.default_project' self.default_project.set_config(ParseDict({ 'participants': [ { 'name': 'test-participant', 'domain_name': 'fl-test.com', 'url': '127.0.0.1:32443' } ], 'variables': [ { 'name': 'test', 'value': 'test' } ] }, ProjectProto())) self.default_project.set_certificate(ParseDict({ 'domain_name_to_cert': {'fl-test.com': {'certs': parse_certificates(self.TEST_CERTIFICATES)}}, }, CertificateStorage())) self.default_project.comment = 'test comment' db.session.add(self.default_project) workflow = Workflow(name='workflow_key_get1', project_id=1) db.session.add(workflow) db.session.commit()
def test_parse_certificates(self): file_names = [ 'client/client.pem', 'client/client.key', 'client/intermediate.pem', 'client/root.pem', 'server/server.pem', 'server/server.key', 'server/intermediate.pem', 'server/root.pem' ] with open(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'test.tar.gz'), 'rb') as file: certificates = parse_certificates(b64encode(file.read())) for file_name in file_names: self.assertEqual(str(b64decode(certificates.get(file_name)), encoding='utf-8'), 'test {}'.format(file_name))
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: 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()}