def update_job_labels(id, body, **kwargs): """ Update labels on a job. :param id: Job ID :type id: str :param body: :type body: dict | bytes :rtype: UpdateJobLabelsResponse """ payload = UpdateJobLabelsRequest.from_dict(body).labels url = '{cromwell_url}/{id}/labels'.format(cromwell_url=_get_base_url(), id=id) response = requests.patch(url, json=payload, auth=kwargs.get('auth'), headers=kwargs.get('auth_headers')) if response.status_code != 200: handle_error(response) # Follow API spec result = response.json() return UpdateJobLabelsResponse(labels=result.get('labels'))
def update_job_labels(id, body, **kwargs): """ Update labels on a job. :param id: Job ID :type id: str :param body: :type body: dict | bytes :rtype: UpdateJobLabelsResponse """ payload = UpdateJobLabelsRequest.from_dict(body).labels url = '{cromwell_url}/{id}/labels'.format(cromwell_url=_get_base_url(), id=id) response = requests.patch(url, json=payload, auth=kwargs.get('auth'), headers=kwargs.get('auth_headers')) if response.status_code == InternalServerError.code: raise InternalServerError(response.json().get('message')) elif response.status_code == BadRequest.code: raise BadRequest(response.json().get('message')) elif response.status_code == NotFound.code: raise NotFound(response.json().get('message')) response.raise_for_status() # Follow API spec result = response.json() return UpdateJobLabelsResponse(labels=result.get('labels'))
def test_update_job_labels_bad_request(self, mock_request): workflow_id = 'id' error_message = "Invalid label: `` did not match the regex [a-z]([-a-z0-9]*[a-z0-9])?." def _request_callback(request, context): context.status_code = 400 return {"status": "fail", "message": error_message} update_label_url = self.base_url + '/{id}/labels'.format( id=workflow_id) mock_request.patch(update_label_url, json=_request_callback) payload = UpdateJobLabelsRequest(labels={"": "test_invalid_label"}) response = self.client.open( '/jobs/{id}/updateLabels'.format(id=workflow_id), method='POST', data=json.dumps(payload), content_type='application/json') self.assertStatus(response, 400) self.assertEquals(json.loads(response.data)['detail'], error_message)
def test_update_job_labels_undefined_unsupported_media_type_exception( self, mock_request): workflow_id = 'id' error_message = b'Invalid Content-type (), expected JSON data' def _request_callback(request, context): context.status_code = 415 return error_message update_label_url = self.base_url + '/{id}/labels'.format( id=workflow_id) mock_request.patch(update_label_url, json=_request_callback) payload = UpdateJobLabelsRequest(labels={"test_label": None}) response = self.client.open( '/jobs/{id}/updateLabels'.format(id=workflow_id), headers={'Accept': 'application/json'}, method='POST', data=json.dumps(payload)) self.assertStatus(response, 415) self.assertEquals(json.loads(response.data)['detail'], error_message)
def test_update_job_labels_internal_server_error(self, mock_request): workflow_id = 'id' error_message = "Invalid workflow ID: test_invalid_workflow_id" def _request_callback(request, context): context.status_code = 500 return {"status": "error", "message": error_message} update_label_url = self.base_url + '/{id}/labels'.format( id=workflow_id) mock_request.patch(update_label_url, json=_request_callback) payload = UpdateJobLabelsRequest( labels={"test_label": "test_label_value"}) response = self.client.open( '/jobs/{id}/updateLabels'.format(id=workflow_id), method='POST', data=json.dumps(payload), content_type='application/json') self.assertStatus(response, 500) self.assertEquals(json.loads(response.data)['detail'], error_message)
def test_update_job_labels_not_found(self, mock_request): """Note: This status code is not currently properly returned by the Cromwell actually the error 'Unrecognized workflow ID' will return with a status code 500 now, the Cromwell team will address this issue in the near future.""" workflow_id = 'id' error_message = "Unrecognized workflow ID: 12345678-aaaa-bbbb-cccc-dddddddddddd" def _request_callback(request, context): context.status_code = 404 return {"status": "error", "message": error_message} update_label_url = self.base_url + '/{id}/labels'.format( id=workflow_id) mock_request.patch(update_label_url, json=_request_callback) payload = UpdateJobLabelsRequest( labels={"test_label": "test_label_value"}) response = self.client.open( '/jobs/{id}/updateLabels'.format(id=workflow_id), method='POST', data=json.dumps(payload), content_type='application/json') self.assertStatus(response, 404) self.assertEquals(json.loads(response.data)['detail'], error_message)
def test_update_job_labels_returns_200(self, mock_request): """ Test case for update_job_labels. Update job's labels. Currently Cromwell will ONLY return the UPDATED labels instead of ALL labels of the job, the Job Manager makes two separate HTTP requests here to Cromwell so that it can get ALL labels. """ workflow_id = 'id' workflow_name = 'test' status = 'Succeeded' timestamp = '2017-11-08T05:06:41.424Z' inputs = {'test.inputs': 'gs://project-bucket/test/inputs.txt'} outputs = { 'test.analysis.outputs': 'gs://project-bucket/test/outputs.txt' } labels = {} backend_log = '/cromwell/cromwell-executions/id/call-analysis/call-analysis-log' attempts = 1 return_code = 0 def _request_callback_labels(request, context): context.status_code = 200 return {"labels": {"test_label": "test_label_value"}} def _request_callback_get_job(request, context): context.status_code = 200 return { 'workflowName': workflow_name, 'id': workflow_id, 'status': status, 'calls': { 'test.analysis': [{ 'executionStatus': 'Done', 'start': timestamp, 'end': timestamp, 'backendLog': backend_log, 'returnCode': return_code, 'inputs': inputs, 'outputs': outputs, 'attempt': attempts }] }, 'inputs': inputs, 'labels': labels, 'outputs': outputs, 'submission': timestamp, 'end': timestamp, 'start': timestamp, 'failures': [ {'causedBy': [ { 'causedBy': [], 'message': 'Task test.analysis failed' } ], 'message': 'Workflow failed'} ] } # yapf: disable update_label_url = self.base_url + '/{id}/labels'.format( id=workflow_id) cromwell_url = self.base_url + '/{id}/metadata'.format(id=workflow_id) mock_request.patch(update_label_url, json=_request_callback_labels) mock_request.get(cromwell_url, json=_request_callback_get_job) payload = UpdateJobLabelsRequest( labels={"test_label": "test_label_value"}) response = self.client.open( '/jobs/{id}/updateLabels'.format(id=workflow_id), method='POST', data=json.dumps(payload), content_type='application/json') self.assertStatus(response, 200) self.assertEquals(response.json, {"labels": { "test_label": "test_label_value" }})
def test_update_job_labels_returns_all_labels(self, mock_request): workflow_id = 'id' workflow_name = 'test' status = 'Succeeded' timestamp = '2017-11-08T05:06:41.424Z' inputs = {'test.inputs': 'gs://project-bucket/test/inputs.txt'} outputs = { 'test.analysis.outputs': 'gs://project-bucket/test/outputs.txt' } labels = { "existing_test_label1": "existing_test_label_value1", "existing_test_label2": "existing_test_label_value2" } backend_log = '/cromwell/cromwell-executions/id/call-analysis/call-analysis-log' attempts = 1 return_code = 0 def _request_callback_labels(request, context): context.status_code = 200 return { "labels": { "new_test_label": "new_test_label_value", "existing_test_label1": "existing_test_label_value1", "existing_test_label2": "existing_test_label_value2" } } def _request_callback_get_job(request, context): context.status_code = 200 return { 'workflowName': workflow_name, 'id': workflow_id, 'status': status, 'calls': { 'test.analysis': [{ 'executionStatus': 'Done', 'start': timestamp, 'end': timestamp, 'backendLog': backend_log, 'returnCode': return_code, 'inputs': inputs, 'attempt': attempts }] }, 'inputs': inputs, 'labels': labels, 'outputs': outputs, 'submission': timestamp, 'end': timestamp, 'start': timestamp, 'failures': [ {'causedBy': [ { 'causedBy': [], 'message': 'Task test.analysis failed' } ], 'message': 'Workflow failed'} ] } # yapf: disable update_label_url = self.base_url + '/{id}/labels'.format( id=workflow_id) cromwell_url = self.base_url + '/{id}/metadata'.format(id=workflow_id) mock_request.patch(update_label_url, json=_request_callback_labels) mock_request.get(cromwell_url, json=_request_callback_get_job) payload = UpdateJobLabelsRequest( labels={"new_test_label": "new_test_label_value"}) response = self.client.open( '/jobs/{id}/updateLabels'.format(id=workflow_id), method='POST', data=json.dumps(payload), content_type='application/json') expected_result = UpdateJobLabelsResponse.from_dict({ "labels": { "existing_test_label1": "existing_test_label_value1", "existing_test_label2": "existing_test_label_value2", "new_test_label": "new_test_label_value" } }) result = UpdateJobLabelsResponse.from_dict(response.json) self.assertStatus(response, 200) self.assertDictEqual(result.labels, expected_result.labels)