proximl 0.5.8__py3-none-any.whl → 0.5.9__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/cli/project/__init__.py +153 -0
- proximl/cli/project/key.py +124 -0
- proximl/cli/project/secret.py +71 -0
- proximl/projects/__init__.py +3 -0
- proximl/projects/data_connectors.py +63 -0
- proximl/projects/datastores.py +58 -0
- proximl/projects/keys.py +71 -0
- proximl/projects/projects.py +83 -0
- proximl/projects/secrets.py +70 -0
- proximl/projects/services.py +63 -0
- {proximl-0.5.8.dist-info → proximl-0.5.9.dist-info}/METADATA +1 -1
- {proximl-0.5.8.dist-info → proximl-0.5.9.dist-info}/RECORD +30 -6
- tests/integration/projects/__init__.py +0 -0
- tests/integration/projects/conftest.py +8 -0
- tests/integration/projects/test_projects_integration.py +38 -0
- tests/integration/projects/test_projects_keys_integration.py +43 -0
- tests/integration/projects/test_projects_secrets_integration.py +44 -0
- tests/unit/projects/__init__.py +0 -0
- tests/unit/projects/test_project_data_connectors_unit.py +102 -0
- tests/unit/projects/test_project_datastores_unit.py +96 -0
- tests/unit/projects/test_project_keys_unit.py +96 -0
- tests/unit/projects/test_project_secrets_unit.py +101 -0
- tests/unit/projects/test_project_services_unit.py +102 -0
- tests/unit/projects/test_projects_unit.py +128 -0
- tests/unit/test_auth_unit.py +30 -0
- tests/unit/test_proximl_unit.py +54 -0
- {proximl-0.5.8.dist-info → proximl-0.5.9.dist-info}/LICENSE +0 -0
- {proximl-0.5.8.dist-info → proximl-0.5.9.dist-info}/WHEEL +0 -0
- {proximl-0.5.8.dist-info → proximl-0.5.9.dist-info}/entry_points.txt +0 -0
- {proximl-0.5.8.dist-info → proximl-0.5.9.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import click
|
|
2
|
+
from proximl.cli import cli, pass_config, search_by_id_name
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@cli.group()
|
|
6
|
+
@pass_config
|
|
7
|
+
def project(config):
|
|
8
|
+
"""proxiML project commands."""
|
|
9
|
+
pass
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@project.command()
|
|
13
|
+
@pass_config
|
|
14
|
+
def list(config):
|
|
15
|
+
"""List projects."""
|
|
16
|
+
data = [
|
|
17
|
+
["ID", "NAME", "OWNER", "MINE"],
|
|
18
|
+
[
|
|
19
|
+
"-" * 80,
|
|
20
|
+
"-" * 80,
|
|
21
|
+
"-" * 80,
|
|
22
|
+
"-" * 80,
|
|
23
|
+
],
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
projects = config.proximl.run(config.proximl.client.projects.list())
|
|
27
|
+
|
|
28
|
+
for project in projects:
|
|
29
|
+
data.append(
|
|
30
|
+
[
|
|
31
|
+
project.id,
|
|
32
|
+
project.name,
|
|
33
|
+
project.owner_name,
|
|
34
|
+
"X" if project.is_owner else "",
|
|
35
|
+
]
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
for row in data:
|
|
39
|
+
click.echo(
|
|
40
|
+
"{: >38.36} {: >30.28} {: >15.13} {: >4.4}" "".format(*row),
|
|
41
|
+
file=config.stdout,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@project.command()
|
|
46
|
+
@click.argument("name", type=click.STRING)
|
|
47
|
+
@pass_config
|
|
48
|
+
def create(config, name):
|
|
49
|
+
"""
|
|
50
|
+
Create a project.
|
|
51
|
+
|
|
52
|
+
Project is created with the specified NAME.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
return config.proximl.run(
|
|
56
|
+
config.proximl.client.projects.create(
|
|
57
|
+
name=name,
|
|
58
|
+
)
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@project.command()
|
|
63
|
+
@click.argument("project", type=click.STRING)
|
|
64
|
+
@pass_config
|
|
65
|
+
def remove(config, project):
|
|
66
|
+
"""
|
|
67
|
+
Remove a project.
|
|
68
|
+
|
|
69
|
+
PROJECT may be specified by name or ID, but ID is preferred.
|
|
70
|
+
"""
|
|
71
|
+
projects = config.proximl.run(config.proximl.client.projects.list())
|
|
72
|
+
|
|
73
|
+
found = search_by_id_name(project, projects)
|
|
74
|
+
if None is found:
|
|
75
|
+
raise click.UsageError("Cannot find specified project.")
|
|
76
|
+
|
|
77
|
+
return config.proximl.run(found.remove())
|
|
78
|
+
|
|
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
|
+
from proximl.cli.project.secret import secret
|
|
153
|
+
from proximl.cli.project.key import key
|
|
@@ -0,0 +1,124 @@
|
|
|
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))
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import click
|
|
2
|
+
from proximl.cli import pass_config
|
|
3
|
+
from proximl.cli.project import project
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@project.group()
|
|
7
|
+
@pass_config
|
|
8
|
+
def secret(config):
|
|
9
|
+
"""proxiML project secret commands."""
|
|
10
|
+
pass
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@secret.command()
|
|
14
|
+
@pass_config
|
|
15
|
+
def list(config):
|
|
16
|
+
"""List secrets."""
|
|
17
|
+
data = [
|
|
18
|
+
["NAME", "CREATED BY", "UPDATED AT"],
|
|
19
|
+
[
|
|
20
|
+
"-" * 80,
|
|
21
|
+
"-" * 80,
|
|
22
|
+
"-" * 80,
|
|
23
|
+
],
|
|
24
|
+
]
|
|
25
|
+
project = config.proximl.run(config.proximl.client.projects.get_current())
|
|
26
|
+
secrets = config.proximl.run(project.secrets.list())
|
|
27
|
+
|
|
28
|
+
for secret in secrets:
|
|
29
|
+
data.append(
|
|
30
|
+
[
|
|
31
|
+
secret.name,
|
|
32
|
+
secret.created_by,
|
|
33
|
+
secret.updated_at.isoformat(timespec="seconds"),
|
|
34
|
+
]
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
for row in data:
|
|
38
|
+
click.echo(
|
|
39
|
+
"{: >38.36} {: >30.28} {: >28.26}" "".format(*row),
|
|
40
|
+
file=config.stdout,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@secret.command()
|
|
45
|
+
@click.argument("name", type=click.STRING)
|
|
46
|
+
@pass_config
|
|
47
|
+
def put(config, name):
|
|
48
|
+
"""
|
|
49
|
+
Set a secret value.
|
|
50
|
+
|
|
51
|
+
Secret is created with the specified NAME.
|
|
52
|
+
"""
|
|
53
|
+
project = config.proximl.run(config.proximl.client.projects.get_current())
|
|
54
|
+
|
|
55
|
+
value = click.prompt("Enter the secret value", type=str, hide_input=True)
|
|
56
|
+
|
|
57
|
+
return config.proximl.run(project.secrets.put(name=name, value=value))
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@secret.command()
|
|
61
|
+
@click.argument("name", type=click.STRING)
|
|
62
|
+
@pass_config
|
|
63
|
+
def remove(config, name):
|
|
64
|
+
"""
|
|
65
|
+
Remove a secret.
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
"""
|
|
69
|
+
project = config.proximl.run(config.proximl.client.projects.get_current())
|
|
70
|
+
|
|
71
|
+
return config.proximl.run(project.secret.remove(name))
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import logging
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class ProjectDataConnectors(object):
|
|
6
|
+
def __init__(self, proximl, project_id):
|
|
7
|
+
self.proximl = proximl
|
|
8
|
+
self.project_id = project_id
|
|
9
|
+
|
|
10
|
+
async def list(self, **kwargs):
|
|
11
|
+
resp = await self.proximl._query(
|
|
12
|
+
f"/project/{self.project_id}/data_connectors", "GET", kwargs
|
|
13
|
+
)
|
|
14
|
+
data_connectors = [
|
|
15
|
+
ProjectDataConnector(self.proximl, **data_connector)
|
|
16
|
+
for data_connector in resp
|
|
17
|
+
]
|
|
18
|
+
return data_connectors
|
|
19
|
+
|
|
20
|
+
async def refresh(self):
|
|
21
|
+
await self.proximl._query(
|
|
22
|
+
f"/project/{self.project_id}/data_connectors", "PATCH"
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class ProjectDataConnector:
|
|
27
|
+
def __init__(self, proximl, **kwargs):
|
|
28
|
+
self.proximl = proximl
|
|
29
|
+
self._entity = kwargs
|
|
30
|
+
self._id = self._entity.get("id")
|
|
31
|
+
self._project_uuid = self._entity.get("project_uuid")
|
|
32
|
+
self._name = self._entity.get("name")
|
|
33
|
+
self._type = self._entity.get("type")
|
|
34
|
+
self._region_uuid = self._entity.get("region_uuid")
|
|
35
|
+
|
|
36
|
+
@property
|
|
37
|
+
def id(self) -> str:
|
|
38
|
+
return self._id
|
|
39
|
+
|
|
40
|
+
@property
|
|
41
|
+
def project_uuid(self) -> str:
|
|
42
|
+
return self._project_uuid
|
|
43
|
+
|
|
44
|
+
@property
|
|
45
|
+
def name(self) -> str:
|
|
46
|
+
return self._name
|
|
47
|
+
|
|
48
|
+
@property
|
|
49
|
+
def type(self) -> str:
|
|
50
|
+
return self._type
|
|
51
|
+
|
|
52
|
+
@property
|
|
53
|
+
def region_uuid(self) -> str:
|
|
54
|
+
return self._region_uuid
|
|
55
|
+
|
|
56
|
+
def __str__(self):
|
|
57
|
+
return json.dumps({k: v for k, v in self._entity.items()})
|
|
58
|
+
|
|
59
|
+
def __repr__(self):
|
|
60
|
+
return f"ProjectDataConnector( proximl , **{self._entity.__repr__()})"
|
|
61
|
+
|
|
62
|
+
def __bool__(self):
|
|
63
|
+
return bool(self._id)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import logging
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class ProjectDatastores(object):
|
|
6
|
+
def __init__(self, proximl, project_id):
|
|
7
|
+
self.proximl = proximl
|
|
8
|
+
self.project_id = project_id
|
|
9
|
+
|
|
10
|
+
async def list(self, **kwargs):
|
|
11
|
+
resp = await self.proximl._query(
|
|
12
|
+
f"/project/{self.project_id}/datastores", "GET", kwargs
|
|
13
|
+
)
|
|
14
|
+
datastores = [ProjectDatastore(self.proximl, **datastore) for datastore in resp]
|
|
15
|
+
return datastores
|
|
16
|
+
|
|
17
|
+
async def refresh(self):
|
|
18
|
+
await self.proximl._query(f"/project/{self.project_id}/datastores", "PATCH")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ProjectDatastore:
|
|
22
|
+
def __init__(self, proximl, **kwargs):
|
|
23
|
+
self.proximl = proximl
|
|
24
|
+
self._entity = kwargs
|
|
25
|
+
self._id = self._entity.get("id")
|
|
26
|
+
self._project_uuid = self._entity.get("project_uuid")
|
|
27
|
+
self._name = self._entity.get("name")
|
|
28
|
+
self._type = self._entity.get("type")
|
|
29
|
+
self._region_uuid = self._entity.get("region_uuid")
|
|
30
|
+
|
|
31
|
+
@property
|
|
32
|
+
def id(self) -> str:
|
|
33
|
+
return self._id
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def project_uuid(self) -> str:
|
|
37
|
+
return self._project_uuid
|
|
38
|
+
|
|
39
|
+
@property
|
|
40
|
+
def name(self) -> str:
|
|
41
|
+
return self._name
|
|
42
|
+
|
|
43
|
+
@property
|
|
44
|
+
def type(self) -> str:
|
|
45
|
+
return self._type
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def region_uuid(self) -> str:
|
|
49
|
+
return self._region_uuid
|
|
50
|
+
|
|
51
|
+
def __str__(self):
|
|
52
|
+
return json.dumps({k: v for k, v in self._entity.items()})
|
|
53
|
+
|
|
54
|
+
def __repr__(self):
|
|
55
|
+
return f"ProjectDatastore( proximl , **{self._entity.__repr__()})"
|
|
56
|
+
|
|
57
|
+
def __bool__(self):
|
|
58
|
+
return bool(self._id)
|
proximl/projects/keys.py
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
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)
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import logging
|
|
3
|
+
from .datastores import ProjectDatastores
|
|
4
|
+
from .data_connectors import ProjectDataConnectors
|
|
5
|
+
from .services import ProjectServices
|
|
6
|
+
from .keys import ProjectKeys
|
|
7
|
+
from .secrets import ProjectSecrets
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Projects(object):
|
|
11
|
+
def __init__(self, proximl):
|
|
12
|
+
self.proximl = proximl
|
|
13
|
+
|
|
14
|
+
async def get(self, id, **kwargs):
|
|
15
|
+
resp = await self.proximl._query(f"/project/{id}", "GET", kwargs)
|
|
16
|
+
return Project(self.proximl, **resp)
|
|
17
|
+
|
|
18
|
+
async def get_current(self, **kwargs):
|
|
19
|
+
resp = await self.proximl._query(
|
|
20
|
+
f"/project/{self.proximl.project}", "GET", kwargs
|
|
21
|
+
)
|
|
22
|
+
return Project(self.proximl, **resp)
|
|
23
|
+
|
|
24
|
+
async def list(self, **kwargs):
|
|
25
|
+
resp = await self.proximl._query(f"/project", "GET", kwargs)
|
|
26
|
+
projects = [Project(self.proximl, **project) for project in resp]
|
|
27
|
+
return projects
|
|
28
|
+
|
|
29
|
+
async def create(self, name, copy_keys=False, copy_secrets=False, **kwargs):
|
|
30
|
+
data = dict(name=name, copy_keys=copy_keys, copy_secrets=copy_secrets)
|
|
31
|
+
payload = {k: v for k, v in data.items() if v is not None}
|
|
32
|
+
logging.info(f"Creating Project {name}")
|
|
33
|
+
resp = await self.proximl._query("/project", "POST", None, payload)
|
|
34
|
+
project = Project(self.proximl, **resp)
|
|
35
|
+
logging.info(f"Created Project {name} with id {project.id}")
|
|
36
|
+
|
|
37
|
+
return project
|
|
38
|
+
|
|
39
|
+
async def remove(self, id, **kwargs):
|
|
40
|
+
await self.proximl._query(f"/project/{id}", "DELETE", kwargs)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class Project:
|
|
44
|
+
def __init__(self, proximl, **kwargs):
|
|
45
|
+
self.proximl = proximl
|
|
46
|
+
self._entity = kwargs
|
|
47
|
+
self._id = self._entity.get("id")
|
|
48
|
+
self._name = self._entity.get("name")
|
|
49
|
+
self._is_owner = self._entity.get("owner")
|
|
50
|
+
self._owner_name = self._entity.get("owner_name")
|
|
51
|
+
self.datastores = ProjectDatastores(self.proximl, self._id)
|
|
52
|
+
self.data_connectors = ProjectDataConnectors(self.proximl, self._id)
|
|
53
|
+
self.services = ProjectServices(self.proximl, self._id)
|
|
54
|
+
self.keys = ProjectKeys(self.proximl, self._id)
|
|
55
|
+
self.secrets = ProjectSecrets(self.proximl, self._id)
|
|
56
|
+
|
|
57
|
+
@property
|
|
58
|
+
def id(self) -> str:
|
|
59
|
+
return self._id
|
|
60
|
+
|
|
61
|
+
@property
|
|
62
|
+
def name(self) -> str:
|
|
63
|
+
return self._name
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def is_owner(self) -> bool:
|
|
67
|
+
return self._is_owner
|
|
68
|
+
|
|
69
|
+
@property
|
|
70
|
+
def owner_name(self) -> str:
|
|
71
|
+
return self._owner_name
|
|
72
|
+
|
|
73
|
+
def __str__(self):
|
|
74
|
+
return json.dumps({k: v for k, v in self._entity.items()})
|
|
75
|
+
|
|
76
|
+
def __repr__(self):
|
|
77
|
+
return f"Project( proximl , **{self._entity.__repr__()})"
|
|
78
|
+
|
|
79
|
+
def __bool__(self):
|
|
80
|
+
return bool(self._id)
|
|
81
|
+
|
|
82
|
+
async def remove(self):
|
|
83
|
+
await self.proximl._query(f"/project/{self._id}", "DELETE")
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import logging
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
from dateutil import parser, tz
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class ProjectSecrets(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}/secrets", "GET", kwargs
|
|
15
|
+
)
|
|
16
|
+
secrets = [ProjectSecret(self.proximl, **service) for service in resp]
|
|
17
|
+
return secrets
|
|
18
|
+
|
|
19
|
+
async def put(self, name, value, **kwargs):
|
|
20
|
+
data = dict(value=value)
|
|
21
|
+
payload = {k: v for k, v in data.items() if v is not None}
|
|
22
|
+
logging.info(f"Creating Project Secret {name}")
|
|
23
|
+
resp = await self.proximl._query(
|
|
24
|
+
f"/project/{self.project_id}/secret/{name}", "PUT", None, payload
|
|
25
|
+
)
|
|
26
|
+
secret = ProjectSecret(self.proximl, **resp)
|
|
27
|
+
logging.info(f"Created Project Key {name} in project {self.project_id}")
|
|
28
|
+
return secret
|
|
29
|
+
|
|
30
|
+
async def remove(self, name, **kwargs):
|
|
31
|
+
await self.proximl._query(
|
|
32
|
+
f"/project/{self.project_id}/secret/{name}", "DELETE", kwargs
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class ProjectSecret:
|
|
37
|
+
def __init__(self, proximl, **kwargs):
|
|
38
|
+
self.proximl = proximl
|
|
39
|
+
self._entity = kwargs
|
|
40
|
+
self._name = self._entity.get("name")
|
|
41
|
+
self._project_uuid = self._entity.get("project_uuid")
|
|
42
|
+
self._created_by = self._entity.get("created_by")
|
|
43
|
+
self._updated_at = self._entity.get("updatedAt")
|
|
44
|
+
|
|
45
|
+
@property
|
|
46
|
+
def name(self) -> str:
|
|
47
|
+
return self._name
|
|
48
|
+
|
|
49
|
+
@property
|
|
50
|
+
def project_uuid(self) -> str:
|
|
51
|
+
return self._project_uuid
|
|
52
|
+
|
|
53
|
+
@property
|
|
54
|
+
def created_by(self) -> str:
|
|
55
|
+
return self._created_by
|
|
56
|
+
|
|
57
|
+
@property
|
|
58
|
+
def updated_at(self) -> datetime:
|
|
59
|
+
timestamp = parser.isoparse(self._updated_at)
|
|
60
|
+
timezone = tz.tzlocal()
|
|
61
|
+
return timestamp.astimezone(timezone)
|
|
62
|
+
|
|
63
|
+
def __str__(self):
|
|
64
|
+
return json.dumps({k: v for k, v in self._entity.items()})
|
|
65
|
+
|
|
66
|
+
def __repr__(self):
|
|
67
|
+
return f"ProjectSecret( proximl , **{self._entity.__repr__()})"
|
|
68
|
+
|
|
69
|
+
def __bool__(self):
|
|
70
|
+
return bool(self._name)
|