trainml 0.5.8__py3-none-any.whl → 0.5.11__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. tests/integration/projects/__init__.py +0 -0
  2. tests/integration/projects/conftest.py +10 -0
  3. tests/integration/projects/test_projects_data_connectors_integration.py +44 -0
  4. tests/integration/projects/test_projects_datastores_integration.py +42 -0
  5. tests/integration/{test_projects_integration.py → projects/test_projects_integration.py} +0 -6
  6. tests/integration/projects/test_projects_keys_integration.py +43 -0
  7. tests/integration/projects/test_projects_secrets_integration.py +44 -0
  8. tests/integration/projects/test_projects_services_integration.py +44 -0
  9. tests/integration/test_checkpoints_integration.py +1 -2
  10. tests/integration/test_models_integration.py +0 -1
  11. tests/unit/cli/projects/__init__.py +0 -0
  12. tests/unit/cli/projects/test_cli_project_data_connector_unit.py +28 -0
  13. tests/unit/cli/projects/test_cli_project_datastore_unit.py +26 -0
  14. tests/unit/cli/projects/test_cli_project_key_unit.py +26 -0
  15. tests/unit/cli/projects/test_cli_project_secret_unit.py +26 -0
  16. tests/unit/cli/projects/test_cli_project_service_unit.py +26 -0
  17. tests/unit/cli/projects/test_cli_project_unit.py +19 -0
  18. tests/unit/cloudbender/test_datastores_unit.py +1 -5
  19. tests/unit/conftest.py +146 -3
  20. tests/unit/projects/__init__.py +0 -0
  21. tests/unit/projects/test_project_data_connectors_unit.py +102 -0
  22. tests/unit/projects/test_project_datastores_unit.py +96 -0
  23. tests/unit/projects/test_project_keys_unit.py +96 -0
  24. tests/unit/projects/test_project_secrets_unit.py +101 -0
  25. tests/unit/projects/test_project_services_unit.py +102 -0
  26. tests/unit/projects/test_projects_unit.py +128 -0
  27. tests/unit/test_checkpoints_unit.py +15 -23
  28. tests/unit/test_datasets_unit.py +15 -20
  29. tests/unit/test_models_unit.py +13 -16
  30. tests/unit/test_volumes_unit.py +3 -0
  31. trainml/__init__.py +1 -1
  32. trainml/checkpoints.py +14 -3
  33. trainml/cli/cloudbender/datastore.py +2 -7
  34. trainml/cli/project/__init__.py +84 -0
  35. trainml/cli/project/data_connector.py +61 -0
  36. trainml/cli/project/datastore.py +61 -0
  37. trainml/cli/project/key.py +124 -0
  38. trainml/cli/project/secret.py +71 -0
  39. trainml/cli/project/service.py +61 -0
  40. trainml/cloudbender/data_connectors.py +8 -0
  41. trainml/cloudbender/datastores.py +9 -19
  42. trainml/cloudbender/nodes.py +44 -1
  43. trainml/cloudbender/providers.py +53 -0
  44. trainml/cloudbender/regions.py +48 -0
  45. trainml/datasets.py +14 -3
  46. trainml/exceptions.py +51 -0
  47. trainml/jobs.py +2 -13
  48. trainml/models.py +14 -3
  49. trainml/projects/__init__.py +3 -0
  50. trainml/projects/data_connectors.py +63 -0
  51. trainml/projects/datastores.py +58 -0
  52. trainml/projects/keys.py +71 -0
  53. trainml/projects/projects.py +83 -0
  54. trainml/projects/secrets.py +70 -0
  55. trainml/projects/services.py +63 -0
  56. trainml/volumes.py +15 -3
  57. {trainml-0.5.8.dist-info → trainml-0.5.11.dist-info}/METADATA +1 -1
  58. {trainml-0.5.8.dist-info → trainml-0.5.11.dist-info}/RECORD +64 -38
  59. tests/unit/cli/cloudbender/test_cli_reservation_unit.py +0 -34
  60. tests/unit/cli/test_cli_project_unit.py +0 -42
  61. tests/unit/cloudbender/test_reservations_unit.py +0 -173
  62. tests/unit/test_projects_unit.py +0 -320
  63. trainml/cli/cloudbender/reservation.py +0 -159
  64. trainml/cli/project.py +0 -149
  65. trainml/cloudbender/reservations.py +0 -126
  66. trainml/projects.py +0 -228
  67. /tests/unit/{test_auth.py → test_auth_unit.py} +0 -0
  68. /tests/unit/{test_trainml.py → test_trainml_unit.py} +0 -0
  69. {trainml-0.5.8.dist-info → trainml-0.5.11.dist-info}/LICENSE +0 -0
  70. {trainml-0.5.8.dist-info → trainml-0.5.11.dist-info}/WHEEL +0 -0
  71. {trainml-0.5.8.dist-info → trainml-0.5.11.dist-info}/entry_points.txt +0 -0
  72. {trainml-0.5.8.dist-info → trainml-0.5.11.dist-info}/top_level.txt +0 -0
@@ -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 = "https://trainml-jobs-dev.s3.us-east-2.amazonaws.com/1/logs/first_one.zip"
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 = "https://trainml-jobs-dev.s3.us-east-2.amazonaws.com/1/vpn/first_one.zip"
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")
@@ -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 = "https://trainml-jobs-dev.s3.us-east-2.amazonaws.com/1/logs/first_one.zip"
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
- self, dataset, mock_trainml
183
- ):
184
- api_response = "https://trainml-jobs-dev.s3.us-east-2.amazonaws.com/1/vpn/first_one.zip"
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
  )
@@ -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 = "https://trainml-jobs-dev.s3.us-east-2.amazonaws.com/1/logs/first_one.zip"
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 = "https://trainml-jobs-dev.s3.us-east-2.amazonaws.com/1/vpn/first_one.zip"
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
  )
@@ -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
@@ -13,5 +13,5 @@ logging.basicConfig(
13
13
  logger = logging.getLogger(__name__)
14
14
 
15
15
 
16
- __version__ = "0.5.8"
16
+ __version__ = "0.5.11"
17
17
  __all__ = "TrainML"
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(self, name, source_type, source_uri, **kwargs):
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
- source_options=kwargs.get("source_options"),
40
- project_uuid=kwargs.get("project_uuid") or self.trainml.active_project,
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", "URI", "ROOT"],
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} {: >12.11} {: >12.11}"
62
- "".format(*row),
57
+ "{: >37.36} {: >29.28} {: >9.8} " "".format(*row),
63
58
  file=config.stdout,
64
59
  )
65
60
 
@@ -0,0 +1,84 @@
1
+ import click
2
+ from trainml.cli import cli, pass_config, search_by_id_name
3
+
4
+
5
+ @cli.group()
6
+ @pass_config
7
+ def project(config):
8
+ """trainML project commands."""
9
+ pass
10
+
11
+
12
+ @project.command()
13
+ @pass_config
14
+ def list(config):
15
+ """List projects."""
16
+ data = [
17
+ ["ID", "NAME", "OWNER", "MINE"],
18
+ [
19
+ "-" * 80,
20
+ "-" * 80,
21
+ "-" * 80,
22
+ "-" * 80,
23
+ ],
24
+ ]
25
+
26
+ projects = config.trainml.run(config.trainml.client.projects.list())
27
+
28
+ for project in projects:
29
+ data.append(
30
+ [
31
+ project.id,
32
+ project.name,
33
+ project.owner_name,
34
+ "X" if project.is_owner else "",
35
+ ]
36
+ )
37
+
38
+ for row in data:
39
+ click.echo(
40
+ "{: >38.36} {: >30.28} {: >15.13} {: >4.4}" "".format(*row),
41
+ file=config.stdout,
42
+ )
43
+
44
+
45
+ @project.command()
46
+ @click.argument("name", type=click.STRING)
47
+ @pass_config
48
+ def create(config, name):
49
+ """
50
+ Create a project.
51
+
52
+ Project is created with the specified NAME.
53
+ """
54
+
55
+ return config.trainml.run(
56
+ config.trainml.client.projects.create(
57
+ name=name,
58
+ )
59
+ )
60
+
61
+
62
+ @project.command()
63
+ @click.argument("project", type=click.STRING)
64
+ @pass_config
65
+ def remove(config, project):
66
+ """
67
+ Remove a project.
68
+
69
+ PROJECT may be specified by name or ID, but ID is preferred.
70
+ """
71
+ projects = config.trainml.run(config.trainml.client.projects.list())
72
+
73
+ found = search_by_id_name(project, projects)
74
+ if None is found:
75
+ raise click.UsageError("Cannot find specified project.")
76
+
77
+ return config.trainml.run(found.remove())
78
+
79
+
80
+ from trainml.cli.project.secret import secret
81
+ from trainml.cli.project.key import key
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
@@ -0,0 +1,61 @@
1
+ import click
2
+ import os
3
+ import json
4
+ import base64
5
+ from pathlib import Path
6
+ from trainml.cli import pass_config
7
+ from trainml.cli.project import project
8
+
9
+
10
+ @project.group()
11
+ @pass_config
12
+ def data_connector(config):
13
+ """trainML project data_connector commands."""
14
+ pass
15
+
16
+
17
+ @data_connector.command()
18
+ @pass_config
19
+ def list(config):
20
+ """List project data_connectors."""
21
+ data = [
22
+ ["ID", "NAME", "TYPE", "REGION_UUID"],
23
+ [
24
+ "-" * 80,
25
+ "-" * 80,
26
+ "-" * 80,
27
+ "-" * 80,
28
+ ],
29
+ ]
30
+ project = config.trainml.run(
31
+ config.trainml.client.projects.get(config.trainml.client.project)
32
+ )
33
+
34
+ data_connectors = config.trainml.run(project.data_connectors.list())
35
+
36
+ for data_connector in data_connectors:
37
+ data.append(
38
+ [
39
+ data_connector.id,
40
+ data_connector.name,
41
+ data_connector.type,
42
+ data_connector.region_uuid,
43
+ ]
44
+ )
45
+
46
+ for row in data:
47
+ click.echo(
48
+ "{: >38.36} {: >30.28} {: >15.13} {: >38.36}" "".format(*row),
49
+ file=config.stdout,
50
+ )
51
+
52
+
53
+ @data_connector.command()
54
+ @pass_config
55
+ def refresh(config):
56
+ """
57
+ Refresh project data_connector list.
58
+ """
59
+ project = config.trainml.run(config.trainml.client.projects.get_current())
60
+
61
+ return config.trainml.run(project.data_connectors.refresh())
@@ -0,0 +1,61 @@
1
+ import click
2
+ import os
3
+ import json
4
+ import base64
5
+ from pathlib import Path
6
+ from trainml.cli import pass_config
7
+ from trainml.cli.project import project
8
+
9
+
10
+ @project.group()
11
+ @pass_config
12
+ def datastore(config):
13
+ """trainML project datastore commands."""
14
+ pass
15
+
16
+
17
+ @datastore.command()
18
+ @pass_config
19
+ def list(config):
20
+ """List project datastores."""
21
+ data = [
22
+ ["ID", "NAME", "TYPE", "REGION_UUID"],
23
+ [
24
+ "-" * 80,
25
+ "-" * 80,
26
+ "-" * 80,
27
+ "-" * 80,
28
+ ],
29
+ ]
30
+ project = config.trainml.run(
31
+ config.trainml.client.projects.get(config.trainml.client.project)
32
+ )
33
+
34
+ datastores = config.trainml.run(project.datastores.list())
35
+
36
+ for datastore in datastores:
37
+ data.append(
38
+ [
39
+ datastore.id,
40
+ datastore.name,
41
+ datastore.type,
42
+ datastore.region_uuid,
43
+ ]
44
+ )
45
+
46
+ for row in data:
47
+ click.echo(
48
+ "{: >38.36} {: >30.28} {: >15.13} {: >38.36}" "".format(*row),
49
+ file=config.stdout,
50
+ )
51
+
52
+
53
+ @datastore.command()
54
+ @pass_config
55
+ def refresh(config):
56
+ """
57
+ Refresh project datastore list.
58
+ """
59
+ project = config.trainml.run(config.trainml.client.projects.get_current())
60
+
61
+ return config.trainml.run(project.datastores.refresh())