cgcsdk 1.0.6__py3-none-any.whl → 1.0.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.
- cgc/.env +1 -1
- cgc/CHANGELOG.md +30 -0
- cgc/cgc.py +7 -1
- cgc/commands/auth/__init__.py +2 -2
- cgc/commands/auth/auth_cmd.py +14 -2
- cgc/commands/auth/auth_responses.py +9 -2
- cgc/commands/auth/auth_utils.py +6 -5
- cgc/commands/cgc_cmd.py +28 -3
- cgc/commands/cgc_cmd_responses.py +8 -0
- cgc/commands/cgc_models.py +9 -0
- cgc/commands/compute/compute_models.py +3 -23
- cgc/commands/compute/compute_utills.py +16 -6
- cgc/commands/db/db_cmd.py +7 -1
- cgc/commands/db/db_models.py +37 -0
- cgc/commands/exceptions.py +8 -0
- cgc/commands/jobs/__init__.py +10 -0
- cgc/commands/jobs/job_utils.py +180 -0
- cgc/commands/jobs/jobs_cmd.py +238 -0
- cgc/commands/jobs/jobs_responses.py +52 -0
- cgc/commands/keys/__init__.py +5 -0
- cgc/commands/keys/keys_cmd.py +176 -0
- cgc/commands/keys/keys_models.py +16 -0
- cgc/commands/keys/keys_responses.py +47 -0
- cgc/commands/keys/keys_utils.py +79 -0
- cgc/commands/resource/resource_cmd.py +2 -1
- cgc/sdk/__init__.py +1 -2
- cgc/sdk/job.py +147 -0
- cgc/sdk/resource.py +1 -0
- cgc/utils/__init__.py +8 -0
- cgc/utils/config_utils.py +5 -1
- cgc/utils/consts/env_consts.py +1 -1
- cgc/utils/custom_exceptions.py +8 -1
- cgc/utils/message_utils.py +1 -1
- cgc/utils/prepare_headers.py +22 -13
- cgc/utils/requests_helper.py +1 -3
- cgcsdk-1.0.9.dist-info/METADATA +66 -0
- {cgcsdk-1.0.6.dist-info → cgcsdk-1.0.9.dist-info}/RECORD +41 -32
- cgc/sdk/handlers.py +0 -24
- cgc/sdk/mongodb.py +0 -204
- cgc/sdk/redis.py +0 -91
- cgcsdk-1.0.6.dist-info/METADATA +0 -39
- {cgcsdk-1.0.6.dist-info → cgcsdk-1.0.9.dist-info}/LICENSE +0 -0
- {cgcsdk-1.0.6.dist-info → cgcsdk-1.0.9.dist-info}/WHEEL +0 -0
- {cgcsdk-1.0.6.dist-info → cgcsdk-1.0.9.dist-info}/entry_points.txt +0 -0
- {cgcsdk-1.0.6.dist-info → cgcsdk-1.0.9.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,238 @@
|
|
1
|
+
import click
|
2
|
+
import json
|
3
|
+
import sys
|
4
|
+
|
5
|
+
from cgc.commands.jobs.job_utils import job_delete_payload, job_create_payload
|
6
|
+
from cgc.commands.jobs.jobs_responses import (
|
7
|
+
job_delete_response,
|
8
|
+
job_list_response,
|
9
|
+
job_create_response,
|
10
|
+
)
|
11
|
+
from cgc.commands.compute.compute_models import GPUsList
|
12
|
+
from cgc.utils.prepare_headers import get_api_url_and_prepare_headers
|
13
|
+
from cgc.utils.response_utils import (
|
14
|
+
retrieve_and_validate_response_send_metric,
|
15
|
+
)
|
16
|
+
from cgc.utils.click_group import CustomGroup, CustomCommand
|
17
|
+
from cgc.utils.requests_helper import call_api, EndpointTypes
|
18
|
+
|
19
|
+
|
20
|
+
@click.group(name="job", cls=CustomGroup, hidden=False)
|
21
|
+
def job_group():
|
22
|
+
"""
|
23
|
+
Management of jobs.
|
24
|
+
"""
|
25
|
+
|
26
|
+
|
27
|
+
@job_group.command("delete", cls=CustomCommand)
|
28
|
+
@click.argument("name", type=click.STRING)
|
29
|
+
def job_delete(name: str):
|
30
|
+
"""
|
31
|
+
Delete an job using backend endpoint.
|
32
|
+
\f
|
33
|
+
:param name: name of job to delete
|
34
|
+
:type name: str
|
35
|
+
"""
|
36
|
+
api_url, headers = get_api_url_and_prepare_headers()
|
37
|
+
url = f"{api_url}/v1/api/job/delete"
|
38
|
+
metric = "job.delete"
|
39
|
+
__payload = job_delete_payload(name=name)
|
40
|
+
__res = call_api(
|
41
|
+
request=EndpointTypes.delete,
|
42
|
+
url=url,
|
43
|
+
headers=headers,
|
44
|
+
data=json.dumps(__payload).encode("utf-8"),
|
45
|
+
)
|
46
|
+
click.echo(
|
47
|
+
job_delete_response(retrieve_and_validate_response_send_metric(__res, metric))
|
48
|
+
)
|
49
|
+
|
50
|
+
|
51
|
+
@job_group.command("list", cls=CustomCommand)
|
52
|
+
def job_list():
|
53
|
+
"""List all ports for a running resource"""
|
54
|
+
api_url, headers = get_api_url_and_prepare_headers()
|
55
|
+
url = f"{api_url}/v1/api/job/list"
|
56
|
+
metric = "job.list"
|
57
|
+
__res = call_api(
|
58
|
+
request=EndpointTypes.get,
|
59
|
+
url=url,
|
60
|
+
headers=headers,
|
61
|
+
)
|
62
|
+
click.echo(
|
63
|
+
job_list_response(retrieve_and_validate_response_send_metric(__res, metric))
|
64
|
+
)
|
65
|
+
|
66
|
+
|
67
|
+
@job_group.command("create", cls=CustomCommand)
|
68
|
+
@click.argument("startup_command", required=False)
|
69
|
+
@click.option(
|
70
|
+
"-n", "--name", "name", type=click.STRING, required=True, help="Desired app name"
|
71
|
+
)
|
72
|
+
@click.option(
|
73
|
+
"-g",
|
74
|
+
"--gpu",
|
75
|
+
"gpu",
|
76
|
+
type=click.INT,
|
77
|
+
default=0,
|
78
|
+
help="How much GPU cards app will use",
|
79
|
+
)
|
80
|
+
@click.option(
|
81
|
+
"-gt",
|
82
|
+
"--gpu-type",
|
83
|
+
"gpu_type",
|
84
|
+
type=click.Choice(GPUsList.get_list(), case_sensitive=False),
|
85
|
+
default="A5000",
|
86
|
+
help="Graphic card used by the app",
|
87
|
+
)
|
88
|
+
@click.option(
|
89
|
+
"-c",
|
90
|
+
"--cpu",
|
91
|
+
"cpu",
|
92
|
+
type=click.INT,
|
93
|
+
default=1,
|
94
|
+
help="How much CPU cores app can use",
|
95
|
+
)
|
96
|
+
@click.option(
|
97
|
+
"-m",
|
98
|
+
"--memory",
|
99
|
+
"memory",
|
100
|
+
type=click.INT,
|
101
|
+
default=2,
|
102
|
+
help="How much Gi RAM app can use",
|
103
|
+
)
|
104
|
+
@click.option(
|
105
|
+
"-v",
|
106
|
+
"--volume",
|
107
|
+
"volumes",
|
108
|
+
multiple=True,
|
109
|
+
help="List of volume names to be mounted with default mount path",
|
110
|
+
)
|
111
|
+
@click.option(
|
112
|
+
"-fp",
|
113
|
+
"--full-path",
|
114
|
+
"volume_full_path",
|
115
|
+
type=click.STRING,
|
116
|
+
help="If set, full path will be used for volume mount. Valid for 1 volume.",
|
117
|
+
)
|
118
|
+
@click.option(
|
119
|
+
"-d",
|
120
|
+
"--resource-data",
|
121
|
+
"resource_data",
|
122
|
+
multiple=True,
|
123
|
+
help="List of optional arguments to be passed to the app, key=value format",
|
124
|
+
)
|
125
|
+
@click.option(
|
126
|
+
"--image",
|
127
|
+
"image_name",
|
128
|
+
type=click.STRING,
|
129
|
+
help="Image to be used by the app",
|
130
|
+
)
|
131
|
+
@click.option(
|
132
|
+
"--repository-secret",
|
133
|
+
"repository_secret",
|
134
|
+
type=click.STRING,
|
135
|
+
help="Use secret to pull image from private repository",
|
136
|
+
)
|
137
|
+
@click.option(
|
138
|
+
"-cm",
|
139
|
+
"--config-map",
|
140
|
+
"config_maps_data",
|
141
|
+
multiple=True,
|
142
|
+
help="List of optional arguments to be passed to the app, key=value format",
|
143
|
+
)
|
144
|
+
@click.option(
|
145
|
+
"--shm",
|
146
|
+
"shm_size",
|
147
|
+
type=click.IntRange(0, 1024, clamp=True),
|
148
|
+
default=0,
|
149
|
+
help="Size of shared memory in Gi",
|
150
|
+
)
|
151
|
+
@click.option(
|
152
|
+
"--ttl",
|
153
|
+
"ttl_seconds_after_finished",
|
154
|
+
type=click.INT,
|
155
|
+
default=None,
|
156
|
+
help="Time to live in seconds after app is finished",
|
157
|
+
)
|
158
|
+
def job_create(
|
159
|
+
gpu: int,
|
160
|
+
gpu_type: str,
|
161
|
+
cpu: int,
|
162
|
+
memory: int,
|
163
|
+
volumes: list[str],
|
164
|
+
volume_full_path: str,
|
165
|
+
resource_data: list[str],
|
166
|
+
config_maps_data: list[str],
|
167
|
+
name: str,
|
168
|
+
shm_size: int,
|
169
|
+
image_name: str,
|
170
|
+
startup_command: str,
|
171
|
+
repository_secret: str,
|
172
|
+
ttl_seconds_after_finished: int,
|
173
|
+
):
|
174
|
+
"""
|
175
|
+
Create job in user namespace.
|
176
|
+
\f
|
177
|
+
:param gpu: number of gpus to be used by app
|
178
|
+
:type gpu: int
|
179
|
+
:param cpu: number of cores to be used by app
|
180
|
+
:type cpu: int
|
181
|
+
:param memory: GB of memory to be used by app
|
182
|
+
:type memory: int
|
183
|
+
:param volumes: list of volumes to mount
|
184
|
+
:type volumes: list[str]
|
185
|
+
:param volume_full_path: if set, full path will be used for volume mount
|
186
|
+
:type volume_full_path: str
|
187
|
+
:param resource_data: list of optional arguments to be passed to the app
|
188
|
+
:type resource_data: list[str]
|
189
|
+
:param config_maps_data: list of optional arguments to be passed to the app
|
190
|
+
:type config_maps_data: list[str]
|
191
|
+
:param name: name of app
|
192
|
+
:type name: str
|
193
|
+
:param shm_size: size of shared memory
|
194
|
+
:type shm_size: int
|
195
|
+
:param image_name: name of image to be used by the app
|
196
|
+
:type image_name: str
|
197
|
+
:param startup_command: command to be executed on app startup; it is stdin input
|
198
|
+
:type startup_command: str
|
199
|
+
:param repository_secret: use secret to pull image from private repository
|
200
|
+
:type repository_secret: str
|
201
|
+
:param ttl_seconds_after_finished: time to live in seconds after app is finished
|
202
|
+
:type ttl_seconds_after_finished: int
|
203
|
+
"""
|
204
|
+
api_url, headers = get_api_url_and_prepare_headers()
|
205
|
+
url = f"{api_url}/v1/api/job/create"
|
206
|
+
cleaned_data = ""
|
207
|
+
if not sys.stdin.isatty():
|
208
|
+
input_data = sys.stdin.read()
|
209
|
+
cleaned_data = input_data.replace("|", "")
|
210
|
+
startup_command = cleaned_data
|
211
|
+
elif startup_command:
|
212
|
+
cleaned_data = startup_command
|
213
|
+
metric = "job.create"
|
214
|
+
__payload = job_create_payload(
|
215
|
+
name=name,
|
216
|
+
cpu=cpu,
|
217
|
+
memory=memory,
|
218
|
+
gpu=gpu,
|
219
|
+
volumes=volumes,
|
220
|
+
volume_full_path=volume_full_path,
|
221
|
+
resource_data=resource_data,
|
222
|
+
config_maps_data=config_maps_data,
|
223
|
+
gpu_type=gpu_type,
|
224
|
+
shm_size=shm_size,
|
225
|
+
image_name=image_name,
|
226
|
+
startup_command=cleaned_data,
|
227
|
+
repository_secret=repository_secret,
|
228
|
+
ttl_seconds_after_finished=ttl_seconds_after_finished,
|
229
|
+
)
|
230
|
+
__res = call_api(
|
231
|
+
request=EndpointTypes.post,
|
232
|
+
url=url,
|
233
|
+
headers=headers,
|
234
|
+
data=json.dumps(__payload).encode("utf-8"),
|
235
|
+
)
|
236
|
+
click.echo(
|
237
|
+
job_create_response(retrieve_and_validate_response_send_metric(__res, metric))
|
238
|
+
)
|
@@ -0,0 +1,52 @@
|
|
1
|
+
from cgc.commands.jobs import NoJobsToList
|
2
|
+
from cgc.commands.jobs.job_utils import get_job_list
|
3
|
+
from cgc.telemetry.basic import change_gauge, setup_gauge
|
4
|
+
from cgc.utils.config_utils import get_namespace
|
5
|
+
from cgc.utils.message_utils import key_error_decorator_for_helpers
|
6
|
+
from cgc.utils.response_utils import (
|
7
|
+
fill_missing_values_in_a_response,
|
8
|
+
tabulate_a_response,
|
9
|
+
)
|
10
|
+
|
11
|
+
|
12
|
+
@key_error_decorator_for_helpers
|
13
|
+
def job_delete_response(data: dict) -> str:
|
14
|
+
"""Create response string for job delete command.
|
15
|
+
|
16
|
+
:param response: dict object from API response.
|
17
|
+
:type response: requests.Response
|
18
|
+
:return: Response string.
|
19
|
+
:rtype: str
|
20
|
+
"""
|
21
|
+
name = data.get("details", {}).get("job_deleted", {}).get("name")
|
22
|
+
change_gauge(f"{get_namespace()}.job.count", -1)
|
23
|
+
return f"Job {name} and its service successfully deleted."
|
24
|
+
|
25
|
+
|
26
|
+
@key_error_decorator_for_helpers
|
27
|
+
def job_list_response(data: dict) -> list:
|
28
|
+
job_pod_list = data.get("details", {}).get("job_pod_list", [])
|
29
|
+
job_list = data.get("details", {}).get("job_list", [])
|
30
|
+
setup_gauge(f"{get_namespace()}.job.count", len(job_list))
|
31
|
+
|
32
|
+
if not job_list:
|
33
|
+
raise NoJobsToList()
|
34
|
+
|
35
|
+
list_of_json_data = get_job_list(job_list, job_pod_list)
|
36
|
+
table = fill_missing_values_in_a_response(list_of_json_data)
|
37
|
+
|
38
|
+
return tabulate_a_response(table)
|
39
|
+
|
40
|
+
|
41
|
+
@key_error_decorator_for_helpers
|
42
|
+
def job_create_response(data: dict) -> str:
|
43
|
+
"""Create response string for job create command.
|
44
|
+
|
45
|
+
:param response: dict object from API response.
|
46
|
+
:type response: requests.Response
|
47
|
+
:return: Response string.
|
48
|
+
:rtype: str
|
49
|
+
"""
|
50
|
+
name = data.get("details", {}).get("job_created", {}).get("name")
|
51
|
+
change_gauge(f"{get_namespace()}.job.count", 1)
|
52
|
+
return f"Job {name} created successfully."
|
@@ -0,0 +1,176 @@
|
|
1
|
+
import json
|
2
|
+
import click
|
3
|
+
from typing import Optional
|
4
|
+
from cgc.commands.keys.keys_responses import (
|
5
|
+
create_ssh_key_response,
|
6
|
+
delete_ssh_key_response,
|
7
|
+
list_ssh_keys_response,
|
8
|
+
update_ssh_key_response,
|
9
|
+
)
|
10
|
+
from cgc.commands.keys.keys_utils import create_ssh_key_payload, update_ssh_key_payload
|
11
|
+
from cgc.commands.keys.keys_models import SSHKeyTypes
|
12
|
+
from cgc.utils.prepare_headers import get_api_url_and_prepare_headers
|
13
|
+
from cgc.utils.response_utils import retrieve_and_validate_response_send_metric
|
14
|
+
from cgc.utils.click_group import CustomGroup, CustomCommand
|
15
|
+
from cgc.utils.requests_helper import call_api, EndpointTypes
|
16
|
+
|
17
|
+
|
18
|
+
@click.group(name="keys", cls=CustomGroup)
|
19
|
+
def keys_group():
|
20
|
+
"""
|
21
|
+
Management of keys.
|
22
|
+
"""
|
23
|
+
|
24
|
+
|
25
|
+
@keys_group.group(name="ssh", cls=CustomGroup)
|
26
|
+
def ssh_keys_group():
|
27
|
+
"""
|
28
|
+
Management of ssh keys.
|
29
|
+
"""
|
30
|
+
|
31
|
+
|
32
|
+
@ssh_keys_group.command("create", cls=CustomCommand)
|
33
|
+
@click.option(
|
34
|
+
"-pk",
|
35
|
+
"--pub-key",
|
36
|
+
"public_key",
|
37
|
+
type=click.STRING,
|
38
|
+
required=False,
|
39
|
+
help="Whole Public key string",
|
40
|
+
)
|
41
|
+
@click.option(
|
42
|
+
"-kt",
|
43
|
+
"--key-type",
|
44
|
+
"key_type",
|
45
|
+
type=click.Choice(SSHKeyTypes.get_list(), case_sensitive=False),
|
46
|
+
required=False,
|
47
|
+
# default="ssh-rsa",
|
48
|
+
help="Type of the key",
|
49
|
+
)
|
50
|
+
@click.option(
|
51
|
+
"-k",
|
52
|
+
"--key",
|
53
|
+
"key",
|
54
|
+
type=click.STRING,
|
55
|
+
required=False,
|
56
|
+
help="Public key",
|
57
|
+
)
|
58
|
+
@click.option(
|
59
|
+
"-c",
|
60
|
+
"--comment",
|
61
|
+
"comment",
|
62
|
+
type=click.STRING,
|
63
|
+
required=False,
|
64
|
+
default="",
|
65
|
+
help="Comment for the key",
|
66
|
+
)
|
67
|
+
def create_ssh_key(
|
68
|
+
public_key: Optional[str] = None,
|
69
|
+
key_type: Optional[str] = None,
|
70
|
+
key: Optional[str] = None,
|
71
|
+
comment: str = "",
|
72
|
+
):
|
73
|
+
"""Create a new SSH key"""
|
74
|
+
api_url, headers = get_api_url_and_prepare_headers()
|
75
|
+
url = f"{api_url}/v1/api/keys/ssh/create"
|
76
|
+
metric = "keys.create"
|
77
|
+
__payload = create_ssh_key_payload(public_key, key_type, key, comment)
|
78
|
+
__res = call_api(
|
79
|
+
request=EndpointTypes.post,
|
80
|
+
url=url,
|
81
|
+
headers=headers,
|
82
|
+
data=json.dumps(__payload).encode("utf-8"),
|
83
|
+
)
|
84
|
+
click.echo(
|
85
|
+
create_ssh_key_response(
|
86
|
+
retrieve_and_validate_response_send_metric(__res, metric)
|
87
|
+
)
|
88
|
+
)
|
89
|
+
|
90
|
+
|
91
|
+
@ssh_keys_group.command("update", cls=CustomCommand)
|
92
|
+
@click.argument("key_id", type=click.STRING)
|
93
|
+
@click.option(
|
94
|
+
"-kt",
|
95
|
+
"--key-type",
|
96
|
+
"key_type",
|
97
|
+
type=click.Choice(SSHKeyTypes.get_list(), case_sensitive=False),
|
98
|
+
# default="ssh-rsa",
|
99
|
+
required=False,
|
100
|
+
help="Type of the key",
|
101
|
+
)
|
102
|
+
@click.option(
|
103
|
+
"-k",
|
104
|
+
"--key",
|
105
|
+
"key",
|
106
|
+
type=click.STRING,
|
107
|
+
required=False,
|
108
|
+
help="Public key",
|
109
|
+
)
|
110
|
+
@click.option(
|
111
|
+
"-c",
|
112
|
+
"--comment",
|
113
|
+
"comment",
|
114
|
+
type=click.STRING,
|
115
|
+
required=False,
|
116
|
+
help="Comment for the key",
|
117
|
+
)
|
118
|
+
def update_ssh_key(
|
119
|
+
key_id: str,
|
120
|
+
key_type: Optional[str] = None,
|
121
|
+
key: Optional[str] = None,
|
122
|
+
comment: Optional[str] = None,
|
123
|
+
):
|
124
|
+
"""Update an existing SSH key"""
|
125
|
+
api_url, headers = get_api_url_and_prepare_headers()
|
126
|
+
url = f"{api_url}/v1/api/keys/ssh/update/{key_id}"
|
127
|
+
metric = "keys.update"
|
128
|
+
__payload = update_ssh_key_payload(key_type, key, comment)
|
129
|
+
__res = call_api(
|
130
|
+
request=EndpointTypes.post,
|
131
|
+
url=url,
|
132
|
+
headers=headers,
|
133
|
+
data=json.dumps(__payload).encode("utf-8"),
|
134
|
+
)
|
135
|
+
click.echo(
|
136
|
+
update_ssh_key_response(
|
137
|
+
retrieve_and_validate_response_send_metric(__res, metric)
|
138
|
+
)
|
139
|
+
)
|
140
|
+
|
141
|
+
|
142
|
+
@ssh_keys_group.command("delete", cls=CustomCommand)
|
143
|
+
@click.argument("key_id", type=click.STRING)
|
144
|
+
def delete_ssh_key(key_id: str):
|
145
|
+
"""Delete an SSH key"""
|
146
|
+
api_url, headers = get_api_url_and_prepare_headers()
|
147
|
+
url = f"{api_url}/v1/api/keys/ssh/delete/{key_id}"
|
148
|
+
metric = "keys.delete"
|
149
|
+
__res = call_api(
|
150
|
+
request=EndpointTypes.delete,
|
151
|
+
url=url,
|
152
|
+
headers=headers,
|
153
|
+
)
|
154
|
+
click.echo(
|
155
|
+
delete_ssh_key_response(
|
156
|
+
retrieve_and_validate_response_send_metric(__res, metric)
|
157
|
+
)
|
158
|
+
)
|
159
|
+
|
160
|
+
|
161
|
+
@ssh_keys_group.command("list", cls=CustomCommand)
|
162
|
+
def list_ssh_keys():
|
163
|
+
"""List all SSH keys"""
|
164
|
+
api_url, headers = get_api_url_and_prepare_headers()
|
165
|
+
url = f"{api_url}/v1/api/keys/ssh/list"
|
166
|
+
metric = "keys.list"
|
167
|
+
__res = call_api(
|
168
|
+
request=EndpointTypes.get,
|
169
|
+
url=url,
|
170
|
+
headers=headers,
|
171
|
+
)
|
172
|
+
click.echo(
|
173
|
+
list_ssh_keys_response(
|
174
|
+
retrieve_and_validate_response_send_metric(__res, metric)
|
175
|
+
)
|
176
|
+
)
|
@@ -0,0 +1,16 @@
|
|
1
|
+
from cgc.commands.cgc_models import CGCEntityList
|
2
|
+
|
3
|
+
|
4
|
+
class SSHKeyTypes(CGCEntityList):
|
5
|
+
"""List of supported SSH key types
|
6
|
+
|
7
|
+
:param Enum: name of SSH key type
|
8
|
+
:type Enum: str
|
9
|
+
"""
|
10
|
+
|
11
|
+
RSA = "ssh-rsa"
|
12
|
+
DSS = "ssh-dss"
|
13
|
+
ECDSA_P256 = "ecdsa-sha2-nistp256"
|
14
|
+
ECDSA_P384 = "ecdsa-sha2-nistp384"
|
15
|
+
ECDSA_P521 = "ecdsa-sha2-nistp521"
|
16
|
+
ED25519 = "ssh-ed25519"
|
@@ -0,0 +1,47 @@
|
|
1
|
+
import click
|
2
|
+
from cgc.utils.message_utils import key_error_decorator_for_helpers
|
3
|
+
from cgc.commands.keys.keys_utils import get_user_ssh_keys
|
4
|
+
from cgc.utils.response_utils import (
|
5
|
+
fill_missing_values_in_a_response,
|
6
|
+
tabulate_a_response,
|
7
|
+
)
|
8
|
+
|
9
|
+
|
10
|
+
@key_error_decorator_for_helpers
|
11
|
+
def create_ssh_key_response(data: dict) -> dict:
|
12
|
+
"""Create a response for creating a new SSH key"""
|
13
|
+
try:
|
14
|
+
key_id = data["details"]["key_id"]
|
15
|
+
except KeyError:
|
16
|
+
raise click.ClickException("Key creation failed!")
|
17
|
+
return f"Key created with ID: {key_id}"
|
18
|
+
|
19
|
+
|
20
|
+
@key_error_decorator_for_helpers
|
21
|
+
def delete_ssh_key_response(data: dict) -> dict:
|
22
|
+
"""Create a response for deleting an SSH key"""
|
23
|
+
try:
|
24
|
+
key_id = data["details"]["key_id"]
|
25
|
+
except KeyError:
|
26
|
+
raise click.ClickException("Key deletion failed!")
|
27
|
+
return f"Key with ID: {key_id} deleted."
|
28
|
+
|
29
|
+
|
30
|
+
@key_error_decorator_for_helpers
|
31
|
+
def list_ssh_keys_response(data: dict) -> dict:
|
32
|
+
"""Create a response for listing all SSH keys"""
|
33
|
+
list_of_json_data = get_user_ssh_keys(data["details"])
|
34
|
+
table = fill_missing_values_in_a_response(list_of_json_data)
|
35
|
+
|
36
|
+
return tabulate_a_response(table)
|
37
|
+
|
38
|
+
|
39
|
+
@key_error_decorator_for_helpers
|
40
|
+
def update_ssh_key_response(data: dict) -> dict:
|
41
|
+
"""Create a response for updating an SSH key"""
|
42
|
+
try:
|
43
|
+
key_id = data["details"]["key_id"]
|
44
|
+
except KeyError:
|
45
|
+
return "Key updated."
|
46
|
+
else:
|
47
|
+
return f"Key updated. New key ID: {key_id}."
|
@@ -0,0 +1,79 @@
|
|
1
|
+
from typing import Optional
|
2
|
+
import click
|
3
|
+
from cgc.commands.keys.keys_models import SSHKeyTypes
|
4
|
+
|
5
|
+
|
6
|
+
def create_ssh_key_payload(
|
7
|
+
public_key: Optional[str] = None,
|
8
|
+
key_type: Optional[str] = None,
|
9
|
+
key: Optional[str] = None,
|
10
|
+
comment: str = "",
|
11
|
+
) -> dict:
|
12
|
+
"""Create a payload for creating a new SSH key"""
|
13
|
+
if public_key:
|
14
|
+
try:
|
15
|
+
key_parts = public_key.split(" ")
|
16
|
+
key_type = key_parts[0] if key_parts[0] in SSHKeyTypes.get_list() else ""
|
17
|
+
if not key_type:
|
18
|
+
raise click.ClickException("Invalid key type")
|
19
|
+
key = key_parts[1]
|
20
|
+
comment = key_parts[2] if len(key_parts) > 2 else comment
|
21
|
+
except IndexError:
|
22
|
+
raise click.ClickException("Invalid public key format")
|
23
|
+
if not key_type or not key:
|
24
|
+
raise click.ClickException("Invalid public key or key_type")
|
25
|
+
payload = {
|
26
|
+
"key_type": key_type,
|
27
|
+
"key": key,
|
28
|
+
"comment": comment,
|
29
|
+
}
|
30
|
+
return payload
|
31
|
+
|
32
|
+
|
33
|
+
def update_ssh_key_payload(
|
34
|
+
key_type: Optional[str] = None,
|
35
|
+
key: Optional[str] = None,
|
36
|
+
comment: Optional[str] = None,
|
37
|
+
) -> dict:
|
38
|
+
"""Create a payload for creating a new SSH key"""
|
39
|
+
payload = {}
|
40
|
+
if key_type:
|
41
|
+
if not key:
|
42
|
+
raise click.ClickException("Invalid public key")
|
43
|
+
payload["key_type"] = key_type
|
44
|
+
if key:
|
45
|
+
if not key_type:
|
46
|
+
raise click.ClickException("Invalid key_type")
|
47
|
+
payload["key"] = key
|
48
|
+
if comment:
|
49
|
+
payload["comment"] = comment
|
50
|
+
return payload
|
51
|
+
|
52
|
+
|
53
|
+
def get_user_ssh_keys(keys: list) -> list:
|
54
|
+
"""
|
55
|
+
Format list of keys for user
|
56
|
+
:param keys: list of user keys
|
57
|
+
:type keys: list
|
58
|
+
:return: formatted list of keys
|
59
|
+
:rtype: list
|
60
|
+
"""
|
61
|
+
output_data = []
|
62
|
+
|
63
|
+
for key in keys:
|
64
|
+
try:
|
65
|
+
key_data = {
|
66
|
+
"key_id": key["key_id"],
|
67
|
+
"key_type": key["key_type"],
|
68
|
+
"key": key["key"],
|
69
|
+
"comment": key["comment"],
|
70
|
+
"date_added": key["date_added"],
|
71
|
+
"date_updated": key["date_updated"],
|
72
|
+
}
|
73
|
+
# appending the rest of labels
|
74
|
+
key_data.update(key)
|
75
|
+
output_data.append(key_data)
|
76
|
+
except KeyError:
|
77
|
+
pass
|
78
|
+
|
79
|
+
return output_data
|
@@ -1,7 +1,8 @@
|
|
1
1
|
import click
|
2
2
|
import json
|
3
3
|
|
4
|
-
from cgc.commands.
|
4
|
+
from cgc.commands.db.db_models import DatabasesList
|
5
|
+
from cgc.commands.compute.compute_models import ComputesList
|
5
6
|
from cgc.commands.compute.compute_responses import (
|
6
7
|
template_list_response,
|
7
8
|
template_get_start_path_response,
|
cgc/sdk/__init__.py
CHANGED
@@ -1,6 +1,5 @@
|
|
1
|
-
from cgc.sdk.mongodb import get_mongo_access as mongo_client
|
2
|
-
from cgc.sdk.redis import get_redis_access as redis_client
|
3
1
|
from cgc.sdk.postgresql import get_postgresql_access as postgresql_client
|
4
2
|
|
5
3
|
import cgc.sdk.resource as resource
|
4
|
+
import cgc.sdk.job as job
|
6
5
|
import cgc.sdk.exceptions as exceptions
|