idmtools-platform-comps 0.0.0.dev0__py3-none-any.whl → 0.0.2__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.
Files changed (64) hide show
  1. idmtools_platform_comps/__init__.py +25 -8
  2. idmtools_platform_comps/cli/__init__.py +4 -0
  3. idmtools_platform_comps/cli/cli_functions.py +50 -0
  4. idmtools_platform_comps/cli/comps.py +492 -0
  5. idmtools_platform_comps/comps_cli.py +48 -0
  6. idmtools_platform_comps/comps_operations/__init__.py +6 -0
  7. idmtools_platform_comps/comps_operations/asset_collection_operations.py +263 -0
  8. idmtools_platform_comps/comps_operations/experiment_operations.py +569 -0
  9. idmtools_platform_comps/comps_operations/simulation_operations.py +678 -0
  10. idmtools_platform_comps/comps_operations/suite_operations.py +228 -0
  11. idmtools_platform_comps/comps_operations/workflow_item_operations.py +269 -0
  12. idmtools_platform_comps/comps_platform.py +309 -0
  13. idmtools_platform_comps/plugin_info.py +168 -0
  14. idmtools_platform_comps/ssmt_operations/__init__.py +6 -0
  15. idmtools_platform_comps/ssmt_operations/simulation_operations.py +77 -0
  16. idmtools_platform_comps/ssmt_operations/workflow_item_operations.py +73 -0
  17. idmtools_platform_comps/ssmt_platform.py +44 -0
  18. idmtools_platform_comps/ssmt_work_items/__init__.py +4 -0
  19. idmtools_platform_comps/ssmt_work_items/comps_work_order_task.py +29 -0
  20. idmtools_platform_comps/ssmt_work_items/comps_workitems.py +113 -0
  21. idmtools_platform_comps/ssmt_work_items/icomps_workflowitem.py +71 -0
  22. idmtools_platform_comps/ssmt_work_items/work_order.py +54 -0
  23. idmtools_platform_comps/utils/__init__.py +4 -0
  24. idmtools_platform_comps/utils/assetize_output/__init__.py +4 -0
  25. idmtools_platform_comps/utils/assetize_output/assetize_output.py +125 -0
  26. idmtools_platform_comps/utils/assetize_output/assetize_ssmt_script.py +144 -0
  27. idmtools_platform_comps/utils/base_singularity_work_order.json +6 -0
  28. idmtools_platform_comps/utils/download/__init__.py +4 -0
  29. idmtools_platform_comps/utils/download/download.py +178 -0
  30. idmtools_platform_comps/utils/download/download_ssmt.py +81 -0
  31. idmtools_platform_comps/utils/download_experiment.py +116 -0
  32. idmtools_platform_comps/utils/file_filter_workitem.py +519 -0
  33. idmtools_platform_comps/utils/general.py +358 -0
  34. idmtools_platform_comps/utils/linux_mounts.py +73 -0
  35. idmtools_platform_comps/utils/lookups.py +123 -0
  36. idmtools_platform_comps/utils/package_version.py +489 -0
  37. idmtools_platform_comps/utils/python_requirements_ac/__init__.py +4 -0
  38. idmtools_platform_comps/utils/python_requirements_ac/create_asset_collection.py +155 -0
  39. idmtools_platform_comps/utils/python_requirements_ac/install_requirements.py +109 -0
  40. idmtools_platform_comps/utils/python_requirements_ac/requirements_to_asset_collection.py +374 -0
  41. idmtools_platform_comps/utils/python_version.py +40 -0
  42. idmtools_platform_comps/utils/scheduling.py +154 -0
  43. idmtools_platform_comps/utils/singularity_build.py +491 -0
  44. idmtools_platform_comps/utils/spatial_output.py +76 -0
  45. idmtools_platform_comps/utils/ssmt_utils/__init__.py +6 -0
  46. idmtools_platform_comps/utils/ssmt_utils/common.py +70 -0
  47. idmtools_platform_comps/utils/ssmt_utils/file_filter.py +568 -0
  48. idmtools_platform_comps/utils/sweeping.py +162 -0
  49. idmtools_platform_comps-0.0.2.dist-info/METADATA +100 -0
  50. idmtools_platform_comps-0.0.2.dist-info/RECORD +62 -0
  51. idmtools_platform_comps-0.0.2.dist-info/entry_points.txt +9 -0
  52. idmtools_platform_comps-0.0.2.dist-info/licenses/LICENSE.TXT +3 -0
  53. {idmtools_platform_comps-0.0.0.dev0.dist-info → idmtools_platform_comps-0.0.2.dist-info}/top_level.txt +1 -0
  54. ssmt_image/Dockerfile +52 -0
  55. ssmt_image/Makefile +21 -0
  56. ssmt_image/__init__.py +6 -0
  57. ssmt_image/bootstrap.sh +30 -0
  58. ssmt_image/build_docker_image.py +161 -0
  59. ssmt_image/pip.conf +3 -0
  60. ssmt_image/push_docker_image.py +49 -0
  61. ssmt_image/requirements.txt +9 -0
  62. idmtools_platform_comps-0.0.0.dev0.dist-info/METADATA +0 -41
  63. idmtools_platform_comps-0.0.0.dev0.dist-info/RECORD +0 -5
  64. {idmtools_platform_comps-0.0.0.dev0.dist-info → idmtools_platform_comps-0.0.2.dist-info}/WHEEL +0 -0
@@ -0,0 +1,29 @@
1
+ """idmtools CompsWorkOrderTask.
2
+
3
+ Copyright 2021, Bill & Melinda Gates Foundation. All rights reserved.
4
+ """
5
+ from dataclasses import dataclass, field
6
+ from idmtools.assets import AssetCollection
7
+ from idmtools.entities.itask import ITask
8
+ from idmtools.entities.simulation import Simulation
9
+ from idmtools_platform_comps.ssmt_work_items.work_order import IWorkOrder
10
+
11
+
12
+ @dataclass
13
+ class CompsWorkOrderTask(ITask):
14
+ """
15
+ Defines a task that is purely work order driven, like Singularity build.
16
+ """
17
+ work_order: IWorkOrder = field(default=None)
18
+
19
+ def gather_common_assets(self) -> AssetCollection:
20
+ """Gather common assets."""
21
+ pass
22
+
23
+ def gather_transient_assets(self) -> AssetCollection:
24
+ """Gather transient assets."""
25
+ pass
26
+
27
+ def reload_from_simulation(self, simulation: Simulation):
28
+ """Reload simulation."""
29
+ pass
@@ -0,0 +1,113 @@
1
+ """idmtools SSMTWorkItem. This is the base of most comps workitems.
2
+
3
+ Copyright 2021, Bill & Melinda Gates Foundation. All rights reserved.
4
+ """
5
+ from logging import getLogger, DEBUG
6
+ from dataclasses import dataclass, field, InitVar
7
+ from uuid import UUID
8
+ from idmtools.assets.file_list import FileList
9
+ from idmtools.entities.command_task import CommandTask
10
+ from idmtools_platform_comps.ssmt_work_items.icomps_workflowitem import ICOMPSWorkflowItem
11
+
12
+ logger = getLogger(__name__)
13
+ user_logger = getLogger(__name__)
14
+
15
+
16
+ @dataclass
17
+ class SSMTWorkItem(ICOMPSWorkflowItem):
18
+ """
19
+ Defines the SSMT WorkItem.
20
+
21
+ Notes:
22
+ - We have lots of workitem bases. We need to consolidate these a bit.
23
+ """
24
+ docker_image: str = field(default=None)
25
+ command: InitVar[str] = None
26
+
27
+ def __post_init__(self, item_name: str, asset_collection_id: UUID, asset_files: FileList, user_files: FileList, command: str):
28
+ """Constructor."""
29
+ if command and not self.task:
30
+ self.task = CommandTask(command)
31
+ else:
32
+ user_logger.warning("You provided both a task and a command. Only using the task")
33
+ super().__post_init__(item_name, asset_collection_id, asset_files, user_files)
34
+
35
+ self.work_item_type = self.work_item_type or 'DockerWorker'
36
+
37
+ def get_base_work_order(self):
38
+ """
39
+ Builder basic work order.
40
+
41
+ Returns: work order as a dictionary
42
+ """
43
+ base_wo = {
44
+ "WorkItem_Type": self.work_item_type,
45
+ "Execution": {
46
+ "ImageName": self.get_comps_ssmt_image_name(),
47
+ "Command": str(self.task.command)
48
+ }
49
+ }
50
+
51
+ return base_wo
52
+
53
+ def get_comps_ssmt_image_name(self):
54
+ """
55
+ Build comps ssmt docker image name.
56
+
57
+ Returns: final validated name
58
+ """
59
+ if self.docker_image:
60
+ return self.docker_image
61
+
62
+ if self.platform.docker_image:
63
+ return self.platform.docker_image
64
+
65
+ SSMT_PRODUCTION_IMAGE = 'docker-production.packages.idmod.org/idmtools/comps_ssmt_worker'
66
+ SSMT_STAGING_IMAGE = 'docker-staging.packages.idmod.org/idmtools/comps_ssmt_worker'
67
+
68
+ from idmtools_platform_comps.utils.package_version import get_latest_ssmt_image_version_from_artifactory
69
+ from idmtools_platform_comps import __version__
70
+
71
+ # Determine the default ssmt docker image
72
+ if "comps.idmod.org" in self.platform.endpoint.lower():
73
+ ssmt_image = SSMT_PRODUCTION_IMAGE
74
+ else:
75
+ ssmt_image = SSMT_STAGING_IMAGE
76
+
77
+ release = get_latest_ssmt_image_version_from_artifactory(base_version=__version__)
78
+
79
+ docker_image = f'{ssmt_image}:{release}'
80
+ if logger.isEnabledFor(DEBUG):
81
+ logger.debug(f'docker_image in use: {docker_image}')
82
+
83
+ return docker_image
84
+
85
+
86
+ @dataclass
87
+ class InputDataWorkItem(ICOMPSWorkflowItem):
88
+ """
89
+ Idm InputDataWorkItem.
90
+
91
+ Notes:
92
+ - TODO add examples
93
+ """
94
+
95
+ def __post_init__(self, item_name: str, asset_collection_id: UUID, asset_files: FileList, user_files: FileList):
96
+ """Constructor."""
97
+ super().__post_init__(item_name, asset_collection_id, asset_files, user_files)
98
+ self.work_item_type = self.work_item_type or 'InputDataWorker'
99
+
100
+
101
+ @dataclass
102
+ class VisToolsWorkItem(ICOMPSWorkflowItem):
103
+ """
104
+ Idm VisToolsWorkItem.
105
+
106
+ Notes:
107
+ - TODO add examples
108
+ """
109
+
110
+ def __post_init__(self, item_name: str, asset_collection_id: UUID, asset_files: FileList, user_files: FileList):
111
+ """Constructor."""
112
+ super().__post_init__(item_name, asset_collection_id, asset_files, user_files)
113
+ self.work_item_type = self.work_item_type or 'VisTools'
@@ -0,0 +1,71 @@
1
+ """idmtools ICOMPSWorkflowItem.
2
+
3
+ Copyright 2021, Bill & Melinda Gates Foundation. All rights reserved.
4
+ """
5
+ from uuid import UUID
6
+ import json
7
+ from abc import ABC
8
+ from dataclasses import field, dataclass
9
+ from idmtools.assets.file_list import FileList
10
+ from idmtools.entities.iworkflow_item import IWorkflowItem
11
+
12
+
13
+ @dataclass
14
+ class ICOMPSWorkflowItem(IWorkflowItem, ABC):
15
+ """
16
+ Interface of idmtools work item.
17
+ """
18
+
19
+ name: str = field(default="idmtools workflow item")
20
+ work_order: dict = field(default_factory=lambda: {})
21
+ work_item_type: str = field(default=None)
22
+ plugin_key: str = field(default="1.0.0.0_RELEASE")
23
+
24
+ def __post_init__(self, item_name: str, asset_collection_id: UUID, asset_files: FileList, user_files: FileList):
25
+ """Constructor."""
26
+ super().__post_init__(item_name, asset_collection_id, asset_files, user_files)
27
+ self.work_order = self.work_order or {}
28
+
29
+ def __repr__(self):
30
+ """Workitem as string."""
31
+ return f"<WorkItem {self.uid}>"
32
+
33
+ def get_base_work_order(self):
34
+ """Get the base work order."""
35
+ base_wo = {"WorkItem_Type": self.work_item_type}
36
+ return base_wo
37
+
38
+ def load_work_order(self, wo_file):
39
+ """Load work order from a file."""
40
+ self.work_order = json.load(open(wo_file, 'rb'))
41
+
42
+ def set_work_order(self, wo):
43
+ """
44
+ Update wo for the name with value.
45
+
46
+ Args:
47
+ wo: user wo
48
+ Returns: None
49
+ """
50
+ self.work_order = wo
51
+
52
+ def update_work_order(self, name, value):
53
+ """
54
+ Update wo for the name with value.
55
+
56
+ Args:
57
+ name: wo arg name
58
+ value: wo arg value
59
+
60
+ Returns: None
61
+ """
62
+ self.work_order[name] = value
63
+
64
+ def clear_wo_args(self):
65
+ """
66
+ Clear all existing wo args.
67
+
68
+ Returns: None
69
+
70
+ """
71
+ self.work_order = {}
@@ -0,0 +1,54 @@
1
+ """idmtools WorkOrder classes.
2
+
3
+ Copyright 2021, Bill & Melinda Gates Foundation. All rights reserved.
4
+ """
5
+ from abc import ABC
6
+ from dataclasses import dataclass, field
7
+ from typing import List, Dict
8
+
9
+
10
+ @dataclass()
11
+ class IWorkOrder(ABC):
12
+ """Base workorder type."""
13
+ WorkItem_Type: str = field()
14
+
15
+
16
+ @dataclass()
17
+ class ExecutionDefinition:
18
+ """Define the execution definition for workorders."""
19
+ Command: str = field()
20
+ ImageName: str = field(default='DockerWorker')
21
+
22
+
23
+ @dataclass()
24
+ class DockerWorkOrder(IWorkOrder):
25
+ """Define the docker worker."""
26
+ WorkItem_Type: str = field(default='DockerWorker')
27
+ Execution: ExecutionDefinition = field(default_factory=ExecutionDefinition)
28
+
29
+
30
+ @dataclass()
31
+ class BuildFlags:
32
+ """Define build flags."""
33
+ section: List[str] = field(default_factory=lambda: ['all'])
34
+ library: str = field(default='https://library.sylabs.io')
35
+ Switches: List['str'] = field(default_factory=lambda: [])
36
+
37
+
38
+ @dataclass()
39
+ class BuildDefinition:
40
+ """Define options for build definitions."""
41
+ Type: str = field(default='singularity')
42
+ Input: str = field(default=None)
43
+ Flags: BuildFlags = field(default_factory=BuildFlags)
44
+
45
+
46
+ @dataclass()
47
+ class ImageBuilderWorkOrder(IWorkOrder):
48
+ """Defines our Image Builder service workorder."""
49
+ WorkItem_Type: str = field(default='ImageBuilderWorker')
50
+ Build: str = field(default=BuildDefinition)
51
+ Output: str = field(default='image.sif')
52
+ Tags: Dict[str, str] = field(default_factory=lambda: dict(type='singularity'))
53
+ AdditionalMounts: List[str] = field(default_factory=list)
54
+ StaticEnvironment: Dict[str, str] = field(default_factory=dict)
@@ -0,0 +1,4 @@
1
+ """idmtools comps utils.
2
+
3
+ Copyright 2021, Bill & Melinda Gates Foundation. All rights reserved.
4
+ """
@@ -0,0 +1,4 @@
1
+ """idmtools assetize output.
2
+
3
+ Copyright 2021, Bill & Melinda Gates Foundation. All rights reserved.
4
+ """
@@ -0,0 +1,125 @@
1
+ """idmtools assetize output work item.
2
+
3
+ Notes:
4
+ - TODO add example heres
5
+
6
+ Copyright 2021, Bill & Melinda Gates Foundation. All rights reserved.
7
+ """
8
+ from logging import getLogger
9
+ from pathlib import PurePath
10
+ from uuid import UUID
11
+ from dataclasses import dataclass, field
12
+ from typing import Union, Dict
13
+ from idmtools.assets import AssetCollection
14
+ from idmtools.assets.file_list import FileList
15
+ from idmtools.entities.iplatform import IPlatform
16
+ from idmtools.entities.relation_type import RelationType
17
+ from idmtools.core.enums import EntityStatus
18
+ from idmtools_platform_comps.utils.file_filter_workitem import FileFilterWorkItem
19
+
20
+ logger = getLogger(__name__)
21
+ user_logger = getLogger('user')
22
+
23
+
24
+ @dataclass(repr=False)
25
+ class AssetizeOutput(FileFilterWorkItem):
26
+ """
27
+ AssetizeOutput allows creating assets from previously ran items in COMPS.
28
+
29
+ Notes:
30
+ - TODO link examples here.
31
+ """
32
+ # Dictionary of tags to apply to the results asset collection
33
+ asset_tags: Dict[str, str] = field(default_factory=dict)
34
+ #: The asset collection created by Assetize
35
+ asset_collection: AssetCollection = field(default=None)
36
+
37
+ def __post_init__(self, item_name: str, asset_collection_id: UUID, asset_files: FileList, user_files: FileList, command: str):
38
+ """Constructor AssetizeOutput init."""
39
+ self._ssmt_script = str(PurePath(__file__).parent.joinpath("assetize_ssmt_script.py"))
40
+ super().__post_init__(item_name, asset_collection_id, asset_files, user_files, command)
41
+
42
+ def _extra_command_args(self, command: str):
43
+ """Add our tags to the command."""
44
+ for name, value in self.asset_tags.items():
45
+ command += f' --asset-tag "{name}={value}"'
46
+ return command
47
+
48
+ def _filter_workitem_pre_creation(self, platform):
49
+ """
50
+ Callback to allow for pre-creation calls.
51
+
52
+ In our case, we check if tags exist. If no tags exists, we use our defalts ones.
53
+
54
+ Args:
55
+ platform: Platform we are creating on.
56
+
57
+ Returns:
58
+ None
59
+ """
60
+ super(AssetizeOutput, self)._filter_workitem_pre_creation(platform)
61
+ if len(self.asset_tags) == 0:
62
+ self.__generate_tags()
63
+
64
+ def __generate_tags(self):
65
+ """
66
+ Add the defaults tags to the WorkItem.
67
+
68
+ Returns:
69
+ None
70
+ """
71
+ for experiment in self.related_experiments:
72
+ self.asset_tags['AssetizedOutputfromFromExperiment'] = str(experiment.id)
73
+ for simulation in self.related_simulations:
74
+ self.asset_tags['AssetizedOutputfromFromSimulation'] = str(simulation.id)
75
+ for work_item in self.related_work_items:
76
+ self.asset_tags['AssetizedOutputfromFromWorkItem'] = str(work_item.id)
77
+ for ac in self.related_asset_collections:
78
+ self.asset_tags['AssetizedOutputfromAssetCollection'] = str(ac.id)
79
+
80
+ def run(self, wait_until_done: bool = False, platform: 'IPlatform' = None, wait_on_done_progress: bool = True, **run_opts) -> Union[AssetCollection, None]:
81
+ """
82
+ Run the AssetizeOutput.
83
+
84
+ Args:
85
+ wait_until_done: Wait until Done will wait for the workitem to complete
86
+ platform: Platform Object
87
+ wait_on_done_progress: When set to true, a progress bar will be shown from the item
88
+ **run_opts: Additional options to pass to Run on platform
89
+
90
+ Returns:
91
+ AssetCollection created if item succeeds
92
+ """
93
+ p = super()._check_for_platform_from_context(platform)
94
+ if 'wait_on_done' in run_opts:
95
+ raise TypeError("The 'wait_on_done' parameter has been removed in idmtools 1.8.0. Please update your code with 'wait_until_done'.")
96
+ p.run_items(self, wait_on_done_progress=wait_on_done_progress, **run_opts)
97
+ if wait_until_done:
98
+ return self.wait(wait_on_done_progress=wait_on_done_progress, platform=p)
99
+
100
+ def wait(self, wait_on_done_progress: bool = True, timeout: int = None, refresh_interval=None, platform: 'IPlatform' = None) -> Union[AssetCollection, None]:
101
+ """
102
+ Waits on Assetize Workitem to finish. This first waits on any dependent items to finish(Experiment/Simulation/WorkItems).
103
+
104
+ Args:
105
+ wait_on_done_progress: When set to true, a progress bar will be shown from the item
106
+ timeout: Timeout for waiting on item. If none, wait will be forever
107
+ refresh_interval: How often to refresh progress
108
+ platform: Platform
109
+
110
+ Returns:
111
+ AssetCollection created if item succeeds
112
+ """
113
+ # wait on related items before we wait on our item
114
+ p = super()._check_for_platform_from_context(platform)
115
+ opts = dict(wait_on_done_progress=wait_on_done_progress, timeout=timeout, refresh_interval=refresh_interval, platform=p)
116
+ self._wait_on_children(**opts)
117
+
118
+ super().wait(**opts)
119
+ if self.status == EntityStatus.SUCCEEDED and not self.dry_run:
120
+ # If we succeeded, get our AC
121
+ comps_workitem = self.get_platform_object(force=True)
122
+ acs = comps_workitem.get_related_asset_collections(RelationType.Created)
123
+ if acs:
124
+ self.asset_collection = AssetCollection.from_id(acs[0].id, platform=p)
125
+ return self.asset_collection
@@ -0,0 +1,144 @@
1
+ """idmtools ssmt script.
2
+
3
+ This script is used on server side only and not meant to be ran on a local machine.
4
+
5
+ Copyright 2021, Bill & Melinda Gates Foundation. All rights reserved.
6
+ """
7
+ # flake8: noqa F405 F403
8
+ import sys
9
+ from argparse import Namespace
10
+ from logging import getLogger
11
+ from COMPS.Data.WorkItem import RelationType
12
+ from typing import List, Dict
13
+ import os
14
+ from COMPS.Data import AssetCollectionFile, WorkItem
15
+
16
+ # we have to support two ways to load the utils. The first is load from Assets
17
+ # the fallback is the installed package
18
+ # this allows us to move forward with changes to utils without need for new images
19
+ try:
20
+ from file_filter import *
21
+ from common import *
22
+ except (FileNotFoundError, ImportError):
23
+ from idmtools_platform_comps.utils.ssmt_utils.file_filter import *
24
+ from idmtools_platform_comps.utils.ssmt_utils.common import *
25
+
26
+ logger = getLogger(__name__)
27
+ user_logger = getLogger('user')
28
+
29
+
30
+ class NoFileFound(Exception):
31
+ doc_link: str = "platforms/comps/errors.html#errors"
32
+
33
+
34
+ def create_asset_collection(file_list: SetOfAssets, ac_files: List[AssetCollectionFile], tags: Dict[str, str]): # pragma: no cover
35
+ """
36
+
37
+ Args:
38
+ file_list:
39
+ ac_files: AC Files
40
+ tags: Tags to add
41
+
42
+ Returns:
43
+
44
+ """
45
+ asset_collection = AssetCollection()
46
+ asset_collection.set_tags(tags)
47
+ # Maps checksum to AssetCollectionFile and the path on disk to file
48
+ asset_collection_map: Dict[uuid.UUID, Tuple[AssetCollectionFile, str, int]] = dict()
49
+ for file in file_list:
50
+ fn = os.path.basename(file[1])
51
+ acf = AssetCollectionFile(file_name=fn, relative_path=file[1].replace(fn, "").strip("/"), md5_checksum=file[2])
52
+ asset_collection_map[file[2]] = (acf, file[0], file[3])
53
+ asset_collection.add_asset(acf)
54
+
55
+ # add files from acs
56
+ for f in ac_files:
57
+ asset_collection.add_asset(f)
58
+
59
+ # do initial save to see what assets are in comps
60
+ missing_files = asset_collection.save(return_missing_files=True)
61
+ if missing_files:
62
+ user_logger.info(f"{len(missing_files)} not currently in COMPS as Assets")
63
+
64
+ ac2 = AssetCollection()
65
+ new_files = 0
66
+ total_to_upload = 0
67
+ for checksum, asset_details in asset_collection_map.items():
68
+ if checksum in missing_files:
69
+ new_files += 1
70
+ total_to_upload += asset_details[2]
71
+ acf = AssetCollectionFile(file_name=asset_details[0].file_name, relative_path=asset_details[0].relative_path)
72
+ ac2.add_asset(acf, asset_details[1])
73
+ else:
74
+ ac2.add_asset(asset_details[0])
75
+ user_logger.info(f"Saving {new_files} totaling {humanfriendly.format_size(total_to_upload)} assets to comps")
76
+ ac2.set_tags(tags)
77
+ ac2.save()
78
+ asset_collection = ac2
79
+ return asset_collection
80
+
81
+
82
+ def get_argument_parser():
83
+ p = get_common_parser("AssetizeOutputs")
84
+ p.add_argument("--asset-tag", action='append', help="List of tags as value pairs. Eg: ABC=123")
85
+ return p
86
+
87
+
88
+ def build_asset_tags(parsed_args: Namespace) -> Dict[str, str]:
89
+ """
90
+ Builds our Asset tag dic from tags
91
+
92
+ Args:
93
+ parsed_args: Parse Arg
94
+
95
+ Returns:
96
+ Dict of tags
97
+ """
98
+ asset_tags = dict()
99
+ if parsed_args.asset_tag:
100
+ for tag in parsed_args.asset_tag:
101
+ name, value = tag.split("=")
102
+ asset_tags[name] = value
103
+ return asset_tags
104
+
105
+
106
+ if __name__ == "__main__": # pragma: no cover
107
+ # build our argument parser and then parse the command line
108
+ parser = get_argument_parser()
109
+ args = parser.parse_args()
110
+
111
+ # Set our JOB config global with config provided
112
+ JOB_CONFIG = vars(args)
113
+ # register our error handler
114
+ sys.excepthook = get_error_handler_dump_config_and_error(JOB_CONFIG)
115
+ print(args)
116
+
117
+ # Parse the common arguments common to filter scripts
118
+ entity_filter_func, fn_format_func = parse_filter_args_common(args)
119
+ # Parse our Tags
120
+ asset_tags = build_asset_tags(args)
121
+
122
+ # login
123
+ client = login_to_env()
124
+
125
+ # Load our workitem
126
+ wi = WorkItem.get(os.environ['COMPS_WORKITEM_GUID'])
127
+
128
+ # Gather all our files in Experiments, Simulations, and Asset Collections
129
+ files, files_from_ac = filter_files_and_assets(args, entity_filter_func, wi, fn_format_func)
130
+ if len(files) == 0 and len(files_from_ac) == 0:
131
+ raise NoFileFound("No files found with patterns specified. Please verify your filters.")
132
+
133
+ ensure_no_duplicates(files_from_ac, files)
134
+
135
+ if args.dry_run:
136
+ print_results(files_from_ac, files)
137
+ else:
138
+ ac = create_asset_collection(files, files_from_ac, tags=asset_tags)
139
+
140
+ with open('asset_collection.id', 'w') as o:
141
+ user_logger.info(ac.id)
142
+ o.write(str(ac.id))
143
+
144
+ wi.add_related_asset_collection(ac.id, RelationType.Created)
@@ -0,0 +1,6 @@
1
+ {
2
+ "WorkItem_Type": "ImageBuilderWorker",
3
+ "Build": {
4
+ "Type": "singularity"
5
+ }
6
+ }
@@ -0,0 +1,4 @@
1
+ """idmtools download workitem.
2
+
3
+ Copyright 2021, Bill & Melinda Gates Foundation. All rights reserved.
4
+ """