def mutation(operations, wait_for_response=False, service_access_token=None): """ Submit a mutation to the graph. If ``wait_for_response == True`` the return value is the reponse JSON, otherwise the mutation UUID is returned. """ knowledge_graph_url = current_app.config['KNOWLEDGE_GRAPH_URL'] headers = {'Authorization': 'Bearer {}'.format(service_access_token)} response = requests.post(join_url(knowledge_graph_url, '/mutation/mutation'), json={'operations': operations}, headers=headers) uuid = response.json()['uuid'] if wait_for_response: completed = False while not completed: response = requests.get(join_url( knowledge_graph_url, '/mutation/mutation/{uuid}'.format(uuid=uuid)), headers=headers).json() completed = response['status'] == 'completed' # sleep for 200 miliseconds time.sleep(0.2) return response return response.json()['uuid']
def mutation(operations, wait_for_response=False, service_access_token=None): """ Submit a mutation to the graph. If ``wait_for_response == True`` the return value is the reponse JSON, otherwise the mutation UUID is returned. """ knowledge_graph_url = current_app.config['KNOWLEDGE_GRAPH_URL'] headers = {'Authorization': 'Bearer {}'.format(service_access_token)} response = requests.post(join_url(knowledge_graph_url, '/mutation/mutation'), json={'operations': operations}, headers=headers) if not 200 <= response.status_code < 300 and 'uuid' not in response.json(): logger.warn('Mutation request failed.', extra={'response': response.json()}) abort(Response('Mutation service failed.', status=504)) uuid = response.json().get('uuid') if wait_for_response: completed = False while not completed: response = requests.get(join_url( knowledge_graph_url, '/mutation/mutation/{uuid}'.format(uuid=uuid)), headers=headers) completed = response.json()['status'] == 'completed' # sleep for 200 miliseconds time.sleep(0.2) return response
def test_missing_kg_endpoint(kg_app, auth_header, kg_requests, monkeypatch): """Test that missing the mutation service is handled gracefully.""" mutation_url = join_url(current_app.config['KNOWLEDGE_GRAPH_URL'], '/mutation/mutation') token_url = current_app.config['DEPLOYER_TOKEN_URL'] def kg_post(*args, **kwargs): """Override requests.post for KG urls.""" if mutation_url in args[0]: """Override /api/mutation/mutation.""" return Response({}, 404) elif token_url in args[0]: """Override fetching access tokens.""" return Response({'access_token': '1234'}, 200) monkeypatch.setattr(requests, 'post', kg_post) with kg_app.test_client() as client: resp = client.post('v1/contexts', data=json.dumps({ 'image': 'hello-world', 'namespace': 'default' }), content_type='application/json', headers=auth_header) assert resp.status_code == 504
def kg_requests(monkeypatch): """Monkeypatch requests to immitate the KnowledgeGraph.""" mutation_url = join_url(current_app.config['KNOWLEDGE_GRAPH_URL'], '/mutation/mutation') named_type_url = join_url(current_app.config['KNOWLEDGE_GRAPH_URL'], '/types/management/named_type') token_url = current_app.config['DEPLOYER_TOKEN_URL'] def kg_post(*args, **kwargs): """Override requests.post for KG urls.""" if mutation_url in args[0]: """Override /api/mutation/mutation.""" return Response({'uuid': '1234'}, 201) elif token_url in args[0]: """Override fetching access tokens.""" return Response({'access_token': '1234'}, 200) else: return r_post(*args, **kwargs) def kg_get(*args, **kwargs): """Overrides requests.get for KG URLs.""" if mutation_url in args[0]: """Override /api/mutation/mutation/uuid.""" return Response( { 'status': 'completed', 'response': { 'event': { 'status': 'success', 'results': [{ 'id': 1234 }] } } }, 200) elif named_type_url in args[0]: """Override /api/types/management/named_type.""" return named_type_response else: return r_get(*args, **kwargs) monkeypatch.setattr(requests, 'get', kg_get) monkeypatch.setattr(requests, 'post', kg_post)
def named_types(self): """Fetch named types from types service.""" if self._named_types is None: service_access_token = get_service_access_token( token_url=current_app.config['DEPLOYER_TOKEN_URL'], audience='renga-services', client_id=current_app.config['RENGA_AUTHORIZATION_CLIENT_ID'], client_secret=current_app. config['RENGA_AUTHORIZATION_CLIENT_SECRET']) headers = { 'Authorization': 'Bearer {}'.format(service_access_token) } self._named_types = requests.get(join_url( current_app.config['KNOWLEDGE_GRAPH_URL'], 'types/management/named_type'), headers=headers).json() return self._named_types
def named_types(self): """Fetch named types from types service.""" if self._named_types is None: service_access_token = get_service_access_token( token_url=current_app.config['DEPLOYER_TOKEN_URL'], audience='renga-services', client_id=current_app.config['RENGA_AUTHORIZATION_CLIENT_ID'], client_secret=current_app. config['RENGA_AUTHORIZATION_CLIENT_SECRET']) headers = { 'Authorization': 'Bearer {}'.format(service_access_token) } response = requests.get(join_url( current_app.config['KNOWLEDGE_GRAPH_URL'], 'types/management/named_type'), headers=headers) if not 200 <= response.status_code < 300: logger.error('Retrieving types failed.') raise RuntimeError('Retrieving types failed.') else: self._named_types = response.json() return self._named_types
def test_failed_mutation(kg_app, auth_header, kg_requests, monkeypatch, engine): """Test response to mutation failure.""" with kg_app.test_client() as client: # 1. test context creation resp = client.post('v1/contexts', data=json.dumps({ 'image': 'hello-world', 'namespace': 'default' }), content_type='application/json', headers=auth_header) context = json.loads(resp.data.decode()) mutation_url = join_url(current_app.config['KNOWLEDGE_GRAPH_URL'], '/mutation/mutation') named_type_url = join_url(current_app.config['KNOWLEDGE_GRAPH_URL'], '/types/management/named_type') def kg_get_failed(*args, **kwargs): """Overrides requests.get for KG URLs.""" if mutation_url in args[0]: """Override /api/mutation/mutation/uuid.""" return Response( { 'status': 'completed', 'response': { 'event': { 'status': 'failed', 'results': [{ 'id': 1234 }] } } }, 200) elif named_type_url in args[0]: """Override /api/types/management/named_type.""" return named_type_response else: return r_get(*args, **kwargs) monkeypatch.setattr(requests, 'get', kg_get_failed) # 2. test failure due to failed mutation with kg_app.test_client() as client: resp = client.post('v1/contexts', data=json.dumps({ 'image': 'hello-world', 'namespace': 'default' }), content_type='application/json', headers=auth_header) assert resp.status_code == 500 # 2. test failure during execution creation resp = client.post('v1/contexts/{0}/executions'.format( context['identifier']), data=json.dumps({'engine': engine}), content_type='application/json', headers=auth_header) assert resp.status_code == 500