Skip to content

Commit 24b3b3a

Browse files
authored
Add the ability to view operation details from Google Pipelines API [BA-5762] (#661)
1 parent 012889f commit 24b3b3a

29 files changed

+2796
-2630
lines changed

Diff for: CHANGELOG.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Job Manager Change Log
22

3+
## v1.3.0 Release Notes
4+
5+
### Added icon that, when clicked, will provide Google Pipelines operation details. (So far) only implemented for a Cromwell backend, and it requires `outsideAuth` to be set to `true` in the authentication section of the `capabilities_config.json` file.
6+
37
## v1.2.3 Release Notes
48

59
### Added logic to avoid 500 error on Job Details page when a workflow failure section does not have a causedBy entry.
@@ -14,7 +18,7 @@
1418

1519
## v1.2.0 Release Notes
1620

17-
### Added the ability with the addition of a specific scope to the capabilities config file to see the contents of Google Storage log files within the UI.
21+
### Added the ability -- with the addition of a specific scope to the capabilities config file -- to see the contents of Google Storage log files within the UI.
1822

1923
## v1.1.1 Release Notes
2024

Diff for: api/jobs.yaml

+60
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ enum: &TIMEFRAME
1515
- DAYS_7
1616
- DAYS_30
1717
- ALL_TIME
18+
1819
paths:
1920
'/capabilities':
2021
get:
@@ -31,6 +32,7 @@ paths:
3132
$ref: '#/responses/ServerError'
3233
tags:
3334
- Capabilities
35+
3436
'/jobs/{id}/abort':
3537
post:
3638
operationId: AbortJob
@@ -56,6 +58,7 @@ paths:
5658
$ref: '#/responses/ServerError'
5759
tags:
5860
- Jobs
61+
5962
'/jobs/{id}/updateLabels':
6063
post:
6164
operationId: UpdateJobLabels
@@ -86,6 +89,7 @@ paths:
8689
description: Server does not implement this method.
8790
tags:
8891
- Jobs
92+
8993
'/jobs/query':
9094
post:
9195
# TODO(calbach): Parameterize sort ordering.
@@ -112,6 +116,7 @@ paths:
112116
$ref: '#/responses/ServerError'
113117
tags:
114118
- Jobs
119+
115120
'/jobs/{id}':
116121
get:
117122
operationId: GetJob
@@ -137,6 +142,7 @@ paths:
137142
$ref: '#/responses/ServerError'
138143
tags:
139144
- Jobs
145+
140146
'/jobs/{id}/{task}/attempts':
141147
get:
142148
operationId: GetTaskAttempts
@@ -167,6 +173,7 @@ paths:
167173
$ref: '#/responses/ServerError'
168174
tags:
169175
- Jobs
176+
170177
'/jobs/{id}/{task}/{index}/attempts':
171178
get:
172179
operationId: GetShardAttempts
@@ -202,6 +209,33 @@ paths:
202209
$ref: '#/responses/ServerError'
203210
tags:
204211
- Jobs
212+
213+
'/jobs/operationDetails':
214+
get:
215+
operationId: GetOperationDetails
216+
summary: Call for operation details from the Google Pipelines API
217+
parameters:
218+
- name: job
219+
description: job ID
220+
required: true
221+
in: query
222+
type: string
223+
- name: operation
224+
description: operation ID
225+
type: string
226+
in: query
227+
responses:
228+
'200':
229+
description: Success
230+
schema:
231+
$ref: '#/definitions/JobOperationResponse'
232+
'404':
233+
$ref: '#/responses/NotFound'
234+
'500':
235+
$ref: '#/responses/ServerError'
236+
tags:
237+
- Jobs
238+
205239
'/aggregations':
206240
get:
207241
operationId: GetJobAggregations
@@ -232,6 +266,7 @@ paths:
232266
$ref: '#/responses/ServerError'
233267
tags:
234268
- Aggregation
269+
235270
'/health':
236271
get:
237272
operationId: Health
@@ -267,6 +302,10 @@ definitions:
267302
forcedLogoutTime:
268303
type: integer
269304
description: Number of milliseconds for the interval of inactivity.
305+
outsideAuth:
306+
type: boolean
307+
description: Whether or not to use an outside service for some auth-related functionality.
308+
default: false
270309

271310
DisplayField:
272311
description: Description of a display field
@@ -379,6 +418,15 @@ definitions:
379418
extensions:
380419
$ref: '#/definitions/ExtendedFields'
381420

421+
JobOperationResponse:
422+
description: Google Pipelines API provided details about an operation
423+
properties:
424+
details:
425+
type: string
426+
id:
427+
type: string
428+
description: operation ID
429+
382430
UpdateJobLabelsRequest:
383431
description: Update labels on a job
384432
properties:
@@ -683,6 +731,9 @@ definitions:
683731
callRoot:
684732
type: string
685733
description: The root directory of the task execution
734+
operationId:
735+
type: string
736+
description: Operation Id for Google Pipelines API
686737
attempts:
687738
type: integer
688739
description: Number of times the task was run
@@ -726,6 +777,9 @@ definitions:
726777
callRoot:
727778
type: string
728779
description: The root directory of the task execution
780+
operationId:
781+
type: string
782+
description: Operation Id for Google Pipelines API
729783
inputs:
730784
type: object
731785
description: Mapping of input fully qualified names to stringified values
@@ -778,6 +832,9 @@ definitions:
778832
callRoot:
779833
type: string
780834
description: If from a task, the root directory of the task or shard execution
835+
operationId:
836+
type: string
837+
description: Operation Id for Google Pipelines API
781838
attempts:
782839
type: integer
783840
description: Number of times the task was run
@@ -824,6 +881,9 @@ definitions:
824881
callRoot:
825882
type: string
826883
description: If from a task, the root directory of the task or shard execution
884+
operationId:
885+
type: string
886+
description: Operation Id for Google Pipelines API
827887
jobId:
828888
type: string
829889
description: >

Diff for: servers/cromwell/jobs/controllers/jobs_controller.py

+35
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from jobs.models.execution_event import ExecutionEvent
2525
from jobs.models.individual_attempt import IndividualAttempt
2626
from jobs.models.job_attempts_response import JobAttemptsResponse
27+
from jobs.models.job_operation_response import JobOperationResponse
2728
from jobs.controllers.utils import job_statuses
2829
from jobs.controllers.utils import task_statuses
2930

@@ -286,6 +287,7 @@ def format_task(task_name, task_metadata):
286287
return_code=latest_attempt.get('returnCode'),
287288
attempts=latest_attempt.get('attempt'),
288289
call_root=latest_attempt.get('callRoot'),
290+
operation_id=latest_attempt.get('jobId'),
289291
job_id=latest_attempt.get('subWorkflowId'),
290292
shards=None,
291293
call_cached=call_cached,
@@ -301,6 +303,7 @@ def format_task_failure(task_name, metadata):
301303
stdout=metadata.get('stdout'),
302304
stderr=metadata.get('stderr'),
303305
call_root=metadata.get('callRoot'),
306+
operation_id=metadata.get('jobId'),
304307
job_id=metadata.get('subWorkflowId'))
305308

306309

@@ -346,6 +349,7 @@ def format_scattered_task(task_name, task_metadata):
346349
stdout=shard.get('stdout'),
347350
stderr=shard.get('stderr'),
348351
call_root=shard.get('callRoot'),
352+
operation_id=shard.get('jobId'),
349353
attempts=shard.get('attempt'),
350354
failure_messages=failure_messages,
351355
job_id=shard.get('subWorkflowId')))
@@ -537,6 +541,36 @@ def handle_error(response):
537541
response.raise_for_status()
538542

539543

544+
@requires_auth
545+
def get_operation_details(job, operation, **kwargs):
546+
"""
547+
Query for operation details from Google Pipelines API
548+
549+
:param job: Job ID
550+
:type id: str
551+
552+
:param operation_id: Operation ID
553+
:type id: str
554+
555+
:rtype: str
556+
"""
557+
558+
capabilities = current_app.config['capabilities']
559+
if hasattr(capabilities, 'authentication') and hasattr(
560+
capabilities.authentication,
561+
'outside_auth') and capabilities.authentication.outside_auth:
562+
url = '{cromwell_url}/{id}/backend/metadata/{backendId}'.format(
563+
cromwell_url=_get_base_url(), id=job, backendId=operation)
564+
response = requests.get(url,
565+
auth=kwargs.get('auth'),
566+
headers=kwargs.get('auth_headers'))
567+
568+
if response.status_code != 200:
569+
handle_error(response)
570+
571+
return JobOperationResponse(id=job, details=response.text)
572+
573+
540574
def _get_execution_events(events):
541575
execution_events = None
542576
if events:
@@ -604,6 +638,7 @@ def _convert_to_attempt(item):
604638
stdout=item.get('stdout'),
605639
stderr=item.get('stderr'),
606640
call_root=item.get('callRoot'),
641+
operation_id=item.get('jobId'),
607642
inputs=item.get('inputs'),
608643
outputs=item.get('outputs'),
609644
start=_parse_datetime(item.get('start')),

Diff for: servers/cromwell/jobs/test/test_auth_utils.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ def test_token_auth_returns_200(self, mock_request):
1515
'cromwell_url': self.base_url,
1616
'cromwell_user': '',
1717
'cromwell_password': '',
18-
'use_caas': True
18+
'use_caas': True,
19+
'capabilities': {}
1920
})
2021

2122
def _request_callback(request, context):
@@ -38,7 +39,8 @@ def test_basic_auth_returns_200(self, mock_request):
3839
'cromwell_url': self.base_url,
3940
'cromwell_user': 'user',
4041
'cromwell_password': 'password',
41-
'use_caas': False
42+
'use_caas': False,
43+
'capabilities': {}
4244
})
4345

4446
def _request_callback(request, context):
@@ -59,7 +61,8 @@ def test_no_auth_with_caas_returns_401(self):
5961
'cromwell_url': self.base_url,
6062
'cromwell_user': '',
6163
'cromwell_password': '',
62-
'use_caas': True
64+
'use_caas': True,
65+
'capabilities': {}
6366
})
6467
response = self.client.open('/jobs/query',
6568
method='POST',

Diff for: servers/cromwell/jobs/test/test_jobs_controller.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ def setUp(self):
2727
'cromwell_url': self.base_url,
2828
'cromwell_user': 'user',
2929
'cromwell_password': 'password',
30-
'use_caas': False
30+
'use_caas': False,
31+
'capabilities': {}
3132
})
3233

3334
@requests_mock.mock()

Diff for: servers/dsub/jobs/controllers/jobs_controller.py

+8
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,14 @@ def get_task_attempts(id, task, **kwargs):
207207
raise NotImplementedError('Tasks not supported by dsub.')
208208

209209

210+
def get_operation_details(job, operation, **kwargs):
211+
"""
212+
Placeholder for query for operation details from Google Pipelines API
213+
214+
"""
215+
raise NotImplementedError('Operation details not supported by dsub.')
216+
217+
210218
def _handle_http_error(error, proj_id):
211219
# TODO(https://github.com/googlegenomics/dsub/issues/79): Push this
212220
# provider-specific error translation down into dstat.

0 commit comments

Comments
 (0)