proximl 0.5.13__py3-none-any.whl → 0.5.13.post1__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.
- proximl/__init__.py +1 -1
- proximl/cli/job/create.py +16 -16
- proximl/cli/project/__init__.py +1 -1
- proximl/cli/project/secret.py +12 -3
- proximl/projects/data_connectors.py +16 -0
- proximl/projects/datastores.py +16 -0
- proximl/projects/projects.py +7 -4
- proximl/projects/secrets.py +1 -1
- proximl/projects/services.py +16 -0
- {proximl-0.5.13.dist-info → proximl-0.5.13.post1.dist-info}/METADATA +1 -1
- {proximl-0.5.13.dist-info → proximl-0.5.13.post1.dist-info}/RECORD +20 -25
- tests/integration/projects/conftest.py +1 -1
- tests/integration/projects/test_projects_secrets_integration.py +1 -1
- tests/integration/test_jobs_integration.py +1 -1
- tests/unit/conftest.py +9 -9
- tests/unit/projects/test_projects_unit.py +1 -1
- proximl/cli/project/key.py +0 -124
- proximl/projects/keys.py +0 -71
- tests/integration/projects/test_projects_keys_integration.py +0 -43
- tests/unit/cli/projects/test_cli_project_key_unit.py +0 -26
- tests/unit/projects/test_project_keys_unit.py +0 -96
- {proximl-0.5.13.dist-info → proximl-0.5.13.post1.dist-info}/LICENSE +0 -0
- {proximl-0.5.13.dist-info → proximl-0.5.13.post1.dist-info}/WHEEL +0 -0
- {proximl-0.5.13.dist-info → proximl-0.5.13.post1.dist-info}/entry_points.txt +0 -0
- {proximl-0.5.13.dist-info → proximl-0.5.13.post1.dist-info}/top_level.txt +0 -0
proximl/__init__.py
CHANGED
proximl/cli/job/create.py
CHANGED
|
@@ -172,12 +172,12 @@ def create(config):
|
|
|
172
172
|
help="Conda packages to install as a comma separated list 'p1,\"p2=v2\",p3'",
|
|
173
173
|
)
|
|
174
174
|
@click.option(
|
|
175
|
-
"--
|
|
175
|
+
"--credential",
|
|
176
176
|
type=click.Choice(
|
|
177
177
|
["aws", "gcp", "kaggle", "azure", "wasabi"],
|
|
178
178
|
case_sensitive=False,
|
|
179
179
|
),
|
|
180
|
-
help="Third Party
|
|
180
|
+
help="Third Party Credentials to add to the job environment",
|
|
181
181
|
multiple=True,
|
|
182
182
|
)
|
|
183
183
|
@click.option(
|
|
@@ -221,7 +221,7 @@ def notebook(
|
|
|
221
221
|
environment,
|
|
222
222
|
custom_image,
|
|
223
223
|
env,
|
|
224
|
-
|
|
224
|
+
credential,
|
|
225
225
|
apt_packages,
|
|
226
226
|
pip_packages,
|
|
227
227
|
conda_packages,
|
|
@@ -254,7 +254,7 @@ def notebook(
|
|
|
254
254
|
data=dict(datasets=datasets),
|
|
255
255
|
model=dict(checkpoints=checkpoints),
|
|
256
256
|
environment=dict(
|
|
257
|
-
|
|
257
|
+
credentials=[k for k in credential],
|
|
258
258
|
),
|
|
259
259
|
)
|
|
260
260
|
|
|
@@ -500,12 +500,12 @@ def notebook(
|
|
|
500
500
|
multiple=True,
|
|
501
501
|
)
|
|
502
502
|
@click.option(
|
|
503
|
-
"--
|
|
503
|
+
"--credential",
|
|
504
504
|
type=click.Choice(
|
|
505
505
|
["aws", "gcp", "kaggle", "azure", "wasabi"],
|
|
506
506
|
case_sensitive=False,
|
|
507
507
|
),
|
|
508
|
-
help="Third Party
|
|
508
|
+
help="Third Party Credentials to add to the job environment",
|
|
509
509
|
multiple=True,
|
|
510
510
|
)
|
|
511
511
|
@click.option(
|
|
@@ -563,7 +563,7 @@ def training(
|
|
|
563
563
|
environment,
|
|
564
564
|
custom_image,
|
|
565
565
|
env,
|
|
566
|
-
|
|
566
|
+
credential,
|
|
567
567
|
apt_packages,
|
|
568
568
|
pip_packages,
|
|
569
569
|
conda_packages,
|
|
@@ -596,7 +596,7 @@ def training(
|
|
|
596
596
|
data=dict(datasets=datasets),
|
|
597
597
|
model=dict(checkpoints=checkpoints),
|
|
598
598
|
environment=dict(
|
|
599
|
-
|
|
599
|
+
credentials=[k for k in credential],
|
|
600
600
|
),
|
|
601
601
|
)
|
|
602
602
|
|
|
@@ -844,12 +844,12 @@ def training(
|
|
|
844
844
|
multiple=True,
|
|
845
845
|
)
|
|
846
846
|
@click.option(
|
|
847
|
-
"--
|
|
847
|
+
"--credential",
|
|
848
848
|
type=click.Choice(
|
|
849
849
|
["aws", "gcp", "kaggle", "azure", "wasabi"],
|
|
850
850
|
case_sensitive=False,
|
|
851
851
|
),
|
|
852
|
-
help="Third Party
|
|
852
|
+
help="Third Party Credentials to add to the job environment",
|
|
853
853
|
multiple=True,
|
|
854
854
|
)
|
|
855
855
|
@click.option(
|
|
@@ -907,7 +907,7 @@ def inference(
|
|
|
907
907
|
environment,
|
|
908
908
|
custom_image,
|
|
909
909
|
env,
|
|
910
|
-
|
|
910
|
+
credential,
|
|
911
911
|
apt_packages,
|
|
912
912
|
pip_packages,
|
|
913
913
|
conda_packages,
|
|
@@ -933,7 +933,7 @@ def inference(
|
|
|
933
933
|
data=dict(datasets=[]),
|
|
934
934
|
model=dict(checkpoints=checkpoints),
|
|
935
935
|
environment=dict(
|
|
936
|
-
|
|
936
|
+
credentials=[k for k in credential],
|
|
937
937
|
),
|
|
938
938
|
)
|
|
939
939
|
|
|
@@ -1163,12 +1163,12 @@ def from_json(config, attach, connect, file):
|
|
|
1163
1163
|
multiple=True,
|
|
1164
1164
|
)
|
|
1165
1165
|
@click.option(
|
|
1166
|
-
"--
|
|
1166
|
+
"--credential",
|
|
1167
1167
|
type=click.Choice(
|
|
1168
1168
|
["aws", "gcp", "kaggle", "azure", "wasabi"],
|
|
1169
1169
|
case_sensitive=False,
|
|
1170
1170
|
),
|
|
1171
|
-
help="Third Party
|
|
1171
|
+
help="Third Party Credentials to add to the job environment",
|
|
1172
1172
|
multiple=True,
|
|
1173
1173
|
)
|
|
1174
1174
|
@click.option(
|
|
@@ -1230,7 +1230,7 @@ def endpoint(
|
|
|
1230
1230
|
environment,
|
|
1231
1231
|
custom_image,
|
|
1232
1232
|
env,
|
|
1233
|
-
|
|
1233
|
+
credential,
|
|
1234
1234
|
apt_packages,
|
|
1235
1235
|
pip_packages,
|
|
1236
1236
|
conda_packages,
|
|
@@ -1257,7 +1257,7 @@ def endpoint(
|
|
|
1257
1257
|
max_price=max_price,
|
|
1258
1258
|
model=dict(checkpoints=checkpoints),
|
|
1259
1259
|
environment=dict(
|
|
1260
|
-
|
|
1260
|
+
credentials=[k for k in credential],
|
|
1261
1261
|
),
|
|
1262
1262
|
)
|
|
1263
1263
|
|
proximl/cli/project/__init__.py
CHANGED
|
@@ -78,7 +78,7 @@ def remove(config, project):
|
|
|
78
78
|
|
|
79
79
|
|
|
80
80
|
from proximl.cli.project.secret import secret
|
|
81
|
-
from proximl.cli.project.
|
|
81
|
+
from proximl.cli.project.credential import credential
|
|
82
82
|
from proximl.cli.project.data_connector import data_connector
|
|
83
83
|
from proximl.cli.project.datastore import datastore
|
|
84
84
|
from proximl.cli.project.service import service
|
proximl/cli/project/secret.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import click
|
|
2
|
+
import os
|
|
2
3
|
from proximl.cli import pass_config
|
|
3
4
|
from proximl.cli.project import project
|
|
4
5
|
|
|
@@ -42,17 +43,25 @@ def list(config):
|
|
|
42
43
|
|
|
43
44
|
|
|
44
45
|
@secret.command()
|
|
46
|
+
@click.option(
|
|
47
|
+
"--file",
|
|
48
|
+
type=click.Path(exists=True, file_okay=True, dir_okay=False, resolve_path=True),
|
|
49
|
+
help="Load the secret value from the file at the provided path",
|
|
50
|
+
)
|
|
45
51
|
@click.argument("name", type=click.STRING)
|
|
46
52
|
@pass_config
|
|
47
|
-
def put(config, name):
|
|
53
|
+
def put(config, file, name):
|
|
48
54
|
"""
|
|
49
55
|
Set a secret value.
|
|
50
56
|
|
|
51
57
|
Secret is created with the specified NAME.
|
|
52
58
|
"""
|
|
53
59
|
project = config.proximl.run(config.proximl.client.projects.get_current())
|
|
54
|
-
|
|
55
|
-
|
|
60
|
+
if file:
|
|
61
|
+
with open(os.path.expanduser(file)) as f:
|
|
62
|
+
value = f.read()
|
|
63
|
+
else:
|
|
64
|
+
value = click.prompt("Enter the secret value", type=str, hide_input=True)
|
|
56
65
|
|
|
57
66
|
return config.proximl.run(project.secrets.put(name=name, value=value))
|
|
58
67
|
|
|
@@ -7,6 +7,12 @@ class ProjectDataConnectors(object):
|
|
|
7
7
|
self.proximl = proximl
|
|
8
8
|
self.project_id = project_id
|
|
9
9
|
|
|
10
|
+
async def get(self, id, **kwargs):
|
|
11
|
+
resp = await self.proximl._query(
|
|
12
|
+
f"/project/{self.project_id}/data_connectors/{id}", "GET", kwargs
|
|
13
|
+
)
|
|
14
|
+
return ProjectDataConnector(self.proximl, **resp)
|
|
15
|
+
|
|
10
16
|
async def list(self, **kwargs):
|
|
11
17
|
resp = await self.proximl._query(
|
|
12
18
|
f"/project/{self.project_id}/data_connectors", "GET", kwargs
|
|
@@ -61,3 +67,13 @@ class ProjectDataConnector:
|
|
|
61
67
|
|
|
62
68
|
def __bool__(self):
|
|
63
69
|
return bool(self._id)
|
|
70
|
+
|
|
71
|
+
async def enable(self):
|
|
72
|
+
await self.proximl._query(
|
|
73
|
+
f"/project/{self._project_uuid}/data_connectors/{self._id}/enable", "PATCH"
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
async def disable(self):
|
|
77
|
+
await self.proximl._query(
|
|
78
|
+
f"/project/{self._project_uuid}/data_connectors/{self._id}/disable", "PATCH"
|
|
79
|
+
)
|
proximl/projects/datastores.py
CHANGED
|
@@ -7,6 +7,12 @@ class ProjectDatastores(object):
|
|
|
7
7
|
self.proximl = proximl
|
|
8
8
|
self.project_id = project_id
|
|
9
9
|
|
|
10
|
+
async def get(self, id, **kwargs):
|
|
11
|
+
resp = await self.proximl._query(
|
|
12
|
+
f"/project/{self.project_id}/datastores/{id}", "GET", kwargs
|
|
13
|
+
)
|
|
14
|
+
return ProjectDatastore(self.proximl, **resp)
|
|
15
|
+
|
|
10
16
|
async def list(self, **kwargs):
|
|
11
17
|
resp = await self.proximl._query(
|
|
12
18
|
f"/project/{self.project_id}/datastores", "GET", kwargs
|
|
@@ -56,3 +62,13 @@ class ProjectDatastore:
|
|
|
56
62
|
|
|
57
63
|
def __bool__(self):
|
|
58
64
|
return bool(self._id)
|
|
65
|
+
|
|
66
|
+
async def enable(self):
|
|
67
|
+
await self.proximl._query(
|
|
68
|
+
f"/project/{self._project_uuid}/datastores/{self._id}/enable", "PATCH"
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
async def disable(self):
|
|
72
|
+
await self.proximl._query(
|
|
73
|
+
f"/project/{self._project_uuid}/datastores/{self._id}/disable", "PATCH"
|
|
74
|
+
)
|
proximl/projects/projects.py
CHANGED
|
@@ -3,7 +3,7 @@ import logging
|
|
|
3
3
|
from .datastores import ProjectDatastores
|
|
4
4
|
from .data_connectors import ProjectDataConnectors
|
|
5
5
|
from .services import ProjectServices
|
|
6
|
-
from .
|
|
6
|
+
from .credentials import ProjectCredentials
|
|
7
7
|
from .secrets import ProjectSecrets
|
|
8
8
|
|
|
9
9
|
|
|
@@ -26,8 +26,11 @@ class Projects(object):
|
|
|
26
26
|
projects = [Project(self.proximl, **project) for project in resp]
|
|
27
27
|
return projects
|
|
28
28
|
|
|
29
|
-
async def create(self, name,
|
|
30
|
-
data = dict(
|
|
29
|
+
async def create(self, name, copy_credentials=False, **kwargs):
|
|
30
|
+
data = dict(
|
|
31
|
+
name=name,
|
|
32
|
+
copy_credentials=copy_credentials,
|
|
33
|
+
)
|
|
31
34
|
payload = {k: v for k, v in data.items() if v is not None}
|
|
32
35
|
logging.info(f"Creating Project {name}")
|
|
33
36
|
resp = await self.proximl._query("/project", "POST", None, payload)
|
|
@@ -51,7 +54,7 @@ class Project:
|
|
|
51
54
|
self.datastores = ProjectDatastores(self.proximl, self._id)
|
|
52
55
|
self.data_connectors = ProjectDataConnectors(self.proximl, self._id)
|
|
53
56
|
self.services = ProjectServices(self.proximl, self._id)
|
|
54
|
-
self.
|
|
57
|
+
self.credentials = ProjectCredentials(self.proximl, self._id)
|
|
55
58
|
self.secrets = ProjectSecrets(self.proximl, self._id)
|
|
56
59
|
|
|
57
60
|
@property
|
proximl/projects/secrets.py
CHANGED
|
@@ -24,7 +24,7 @@ class ProjectSecrets(object):
|
|
|
24
24
|
f"/project/{self.project_id}/secret/{name}", "PUT", None, payload
|
|
25
25
|
)
|
|
26
26
|
secret = ProjectSecret(self.proximl, **resp)
|
|
27
|
-
logging.info(f"Created Project
|
|
27
|
+
logging.info(f"Created Project Secret {name} in project {self.project_id}")
|
|
28
28
|
return secret
|
|
29
29
|
|
|
30
30
|
async def remove(self, name, **kwargs):
|
proximl/projects/services.py
CHANGED
|
@@ -7,6 +7,12 @@ class ProjectServices(object):
|
|
|
7
7
|
self.proximl = proximl
|
|
8
8
|
self.project_id = project_id
|
|
9
9
|
|
|
10
|
+
async def get(self, id, **kwargs):
|
|
11
|
+
resp = await self.proximl._query(
|
|
12
|
+
f"/project/{self.project_id}/services/{id}", "GET", kwargs
|
|
13
|
+
)
|
|
14
|
+
return ProjectService(self.proximl, **resp)
|
|
15
|
+
|
|
10
16
|
async def list(self, **kwargs):
|
|
11
17
|
resp = await self.proximl._query(
|
|
12
18
|
f"/project/{self.project_id}/services", "GET", kwargs
|
|
@@ -61,3 +67,13 @@ class ProjectService:
|
|
|
61
67
|
|
|
62
68
|
def __bool__(self):
|
|
63
69
|
return bool(self._id)
|
|
70
|
+
|
|
71
|
+
async def enable(self):
|
|
72
|
+
await self.proximl._query(
|
|
73
|
+
f"/project/{self._project_uuid}/services/{self._id}/enable", "PATCH"
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
async def disable(self):
|
|
77
|
+
await self.proximl._query(
|
|
78
|
+
f"/project/{self._project_uuid}/services/{self._id}/disable", "PATCH"
|
|
79
|
+
)
|
|
@@ -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=
|
|
5
|
+
proximl/__init__.py,sha256=H24uX4w44gBopXgz6-IQz2EmtKokV3dNMKqD9KEsAKM,439
|
|
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
|
|
@@ -32,13 +32,12 @@ proximl/cli/cloudbender/provider.py,sha256=qhWbDK1tWi00wQWEYqGw7yGoZx0nEjV40GLHR
|
|
|
32
32
|
proximl/cli/cloudbender/region.py,sha256=WnSkY4dXKRJ-FNaoxMfmoh6iuUx5dXCNJmEFT34Xtao,2892
|
|
33
33
|
proximl/cli/cloudbender/service.py,sha256=6NuwlFULJLtOmMy9OFA8GkW4MLvNemAcd_KitQyDXV8,3147
|
|
34
34
|
proximl/cli/job/__init__.py,sha256=s8mU2PvCWDcv4gGT3EmjHn8MIZlXBAoayoZKmnKpXnY,6545
|
|
35
|
-
proximl/cli/job/create.py,sha256=
|
|
36
|
-
proximl/cli/project/__init__.py,sha256=
|
|
35
|
+
proximl/cli/job/create.py,sha256=0EsICgLxP5EniWxN-eTKnJtMoKJJXcfgB5myfNzcDrs,34380
|
|
36
|
+
proximl/cli/project/__init__.py,sha256=ZSiXhsq7O1JwGecsBKBOD1W0VuiwErs-FFsfrXMOiFs,1918
|
|
37
37
|
proximl/cli/project/credential.py,sha256=5vPI6VBIo_YyvAzfUa9ARmz-LUnkdIVW0zbko9t0Q38,3443
|
|
38
38
|
proximl/cli/project/data_connector.py,sha256=CKF4snfrzDmeDXb4au8nV2W9jTweRMDZ89U2GAlBedQ,1411
|
|
39
39
|
proximl/cli/project/datastore.py,sha256=YusrUTKY_qIwEOBN2gXOUoKCUp2qbWTKzquKc0DcUsE,1336
|
|
40
|
-
proximl/cli/project/
|
|
41
|
-
proximl/cli/project/secret.py,sha256=uys2FsXuO_8_EoolQNuOZ9btX4I0LXBeKG8dGx6StMM,1621
|
|
40
|
+
proximl/cli/project/secret.py,sha256=jWj9SNcx4jNKX1E84Fjkj0hRzF1XU0CrdYqNtxYuTpI,1927
|
|
42
41
|
proximl/cli/project/service.py,sha256=06UoGbAWbPPh3kBdH3QXBTzj_k7AfKcD_bAyWGpYeDE,1310
|
|
43
42
|
proximl/cloudbender/__init__.py,sha256=iE29obtC0_9f0IhRvHQcG5aY58fVhVYipTakpjAhdss,64
|
|
44
43
|
proximl/cloudbender/cloudbender.py,sha256=k9Naj_le32YZotM7PRrhml3DxjqRetsHcgg5J4RtJ_4,717
|
|
@@ -52,34 +51,32 @@ proximl/cloudbender/regions.py,sha256=6doBdfMXIQI-uexzvwmNg2ATDzruatw-ixviZSMjon
|
|
|
52
51
|
proximl/cloudbender/services.py,sha256=km3KcIgaRRVb3iuZEIn6ONIekuyXhBgk_brAFJcMMl4,5126
|
|
53
52
|
proximl/projects/__init__.py,sha256=6NKCcHtQMeGB1IyU-djANphfnDX6MEkrXUM5Fyq9fWg,75
|
|
54
53
|
proximl/projects/credentials.py,sha256=hWz6EUEAgltkAQMDjQVsFlVvfWUbZfY3KoWpldnCrXY,2255
|
|
55
|
-
proximl/projects/data_connectors.py,sha256=
|
|
56
|
-
proximl/projects/datastores.py,sha256=
|
|
57
|
-
proximl/projects/
|
|
58
|
-
proximl/projects/
|
|
59
|
-
proximl/projects/
|
|
60
|
-
proximl/projects/services.py,sha256=Jian2RHV9u3pHQKa7AsHKj25DrR4DstB-JaIDhSu7Tw,1679
|
|
54
|
+
proximl/projects/data_connectors.py,sha256=o2-K40BdF85TBXJgj1UMsznBmNHmnYh1qbZtHmmOa2Y,2216
|
|
55
|
+
proximl/projects/datastores.py,sha256=8nHpMEHn3UzsIhmPMoXympbRRJ10XkHdyRhBXUVXyeE,2095
|
|
56
|
+
proximl/projects/projects.py,sha256=V86mKR5USaLaqcKf7XcGIXeH5qmIL0bYITvnwqSTwzI,2792
|
|
57
|
+
proximl/projects/secrets.py,sha256=xlfzRONjT2ySJDcq8FYRQmSU2ZJMdPLS8NbePWYNCeM,2160
|
|
58
|
+
proximl/projects/services.py,sha256=C1YUxixkio8n4AlgmGqZJ93hP3VKOoTXVXTNCkRVd9Y,2206
|
|
61
59
|
tests/integration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
62
60
|
tests/integration/conftest.py,sha256=zRWpherX-yfbpk7xqZk9bIZCyJ-dwVeszY_7kekn2M4,1134
|
|
63
61
|
tests/integration/test_checkpoints_integration.py,sha256=m-m6KM5Iy99bbCyA6VQVBFWc9MI7VItuoAPb_Q6Q0Fk,3206
|
|
64
62
|
tests/integration/test_datasets_integration.py,sha256=Ndp8itnncDSjVH0t5BM5R_-_yL4qt6JrkQAVOTMi1R8,3499
|
|
65
63
|
tests/integration/test_environments_integration.py,sha256=7P6pKSyxA7rTwyNCD9HEaM2ablMG8WcBesOzkG-BgsQ,1403
|
|
66
64
|
tests/integration/test_gpu_types_integration.py,sha256=Zv-yrHcAgKau9BJQvzi92bdrRHhLPl_hbhhzNLEWJ9w,1256
|
|
67
|
-
tests/integration/test_jobs_integration.py,sha256=
|
|
65
|
+
tests/integration/test_jobs_integration.py,sha256=9wY6ZfCv9FkafV0FJ5QRIwO0-8JR-81iB6uLT9C3pQ8,25110
|
|
68
66
|
tests/integration/test_models_integration.py,sha256=cnsao7Zo4PwVCbdAdcBs0xombAslI_X_JOw6ipxdzOA,2878
|
|
69
67
|
tests/integration/test_volumes_integration.py,sha256=Xo2Whw2U-7jyvESIkyex3f0SMXKlExe3kLmsbpXTHhQ,3270
|
|
70
68
|
tests/integration/cloudbender/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
71
69
|
tests/integration/cloudbender/test_providers_integration.py,sha256=gFqPQom-Cn1iZC50_ChQ2us2_f4tIPATQSAUcWdf7ss,1473
|
|
72
70
|
tests/integration/projects/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
73
|
-
tests/integration/projects/conftest.py,sha256=
|
|
71
|
+
tests/integration/projects/conftest.py,sha256=4WbknSwdJgzPAr5qumCJD3Cl1rQFWgGZ5-Wro1ka0xA,249
|
|
74
72
|
tests/integration/projects/test_projects_credentials_integration.py,sha256=_JqE2sGN09gZpvhtMRFjBPXumJ-PqKl8iXOgcYHlvSY,1636
|
|
75
73
|
tests/integration/projects/test_projects_data_connectors_integration.py,sha256=ag6w2FFQYNlAdV83rOqat0FVZnP4JFhDunCvRwMJdzo,1630
|
|
76
74
|
tests/integration/projects/test_projects_datastores_integration.py,sha256=DCHFnCYguhtrZvfTeWgKpPxlkeAXxVfE3IWkM4KjgAc,1469
|
|
77
75
|
tests/integration/projects/test_projects_integration.py,sha256=wlRLxZkMnJZHlNPaeRFjAeyUlMfbgdrrFEI2eMBcoUI,1241
|
|
78
|
-
tests/integration/projects/
|
|
79
|
-
tests/integration/projects/test_projects_secrets_integration.py,sha256=Q8GEJkBE4X38F36sJza3VRo1pWdF9qEEr2kuADqgBB8,1478
|
|
76
|
+
tests/integration/projects/test_projects_secrets_integration.py,sha256=wRkcVkaf-zLWvCdJx9ikJYAoiJXU1esv0diRxwwRFdc,1481
|
|
80
77
|
tests/integration/projects/test_projects_services_integration.py,sha256=MV9tZFTgrUtzImNrc-ZAoHYLbf_ZxAAAeVpxxr5AGdg,1530
|
|
81
78
|
tests/unit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
82
|
-
tests/unit/conftest.py,sha256=
|
|
79
|
+
tests/unit/conftest.py,sha256=11Z49O4mKXtm6xl18kWPomZvbZJQpqdaDYeJHFQbO1A,35588
|
|
83
80
|
tests/unit/test_auth_unit.py,sha256=IJZHT5CZLNfu3MybTdEWIsKlvxNfFYpZ6oWYzbS856g,858
|
|
84
81
|
tests/unit/test_checkpoints_unit.py,sha256=FbBM8Ffqy8JGTpWq2zWAWle2CI8A0MB_zABL_9Mezbk,15965
|
|
85
82
|
tests/unit/test_connections_unit.py,sha256=LFAZzlrvL9oM8rZJTiC1oA9quw1KA2vMUCc3LV6SjXs,5507
|
|
@@ -111,7 +108,6 @@ tests/unit/cli/projects/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG
|
|
|
111
108
|
tests/unit/cli/projects/test_cli_project_credential_unit.py,sha256=wehwquMGwUzwc8iH0bWletS3-kwIXKshoOuXHhJxRUc,943
|
|
112
109
|
tests/unit/cli/projects/test_cli_project_data_connector_unit.py,sha256=RlqgHOUkFv3bmc19pUtGNVD0W1UWBJSDfaI_lzN0ZEA,993
|
|
113
110
|
tests/unit/cli/projects/test_cli_project_datastore_unit.py,sha256=6UMgFwqxBtH65VeWTzXzaXhVfCRoG3Tef6aflqcDlV4,936
|
|
114
|
-
tests/unit/cli/projects/test_cli_project_key_unit.py,sha256=Xb-O4cltVMNvHpSoPtIdfY4hmXUiMv-z5ixY49FKKyM,894
|
|
115
111
|
tests/unit/cli/projects/test_cli_project_secret_unit.py,sha256=tygmgNOOf7C1J5Flo-YRo1-QLI0He5Yc_4Wx50ssC4o,915
|
|
116
112
|
tests/unit/cli/projects/test_cli_project_service_unit.py,sha256=P-u_2-Gpbu0P_MjH6niAMDzj5M8oJYJ5adWcfU4LNpA,922
|
|
117
113
|
tests/unit/cli/projects/test_cli_project_unit.py,sha256=64tR6ae-dQHVEE86N8tDrxOQypvyk8gANXGg6SBEUUI,627
|
|
@@ -128,13 +124,12 @@ tests/unit/projects/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSu
|
|
|
128
124
|
tests/unit/projects/test_project_credentials_unit.py,sha256=y528DyvIm7uc5mFuwiUPjOMO1dkVcMEeYQqzMmKLOuk,3480
|
|
129
125
|
tests/unit/projects/test_project_data_connectors_unit.py,sha256=Yx2yCUgcuN_KfTKynZxse0Nx8jRrSlMygI7R8a-NjE4,3385
|
|
130
126
|
tests/unit/projects/test_project_datastores_unit.py,sha256=WZMKkhpEg2dcevJqT7k6QRcYJF6FJfq177BDk2GWOBk,3129
|
|
131
|
-
tests/unit/projects/test_project_keys_unit.py,sha256=n5Y2rKaenHA6JQFlViE1_dZ00FZ0PhM3C7rQtkuiRGM,3161
|
|
132
127
|
tests/unit/projects/test_project_secrets_unit.py,sha256=VE9L91FJodcwVGizfF65WYMiHZaF0s2AdW1aiJ3z7xA,3276
|
|
133
128
|
tests/unit/projects/test_project_services_unit.py,sha256=PzeNuJRuAG7RkrPWX0FfgFTt6-63FviecrDY06rLQ6A,3331
|
|
134
|
-
tests/unit/projects/test_projects_unit.py,sha256=
|
|
135
|
-
proximl-0.5.13.dist-info/LICENSE,sha256=ADFxLEZDxKY0j4MdyUd5GNuhQ18rnWH5rOz1ZG7yiOA,1069
|
|
136
|
-
proximl-0.5.13.dist-info/METADATA,sha256=
|
|
137
|
-
proximl-0.5.13.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
|
|
138
|
-
proximl-0.5.13.dist-info/entry_points.txt,sha256=HmI311IIabkZReMCXu-nGbvIEW-KfaduAOyfiSqt5SY,63
|
|
139
|
-
proximl-0.5.13.dist-info/top_level.txt,sha256=-TWqc9tAaxmWmW4c7uYsmzPEYUIoh6z02xxqPbv7Kys,23
|
|
140
|
-
proximl-0.5.13.dist-info/RECORD,,
|
|
129
|
+
tests/unit/projects/test_projects_unit.py,sha256=4vMo7TF-SjduoT2ejpuyM3dULslpdqE8-c25M9X-iYc,3810
|
|
130
|
+
proximl-0.5.13.post1.dist-info/LICENSE,sha256=ADFxLEZDxKY0j4MdyUd5GNuhQ18rnWH5rOz1ZG7yiOA,1069
|
|
131
|
+
proximl-0.5.13.post1.dist-info/METADATA,sha256=BvyKWNRgTQNT4Wg2eqJeEwbjcsJWsPoANfYhJUVkfNU,7351
|
|
132
|
+
proximl-0.5.13.post1.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
|
|
133
|
+
proximl-0.5.13.post1.dist-info/entry_points.txt,sha256=HmI311IIabkZReMCXu-nGbvIEW-KfaduAOyfiSqt5SY,63
|
|
134
|
+
proximl-0.5.13.post1.dist-info/top_level.txt,sha256=-TWqc9tAaxmWmW4c7uYsmzPEYUIoh6z02xxqPbv7Kys,23
|
|
135
|
+
proximl-0.5.13.post1.dist-info/RECORD,,
|
|
@@ -4,7 +4,7 @@ from pytest import fixture
|
|
|
4
4
|
@fixture(scope="module")
|
|
5
5
|
async def project(proximl):
|
|
6
6
|
project = await proximl.projects.create(
|
|
7
|
-
name="New Project",
|
|
7
|
+
name="New Project", copy_credentials=False, copy_secrets=False
|
|
8
8
|
)
|
|
9
9
|
yield project
|
|
10
10
|
await project.remove()
|
|
@@ -17,7 +17,7 @@ class ProjectSecretsTests:
|
|
|
17
17
|
yield project_secret
|
|
18
18
|
await project.secrets.remove(name="secret_value")
|
|
19
19
|
|
|
20
|
-
async def
|
|
20
|
+
async def test_list_project_secrets(self, project, project_secret):
|
|
21
21
|
secrets = await project.secrets.list()
|
|
22
22
|
assert len(secrets) > 0
|
|
23
23
|
|
|
@@ -175,7 +175,7 @@ class JobAPIResourceValidationTests:
|
|
|
175
175
|
disk_size=10,
|
|
176
176
|
)
|
|
177
177
|
assert (
|
|
178
|
-
"Invalid Request -
|
|
178
|
+
"Invalid Request - CPU Only may be not be combined with other GPU Types"
|
|
179
179
|
in error.value.message
|
|
180
180
|
)
|
|
181
181
|
|
tests/unit/conftest.py
CHANGED
|
@@ -20,7 +20,7 @@ from proximl.projects import (
|
|
|
20
20
|
from proximl.projects.datastores import ProjectDatastores, ProjectDatastore
|
|
21
21
|
from proximl.projects.services import ProjectServices, ProjectService
|
|
22
22
|
from proximl.projects.data_connectors import ProjectDataConnectors, ProjectDataConnector
|
|
23
|
-
from proximl.projects.
|
|
23
|
+
from proximl.projects.credentials import ProjectCredentials, ProjectCredential
|
|
24
24
|
from proximl.projects.secrets import ProjectSecrets, ProjectSecret
|
|
25
25
|
|
|
26
26
|
from proximl.cloudbender import Cloudbender
|
|
@@ -532,7 +532,7 @@ def mock_jobs():
|
|
|
532
532
|
{"value": "env1val", "key": "env1"},
|
|
533
533
|
{"value": "env2val", "key": "env2"},
|
|
534
534
|
],
|
|
535
|
-
"
|
|
535
|
+
"credentials": ["aws", "gcp"],
|
|
536
536
|
"status": "new",
|
|
537
537
|
},
|
|
538
538
|
"vpn": {
|
|
@@ -609,7 +609,7 @@ def mock_jobs():
|
|
|
609
609
|
"type": "DEEPLEARNING_PY37",
|
|
610
610
|
"image_size": 39656398629,
|
|
611
611
|
"env": [],
|
|
612
|
-
"
|
|
612
|
+
"credentials": [],
|
|
613
613
|
"status": "ready",
|
|
614
614
|
},
|
|
615
615
|
"vpn": {
|
|
@@ -1043,10 +1043,10 @@ def mock_device_configs():
|
|
|
1043
1043
|
@fixture(
|
|
1044
1044
|
scope="session",
|
|
1045
1045
|
)
|
|
1046
|
-
def
|
|
1046
|
+
def mock_project_credentials():
|
|
1047
1047
|
proximl = Mock()
|
|
1048
1048
|
yield [
|
|
1049
|
-
|
|
1049
|
+
ProjectCredential(
|
|
1050
1050
|
proximl,
|
|
1051
1051
|
**{
|
|
1052
1052
|
"project_uuid": "proj-id-1",
|
|
@@ -1055,7 +1055,7 @@ def mock_project_keys():
|
|
|
1055
1055
|
"updatedAt": "2023-06-02T21:22:40.084Z",
|
|
1056
1056
|
},
|
|
1057
1057
|
),
|
|
1058
|
-
|
|
1058
|
+
ProjectCredential(
|
|
1059
1059
|
proximl,
|
|
1060
1060
|
**{
|
|
1061
1061
|
"project_uuid": "proj-id-1",
|
|
@@ -1117,7 +1117,7 @@ def mock_proximl(
|
|
|
1117
1117
|
mock_project_datastores,
|
|
1118
1118
|
mock_project_services,
|
|
1119
1119
|
mock_project_data_connectors,
|
|
1120
|
-
|
|
1120
|
+
mock_project_credentials,
|
|
1121
1121
|
mock_project_secrets,
|
|
1122
1122
|
):
|
|
1123
1123
|
proximl = create_autospec(ProxiML)
|
|
@@ -1150,8 +1150,8 @@ def mock_proximl(
|
|
|
1150
1150
|
proximl.projects.data_connectors.list = AsyncMock(
|
|
1151
1151
|
return_value=mock_project_data_connectors
|
|
1152
1152
|
)
|
|
1153
|
-
proximl.projects.
|
|
1154
|
-
proximl.projects.
|
|
1153
|
+
proximl.projects.credentials = create_autospec(ProjectCredentials)
|
|
1154
|
+
proximl.projects.credentials.list = AsyncMock(return_value=mock_project_credentials)
|
|
1155
1155
|
proximl.projects.secrets = create_autospec(ProjectSecrets)
|
|
1156
1156
|
proximl.projects.secrets.list = AsyncMock(return_value=mock_project_secrets)
|
|
1157
1157
|
|
|
@@ -75,7 +75,7 @@ class ProjectsTests:
|
|
|
75
75
|
requested_config = dict(
|
|
76
76
|
name="new project",
|
|
77
77
|
)
|
|
78
|
-
expected_payload = dict(name="new project",
|
|
78
|
+
expected_payload = dict(name="new project", copy_credentials=False)
|
|
79
79
|
api_response = {
|
|
80
80
|
"id": "project-id-1",
|
|
81
81
|
"name": "new project",
|
proximl/cli/project/key.py
DELETED
|
@@ -1,124 +0,0 @@
|
|
|
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 key(config):
|
|
13
|
-
"""proxiML project key commands."""
|
|
14
|
-
pass
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
@key.command()
|
|
18
|
-
@pass_config
|
|
19
|
-
def list(config):
|
|
20
|
-
"""List keys."""
|
|
21
|
-
data = [
|
|
22
|
-
["TYPE", "KEY ID", "UPDATED AT"],
|
|
23
|
-
[
|
|
24
|
-
"-" * 80,
|
|
25
|
-
"-" * 80,
|
|
26
|
-
"-" * 80,
|
|
27
|
-
],
|
|
28
|
-
]
|
|
29
|
-
project = config.proximl.run(config.proximl.client.projects.get_current())
|
|
30
|
-
keys = config.proximl.run(project.keys.list())
|
|
31
|
-
|
|
32
|
-
for key in keys:
|
|
33
|
-
data.append(
|
|
34
|
-
[
|
|
35
|
-
key.type,
|
|
36
|
-
key.key_id,
|
|
37
|
-
key.updated_at.isoformat(timespec="seconds"),
|
|
38
|
-
]
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
for row in data:
|
|
42
|
-
click.echo(
|
|
43
|
-
"{: >13.11} {: >37.35} {: >28.26}" "".format(*row),
|
|
44
|
-
file=config.stdout,
|
|
45
|
-
)
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
@key.command()
|
|
49
|
-
@click.argument(
|
|
50
|
-
"type",
|
|
51
|
-
type=click.Choice(
|
|
52
|
-
[
|
|
53
|
-
"aws",
|
|
54
|
-
"azure",
|
|
55
|
-
"docker",
|
|
56
|
-
"gcp",
|
|
57
|
-
"huggingface",
|
|
58
|
-
"kaggle",
|
|
59
|
-
"ngc",
|
|
60
|
-
"wasabi",
|
|
61
|
-
],
|
|
62
|
-
case_sensitive=False,
|
|
63
|
-
),
|
|
64
|
-
)
|
|
65
|
-
@pass_config
|
|
66
|
-
def put(config, type):
|
|
67
|
-
"""
|
|
68
|
-
Set a key.
|
|
69
|
-
|
|
70
|
-
A key is uploaded.
|
|
71
|
-
"""
|
|
72
|
-
project = config.proximl.run(config.proximl.client.projects.get_current())
|
|
73
|
-
|
|
74
|
-
tenant = None
|
|
75
|
-
|
|
76
|
-
if type in ["aws", "wasabi"]:
|
|
77
|
-
key_id = click.prompt("Enter the key ID", type=str, hide_input=False)
|
|
78
|
-
secret = click.prompt("Enter the secret key", type=str, hide_input=True)
|
|
79
|
-
elif type == "azure":
|
|
80
|
-
key_id = click.prompt(
|
|
81
|
-
"Enter the Application (client) ID", type=str, hide_input=False
|
|
82
|
-
)
|
|
83
|
-
tenant = click.prompt(
|
|
84
|
-
"Enter the Directory (tenant) ley", type=str, hide_input=False
|
|
85
|
-
)
|
|
86
|
-
secret = click.prompt("Enter the client secret", type=str, hide_input=True)
|
|
87
|
-
elif type in ["docker", "huggingface"]:
|
|
88
|
-
key_id = click.prompt("Enter the username", type=str, hide_input=False)
|
|
89
|
-
secret = click.prompt("Enter the access token", type=str, hide_input=True)
|
|
90
|
-
elif type in ["gcp", "kaggle"]:
|
|
91
|
-
file_name = click.prompt(
|
|
92
|
-
"Enter the path of the credentials file",
|
|
93
|
-
type=click.Path(
|
|
94
|
-
exists=True, file_okay=True, dir_okay=False, resolve_path=True
|
|
95
|
-
),
|
|
96
|
-
hide_input=False,
|
|
97
|
-
)
|
|
98
|
-
key_id = os.path.basename(file_name)
|
|
99
|
-
with open(file_name) as f:
|
|
100
|
-
secret = json.load(f)
|
|
101
|
-
secret = json.dumps(secret)
|
|
102
|
-
elif type == "ngc":
|
|
103
|
-
key_id = "$oauthtoken"
|
|
104
|
-
secret = click.prompt("Enter the access token", type=str, hide_input=True)
|
|
105
|
-
else:
|
|
106
|
-
raise click.UsageError("Unsupported key type")
|
|
107
|
-
|
|
108
|
-
return config.proximl.run(
|
|
109
|
-
project.keys.put(type=type, key_id=key_id, secret=secret, tenant=tenant)
|
|
110
|
-
)
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
@key.command()
|
|
114
|
-
@click.argument("name", type=click.STRING)
|
|
115
|
-
@pass_config
|
|
116
|
-
def remove(config, name):
|
|
117
|
-
"""
|
|
118
|
-
Remove a key.
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
"""
|
|
122
|
-
project = config.proximl.run(config.proximl.client.projects.get_current())
|
|
123
|
-
|
|
124
|
-
return config.proximl.run(project.key.remove(name))
|
proximl/projects/keys.py
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
import logging
|
|
3
|
-
from datetime import datetime
|
|
4
|
-
from dateutil import parser, tz
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class ProjectKeys(object):
|
|
8
|
-
def __init__(self, proximl, project_id):
|
|
9
|
-
self.proximl = proximl
|
|
10
|
-
self.project_id = project_id
|
|
11
|
-
|
|
12
|
-
async def list(self, **kwargs):
|
|
13
|
-
resp = await self.proximl._query(
|
|
14
|
-
f"/project/{self.project_id}/keys", "GET", kwargs
|
|
15
|
-
)
|
|
16
|
-
keys = [ProjectKey(self.proximl, **service) for service in resp]
|
|
17
|
-
return keys
|
|
18
|
-
|
|
19
|
-
async def put(self, type, key_id, secret, tenant=None, **kwargs):
|
|
20
|
-
data = dict(key_id=key_id, secret=secret, tenant=tenant)
|
|
21
|
-
payload = {k: v for k, v in data.items() if v is not None}
|
|
22
|
-
logging.info(f"Creating Project Key {type}")
|
|
23
|
-
resp = await self.proximl._query(
|
|
24
|
-
f"/project/{self.project_id}/key/{type}", "PUT", None, payload
|
|
25
|
-
)
|
|
26
|
-
key = ProjectKey(self.proximl, **resp)
|
|
27
|
-
logging.info(f"Created Project Key {type} in project {self.project_id}")
|
|
28
|
-
|
|
29
|
-
return key
|
|
30
|
-
|
|
31
|
-
async def remove(self, type, **kwargs):
|
|
32
|
-
await self.proximl._query(
|
|
33
|
-
f"/project/{self.project_id}/key/{type}", "DELETE", kwargs
|
|
34
|
-
)
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
class ProjectKey:
|
|
38
|
-
def __init__(self, proximl, **kwargs):
|
|
39
|
-
self.proximl = proximl
|
|
40
|
-
self._entity = kwargs
|
|
41
|
-
self._type = self._entity.get("type")
|
|
42
|
-
self._project_uuid = self._entity.get("project_uuid")
|
|
43
|
-
self._key_id = self._entity.get("key_id")
|
|
44
|
-
self._updated_at = self._entity.get("updatedAt")
|
|
45
|
-
|
|
46
|
-
@property
|
|
47
|
-
def type(self) -> str:
|
|
48
|
-
return self._type
|
|
49
|
-
|
|
50
|
-
@property
|
|
51
|
-
def project_uuid(self) -> str:
|
|
52
|
-
return self._project_uuid
|
|
53
|
-
|
|
54
|
-
@property
|
|
55
|
-
def key_id(self) -> str:
|
|
56
|
-
return self._key_id
|
|
57
|
-
|
|
58
|
-
@property
|
|
59
|
-
def updated_at(self) -> datetime:
|
|
60
|
-
timestamp = parser.isoparse(self._updated_at)
|
|
61
|
-
timezone = tz.tzlocal()
|
|
62
|
-
return timestamp.astimezone(timezone)
|
|
63
|
-
|
|
64
|
-
def __str__(self):
|
|
65
|
-
return json.dumps({k: v for k, v in self._entity.items()})
|
|
66
|
-
|
|
67
|
-
def __repr__(self):
|
|
68
|
-
return f"ProjectKey( proximl , **{self._entity.__repr__()})"
|
|
69
|
-
|
|
70
|
-
def __bool__(self):
|
|
71
|
-
return bool(self._type)
|
|
@@ -1,43 +0,0 @@
|
|
|
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 ProjectKeysTests:
|
|
12
|
-
@fixture(scope="class")
|
|
13
|
-
async def project_key(self, project):
|
|
14
|
-
project_key = await project.keys.put(
|
|
15
|
-
type="aws", key_id="ASFHALKF", secret="IUHKLHKAHF"
|
|
16
|
-
)
|
|
17
|
-
yield project_key
|
|
18
|
-
await project.keys.remove(type="aws")
|
|
19
|
-
|
|
20
|
-
async def test_list_project_keys(self, project, project_key):
|
|
21
|
-
keys = await project.keys.list()
|
|
22
|
-
assert len(keys) > 0
|
|
23
|
-
|
|
24
|
-
async def test_project_key_properties(self, project, project_key):
|
|
25
|
-
assert isinstance(project_key.project_uuid, str)
|
|
26
|
-
assert isinstance(project_key.type, str)
|
|
27
|
-
assert isinstance(project_key.key_id, str)
|
|
28
|
-
assert project_key.type == "aws"
|
|
29
|
-
assert project.id == project_key.project_uuid
|
|
30
|
-
|
|
31
|
-
async def test_project_key_str(self, project_key):
|
|
32
|
-
string = str(project_key)
|
|
33
|
-
regex = r"^{.*\"type\": \"" + project_key.type + r"\".*}$"
|
|
34
|
-
assert isinstance(string, str)
|
|
35
|
-
assert re.match(regex, string)
|
|
36
|
-
|
|
37
|
-
async def test_project_key_repr(self, project_key):
|
|
38
|
-
string = repr(project_key)
|
|
39
|
-
regex = (
|
|
40
|
-
r"^ProjectKey\( proximl , \*\*{.*'type': '" + project_key.type + r"'.*}\)$"
|
|
41
|
-
)
|
|
42
|
-
assert isinstance(string, str)
|
|
43
|
-
assert re.match(regex, string)
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import re
|
|
2
|
-
import json
|
|
3
|
-
import click
|
|
4
|
-
from unittest.mock import AsyncMock, patch, create_autospec
|
|
5
|
-
from pytest import mark, fixture, raises
|
|
6
|
-
|
|
7
|
-
pytestmark = [mark.cli, mark.unit, mark.projects]
|
|
8
|
-
|
|
9
|
-
from proximl.cli.project import key as specimen
|
|
10
|
-
from proximl.projects import (
|
|
11
|
-
Project,
|
|
12
|
-
)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def test_list_keys(runner, mock_project_keys):
|
|
16
|
-
with patch("proximl.cli.ProxiML", new=AsyncMock) as mock_proximl:
|
|
17
|
-
project = create_autospec(Project)
|
|
18
|
-
mock_proximl.projects = AsyncMock()
|
|
19
|
-
mock_proximl.projects.get = AsyncMock(return_value=project)
|
|
20
|
-
mock_proximl.projects.get_current = AsyncMock(return_value=project)
|
|
21
|
-
project.keys = AsyncMock()
|
|
22
|
-
project.keys.list = AsyncMock(return_value=mock_project_keys)
|
|
23
|
-
result = runner.invoke(specimen, ["list"])
|
|
24
|
-
print(result)
|
|
25
|
-
assert result.exit_code == 0
|
|
26
|
-
project.keys.list.assert_called_once()
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import re
|
|
2
|
-
import json
|
|
3
|
-
import logging
|
|
4
|
-
from unittest.mock import AsyncMock, patch
|
|
5
|
-
from pytest import mark, fixture, raises
|
|
6
|
-
from aiohttp import WSMessage, WSMsgType
|
|
7
|
-
|
|
8
|
-
import proximl.projects.keys as specimen
|
|
9
|
-
from proximl.exceptions import (
|
|
10
|
-
ApiError,
|
|
11
|
-
SpecificationError,
|
|
12
|
-
ProxiMLException,
|
|
13
|
-
)
|
|
14
|
-
|
|
15
|
-
pytestmark = [mark.sdk, mark.unit, mark.projects]
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
@fixture
|
|
19
|
-
def project_keys(mock_proximl):
|
|
20
|
-
yield specimen.ProjectKeys(mock_proximl, project_id="1")
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
@fixture
|
|
24
|
-
def project_key(mock_proximl):
|
|
25
|
-
yield specimen.ProjectKey(
|
|
26
|
-
mock_proximl, project_uuid="proj-id-1", type="aws", key_id="AIYHGFSDLK"
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
class ProjectKeysTests:
|
|
31
|
-
@mark.asyncio
|
|
32
|
-
async def test_project_keys_list(self, project_keys, mock_proximl):
|
|
33
|
-
api_response = [
|
|
34
|
-
{"project_uuid": "proj-id-1", "type": "aws", "key_id": "AIYHGFSDLK"},
|
|
35
|
-
{"project_uuid": "proj-id-1", "type": "gcp", "key_id": "credentials.json"},
|
|
36
|
-
]
|
|
37
|
-
mock_proximl._query = AsyncMock(return_value=api_response)
|
|
38
|
-
resp = await project_keys.list()
|
|
39
|
-
mock_proximl._query.assert_called_once_with("/project/1/keys", "GET", dict())
|
|
40
|
-
assert len(resp) == 2
|
|
41
|
-
|
|
42
|
-
@mark.asyncio
|
|
43
|
-
async def test_remove_project_key(
|
|
44
|
-
self,
|
|
45
|
-
project_keys,
|
|
46
|
-
mock_proximl,
|
|
47
|
-
):
|
|
48
|
-
api_response = dict()
|
|
49
|
-
mock_proximl._query = AsyncMock(return_value=api_response)
|
|
50
|
-
await project_keys.remove("aws")
|
|
51
|
-
mock_proximl._query.assert_called_once_with(
|
|
52
|
-
"/project/1/key/aws", "DELETE", dict()
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
@mark.asyncio
|
|
56
|
-
async def test_put_project_key(self, project_keys, mock_proximl):
|
|
57
|
-
requested_config = dict(type="aws", key_id="AIUDHADA", secret="ASKHJSLKF")
|
|
58
|
-
expected_payload = dict(key_id="AIUDHADA", secret="ASKHJSLKF")
|
|
59
|
-
api_response = {
|
|
60
|
-
"project_uuid": "project-id-1",
|
|
61
|
-
"type": "aws",
|
|
62
|
-
"key_id": "AIUDHADA",
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
mock_proximl._query = AsyncMock(return_value=api_response)
|
|
66
|
-
response = await project_keys.put(**requested_config)
|
|
67
|
-
mock_proximl._query.assert_called_once_with(
|
|
68
|
-
"/project/1/key/aws", "PUT", None, expected_payload
|
|
69
|
-
)
|
|
70
|
-
assert response.type == "aws"
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
class ProjectKeyTests:
|
|
74
|
-
def test_project_key_properties(self, project_key):
|
|
75
|
-
assert isinstance(project_key.type, str)
|
|
76
|
-
assert isinstance(project_key.key_id, str)
|
|
77
|
-
assert isinstance(project_key.project_uuid, str)
|
|
78
|
-
|
|
79
|
-
def test_project_key_str(self, project_key):
|
|
80
|
-
string = str(project_key)
|
|
81
|
-
regex = r"^{.*\"type\": \"" + project_key.type + r"\".*}$"
|
|
82
|
-
assert isinstance(string, str)
|
|
83
|
-
assert re.match(regex, string)
|
|
84
|
-
|
|
85
|
-
def test_project_key_repr(self, project_key):
|
|
86
|
-
string = repr(project_key)
|
|
87
|
-
regex = (
|
|
88
|
-
r"^ProjectKey\( proximl , \*\*{.*'type': '" + project_key.type + r"'.*}\)$"
|
|
89
|
-
)
|
|
90
|
-
assert isinstance(string, str)
|
|
91
|
-
assert re.match(regex, string)
|
|
92
|
-
|
|
93
|
-
def test_project_key_bool(self, project_key, mock_proximl):
|
|
94
|
-
empty_project_key = specimen.ProjectKey(mock_proximl)
|
|
95
|
-
assert bool(project_key)
|
|
96
|
-
assert not bool(empty_project_key)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|