cgcsdk 1.0.5__py3-none-any.whl → 1.0.7__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 +21 -3
- cgc/cgc.py +5 -1
- cgc/commands/cgc_cmd.py +28 -3
- cgc/commands/cgc_cmd_responses.py +8 -0
- cgc/commands/cgc_helpers.py +0 -12
- cgc/commands/compute/compute_cmd.py +23 -10
- cgc/commands/compute/compute_models.py +2 -0
- cgc/commands/compute/compute_utills.py +16 -6
- cgc/commands/db/db_cmd.py +1 -1
- cgc/commands/jobs/__init__.py +10 -0
- cgc/commands/jobs/job_utils.py +175 -0
- cgc/commands/jobs/jobs_cmd.py +238 -0
- cgc/commands/jobs/jobs_responses.py +52 -0
- cgc/commands/resource/resource_cmd.py +2 -2
- cgc/commands/volume/volume_cmd.py +4 -4
- cgc/sdk/__init__.py +1 -0
- cgc/sdk/job.py +147 -0
- cgc/sdk/resource.py +52 -53
- cgc/utils/custom_exceptions.py +6 -1
- cgc/utils/prepare_headers.py +2 -2
- cgcsdk-1.0.7.dist-info/METADATA +70 -0
- {cgcsdk-1.0.5.dist-info → cgcsdk-1.0.7.dist-info}/RECORD +27 -22
- {cgcsdk-1.0.5.dist-info → cgcsdk-1.0.7.dist-info}/WHEEL +1 -1
- cgcsdk-1.0.5.dist-info/METADATA +0 -39
- {cgcsdk-1.0.5.dist-info → cgcsdk-1.0.7.dist-info}/LICENSE +0 -0
- {cgcsdk-1.0.5.dist-info → cgcsdk-1.0.7.dist-info}/entry_points.txt +0 -0
- {cgcsdk-1.0.5.dist-info → cgcsdk-1.0.7.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_pod_list, job_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."
|
@@ -72,7 +72,7 @@ def compute_restart(name: str):
|
|
72
72
|
request=EndpointTypes.post,
|
73
73
|
url=url,
|
74
74
|
headers=headers,
|
75
|
-
data=json.dumps(__payload),
|
75
|
+
data=json.dumps(__payload).encode("utf-8"),
|
76
76
|
)
|
77
77
|
click.echo(
|
78
78
|
compute_restart_response(
|
@@ -116,7 +116,7 @@ def resource_delete(name: str):
|
|
116
116
|
request=EndpointTypes.delete,
|
117
117
|
url=url,
|
118
118
|
headers=headers,
|
119
|
-
data=json.dumps(__payload),
|
119
|
+
data=json.dumps(__payload).encode("utf-8"),
|
120
120
|
)
|
121
121
|
click.echo(
|
122
122
|
compute_delete_response(
|
@@ -94,7 +94,7 @@ def volume_create(name: str, size: int, disk_type: str, access: str):
|
|
94
94
|
__res = call_api(
|
95
95
|
request=EndpointTypes.post,
|
96
96
|
url=url,
|
97
|
-
data=json.dumps(__payload),
|
97
|
+
data=json.dumps(__payload).encode("utf-8"),
|
98
98
|
headers=headers,
|
99
99
|
)
|
100
100
|
click.echo(
|
@@ -132,7 +132,7 @@ def volume_delete(name: str, force_delete: bool):
|
|
132
132
|
__res = call_api(
|
133
133
|
request=EndpointTypes.delete,
|
134
134
|
url=url,
|
135
|
-
data=json.dumps(__payload),
|
135
|
+
data=json.dumps(__payload).encode("utf-8"),
|
136
136
|
headers=headers,
|
137
137
|
)
|
138
138
|
click.echo(
|
@@ -182,7 +182,7 @@ def volume_umount(name: str, target_template_names):
|
|
182
182
|
__res = call_api(
|
183
183
|
request=EndpointTypes.post,
|
184
184
|
url=url,
|
185
|
-
data=json.dumps(__payload),
|
185
|
+
data=json.dumps(__payload).encode("utf-8"),
|
186
186
|
headers=headers,
|
187
187
|
)
|
188
188
|
click.echo(
|
@@ -270,7 +270,7 @@ def volume_mount(
|
|
270
270
|
__res = call_api(
|
271
271
|
request=EndpointTypes.post,
|
272
272
|
url=url,
|
273
|
-
data=json.dumps(__payload),
|
273
|
+
data=json.dumps(__payload).encode("utf-8"),
|
274
274
|
headers=headers,
|
275
275
|
)
|
276
276
|
click.echo(
|
cgc/sdk/__init__.py
CHANGED
cgc/sdk/job.py
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
import json as _json
|
2
|
+
from typing import Optional
|
3
|
+
import cgc.sdk.exceptions as _exceptions
|
4
|
+
from cgc.utils.custom_exceptions import CUSTOM_EXCEPTIONS
|
5
|
+
import cgc.utils.prepare_headers as _prepare_headers
|
6
|
+
import cgc.commands.jobs.job_utils as _job_utils
|
7
|
+
import cgc.utils.requests_helper as _requests_helper
|
8
|
+
import cgc.utils.response_utils as _response_utils
|
9
|
+
from cgc.commands.compute.compute_models import GPUsList
|
10
|
+
|
11
|
+
|
12
|
+
def job_create(
|
13
|
+
name: str,
|
14
|
+
image_name: str,
|
15
|
+
cpu: int = 1,
|
16
|
+
memory: int = 2,
|
17
|
+
shm_size: int = 0,
|
18
|
+
gpu: int = 0,
|
19
|
+
gpu_type: str = "A5000",
|
20
|
+
volumes: list = [],
|
21
|
+
volume_full_path: str = "",
|
22
|
+
startup_command: str = "",
|
23
|
+
repository_secret: str = "",
|
24
|
+
resource_data: list = [],
|
25
|
+
config_maps_data: list = [],
|
26
|
+
ttl_seconds_after_finished: Optional[int] = None,
|
27
|
+
):
|
28
|
+
"""
|
29
|
+
Create a custom compute resource.
|
30
|
+
|
31
|
+
:param name: The name of the compute resource.
|
32
|
+
:type name: str
|
33
|
+
:param image_name: The name of the image to use for the compute resource.
|
34
|
+
:type image_name: str,
|
35
|
+
:param cpu: The number of CPUs for the compute resource, defaults to 1.
|
36
|
+
:type cpu: int, optional
|
37
|
+
:param memory: The amount of memory (in GB) for the compute resource, defaults to 2.
|
38
|
+
:type memory: int, optional
|
39
|
+
:param shm_size: The size of the shared memory (in GB) for the compute resource, defaults to 0.
|
40
|
+
:type shm_size: int, optional
|
41
|
+
:param gpu: The number of GPUs for the compute resource, defaults to 0.
|
42
|
+
:type gpu: int, optional
|
43
|
+
:param gpu_type: The type of GPU for the compute resource, defaults to "A5000".
|
44
|
+
:type gpu_type: str, optional
|
45
|
+
:param volumes: The list of volumes to attach to the compute resource, defaults to [].
|
46
|
+
:type volumes: list, optional
|
47
|
+
:param volume_full_path: The full path of the volume, defaults to "".
|
48
|
+
:type volume_full_path: str, optional
|
49
|
+
:param startup_command: The startup command for the compute resource, defaults to "".
|
50
|
+
:type startup_command: str, optional
|
51
|
+
:param repository_secret: The secret for accessing the repository, defaults to "".
|
52
|
+
:type repository_secret: str, optional
|
53
|
+
:param resource_data: The additional resource data, defaults to [].
|
54
|
+
:type resource_data: list, optional
|
55
|
+
:param config_maps_data: The additional config maps data, defaults to [].
|
56
|
+
:type config_maps_data: list, optional
|
57
|
+
:param ttl_seconds_after_finished: The time to live in seconds after the app is finished, defaults to None.
|
58
|
+
:type ttl_seconds_after_finished: int, optional
|
59
|
+
:raises _SDKException: If the image name is not provided.
|
60
|
+
:raises _SDKException: If an invalid GPU type is specified.
|
61
|
+
:return: The response from the API call.
|
62
|
+
:rtype: _type_
|
63
|
+
"""
|
64
|
+
if not image_name:
|
65
|
+
raise _exceptions.SDKException(-2, "Image name is required")
|
66
|
+
api_url, headers = _prepare_headers.get_api_url_and_prepare_headers()
|
67
|
+
url = f"{api_url}/v1/api/job/create"
|
68
|
+
metric = "job.create"
|
69
|
+
gpu_type = gpu_type.upper()
|
70
|
+
if gpu_type not in GPUsList.get_list():
|
71
|
+
raise _exceptions.SDKException(-3, f"Invalid GPU type: {gpu_type}")
|
72
|
+
__payload = _job_utils.job_create_payload(
|
73
|
+
name=name,
|
74
|
+
cpu=cpu,
|
75
|
+
memory=memory,
|
76
|
+
gpu=gpu,
|
77
|
+
gpu_type=gpu_type,
|
78
|
+
volumes=volumes,
|
79
|
+
volume_full_path=volume_full_path,
|
80
|
+
resource_data=resource_data,
|
81
|
+
config_maps_data=config_maps_data,
|
82
|
+
shm_size=shm_size,
|
83
|
+
image_name=image_name,
|
84
|
+
startup_command=startup_command,
|
85
|
+
repository_secret=repository_secret,
|
86
|
+
ttl_seconds_after_finished=ttl_seconds_after_finished,
|
87
|
+
)
|
88
|
+
|
89
|
+
__res = _requests_helper.call_api(
|
90
|
+
request=_requests_helper.EndpointTypes.post,
|
91
|
+
url=url,
|
92
|
+
headers=headers,
|
93
|
+
data=_json.dumps(__payload).encode("utf-8"),
|
94
|
+
)
|
95
|
+
|
96
|
+
return _response_utils.retrieve_and_validate_response_send_metric_for_sdk(
|
97
|
+
__res, metric
|
98
|
+
)
|
99
|
+
|
100
|
+
|
101
|
+
def job_list():
|
102
|
+
"""
|
103
|
+
List jobs using backend endpoint.
|
104
|
+
|
105
|
+
:return: response from the API call
|
106
|
+
:rtype: dict
|
107
|
+
"""
|
108
|
+
api_url, headers = _prepare_headers.get_api_url_and_prepare_headers()
|
109
|
+
url = f"{api_url}/v1/api/job/list"
|
110
|
+
metric = "job.list"
|
111
|
+
__res = _requests_helper.call_api(
|
112
|
+
request=_requests_helper.EndpointTypes.get,
|
113
|
+
url=url,
|
114
|
+
headers=headers,
|
115
|
+
)
|
116
|
+
|
117
|
+
return _response_utils.retrieve_and_validate_response_send_metric_for_sdk(
|
118
|
+
__res, metric
|
119
|
+
)
|
120
|
+
# job_pod_list = _response.get("details", {}).get("job_pod_list", [])
|
121
|
+
# job_list = _response.get("details", {}).get("job_list", [])
|
122
|
+
# return _job_utils.get_job_list(job_pod_list, job_list)
|
123
|
+
|
124
|
+
|
125
|
+
def job_delete(name: str):
|
126
|
+
"""
|
127
|
+
Delete job using backend endpoint.
|
128
|
+
|
129
|
+
:param name: name of job to delete
|
130
|
+
:type name: str
|
131
|
+
:return: response from the API call
|
132
|
+
:rtype: dict
|
133
|
+
"""
|
134
|
+
api_url, headers = _prepare_headers.get_api_url_and_prepare_headers()
|
135
|
+
url = f"{api_url}/v1/api/job/delete"
|
136
|
+
metric = "job.delete"
|
137
|
+
__payload = _job_utils.job_delete_payload(name=name)
|
138
|
+
__res = _requests_helper.call_api(
|
139
|
+
request=_requests_helper.EndpointTypes.delete,
|
140
|
+
url=url,
|
141
|
+
headers=headers,
|
142
|
+
data=_json.dumps(__payload).encode("utf-8"),
|
143
|
+
)
|
144
|
+
|
145
|
+
return _response_utils.retrieve_and_validate_response_send_metric_for_sdk(
|
146
|
+
__res, metric
|
147
|
+
)
|
cgc/sdk/resource.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import json as _json
|
2
|
-
import re
|
3
2
|
import cgc.sdk.exceptions as _exceptions
|
3
|
+
from cgc.utils.custom_exceptions import CUSTOM_EXCEPTIONS
|
4
4
|
import cgc.utils.prepare_headers as _prepare_headers
|
5
5
|
import cgc.commands.compute.compute_utills as _compute_utills
|
6
6
|
import cgc.utils.requests_helper as _requests_helper
|
@@ -20,41 +20,36 @@ def start_function_loop(function, infinite: bool = True, *args, **kwargs):
|
|
20
20
|
**kwargs: Keyword arguments to be passed to the function.
|
21
21
|
|
22
22
|
Raises:
|
23
|
-
_SDKException: If the
|
23
|
+
_SDKException: If the response code is not 200 after 5 attempts (if finite) or if the response code is 409.
|
24
24
|
|
25
25
|
Returns:
|
26
26
|
None
|
27
27
|
"""
|
28
|
-
|
28
|
+
import logging
|
29
29
|
|
30
30
|
counter = 0
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
logging.warning(e)
|
54
|
-
else:
|
55
|
-
raise e
|
56
|
-
else:
|
57
|
-
return response
|
31
|
+
while True:
|
32
|
+
try:
|
33
|
+
counter += 1
|
34
|
+
response = function(*args, **kwargs)
|
35
|
+
|
36
|
+
if type(response) is bool:
|
37
|
+
if response:
|
38
|
+
break
|
39
|
+
elif type(response) is dict:
|
40
|
+
if response["code"] == 409:
|
41
|
+
raise _exceptions.SDKException(409, response)
|
42
|
+
return response
|
43
|
+
except _exceptions.SDKException as e:
|
44
|
+
if e.code == 409:
|
45
|
+
logging.warning(e)
|
46
|
+
return
|
47
|
+
logging.error(e)
|
48
|
+
finally:
|
49
|
+
if not infinite and counter > 4:
|
50
|
+
raise _exceptions.SDKException(
|
51
|
+
-1, "Response code not 200 after 5 attempts."
|
52
|
+
)
|
58
53
|
|
59
54
|
|
60
55
|
def stop_function_loop(function, infinite: bool = True, *args, **kwargs):
|
@@ -68,32 +63,35 @@ def stop_function_loop(function, infinite: bool = True, *args, **kwargs):
|
|
68
63
|
**kwargs: Arbitrary keyword arguments to be passed to the function.
|
69
64
|
|
70
65
|
Raises:
|
71
|
-
_SDKException: If the
|
66
|
+
_SDKException: If the response code is not 200 after 5 attempts (if finite) or if the response code is 404.
|
72
67
|
|
73
68
|
Returns:
|
74
69
|
None
|
75
70
|
"""
|
76
|
-
|
71
|
+
import logging
|
77
72
|
|
78
73
|
counter = 0
|
79
|
-
|
80
|
-
|
81
|
-
while not response:
|
82
|
-
counter += 1
|
83
|
-
if not infinite and counter > 10:
|
84
|
-
raise _exceptions.SDKException(-1, response)
|
85
|
-
sleep(5)
|
86
|
-
response = function(*args, **kwargs)
|
87
|
-
elif type(response) is dict:
|
88
|
-
while response["code"] != 200:
|
74
|
+
while True:
|
75
|
+
try:
|
89
76
|
counter += 1
|
90
|
-
if not infinite and counter > 10:
|
91
|
-
raise _exceptions.SDKException(-1, response)
|
92
|
-
sleep(5)
|
93
77
|
response = function(*args, **kwargs)
|
94
|
-
|
95
|
-
|
96
|
-
|
78
|
+
if type(response) is bool:
|
79
|
+
if not response:
|
80
|
+
break
|
81
|
+
elif type(response) is dict:
|
82
|
+
if response["code"] == 404:
|
83
|
+
raise _exceptions.SDKException(404, response)
|
84
|
+
return response
|
85
|
+
except _exceptions.SDKException as e:
|
86
|
+
if e.code == 404:
|
87
|
+
logging.warning(e)
|
88
|
+
return
|
89
|
+
logging.error(e)
|
90
|
+
finally:
|
91
|
+
if not infinite and counter > 4:
|
92
|
+
raise _exceptions.SDKException(
|
93
|
+
-1, "Response code not 200 after 5 attempts."
|
94
|
+
)
|
97
95
|
|
98
96
|
|
99
97
|
def compute_list():
|
@@ -116,6 +114,7 @@ def compute_list():
|
|
116
114
|
class ResourceTypes(_Enum):
|
117
115
|
compute = "compute"
|
118
116
|
db = "db"
|
117
|
+
job = "job"
|
119
118
|
|
120
119
|
|
121
120
|
def _resource_status_ready(name: str, response: dict):
|
@@ -266,7 +265,7 @@ def compute_create_custom(
|
|
266
265
|
request=_requests_helper.EndpointTypes.post,
|
267
266
|
url=url,
|
268
267
|
headers=headers,
|
269
|
-
data=_json.dumps(__payload),
|
268
|
+
data=_json.dumps(__payload).encode("utf-8"),
|
270
269
|
)
|
271
270
|
|
272
271
|
return _response_utils.retrieve_and_validate_response_send_metric_for_sdk(
|
@@ -302,7 +301,7 @@ def resource_update_port(
|
|
302
301
|
request=_requests_helper.EndpointTypes.post,
|
303
302
|
url=url,
|
304
303
|
headers=headers,
|
305
|
-
data=_json.dumps(__payload),
|
304
|
+
data=_json.dumps(__payload).encode("utf-8"),
|
306
305
|
)
|
307
306
|
|
308
307
|
return _response_utils.retrieve_and_validate_response_send_metric_for_sdk(
|
@@ -336,7 +335,7 @@ def resource_add_port(name: str, port_name: str, new_port: int, ingress: bool =
|
|
336
335
|
request=_requests_helper.EndpointTypes.post,
|
337
336
|
url=url,
|
338
337
|
headers=headers,
|
339
|
-
data=_json.dumps(__payload),
|
338
|
+
data=_json.dumps(__payload).encode("utf-8"),
|
340
339
|
)
|
341
340
|
|
342
341
|
return _response_utils.retrieve_and_validate_response_send_metric_for_sdk(
|
@@ -369,7 +368,7 @@ def resource_delete_port(
|
|
369
368
|
request=_requests_helper.EndpointTypes.post,
|
370
369
|
url=url,
|
371
370
|
headers=headers,
|
372
|
-
data=_json.dumps(__payload),
|
371
|
+
data=_json.dumps(__payload).encode("utf-8"),
|
373
372
|
)
|
374
373
|
|
375
374
|
return _response_utils.retrieve_and_validate_response_send_metric_for_sdk(
|
@@ -417,7 +416,7 @@ def resource_delete(name: str):
|
|
417
416
|
request=_requests_helper.EndpointTypes.delete,
|
418
417
|
url=url,
|
419
418
|
headers=headers,
|
420
|
-
data=_json.dumps(__payload),
|
419
|
+
data=_json.dumps(__payload).encode("utf-8"),
|
421
420
|
)
|
422
421
|
|
423
422
|
return _response_utils.retrieve_and_validate_response_send_metric_for_sdk(
|