From 71487428536b2cefec8e652ebf590c5c76d4c1d3 Mon Sep 17 00:00:00 2001 From: Ryan Golhar Date: Mon, 13 May 2024 10:49:13 -0400 Subject: [PATCH 01/17] Adding AWS Omics support --- src/cwl_platform/__init__.py | 4 +- src/cwl_platform/omics_platform.py | 178 +++++++++++++++++++++++++++++ 2 files changed, 180 insertions(+), 2 deletions(-) create mode 100644 src/cwl_platform/omics_platform.py diff --git a/src/cwl_platform/__init__.py b/src/cwl_platform/__init__.py index 25fc722f..86cbe43d 100644 --- a/src/cwl_platform/__init__.py +++ b/src/cwl_platform/__init__.py @@ -6,12 +6,12 @@ from .arvados_platform import ArvadosPlatform from .sevenbridges_platform import SevenBridgesPlatform -#from .omics_platform import OmicsPlatform +from .omics_platform import OmicsPlatform # Move this for a config file SUPPORTED_PLATFORMS = { 'Arvados': ArvadosPlatform, -# 'Omics': OmicsPlatform, + 'Omics': OmicsPlatform, 'SevenBridges': SevenBridgesPlatform } diff --git a/src/cwl_platform/omics_platform.py b/src/cwl_platform/omics_platform.py new file mode 100644 index 00000000..d3a373a9 --- /dev/null +++ b/src/cwl_platform/omics_platform.py @@ -0,0 +1,178 @@ +''' +AWS HealthOmics class +''' + +import logging +import boto3 +import botocore + +from .base_platform import Platform + +logger = logging.getLogger(__name__) + +class OmicsPlatform(Platform): + ''' AWS HealthOmics Platform class ''' + def __init__(self, name): + super().__init__(name) + self.api = None + + def connect(self): + ''' Connect to AWS Omics platform''' + self.api = boto3.client('omics') + + def copy_folder(self, reference_project, reference_folder, destination_project): + ''' + Do nothing and return reference folder, which should be an S3 path. + ''' + return reference_folder + + def copy_workflow(self, src_workflow, destination_project): + '''Do nothing and return workflow id''' + return src_workflow + + def copy_workflows(self, reference_project, destination_project): + '''Do nothing. This function seems not used in launcher?''' + pass + + def delete_task(self, task): + ''' Delete a task/workflow/process ''' + self.logger.info('TBD: Deleting task %s', task) + + @classmethod + def detect(cls): + return False + + def get_current_task(self): + ''' Get the current task ''' + return None + + def get_file_id(self, project, file_path): + '''Return file s3 path for Omics job input''' + return file_path + + def get_folder_id(self, project, folder_path): + ''' + There is not unique ID for a folder in s3, so just return the folder_path + The one caveat is that Omics wants trailing slashes on folder paths, so add one. + ''' + return folder_path + "/" + + def get_task_input(self, task, input_name): + ''' Retrieve the input field of the task ''' + self.logger.info("TBD: Getting input for task %s", task) + return None + + def get_task_state(self, task, refresh=False): + ''' + Get status of run by task_id. + task: A dictionary of omics response from start_run. Includes Run ID, Name, Tags, etc. + return status of the run (Complete, Failed, Running, Cancelled, Queued). + ''' + + try: + run_info = self.api.get_run(id=task['id']) + job_status = run_info['status'] + except: + raise ValueError('No Status information found for job %s. Check job status.', task['id']) + + if job_status == 'COMPLETED': + return 'Complete' + if job_status == 'FAILED': + return 'Failed' + if job_status in ['STARTING','RUNNING','STOPPING']: + return 'Running' + if job_status in ['CANCELLED','DELETED']: + return 'Cancelled' + if job_status == 'PENDING': + return 'Queued' + + raise ValueError('Unknown task state: %s : %s', task['id'], job_status) + + def get_task_output(self, task, output_name): + ''' Retrieve the output field of the task ''' + taskinfo = self.api.get_run(id=task) + # TODO: get_run only returns OutputUri. Get file path based on output_name (filename)? + filename = None + # TODO: We shouldn't be hard-coding stuff like this. these functions should be very generic. + if output_name == 'RecalibratedBAM': + filename = taskinfo.name + '.bam' + if filename == None: + raise ValueError(f"Cannot find output file for: {output_name}") + return taskinfo['outputUri'] + filename + + def get_task_output_filename(self, task, output_name): + ''' Retrieve the output field of the task and return filename''' + self.logger.info("TBD: Getting output filename for task %s", task) + return None + + def get_tasks_by_name(self, project, task_name): + ''' Get a tasks by its name ''' + tasks = [] + runs = self.api.list_runs(name=task_name) + for item in runs['items']: + run = self.api.get_run(id=item['id']) + if 'ProjectId' in project: + if run['tags']['ProjectId'] == project['ProjectId']: + tasks.append(run) + elif 'ProjectName' in project: + if run['tags']['ProjectName'] == project['ProjectName']: + tasks.append(run) + return tasks + + def get_project(self): + ''' + Since there is no concept of project in Omics, raise an error. + ''' + raise ValueError("Omics does not support project. Use get_project_by_id or get_project_by_name instead.") + + def get_project_by_name(self, project_name): + ''' Return a dictionary of project to provide project_name tag info for omics jobs ''' + project = { + 'ProjectName': project_name + } + return project + + def get_project_by_id(self, project_id): + ''' Return a dictionary of project to provide project_id tag info for omics jobs''' + project = { + 'ProjectId': project_id + } + return project + + def stage_task_output(self, task, project, output_to_export, output_directory_name, download=False): + ''' TODO ''' + return + + def submit_task(self, name, project, workflow, parameters): + ''' + Submit workflow for one sample. + name: sample ID. + project: dictionary of {'ProjectName':'string'} or {'ProjectId':'string'}, used for add run tag. + workflow: workflow ID in omics. + parameters: dictionary of input parameters. + + return omics response for start_run. + ''' + # A subfolder is created with the Run ID assigned by Omics such that task output is seperate. + base_output_path = 's3://bmsrd-ngs-omics/runs' + + try: + logger.debug("Starting run for %s", name) + # TODO: The roleArn should be a parameter to this function, and not hard-coded. + # Put this in the pipeline_config.py. + job = self.api.start_run(workflowId=workflow, + workflowType='PRIVATE', + roleArn='arn:aws:iam::483421617021:role/ngs360-servicerole', + parameters=parameters, + name=name, + tags=project, + outputUri=base_output_path) + logger.info('Started run for %s, RunID: %s',name,job['id']) + return job + except botocore.exceptions.ClientError as err: + logger.error('Could not start run for %s: %s', name, err) + return None + + def upload_file_to_project(self, filename, project, dest_folder, destination_filename=None, overwrite=False): # pylint: disable=too-many-arguments + self.logger.info("TBD: Uploading file %s to project %s", filename, project) + return None From 2aab38583dc9d3653d47c70cf5beedb641568c13 Mon Sep 17 00:00:00 2001 From: Ryan Golhar Date: Mon, 13 May 2024 10:50:24 -0400 Subject: [PATCH 02/17] Remove hard-coded role arn --- src/cwl_platform/omics_platform.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cwl_platform/omics_platform.py b/src/cwl_platform/omics_platform.py index d3a373a9..c23c9ac8 100644 --- a/src/cwl_platform/omics_platform.py +++ b/src/cwl_platform/omics_platform.py @@ -162,7 +162,7 @@ def submit_task(self, name, project, workflow, parameters): # Put this in the pipeline_config.py. job = self.api.start_run(workflowId=workflow, workflowType='PRIVATE', - roleArn='arn:aws:iam::483421617021:role/ngs360-servicerole', + roleArn=self.role_arn, parameters=parameters, name=name, tags=project, From b47fad37552d295941c8d2e73c93e63690a04629 Mon Sep 17 00:00:00 2001 From: Ryan Golhar Date: Mon, 13 May 2024 10:52:35 -0400 Subject: [PATCH 03/17] Remove hard-coded output path --- src/cwl_platform/omics_platform.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cwl_platform/omics_platform.py b/src/cwl_platform/omics_platform.py index c23c9ac8..eff4872b 100644 --- a/src/cwl_platform/omics_platform.py +++ b/src/cwl_platform/omics_platform.py @@ -15,6 +15,7 @@ class OmicsPlatform(Platform): def __init__(self, name): super().__init__(name) self.api = None + self.role_arn = None def connect(self): ''' Connect to AWS Omics platform''' @@ -153,8 +154,7 @@ def submit_task(self, name, project, workflow, parameters): return omics response for start_run. ''' - # A subfolder is created with the Run ID assigned by Omics such that task output is seperate. - base_output_path = 's3://bmsrd-ngs-omics/runs' + base_output_path = parameters.pop('OutputUri') try: logger.debug("Starting run for %s", name) From f4b1d196daa7301067f39cd739561d0bdce47889 Mon Sep 17 00:00:00 2001 From: Ryan Golhar Date: Mon, 13 May 2024 10:54:06 -0400 Subject: [PATCH 04/17] Add boto3 to requirements.txt --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 5099bf4e..d1edd6b2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ +boto3 chardet arvados-python-client sevenbridges-python From aeda697361986b5639acacaeeef28f68c47ea020 Mon Sep 17 00:00:00 2001 From: Ryan Golhar Date: Mon, 13 May 2024 11:05:22 -0400 Subject: [PATCH 05/17] Get role arn from connect() parameters --- src/cwl_platform/omics_platform.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/cwl_platform/omics_platform.py b/src/cwl_platform/omics_platform.py index eff4872b..4b67daa4 100644 --- a/src/cwl_platform/omics_platform.py +++ b/src/cwl_platform/omics_platform.py @@ -17,10 +17,11 @@ def __init__(self, name): self.api = None self.role_arn = None - def connect(self): + def connect(self, **kwargs): ''' Connect to AWS Omics platform''' self.api = boto3.client('omics') - + self.role_arn = kwargs.get('role_arn') + def copy_folder(self, reference_project, reference_folder, destination_project): ''' Do nothing and return reference folder, which should be an S3 path. From 4107460216d83757b376964bc8d45104afde0c0b Mon Sep 17 00:00:00 2001 From: Ryan Golhar Date: Mon, 13 May 2024 11:08:25 -0400 Subject: [PATCH 06/17] Add stage_output_files --- src/cwl_platform/omics_platform.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/cwl_platform/omics_platform.py b/src/cwl_platform/omics_platform.py index 4b67daa4..109dff4f 100644 --- a/src/cwl_platform/omics_platform.py +++ b/src/cwl_platform/omics_platform.py @@ -141,6 +141,10 @@ def get_project_by_id(self, project_id): } return project + def stage_output_files(self, project, output_files): + ''' TODO ''' + return + def stage_task_output(self, task, project, output_to_export, output_directory_name, download=False): ''' TODO ''' return From 7f190ab5554b30eb19baeee1a934af3810612848 Mon Sep 17 00:00:00 2001 From: Ryan Golhar Date: Mon, 13 May 2024 11:09:53 -0400 Subject: [PATCH 07/17] Update get_project --- src/cwl_platform/omics_platform.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cwl_platform/omics_platform.py b/src/cwl_platform/omics_platform.py index 109dff4f..b187794a 100644 --- a/src/cwl_platform/omics_platform.py +++ b/src/cwl_platform/omics_platform.py @@ -123,9 +123,9 @@ def get_tasks_by_name(self, project, task_name): def get_project(self): ''' - Since there is no concept of project in Omics, raise an error. + Since there is no concept of project in Omics, return None ''' - raise ValueError("Omics does not support project. Use get_project_by_id or get_project_by_name instead.") + return None def get_project_by_name(self, project_name): ''' Return a dictionary of project to provide project_name tag info for omics jobs ''' From 3e45a6ffe0b8269c4652523b0d6e5551a3bf3391 Mon Sep 17 00:00:00 2001 From: Ryan Golhar Date: Mon, 13 May 2024 11:11:24 -0400 Subject: [PATCH 08/17] Revert get_project --- src/cwl_platform/omics_platform.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cwl_platform/omics_platform.py b/src/cwl_platform/omics_platform.py index b187794a..da83370b 100644 --- a/src/cwl_platform/omics_platform.py +++ b/src/cwl_platform/omics_platform.py @@ -123,9 +123,9 @@ def get_tasks_by_name(self, project, task_name): def get_project(self): ''' - Since there is no concept of project in Omics, return None + Since there is no concept of project in Omics, raise an error. ''' - return None + raise ValueError("Omics does not support get_project. Use get_project_by_id or get_project_by_name instead.") def get_project_by_name(self, project_name): ''' Return a dictionary of project to provide project_name tag info for omics jobs ''' From 4e5cdfae2441d5cfd3a76b55baafc1951d58efda Mon Sep 17 00:00:00 2001 From: Ryan Golhar Date: Mon, 13 May 2024 11:24:28 -0400 Subject: [PATCH 09/17] Add notes for copy_folder --- src/cwl_platform/omics_platform.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/cwl_platform/omics_platform.py b/src/cwl_platform/omics_platform.py index da83370b..77c64569 100644 --- a/src/cwl_platform/omics_platform.py +++ b/src/cwl_platform/omics_platform.py @@ -25,6 +25,9 @@ def connect(self, **kwargs): def copy_folder(self, reference_project, reference_folder, destination_project): ''' Do nothing and return reference folder, which should be an S3 path. + NOTE: Launchers copy the reference folder to the destination project so that everything is co-located. + However this can cause lots of data duplication in S3. For now we will just use the reference folder + until another use-case is identified that we need to copy the data. ''' return reference_folder From f6f1dd8ce7601a818655c2219237987359c355e4 Mon Sep 17 00:00:00 2001 From: Ryan Golhar Date: Mon, 13 May 2024 11:26:00 -0400 Subject: [PATCH 10/17] Add trailing slash only if its missing --- src/cwl_platform/omics_platform.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cwl_platform/omics_platform.py b/src/cwl_platform/omics_platform.py index 77c64569..8e93c130 100644 --- a/src/cwl_platform/omics_platform.py +++ b/src/cwl_platform/omics_platform.py @@ -60,6 +60,8 @@ def get_folder_id(self, project, folder_path): There is not unique ID for a folder in s3, so just return the folder_path The one caveat is that Omics wants trailing slashes on folder paths, so add one. ''' + if folder_path.endswith("/"): + return folder_path return folder_path + "/" def get_task_input(self, task, input_name): From e551a391ba9dcd10099a410c46241955f6d3992b Mon Sep 17 00:00:00 2001 From: Ryan Golhar Date: Mon, 13 May 2024 11:44:41 -0400 Subject: [PATCH 11/17] Add output_bucket --- src/cwl_platform/omics_platform.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/cwl_platform/omics_platform.py b/src/cwl_platform/omics_platform.py index 8e93c130..f098d5f9 100644 --- a/src/cwl_platform/omics_platform.py +++ b/src/cwl_platform/omics_platform.py @@ -15,13 +15,15 @@ class OmicsPlatform(Platform): def __init__(self, name): super().__init__(name) self.api = None + self.output_bucket = None self.role_arn = None def connect(self, **kwargs): ''' Connect to AWS Omics platform''' self.api = boto3.client('omics') + self.outout_bucket = kwargs.get('output_bucket') self.role_arn = kwargs.get('role_arn') - + def copy_folder(self, reference_project, reference_folder, destination_project): ''' Do nothing and return reference folder, which should be an S3 path. @@ -158,13 +160,17 @@ def submit_task(self, name, project, workflow, parameters): ''' Submit workflow for one sample. name: sample ID. - project: dictionary of {'ProjectName':'string'} or {'ProjectId':'string'}, used for add run tag. + project: dictionary of {'ProjectName': 'string'} or {'ProjectId': 'string'} workflow: workflow ID in omics. parameters: dictionary of input parameters. return omics response for start_run. ''' - base_output_path = parameters.pop('OutputUri') + base_output_path = f"s3://{self.output_bucket}/" + if 'ProjectName' in project: + base_output_path += f"{project['ProjectName']}/{workflow}/{name}/" + else: + base_output_path += f"{project['ProjectId']}/{workflow}/{name}/" try: logger.debug("Starting run for %s", name) From 83803c438418912fa39a8a2c8725b40ae617597e Mon Sep 17 00:00:00 2001 From: Ryan Golhar Date: Mon, 13 May 2024 11:47:50 -0400 Subject: [PATCH 12/17] Add output_bucket --- src/cwl_platform/omics_platform.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cwl_platform/omics_platform.py b/src/cwl_platform/omics_platform.py index f098d5f9..90877ff4 100644 --- a/src/cwl_platform/omics_platform.py +++ b/src/cwl_platform/omics_platform.py @@ -21,7 +21,7 @@ def __init__(self, name): def connect(self, **kwargs): ''' Connect to AWS Omics platform''' self.api = boto3.client('omics') - self.outout_bucket = kwargs.get('output_bucket') + self.output_bucket = kwargs.get('output_bucket') self.role_arn = kwargs.get('role_arn') def copy_folder(self, reference_project, reference_folder, destination_project): From 008806804076fcec4e41f54731f8af0dc0599731 Mon Sep 17 00:00:00 2001 From: Ryan Golhar Date: Mon, 13 May 2024 14:59:46 -0400 Subject: [PATCH 13/17] Implement throttling to 1 TPS on Omics --- requirements.txt | 1 + src/cwl_platform/omics_platform.py | 3 +++ 2 files changed, 4 insertions(+) diff --git a/requirements.txt b/requirements.txt index d1edd6b2..dd8bb0e8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,4 @@ boto3 chardet arvados-python-client sevenbridges-python +tenacity diff --git a/src/cwl_platform/omics_platform.py b/src/cwl_platform/omics_platform.py index 90877ff4..0dace8cd 100644 --- a/src/cwl_platform/omics_platform.py +++ b/src/cwl_platform/omics_platform.py @@ -6,6 +6,8 @@ import boto3 import botocore +from tenacity import retry + from .base_platform import Platform logger = logging.getLogger(__name__) @@ -156,6 +158,7 @@ def stage_task_output(self, task, project, output_to_export, output_directory_na ''' TODO ''' return + @retry(wait=wait_fixed(2)) def submit_task(self, name, project, workflow, parameters): ''' Submit workflow for one sample. From 01e5f6fdf2a2bccec41aa5c2a9d38bbeeb41be89 Mon Sep 17 00:00:00 2001 From: Ryan Golhar Date: Mon, 13 May 2024 14:59:55 -0400 Subject: [PATCH 14/17] Implement throttling to 1 TPS on Omics --- src/cwl_platform/omics_platform.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cwl_platform/omics_platform.py b/src/cwl_platform/omics_platform.py index 0dace8cd..1d494fcc 100644 --- a/src/cwl_platform/omics_platform.py +++ b/src/cwl_platform/omics_platform.py @@ -6,7 +6,7 @@ import boto3 import botocore -from tenacity import retry +from tenacity import retry, wait_fixed from .base_platform import Platform @@ -158,7 +158,7 @@ def stage_task_output(self, task, project, output_to_export, output_directory_na ''' TODO ''' return - @retry(wait=wait_fixed(2)) + @retry(wait=wait_fixed(1)) def submit_task(self, name, project, workflow, parameters): ''' Submit workflow for one sample. From 16670134dc2f3cc454591fec6b6355c7842c61ff Mon Sep 17 00:00:00 2001 From: Ryan Golhar Date: Sun, 25 Aug 2024 00:27:36 +0000 Subject: [PATCH 15/17] Adding unit tests for AWS Omics --- tests/test_omics_platform.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 tests/test_omics_platform.py diff --git a/tests/test_omics_platform.py b/tests/test_omics_platform.py new file mode 100644 index 00000000..60530290 --- /dev/null +++ b/tests/test_omics_platform.py @@ -0,0 +1,23 @@ +''' +Test Module for AWS Omics Platform +''' +import unittest +import os +import mock +from mock import MagicMock, patch + +from cwl_platform.omics_platform import OmicsPlatform + +class TestOmicsPlaform(unittest.TestCase): + ''' + Test Class for Omics Platform + ''' + def setUp(self) -> None: + self.platform = OmicsPlatform('Omics') + return super().setUp() + + def runTest(self): + pass + +if __name__ == '__main__': + unittest.main() From 406bc2b35183310eaf7787bdb6d2a47d34f4e7a4 Mon Sep 17 00:00:00 2001 From: Ryan Golhar Date: Sun, 25 Aug 2024 00:32:51 +0000 Subject: [PATCH 16/17] Add missing implementations for functions --- .coverage | Bin 53248 -> 0 bytes src/cwl_platform/omics_platform.py | 9 +++++++++ 2 files changed, 9 insertions(+) delete mode 100644 .coverage diff --git a/.coverage b/.coverage deleted file mode 100644 index dd294d0d04811627f6eb5fc516b248039f21ffd2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53248 zcmeI)*>4*~90%~(BX*oPY*1<4G*lTOAPvn))mF3*O?o_3RO&&+3li?y9w$rf-DG#2 zLluy;NJU8e1Dvl&Ji%YUAJ7NNf51!C7eFc?Ar%3?-yX4@#!Yytl6+V8dXJgena^Ba z+sRv3FFB!-RnM>6p*$w~g{FyVDTNR{^z5T&x@2j?On2y2YuWC!*(1iwTA%f{$Y(wk z*1LU|t+D(UeXsW3&)0LG^nR7Kb7eY#1p*L&00j27z}nS(wlFZD-F`o`OEnexc3JuH zy6@bz3p3X*$m=s_FI|xFF?pm%(lRzCXQb~f$$90=s#8j^S)EJ{S|prt&BzilB~p|a;!IQJ#rcFS`r z7?t*V3CkYkb2*Gl>wEQy(33UCjf&|8PUv{9RLiQ|2vud%0**3Tx)5G#X(+85T%a3q z%;Z`vI?c$N#7u%Gk*kzB*GpNO5&6;-Im)x!sF#TRy+(bWD~Dpl7Y@BnF+0T#y`-?) zuA5EjvRU4?>P*SGM&now*I8(&^~xWW&6uN6F?Q=(yUJ{UU`b=9JXO{9HOEs_5-qxZP6DaB+G!~@6 zstvcyT_xZ$l)Xje+p}ssIU5fP&$=N|)0xU;3KxbtHJ$Y)P@G!d>{%PgWDA3X+U;D_ zjFQ?)Ub1aXD6Pp&hSBs?UD-jyPY05x4U%b$<|vu=k>m^&XDpj3%nWuaP7I9nQ%o^UjAUY^HIXq_vJPHNFvgCO+WxMg*Krt=` zbWJCaQ68S0mCiKN2v#_a*~Q@~PwC{s!~AvXbZP&hje6a7E6IGt({P+Bjs4s?`8x3+ zLJ{RKb;^Lc=!P`YM3b{TVx{Si&yxwKTDL24cjroJNpWdTJ&{~I8=bd96*_e#IY^Y5 zs9`PHfh_xqPSRXDGHg7p8E|bCr+CeG$=&=`Zf!`*7LFd()*4A?jK`T`K$CjiPP3it z>TQi=!^viQxl98tz1wMRCv4Zk!MpJlcyNnruoNq#p_2DHJtKUBuUU@;J+MFk0uX=z z1Rwwb2tWV=5P$##Ah7!c3{BUveE+XoKMU(OT48|z1Rwwb2tWV=5P$##AOHafKwxJI zVkljA4GC;3PIy7f?453N6UW&x3F2tWV=5P$##AOHafKmY;| zfB*zifxK~8OFsqBdyK(c@*x0!|8H8a3G2S~nN_6?ED(SI1Rwwb2tWV=5P$##AOL|q zEpW;-#I1?)Qmr^&vqSoyDD{cJFK;-Y7L{A_oyx2V)`QW1C3xL1#LW#sH^wd5fohF& zTsOqR7IAEU(XM!Hmm1RyVQ&$wSae(`EEXwe{QbXa9TnD3*5}qNZD4@_1Rwwb2tWV= z5P$##AOHaf>}`S5#w~4&8|$FM{l9t4xVcr_jrae?31eZaIGf!6>tlwU+ajAS_y73+ ze|x)8qx2Af00bZa0SG_<0uX=z1R${M1q}M7Kp%hquUUT!dSHP71Rwwb2tWV=5P$## zAOHafKwuXN7)D<%{`>zaVf}7>ZQZe^c40A5BnUtN0uX=z1Rwwb2tWV=5P-n{7r0_} zX}L9NK05W+0drcIoPsGNt-GVgkN-?-$&usJf;Rbhze!s!t*$=TeO~AX&YYveeCCB0 zC%^naJ7kzz?u7B{$z!Y9y?giaH>%ZYCjYUP5eI*`rt{Ta)*pS_HCZ_LocXW5Djw<- zl^04_h*crJ(KNxwOxlUAEza_*)-C%*oCSJ`7S65g)y!P((D&bsnnE|@zyE(AtjE?L z)-TqBI2_gxfB*y_009U<00Izz00bZa0SN3ofed}ZpqXa$Vi?hjuAB5RK=l2;=-+uI zLXIH-0SG_<0uX=z1Rwwb2tWV=5ZJx|fB%pB|LuDrBm^J;0SG_<0uX=z1Rwwb2tZ&b k3h>|m Date: Sun, 25 Aug 2024 01:02:49 +0000 Subject: [PATCH 17/17] Add comment --- src/cwl_platform/omics_platform.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/cwl_platform/omics_platform.py b/src/cwl_platform/omics_platform.py index 65732294..1541c0cb 100644 --- a/src/cwl_platform/omics_platform.py +++ b/src/cwl_platform/omics_platform.py @@ -21,7 +21,11 @@ def __init__(self, name): self.role_arn = None def connect(self, **kwargs): - ''' Connect to AWS Omics platform''' + ''' + Connect to AWS Omics platform + + If ~/.aws/credentials or ~/.aws/config does not provide a region, region should be specified in the AWS_DEFAULT_REGION environment variable. + ''' self.api = boto3.client('omics') self.output_bucket = kwargs.get('output_bucket') self.role_arn = kwargs.get('role_arn')