kaqing 2.0.110__py3-none-any.whl → 2.0.214__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.
Potentially problematic release.
This version of kaqing might be problematic. Click here for more details.
- adam/__init__.py +0 -2
- adam/app_session.py +9 -12
- adam/apps.py +18 -4
- adam/batch.py +19 -19
- adam/checks/check_utils.py +16 -46
- adam/checks/cpu.py +7 -1
- adam/checks/cpu_metrics.py +52 -0
- adam/checks/disk.py +2 -3
- adam/columns/columns.py +3 -1
- adam/columns/cpu.py +3 -1
- adam/columns/cpu_metrics.py +22 -0
- adam/columns/memory.py +3 -4
- adam/commands/__init__.py +24 -0
- adam/commands/app/app.py +38 -0
- adam/commands/{app_ping.py → app/app_ping.py} +7 -13
- adam/commands/{login.py → app/login.py} +22 -24
- adam/commands/app/show_app_actions.py +49 -0
- adam/commands/{show → app}/show_app_id.py +8 -11
- adam/commands/{show → app}/show_app_queues.py +7 -14
- adam/commands/app/show_login.py +56 -0
- adam/commands/app/utils_app.py +106 -0
- adam/commands/audit/audit.py +22 -40
- adam/commands/audit/audit_repair_tables.py +15 -19
- adam/commands/audit/audit_run.py +15 -22
- adam/commands/audit/completions_l.py +15 -0
- adam/commands/audit/show_last10.py +4 -18
- adam/commands/audit/show_slow10.py +4 -17
- adam/commands/audit/show_top10.py +4 -16
- adam/commands/audit/utils_show_top10.py +15 -3
- 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/cassandra/__init__.py +0 -0
- adam/commands/cassandra/download_cassandra_log.py +45 -0
- adam/commands/{restart.py → cassandra/restart_cluster.py} +12 -26
- adam/commands/cassandra/restart_node.py +51 -0
- adam/commands/cassandra/restart_nodes.py +47 -0
- adam/commands/{rollout.py → cassandra/rollout.py} +20 -25
- adam/commands/cassandra/show_cassandra_repairs.py +37 -0
- adam/commands/cassandra/show_cassandra_status.py +117 -0
- adam/commands/{show → cassandra}/show_cassandra_version.py +5 -18
- adam/commands/cassandra/show_processes.py +50 -0
- adam/commands/cassandra/show_storage.py +44 -0
- adam/commands/{watch.py → cassandra/watch.py} +26 -29
- adam/commands/cli/__init__.py +0 -0
- adam/commands/{cli_commands.py → cli/cli_commands.py} +8 -4
- adam/commands/cli/clipboard_copy.py +86 -0
- adam/commands/cli/show_cli_commands.py +56 -0
- adam/commands/code.py +57 -0
- adam/commands/command.py +211 -40
- adam/commands/commands_utils.py +20 -27
- adam/commands/config/__init__.py +0 -0
- adam/commands/{param_get.py → config/param_get.py} +11 -14
- adam/commands/{param_set.py → config/param_set.py} +8 -12
- adam/commands/{show → config}/show_params.py +2 -5
- adam/commands/cql/alter_tables.py +66 -0
- adam/commands/cql/completions_c.py +29 -0
- adam/commands/cql/cqlsh.py +10 -32
- adam/commands/cql/utils_cql.py +306 -0
- adam/commands/debug/__init__.py +0 -0
- adam/commands/debug/debug.py +22 -0
- adam/commands/debug/debug_completes.py +35 -0
- adam/commands/debug/debug_timings.py +35 -0
- adam/commands/debug/show_offloaded_completes.py +45 -0
- adam/commands/deploy/code_start.py +7 -10
- adam/commands/deploy/code_stop.py +4 -21
- adam/commands/deploy/code_utils.py +3 -3
- adam/commands/deploy/deploy.py +4 -27
- adam/commands/deploy/deploy_frontend.py +14 -17
- adam/commands/deploy/deploy_pg_agent.py +3 -6
- adam/commands/deploy/deploy_pod.py +65 -73
- adam/commands/deploy/deploy_utils.py +14 -24
- adam/commands/deploy/undeploy.py +4 -27
- adam/commands/deploy/undeploy_frontend.py +4 -7
- adam/commands/deploy/undeploy_pg_agent.py +6 -8
- adam/commands/deploy/undeploy_pod.py +11 -12
- adam/commands/devices/__init__.py +0 -0
- adam/commands/devices/device.py +149 -0
- adam/commands/devices/device_app.py +163 -0
- adam/commands/devices/device_auit_log.py +49 -0
- adam/commands/devices/device_cass.py +179 -0
- adam/commands/devices/device_export.py +87 -0
- adam/commands/devices/device_postgres.py +160 -0
- adam/commands/devices/devices.py +25 -0
- adam/commands/diag/__init__.py +0 -0
- adam/commands/{check.py → diag/check.py} +16 -25
- adam/commands/diag/generate_report.py +52 -0
- adam/commands/diag/issues.py +43 -0
- adam/commands/exit.py +1 -4
- adam/commands/export/__init__.py +0 -0
- adam/commands/export/clean_up_all_export_sessions.py +37 -0
- adam/commands/export/clean_up_export_sessions.py +39 -0
- adam/commands/export/completions_x.py +11 -0
- adam/commands/export/download_export_session.py +40 -0
- adam/commands/export/drop_export_database.py +39 -0
- adam/commands/export/drop_export_databases.py +37 -0
- adam/commands/export/export.py +37 -0
- adam/commands/export/export_databases.py +251 -0
- adam/commands/export/export_select.py +34 -0
- adam/commands/export/export_sessions.py +210 -0
- adam/commands/export/export_use.py +49 -0
- adam/commands/export/export_x_select.py +48 -0
- adam/commands/export/exporter.py +419 -0
- adam/commands/export/import_files.py +44 -0
- adam/commands/export/import_session.py +40 -0
- adam/commands/export/importer.py +81 -0
- adam/commands/export/importer_athena.py +157 -0
- adam/commands/export/importer_sqlite.py +78 -0
- adam/commands/export/show_column_counts.py +45 -0
- adam/commands/export/show_export_databases.py +39 -0
- adam/commands/export/show_export_session.py +39 -0
- adam/commands/export/show_export_sessions.py +37 -0
- adam/commands/export/utils_export.py +366 -0
- adam/commands/fs/__init__.py +0 -0
- adam/commands/fs/cat.py +36 -0
- adam/commands/fs/cat_local.py +42 -0
- adam/commands/fs/cd.py +41 -0
- adam/commands/fs/download_file.py +47 -0
- adam/commands/fs/find_files.py +51 -0
- adam/commands/fs/find_processes.py +76 -0
- adam/commands/fs/head.py +36 -0
- adam/commands/fs/ls.py +41 -0
- adam/commands/fs/ls_local.py +40 -0
- adam/commands/fs/pwd.py +45 -0
- adam/commands/fs/rm.py +18 -0
- adam/commands/fs/rm_downloads.py +39 -0
- adam/commands/fs/rm_logs.py +38 -0
- adam/commands/{shell.py → fs/shell.py} +12 -4
- adam/commands/{show → fs}/show_adam.py +3 -3
- adam/commands/{show → fs}/show_host.py +1 -1
- adam/commands/help.py +5 -3
- adam/commands/intermediate_command.py +52 -0
- adam/commands/kubectl.py +38 -0
- adam/commands/medusa/medusa.py +4 -22
- adam/commands/medusa/medusa_backup.py +20 -27
- adam/commands/medusa/medusa_restore.py +35 -48
- adam/commands/medusa/medusa_show_backupjobs.py +16 -18
- adam/commands/medusa/medusa_show_restorejobs.py +13 -18
- adam/commands/medusa/utils_medusa.py +15 -0
- adam/commands/nodetool/__init__.py +0 -0
- adam/commands/{nodetool.py → nodetool/nodetool.py} +9 -20
- adam/commands/postgres/completions_p.py +22 -0
- adam/commands/postgres/postgres.py +47 -55
- adam/commands/postgres/postgres_databases.py +269 -0
- adam/commands/postgres/postgres_ls.py +5 -9
- adam/commands/postgres/postgres_preview.py +5 -9
- adam/commands/postgres/utils_postgres.py +80 -0
- adam/commands/preview_table.py +8 -44
- adam/commands/reaper/reaper.py +4 -27
- adam/commands/reaper/reaper_forward.py +49 -56
- adam/commands/reaper/reaper_forward_session.py +6 -0
- adam/commands/reaper/reaper_forward_stop.py +10 -16
- adam/commands/reaper/reaper_restart.py +7 -14
- adam/commands/reaper/reaper_run_abort.py +8 -33
- adam/commands/reaper/reaper_runs.py +43 -58
- adam/commands/reaper/reaper_runs_abort.py +29 -49
- adam/commands/reaper/reaper_schedule_activate.py +14 -33
- adam/commands/reaper/reaper_schedule_start.py +9 -33
- adam/commands/reaper/reaper_schedule_stop.py +9 -33
- adam/commands/reaper/reaper_schedules.py +4 -14
- adam/commands/reaper/reaper_status.py +8 -16
- adam/commands/reaper/utils_reaper.py +203 -0
- adam/commands/repair/repair.py +4 -22
- adam/commands/repair/repair_log.py +5 -11
- adam/commands/repair/repair_run.py +27 -34
- adam/commands/repair/repair_scan.py +32 -40
- adam/commands/repair/repair_stop.py +5 -12
- adam/commands/show.py +40 -0
- adam/config.py +5 -15
- adam/embedded_params.py +1 -1
- adam/log.py +4 -4
- adam/repl.py +83 -116
- adam/repl_commands.py +86 -45
- adam/repl_session.py +9 -1
- adam/repl_state.py +176 -40
- adam/sql/async_executor.py +62 -0
- adam/sql/lark_completer.py +286 -0
- adam/sql/lark_parser.py +604 -0
- adam/sql/qingl.lark +1076 -0
- adam/sql/sql_completer.py +52 -27
- adam/sql/sql_state_machine.py +131 -19
- adam/sso/authn_ad.py +6 -8
- adam/sso/authn_okta.py +4 -6
- adam/sso/cred_cache.py +4 -9
- adam/sso/idp.py +9 -12
- adam/utils.py +670 -31
- adam/utils_athena.py +145 -0
- adam/utils_audits.py +12 -103
- adam/utils_issues.py +32 -0
- adam/utils_k8s/app_clusters.py +35 -0
- adam/utils_k8s/app_pods.py +41 -0
- adam/utils_k8s/cassandra_clusters.py +35 -20
- adam/utils_k8s/cassandra_nodes.py +15 -6
- adam/utils_k8s/custom_resources.py +16 -17
- adam/utils_k8s/ingresses.py +2 -2
- adam/utils_k8s/jobs.py +7 -11
- adam/utils_k8s/k8s.py +96 -0
- adam/utils_k8s/kube_context.py +3 -6
- adam/{pod_exec_result.py → utils_k8s/pod_exec_result.py} +13 -4
- adam/utils_k8s/pods.py +159 -89
- adam/utils_k8s/secrets.py +4 -4
- adam/utils_k8s/service_accounts.py +5 -4
- adam/utils_k8s/services.py +2 -2
- adam/utils_k8s/statefulsets.py +6 -14
- adam/utils_local.py +80 -0
- adam/utils_net.py +4 -4
- adam/utils_repl/__init__.py +0 -0
- adam/utils_repl/appendable_completer.py +6 -0
- adam/utils_repl/automata_completer.py +48 -0
- adam/utils_repl/repl_completer.py +93 -0
- adam/utils_repl/state_machine.py +173 -0
- adam/utils_sqlite.py +132 -0
- adam/version.py +1 -1
- {kaqing-2.0.110.dist-info → kaqing-2.0.214.dist-info}/METADATA +1 -1
- kaqing-2.0.214.dist-info/RECORD +272 -0
- kaqing-2.0.214.dist-info/top_level.txt +2 -0
- teddy/__init__.py +0 -0
- teddy/lark_parser.py +436 -0
- teddy/lark_parser2.py +618 -0
- adam/commands/alter_tables.py +0 -81
- adam/commands/app.py +0 -67
- adam/commands/bash.py +0 -150
- adam/commands/cd.py +0 -125
- adam/commands/cp.py +0 -95
- adam/commands/cql/cql_completions.py +0 -15
- adam/commands/cql/cql_utils.py +0 -112
- adam/commands/devices.py +0 -118
- adam/commands/issues.py +0 -75
- adam/commands/logs.py +0 -40
- adam/commands/ls.py +0 -146
- adam/commands/postgres/postgres_context.py +0 -239
- adam/commands/postgres/postgres_utils.py +0 -31
- adam/commands/postgres/psql_completions.py +0 -10
- adam/commands/pwd.py +0 -77
- adam/commands/reaper/reaper_session.py +0 -159
- adam/commands/report.py +0 -63
- adam/commands/show/show.py +0 -54
- adam/commands/show/show_app_actions.py +0 -56
- adam/commands/show/show_cassandra_status.py +0 -128
- adam/commands/show/show_commands.py +0 -61
- adam/commands/show/show_login.py +0 -63
- adam/commands/show/show_processes.py +0 -53
- adam/commands/show/show_repairs.py +0 -47
- adam/commands/show/show_storage.py +0 -52
- kaqing-2.0.110.dist-info/RECORD +0 -187
- kaqing-2.0.110.dist-info/top_level.txt +0 -1
- /adam/commands/{show → app}/__init__.py +0 -0
- /adam/commands/{nodetool_commands.py → nodetool/nodetool_commands.py} +0 -0
- {kaqing-2.0.110.dist-info → kaqing-2.0.214.dist-info}/WHEEL +0 -0
- {kaqing-2.0.110.dist-info → kaqing-2.0.214.dist-info}/entry_points.txt +0 -0
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
from collections.abc import Callable
|
|
2
|
-
import threading
|
|
3
|
-
from kubernetes import client
|
|
4
|
-
import portforward
|
|
5
|
-
import re
|
|
6
|
-
import requests
|
|
7
|
-
from typing import List, cast
|
|
8
|
-
|
|
9
|
-
from adam.config import Config
|
|
10
|
-
from adam.utils_k8s.kube_context import KubeContext
|
|
11
|
-
from adam.repl_state import ReplState
|
|
12
|
-
from adam.utils import lines_to_tabular, log2
|
|
13
|
-
|
|
14
|
-
class ReaperSession:
|
|
15
|
-
is_forwarding = False
|
|
16
|
-
stopping = threading.Event()
|
|
17
|
-
schedules_ids_by_cluster: dict[str, list[str]] = {}
|
|
18
|
-
|
|
19
|
-
def __init__(self, pod: str, headers: dict[str, str] = None):
|
|
20
|
-
self.pod = pod
|
|
21
|
-
self.headers = headers
|
|
22
|
-
|
|
23
|
-
def login(self, state: ReplState, local_addr: str, remote_addr: str, show_output = True) -> str :
|
|
24
|
-
user, pw = state.user_pass(secret_path='reaper.secret')
|
|
25
|
-
|
|
26
|
-
response = requests.post(f'http://{local_addr}/login', headers={
|
|
27
|
-
'Accept': '*'
|
|
28
|
-
},data={
|
|
29
|
-
'username':user,
|
|
30
|
-
'password':pw})
|
|
31
|
-
if show_output:
|
|
32
|
-
log2(f'POST {remote_addr}/login')
|
|
33
|
-
log2(f' username={user}&password={pw}')
|
|
34
|
-
|
|
35
|
-
if int(response.status_code / 100) != 2:
|
|
36
|
-
if show_output:
|
|
37
|
-
log2("login failed")
|
|
38
|
-
return None
|
|
39
|
-
|
|
40
|
-
return response.headers['Set-Cookie']
|
|
41
|
-
|
|
42
|
-
def port_forwarded(self, state: ReplState, path: str, body: Callable[[str, dict[str, str]], requests.Response], method: str = None, show_output = True):
|
|
43
|
-
local_port = Config().get('reaper.port-forward.local-port', 9001)
|
|
44
|
-
target_port = 8080
|
|
45
|
-
|
|
46
|
-
def f(local_addr: str, remote_addr: str):
|
|
47
|
-
if not self.headers:
|
|
48
|
-
self.headers = self.cookie_header(state, local_addr, remote_addr, show_output=show_output)
|
|
49
|
-
|
|
50
|
-
if show_output and method:
|
|
51
|
-
log2(f'{method} {remote_addr}/{path}')
|
|
52
|
-
response = body(f'http://{local_addr}/{path}', self.headers)
|
|
53
|
-
|
|
54
|
-
if response:
|
|
55
|
-
if int(response.status_code / 100) != 2:
|
|
56
|
-
if show_output:
|
|
57
|
-
log2(response.status_code)
|
|
58
|
-
return response
|
|
59
|
-
|
|
60
|
-
if show_output:
|
|
61
|
-
log2()
|
|
62
|
-
|
|
63
|
-
return response if response else 'no-response'
|
|
64
|
-
|
|
65
|
-
if KubeContext.in_cluster():
|
|
66
|
-
# cs-a526330d23-cs-a526330d23-default-sts-0 ->
|
|
67
|
-
# curl http://cs-a526330d23-cs-a526330d23-reaper-service.stgawsscpsr.svc.cluster.local:8080
|
|
68
|
-
groups = re.match(r'^(.*?-.*?-.*?-.*?-).*', state.sts)
|
|
69
|
-
if groups:
|
|
70
|
-
svc_name = Config().get('reaper.service-name', 'reaper-service')
|
|
71
|
-
svc = f'{groups[1]}{svc_name}.{state.namespace}.svc.cluster.local:{target_port}'
|
|
72
|
-
return f(local_addr=svc, remote_addr=svc)
|
|
73
|
-
else:
|
|
74
|
-
return None
|
|
75
|
-
else:
|
|
76
|
-
with portforward.forward(state.namespace, self.pod, local_port, target_port):
|
|
77
|
-
return f(local_addr=f'localhost:{local_port}', remote_addr=f'{self.pod}:{target_port}')
|
|
78
|
-
|
|
79
|
-
def cookie_header(self, state: ReplState, local_addr, remote_addr, show_output = True):
|
|
80
|
-
return {'Cookie': self.login(state, local_addr, remote_addr, show_output=show_output)}
|
|
81
|
-
|
|
82
|
-
def create(state: ReplState) -> 'ReaperSession':
|
|
83
|
-
pods = ReaperSession.list_reaper_pods(state.sts if state.sts else state.pod, state.namespace)
|
|
84
|
-
if pods:
|
|
85
|
-
return ReaperSession(pods[0].metadata.name)
|
|
86
|
-
else:
|
|
87
|
-
log2('No reaper found.')
|
|
88
|
-
|
|
89
|
-
return None
|
|
90
|
-
|
|
91
|
-
def list_reaper_pods(sts_name: str, namespace: str) -> List[client.V1Pod]:
|
|
92
|
-
v1 = client.CoreV1Api()
|
|
93
|
-
|
|
94
|
-
# k8ssandra.io/reaper: cs-d0767a536f-cs-d0767a536f-reaper
|
|
95
|
-
groups = re.match(Config().get('reaper.pod.cluster-regex', r'(.*?-.*?-.*?-.*?)-.*'), sts_name)
|
|
96
|
-
label_selector = Config().get('reaper.pod.label-selector', 'k8ssandra.io/reaper={cluster}-reaper').replace('{cluster}', groups[1])
|
|
97
|
-
|
|
98
|
-
return cast(List[client.V1Pod], v1.list_namespaced_pod(namespace, label_selector=label_selector).items)
|
|
99
|
-
|
|
100
|
-
def show_schedules(self, state: ReplState, filter: Callable[[list[dict]], dict] = None):
|
|
101
|
-
schedules = self.list_schedules(state, filter=filter)
|
|
102
|
-
# forced refresh of schedule list
|
|
103
|
-
if not filter:
|
|
104
|
-
self.schedules_ids_by_cluster[state.sts] = [schedule['id'] for schedule in schedules]
|
|
105
|
-
self.show_schedules_tabular(schedules)
|
|
106
|
-
|
|
107
|
-
def schedule_ids(self, state: ReplState, show_output = True, filter: Callable[[list[dict]], dict] = None):
|
|
108
|
-
schedules = self.list_schedules(state, show_output=show_output, filter=filter)
|
|
109
|
-
return [schedule['id'] for schedule in schedules]
|
|
110
|
-
|
|
111
|
-
def list_schedules(self, state: ReplState, show_output = True, filter: Callable[[list[dict]], dict] = None) -> list[dict]:
|
|
112
|
-
def body(uri: str, headers: dict[str, str]):
|
|
113
|
-
return requests.get(uri, headers=headers)
|
|
114
|
-
|
|
115
|
-
response = self.port_forwarded(state, 'repair_schedule', body, method='GET', show_output=show_output)
|
|
116
|
-
if not response:
|
|
117
|
-
return
|
|
118
|
-
|
|
119
|
-
res = response.json()
|
|
120
|
-
if filter:
|
|
121
|
-
res = filter(res)
|
|
122
|
-
|
|
123
|
-
return res
|
|
124
|
-
|
|
125
|
-
def show_schedules_tabular(self, schedules: list[dict]):
|
|
126
|
-
log2(lines_to_tabular([f"{schedule['id']} {schedule['state']} {schedule['cluster_name']} {schedule['keyspace_name']}" for schedule in schedules], 'ID STATE CLUSTER KEYSPACE'))
|
|
127
|
-
|
|
128
|
-
def show_schedule(self, state: ReplState, schedule_id: str):
|
|
129
|
-
def filter(schedules: list[dict]):
|
|
130
|
-
return [schedule for schedule in schedules if schedule['id'] == schedule_id]
|
|
131
|
-
|
|
132
|
-
self.show_schedules(state, filter)
|
|
133
|
-
|
|
134
|
-
def reaper_spec(self, state: ReplState) -> dict[str, any]:
|
|
135
|
-
user, pw = state.user_pass(secret_path='reaper.secret')
|
|
136
|
-
local_port = Config().get('reaper.port-forward.local-port', 9001)
|
|
137
|
-
|
|
138
|
-
return {
|
|
139
|
-
'pod': self.pod,
|
|
140
|
-
'exec': f'kubectl exec -it {self.pod} -n {state.namespace} -- bash',
|
|
141
|
-
'forward': f'kubectl port-forward pods/{self.pod} -n {state.namespace} {local_port}:8080',
|
|
142
|
-
'web-uri': f'http://localhost:{local_port}/webui',
|
|
143
|
-
'username': user,
|
|
144
|
-
'password': pw
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
def cached_schedule_ids(state: ReplState) -> list[str]:
|
|
148
|
-
if state.sts in ReaperSession.schedules_ids_by_cluster:
|
|
149
|
-
return ReaperSession.schedules_ids_by_cluster[state.sts]
|
|
150
|
-
|
|
151
|
-
if reaper := ReaperSession.create(state):
|
|
152
|
-
Config().wait_log('Inspecting Cassandra Reaper...')
|
|
153
|
-
|
|
154
|
-
schedules = reaper.schedule_ids(state, show_output = False)
|
|
155
|
-
ReaperSession.schedules_ids_by_cluster[state.sts] = schedules
|
|
156
|
-
|
|
157
|
-
return schedules
|
|
158
|
-
|
|
159
|
-
return []
|
adam/commands/report.py
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import click
|
|
2
|
-
import json
|
|
3
|
-
|
|
4
|
-
from adam.checks.check_result import CheckResult
|
|
5
|
-
from adam.checks.check_utils import run_checks
|
|
6
|
-
from adam.commands.command import Command
|
|
7
|
-
from adam.repl_state import ReplState
|
|
8
|
-
from adam.utils import log2
|
|
9
|
-
|
|
10
|
-
class Report(Command):
|
|
11
|
-
COMMAND = 'report'
|
|
12
|
-
|
|
13
|
-
# the singleton pattern
|
|
14
|
-
def __new__(cls, *args, **kwargs):
|
|
15
|
-
if not hasattr(cls, 'instance'): cls.instance = super(Report, 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 Report.COMMAND
|
|
24
|
-
|
|
25
|
-
def required(self):
|
|
26
|
-
return ReplState.NON_L
|
|
27
|
-
|
|
28
|
-
def run(self, cmd: str, state: ReplState):
|
|
29
|
-
if not(args := self.args(cmd)):
|
|
30
|
-
return super().run(cmd, state)
|
|
31
|
-
|
|
32
|
-
output: dict[str, any] = {}
|
|
33
|
-
state, args = self.apply_state(args, state)
|
|
34
|
-
if not self.validate_state(state):
|
|
35
|
-
return state
|
|
36
|
-
|
|
37
|
-
if state.in_repl:
|
|
38
|
-
args, show = Command.extract_options(args, ['-s', '--show'])
|
|
39
|
-
|
|
40
|
-
args, redirect = Command.extract_options(args, ['>'])
|
|
41
|
-
if not redirect or not args:
|
|
42
|
-
log2('Please specify file name: e.g. report > /tmp/report.log')
|
|
43
|
-
return 'no-report-destination'
|
|
44
|
-
|
|
45
|
-
results = run_checks(state.sts, state.namespace, state.pod, show_output=show)
|
|
46
|
-
output = CheckResult.report(results)
|
|
47
|
-
with open(args[0], "w") as json_file:
|
|
48
|
-
json.dump(output, json_file, indent=2)
|
|
49
|
-
log2(f'Report stored in {args[0]}.')
|
|
50
|
-
else:
|
|
51
|
-
args, show = Command.extract_options(args, ['-s', '--show'])
|
|
52
|
-
|
|
53
|
-
results = run_checks(state.sts, state.namespace, state.pod, show_output=show)
|
|
54
|
-
output = CheckResult.report(results)
|
|
55
|
-
click.echo(json.dumps(output, indent=2))
|
|
56
|
-
|
|
57
|
-
return output
|
|
58
|
-
|
|
59
|
-
def completion(self, _: ReplState):
|
|
60
|
-
return {Report.COMMAND: {">": None}}
|
|
61
|
-
|
|
62
|
-
def help(self, _: ReplState):
|
|
63
|
-
return f"{Report.COMMAND} > <file-name>\t generate report"
|
adam/commands/show/show.py
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import click
|
|
2
|
-
|
|
3
|
-
from adam.commands.audit.show_last10 import ShowLast10
|
|
4
|
-
from adam.commands.command import Command
|
|
5
|
-
from adam.commands.medusa.medusa_show_backupjobs import MedusaShowBackupJobs
|
|
6
|
-
from adam.commands.medusa.medusa_show_restorejobs import MedusaShowRestoreJobs
|
|
7
|
-
from adam.commands.show.show_app_actions import ShowAppActions
|
|
8
|
-
from adam.commands.show.show_app_queues import ShowAppQueues
|
|
9
|
-
from adam.commands.show.show_host import ShowHost
|
|
10
|
-
from adam.commands.show.show_login import ShowLogin
|
|
11
|
-
from .show_params import ShowParams
|
|
12
|
-
from .show_app_id import ShowAppId
|
|
13
|
-
from .show_cassandra_status import ShowCassandraStatus
|
|
14
|
-
from .show_cassandra_version import ShowCassandraVersion
|
|
15
|
-
from .show_commands import ShowKubectlCommands
|
|
16
|
-
from .show_processes import ShowProcesses
|
|
17
|
-
from .show_repairs import ShowRepairs
|
|
18
|
-
from .show_storage import ShowStorage
|
|
19
|
-
from .show_adam import ShowAdam
|
|
20
|
-
from adam.repl_state import ReplState
|
|
21
|
-
|
|
22
|
-
class Show(Command):
|
|
23
|
-
COMMAND = 'show'
|
|
24
|
-
|
|
25
|
-
# the singleton pattern
|
|
26
|
-
def __new__(cls, *args, **kwargs):
|
|
27
|
-
if not hasattr(cls, 'instance'): cls.instance = super(Show, cls).__new__(cls)
|
|
28
|
-
|
|
29
|
-
return cls.instance
|
|
30
|
-
|
|
31
|
-
def __init__(self, successor: Command=None):
|
|
32
|
-
super().__init__(successor)
|
|
33
|
-
|
|
34
|
-
def command(self):
|
|
35
|
-
return Show.COMMAND
|
|
36
|
-
|
|
37
|
-
def run(self, cmd: str, state: ReplState):
|
|
38
|
-
if not(args := self.args(cmd)):
|
|
39
|
-
return super().run(cmd, state)
|
|
40
|
-
|
|
41
|
-
return super().intermediate_run(cmd, state, args, Show.cmd_list())
|
|
42
|
-
|
|
43
|
-
def cmd_list():
|
|
44
|
-
return [ShowAppActions(), ShowAppId(), ShowAppQueues(), ShowHost(), ShowLogin(), ShowKubectlCommands(),
|
|
45
|
-
ShowParams(), ShowProcesses(), ShowRepairs(), ShowStorage(), ShowAdam(),
|
|
46
|
-
ShowCassandraStatus(), ShowCassandraVersion(), MedusaShowRestoreJobs(), MedusaShowBackupJobs(),
|
|
47
|
-
ShowLast10()]
|
|
48
|
-
|
|
49
|
-
def completion(self, state: ReplState):
|
|
50
|
-
return super().completion(state)
|
|
51
|
-
|
|
52
|
-
class ShowCommandHelper(click.Command):
|
|
53
|
-
def get_help(self, ctx: click.Context):
|
|
54
|
-
Command.intermediate_help(super().get_help(ctx), Show.COMMAND, Show.cmd_list(), show_cluster_help=True)
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
from adam.app_session import AppSession
|
|
2
|
-
from adam.apps import AppAction, Apps
|
|
3
|
-
from adam.commands.command import Command
|
|
4
|
-
from adam.config import Config
|
|
5
|
-
from adam.repl_state import ReplState
|
|
6
|
-
from adam.utils import lines_to_tabular, log
|
|
7
|
-
|
|
8
|
-
class ShowAppActions(Command):
|
|
9
|
-
COMMAND = 'show app actions'
|
|
10
|
-
|
|
11
|
-
# the singleton pattern
|
|
12
|
-
def __new__(cls, *args, **kwargs):
|
|
13
|
-
if not hasattr(cls, 'instance'): cls.instance = super(ShowAppActions, cls).__new__(cls)
|
|
14
|
-
|
|
15
|
-
return cls.instance
|
|
16
|
-
|
|
17
|
-
def __init__(self, successor: Command=None):
|
|
18
|
-
super().__init__(successor)
|
|
19
|
-
|
|
20
|
-
def command(self):
|
|
21
|
-
return ShowAppActions.COMMAND
|
|
22
|
-
|
|
23
|
-
def required(self):
|
|
24
|
-
return ReplState.A
|
|
25
|
-
|
|
26
|
-
def run(self, cmd: str, state: ReplState):
|
|
27
|
-
if not self.args(cmd):
|
|
28
|
-
return super().run(cmd, state)
|
|
29
|
-
|
|
30
|
-
lines = []
|
|
31
|
-
for typ in Apps().app_types():
|
|
32
|
-
for action in typ.actions:
|
|
33
|
-
a: AppAction = action
|
|
34
|
-
args = ','.join(a.arguments())
|
|
35
|
-
if args:
|
|
36
|
-
line = f'{typ.name}.{a.name},{args}'
|
|
37
|
-
else:
|
|
38
|
-
line = f'{typ.name}.{a.name},'
|
|
39
|
-
if a.help:
|
|
40
|
-
line = f'{line},{a.help}'
|
|
41
|
-
lines.append(line)
|
|
42
|
-
log(lines_to_tabular(lines, 'ACTION,ARGS,DESCRIPTION', separator=','))
|
|
43
|
-
log()
|
|
44
|
-
|
|
45
|
-
app_session: AppSession = AppSession.create(state.app_env or 'c3', state.app_app or 'c3')
|
|
46
|
-
endpoint = Config().get('app.console-endpoint', 'https://{host}/{env}/{app}/static/console/index.html')
|
|
47
|
-
endpoint = endpoint.replace('{host}', app_session.host).replace('{env}', app_session.env).replace('{app}', state.app_app or 'c3')
|
|
48
|
-
log(lines_to_tabular([f'CONSOLE:,{endpoint}'], separator=','))
|
|
49
|
-
|
|
50
|
-
return lines
|
|
51
|
-
|
|
52
|
-
def completion(self, state: ReplState):
|
|
53
|
-
return super().completion(state)
|
|
54
|
-
|
|
55
|
-
def help(self, _: ReplState):
|
|
56
|
-
return f"{ShowAppActions.COMMAND}\t show app actions"
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import sys
|
|
2
|
-
|
|
3
|
-
from adam.checks.check_result import CheckResult
|
|
4
|
-
from adam.checks.check_utils import run_checks
|
|
5
|
-
from adam.checks.compactionstats import CompactionStats
|
|
6
|
-
from adam.checks.gossip import Gossip
|
|
7
|
-
from adam.columns.columns import Columns
|
|
8
|
-
from adam.commands.command import Command
|
|
9
|
-
from adam.commands.issues import Issues
|
|
10
|
-
from adam.config import Config
|
|
11
|
-
from adam.utils_k8s.cassandra_nodes import CassandraNodes
|
|
12
|
-
from adam.utils_k8s.secrets import Secrets
|
|
13
|
-
from adam.utils_k8s.statefulsets import StatefulSets
|
|
14
|
-
from adam.repl_state import ReplState, RequiredState
|
|
15
|
-
from adam.utils import lines_to_tabular, log, log2
|
|
16
|
-
from adam.checks.status import parse_nodetool_status
|
|
17
|
-
|
|
18
|
-
class ShowCassandraStatus(Command):
|
|
19
|
-
COMMAND = 'show cassandra status'
|
|
20
|
-
|
|
21
|
-
# the singleton pattern
|
|
22
|
-
def __new__(cls, *args, **kwargs):
|
|
23
|
-
if not hasattr(cls, 'instance'): cls.instance = super(ShowCassandraStatus, cls).__new__(cls)
|
|
24
|
-
|
|
25
|
-
return cls.instance
|
|
26
|
-
|
|
27
|
-
def __init__(self, successor: Command=None):
|
|
28
|
-
super().__init__(successor)
|
|
29
|
-
|
|
30
|
-
def command(self):
|
|
31
|
-
return ShowCassandraStatus.COMMAND
|
|
32
|
-
|
|
33
|
-
def required(self):
|
|
34
|
-
return RequiredState.CLUSTER_OR_POD
|
|
35
|
-
|
|
36
|
-
def run(self, cmd: str, state: ReplState):
|
|
37
|
-
if not(args := self.args(cmd)):
|
|
38
|
-
return super().run(cmd, state)
|
|
39
|
-
|
|
40
|
-
state, args = self.apply_state(args, state)
|
|
41
|
-
if not self.validate_state(state):
|
|
42
|
-
return state
|
|
43
|
-
|
|
44
|
-
args, show_output = Command.extract_options(args, ['-s', '--show'])
|
|
45
|
-
|
|
46
|
-
if state.namespace and state.pod:
|
|
47
|
-
# self.show_table(state, [state.pod], state.namespace, show_output=show_output)
|
|
48
|
-
self.show_single_pod(state.sts, state.pod, state.namespace, show_output=show_output)
|
|
49
|
-
elif state.namespace and state.sts:
|
|
50
|
-
self.merge(state.sts, StatefulSets.pod_names(state.sts, state.namespace), state.namespace, Config().get('nodetool.samples', sys.maxsize), show_output=show_output)
|
|
51
|
-
|
|
52
|
-
return state
|
|
53
|
-
|
|
54
|
-
def show_single_pod(self, statefulset: str, pod_name: str, ns: str, show_output = False):
|
|
55
|
-
pod_name = pod_name.split('(')[0]
|
|
56
|
-
user, pw = Secrets.get_user_pass(pod_name, ns)
|
|
57
|
-
try:
|
|
58
|
-
result = CassandraNodes.exec(pod_name, ns, f"nodetool -u {user} -pw {pw} status", show_out=False)
|
|
59
|
-
status = parse_nodetool_status(result.stdout)
|
|
60
|
-
check_results = run_checks(cluster=statefulset, namespace=ns, checks=[CompactionStats(), Gossip()], show_output=show_output)
|
|
61
|
-
self.show_table(status, check_results)
|
|
62
|
-
except Exception as e:
|
|
63
|
-
log2(e)
|
|
64
|
-
|
|
65
|
-
def merge(self, statefulset: str, pod_names: list[str], ns: str, samples: int, show_output=False):
|
|
66
|
-
statuses: list[list[dict]] = []
|
|
67
|
-
for pod_name in pod_names:
|
|
68
|
-
pod_name = pod_name.split('(')[0]
|
|
69
|
-
user, pw = Secrets.get_user_pass(pod_name, ns)
|
|
70
|
-
|
|
71
|
-
try:
|
|
72
|
-
result = CassandraNodes.exec(pod_name, ns, f"nodetool -u {user} -pw {pw} status", show_out=False)
|
|
73
|
-
status = parse_nodetool_status(result.stdout)
|
|
74
|
-
if status:
|
|
75
|
-
statuses.append(status)
|
|
76
|
-
if samples <= len(statuses) and len(pod_names) != len(statuses):
|
|
77
|
-
break
|
|
78
|
-
except Exception as e:
|
|
79
|
-
log2(e)
|
|
80
|
-
|
|
81
|
-
combined_status = self.merge_status(statuses)
|
|
82
|
-
log2(f'Showing merged status from {len(statuses)}/{len(pod_names)} nodes...')
|
|
83
|
-
check_results = run_checks(cluster=statefulset, namespace=ns, checks=[CompactionStats(), Gossip()], show_output=show_output)
|
|
84
|
-
self.show_table(combined_status, check_results)
|
|
85
|
-
|
|
86
|
-
return combined_status
|
|
87
|
-
|
|
88
|
-
def merge_status(self, statuses: list[list[dict]]):
|
|
89
|
-
combined = statuses[0]
|
|
90
|
-
|
|
91
|
-
status_by_host = {}
|
|
92
|
-
for status in statuses[0]:
|
|
93
|
-
status_by_host[status['host_id']] = status
|
|
94
|
-
for status in statuses[1:]:
|
|
95
|
-
for s in status:
|
|
96
|
-
if s['host_id'] in status_by_host:
|
|
97
|
-
c = status_by_host[s['host_id']]
|
|
98
|
-
if c['status'] == 'UN' and s['status'] == 'DN':
|
|
99
|
-
c['status'] = 'DN*'
|
|
100
|
-
else:
|
|
101
|
-
combined.append(s)
|
|
102
|
-
|
|
103
|
-
return combined
|
|
104
|
-
|
|
105
|
-
def show_table(self, status: list[dict[str, any]], check_results: list[CheckResult]):
|
|
106
|
-
cols = Config().get('status.columns', 'status,address,load,tokens,owns,host_id,gossip,compactions')
|
|
107
|
-
header = Config().get('status.header', '--,Address,Load,Tokens,Owns,Host ID,GOSSIP,COMPACTIONS')
|
|
108
|
-
columns = Columns.create_columns(cols)
|
|
109
|
-
|
|
110
|
-
def line(status: dict):
|
|
111
|
-
cells = [c.host_value(check_results, status) for c in columns]
|
|
112
|
-
return ','.join(cells)
|
|
113
|
-
|
|
114
|
-
lines = [line(d) for d in status]
|
|
115
|
-
lines.sort()
|
|
116
|
-
|
|
117
|
-
log(lines_to_tabular(lines, header, separator=','))
|
|
118
|
-
|
|
119
|
-
Issues.show(check_results)
|
|
120
|
-
|
|
121
|
-
def completion(self, state: ReplState):
|
|
122
|
-
if state.sts:
|
|
123
|
-
return super().completion(state)
|
|
124
|
-
|
|
125
|
-
return {}
|
|
126
|
-
|
|
127
|
-
def help(self, _: ReplState):
|
|
128
|
-
return f'{ShowCassandraStatus.COMMAND} [-s]\t show merged nodetool status -s show commands on nodes'
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
from adam.commands.command import Command
|
|
2
|
-
from adam.commands.cli_commands import CliCommands
|
|
3
|
-
from adam.repl_state import ReplState, RequiredState
|
|
4
|
-
from adam.utils import lines_to_tabular, log
|
|
5
|
-
|
|
6
|
-
class ShowKubectlCommands(Command):
|
|
7
|
-
COMMAND = 'show cli-commands'
|
|
8
|
-
|
|
9
|
-
# the singleton pattern
|
|
10
|
-
def __new__(cls, *args, **kwargs):
|
|
11
|
-
if not hasattr(cls, 'instance'): cls.instance = super(ShowKubectlCommands, 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 ShowKubectlCommands.COMMAND
|
|
20
|
-
|
|
21
|
-
def required(self):
|
|
22
|
-
return RequiredState.CLUSTER_OR_POD
|
|
23
|
-
|
|
24
|
-
def run(self, cmd: str, state: ReplState):
|
|
25
|
-
if not self.args(cmd):
|
|
26
|
-
return super().run(cmd, state)
|
|
27
|
-
|
|
28
|
-
if not self.validate_state(state):
|
|
29
|
-
return state
|
|
30
|
-
|
|
31
|
-
v = CliCommands.values(state, collapse=True)
|
|
32
|
-
# node-exec-?, nodetool-?, cql-?, reaper-exec, reaper-forward, reaper-ui, reaper-username, reaper-password
|
|
33
|
-
cmds = [
|
|
34
|
-
f'bash,{v["node-exec-?"]}',
|
|
35
|
-
f'nodetool,{v["nodetool-?"]}',
|
|
36
|
-
f'cql,{v["cql-?"]}',
|
|
37
|
-
]
|
|
38
|
-
|
|
39
|
-
if 'reaper-exec' in v:
|
|
40
|
-
cmds += [
|
|
41
|
-
f'reaper,{v["reaper-exec"]}',
|
|
42
|
-
f',{v["reaper-forward"]} * should be run from your laptop',
|
|
43
|
-
f',{v["reaper-ui"]}',
|
|
44
|
-
f',{v["reaper-username"]}',
|
|
45
|
-
f',{v["reaper-password"]}',
|
|
46
|
-
]
|
|
47
|
-
|
|
48
|
-
cmds += [f'{k},{v0}' for k, v0 in v.items() if k.startswith('pg-')]
|
|
49
|
-
|
|
50
|
-
log(lines_to_tabular(cmds, separator=','))
|
|
51
|
-
|
|
52
|
-
return cmds
|
|
53
|
-
|
|
54
|
-
def completion(self, state: ReplState):
|
|
55
|
-
if not state.sts:
|
|
56
|
-
return {}
|
|
57
|
-
|
|
58
|
-
return super().completion(state)
|
|
59
|
-
|
|
60
|
-
def help(self, _: ReplState):
|
|
61
|
-
return f"{ShowKubectlCommands.COMMAND}\t show kubectl commands"
|
adam/commands/show/show_login.py
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import time
|
|
2
|
-
import traceback
|
|
3
|
-
|
|
4
|
-
from adam.apps import Apps
|
|
5
|
-
from adam.config import Config
|
|
6
|
-
from adam.sso.idp import Idp
|
|
7
|
-
from adam.sso.idp_login import IdpLogin
|
|
8
|
-
from adam.commands.command import Command
|
|
9
|
-
from adam.repl_state import ReplState
|
|
10
|
-
from adam.utils import duration, lines_to_tabular, log, log2
|
|
11
|
-
|
|
12
|
-
class ShowLogin(Command):
|
|
13
|
-
COMMAND = 'show login'
|
|
14
|
-
|
|
15
|
-
# the singleton pattern
|
|
16
|
-
def __new__(cls, *args, **kwargs):
|
|
17
|
-
if not hasattr(cls, 'instance'): cls.instance = super(ShowLogin, 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 ShowLogin.COMMAND
|
|
26
|
-
|
|
27
|
-
def required(self):
|
|
28
|
-
return ReplState.NON_L
|
|
29
|
-
|
|
30
|
-
def run(self, cmd: str, state: ReplState):
|
|
31
|
-
if not(args := self.args(cmd)):
|
|
32
|
-
return super().run(cmd, state)
|
|
33
|
-
|
|
34
|
-
state, args = self.apply_state(args, state)
|
|
35
|
-
|
|
36
|
-
login: IdpLogin = None
|
|
37
|
-
try:
|
|
38
|
-
if not(host := Apps.app_host('c3', 'c3', state.namespace)):
|
|
39
|
-
log2('Cannot locate ingress for app.')
|
|
40
|
-
return state
|
|
41
|
-
|
|
42
|
-
login = Idp.login(host, use_token_from_env=True)
|
|
43
|
-
if login and login.id_token_obj:
|
|
44
|
-
it = login.id_token_obj
|
|
45
|
-
lines = [
|
|
46
|
-
f'email\t{it.email}',
|
|
47
|
-
f'user\t{it.username}',
|
|
48
|
-
f'IDP expires in\t{duration(time.time(), it.exp)}',
|
|
49
|
-
f'IDP Groups\t{",".join(it.groups)}'
|
|
50
|
-
]
|
|
51
|
-
log(lines_to_tabular(lines, separator='\t'))
|
|
52
|
-
except Exception as e:
|
|
53
|
-
log2(e)
|
|
54
|
-
if Config().is_debug():
|
|
55
|
-
log2(traceback.format_exc())
|
|
56
|
-
|
|
57
|
-
return state
|
|
58
|
-
|
|
59
|
-
def completion(self, state: ReplState):
|
|
60
|
-
return super().completion(state)
|
|
61
|
-
|
|
62
|
-
def help(self, _: ReplState):
|
|
63
|
-
return f'{ShowLogin.COMMAND}\t show login details'
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
from adam.commands.command import Command
|
|
2
|
-
from adam.commands.commands_utils import show_table
|
|
3
|
-
from adam.config import Config
|
|
4
|
-
from adam.utils_k8s.statefulsets import StatefulSets
|
|
5
|
-
from adam.repl_state import ReplState, RequiredState
|
|
6
|
-
|
|
7
|
-
class ShowProcesses(Command):
|
|
8
|
-
COMMAND = 'show processes'
|
|
9
|
-
|
|
10
|
-
# the singleton pattern
|
|
11
|
-
def __new__(cls, *args, **kwargs):
|
|
12
|
-
if not hasattr(cls, 'instance'): cls.instance = super(ShowProcesses, cls).__new__(cls)
|
|
13
|
-
|
|
14
|
-
return cls.instance
|
|
15
|
-
|
|
16
|
-
def __init__(self, successor: Command=None):
|
|
17
|
-
super().__init__(successor)
|
|
18
|
-
|
|
19
|
-
def command(self):
|
|
20
|
-
return ShowProcesses.COMMAND
|
|
21
|
-
|
|
22
|
-
def required(self):
|
|
23
|
-
return RequiredState.CLUSTER_OR_POD
|
|
24
|
-
|
|
25
|
-
def run(self, cmd: str, state: ReplState):
|
|
26
|
-
if not(args := self.args(cmd)):
|
|
27
|
-
return super().run(cmd, state)
|
|
28
|
-
|
|
29
|
-
state, args = self.apply_state(args, state)
|
|
30
|
-
if not self.validate_state(state):
|
|
31
|
-
return state
|
|
32
|
-
|
|
33
|
-
args, show_output = Command.extract_options(args, ['-s', '--show'])
|
|
34
|
-
|
|
35
|
-
cols = Config().get('processes.columns', 'pod,cpu,mem')
|
|
36
|
-
header = Config().get('processes.header', 'POD_NAME,CPU,MEM/LIMIT')
|
|
37
|
-
|
|
38
|
-
if state.pod:
|
|
39
|
-
show_table(state, [state.pod], cols, header, show_output=show_output)
|
|
40
|
-
elif state.sts:
|
|
41
|
-
pod_names = [pod.metadata.name for pod in StatefulSets.pods(state.sts, state.namespace)]
|
|
42
|
-
show_table(state, pod_names, cols, header, show_output=show_output)
|
|
43
|
-
|
|
44
|
-
return state
|
|
45
|
-
|
|
46
|
-
def completion(self, state: ReplState):
|
|
47
|
-
if not state.sts:
|
|
48
|
-
return {}
|
|
49
|
-
|
|
50
|
-
return super().completion(state)
|
|
51
|
-
|
|
52
|
-
def help(self, _: ReplState):
|
|
53
|
-
return f'{ShowProcesses.COMMAND} [-s]\t show process overview -s show commands on nodes'
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
from adam.commands.command import Command
|
|
2
|
-
from adam.utils_k8s.cassandra_clusters import CassandraClusters
|
|
3
|
-
from adam.utils_k8s.cassandra_nodes import CassandraNodes
|
|
4
|
-
from adam.repl_state import ReplState, RequiredState
|
|
5
|
-
|
|
6
|
-
class ShowRepairs(Command):
|
|
7
|
-
COMMAND = 'show cassandra repairs'
|
|
8
|
-
|
|
9
|
-
# the singleton pattern
|
|
10
|
-
def __new__(cls, *args, **kwargs):
|
|
11
|
-
if not hasattr(cls, 'instance'): cls.instance = super(ShowRepairs, 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 ShowRepairs.COMMAND
|
|
20
|
-
|
|
21
|
-
def required(self):
|
|
22
|
-
return RequiredState.CLUSTER_OR_POD
|
|
23
|
-
|
|
24
|
-
def run(self, cmd: str, state: ReplState):
|
|
25
|
-
if not(args := self.args(cmd)):
|
|
26
|
-
return super().run(cmd, state)
|
|
27
|
-
|
|
28
|
-
state, _ = state.apply_args(args)
|
|
29
|
-
if not self.validate_state(state):
|
|
30
|
-
return state
|
|
31
|
-
|
|
32
|
-
user, pw = state.user_pass()
|
|
33
|
-
command = f"nodetool -u {user} -pw {pw} repair_admin list"
|
|
34
|
-
|
|
35
|
-
if state.pod:
|
|
36
|
-
return CassandraNodes.exec(state.pod, state.namespace, command)
|
|
37
|
-
else:
|
|
38
|
-
return CassandraClusters.exec(state.sts, state.namespace, command, action='nodetool')
|
|
39
|
-
|
|
40
|
-
def completion(self, state: ReplState):
|
|
41
|
-
if state.sts:
|
|
42
|
-
return super().completion(state)
|
|
43
|
-
|
|
44
|
-
return {}
|
|
45
|
-
|
|
46
|
-
def help(self, _: ReplState):
|
|
47
|
-
return f'{ShowRepairs.COMMAND}\t show Cassandra repairs'
|