proximl 0.5.14__py3-none-any.whl → 0.5.15__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 (27) hide show
  1. proximl/__init__.py +1 -1
  2. proximl/cloudbender/services.py +19 -1
  3. proximl/projects/services.py +17 -0
  4. {proximl-0.5.14.dist-info → proximl-0.5.15.dist-info}/METADATA +1 -1
  5. {proximl-0.5.14.dist-info → proximl-0.5.15.dist-info}/RECORD +27 -24
  6. tests/integration/cloudbender/conftest.py +28 -0
  7. tests/integration/cloudbender/test_providers_integration.py +3 -8
  8. tests/integration/cloudbender/test_regions_integration.py +42 -0
  9. tests/integration/cloudbender/test_services_integration.py +87 -0
  10. tests/integration/conftest.py +1 -1
  11. tests/integration/projects/conftest.py +2 -1
  12. tests/integration/projects/test_projects_credentials_integration.py +1 -0
  13. tests/integration/projects/test_projects_data_connectors_integration.py +1 -0
  14. tests/integration/projects/test_projects_datastores_integration.py +1 -0
  15. tests/integration/projects/test_projects_integration.py +1 -0
  16. tests/integration/projects/test_projects_members_integration.py +1 -0
  17. tests/integration/projects/test_projects_secrets_integration.py +1 -0
  18. tests/integration/projects/test_projects_services_integration.py +1 -0
  19. tests/integration/test_checkpoints_integration.py +1 -0
  20. tests/integration/test_datasets_integration.py +1 -0
  21. tests/integration/test_jobs_integration.py +5 -0
  22. tests/integration/test_models_integration.py +1 -0
  23. tests/integration/test_volumes_integration.py +1 -0
  24. {proximl-0.5.14.dist-info → proximl-0.5.15.dist-info}/LICENSE +0 -0
  25. {proximl-0.5.14.dist-info → proximl-0.5.15.dist-info}/WHEEL +0 -0
  26. {proximl-0.5.14.dist-info → proximl-0.5.15.dist-info}/entry_points.txt +0 -0
  27. {proximl-0.5.14.dist-info → proximl-0.5.15.dist-info}/top_level.txt +0 -0
proximl/__init__.py CHANGED
@@ -13,5 +13,5 @@ logging.basicConfig(
13
13
  logger = logging.getLogger(__name__)
14
14
 
15
15
 
16
- __version__ = "0.5.14"
16
+ __version__ = "0.5.15"
17
17
  __all__ = "ProxiML"
@@ -67,7 +67,7 @@ class Services(object):
67
67
 
68
68
 
69
69
  class Service:
70
- def __init__(self, proximl, **kwargs):
70
+ def __init__(self, proximl, **kwargs):
71
71
  self.proximl = proximl
72
72
  self._service = kwargs
73
73
  self._id = self._service.get("service_id")
@@ -177,3 +177,21 @@ class Service:
177
177
  logging.debug(f"self: {self}, retry count {count}")
178
178
 
179
179
  raise ProxiMLException(f"Timeout waiting for {status}")
180
+
181
+ async def generate_certificate(self, **kwargs):
182
+ resp = await self.proximl._query(
183
+ f"/provider/{self._provider_uuid}/region/{self._region_uuid}/service/{self._id}/certificate",
184
+ "POST",
185
+ kwargs
186
+ )
187
+ self.__init__(self.proximl, **resp)
188
+ return self
189
+
190
+ async def sign_client_certificate(self, csr, **kwargs):
191
+ certificate = await self.proximl._query(
192
+ f"/provider/{self._provider_uuid}/region/{self._region_uuid}/service/{self._id}/certificate/sign",
193
+ "POST",
194
+ kwargs,
195
+ dict(csr=csr)
196
+ )
197
+ return certificate
@@ -77,3 +77,20 @@ class ProjectService:
77
77
  await self.proximl._query(
78
78
  f"/project/{self._project_uuid}/services/{self._id}/disable", "PATCH"
79
79
  )
80
+
81
+ async def get_service_ca_certificate(self, **kwargs):
82
+ certificate = await self.proximl._query(
83
+ f"/project/{self._project_uuid}/services/{self._id}/certificate/ca",
84
+ "GET",
85
+ kwargs,
86
+ )
87
+ return certificate
88
+
89
+ async def sign_client_certificate(self, csr, **kwargs):
90
+ certificate = await self.proximl._query(
91
+ f"/project/{self._project_uuid}/services/{self._id}/certificate/sign",
92
+ "POST",
93
+ kwargs,
94
+ dict(csr=csr)
95
+ )
96
+ return certificate
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: proximl
3
- Version: 0.5.14
3
+ Version: 0.5.15
4
4
  Summary: proxiML client SDK and command line utilities
5
5
  Home-page: https://github.com/proxiML/python-sdk
6
6
  Author: proxiML
@@ -2,7 +2,7 @@ examples/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  examples/create_dataset_and_training_job.py,sha256=Fqueoz2KD1MTxnU960iqHUdxvo68Xe64HT5XS55lI9w,1178
3
3
  examples/local_storage.py,sha256=6K6LMO7ZPI7N2KdBcgqXSvdsqJfjISzN4yRO9YrJqbA,1745
4
4
  examples/training_inference_pipeline.py,sha256=pxux0QUUtRXxKj2rX-6fPEKBIi43mhRd1zJ-Lf1ZJGI,2334
5
- proximl/__init__.py,sha256=iO6-pU6BIwDgKVSlSYqbBe88EBQnbAkS6-sVe7xBBJA,433
5
+ proximl/__init__.py,sha256=cS84qd0OsBVm8H9pmmykeIzYpGPYj5wbaGNpQezWMdI,433
6
6
  proximl/__main__.py,sha256=JgErYkiskih8Y6oRwowALtR-rwQhAAdqOYWjQraRIPI,59
7
7
  proximl/auth.py,sha256=LacGBDAVel5HcJx7JXp1wVn3s0gZc7nf--vDfSFOXYU,26565
8
8
  proximl/checkpoints.py,sha256=Ezpiab9Wfcmd2h5Slm9U5lekZGXiPzvhDKxXXgla1yo,8790
@@ -48,7 +48,7 @@ proximl/cloudbender/devices.py,sha256=vHooaOw2k2Tf99FJHnVZTgggqCTYJg7rq46aUPW0k8
48
48
  proximl/cloudbender/nodes.py,sha256=T7aCh2O6sF2tFX4D5a7wDW8hJmEgHoCV9So1kg70tdg,5924
49
49
  proximl/cloudbender/providers.py,sha256=KLO4Pc8yeW8TpSDICgTw3NxN44_0s4HptVsR2hHc28w,3738
50
50
  proximl/cloudbender/regions.py,sha256=6doBdfMXIQI-uexzvwmNg2ATDzruatw-ixviZSMjonU,5157
51
- proximl/cloudbender/services.py,sha256=km3KcIgaRRVb3iuZEIn6ONIekuyXhBgk_brAFJcMMl4,5126
51
+ proximl/cloudbender/services.py,sha256=FOhtRozqNroO9Ru6gtsKgjumGREiLCooXMXchDh5cNM,5773
52
52
  proximl/projects/__init__.py,sha256=6NKCcHtQMeGB1IyU-djANphfnDX6MEkrXUM5Fyq9fWg,75
53
53
  proximl/projects/credentials.py,sha256=hWz6EUEAgltkAQMDjQVsFlVvfWUbZfY3KoWpldnCrXY,2255
54
54
  proximl/projects/data_connectors.py,sha256=o2-K40BdF85TBXJgj1UMsznBmNHmnYh1qbZtHmmOa2Y,2216
@@ -56,27 +56,30 @@ proximl/projects/datastores.py,sha256=8nHpMEHn3UzsIhmPMoXympbRRJ10XkHdyRhBXUVXye
56
56
  proximl/projects/members.py,sha256=siREAa-Oac1pLGRHMXmj3ShoB0DVl8uY34eFdTlSezA,2826
57
57
  proximl/projects/projects.py,sha256=PJYUaXbYMINcvlDQePKUSAz6uO11jg9tj5gJW-cNjGQ,2890
58
58
  proximl/projects/secrets.py,sha256=xlfzRONjT2ySJDcq8FYRQmSU2ZJMdPLS8NbePWYNCeM,2160
59
- proximl/projects/services.py,sha256=C1YUxixkio8n4AlgmGqZJ93hP3VKOoTXVXTNCkRVd9Y,2206
59
+ proximl/projects/services.py,sha256=aCESZjqfI9K-iXl8uJQsjEyoX29LuPaNv_TFjK6B2Ts,2771
60
60
  tests/integration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
61
- tests/integration/conftest.py,sha256=zRWpherX-yfbpk7xqZk9bIZCyJ-dwVeszY_7kekn2M4,1134
62
- tests/integration/test_checkpoints_integration.py,sha256=m-m6KM5Iy99bbCyA6VQVBFWc9MI7VItuoAPb_Q6Q0Fk,3206
63
- tests/integration/test_datasets_integration.py,sha256=Ndp8itnncDSjVH0t5BM5R_-_yL4qt6JrkQAVOTMi1R8,3499
61
+ tests/integration/conftest.py,sha256=rqOKgDZ37SZH6CxXZIQSHtx8SF5GC1MlC49Zb5xrzsk,1135
62
+ tests/integration/test_checkpoints_integration.py,sha256=2gKhbax96ePIEZqcM4IeqSB0fTOYPh9nexNJtC96LuU,3239
63
+ tests/integration/test_datasets_integration.py,sha256=y8NL7fKQvZhJs1r9UAcLjXI0832tHr9XfIaRhHX9aOk,3529
64
64
  tests/integration/test_environments_integration.py,sha256=7P6pKSyxA7rTwyNCD9HEaM2ablMG8WcBesOzkG-BgsQ,1403
65
65
  tests/integration/test_gpu_types_integration.py,sha256=Zv-yrHcAgKau9BJQvzi92bdrRHhLPl_hbhhzNLEWJ9w,1256
66
- tests/integration/test_jobs_integration.py,sha256=TAezhtUhe-Prigo6mwnNOivycbnPGBhAXZslvujMRI4,25100
67
- tests/integration/test_models_integration.py,sha256=cnsao7Zo4PwVCbdAdcBs0xombAslI_X_JOw6ipxdzOA,2878
68
- tests/integration/test_volumes_integration.py,sha256=Xo2Whw2U-7jyvESIkyex3f0SMXKlExe3kLmsbpXTHhQ,3270
66
+ tests/integration/test_jobs_integration.py,sha256=mSgPERDycfphLuLd7Hp3tSo-SpnbACp963x99K3XbtU,25263
67
+ tests/integration/test_models_integration.py,sha256=du9i3GsWjwEWei_-5BzfoBneBNcZ-9NQsDdOfn4dzd8,2906
68
+ tests/integration/test_volumes_integration.py,sha256=fTsP5_wyspzR_DX_ArXz5Fflq2dEmXtJbhwqCjSQDOA,3299
69
69
  tests/integration/cloudbender/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
70
- tests/integration/cloudbender/test_providers_integration.py,sha256=gFqPQom-Cn1iZC50_ChQ2us2_f4tIPATQSAUcWdf7ss,1473
70
+ tests/integration/cloudbender/conftest.py,sha256=K1EQC7U7aBnywJq-QvBZINqHtQm7kq5feDWVKAtp22E,777
71
+ tests/integration/cloudbender/test_providers_integration.py,sha256=8_1TBxcIpQcET7VStHIsi_-_3j5hs8H-icsKN3qnNa8,1327
72
+ tests/integration/cloudbender/test_regions_integration.py,sha256=9Cj2s2cX07iUnhYvFyrNxLxYHCPVjAA9Gfes7Xf7OV0,1406
73
+ tests/integration/cloudbender/test_services_integration.py,sha256=ziw3K-48Yl2Rzy-rCNw9QZ5m3TtfmQecdgdTpzSuUVA,3367
71
74
  tests/integration/projects/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
72
- tests/integration/projects/conftest.py,sha256=4WbknSwdJgzPAr5qumCJD3Cl1rQFWgGZ5-Wro1ka0xA,249
73
- tests/integration/projects/test_projects_credentials_integration.py,sha256=_JqE2sGN09gZpvhtMRFjBPXumJ-PqKl8iXOgcYHlvSY,1636
74
- tests/integration/projects/test_projects_data_connectors_integration.py,sha256=ag6w2FFQYNlAdV83rOqat0FVZnP4JFhDunCvRwMJdzo,1630
75
- tests/integration/projects/test_projects_datastores_integration.py,sha256=DCHFnCYguhtrZvfTeWgKpPxlkeAXxVfE3IWkM4KjgAc,1469
76
- tests/integration/projects/test_projects_integration.py,sha256=wlRLxZkMnJZHlNPaeRFjAeyUlMfbgdrrFEI2eMBcoUI,1241
77
- tests/integration/projects/test_projects_members_integration.py,sha256=3URbefe0DD0rMjwcWpBV521Yt9k9tLVL3nn6mNRPp4g,1843
78
- tests/integration/projects/test_projects_secrets_integration.py,sha256=wRkcVkaf-zLWvCdJx9ikJYAoiJXU1esv0diRxwwRFdc,1481
79
- tests/integration/projects/test_projects_services_integration.py,sha256=MV9tZFTgrUtzImNrc-ZAoHYLbf_ZxAAAeVpxxr5AGdg,1530
75
+ tests/integration/projects/conftest.py,sha256=C_UumszWK-Es39ULv-Lz4TvbMdXXKQvZV6OwFSX8Mn0,294
76
+ tests/integration/projects/test_projects_credentials_integration.py,sha256=-OXDLaaWm_W0-AHDEHbMATjPGkyoAd_Vf3UsVJBg0_A,1675
77
+ tests/integration/projects/test_projects_data_connectors_integration.py,sha256=UBeqWbGoVZCH4BIVm4t9_L4mwzbN7oqncZyxcuwEnZQ,1669
78
+ tests/integration/projects/test_projects_datastores_integration.py,sha256=M-Hv3bSgG6FZap-WFA2DavqUaNJ4K9W4Du5214dURjQ,1508
79
+ tests/integration/projects/test_projects_integration.py,sha256=s5_M04wIKh4VHEdcc6FImUz5KhTS0-Wgxd6CMvWNmy8,1280
80
+ tests/integration/projects/test_projects_members_integration.py,sha256=4i4SeDCDZwmG82tjQEDyyFU-U52aBE5TeSXIP3RW8sA,1882
81
+ tests/integration/projects/test_projects_secrets_integration.py,sha256=TyqItJs-SBzOUwDy3vs_-yrDXeDF8r1_bAovr8C1a_s,1520
82
+ tests/integration/projects/test_projects_services_integration.py,sha256=cHOGSUpl3rqYJnCrbYp-2Zmn1ngFJTDV9Io7K8fDOp0,1569
80
83
  tests/unit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
81
84
  tests/unit/conftest.py,sha256=11Z49O4mKXtm6xl18kWPomZvbZJQpqdaDYeJHFQbO1A,35588
82
85
  tests/unit/test_auth_unit.py,sha256=IJZHT5CZLNfu3MybTdEWIsKlvxNfFYpZ6oWYzbS856g,858
@@ -130,9 +133,9 @@ tests/unit/projects/test_project_members_unit.py,sha256=dtbRfP454mviQYn6Dc0Uzyb3
130
133
  tests/unit/projects/test_project_secrets_unit.py,sha256=VE9L91FJodcwVGizfF65WYMiHZaF0s2AdW1aiJ3z7xA,3276
131
134
  tests/unit/projects/test_project_services_unit.py,sha256=PzeNuJRuAG7RkrPWX0FfgFTt6-63FviecrDY06rLQ6A,3331
132
135
  tests/unit/projects/test_projects_unit.py,sha256=4vMo7TF-SjduoT2ejpuyM3dULslpdqE8-c25M9X-iYc,3810
133
- proximl-0.5.14.dist-info/LICENSE,sha256=ADFxLEZDxKY0j4MdyUd5GNuhQ18rnWH5rOz1ZG7yiOA,1069
134
- proximl-0.5.14.dist-info/METADATA,sha256=gGFu62XfxbC3WtzrYBSfHygX-5l2n2Gg3jz39NCy9ck,7345
135
- proximl-0.5.14.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
136
- proximl-0.5.14.dist-info/entry_points.txt,sha256=HmI311IIabkZReMCXu-nGbvIEW-KfaduAOyfiSqt5SY,63
137
- proximl-0.5.14.dist-info/top_level.txt,sha256=-TWqc9tAaxmWmW4c7uYsmzPEYUIoh6z02xxqPbv7Kys,23
138
- proximl-0.5.14.dist-info/RECORD,,
136
+ proximl-0.5.15.dist-info/LICENSE,sha256=ADFxLEZDxKY0j4MdyUd5GNuhQ18rnWH5rOz1ZG7yiOA,1069
137
+ proximl-0.5.15.dist-info/METADATA,sha256=9lwoFniw9bBF974xxoeOv2j89XLjBGienszKZwhh-9c,7345
138
+ proximl-0.5.15.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
139
+ proximl-0.5.15.dist-info/entry_points.txt,sha256=HmI311IIabkZReMCXu-nGbvIEW-KfaduAOyfiSqt5SY,63
140
+ proximl-0.5.15.dist-info/top_level.txt,sha256=-TWqc9tAaxmWmW4c7uYsmzPEYUIoh6z02xxqPbv7Kys,23
141
+ proximl-0.5.15.dist-info/RECORD,,
@@ -0,0 +1,28 @@
1
+
2
+ from pytest import fixture, mark
3
+
4
+
5
+ pytestmark = [mark.integration,mark.cloudbender]
6
+
7
+ @fixture(scope="session")
8
+ @mark.create
9
+ @mark.asyncio
10
+ @mark.xdist_group("cloudbender_resources")
11
+ async def provider( proximl):
12
+ provider = await proximl.cloudbender.providers.enable(type="test")
13
+ await provider.wait_for("ready")
14
+ yield provider
15
+ await provider.remove()
16
+
17
+ @fixture(scope="session")
18
+ @mark.create
19
+ @mark.asyncio
20
+ @mark.xdist_group("cloudbender_resources")
21
+ async def region(proximl, provider):
22
+ region = await proximl.cloudbender.regions.create(provider_uuid=provider.id,name="test-region",
23
+ public=False,
24
+ storage=dict(mode="local"),)
25
+ await region.wait_for("healthy")
26
+ yield region
27
+ await region.remove()
28
+ await region.wait_for("archived")
@@ -8,14 +8,9 @@ pytestmark = [mark.sdk, mark.integration, mark.cloudbender, mark.providers]
8
8
 
9
9
  @mark.create
10
10
  @mark.asyncio
11
- class GetProvidersTests:
12
- @fixture(scope="class")
13
- async def provider(self, proximl):
14
- provider = await proximl.cloudbender.providers.enable(type="test")
15
- yield provider
16
- await provider.remove()
17
-
18
- async def test_get_providers(self, proximl):
11
+ @mark.xdist_group("cloudbender_resources")
12
+ class GetProviderTests:
13
+ async def test_get_providers(self, proximl, provider):
19
14
  providers = await proximl.cloudbender.providers.list()
20
15
  assert len(providers) > 0
21
16
 
@@ -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.cloudbender, mark.regions]
7
+
8
+
9
+ @mark.create
10
+ @mark.asyncio
11
+ @mark.xdist_group("cloudbender_resources")
12
+ class GetRegionTests:
13
+ async def test_get_regions(self, proximl, provider, region):
14
+ regions = await proximl.cloudbender.regions.list(provider_uuid=provider.id)
15
+ assert len(regions) > 0
16
+
17
+ async def test_get_region(self, proximl, provider, region):
18
+ response = await proximl.cloudbender.regions.get(provider.id, region.id)
19
+ assert response.id == region.id
20
+
21
+ async def test_region_properties(self, provider, region):
22
+ assert isinstance(region.id, str)
23
+ assert isinstance(region.provider_uuid, str)
24
+ assert isinstance(region.type, str)
25
+ assert region.type == "test"
26
+ assert region.provider_uuid == provider.id
27
+
28
+ async def test_region_str(self, region):
29
+ string = str(region)
30
+ regex = r"^{.*\"region_uuid\": \"" + region.id + r"\".*}$"
31
+ assert isinstance(string, str)
32
+ assert re.match(regex, string)
33
+
34
+ async def test_region_repr(self, region):
35
+ string = repr(region)
36
+ regex = (
37
+ r"^Region\( proximl , \*\*{.*'region_uuid': '"
38
+ + region.id
39
+ + r"'.*}\)$"
40
+ )
41
+ assert isinstance(string, str)
42
+ assert re.match(regex, string)
@@ -0,0 +1,87 @@
1
+ import re
2
+ import sys
3
+ import asyncio
4
+ from pytest import mark, fixture
5
+ from cryptography import x509
6
+ from cryptography.x509.oid import NameOID, ExtendedKeyUsageOID
7
+ from cryptography.hazmat.primitives.asymmetric import rsa
8
+ from cryptography.hazmat.primitives import serialization, hashes
9
+
10
+ pytestmark = [mark.sdk, mark.integration, mark.cloudbender, mark.regions]
11
+
12
+ def get_csr(service_id):
13
+ private_key = rsa.generate_private_key(
14
+ public_exponent=65537,
15
+ key_size=4096
16
+ )
17
+ csr = x509.CertificateSigningRequestBuilder().subject_name(x509.Name([
18
+ x509.NameAttribute(NameOID.COUNTRY_NAME, "US"),
19
+ x509.NameAttribute(NameOID.ORGANIZATION_NAME, "proxiML"),
20
+ x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, service_id),
21
+ x509.NameAttribute(NameOID.COMMON_NAME, "test-client"), # Client identity
22
+ ])).add_extension(
23
+ x509.ExtendedKeyUsage([
24
+ ExtendedKeyUsageOID.CLIENT_AUTH # Client authentication usage
25
+ ]),
26
+ critical=True
27
+ ).sign(private_key, hashes.SHA256())
28
+ return csr.public_bytes(serialization.Encoding.PEM).decode("utf-8")
29
+
30
+ @mark.create
31
+ @mark.asyncio
32
+ @mark.xdist_group("cloudbender_resources")
33
+ class GetServiceTests:
34
+ @fixture(scope="class")
35
+ async def service(self, proximl, region):
36
+ service = await proximl.cloudbender.services.create(
37
+ provider_uuid=region.provider_uuid,
38
+ region_uuid=region.id,
39
+ name="CLI Automated Service",
40
+ type="tcp",
41
+ port="8989",
42
+ public=False,
43
+ )
44
+ await service.wait_for("active")
45
+ yield service
46
+ await service.remove()
47
+ await service.wait_for("archived")
48
+
49
+ async def test_get_services(self, proximl, region,service):
50
+ services = await proximl.cloudbender.services.list(provider_uuid=region.provider_uuid, region_uuid=region.id)
51
+ assert len(services) > 0
52
+
53
+ async def test_get_service(self, proximl, provider, region, service):
54
+ response = await proximl.cloudbender.services.get(provider.id, region.id, service.id)
55
+ assert response.id == service.id
56
+
57
+ async def test_service_properties(self, region, service):
58
+ assert isinstance(service.id, str)
59
+ assert isinstance(service.provider_uuid, str)
60
+ assert isinstance(service.region_uuid, str)
61
+ assert isinstance(service.public, bool)
62
+ assert service.port == "8989"
63
+ assert service.provider_uuid == region.provider_uuid
64
+ assert service.region_uuid == region.id
65
+
66
+ async def test_service_str(self, service):
67
+ string = str(service)
68
+ regex = r"^{.*\"service_id\": \"" + service.id + r"\".*}$"
69
+ assert isinstance(string, str)
70
+ assert re.match(regex, string)
71
+
72
+ async def test_service_repr(self, service):
73
+ string = repr(service)
74
+ regex = (
75
+ r"^Service\( proximl , \*\*{.*'service_id': '"
76
+ + service.id
77
+ + r"'.*}\)$"
78
+ )
79
+ assert isinstance(string, str)
80
+ assert re.match(regex, string)
81
+
82
+ async def test_service_certificate(self, service):
83
+ service = await service.generate_certificate()
84
+ assert isinstance(service._service.get("auth_cert"), str)
85
+ csr = get_csr(service.id)
86
+ certificate = await service.sign_client_certificate(csr)
87
+ assert isinstance(certificate, str)
@@ -40,7 +40,7 @@ def env(request):
40
40
  yield ENVS[env]
41
41
 
42
42
 
43
- @fixture(scope="module")
43
+ @fixture(scope="session")
44
44
  def proximl(env):
45
45
  proximl = ProxiML(**env)
46
46
  yield proximl
@@ -1,7 +1,8 @@
1
- from pytest import fixture
1
+ from pytest import fixture, mark
2
2
 
3
3
 
4
4
  @fixture(scope="module")
5
+ @mark.xdist_group("project_resources")
5
6
  async def project(proximl):
6
7
  project = await proximl.projects.create(
7
8
  name="New Project", copy_credentials=False, copy_secrets=False
@@ -8,6 +8,7 @@ pytestmark = [mark.sdk, mark.integration, mark.projects]
8
8
 
9
9
  @mark.create
10
10
  @mark.asyncio
11
+ @mark.xdist_group("project_resources")
11
12
  class ProjectCredentialsTests:
12
13
  @fixture(scope="class")
13
14
  async def project_credential(self, project):
@@ -8,6 +8,7 @@ pytestmark = [mark.sdk, mark.integration, mark.projects]
8
8
 
9
9
  @mark.create
10
10
  @mark.asyncio
11
+ @mark.xdist_group("project_resources")
11
12
  class ProjectDataConnectorsTests:
12
13
  @fixture(scope="class")
13
14
  async def project_data_connector(self, project):
@@ -8,6 +8,7 @@ pytestmark = [mark.sdk, mark.integration, mark.projects]
8
8
 
9
9
  @mark.create
10
10
  @mark.asyncio
11
+ @mark.xdist_group("project_resources")
11
12
  class ProjectDatastoresTests:
12
13
  @fixture(scope="class")
13
14
  async def project_datastore(self, project):
@@ -8,6 +8,7 @@ pytestmark = [mark.sdk, mark.integration, mark.projects]
8
8
 
9
9
  @mark.create
10
10
  @mark.asyncio
11
+ @mark.xdist_group("project_resources")
11
12
  class GetProjectsTests:
12
13
  async def test_get_projects(self, proximl):
13
14
  projects = await proximl.projects.list()
@@ -8,6 +8,7 @@ pytestmark = [mark.sdk, mark.integration, mark.projects]
8
8
 
9
9
  @mark.create
10
10
  @mark.asyncio
11
+ @mark.xdist_group("project_resources")
11
12
  class ProjectMembersTests:
12
13
  @fixture(scope="class")
13
14
  async def project_member(self, project):
@@ -8,6 +8,7 @@ pytestmark = [mark.sdk, mark.integration, mark.projects]
8
8
 
9
9
  @mark.create
10
10
  @mark.asyncio
11
+ @mark.xdist_group("project_resources")
11
12
  class ProjectSecretsTests:
12
13
  @fixture(scope="class")
13
14
  async def project_secret(self, project):
@@ -8,6 +8,7 @@ pytestmark = [mark.sdk, mark.integration, mark.projects]
8
8
 
9
9
  @mark.create
10
10
  @mark.asyncio
11
+ @mark.xdist_group("project_resources")
11
12
  class ProjectServicesTests:
12
13
  @fixture(scope="class")
13
14
  async def project_service(self, project):
@@ -8,6 +8,7 @@ pytestmark = [mark.sdk, mark.integration, mark.checkpoints]
8
8
 
9
9
  @mark.create
10
10
  @mark.asyncio
11
+ @mark.xdist_group("checkpoints")
11
12
  class GetCheckpointTests:
12
13
  @fixture(scope="class")
13
14
  async def checkpoint(self, proximl):
@@ -8,6 +8,7 @@ pytestmark = [mark.sdk, mark.integration, mark.datasets]
8
8
 
9
9
  @mark.create
10
10
  @mark.asyncio
11
+ @mark.xdist_group("datasets")
11
12
  class GetDatasetTests:
12
13
  @fixture(scope="class")
13
14
  async def dataset(self, proximl):
@@ -20,6 +20,7 @@ def extract_domain_suffix(hostname):
20
20
 
21
21
 
22
22
  @fixture(scope="class")
23
+ @mark.xdist_group("job_lifecycle")
23
24
  async def job(proximl):
24
25
  job = await proximl.jobs.create(
25
26
  name="CLI Automated Tests - Job Lifecycle",
@@ -38,6 +39,7 @@ async def job(proximl):
38
39
 
39
40
  @mark.create
40
41
  @mark.asyncio
42
+ @mark.xdist_group("job_lifecycle")
41
43
  class JobLifeCycleTests:
42
44
  async def test_wait_for_running(self, job):
43
45
  assert job.status != "running"
@@ -413,6 +415,7 @@ class JobAPIWorkerValidationTests:
413
415
 
414
416
  @mark.create
415
417
  @mark.asyncio
418
+ @mark.xdist_group("job_io")
416
419
  class JobIOTests:
417
420
  async def test_job_local_output(self, proximl, capsys):
418
421
  temp_dir = tempfile.TemporaryDirectory()
@@ -527,6 +530,7 @@ class JobIOTests:
527
530
 
528
531
  @mark.create
529
532
  @mark.asyncio
533
+ @mark.xdist_group("job_types")
530
534
  class JobTypeTests:
531
535
  async def test_endpoint(self, proximl):
532
536
 
@@ -648,6 +652,7 @@ class JobTypeTests:
648
652
 
649
653
  @mark.create
650
654
  @mark.asyncio
655
+ @mark.xdist_group("job_features")
651
656
  class JobFeatureTests:
652
657
  async def test_cpu_instance(self, proximl, capsys):
653
658
  job = await proximl.jobs.create(
@@ -8,6 +8,7 @@ pytestmark = [mark.sdk, mark.integration, mark.models]
8
8
 
9
9
  @mark.create
10
10
  @mark.asyncio
11
+ @mark.xdist_group("models")
11
12
  class GetModelTests:
12
13
  @fixture(scope="class")
13
14
  async def model(self, proximl):
@@ -8,6 +8,7 @@ pytestmark = [mark.sdk, mark.integration, mark.volumes]
8
8
 
9
9
  @mark.create
10
10
  @mark.asyncio
11
+ @mark.xdist_group("volumes")
11
12
  class GetVolumeTests:
12
13
  @fixture(scope="class")
13
14
  async def volume(self, proximl):