firecloud-api-cds 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- firecloud_api_cds/__init__.py +11 -0
- firecloud_api_cds/api.py +1774 -0
- firecloud_api_cds/config.py +26 -0
- firecloud_api_cds/entity.py +71 -0
- firecloud_api_cds/errors.py +16 -0
- firecloud_api_cds/fccore.py +221 -0
- firecloud_api_cds/fiss.py +2983 -0
- firecloud_api_cds/method.py +85 -0
- firecloud_api_cds/submission.py +31 -0
- firecloud_api_cds/supervisor.py +289 -0
- firecloud_api_cds/workspace.py +323 -0
- firecloud_api_cds-0.2.0.dist-info/METADATA +18 -0
- firecloud_api_cds-0.2.0.dist-info/RECORD +15 -0
- firecloud_api_cds-0.2.0.dist-info/WHEEL +4 -0
- firecloud_api_cds-0.2.0.dist-info/licenses/LICENSE +30 -0
firecloud_api_cds/api.py
ADDED
|
@@ -0,0 +1,1774 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module provides python bindings for the Firecloud API.
|
|
3
|
+
For more details see https://software.broadinstitute.org/firecloud/
|
|
4
|
+
|
|
5
|
+
To see how the python bindings map to the RESTful endpoints view
|
|
6
|
+
the README at https://pypi.python.org/pypi/firecloud.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import print_function
|
|
10
|
+
import json
|
|
11
|
+
import sys
|
|
12
|
+
import os
|
|
13
|
+
import io
|
|
14
|
+
import logging
|
|
15
|
+
import subprocess
|
|
16
|
+
try:
|
|
17
|
+
from collections.abc import Iterable
|
|
18
|
+
except ImportError:
|
|
19
|
+
from collections import Iterable
|
|
20
|
+
|
|
21
|
+
from six.moves.urllib.parse import urlencode, urljoin
|
|
22
|
+
from six import string_types
|
|
23
|
+
|
|
24
|
+
import inspect
|
|
25
|
+
|
|
26
|
+
import google.auth
|
|
27
|
+
from google.auth.exceptions import DefaultCredentialsError, RefreshError
|
|
28
|
+
from google.auth.transport.requests import AuthorizedSession, Request
|
|
29
|
+
from google.oauth2 import id_token
|
|
30
|
+
|
|
31
|
+
from .errors import FireCloudServerError
|
|
32
|
+
from .fccore import __fcconfig as fcconfig
|
|
33
|
+
|
|
34
|
+
FISS_USER_AGENT = "FISS/0.16.38"
|
|
35
|
+
|
|
36
|
+
# Set Global Authorized Session
|
|
37
|
+
__SESSION = None
|
|
38
|
+
__USER_ID = None
|
|
39
|
+
|
|
40
|
+
# Suppress warnings about project ID
|
|
41
|
+
logging.getLogger('google.auth').setLevel(logging.ERROR)
|
|
42
|
+
|
|
43
|
+
#################################################
|
|
44
|
+
# Utilities
|
|
45
|
+
#################################################
|
|
46
|
+
def _set_session():
|
|
47
|
+
""" Sets global __SESSION and __USER_ID if they haven't been set """
|
|
48
|
+
global __SESSION
|
|
49
|
+
global __USER_ID
|
|
50
|
+
|
|
51
|
+
if __SESSION is None:
|
|
52
|
+
# determine if clock_skew_in_seconds is a parameter for id_token.verify_oauth2_token()
|
|
53
|
+
try: # PY3
|
|
54
|
+
argspec = inspect.getfullargspec(id_token.verify_oauth2_token)
|
|
55
|
+
except AttributeError: # PY2
|
|
56
|
+
argspec = inspect.getargspec(id_token.verify_oauth2_token)
|
|
57
|
+
|
|
58
|
+
try:
|
|
59
|
+
__SESSION = AuthorizedSession(google.auth.default(['https://www.googleapis.com/auth/userinfo.profile',
|
|
60
|
+
'https://www.googleapis.com/auth/userinfo.email'])[0])
|
|
61
|
+
health()
|
|
62
|
+
# google.auth 2.1.0 introduced a restrictive clock skew that was unmodifiable until 2.3.2
|
|
63
|
+
if 'clock_skew_in_seconds' in argspec.args:
|
|
64
|
+
__USER_ID = id_token.verify_oauth2_token(__SESSION.credentials.id_token,
|
|
65
|
+
Request(session=__SESSION),
|
|
66
|
+
clock_skew_in_seconds=10)['email']
|
|
67
|
+
else:
|
|
68
|
+
__USER_ID = id_token.verify_oauth2_token(__SESSION.credentials.id_token,
|
|
69
|
+
Request(session=__SESSION))['email']
|
|
70
|
+
except AttributeError:
|
|
71
|
+
__USER_ID = __SESSION.credentials.service_account_email
|
|
72
|
+
except (DefaultCredentialsError, RefreshError) as gae:
|
|
73
|
+
if os.getenv('SERVER_SOFTWARE', '').startswith('Google App Engine/'):
|
|
74
|
+
raise
|
|
75
|
+
logging.warning("Unable to determine/refresh application credentials")
|
|
76
|
+
try:
|
|
77
|
+
subprocess.check_call(['gcloud', 'auth', 'application-default',
|
|
78
|
+
'login', '--no-launch-browser'])
|
|
79
|
+
__SESSION = AuthorizedSession(google.auth.default(['https://www.googleapis.com/auth/userinfo.profile',
|
|
80
|
+
'https://www.googleapis.com/auth/userinfo.email'])[0])
|
|
81
|
+
except subprocess.CalledProcessError as cpe:
|
|
82
|
+
if cpe.returncode < 0:
|
|
83
|
+
logging.exception("%s was terminated by signal %d",
|
|
84
|
+
cpe.cmd, -cpe.returncode)
|
|
85
|
+
else:
|
|
86
|
+
logging.exception("%s returned %d", cpe.cmd,
|
|
87
|
+
cpe.returncode)
|
|
88
|
+
raise gae
|
|
89
|
+
|
|
90
|
+
def _fiss_agent_header(headers=None):
|
|
91
|
+
""" Return request headers for fiss.
|
|
92
|
+
Inserts FISS as the User-Agent.
|
|
93
|
+
Initializes __SESSION if it hasn't been set.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
headers (dict): Include additional headers as key-value pairs
|
|
97
|
+
|
|
98
|
+
"""
|
|
99
|
+
_set_session()
|
|
100
|
+
|
|
101
|
+
fiss_headers = {"User-Agent" : FISS_USER_AGENT}
|
|
102
|
+
if headers is not None:
|
|
103
|
+
fiss_headers.update(headers)
|
|
104
|
+
return fiss_headers
|
|
105
|
+
|
|
106
|
+
def __get(methcall, headers=None, root_url=None, **kwargs):
|
|
107
|
+
if not headers:
|
|
108
|
+
headers = _fiss_agent_header()
|
|
109
|
+
if root_url is None:
|
|
110
|
+
root_url = fcconfig.root_url
|
|
111
|
+
r = __SESSION.get(urljoin(root_url, methcall), headers=headers, **kwargs)
|
|
112
|
+
if fcconfig.verbosity > 1:
|
|
113
|
+
print('FISSFC call: %s' % r.url, file=sys.stderr)
|
|
114
|
+
return r
|
|
115
|
+
|
|
116
|
+
def __patch(methcall, headers=None, root_url=None, **kwargs):
|
|
117
|
+
if not headers:
|
|
118
|
+
headers = _fiss_agent_header({"Content-type": "application/json"})
|
|
119
|
+
if root_url is None:
|
|
120
|
+
root_url = fcconfig.root_url
|
|
121
|
+
r = __SESSION.patch(urljoin(root_url, methcall), headers=headers, **kwargs)
|
|
122
|
+
if fcconfig.verbosity > 1:
|
|
123
|
+
info = r.url
|
|
124
|
+
data = kwargs.get("data", None)
|
|
125
|
+
if data:
|
|
126
|
+
info += " \n(data=%s) " % data
|
|
127
|
+
json = kwargs.get("json", None)
|
|
128
|
+
if json:
|
|
129
|
+
info += " \n(json=%s) " % json
|
|
130
|
+
print('FISSFC call: PATCH %s' % info, file=sys.stderr)
|
|
131
|
+
return r
|
|
132
|
+
|
|
133
|
+
def __post(methcall, headers=None, root_url=None, **kwargs):
|
|
134
|
+
if not headers:
|
|
135
|
+
headers = _fiss_agent_header({"Content-type": "application/json"})
|
|
136
|
+
if root_url is None:
|
|
137
|
+
root_url = fcconfig.root_url
|
|
138
|
+
r = __SESSION.post(urljoin(root_url, methcall), headers=headers, **kwargs)
|
|
139
|
+
if fcconfig.verbosity > 1:
|
|
140
|
+
info = r.url
|
|
141
|
+
json = kwargs.get("json", None)
|
|
142
|
+
if json:
|
|
143
|
+
info += " \n(json=%s) " % json
|
|
144
|
+
print('FISSFC call: POST %s' % info, file=sys.stderr)
|
|
145
|
+
return r
|
|
146
|
+
|
|
147
|
+
def __put(methcall, headers=None, root_url=None, **kwargs):
|
|
148
|
+
if not headers:
|
|
149
|
+
headers = _fiss_agent_header()
|
|
150
|
+
if root_url is None:
|
|
151
|
+
root_url = fcconfig.root_url
|
|
152
|
+
r = __SESSION.put(urljoin(root_url, methcall), headers=headers, **kwargs)
|
|
153
|
+
if fcconfig.verbosity > 1:
|
|
154
|
+
info = r.url
|
|
155
|
+
json = kwargs.get("json", None)
|
|
156
|
+
if json:
|
|
157
|
+
info += " \n(json=%s) " % json
|
|
158
|
+
print('FISSFC call: PUT %s' % info, file=sys.stderr)
|
|
159
|
+
return r
|
|
160
|
+
|
|
161
|
+
def __delete(methcall, headers=None, root_url=None):
|
|
162
|
+
if not headers:
|
|
163
|
+
headers = _fiss_agent_header()
|
|
164
|
+
if root_url is None:
|
|
165
|
+
root_url = fcconfig.root_url
|
|
166
|
+
r = __SESSION.delete(urljoin(root_url, methcall), headers=headers)
|
|
167
|
+
if fcconfig.verbosity > 1:
|
|
168
|
+
print('FISSFC call: DELETE %s' % r.url, file=sys.stderr)
|
|
169
|
+
return r
|
|
170
|
+
|
|
171
|
+
def _check_response_code(response, codes):
|
|
172
|
+
"""
|
|
173
|
+
Throws an exception if the http response is not expected. Can check single
|
|
174
|
+
integer or list of valid responses.
|
|
175
|
+
|
|
176
|
+
Example usage:
|
|
177
|
+
>>> r = api.get_workspace("broad-firecloud-testing", "Fake-Bucket")
|
|
178
|
+
>>> _check_response_code(r, 200)
|
|
179
|
+
... FireCloudServerError ...
|
|
180
|
+
"""
|
|
181
|
+
if type(codes) == int:
|
|
182
|
+
codes = [codes]
|
|
183
|
+
if response.status_code not in codes:
|
|
184
|
+
try:
|
|
185
|
+
msg = json.dumps(response.json())
|
|
186
|
+
except:
|
|
187
|
+
msg = response.text
|
|
188
|
+
raise FireCloudServerError(response.status_code, msg)
|
|
189
|
+
|
|
190
|
+
def whoami():
|
|
191
|
+
""" Return __USER_ID """
|
|
192
|
+
_set_session()
|
|
193
|
+
return __USER_ID
|
|
194
|
+
|
|
195
|
+
##############################################################
|
|
196
|
+
# 1. Orchestration API calls, see https://api.firecloud.org/
|
|
197
|
+
##############################################################
|
|
198
|
+
|
|
199
|
+
##################
|
|
200
|
+
### 1.1 Entities
|
|
201
|
+
##################
|
|
202
|
+
|
|
203
|
+
def get_entities_with_type(namespace, workspace):
|
|
204
|
+
"""List entities in a workspace.
|
|
205
|
+
|
|
206
|
+
Args:
|
|
207
|
+
namespace (str): project to which workspace belongs
|
|
208
|
+
workspace (str): Workspace name
|
|
209
|
+
|
|
210
|
+
Swagger:
|
|
211
|
+
https://api.firecloud.org/#!/Entities/getEntitiesWithType
|
|
212
|
+
"""
|
|
213
|
+
uri = "workspaces/{0}/{1}/entities_with_type".format(namespace, workspace)
|
|
214
|
+
return __get(uri)
|
|
215
|
+
|
|
216
|
+
def list_entity_types(namespace, workspace):
|
|
217
|
+
"""List the entity types present in a workspace.
|
|
218
|
+
|
|
219
|
+
Args:
|
|
220
|
+
namespace (str): project to which workspace belongs
|
|
221
|
+
workspace (str): Workspace name
|
|
222
|
+
|
|
223
|
+
Swagger:
|
|
224
|
+
https://api.firecloud.org/#!/Entities/getEntityTypes
|
|
225
|
+
"""
|
|
226
|
+
headers = _fiss_agent_header({"Content-type": "application/json"})
|
|
227
|
+
uri = "workspaces/{0}/{1}/entities".format(namespace, workspace)
|
|
228
|
+
return __get(uri, headers=headers)
|
|
229
|
+
|
|
230
|
+
def upload_entities(namespace, workspace, entity_data, model='firecloud',
|
|
231
|
+
delete_empty=False):
|
|
232
|
+
"""Upload entities from tab-delimited string.
|
|
233
|
+
|
|
234
|
+
Args:
|
|
235
|
+
namespace (str): project to which workspace belongs
|
|
236
|
+
workspace (str): Workspace name
|
|
237
|
+
entity_data (str): TSV string describing entites
|
|
238
|
+
model (str): Data Model type. "firecloud" (default) or "flexible"
|
|
239
|
+
delete_empty (bool): Values left blank in the TSV will be deleted if set to true
|
|
240
|
+
|
|
241
|
+
Swagger:
|
|
242
|
+
https://api.firecloud.org/#!/Entities/importEntities
|
|
243
|
+
https://api.firecloud.org/#!/Entities/flexibleImportEntities
|
|
244
|
+
"""
|
|
245
|
+
params = {"deleteEmptyValues": delete_empty}
|
|
246
|
+
body = urlencode({"entities" : entity_data})
|
|
247
|
+
headers = _fiss_agent_header({
|
|
248
|
+
'Content-type': "application/x-www-form-urlencoded"
|
|
249
|
+
})
|
|
250
|
+
endpoint = 'importEntities'
|
|
251
|
+
if model == 'flexible':
|
|
252
|
+
endpoint = 'flexibleImportEntities'
|
|
253
|
+
uri = "workspaces/{0}/{1}/{2}".format(namespace, workspace, endpoint)
|
|
254
|
+
return __post(uri, headers=headers, data=body, params=params)
|
|
255
|
+
|
|
256
|
+
def upload_entities_tsv(namespace, workspace, entities_tsv, model='firecloud'):
|
|
257
|
+
"""Upload entities from a tsv loadfile.
|
|
258
|
+
|
|
259
|
+
File-based wrapper for api.upload_entities().
|
|
260
|
+
A loadfile is a tab-separated text file with a header row
|
|
261
|
+
describing entity type and attribute names, followed by
|
|
262
|
+
rows of entities and their attribute values.
|
|
263
|
+
|
|
264
|
+
Ex:
|
|
265
|
+
entity:participant_id age alive
|
|
266
|
+
participant_23 25 Y
|
|
267
|
+
participant_27 35 N
|
|
268
|
+
|
|
269
|
+
Args:
|
|
270
|
+
namespace (str): project to which workspace belongs
|
|
271
|
+
workspace (str): Workspace name
|
|
272
|
+
entities_tsv (file): FireCloud loadfile, see format above
|
|
273
|
+
model (str): Data Model type. "firecloud" (default) or "flexible"
|
|
274
|
+
"""
|
|
275
|
+
if isinstance(entities_tsv, string_types):
|
|
276
|
+
with open(entities_tsv, "r") as tsv:
|
|
277
|
+
entity_data = tsv.read()
|
|
278
|
+
elif isinstance(entities_tsv, io.StringIO):
|
|
279
|
+
entity_data = entities_tsv.getvalue()
|
|
280
|
+
else:
|
|
281
|
+
raise ValueError('Unsupported input type.')
|
|
282
|
+
return upload_entities(namespace, workspace, entity_data, model)
|
|
283
|
+
|
|
284
|
+
def copy_entities(from_namespace, from_workspace, to_namespace,
|
|
285
|
+
to_workspace, etype, enames, link_existing_entities=False):
|
|
286
|
+
"""Copy entities between workspaces
|
|
287
|
+
|
|
288
|
+
Args:
|
|
289
|
+
from_namespace (str): project (namespace) to which source workspace belongs
|
|
290
|
+
from_workspace (str): Source workspace name
|
|
291
|
+
to_namespace (str): project (namespace) to which target workspace belongs
|
|
292
|
+
to_workspace (str): Target workspace name
|
|
293
|
+
etype (str): Entity type
|
|
294
|
+
enames (list(str)): List of entity names to copy
|
|
295
|
+
link_existing_entities (boolean): Link all soft conflicts to the entities that already exist.
|
|
296
|
+
|
|
297
|
+
Swagger:
|
|
298
|
+
https://api.firecloud.org/#!/Entities/copyEntities
|
|
299
|
+
"""
|
|
300
|
+
|
|
301
|
+
uri = "workspaces/{0}/{1}/entities/copy".format(to_namespace, to_workspace)
|
|
302
|
+
body = {
|
|
303
|
+
"sourceWorkspace": {
|
|
304
|
+
"namespace": from_namespace,
|
|
305
|
+
"name": from_workspace
|
|
306
|
+
},
|
|
307
|
+
"entityType": etype,
|
|
308
|
+
"entityNames": enames
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
return __post(uri, json=body, params={'linkExistingEntities':
|
|
312
|
+
str(link_existing_entities).lower()})
|
|
313
|
+
|
|
314
|
+
def get_entities(namespace, workspace, etype):
|
|
315
|
+
"""List entities of given type in a workspace.
|
|
316
|
+
|
|
317
|
+
Response content will be in JSON format.
|
|
318
|
+
|
|
319
|
+
Args:
|
|
320
|
+
namespace (str): project to which workspace belongs
|
|
321
|
+
workspace (str): Workspace name
|
|
322
|
+
etype (str): Entity type
|
|
323
|
+
|
|
324
|
+
Swagger:
|
|
325
|
+
https://api.firecloud.org/#!/Entities/getEntities
|
|
326
|
+
"""
|
|
327
|
+
uri = "workspaces/{0}/{1}/entities/{2}".format(namespace, workspace, etype)
|
|
328
|
+
return __get(uri)
|
|
329
|
+
|
|
330
|
+
def get_entities_tsv(namespace, workspace, etype, attrs=None, model="firecloud"):
|
|
331
|
+
"""List entities of given type in a workspace as a TSV.
|
|
332
|
+
|
|
333
|
+
Similar to get_entities(), but the response is a TSV.
|
|
334
|
+
|
|
335
|
+
Args:
|
|
336
|
+
namespace (str): project to which workspace belongs
|
|
337
|
+
workspace (str): Workspace name
|
|
338
|
+
etype (str): Entity type
|
|
339
|
+
attrs (list): list of ordered attribute names to be in downloaded tsv
|
|
340
|
+
model (str): Data Model type. "firecloud" (default) or "flexible"
|
|
341
|
+
|
|
342
|
+
Swagger:
|
|
343
|
+
https://api.firecloud.org/#!/Entities/downloadEntitiesTSV
|
|
344
|
+
"""
|
|
345
|
+
params = {'model': model}
|
|
346
|
+
if attrs is not None:
|
|
347
|
+
params['attributeNames'] = ','.join(attrs)
|
|
348
|
+
uri = "workspaces/{0}/{1}/entities/{2}/tsv".format(namespace,
|
|
349
|
+
workspace, etype)
|
|
350
|
+
return __get(uri, params=params)
|
|
351
|
+
|
|
352
|
+
def get_entity(namespace, workspace, etype, ename):
|
|
353
|
+
"""Request entity information.
|
|
354
|
+
|
|
355
|
+
Gets entity metadata and attributes.
|
|
356
|
+
|
|
357
|
+
Args:
|
|
358
|
+
namespace (str): project to which workspace belongs
|
|
359
|
+
workspace (str): Workspace name
|
|
360
|
+
etype (str): Entity type
|
|
361
|
+
ename (str): The entity's unique id
|
|
362
|
+
|
|
363
|
+
Swagger:
|
|
364
|
+
https://api.firecloud.org/#!/Entities/getEntity
|
|
365
|
+
"""
|
|
366
|
+
uri = "workspaces/{0}/{1}/entities/{2}/{3}".format(namespace,
|
|
367
|
+
workspace, etype, ename)
|
|
368
|
+
return __get(uri)
|
|
369
|
+
|
|
370
|
+
def delete_entities(namespace, workspace, json_body):
|
|
371
|
+
"""Delete entities in a workspace.
|
|
372
|
+
|
|
373
|
+
Note: This action is not reversible. Be careful!
|
|
374
|
+
|
|
375
|
+
Args:
|
|
376
|
+
namespace (str): project to which workspace belongs
|
|
377
|
+
workspace (str): Workspace name
|
|
378
|
+
json_body:
|
|
379
|
+
[
|
|
380
|
+
{
|
|
381
|
+
"entityType": "string",
|
|
382
|
+
"entityName": "string"
|
|
383
|
+
}
|
|
384
|
+
]
|
|
385
|
+
|
|
386
|
+
Swagger:
|
|
387
|
+
https://api.firecloud.org/#!/Entities/deleteEntities
|
|
388
|
+
"""
|
|
389
|
+
|
|
390
|
+
uri = "workspaces/{0}/{1}/entities/delete".format(namespace, workspace)
|
|
391
|
+
return __post(uri, json=json_body)
|
|
392
|
+
|
|
393
|
+
def delete_entity_type(namespace, workspace, etype, ename):
|
|
394
|
+
"""Delete specified entities of a single type in a workspace.
|
|
395
|
+
|
|
396
|
+
Note: This action is not reversible. Be careful!
|
|
397
|
+
|
|
398
|
+
Args:
|
|
399
|
+
namespace (str): project to which workspace belongs
|
|
400
|
+
workspace (str): Workspace name
|
|
401
|
+
etype (str): Entity type
|
|
402
|
+
ename (str, or iterable of str): unique entity id(s)
|
|
403
|
+
|
|
404
|
+
Swagger:
|
|
405
|
+
https://api.firecloud.org/#!/Entities/deleteEntities
|
|
406
|
+
"""
|
|
407
|
+
|
|
408
|
+
uri = "workspaces/{0}/{1}/entities/delete".format(namespace, workspace)
|
|
409
|
+
if isinstance(ename, string_types):
|
|
410
|
+
body = [{"entityType":etype, "entityName":ename}]
|
|
411
|
+
elif isinstance(ename, Iterable):
|
|
412
|
+
body = [{"entityType":etype, "entityName":i} for i in ename]
|
|
413
|
+
|
|
414
|
+
return __post(uri, json=body)
|
|
415
|
+
|
|
416
|
+
def delete_entities_of_type(namespace, workspace, etype):
|
|
417
|
+
"""Delete all entities of a type in a workspace.
|
|
418
|
+
|
|
419
|
+
Note: This action is not reversible. Be careful!
|
|
420
|
+
|
|
421
|
+
Args:
|
|
422
|
+
namespace (str): project to which workspace belongs
|
|
423
|
+
workspace (str): Workspace name
|
|
424
|
+
etype (str): Entity type
|
|
425
|
+
|
|
426
|
+
Swagger:
|
|
427
|
+
https://api.firecloud.org/#/Entities/deleteEntitiesOfType
|
|
428
|
+
"""
|
|
429
|
+
|
|
430
|
+
uri = "workspaces/{0}/{1}/entityTypes/{2}".format(namespace, workspace,
|
|
431
|
+
etype)
|
|
432
|
+
return __delete(uri)
|
|
433
|
+
|
|
434
|
+
def delete_participant(namespace, workspace, name):
|
|
435
|
+
"""Delete participant in a workspace.
|
|
436
|
+
|
|
437
|
+
Convenience wrapper for api.delete_entity().
|
|
438
|
+
Note: This action is not reversible. Be careful!
|
|
439
|
+
|
|
440
|
+
Args:
|
|
441
|
+
namespace (str): project to which workspace belongs
|
|
442
|
+
workspace (str): Workspace name
|
|
443
|
+
name (str, or iterable of str): participant_id(s)
|
|
444
|
+
"""
|
|
445
|
+
return delete_entity_type(namespace, workspace, "participant", name)
|
|
446
|
+
|
|
447
|
+
def delete_participant_set(namespace, workspace, name):
|
|
448
|
+
"""Delete participant set in a workspace.
|
|
449
|
+
|
|
450
|
+
Convenience wrapper for api.delete_entity().
|
|
451
|
+
Note: This action is not reversible. Be careful!
|
|
452
|
+
|
|
453
|
+
Args:
|
|
454
|
+
namespace (str): project to which workspace belongs
|
|
455
|
+
workspace (str): Workspace name
|
|
456
|
+
name (str, or iterable of str): participant_set_id(s)
|
|
457
|
+
"""
|
|
458
|
+
return delete_entity_type(namespace, workspace, "participant_set", name)
|
|
459
|
+
|
|
460
|
+
def delete_sample(namespace, workspace, name):
|
|
461
|
+
"""Delete sample in a workspace.
|
|
462
|
+
|
|
463
|
+
Convenience wrapper for api.delete_entity().
|
|
464
|
+
Note: This action is not reversible. Be careful!
|
|
465
|
+
|
|
466
|
+
Args:
|
|
467
|
+
namespace (str): project to which workspace belongs
|
|
468
|
+
workspace (str): Workspace name
|
|
469
|
+
name (str, or iterable of str): sample_id(s)
|
|
470
|
+
"""
|
|
471
|
+
return delete_entity_type(namespace, workspace, "sample", name)
|
|
472
|
+
|
|
473
|
+
def delete_sample_set(namespace, workspace, name):
|
|
474
|
+
"""Delete sample set in a workspace.
|
|
475
|
+
|
|
476
|
+
Convenience wrapper for api.delete_entity().
|
|
477
|
+
Note: This action is not reversible. Be careful!
|
|
478
|
+
|
|
479
|
+
Args:
|
|
480
|
+
namespace (str): project to which workspace belongs
|
|
481
|
+
workspace (str): Workspace name
|
|
482
|
+
name (str, or iterable of str): sample_set_id(s)
|
|
483
|
+
"""
|
|
484
|
+
return delete_entity_type(namespace, workspace, "sample_set", name)
|
|
485
|
+
|
|
486
|
+
def delete_pair(namespace, workspace, name):
|
|
487
|
+
"""Delete pair in a workspace.
|
|
488
|
+
|
|
489
|
+
Convenience wrapper for api.delete_entity().
|
|
490
|
+
Note: This action is not reversible. Be careful!
|
|
491
|
+
|
|
492
|
+
Args:
|
|
493
|
+
namespace (str): project to which workspace belongs
|
|
494
|
+
workspace (str): Workspace name
|
|
495
|
+
name (str, or iterable of str): pair_id(s)
|
|
496
|
+
"""
|
|
497
|
+
return delete_entity_type(namespace, workspace, "pair", name)
|
|
498
|
+
|
|
499
|
+
def delete_pair_set(namespace, workspace, name):
|
|
500
|
+
"""Delete pair set in a workspace.
|
|
501
|
+
|
|
502
|
+
Convenience wrapper for api.delete_entity().
|
|
503
|
+
Note: This action is not reversible. Be careful!
|
|
504
|
+
|
|
505
|
+
Args:
|
|
506
|
+
namespace (str): project to which workspace belongs
|
|
507
|
+
workspace (str): Workspace name
|
|
508
|
+
name (str, or iterable of str): pair_set_id(s)
|
|
509
|
+
"""
|
|
510
|
+
return delete_entity_type(namespace, workspace, "pair_set", name)
|
|
511
|
+
|
|
512
|
+
def get_entities_query(namespace, workspace, etype, page=1, page_size=100,
|
|
513
|
+
sort_direction="asc", filter_terms=None,
|
|
514
|
+
filter_operator=None, fields=None):
|
|
515
|
+
"""Paginated version of get_entities_with_type.
|
|
516
|
+
|
|
517
|
+
Args:
|
|
518
|
+
namespace (str): project to which workspace belongs
|
|
519
|
+
workspace (str): Workspace name
|
|
520
|
+
etype (str): Entity type
|
|
521
|
+
page (int): Page number, 1-indexed
|
|
522
|
+
page_size (int): Number of entities to return per page
|
|
523
|
+
sort_direction (str): "asc" or "desc"
|
|
524
|
+
filter_terms (str): Space-separated list to text match
|
|
525
|
+
filter_operator (str): "and" or "or" - determines if one or all
|
|
526
|
+
filter_terms must have a match. Default: "and"
|
|
527
|
+
fields (str): Comma-separated list of which fields to populate
|
|
528
|
+
|
|
529
|
+
Swagger:
|
|
530
|
+
https://api.firecloud.org/#!/Entities/entityQuery
|
|
531
|
+
|
|
532
|
+
"""
|
|
533
|
+
|
|
534
|
+
# Initial parameters for pagination
|
|
535
|
+
params = {
|
|
536
|
+
"page" : page,
|
|
537
|
+
"pageSize" : page_size,
|
|
538
|
+
"sortDirection" : sort_direction
|
|
539
|
+
}
|
|
540
|
+
if filter_terms:
|
|
541
|
+
params['filterTerms'] = filter_terms
|
|
542
|
+
if filter_operator:
|
|
543
|
+
params['filterOperator'] = filter_operator
|
|
544
|
+
if fields:
|
|
545
|
+
params['fields'] = fields
|
|
546
|
+
|
|
547
|
+
uri = "workspaces/{0}/{1}/entityQuery/{2}".format(namespace,workspace,etype)
|
|
548
|
+
return __get(uri, params=params)
|
|
549
|
+
|
|
550
|
+
def rename_entity(namespace, workspace, etype, ename, name):
|
|
551
|
+
"""Rename entity in a workspace
|
|
552
|
+
|
|
553
|
+
Args:
|
|
554
|
+
namespace (str): project to which workspace belongs
|
|
555
|
+
workspace (str): Workspace name
|
|
556
|
+
etype (str): Entity type
|
|
557
|
+
ename (str): Entity name
|
|
558
|
+
name (str): New entity name
|
|
559
|
+
|
|
560
|
+
Swagger:
|
|
561
|
+
https://api.firecloud.org/#/Entities/renameEntity
|
|
562
|
+
"""
|
|
563
|
+
|
|
564
|
+
body = {"name": name}
|
|
565
|
+
uri = "workspaces/{0}/{1}/entities/{2}/{3}/rename".format(namespace,
|
|
566
|
+
workspace, etype,
|
|
567
|
+
ename)
|
|
568
|
+
return __post(uri, json=body)
|
|
569
|
+
|
|
570
|
+
def rename_entity_type(namespace, workspace, etype, name):
|
|
571
|
+
"""Rename entity type in a workspace
|
|
572
|
+
|
|
573
|
+
Args:
|
|
574
|
+
namespace (str): project to which workspace belongs
|
|
575
|
+
workspace (str): Workspace name
|
|
576
|
+
etype (str): Entity type
|
|
577
|
+
name (str): New entity type name
|
|
578
|
+
|
|
579
|
+
Swagger:
|
|
580
|
+
https://api.firecloud.org/#/Entities/renameEntityType
|
|
581
|
+
"""
|
|
582
|
+
|
|
583
|
+
body = {"newName": name}
|
|
584
|
+
uri = "workspaces/{0}/{1}/entityTypes/{2}".format(namespace, workspace,
|
|
585
|
+
etype)
|
|
586
|
+
return __patch(uri, json=body)
|
|
587
|
+
|
|
588
|
+
def rename_entity_type_attribute(namespace, workspace, etype, attr, name):
|
|
589
|
+
"""Change the attribute name for an entity type in a workspace. If the old
|
|
590
|
+
name doesn't exist the update will fail. If the new name already exists,
|
|
591
|
+
the update will fail, and no records will be updated.
|
|
592
|
+
|
|
593
|
+
Args:
|
|
594
|
+
namespace (str): project to which workspace belongs
|
|
595
|
+
workspace (str): Workspace name
|
|
596
|
+
etype (str): Entity type
|
|
597
|
+
attr (str): Attribute
|
|
598
|
+
name (str): New attribute name
|
|
599
|
+
|
|
600
|
+
Swagger:
|
|
601
|
+
https://api.firecloud.org/#/Entities/rename_entity_attributes
|
|
602
|
+
"""
|
|
603
|
+
body = {"newAttributeName": name}
|
|
604
|
+
uri = "workspaces/{0}/{1}/entityTypes/{2}/attributes/{3}".format(namespace,
|
|
605
|
+
workspace,
|
|
606
|
+
etype,
|
|
607
|
+
attr)
|
|
608
|
+
return __patch(uri, json=body)
|
|
609
|
+
|
|
610
|
+
def update_entity(namespace, workspace, etype, ename, updates):
|
|
611
|
+
""" Update entity attributes in a workspace.
|
|
612
|
+
|
|
613
|
+
Args:
|
|
614
|
+
namespace (str): project to which workspace belongs
|
|
615
|
+
workspace (str): Workspace name
|
|
616
|
+
etype (str): Entity type
|
|
617
|
+
ename (str): Entity name
|
|
618
|
+
updates (list(dict)): List of updates to entity from _attr_set, e.g.
|
|
619
|
+
|
|
620
|
+
Swagger:
|
|
621
|
+
https://api.firecloud.org/#!/Entities/update_entity
|
|
622
|
+
"""
|
|
623
|
+
headers = _fiss_agent_header({"Content-type": "application/json"})
|
|
624
|
+
uri = "{0}workspaces/{1}/{2}/entities/{3}/{4}".format(fcconfig.root_url,
|
|
625
|
+
namespace, workspace, etype, ename)
|
|
626
|
+
|
|
627
|
+
# FIXME: create __patch method, akin to __get, __delete etc
|
|
628
|
+
return __SESSION.patch(uri, headers=headers, json=updates)
|
|
629
|
+
|
|
630
|
+
###############################
|
|
631
|
+
### 1.2 Method Configurations
|
|
632
|
+
###############################
|
|
633
|
+
|
|
634
|
+
def list_workspace_configs(namespace, workspace, allRepos=False):
|
|
635
|
+
"""List method configurations in workspace.
|
|
636
|
+
|
|
637
|
+
Args:
|
|
638
|
+
namespace (str): project to which workspace belongs
|
|
639
|
+
workspace (str): Workspace name
|
|
640
|
+
allRepos (bool): list configs for all repos, not just Agora
|
|
641
|
+
|
|
642
|
+
Swagger:
|
|
643
|
+
https://api.firecloud.org/#!/Method_Configurations/listWorkspaceMethodConfigs
|
|
644
|
+
DUPLICATE: https://api.firecloud.org/#!/Workspaces/listWorkspaceMethodConfigs
|
|
645
|
+
"""
|
|
646
|
+
uri = "workspaces/{0}/{1}/methodconfigs".format(namespace, workspace)
|
|
647
|
+
return __get(uri, params={'allRepos': allRepos})
|
|
648
|
+
|
|
649
|
+
def create_workspace_config(namespace, workspace, body):
|
|
650
|
+
"""Create method configuration in workspace.
|
|
651
|
+
|
|
652
|
+
Args:
|
|
653
|
+
namespace (str): project to which workspace belongs
|
|
654
|
+
workspace (str): Workspace name
|
|
655
|
+
body (json) : a filled-in JSON object for the new method config
|
|
656
|
+
(e.g. see return value of get_workspace_config)
|
|
657
|
+
|
|
658
|
+
Swagger:
|
|
659
|
+
https://api.firecloud.org/#!/Method_Configurations/postWorkspaceMethodConfig
|
|
660
|
+
DUPLICATE: https://api.firecloud.org/#!/Workspaces/postWorkspaceMethodConfig
|
|
661
|
+
"""
|
|
662
|
+
|
|
663
|
+
#json_body = {
|
|
664
|
+
# "namespace" : mnamespace,
|
|
665
|
+
# "name" : method,
|
|
666
|
+
# "rootEntityType" : root_etype,
|
|
667
|
+
# "inputs" : {},
|
|
668
|
+
# "outputs" : {},
|
|
669
|
+
# "prerequisites" : {}
|
|
670
|
+
#}
|
|
671
|
+
uri = "workspaces/{0}/{1}/methodconfigs".format(namespace, workspace)
|
|
672
|
+
return __post(uri, json=body)
|
|
673
|
+
|
|
674
|
+
def delete_workspace_config(namespace, workspace, cnamespace, config):
|
|
675
|
+
"""Delete method configuration in workspace.
|
|
676
|
+
|
|
677
|
+
Args:
|
|
678
|
+
namespace (str): project to which workspace belongs
|
|
679
|
+
workspace (str): Workspace name
|
|
680
|
+
mnamespace (str): Method namespace
|
|
681
|
+
method (str): Method name
|
|
682
|
+
|
|
683
|
+
Swagger:
|
|
684
|
+
https://api.firecloud.org/#!/Method_Configurations/deleteWorkspaceMethodConfig
|
|
685
|
+
"""
|
|
686
|
+
uri = "workspaces/{0}/{1}/method_configs/{2}/{3}".format(namespace,
|
|
687
|
+
workspace, cnamespace, config)
|
|
688
|
+
return __delete(uri)
|
|
689
|
+
|
|
690
|
+
def get_workspace_config(namespace, workspace, cnamespace, config):
|
|
691
|
+
"""Get method configuration in workspace.
|
|
692
|
+
|
|
693
|
+
Args:
|
|
694
|
+
namespace (str): project to which workspace belongs
|
|
695
|
+
workspace (str): Workspace name
|
|
696
|
+
cnamespace (str): Config namespace
|
|
697
|
+
config (str): Config name
|
|
698
|
+
|
|
699
|
+
Swagger:
|
|
700
|
+
https://api.firecloud.org/#!/Method_Configurations/getWorkspaceMethodConfig
|
|
701
|
+
"""
|
|
702
|
+
|
|
703
|
+
uri = "workspaces/{0}/{1}/method_configs/{2}/{3}".format(namespace,
|
|
704
|
+
workspace, cnamespace, config)
|
|
705
|
+
return __get(uri)
|
|
706
|
+
|
|
707
|
+
def overwrite_workspace_config(namespace, workspace, cnamespace, configname, body):
|
|
708
|
+
"""Add or overwrite method configuration in workspace.
|
|
709
|
+
|
|
710
|
+
Args:
|
|
711
|
+
namespace (str): project to which workspace belongs
|
|
712
|
+
workspace (str): Workspace name
|
|
713
|
+
cnamespace (str): Configuration namespace
|
|
714
|
+
configname (str): Configuration name
|
|
715
|
+
body (json): new body (definition) of the method config
|
|
716
|
+
|
|
717
|
+
Swagger:
|
|
718
|
+
https://api.firecloud.org/#!/Method_Configurations/overwriteWorkspaceMethodConfig
|
|
719
|
+
"""
|
|
720
|
+
headers = _fiss_agent_header({"Content-type": "application/json"})
|
|
721
|
+
uri = "workspaces/{0}/{1}/method_configs/{2}/{3}".format(namespace,
|
|
722
|
+
workspace, cnamespace, configname)
|
|
723
|
+
return __put(uri, headers=headers, json=body)
|
|
724
|
+
|
|
725
|
+
def update_workspace_config(namespace, workspace, cnamespace, configname, body):
|
|
726
|
+
"""Update method configuration in workspace.
|
|
727
|
+
|
|
728
|
+
Args:
|
|
729
|
+
namespace (str): project to which workspace belongs
|
|
730
|
+
workspace (str): Workspace name
|
|
731
|
+
cnamespace (str): Configuration namespace
|
|
732
|
+
configname (str): Configuration name
|
|
733
|
+
body (json): new body (definition) of the method config
|
|
734
|
+
|
|
735
|
+
Swagger:
|
|
736
|
+
https://api.firecloud.org/#!/Method_Configurations/updateWorkspaceMethodConfig
|
|
737
|
+
"""
|
|
738
|
+
uri = "workspaces/{0}/{1}/method_configs/{2}/{3}".format(namespace,
|
|
739
|
+
workspace, cnamespace, configname)
|
|
740
|
+
return __post(uri, json=body)
|
|
741
|
+
|
|
742
|
+
def validate_config(namespace, workspace, cnamespace, config):
|
|
743
|
+
"""Get syntax validation for a configuration.
|
|
744
|
+
|
|
745
|
+
Args:
|
|
746
|
+
namespace (str): project to which workspace belongs
|
|
747
|
+
workspace (str): Workspace name
|
|
748
|
+
cnamespace (str): Configuration namespace
|
|
749
|
+
config (str): Configuration name
|
|
750
|
+
|
|
751
|
+
Swagger:
|
|
752
|
+
https://api.firecloud.org/#!/Method_Configurations/validate_method_configuration
|
|
753
|
+
"""
|
|
754
|
+
uri = "workspaces/{0}/{1}/method_configs/{2}/{3}/validate".format(namespace,
|
|
755
|
+
workspace, cnamespace, config)
|
|
756
|
+
return __get(uri)
|
|
757
|
+
|
|
758
|
+
def rename_workspace_config(namespace, workspace, cnamespace, config,
|
|
759
|
+
new_namespace, new_name):
|
|
760
|
+
"""Rename a method configuration in a workspace.
|
|
761
|
+
|
|
762
|
+
Args:
|
|
763
|
+
namespace (str): project to which workspace belongs
|
|
764
|
+
workspace (str): Workspace name
|
|
765
|
+
mnamespace (str): Config namespace
|
|
766
|
+
config (str): Config name
|
|
767
|
+
new_namespace (str): Updated config namespace
|
|
768
|
+
new_name (str): Updated method name
|
|
769
|
+
|
|
770
|
+
Swagger:
|
|
771
|
+
https://api.firecloud.org/#!/Method_Configurations/renameWorkspaceMethodConfig
|
|
772
|
+
"""
|
|
773
|
+
|
|
774
|
+
body = {
|
|
775
|
+
"namespace" : new_namespace,
|
|
776
|
+
"name" : new_name,
|
|
777
|
+
# I have no idea why this is required by FC, but it is...
|
|
778
|
+
"workspaceName" : {
|
|
779
|
+
"namespace" : namespace,
|
|
780
|
+
"name" : workspace
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
uri = "workspaces/{0}/{1}/method_configs/{2}/{3}/rename".format(namespace,
|
|
784
|
+
workspace, cnamespace, config)
|
|
785
|
+
return __post(uri, json=body)
|
|
786
|
+
|
|
787
|
+
def copy_config_from_repo(namespace, workspace, from_cnamespace,
|
|
788
|
+
from_config, from_snapshot_id, to_cnamespace,
|
|
789
|
+
to_config):
|
|
790
|
+
"""Copy a method config from the methods repository to a workspace.
|
|
791
|
+
|
|
792
|
+
Args:
|
|
793
|
+
namespace (str): project to which workspace belongs
|
|
794
|
+
workspace (str): Workspace name
|
|
795
|
+
from_cnamespace (str): Source configuration namespace
|
|
796
|
+
from_config (str): Source configuration name
|
|
797
|
+
from_snapshot_id (int): Source configuration snapshot_id
|
|
798
|
+
to_cnamespace (str): Target configuration namespace
|
|
799
|
+
to_config (str): Target configuration name
|
|
800
|
+
|
|
801
|
+
Swagger:
|
|
802
|
+
https://api.firecloud.org/#!/Method_Configurations/copyFromMethodRepo
|
|
803
|
+
DUPLICATE: https://api.firecloud.org/#!/Method_Repository/copyFromMethodRepo
|
|
804
|
+
"""
|
|
805
|
+
|
|
806
|
+
body = {
|
|
807
|
+
"configurationNamespace" : from_cnamespace,
|
|
808
|
+
"configurationName" : from_config,
|
|
809
|
+
"configurationSnapshotId" : from_snapshot_id,
|
|
810
|
+
"destinationNamespace" : to_cnamespace,
|
|
811
|
+
"destinationName" : to_config
|
|
812
|
+
}
|
|
813
|
+
uri = "workspaces/{0}/{1}/method_configs/copyFromMethodRepo".format(
|
|
814
|
+
namespace, workspace)
|
|
815
|
+
return __post(uri, json=body)
|
|
816
|
+
|
|
817
|
+
def copy_config_to_repo(namespace, workspace, from_cnamespace,
|
|
818
|
+
from_config, to_cnamespace, to_config):
|
|
819
|
+
"""Copy a method config from a workspace to the methods repository.
|
|
820
|
+
|
|
821
|
+
Args:
|
|
822
|
+
namespace (str): project to which workspace belongs
|
|
823
|
+
workspace (str): Workspace name
|
|
824
|
+
from_cnamespace (str): Source configuration namespace
|
|
825
|
+
from_config (str): Source configuration name
|
|
826
|
+
to_cnamespace (str): Target configuration namespace
|
|
827
|
+
to_config (str): Target configuration name
|
|
828
|
+
|
|
829
|
+
Swagger:
|
|
830
|
+
https://api.firecloud.org/#!/Method_Configurations/copyToMethodRepo
|
|
831
|
+
DUPLICATE: https://api.firecloud.org/#!/Method_Repository/copyToMethodRepo
|
|
832
|
+
"""
|
|
833
|
+
|
|
834
|
+
body = {
|
|
835
|
+
"configurationNamespace" : to_cnamespace,
|
|
836
|
+
"configurationName" : to_config,
|
|
837
|
+
"sourceNamespace" : from_cnamespace,
|
|
838
|
+
"sourceName" : from_config
|
|
839
|
+
}
|
|
840
|
+
uri = "workspaces/{0}/{1}/method_configs/copyToMethodRepo".format(
|
|
841
|
+
namespace, workspace)
|
|
842
|
+
return __post(uri, json=body)
|
|
843
|
+
|
|
844
|
+
###########################
|
|
845
|
+
### 1.3 Method Repository
|
|
846
|
+
###########################
|
|
847
|
+
|
|
848
|
+
def list_repository_methods(namespace=None, name=None, snapshotId=None):
|
|
849
|
+
"""List method(s) in the methods repository.
|
|
850
|
+
|
|
851
|
+
Args:
|
|
852
|
+
namespace (str): Method Repository namespace
|
|
853
|
+
name (str): method name
|
|
854
|
+
snapshotId (int): method snapshot ID
|
|
855
|
+
|
|
856
|
+
Swagger:
|
|
857
|
+
https://api.firecloud.org/#!/Method_Repository/listMethodRepositoryMethods
|
|
858
|
+
"""
|
|
859
|
+
params = {k:v for (k,v) in locals().items() if v is not None}
|
|
860
|
+
return __get("methods", params=params)
|
|
861
|
+
|
|
862
|
+
def list_repository_configs(namespace=None, name=None, snapshotId=None):
|
|
863
|
+
"""List configurations in the methods repository.
|
|
864
|
+
|
|
865
|
+
Args:
|
|
866
|
+
namespace (str): Method Repository namespace
|
|
867
|
+
name (str): config name
|
|
868
|
+
snapshotId (int): config snapshot ID
|
|
869
|
+
|
|
870
|
+
Swagger:
|
|
871
|
+
https://api.firecloud.org/#!/Method_Repository/listMethodRepositoryConfigurations
|
|
872
|
+
"""
|
|
873
|
+
params = {k:v for (k,v) in locals().items() if v is not None}
|
|
874
|
+
return __get("configurations", params=params)
|
|
875
|
+
|
|
876
|
+
def get_config_template(namespace, method, version):
|
|
877
|
+
"""Get the configuration template for a method.
|
|
878
|
+
|
|
879
|
+
The method should exist in the methods repository.
|
|
880
|
+
|
|
881
|
+
Args:
|
|
882
|
+
namespace (str): Method's namespace
|
|
883
|
+
method (str): method name
|
|
884
|
+
version (int): snapshot_id of the method
|
|
885
|
+
|
|
886
|
+
Swagger:
|
|
887
|
+
https://api.firecloud.org/#!/Method_Repository/createMethodTemplate
|
|
888
|
+
"""
|
|
889
|
+
|
|
890
|
+
body = {
|
|
891
|
+
"methodNamespace" : namespace,
|
|
892
|
+
"methodName" : method,
|
|
893
|
+
"methodVersion" : int(version)
|
|
894
|
+
}
|
|
895
|
+
return __post("template", json=body)
|
|
896
|
+
|
|
897
|
+
def get_inputs_outputs(namespace, method, snapshot_id):
|
|
898
|
+
"""Get a description of the inputs and outputs for a method.
|
|
899
|
+
|
|
900
|
+
The method should exist in the methods repository.
|
|
901
|
+
|
|
902
|
+
Args:
|
|
903
|
+
namespace (str): Methods namespace
|
|
904
|
+
method (str): method name
|
|
905
|
+
snapshot_id (int): snapshot_id of the method
|
|
906
|
+
|
|
907
|
+
Swagger:
|
|
908
|
+
https://api.firecloud.org/#!/Method_Repository/getMethodIO
|
|
909
|
+
"""
|
|
910
|
+
|
|
911
|
+
body = {
|
|
912
|
+
"methodNamespace" : namespace,
|
|
913
|
+
"methodName" : method,
|
|
914
|
+
"methodVersion" : snapshot_id
|
|
915
|
+
}
|
|
916
|
+
return __post("inputsOutputs", json=body)
|
|
917
|
+
|
|
918
|
+
def get_repository_config(namespace, config, snapshot_id):
|
|
919
|
+
"""Get a method configuration from the methods repository.
|
|
920
|
+
|
|
921
|
+
Args:
|
|
922
|
+
namespace (str): Methods namespace
|
|
923
|
+
config (str): config name
|
|
924
|
+
snapshot_id (int): snapshot_id of the method
|
|
925
|
+
|
|
926
|
+
Swagger:
|
|
927
|
+
https://api.firecloud.org/#!/Method_Repository/getMethodRepositoryConfiguration
|
|
928
|
+
"""
|
|
929
|
+
uri = "configurations/{0}/{1}/{2}".format(namespace, config, snapshot_id)
|
|
930
|
+
return __get(uri)
|
|
931
|
+
|
|
932
|
+
def get_repository_method(namespace, method, snapshot_id, wdl_only=False):
|
|
933
|
+
"""Get a method definition from the method repository.
|
|
934
|
+
|
|
935
|
+
Args:
|
|
936
|
+
namespace (str): Methods namespace
|
|
937
|
+
method (str): method name
|
|
938
|
+
version (int): snapshot_id of the method
|
|
939
|
+
wdl_only (bool): Exclude metadata
|
|
940
|
+
|
|
941
|
+
Swagger:
|
|
942
|
+
https://api.firecloud.org/#!/Method_Repository/get_api_methods_namespace_name_snapshotId
|
|
943
|
+
"""
|
|
944
|
+
uri = "methods/{0}/{1}/{2}?onlyPayload={3}".format(namespace, method,
|
|
945
|
+
snapshot_id,
|
|
946
|
+
str(wdl_only).lower())
|
|
947
|
+
return __get(uri)
|
|
948
|
+
|
|
949
|
+
def update_repository_method(namespace, method, synopsis, wdl, doc=None,
|
|
950
|
+
comment=""):
|
|
951
|
+
"""Create/Update workflow definition.
|
|
952
|
+
|
|
953
|
+
FireCloud will create a new snapshot_id for the given workflow.
|
|
954
|
+
|
|
955
|
+
Args:
|
|
956
|
+
namespace (str): Methods namespace
|
|
957
|
+
method (str): method name
|
|
958
|
+
synopsis (str): short (<80 char) description of method
|
|
959
|
+
wdl (file): Workflow Description Language file
|
|
960
|
+
doc (file): (Optional) Additional documentation
|
|
961
|
+
comment (str): (Optional) Comment specific to this snapshot
|
|
962
|
+
|
|
963
|
+
Swagger:
|
|
964
|
+
https://api.firecloud.org/#!/Method_Repository/post_api_methods
|
|
965
|
+
|
|
966
|
+
"""
|
|
967
|
+
with open(wdl, 'r') as wf:
|
|
968
|
+
wdl_payload = wf.read()
|
|
969
|
+
if doc is not None:
|
|
970
|
+
with open (doc, 'r') as df:
|
|
971
|
+
doc = df.read()
|
|
972
|
+
|
|
973
|
+
body = {
|
|
974
|
+
"namespace": namespace,
|
|
975
|
+
"name": method,
|
|
976
|
+
"entityType": "Workflow",
|
|
977
|
+
"payload": wdl_payload,
|
|
978
|
+
"documentation": doc,
|
|
979
|
+
"synopsis": synopsis,
|
|
980
|
+
"snapshotComment": comment
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
return __post("methods",
|
|
984
|
+
json={key: value for key, value in body.items() if value})
|
|
985
|
+
|
|
986
|
+
def delete_repository_method(namespace, name, snapshot_id):
|
|
987
|
+
"""Redacts a method and all of its associated configurations.
|
|
988
|
+
|
|
989
|
+
The method should exist in the methods repository.
|
|
990
|
+
|
|
991
|
+
Args:
|
|
992
|
+
namespace (str): Methods namespace
|
|
993
|
+
method (str): method name
|
|
994
|
+
snapshot_id (int): snapshot_id of the method
|
|
995
|
+
|
|
996
|
+
Swagger:
|
|
997
|
+
https://api.firecloud.org/#!/Method_Repository/delete_api_methods_namespace_name_snapshotId
|
|
998
|
+
"""
|
|
999
|
+
uri = "methods/{0}/{1}/{2}".format(namespace, name, snapshot_id)
|
|
1000
|
+
return __delete(uri)
|
|
1001
|
+
|
|
1002
|
+
def delete_repository_config(namespace, name, snapshot_id):
|
|
1003
|
+
"""Redacts a configuration and all of its associated configurations.
|
|
1004
|
+
|
|
1005
|
+
The configuration should exist in the methods repository.
|
|
1006
|
+
|
|
1007
|
+
Args:
|
|
1008
|
+
namespace (str): configuration namespace
|
|
1009
|
+
configuration (str): configuration name
|
|
1010
|
+
snapshot_id (int): snapshot_id of the configuration
|
|
1011
|
+
|
|
1012
|
+
Swagger:
|
|
1013
|
+
https://api.firecloud.org/#!/Method_Repository/delete_api_configurations_namespace_name_snapshotId
|
|
1014
|
+
"""
|
|
1015
|
+
uri = "configurations/{0}/{1}/{2}".format(namespace, name, snapshot_id)
|
|
1016
|
+
return __delete(uri)
|
|
1017
|
+
|
|
1018
|
+
def get_repository_method_acl(namespace, method, snapshot_id):
|
|
1019
|
+
"""Get permissions for a method.
|
|
1020
|
+
|
|
1021
|
+
The method should exist in the methods repository.
|
|
1022
|
+
|
|
1023
|
+
Args:
|
|
1024
|
+
namespace (str): Methods namespace
|
|
1025
|
+
method (str): method name
|
|
1026
|
+
version (int): snapshot_id of the method
|
|
1027
|
+
|
|
1028
|
+
Swagger:
|
|
1029
|
+
https://api.firecloud.org/#!/Method_Repository/getMethodACL
|
|
1030
|
+
"""
|
|
1031
|
+
uri = "methods/{0}/{1}/{2}/permissions".format(namespace,method,snapshot_id)
|
|
1032
|
+
return __get(uri)
|
|
1033
|
+
|
|
1034
|
+
def update_repository_method_acl(namespace, method, snapshot_id, acl_updates):
|
|
1035
|
+
"""Set method permissions.
|
|
1036
|
+
|
|
1037
|
+
The method should exist in the methods repository.
|
|
1038
|
+
|
|
1039
|
+
Args:
|
|
1040
|
+
namespace (str): Methods namespace
|
|
1041
|
+
method (str): method name
|
|
1042
|
+
snapshot_id (int): snapshot_id of the method
|
|
1043
|
+
acl_updates (list(dict)): List of access control updates
|
|
1044
|
+
|
|
1045
|
+
Swagger:
|
|
1046
|
+
https://api.firecloud.org/#!/Method_Repository/setMethodACL
|
|
1047
|
+
"""
|
|
1048
|
+
|
|
1049
|
+
uri = "methods/{0}/{1}/{2}/permissions".format(namespace,method,snapshot_id)
|
|
1050
|
+
return __post(uri, json=acl_updates)
|
|
1051
|
+
|
|
1052
|
+
def get_repository_config_acl(namespace, config, snapshot_id):
|
|
1053
|
+
"""Get configuration permissions.
|
|
1054
|
+
|
|
1055
|
+
The configuration should exist in the methods repository.
|
|
1056
|
+
|
|
1057
|
+
Args:
|
|
1058
|
+
namespace (str): Configuration namespace
|
|
1059
|
+
config (str): Configuration name
|
|
1060
|
+
snapshot_id (int): snapshot_id of the method
|
|
1061
|
+
|
|
1062
|
+
Swagger:
|
|
1063
|
+
https://api.firecloud.org/#!/Method_Repository/getConfigACL
|
|
1064
|
+
"""
|
|
1065
|
+
uri = "configurations/{0}/{1}/{2}/permissions".format(namespace,
|
|
1066
|
+
config, snapshot_id)
|
|
1067
|
+
return __get(uri)
|
|
1068
|
+
|
|
1069
|
+
def update_repository_config_acl(namespace, config, snapshot_id, acl_updates):
|
|
1070
|
+
"""Set configuration permissions.
|
|
1071
|
+
|
|
1072
|
+
The configuration should exist in the methods repository.
|
|
1073
|
+
|
|
1074
|
+
Args:
|
|
1075
|
+
namespace (str): Configuration namespace
|
|
1076
|
+
config (str): Configuration name
|
|
1077
|
+
snapshot_id (int): snapshot_id of the method
|
|
1078
|
+
acl_updates (list(dict)): List of access control updates
|
|
1079
|
+
|
|
1080
|
+
Swagger:
|
|
1081
|
+
https://api.firecloud.org/#!/Method_Repository/setConfigACL
|
|
1082
|
+
"""
|
|
1083
|
+
|
|
1084
|
+
uri = "configurations/{0}/{1}/{2}/permissions".format(namespace,
|
|
1085
|
+
config, snapshot_id)
|
|
1086
|
+
return __post(uri, json=acl_updates)
|
|
1087
|
+
|
|
1088
|
+
def get_method_configurations(namespace, method_name):
|
|
1089
|
+
"""Get method configurations.
|
|
1090
|
+
|
|
1091
|
+
Given the namespace/name of a method, returns all configurations in
|
|
1092
|
+
the repository that reference that method.
|
|
1093
|
+
|
|
1094
|
+
Args:
|
|
1095
|
+
namespace (str): Method namespace
|
|
1096
|
+
method_name (str): Method name
|
|
1097
|
+
|
|
1098
|
+
Swagger:
|
|
1099
|
+
https://api.firecloud.org/#!/Method_Repository/get_api_methods_namespace_name_configurations
|
|
1100
|
+
|
|
1101
|
+
"""
|
|
1102
|
+
|
|
1103
|
+
uri = "methods/{0}/{1}/configurations".format(namespace, method_name)
|
|
1104
|
+
|
|
1105
|
+
return __get(uri)
|
|
1106
|
+
|
|
1107
|
+
def get_api_methods_definitions():
|
|
1108
|
+
"""List method definitions.
|
|
1109
|
+
|
|
1110
|
+
List method definitions - i.e. unique namespace/name pairs -
|
|
1111
|
+
with counts of snapshots and associated configurations
|
|
1112
|
+
|
|
1113
|
+
Swagger:
|
|
1114
|
+
https://api.firecloud.org/#!/Method_Repository/get_api_methods_definitions
|
|
1115
|
+
|
|
1116
|
+
"""
|
|
1117
|
+
|
|
1118
|
+
uri = "methods/definitions"
|
|
1119
|
+
|
|
1120
|
+
return __get(uri)
|
|
1121
|
+
|
|
1122
|
+
|
|
1123
|
+
#################
|
|
1124
|
+
### 1.4 Profile
|
|
1125
|
+
#################
|
|
1126
|
+
|
|
1127
|
+
def list_billing_projects():
|
|
1128
|
+
"""list billing projects for a user.
|
|
1129
|
+
|
|
1130
|
+
Swagger:
|
|
1131
|
+
https://api.firecloud.org/#/BillingV2/listUserBillingProjectsV2
|
|
1132
|
+
"""
|
|
1133
|
+
return __get("billing/v2")
|
|
1134
|
+
|
|
1135
|
+
def get_proxy_group(email=None):
|
|
1136
|
+
"""Returns the proxy group email for the current user
|
|
1137
|
+
|
|
1138
|
+
Args:
|
|
1139
|
+
email (str): User email whose proxy group to retrieve
|
|
1140
|
+
if None uses current user email
|
|
1141
|
+
|
|
1142
|
+
Swagger:
|
|
1143
|
+
https://api.firecloud.org/#/Profile/getProxyGroup
|
|
1144
|
+
"""
|
|
1145
|
+
if email is None:
|
|
1146
|
+
email = whoami()
|
|
1147
|
+
uri = "proxyGroup/{}".format(email)
|
|
1148
|
+
return __get(uri)
|
|
1149
|
+
|
|
1150
|
+
################
|
|
1151
|
+
### 1.5 Status
|
|
1152
|
+
################
|
|
1153
|
+
|
|
1154
|
+
def get_status():
|
|
1155
|
+
"""Request the status of FireCloud services.
|
|
1156
|
+
|
|
1157
|
+
Swagger:
|
|
1158
|
+
https://api.firecloud.org/#!/Status/status
|
|
1159
|
+
"""
|
|
1160
|
+
root_url = fcconfig.root_url.rpartition("api")[0]
|
|
1161
|
+
return __get("status", root_url=root_url)
|
|
1162
|
+
|
|
1163
|
+
def health():
|
|
1164
|
+
"""Health of FireCloud API.
|
|
1165
|
+
|
|
1166
|
+
Swagger:
|
|
1167
|
+
https://api.firecloud.org/#!/Status/health
|
|
1168
|
+
"""
|
|
1169
|
+
root_url = fcconfig.root_url.rpartition("api")[0]
|
|
1170
|
+
return __get("health", root_url=root_url)
|
|
1171
|
+
|
|
1172
|
+
######################
|
|
1173
|
+
### 1.6 Submissions
|
|
1174
|
+
######################
|
|
1175
|
+
|
|
1176
|
+
def list_submissions(namespace, workspace):
|
|
1177
|
+
"""List submissions in FireCloud workspace.
|
|
1178
|
+
|
|
1179
|
+
Args:
|
|
1180
|
+
namespace (str): project to which workspace belongs
|
|
1181
|
+
workspace (str): Workspace name
|
|
1182
|
+
|
|
1183
|
+
Swagger:
|
|
1184
|
+
https://api.firecloud.org/#!/Submissions/listSubmissions
|
|
1185
|
+
"""
|
|
1186
|
+
uri = "workspaces/{0}/{1}/submissions".format(namespace, workspace)
|
|
1187
|
+
return __get(uri)
|
|
1188
|
+
|
|
1189
|
+
def create_submission(wnamespace, workspace, cnamespace, config,
|
|
1190
|
+
entity=None, etype=None, expression=None,
|
|
1191
|
+
use_callcache=True, delete_intermediate_output_files=False,
|
|
1192
|
+
use_reference_disks=False, memory_retry_multiplier=0,
|
|
1193
|
+
per_workflow_cost_cap=None, workflow_failure_mode="",
|
|
1194
|
+
user_comment=""):
|
|
1195
|
+
"""Submit job in FireCloud workspace.
|
|
1196
|
+
|
|
1197
|
+
Args:
|
|
1198
|
+
wnamespace (str): project to which workspace belongs
|
|
1199
|
+
workspace (str): Workspace name
|
|
1200
|
+
cnamespace (str): Method configuration namespace
|
|
1201
|
+
config (str): Method configuration name
|
|
1202
|
+
entity (str): Entity to submit job on. Should be the same type as
|
|
1203
|
+
the root entity type of the method config, unless an
|
|
1204
|
+
expression is used
|
|
1205
|
+
etype (str): Entity type of root_entity
|
|
1206
|
+
expression (str): Instead of using entity as the root entity,
|
|
1207
|
+
evaluate the root entity from this expression.
|
|
1208
|
+
use_callcache (bool): use call cache if applicable (default: true)
|
|
1209
|
+
delete_intermediate_output_files (bool): Whether or not to delete
|
|
1210
|
+
intermediate output files when the workflow completes. See Cromwell
|
|
1211
|
+
docs (https://cromwell.readthedocs.io/en/develop/wf_options/Google)
|
|
1212
|
+
for more information
|
|
1213
|
+
use_reference_disks (bool): Whether or not to use pre-built disks for
|
|
1214
|
+
common genome references
|
|
1215
|
+
memory_retry_multiplier (float): If a task fails due to running out of
|
|
1216
|
+
memory and the task has maxRetries in its runtime attributes, then
|
|
1217
|
+
it will be retried with its memory multiplied by this amount. See
|
|
1218
|
+
Cromwell docs
|
|
1219
|
+
(https://cromwell.readthedocs.io/en/develop/cromwell_features/RetryWithMoreMemory)
|
|
1220
|
+
for more information
|
|
1221
|
+
per_workflow_cost_cap (float): A cost threshold in USD to apply to individual
|
|
1222
|
+
workflows. When the estimated cost is exceeded, the workflow is terminated.
|
|
1223
|
+
workflow_failure_mode (str): What happens after a task fails. Choose from
|
|
1224
|
+
ContinueWhilePossible and NoNewCalls. Defaults to NoNewCalls if not
|
|
1225
|
+
specified. See Cromwell docs
|
|
1226
|
+
(https://cromwell.readthedocs.io/en/develop/execution/ExecutionTwists/#failure-modes)
|
|
1227
|
+
for more information.
|
|
1228
|
+
user_comment: Freeform user defined description, optional (max length
|
|
1229
|
+
1000 characters)
|
|
1230
|
+
|
|
1231
|
+
Swagger:
|
|
1232
|
+
https://api.firecloud.org/#!/Submissions/createSubmission
|
|
1233
|
+
"""
|
|
1234
|
+
|
|
1235
|
+
uri = "workspaces/{0}/{1}/submissions".format(wnamespace, workspace)
|
|
1236
|
+
body = {
|
|
1237
|
+
"methodConfigurationNamespace" : cnamespace,
|
|
1238
|
+
"methodConfigurationName" : config,
|
|
1239
|
+
"useCallCache" : use_callcache
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
if etype:
|
|
1243
|
+
body['entityType'] = etype
|
|
1244
|
+
|
|
1245
|
+
if entity:
|
|
1246
|
+
body['entityName'] = entity
|
|
1247
|
+
|
|
1248
|
+
if expression:
|
|
1249
|
+
body['expression'] = expression
|
|
1250
|
+
|
|
1251
|
+
if delete_intermediate_output_files:
|
|
1252
|
+
body['deleteIntermediateOutputFiles'] = delete_intermediate_output_files
|
|
1253
|
+
|
|
1254
|
+
if use_reference_disks:
|
|
1255
|
+
body['useReferenceDisks'] = use_reference_disks
|
|
1256
|
+
|
|
1257
|
+
if memory_retry_multiplier:
|
|
1258
|
+
body['memoryRetryMultiplier'] = memory_retry_multiplier
|
|
1259
|
+
|
|
1260
|
+
if per_workflow_cost_cap:
|
|
1261
|
+
body['perWorkflowCostCap'] = per_workflow_cost_cap
|
|
1262
|
+
|
|
1263
|
+
if workflow_failure_mode:
|
|
1264
|
+
body['workflowFailureMode'] = workflow_failure_mode
|
|
1265
|
+
|
|
1266
|
+
if user_comment:
|
|
1267
|
+
body['userComment'] = user_comment
|
|
1268
|
+
|
|
1269
|
+
return __post(uri, json=body)
|
|
1270
|
+
|
|
1271
|
+
def abort_submission(namespace, workspace, submission_id):
|
|
1272
|
+
"""Abort running job in a workspace.
|
|
1273
|
+
|
|
1274
|
+
Args:
|
|
1275
|
+
namespace (str): project to which workspace belongs
|
|
1276
|
+
workspace (str): Workspace name
|
|
1277
|
+
submission_id (str): Submission's unique identifier
|
|
1278
|
+
|
|
1279
|
+
Swagger:
|
|
1280
|
+
https://api.firecloud.org/#!/Submissions/deleteSubmission
|
|
1281
|
+
"""
|
|
1282
|
+
uri = "workspaces/{0}/{1}/submissions/{2}".format(namespace,
|
|
1283
|
+
workspace, submission_id)
|
|
1284
|
+
return __delete(uri)
|
|
1285
|
+
|
|
1286
|
+
def get_submission(namespace, workspace, submission_id):
|
|
1287
|
+
"""Request submission information.
|
|
1288
|
+
|
|
1289
|
+
Args:
|
|
1290
|
+
namespace (str): project to which workspace belongs
|
|
1291
|
+
workspace (str): Workspace name
|
|
1292
|
+
submission_id (str): Submission's unique identifier
|
|
1293
|
+
|
|
1294
|
+
Swagger:
|
|
1295
|
+
https://api.firecloud.org/#!/Submissions/monitorSubmission
|
|
1296
|
+
"""
|
|
1297
|
+
uri = "workspaces/{0}/{1}/submissions/{2}".format(namespace,
|
|
1298
|
+
workspace, submission_id)
|
|
1299
|
+
return __get(uri)
|
|
1300
|
+
|
|
1301
|
+
def get_workflow_metadata(namespace, workspace, submission_id, workflow_id,
|
|
1302
|
+
include_key=None, exclude_key=None,
|
|
1303
|
+
expand_sub_workflows=False):
|
|
1304
|
+
"""Request the metadata for a workflow in a submission.
|
|
1305
|
+
|
|
1306
|
+
Args:
|
|
1307
|
+
namespace (str): project to which workspace belongs
|
|
1308
|
+
workspace (str): Workspace name
|
|
1309
|
+
submission_id (str): Submission's unique identifier
|
|
1310
|
+
workflow_id (str): Workflow's unique identifier.
|
|
1311
|
+
include_key (array[str]): When specified, return only these keys in the
|
|
1312
|
+
response. Matches any key in the response, including within nested
|
|
1313
|
+
blocks. May not be used with exclude_key.
|
|
1314
|
+
exclude_key (array[str]): When specified, omit these keys from the
|
|
1315
|
+
response. Matches any key in the response, including within nested
|
|
1316
|
+
blocks. May not be used with include_key.
|
|
1317
|
+
expand_sub_workflows (bool): When true, metadata for sub workflows will
|
|
1318
|
+
be fetched and inserted automatically in the metadata response.
|
|
1319
|
+
|
|
1320
|
+
Swagger:
|
|
1321
|
+
https://api.firecloud.org/#!/Submissions/workflowMetadata
|
|
1322
|
+
"""
|
|
1323
|
+
uri = "workspaces/{0}/{1}/submissions/{2}/workflows/{3}".format(namespace,
|
|
1324
|
+
workspace, submission_id, workflow_id)
|
|
1325
|
+
params = {}
|
|
1326
|
+
if include_key is not None:
|
|
1327
|
+
params["includeKey"] = include_key
|
|
1328
|
+
if exclude_key is not None:
|
|
1329
|
+
params["excludeKey"] = exclude_key
|
|
1330
|
+
if expand_sub_workflows:
|
|
1331
|
+
params["expandSubWorkflows"] = expand_sub_workflows
|
|
1332
|
+
return __get(uri, params=params)
|
|
1333
|
+
|
|
1334
|
+
def get_workflow_outputs(namespace, workspace, submission_id, workflow_id):
|
|
1335
|
+
"""Request the outputs for a workflow in a submission.
|
|
1336
|
+
|
|
1337
|
+
Args:
|
|
1338
|
+
namespace (str): project to which workspace belongs
|
|
1339
|
+
workspace (str): Workspace name
|
|
1340
|
+
submission_id (str): Submission's unique identifier
|
|
1341
|
+
workflow_id (str): Workflow's unique identifier.
|
|
1342
|
+
|
|
1343
|
+
Swagger:
|
|
1344
|
+
https://api.firecloud.org/#!/Submissions/workflowOutputsInSubmission
|
|
1345
|
+
"""
|
|
1346
|
+
uri = "workspaces/{0}/{1}/".format(namespace, workspace)
|
|
1347
|
+
uri += "submissions/{0}/workflows/{1}/outputs".format(submission_id,
|
|
1348
|
+
workflow_id)
|
|
1349
|
+
return __get(uri)
|
|
1350
|
+
|
|
1351
|
+
def get_workflow_cost(namespace, workspace, submission_id, workflow_id):
|
|
1352
|
+
"""Request the cost for a workflow in a submission.
|
|
1353
|
+
|
|
1354
|
+
Args:
|
|
1355
|
+
namespace (str): project to which workspace belongs
|
|
1356
|
+
workspace (str): Workspace name
|
|
1357
|
+
submission_id (str): Submission's unique identifier
|
|
1358
|
+
workflow_id (str): Workflow's unique identifier.
|
|
1359
|
+
|
|
1360
|
+
Swagger:
|
|
1361
|
+
https://api.firecloud.org/#!/Submissions/workflowCostInSubmission
|
|
1362
|
+
"""
|
|
1363
|
+
uri = "workspaces/{0}/{1}/".format(namespace, workspace)
|
|
1364
|
+
uri += "submissions/{0}/workflows/{1}/cost".format(submission_id,
|
|
1365
|
+
workflow_id)
|
|
1366
|
+
return __get(uri)
|
|
1367
|
+
|
|
1368
|
+
def get_submission_queue():
|
|
1369
|
+
""" List workflow counts by queueing state.
|
|
1370
|
+
|
|
1371
|
+
Swagger:
|
|
1372
|
+
https://api.firecloud.org/#!/Submissions/workflowQueueStatus
|
|
1373
|
+
"""
|
|
1374
|
+
return __get("submissions/queueStatus")
|
|
1375
|
+
|
|
1376
|
+
#####################
|
|
1377
|
+
### 1.7 Workspaces
|
|
1378
|
+
#####################
|
|
1379
|
+
|
|
1380
|
+
def list_workspaces(fields=None):
|
|
1381
|
+
"""Request list of FireCloud workspaces.
|
|
1382
|
+
|
|
1383
|
+
Args:
|
|
1384
|
+
fields (str): a comma-delimited list of values that limits the
|
|
1385
|
+
response payload to include only those keys and exclude other
|
|
1386
|
+
keys (e.g., to include {"workspace": {"attributes": {...}}},
|
|
1387
|
+
specify "workspace.attributes").
|
|
1388
|
+
|
|
1389
|
+
Swagger:
|
|
1390
|
+
https://api.firecloud.org/#!/Workspaces/listWorkspaces
|
|
1391
|
+
"""
|
|
1392
|
+
if fields is None:
|
|
1393
|
+
return __get("workspaces")
|
|
1394
|
+
else:
|
|
1395
|
+
return __get("workspaces", params={"fields": fields})
|
|
1396
|
+
|
|
1397
|
+
def get_storage_cost(namespace, workspace):
|
|
1398
|
+
"""Request average monthly storage cost for workspace.
|
|
1399
|
+
Args:
|
|
1400
|
+
namespace (str): project to which workspace belongs
|
|
1401
|
+
workspace (str): Workspace name
|
|
1402
|
+
Swagger:
|
|
1403
|
+
https://api.firecloud.org/#/WorkspacesV2/getStorageCostEstimateV2
|
|
1404
|
+
"""
|
|
1405
|
+
uri = "workspaces/v2/{0}/{1}/storageCostEstimate".format(namespace, workspace)
|
|
1406
|
+
return __get(uri)
|
|
1407
|
+
|
|
1408
|
+
def get_bucket_usage(namespace, workspace):
|
|
1409
|
+
"""Request google bucket usage for workspace.
|
|
1410
|
+
Args:
|
|
1411
|
+
namespace (str): project to which workspace belongs
|
|
1412
|
+
workspace (str): Workspace name
|
|
1413
|
+
"""
|
|
1414
|
+
return get_storage_cost(namespace, workspace)
|
|
1415
|
+
|
|
1416
|
+
def create_workspace(namespace, name, authorizationDomain="", attributes=None,
|
|
1417
|
+
noWorkspaceOwner=False, bucketLocation=""):
|
|
1418
|
+
"""Create a new FireCloud Workspace.
|
|
1419
|
+
|
|
1420
|
+
Args:
|
|
1421
|
+
namespace (str): The namespace (billing project) the workspace belongs to
|
|
1422
|
+
name (str): The name of the workspace
|
|
1423
|
+
authorizationDomain (str|list): The list of groups in the Authorization
|
|
1424
|
+
Domain (empty if no AD is set)
|
|
1425
|
+
attributes (dict): Workspace attributes as key value pairs
|
|
1426
|
+
noWorkspaceOwner (bool): Optional, false if not specified. If true, the
|
|
1427
|
+
workspace is created with a Billing Project
|
|
1428
|
+
owner but no workspace owner. Requires being a
|
|
1429
|
+
Billing Project owner.
|
|
1430
|
+
bucketLocation (str): Region (NOT multi-region) in which bucket
|
|
1431
|
+
attached to the workspace should be created. If
|
|
1432
|
+
not provided, the bucket will be created in the
|
|
1433
|
+
'US' multi-region.
|
|
1434
|
+
|
|
1435
|
+
Swagger:
|
|
1436
|
+
https://api.firecloud.org/#!/Workspaces/createWorkspace
|
|
1437
|
+
"""
|
|
1438
|
+
|
|
1439
|
+
if not attributes:
|
|
1440
|
+
attributes = dict()
|
|
1441
|
+
|
|
1442
|
+
body = {
|
|
1443
|
+
"namespace": namespace,
|
|
1444
|
+
"name": name,
|
|
1445
|
+
"attributes": attributes
|
|
1446
|
+
}
|
|
1447
|
+
|
|
1448
|
+
if authorizationDomain:
|
|
1449
|
+
if isinstance(authorizationDomain, string_types):
|
|
1450
|
+
authDomain = [{"membersGroupName": authorizationDomain}]
|
|
1451
|
+
else:
|
|
1452
|
+
authDomain = [{"membersGroupName": groupName} for groupName in authorizationDomain]
|
|
1453
|
+
else:
|
|
1454
|
+
authDomain = []
|
|
1455
|
+
|
|
1456
|
+
body["authorizationDomain"] = authDomain
|
|
1457
|
+
|
|
1458
|
+
if noWorkspaceOwner:
|
|
1459
|
+
body["noWorkspaceOwner"] = noWorkspaceOwner
|
|
1460
|
+
|
|
1461
|
+
if bucketLocation:
|
|
1462
|
+
body["bucketLocation"] = bucketLocation
|
|
1463
|
+
|
|
1464
|
+
return __post("workspaces", json=body)
|
|
1465
|
+
|
|
1466
|
+
def delete_workspace(namespace, workspace):
|
|
1467
|
+
"""Delete FireCloud Workspace.
|
|
1468
|
+
|
|
1469
|
+
Note: This action is not reversible. Be careful!
|
|
1470
|
+
|
|
1471
|
+
Args:
|
|
1472
|
+
namespace (str): project to which workspace belongs
|
|
1473
|
+
workspace (str): Workspace name
|
|
1474
|
+
|
|
1475
|
+
Swagger:
|
|
1476
|
+
https://api.firecloud.org/#!/Workspaces/deleteWorkspace
|
|
1477
|
+
"""
|
|
1478
|
+
uri = "workspaces/{0}/{1}".format(namespace, workspace)
|
|
1479
|
+
return __delete(uri)
|
|
1480
|
+
|
|
1481
|
+
def get_workspace(namespace, workspace, fields=None):
|
|
1482
|
+
"""Request FireCloud Workspace information.
|
|
1483
|
+
|
|
1484
|
+
Args:
|
|
1485
|
+
namespace (str): project to which workspace belongs
|
|
1486
|
+
workspace (str): Workspace name
|
|
1487
|
+
fields (str): a comma-delimited list of values that limits the
|
|
1488
|
+
response payload to include only those keys and exclude other
|
|
1489
|
+
keys (e.g., to include {"workspace": {"attributes": {...}}},
|
|
1490
|
+
specify "workspace.attributes").
|
|
1491
|
+
|
|
1492
|
+
Swagger:
|
|
1493
|
+
https://api.firecloud.org/#!/Workspaces/getWorkspace
|
|
1494
|
+
"""
|
|
1495
|
+
uri = "workspaces/{0}/{1}".format(namespace, workspace)
|
|
1496
|
+
if fields is None:
|
|
1497
|
+
return __get(uri)
|
|
1498
|
+
else:
|
|
1499
|
+
return __get(uri, params={"fields": fields})
|
|
1500
|
+
|
|
1501
|
+
def get_workspace_acl(namespace, workspace):
|
|
1502
|
+
"""Request FireCloud access aontrol list for workspace.
|
|
1503
|
+
|
|
1504
|
+
Args:
|
|
1505
|
+
namespace (str): project to which workspace belongs
|
|
1506
|
+
workspace (str): Workspace name
|
|
1507
|
+
|
|
1508
|
+
Swagger:
|
|
1509
|
+
https://api.firecloud.org/#!/Workspaces/getWorkspaceAcl
|
|
1510
|
+
"""
|
|
1511
|
+
uri = "workspaces/{0}/{1}/acl".format(namespace, workspace)
|
|
1512
|
+
return __get(uri)
|
|
1513
|
+
|
|
1514
|
+
def update_workspace_acl(namespace, workspace, acl_updates, invite_users_not_found=False):
|
|
1515
|
+
"""Update workspace access control list.
|
|
1516
|
+
|
|
1517
|
+
Args:
|
|
1518
|
+
namespace (str): project to which workspace belongs
|
|
1519
|
+
workspace (str): Workspace name
|
|
1520
|
+
acl_updates (list(dict)): Acl updates as dicts with two keys:
|
|
1521
|
+
"email" - Firecloud user email
|
|
1522
|
+
"accessLevel" - one of "OWNER", "READER", "WRITER", "NO ACCESS"
|
|
1523
|
+
Example: {"email":"user1@mail.com", "accessLevel":"WRITER"}
|
|
1524
|
+
invite_users_not_found (bool): true to invite unregistered users, false to ignore
|
|
1525
|
+
|
|
1526
|
+
Swagger:
|
|
1527
|
+
https://api.firecloud.org/#!/Workspaces/updateWorkspaceACL
|
|
1528
|
+
"""
|
|
1529
|
+
uri = "{0}workspaces/{1}/{2}/acl?inviteUsersNotFound={3}".format(fcconfig.root_url,
|
|
1530
|
+
namespace, workspace, str(invite_users_not_found).lower())
|
|
1531
|
+
headers = _fiss_agent_header({"Content-type": "application/json"})
|
|
1532
|
+
# FIXME: create __patch method, akin to __get, __delete etc
|
|
1533
|
+
return __SESSION.patch(uri, headers=headers, data=json.dumps(acl_updates))
|
|
1534
|
+
|
|
1535
|
+
def clone_workspace(from_namespace, from_workspace, to_namespace, to_workspace,
|
|
1536
|
+
authorizationDomain="", copyFilesWithPrefix=None, bucketLocation=None):
|
|
1537
|
+
"""Clone a FireCloud workspace.
|
|
1538
|
+
|
|
1539
|
+
A clone is a shallow copy of a FireCloud workspace, enabling
|
|
1540
|
+
easy sharing of data, such as TCGA data, without duplication.
|
|
1541
|
+
|
|
1542
|
+
Args:
|
|
1543
|
+
from_namespace (str): project (namespace) to which source workspace belongs
|
|
1544
|
+
from_workspace (str): Source workspace's name
|
|
1545
|
+
to_namespace (str): project to which target workspace belongs
|
|
1546
|
+
to_workspace (str): Target workspace's name
|
|
1547
|
+
authorizationDomain: (str) required authorization domains
|
|
1548
|
+
copyFilesWithPrefix: (str) prefix of bucket objects to copy to the destination workspace
|
|
1549
|
+
|
|
1550
|
+
Swagger:
|
|
1551
|
+
https://api.firecloud.org/#!/Workspaces/cloneWorkspace
|
|
1552
|
+
"""
|
|
1553
|
+
|
|
1554
|
+
if authorizationDomain:
|
|
1555
|
+
if isinstance(authorizationDomain, string_types):
|
|
1556
|
+
authDomain = [{"membersGroupName": authorizationDomain}]
|
|
1557
|
+
else:
|
|
1558
|
+
authDomain = [{"membersGroupName": authDomain} for authDomain in authorizationDomain]
|
|
1559
|
+
else:
|
|
1560
|
+
authDomain = []
|
|
1561
|
+
|
|
1562
|
+
body = {
|
|
1563
|
+
"namespace": to_namespace,
|
|
1564
|
+
"name": to_workspace,
|
|
1565
|
+
"attributes": dict(),
|
|
1566
|
+
"authorizationDomain": authDomain,
|
|
1567
|
+
}
|
|
1568
|
+
|
|
1569
|
+
if copyFilesWithPrefix is not None:
|
|
1570
|
+
body["copyFilesWithPrefix"] = copyFilesWithPrefix
|
|
1571
|
+
if bucketLocation is not None:
|
|
1572
|
+
body["bucketLocation"] = bucketLocation
|
|
1573
|
+
|
|
1574
|
+
uri = "workspaces/{0}/{1}/clone".format(from_namespace, from_workspace)
|
|
1575
|
+
return __post(uri, json=body)
|
|
1576
|
+
|
|
1577
|
+
def lock_workspace(namespace, workspace):
|
|
1578
|
+
"""Lock FireCloud workspace, making it read-only.
|
|
1579
|
+
|
|
1580
|
+
This prevents modifying attributes or submitting workflows
|
|
1581
|
+
in the workspace. Can be undone with unlock_workspace()
|
|
1582
|
+
|
|
1583
|
+
Args:
|
|
1584
|
+
namespace (str): project to which workspace belongs
|
|
1585
|
+
workspace (str): Workspace name
|
|
1586
|
+
|
|
1587
|
+
Swagger:
|
|
1588
|
+
https://api.firecloud.org/#!/Workspaces/lockWorkspace
|
|
1589
|
+
"""
|
|
1590
|
+
uri = "workspaces/{0}/{1}/lock".format(namespace, workspace)
|
|
1591
|
+
return __put(uri)
|
|
1592
|
+
|
|
1593
|
+
def unlock_workspace(namespace, workspace):
|
|
1594
|
+
"""Unlock FireCloud workspace.
|
|
1595
|
+
|
|
1596
|
+
Enables modifications to a workspace. See lock_workspace()
|
|
1597
|
+
|
|
1598
|
+
Args:
|
|
1599
|
+
namespace (str): project to which workspace belongs
|
|
1600
|
+
workspace (str): Workspace name
|
|
1601
|
+
|
|
1602
|
+
Swagger:
|
|
1603
|
+
https://api.firecloud.org/#!/Workspaces/unlockWorkspace
|
|
1604
|
+
"""
|
|
1605
|
+
uri = "workspaces/{0}/{1}/unlock".format(namespace, workspace)
|
|
1606
|
+
return __put(uri)
|
|
1607
|
+
|
|
1608
|
+
def update_workspace_attributes(namespace, workspace, attrs):
|
|
1609
|
+
"""Update or remove workspace attributes.
|
|
1610
|
+
|
|
1611
|
+
Args:
|
|
1612
|
+
namespace (str): project to which workspace belongs
|
|
1613
|
+
workspace (str): Workspace name
|
|
1614
|
+
attrs (list(dict)): List of update operations for workspace attributes.
|
|
1615
|
+
Use the helper dictionary construction functions to create these:
|
|
1616
|
+
|
|
1617
|
+
_attr_set() : Set/Update attribute
|
|
1618
|
+
_attr_rem() : Remove attribute
|
|
1619
|
+
_attr_ladd() : Add member to list attribute
|
|
1620
|
+
_attr_lrem() : Remove member from list attribute
|
|
1621
|
+
_attr_vlcreate() : Create a value-list attribute
|
|
1622
|
+
_attr_erlcreate() : Create an entity-reference list attribute
|
|
1623
|
+
|
|
1624
|
+
Swagger:
|
|
1625
|
+
https://api.firecloud.org/#!/Workspaces/updateAttributes
|
|
1626
|
+
"""
|
|
1627
|
+
headers = _fiss_agent_header({"Content-type": "application/json"})
|
|
1628
|
+
uri = "{0}workspaces/{1}/{2}/updateAttributes".format(fcconfig.root_url,
|
|
1629
|
+
namespace, workspace)
|
|
1630
|
+
body = json.dumps(attrs)
|
|
1631
|
+
|
|
1632
|
+
# FIXME: create __patch method, akin to __get, __delete etc
|
|
1633
|
+
return __SESSION.patch(uri, headers=headers, data=body)
|
|
1634
|
+
|
|
1635
|
+
# Helper functions to create attribute update dictionaries
|
|
1636
|
+
|
|
1637
|
+
def _attr_set(attr, value):
|
|
1638
|
+
"""Create an 'update' dictionary for update_workspace_attributes() and
|
|
1639
|
+
update_entity()"""
|
|
1640
|
+
return {
|
|
1641
|
+
"op" : "AddUpdateAttribute",
|
|
1642
|
+
"attributeName" : attr,
|
|
1643
|
+
"addUpdateAttribute" : value
|
|
1644
|
+
}
|
|
1645
|
+
|
|
1646
|
+
def _attr_rem(attr):
|
|
1647
|
+
"""Create a 'remove' dictionary for update_workspace_attributes() and
|
|
1648
|
+
update_entity()"""
|
|
1649
|
+
return {
|
|
1650
|
+
"op" : "RemoveAttribute",
|
|
1651
|
+
"attributeName" : attr
|
|
1652
|
+
}
|
|
1653
|
+
|
|
1654
|
+
def _attr_ladd(attr, value):
|
|
1655
|
+
"""Create a 'list add' dictionary for update_workspace_attributes() and
|
|
1656
|
+
update_entity()"""
|
|
1657
|
+
return {
|
|
1658
|
+
"op" : "AddListMember",
|
|
1659
|
+
"attributeListName" : attr,
|
|
1660
|
+
"newMember" : value
|
|
1661
|
+
}
|
|
1662
|
+
|
|
1663
|
+
def _attr_lrem(attr, value):
|
|
1664
|
+
"""Create a 'list remove' dictionary for update_workspace_attributes() and
|
|
1665
|
+
update_entity()"""
|
|
1666
|
+
return {
|
|
1667
|
+
"op" : "RemoveListMember",
|
|
1668
|
+
"attributeListName" : attr,
|
|
1669
|
+
"removeMember" : value,
|
|
1670
|
+
}
|
|
1671
|
+
|
|
1672
|
+
def _attr_vlcreate(attr):
|
|
1673
|
+
"""Create a 'value-list create' dict for update_workspace_attributes() and
|
|
1674
|
+
update_entity()"""
|
|
1675
|
+
return {
|
|
1676
|
+
"op" : "CreateAttributeValueList",
|
|
1677
|
+
"attributeName" : attr
|
|
1678
|
+
}
|
|
1679
|
+
|
|
1680
|
+
def _attr_erlcreate(attr):
|
|
1681
|
+
"""Create a 'entity-reference list create' dictionary for
|
|
1682
|
+
update_workspace_attributes() and update_entity()"""
|
|
1683
|
+
return {
|
|
1684
|
+
"op" : "CreateAttributeEntityReferenceList",
|
|
1685
|
+
"attributeListName" : attr
|
|
1686
|
+
}
|
|
1687
|
+
|
|
1688
|
+
#####################
|
|
1689
|
+
### 1.8 Groups
|
|
1690
|
+
#####################
|
|
1691
|
+
|
|
1692
|
+
def get_groups():
|
|
1693
|
+
"""Get the list of the groups that the caller is a member of
|
|
1694
|
+
|
|
1695
|
+
Swagger:
|
|
1696
|
+
https://api.firecloud.org/#!/Groups/getGroups
|
|
1697
|
+
"""
|
|
1698
|
+
return __get('groups')
|
|
1699
|
+
|
|
1700
|
+
def get_group(group):
|
|
1701
|
+
"""View the members in a group (must be an Admin of the group)
|
|
1702
|
+
|
|
1703
|
+
Args:
|
|
1704
|
+
group (str): Group name
|
|
1705
|
+
|
|
1706
|
+
Swagger:
|
|
1707
|
+
https://api.firecloud.org/#!/Groups/getGroup
|
|
1708
|
+
"""
|
|
1709
|
+
uri = "groups/{0}".format(group)
|
|
1710
|
+
return __get(uri)
|
|
1711
|
+
|
|
1712
|
+
def delete_group(group):
|
|
1713
|
+
"""Delete a group that the caller owns
|
|
1714
|
+
|
|
1715
|
+
Args:
|
|
1716
|
+
group (str): Group name
|
|
1717
|
+
|
|
1718
|
+
Swagger:
|
|
1719
|
+
https://api.firecloud.org/#!/Groups/deleteGroup
|
|
1720
|
+
"""
|
|
1721
|
+
uri = "groups/{0}".format(group)
|
|
1722
|
+
return __delete(uri)
|
|
1723
|
+
|
|
1724
|
+
def create_group(group):
|
|
1725
|
+
"""Create a new group
|
|
1726
|
+
|
|
1727
|
+
Args:
|
|
1728
|
+
group (str): Group name
|
|
1729
|
+
|
|
1730
|
+
Swagger:
|
|
1731
|
+
https://api.firecloud.org/#!/Groups/createGroup
|
|
1732
|
+
"""
|
|
1733
|
+
uri = "groups/{0}".format(group)
|
|
1734
|
+
return __post(uri)
|
|
1735
|
+
|
|
1736
|
+
def add_user_to_group(group, role, email):
|
|
1737
|
+
"""Add a user to a group the caller owns
|
|
1738
|
+
|
|
1739
|
+
Args:
|
|
1740
|
+
group (str): Group name
|
|
1741
|
+
role (str) : Role of user for group; either 'member' or 'admin'
|
|
1742
|
+
email (str): Email of user or group to add
|
|
1743
|
+
|
|
1744
|
+
Swagger:
|
|
1745
|
+
https://api.firecloud.org/#!/Groups/addUserToGroup
|
|
1746
|
+
"""
|
|
1747
|
+
uri = "groups/{0}/{1}/{2}".format(group, role, email)
|
|
1748
|
+
return __put(uri)
|
|
1749
|
+
|
|
1750
|
+
def remove_user_from_group(group, role, email):
|
|
1751
|
+
"""Remove a user from a group the caller owns
|
|
1752
|
+
|
|
1753
|
+
Args:
|
|
1754
|
+
group (str): Group name
|
|
1755
|
+
role (str) : Role of user for group; either 'member' or 'admin'
|
|
1756
|
+
email (str): Email of user or group to remove
|
|
1757
|
+
|
|
1758
|
+
Swagger:
|
|
1759
|
+
https://api.firecloud.org/#!/Groups/removeUserFromGroup
|
|
1760
|
+
"""
|
|
1761
|
+
uri = "groups/{0}/{1}/{2}".format(group, role, email)
|
|
1762
|
+
return __delete(uri)
|
|
1763
|
+
|
|
1764
|
+
def request_access_to_group(group):
|
|
1765
|
+
"""Request access to a group
|
|
1766
|
+
|
|
1767
|
+
Args:
|
|
1768
|
+
group (str): Group name
|
|
1769
|
+
|
|
1770
|
+
Swagger:
|
|
1771
|
+
https://api.firecloud.org/#!/Groups/requestAccessToGroup
|
|
1772
|
+
"""
|
|
1773
|
+
uri = "groups/{0}/requestAccess".format(group)
|
|
1774
|
+
return __post(uri)
|