hcs-cli 0.1.320__py3-none-any.whl → 0.1.322__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.
- hcs_cli/__init__.py +1 -1
- hcs_cli/cmds/api.py +10 -28
- hcs_cli/cmds/clouddriver/{summary.py → service.py} +11 -4
- hcs_cli/cmds/dev/fs/provided_files/mqtt-secret.yaml +3 -3
- hcs_cli/cmds/hoc/stats.py +47 -21
- hcs_cli/cmds/scm/template.py +7 -3
- hcs_cli/cmds/task.py +48 -1
- hcs_cli/payload/lcm/azure-dummy.json +2 -1
- hcs_cli/payload/lcm/zero.json +3 -2
- hcs_cli/service/api.py +104 -0
- hcs_cli/service/clouddriver/__init__.py +2 -0
- hcs_cli/service/clouddriver/service.py +29 -0
- hcs_cli/service/task.py +6 -0
- hcs_cli/support/scm/plan-editor.html.template +570 -48
- hcs_cli/support/scm/plan_editor.py +73 -2
- {hcs_cli-0.1.320.dist-info → hcs_cli-0.1.322.dist-info}/METADATA +2 -2
- {hcs_cli-0.1.320.dist-info → hcs_cli-0.1.322.dist-info}/RECORD +20 -18
- /hcs_cli/payload/lcm/{zero-new.json → zero-legacy.json} +0 -0
- {hcs_cli-0.1.320.dist-info → hcs_cli-0.1.322.dist-info}/WHEEL +0 -0
- {hcs_cli-0.1.320.dist-info → hcs_cli-0.1.322.dist-info}/entry_points.txt +0 -0
hcs_cli/__init__.py
CHANGED
hcs_cli/cmds/api.py
CHANGED
|
@@ -3,8 +3,7 @@ import sys
|
|
|
3
3
|
|
|
4
4
|
import click
|
|
5
5
|
from hcs_core.ctxp import CtxpException, profile
|
|
6
|
-
from
|
|
7
|
-
from hcs_core.util.query_util import PageRequest
|
|
6
|
+
from hcs_cli.service import api as hcs_api
|
|
8
7
|
|
|
9
8
|
|
|
10
9
|
def _has_stdin_data():
|
|
@@ -143,12 +142,10 @@ def api(
|
|
|
143
142
|
if not path.startswith("/"):
|
|
144
143
|
raise click.UsageError("Path must start with a '/'. Please provide a valid context path. Provided path=" + path)
|
|
145
144
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
if is_regional_service(service_path):
|
|
149
|
-
client = regional_service_client(service_path, region=region)
|
|
145
|
+
if region or hdc:
|
|
146
|
+
handler = hcs_api.with_context(hdc=hdc, region=region)
|
|
150
147
|
else:
|
|
151
|
-
|
|
148
|
+
handler = hcs_api
|
|
152
149
|
|
|
153
150
|
if header:
|
|
154
151
|
headers = {h.split(":")[0].strip(): h.split(":")[1].strip() for h in header}
|
|
@@ -158,28 +155,13 @@ def api(
|
|
|
158
155
|
# print( f"{method} {api_path} text={raw_data} json={json_data}" )
|
|
159
156
|
|
|
160
157
|
if method == "GET":
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
def _get_page(query_string):
|
|
164
|
-
url = api_path
|
|
165
|
-
if url.find("?") > 0:
|
|
166
|
-
url += "&" + query_string
|
|
167
|
-
else:
|
|
168
|
-
url += "?" + query_string
|
|
169
|
-
ret = client.get(url)
|
|
170
|
-
return ret
|
|
171
|
-
|
|
172
|
-
response = PageRequest(_get_page, size=100, limit=0).get()
|
|
173
|
-
else:
|
|
174
|
-
response = client.get(api_path, headers=headers, raise_on_404=raise_on_404)
|
|
158
|
+
return handler.get(path, headers=headers, all_pages=all_pages, raise_on_404=raise_on_404)
|
|
175
159
|
elif method == "POST":
|
|
176
|
-
|
|
160
|
+
return handler.post(path, headers=headers, text=raw_data, json=json_data)
|
|
177
161
|
elif method == "PUT":
|
|
178
|
-
|
|
162
|
+
return handler.put(path, headers=headers, text=raw_data, json=json_data)
|
|
179
163
|
elif method == "DELETE":
|
|
180
|
-
|
|
164
|
+
return handler.delete(path, headers=headers, raise_on_404=raise_on_404)
|
|
181
165
|
elif method == "PATCH":
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
raise click.UsageError(f"Unsupported HTTP method: {method}")
|
|
185
|
-
return response
|
|
166
|
+
return handler.patch(path, headers=headers, text=raw_data, json=json_data)
|
|
167
|
+
raise click.UsageError(f"Unsupported HTTP method: {method}")
|
|
@@ -15,10 +15,17 @@ limitations under the License.
|
|
|
15
15
|
|
|
16
16
|
import click
|
|
17
17
|
|
|
18
|
-
from hcs_cli.service
|
|
18
|
+
from hcs_cli.service import clouddriver as cd
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
@click.command()
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
@click.argument("name", type=str, required=True)
|
|
23
|
+
def action(name: str, **kwargs):
|
|
24
|
+
"""Get perform an action"""
|
|
25
|
+
return cd.action(name, kwargs)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@click.command()
|
|
29
|
+
def health(**kwargs):
|
|
30
|
+
"""Get health"""
|
|
31
|
+
return cd.health()
|
|
@@ -75,7 +75,7 @@ stringData:
|
|
|
75
75
|
JcSvTMU2HOuQ/q6vFZq3PRbvroMeXlw2WJrqO3vu04SZwYiP8dcrlHTXQJh+Mp9T
|
|
76
76
|
mQ==
|
|
77
77
|
-----END CERTIFICATE-----
|
|
78
|
-
|
|
78
|
+
mqtt.ca-key: |-
|
|
79
79
|
-----BEGIN PRIVATE KEY-----
|
|
80
80
|
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDUNJx2Cf0noNHc
|
|
81
81
|
DXB9AFPSFMkkpwxb0wtqaCLiB7v5zkF7CVBl5LnecVk7CM8bJY62H90Lv8Zv/2sl
|
|
@@ -104,7 +104,7 @@ stringData:
|
|
|
104
104
|
boPQ+RK1VKj5UFkUKz5LiohLmCBEQ7sh1HBS2Vje8MFtg0P138sRlbMCvdAEARTZ
|
|
105
105
|
uQfAKLns7QFf9W1C60AVAQ==
|
|
106
106
|
-----END PRIVATE KEY-----
|
|
107
|
-
|
|
107
|
+
mqtt.client-cert: |-
|
|
108
108
|
-----BEGIN CERTIFICATE-----
|
|
109
109
|
MIIFKDCCAxCgAwIBAgIFALjj4O4wDQYJKoZIhvcNAQELBQAwdTELMAkGA1UEBhMC
|
|
110
110
|
VVMxCzAJBgNVBAgMAkNBMR8wHQYDVQQKDBZIb3Jpem9uIENsb3VkIFNlcnZpY2Vz
|
|
@@ -204,7 +204,7 @@ stringData:
|
|
|
204
204
|
JcSvTMU2HOuQ/q6vFZq3PRbvroMeXlw2WJrqO3vu04SZwYiP8dcrlHTXQJh+Mp9T
|
|
205
205
|
mQ==
|
|
206
206
|
-----END CERTIFICATE-----
|
|
207
|
-
|
|
207
|
+
mqtt.client-key: |-
|
|
208
208
|
-----BEGIN PRIVATE KEY-----
|
|
209
209
|
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC40aC4pyy0+++D
|
|
210
210
|
kD1cPRsMWO4ANZ8L4LaaHcg/e/1NbiExd/QlZESNJnnIyD29qY1h9WGEVDHtInsl
|
hcs_cli/cmds/hoc/stats.py
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import click
|
|
2
|
-
import
|
|
2
|
+
import datetime
|
|
3
3
|
import json
|
|
4
|
+
import time
|
|
5
|
+
|
|
4
6
|
from hcs_cli.service.hoc import diagnostic
|
|
5
7
|
from hcs_cli.service import tsctl
|
|
6
8
|
|
|
@@ -22,25 +24,49 @@ def aggregate_connects(from_: int, to: int, wait: bool, verbose: bool):
|
|
|
22
24
|
return "", 1
|
|
23
25
|
|
|
24
26
|
if wait:
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
27
|
+
wait_for_task(result)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@click.command(name="stats-aggregate-connects-day-before")
|
|
31
|
+
@click.option("--wait", type=bool, required=False, is_flag=True, default=False)
|
|
32
|
+
@click.option("--verbose", type=bool, required=False, is_flag=True, default=False)
|
|
33
|
+
def aggregate_connects_day_before(wait: bool, verbose: bool):
|
|
34
|
+
dt = datetime.datetime.utcnow().replace(hour=0, minute=0, second=0, microsecond=0)
|
|
35
|
+
dt_2_days_ago = dt - datetime.timedelta(days=2)
|
|
36
|
+
dt_1_day_ago = dt - datetime.timedelta(days=1)
|
|
37
|
+
|
|
38
|
+
print(f"Aggregating connect events from {dt_2_days_ago} to {dt_1_day_ago}")
|
|
39
|
+
from_ = int(dt_2_days_ago.timestamp())
|
|
40
|
+
to = int(dt_1_day_ago.timestamp())
|
|
41
|
+
payload = {"from": from_, "to": to}
|
|
42
|
+
result = diagnostic.aggregateConnects(payload, verbose=verbose)
|
|
43
|
+
click.echo(result)
|
|
44
|
+
if not result:
|
|
45
|
+
return "", 1
|
|
46
|
+
if wait:
|
|
47
|
+
wait_for_task(result)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def wait_for_task(result: dict):
|
|
51
|
+
print("Waiting for task to complete...")
|
|
52
|
+
totalWaitTime = 0
|
|
53
|
+
while True:
|
|
54
|
+
time.sleep(10)
|
|
55
|
+
taskStatus = tsctl.task.lastlog(result.namespace, result.group, result.taskKey)
|
|
56
|
+
if "state" in taskStatus and taskStatus.state == "Error":
|
|
57
|
+
print(f"Task is in {taskStatus.state} state - {taskStatus.error} ")
|
|
45
58
|
print(json.dumps(taskStatus, indent=2))
|
|
46
59
|
break
|
|
60
|
+
if "state" in taskStatus and taskStatus.state == "Success":
|
|
61
|
+
print("Task completed successfully.")
|
|
62
|
+
print(json.dumps(taskStatus, indent=2))
|
|
63
|
+
break
|
|
64
|
+
if ("state" in taskStatus and taskStatus.state == "") or "state" not in taskStatus:
|
|
65
|
+
print("Task is still in progress...")
|
|
66
|
+
totalWaitTime += 10
|
|
67
|
+
if totalWaitTime >= 600:
|
|
68
|
+
print("Waited for 10 minutes, exiting.")
|
|
69
|
+
break
|
|
70
|
+
continue
|
|
71
|
+
print(json.dumps(taskStatus, indent=2))
|
|
72
|
+
break
|
hcs_cli/cmds/scm/template.py
CHANGED
|
@@ -37,11 +37,15 @@ def template(id: str, org: str, **kwargs):
|
|
|
37
37
|
if not plan:
|
|
38
38
|
return None, 1
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
template_data = hcs.template.get(org_id=org_id, id=id)
|
|
41
41
|
|
|
42
|
-
plan["meta"]["maxCapacity"] =
|
|
42
|
+
plan["meta"]["maxCapacity"] = template_data["sparePolicy"]["limit"]
|
|
43
43
|
calendar = plan["calendar"]
|
|
44
44
|
for key in calendar:
|
|
45
45
|
calendar[key]["calculatedCapacity"] = calendar[key]["idealCapacity"]
|
|
46
46
|
calendar[key]["idealCapacity"] = calendar[key]["forecastCapacity"]
|
|
47
|
-
|
|
47
|
+
|
|
48
|
+
# fetch usage data for the usage chart
|
|
49
|
+
usage = hcs.scm.template_usage(org_id, id)
|
|
50
|
+
|
|
51
|
+
edit_plan(plan, template_data["name"], usage)
|
hcs_cli/cmds/task.py
CHANGED
|
@@ -17,6 +17,7 @@ import click
|
|
|
17
17
|
import hcs_core.sglib.cli_options as cli
|
|
18
18
|
import yumako
|
|
19
19
|
from hcs_core.ctxp import CtxpException, recent, util
|
|
20
|
+
from datetime import datetime
|
|
20
21
|
|
|
21
22
|
from hcs_cli.service import task
|
|
22
23
|
|
|
@@ -222,6 +223,7 @@ def use(namespace: str, group: str, smart_path: str, reset: bool, **kwargs):
|
|
|
222
223
|
required=False,
|
|
223
224
|
help="Filter tasks by state, for one-time tasks only. Comma separated values. E.g. Init,Running,Canceled,Error,Success",
|
|
224
225
|
)
|
|
226
|
+
@click.option("--v1", is_flag=True, default=False, required=False, help="Use v1 task API.")
|
|
225
227
|
@click.option("--v1log", is_flag=True, default=False, required=False, help="Fetch last log for v1 tasks.")
|
|
226
228
|
@cli.limit
|
|
227
229
|
@cli.search
|
|
@@ -476,7 +478,7 @@ def retrigger(org: str, namespace: str, group: str, smart_path: str, execution_i
|
|
|
476
478
|
return task.retrigger(org_id, namespace, group, key, execution_id)
|
|
477
479
|
|
|
478
480
|
|
|
479
|
-
@task_cmd_group.command()
|
|
481
|
+
@task_cmd_group.command(hidden=True)
|
|
480
482
|
@cli.org_id
|
|
481
483
|
@click.option("--namespace", "-n", type=str, required=False)
|
|
482
484
|
@click.option("--group", "-g", type=str, required=False)
|
|
@@ -496,6 +498,51 @@ def resubmit(org: str, namespace: str, group: str, smart_path: str, confirm: boo
|
|
|
496
498
|
return task.resubmit(org_id, namespace, group, key)
|
|
497
499
|
|
|
498
500
|
|
|
501
|
+
@task_cmd_group.command()
|
|
502
|
+
@cli.org_id
|
|
503
|
+
@click.option("--namespace", "-n", type=str, required=False)
|
|
504
|
+
@click.option("--group", "-g", type=str, required=False)
|
|
505
|
+
@click.option(
|
|
506
|
+
"--reference", "-r", type=str, required=True, help="Reference task to copy parameters from, format: [[<namespace>/]<group>/]<key>."
|
|
507
|
+
)
|
|
508
|
+
@click.option(
|
|
509
|
+
"--at", type=str, required=False, help="Schedule time, exact time 'YYYY-MM-DD HH:MM:SS', or delta time '1h30m', default is now."
|
|
510
|
+
)
|
|
511
|
+
@click.argument("smart_path", type=str, required=True)
|
|
512
|
+
def duplicate(org: str, namespace: str, group: str, smart_path: str, at: str, **kwargs):
|
|
513
|
+
"""Duplicate an existing task to run once, immediately or at a specific time."""
|
|
514
|
+
namespace, group, key = _parse_task_param(namespace, group, smart_path)
|
|
515
|
+
org_id = cli.get_org_id(org)
|
|
516
|
+
ret = task.get(org_id, namespace, group, key, **kwargs)
|
|
517
|
+
if not ret:
|
|
518
|
+
return f"Task {namespace}/{group}/{key} not found.", 1
|
|
519
|
+
|
|
520
|
+
# Clone the task
|
|
521
|
+
new_task = ret.model_copy()
|
|
522
|
+
new_task.key = None # Clear the key to let the system generate a new one
|
|
523
|
+
new_task.log = None # Clear the log for the new task
|
|
524
|
+
new_task.meta["_duplicatedFrom"] = key # Track the source task
|
|
525
|
+
|
|
526
|
+
# Handle schedule based on 'at' parameter
|
|
527
|
+
if at and at.lower() != "now":
|
|
528
|
+
now_ms = int(datetime.now().timestamp() * 1000)
|
|
529
|
+
try:
|
|
530
|
+
# Try to parse as exact time (YYYY-MM-DD HH:MM:SS)
|
|
531
|
+
scheduled_dt = datetime.strptime(at, "%Y-%m-%d %H:%M:%S")
|
|
532
|
+
scheduled_ms = int(scheduled_dt.timestamp() * 1000)
|
|
533
|
+
except ValueError:
|
|
534
|
+
# Parse as delta time (e.g., 1h30m)
|
|
535
|
+
delta_seconds = yumako.time.duration(at)
|
|
536
|
+
scheduled_ms = now_ms + int(delta_seconds * 1000)
|
|
537
|
+
|
|
538
|
+
if scheduled_ms > now_ms:
|
|
539
|
+
new_task.schedule = task.Schedule(initialDelayMs=scheduled_ms)
|
|
540
|
+
else:
|
|
541
|
+
new_task.schedule = None # run immediately
|
|
542
|
+
|
|
543
|
+
return task.create(org_id, namespace, new_task)
|
|
544
|
+
|
|
545
|
+
|
|
499
546
|
def _parse_task_param(namespace: str, group: str, smart_path: str):
|
|
500
547
|
if smart_path:
|
|
501
548
|
parts = smart_path.split("/")
|
hcs_cli/payload/lcm/zero.json
CHANGED
hcs_cli/service/api.py
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
from hcs_core.sglib.client_util import hdc_service_client, is_regional_service, regional_service_client
|
|
3
|
+
from hcs_core.util.query_util import PageRequest
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def _parse_path(path: str, hdc: str = None, region: str = None):
|
|
7
|
+
service_path = path.split("/")[1]
|
|
8
|
+
api_path = path[len(service_path) + 1 :]
|
|
9
|
+
if is_regional_service(service_path):
|
|
10
|
+
client = regional_service_client(service_path, region=region)
|
|
11
|
+
else:
|
|
12
|
+
client = hdc_service_client(service_path, hdc=hdc)
|
|
13
|
+
return api_path, client
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _get(
|
|
17
|
+
path: str, headers: Optional[dict] = None, all_pages: bool = False, raise_on_404: bool = False, hdc: str = None, region: str = None
|
|
18
|
+
):
|
|
19
|
+
api_path, client = _parse_path(path, hdc=hdc, region=region)
|
|
20
|
+
if all_pages:
|
|
21
|
+
|
|
22
|
+
def _get_page(query_string):
|
|
23
|
+
url = api_path
|
|
24
|
+
if url.find("?") > 0:
|
|
25
|
+
url += "&" + query_string
|
|
26
|
+
else:
|
|
27
|
+
url += "?" + query_string
|
|
28
|
+
ret = client.get(url)
|
|
29
|
+
return ret
|
|
30
|
+
|
|
31
|
+
return PageRequest(_get_page, size=100, limit=0).get()
|
|
32
|
+
else:
|
|
33
|
+
return client.get(api_path, headers=headers, raise_on_404=raise_on_404)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _post(
|
|
37
|
+
path: str, headers: Optional[dict] = None, text: Optional[str] = None, json: Optional[dict] = None, hdc: str = None, region: str = None
|
|
38
|
+
):
|
|
39
|
+
api_path, client = _parse_path(path, hdc=hdc, region=region)
|
|
40
|
+
return client.post(api_path, text=text, json=json, headers=headers)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _put(
|
|
44
|
+
path: str, headers: Optional[dict] = None, text: Optional[str] = None, json: Optional[dict] = None, hdc: str = None, region: str = None
|
|
45
|
+
):
|
|
46
|
+
api_path, client = _parse_path(path, hdc=hdc, region=region)
|
|
47
|
+
return client.put(api_path, text=text, json=json, headers=headers)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _delete(path: str, headers: Optional[dict] = None, raise_on_404: bool = False, hdc: str = None, region: str = None):
|
|
51
|
+
api_path, client = _parse_path(path, hdc=hdc, region=region)
|
|
52
|
+
return client.delete(api_path, headers=headers, raise_on_404=raise_on_404)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _patch(
|
|
56
|
+
path: str, headers: Optional[dict] = None, text: Optional[str] = None, json: Optional[dict] = None, hdc: str = None, region: str = None
|
|
57
|
+
):
|
|
58
|
+
api_path, client = _parse_path(path, hdc=hdc, region=region)
|
|
59
|
+
return client.patch(api_path, text=text, json=json, headers=headers)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class APIContext:
|
|
63
|
+
"""Context-aware API wrapper that maintains hdc and region for all requests."""
|
|
64
|
+
|
|
65
|
+
def __init__(self, hdc: str = None, region: str = None):
|
|
66
|
+
self.hdc = hdc
|
|
67
|
+
self.region = region
|
|
68
|
+
|
|
69
|
+
def get(self, path: str, headers: Optional[dict] = None, all_pages: bool = False, raise_on_404: bool = False):
|
|
70
|
+
return _get(path, headers=headers, all_pages=all_pages, raise_on_404=raise_on_404, hdc=self.hdc, region=self.region)
|
|
71
|
+
|
|
72
|
+
def post(self, path: str, headers: Optional[dict] = None, text: Optional[str] = None, json: Optional[dict] = None):
|
|
73
|
+
return _post(path, headers=headers, text=text, json=json, hdc=self.hdc, region=self.region)
|
|
74
|
+
|
|
75
|
+
def put(self, path: str, headers: Optional[dict] = None, text: Optional[str] = None, json: Optional[dict] = None):
|
|
76
|
+
return _put(path, headers=headers, text=text, json=json, hdc=self.hdc, region=self.region)
|
|
77
|
+
|
|
78
|
+
def delete(self, path: str, headers: Optional[dict] = None, raise_on_404: bool = False):
|
|
79
|
+
return _delete(path, headers=headers, raise_on_404=raise_on_404, hdc=self.hdc, region=self.region)
|
|
80
|
+
|
|
81
|
+
def patch(self, path: str, headers: Optional[dict] = None, text: Optional[str] = None, json: Optional[dict] = None):
|
|
82
|
+
return _patch(path, headers=headers, text=text, json=json, hdc=self.hdc, region=self.region)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def with_context(hdc: str = None, region: str = None):
|
|
86
|
+
"""Create a context-aware API wrapper with the specified hdc and region.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
hdc: HDC name for global services
|
|
90
|
+
region: Region name for regional services
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
APIContext: An object with get(), post(), put(), delete(), patch() methods
|
|
94
|
+
"""
|
|
95
|
+
return APIContext(hdc=hdc, region=region)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
_no_context_api = APIContext()
|
|
99
|
+
|
|
100
|
+
get = _no_context_api.get
|
|
101
|
+
post = _no_context_api.post
|
|
102
|
+
put = _no_context_api.put
|
|
103
|
+
delete = _no_context_api.delete
|
|
104
|
+
patch = _no_context_api.patch
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Copyright 2023-2023 VMware Inc.
|
|
3
|
+
SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
you may not use this file except in compliance with the License.
|
|
7
|
+
You may obtain a copy of the License at
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
See the License for the specific language governing permissions and
|
|
13
|
+
limitations under the License.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import logging
|
|
17
|
+
|
|
18
|
+
from hcs_core.sglib.client_util import hdc_service_client
|
|
19
|
+
|
|
20
|
+
log = logging.getLogger(__name__)
|
|
21
|
+
_client = hdc_service_client("clouddriver")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def action(name: str, params: dict):
|
|
25
|
+
return _client.post(f"/v1/action/{name}", params)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def health():
|
|
29
|
+
return _client.get("/v1/health")
|
hcs_cli/service/task.py
CHANGED
|
@@ -205,6 +205,12 @@ def resubmit(org_id: str, namespace: str, group: str, key: str, **kwargs):
|
|
|
205
205
|
return _tsctl_client.post(url, body)
|
|
206
206
|
|
|
207
207
|
|
|
208
|
+
def create(org_id: str, namespace: str, task: TaskModel, **kwargs):
|
|
209
|
+
url = f"/v1/namespaces/{namespace}/tasks?org_id={org_id}"
|
|
210
|
+
body = TaskModel.model_dump_json(task)
|
|
211
|
+
return _tsctl_client.post(url, body)
|
|
212
|
+
|
|
213
|
+
|
|
208
214
|
def logs(org_id: str, namespace: str, group: str, key: str, search: str, **kwargs):
|
|
209
215
|
search_parts = []
|
|
210
216
|
if org_id:
|