trainml 0.5.4__py3-none-any.whl → 0.5.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.
Files changed (37) hide show
  1. tests/integration/test_checkpoints_integration.py +7 -5
  2. tests/integration/test_datasets_integration.py +4 -5
  3. tests/integration/test_jobs_integration.py +40 -2
  4. tests/integration/test_models_integration.py +8 -10
  5. tests/integration/test_projects_integration.py +2 -6
  6. tests/integration/test_volumes_integration.py +100 -0
  7. tests/unit/cli/cloudbender/test_cli_reservation_unit.py +10 -14
  8. tests/unit/cli/test_cli_project_unit.py +5 -9
  9. tests/unit/cli/test_cli_volume_unit.py +20 -0
  10. tests/unit/cloudbender/test_services_unit.py +161 -0
  11. tests/unit/conftest.py +94 -21
  12. tests/unit/test_projects_unit.py +34 -48
  13. tests/unit/test_volumes_unit.py +447 -0
  14. trainml/__init__.py +1 -1
  15. trainml/cli/__init__.py +3 -6
  16. trainml/cli/cloudbender/__init__.py +1 -1
  17. trainml/cli/cloudbender/service.py +129 -0
  18. trainml/cli/project.py +10 -15
  19. trainml/cli/volume.py +235 -0
  20. trainml/cloudbender/cloudbender.py +2 -2
  21. trainml/cloudbender/services.py +115 -0
  22. trainml/exceptions.py +21 -12
  23. trainml/jobs.py +36 -39
  24. trainml/projects.py +19 -30
  25. trainml/trainml.py +7 -15
  26. trainml/volumes.py +255 -0
  27. {trainml-0.5.4.dist-info → trainml-0.5.6.dist-info}/METADATA +1 -1
  28. {trainml-0.5.4.dist-info → trainml-0.5.6.dist-info}/RECORD +32 -29
  29. tests/integration/test_providers_integration.py +0 -46
  30. tests/unit/test_providers_unit.py +0 -125
  31. trainml/cli/job.py +0 -173
  32. trainml/cli/provider.py +0 -75
  33. trainml/providers.py +0 -63
  34. {trainml-0.5.4.dist-info → trainml-0.5.6.dist-info}/LICENSE +0 -0
  35. {trainml-0.5.4.dist-info → trainml-0.5.6.dist-info}/WHEEL +0 -0
  36. {trainml-0.5.4.dist-info → trainml-0.5.6.dist-info}/entry_points.txt +0 -0
  37. {trainml-0.5.4.dist-info → trainml-0.5.6.dist-info}/top_level.txt +0 -0
tests/unit/conftest.py CHANGED
@@ -7,6 +7,7 @@ from trainml.trainml import TrainML
7
7
  from trainml.auth import Auth
8
8
  from trainml.datasets import Dataset, Datasets
9
9
  from trainml.checkpoints import Checkpoint, Checkpoints
10
+ from trainml.volumes import Volume, Volumes
10
11
  from trainml.models import Model, Models
11
12
  from trainml.gpu_types import GpuType, GpuTypes
12
13
  from trainml.environments import Environment, Environments
@@ -16,7 +17,7 @@ from trainml.projects import (
16
17
  Projects,
17
18
  Project,
18
19
  ProjectDatastore,
19
- ProjectReservation,
20
+ ProjectService,
20
21
  )
21
22
  from trainml.cloudbender import Cloudbender
22
23
  from trainml.cloudbender.providers import Provider, Providers
@@ -24,7 +25,7 @@ from trainml.cloudbender.regions import Region, Regions
24
25
  from trainml.cloudbender.nodes import Node, Nodes
25
26
  from trainml.cloudbender.devices import Device, Devices
26
27
  from trainml.cloudbender.datastores import Datastore, Datastores
27
- from trainml.cloudbender.reservations import Reservation, Reservations
28
+ from trainml.cloudbender.services import Service, Services
28
29
  from trainml.cloudbender.device_configs import DeviceConfig, DeviceConfigs
29
30
 
30
31
 
@@ -258,6 +259,79 @@ def mock_models():
258
259
  ]
259
260
 
260
261
 
262
+ @fixture(scope="session")
263
+ def mock_my_volumes():
264
+ trainml = Mock()
265
+ yield [
266
+ Volume(
267
+ trainml,
268
+ id="1",
269
+ project_uuid="proj-id-1",
270
+ name="first one",
271
+ status="ready",
272
+ capacity="10G",
273
+ used_size=100000000,
274
+ billed_size=100000000,
275
+ createdAt="2020-12-31T23:59:59.000Z",
276
+ ),
277
+ Volume(
278
+ trainml,
279
+ id="2",
280
+ project_uuid="proj-id-1",
281
+ name="second one",
282
+ status="ready",
283
+ capacity="10G",
284
+ used_size=100000000,
285
+ billed_size=100000000,
286
+ createdAt="2021-01-01T00:00:01.000Z",
287
+ ),
288
+ Volume(
289
+ trainml,
290
+ id="3",
291
+ project_uuid="proj-id-1",
292
+ name="first one",
293
+ status="ready",
294
+ capacity="10G",
295
+ used_size=100000000,
296
+ billed_size=100000000,
297
+ createdAt="2021-01-01T00:00:01.000Z",
298
+ ),
299
+ Volume(
300
+ trainml,
301
+ id="4",
302
+ project_uuid="proj-id-1",
303
+ name="other one",
304
+ status="ready",
305
+ capacity="10G",
306
+ used_size=100000000,
307
+ billed_size=100000000,
308
+ createdAt="2020-12-31T23:59:59.000Z",
309
+ ),
310
+ Volume(
311
+ trainml,
312
+ id="5",
313
+ project_uuid="proj-id-1",
314
+ name="not ready",
315
+ status="new",
316
+ capacity="10G",
317
+ used_size=100000000,
318
+ billed_size=100000000,
319
+ createdAt="2021-01-01T00:00:01.000Z",
320
+ ),
321
+ Volume(
322
+ trainml,
323
+ id="6",
324
+ project_uuid="proj-id-1",
325
+ name="failed",
326
+ status="failed",
327
+ capacity="10G",
328
+ used_size=100000000,
329
+ billed_size=100000000,
330
+ createdAt="2021-01-01T00:00:01.000Z",
331
+ ),
332
+ ]
333
+
334
+
261
335
  @fixture(scope="session")
262
336
  def mock_gpu_types():
263
337
  trainml = Mock()
@@ -813,27 +887,27 @@ def mock_project_datastores():
813
887
 
814
888
 
815
889
  @fixture(scope="session")
816
- def mock_reservations():
890
+ def mock_services():
817
891
  trainml = Mock()
818
892
  yield [
819
- Reservation(
893
+ Service(
820
894
  trainml,
821
895
  **{
822
896
  "provider_uuid": "prov-id-1",
823
897
  "region_uuid": "reg-id-1",
824
- "reservation_id": "res-id-1",
898
+ "service_id": "res-id-1",
825
899
  "type": "port",
826
900
  "name": "On-Prem Service A",
827
901
  "resource": "8001",
828
902
  "hostname": "service-a.local",
829
903
  },
830
904
  ),
831
- Reservation(
905
+ Service(
832
906
  trainml,
833
907
  **{
834
908
  "provider_uuid": "prov-id-2",
835
909
  "region_uuid": "reg-id-2",
836
- "reservation_id": "res-id-2",
910
+ "service_id": "res-id-2",
837
911
  "type": "port",
838
912
  "name": "Cloud Service B",
839
913
  "resource": "8001",
@@ -844,10 +918,10 @@ def mock_reservations():
844
918
 
845
919
 
846
920
  @fixture(scope="session")
847
- def mock_project_reservations():
921
+ def mock_project_services():
848
922
  trainml = Mock()
849
923
  yield [
850
- ProjectReservation(
924
+ ProjectService(
851
925
  trainml,
852
926
  **{
853
927
  "project_uuid": "proj-id-1",
@@ -859,7 +933,7 @@ def mock_project_reservations():
859
933
  "hostname": "service-a.local",
860
934
  },
861
935
  ),
862
- ProjectReservation(
936
+ ProjectService(
863
937
  trainml,
864
938
  **{
865
939
  "project_uuid": "proj-id-1",
@@ -903,6 +977,9 @@ def mock_device_configs():
903
977
  def mock_trainml(
904
978
  mock_my_datasets,
905
979
  mock_public_datasets,
980
+ mock_my_checkpoints,
981
+ mock_public_checkpoints,
982
+ mock_my_volumes,
906
983
  mock_models,
907
984
  mock_gpu_types,
908
985
  mock_environments,
@@ -913,7 +990,7 @@ def mock_trainml(
913
990
  mock_nodes,
914
991
  mock_devices,
915
992
  mock_datastores,
916
- mock_reservations,
993
+ mock_services,
917
994
  mock_device_configs,
918
995
  ):
919
996
  trainml = create_autospec(TrainML)
@@ -921,6 +998,7 @@ def mock_trainml(
921
998
  trainml.project = "proj-id-1"
922
999
  trainml.datasets = create_autospec(Datasets)
923
1000
  trainml.checkpoints = create_autospec(Checkpoints)
1001
+ trainml.volumes = create_autospec(Volumes)
924
1002
  trainml.models = create_autospec(Models)
925
1003
  trainml.gpu_types = create_autospec(GpuTypes)
926
1004
  trainml.environments = create_autospec(Environments)
@@ -930,10 +1008,9 @@ def mock_trainml(
930
1008
  trainml.datasets.list = AsyncMock(return_value=mock_my_datasets)
931
1009
  trainml.datasets.list_public = AsyncMock(return_value=mock_public_datasets)
932
1010
  trainml.checkpoints.list = AsyncMock(return_value=mock_my_checkpoints)
933
- trainml.checkpoints.list_public = AsyncMock(
934
- return_value=mock_public_checkpoints
935
- )
1011
+ trainml.checkpoints.list_public = AsyncMock(return_value=mock_public_checkpoints)
936
1012
  trainml.models.list = AsyncMock(return_value=mock_models)
1013
+ trainml.volumes.list = AsyncMock(return_value=mock_my_volumes)
937
1014
  trainml.gpu_types.list = AsyncMock(return_value=mock_gpu_types)
938
1015
  trainml.environments.list = AsyncMock(return_value=mock_environments)
939
1016
  trainml.jobs.list = AsyncMock(return_value=mock_jobs)
@@ -950,13 +1027,9 @@ def mock_trainml(
950
1027
  trainml.cloudbender.devices = create_autospec(Nodes)
951
1028
  trainml.cloudbender.devices.list = AsyncMock(return_value=mock_devices)
952
1029
  trainml.cloudbender.datastores = create_autospec(Datastores)
953
- trainml.cloudbender.datastores.list = AsyncMock(
954
- return_value=mock_datastores
955
- )
956
- trainml.cloudbender.reservations = create_autospec(Reservations)
957
- trainml.cloudbender.reservations.list = AsyncMock(
958
- return_value=mock_reservations
959
- )
1030
+ trainml.cloudbender.datastores.list = AsyncMock(return_value=mock_datastores)
1031
+ trainml.cloudbender.services = create_autospec(Services)
1032
+ trainml.cloudbender.services.list = AsyncMock(return_value=mock_services)
960
1033
  trainml.cloudbender.device_configs = create_autospec(DeviceConfigs)
961
1034
  trainml.cloudbender.device_configs.list = AsyncMock(
962
1035
  return_value=mock_device_configs
@@ -49,11 +49,11 @@ def project_datastore(mock_trainml):
49
49
 
50
50
 
51
51
  @fixture
52
- def project_reservation(mock_trainml):
53
- yield specimen.ProjectReservation(
52
+ def project_service(mock_trainml):
53
+ yield specimen.ProjectService(
54
54
  mock_trainml,
55
55
  id="res-id-1",
56
- name="reservation 1",
56
+ name="service 1",
57
57
  project_uuid="proj-id-1",
58
58
  region_uuid="reg-id-1",
59
59
  type="port",
@@ -72,9 +72,7 @@ class ProjectsTests:
72
72
  api_response = dict()
73
73
  mock_trainml._query = AsyncMock(return_value=api_response)
74
74
  await projects.get("1234")
75
- mock_trainml._query.assert_called_once_with(
76
- "/project/1234", "GET", dict()
77
- )
75
+ mock_trainml._query.assert_called_once_with("/project/1234", "GET", dict())
78
76
 
79
77
  @mark.asyncio
80
78
  async def test_list_projects(
@@ -96,9 +94,7 @@ class ProjectsTests:
96
94
  api_response = dict()
97
95
  mock_trainml._query = AsyncMock(return_value=api_response)
98
96
  await projects.remove("4567")
99
- mock_trainml._query.assert_called_once_with(
100
- "/project/4567", "DELETE", dict()
101
- )
97
+ mock_trainml._query.assert_called_once_with("/project/4567", "DELETE", dict())
102
98
 
103
99
  @mark.asyncio
104
100
  async def test_create_project_simple(self, projects, mock_trainml):
@@ -156,36 +152,36 @@ class ProjectDatastoreTests:
156
152
  assert not bool(empty_project_datastore)
157
153
 
158
154
 
159
- class ProjectReservationTests:
160
- def test_project_reservation_properties(self, project_reservation):
161
- assert isinstance(project_reservation.id, str)
162
- assert isinstance(project_reservation.name, str)
163
- assert isinstance(project_reservation.project_uuid, str)
164
- assert isinstance(project_reservation.type, str)
165
- assert isinstance(project_reservation.hostname, str)
166
- assert isinstance(project_reservation.resource, str)
167
- assert isinstance(project_reservation.region_uuid, str)
155
+ class ProjectServiceTests:
156
+ def test_project_service_properties(self, project_service):
157
+ assert isinstance(project_service.id, str)
158
+ assert isinstance(project_service.name, str)
159
+ assert isinstance(project_service.project_uuid, str)
160
+ assert isinstance(project_service.type, str)
161
+ assert isinstance(project_service.hostname, str)
162
+ assert isinstance(project_service.resource, str)
163
+ assert isinstance(project_service.region_uuid, str)
168
164
 
169
- def test_project_reservation_str(self, project_reservation):
170
- string = str(project_reservation)
171
- regex = r"^{.*\"id\": \"" + project_reservation.id + r"\".*}$"
165
+ def test_project_service_str(self, project_service):
166
+ string = str(project_service)
167
+ regex = r"^{.*\"id\": \"" + project_service.id + r"\".*}$"
172
168
  assert isinstance(string, str)
173
169
  assert re.match(regex, string)
174
170
 
175
- def test_project_reservation_repr(self, project_reservation):
176
- string = repr(project_reservation)
171
+ def test_project_service_repr(self, project_service):
172
+ string = repr(project_service)
177
173
  regex = (
178
- r"^ProjectReservation\( trainml , \*\*{.*'id': '"
179
- + project_reservation.id
174
+ r"^ProjectService\( trainml , \*\*{.*'id': '"
175
+ + project_service.id
180
176
  + r"'.*}\)$"
181
177
  )
182
178
  assert isinstance(string, str)
183
179
  assert re.match(regex, string)
184
180
 
185
- def test_project_reservation_bool(self, project_reservation, mock_trainml):
186
- empty_project_reservation = specimen.ProjectReservation(mock_trainml)
187
- assert bool(project_reservation)
188
- assert not bool(empty_project_reservation)
181
+ def test_project_service_bool(self, project_service, mock_trainml):
182
+ empty_project_service = specimen.ProjectService(mock_trainml)
183
+ assert bool(project_service)
184
+ assert not bool(empty_project_service)
189
185
 
190
186
 
191
187
  class ProjectTests:
@@ -203,9 +199,7 @@ class ProjectTests:
203
199
 
204
200
  def test_project_repr(self, project):
205
201
  string = repr(project)
206
- regex = (
207
- r"^Project\( trainml , \*\*{.*'id': '" + project.id + r"'.*}\)$"
208
- )
202
+ regex = r"^Project\( trainml , \*\*{.*'id': '" + project.id + r"'.*}\)$"
209
203
  assert isinstance(string, str)
210
204
  assert re.match(regex, string)
211
205
 
@@ -226,18 +220,14 @@ class ProjectTests:
226
220
  api_response = dict()
227
221
  mock_trainml._query = AsyncMock(return_value=api_response)
228
222
  await project.refresh_datastores()
229
- mock_trainml._query.assert_called_once_with(
230
- "/project/1/datastores", "PATCH"
231
- )
223
+ mock_trainml._query.assert_called_once_with("/project/1/datastores", "PATCH")
232
224
 
233
225
  @mark.asyncio
234
- async def test_project_refresh_reservations(self, project, mock_trainml):
226
+ async def test_project_refresh_services(self, project, mock_trainml):
235
227
  api_response = dict()
236
228
  mock_trainml._query = AsyncMock(return_value=api_response)
237
- await project.refresh_reservations()
238
- mock_trainml._query.assert_called_once_with(
239
- "/project/1/reservations", "PATCH"
240
- )
229
+ await project.refresh_services()
230
+ mock_trainml._query.assert_called_once_with("/project/1/services", "PATCH")
241
231
 
242
232
  @mark.asyncio
243
233
  async def test_project_list_datastores(self, project, mock_trainml):
@@ -259,13 +249,11 @@ class ProjectTests:
259
249
  ]
260
250
  mock_trainml._query = AsyncMock(return_value=api_response)
261
251
  resp = await project.list_datastores()
262
- mock_trainml._query.assert_called_once_with(
263
- "/project/1/datastores", "GET"
264
- )
252
+ mock_trainml._query.assert_called_once_with("/project/1/datastores", "GET")
265
253
  assert len(resp) == 2
266
254
 
267
255
  @mark.asyncio
268
- async def test_project_list_reservations(self, project, mock_trainml):
256
+ async def test_project_list_services(self, project, mock_trainml):
269
257
  api_response = [
270
258
  {
271
259
  "project_uuid": "proj-id-1",
@@ -287,8 +275,6 @@ class ProjectTests:
287
275
  },
288
276
  ]
289
277
  mock_trainml._query = AsyncMock(return_value=api_response)
290
- resp = await project.list_reservations()
291
- mock_trainml._query.assert_called_once_with(
292
- "/project/1/reservations", "GET"
293
- )
278
+ resp = await project.list_services()
279
+ mock_trainml._query.assert_called_once_with("/project/1/services", "GET")
294
280
  assert len(resp) == 2