def get_job(id, **kwargs): """ Query for job and task-level metadata for a specified job :param id: Job ID :type id: str :rtype: JobMetadataResponse """ url = '{cromwell_url}/{id}/metadata?{query}'.format( cromwell_url=_get_base_url(), id=id, query='includeKey=' + '&includeKey='.join(job_include_keys)) response = requests.get(url, auth=kwargs.get('auth'), headers=kwargs.get('auth_headers')) if response.status_code != 200: handle_error(response) job = response.json() failures = [ format_task_failure(name, m) for name, metadata in job.get('calls', {}).items() for m in metadata if m.get('failures') is not None ] # if there are no tasks/subworkflows but there are errors, get them if not len(failures) and job.get('failures'): failures = [format_workflow_failure(f) for f in job.get('failures')] tasks = [ format_task(task_name, task_metadata) for task_name, task_metadata in job.get('calls', {}).items() ] sorted_tasks = sorted(tasks, key=lambda t: t.start) start = _parse_datetime(job.get('start')) submission = _parse_datetime(job.get('submission')) if submission is None: # Submission is required by the common jobs API. Submission may be missing # for subworkflows in which case we fallback to the workflow start time # or, if not started, the current time. This fallback logic may be # removed if/when Cromwell changes behavior per https://github.com/broadinstitute/cromwell/issues/2968. submission = start or datetime.utcnow() return JobMetadataResponse( id=id, name=job.get('workflowName'), status=job_statuses.cromwell_workflow_status_to_api(job.get('status')), submission=submission, start=start, end=_parse_datetime(job.get('end')), inputs=update_key_names(job.get('inputs', {})), outputs=update_key_names(job.get('outputs', {})), labels=job.get('labels'), failures=failures, extensions=ExtendedFields(tasks=sorted_tasks, parent_job_id=job.get('parentWorkflowId')))
def _metadata_response(id, job): return JobMetadataResponse(id=id, status=job_statuses.dsub_to_api(job), submission=job['create-time'], name=job['job-name'], start=job.get('start-time'), end=job['end-time'], inputs=job['inputs'], outputs=job['outputs'], labels=labels.dsub_to_api(job), failures=failures.get_failures(job), extensions=extensions.get_extensions(job))
def get_job(id, **kwargs): """ Query for job and task-level metadata for a specified job :param id: Job ID :type id: str :rtype: JobMetadataResponse """ url = '{cromwell_url}/{id}/metadata'.format(cromwell_url=_get_base_url(), id=id) response = requests.get(url, auth=kwargs.get('auth'), headers=kwargs.get('auth_headers')) job = response.json() if response.status_code == BadRequest.code: raise BadRequest(job.get('message')) elif response.status_code == NotFound.code: raise NotFound(job.get('message')) elif response.status_code == InternalServerError.code: raise InternalServerError(job.get('message')) failures = None if job.get('failures'): failures = [ FailureMessage(failure=f['message']) for f in job['failures'] ] # Get the most recent run of each task in task_metadata tasks = [ format_task(task_name, task_metadata[-1]) for task_name, task_metadata in job.get('calls', {}).items() ] sorted_tasks = sorted(tasks, key=lambda t: t.start) start = _parse_datetime(job.get('start')) submission = _parse_datetime(job.get('submission')) if submission is None: # Submission is required by the common jobs API. Submission may be missing # for subworkflows in which case we fallback to the workflow start time # or, if not started, the current time. This fallback logic may be # removed if/when Cromwell changes behavior per https://github.com/broadinstitute/cromwell/issues/2968. submission = start or datetime.utcnow() return JobMetadataResponse(id=id, name=job.get('workflowName'), status=job.get('status'), submission=submission, start=start, end=_parse_datetime(job.get('end')), inputs=update_key_names(job.get('inputs', {})), outputs=update_key_names(job.get('outputs', {})), labels=job.get('labels'), failures=failures, extensions=ExtendedFields(tasks=sorted_tasks))
def must_get_job(self, job_id): resp = self.client.open('/jobs/{}'.format(job_id), method='GET') self.assert_status(resp, 200) return JobMetadataResponse.from_dict(resp.json)