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.

Files changed (251) hide show
  1. adam/__init__.py +0 -2
  2. adam/app_session.py +9 -12
  3. adam/apps.py +18 -4
  4. adam/batch.py +19 -19
  5. adam/checks/check_utils.py +16 -46
  6. adam/checks/cpu.py +7 -1
  7. adam/checks/cpu_metrics.py +52 -0
  8. adam/checks/disk.py +2 -3
  9. adam/columns/columns.py +3 -1
  10. adam/columns/cpu.py +3 -1
  11. adam/columns/cpu_metrics.py +22 -0
  12. adam/columns/memory.py +3 -4
  13. adam/commands/__init__.py +24 -0
  14. adam/commands/app/app.py +38 -0
  15. adam/commands/{app_ping.py → app/app_ping.py} +7 -13
  16. adam/commands/{login.py → app/login.py} +22 -24
  17. adam/commands/app/show_app_actions.py +49 -0
  18. adam/commands/{show → app}/show_app_id.py +8 -11
  19. adam/commands/{show → app}/show_app_queues.py +7 -14
  20. adam/commands/app/show_login.py +56 -0
  21. adam/commands/app/utils_app.py +106 -0
  22. adam/commands/audit/audit.py +22 -40
  23. adam/commands/audit/audit_repair_tables.py +15 -19
  24. adam/commands/audit/audit_run.py +15 -22
  25. adam/commands/audit/completions_l.py +15 -0
  26. adam/commands/audit/show_last10.py +4 -18
  27. adam/commands/audit/show_slow10.py +4 -17
  28. adam/commands/audit/show_top10.py +4 -16
  29. adam/commands/audit/utils_show_top10.py +15 -3
  30. adam/commands/bash/__init__.py +5 -0
  31. adam/commands/bash/bash.py +36 -0
  32. adam/commands/bash/bash_completer.py +93 -0
  33. adam/commands/bash/utils_bash.py +16 -0
  34. adam/commands/cassandra/__init__.py +0 -0
  35. adam/commands/cassandra/download_cassandra_log.py +45 -0
  36. adam/commands/{restart.py → cassandra/restart_cluster.py} +12 -26
  37. adam/commands/cassandra/restart_node.py +51 -0
  38. adam/commands/cassandra/restart_nodes.py +47 -0
  39. adam/commands/{rollout.py → cassandra/rollout.py} +20 -25
  40. adam/commands/cassandra/show_cassandra_repairs.py +37 -0
  41. adam/commands/cassandra/show_cassandra_status.py +117 -0
  42. adam/commands/{show → cassandra}/show_cassandra_version.py +5 -18
  43. adam/commands/cassandra/show_processes.py +50 -0
  44. adam/commands/cassandra/show_storage.py +44 -0
  45. adam/commands/{watch.py → cassandra/watch.py} +26 -29
  46. adam/commands/cli/__init__.py +0 -0
  47. adam/commands/{cli_commands.py → cli/cli_commands.py} +8 -4
  48. adam/commands/cli/clipboard_copy.py +86 -0
  49. adam/commands/cli/show_cli_commands.py +56 -0
  50. adam/commands/code.py +57 -0
  51. adam/commands/command.py +211 -40
  52. adam/commands/commands_utils.py +20 -27
  53. adam/commands/config/__init__.py +0 -0
  54. adam/commands/{param_get.py → config/param_get.py} +11 -14
  55. adam/commands/{param_set.py → config/param_set.py} +8 -12
  56. adam/commands/{show → config}/show_params.py +2 -5
  57. adam/commands/cql/alter_tables.py +66 -0
  58. adam/commands/cql/completions_c.py +29 -0
  59. adam/commands/cql/cqlsh.py +10 -32
  60. adam/commands/cql/utils_cql.py +306 -0
  61. adam/commands/debug/__init__.py +0 -0
  62. adam/commands/debug/debug.py +22 -0
  63. adam/commands/debug/debug_completes.py +35 -0
  64. adam/commands/debug/debug_timings.py +35 -0
  65. adam/commands/debug/show_offloaded_completes.py +45 -0
  66. adam/commands/deploy/code_start.py +7 -10
  67. adam/commands/deploy/code_stop.py +4 -21
  68. adam/commands/deploy/code_utils.py +3 -3
  69. adam/commands/deploy/deploy.py +4 -27
  70. adam/commands/deploy/deploy_frontend.py +14 -17
  71. adam/commands/deploy/deploy_pg_agent.py +3 -6
  72. adam/commands/deploy/deploy_pod.py +65 -73
  73. adam/commands/deploy/deploy_utils.py +14 -24
  74. adam/commands/deploy/undeploy.py +4 -27
  75. adam/commands/deploy/undeploy_frontend.py +4 -7
  76. adam/commands/deploy/undeploy_pg_agent.py +6 -8
  77. adam/commands/deploy/undeploy_pod.py +11 -12
  78. adam/commands/devices/__init__.py +0 -0
  79. adam/commands/devices/device.py +149 -0
  80. adam/commands/devices/device_app.py +163 -0
  81. adam/commands/devices/device_auit_log.py +49 -0
  82. adam/commands/devices/device_cass.py +179 -0
  83. adam/commands/devices/device_export.py +87 -0
  84. adam/commands/devices/device_postgres.py +160 -0
  85. adam/commands/devices/devices.py +25 -0
  86. adam/commands/diag/__init__.py +0 -0
  87. adam/commands/{check.py → diag/check.py} +16 -25
  88. adam/commands/diag/generate_report.py +52 -0
  89. adam/commands/diag/issues.py +43 -0
  90. adam/commands/exit.py +1 -4
  91. adam/commands/export/__init__.py +0 -0
  92. adam/commands/export/clean_up_all_export_sessions.py +37 -0
  93. adam/commands/export/clean_up_export_sessions.py +39 -0
  94. adam/commands/export/completions_x.py +11 -0
  95. adam/commands/export/download_export_session.py +40 -0
  96. adam/commands/export/drop_export_database.py +39 -0
  97. adam/commands/export/drop_export_databases.py +37 -0
  98. adam/commands/export/export.py +37 -0
  99. adam/commands/export/export_databases.py +251 -0
  100. adam/commands/export/export_select.py +34 -0
  101. adam/commands/export/export_sessions.py +210 -0
  102. adam/commands/export/export_use.py +49 -0
  103. adam/commands/export/export_x_select.py +48 -0
  104. adam/commands/export/exporter.py +419 -0
  105. adam/commands/export/import_files.py +44 -0
  106. adam/commands/export/import_session.py +40 -0
  107. adam/commands/export/importer.py +81 -0
  108. adam/commands/export/importer_athena.py +157 -0
  109. adam/commands/export/importer_sqlite.py +78 -0
  110. adam/commands/export/show_column_counts.py +45 -0
  111. adam/commands/export/show_export_databases.py +39 -0
  112. adam/commands/export/show_export_session.py +39 -0
  113. adam/commands/export/show_export_sessions.py +37 -0
  114. adam/commands/export/utils_export.py +366 -0
  115. adam/commands/fs/__init__.py +0 -0
  116. adam/commands/fs/cat.py +36 -0
  117. adam/commands/fs/cat_local.py +42 -0
  118. adam/commands/fs/cd.py +41 -0
  119. adam/commands/fs/download_file.py +47 -0
  120. adam/commands/fs/find_files.py +51 -0
  121. adam/commands/fs/find_processes.py +76 -0
  122. adam/commands/fs/head.py +36 -0
  123. adam/commands/fs/ls.py +41 -0
  124. adam/commands/fs/ls_local.py +40 -0
  125. adam/commands/fs/pwd.py +45 -0
  126. adam/commands/fs/rm.py +18 -0
  127. adam/commands/fs/rm_downloads.py +39 -0
  128. adam/commands/fs/rm_logs.py +38 -0
  129. adam/commands/{shell.py → fs/shell.py} +12 -4
  130. adam/commands/{show → fs}/show_adam.py +3 -3
  131. adam/commands/{show → fs}/show_host.py +1 -1
  132. adam/commands/help.py +5 -3
  133. adam/commands/intermediate_command.py +52 -0
  134. adam/commands/kubectl.py +38 -0
  135. adam/commands/medusa/medusa.py +4 -22
  136. adam/commands/medusa/medusa_backup.py +20 -27
  137. adam/commands/medusa/medusa_restore.py +35 -48
  138. adam/commands/medusa/medusa_show_backupjobs.py +16 -18
  139. adam/commands/medusa/medusa_show_restorejobs.py +13 -18
  140. adam/commands/medusa/utils_medusa.py +15 -0
  141. adam/commands/nodetool/__init__.py +0 -0
  142. adam/commands/{nodetool.py → nodetool/nodetool.py} +9 -20
  143. adam/commands/postgres/completions_p.py +22 -0
  144. adam/commands/postgres/postgres.py +47 -55
  145. adam/commands/postgres/postgres_databases.py +269 -0
  146. adam/commands/postgres/postgres_ls.py +5 -9
  147. adam/commands/postgres/postgres_preview.py +5 -9
  148. adam/commands/postgres/utils_postgres.py +80 -0
  149. adam/commands/preview_table.py +8 -44
  150. adam/commands/reaper/reaper.py +4 -27
  151. adam/commands/reaper/reaper_forward.py +49 -56
  152. adam/commands/reaper/reaper_forward_session.py +6 -0
  153. adam/commands/reaper/reaper_forward_stop.py +10 -16
  154. adam/commands/reaper/reaper_restart.py +7 -14
  155. adam/commands/reaper/reaper_run_abort.py +8 -33
  156. adam/commands/reaper/reaper_runs.py +43 -58
  157. adam/commands/reaper/reaper_runs_abort.py +29 -49
  158. adam/commands/reaper/reaper_schedule_activate.py +14 -33
  159. adam/commands/reaper/reaper_schedule_start.py +9 -33
  160. adam/commands/reaper/reaper_schedule_stop.py +9 -33
  161. adam/commands/reaper/reaper_schedules.py +4 -14
  162. adam/commands/reaper/reaper_status.py +8 -16
  163. adam/commands/reaper/utils_reaper.py +203 -0
  164. adam/commands/repair/repair.py +4 -22
  165. adam/commands/repair/repair_log.py +5 -11
  166. adam/commands/repair/repair_run.py +27 -34
  167. adam/commands/repair/repair_scan.py +32 -40
  168. adam/commands/repair/repair_stop.py +5 -12
  169. adam/commands/show.py +40 -0
  170. adam/config.py +5 -15
  171. adam/embedded_params.py +1 -1
  172. adam/log.py +4 -4
  173. adam/repl.py +83 -116
  174. adam/repl_commands.py +86 -45
  175. adam/repl_session.py +9 -1
  176. adam/repl_state.py +176 -40
  177. adam/sql/async_executor.py +62 -0
  178. adam/sql/lark_completer.py +286 -0
  179. adam/sql/lark_parser.py +604 -0
  180. adam/sql/qingl.lark +1076 -0
  181. adam/sql/sql_completer.py +52 -27
  182. adam/sql/sql_state_machine.py +131 -19
  183. adam/sso/authn_ad.py +6 -8
  184. adam/sso/authn_okta.py +4 -6
  185. adam/sso/cred_cache.py +4 -9
  186. adam/sso/idp.py +9 -12
  187. adam/utils.py +670 -31
  188. adam/utils_athena.py +145 -0
  189. adam/utils_audits.py +12 -103
  190. adam/utils_issues.py +32 -0
  191. adam/utils_k8s/app_clusters.py +35 -0
  192. adam/utils_k8s/app_pods.py +41 -0
  193. adam/utils_k8s/cassandra_clusters.py +35 -20
  194. adam/utils_k8s/cassandra_nodes.py +15 -6
  195. adam/utils_k8s/custom_resources.py +16 -17
  196. adam/utils_k8s/ingresses.py +2 -2
  197. adam/utils_k8s/jobs.py +7 -11
  198. adam/utils_k8s/k8s.py +96 -0
  199. adam/utils_k8s/kube_context.py +3 -6
  200. adam/{pod_exec_result.py → utils_k8s/pod_exec_result.py} +13 -4
  201. adam/utils_k8s/pods.py +159 -89
  202. adam/utils_k8s/secrets.py +4 -4
  203. adam/utils_k8s/service_accounts.py +5 -4
  204. adam/utils_k8s/services.py +2 -2
  205. adam/utils_k8s/statefulsets.py +6 -14
  206. adam/utils_local.py +80 -0
  207. adam/utils_net.py +4 -4
  208. adam/utils_repl/__init__.py +0 -0
  209. adam/utils_repl/appendable_completer.py +6 -0
  210. adam/utils_repl/automata_completer.py +48 -0
  211. adam/utils_repl/repl_completer.py +93 -0
  212. adam/utils_repl/state_machine.py +173 -0
  213. adam/utils_sqlite.py +132 -0
  214. adam/version.py +1 -1
  215. {kaqing-2.0.110.dist-info → kaqing-2.0.214.dist-info}/METADATA +1 -1
  216. kaqing-2.0.214.dist-info/RECORD +272 -0
  217. kaqing-2.0.214.dist-info/top_level.txt +2 -0
  218. teddy/__init__.py +0 -0
  219. teddy/lark_parser.py +436 -0
  220. teddy/lark_parser2.py +618 -0
  221. adam/commands/alter_tables.py +0 -81
  222. adam/commands/app.py +0 -67
  223. adam/commands/bash.py +0 -150
  224. adam/commands/cd.py +0 -125
  225. adam/commands/cp.py +0 -95
  226. adam/commands/cql/cql_completions.py +0 -15
  227. adam/commands/cql/cql_utils.py +0 -112
  228. adam/commands/devices.py +0 -118
  229. adam/commands/issues.py +0 -75
  230. adam/commands/logs.py +0 -40
  231. adam/commands/ls.py +0 -146
  232. adam/commands/postgres/postgres_context.py +0 -239
  233. adam/commands/postgres/postgres_utils.py +0 -31
  234. adam/commands/postgres/psql_completions.py +0 -10
  235. adam/commands/pwd.py +0 -77
  236. adam/commands/reaper/reaper_session.py +0 -159
  237. adam/commands/report.py +0 -63
  238. adam/commands/show/show.py +0 -54
  239. adam/commands/show/show_app_actions.py +0 -56
  240. adam/commands/show/show_cassandra_status.py +0 -128
  241. adam/commands/show/show_commands.py +0 -61
  242. adam/commands/show/show_login.py +0 -63
  243. adam/commands/show/show_processes.py +0 -53
  244. adam/commands/show/show_repairs.py +0 -47
  245. adam/commands/show/show_storage.py +0 -52
  246. kaqing-2.0.110.dist-info/RECORD +0 -187
  247. kaqing-2.0.110.dist-info/top_level.txt +0 -1
  248. /adam/commands/{show → app}/__init__.py +0 -0
  249. /adam/commands/{nodetool_commands.py → nodetool/nodetool_commands.py} +0 -0
  250. {kaqing-2.0.110.dist-info → kaqing-2.0.214.dist-info}/WHEEL +0 -0
  251. {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"
@@ -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"
@@ -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'