yellowdog-cli 9.1.0__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.
- yellowdog_cli/__init__.py +3 -0
- yellowdog_cli/abort.py +142 -0
- yellowdog_cli/application.py +108 -0
- yellowdog_cli/boost.py +42 -0
- yellowdog_cli/cancel.py +182 -0
- yellowdog_cli/cloudwizard.py +83 -0
- yellowdog_cli/compare.py +722 -0
- yellowdog_cli/create.py +1401 -0
- yellowdog_cli/delete.py +83 -0
- yellowdog_cli/download.py +63 -0
- yellowdog_cli/finish.py +161 -0
- yellowdog_cli/follow.py +23 -0
- yellowdog_cli/format_json.py +54 -0
- yellowdog_cli/hold.py +18 -0
- yellowdog_cli/instantiate.py +339 -0
- yellowdog_cli/jsonnet2json.py +33 -0
- yellowdog_cli/list.py +976 -0
- yellowdog_cli/ls.py +189 -0
- yellowdog_cli/nodeaction.py +650 -0
- yellowdog_cli/provision.py +543 -0
- yellowdog_cli/remove.py +579 -0
- yellowdog_cli/resize.py +140 -0
- yellowdog_cli/show.py +325 -0
- yellowdog_cli/shutdown.py +170 -0
- yellowdog_cli/start.py +18 -0
- yellowdog_cli/submit.py +1464 -0
- yellowdog_cli/terminate.py +274 -0
- yellowdog_cli/upload.py +77 -0
- yellowdog_cli/utils/__init__.py +0 -0
- yellowdog_cli/utils/args.py +2198 -0
- yellowdog_cli/utils/check_imports.py +30 -0
- yellowdog_cli/utils/cloudwizard_aws.py +800 -0
- yellowdog_cli/utils/cloudwizard_aws_types.py +31 -0
- yellowdog_cli/utils/cloudwizard_azure.py +622 -0
- yellowdog_cli/utils/cloudwizard_common.py +363 -0
- yellowdog_cli/utils/cloudwizard_gcp.py +228 -0
- yellowdog_cli/utils/compact_json.py +106 -0
- yellowdog_cli/utils/config_types.py +101 -0
- yellowdog_cli/utils/csv_data.py +397 -0
- yellowdog_cli/utils/dataclient_utils.py +517 -0
- yellowdog_cli/utils/dataclient_wrapper.py +37 -0
- yellowdog_cli/utils/entity_utils.py +1176 -0
- yellowdog_cli/utils/follow_utils.py +393 -0
- yellowdog_cli/utils/interactive.py +190 -0
- yellowdog_cli/utils/items.py +67 -0
- yellowdog_cli/utils/load_config.py +757 -0
- yellowdog_cli/utils/load_resources.py +134 -0
- yellowdog_cli/utils/misc_utils.py +267 -0
- yellowdog_cli/utils/printing.py +1575 -0
- yellowdog_cli/utils/property_names.py +237 -0
- yellowdog_cli/utils/provision_utils.py +112 -0
- yellowdog_cli/utils/rclone_utils.py +166 -0
- yellowdog_cli/utils/rich_console_input_fixed.py +62 -0
- yellowdog_cli/utils/settings.py +232 -0
- yellowdog_cli/utils/start_hold_common.py +158 -0
- yellowdog_cli/utils/submit_utils.py +699 -0
- yellowdog_cli/utils/type_check.py +77 -0
- yellowdog_cli/utils/validate_properties.py +75 -0
- yellowdog_cli/utils/variables.py +689 -0
- yellowdog_cli/utils/wrapper.py +98 -0
- yellowdog_cli/utils/ydid_utils.py +143 -0
- yellowdog_cli/version.py +42 -0
- yellowdog_cli-9.1.0.dist-info/METADATA +106 -0
- yellowdog_cli-9.1.0.dist-info/RECORD +68 -0
- yellowdog_cli-9.1.0.dist-info/WHEEL +5 -0
- yellowdog_cli-9.1.0.dist-info/entry_points.txt +29 -0
- yellowdog_cli-9.1.0.dist-info/licenses/LICENSE +201 -0
- yellowdog_cli-9.1.0.dist-info/top_level.txt +1 -0
yellowdog_cli/abort.py
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
A script to abort Tasks without cancelling their Work Requirements.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from yellowdog_client.model import (
|
|
8
|
+
Task,
|
|
9
|
+
TaskSearch,
|
|
10
|
+
TaskStatus,
|
|
11
|
+
WorkRequirementStatus,
|
|
12
|
+
WorkRequirementSummary,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
from yellowdog_cli.utils.entity_utils import (
|
|
16
|
+
get_filtered_work_requirement_summaries,
|
|
17
|
+
get_task_group_name,
|
|
18
|
+
)
|
|
19
|
+
from yellowdog_cli.utils.interactive import confirmed, select
|
|
20
|
+
from yellowdog_cli.utils.printing import (
|
|
21
|
+
print_error,
|
|
22
|
+
print_info,
|
|
23
|
+
sorted_objects,
|
|
24
|
+
)
|
|
25
|
+
from yellowdog_cli.utils.wrapper import ARGS_PARSER, CLIENT, CONFIG_COMMON, main_wrapper
|
|
26
|
+
from yellowdog_cli.utils.ydid_utils import YDIDType, get_ydid_type
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@main_wrapper
|
|
30
|
+
def main():
|
|
31
|
+
|
|
32
|
+
if ARGS_PARSER.task_id_list:
|
|
33
|
+
_abort_tasks_by_name_or_id(ARGS_PARSER.task_id_list)
|
|
34
|
+
return
|
|
35
|
+
|
|
36
|
+
print_info(
|
|
37
|
+
"Finding active Work Requirements in "
|
|
38
|
+
f"namespace '{CONFIG_COMMON.namespace}' with tags "
|
|
39
|
+
f"including '{CONFIG_COMMON.name_tag}'"
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
# Abort Tasks is always interactive
|
|
43
|
+
ARGS_PARSER.interactive = True
|
|
44
|
+
|
|
45
|
+
selected_work_requirement_summaries: list[WorkRequirementSummary] = (
|
|
46
|
+
get_filtered_work_requirement_summaries(
|
|
47
|
+
CLIENT,
|
|
48
|
+
namespace=CONFIG_COMMON.namespace,
|
|
49
|
+
tag=CONFIG_COMMON.name_tag,
|
|
50
|
+
exclude_filter=[
|
|
51
|
+
WorkRequirementStatus.COMPLETED,
|
|
52
|
+
WorkRequirementStatus.CANCELLED,
|
|
53
|
+
WorkRequirementStatus.FAILED,
|
|
54
|
+
],
|
|
55
|
+
)
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
if selected_work_requirement_summaries:
|
|
59
|
+
selected_work_requirement_summaries = select(
|
|
60
|
+
CLIENT,
|
|
61
|
+
selected_work_requirement_summaries,
|
|
62
|
+
single_result=True,
|
|
63
|
+
override_quiet=True,
|
|
64
|
+
)
|
|
65
|
+
else:
|
|
66
|
+
print_info("No matching Work Requirements found")
|
|
67
|
+
|
|
68
|
+
if len(selected_work_requirement_summaries) == 1:
|
|
69
|
+
abort_tasks_selectively(selected_work_requirement_summaries[0])
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def abort_tasks_selectively(
|
|
73
|
+
wr_summary: WorkRequirementSummary,
|
|
74
|
+
) -> None:
|
|
75
|
+
"""
|
|
76
|
+
Abort selected Tasks in a Work Requirements
|
|
77
|
+
"""
|
|
78
|
+
print_info(f"Aborting Tasks in Work Requirement '{wr_summary.name}'")
|
|
79
|
+
|
|
80
|
+
task_search = TaskSearch(
|
|
81
|
+
workRequirementId=wr_summary.id,
|
|
82
|
+
statuses=[TaskStatus.EXECUTING],
|
|
83
|
+
)
|
|
84
|
+
tasks: list[Task] = CLIENT.work_client.find_tasks(task_search)
|
|
85
|
+
|
|
86
|
+
if tasks:
|
|
87
|
+
tasks = select(CLIENT, sorted_objects(tasks), override_quiet=True)
|
|
88
|
+
else:
|
|
89
|
+
print_info(
|
|
90
|
+
"No currently executing Tasks in this Work Requirement",
|
|
91
|
+
override_quiet=True,
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
aborted_tasks = 0
|
|
95
|
+
if tasks and confirmed(f"Abort {len(tasks)} Task(s)?"):
|
|
96
|
+
for task in tasks:
|
|
97
|
+
try:
|
|
98
|
+
CLIENT.work_client.cancel_task(task, abort=True)
|
|
99
|
+
print_info(
|
|
100
|
+
f"Aborted Task '{task.name}' in Task Group"
|
|
101
|
+
f" '{get_task_group_name(CLIENT, wr_summary, task)}' in Work"
|
|
102
|
+
f" Requirement '{wr_summary.name}'"
|
|
103
|
+
)
|
|
104
|
+
aborted_tasks += 1
|
|
105
|
+
except Exception as e:
|
|
106
|
+
print_error(f"Unable to abort Task '{task.name}': {e}")
|
|
107
|
+
|
|
108
|
+
if aborted_tasks == 0:
|
|
109
|
+
print_info("No Tasks Aborted")
|
|
110
|
+
elif aborted_tasks > 1:
|
|
111
|
+
print_info(f"Aborted {aborted_tasks} Tasks")
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _abort_tasks_by_name_or_id(task_id_list: list[str]):
|
|
115
|
+
"""
|
|
116
|
+
Abort Tasks by their YDIDs.
|
|
117
|
+
"""
|
|
118
|
+
aborted_count = 0
|
|
119
|
+
for task_id in task_id_list:
|
|
120
|
+
if get_ydid_type(task_id) != YDIDType.TASK:
|
|
121
|
+
print_error(f"ID '{task_id}' is not a valid Task YDID")
|
|
122
|
+
continue
|
|
123
|
+
|
|
124
|
+
if not confirmed(f"Cancel and abort Task '{task_id}'?"):
|
|
125
|
+
continue
|
|
126
|
+
|
|
127
|
+
try:
|
|
128
|
+
CLIENT.work_client.cancel_task_by_id(task_id, abort=True)
|
|
129
|
+
print_info(f"Cancelled and aborted Task '{task_id}'")
|
|
130
|
+
aborted_count += 1
|
|
131
|
+
except Exception as e:
|
|
132
|
+
print_error(f"Unable to cancel and abort Task '{task_id}': {e}")
|
|
133
|
+
|
|
134
|
+
if aborted_count > 1:
|
|
135
|
+
print_info(f"Cancelled and aborted {aborted_count} Tasks")
|
|
136
|
+
elif aborted_count == 0:
|
|
137
|
+
print_info("No Tasks cancelled and aborted")
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
# Entry point
|
|
141
|
+
if __name__ == "__main__":
|
|
142
|
+
main()
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
A script for reporting on the details of the Application being used.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import cast
|
|
8
|
+
|
|
9
|
+
from yellowdog_client.model import ApplicationDetails
|
|
10
|
+
|
|
11
|
+
from yellowdog_cli.utils.entity_utils import (
|
|
12
|
+
get_all_roles_and_namespaces_for_application,
|
|
13
|
+
get_application_details,
|
|
14
|
+
get_application_group_summaries,
|
|
15
|
+
)
|
|
16
|
+
from yellowdog_cli.utils.printing import print_simple
|
|
17
|
+
from yellowdog_cli.utils.wrapper import CLIENT, CONFIG_COMMON, main_wrapper
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@main_wrapper
|
|
21
|
+
def main():
|
|
22
|
+
|
|
23
|
+
application_details: ApplicationDetails = get_application_details(CLIENT)
|
|
24
|
+
|
|
25
|
+
print()
|
|
26
|
+
print_simple(
|
|
27
|
+
f" Application name: {application_details.name}",
|
|
28
|
+
override_quiet=True,
|
|
29
|
+
)
|
|
30
|
+
print_simple(
|
|
31
|
+
f" Application ID: {application_details.id}",
|
|
32
|
+
override_quiet=True,
|
|
33
|
+
)
|
|
34
|
+
print_simple(
|
|
35
|
+
f" Account name: {application_details.accountName}",
|
|
36
|
+
override_quiet=True,
|
|
37
|
+
)
|
|
38
|
+
if "api" in CONFIG_COMMON.url:
|
|
39
|
+
print_simple(
|
|
40
|
+
" Portal URL: "
|
|
41
|
+
f"{CONFIG_COMMON.url.replace('api', 'portal')}"
|
|
42
|
+
f"/#/signin?account={application_details.accountName}",
|
|
43
|
+
override_quiet=True,
|
|
44
|
+
)
|
|
45
|
+
print_simple(
|
|
46
|
+
f" Account ID: {application_details.accountId}",
|
|
47
|
+
override_quiet=True,
|
|
48
|
+
)
|
|
49
|
+
features = (
|
|
50
|
+
""
|
|
51
|
+
if application_details.features is None
|
|
52
|
+
else ", ".join([str(feature) for feature in application_details.features])
|
|
53
|
+
)
|
|
54
|
+
print_simple(
|
|
55
|
+
f" Account features: {features}",
|
|
56
|
+
override_quiet=True,
|
|
57
|
+
)
|
|
58
|
+
all_ns_readable = "Yes" if application_details.allNamespacesReadable else "No"
|
|
59
|
+
print_simple(
|
|
60
|
+
f" All namespaces readable: {all_ns_readable}",
|
|
61
|
+
override_quiet=True,
|
|
62
|
+
)
|
|
63
|
+
if not application_details.allNamespacesReadable:
|
|
64
|
+
readable_namespaces = (
|
|
65
|
+
""
|
|
66
|
+
if application_details.readableNamespaces is None
|
|
67
|
+
else ", ".join(application_details.readableNamespaces)
|
|
68
|
+
)
|
|
69
|
+
print_simple(
|
|
70
|
+
f" Readable namespaces: {readable_namespaces}",
|
|
71
|
+
override_quiet=True,
|
|
72
|
+
)
|
|
73
|
+
try:
|
|
74
|
+
groups = get_application_group_summaries(
|
|
75
|
+
CLIENT, cast(str, application_details.id)
|
|
76
|
+
)
|
|
77
|
+
group_names = ", ".join([cast(str, group.name) for group in groups])
|
|
78
|
+
print_simple(
|
|
79
|
+
f" In group(s): {group_names}",
|
|
80
|
+
override_quiet=True,
|
|
81
|
+
)
|
|
82
|
+
for i, (role, namespaces) in enumerate(
|
|
83
|
+
get_all_roles_and_namespaces_for_application(
|
|
84
|
+
CLIENT, cast(str, application_details.id)
|
|
85
|
+
).items()
|
|
86
|
+
):
|
|
87
|
+
msg = f"{role} [{', '.join(namespaces)}]"
|
|
88
|
+
if i == 0:
|
|
89
|
+
print_simple(
|
|
90
|
+
f" With role(s) [in namespace(s)]: {msg}",
|
|
91
|
+
override_quiet=True,
|
|
92
|
+
)
|
|
93
|
+
else:
|
|
94
|
+
print_simple(
|
|
95
|
+
f" {msg}",
|
|
96
|
+
override_quiet=True,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
except Exception as e:
|
|
100
|
+
if "Forbidden" in str(e):
|
|
101
|
+
print_simple(
|
|
102
|
+
" Groups and roles: "
|
|
103
|
+
"Cannot be determined due to application permissions",
|
|
104
|
+
override_quiet=True,
|
|
105
|
+
)
|
|
106
|
+
else:
|
|
107
|
+
pass
|
|
108
|
+
print()
|
yellowdog_cli/boost.py
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
A script to boost allowances.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from yellowdog_cli.utils.interactive import confirmed
|
|
8
|
+
from yellowdog_cli.utils.printing import print_error, print_info
|
|
9
|
+
from yellowdog_cli.utils.wrapper import ARGS_PARSER, CLIENT, main_wrapper
|
|
10
|
+
from yellowdog_cli.utils.ydid_utils import YDIDType, get_ydid_type
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@main_wrapper
|
|
14
|
+
def main():
|
|
15
|
+
|
|
16
|
+
count = 0
|
|
17
|
+
for allowance in ARGS_PARSER.allowance_list:
|
|
18
|
+
if get_ydid_type(allowance) != YDIDType.ALLOWANCE:
|
|
19
|
+
print_error(f"Not a valid Allowance ID: '{allowance}'")
|
|
20
|
+
continue
|
|
21
|
+
if not confirmed(
|
|
22
|
+
f"Boost Allowance {allowance} by {ARGS_PARSER.boost_hours} hours?"
|
|
23
|
+
):
|
|
24
|
+
continue
|
|
25
|
+
try:
|
|
26
|
+
CLIENT.allowances_client.boost_allowance_by_id(
|
|
27
|
+
allowance, ARGS_PARSER.boost_hours
|
|
28
|
+
)
|
|
29
|
+
print_info(
|
|
30
|
+
f"Boosted Allowance {allowance} by {ARGS_PARSER.boost_hours} hours"
|
|
31
|
+
)
|
|
32
|
+
count += 1
|
|
33
|
+
except Exception as e:
|
|
34
|
+
print_error(f"Unable to boost Allowance {allowance}: {e}")
|
|
35
|
+
|
|
36
|
+
if count > 1:
|
|
37
|
+
print_info(f"Boosted {count} allowances by {ARGS_PARSER.boost_hours} hours")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
# Standalone entry point
|
|
41
|
+
if __name__ == "__main__":
|
|
42
|
+
main()
|
yellowdog_cli/cancel.py
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
A script to cancel Work Requirements and optionally abort Tasks.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import cast
|
|
8
|
+
|
|
9
|
+
from yellowdog_client.model import (
|
|
10
|
+
WorkRequirement,
|
|
11
|
+
WorkRequirementStatus,
|
|
12
|
+
WorkRequirementSummary,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
from yellowdog_cli.utils.entity_utils import (
|
|
16
|
+
get_filtered_work_requirement_summaries,
|
|
17
|
+
get_work_requirement_summary_by_name_or_id,
|
|
18
|
+
)
|
|
19
|
+
from yellowdog_cli.utils.follow_utils import follow_ids
|
|
20
|
+
from yellowdog_cli.utils.interactive import confirmed, select
|
|
21
|
+
from yellowdog_cli.utils.misc_utils import link_entity
|
|
22
|
+
from yellowdog_cli.utils.printing import print_error, print_info, print_warning
|
|
23
|
+
from yellowdog_cli.utils.wrapper import ARGS_PARSER, CLIENT, CONFIG_COMMON, main_wrapper
|
|
24
|
+
from yellowdog_cli.utils.ydid_utils import YDIDType, get_ydid_type
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@main_wrapper
|
|
28
|
+
def main():
|
|
29
|
+
if ARGS_PARSER.work_requirement_names:
|
|
30
|
+
_cancel_work_requirements_by_name_or_id(ARGS_PARSER.work_requirement_names)
|
|
31
|
+
return
|
|
32
|
+
|
|
33
|
+
print_info(
|
|
34
|
+
"Cancelling Work Requirements in namespace "
|
|
35
|
+
f"'{CONFIG_COMMON.namespace}' with tags "
|
|
36
|
+
f"including '{CONFIG_COMMON.name_tag}'"
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
selected_work_requirement_summaries: list[WorkRequirementSummary] = (
|
|
40
|
+
get_filtered_work_requirement_summaries(
|
|
41
|
+
client=CLIENT,
|
|
42
|
+
namespace=CONFIG_COMMON.namespace,
|
|
43
|
+
tag=CONFIG_COMMON.name_tag,
|
|
44
|
+
exclude_filter=[
|
|
45
|
+
WorkRequirementStatus.COMPLETED,
|
|
46
|
+
WorkRequirementStatus.CANCELLED,
|
|
47
|
+
WorkRequirementStatus.FAILED,
|
|
48
|
+
],
|
|
49
|
+
)
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
cancelled_count = 0
|
|
53
|
+
cancelling_count = 0
|
|
54
|
+
work_requirement_ids: list[str] = []
|
|
55
|
+
|
|
56
|
+
if selected_work_requirement_summaries:
|
|
57
|
+
selected_work_requirement_summaries = select(
|
|
58
|
+
CLIENT, selected_work_requirement_summaries
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
if selected_work_requirement_summaries and confirmed(
|
|
62
|
+
f"Cancel {len(selected_work_requirement_summaries)} "
|
|
63
|
+
f"Work Requirement(s)"
|
|
64
|
+
f"{'' if not ARGS_PARSER.abort else ' and abort all allocated tasks'}?"
|
|
65
|
+
):
|
|
66
|
+
for work_summary in selected_work_requirement_summaries:
|
|
67
|
+
if work_summary.status != WorkRequirementStatus.CANCELLING:
|
|
68
|
+
try:
|
|
69
|
+
CLIENT.work_client.cancel_work_requirement_by_id(
|
|
70
|
+
work_summary.id, ARGS_PARSER.abort
|
|
71
|
+
)
|
|
72
|
+
work_requirement: WorkRequirement = (
|
|
73
|
+
CLIENT.work_client.get_work_requirement_by_id(work_summary.id)
|
|
74
|
+
)
|
|
75
|
+
cancelled_count += 1
|
|
76
|
+
print_info(
|
|
77
|
+
f"Cancelled {link_entity(CONFIG_COMMON.url, work_requirement)} "
|
|
78
|
+
f"('{work_summary.name}')"
|
|
79
|
+
f"{'' if not ARGS_PARSER.abort else ' and aborted all allocated tasks'}"
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
except Exception as e:
|
|
83
|
+
print_error(
|
|
84
|
+
f"Failed to cancel Work Requirement '{work_summary.name}': {e}"
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
elif work_summary.status == WorkRequirementStatus.CANCELLING:
|
|
88
|
+
print_info(
|
|
89
|
+
f"Work Requirement '{work_summary.name}' is already cancelling"
|
|
90
|
+
)
|
|
91
|
+
cancelling_count += 1
|
|
92
|
+
work_requirement_ids.append(work_summary.id)
|
|
93
|
+
|
|
94
|
+
if cancelled_count > 1:
|
|
95
|
+
print_info(f"Cancelled {cancelled_count} Work Requirement(s)")
|
|
96
|
+
elif cancelled_count == 0 and cancelling_count == 0:
|
|
97
|
+
print_info("No Work Requirements to cancel")
|
|
98
|
+
|
|
99
|
+
if ARGS_PARSER.follow:
|
|
100
|
+
follow_ids(work_requirement_ids)
|
|
101
|
+
|
|
102
|
+
else:
|
|
103
|
+
print_info("No Work Requirements to cancel")
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def _cancel_work_requirements_by_name_or_id(names_or_ids: list[str]):
|
|
107
|
+
"""
|
|
108
|
+
Cancel Work Requirements by their names or IDs.
|
|
109
|
+
"""
|
|
110
|
+
work_requirement_summaries: list[WorkRequirementSummary] = []
|
|
111
|
+
|
|
112
|
+
for name_or_id in names_or_ids:
|
|
113
|
+
|
|
114
|
+
# Handle a task ID
|
|
115
|
+
if get_ydid_type(name_or_id) == YDIDType.TASK:
|
|
116
|
+
if not confirmed(
|
|
117
|
+
f"Cancel {'' if not ARGS_PARSER.abort else 'and abort '}"
|
|
118
|
+
f"Task '{name_or_id}'?"
|
|
119
|
+
):
|
|
120
|
+
continue
|
|
121
|
+
try:
|
|
122
|
+
CLIENT.work_client.cancel_task_by_id(name_or_id, ARGS_PARSER.abort)
|
|
123
|
+
except Exception as e:
|
|
124
|
+
print_error(f"Failed to cancel Task '{name_or_id}': {e}")
|
|
125
|
+
continue
|
|
126
|
+
|
|
127
|
+
work_requirement_summary = get_work_requirement_summary_by_name_or_id(
|
|
128
|
+
CLIENT,
|
|
129
|
+
name_or_id,
|
|
130
|
+
namespace=CONFIG_COMMON.namespace,
|
|
131
|
+
)
|
|
132
|
+
if work_requirement_summary is None:
|
|
133
|
+
print_error(f"Work Requirement '{name_or_id}' not found")
|
|
134
|
+
continue
|
|
135
|
+
|
|
136
|
+
if work_requirement_summary.status not in [
|
|
137
|
+
WorkRequirementStatus.RUNNING,
|
|
138
|
+
WorkRequirementStatus.HELD,
|
|
139
|
+
WorkRequirementStatus.FINISHING,
|
|
140
|
+
]:
|
|
141
|
+
print_warning(
|
|
142
|
+
f"Work Requirement '{name_or_id}' is not in a valid state"
|
|
143
|
+
f" ('{work_requirement_summary.status}') for cancellation"
|
|
144
|
+
)
|
|
145
|
+
continue
|
|
146
|
+
|
|
147
|
+
work_requirement_summaries.append(work_requirement_summary)
|
|
148
|
+
fq_name = (
|
|
149
|
+
f"{work_requirement_summary.namespace}/{work_requirement_summary.name}"
|
|
150
|
+
)
|
|
151
|
+
if work_requirement_summary.status == WorkRequirementStatus.CANCELLING:
|
|
152
|
+
print_info(
|
|
153
|
+
f"Work Requirement '{fq_name}' ({work_requirement_summary.id}) "
|
|
154
|
+
"is already cancelling"
|
|
155
|
+
)
|
|
156
|
+
else:
|
|
157
|
+
if not confirmed(
|
|
158
|
+
f"Cancel Work Requirement '{fq_name}' ({work_requirement_summary.id})"
|
|
159
|
+
f"{'' if not ARGS_PARSER.abort else ' and abort all allocated tasks'}?"
|
|
160
|
+
):
|
|
161
|
+
continue
|
|
162
|
+
try:
|
|
163
|
+
CLIENT.work_client.cancel_work_requirement_by_id(
|
|
164
|
+
work_requirement_summary.id, ARGS_PARSER.abort
|
|
165
|
+
)
|
|
166
|
+
print_info(
|
|
167
|
+
f"Cancelled Work Requirement '{fq_name}' ({work_requirement_summary.id})"
|
|
168
|
+
f"{'' if not ARGS_PARSER.abort else ' and aborted all allocated tasks'}"
|
|
169
|
+
)
|
|
170
|
+
except Exception as e:
|
|
171
|
+
print_error(
|
|
172
|
+
f"Failed to cancel Work Requirement '{fq_name}' "
|
|
173
|
+
f"({work_requirement_summary.id}): {e}"
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
if ARGS_PARSER.follow:
|
|
177
|
+
follow_ids([cast(str, wrs.id) for wrs in work_requirement_summaries])
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
# Entry point
|
|
181
|
+
if __name__ == "__main__":
|
|
182
|
+
main()
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Cloud Wizard: cloud provider and YellowDog account setup.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from yellowdog_cli.utils.check_imports import check_cloudwizard_imports
|
|
8
|
+
from yellowdog_cli.utils.cloudwizard_aws import AWSConfig
|
|
9
|
+
from yellowdog_cli.utils.cloudwizard_azure import AzureConfig
|
|
10
|
+
from yellowdog_cli.utils.cloudwizard_gcp import GCPConfig
|
|
11
|
+
from yellowdog_cli.utils.printing import print_error, print_info, print_warning
|
|
12
|
+
from yellowdog_cli.utils.wrapper import ARGS_PARSER, CLIENT, main_wrapper
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@main_wrapper
|
|
16
|
+
def main():
|
|
17
|
+
"""
|
|
18
|
+
Main dispatcher for Cloud Wizard setup and teardown
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
check_cloudwizard_imports()
|
|
22
|
+
|
|
23
|
+
if ARGS_PARSER.cloud_provider.lower() in ["aws", "amazon"]:
|
|
24
|
+
print_info("YellowDog automated cloud provider setup/teardown for 'AWS'")
|
|
25
|
+
cloud_provider_config = AWSConfig(
|
|
26
|
+
client=CLIENT,
|
|
27
|
+
region_name=ARGS_PARSER.region_name,
|
|
28
|
+
show_secrets=ARGS_PARSER.show_secrets,
|
|
29
|
+
instance_type=ARGS_PARSER.instance_type,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
elif ARGS_PARSER.cloud_provider.lower() in ["gcp", "gce", "google"]:
|
|
33
|
+
print_info("YellowDog automated cloud provider setup/teardown for 'GCP'")
|
|
34
|
+
if ARGS_PARSER.credentials_file is None:
|
|
35
|
+
print_error(
|
|
36
|
+
"Credentials file ('--credentials-file') must be supplied for GCP"
|
|
37
|
+
)
|
|
38
|
+
return
|
|
39
|
+
cloud_provider_config = GCPConfig(
|
|
40
|
+
service_account_file=ARGS_PARSER.credentials_file,
|
|
41
|
+
client=CLIENT,
|
|
42
|
+
instance_type=ARGS_PARSER.instance_type,
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
elif ARGS_PARSER.cloud_provider.lower() in ["azure", "microsoft"]:
|
|
46
|
+
print_info("YellowDog automated cloud provider setup/teardown for 'Azure'")
|
|
47
|
+
cloud_provider_config = AzureConfig(
|
|
48
|
+
client=CLIENT,
|
|
49
|
+
instance_type=ARGS_PARSER.instance_type,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
elif ARGS_PARSER.cloud_provider.lower() in [
|
|
53
|
+
"oci",
|
|
54
|
+
"oracle",
|
|
55
|
+
"alibaba",
|
|
56
|
+
]:
|
|
57
|
+
print_warning(
|
|
58
|
+
f"Cloud provider '{ARGS_PARSER.cloud_provider}' is not yet supported by"
|
|
59
|
+
" Cloud Wizard"
|
|
60
|
+
)
|
|
61
|
+
return
|
|
62
|
+
|
|
63
|
+
else:
|
|
64
|
+
print_error(f"Unknown cloud provider '{ARGS_PARSER.cloud_provider}'")
|
|
65
|
+
return
|
|
66
|
+
|
|
67
|
+
if ARGS_PARSER.operation == "setup":
|
|
68
|
+
cloud_provider_config.setup()
|
|
69
|
+
|
|
70
|
+
elif ARGS_PARSER.operation == "teardown":
|
|
71
|
+
cloud_provider_config.teardown()
|
|
72
|
+
|
|
73
|
+
elif ARGS_PARSER.operation in ["add-ssh", "remove-ssh"]:
|
|
74
|
+
cloud_provider_config.set_ssh_ingress_rule(
|
|
75
|
+
ARGS_PARSER.operation, ARGS_PARSER.region_name
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
if __name__ == "__main__":
|
|
80
|
+
"""
|
|
81
|
+
Standalone entry point
|
|
82
|
+
"""
|
|
83
|
+
main()
|