cgcsdk 1.0.7__py3-none-any.whl → 1.0.10__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 +29 -0
- cgc/cgc.py +4 -0
- 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_models.py +9 -0
- cgc/commands/compute/compute_cmd.py +1 -1
- cgc/commands/compute/compute_models.py +1 -23
- cgc/commands/compute/compute_responses.py +1 -1
- cgc/commands/db/db_cmd.py +8 -2
- cgc/commands/db/db_models.py +37 -0
- cgc/commands/exceptions.py +8 -0
- cgc/commands/jobs/job_utils.py +37 -32
- cgc/commands/jobs/jobs_responses.py +1 -1
- cgc/commands/resource/resource_cmd.py +3 -2
- cgc/commands/user/__init__.py +14 -0
- cgc/commands/user/keys_cmd.py +179 -0
- cgc/commands/user/keys_models.py +16 -0
- cgc/commands/user/keys_responses.py +44 -0
- cgc/commands/user/keys_utils.py +79 -0
- cgc/commands/user/secret_cmd.py +154 -0
- cgc/commands/user/secret_responses.py +44 -0
- cgc/commands/user/secret_utils.py +60 -0
- cgc/sdk/__init__.py +0 -2
- cgc/sdk/job.py +1 -1
- cgc/sdk/resource.py +6 -6
- cgc/tests/responses_tests.py +1 -1
- 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 +3 -0
- cgc/utils/message_utils.py +1 -1
- cgc/utils/prepare_headers.py +22 -13
- cgc/utils/requests_helper.py +2 -2
- cgcsdk-1.0.10.dist-info/LICENSE +0 -0
- {cgcsdk-1.0.7.dist-info → cgcsdk-1.0.10.dist-info}/METADATA +3 -7
- {cgcsdk-1.0.7.dist-info → cgcsdk-1.0.10.dist-info}/RECORD +44 -36
- cgc/sdk/handlers.py +0 -24
- cgc/sdk/mongodb.py +0 -204
- cgc/sdk/redis.py +0 -91
- /cgc/commands/compute/{compute_utills.py → compute_utils.py} +0 -0
- /cgcsdk-1.0.7.dist-info/LICENSE → /cgc/commands/user/secret_models.py +0 -0
- {cgcsdk-1.0.7.dist-info → cgcsdk-1.0.10.dist-info}/WHEEL +0 -0
- {cgcsdk-1.0.7.dist-info → cgcsdk-1.0.10.dist-info}/entry_points.txt +0 -0
- {cgcsdk-1.0.7.dist-info → cgcsdk-1.0.10.dist-info}/top_level.txt +0 -0
@@ -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,44 @@
|
|
1
|
+
import click
|
2
|
+
from cgc.utils.message_utils import key_error_decorator_for_helpers
|
3
|
+
from cgc.commands.user.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) -> str:
|
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) -> str:
|
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) -> str:
|
32
|
+
"""Create a response for listing all SSH keys"""
|
33
|
+
list_of_json_data = get_user_ssh_keys(data["details"])
|
34
|
+
if not list_of_json_data:
|
35
|
+
return "No keys found."
|
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 update_ssh_key_response(_: dict) -> str:
|
43
|
+
"""Create a response for updating an SSH key"""
|
44
|
+
return "Key updated."
|
@@ -0,0 +1,79 @@
|
|
1
|
+
from typing import Optional
|
2
|
+
import click
|
3
|
+
from cgc.commands.user.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
|
@@ -0,0 +1,154 @@
|
|
1
|
+
import json
|
2
|
+
from typing import Optional, Set
|
3
|
+
import click
|
4
|
+
|
5
|
+
from cgc.utils.prepare_headers import get_api_url_and_prepare_headers
|
6
|
+
from cgc.utils.response_utils import retrieve_and_validate_response_send_metric
|
7
|
+
from cgc.utils.click_group import CustomGroup, CustomCommand
|
8
|
+
from cgc.utils.requests_helper import call_api, EndpointTypes
|
9
|
+
from cgc.commands.user.secret_utils import create_secret_payload, update_secret_payload
|
10
|
+
from cgc.commands.user.secret_responses import (
|
11
|
+
create_secret_response,
|
12
|
+
update_secret_response,
|
13
|
+
delete_secret_response,
|
14
|
+
list_secrets_response,
|
15
|
+
)
|
16
|
+
|
17
|
+
|
18
|
+
@click.group(name="secret", cls=CustomGroup)
|
19
|
+
def secret_group():
|
20
|
+
"""
|
21
|
+
Management of secrets.
|
22
|
+
"""
|
23
|
+
|
24
|
+
|
25
|
+
@secret_group.command("create", cls=CustomCommand)
|
26
|
+
@click.argument("secret_name", type=click.STRING)
|
27
|
+
@click.option(
|
28
|
+
"-r",
|
29
|
+
"--registry-list",
|
30
|
+
"registry_list",
|
31
|
+
multiple=True,
|
32
|
+
help="URL of the registry",
|
33
|
+
required=True,
|
34
|
+
)
|
35
|
+
@click.option(
|
36
|
+
"-u",
|
37
|
+
"--username",
|
38
|
+
"username",
|
39
|
+
type=click.STRING,
|
40
|
+
help="Username for the registry",
|
41
|
+
required=True,
|
42
|
+
)
|
43
|
+
@click.option(
|
44
|
+
"-p",
|
45
|
+
"--password",
|
46
|
+
"password",
|
47
|
+
type=click.STRING,
|
48
|
+
help="Password for the username",
|
49
|
+
required=True,
|
50
|
+
)
|
51
|
+
def create_secret(
|
52
|
+
secret_name: str, registry_list: Set[str], username: str, password: str
|
53
|
+
):
|
54
|
+
"""Create a new secret in the namespace"""
|
55
|
+
api_url, headers = get_api_url_and_prepare_headers()
|
56
|
+
url = f"{api_url}/v1/api/secret/create"
|
57
|
+
metric = "user.secret.create"
|
58
|
+
__payload = create_secret_payload(secret_name, registry_list, username, password)
|
59
|
+
__res = call_api(
|
60
|
+
request=EndpointTypes.post,
|
61
|
+
url=url,
|
62
|
+
headers=headers,
|
63
|
+
data=json.dumps(__payload).encode("utf-8"),
|
64
|
+
)
|
65
|
+
click.echo(
|
66
|
+
create_secret_response(
|
67
|
+
retrieve_and_validate_response_send_metric(__res, metric)
|
68
|
+
),
|
69
|
+
color="green",
|
70
|
+
)
|
71
|
+
|
72
|
+
|
73
|
+
@secret_group.command("update", cls=CustomCommand)
|
74
|
+
@click.argument("secret_name", type=click.STRING)
|
75
|
+
@click.option(
|
76
|
+
"-r",
|
77
|
+
"--registry-list",
|
78
|
+
"registry_list",
|
79
|
+
multiple=True,
|
80
|
+
help="URL of the registry",
|
81
|
+
)
|
82
|
+
@click.option(
|
83
|
+
"-u",
|
84
|
+
"--username",
|
85
|
+
"username",
|
86
|
+
type=click.STRING,
|
87
|
+
help="Username for the registry",
|
88
|
+
)
|
89
|
+
@click.option(
|
90
|
+
"-p",
|
91
|
+
"--password",
|
92
|
+
"password",
|
93
|
+
type=click.STRING,
|
94
|
+
help="Password for the username",
|
95
|
+
)
|
96
|
+
def update_secret(
|
97
|
+
secret_name: str,
|
98
|
+
registry_list: Optional[Set[str]] = None,
|
99
|
+
username: Optional[str] = None,
|
100
|
+
password: Optional[str] = None,
|
101
|
+
):
|
102
|
+
"""Update an existing secret in the namespace"""
|
103
|
+
api_url, headers = get_api_url_and_prepare_headers()
|
104
|
+
url = f"{api_url}/v1/api/secret/manage/{secret_name}"
|
105
|
+
metric = "user.secret.update"
|
106
|
+
__payload = update_secret_payload(registry_list, username, password)
|
107
|
+
__res = call_api(
|
108
|
+
request=EndpointTypes.put,
|
109
|
+
url=url,
|
110
|
+
headers=headers,
|
111
|
+
data=json.dumps(__payload).encode("utf-8"),
|
112
|
+
)
|
113
|
+
click.echo(
|
114
|
+
update_secret_response(
|
115
|
+
retrieve_and_validate_response_send_metric(__res, metric)
|
116
|
+
),
|
117
|
+
color="green",
|
118
|
+
)
|
119
|
+
|
120
|
+
|
121
|
+
@secret_group.command("delete", cls=CustomCommand)
|
122
|
+
@click.argument("secret_name", type=click.STRING)
|
123
|
+
def delete_secret(secret_name: str):
|
124
|
+
"""Delete an secret"""
|
125
|
+
api_url, headers = get_api_url_and_prepare_headers()
|
126
|
+
url = f"{api_url}/v1/api/secret/manage/{secret_name}"
|
127
|
+
metric = "user.secret.delete"
|
128
|
+
__res = call_api(
|
129
|
+
request=EndpointTypes.delete,
|
130
|
+
url=url,
|
131
|
+
headers=headers,
|
132
|
+
)
|
133
|
+
click.echo(
|
134
|
+
delete_secret_response(
|
135
|
+
retrieve_and_validate_response_send_metric(__res, metric)
|
136
|
+
),
|
137
|
+
color="green",
|
138
|
+
)
|
139
|
+
|
140
|
+
|
141
|
+
@secret_group.command("list", cls=CustomCommand)
|
142
|
+
def list_secrets():
|
143
|
+
"""List all secrets in the namespace"""
|
144
|
+
api_url, headers = get_api_url_and_prepare_headers()
|
145
|
+
url = f"{api_url}/v1/api/secret/list"
|
146
|
+
metric = "user.secret.list"
|
147
|
+
__res = call_api(
|
148
|
+
request=EndpointTypes.get,
|
149
|
+
url=url,
|
150
|
+
headers=headers,
|
151
|
+
)
|
152
|
+
click.echo(
|
153
|
+
list_secrets_response(retrieve_and_validate_response_send_metric(__res, metric))
|
154
|
+
)
|
@@ -0,0 +1,44 @@
|
|
1
|
+
import click
|
2
|
+
|
3
|
+
from cgc.commands.user import NoSecretsToList
|
4
|
+
from cgc.commands.user.secret_utils import get_secret_list
|
5
|
+
from cgc.telemetry.basic import setup_gauge
|
6
|
+
from cgc.utils.config_utils import get_namespace
|
7
|
+
from cgc.utils.message_utils import key_error_decorator_for_helpers
|
8
|
+
from cgc.utils.response_utils import (
|
9
|
+
fill_missing_values_in_a_response,
|
10
|
+
tabulate_a_response,
|
11
|
+
)
|
12
|
+
|
13
|
+
|
14
|
+
@key_error_decorator_for_helpers
|
15
|
+
def create_secret_response(data: dict) -> str:
|
16
|
+
"""Create a response for creating a new secret in the namespace"""
|
17
|
+
return f'Secret {data.get("details", {}).get("secret_name")} successfully created.'
|
18
|
+
|
19
|
+
|
20
|
+
@key_error_decorator_for_helpers
|
21
|
+
def update_secret_response(data: dict) -> str:
|
22
|
+
"""Create a response for updating a secret in the namespace"""
|
23
|
+
return f'Secret {data.get("details", {}).get("secret_name")} successfully updated.'
|
24
|
+
|
25
|
+
|
26
|
+
@key_error_decorator_for_helpers
|
27
|
+
def delete_secret_response(data: dict) -> str:
|
28
|
+
"""Create a response for deleting a secret in the namespace"""
|
29
|
+
return f'Secret {data.get("details", {}).get("secret_name")} successfully deleted.'
|
30
|
+
|
31
|
+
|
32
|
+
@key_error_decorator_for_helpers
|
33
|
+
def list_secrets_response(data: dict) -> str:
|
34
|
+
"""Create a response for listing all secrets in the namespace"""
|
35
|
+
secret_list = data.get("details", {}).get("secret_names", [])
|
36
|
+
setup_gauge(f"{get_namespace()}.secret.count", len(secret_list))
|
37
|
+
|
38
|
+
if not secret_list:
|
39
|
+
raise NoSecretsToList()
|
40
|
+
|
41
|
+
list_of_json_data = get_secret_list(secret_list)
|
42
|
+
table = fill_missing_values_in_a_response(list_of_json_data)
|
43
|
+
|
44
|
+
return tabulate_a_response(table)
|
@@ -0,0 +1,60 @@
|
|
1
|
+
from typing import Set
|
2
|
+
|
3
|
+
|
4
|
+
def create_secret_payload(
|
5
|
+
secret_name: str, registry_list: Set[str], username: str, password: str
|
6
|
+
) -> dict:
|
7
|
+
"""Create a payload for creating a new secret"""
|
8
|
+
payload = {
|
9
|
+
"name": secret_name,
|
10
|
+
"registry_list": registry_list,
|
11
|
+
"username": username,
|
12
|
+
"password": password,
|
13
|
+
}
|
14
|
+
return payload
|
15
|
+
|
16
|
+
|
17
|
+
def update_secret_payload(
|
18
|
+
registry_list: Set[str], username: str, password: str
|
19
|
+
) -> dict:
|
20
|
+
"""Create a payload for updating a secret"""
|
21
|
+
payload = {}
|
22
|
+
if registry_list:
|
23
|
+
payload["registry_list"] = registry_list
|
24
|
+
if username:
|
25
|
+
payload["username"] = username
|
26
|
+
if password:
|
27
|
+
payload["password"] = password
|
28
|
+
return payload
|
29
|
+
|
30
|
+
|
31
|
+
def _get_secret_json_data(secret_list: list):
|
32
|
+
"""Formats and returns list of secrets to print.
|
33
|
+
|
34
|
+
:param job_list: list of secrets
|
35
|
+
:type job_list: list
|
36
|
+
:return: formatted list of secrets
|
37
|
+
:rtype: list
|
38
|
+
"""
|
39
|
+
output_data = []
|
40
|
+
|
41
|
+
for secret in secret_list:
|
42
|
+
try:
|
43
|
+
|
44
|
+
secret_data = {
|
45
|
+
"name": secret.get("secret"),
|
46
|
+
"secret_type": secret.get("secret_type"),
|
47
|
+
"registry_list": secret.get("registry_list", []),
|
48
|
+
"secret_admin": secret.get("secret_admin"),
|
49
|
+
"date_created": f'{secret.get("date_created")} UTC',
|
50
|
+
"whitelist": secret.get("whitelist", ["*"]),
|
51
|
+
}
|
52
|
+
output_data.append(secret_data)
|
53
|
+
except KeyError:
|
54
|
+
pass
|
55
|
+
|
56
|
+
return output_data
|
57
|
+
|
58
|
+
|
59
|
+
def get_secret_list(secret_list: list):
|
60
|
+
return _get_secret_json_data(secret_list)
|
cgc/sdk/__init__.py
CHANGED
cgc/sdk/job.py
CHANGED
@@ -119,7 +119,7 @@ def job_list():
|
|
119
119
|
)
|
120
120
|
# job_pod_list = _response.get("details", {}).get("job_pod_list", [])
|
121
121
|
# job_list = _response.get("details", {}).get("job_list", [])
|
122
|
-
# return _job_utils.get_job_list(
|
122
|
+
# return _job_utils.get_job_list(job_list)
|
123
123
|
|
124
124
|
|
125
125
|
def job_delete(name: str):
|
cgc/sdk/resource.py
CHANGED
@@ -2,7 +2,7 @@ import json as _json
|
|
2
2
|
import cgc.sdk.exceptions as _exceptions
|
3
3
|
from cgc.utils.custom_exceptions import CUSTOM_EXCEPTIONS
|
4
4
|
import cgc.utils.prepare_headers as _prepare_headers
|
5
|
-
import cgc.commands.compute.
|
5
|
+
import cgc.commands.compute.compute_utils as _compute_utils
|
6
6
|
import cgc.utils.requests_helper as _requests_helper
|
7
7
|
import cgc.utils.response_utils as _response_utils
|
8
8
|
from enum import Enum as _Enum
|
@@ -243,7 +243,7 @@ def compute_create_custom(
|
|
243
243
|
gpu_type = gpu_type.upper()
|
244
244
|
if gpu_type not in GPUsList.get_list():
|
245
245
|
raise _exceptions.SDKException(-3, f"Invalid GPU type: {gpu_type}")
|
246
|
-
__payload =
|
246
|
+
__payload = _compute_utils.compute_create_payload(
|
247
247
|
name=name,
|
248
248
|
entity="custom",
|
249
249
|
cpu=cpu,
|
@@ -291,7 +291,7 @@ def resource_update_port(
|
|
291
291
|
api_url, headers = _prepare_headers.get_api_url_and_prepare_headers()
|
292
292
|
url = f"{api_url}/v1/api/resource/ports?port_modification_mode=UPDATE"
|
293
293
|
metric = "resource.ports.update"
|
294
|
-
__payload =
|
294
|
+
__payload = _compute_utils.port_modification_payload(
|
295
295
|
port_name=port_name,
|
296
296
|
port_number=new_port,
|
297
297
|
ingress=ingress,
|
@@ -325,7 +325,7 @@ def resource_add_port(name: str, port_name: str, new_port: int, ingress: bool =
|
|
325
325
|
api_url, headers = _prepare_headers.get_api_url_and_prepare_headers()
|
326
326
|
url = f"{api_url}/v1/api/resource/ports?port_modification_mode=ADD"
|
327
327
|
metric = "resource.ports.add"
|
328
|
-
__payload =
|
328
|
+
__payload = _compute_utils.port_modification_payload(
|
329
329
|
port_name=port_name,
|
330
330
|
port_number=new_port,
|
331
331
|
ingress=ingress,
|
@@ -360,7 +360,7 @@ def resource_delete_port(
|
|
360
360
|
api_url, headers = _prepare_headers.get_api_url_and_prepare_headers()
|
361
361
|
url = f"{api_url}/v1/api/resource/ports?port_modification_mode=DELETE"
|
362
362
|
metric = "resource.ports.delete"
|
363
|
-
__payload =
|
363
|
+
__payload = _compute_utils.port_delete_payload(
|
364
364
|
port_name=port_name,
|
365
365
|
app_name=name,
|
366
366
|
)
|
@@ -411,7 +411,7 @@ def resource_delete(name: str):
|
|
411
411
|
api_url, headers = _prepare_headers.get_api_url_and_prepare_headers()
|
412
412
|
url = f"{api_url}/v1/api/resource/delete"
|
413
413
|
metric = "resource.delete"
|
414
|
-
__payload =
|
414
|
+
__payload = _compute_utils.compute_delete_payload(name=name)
|
415
415
|
__res = _requests_helper.call_api(
|
416
416
|
request=_requests_helper.EndpointTypes.delete,
|
417
417
|
url=url,
|
cgc/tests/responses_tests.py
CHANGED
@@ -27,7 +27,7 @@ from cgc.utils.response_utils import (
|
|
27
27
|
tabulate_a_response,
|
28
28
|
fill_missing_values_in_a_response,
|
29
29
|
)
|
30
|
-
from cgc.commands.compute.
|
30
|
+
from cgc.commands.compute.compute_utils import get_app_list
|
31
31
|
|
32
32
|
|
33
33
|
class TestVolumeResponses(unittest.TestCase):
|
cgc/utils/__init__.py
CHANGED
@@ -20,6 +20,14 @@ def require_confirm_loop(message: str):
|
|
20
20
|
exit(0)
|
21
21
|
|
22
22
|
|
23
|
+
def require_answer_loop(message: str, default: str):
|
24
|
+
while True:
|
25
|
+
answer = input(f"{message}: [{default}]").lower()
|
26
|
+
if answer == "":
|
27
|
+
return default
|
28
|
+
return answer
|
29
|
+
|
30
|
+
|
23
31
|
def quick_sort(collection: list) -> list:
|
24
32
|
"""A pure Python implementation of quick sort algorithm
|
25
33
|
|
cgc/utils/config_utils.py
CHANGED
@@ -5,7 +5,7 @@ import click
|
|
5
5
|
|
6
6
|
from cgc.commands.auth import NoNamespaceInConfig, NoConfigFileFound
|
7
7
|
from cgc.utils.message_utils import prepare_error_message
|
8
|
-
from cgc.utils.consts.env_consts import get_config_file_name
|
8
|
+
from cgc.utils.consts.env_consts import CGC_API_URL, CGC_SECRET, get_config_file_name
|
9
9
|
|
10
10
|
|
11
11
|
def get_config_path():
|
@@ -78,6 +78,10 @@ def read_from_cfg(key: str, filename=None):
|
|
78
78
|
except KeyError:
|
79
79
|
if key == "namespace":
|
80
80
|
raise NoNamespaceInConfig()
|
81
|
+
elif key == "cgc_secret":
|
82
|
+
return CGC_SECRET
|
83
|
+
elif key == "cgc_api_url":
|
84
|
+
return CGC_API_URL
|
81
85
|
print("Config file is corrupted. Please contact support at support@comtegra.pl")
|
82
86
|
sys.exit()
|
83
87
|
|
cgc/utils/consts/env_consts.py
CHANGED
@@ -33,7 +33,7 @@ else:
|
|
33
33
|
raise Exception("not defined API_SECURE_CONNECTION. set yes/no")
|
34
34
|
|
35
35
|
API_PORT = os.getenv("API_PORT")
|
36
|
-
|
36
|
+
CGC_API_URL = f"{__prefix}://{API_HOST}:{API_PORT}"
|
37
37
|
TMP_DIR = os.getenv("TMP_DIR")
|
38
38
|
RELEASE = int(os.getenv("RELEASE"))
|
39
39
|
MAJOR_VERSION = int(os.getenv("MAJOR_VERSION"))
|
cgc/utils/custom_exceptions.py
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
CUSTOM_EXCEPTIONS = {
|
5
5
|
500: {
|
6
6
|
"UNDEFINED": "undefined exception",
|
7
|
+
"USER_KEY_CREATE_ERROR": "Error while creating key",
|
7
8
|
},
|
8
9
|
413: {
|
9
10
|
"PVC_CREATE_STORAGE_LIMIT_EXCEEDED": "This request exceeds your storage limits",
|
@@ -17,6 +18,7 @@ CUSTOM_EXCEPTIONS = {
|
|
17
18
|
"RESOURCE_PORTS_ALREADY_EXISTS": "Port with this name already exists.",
|
18
19
|
"RESOURCE_TEMPLATE_NAME_ALREADY_EXISTS": "Resource with this name already exists.",
|
19
20
|
"JOB_CREATE_ALREADY_EXISTS": "Job with this name already exists.",
|
21
|
+
"USER_KEY_ALREADY_EXISTS": "Key with these data already exists.",
|
20
22
|
},
|
21
23
|
404: {
|
22
24
|
"PVC_CREATE_NO_SC": "Selected disk type and access mode unavailable",
|
@@ -33,6 +35,7 @@ CUSTOM_EXCEPTIONS = {
|
|
33
35
|
"COMPUTE_RESOURCE_QUOTA_NOT_FOUND": "You do not have enforced limits on your namespace.",
|
34
36
|
"JOB_NOT_FOUND": "Job with this name not found.",
|
35
37
|
"RESOURCE_NOT_FOUND": "Resource with this name not found.",
|
38
|
+
"USER_KEY_NOT_FOUND": "Key with this id not found.",
|
36
39
|
},
|
37
40
|
400: {
|
38
41
|
"WRONG_DATE_FORMAT": "Wrong date format.",
|
cgc/utils/message_utils.py
CHANGED
@@ -58,7 +58,7 @@ def key_error_decorator_for_helpers(func):
|
|
58
58
|
if "debug" in kwargs:
|
59
59
|
raise err
|
60
60
|
return prepare_error_message(UNKNOWN_ERROR)
|
61
|
-
except ResponseException as err:
|
61
|
+
except (ResponseException, click.ClickException) as err:
|
62
62
|
return prepare_warning_message(err)
|
63
63
|
|
64
64
|
return wrapper
|
cgc/utils/prepare_headers.py
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
from cgc.utils.config_utils import read_from_cfg
|
2
|
-
from cgc.utils.consts.env_consts import API_URL, CGC_SECRET
|
3
2
|
from cgc.commands.auth import auth_utils
|
4
3
|
from cgc.utils.message_utils import key_error_decorator_for_helpers
|
5
4
|
|
@@ -13,41 +12,51 @@ def load_user_api_keys():
|
|
13
12
|
return read_from_cfg("api_key"), read_from_cfg("api_secret")
|
14
13
|
|
15
14
|
|
15
|
+
def load_user_cgc_secret():
|
16
|
+
return read_from_cfg("cgc_secret")
|
17
|
+
|
18
|
+
|
19
|
+
def load_user_api_url():
|
20
|
+
return read_from_cfg("cgc_api_url")
|
21
|
+
|
22
|
+
|
16
23
|
@key_error_decorator_for_helpers
|
17
24
|
def get_api_url_and_prepare_headers():
|
18
|
-
"""Loads
|
25
|
+
"""Loads CGC_API_URL and user api keys into single function. Mend to be used as single point of truth for all endpoints except register - due to different Content-Type header
|
19
26
|
|
20
|
-
:return:
|
27
|
+
:return: CGC_API_URL and headers
|
21
28
|
:rtype: string and dict
|
22
29
|
"""
|
23
30
|
api_key, api_secret = load_user_api_keys()
|
24
31
|
headers = {
|
25
|
-
"Content-Type": "application/json; charset=UTF-8",
|
26
32
|
"accept": "application/json",
|
33
|
+
"Content-Type": "application/json; charset=UTF-8",
|
34
|
+
"comtegra-cgc": load_user_cgc_secret(),
|
27
35
|
"api-key": api_key,
|
28
36
|
"api-secret": api_secret,
|
29
|
-
"comtegra-cgc": CGC_SECRET,
|
30
37
|
}
|
31
|
-
return
|
38
|
+
return load_user_api_url(), headers
|
32
39
|
|
33
40
|
|
34
|
-
def get_url_and_prepare_headers_register(
|
41
|
+
def get_url_and_prepare_headers_register(
|
42
|
+
user_id: str, access_key: str, url: str = None, secret: str = None
|
43
|
+
):
|
35
44
|
"""Creates and returns url and headers for register request.
|
36
45
|
|
37
46
|
:return: url, headers
|
38
47
|
:rtype: string and dict
|
39
48
|
"""
|
40
|
-
url = f"{
|
49
|
+
url = f"{load_user_api_url() if url is None else url}/v1/api/user/register?user_id={user_id}&access_key={access_key}"
|
41
50
|
headers = {
|
42
51
|
"accept": "application/json",
|
43
|
-
"comtegra-cgc": CGC_SECRET,
|
44
52
|
"Content-Type": "octet-stream",
|
53
|
+
"comtegra-cgc": load_user_cgc_secret() if secret is None else secret,
|
45
54
|
}
|
46
55
|
return url, headers
|
47
56
|
|
48
57
|
|
49
58
|
def get_url_and_headers_jwt_token():
|
50
|
-
url = f"{
|
59
|
+
url = f"{load_user_api_url()}/v1/api/user/create/token"
|
51
60
|
headers = {
|
52
61
|
"accept": "application/json",
|
53
62
|
"Content-Type": "application/x-www-form-urlencoded",
|
@@ -64,8 +73,8 @@ def prepare_headers_api_key(user_id: str = None, password: str = None):
|
|
64
73
|
"""
|
65
74
|
headers = {
|
66
75
|
"accept": "application/json",
|
67
|
-
"comtegra-cgc": CGC_SECRET,
|
68
76
|
"Authorization": f"Bearer {auth_utils.get_jwt(user_id, password)}",
|
77
|
+
"comtegra-cgc": load_user_cgc_secret(),
|
69
78
|
}
|
70
79
|
return headers
|
71
80
|
|
@@ -76,10 +85,10 @@ def get_api_url_and_prepare_headers_version_control():
|
|
76
85
|
:return: url and headers in a for of dictionary
|
77
86
|
:rtype: string, dict
|
78
87
|
"""
|
79
|
-
url = f"{
|
88
|
+
url = f"{load_user_api_url()}/v1/api/info/version"
|
80
89
|
headers = {
|
81
90
|
"accept": "application/json",
|
82
|
-
"comtegra-cgc": CGC_SECRET,
|
83
91
|
"Content-Type": "application/json",
|
92
|
+
"comtegra-cgc": load_user_cgc_secret(),
|
84
93
|
}
|
85
94
|
return url, headers
|
cgc/utils/requests_helper.py
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
import requests
|
2
2
|
import urllib3
|
3
3
|
import urllib3.exceptions
|
4
|
-
import ssl
|
5
4
|
import click
|
6
5
|
import sys
|
7
6
|
|
@@ -24,10 +23,11 @@ class EndpointTypes(Enum):
|
|
24
23
|
get = requests.get
|
25
24
|
post = requests.post
|
26
25
|
delete = requests.delete
|
26
|
+
put = requests.put
|
27
27
|
|
28
28
|
|
29
29
|
def _process_endpoint_kwargs(**kwargs):
|
30
|
-
if
|
30
|
+
if "timeout" not in kwargs.keys():
|
31
31
|
kwargs["timeout"] = 30
|
32
32
|
return kwargs
|
33
33
|
|
File without changes
|