trainml 0.5.9__py3-none-any.whl → 0.5.12__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.
- tests/integration/projects/conftest.py +3 -1
- tests/integration/projects/test_projects_credentials_integration.py +45 -0
- tests/integration/projects/test_projects_data_connectors_integration.py +44 -0
- tests/integration/projects/test_projects_datastores_integration.py +42 -0
- tests/integration/projects/test_projects_secrets_integration.py +1 -1
- tests/integration/projects/test_projects_services_integration.py +44 -0
- tests/integration/test_checkpoints_integration.py +1 -2
- tests/integration/test_models_integration.py +0 -1
- tests/unit/cli/projects/__init__.py +0 -0
- tests/unit/cli/projects/test_cli_project_credential_unit.py +26 -0
- tests/unit/cli/projects/test_cli_project_data_connector_unit.py +28 -0
- tests/unit/cli/projects/test_cli_project_datastore_unit.py +26 -0
- tests/unit/cli/projects/test_cli_project_key_unit.py +26 -0
- tests/unit/cli/projects/test_cli_project_secret_unit.py +26 -0
- tests/unit/cli/projects/test_cli_project_service_unit.py +26 -0
- tests/unit/cli/projects/test_cli_project_unit.py +19 -0
- tests/unit/cloudbender/test_datastores_unit.py +1 -5
- tests/unit/conftest.py +79 -6
- tests/unit/projects/test_project_credentials_unit.py +100 -0
- tests/unit/projects/test_projects_unit.py +1 -1
- tests/unit/test_checkpoints_unit.py +15 -23
- tests/unit/test_datasets_unit.py +15 -20
- tests/unit/test_models_unit.py +13 -16
- tests/unit/test_volumes_unit.py +3 -0
- trainml/__init__.py +1 -1
- trainml/checkpoints.py +14 -3
- trainml/cli/cloudbender/datastore.py +2 -7
- trainml/cli/job/create.py +16 -16
- trainml/cli/project/__init__.py +4 -73
- trainml/cli/project/credential.py +128 -0
- trainml/cli/project/data_connector.py +61 -0
- trainml/cli/project/datastore.py +61 -0
- trainml/cli/project/secret.py +12 -3
- trainml/cli/project/service.py +61 -0
- trainml/cloudbender/data_connectors.py +8 -0
- trainml/cloudbender/datastores.py +9 -19
- trainml/cloudbender/nodes.py +44 -1
- trainml/cloudbender/providers.py +53 -0
- trainml/cloudbender/regions.py +48 -0
- trainml/datasets.py +14 -3
- trainml/exceptions.py +51 -0
- trainml/jobs.py +2 -13
- trainml/models.py +14 -3
- trainml/projects/credentials.py +71 -0
- trainml/projects/projects.py +7 -4
- trainml/projects/secrets.py +1 -1
- trainml/volumes.py +15 -3
- {trainml-0.5.9.dist-info → trainml-0.5.12.dist-info}/METADATA +1 -1
- {trainml-0.5.9.dist-info → trainml-0.5.12.dist-info}/RECORD +53 -46
- tests/integration/test_projects_integration.py +0 -44
- tests/unit/cli/cloudbender/test_cli_reservation_unit.py +0 -34
- tests/unit/cli/test_cli_project_unit.py +0 -42
- tests/unit/cloudbender/test_reservations_unit.py +0 -173
- tests/unit/test_auth.py +0 -30
- tests/unit/test_projects_unit.py +0 -320
- tests/unit/test_trainml.py +0 -54
- trainml/cli/cloudbender/reservation.py +0 -159
- trainml/cli/project.py +0 -149
- trainml/cloudbender/reservations.py +0 -126
- trainml/projects.py +0 -228
- {trainml-0.5.9.dist-info → trainml-0.5.12.dist-info}/LICENSE +0 -0
- {trainml-0.5.9.dist-info → trainml-0.5.12.dist-info}/WHEEL +0 -0
- {trainml-0.5.9.dist-info → trainml-0.5.12.dist-info}/entry_points.txt +0 -0
- {trainml-0.5.9.dist-info → trainml-0.5.12.dist-info}/top_level.txt +0 -0
|
@@ -75,7 +75,7 @@ class ProjectsTests:
|
|
|
75
75
|
requested_config = dict(
|
|
76
76
|
name="new project",
|
|
77
77
|
)
|
|
78
|
-
expected_payload = dict(name="new project",
|
|
78
|
+
expected_payload = dict(name="new project", copy_credentials=False)
|
|
79
79
|
api_response = {
|
|
80
80
|
"id": "project-id-1",
|
|
81
81
|
"name": "new project",
|
|
@@ -44,9 +44,7 @@ class CheckpointsTests:
|
|
|
44
44
|
api_response = dict()
|
|
45
45
|
mock_trainml._query = AsyncMock(return_value=api_response)
|
|
46
46
|
await checkpoints.get("1234")
|
|
47
|
-
mock_trainml._query.assert_called_once_with(
|
|
48
|
-
"/checkpoint/1234", "GET", dict()
|
|
49
|
-
)
|
|
47
|
+
mock_trainml._query.assert_called_once_with("/checkpoint/1234", "GET", dict())
|
|
50
48
|
|
|
51
49
|
@mark.asyncio
|
|
52
50
|
async def test_list_checkpoints(
|
|
@@ -57,9 +55,7 @@ class CheckpointsTests:
|
|
|
57
55
|
api_response = dict()
|
|
58
56
|
mock_trainml._query = AsyncMock(return_value=api_response)
|
|
59
57
|
await checkpoints.list()
|
|
60
|
-
mock_trainml._query.assert_called_once_with(
|
|
61
|
-
"/checkpoint", "GET", dict()
|
|
62
|
-
)
|
|
58
|
+
mock_trainml._query.assert_called_once_with("/checkpoint", "GET", dict())
|
|
63
59
|
|
|
64
60
|
@mark.asyncio
|
|
65
61
|
async def test_remove_checkpoint(
|
|
@@ -86,11 +82,13 @@ class CheckpointsTests:
|
|
|
86
82
|
name="new checkpoint",
|
|
87
83
|
source_type="aws",
|
|
88
84
|
source_uri="s3://trainml-examples/checkpoints/resnet50",
|
|
85
|
+
type="evefs",
|
|
89
86
|
)
|
|
90
87
|
api_response = {
|
|
91
88
|
"project_uuid": "cus-id-1",
|
|
92
89
|
"checkpoint_uuid": "checkpoint-id-1",
|
|
93
90
|
"name": "new checkpoint",
|
|
91
|
+
"type": "evefs",
|
|
94
92
|
"status": "new",
|
|
95
93
|
"source_type": "aws",
|
|
96
94
|
"source_uri": "s3://trainml-examples/checkpoints/resnet50",
|
|
@@ -135,7 +133,9 @@ class CheckpointTests:
|
|
|
135
133
|
|
|
136
134
|
@mark.asyncio
|
|
137
135
|
async def test_checkpoint_get_log_url(self, checkpoint, mock_trainml):
|
|
138
|
-
api_response =
|
|
136
|
+
api_response = (
|
|
137
|
+
"https://trainml-jobs-dev.s3.us-east-2.amazonaws.com/1/logs/first_one.zip"
|
|
138
|
+
)
|
|
139
139
|
mock_trainml._query = AsyncMock(return_value=api_response)
|
|
140
140
|
response = await checkpoint.get_log_url()
|
|
141
141
|
mock_trainml._query.assert_called_once_with(
|
|
@@ -163,7 +163,9 @@ class CheckpointTests:
|
|
|
163
163
|
async def test_checkpoint_get_connection_utility_url(
|
|
164
164
|
self, checkpoint, mock_trainml
|
|
165
165
|
):
|
|
166
|
-
api_response =
|
|
166
|
+
api_response = (
|
|
167
|
+
"https://trainml-jobs-dev.s3.us-east-2.amazonaws.com/1/vpn/first_one.zip"
|
|
168
|
+
)
|
|
167
169
|
mock_trainml._query = AsyncMock(return_value=api_response)
|
|
168
170
|
response = await checkpoint.get_connection_utility_url()
|
|
169
171
|
mock_trainml._query.assert_called_once_with(
|
|
@@ -338,9 +340,7 @@ class CheckpointTests:
|
|
|
338
340
|
assert response.id == "data-id-1"
|
|
339
341
|
|
|
340
342
|
@mark.asyncio
|
|
341
|
-
async def test_checkpoint_wait_for_successful(
|
|
342
|
-
self, checkpoint, mock_trainml
|
|
343
|
-
):
|
|
343
|
+
async def test_checkpoint_wait_for_successful(self, checkpoint, mock_trainml):
|
|
344
344
|
api_response = {
|
|
345
345
|
"customer_uuid": "cus-id-1",
|
|
346
346
|
"checkpoint_uuid": "data-id-1",
|
|
@@ -373,9 +373,7 @@ class CheckpointTests:
|
|
|
373
373
|
mock_trainml._query.assert_not_called()
|
|
374
374
|
|
|
375
375
|
@mark.asyncio
|
|
376
|
-
async def test_checkpoint_wait_for_incorrect_status(
|
|
377
|
-
self, checkpoint, mock_trainml
|
|
378
|
-
):
|
|
376
|
+
async def test_checkpoint_wait_for_incorrect_status(self, checkpoint, mock_trainml):
|
|
379
377
|
api_response = None
|
|
380
378
|
mock_trainml._query = AsyncMock(return_value=api_response)
|
|
381
379
|
with raises(SpecificationError):
|
|
@@ -383,9 +381,7 @@ class CheckpointTests:
|
|
|
383
381
|
mock_trainml._query.assert_not_called()
|
|
384
382
|
|
|
385
383
|
@mark.asyncio
|
|
386
|
-
async def test_checkpoint_wait_for_with_delay(
|
|
387
|
-
self, checkpoint, mock_trainml
|
|
388
|
-
):
|
|
384
|
+
async def test_checkpoint_wait_for_with_delay(self, checkpoint, mock_trainml):
|
|
389
385
|
api_response_initial = dict(
|
|
390
386
|
checkpoint_uuid="1",
|
|
391
387
|
name="first one",
|
|
@@ -441,9 +437,7 @@ class CheckpointTests:
|
|
|
441
437
|
self, checkpoint, mock_trainml
|
|
442
438
|
):
|
|
443
439
|
mock_trainml._query = AsyncMock(
|
|
444
|
-
side_effect=ApiError(
|
|
445
|
-
404, dict(errorMessage="Checkpoint Not Found")
|
|
446
|
-
)
|
|
440
|
+
side_effect=ApiError(404, dict(errorMessage="Checkpoint Not Found"))
|
|
447
441
|
)
|
|
448
442
|
await checkpoint.wait_for("archived")
|
|
449
443
|
mock_trainml._query.assert_called()
|
|
@@ -453,9 +447,7 @@ class CheckpointTests:
|
|
|
453
447
|
self, checkpoint, mock_trainml
|
|
454
448
|
):
|
|
455
449
|
mock_trainml._query = AsyncMock(
|
|
456
|
-
side_effect=ApiError(
|
|
457
|
-
404, dict(errorMessage="Checkpoint Not Found")
|
|
458
|
-
)
|
|
450
|
+
side_effect=ApiError(404, dict(errorMessage="Checkpoint Not Found"))
|
|
459
451
|
)
|
|
460
452
|
with raises(ApiError):
|
|
461
453
|
await checkpoint.wait_for("ready")
|
tests/unit/test_datasets_unit.py
CHANGED
|
@@ -28,6 +28,7 @@ def dataset(mock_trainml):
|
|
|
28
28
|
dataset_uuid="1",
|
|
29
29
|
project_uuid="proj-id-1",
|
|
30
30
|
name="first one",
|
|
31
|
+
type="evefs",
|
|
31
32
|
status="downloading",
|
|
32
33
|
size=100000,
|
|
33
34
|
createdAt="2020-12-31T23:59:59.000Z",
|
|
@@ -103,6 +104,7 @@ class DatasetsTests:
|
|
|
103
104
|
name="new dataset",
|
|
104
105
|
source_type="aws",
|
|
105
106
|
source_uri="s3://trainml-examples/data/cifar10",
|
|
107
|
+
type="evefs",
|
|
106
108
|
)
|
|
107
109
|
api_response = {
|
|
108
110
|
"customer_uuid": "cus-id-1",
|
|
@@ -110,6 +112,7 @@ class DatasetsTests:
|
|
|
110
112
|
"dataset_uuid": "data-id-1",
|
|
111
113
|
"name": "new dataset",
|
|
112
114
|
"status": "new",
|
|
115
|
+
"type": "evefs",
|
|
113
116
|
"source_type": "aws",
|
|
114
117
|
"source_uri": "s3://trainml-examples/data/cifar10",
|
|
115
118
|
"createdAt": "2020-12-20T16:46:23.909Z",
|
|
@@ -139,9 +142,7 @@ class DatasetTests:
|
|
|
139
142
|
def test_dataset_repr(self, dataset):
|
|
140
143
|
string = repr(dataset)
|
|
141
144
|
regex = (
|
|
142
|
-
r"^Dataset\( trainml , \*\*{.*'dataset_uuid': '"
|
|
143
|
-
+ dataset.id
|
|
144
|
-
+ r"'.*}\)$"
|
|
145
|
+
r"^Dataset\( trainml , \*\*{.*'dataset_uuid': '" + dataset.id + r"'.*}\)$"
|
|
145
146
|
)
|
|
146
147
|
assert isinstance(string, str)
|
|
147
148
|
assert re.match(regex, string)
|
|
@@ -153,7 +154,9 @@ class DatasetTests:
|
|
|
153
154
|
|
|
154
155
|
@mark.asyncio
|
|
155
156
|
async def test_dataset_get_log_url(self, dataset, mock_trainml):
|
|
156
|
-
api_response =
|
|
157
|
+
api_response = (
|
|
158
|
+
"https://trainml-jobs-dev.s3.us-east-2.amazonaws.com/1/logs/first_one.zip"
|
|
159
|
+
)
|
|
157
160
|
mock_trainml._query = AsyncMock(return_value=api_response)
|
|
158
161
|
response = await dataset.get_log_url()
|
|
159
162
|
mock_trainml._query.assert_called_once_with(
|
|
@@ -178,10 +181,10 @@ class DatasetTests:
|
|
|
178
181
|
assert response == api_response
|
|
179
182
|
|
|
180
183
|
@mark.asyncio
|
|
181
|
-
async def test_dataset_get_connection_utility_url(
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
184
|
+
async def test_dataset_get_connection_utility_url(self, dataset, mock_trainml):
|
|
185
|
+
api_response = (
|
|
186
|
+
"https://trainml-jobs-dev.s3.us-east-2.amazonaws.com/1/vpn/first_one.zip"
|
|
187
|
+
)
|
|
185
188
|
mock_trainml._query = AsyncMock(return_value=api_response)
|
|
186
189
|
response = await dataset.get_connection_utility_url()
|
|
187
190
|
mock_trainml._query.assert_called_once_with(
|
|
@@ -388,9 +391,7 @@ class DatasetTests:
|
|
|
388
391
|
mock_trainml._query.assert_not_called()
|
|
389
392
|
|
|
390
393
|
@mark.asyncio
|
|
391
|
-
async def test_dataset_wait_for_incorrect_status(
|
|
392
|
-
self, dataset, mock_trainml
|
|
393
|
-
):
|
|
394
|
+
async def test_dataset_wait_for_incorrect_status(self, dataset, mock_trainml):
|
|
394
395
|
api_response = None
|
|
395
396
|
mock_trainml._query = AsyncMock(return_value=api_response)
|
|
396
397
|
with raises(SpecificationError):
|
|
@@ -435,9 +436,7 @@ class DatasetTests:
|
|
|
435
436
|
mock_trainml._query.assert_called()
|
|
436
437
|
|
|
437
438
|
@mark.asyncio
|
|
438
|
-
async def test_dataset_wait_for_dataset_failed(
|
|
439
|
-
self, dataset, mock_trainml
|
|
440
|
-
):
|
|
439
|
+
async def test_dataset_wait_for_dataset_failed(self, dataset, mock_trainml):
|
|
441
440
|
api_response = dict(
|
|
442
441
|
dataset_uuid="1",
|
|
443
442
|
name="first one",
|
|
@@ -450,9 +449,7 @@ class DatasetTests:
|
|
|
450
449
|
mock_trainml._query.assert_called()
|
|
451
450
|
|
|
452
451
|
@mark.asyncio
|
|
453
|
-
async def test_dataset_wait_for_archived_succeeded(
|
|
454
|
-
self, dataset, mock_trainml
|
|
455
|
-
):
|
|
452
|
+
async def test_dataset_wait_for_archived_succeeded(self, dataset, mock_trainml):
|
|
456
453
|
mock_trainml._query = AsyncMock(
|
|
457
454
|
side_effect=ApiError(404, dict(errorMessage="Dataset Not Found"))
|
|
458
455
|
)
|
|
@@ -460,9 +457,7 @@ class DatasetTests:
|
|
|
460
457
|
mock_trainml._query.assert_called()
|
|
461
458
|
|
|
462
459
|
@mark.asyncio
|
|
463
|
-
async def test_dataset_wait_for_unexpected_api_error(
|
|
464
|
-
self, dataset, mock_trainml
|
|
465
|
-
):
|
|
460
|
+
async def test_dataset_wait_for_unexpected_api_error(self, dataset, mock_trainml):
|
|
466
461
|
mock_trainml._query = AsyncMock(
|
|
467
462
|
side_effect=ApiError(404, dict(errorMessage="Dataset Not Found"))
|
|
468
463
|
)
|
tests/unit/test_models_unit.py
CHANGED
|
@@ -28,6 +28,7 @@ def model(mock_trainml):
|
|
|
28
28
|
model_uuid="1",
|
|
29
29
|
project_uuid="proj-id-1",
|
|
30
30
|
name="first one",
|
|
31
|
+
type="evefs",
|
|
31
32
|
status="downloading",
|
|
32
33
|
size=100000,
|
|
33
34
|
createdAt="2020-12-31T23:59:59.000Z",
|
|
@@ -44,9 +45,7 @@ class ModelsTests:
|
|
|
44
45
|
api_response = dict()
|
|
45
46
|
mock_trainml._query = AsyncMock(return_value=api_response)
|
|
46
47
|
await models.get("1234")
|
|
47
|
-
mock_trainml._query.assert_called_once_with(
|
|
48
|
-
"/model/1234", "GET", dict()
|
|
49
|
-
)
|
|
48
|
+
mock_trainml._query.assert_called_once_with("/model/1234", "GET", dict())
|
|
50
49
|
|
|
51
50
|
@mark.asyncio
|
|
52
51
|
async def test_list_models(
|
|
@@ -84,12 +83,14 @@ class ModelsTests:
|
|
|
84
83
|
name="new model",
|
|
85
84
|
source_type="aws",
|
|
86
85
|
source_uri="s3://trainml-examples/models/resnet50",
|
|
86
|
+
type="evefs",
|
|
87
87
|
)
|
|
88
88
|
api_response = {
|
|
89
89
|
"customer_uuid": "cus-id-1",
|
|
90
90
|
"model_uuid": "model-id-1",
|
|
91
91
|
"name": "new model",
|
|
92
92
|
"status": "new",
|
|
93
|
+
"type": "evefs",
|
|
93
94
|
"source_type": "aws",
|
|
94
95
|
"source_uri": "s3://trainml-examples/models/resnet50",
|
|
95
96
|
"createdAt": "2020-12-20T16:46:23.909Z",
|
|
@@ -118,11 +119,7 @@ class ModelTests:
|
|
|
118
119
|
|
|
119
120
|
def test_model_repr(self, model):
|
|
120
121
|
string = repr(model)
|
|
121
|
-
regex = (
|
|
122
|
-
r"^Model\( trainml , \*\*{.*'model_uuid': '"
|
|
123
|
-
+ model.id
|
|
124
|
-
+ r"'.*}\)$"
|
|
125
|
-
)
|
|
122
|
+
regex = r"^Model\( trainml , \*\*{.*'model_uuid': '" + model.id + r"'.*}\)$"
|
|
126
123
|
assert isinstance(string, str)
|
|
127
124
|
assert re.match(regex, string)
|
|
128
125
|
|
|
@@ -133,7 +130,9 @@ class ModelTests:
|
|
|
133
130
|
|
|
134
131
|
@mark.asyncio
|
|
135
132
|
async def test_model_get_log_url(self, model, mock_trainml):
|
|
136
|
-
api_response =
|
|
133
|
+
api_response = (
|
|
134
|
+
"https://trainml-jobs-dev.s3.us-east-2.amazonaws.com/1/logs/first_one.zip"
|
|
135
|
+
)
|
|
137
136
|
mock_trainml._query = AsyncMock(return_value=api_response)
|
|
138
137
|
response = await model.get_log_url()
|
|
139
138
|
mock_trainml._query.assert_called_once_with(
|
|
@@ -159,7 +158,9 @@ class ModelTests:
|
|
|
159
158
|
|
|
160
159
|
@mark.asyncio
|
|
161
160
|
async def test_model_get_connection_utility_url(self, model, mock_trainml):
|
|
162
|
-
api_response =
|
|
161
|
+
api_response = (
|
|
162
|
+
"https://trainml-jobs-dev.s3.us-east-2.amazonaws.com/1/vpn/first_one.zip"
|
|
163
|
+
)
|
|
163
164
|
mock_trainml._query = AsyncMock(return_value=api_response)
|
|
164
165
|
response = await model.get_connection_utility_url()
|
|
165
166
|
mock_trainml._query.assert_called_once_with(
|
|
@@ -425,9 +426,7 @@ class ModelTests:
|
|
|
425
426
|
mock_trainml._query.assert_called()
|
|
426
427
|
|
|
427
428
|
@mark.asyncio
|
|
428
|
-
async def test_model_wait_for_archived_succeeded(
|
|
429
|
-
self, model, mock_trainml
|
|
430
|
-
):
|
|
429
|
+
async def test_model_wait_for_archived_succeeded(self, model, mock_trainml):
|
|
431
430
|
mock_trainml._query = AsyncMock(
|
|
432
431
|
side_effect=ApiError(404, dict(errorMessage="Model Not Found"))
|
|
433
432
|
)
|
|
@@ -435,9 +434,7 @@ class ModelTests:
|
|
|
435
434
|
mock_trainml._query.assert_called()
|
|
436
435
|
|
|
437
436
|
@mark.asyncio
|
|
438
|
-
async def test_model_wait_for_unexpected_api_error(
|
|
439
|
-
self, model, mock_trainml
|
|
440
|
-
):
|
|
437
|
+
async def test_model_wait_for_unexpected_api_error(self, model, mock_trainml):
|
|
441
438
|
mock_trainml._query = AsyncMock(
|
|
442
439
|
side_effect=ApiError(404, dict(errorMessage="Model Not Found"))
|
|
443
440
|
)
|
tests/unit/test_volumes_unit.py
CHANGED
|
@@ -26,6 +26,7 @@ def volume(mock_trainml):
|
|
|
26
26
|
yield specimen.Volume(
|
|
27
27
|
mock_trainml,
|
|
28
28
|
id="1",
|
|
29
|
+
type="evefs",
|
|
29
30
|
project_uuid="proj-id-1",
|
|
30
31
|
name="first one",
|
|
31
32
|
status="downloading",
|
|
@@ -86,12 +87,14 @@ class VolumesTests:
|
|
|
86
87
|
source_type="aws",
|
|
87
88
|
source_uri="s3://trainml-examples/volumes/resnet50",
|
|
88
89
|
capacity="10G",
|
|
90
|
+
type="evefs",
|
|
89
91
|
)
|
|
90
92
|
api_response = {
|
|
91
93
|
"project_uuid": "cus-id-1",
|
|
92
94
|
"id": "volume-id-1",
|
|
93
95
|
"name": "new volume",
|
|
94
96
|
"status": "new",
|
|
97
|
+
"type": "evefs",
|
|
95
98
|
"source_type": "aws",
|
|
96
99
|
"capacity": "10G",
|
|
97
100
|
"source_uri": "s3://trainml-examples/volumes/resnet50",
|
trainml/__init__.py
CHANGED
trainml/checkpoints.py
CHANGED
|
@@ -31,13 +31,24 @@ class Checkpoints(object):
|
|
|
31
31
|
datasets = [Checkpoint(self.trainml, **dataset) for dataset in resp]
|
|
32
32
|
return datasets
|
|
33
33
|
|
|
34
|
-
async def create(
|
|
34
|
+
async def create(
|
|
35
|
+
self,
|
|
36
|
+
name,
|
|
37
|
+
source_type,
|
|
38
|
+
source_uri,
|
|
39
|
+
type="evefs",
|
|
40
|
+
project_uuid=None,
|
|
41
|
+
**kwargs,
|
|
42
|
+
):
|
|
43
|
+
if not project_uuid:
|
|
44
|
+
project_uuid = self.trainml.active_project
|
|
35
45
|
data = dict(
|
|
36
46
|
name=name,
|
|
37
47
|
source_type=source_type,
|
|
38
48
|
source_uri=source_uri,
|
|
39
|
-
|
|
40
|
-
|
|
49
|
+
project_uuid=project_uuid,
|
|
50
|
+
type=type,
|
|
51
|
+
**kwargs,
|
|
41
52
|
)
|
|
42
53
|
payload = {k: v for k, v in data.items() if v is not None}
|
|
43
54
|
logging.info(f"Creating Checkpoint {name}")
|
|
@@ -29,13 +29,11 @@ def datastore(config):
|
|
|
29
29
|
def list(config, provider, region):
|
|
30
30
|
"""List datastores."""
|
|
31
31
|
data = [
|
|
32
|
-
["ID", "NAME", "TYPE"
|
|
32
|
+
["ID", "NAME", "TYPE"],
|
|
33
33
|
[
|
|
34
34
|
"-" * 80,
|
|
35
35
|
"-" * 80,
|
|
36
36
|
"-" * 80,
|
|
37
|
-
"-" * 80,
|
|
38
|
-
"-" * 80,
|
|
39
37
|
],
|
|
40
38
|
]
|
|
41
39
|
|
|
@@ -51,15 +49,12 @@ def list(config, provider, region):
|
|
|
51
49
|
datastore.id,
|
|
52
50
|
datastore.name,
|
|
53
51
|
datastore.type,
|
|
54
|
-
datastore.uri,
|
|
55
|
-
datastore.root,
|
|
56
52
|
]
|
|
57
53
|
)
|
|
58
54
|
|
|
59
55
|
for row in data:
|
|
60
56
|
click.echo(
|
|
61
|
-
"{: >37.36} {: >29.28} {: >9.8}
|
|
62
|
-
"".format(*row),
|
|
57
|
+
"{: >37.36} {: >29.28} {: >9.8} " "".format(*row),
|
|
63
58
|
file=config.stdout,
|
|
64
59
|
)
|
|
65
60
|
|
trainml/cli/job/create.py
CHANGED
|
@@ -172,12 +172,12 @@ def create(config):
|
|
|
172
172
|
help="Conda packages to install as a comma separated list 'p1,\"p2=v2\",p3'",
|
|
173
173
|
)
|
|
174
174
|
@click.option(
|
|
175
|
-
"--
|
|
175
|
+
"--credential",
|
|
176
176
|
type=click.Choice(
|
|
177
177
|
["aws", "gcp", "kaggle", "azure", "wasabi"],
|
|
178
178
|
case_sensitive=False,
|
|
179
179
|
),
|
|
180
|
-
help="Third Party
|
|
180
|
+
help="Third Party Credentials to add to the job environment",
|
|
181
181
|
multiple=True,
|
|
182
182
|
)
|
|
183
183
|
@click.option(
|
|
@@ -221,7 +221,7 @@ def notebook(
|
|
|
221
221
|
environment,
|
|
222
222
|
custom_image,
|
|
223
223
|
env,
|
|
224
|
-
|
|
224
|
+
credential,
|
|
225
225
|
apt_packages,
|
|
226
226
|
pip_packages,
|
|
227
227
|
conda_packages,
|
|
@@ -254,7 +254,7 @@ def notebook(
|
|
|
254
254
|
data=dict(datasets=datasets),
|
|
255
255
|
model=dict(checkpoints=checkpoints),
|
|
256
256
|
environment=dict(
|
|
257
|
-
|
|
257
|
+
credentials=[k for k in credential],
|
|
258
258
|
),
|
|
259
259
|
)
|
|
260
260
|
|
|
@@ -500,12 +500,12 @@ def notebook(
|
|
|
500
500
|
multiple=True,
|
|
501
501
|
)
|
|
502
502
|
@click.option(
|
|
503
|
-
"--
|
|
503
|
+
"--credential",
|
|
504
504
|
type=click.Choice(
|
|
505
505
|
["aws", "gcp", "kaggle", "azure", "wasabi"],
|
|
506
506
|
case_sensitive=False,
|
|
507
507
|
),
|
|
508
|
-
help="Third Party
|
|
508
|
+
help="Third Party Credentials to add to the job environment",
|
|
509
509
|
multiple=True,
|
|
510
510
|
)
|
|
511
511
|
@click.option(
|
|
@@ -563,7 +563,7 @@ def training(
|
|
|
563
563
|
environment,
|
|
564
564
|
custom_image,
|
|
565
565
|
env,
|
|
566
|
-
|
|
566
|
+
credential,
|
|
567
567
|
apt_packages,
|
|
568
568
|
pip_packages,
|
|
569
569
|
conda_packages,
|
|
@@ -596,7 +596,7 @@ def training(
|
|
|
596
596
|
data=dict(datasets=datasets),
|
|
597
597
|
model=dict(checkpoints=checkpoints),
|
|
598
598
|
environment=dict(
|
|
599
|
-
|
|
599
|
+
credentials=[k for k in credential],
|
|
600
600
|
),
|
|
601
601
|
)
|
|
602
602
|
|
|
@@ -844,12 +844,12 @@ def training(
|
|
|
844
844
|
multiple=True,
|
|
845
845
|
)
|
|
846
846
|
@click.option(
|
|
847
|
-
"--
|
|
847
|
+
"--credential",
|
|
848
848
|
type=click.Choice(
|
|
849
849
|
["aws", "gcp", "kaggle", "azure", "wasabi"],
|
|
850
850
|
case_sensitive=False,
|
|
851
851
|
),
|
|
852
|
-
help="Third Party
|
|
852
|
+
help="Third Party Credentials to add to the job environment",
|
|
853
853
|
multiple=True,
|
|
854
854
|
)
|
|
855
855
|
@click.option(
|
|
@@ -907,7 +907,7 @@ def inference(
|
|
|
907
907
|
environment,
|
|
908
908
|
custom_image,
|
|
909
909
|
env,
|
|
910
|
-
|
|
910
|
+
credential,
|
|
911
911
|
apt_packages,
|
|
912
912
|
pip_packages,
|
|
913
913
|
conda_packages,
|
|
@@ -933,7 +933,7 @@ def inference(
|
|
|
933
933
|
data=dict(datasets=[]),
|
|
934
934
|
model=dict(checkpoints=checkpoints),
|
|
935
935
|
environment=dict(
|
|
936
|
-
|
|
936
|
+
credentials=[k for k in credential],
|
|
937
937
|
),
|
|
938
938
|
)
|
|
939
939
|
|
|
@@ -1163,12 +1163,12 @@ def from_json(config, attach, connect, file):
|
|
|
1163
1163
|
multiple=True,
|
|
1164
1164
|
)
|
|
1165
1165
|
@click.option(
|
|
1166
|
-
"--
|
|
1166
|
+
"--credential",
|
|
1167
1167
|
type=click.Choice(
|
|
1168
1168
|
["aws", "gcp", "kaggle", "azure", "wasabi"],
|
|
1169
1169
|
case_sensitive=False,
|
|
1170
1170
|
),
|
|
1171
|
-
help="Third Party
|
|
1171
|
+
help="Third Party Credentials to add to the job environment",
|
|
1172
1172
|
multiple=True,
|
|
1173
1173
|
)
|
|
1174
1174
|
@click.option(
|
|
@@ -1230,7 +1230,7 @@ def endpoint(
|
|
|
1230
1230
|
environment,
|
|
1231
1231
|
custom_image,
|
|
1232
1232
|
env,
|
|
1233
|
-
|
|
1233
|
+
credential,
|
|
1234
1234
|
apt_packages,
|
|
1235
1235
|
pip_packages,
|
|
1236
1236
|
conda_packages,
|
|
@@ -1257,7 +1257,7 @@ def endpoint(
|
|
|
1257
1257
|
max_price=max_price,
|
|
1258
1258
|
model=dict(checkpoints=checkpoints),
|
|
1259
1259
|
environment=dict(
|
|
1260
|
-
|
|
1260
|
+
credentials=[k for k in credential],
|
|
1261
1261
|
),
|
|
1262
1262
|
)
|
|
1263
1263
|
|
trainml/cli/project/__init__.py
CHANGED
|
@@ -77,77 +77,8 @@ def remove(config, project):
|
|
|
77
77
|
return config.trainml.run(found.remove())
|
|
78
78
|
|
|
79
79
|
|
|
80
|
-
@project.command()
|
|
81
|
-
@pass_config
|
|
82
|
-
def list_datastores(config):
|
|
83
|
-
"""List project datastores."""
|
|
84
|
-
data = [
|
|
85
|
-
["ID", "NAME", "TYPE", "REGION_UUID"],
|
|
86
|
-
[
|
|
87
|
-
"-" * 80,
|
|
88
|
-
"-" * 80,
|
|
89
|
-
"-" * 80,
|
|
90
|
-
"-" * 80,
|
|
91
|
-
],
|
|
92
|
-
]
|
|
93
|
-
project = config.trainml.run(
|
|
94
|
-
config.trainml.client.projects.get(config.trainml.client.project)
|
|
95
|
-
)
|
|
96
|
-
|
|
97
|
-
datastores = config.trainml.run(project.list_datastores())
|
|
98
|
-
|
|
99
|
-
for datastore in datastores:
|
|
100
|
-
data.append(
|
|
101
|
-
[
|
|
102
|
-
datastore.id,
|
|
103
|
-
datastore.name,
|
|
104
|
-
datastore.type,
|
|
105
|
-
datastore.region_uuid,
|
|
106
|
-
]
|
|
107
|
-
)
|
|
108
|
-
|
|
109
|
-
for row in data:
|
|
110
|
-
click.echo(
|
|
111
|
-
"{: >38.36} {: >30.28} {: >15.13} {: >38.36}" "".format(*row),
|
|
112
|
-
file=config.stdout,
|
|
113
|
-
)
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
@project.command()
|
|
117
|
-
@pass_config
|
|
118
|
-
def list_services(config):
|
|
119
|
-
"""List project services."""
|
|
120
|
-
data = [
|
|
121
|
-
["ID", "NAME", "HOSTNAME", "REGION_UUID"],
|
|
122
|
-
[
|
|
123
|
-
"-" * 80,
|
|
124
|
-
"-" * 80,
|
|
125
|
-
"-" * 80,
|
|
126
|
-
"-" * 80,
|
|
127
|
-
],
|
|
128
|
-
]
|
|
129
|
-
project = config.trainml.run(
|
|
130
|
-
config.trainml.client.projects.get(config.trainml.client.project)
|
|
131
|
-
)
|
|
132
|
-
|
|
133
|
-
services = config.trainml.run(project.list_services())
|
|
134
|
-
|
|
135
|
-
for service in services:
|
|
136
|
-
data.append(
|
|
137
|
-
[
|
|
138
|
-
service.id,
|
|
139
|
-
service.name,
|
|
140
|
-
service.hostname,
|
|
141
|
-
service.region_uuid,
|
|
142
|
-
]
|
|
143
|
-
)
|
|
144
|
-
|
|
145
|
-
for row in data:
|
|
146
|
-
click.echo(
|
|
147
|
-
"{: >38.36} {: >30.28} {: >30.28} {: >38.36}" "".format(*row),
|
|
148
|
-
file=config.stdout,
|
|
149
|
-
)
|
|
150
|
-
|
|
151
|
-
|
|
152
80
|
from trainml.cli.project.secret import secret
|
|
153
|
-
from trainml.cli.project.
|
|
81
|
+
from trainml.cli.project.credential import credential
|
|
82
|
+
from trainml.cli.project.data_connector import data_connector
|
|
83
|
+
from trainml.cli.project.datastore import datastore
|
|
84
|
+
from trainml.cli.project.service import service
|