dtlpy 1.114.17__py3-none-any.whl → 1.116.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 -311
- 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 -296
- dtlpy/entities/collection.py +38 -38
- dtlpy/entities/command.py +169 -169
- dtlpy/entities/compute.py +449 -442
- dtlpy/entities/dataset.py +1299 -1285
- dtlpy/entities/directory_tree.py +44 -44
- dtlpy/entities/dpk.py +470 -470
- dtlpy/entities/driver.py +235 -223
- dtlpy/entities/execution.py +397 -397
- dtlpy/entities/feature.py +124 -124
- dtlpy/entities/feature_set.py +145 -145
- dtlpy/entities/filters.py +798 -645
- dtlpy/entities/gis_item.py +107 -107
- dtlpy/entities/integration.py +184 -184
- dtlpy/entities/item.py +959 -953
- 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 -499
- dtlpy/entities/recipe.py +301 -301
- dtlpy/entities/reflect_dict.py +102 -102
- dtlpy/entities/resource_execution.py +138 -138
- dtlpy/entities/service.py +963 -958
- 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 +1257 -1086
- 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 -158
- dtlpy/repositories/compositions.py +61 -61
- dtlpy/repositories/computes.py +439 -435
- dtlpy/repositories/datasets.py +1504 -1291
- dtlpy/repositories/downloader.py +976 -903
- dtlpy/repositories/dpks.py +433 -433
- dtlpy/repositories/drivers.py +482 -470
- dtlpy/repositories/executions.py +815 -817
- dtlpy/repositories/feature_sets.py +226 -226
- dtlpy/repositories/features.py +255 -238
- dtlpy/repositories/integrations.py +484 -484
- dtlpy/repositories/items.py +912 -909
- dtlpy/repositories/messages.py +94 -94
- dtlpy/repositories/models.py +1000 -988
- 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 +419 -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 -651
- dtlpy/repositories/webhooks.py +249 -249
- dtlpy/services/__init__.py +22 -22
- dtlpy/services/aihttp_retry.py +131 -131
- dtlpy/services/api_client.py +1785 -1782
- 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.114.17.data → dtlpy-1.116.6.data}/scripts/dlp +1 -1
- dtlpy-1.116.6.data/scripts/dlp.bat +2 -0
- {dtlpy-1.114.17.data → dtlpy-1.116.6.data}/scripts/dlp.py +128 -128
- {dtlpy-1.114.17.dist-info → dtlpy-1.116.6.dist-info}/METADATA +186 -183
- dtlpy-1.116.6.dist-info/RECORD +239 -0
- {dtlpy-1.114.17.dist-info → dtlpy-1.116.6.dist-info}/WHEEL +1 -1
- {dtlpy-1.114.17.dist-info → dtlpy-1.116.6.dist-info}/licenses/LICENSE +200 -200
- tests/features/environment.py +551 -551
- dtlpy/assets/__pycache__/__init__.cpython-310.pyc +0 -0
- dtlpy-1.114.17.data/scripts/dlp.bat +0 -2
- dtlpy-1.114.17.dist-info/RECORD +0 -240
- {dtlpy-1.114.17.dist-info → dtlpy-1.116.6.dist-info}/entry_points.txt +0 -0
- {dtlpy-1.114.17.dist-info → dtlpy-1.116.6.dist-info}/top_level.txt +0 -0
dtlpy/repositories/drivers.py
CHANGED
|
@@ -1,470 +1,482 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
import re
|
|
3
|
-
|
|
4
|
-
from .. import entities, miscellaneous, exceptions, _api_reference
|
|
5
|
-
from ..services.api_client import ApiClient
|
|
6
|
-
|
|
7
|
-
logger = logging.getLogger(name="dtlpy")
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class Drivers:
|
|
11
|
-
"""
|
|
12
|
-
Drivers Repository
|
|
13
|
-
|
|
14
|
-
The Drivers class allows users to manage drivers that are used to connect with external storage.
|
|
15
|
-
Read more about external storage in our `documentation <https://dataloop.ai/docs/overview-1>`_ and `developers' docs <https://developers.dataloop.ai/tutorials/data_management/>`_.
|
|
16
|
-
"""
|
|
17
|
-
|
|
18
|
-
def __init__(self, client_api: ApiClient, project: entities.Project = None):
|
|
19
|
-
"""
|
|
20
|
-
Initialize the Drivers repository.
|
|
21
|
-
|
|
22
|
-
:param ApiClient client_api: The API client instance
|
|
23
|
-
:param Project project: Optional project entity. If not provided, will try to get from checkout
|
|
24
|
-
"""
|
|
25
|
-
self._client_api = client_api
|
|
26
|
-
self._project = project
|
|
27
|
-
|
|
28
|
-
############
|
|
29
|
-
# entities #
|
|
30
|
-
############
|
|
31
|
-
@property
|
|
32
|
-
def project(self) -> entities.Project:
|
|
33
|
-
if self._project is None:
|
|
34
|
-
# try get checkout
|
|
35
|
-
project = self._client_api.state_io.get("project")
|
|
36
|
-
if project is not None:
|
|
37
|
-
self._project = entities.Project.from_json(_json=project, client_api=self._client_api)
|
|
38
|
-
if self._project is None:
|
|
39
|
-
raise exceptions.PlatformException(
|
|
40
|
-
error="2001",
|
|
41
|
-
message="Cannot perform action WITHOUT Project entity in Drivers repository."
|
|
42
|
-
" Please checkout or set a project",
|
|
43
|
-
)
|
|
44
|
-
assert isinstance(self._project, entities.Project)
|
|
45
|
-
return self._project
|
|
46
|
-
|
|
47
|
-
@project.setter
|
|
48
|
-
def project(self, project: entities.Project):
|
|
49
|
-
"""
|
|
50
|
-
Set the project for this Drivers repository.
|
|
51
|
-
|
|
52
|
-
:param Project project: The project entity to set
|
|
53
|
-
:raises ValueError: If the provided project is not a valid Project entity
|
|
54
|
-
"""
|
|
55
|
-
if not isinstance(project, entities.Project):
|
|
56
|
-
raise ValueError("Must input a valid Project entity")
|
|
57
|
-
self._project = project
|
|
58
|
-
|
|
59
|
-
###########
|
|
60
|
-
# methods #
|
|
61
|
-
###########
|
|
62
|
-
def __get_by_id(self, driver_id) -> entities.Driver:
|
|
63
|
-
"""
|
|
64
|
-
Get a driver by its ID from the platform.
|
|
65
|
-
|
|
66
|
-
:param str driver_id: The driver ID
|
|
67
|
-
:return: Driver object
|
|
68
|
-
:rtype: dtlpy.entities.driver.Driver
|
|
69
|
-
:raises PlatformException: If the driver is not found or there's an API error
|
|
70
|
-
"""
|
|
71
|
-
success, response = self._client_api.gen_request(req_type="get", path="/drivers/{}".format(driver_id))
|
|
72
|
-
if success:
|
|
73
|
-
_json = response.json()
|
|
74
|
-
driver = self._getDriverClass(_json).from_json(client_api=self._client_api, _json=_json)
|
|
75
|
-
else:
|
|
76
|
-
raise exceptions.PlatformException(response)
|
|
77
|
-
return driver
|
|
78
|
-
|
|
79
|
-
@_api_reference.add(path="/drivers", method="get")
|
|
80
|
-
def list(self) -> miscellaneous.List[entities.Driver]:
|
|
81
|
-
"""
|
|
82
|
-
Get the project's drivers list.
|
|
83
|
-
|
|
84
|
-
**Prerequisites**: You must be in the role of an *owner* or *developer*.
|
|
85
|
-
|
|
86
|
-
:return: List of Drivers objects
|
|
87
|
-
:rtype: list
|
|
88
|
-
|
|
89
|
-
**Example**:
|
|
90
|
-
|
|
91
|
-
.. code-block:: python
|
|
92
|
-
|
|
93
|
-
project.drivers.list()
|
|
94
|
-
|
|
95
|
-
"""
|
|
96
|
-
|
|
97
|
-
success, response = self._client_api.gen_request(
|
|
98
|
-
req_type="get", path="/drivers?projectId={}".format(self.project.id)
|
|
99
|
-
)
|
|
100
|
-
if not success:
|
|
101
|
-
raise exceptions.PlatformException(response)
|
|
102
|
-
drivers = miscellaneous.List(
|
|
103
|
-
[
|
|
104
|
-
self._getDriverClass(_json).from_json(_json=_json, client_api=self._client_api)
|
|
105
|
-
for _json in response.json()
|
|
106
|
-
]
|
|
107
|
-
)
|
|
108
|
-
return drivers
|
|
109
|
-
|
|
110
|
-
def _getDriverClass(self, _json):
|
|
111
|
-
"""
|
|
112
|
-
Determine the appropriate driver class based on the driver type in the JSON response.
|
|
113
|
-
|
|
114
|
-
:param dict _json: The JSON response containing driver information
|
|
115
|
-
:return: The appropriate driver class (S3Driver, GcsDriver, AzureBlobDriver, or Driver)
|
|
116
|
-
:rtype: type
|
|
117
|
-
"""
|
|
118
|
-
driver_type = _json.get("type", None)
|
|
119
|
-
if driver_type == entities.ExternalStorage.S3:
|
|
120
|
-
driver_class = entities.S3Driver
|
|
121
|
-
elif driver_type == entities.ExternalStorage.GCS:
|
|
122
|
-
driver_class = entities.GcsDriver
|
|
123
|
-
elif driver_type in [entities.ExternalStorage.AZUREBLOB, entities.ExternalStorage.AZURE_DATALAKE_GEN2]:
|
|
124
|
-
driver_class = entities.AzureBlobDriver
|
|
125
|
-
else:
|
|
126
|
-
driver_class = entities.Driver
|
|
127
|
-
return driver_class
|
|
128
|
-
|
|
129
|
-
@_api_reference.add(path="/drivers/{id}", method="get")
|
|
130
|
-
def get(self, driver_name: str = None, driver_id: str = None) -> entities.Driver:
|
|
131
|
-
"""
|
|
132
|
-
Get a Driver object to use in your code.
|
|
133
|
-
|
|
134
|
-
**Prerequisites**: You must be in the role of an *owner* or *developer*.
|
|
135
|
-
|
|
136
|
-
You must provide at least ONE of the following params: driver_name, driver_id.
|
|
137
|
-
|
|
138
|
-
:param str driver_name: optional - search by name
|
|
139
|
-
:param str driver_id: optional - search by id
|
|
140
|
-
:return: Driver object
|
|
141
|
-
:rtype: dtlpy.entities.driver.Driver
|
|
142
|
-
|
|
143
|
-
**Example**:
|
|
144
|
-
|
|
145
|
-
.. code-block:: python
|
|
146
|
-
|
|
147
|
-
project.drivers.get(driver_id='driver_id')
|
|
148
|
-
"""
|
|
149
|
-
if driver_id is not None:
|
|
150
|
-
driver = self.__get_by_id(driver_id)
|
|
151
|
-
elif driver_name is not None:
|
|
152
|
-
drivers = self.list()
|
|
153
|
-
driver = [driver for driver in drivers if driver.name == driver_name]
|
|
154
|
-
if not driver:
|
|
155
|
-
# list is empty
|
|
156
|
-
raise exceptions.PlatformException(
|
|
157
|
-
error="404", message="Driver not found. Name: {}".format(driver_name)
|
|
158
|
-
)
|
|
159
|
-
# driver = None
|
|
160
|
-
elif len(driver) > 1:
|
|
161
|
-
# more than one matching driver
|
|
162
|
-
raise exceptions.PlatformException(
|
|
163
|
-
error="404", message='More than one driver with same name. Please "get" by id'
|
|
164
|
-
)
|
|
165
|
-
else:
|
|
166
|
-
driver = driver[0]
|
|
167
|
-
else:
|
|
168
|
-
raise exceptions.PlatformException(error="400", message="Must provide an identifier (name or id) in inputs")
|
|
169
|
-
return driver
|
|
170
|
-
|
|
171
|
-
@_api_reference.add(path="/drivers", method="post")
|
|
172
|
-
def _create_driver(self, payload: dict):
|
|
173
|
-
"""
|
|
174
|
-
Create a driver on the platform using the provided payload.
|
|
175
|
-
|
|
176
|
-
:param dict payload: The driver creation payload
|
|
177
|
-
:return: The created driver object
|
|
178
|
-
:rtype: dtlpy.entities.driver.Driver
|
|
179
|
-
:raises PlatformException: If the driver creation fails
|
|
180
|
-
"""
|
|
181
|
-
success, response = self._client_api.gen_request(req_type="post", path="/drivers", json_req=payload)
|
|
182
|
-
if not success:
|
|
183
|
-
raise exceptions.PlatformException(response)
|
|
184
|
-
else:
|
|
185
|
-
_json = response.json()
|
|
186
|
-
return self._getDriverClass(_json).from_json(_json=_json, client_api=self._client_api)
|
|
187
|
-
|
|
188
|
-
def create_powerscale_s3(
|
|
189
|
-
self,
|
|
190
|
-
name: str,
|
|
191
|
-
integration: entities.Integration,
|
|
192
|
-
elastic_index: str,
|
|
193
|
-
endpoint: str,
|
|
194
|
-
bucket_name: str,
|
|
195
|
-
region: str,
|
|
196
|
-
elastic_index_path: str,
|
|
197
|
-
path: str = None,
|
|
198
|
-
project_id: str = None,
|
|
199
|
-
allow_external_delete: bool = False
|
|
200
|
-
):
|
|
201
|
-
"""
|
|
202
|
-
Create a PowerScale S3 driver.
|
|
203
|
-
|
|
204
|
-
**Prerequisites**: You must be in the role of an *owner* or *developer*.
|
|
205
|
-
|
|
206
|
-
:param str name: The driver name
|
|
207
|
-
:param Integration integration: The S3 integration to use
|
|
208
|
-
:param str elastic_index: The elastic index for PowerScale S3 driver
|
|
209
|
-
:param str project_id: Optional project ID. If not provided, uses the current project
|
|
210
|
-
:param bool allow_external_delete: True to allow deleting files from external storage when files are deleted in your Dataloop storage
|
|
211
|
-
:param str endpoint: The endpoint URL. Must be in the format 'http://<hostname>:<port>' or 'https://<hostname>:<port>'
|
|
212
|
-
:param str bucket_name: The external bucket name
|
|
213
|
-
:param str region: The bucket region (relevant for S3)
|
|
214
|
-
:param str elastic_index_path: The elastic index path for PowerScale S3 driver
|
|
215
|
-
:param str path: The path to the NFS driver
|
|
216
|
-
:return: The created PowerScale S3 driver object
|
|
217
|
-
:rtype: dtlpy.entities.driver.Driver
|
|
218
|
-
:raises ValueError: If the integration type is not S3
|
|
219
|
-
:raises PlatformException: If the driver creation fails
|
|
220
|
-
|
|
221
|
-
**Example**:
|
|
222
|
-
|
|
223
|
-
.. code-block:: python
|
|
224
|
-
|
|
225
|
-
project.drivers.create_powerscale_s3(
|
|
226
|
-
name='powerscale_driver',
|
|
227
|
-
integration=integration,
|
|
228
|
-
elastic_index='my_index',
|
|
229
|
-
elastic_index_path='my_index_path',
|
|
230
|
-
endpoint='http://location:8765',
|
|
231
|
-
bucket_name='my_bucket',
|
|
232
|
-
region='us-west-1',
|
|
233
|
-
path='my_path'
|
|
234
|
-
)
|
|
235
|
-
"""
|
|
236
|
-
if not integration.type == entities.IntegrationType.S3:
|
|
237
|
-
raise ValueError("Integration type must be S3 for PowerScale S3 driver")
|
|
238
|
-
|
|
239
|
-
payload = {
|
|
240
|
-
"integrationId": integration.id,
|
|
241
|
-
"integrationType": integration.type,
|
|
242
|
-
"name": name,
|
|
243
|
-
"metadata": {"system": {"projectId": self.project.id if project_id is None else project_id}},
|
|
244
|
-
"type": entities.ExternalStorage.POWERSCALE_S3,
|
|
245
|
-
"payload": {
|
|
246
|
-
"elasticIndex": elastic_index,
|
|
247
|
-
"endpoint": endpoint,
|
|
248
|
-
"path": path,
|
|
249
|
-
"elasticIndexPath": elastic_index_path,
|
|
250
|
-
"bucketName": bucket_name,
|
|
251
|
-
"region": region
|
|
252
|
-
},
|
|
253
|
-
"allowExternalDelete": allow_external_delete,
|
|
254
|
-
"creator": self._client_api.info().get("user_email"),
|
|
255
|
-
}
|
|
256
|
-
return self._create_driver(payload)
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
def create_powerscale_nfs(
|
|
260
|
-
self,
|
|
261
|
-
name: str,
|
|
262
|
-
elastic_index: str,
|
|
263
|
-
elastic_index_path: str,
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
:param str
|
|
274
|
-
:param str
|
|
275
|
-
:param
|
|
276
|
-
:param str
|
|
277
|
-
:
|
|
278
|
-
:
|
|
279
|
-
:
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
:
|
|
320
|
-
:
|
|
321
|
-
:
|
|
322
|
-
:
|
|
323
|
-
:
|
|
324
|
-
:
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
:
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
"type"
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
:
|
|
386
|
-
:
|
|
387
|
-
:
|
|
388
|
-
:
|
|
389
|
-
:
|
|
390
|
-
:
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
:
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
"
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
1
|
+
import logging
|
|
2
|
+
import re
|
|
3
|
+
|
|
4
|
+
from .. import entities, miscellaneous, exceptions, _api_reference
|
|
5
|
+
from ..services.api_client import ApiClient
|
|
6
|
+
|
|
7
|
+
logger = logging.getLogger(name="dtlpy")
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Drivers:
|
|
11
|
+
"""
|
|
12
|
+
Drivers Repository
|
|
13
|
+
|
|
14
|
+
The Drivers class allows users to manage drivers that are used to connect with external storage.
|
|
15
|
+
Read more about external storage in our `documentation <https://dataloop.ai/docs/overview-1>`_ and `developers' docs <https://developers.dataloop.ai/tutorials/data_management/>`_.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def __init__(self, client_api: ApiClient, project: entities.Project = None):
|
|
19
|
+
"""
|
|
20
|
+
Initialize the Drivers repository.
|
|
21
|
+
|
|
22
|
+
:param ApiClient client_api: The API client instance
|
|
23
|
+
:param Project project: Optional project entity. If not provided, will try to get from checkout
|
|
24
|
+
"""
|
|
25
|
+
self._client_api = client_api
|
|
26
|
+
self._project = project
|
|
27
|
+
|
|
28
|
+
############
|
|
29
|
+
# entities #
|
|
30
|
+
############
|
|
31
|
+
@property
|
|
32
|
+
def project(self) -> entities.Project:
|
|
33
|
+
if self._project is None:
|
|
34
|
+
# try get checkout
|
|
35
|
+
project = self._client_api.state_io.get("project")
|
|
36
|
+
if project is not None:
|
|
37
|
+
self._project = entities.Project.from_json(_json=project, client_api=self._client_api)
|
|
38
|
+
if self._project is None:
|
|
39
|
+
raise exceptions.PlatformException(
|
|
40
|
+
error="2001",
|
|
41
|
+
message="Cannot perform action WITHOUT Project entity in Drivers repository."
|
|
42
|
+
" Please checkout or set a project",
|
|
43
|
+
)
|
|
44
|
+
assert isinstance(self._project, entities.Project)
|
|
45
|
+
return self._project
|
|
46
|
+
|
|
47
|
+
@project.setter
|
|
48
|
+
def project(self, project: entities.Project):
|
|
49
|
+
"""
|
|
50
|
+
Set the project for this Drivers repository.
|
|
51
|
+
|
|
52
|
+
:param Project project: The project entity to set
|
|
53
|
+
:raises ValueError: If the provided project is not a valid Project entity
|
|
54
|
+
"""
|
|
55
|
+
if not isinstance(project, entities.Project):
|
|
56
|
+
raise ValueError("Must input a valid Project entity")
|
|
57
|
+
self._project = project
|
|
58
|
+
|
|
59
|
+
###########
|
|
60
|
+
# methods #
|
|
61
|
+
###########
|
|
62
|
+
def __get_by_id(self, driver_id) -> entities.Driver:
|
|
63
|
+
"""
|
|
64
|
+
Get a driver by its ID from the platform.
|
|
65
|
+
|
|
66
|
+
:param str driver_id: The driver ID
|
|
67
|
+
:return: Driver object
|
|
68
|
+
:rtype: dtlpy.entities.driver.Driver
|
|
69
|
+
:raises PlatformException: If the driver is not found or there's an API error
|
|
70
|
+
"""
|
|
71
|
+
success, response = self._client_api.gen_request(req_type="get", path="/drivers/{}".format(driver_id))
|
|
72
|
+
if success:
|
|
73
|
+
_json = response.json()
|
|
74
|
+
driver = self._getDriverClass(_json).from_json(client_api=self._client_api, _json=_json)
|
|
75
|
+
else:
|
|
76
|
+
raise exceptions.PlatformException(response)
|
|
77
|
+
return driver
|
|
78
|
+
|
|
79
|
+
@_api_reference.add(path="/drivers", method="get")
|
|
80
|
+
def list(self) -> miscellaneous.List[entities.Driver]:
|
|
81
|
+
"""
|
|
82
|
+
Get the project's drivers list.
|
|
83
|
+
|
|
84
|
+
**Prerequisites**: You must be in the role of an *owner* or *developer*.
|
|
85
|
+
|
|
86
|
+
:return: List of Drivers objects
|
|
87
|
+
:rtype: list
|
|
88
|
+
|
|
89
|
+
**Example**:
|
|
90
|
+
|
|
91
|
+
.. code-block:: python
|
|
92
|
+
|
|
93
|
+
project.drivers.list()
|
|
94
|
+
|
|
95
|
+
"""
|
|
96
|
+
|
|
97
|
+
success, response = self._client_api.gen_request(
|
|
98
|
+
req_type="get", path="/drivers?projectId={}".format(self.project.id)
|
|
99
|
+
)
|
|
100
|
+
if not success:
|
|
101
|
+
raise exceptions.PlatformException(response)
|
|
102
|
+
drivers = miscellaneous.List(
|
|
103
|
+
[
|
|
104
|
+
self._getDriverClass(_json).from_json(_json=_json, client_api=self._client_api)
|
|
105
|
+
for _json in response.json()
|
|
106
|
+
]
|
|
107
|
+
)
|
|
108
|
+
return drivers
|
|
109
|
+
|
|
110
|
+
def _getDriverClass(self, _json):
|
|
111
|
+
"""
|
|
112
|
+
Determine the appropriate driver class based on the driver type in the JSON response.
|
|
113
|
+
|
|
114
|
+
:param dict _json: The JSON response containing driver information
|
|
115
|
+
:return: The appropriate driver class (S3Driver, GcsDriver, AzureBlobDriver, or Driver)
|
|
116
|
+
:rtype: type
|
|
117
|
+
"""
|
|
118
|
+
driver_type = _json.get("type", None)
|
|
119
|
+
if driver_type == entities.ExternalStorage.S3:
|
|
120
|
+
driver_class = entities.S3Driver
|
|
121
|
+
elif driver_type == entities.ExternalStorage.GCS:
|
|
122
|
+
driver_class = entities.GcsDriver
|
|
123
|
+
elif driver_type in [entities.ExternalStorage.AZUREBLOB, entities.ExternalStorage.AZURE_DATALAKE_GEN2]:
|
|
124
|
+
driver_class = entities.AzureBlobDriver
|
|
125
|
+
else:
|
|
126
|
+
driver_class = entities.Driver
|
|
127
|
+
return driver_class
|
|
128
|
+
|
|
129
|
+
@_api_reference.add(path="/drivers/{id}", method="get")
|
|
130
|
+
def get(self, driver_name: str = None, driver_id: str = None) -> entities.Driver:
|
|
131
|
+
"""
|
|
132
|
+
Get a Driver object to use in your code.
|
|
133
|
+
|
|
134
|
+
**Prerequisites**: You must be in the role of an *owner* or *developer*.
|
|
135
|
+
|
|
136
|
+
You must provide at least ONE of the following params: driver_name, driver_id.
|
|
137
|
+
|
|
138
|
+
:param str driver_name: optional - search by name
|
|
139
|
+
:param str driver_id: optional - search by id
|
|
140
|
+
:return: Driver object
|
|
141
|
+
:rtype: dtlpy.entities.driver.Driver
|
|
142
|
+
|
|
143
|
+
**Example**:
|
|
144
|
+
|
|
145
|
+
.. code-block:: python
|
|
146
|
+
|
|
147
|
+
project.drivers.get(driver_id='driver_id')
|
|
148
|
+
"""
|
|
149
|
+
if driver_id is not None:
|
|
150
|
+
driver = self.__get_by_id(driver_id)
|
|
151
|
+
elif driver_name is not None:
|
|
152
|
+
drivers = self.list()
|
|
153
|
+
driver = [driver for driver in drivers if driver.name == driver_name]
|
|
154
|
+
if not driver:
|
|
155
|
+
# list is empty
|
|
156
|
+
raise exceptions.PlatformException(
|
|
157
|
+
error="404", message="Driver not found. Name: {}".format(driver_name)
|
|
158
|
+
)
|
|
159
|
+
# driver = None
|
|
160
|
+
elif len(driver) > 1:
|
|
161
|
+
# more than one matching driver
|
|
162
|
+
raise exceptions.PlatformException(
|
|
163
|
+
error="404", message='More than one driver with same name. Please "get" by id'
|
|
164
|
+
)
|
|
165
|
+
else:
|
|
166
|
+
driver = driver[0]
|
|
167
|
+
else:
|
|
168
|
+
raise exceptions.PlatformException(error="400", message="Must provide an identifier (name or id) in inputs")
|
|
169
|
+
return driver
|
|
170
|
+
|
|
171
|
+
@_api_reference.add(path="/drivers", method="post")
|
|
172
|
+
def _create_driver(self, payload: dict):
|
|
173
|
+
"""
|
|
174
|
+
Create a driver on the platform using the provided payload.
|
|
175
|
+
|
|
176
|
+
:param dict payload: The driver creation payload
|
|
177
|
+
:return: The created driver object
|
|
178
|
+
:rtype: dtlpy.entities.driver.Driver
|
|
179
|
+
:raises PlatformException: If the driver creation fails
|
|
180
|
+
"""
|
|
181
|
+
success, response = self._client_api.gen_request(req_type="post", path="/drivers", json_req=payload)
|
|
182
|
+
if not success:
|
|
183
|
+
raise exceptions.PlatformException(response)
|
|
184
|
+
else:
|
|
185
|
+
_json = response.json()
|
|
186
|
+
return self._getDriverClass(_json).from_json(_json=_json, client_api=self._client_api)
|
|
187
|
+
|
|
188
|
+
def create_powerscale_s3(
|
|
189
|
+
self,
|
|
190
|
+
name: str,
|
|
191
|
+
integration: entities.Integration,
|
|
192
|
+
elastic_index: str,
|
|
193
|
+
endpoint: str,
|
|
194
|
+
bucket_name: str,
|
|
195
|
+
region: str,
|
|
196
|
+
elastic_index_path: str,
|
|
197
|
+
path: str = None,
|
|
198
|
+
project_id: str = None,
|
|
199
|
+
allow_external_delete: bool = False
|
|
200
|
+
):
|
|
201
|
+
"""
|
|
202
|
+
Create a PowerScale S3 driver.
|
|
203
|
+
|
|
204
|
+
**Prerequisites**: You must be in the role of an *owner* or *developer*.
|
|
205
|
+
|
|
206
|
+
:param str name: The driver name
|
|
207
|
+
:param Integration integration: The S3 integration to use
|
|
208
|
+
:param str elastic_index: The elastic index for PowerScale S3 driver
|
|
209
|
+
:param str project_id: Optional project ID. If not provided, uses the current project
|
|
210
|
+
:param bool allow_external_delete: True to allow deleting files from external storage when files are deleted in your Dataloop storage
|
|
211
|
+
:param str endpoint: The endpoint URL. Must be in the format 'http://<hostname>:<port>' or 'https://<hostname>:<port>'
|
|
212
|
+
:param str bucket_name: The external bucket name
|
|
213
|
+
:param str region: The bucket region (relevant for S3)
|
|
214
|
+
:param str elastic_index_path: The elastic index path for PowerScale S3 driver
|
|
215
|
+
:param str path: The path to the NFS driver
|
|
216
|
+
:return: The created PowerScale S3 driver object
|
|
217
|
+
:rtype: dtlpy.entities.driver.Driver
|
|
218
|
+
:raises ValueError: If the integration type is not S3
|
|
219
|
+
:raises PlatformException: If the driver creation fails
|
|
220
|
+
|
|
221
|
+
**Example**:
|
|
222
|
+
|
|
223
|
+
.. code-block:: python
|
|
224
|
+
|
|
225
|
+
project.drivers.create_powerscale_s3(
|
|
226
|
+
name='powerscale_driver',
|
|
227
|
+
integration=integration,
|
|
228
|
+
elastic_index='my_index',
|
|
229
|
+
elastic_index_path='my_index_path',
|
|
230
|
+
endpoint='http://location:8765',
|
|
231
|
+
bucket_name='my_bucket',
|
|
232
|
+
region='us-west-1',
|
|
233
|
+
path='my_path'
|
|
234
|
+
)
|
|
235
|
+
"""
|
|
236
|
+
if not integration.type == entities.IntegrationType.S3:
|
|
237
|
+
raise ValueError("Integration type must be S3 for PowerScale S3 driver")
|
|
238
|
+
|
|
239
|
+
payload = {
|
|
240
|
+
"integrationId": integration.id,
|
|
241
|
+
"integrationType": integration.type,
|
|
242
|
+
"name": name,
|
|
243
|
+
"metadata": {"system": {"projectId": self.project.id if project_id is None else project_id}},
|
|
244
|
+
"type": entities.ExternalStorage.POWERSCALE_S3,
|
|
245
|
+
"payload": {
|
|
246
|
+
"elasticIndex": elastic_index,
|
|
247
|
+
"endpoint": endpoint,
|
|
248
|
+
"path": path,
|
|
249
|
+
"elasticIndexPath": elastic_index_path,
|
|
250
|
+
"bucketName": bucket_name,
|
|
251
|
+
"region": region
|
|
252
|
+
},
|
|
253
|
+
"allowExternalDelete": allow_external_delete,
|
|
254
|
+
"creator": self._client_api.info().get("user_email"),
|
|
255
|
+
}
|
|
256
|
+
return self._create_driver(payload)
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
def create_powerscale_nfs(
|
|
260
|
+
self,
|
|
261
|
+
name: str,
|
|
262
|
+
elastic_index: str,
|
|
263
|
+
elastic_index_path: str,
|
|
264
|
+
integration: entities.Integration = None,
|
|
265
|
+
project_id: str = None,
|
|
266
|
+
allow_external_delete: bool = False
|
|
267
|
+
):
|
|
268
|
+
"""
|
|
269
|
+
Create a PowerScale NFS driver.
|
|
270
|
+
|
|
271
|
+
**Prerequisites**: You must be in the role of an *owner* or *developer*.
|
|
272
|
+
|
|
273
|
+
:param str name: The driver name
|
|
274
|
+
:param str elastic_index: The elastic index for PowerScale NFS driver
|
|
275
|
+
:param Integration integration (optional): The S3 integration to use. If not provided, integration id will be 'system'
|
|
276
|
+
:param str project_id: Optional project ID. If not provided, uses the current project
|
|
277
|
+
:param bool allow_external_delete: True to allow deleting files from external storage when files are deleted in your Dataloop storage
|
|
278
|
+
:param str elastic_index_path: The elastic index path for PowerScale NFS driver
|
|
279
|
+
:return: The created PowerScale NFS driver object
|
|
280
|
+
:rtype: dtlpy.entities.driver.Driver
|
|
281
|
+
:raises PlatformException: If the driver creation fails
|
|
282
|
+
|
|
283
|
+
**Example**:
|
|
284
|
+
|
|
285
|
+
.. code-block:: python
|
|
286
|
+
|
|
287
|
+
project.drivers.create_powerscale_nfs(
|
|
288
|
+
name='powerscale_driver',
|
|
289
|
+
elastic_index='my_index',
|
|
290
|
+
elastic_index_path='my_index_path',
|
|
291
|
+
)
|
|
292
|
+
"""
|
|
293
|
+
|
|
294
|
+
integration_id = 'system'
|
|
295
|
+
integration_type = None
|
|
296
|
+
if integration is not None:
|
|
297
|
+
if not integration.type == entities.IntegrationType.S3:
|
|
298
|
+
raise ValueError("Integration type must be S3 for PowerScale NFS driver")
|
|
299
|
+
integration_id = integration.id
|
|
300
|
+
integration_type = integration.type
|
|
301
|
+
|
|
302
|
+
payload = {
|
|
303
|
+
"integrationId": integration_id,
|
|
304
|
+
"integrationType": integration_type,
|
|
305
|
+
"name": name,
|
|
306
|
+
"metadata": {"system": {"projectId": self.project.id if project_id is None else project_id}},
|
|
307
|
+
"type": entities.ExternalStorage.POWERSCALE_NFS,
|
|
308
|
+
"payload": {"elasticIndex": elastic_index, "elasticIndexPath": elastic_index_path},
|
|
309
|
+
"allowExternalDelete": allow_external_delete,
|
|
310
|
+
"creator": self._client_api.info().get("user_email"),
|
|
311
|
+
}
|
|
312
|
+
return self._create_driver(payload)
|
|
313
|
+
|
|
314
|
+
def create_min_io(
|
|
315
|
+
self,
|
|
316
|
+
name: str,
|
|
317
|
+
integration: entities.Integration,
|
|
318
|
+
bucket_name: str,
|
|
319
|
+
endpoint: str,
|
|
320
|
+
project_id: str = None,
|
|
321
|
+
allow_external_delete: bool = True,
|
|
322
|
+
region: str = None,
|
|
323
|
+
storage_class: str = "",
|
|
324
|
+
path: str = "",
|
|
325
|
+
):
|
|
326
|
+
"""
|
|
327
|
+
Create a MinIO driver.
|
|
328
|
+
|
|
329
|
+
**Prerequisites**: You must be in the role of an *owner* or *developer*.
|
|
330
|
+
|
|
331
|
+
:param str name: The driver name
|
|
332
|
+
:param Integration integration: The S3 integration to use
|
|
333
|
+
:param str bucket_name: The external bucket name
|
|
334
|
+
:param str endpoint: The MinIO endpoint URL. Must be in the format 'http://<hostname>:<port>' or 'https://<hostname>:<port>'
|
|
335
|
+
:param str project_id: Optional project ID. If not provided, uses the current project
|
|
336
|
+
:param bool allow_external_delete: True to allow deleting files from external storage when files are deleted in your Dataloop storage
|
|
337
|
+
:param str region: The bucket region (relevant for S3)
|
|
338
|
+
:param str storage_class: The storage class (relevant for S3)
|
|
339
|
+
:param str path: Optional path. By default path is the root folder. Path is case sensitive
|
|
340
|
+
:return: The created MinIO driver object
|
|
341
|
+
:rtype: dtlpy.entities.driver.Driver
|
|
342
|
+
:raises ValueError: If the integration type is not S3 or if the endpoint URL format is invalid
|
|
343
|
+
:raises PlatformException: If the driver creation fails
|
|
344
|
+
|
|
345
|
+
**Example**:
|
|
346
|
+
|
|
347
|
+
.. code-block:: python
|
|
348
|
+
|
|
349
|
+
project.drivers.create_min_io(
|
|
350
|
+
name='minio_driver',
|
|
351
|
+
integration=integration,
|
|
352
|
+
bucket_name='my_bucket',
|
|
353
|
+
endpoint='http://localhost:9000'
|
|
354
|
+
)
|
|
355
|
+
"""
|
|
356
|
+
if not integration.type == entities.IntegrationType.S3:
|
|
357
|
+
raise ValueError("Integration type must be S3 for Minio driver")
|
|
358
|
+
|
|
359
|
+
if not re.match(r"^https?://[A-Za-z0-9.-]+:\d+$", endpoint):
|
|
360
|
+
raise ValueError(
|
|
361
|
+
f"Invalid endpoint URL '{endpoint}'. Must be 'http://<hostname>:<port>' or 'https://<hostname>:<port>'."
|
|
362
|
+
)
|
|
363
|
+
|
|
364
|
+
payload = {
|
|
365
|
+
"integrationId": integration.id,
|
|
366
|
+
"integrationType": integration.type,
|
|
367
|
+
"name": name,
|
|
368
|
+
"metadata": {"system": {"projectId": self.project.id if project_id is None else project_id}},
|
|
369
|
+
"type": entities.ExternalStorage.MIN_IO,
|
|
370
|
+
"payload": {"bucketName": bucket_name, "storageClass": storage_class, "region": region, "path": path, "endpoint": endpoint},
|
|
371
|
+
"allowExternalDelete": allow_external_delete,
|
|
372
|
+
"creator": self._client_api.info().get("user_email"),
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
return self._create_driver(payload)
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
def create(
|
|
379
|
+
self,
|
|
380
|
+
name: str,
|
|
381
|
+
driver_type: entities.ExternalStorage,
|
|
382
|
+
integration_id: str,
|
|
383
|
+
bucket_name: str,
|
|
384
|
+
integration_type: entities.IntegrationType,
|
|
385
|
+
project_id: str = None,
|
|
386
|
+
allow_external_delete: bool = True,
|
|
387
|
+
region: str = None,
|
|
388
|
+
storage_class: str = "",
|
|
389
|
+
path: str = "",
|
|
390
|
+
endpoint: str = None
|
|
391
|
+
):
|
|
392
|
+
"""
|
|
393
|
+
Create a storage driver.
|
|
394
|
+
|
|
395
|
+
**Prerequisites**: You must be in the role of an *owner* or *developer*.
|
|
396
|
+
|
|
397
|
+
:param str name: the driver name
|
|
398
|
+
:param ExternalStorage driver_type: dl.ExternalStorage (Enum). For all options run: list(dl.ExsternalStorage)
|
|
399
|
+
:param str integration_id: the integration id
|
|
400
|
+
:param str bucket_name: the external bucket name
|
|
401
|
+
:param IntegrationType integration_type: dl.IntegrationType (Enum). For all options run: list(dl.IntegrationType)
|
|
402
|
+
:param str project_id: project id
|
|
403
|
+
:param bool allow_external_delete: true to allow deleting files from external storage when files are deleted in your Dataloop storage
|
|
404
|
+
:param str region: relevant only for s3 - the bucket region
|
|
405
|
+
:param str storage_class: relevant only for s3
|
|
406
|
+
:param str path: Optional. By default path is the root folder. Path is case sensitive integration
|
|
407
|
+
:param str endpoint: Optional. Custom endpoint for minio storage. Must be in the format 'http://<hostname>:<port>' or 'https://<hostname>:<port>'.
|
|
408
|
+
:return: driver object
|
|
409
|
+
:rtype: dtlpy.entities.driver.Driver
|
|
410
|
+
|
|
411
|
+
**Example**:
|
|
412
|
+
|
|
413
|
+
.. code-block:: python
|
|
414
|
+
|
|
415
|
+
project.drivers.create(name='driver_name',
|
|
416
|
+
driver_type=dl.ExternalStorage.S3,
|
|
417
|
+
integration_id='integration_id',
|
|
418
|
+
bucket_name='bucket_name',
|
|
419
|
+
project_id='project_id',
|
|
420
|
+
region='ey-west-1')
|
|
421
|
+
"""
|
|
422
|
+
if integration_type is None:
|
|
423
|
+
integration_type = driver_type
|
|
424
|
+
if driver_type == entities.ExternalStorage.S3:
|
|
425
|
+
bucket_payload = "bucketName"
|
|
426
|
+
if endpoint:
|
|
427
|
+
if not re.match(r"^https?://[A-Za-z0-9.-]+:\d+$", endpoint):
|
|
428
|
+
raise ValueError(
|
|
429
|
+
f"Invalid endpoint URL '{endpoint}'. Must be 'http://<hostname>:<port>' or 'https://<hostname>:<port>'."
|
|
430
|
+
)
|
|
431
|
+
|
|
432
|
+
elif driver_type == entities.ExternalStorage.GCS:
|
|
433
|
+
bucket_payload = "bucket"
|
|
434
|
+
else:
|
|
435
|
+
bucket_payload = "containerName"
|
|
436
|
+
payload = {
|
|
437
|
+
"integrationId": integration_id,
|
|
438
|
+
"integrationType": integration_type,
|
|
439
|
+
"name": name,
|
|
440
|
+
"metadata": {"system": {"projectId": self.project.id if project_id is None else project_id}},
|
|
441
|
+
"type": driver_type,
|
|
442
|
+
"payload": {bucket_payload: bucket_name, "storageClass": storage_class, "region": region, "path": path},
|
|
443
|
+
"allowExternalDelete": allow_external_delete,
|
|
444
|
+
"creator": self._client_api.info().get("user_email"),
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
if endpoint and driver_type == entities.ExternalStorage.S3:
|
|
448
|
+
payload["payload"]["endpoint"] = endpoint
|
|
449
|
+
|
|
450
|
+
return self._create_driver(payload)
|
|
451
|
+
|
|
452
|
+
@_api_reference.add(path="/drivers/{id}", method="delete")
|
|
453
|
+
def delete(self, driver_name: str = None, driver_id: str = None, sure: bool = False, really: bool = False):
|
|
454
|
+
"""
|
|
455
|
+
Delete a driver forever!
|
|
456
|
+
|
|
457
|
+
**Prerequisites**: You must be an *owner* or *developer* to use this method.
|
|
458
|
+
|
|
459
|
+
**Example**:
|
|
460
|
+
|
|
461
|
+
.. code-block:: python
|
|
462
|
+
|
|
463
|
+
project.drivers.delete(dataset_id='dataset_id', sure=True, really=True)
|
|
464
|
+
|
|
465
|
+
:param str driver_name: optional - search by name
|
|
466
|
+
:param str driver_id: optional - search by id
|
|
467
|
+
:param bool sure: Are you sure you want to delete?
|
|
468
|
+
:param bool really: Really really sure?
|
|
469
|
+
:return: True if success
|
|
470
|
+
:rtype: bool
|
|
471
|
+
"""
|
|
472
|
+
if sure and really:
|
|
473
|
+
driver = self.get(driver_name=driver_name, driver_id=driver_id)
|
|
474
|
+
success, response = self._client_api.gen_request(req_type="delete", path="/drivers/{}".format(driver.id))
|
|
475
|
+
if not success:
|
|
476
|
+
raise exceptions.PlatformException(response)
|
|
477
|
+
logger.info("Driver {!r} was deleted successfully".format(driver.name))
|
|
478
|
+
return True
|
|
479
|
+
else:
|
|
480
|
+
raise exceptions.PlatformException(
|
|
481
|
+
error="403", message="Cant delete driver from SDK. Please login to platform to delete"
|
|
482
|
+
)
|