kaqing 1.77.0__py3-none-any.whl → 2.0.171__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.
- adam/__init__.py +1 -0
- adam/app_session.py +182 -0
- {walker → adam}/apps.py +8 -24
- {walker → adam}/batch.py +54 -97
- {walker → adam}/checks/check.py +3 -3
- {walker → adam}/checks/check_result.py +1 -1
- adam/checks/check_utils.py +65 -0
- {walker → adam}/checks/compactionstats.py +6 -6
- {walker → adam}/checks/cpu.py +14 -8
- adam/checks/cpu_metrics.py +52 -0
- {walker → adam}/checks/disk.py +6 -6
- {walker → adam}/checks/gossip.py +5 -5
- {walker → adam}/checks/memory.py +7 -7
- {walker → adam}/checks/status.py +5 -5
- {walker → adam}/cli.py +3 -3
- {walker → adam}/columns/column.py +1 -1
- adam/columns/columns.py +45 -0
- {walker → adam}/columns/compactions.py +5 -5
- {walker → adam}/columns/cpu.py +6 -4
- adam/columns/cpu_metrics.py +22 -0
- {walker → adam}/columns/dir_data.py +3 -3
- {walker → adam}/columns/dir_snapshots.py +3 -3
- {walker → adam}/columns/gossip.py +5 -5
- {walker → adam}/columns/host_id.py +3 -3
- {walker → adam}/columns/memory.py +3 -3
- {walker → adam}/columns/node_address.py +3 -3
- {walker → adam}/columns/node_load.py +3 -3
- {walker → adam}/columns/node_owns.py +3 -3
- {walker → adam}/columns/node_status.py +3 -3
- {walker → adam}/columns/node_tokens.py +3 -3
- {walker → adam}/columns/node_utils.py +2 -2
- {walker → adam}/columns/pod_name.py +2 -2
- {walker → adam}/columns/volume_cassandra.py +4 -4
- {walker → adam}/columns/volume_root.py +3 -3
- adam/commands/__init__.py +15 -0
- adam/commands/alter_tables.py +81 -0
- adam/commands/app_cmd.py +38 -0
- {walker → adam}/commands/app_ping.py +10 -16
- adam/commands/audit/audit.py +84 -0
- adam/commands/audit/audit_repair_tables.py +74 -0
- adam/commands/audit/audit_run.py +50 -0
- adam/commands/audit/show_last10.py +48 -0
- adam/commands/audit/show_slow10.py +47 -0
- adam/commands/audit/show_top10.py +45 -0
- adam/commands/audit/utils_show_top10.py +59 -0
- adam/commands/bash/__init__.py +5 -0
- adam/commands/bash/bash.py +36 -0
- adam/commands/bash/bash_completer.py +93 -0
- adam/commands/bash/utils_bash.py +16 -0
- adam/commands/cat.py +50 -0
- adam/commands/cd.py +43 -0
- adam/commands/check.py +73 -0
- {walker → adam}/commands/cli_commands.py +7 -8
- adam/commands/code.py +57 -0
- adam/commands/command.py +190 -0
- {walker → adam}/commands/command_helpers.py +1 -1
- {walker → adam}/commands/commands_utils.py +15 -25
- adam/commands/cp.py +89 -0
- adam/commands/cql/cql_completions.py +33 -0
- {walker/commands → adam/commands/cql}/cqlsh.py +20 -35
- adam/commands/cql/utils_cql.py +343 -0
- {walker/commands/frontend → adam/commands/deploy}/code_start.py +11 -14
- adam/commands/deploy/code_stop.py +40 -0
- {walker/commands/frontend → adam/commands/deploy}/code_utils.py +7 -9
- adam/commands/deploy/deploy.py +25 -0
- adam/commands/deploy/deploy_frontend.py +49 -0
- adam/commands/deploy/deploy_pg_agent.py +35 -0
- adam/commands/deploy/deploy_pod.py +108 -0
- adam/commands/deploy/deploy_utils.py +29 -0
- adam/commands/deploy/undeploy.py +25 -0
- adam/commands/deploy/undeploy_frontend.py +38 -0
- adam/commands/deploy/undeploy_pg_agent.py +39 -0
- adam/commands/deploy/undeploy_pod.py +48 -0
- adam/commands/devices/device.py +118 -0
- adam/commands/devices/device_app.py +173 -0
- adam/commands/devices/device_auit_log.py +49 -0
- adam/commands/devices/device_cass.py +185 -0
- adam/commands/devices/device_export.py +86 -0
- adam/commands/devices/device_postgres.py +144 -0
- adam/commands/devices/devices.py +25 -0
- {walker → adam}/commands/exit.py +3 -6
- adam/commands/export/clean_up_all_export_sessions.py +37 -0
- adam/commands/export/clean_up_export_sessions.py +51 -0
- adam/commands/export/drop_export_database.py +55 -0
- adam/commands/export/drop_export_databases.py +43 -0
- adam/commands/export/export.py +53 -0
- adam/commands/export/export_databases.py +170 -0
- adam/commands/export/export_handlers.py +71 -0
- adam/commands/export/export_select.py +81 -0
- adam/commands/export/export_select_x.py +54 -0
- adam/commands/export/export_use.py +52 -0
- adam/commands/export/exporter.py +352 -0
- adam/commands/export/import_session.py +40 -0
- adam/commands/export/importer.py +67 -0
- adam/commands/export/importer_athena.py +80 -0
- adam/commands/export/importer_sqlite.py +47 -0
- adam/commands/export/show_column_counts.py +54 -0
- adam/commands/export/show_export_databases.py +36 -0
- adam/commands/export/show_export_session.py +48 -0
- adam/commands/export/show_export_sessions.py +44 -0
- adam/commands/export/utils_export.py +314 -0
- {walker → adam}/commands/help.py +17 -12
- adam/commands/intermediate_command.py +49 -0
- adam/commands/issues.py +43 -0
- adam/commands/kubectl.py +38 -0
- adam/commands/login.py +70 -0
- {walker → adam}/commands/logs.py +8 -10
- adam/commands/ls.py +41 -0
- adam/commands/medusa/medusa.py +27 -0
- adam/commands/medusa/medusa_backup.py +57 -0
- adam/commands/medusa/medusa_restore.py +83 -0
- adam/commands/medusa/medusa_show_backupjobs.py +51 -0
- adam/commands/medusa/medusa_show_restorejobs.py +47 -0
- {walker → adam}/commands/nodetool.py +17 -21
- {walker → adam}/commands/param_get.py +15 -16
- adam/commands/param_set.py +43 -0
- adam/commands/postgres/postgres.py +104 -0
- adam/commands/postgres/postgres_context.py +274 -0
- {walker → adam}/commands/postgres/postgres_ls.py +7 -11
- {walker → adam}/commands/postgres/postgres_preview.py +8 -13
- adam/commands/postgres/psql_completions.py +10 -0
- adam/commands/postgres/utils_postgres.py +66 -0
- adam/commands/preview_table.py +37 -0
- adam/commands/pwd.py +47 -0
- adam/commands/reaper/reaper.py +35 -0
- adam/commands/reaper/reaper_forward.py +93 -0
- adam/commands/reaper/reaper_forward_session.py +6 -0
- {walker → adam}/commands/reaper/reaper_forward_stop.py +13 -19
- {walker → adam}/commands/reaper/reaper_restart.py +10 -17
- adam/commands/reaper/reaper_run_abort.py +46 -0
- adam/commands/reaper/reaper_runs.py +82 -0
- adam/commands/reaper/reaper_runs_abort.py +63 -0
- adam/commands/reaper/reaper_schedule_activate.py +45 -0
- adam/commands/reaper/reaper_schedule_start.py +45 -0
- adam/commands/reaper/reaper_schedule_stop.py +45 -0
- {walker → adam}/commands/reaper/reaper_schedules.py +6 -16
- {walker → adam}/commands/reaper/reaper_status.py +11 -19
- adam/commands/reaper/utils_reaper.py +196 -0
- adam/commands/repair/repair.py +26 -0
- {walker → adam}/commands/repair/repair_log.py +7 -10
- adam/commands/repair/repair_run.py +70 -0
- adam/commands/repair/repair_scan.py +71 -0
- {walker → adam}/commands/repair/repair_stop.py +8 -11
- adam/commands/report.py +61 -0
- adam/commands/restart.py +60 -0
- {walker → adam}/commands/rollout.py +25 -30
- adam/commands/shell.py +34 -0
- adam/commands/show/show.py +39 -0
- walker/commands/show/show_version.py → adam/commands/show/show_adam.py +14 -10
- adam/commands/show/show_app_actions.py +57 -0
- {walker → adam}/commands/show/show_app_id.py +12 -15
- {walker → adam}/commands/show/show_app_queues.py +9 -12
- adam/commands/show/show_cassandra_repairs.py +38 -0
- adam/commands/show/show_cassandra_status.py +124 -0
- {walker → adam}/commands/show/show_cassandra_version.py +6 -16
- adam/commands/show/show_commands.py +59 -0
- walker/commands/show/show_storage.py → adam/commands/show/show_host.py +11 -13
- adam/commands/show/show_login.py +62 -0
- {walker → adam}/commands/show/show_params.py +4 -4
- adam/commands/show/show_processes.py +51 -0
- adam/commands/show/show_storage.py +42 -0
- adam/commands/watch.py +82 -0
- {walker → adam}/config.py +10 -22
- {walker → adam}/embedded_apps.py +1 -1
- adam/embedded_params.py +2 -0
- adam/log.py +47 -0
- {walker → adam}/pod_exec_result.py +10 -2
- adam/repl.py +182 -0
- adam/repl_commands.py +124 -0
- adam/repl_state.py +458 -0
- adam/sql/__init__.py +0 -0
- adam/sql/sql_completer.py +120 -0
- adam/sql/sql_state_machine.py +618 -0
- adam/sql/term_completer.py +76 -0
- adam/sso/__init__.py +0 -0
- {walker → adam}/sso/authenticator.py +5 -1
- adam/sso/authn_ad.py +170 -0
- {walker → adam}/sso/authn_okta.py +39 -22
- adam/sso/cred_cache.py +60 -0
- adam/sso/id_token.py +23 -0
- adam/sso/idp.py +143 -0
- adam/sso/idp_login.py +50 -0
- adam/sso/idp_session.py +55 -0
- adam/sso/sso_config.py +63 -0
- adam/utils.py +679 -0
- adam/utils_app.py +98 -0
- adam/utils_athena.py +145 -0
- adam/utils_audits.py +106 -0
- adam/utils_issues.py +32 -0
- adam/utils_k8s/__init__.py +0 -0
- adam/utils_k8s/app_clusters.py +28 -0
- adam/utils_k8s/app_pods.py +33 -0
- adam/utils_k8s/cassandra_clusters.py +36 -0
- adam/utils_k8s/cassandra_nodes.py +33 -0
- adam/utils_k8s/config_maps.py +34 -0
- {walker/k8s_utils → adam/utils_k8s}/custom_resources.py +7 -2
- adam/utils_k8s/deployment.py +56 -0
- {walker/k8s_utils → adam/utils_k8s}/ingresses.py +3 -4
- {walker/k8s_utils → adam/utils_k8s}/jobs.py +3 -3
- adam/utils_k8s/k8s.py +87 -0
- {walker/k8s_utils → adam/utils_k8s}/kube_context.py +4 -4
- adam/utils_k8s/pods.py +290 -0
- {walker/k8s_utils → adam/utils_k8s}/secrets.py +8 -4
- adam/utils_k8s/service_accounts.py +170 -0
- {walker/k8s_utils → adam/utils_k8s}/services.py +3 -4
- {walker/k8s_utils → adam/utils_k8s}/statefulsets.py +6 -16
- {walker/k8s_utils → adam/utils_k8s}/volumes.py +10 -1
- adam/utils_net.py +24 -0
- adam/utils_repl/__init__.py +0 -0
- adam/utils_repl/automata_completer.py +48 -0
- adam/utils_repl/repl_completer.py +46 -0
- adam/utils_repl/state_machine.py +173 -0
- adam/utils_sqlite.py +109 -0
- adam/version.py +5 -0
- {kaqing-1.77.0.dist-info → kaqing-2.0.171.dist-info}/METADATA +1 -1
- kaqing-2.0.171.dist-info/RECORD +236 -0
- kaqing-2.0.171.dist-info/entry_points.txt +3 -0
- kaqing-2.0.171.dist-info/top_level.txt +1 -0
- kaqing-1.77.0.dist-info/RECORD +0 -159
- kaqing-1.77.0.dist-info/entry_points.txt +0 -3
- kaqing-1.77.0.dist-info/top_level.txt +0 -1
- walker/__init__.py +0 -3
- walker/app_session.py +0 -168
- walker/checks/check_utils.py +0 -97
- walker/columns/columns.py +0 -43
- walker/commands/add_user.py +0 -68
- walker/commands/app.py +0 -67
- walker/commands/bash.py +0 -87
- walker/commands/cd.py +0 -115
- walker/commands/check.py +0 -68
- walker/commands/command.py +0 -104
- walker/commands/cp.py +0 -95
- walker/commands/cql_utils.py +0 -53
- walker/commands/devices.py +0 -89
- walker/commands/frontend/code_stop.py +0 -57
- walker/commands/frontend/setup.py +0 -60
- walker/commands/frontend/setup_frontend.py +0 -58
- walker/commands/frontend/teardown.py +0 -61
- walker/commands/frontend/teardown_frontend.py +0 -42
- walker/commands/issues.py +0 -69
- walker/commands/login.py +0 -72
- walker/commands/ls.py +0 -145
- walker/commands/medusa/medusa.py +0 -69
- walker/commands/medusa/medusa_backup.py +0 -61
- walker/commands/medusa/medusa_restore.py +0 -86
- walker/commands/medusa/medusa_show_backupjobs.py +0 -52
- walker/commands/medusa/medusa_show_restorejobs.py +0 -52
- walker/commands/param_set.py +0 -44
- walker/commands/postgres/postgres.py +0 -113
- walker/commands/postgres/postgres_session.py +0 -225
- walker/commands/preview_table.py +0 -98
- walker/commands/processes.py +0 -53
- walker/commands/pwd.py +0 -64
- walker/commands/reaper/reaper.py +0 -78
- walker/commands/reaper/reaper_forward.py +0 -100
- walker/commands/reaper/reaper_run_abort.py +0 -65
- walker/commands/reaper/reaper_runs.py +0 -97
- walker/commands/reaper/reaper_runs_abort.py +0 -83
- walker/commands/reaper/reaper_schedule_activate.py +0 -64
- walker/commands/reaper/reaper_schedule_start.py +0 -64
- walker/commands/reaper/reaper_schedule_stop.py +0 -64
- walker/commands/reaper/reaper_session.py +0 -159
- walker/commands/repair/repair.py +0 -68
- walker/commands/repair/repair_run.py +0 -72
- walker/commands/repair/repair_scan.py +0 -79
- walker/commands/report.py +0 -57
- walker/commands/restart.py +0 -61
- walker/commands/show/show.py +0 -72
- walker/commands/show/show_app_actions.py +0 -53
- walker/commands/show/show_cassandra_status.py +0 -35
- walker/commands/show/show_commands.py +0 -58
- walker/commands/show/show_processes.py +0 -35
- walker/commands/show/show_repairs.py +0 -47
- walker/commands/status.py +0 -128
- walker/commands/storage.py +0 -52
- walker/commands/user_entry.py +0 -69
- walker/commands/watch.py +0 -85
- walker/embedded_params.py +0 -2
- walker/k8s_utils/cassandra_clusters.py +0 -48
- walker/k8s_utils/cassandra_nodes.py +0 -26
- walker/k8s_utils/pods.py +0 -211
- walker/repl.py +0 -165
- walker/repl_commands.py +0 -58
- walker/repl_state.py +0 -211
- walker/sso/authn_ad.py +0 -94
- walker/sso/idp.py +0 -150
- walker/sso/idp_login.py +0 -29
- walker/sso/sso_config.py +0 -45
- walker/utils.py +0 -194
- walker/version.py +0 -5
- {walker → adam}/checks/__init__.py +0 -0
- {walker → adam}/checks/check_context.py +0 -0
- {walker → adam}/checks/issue.py +0 -0
- {walker → adam}/cli_group.py +0 -0
- {walker → adam}/columns/__init__.py +0 -0
- {walker/commands → adam/commands/audit}/__init__.py +0 -0
- {walker/commands/frontend → adam/commands/cql}/__init__.py +0 -0
- {walker/commands/medusa → adam/commands/deploy}/__init__.py +0 -0
- {walker/commands/postgres → adam/commands/devices}/__init__.py +0 -0
- {walker/commands/reaper → adam/commands/export}/__init__.py +0 -0
- {walker/commands/repair → adam/commands/medusa}/__init__.py +0 -0
- {walker → adam}/commands/nodetool_commands.py +0 -0
- {walker/commands/show → adam/commands/postgres}/__init__.py +0 -0
- {walker/k8s_utils → adam/commands/reaper}/__init__.py +0 -0
- {walker/sso → adam/commands/repair}/__init__.py +0 -0
- /walker/medusa_show_restorejobs.py → /adam/commands/show/__init__.py +0 -0
- {walker → adam}/repl_session.py +0 -0
- {kaqing-1.77.0.dist-info → kaqing-2.0.171.dist-info}/WHEEL +0 -0
walker/checks/check_utils.py
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
from collections.abc import Callable
|
|
2
|
-
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
3
|
-
import time
|
|
4
|
-
|
|
5
|
-
from walker.checks.check import Check
|
|
6
|
-
from walker.checks.check_context import CheckContext
|
|
7
|
-
from walker.checks.check_result import CheckResult
|
|
8
|
-
from walker.checks.compactionstats import CompactionStats
|
|
9
|
-
from walker.checks.cpu import Cpu
|
|
10
|
-
from walker.checks.disk import Disk
|
|
11
|
-
from walker.checks.gossip import Gossip
|
|
12
|
-
from walker.checks.issue import Issue
|
|
13
|
-
from walker.checks.memory import Memory
|
|
14
|
-
from walker.checks.status import Status
|
|
15
|
-
from walker.config import Config
|
|
16
|
-
from walker.k8s_utils.cassandra_nodes import CassandraNodes
|
|
17
|
-
from walker.k8s_utils.kube_context import KubeContext
|
|
18
|
-
from walker.k8s_utils.secrets import Secrets
|
|
19
|
-
from walker.k8s_utils.statefulsets import StatefulSets
|
|
20
|
-
from walker.utils import elapsed_time, log2
|
|
21
|
-
|
|
22
|
-
def all_checks() -> list[Check]:
|
|
23
|
-
return [CompactionStats(), Cpu(), Gossip(), Memory(), Disk(), Status()]
|
|
24
|
-
|
|
25
|
-
def checks_from_csv(check_str: str):
|
|
26
|
-
checks: list[Check] = []
|
|
27
|
-
|
|
28
|
-
checks_by_name = {c.name(): c for c in all_checks()}
|
|
29
|
-
|
|
30
|
-
if check_str:
|
|
31
|
-
for check_name in check_str.strip(' ').split(','):
|
|
32
|
-
if check_name in checks_by_name:
|
|
33
|
-
checks.append(checks_by_name[check_name])
|
|
34
|
-
else:
|
|
35
|
-
log2(f'Invalid check name: {check_name}.')
|
|
36
|
-
|
|
37
|
-
return None
|
|
38
|
-
|
|
39
|
-
return checks
|
|
40
|
-
|
|
41
|
-
def run_checks(cluster: str = None, namespace: str = None, pod: str = None, checks: list[Check] = None, show_output=True):
|
|
42
|
-
if not checks:
|
|
43
|
-
checks = all_checks()
|
|
44
|
-
|
|
45
|
-
sss: list[tuple[str, str]] = StatefulSets.list_sts_name_and_ns()
|
|
46
|
-
|
|
47
|
-
action = 'issues'
|
|
48
|
-
crs: list[CheckResult] = []
|
|
49
|
-
|
|
50
|
-
def on_clusters(f: Callable[[any, list[str]], any]):
|
|
51
|
-
for ss, ns in sss:
|
|
52
|
-
if (not cluster or cluster == ss) and (not namespace or namespace == ns):
|
|
53
|
-
pods = StatefulSets.pods(ss, ns)
|
|
54
|
-
for pod_name in [pod.metadata.name for pod in pods]:
|
|
55
|
-
if not pod or pod == pod_name:
|
|
56
|
-
f(ss, ns, pod_name, show_output)
|
|
57
|
-
|
|
58
|
-
max_workers = Config().action_workers(action, 30)
|
|
59
|
-
if max_workers < 2:
|
|
60
|
-
def serial(ss, ns, pod_name, show_output):
|
|
61
|
-
if not pod or pod == pod_name:
|
|
62
|
-
crs.append(run_checks_on_pod(checks, ss[0], ns, pod_name, show_output))
|
|
63
|
-
|
|
64
|
-
on_clusters(serial)
|
|
65
|
-
else:
|
|
66
|
-
if KubeContext.show_parallelism():
|
|
67
|
-
log2(f'Executing on all nodes from statefulset with {max_workers} workers...')
|
|
68
|
-
start_time = time.time()
|
|
69
|
-
try:
|
|
70
|
-
futures = []
|
|
71
|
-
with ThreadPoolExecutor(max_workers=max_workers) as executor:
|
|
72
|
-
def submit(ss, ns, pod_name, show_output):
|
|
73
|
-
f = executor.submit(run_checks_on_pod, checks, ss, ns, pod_name, show_output,)
|
|
74
|
-
if f: futures.append(f)
|
|
75
|
-
|
|
76
|
-
on_clusters(submit)
|
|
77
|
-
|
|
78
|
-
crs = [future.result() for future in as_completed(futures)]
|
|
79
|
-
finally:
|
|
80
|
-
if KubeContext.show_parallelism():
|
|
81
|
-
log2(f"Parallel {action} elapsed time: {elapsed_time(start_time)} with {max_workers} workers")
|
|
82
|
-
|
|
83
|
-
return crs
|
|
84
|
-
|
|
85
|
-
def run_checks_on_pod(checks: list[Check], cluster: str = None, namespace: str = None, pod: str = None, show_output=True):
|
|
86
|
-
host_id = CassandraNodes.get_host_id(pod, namespace)
|
|
87
|
-
user, pw = Secrets.get_user_pass(pod, namespace)
|
|
88
|
-
results = {}
|
|
89
|
-
issues: list[Issue] = []
|
|
90
|
-
for c in checks:
|
|
91
|
-
check_results = c.check(CheckContext(cluster, host_id, pod, namespace, user, pw, show_output=show_output))
|
|
92
|
-
if check_results.details:
|
|
93
|
-
results = results | {check_results.name: check_results.details}
|
|
94
|
-
if check_results.issues:
|
|
95
|
-
issues.extend(check_results.issues)
|
|
96
|
-
|
|
97
|
-
return CheckResult(None, results, issues)
|
walker/columns/columns.py
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
from walker.columns.column import Column
|
|
2
|
-
from walker.columns.compactions import Compactions
|
|
3
|
-
from walker.columns.cpu import Cpu
|
|
4
|
-
from walker.columns.dir_data import DataDir
|
|
5
|
-
from walker.columns.dir_snapshots import SnapshotsDir
|
|
6
|
-
from walker.columns.gossip import Gossip
|
|
7
|
-
from walker.columns.host_id import HostId
|
|
8
|
-
from walker.columns.memory import Memory
|
|
9
|
-
from walker.columns.node_address import NodeAddress
|
|
10
|
-
from walker.columns.node_load import NodeLoad
|
|
11
|
-
from walker.columns.node_owns import NodeOwns
|
|
12
|
-
from walker.columns.node_status import NodeStatus
|
|
13
|
-
from walker.columns.node_tokens import NodeTokens
|
|
14
|
-
from walker.columns.pod_name import PodName
|
|
15
|
-
from walker.columns.volume_cassandra import CassandraVolume
|
|
16
|
-
from walker.columns.volume_root import RootVolume
|
|
17
|
-
|
|
18
|
-
def collect_checks(columns: list[Column]):
|
|
19
|
-
checks = sum([c.checks() for c in columns], [])
|
|
20
|
-
return {cc.name(): cc for cc in checks}.values()
|
|
21
|
-
|
|
22
|
-
class Columns:
|
|
23
|
-
COLUMNS_BY_NAME = None
|
|
24
|
-
|
|
25
|
-
def all_columns():
|
|
26
|
-
return [Compactions(), Cpu(), DataDir(), SnapshotsDir(), Gossip(), HostId(), Memory(),
|
|
27
|
-
NodeAddress(), NodeLoad(), NodeOwns(), NodeStatus(),NodeTokens(), PodName(), CassandraVolume(), RootVolume()]
|
|
28
|
-
|
|
29
|
-
def columns_by_name():
|
|
30
|
-
return {c.name(): c.__class__ for c in Columns.all_columns()}
|
|
31
|
-
|
|
32
|
-
def create_columns(columns: str):
|
|
33
|
-
if not Columns.COLUMNS_BY_NAME:
|
|
34
|
-
Columns.COLUMNS_BY_NAME = Columns.columns_by_name()
|
|
35
|
-
|
|
36
|
-
cols = []
|
|
37
|
-
for name in columns.split(','):
|
|
38
|
-
name = name.strip(' ')
|
|
39
|
-
if not name in Columns.COLUMNS_BY_NAME:
|
|
40
|
-
return None
|
|
41
|
-
cols.append(Columns.COLUMNS_BY_NAME[name]())
|
|
42
|
-
|
|
43
|
-
return cols
|
walker/commands/add_user.py
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import signal
|
|
2
|
-
import traceback
|
|
3
|
-
|
|
4
|
-
from walker.app_session import AppSession
|
|
5
|
-
from walker.apps import Apps
|
|
6
|
-
from walker.sso.idp import Idp
|
|
7
|
-
from walker.sso.idp_login import IdpLogin
|
|
8
|
-
from walker.commands.command import Command
|
|
9
|
-
from walker.repl_state import ReplState
|
|
10
|
-
from walker.utils import log, log2
|
|
11
|
-
|
|
12
|
-
class AddAdmin(Command):
|
|
13
|
-
COMMAND = 'add admin'
|
|
14
|
-
|
|
15
|
-
# the singleton pattern
|
|
16
|
-
def __new__(cls, *args, **kwargs):
|
|
17
|
-
if not hasattr(cls, 'instance'): cls.instance = super(AddAdmin, cls).__new__(cls)
|
|
18
|
-
|
|
19
|
-
return cls.instance
|
|
20
|
-
|
|
21
|
-
def __init__(self, successor: Command=None):
|
|
22
|
-
super().__init__(successor)
|
|
23
|
-
|
|
24
|
-
def command(self):
|
|
25
|
-
return AddAdmin.COMMAND
|
|
26
|
-
|
|
27
|
-
def run(self, cmd: str, state: ReplState):
|
|
28
|
-
def custom_handler(signum, frame):
|
|
29
|
-
AppSession.ctrl_c_entered = True
|
|
30
|
-
|
|
31
|
-
signal.signal(signal.SIGINT, custom_handler)
|
|
32
|
-
|
|
33
|
-
if not(args := self.args(cmd)):
|
|
34
|
-
return super().run(cmd, state)
|
|
35
|
-
|
|
36
|
-
state, args = self.apply_state(args, state)
|
|
37
|
-
|
|
38
|
-
args, print_token = Command.extract_options(args, '--print-token')
|
|
39
|
-
|
|
40
|
-
username: str = None
|
|
41
|
-
if len(args) > 0:
|
|
42
|
-
username = args[0]
|
|
43
|
-
|
|
44
|
-
login: IdpLogin = None
|
|
45
|
-
while not login:
|
|
46
|
-
try:
|
|
47
|
-
if not(host := Apps.app_host('c3', 'c3', state.namespace)):
|
|
48
|
-
log2('Cannot locate ingress for app.')
|
|
49
|
-
username = None
|
|
50
|
-
continue
|
|
51
|
-
|
|
52
|
-
if not (login := Idp.login(host, username=username, use_cached=False)):
|
|
53
|
-
log2('Invalid username/password. Please try again.')
|
|
54
|
-
username = None
|
|
55
|
-
except:
|
|
56
|
-
log2(traceback.format_exc())
|
|
57
|
-
pass
|
|
58
|
-
|
|
59
|
-
if print_token:
|
|
60
|
-
log(f'IDP_TOKEN={login.ser()}')
|
|
61
|
-
|
|
62
|
-
return state
|
|
63
|
-
|
|
64
|
-
def completion(self, _: ReplState):
|
|
65
|
-
return {}
|
|
66
|
-
|
|
67
|
-
def help(self, _: ReplState):
|
|
68
|
-
return f'{AddAdmin.COMMAND}\t SSO login'
|
walker/commands/app.py
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
|
|
3
|
-
from walker.apps import Apps
|
|
4
|
-
from walker.commands.command import Command
|
|
5
|
-
from walker.repl_state import ReplState, RequiredState
|
|
6
|
-
from walker.app_session import AppSession
|
|
7
|
-
from walker.utils import log2
|
|
8
|
-
|
|
9
|
-
class App(Command):
|
|
10
|
-
COMMAND = 'app'
|
|
11
|
-
|
|
12
|
-
# the singleton pattern
|
|
13
|
-
def __new__(cls, *args, **kwargs):
|
|
14
|
-
if not hasattr(cls, 'instance'): cls.instance = super(App, cls).__new__(cls)
|
|
15
|
-
|
|
16
|
-
return cls.instance
|
|
17
|
-
|
|
18
|
-
def __init__(self, successor: Command=None):
|
|
19
|
-
super().__init__(successor)
|
|
20
|
-
|
|
21
|
-
def command(self):
|
|
22
|
-
return App.COMMAND
|
|
23
|
-
|
|
24
|
-
def required(self):
|
|
25
|
-
return RequiredState.CLUSTER_OR_POD
|
|
26
|
-
|
|
27
|
-
def run(self, cmd: str, state: ReplState):
|
|
28
|
-
if not(args := self.args(cmd)):
|
|
29
|
-
return super().run(cmd, state)
|
|
30
|
-
|
|
31
|
-
state, args = self.apply_state(args, state)
|
|
32
|
-
if not self.validate_state(state, app_required=RequiredState.APP_APP):
|
|
33
|
-
return state
|
|
34
|
-
|
|
35
|
-
args, forced = Command.extract_options(args, '--force')
|
|
36
|
-
|
|
37
|
-
if not args:
|
|
38
|
-
return 'arg missing'
|
|
39
|
-
|
|
40
|
-
t_f = args[0].split('.')
|
|
41
|
-
if len(t_f) < 2:
|
|
42
|
-
return 'arg missing'
|
|
43
|
-
|
|
44
|
-
payload, valid = Apps().payload(t_f[0], t_f[1], args[1:] if len(args) > 1 else [])
|
|
45
|
-
if not valid:
|
|
46
|
-
log2('Missing one or more action arguments.')
|
|
47
|
-
return state
|
|
48
|
-
|
|
49
|
-
if payload:
|
|
50
|
-
try:
|
|
51
|
-
payload = json.loads(payload)
|
|
52
|
-
except json.decoder.JSONDecodeError as e:
|
|
53
|
-
log2(f'Invalid json argument: {e}')
|
|
54
|
-
return state
|
|
55
|
-
|
|
56
|
-
AppSession.run(state.app_env, state.app_app, state.namespace, t_f[0], t_f[1], payload=payload, forced=forced)
|
|
57
|
-
|
|
58
|
-
return state
|
|
59
|
-
|
|
60
|
-
def completion(self, state: ReplState):
|
|
61
|
-
if state.app_app:
|
|
62
|
-
return super().completion(state, {'--force': None})
|
|
63
|
-
|
|
64
|
-
return {}
|
|
65
|
-
|
|
66
|
-
def help(self, _: ReplState):
|
|
67
|
-
return f"{App.COMMAND} [--force]\t post app API query with type and function"
|
walker/commands/bash.py
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
from walker.commands.command import Command
|
|
2
|
-
from walker.k8s_utils.cassandra_clusters import CassandraClusters
|
|
3
|
-
from walker.k8s_utils.cassandra_nodes import CassandraNodes
|
|
4
|
-
from walker.repl_state import BashSession, ReplState, RequiredState
|
|
5
|
-
|
|
6
|
-
class Bash(Command):
|
|
7
|
-
COMMAND = 'bash'
|
|
8
|
-
|
|
9
|
-
# the singleton pattern
|
|
10
|
-
def __new__(cls, *args, **kwargs):
|
|
11
|
-
if not hasattr(cls, 'instance'): cls.instance = super(Bash, cls).__new__(cls)
|
|
12
|
-
|
|
13
|
-
return cls.instance
|
|
14
|
-
|
|
15
|
-
def __init__(self, successor: Command=None):
|
|
16
|
-
super().__init__(successor)
|
|
17
|
-
|
|
18
|
-
def command(self):
|
|
19
|
-
return Bash.COMMAND
|
|
20
|
-
|
|
21
|
-
def required(self):
|
|
22
|
-
return RequiredState.CLUSTER_OR_POD
|
|
23
|
-
|
|
24
|
-
def run(self, cmd: str, s0: ReplState):
|
|
25
|
-
if not(args := self.args(cmd)):
|
|
26
|
-
return super().run(cmd, s0)
|
|
27
|
-
|
|
28
|
-
state, args = self.apply_state(args, s0)
|
|
29
|
-
if not self.validate_state(state):
|
|
30
|
-
return state
|
|
31
|
-
|
|
32
|
-
if state.in_repl:
|
|
33
|
-
r = self.exec_with_dir(s0, args)
|
|
34
|
-
if not r:
|
|
35
|
-
state.exit_bash()
|
|
36
|
-
|
|
37
|
-
return 'inconsistent pwd'
|
|
38
|
-
|
|
39
|
-
return r
|
|
40
|
-
else:
|
|
41
|
-
a = ' '.join(args)
|
|
42
|
-
command = f'bash -c "{a}"'
|
|
43
|
-
|
|
44
|
-
if state.pod:
|
|
45
|
-
CassandraNodes.exec(state.pod, state.namespace, command, show_out=True)
|
|
46
|
-
elif state.sts:
|
|
47
|
-
CassandraClusters.exec(state.sts, state.namespace, command, action='bash', show_out=True)
|
|
48
|
-
|
|
49
|
-
return state
|
|
50
|
-
|
|
51
|
-
def exec_with_dir(self, state: ReplState, args: list[str]):
|
|
52
|
-
session_just_created = False
|
|
53
|
-
if not args:
|
|
54
|
-
session_just_created = True
|
|
55
|
-
session = BashSession(state.device)
|
|
56
|
-
state.enter_bash(session)
|
|
57
|
-
|
|
58
|
-
if state.bash_session:
|
|
59
|
-
if args != ['pwd']:
|
|
60
|
-
if args:
|
|
61
|
-
args.append('&&')
|
|
62
|
-
args.extend(['pwd', '>', f'/tmp/.qing-{state.bash_session.session_id}'])
|
|
63
|
-
|
|
64
|
-
if not session_just_created:
|
|
65
|
-
if pwd := state.bash_session.pwd(state):
|
|
66
|
-
args = ['cd', pwd, '&&'] + args
|
|
67
|
-
|
|
68
|
-
a = ' '.join(args)
|
|
69
|
-
command = f'bash -c "{a}"'
|
|
70
|
-
|
|
71
|
-
rs = []
|
|
72
|
-
|
|
73
|
-
if state.pod:
|
|
74
|
-
rs = [CassandraNodes.exec(state.pod, state.namespace, command, show_out=not session_just_created)]
|
|
75
|
-
elif state.sts:
|
|
76
|
-
rs = CassandraClusters.exec(state.sts, state.namespace, command, action='bash', show_out=not session_just_created)
|
|
77
|
-
|
|
78
|
-
return rs
|
|
79
|
-
|
|
80
|
-
def completion(self, state: ReplState):
|
|
81
|
-
if state.pod or state.sts:
|
|
82
|
-
return {Bash.COMMAND: None}
|
|
83
|
-
|
|
84
|
-
return {}
|
|
85
|
-
|
|
86
|
-
def help(self, _: ReplState):
|
|
87
|
-
return f'{Bash.COMMAND} [bash-commands]\t run bash'
|
walker/commands/cd.py
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
from walker.commands.command import Command
|
|
2
|
-
from walker.commands.postgres.postgres_session import PostgresSession
|
|
3
|
-
from walker.k8s_utils.cassandra_clusters import CassandraClusters
|
|
4
|
-
from walker.k8s_utils.kube_context import KubeContext
|
|
5
|
-
from walker.k8s_utils.statefulsets import StatefulSets
|
|
6
|
-
from walker.repl_state import ReplState
|
|
7
|
-
from walker.utils import log2
|
|
8
|
-
from walker.apps import Apps
|
|
9
|
-
|
|
10
|
-
class Cd(Command):
|
|
11
|
-
COMMAND = 'cd'
|
|
12
|
-
|
|
13
|
-
# the singleton pattern
|
|
14
|
-
def __new__(cls, *args, **kwargs):
|
|
15
|
-
if not hasattr(cls, 'instance'): cls.instance = super(Cd, cls).__new__(cls)
|
|
16
|
-
|
|
17
|
-
return cls.instance
|
|
18
|
-
|
|
19
|
-
def __init__(self, successor: Command=None):
|
|
20
|
-
super().__init__(successor)
|
|
21
|
-
|
|
22
|
-
def command(self):
|
|
23
|
-
return Cd.COMMAND
|
|
24
|
-
|
|
25
|
-
def run(self, cmd: str, state: ReplState):
|
|
26
|
-
if not(args := self.args(cmd)):
|
|
27
|
-
return super().run(cmd, state)
|
|
28
|
-
|
|
29
|
-
if len(args) < 2:
|
|
30
|
-
return state
|
|
31
|
-
|
|
32
|
-
arg = args[1]
|
|
33
|
-
for dir in arg.split('/'):
|
|
34
|
-
if state.device == ReplState.P:
|
|
35
|
-
if dir == '':
|
|
36
|
-
state.pg_path = None
|
|
37
|
-
else:
|
|
38
|
-
session = PostgresSession(state.namespace, state.pg_path)
|
|
39
|
-
# patch up state.namespace from pg cd
|
|
40
|
-
if not state.namespace and (ns := session.find_namespace(arg)):
|
|
41
|
-
state.namespace = ns
|
|
42
|
-
state.pg_path = session.directory(arg)
|
|
43
|
-
elif state.device == ReplState.A:
|
|
44
|
-
if dir == '':
|
|
45
|
-
state.app_env = None
|
|
46
|
-
state.app_app = None
|
|
47
|
-
elif dir == '..':
|
|
48
|
-
if state.app_app:
|
|
49
|
-
state.app_app = None
|
|
50
|
-
else:
|
|
51
|
-
state.app_env = None
|
|
52
|
-
else:
|
|
53
|
-
if not state.app_env:
|
|
54
|
-
tks = dir.split('@')
|
|
55
|
-
if len(tks) > 1:
|
|
56
|
-
state.namespace = tks[1]
|
|
57
|
-
|
|
58
|
-
state.app_env = dir.split('@')[0]
|
|
59
|
-
else:
|
|
60
|
-
state.app_app = dir
|
|
61
|
-
else:
|
|
62
|
-
if dir == '':
|
|
63
|
-
state.sts = None
|
|
64
|
-
state.pod = None
|
|
65
|
-
elif dir == '..':
|
|
66
|
-
if state.pod:
|
|
67
|
-
state.pod = None
|
|
68
|
-
else:
|
|
69
|
-
state.sts = None
|
|
70
|
-
else:
|
|
71
|
-
if not state.sts:
|
|
72
|
-
ss_and_ns = dir.split('@')
|
|
73
|
-
state.sts = ss_and_ns[0]
|
|
74
|
-
state.namespace = ss_and_ns[1]
|
|
75
|
-
elif not state.pod:
|
|
76
|
-
p, _ = KubeContext.is_pod_name(dir)
|
|
77
|
-
if p:
|
|
78
|
-
state.pod = p
|
|
79
|
-
else:
|
|
80
|
-
names = CassandraClusters.pod_names_by_host_id(state.sts, state.namespace);
|
|
81
|
-
if dir in names:
|
|
82
|
-
state.pod = names[dir]
|
|
83
|
-
else:
|
|
84
|
-
log2('Not a valid pod name or host id.')
|
|
85
|
-
|
|
86
|
-
return state
|
|
87
|
-
|
|
88
|
-
def completion(self, state: ReplState):
|
|
89
|
-
if state.device == ReplState.P:
|
|
90
|
-
pg = PostgresSession(state.namespace, state.pg_path) if state.pg_path else None
|
|
91
|
-
if pg and pg.db:
|
|
92
|
-
return {Cd.COMMAND: {'..': None}}
|
|
93
|
-
elif pg and pg.host:
|
|
94
|
-
return {Cd.COMMAND: {'..': None} | {p['name']: None for p in pg.databases()}}
|
|
95
|
-
else:
|
|
96
|
-
return {Cd.COMMAND: {p: None for p in PostgresSession.hosts(state.namespace)}}
|
|
97
|
-
elif state.device == ReplState.A:
|
|
98
|
-
if state.app_app:
|
|
99
|
-
return {Cd.COMMAND: {'..': None}}
|
|
100
|
-
elif state.app_env:
|
|
101
|
-
return {Cd.COMMAND: {'..': None} | {app[0].split('-')[1]: None for app in Apps.apps(state.app_env)}}
|
|
102
|
-
else:
|
|
103
|
-
return {Cd.COMMAND: {'..': None} | {env[0]: None for env in Apps.envs()}}
|
|
104
|
-
else:
|
|
105
|
-
if state.pod:
|
|
106
|
-
return {Cd.COMMAND: {'..': None}}
|
|
107
|
-
elif state.sts:
|
|
108
|
-
return {Cd.COMMAND: {'..': None} | {p: None for p in StatefulSets.pod_names(state.sts, state.namespace)}}
|
|
109
|
-
else:
|
|
110
|
-
return {Cd.COMMAND: {p: None for p in StatefulSets.list_sts_names()}}
|
|
111
|
-
|
|
112
|
-
return {}
|
|
113
|
-
|
|
114
|
-
def help(self, _: ReplState):
|
|
115
|
-
return f'{Cd.COMMAND} <path> | .. \t move around'
|
walker/commands/check.py
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import click
|
|
2
|
-
|
|
3
|
-
from walker.checks.check_result import CheckResult
|
|
4
|
-
from walker.checks.check_utils import all_checks, checks_from_csv, run_checks
|
|
5
|
-
from walker.commands.command import Command
|
|
6
|
-
from walker.commands.command_helpers import ClusterOrPodCommandHelper
|
|
7
|
-
from walker.commands.issues import Issues
|
|
8
|
-
from walker.repl_state import ReplState
|
|
9
|
-
from walker.utils import lines_to_tabular, log
|
|
10
|
-
|
|
11
|
-
class Check(Issues):
|
|
12
|
-
COMMAND = 'check'
|
|
13
|
-
|
|
14
|
-
# the singleton pattern
|
|
15
|
-
def __new__(cls, *args, **kwargs):
|
|
16
|
-
if not hasattr(cls, 'instance'): cls.instance = super(Check, cls).__new__(cls)
|
|
17
|
-
|
|
18
|
-
return cls.instance
|
|
19
|
-
|
|
20
|
-
def __init__(self, successor: Command=None):
|
|
21
|
-
super().__init__(successor)
|
|
22
|
-
|
|
23
|
-
def command(self):
|
|
24
|
-
return Check.COMMAND
|
|
25
|
-
|
|
26
|
-
def run(self, cmd: str, state: ReplState):
|
|
27
|
-
if not(args := self.args(cmd)):
|
|
28
|
-
return super().run(cmd, state)
|
|
29
|
-
|
|
30
|
-
state, args = self.apply_state(args, state)
|
|
31
|
-
args, show = Command.extract_options(args, ['-s', '--show'])
|
|
32
|
-
|
|
33
|
-
if not args:
|
|
34
|
-
if state.in_repl:
|
|
35
|
-
log(lines_to_tabular([check.help() for check in all_checks()], separator=':'))
|
|
36
|
-
else:
|
|
37
|
-
log('* Check name is missing.')
|
|
38
|
-
Command.display_help()
|
|
39
|
-
return 'arg missing'
|
|
40
|
-
|
|
41
|
-
checks = checks_from_csv(args[0])
|
|
42
|
-
if not checks:
|
|
43
|
-
return 'invalid check name'
|
|
44
|
-
|
|
45
|
-
results = run_checks(state.sts, state.namespace, state.pod, checks=checks, show_output=show)
|
|
46
|
-
|
|
47
|
-
issues = CheckResult.collect_issues(results)
|
|
48
|
-
Issues.show_issues(issues, in_repl=state.in_repl)
|
|
49
|
-
|
|
50
|
-
return issues if issues else 'no issues found'
|
|
51
|
-
|
|
52
|
-
def completion(self, _: ReplState):
|
|
53
|
-
return {Check.COMMAND: {check.name(): None for check in all_checks()}}
|
|
54
|
-
|
|
55
|
-
def help(self, _: ReplState):
|
|
56
|
-
return f'{Check.COMMAND} <check-name>\t run a single check'
|
|
57
|
-
|
|
58
|
-
class CheckCommandHelper(click.Command):
|
|
59
|
-
def get_help(self, ctx: click.Context):
|
|
60
|
-
log(super().get_help(ctx))
|
|
61
|
-
log()
|
|
62
|
-
log('Check-names:')
|
|
63
|
-
|
|
64
|
-
for check in all_checks():
|
|
65
|
-
log(f' {check.name()}')
|
|
66
|
-
log()
|
|
67
|
-
|
|
68
|
-
ClusterOrPodCommandHelper.cluter_or_pod_help()
|
walker/commands/command.py
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
from abc import abstractmethod
|
|
2
|
-
import copy
|
|
3
|
-
import subprocess
|
|
4
|
-
import sys
|
|
5
|
-
|
|
6
|
-
from walker.repl_state import ReplState, RequiredState
|
|
7
|
-
|
|
8
|
-
repl_cmds: list['Command'] = []
|
|
9
|
-
|
|
10
|
-
class Command:
|
|
11
|
-
"""Abstract base class for commands"""
|
|
12
|
-
def __init__(self, successor: 'Command'=None):
|
|
13
|
-
if not hasattr(self, '_successor'):
|
|
14
|
-
self._successor = successor
|
|
15
|
-
|
|
16
|
-
@abstractmethod
|
|
17
|
-
def command(self) -> str:
|
|
18
|
-
pass
|
|
19
|
-
|
|
20
|
-
# The chain of responsibility pattern
|
|
21
|
-
# Do not do child of child!!!
|
|
22
|
-
@abstractmethod
|
|
23
|
-
def run(self, cmd: str, state: ReplState):
|
|
24
|
-
if self._successor:
|
|
25
|
-
return self._successor.run(cmd, state)
|
|
26
|
-
|
|
27
|
-
return None
|
|
28
|
-
|
|
29
|
-
def completion(self, _: ReplState, leaf: dict[str, any] = None) -> dict[str, any]:
|
|
30
|
-
# COMMAND = 'reaper activate schedule'
|
|
31
|
-
d = leaf
|
|
32
|
-
for t in reversed(self.command().split(' ')):
|
|
33
|
-
d = {t: d}
|
|
34
|
-
|
|
35
|
-
return d
|
|
36
|
-
|
|
37
|
-
def required(self) -> RequiredState:
|
|
38
|
-
return None
|
|
39
|
-
|
|
40
|
-
def validate_state(self, state: ReplState, pg_required: RequiredState = None, app_required: RequiredState = None):
|
|
41
|
-
return state.validate(self.required(), pg_required=pg_required, app_required=app_required)
|
|
42
|
-
|
|
43
|
-
@abstractmethod
|
|
44
|
-
def help(self, state: ReplState) -> str:
|
|
45
|
-
pass
|
|
46
|
-
|
|
47
|
-
def args(self, cmd: str):
|
|
48
|
-
a = list(filter(None, cmd.split(' ')))
|
|
49
|
-
spec = self.command_tokens()
|
|
50
|
-
if spec != a[:len(spec)]:
|
|
51
|
-
return None
|
|
52
|
-
|
|
53
|
-
return a
|
|
54
|
-
|
|
55
|
-
def apply_state(self, args: list[str], state: ReplState, resolve_pg = True) -> tuple[ReplState, list[str]]:
|
|
56
|
-
return state.apply_args(args, cmd=self.command_tokens(), resolve_pg=resolve_pg)
|
|
57
|
-
|
|
58
|
-
def command_tokens(self):
|
|
59
|
-
return self.command().split(' ')
|
|
60
|
-
|
|
61
|
-
# build a chain-of-responsibility chain
|
|
62
|
-
def chain(cl: list['Command']):
|
|
63
|
-
global repl_cmds
|
|
64
|
-
repl_cmds.extend(cl)
|
|
65
|
-
|
|
66
|
-
cmds = cl[0]
|
|
67
|
-
cmd = cmds
|
|
68
|
-
for successor in cl[1:]:
|
|
69
|
-
cmd._successor = successor
|
|
70
|
-
cmd = successor
|
|
71
|
-
|
|
72
|
-
return cmds
|
|
73
|
-
|
|
74
|
-
def command_to_completion(self):
|
|
75
|
-
# COMMAND = 'reaper activate schedule'
|
|
76
|
-
d = None
|
|
77
|
-
for t in reversed(self.command().split(' ')):
|
|
78
|
-
d = {t: d}
|
|
79
|
-
|
|
80
|
-
return d
|
|
81
|
-
|
|
82
|
-
def display_help():
|
|
83
|
-
args = copy.copy(sys.argv)
|
|
84
|
-
args.extend(['--help'])
|
|
85
|
-
subprocess.run(args)
|
|
86
|
-
|
|
87
|
-
def extract_options(args: list[str], names: list[str]):
|
|
88
|
-
found: list[str] = []
|
|
89
|
-
|
|
90
|
-
new_args: list[str] = []
|
|
91
|
-
for arg in args:
|
|
92
|
-
if arg in names:
|
|
93
|
-
found.append(arg)
|
|
94
|
-
else:
|
|
95
|
-
new_args.append(arg)
|
|
96
|
-
|
|
97
|
-
return new_args, found
|
|
98
|
-
|
|
99
|
-
def print_chain(cmd: 'Command'):
|
|
100
|
-
print(f'{cmd.command()}', end = '')
|
|
101
|
-
while s := cmd._successor:
|
|
102
|
-
print(f'-> {s.command()}', end = '')
|
|
103
|
-
cmd = s
|
|
104
|
-
print()
|