proximl 0.5.10__tar.gz → 0.5.11__tar.gz

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 (142) hide show
  1. {proximl-0.5.10/proximl.egg-info → proximl-0.5.11}/PKG-INFO +1 -1
  2. {proximl-0.5.10 → proximl-0.5.11}/proximl/__init__.py +1 -1
  3. {proximl-0.5.10 → proximl-0.5.11}/proximl/cli/project/__init__.py +3 -72
  4. proximl-0.5.11/proximl/cli/project/data_connector.py +61 -0
  5. proximl-0.5.11/proximl/cli/project/datastore.py +61 -0
  6. proximl-0.5.11/proximl/cli/project/service.py +61 -0
  7. {proximl-0.5.10 → proximl-0.5.11}/proximl/cloudbender/nodes.py +4 -6
  8. {proximl-0.5.10 → proximl-0.5.11}/proximl/cloudbender/providers.py +53 -0
  9. {proximl-0.5.10 → proximl-0.5.11}/proximl/cloudbender/regions.py +48 -0
  10. {proximl-0.5.10 → proximl-0.5.11}/proximl/exceptions.py +51 -0
  11. {proximl-0.5.10 → proximl-0.5.11/proximl.egg-info}/PKG-INFO +1 -1
  12. {proximl-0.5.10 → proximl-0.5.11}/proximl.egg-info/SOURCES.txt +13 -1
  13. {proximl-0.5.10 → proximl-0.5.11}/tests/integration/projects/conftest.py +3 -1
  14. proximl-0.5.11/tests/integration/projects/test_projects_data_connectors_integration.py +44 -0
  15. proximl-0.5.11/tests/integration/projects/test_projects_datastores_integration.py +42 -0
  16. proximl-0.5.11/tests/integration/projects/test_projects_services_integration.py +44 -0
  17. {proximl-0.5.10 → proximl-0.5.11}/tests/integration/test_checkpoints_integration.py +1 -1
  18. proximl-0.5.11/tests/unit/cli/projects/test_cli_project_data_connector_unit.py +28 -0
  19. proximl-0.5.11/tests/unit/cli/projects/test_cli_project_datastore_unit.py +26 -0
  20. proximl-0.5.11/tests/unit/cli/projects/test_cli_project_key_unit.py +26 -0
  21. proximl-0.5.11/tests/unit/cli/projects/test_cli_project_secret_unit.py +26 -0
  22. proximl-0.5.11/tests/unit/cli/projects/test_cli_project_service_unit.py +26 -0
  23. proximl-0.5.11/tests/unit/cli/projects/test_cli_project_unit.py +19 -0
  24. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/conftest.py +77 -4
  25. proximl-0.5.11/tests/unit/projects/__init__.py +0 -0
  26. proximl-0.5.10/tests/unit/cli/test_cli_project_unit.py +0 -42
  27. {proximl-0.5.10 → proximl-0.5.11}/LICENSE +0 -0
  28. {proximl-0.5.10 → proximl-0.5.11}/README.md +0 -0
  29. {proximl-0.5.10 → proximl-0.5.11}/examples/__init__.py +0 -0
  30. {proximl-0.5.10 → proximl-0.5.11}/examples/create_dataset_and_training_job.py +0 -0
  31. {proximl-0.5.10 → proximl-0.5.11}/examples/local_storage.py +0 -0
  32. {proximl-0.5.10 → proximl-0.5.11}/examples/training_inference_pipeline.py +0 -0
  33. {proximl-0.5.10 → proximl-0.5.11}/proximl/__main__.py +0 -0
  34. {proximl-0.5.10 → proximl-0.5.11}/proximl/auth.py +0 -0
  35. {proximl-0.5.10 → proximl-0.5.11}/proximl/checkpoints.py +0 -0
  36. {proximl-0.5.10 → proximl-0.5.11}/proximl/cli/__init__.py +0 -0
  37. {proximl-0.5.10 → proximl-0.5.11}/proximl/cli/checkpoint.py +0 -0
  38. {proximl-0.5.10 → proximl-0.5.11}/proximl/cli/cloudbender/__init__.py +0 -0
  39. {proximl-0.5.10 → proximl-0.5.11}/proximl/cli/cloudbender/data_connector.py +0 -0
  40. {proximl-0.5.10 → proximl-0.5.11}/proximl/cli/cloudbender/datastore.py +0 -0
  41. {proximl-0.5.10 → proximl-0.5.11}/proximl/cli/cloudbender/device.py +0 -0
  42. {proximl-0.5.10 → proximl-0.5.11}/proximl/cli/cloudbender/node.py +0 -0
  43. {proximl-0.5.10 → proximl-0.5.11}/proximl/cli/cloudbender/provider.py +0 -0
  44. {proximl-0.5.10 → proximl-0.5.11}/proximl/cli/cloudbender/region.py +0 -0
  45. {proximl-0.5.10 → proximl-0.5.11}/proximl/cli/cloudbender/service.py +0 -0
  46. {proximl-0.5.10 → proximl-0.5.11}/proximl/cli/connection.py +0 -0
  47. {proximl-0.5.10 → proximl-0.5.11}/proximl/cli/dataset.py +0 -0
  48. {proximl-0.5.10 → proximl-0.5.11}/proximl/cli/environment.py +0 -0
  49. {proximl-0.5.10 → proximl-0.5.11}/proximl/cli/gpu.py +0 -0
  50. {proximl-0.5.10 → proximl-0.5.11}/proximl/cli/job/__init__.py +0 -0
  51. {proximl-0.5.10 → proximl-0.5.11}/proximl/cli/job/create.py +0 -0
  52. {proximl-0.5.10 → proximl-0.5.11}/proximl/cli/model.py +0 -0
  53. {proximl-0.5.10 → proximl-0.5.11}/proximl/cli/project/key.py +0 -0
  54. {proximl-0.5.10 → proximl-0.5.11}/proximl/cli/project/secret.py +0 -0
  55. {proximl-0.5.10 → proximl-0.5.11}/proximl/cli/volume.py +0 -0
  56. {proximl-0.5.10 → proximl-0.5.11}/proximl/cloudbender/__init__.py +0 -0
  57. {proximl-0.5.10 → proximl-0.5.11}/proximl/cloudbender/cloudbender.py +0 -0
  58. {proximl-0.5.10 → proximl-0.5.11}/proximl/cloudbender/data_connectors.py +0 -0
  59. {proximl-0.5.10 → proximl-0.5.11}/proximl/cloudbender/datastores.py +0 -0
  60. {proximl-0.5.10 → proximl-0.5.11}/proximl/cloudbender/device_configs.py +0 -0
  61. {proximl-0.5.10 → proximl-0.5.11}/proximl/cloudbender/devices.py +0 -0
  62. {proximl-0.5.10 → proximl-0.5.11}/proximl/cloudbender/services.py +0 -0
  63. {proximl-0.5.10 → proximl-0.5.11}/proximl/connections.py +0 -0
  64. {proximl-0.5.10 → proximl-0.5.11}/proximl/datasets.py +0 -0
  65. {proximl-0.5.10 → proximl-0.5.11}/proximl/environments.py +0 -0
  66. {proximl-0.5.10 → proximl-0.5.11}/proximl/gpu_types.py +0 -0
  67. {proximl-0.5.10 → proximl-0.5.11}/proximl/jobs.py +0 -0
  68. {proximl-0.5.10 → proximl-0.5.11}/proximl/models.py +0 -0
  69. {proximl-0.5.10 → proximl-0.5.11}/proximl/projects/__init__.py +0 -0
  70. {proximl-0.5.10 → proximl-0.5.11}/proximl/projects/data_connectors.py +0 -0
  71. {proximl-0.5.10 → proximl-0.5.11}/proximl/projects/datastores.py +0 -0
  72. {proximl-0.5.10 → proximl-0.5.11}/proximl/projects/keys.py +0 -0
  73. {proximl-0.5.10 → proximl-0.5.11}/proximl/projects/projects.py +0 -0
  74. {proximl-0.5.10 → proximl-0.5.11}/proximl/projects/secrets.py +0 -0
  75. {proximl-0.5.10 → proximl-0.5.11}/proximl/projects/services.py +0 -0
  76. {proximl-0.5.10 → proximl-0.5.11}/proximl/proximl.py +0 -0
  77. {proximl-0.5.10 → proximl-0.5.11}/proximl/volumes.py +0 -0
  78. {proximl-0.5.10 → proximl-0.5.11}/proximl.egg-info/dependency_links.txt +0 -0
  79. {proximl-0.5.10 → proximl-0.5.11}/proximl.egg-info/entry_points.txt +0 -0
  80. {proximl-0.5.10 → proximl-0.5.11}/proximl.egg-info/requires.txt +0 -0
  81. {proximl-0.5.10 → proximl-0.5.11}/proximl.egg-info/top_level.txt +0 -0
  82. {proximl-0.5.10 → proximl-0.5.11}/pyproject.toml +0 -0
  83. {proximl-0.5.10 → proximl-0.5.11}/setup.cfg +0 -0
  84. {proximl-0.5.10 → proximl-0.5.11}/setup.py +0 -0
  85. {proximl-0.5.10 → proximl-0.5.11}/tests/integration/__init__.py +0 -0
  86. {proximl-0.5.10 → proximl-0.5.11}/tests/integration/cloudbender/__init__.py +0 -0
  87. {proximl-0.5.10 → proximl-0.5.11}/tests/integration/cloudbender/test_providers_integration.py +0 -0
  88. {proximl-0.5.10 → proximl-0.5.11}/tests/integration/conftest.py +0 -0
  89. {proximl-0.5.10 → proximl-0.5.11}/tests/integration/projects/__init__.py +0 -0
  90. {proximl-0.5.10 → proximl-0.5.11}/tests/integration/projects/test_projects_integration.py +0 -0
  91. {proximl-0.5.10 → proximl-0.5.11}/tests/integration/projects/test_projects_keys_integration.py +0 -0
  92. {proximl-0.5.10 → proximl-0.5.11}/tests/integration/projects/test_projects_secrets_integration.py +0 -0
  93. {proximl-0.5.10 → proximl-0.5.11}/tests/integration/test_datasets_integration.py +0 -0
  94. {proximl-0.5.10 → proximl-0.5.11}/tests/integration/test_environments_integration.py +0 -0
  95. {proximl-0.5.10 → proximl-0.5.11}/tests/integration/test_gpu_types_integration.py +0 -0
  96. {proximl-0.5.10 → proximl-0.5.11}/tests/integration/test_jobs_integration.py +0 -0
  97. {proximl-0.5.10 → proximl-0.5.11}/tests/integration/test_models_integration.py +0 -0
  98. {proximl-0.5.10 → proximl-0.5.11}/tests/integration/test_volumes_integration.py +0 -0
  99. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/__init__.py +0 -0
  100. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/cli/__init__.py +0 -0
  101. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/cli/cloudbender/__init__.py +0 -0
  102. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/cli/cloudbender/test_cli_datastore_unit.py +0 -0
  103. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/cli/cloudbender/test_cli_device_unit.py +0 -0
  104. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/cli/cloudbender/test_cli_node_unit.py +0 -0
  105. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/cli/cloudbender/test_cli_provider_unit.py +0 -0
  106. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/cli/cloudbender/test_cli_region_unit.py +0 -0
  107. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/cli/cloudbender/test_cli_service_unit.py +0 -0
  108. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/cli/conftest.py +0 -0
  109. {proximl-0.5.10/tests/unit/cloudbender → proximl-0.5.11/tests/unit/cli/projects}/__init__.py +0 -0
  110. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/cli/test_cli_checkpoint_unit.py +0 -0
  111. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/cli/test_cli_datasets_unit.py +0 -0
  112. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/cli/test_cli_environment_unit.py +0 -0
  113. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/cli/test_cli_gpu_unit.py +0 -0
  114. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/cli/test_cli_job_unit.py +0 -0
  115. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/cli/test_cli_model_unit.py +0 -0
  116. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/cli/test_cli_volume_unit.py +0 -0
  117. {proximl-0.5.10/tests/unit/projects → proximl-0.5.11/tests/unit/cloudbender}/__init__.py +0 -0
  118. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/cloudbender/test_data_connectors_unit.py +0 -0
  119. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/cloudbender/test_datastores_unit.py +0 -0
  120. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/cloudbender/test_device_configs_unit.py +0 -0
  121. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/cloudbender/test_devices_unit.py +0 -0
  122. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/cloudbender/test_nodes_unit.py +0 -0
  123. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/cloudbender/test_providers_unit.py +0 -0
  124. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/cloudbender/test_regions_unit.py +0 -0
  125. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/cloudbender/test_services_unit.py +0 -0
  126. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/projects/test_project_data_connectors_unit.py +0 -0
  127. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/projects/test_project_datastores_unit.py +0 -0
  128. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/projects/test_project_keys_unit.py +0 -0
  129. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/projects/test_project_secrets_unit.py +0 -0
  130. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/projects/test_project_services_unit.py +0 -0
  131. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/projects/test_projects_unit.py +0 -0
  132. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/test_auth_unit.py +0 -0
  133. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/test_checkpoints_unit.py +0 -0
  134. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/test_connections_unit.py +0 -0
  135. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/test_datasets_unit.py +0 -0
  136. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/test_environments_unit.py +0 -0
  137. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/test_exceptions.py +0 -0
  138. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/test_gpu_types_unit.py +0 -0
  139. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/test_jobs_unit.py +0 -0
  140. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/test_models_unit.py +0 -0
  141. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/test_proximl_unit.py +0 -0
  142. {proximl-0.5.10 → proximl-0.5.11}/tests/unit/test_volumes_unit.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: proximl
3
- Version: 0.5.10
3
+ Version: 0.5.11
4
4
  Summary: proxiML client SDK and command line utilities
5
5
  Home-page: https://github.com/proxiML/python-sdk
6
6
  Author: proxiML
@@ -13,5 +13,5 @@ logging.basicConfig(
13
13
  logger = logging.getLogger(__name__)
14
14
 
15
15
 
16
- __version__ = "0.5.10"
16
+ __version__ = "0.5.11"
17
17
  __all__ = "ProxiML"
@@ -77,77 +77,8 @@ def remove(config, project):
77
77
  return config.proximl.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.proximl.run(
94
- config.proximl.client.projects.get(config.proximl.client.project)
95
- )
96
-
97
- datastores = config.proximl.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.proximl.run(
130
- config.proximl.client.projects.get(config.proximl.client.project)
131
- )
132
-
133
- services = config.proximl.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 proximl.cli.project.secret import secret
153
81
  from proximl.cli.project.key import key
82
+ from proximl.cli.project.data_connector import data_connector
83
+ from proximl.cli.project.datastore import datastore
84
+ from proximl.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 proximl.cli import pass_config
7
+ from proximl.cli.project import project
8
+
9
+
10
+ @project.group()
11
+ @pass_config
12
+ def data_connector(config):
13
+ """proxiML 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.proximl.run(
31
+ config.proximl.client.projects.get(config.proximl.client.project)
32
+ )
33
+
34
+ data_connectors = config.proximl.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.proximl.run(config.proximl.client.projects.get_current())
60
+
61
+ return config.proximl.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 proximl.cli import pass_config
7
+ from proximl.cli.project import project
8
+
9
+
10
+ @project.group()
11
+ @pass_config
12
+ def datastore(config):
13
+ """proxiML 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.proximl.run(
31
+ config.proximl.client.projects.get(config.proximl.client.project)
32
+ )
33
+
34
+ datastores = config.proximl.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.proximl.run(config.proximl.client.projects.get_current())
60
+
61
+ return config.proximl.run(project.datastores.refresh())
@@ -0,0 +1,61 @@
1
+ import click
2
+ import os
3
+ import json
4
+ import base64
5
+ from pathlib import Path
6
+ from proximl.cli import pass_config
7
+ from proximl.cli.project import project
8
+
9
+
10
+ @project.group()
11
+ @pass_config
12
+ def service(config):
13
+ """proxiML project service commands."""
14
+ pass
15
+
16
+
17
+ @service.command()
18
+ @pass_config
19
+ def list(config):
20
+ """List project services."""
21
+ data = [
22
+ ["ID", "NAME", "TYPE", "REGION_UUID"],
23
+ [
24
+ "-" * 80,
25
+ "-" * 80,
26
+ "-" * 80,
27
+ "-" * 80,
28
+ ],
29
+ ]
30
+ project = config.proximl.run(
31
+ config.proximl.client.projects.get(config.proximl.client.project)
32
+ )
33
+
34
+ services = config.proximl.run(project.services.list())
35
+
36
+ for service in services:
37
+ data.append(
38
+ [
39
+ service.id,
40
+ service.name,
41
+ service.hostname,
42
+ service.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
+ @service.command()
54
+ @pass_config
55
+ def refresh(config):
56
+ """
57
+ Refresh project service list.
58
+ """
59
+ project = config.proximl.run(config.proximl.client.projects.get_current())
60
+
61
+ return config.proximl.run(project.services.refresh())
@@ -3,11 +3,7 @@ import logging
3
3
  import asyncio
4
4
  import math
5
5
 
6
- from proximl.exceptions import (
7
- ApiError,
8
- SpecificationError,
9
- ProxiMLException,
10
- )
6
+ from proximl.exceptions import ApiError, SpecificationError, ProxiMLException, NodeError
11
7
 
12
8
 
13
9
  class Nodes(object):
@@ -37,7 +33,7 @@ class Nodes(object):
37
33
  region_uuid,
38
34
  friendly_name,
39
35
  hostname,
40
- minion_id,
36
+ minion_id=None,
41
37
  type="permanent",
42
38
  service="compute",
43
39
  **kwargs,
@@ -191,6 +187,8 @@ class Node:
191
187
  if status == "archived" and e.status == 404:
192
188
  return
193
189
  raise e
190
+ if self.status in ["errored", "failed"]:
191
+ raise NodeError(self.status, self)
194
192
  if self.status == status:
195
193
  return self
196
194
  else:
@@ -1,7 +1,16 @@
1
1
  import json
2
2
  import logging
3
+ import asyncio
4
+ import math
3
5
  from datetime import datetime
4
6
 
7
+ from proximl.exceptions import (
8
+ ApiError,
9
+ SpecificationError,
10
+ ProxiMLException,
11
+ ProviderError,
12
+ )
13
+
5
14
 
6
15
  class Providers(object):
7
16
  def __init__(self, proximl):
@@ -36,6 +45,7 @@ class Provider:
36
45
  self._provider = kwargs
37
46
  self._id = self._provider.get("provider_uuid")
38
47
  self._type = self._provider.get("type")
48
+ self._status = self._provider.get("status")
39
49
  self._credits = self._provider.get("credits")
40
50
 
41
51
  @property
@@ -46,6 +56,10 @@ class Provider:
46
56
  def type(self) -> str:
47
57
  return self._type
48
58
 
59
+ @property
60
+ def status(self) -> str:
61
+ return self._status
62
+
49
63
  @property
50
64
  def credits(self) -> float:
51
65
  return self._credits
@@ -69,3 +83,42 @@ class Provider:
69
83
  )
70
84
  self.__init__(self.proximl, **resp)
71
85
  return self
86
+
87
+ async def wait_for(self, status, timeout=300):
88
+ if self.status == status:
89
+ return
90
+ valid_statuses = ["ready", "archived"]
91
+ if not status in valid_statuses:
92
+ raise SpecificationError(
93
+ "status",
94
+ f"Invalid wait_for status {status}. Valid statuses are: {valid_statuses}",
95
+ )
96
+ MAX_TIMEOUT = 24 * 60 * 60
97
+ if timeout > MAX_TIMEOUT:
98
+ raise SpecificationError(
99
+ "timeout",
100
+ f"timeout must be less than {MAX_TIMEOUT} seconds.",
101
+ )
102
+
103
+ POLL_INTERVAL_MIN = 5
104
+ POLL_INTERVAL_MAX = 60
105
+ POLL_INTERVAL = max(min(timeout / 60, POLL_INTERVAL_MAX), POLL_INTERVAL_MIN)
106
+ retry_count = math.ceil(timeout / POLL_INTERVAL)
107
+ count = 0
108
+ while count < retry_count:
109
+ await asyncio.sleep(POLL_INTERVAL)
110
+ try:
111
+ await self.refresh()
112
+ except ApiError as e:
113
+ if status == "archived" and e.status == 404:
114
+ return
115
+ raise e
116
+ if self.status in ["errored", "failed"]:
117
+ raise ProviderError(self.status, self)
118
+ if self.status == status:
119
+ return self
120
+ else:
121
+ count += 1
122
+ logging.debug(f"self: {self}, retry count {count}")
123
+
124
+ raise ProxiMLException(f"Timeout waiting for {status}")
@@ -1,5 +1,14 @@
1
1
  import json
2
2
  import logging
3
+ import asyncio
4
+ import math
5
+
6
+ from proximl.exceptions import (
7
+ ApiError,
8
+ SpecificationError,
9
+ ProxiMLException,
10
+ RegionError,
11
+ )
3
12
 
4
13
 
5
14
  class Regions(object):
@@ -111,3 +120,42 @@ class Region:
111
120
  None,
112
121
  dict(project_uuid=project_uuid, checkpoint_uuid=checkpoint_uuid),
113
122
  )
123
+
124
+ async def wait_for(self, status, timeout=300):
125
+ if self.status == status:
126
+ return
127
+ valid_statuses = ["healthy", "offline", "archived"]
128
+ if not status in valid_statuses:
129
+ raise SpecificationError(
130
+ "status",
131
+ f"Invalid wait_for status {status}. Valid statuses are: {valid_statuses}",
132
+ )
133
+ MAX_TIMEOUT = 24 * 60 * 60
134
+ if timeout > MAX_TIMEOUT:
135
+ raise SpecificationError(
136
+ "timeout",
137
+ f"timeout must be less than {MAX_TIMEOUT} seconds.",
138
+ )
139
+
140
+ POLL_INTERVAL_MIN = 5
141
+ POLL_INTERVAL_MAX = 60
142
+ POLL_INTERVAL = max(min(timeout / 60, POLL_INTERVAL_MAX), POLL_INTERVAL_MIN)
143
+ retry_count = math.ceil(timeout / POLL_INTERVAL)
144
+ count = 0
145
+ while count < retry_count:
146
+ await asyncio.sleep(POLL_INTERVAL)
147
+ try:
148
+ await self.refresh()
149
+ except ApiError as e:
150
+ if status == "archived" and e.status == 404:
151
+ return
152
+ raise e
153
+ if self.status in ["errored", "failed"]:
154
+ raise RegionError(self.status, self)
155
+ if self.status == status:
156
+ return self
157
+ else:
158
+ count += 1
159
+ logging.debug(f"self: {self}, retry count {count}")
160
+
161
+ raise ProxiMLException(f"Timeout waiting for {status}")
@@ -147,3 +147,54 @@ class SpecificationError(ProxiMLException):
147
147
 
148
148
  def __str__(self):
149
149
  return "SpecificationError({self.attribute}, {self.message})".format(self=self)
150
+
151
+
152
+ class NodeError(ProxiMLException):
153
+ def __init__(self, status, data, *args):
154
+ super().__init__(data, *args)
155
+ self._status = status
156
+ self._message = data
157
+
158
+ @property
159
+ def status(self) -> str:
160
+ return self._status
161
+
162
+ def __repr__(self):
163
+ return "NodeError({self.status}, {self.message})".format(self=self)
164
+
165
+ def __str__(self):
166
+ return "NodeError({self.status}, {self.message})".format(self=self)
167
+
168
+
169
+ class ProviderError(ProxiMLException):
170
+ def __init__(self, status, data, *args):
171
+ super().__init__(data, *args)
172
+ self._status = status
173
+ self._message = data
174
+
175
+ @property
176
+ def status(self) -> str:
177
+ return self._status
178
+
179
+ def __repr__(self):
180
+ return "ProviderError({self.status}, {self.message})".format(self=self)
181
+
182
+ def __str__(self):
183
+ return "ProviderError({self.status}, {self.message})".format(self=self)
184
+
185
+
186
+ class RegionError(ProxiMLException):
187
+ def __init__(self, status, data, *args):
188
+ super().__init__(data, *args)
189
+ self._status = status
190
+ self._message = data
191
+
192
+ @property
193
+ def status(self) -> str:
194
+ return self._status
195
+
196
+ def __repr__(self):
197
+ return "RegionError({self.status}, {self.message})".format(self=self)
198
+
199
+ def __str__(self):
200
+ return "RegionError({self.status}, {self.message})".format(self=self)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: proximl
3
- Version: 0.5.10
3
+ Version: 0.5.11
4
4
  Summary: proxiML client SDK and command line utilities
5
5
  Home-page: https://github.com/proxiML/python-sdk
6
6
  Author: proxiML
@@ -44,8 +44,11 @@ proximl/cli/cloudbender/service.py
44
44
  proximl/cli/job/__init__.py
45
45
  proximl/cli/job/create.py
46
46
  proximl/cli/project/__init__.py
47
+ proximl/cli/project/data_connector.py
48
+ proximl/cli/project/datastore.py
47
49
  proximl/cli/project/key.py
48
50
  proximl/cli/project/secret.py
51
+ proximl/cli/project/service.py
49
52
  proximl/cloudbender/__init__.py
50
53
  proximl/cloudbender/cloudbender.py
51
54
  proximl/cloudbender/data_connectors.py
@@ -76,9 +79,12 @@ tests/integration/cloudbender/__init__.py
76
79
  tests/integration/cloudbender/test_providers_integration.py
77
80
  tests/integration/projects/__init__.py
78
81
  tests/integration/projects/conftest.py
82
+ tests/integration/projects/test_projects_data_connectors_integration.py
83
+ tests/integration/projects/test_projects_datastores_integration.py
79
84
  tests/integration/projects/test_projects_integration.py
80
85
  tests/integration/projects/test_projects_keys_integration.py
81
86
  tests/integration/projects/test_projects_secrets_integration.py
87
+ tests/integration/projects/test_projects_services_integration.py
82
88
  tests/unit/__init__.py
83
89
  tests/unit/conftest.py
84
90
  tests/unit/test_auth_unit.py
@@ -100,7 +106,6 @@ tests/unit/cli/test_cli_environment_unit.py
100
106
  tests/unit/cli/test_cli_gpu_unit.py
101
107
  tests/unit/cli/test_cli_job_unit.py
102
108
  tests/unit/cli/test_cli_model_unit.py
103
- tests/unit/cli/test_cli_project_unit.py
104
109
  tests/unit/cli/test_cli_volume_unit.py
105
110
  tests/unit/cli/cloudbender/__init__.py
106
111
  tests/unit/cli/cloudbender/test_cli_datastore_unit.py
@@ -109,6 +114,13 @@ tests/unit/cli/cloudbender/test_cli_node_unit.py
109
114
  tests/unit/cli/cloudbender/test_cli_provider_unit.py
110
115
  tests/unit/cli/cloudbender/test_cli_region_unit.py
111
116
  tests/unit/cli/cloudbender/test_cli_service_unit.py
117
+ tests/unit/cli/projects/__init__.py
118
+ tests/unit/cli/projects/test_cli_project_data_connector_unit.py
119
+ tests/unit/cli/projects/test_cli_project_datastore_unit.py
120
+ tests/unit/cli/projects/test_cli_project_key_unit.py
121
+ tests/unit/cli/projects/test_cli_project_secret_unit.py
122
+ tests/unit/cli/projects/test_cli_project_service_unit.py
123
+ tests/unit/cli/projects/test_cli_project_unit.py
112
124
  tests/unit/cloudbender/__init__.py
113
125
  tests/unit/cloudbender/test_data_connectors_unit.py
114
126
  tests/unit/cloudbender/test_datastores_unit.py
@@ -3,6 +3,8 @@ from pytest import fixture
3
3
 
4
4
  @fixture(scope="module")
5
5
  async def project(proximl):
6
- project = await proximl.projects.create(name="New Project", copy_keys=False)
6
+ project = await proximl.projects.create(
7
+ name="New Project", copy_keys=False, copy_secrets=False
8
+ )
7
9
  yield project
8
10
  await project.remove()
@@ -0,0 +1,44 @@
1
+ import re
2
+ import sys
3
+ import asyncio
4
+ from pytest import mark, fixture
5
+
6
+ pytestmark = [mark.sdk, mark.integration, mark.projects]
7
+
8
+
9
+ @mark.create
10
+ @mark.asyncio
11
+ class ProjectDataConnectorsTests:
12
+ @fixture(scope="class")
13
+ async def project_data_connector(self, project):
14
+ data_connectors = await project.data_connectors.list()
15
+ yield data_connectors[0]
16
+
17
+ async def test_list_project_data_connectors(self, project, project_data_connector):
18
+ data_connectors = await project.data_connectors.list()
19
+ assert len(data_connectors) > 0
20
+
21
+ async def test_project_data_connector_properties(
22
+ self, project, project_data_connector
23
+ ):
24
+ assert isinstance(project_data_connector.project_uuid, str)
25
+ assert isinstance(project_data_connector.type, str)
26
+ assert isinstance(project_data_connector.name, str)
27
+ assert isinstance(project_data_connector.region_uuid, str)
28
+ assert project.id == project_data_connector.project_uuid
29
+
30
+ async def test_project_data_connector_str(self, project_data_connector):
31
+ string = str(project_data_connector)
32
+ regex = r"^{.*\"name\": \"" + project_data_connector.name + r"\".*}$"
33
+ assert isinstance(string, str)
34
+ assert re.match(regex, string)
35
+
36
+ async def test_project_data_connector_repr(self, project_data_connector):
37
+ string = repr(project_data_connector)
38
+ regex = (
39
+ r"^ProjectDataConnector\( proximl , \*\*{.*'name': '"
40
+ + project_data_connector.name
41
+ + r"'.*}\)$"
42
+ )
43
+ assert isinstance(string, str)
44
+ assert re.match(regex, string)
@@ -0,0 +1,42 @@
1
+ import re
2
+ import sys
3
+ import asyncio
4
+ from pytest import mark, fixture
5
+
6
+ pytestmark = [mark.sdk, mark.integration, mark.projects]
7
+
8
+
9
+ @mark.create
10
+ @mark.asyncio
11
+ class ProjectDatastoresTests:
12
+ @fixture(scope="class")
13
+ async def project_datastore(self, project):
14
+ datastores = await project.datastores.list()
15
+ yield datastores[0]
16
+
17
+ async def test_list_project_datastores(self, project):
18
+ datastores = await project.datastores.list()
19
+ assert len(datastores) > 0
20
+
21
+ async def test_project_datastore_properties(self, project, project_datastore):
22
+ assert isinstance(project_datastore.project_uuid, str)
23
+ assert isinstance(project_datastore.type, str)
24
+ assert isinstance(project_datastore.name, str)
25
+ assert isinstance(project_datastore.region_uuid, str)
26
+ assert project.id == project_datastore.project_uuid
27
+
28
+ async def test_project_datastore_str(self, project_datastore):
29
+ string = str(project_datastore)
30
+ regex = r"^{.*\"name\": \"" + project_datastore.name + r"\".*}$"
31
+ assert isinstance(string, str)
32
+ assert re.match(regex, string)
33
+
34
+ async def test_project_datastore_repr(self, project_datastore):
35
+ string = repr(project_datastore)
36
+ regex = (
37
+ r"^ProjectDatastore\( proximl , \*\*{.*'name': '"
38
+ + project_datastore.name
39
+ + r"'.*}\)$"
40
+ )
41
+ assert isinstance(string, str)
42
+ assert re.match(regex, string)