dtlpy 1.115.44__py3-none-any.whl → 1.117.6__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.
- dtlpy/__init__.py +491 -491
- dtlpy/__version__.py +1 -1
- dtlpy/assets/__init__.py +26 -26
- dtlpy/assets/code_server/config.yaml +2 -2
- dtlpy/assets/code_server/installation.sh +24 -24
- dtlpy/assets/code_server/launch.json +13 -13
- dtlpy/assets/code_server/settings.json +2 -2
- dtlpy/assets/main.py +53 -53
- dtlpy/assets/main_partial.py +18 -18
- dtlpy/assets/mock.json +11 -11
- dtlpy/assets/model_adapter.py +83 -83
- dtlpy/assets/package.json +61 -61
- dtlpy/assets/package_catalog.json +29 -29
- dtlpy/assets/package_gitignore +307 -307
- dtlpy/assets/service_runners/__init__.py +33 -33
- dtlpy/assets/service_runners/converter.py +96 -96
- dtlpy/assets/service_runners/multi_method.py +49 -49
- dtlpy/assets/service_runners/multi_method_annotation.py +54 -54
- dtlpy/assets/service_runners/multi_method_dataset.py +55 -55
- dtlpy/assets/service_runners/multi_method_item.py +52 -52
- dtlpy/assets/service_runners/multi_method_json.py +52 -52
- dtlpy/assets/service_runners/single_method.py +37 -37
- dtlpy/assets/service_runners/single_method_annotation.py +43 -43
- dtlpy/assets/service_runners/single_method_dataset.py +43 -43
- dtlpy/assets/service_runners/single_method_item.py +41 -41
- dtlpy/assets/service_runners/single_method_json.py +42 -42
- dtlpy/assets/service_runners/single_method_multi_input.py +45 -45
- dtlpy/assets/voc_annotation_template.xml +23 -23
- dtlpy/caches/base_cache.py +32 -32
- dtlpy/caches/cache.py +473 -473
- dtlpy/caches/dl_cache.py +201 -201
- dtlpy/caches/filesystem_cache.py +89 -89
- dtlpy/caches/redis_cache.py +84 -84
- dtlpy/dlp/__init__.py +20 -20
- dtlpy/dlp/cli_utilities.py +367 -367
- dtlpy/dlp/command_executor.py +764 -764
- dtlpy/dlp/dlp +1 -1
- dtlpy/dlp/dlp.bat +1 -1
- dtlpy/dlp/dlp.py +128 -128
- dtlpy/dlp/parser.py +651 -651
- dtlpy/entities/__init__.py +83 -83
- dtlpy/entities/analytic.py +347 -347
- dtlpy/entities/annotation.py +1879 -1879
- dtlpy/entities/annotation_collection.py +699 -699
- dtlpy/entities/annotation_definitions/__init__.py +20 -20
- dtlpy/entities/annotation_definitions/base_annotation_definition.py +100 -100
- dtlpy/entities/annotation_definitions/box.py +195 -195
- dtlpy/entities/annotation_definitions/classification.py +67 -67
- dtlpy/entities/annotation_definitions/comparison.py +72 -72
- dtlpy/entities/annotation_definitions/cube.py +204 -204
- dtlpy/entities/annotation_definitions/cube_3d.py +149 -149
- dtlpy/entities/annotation_definitions/description.py +32 -32
- dtlpy/entities/annotation_definitions/ellipse.py +124 -124
- dtlpy/entities/annotation_definitions/free_text.py +62 -62
- dtlpy/entities/annotation_definitions/gis.py +69 -69
- dtlpy/entities/annotation_definitions/note.py +139 -139
- dtlpy/entities/annotation_definitions/point.py +117 -117
- dtlpy/entities/annotation_definitions/polygon.py +182 -182
- dtlpy/entities/annotation_definitions/polyline.py +111 -111
- dtlpy/entities/annotation_definitions/pose.py +92 -92
- dtlpy/entities/annotation_definitions/ref_image.py +86 -86
- dtlpy/entities/annotation_definitions/segmentation.py +240 -240
- dtlpy/entities/annotation_definitions/subtitle.py +34 -34
- dtlpy/entities/annotation_definitions/text.py +85 -85
- dtlpy/entities/annotation_definitions/undefined_annotation.py +74 -74
- dtlpy/entities/app.py +220 -220
- dtlpy/entities/app_module.py +107 -107
- dtlpy/entities/artifact.py +174 -174
- dtlpy/entities/assignment.py +399 -399
- dtlpy/entities/base_entity.py +214 -214
- dtlpy/entities/bot.py +113 -113
- dtlpy/entities/codebase.py +292 -292
- dtlpy/entities/collection.py +38 -38
- dtlpy/entities/command.py +169 -169
- dtlpy/entities/compute.py +449 -449
- dtlpy/entities/dataset.py +1299 -1299
- dtlpy/entities/directory_tree.py +44 -44
- dtlpy/entities/dpk.py +470 -470
- dtlpy/entities/driver.py +235 -235
- dtlpy/entities/execution.py +397 -397
- dtlpy/entities/feature.py +124 -124
- dtlpy/entities/feature_set.py +152 -145
- dtlpy/entities/filters.py +798 -798
- dtlpy/entities/gis_item.py +107 -107
- dtlpy/entities/integration.py +184 -184
- dtlpy/entities/item.py +975 -959
- dtlpy/entities/label.py +123 -123
- dtlpy/entities/links.py +85 -85
- dtlpy/entities/message.py +175 -175
- dtlpy/entities/model.py +684 -684
- dtlpy/entities/node.py +1005 -1005
- dtlpy/entities/ontology.py +810 -803
- dtlpy/entities/organization.py +287 -287
- dtlpy/entities/package.py +657 -657
- dtlpy/entities/package_defaults.py +5 -5
- dtlpy/entities/package_function.py +185 -185
- dtlpy/entities/package_module.py +113 -113
- dtlpy/entities/package_slot.py +118 -118
- dtlpy/entities/paged_entities.py +299 -299
- dtlpy/entities/pipeline.py +624 -624
- dtlpy/entities/pipeline_execution.py +279 -279
- dtlpy/entities/project.py +394 -394
- dtlpy/entities/prompt_item.py +505 -505
- dtlpy/entities/recipe.py +301 -301
- dtlpy/entities/reflect_dict.py +102 -102
- dtlpy/entities/resource_execution.py +138 -138
- dtlpy/entities/service.py +974 -963
- dtlpy/entities/service_driver.py +117 -117
- dtlpy/entities/setting.py +294 -294
- dtlpy/entities/task.py +495 -495
- dtlpy/entities/time_series.py +143 -143
- dtlpy/entities/trigger.py +426 -426
- dtlpy/entities/user.py +118 -118
- dtlpy/entities/webhook.py +124 -124
- dtlpy/examples/__init__.py +19 -19
- dtlpy/examples/add_labels.py +135 -135
- dtlpy/examples/add_metadata_to_item.py +21 -21
- dtlpy/examples/annotate_items_using_model.py +65 -65
- dtlpy/examples/annotate_video_using_model_and_tracker.py +75 -75
- dtlpy/examples/annotations_convert_to_voc.py +9 -9
- dtlpy/examples/annotations_convert_to_yolo.py +9 -9
- dtlpy/examples/convert_annotation_types.py +51 -51
- dtlpy/examples/converter.py +143 -143
- dtlpy/examples/copy_annotations.py +22 -22
- dtlpy/examples/copy_folder.py +31 -31
- dtlpy/examples/create_annotations.py +51 -51
- dtlpy/examples/create_video_annotations.py +83 -83
- dtlpy/examples/delete_annotations.py +26 -26
- dtlpy/examples/filters.py +113 -113
- dtlpy/examples/move_item.py +23 -23
- dtlpy/examples/play_video_annotation.py +13 -13
- dtlpy/examples/show_item_and_mask.py +53 -53
- dtlpy/examples/triggers.py +49 -49
- dtlpy/examples/upload_batch_of_items.py +20 -20
- dtlpy/examples/upload_items_and_custom_format_annotations.py +55 -55
- dtlpy/examples/upload_items_with_modalities.py +43 -43
- dtlpy/examples/upload_segmentation_annotations_from_mask_image.py +44 -44
- dtlpy/examples/upload_yolo_format_annotations.py +70 -70
- dtlpy/exceptions.py +125 -125
- dtlpy/miscellaneous/__init__.py +20 -20
- dtlpy/miscellaneous/dict_differ.py +95 -95
- dtlpy/miscellaneous/git_utils.py +217 -217
- dtlpy/miscellaneous/json_utils.py +14 -14
- dtlpy/miscellaneous/list_print.py +105 -105
- dtlpy/miscellaneous/zipping.py +130 -130
- dtlpy/ml/__init__.py +20 -20
- dtlpy/ml/base_feature_extractor_adapter.py +27 -27
- dtlpy/ml/base_model_adapter.py +1287 -1230
- dtlpy/ml/metrics.py +461 -461
- dtlpy/ml/predictions_utils.py +274 -274
- dtlpy/ml/summary_writer.py +57 -57
- dtlpy/ml/train_utils.py +60 -60
- dtlpy/new_instance.py +252 -252
- dtlpy/repositories/__init__.py +56 -56
- dtlpy/repositories/analytics.py +85 -85
- dtlpy/repositories/annotations.py +916 -916
- dtlpy/repositories/apps.py +383 -383
- dtlpy/repositories/artifacts.py +452 -452
- dtlpy/repositories/assignments.py +599 -599
- dtlpy/repositories/bots.py +213 -213
- dtlpy/repositories/codebases.py +559 -559
- dtlpy/repositories/collections.py +332 -332
- dtlpy/repositories/commands.py +152 -152
- dtlpy/repositories/compositions.py +61 -61
- dtlpy/repositories/computes.py +439 -439
- dtlpy/repositories/datasets.py +1585 -1504
- dtlpy/repositories/downloader.py +1157 -923
- dtlpy/repositories/dpks.py +433 -433
- dtlpy/repositories/drivers.py +482 -482
- dtlpy/repositories/executions.py +815 -815
- dtlpy/repositories/feature_sets.py +256 -226
- dtlpy/repositories/features.py +255 -255
- dtlpy/repositories/integrations.py +484 -484
- dtlpy/repositories/items.py +912 -912
- dtlpy/repositories/messages.py +94 -94
- dtlpy/repositories/models.py +1000 -1000
- dtlpy/repositories/nodes.py +80 -80
- dtlpy/repositories/ontologies.py +511 -511
- dtlpy/repositories/organizations.py +525 -525
- dtlpy/repositories/packages.py +1941 -1941
- dtlpy/repositories/pipeline_executions.py +451 -451
- dtlpy/repositories/pipelines.py +640 -640
- dtlpy/repositories/projects.py +539 -539
- dtlpy/repositories/recipes.py +429 -399
- dtlpy/repositories/resource_executions.py +137 -137
- dtlpy/repositories/schema.py +120 -120
- dtlpy/repositories/service_drivers.py +213 -213
- dtlpy/repositories/services.py +1704 -1704
- dtlpy/repositories/settings.py +339 -339
- dtlpy/repositories/tasks.py +1477 -1477
- dtlpy/repositories/times_series.py +278 -278
- dtlpy/repositories/triggers.py +536 -536
- dtlpy/repositories/upload_element.py +257 -257
- dtlpy/repositories/uploader.py +661 -661
- dtlpy/repositories/webhooks.py +249 -249
- dtlpy/services/__init__.py +22 -22
- dtlpy/services/aihttp_retry.py +131 -131
- dtlpy/services/api_client.py +1786 -1785
- dtlpy/services/api_reference.py +40 -40
- dtlpy/services/async_utils.py +133 -133
- dtlpy/services/calls_counter.py +44 -44
- dtlpy/services/check_sdk.py +68 -68
- dtlpy/services/cookie.py +115 -115
- dtlpy/services/create_logger.py +156 -156
- dtlpy/services/events.py +84 -84
- dtlpy/services/logins.py +235 -235
- dtlpy/services/reporter.py +256 -256
- dtlpy/services/service_defaults.py +91 -91
- dtlpy/utilities/__init__.py +20 -20
- dtlpy/utilities/annotations/__init__.py +16 -16
- dtlpy/utilities/annotations/annotation_converters.py +269 -269
- dtlpy/utilities/base_package_runner.py +285 -264
- dtlpy/utilities/converter.py +1650 -1650
- dtlpy/utilities/dataset_generators/__init__.py +1 -1
- dtlpy/utilities/dataset_generators/dataset_generator.py +670 -670
- dtlpy/utilities/dataset_generators/dataset_generator_tensorflow.py +23 -23
- dtlpy/utilities/dataset_generators/dataset_generator_torch.py +21 -21
- dtlpy/utilities/local_development/__init__.py +1 -1
- dtlpy/utilities/local_development/local_session.py +179 -179
- dtlpy/utilities/reports/__init__.py +2 -2
- dtlpy/utilities/reports/figures.py +343 -343
- dtlpy/utilities/reports/report.py +71 -71
- dtlpy/utilities/videos/__init__.py +17 -17
- dtlpy/utilities/videos/video_player.py +598 -598
- dtlpy/utilities/videos/videos.py +470 -470
- {dtlpy-1.115.44.data → dtlpy-1.117.6.data}/scripts/dlp +1 -1
- dtlpy-1.117.6.data/scripts/dlp.bat +2 -0
- {dtlpy-1.115.44.data → dtlpy-1.117.6.data}/scripts/dlp.py +128 -128
- {dtlpy-1.115.44.dist-info → dtlpy-1.117.6.dist-info}/METADATA +186 -186
- dtlpy-1.117.6.dist-info/RECORD +239 -0
- {dtlpy-1.115.44.dist-info → dtlpy-1.117.6.dist-info}/WHEEL +1 -1
- {dtlpy-1.115.44.dist-info → dtlpy-1.117.6.dist-info}/licenses/LICENSE +200 -200
- tests/features/environment.py +551 -551
- dtlpy/assets/__pycache__/__init__.cpython-310.pyc +0 -0
- dtlpy-1.115.44.data/scripts/dlp.bat +0 -2
- dtlpy-1.115.44.dist-info/RECORD +0 -240
- {dtlpy-1.115.44.dist-info → dtlpy-1.117.6.dist-info}/entry_points.txt +0 -0
- {dtlpy-1.115.44.dist-info → dtlpy-1.117.6.dist-info}/top_level.txt +0 -0
dtlpy/repositories/apps.py
CHANGED
|
@@ -1,383 +1,383 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
|
|
3
|
-
from .. import entities, exceptions, miscellaneous, repositories
|
|
4
|
-
from ..services.api_client import ApiClient
|
|
5
|
-
|
|
6
|
-
logger = logging.getLogger(name='dtlpy')
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class Apps:
|
|
10
|
-
|
|
11
|
-
def __init__(self, client_api: ApiClient, project: entities.Project = None, project_id: str = None):
|
|
12
|
-
self._client_api = client_api
|
|
13
|
-
self._project = project
|
|
14
|
-
self._project_id = project_id
|
|
15
|
-
self._commands = None
|
|
16
|
-
|
|
17
|
-
@property
|
|
18
|
-
def project(self) -> entities.Project:
|
|
19
|
-
if self._project is None:
|
|
20
|
-
if self._project_id is None:
|
|
21
|
-
raise exceptions.PlatformException(
|
|
22
|
-
error='2001',
|
|
23
|
-
message='Missing "project". need to set a Project entity or use project.apps repository')
|
|
24
|
-
else:
|
|
25
|
-
self._project = repositories.Projects(client_api=self._client_api).get(project_id=self._project_id)
|
|
26
|
-
assert isinstance(self._project, entities.Project)
|
|
27
|
-
return self._project
|
|
28
|
-
|
|
29
|
-
@property
|
|
30
|
-
def commands(self) -> repositories.Commands:
|
|
31
|
-
if self._commands is None:
|
|
32
|
-
self._commands = repositories.Commands(client_api=self._client_api)
|
|
33
|
-
return self._commands
|
|
34
|
-
|
|
35
|
-
@project.setter
|
|
36
|
-
def project(self, project: entities.Project):
|
|
37
|
-
if not isinstance(project, entities.Project):
|
|
38
|
-
raise ValueError('Must input a valid Project entity')
|
|
39
|
-
self._project = project
|
|
40
|
-
|
|
41
|
-
def get(self,
|
|
42
|
-
app_name: str = None,
|
|
43
|
-
app_id: str = None,
|
|
44
|
-
fetch: bool = None) -> entities.App:
|
|
45
|
-
"""
|
|
46
|
-
Get an app object.
|
|
47
|
-
|
|
48
|
-
note: It's required to pass either app_id of app_name
|
|
49
|
-
|
|
50
|
-
:param str app_id: optional - search by id.
|
|
51
|
-
:param str app_name: optional - search by name.
|
|
52
|
-
:param bool fetch: optional - fetch entity from platform, default taken from cookie
|
|
53
|
-
|
|
54
|
-
**Example**:
|
|
55
|
-
|
|
56
|
-
.. code-block:: python
|
|
57
|
-
app = self.apps.get(app_id='app_id')
|
|
58
|
-
"""
|
|
59
|
-
if fetch is None:
|
|
60
|
-
fetch = self._client_api.fetch_entities
|
|
61
|
-
|
|
62
|
-
if app_id is None and app_name is None:
|
|
63
|
-
raise exceptions.PlatformException(
|
|
64
|
-
error='400',
|
|
65
|
-
message='You must provide an identifier in inputs')
|
|
66
|
-
if fetch:
|
|
67
|
-
if app_name is not None:
|
|
68
|
-
app = self.__get_by_name(name=app_name)
|
|
69
|
-
else:
|
|
70
|
-
success, response = self._client_api.gen_request(req_type='get', path="/apps/{}".format(app_id))
|
|
71
|
-
if not success:
|
|
72
|
-
raise exceptions.PlatformException(response)
|
|
73
|
-
app = entities.App.from_json(client_api=self._client_api,
|
|
74
|
-
_json=response.json(),
|
|
75
|
-
project=self._project)
|
|
76
|
-
else:
|
|
77
|
-
app = entities.App.from_json(
|
|
78
|
-
_json={
|
|
79
|
-
'id': app_id,
|
|
80
|
-
'name': app_name
|
|
81
|
-
},
|
|
82
|
-
client_api=self._client_api,
|
|
83
|
-
project=self._project,
|
|
84
|
-
is_fetched=False
|
|
85
|
-
)
|
|
86
|
-
assert isinstance(app, entities.App)
|
|
87
|
-
return app
|
|
88
|
-
|
|
89
|
-
def __get_by_name(self, name) -> entities.App:
|
|
90
|
-
filters = entities.Filters(field='name',
|
|
91
|
-
values=name,
|
|
92
|
-
resource=entities.FiltersResource.APP,
|
|
93
|
-
use_defaults=False)
|
|
94
|
-
if self._project is not None:
|
|
95
|
-
filters.add(field='projectId', values=self.project.id)
|
|
96
|
-
apps = self.list(filters=filters)
|
|
97
|
-
if apps.items_count == 0:
|
|
98
|
-
raise exceptions.PlatformException(
|
|
99
|
-
error='404',
|
|
100
|
-
message='app not found. Name: {}'.format(name))
|
|
101
|
-
elif apps.items_count > 1:
|
|
102
|
-
raise exceptions.PlatformException(
|
|
103
|
-
error='400',
|
|
104
|
-
message='More than one app found by the name of: {} '.format(apps))
|
|
105
|
-
return apps.items[0]
|
|
106
|
-
|
|
107
|
-
def _build_entities_from_response(self, response_items) -> miscellaneous.List[entities.App]:
|
|
108
|
-
pool = self._client_api.thread_pools(pool_name='entity.create')
|
|
109
|
-
jobs = [None for _ in range(len(response_items))]
|
|
110
|
-
# return triggers list
|
|
111
|
-
for i_item, item in enumerate(response_items):
|
|
112
|
-
jobs[i_item] = pool.submit(entities.App._protected_from_json,
|
|
113
|
-
**{'client_api': self._client_api,
|
|
114
|
-
'_json': item,
|
|
115
|
-
'project': self._project})
|
|
116
|
-
# get all results
|
|
117
|
-
results = [j.result() for j in jobs]
|
|
118
|
-
# log errors
|
|
119
|
-
_ = [logger.warning(r[1]) for r in results if r[0] is False]
|
|
120
|
-
# return good jobs
|
|
121
|
-
items = miscellaneous.List([r[1] for r in results if r[0] is True])
|
|
122
|
-
return items
|
|
123
|
-
|
|
124
|
-
def _list(self, filters: entities.Filters):
|
|
125
|
-
url = '/apps/query'
|
|
126
|
-
|
|
127
|
-
# request
|
|
128
|
-
success, response = self._client_api.gen_request(req_type='post',
|
|
129
|
-
path=url,
|
|
130
|
-
json_req=filters.prepare())
|
|
131
|
-
if not success:
|
|
132
|
-
raise exceptions.PlatformException(response)
|
|
133
|
-
return response.json()
|
|
134
|
-
|
|
135
|
-
def list(self, filters: entities.Filters = None, project_id: str = None) -> entities.PagedEntities:
|
|
136
|
-
"""
|
|
137
|
-
List the available apps in the specified project.
|
|
138
|
-
|
|
139
|
-
:param entities.Filters filters: the filters to apply to the list
|
|
140
|
-
:param str project_id: the project id to apply thew filters on.
|
|
141
|
-
:return a paged entity representing the list of apps.
|
|
142
|
-
|
|
143
|
-
** Example **
|
|
144
|
-
.. code-block:: python
|
|
145
|
-
apps = dl.apps.list(project_id='id')
|
|
146
|
-
"""
|
|
147
|
-
if filters is None:
|
|
148
|
-
filters = entities.Filters(resource=entities.FiltersResource.APP)
|
|
149
|
-
# assert type filters
|
|
150
|
-
elif not isinstance(filters, entities.Filters):
|
|
151
|
-
raise exceptions.PlatformException(error='400',
|
|
152
|
-
message='Unknown filters type: {!r}'.format(type(filters)))
|
|
153
|
-
if filters.resource != entities.FiltersResource.APP:
|
|
154
|
-
raise exceptions.PlatformException(
|
|
155
|
-
error='400',
|
|
156
|
-
message='Filters resource must to be FiltersResource.APP. Got: {!r}'.format(filters.resource))
|
|
157
|
-
|
|
158
|
-
# noinspection DuplicatedCode
|
|
159
|
-
if project_id is None and self._project is not None:
|
|
160
|
-
project_id = self._project.id
|
|
161
|
-
|
|
162
|
-
if project_id is not None:
|
|
163
|
-
filters.add(field='projectId', values=project_id)
|
|
164
|
-
|
|
165
|
-
paged = entities.PagedEntities(items_repository=self,
|
|
166
|
-
filters=filters,
|
|
167
|
-
page_offset=filters.page,
|
|
168
|
-
page_size=filters.page_size,
|
|
169
|
-
project_id=project_id,
|
|
170
|
-
client_api=self._client_api)
|
|
171
|
-
paged.get_page()
|
|
172
|
-
return paged
|
|
173
|
-
|
|
174
|
-
def update(self, app: entities.App = None, app_id: str = None, wait: bool = True) -> bool:
|
|
175
|
-
"""
|
|
176
|
-
Update the current app to the new configuration
|
|
177
|
-
|
|
178
|
-
:param entities.App app: The app to update.
|
|
179
|
-
:param str app_id: The app id to update.
|
|
180
|
-
:param bool wait: wait for the operation to finish.
|
|
181
|
-
:return bool whether the operation ran successfully or not
|
|
182
|
-
|
|
183
|
-
**Example**
|
|
184
|
-
.. code-block:: python
|
|
185
|
-
succeed = dl.apps.update(app)
|
|
186
|
-
"""
|
|
187
|
-
if app_id is not None and app is None:
|
|
188
|
-
app = self.get(app_id=app_id)
|
|
189
|
-
if app is None:
|
|
190
|
-
raise exceptions.PlatformException(error='400', message='You must provide app or app_id')
|
|
191
|
-
success, response = self._client_api.gen_request(req_type='put',
|
|
192
|
-
path=f"/apps/{app.id}",
|
|
193
|
-
json_req=app.to_json())
|
|
194
|
-
if not success:
|
|
195
|
-
raise exceptions.PlatformException(response)
|
|
196
|
-
|
|
197
|
-
app = entities.App.from_json(
|
|
198
|
-
_json=response.json(),
|
|
199
|
-
client_api=self._client_api,
|
|
200
|
-
project=self.project
|
|
201
|
-
)
|
|
202
|
-
if app.metadata:
|
|
203
|
-
command_id = app.metadata.get('system', {}).get('commands', {}).get('update', None)
|
|
204
|
-
if wait and app.status == entities.CompositionStatus.UPDATING and command_id is not None:
|
|
205
|
-
command = self.commands.get(command_id=command_id, url='api/v1/commands/faas/{}'.format(command_id))
|
|
206
|
-
command.wait()
|
|
207
|
-
app = self.get(app_id=app.id)
|
|
208
|
-
|
|
209
|
-
return success
|
|
210
|
-
|
|
211
|
-
def install(self,
|
|
212
|
-
dpk: entities.Dpk,
|
|
213
|
-
app_name: str = None,
|
|
214
|
-
organization_id: str = None,
|
|
215
|
-
custom_installation: dict = None,
|
|
216
|
-
scope: entities.AppScope = None,
|
|
217
|
-
wait: bool = True,
|
|
218
|
-
integrations: list = None
|
|
219
|
-
) -> entities.App:
|
|
220
|
-
"""
|
|
221
|
-
Install the specified app in the project.
|
|
222
|
-
|
|
223
|
-
Note: You must pass either the app_id or app_name
|
|
224
|
-
:param entities.App dpk: the app entity
|
|
225
|
-
:param str app_name: installed app name. default is the dpk name
|
|
226
|
-
:param str organization_id: the organization which you want to apply on the filter.
|
|
227
|
-
:param dict custom_installation: partial installation.
|
|
228
|
-
:param str scope: the scope of the app. default is project.
|
|
229
|
-
:param bool wait: wait for the operation to finish.
|
|
230
|
-
:param list integrations: list of integrations to install with the app.
|
|
231
|
-
|
|
232
|
-
:return the installed app.
|
|
233
|
-
:rtype entities.App
|
|
234
|
-
|
|
235
|
-
**Example**
|
|
236
|
-
.. code-block:: python
|
|
237
|
-
app = dl.apps.install(dpk=dpk)
|
|
238
|
-
"""
|
|
239
|
-
if dpk is None:
|
|
240
|
-
raise exceptions.PlatformException(error='400', message='You must provide an app')
|
|
241
|
-
|
|
242
|
-
if app_name is None:
|
|
243
|
-
app_name = dpk.display_name
|
|
244
|
-
if isinstance(scope, entities.AppScope):
|
|
245
|
-
scope = scope.value
|
|
246
|
-
app = entities.App.from_json(_json={'name': app_name,
|
|
247
|
-
'projectId': self.project.id,
|
|
248
|
-
'orgId': organization_id,
|
|
249
|
-
'dpkName': dpk.name,
|
|
250
|
-
"customInstallation": custom_installation,
|
|
251
|
-
'dpkVersion': dpk.version,
|
|
252
|
-
'scope': scope,
|
|
253
|
-
'integrations': integrations
|
|
254
|
-
},
|
|
255
|
-
client_api=self._client_api,
|
|
256
|
-
project=self.project)
|
|
257
|
-
success, response = self._client_api.gen_request(req_type='post',
|
|
258
|
-
path="/apps",
|
|
259
|
-
json_req=app.to_json())
|
|
260
|
-
if not success:
|
|
261
|
-
raise exceptions.PlatformException(response)
|
|
262
|
-
app = entities.App.from_json(_json=response.json(),
|
|
263
|
-
client_api=self._client_api,
|
|
264
|
-
project=self.project)
|
|
265
|
-
|
|
266
|
-
if app.metadata:
|
|
267
|
-
command_id = app.metadata.get('system', {}).get('commands', {}).get('install', None)
|
|
268
|
-
if wait and app.status == entities.CompositionStatus.INITIALIZING and command_id is not None:
|
|
269
|
-
command = self.commands.get(command_id=command_id, url='api/v1/commands/faas/{}'.format(command_id))
|
|
270
|
-
command.wait()
|
|
271
|
-
app = self.get(app_id=app.id)
|
|
272
|
-
|
|
273
|
-
return app
|
|
274
|
-
|
|
275
|
-
def uninstall(self, app_id: str = None, app_name: str = None, wait: bool = True) -> bool:
|
|
276
|
-
"""
|
|
277
|
-
Delete an app entity.
|
|
278
|
-
|
|
279
|
-
Note: You are required to add either app_id or app_name.
|
|
280
|
-
|
|
281
|
-
:param str app_id: optional - the id of the app.
|
|
282
|
-
:param str app_name: optional - the name of the app.
|
|
283
|
-
:param bool wait: optional - wait for the operation to finish.
|
|
284
|
-
:return whether we succeed uninstalling the specified app.
|
|
285
|
-
:rtype bool
|
|
286
|
-
|
|
287
|
-
**Example**
|
|
288
|
-
.. code-block:: python
|
|
289
|
-
# succeed = dl.apps.delete(app_id='app_id')
|
|
290
|
-
"""
|
|
291
|
-
if app_id is None and app_name is None:
|
|
292
|
-
raise exceptions.PlatformException(
|
|
293
|
-
error='400',
|
|
294
|
-
message='You must provide an identifier in inputs')
|
|
295
|
-
if app_name is not None:
|
|
296
|
-
app = self.__get_by_name(app_name)
|
|
297
|
-
app_id = app.id
|
|
298
|
-
|
|
299
|
-
success, response = self._client_api.gen_request(req_type='delete', path='/apps/{}'.format(app_id))
|
|
300
|
-
if not success:
|
|
301
|
-
raise exceptions.PlatformException(response)
|
|
302
|
-
|
|
303
|
-
try:
|
|
304
|
-
app = self.get(app_id=app_id)
|
|
305
|
-
except Exception as e:
|
|
306
|
-
if e.status_code == '404':
|
|
307
|
-
return success
|
|
308
|
-
else:
|
|
309
|
-
raise e
|
|
310
|
-
if app.metadata:
|
|
311
|
-
command_id = app.metadata.get('system', {}).get('commands', {}).get('uninstall', None)
|
|
312
|
-
if wait and app.status == entities.CompositionStatus.TERMINATING and command_id is not None:
|
|
313
|
-
command = self.commands.get(command_id=command_id, url='api/v1/commands/faas/{}'.format(command_id))
|
|
314
|
-
command.wait()
|
|
315
|
-
|
|
316
|
-
logger.debug(f"App deleted successfully (id: {app_id}, name: {app_name}")
|
|
317
|
-
return success
|
|
318
|
-
|
|
319
|
-
def resume(self, app: entities.App = None, app_id: str = None) -> bool:
|
|
320
|
-
"""
|
|
321
|
-
Activate an app entity.
|
|
322
|
-
|
|
323
|
-
Note: You are required to add either app or app_id.
|
|
324
|
-
|
|
325
|
-
:param entities.App app: the app entity
|
|
326
|
-
:param str app_id: optional - the id of the app.
|
|
327
|
-
:return whether we succeed activating the specified app.
|
|
328
|
-
:rtype bool
|
|
329
|
-
|
|
330
|
-
**Example**
|
|
331
|
-
.. code-block:: python
|
|
332
|
-
# succeed = dl.apps.resume(app)
|
|
333
|
-
"""
|
|
334
|
-
if app_id is not None and app is None:
|
|
335
|
-
app = self.get(app_id=app_id)
|
|
336
|
-
|
|
337
|
-
if app and app.status == entities.CompositionStatus.INSTALLED:
|
|
338
|
-
raise exceptions.PlatformException(
|
|
339
|
-
error='400',
|
|
340
|
-
message='Application is already active'
|
|
341
|
-
)
|
|
342
|
-
if app is None:
|
|
343
|
-
raise exceptions.PlatformException(error='400', message='You must provide app or app_id')
|
|
344
|
-
|
|
345
|
-
success, response = self._client_api.gen_request(req_type='post', path='/apps/{}/activate'.format(app.id))
|
|
346
|
-
if not success:
|
|
347
|
-
raise exceptions.PlatformException(response)
|
|
348
|
-
|
|
349
|
-
logger.debug(f"App resumed successfully (id: {app.id}, name: {app.name}")
|
|
350
|
-
return success
|
|
351
|
-
|
|
352
|
-
def pause(self, app: entities.App = None, app_id: str = None) -> bool:
|
|
353
|
-
"""
|
|
354
|
-
Pausing an app entity.
|
|
355
|
-
|
|
356
|
-
Note: You are required to add either app or app_id.
|
|
357
|
-
|
|
358
|
-
:param entities.App app: the app entity
|
|
359
|
-
:param str app_id: optional - the id of the app.
|
|
360
|
-
:return whether we succeed pausing the specified app.
|
|
361
|
-
:rtype bool
|
|
362
|
-
|
|
363
|
-
**Example**
|
|
364
|
-
.. code-block:: python
|
|
365
|
-
# succeed = dl.apps.pause(app)
|
|
366
|
-
"""
|
|
367
|
-
if app_id is not None and app is None:
|
|
368
|
-
app = self.get(app_id=app_id)
|
|
369
|
-
|
|
370
|
-
if app and app.status == entities.CompositionStatus.UNINSTALLED:
|
|
371
|
-
raise exceptions.PlatformException(
|
|
372
|
-
error='400',
|
|
373
|
-
message='Application is already inactive'
|
|
374
|
-
)
|
|
375
|
-
if app is None:
|
|
376
|
-
raise exceptions.PlatformException(error='400', message='You must provide app or app_id')
|
|
377
|
-
|
|
378
|
-
success, response = self._client_api.gen_request(req_type='post', path='/apps/{}/deactivate'.format(app.id))
|
|
379
|
-
if not success:
|
|
380
|
-
raise exceptions.PlatformException(response)
|
|
381
|
-
|
|
382
|
-
logger.debug(f"App paused successfully (id: {app.id}, name: {app.name}")
|
|
383
|
-
return success
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
from .. import entities, exceptions, miscellaneous, repositories
|
|
4
|
+
from ..services.api_client import ApiClient
|
|
5
|
+
|
|
6
|
+
logger = logging.getLogger(name='dtlpy')
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Apps:
|
|
10
|
+
|
|
11
|
+
def __init__(self, client_api: ApiClient, project: entities.Project = None, project_id: str = None):
|
|
12
|
+
self._client_api = client_api
|
|
13
|
+
self._project = project
|
|
14
|
+
self._project_id = project_id
|
|
15
|
+
self._commands = None
|
|
16
|
+
|
|
17
|
+
@property
|
|
18
|
+
def project(self) -> entities.Project:
|
|
19
|
+
if self._project is None:
|
|
20
|
+
if self._project_id is None:
|
|
21
|
+
raise exceptions.PlatformException(
|
|
22
|
+
error='2001',
|
|
23
|
+
message='Missing "project". need to set a Project entity or use project.apps repository')
|
|
24
|
+
else:
|
|
25
|
+
self._project = repositories.Projects(client_api=self._client_api).get(project_id=self._project_id)
|
|
26
|
+
assert isinstance(self._project, entities.Project)
|
|
27
|
+
return self._project
|
|
28
|
+
|
|
29
|
+
@property
|
|
30
|
+
def commands(self) -> repositories.Commands:
|
|
31
|
+
if self._commands is None:
|
|
32
|
+
self._commands = repositories.Commands(client_api=self._client_api)
|
|
33
|
+
return self._commands
|
|
34
|
+
|
|
35
|
+
@project.setter
|
|
36
|
+
def project(self, project: entities.Project):
|
|
37
|
+
if not isinstance(project, entities.Project):
|
|
38
|
+
raise ValueError('Must input a valid Project entity')
|
|
39
|
+
self._project = project
|
|
40
|
+
|
|
41
|
+
def get(self,
|
|
42
|
+
app_name: str = None,
|
|
43
|
+
app_id: str = None,
|
|
44
|
+
fetch: bool = None) -> entities.App:
|
|
45
|
+
"""
|
|
46
|
+
Get an app object.
|
|
47
|
+
|
|
48
|
+
note: It's required to pass either app_id of app_name
|
|
49
|
+
|
|
50
|
+
:param str app_id: optional - search by id.
|
|
51
|
+
:param str app_name: optional - search by name.
|
|
52
|
+
:param bool fetch: optional - fetch entity from platform, default taken from cookie
|
|
53
|
+
|
|
54
|
+
**Example**:
|
|
55
|
+
|
|
56
|
+
.. code-block:: python
|
|
57
|
+
app = self.apps.get(app_id='app_id')
|
|
58
|
+
"""
|
|
59
|
+
if fetch is None:
|
|
60
|
+
fetch = self._client_api.fetch_entities
|
|
61
|
+
|
|
62
|
+
if app_id is None and app_name is None:
|
|
63
|
+
raise exceptions.PlatformException(
|
|
64
|
+
error='400',
|
|
65
|
+
message='You must provide an identifier in inputs')
|
|
66
|
+
if fetch:
|
|
67
|
+
if app_name is not None:
|
|
68
|
+
app = self.__get_by_name(name=app_name)
|
|
69
|
+
else:
|
|
70
|
+
success, response = self._client_api.gen_request(req_type='get', path="/apps/{}".format(app_id))
|
|
71
|
+
if not success:
|
|
72
|
+
raise exceptions.PlatformException(response)
|
|
73
|
+
app = entities.App.from_json(client_api=self._client_api,
|
|
74
|
+
_json=response.json(),
|
|
75
|
+
project=self._project)
|
|
76
|
+
else:
|
|
77
|
+
app = entities.App.from_json(
|
|
78
|
+
_json={
|
|
79
|
+
'id': app_id,
|
|
80
|
+
'name': app_name
|
|
81
|
+
},
|
|
82
|
+
client_api=self._client_api,
|
|
83
|
+
project=self._project,
|
|
84
|
+
is_fetched=False
|
|
85
|
+
)
|
|
86
|
+
assert isinstance(app, entities.App)
|
|
87
|
+
return app
|
|
88
|
+
|
|
89
|
+
def __get_by_name(self, name) -> entities.App:
|
|
90
|
+
filters = entities.Filters(field='name',
|
|
91
|
+
values=name,
|
|
92
|
+
resource=entities.FiltersResource.APP,
|
|
93
|
+
use_defaults=False)
|
|
94
|
+
if self._project is not None:
|
|
95
|
+
filters.add(field='projectId', values=self.project.id)
|
|
96
|
+
apps = self.list(filters=filters)
|
|
97
|
+
if apps.items_count == 0:
|
|
98
|
+
raise exceptions.PlatformException(
|
|
99
|
+
error='404',
|
|
100
|
+
message='app not found. Name: {}'.format(name))
|
|
101
|
+
elif apps.items_count > 1:
|
|
102
|
+
raise exceptions.PlatformException(
|
|
103
|
+
error='400',
|
|
104
|
+
message='More than one app found by the name of: {} '.format(apps))
|
|
105
|
+
return apps.items[0]
|
|
106
|
+
|
|
107
|
+
def _build_entities_from_response(self, response_items) -> miscellaneous.List[entities.App]:
|
|
108
|
+
pool = self._client_api.thread_pools(pool_name='entity.create')
|
|
109
|
+
jobs = [None for _ in range(len(response_items))]
|
|
110
|
+
# return triggers list
|
|
111
|
+
for i_item, item in enumerate(response_items):
|
|
112
|
+
jobs[i_item] = pool.submit(entities.App._protected_from_json,
|
|
113
|
+
**{'client_api': self._client_api,
|
|
114
|
+
'_json': item,
|
|
115
|
+
'project': self._project})
|
|
116
|
+
# get all results
|
|
117
|
+
results = [j.result() for j in jobs]
|
|
118
|
+
# log errors
|
|
119
|
+
_ = [logger.warning(r[1]) for r in results if r[0] is False]
|
|
120
|
+
# return good jobs
|
|
121
|
+
items = miscellaneous.List([r[1] for r in results if r[0] is True])
|
|
122
|
+
return items
|
|
123
|
+
|
|
124
|
+
def _list(self, filters: entities.Filters):
|
|
125
|
+
url = '/apps/query'
|
|
126
|
+
|
|
127
|
+
# request
|
|
128
|
+
success, response = self._client_api.gen_request(req_type='post',
|
|
129
|
+
path=url,
|
|
130
|
+
json_req=filters.prepare())
|
|
131
|
+
if not success:
|
|
132
|
+
raise exceptions.PlatformException(response)
|
|
133
|
+
return response.json()
|
|
134
|
+
|
|
135
|
+
def list(self, filters: entities.Filters = None, project_id: str = None) -> entities.PagedEntities:
|
|
136
|
+
"""
|
|
137
|
+
List the available apps in the specified project.
|
|
138
|
+
|
|
139
|
+
:param entities.Filters filters: the filters to apply to the list
|
|
140
|
+
:param str project_id: the project id to apply thew filters on.
|
|
141
|
+
:return a paged entity representing the list of apps.
|
|
142
|
+
|
|
143
|
+
** Example **
|
|
144
|
+
.. code-block:: python
|
|
145
|
+
apps = dl.apps.list(project_id='id')
|
|
146
|
+
"""
|
|
147
|
+
if filters is None:
|
|
148
|
+
filters = entities.Filters(resource=entities.FiltersResource.APP)
|
|
149
|
+
# assert type filters
|
|
150
|
+
elif not isinstance(filters, entities.Filters):
|
|
151
|
+
raise exceptions.PlatformException(error='400',
|
|
152
|
+
message='Unknown filters type: {!r}'.format(type(filters)))
|
|
153
|
+
if filters.resource != entities.FiltersResource.APP:
|
|
154
|
+
raise exceptions.PlatformException(
|
|
155
|
+
error='400',
|
|
156
|
+
message='Filters resource must to be FiltersResource.APP. Got: {!r}'.format(filters.resource))
|
|
157
|
+
|
|
158
|
+
# noinspection DuplicatedCode
|
|
159
|
+
if project_id is None and self._project is not None:
|
|
160
|
+
project_id = self._project.id
|
|
161
|
+
|
|
162
|
+
if project_id is not None:
|
|
163
|
+
filters.add(field='projectId', values=project_id)
|
|
164
|
+
|
|
165
|
+
paged = entities.PagedEntities(items_repository=self,
|
|
166
|
+
filters=filters,
|
|
167
|
+
page_offset=filters.page,
|
|
168
|
+
page_size=filters.page_size,
|
|
169
|
+
project_id=project_id,
|
|
170
|
+
client_api=self._client_api)
|
|
171
|
+
paged.get_page()
|
|
172
|
+
return paged
|
|
173
|
+
|
|
174
|
+
def update(self, app: entities.App = None, app_id: str = None, wait: bool = True) -> bool:
|
|
175
|
+
"""
|
|
176
|
+
Update the current app to the new configuration
|
|
177
|
+
|
|
178
|
+
:param entities.App app: The app to update.
|
|
179
|
+
:param str app_id: The app id to update.
|
|
180
|
+
:param bool wait: wait for the operation to finish.
|
|
181
|
+
:return bool whether the operation ran successfully or not
|
|
182
|
+
|
|
183
|
+
**Example**
|
|
184
|
+
.. code-block:: python
|
|
185
|
+
succeed = dl.apps.update(app)
|
|
186
|
+
"""
|
|
187
|
+
if app_id is not None and app is None:
|
|
188
|
+
app = self.get(app_id=app_id)
|
|
189
|
+
if app is None:
|
|
190
|
+
raise exceptions.PlatformException(error='400', message='You must provide app or app_id')
|
|
191
|
+
success, response = self._client_api.gen_request(req_type='put',
|
|
192
|
+
path=f"/apps/{app.id}",
|
|
193
|
+
json_req=app.to_json())
|
|
194
|
+
if not success:
|
|
195
|
+
raise exceptions.PlatformException(response)
|
|
196
|
+
|
|
197
|
+
app = entities.App.from_json(
|
|
198
|
+
_json=response.json(),
|
|
199
|
+
client_api=self._client_api,
|
|
200
|
+
project=self.project
|
|
201
|
+
)
|
|
202
|
+
if app.metadata:
|
|
203
|
+
command_id = app.metadata.get('system', {}).get('commands', {}).get('update', None)
|
|
204
|
+
if wait and app.status == entities.CompositionStatus.UPDATING and command_id is not None:
|
|
205
|
+
command = self.commands.get(command_id=command_id, url='api/v1/commands/faas/{}'.format(command_id))
|
|
206
|
+
command.wait()
|
|
207
|
+
app = self.get(app_id=app.id)
|
|
208
|
+
|
|
209
|
+
return success
|
|
210
|
+
|
|
211
|
+
def install(self,
|
|
212
|
+
dpk: entities.Dpk,
|
|
213
|
+
app_name: str = None,
|
|
214
|
+
organization_id: str = None,
|
|
215
|
+
custom_installation: dict = None,
|
|
216
|
+
scope: entities.AppScope = None,
|
|
217
|
+
wait: bool = True,
|
|
218
|
+
integrations: list = None
|
|
219
|
+
) -> entities.App:
|
|
220
|
+
"""
|
|
221
|
+
Install the specified app in the project.
|
|
222
|
+
|
|
223
|
+
Note: You must pass either the app_id or app_name
|
|
224
|
+
:param entities.App dpk: the app entity
|
|
225
|
+
:param str app_name: installed app name. default is the dpk name
|
|
226
|
+
:param str organization_id: the organization which you want to apply on the filter.
|
|
227
|
+
:param dict custom_installation: partial installation.
|
|
228
|
+
:param str scope: the scope of the app. default is project.
|
|
229
|
+
:param bool wait: wait for the operation to finish.
|
|
230
|
+
:param list integrations: list of integrations to install with the app.
|
|
231
|
+
|
|
232
|
+
:return the installed app.
|
|
233
|
+
:rtype entities.App
|
|
234
|
+
|
|
235
|
+
**Example**
|
|
236
|
+
.. code-block:: python
|
|
237
|
+
app = dl.apps.install(dpk=dpk)
|
|
238
|
+
"""
|
|
239
|
+
if dpk is None:
|
|
240
|
+
raise exceptions.PlatformException(error='400', message='You must provide an app')
|
|
241
|
+
|
|
242
|
+
if app_name is None:
|
|
243
|
+
app_name = dpk.display_name
|
|
244
|
+
if isinstance(scope, entities.AppScope):
|
|
245
|
+
scope = scope.value
|
|
246
|
+
app = entities.App.from_json(_json={'name': app_name,
|
|
247
|
+
'projectId': self.project.id,
|
|
248
|
+
'orgId': organization_id,
|
|
249
|
+
'dpkName': dpk.name,
|
|
250
|
+
"customInstallation": custom_installation,
|
|
251
|
+
'dpkVersion': dpk.version,
|
|
252
|
+
'scope': scope,
|
|
253
|
+
'integrations': integrations
|
|
254
|
+
},
|
|
255
|
+
client_api=self._client_api,
|
|
256
|
+
project=self.project)
|
|
257
|
+
success, response = self._client_api.gen_request(req_type='post',
|
|
258
|
+
path="/apps",
|
|
259
|
+
json_req=app.to_json())
|
|
260
|
+
if not success:
|
|
261
|
+
raise exceptions.PlatformException(response)
|
|
262
|
+
app = entities.App.from_json(_json=response.json(),
|
|
263
|
+
client_api=self._client_api,
|
|
264
|
+
project=self.project)
|
|
265
|
+
|
|
266
|
+
if app.metadata:
|
|
267
|
+
command_id = app.metadata.get('system', {}).get('commands', {}).get('install', None)
|
|
268
|
+
if wait and app.status == entities.CompositionStatus.INITIALIZING and command_id is not None:
|
|
269
|
+
command = self.commands.get(command_id=command_id, url='api/v1/commands/faas/{}'.format(command_id))
|
|
270
|
+
command.wait()
|
|
271
|
+
app = self.get(app_id=app.id)
|
|
272
|
+
|
|
273
|
+
return app
|
|
274
|
+
|
|
275
|
+
def uninstall(self, app_id: str = None, app_name: str = None, wait: bool = True) -> bool:
|
|
276
|
+
"""
|
|
277
|
+
Delete an app entity.
|
|
278
|
+
|
|
279
|
+
Note: You are required to add either app_id or app_name.
|
|
280
|
+
|
|
281
|
+
:param str app_id: optional - the id of the app.
|
|
282
|
+
:param str app_name: optional - the name of the app.
|
|
283
|
+
:param bool wait: optional - wait for the operation to finish.
|
|
284
|
+
:return whether we succeed uninstalling the specified app.
|
|
285
|
+
:rtype bool
|
|
286
|
+
|
|
287
|
+
**Example**
|
|
288
|
+
.. code-block:: python
|
|
289
|
+
# succeed = dl.apps.delete(app_id='app_id')
|
|
290
|
+
"""
|
|
291
|
+
if app_id is None and app_name is None:
|
|
292
|
+
raise exceptions.PlatformException(
|
|
293
|
+
error='400',
|
|
294
|
+
message='You must provide an identifier in inputs')
|
|
295
|
+
if app_name is not None:
|
|
296
|
+
app = self.__get_by_name(app_name)
|
|
297
|
+
app_id = app.id
|
|
298
|
+
|
|
299
|
+
success, response = self._client_api.gen_request(req_type='delete', path='/apps/{}'.format(app_id))
|
|
300
|
+
if not success:
|
|
301
|
+
raise exceptions.PlatformException(response)
|
|
302
|
+
|
|
303
|
+
try:
|
|
304
|
+
app = self.get(app_id=app_id)
|
|
305
|
+
except Exception as e:
|
|
306
|
+
if e.status_code == '404':
|
|
307
|
+
return success
|
|
308
|
+
else:
|
|
309
|
+
raise e
|
|
310
|
+
if app.metadata:
|
|
311
|
+
command_id = app.metadata.get('system', {}).get('commands', {}).get('uninstall', None)
|
|
312
|
+
if wait and app.status == entities.CompositionStatus.TERMINATING and command_id is not None:
|
|
313
|
+
command = self.commands.get(command_id=command_id, url='api/v1/commands/faas/{}'.format(command_id))
|
|
314
|
+
command.wait()
|
|
315
|
+
|
|
316
|
+
logger.debug(f"App deleted successfully (id: {app_id}, name: {app_name}")
|
|
317
|
+
return success
|
|
318
|
+
|
|
319
|
+
def resume(self, app: entities.App = None, app_id: str = None) -> bool:
|
|
320
|
+
"""
|
|
321
|
+
Activate an app entity.
|
|
322
|
+
|
|
323
|
+
Note: You are required to add either app or app_id.
|
|
324
|
+
|
|
325
|
+
:param entities.App app: the app entity
|
|
326
|
+
:param str app_id: optional - the id of the app.
|
|
327
|
+
:return whether we succeed activating the specified app.
|
|
328
|
+
:rtype bool
|
|
329
|
+
|
|
330
|
+
**Example**
|
|
331
|
+
.. code-block:: python
|
|
332
|
+
# succeed = dl.apps.resume(app)
|
|
333
|
+
"""
|
|
334
|
+
if app_id is not None and app is None:
|
|
335
|
+
app = self.get(app_id=app_id)
|
|
336
|
+
|
|
337
|
+
if app and app.status == entities.CompositionStatus.INSTALLED:
|
|
338
|
+
raise exceptions.PlatformException(
|
|
339
|
+
error='400',
|
|
340
|
+
message='Application is already active'
|
|
341
|
+
)
|
|
342
|
+
if app is None:
|
|
343
|
+
raise exceptions.PlatformException(error='400', message='You must provide app or app_id')
|
|
344
|
+
|
|
345
|
+
success, response = self._client_api.gen_request(req_type='post', path='/apps/{}/activate'.format(app.id))
|
|
346
|
+
if not success:
|
|
347
|
+
raise exceptions.PlatformException(response)
|
|
348
|
+
|
|
349
|
+
logger.debug(f"App resumed successfully (id: {app.id}, name: {app.name}")
|
|
350
|
+
return success
|
|
351
|
+
|
|
352
|
+
def pause(self, app: entities.App = None, app_id: str = None) -> bool:
|
|
353
|
+
"""
|
|
354
|
+
Pausing an app entity.
|
|
355
|
+
|
|
356
|
+
Note: You are required to add either app or app_id.
|
|
357
|
+
|
|
358
|
+
:param entities.App app: the app entity
|
|
359
|
+
:param str app_id: optional - the id of the app.
|
|
360
|
+
:return whether we succeed pausing the specified app.
|
|
361
|
+
:rtype bool
|
|
362
|
+
|
|
363
|
+
**Example**
|
|
364
|
+
.. code-block:: python
|
|
365
|
+
# succeed = dl.apps.pause(app)
|
|
366
|
+
"""
|
|
367
|
+
if app_id is not None and app is None:
|
|
368
|
+
app = self.get(app_id=app_id)
|
|
369
|
+
|
|
370
|
+
if app and app.status == entities.CompositionStatus.UNINSTALLED:
|
|
371
|
+
raise exceptions.PlatformException(
|
|
372
|
+
error='400',
|
|
373
|
+
message='Application is already inactive'
|
|
374
|
+
)
|
|
375
|
+
if app is None:
|
|
376
|
+
raise exceptions.PlatformException(error='400', message='You must provide app or app_id')
|
|
377
|
+
|
|
378
|
+
success, response = self._client_api.gen_request(req_type='post', path='/apps/{}/deactivate'.format(app.id))
|
|
379
|
+
if not success:
|
|
380
|
+
raise exceptions.PlatformException(response)
|
|
381
|
+
|
|
382
|
+
logger.debug(f"App paused successfully (id: {app.id}, name: {app.name}")
|
|
383
|
+
return success
|