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.
Files changed (308) hide show
  1. adam/__init__.py +1 -0
  2. adam/app_session.py +182 -0
  3. {walker → adam}/apps.py +8 -24
  4. {walker → adam}/batch.py +54 -97
  5. {walker → adam}/checks/check.py +3 -3
  6. {walker → adam}/checks/check_result.py +1 -1
  7. adam/checks/check_utils.py +65 -0
  8. {walker → adam}/checks/compactionstats.py +6 -6
  9. {walker → adam}/checks/cpu.py +14 -8
  10. adam/checks/cpu_metrics.py +52 -0
  11. {walker → adam}/checks/disk.py +6 -6
  12. {walker → adam}/checks/gossip.py +5 -5
  13. {walker → adam}/checks/memory.py +7 -7
  14. {walker → adam}/checks/status.py +5 -5
  15. {walker → adam}/cli.py +3 -3
  16. {walker → adam}/columns/column.py +1 -1
  17. adam/columns/columns.py +45 -0
  18. {walker → adam}/columns/compactions.py +5 -5
  19. {walker → adam}/columns/cpu.py +6 -4
  20. adam/columns/cpu_metrics.py +22 -0
  21. {walker → adam}/columns/dir_data.py +3 -3
  22. {walker → adam}/columns/dir_snapshots.py +3 -3
  23. {walker → adam}/columns/gossip.py +5 -5
  24. {walker → adam}/columns/host_id.py +3 -3
  25. {walker → adam}/columns/memory.py +3 -3
  26. {walker → adam}/columns/node_address.py +3 -3
  27. {walker → adam}/columns/node_load.py +3 -3
  28. {walker → adam}/columns/node_owns.py +3 -3
  29. {walker → adam}/columns/node_status.py +3 -3
  30. {walker → adam}/columns/node_tokens.py +3 -3
  31. {walker → adam}/columns/node_utils.py +2 -2
  32. {walker → adam}/columns/pod_name.py +2 -2
  33. {walker → adam}/columns/volume_cassandra.py +4 -4
  34. {walker → adam}/columns/volume_root.py +3 -3
  35. adam/commands/__init__.py +15 -0
  36. adam/commands/alter_tables.py +81 -0
  37. adam/commands/app_cmd.py +38 -0
  38. {walker → adam}/commands/app_ping.py +10 -16
  39. adam/commands/audit/audit.py +84 -0
  40. adam/commands/audit/audit_repair_tables.py +74 -0
  41. adam/commands/audit/audit_run.py +50 -0
  42. adam/commands/audit/show_last10.py +48 -0
  43. adam/commands/audit/show_slow10.py +47 -0
  44. adam/commands/audit/show_top10.py +45 -0
  45. adam/commands/audit/utils_show_top10.py +59 -0
  46. adam/commands/bash/__init__.py +5 -0
  47. adam/commands/bash/bash.py +36 -0
  48. adam/commands/bash/bash_completer.py +93 -0
  49. adam/commands/bash/utils_bash.py +16 -0
  50. adam/commands/cat.py +50 -0
  51. adam/commands/cd.py +43 -0
  52. adam/commands/check.py +73 -0
  53. {walker → adam}/commands/cli_commands.py +7 -8
  54. adam/commands/code.py +57 -0
  55. adam/commands/command.py +190 -0
  56. {walker → adam}/commands/command_helpers.py +1 -1
  57. {walker → adam}/commands/commands_utils.py +15 -25
  58. adam/commands/cp.py +89 -0
  59. adam/commands/cql/cql_completions.py +33 -0
  60. {walker/commands → adam/commands/cql}/cqlsh.py +20 -35
  61. adam/commands/cql/utils_cql.py +343 -0
  62. {walker/commands/frontend → adam/commands/deploy}/code_start.py +11 -14
  63. adam/commands/deploy/code_stop.py +40 -0
  64. {walker/commands/frontend → adam/commands/deploy}/code_utils.py +7 -9
  65. adam/commands/deploy/deploy.py +25 -0
  66. adam/commands/deploy/deploy_frontend.py +49 -0
  67. adam/commands/deploy/deploy_pg_agent.py +35 -0
  68. adam/commands/deploy/deploy_pod.py +108 -0
  69. adam/commands/deploy/deploy_utils.py +29 -0
  70. adam/commands/deploy/undeploy.py +25 -0
  71. adam/commands/deploy/undeploy_frontend.py +38 -0
  72. adam/commands/deploy/undeploy_pg_agent.py +39 -0
  73. adam/commands/deploy/undeploy_pod.py +48 -0
  74. adam/commands/devices/device.py +118 -0
  75. adam/commands/devices/device_app.py +173 -0
  76. adam/commands/devices/device_auit_log.py +49 -0
  77. adam/commands/devices/device_cass.py +185 -0
  78. adam/commands/devices/device_export.py +86 -0
  79. adam/commands/devices/device_postgres.py +144 -0
  80. adam/commands/devices/devices.py +25 -0
  81. {walker → adam}/commands/exit.py +3 -6
  82. adam/commands/export/clean_up_all_export_sessions.py +37 -0
  83. adam/commands/export/clean_up_export_sessions.py +51 -0
  84. adam/commands/export/drop_export_database.py +55 -0
  85. adam/commands/export/drop_export_databases.py +43 -0
  86. adam/commands/export/export.py +53 -0
  87. adam/commands/export/export_databases.py +170 -0
  88. adam/commands/export/export_handlers.py +71 -0
  89. adam/commands/export/export_select.py +81 -0
  90. adam/commands/export/export_select_x.py +54 -0
  91. adam/commands/export/export_use.py +52 -0
  92. adam/commands/export/exporter.py +352 -0
  93. adam/commands/export/import_session.py +40 -0
  94. adam/commands/export/importer.py +67 -0
  95. adam/commands/export/importer_athena.py +80 -0
  96. adam/commands/export/importer_sqlite.py +47 -0
  97. adam/commands/export/show_column_counts.py +54 -0
  98. adam/commands/export/show_export_databases.py +36 -0
  99. adam/commands/export/show_export_session.py +48 -0
  100. adam/commands/export/show_export_sessions.py +44 -0
  101. adam/commands/export/utils_export.py +314 -0
  102. {walker → adam}/commands/help.py +17 -12
  103. adam/commands/intermediate_command.py +49 -0
  104. adam/commands/issues.py +43 -0
  105. adam/commands/kubectl.py +38 -0
  106. adam/commands/login.py +70 -0
  107. {walker → adam}/commands/logs.py +8 -10
  108. adam/commands/ls.py +41 -0
  109. adam/commands/medusa/medusa.py +27 -0
  110. adam/commands/medusa/medusa_backup.py +57 -0
  111. adam/commands/medusa/medusa_restore.py +83 -0
  112. adam/commands/medusa/medusa_show_backupjobs.py +51 -0
  113. adam/commands/medusa/medusa_show_restorejobs.py +47 -0
  114. {walker → adam}/commands/nodetool.py +17 -21
  115. {walker → adam}/commands/param_get.py +15 -16
  116. adam/commands/param_set.py +43 -0
  117. adam/commands/postgres/postgres.py +104 -0
  118. adam/commands/postgres/postgres_context.py +274 -0
  119. {walker → adam}/commands/postgres/postgres_ls.py +7 -11
  120. {walker → adam}/commands/postgres/postgres_preview.py +8 -13
  121. adam/commands/postgres/psql_completions.py +10 -0
  122. adam/commands/postgres/utils_postgres.py +66 -0
  123. adam/commands/preview_table.py +37 -0
  124. adam/commands/pwd.py +47 -0
  125. adam/commands/reaper/reaper.py +35 -0
  126. adam/commands/reaper/reaper_forward.py +93 -0
  127. adam/commands/reaper/reaper_forward_session.py +6 -0
  128. {walker → adam}/commands/reaper/reaper_forward_stop.py +13 -19
  129. {walker → adam}/commands/reaper/reaper_restart.py +10 -17
  130. adam/commands/reaper/reaper_run_abort.py +46 -0
  131. adam/commands/reaper/reaper_runs.py +82 -0
  132. adam/commands/reaper/reaper_runs_abort.py +63 -0
  133. adam/commands/reaper/reaper_schedule_activate.py +45 -0
  134. adam/commands/reaper/reaper_schedule_start.py +45 -0
  135. adam/commands/reaper/reaper_schedule_stop.py +45 -0
  136. {walker → adam}/commands/reaper/reaper_schedules.py +6 -16
  137. {walker → adam}/commands/reaper/reaper_status.py +11 -19
  138. adam/commands/reaper/utils_reaper.py +196 -0
  139. adam/commands/repair/repair.py +26 -0
  140. {walker → adam}/commands/repair/repair_log.py +7 -10
  141. adam/commands/repair/repair_run.py +70 -0
  142. adam/commands/repair/repair_scan.py +71 -0
  143. {walker → adam}/commands/repair/repair_stop.py +8 -11
  144. adam/commands/report.py +61 -0
  145. adam/commands/restart.py +60 -0
  146. {walker → adam}/commands/rollout.py +25 -30
  147. adam/commands/shell.py +34 -0
  148. adam/commands/show/show.py +39 -0
  149. walker/commands/show/show_version.py → adam/commands/show/show_adam.py +14 -10
  150. adam/commands/show/show_app_actions.py +57 -0
  151. {walker → adam}/commands/show/show_app_id.py +12 -15
  152. {walker → adam}/commands/show/show_app_queues.py +9 -12
  153. adam/commands/show/show_cassandra_repairs.py +38 -0
  154. adam/commands/show/show_cassandra_status.py +124 -0
  155. {walker → adam}/commands/show/show_cassandra_version.py +6 -16
  156. adam/commands/show/show_commands.py +59 -0
  157. walker/commands/show/show_storage.py → adam/commands/show/show_host.py +11 -13
  158. adam/commands/show/show_login.py +62 -0
  159. {walker → adam}/commands/show/show_params.py +4 -4
  160. adam/commands/show/show_processes.py +51 -0
  161. adam/commands/show/show_storage.py +42 -0
  162. adam/commands/watch.py +82 -0
  163. {walker → adam}/config.py +10 -22
  164. {walker → adam}/embedded_apps.py +1 -1
  165. adam/embedded_params.py +2 -0
  166. adam/log.py +47 -0
  167. {walker → adam}/pod_exec_result.py +10 -2
  168. adam/repl.py +182 -0
  169. adam/repl_commands.py +124 -0
  170. adam/repl_state.py +458 -0
  171. adam/sql/__init__.py +0 -0
  172. adam/sql/sql_completer.py +120 -0
  173. adam/sql/sql_state_machine.py +618 -0
  174. adam/sql/term_completer.py +76 -0
  175. adam/sso/__init__.py +0 -0
  176. {walker → adam}/sso/authenticator.py +5 -1
  177. adam/sso/authn_ad.py +170 -0
  178. {walker → adam}/sso/authn_okta.py +39 -22
  179. adam/sso/cred_cache.py +60 -0
  180. adam/sso/id_token.py +23 -0
  181. adam/sso/idp.py +143 -0
  182. adam/sso/idp_login.py +50 -0
  183. adam/sso/idp_session.py +55 -0
  184. adam/sso/sso_config.py +63 -0
  185. adam/utils.py +679 -0
  186. adam/utils_app.py +98 -0
  187. adam/utils_athena.py +145 -0
  188. adam/utils_audits.py +106 -0
  189. adam/utils_issues.py +32 -0
  190. adam/utils_k8s/__init__.py +0 -0
  191. adam/utils_k8s/app_clusters.py +28 -0
  192. adam/utils_k8s/app_pods.py +33 -0
  193. adam/utils_k8s/cassandra_clusters.py +36 -0
  194. adam/utils_k8s/cassandra_nodes.py +33 -0
  195. adam/utils_k8s/config_maps.py +34 -0
  196. {walker/k8s_utils → adam/utils_k8s}/custom_resources.py +7 -2
  197. adam/utils_k8s/deployment.py +56 -0
  198. {walker/k8s_utils → adam/utils_k8s}/ingresses.py +3 -4
  199. {walker/k8s_utils → adam/utils_k8s}/jobs.py +3 -3
  200. adam/utils_k8s/k8s.py +87 -0
  201. {walker/k8s_utils → adam/utils_k8s}/kube_context.py +4 -4
  202. adam/utils_k8s/pods.py +290 -0
  203. {walker/k8s_utils → adam/utils_k8s}/secrets.py +8 -4
  204. adam/utils_k8s/service_accounts.py +170 -0
  205. {walker/k8s_utils → adam/utils_k8s}/services.py +3 -4
  206. {walker/k8s_utils → adam/utils_k8s}/statefulsets.py +6 -16
  207. {walker/k8s_utils → adam/utils_k8s}/volumes.py +10 -1
  208. adam/utils_net.py +24 -0
  209. adam/utils_repl/__init__.py +0 -0
  210. adam/utils_repl/automata_completer.py +48 -0
  211. adam/utils_repl/repl_completer.py +46 -0
  212. adam/utils_repl/state_machine.py +173 -0
  213. adam/utils_sqlite.py +109 -0
  214. adam/version.py +5 -0
  215. {kaqing-1.77.0.dist-info → kaqing-2.0.171.dist-info}/METADATA +1 -1
  216. kaqing-2.0.171.dist-info/RECORD +236 -0
  217. kaqing-2.0.171.dist-info/entry_points.txt +3 -0
  218. kaqing-2.0.171.dist-info/top_level.txt +1 -0
  219. kaqing-1.77.0.dist-info/RECORD +0 -159
  220. kaqing-1.77.0.dist-info/entry_points.txt +0 -3
  221. kaqing-1.77.0.dist-info/top_level.txt +0 -1
  222. walker/__init__.py +0 -3
  223. walker/app_session.py +0 -168
  224. walker/checks/check_utils.py +0 -97
  225. walker/columns/columns.py +0 -43
  226. walker/commands/add_user.py +0 -68
  227. walker/commands/app.py +0 -67
  228. walker/commands/bash.py +0 -87
  229. walker/commands/cd.py +0 -115
  230. walker/commands/check.py +0 -68
  231. walker/commands/command.py +0 -104
  232. walker/commands/cp.py +0 -95
  233. walker/commands/cql_utils.py +0 -53
  234. walker/commands/devices.py +0 -89
  235. walker/commands/frontend/code_stop.py +0 -57
  236. walker/commands/frontend/setup.py +0 -60
  237. walker/commands/frontend/setup_frontend.py +0 -58
  238. walker/commands/frontend/teardown.py +0 -61
  239. walker/commands/frontend/teardown_frontend.py +0 -42
  240. walker/commands/issues.py +0 -69
  241. walker/commands/login.py +0 -72
  242. walker/commands/ls.py +0 -145
  243. walker/commands/medusa/medusa.py +0 -69
  244. walker/commands/medusa/medusa_backup.py +0 -61
  245. walker/commands/medusa/medusa_restore.py +0 -86
  246. walker/commands/medusa/medusa_show_backupjobs.py +0 -52
  247. walker/commands/medusa/medusa_show_restorejobs.py +0 -52
  248. walker/commands/param_set.py +0 -44
  249. walker/commands/postgres/postgres.py +0 -113
  250. walker/commands/postgres/postgres_session.py +0 -225
  251. walker/commands/preview_table.py +0 -98
  252. walker/commands/processes.py +0 -53
  253. walker/commands/pwd.py +0 -64
  254. walker/commands/reaper/reaper.py +0 -78
  255. walker/commands/reaper/reaper_forward.py +0 -100
  256. walker/commands/reaper/reaper_run_abort.py +0 -65
  257. walker/commands/reaper/reaper_runs.py +0 -97
  258. walker/commands/reaper/reaper_runs_abort.py +0 -83
  259. walker/commands/reaper/reaper_schedule_activate.py +0 -64
  260. walker/commands/reaper/reaper_schedule_start.py +0 -64
  261. walker/commands/reaper/reaper_schedule_stop.py +0 -64
  262. walker/commands/reaper/reaper_session.py +0 -159
  263. walker/commands/repair/repair.py +0 -68
  264. walker/commands/repair/repair_run.py +0 -72
  265. walker/commands/repair/repair_scan.py +0 -79
  266. walker/commands/report.py +0 -57
  267. walker/commands/restart.py +0 -61
  268. walker/commands/show/show.py +0 -72
  269. walker/commands/show/show_app_actions.py +0 -53
  270. walker/commands/show/show_cassandra_status.py +0 -35
  271. walker/commands/show/show_commands.py +0 -58
  272. walker/commands/show/show_processes.py +0 -35
  273. walker/commands/show/show_repairs.py +0 -47
  274. walker/commands/status.py +0 -128
  275. walker/commands/storage.py +0 -52
  276. walker/commands/user_entry.py +0 -69
  277. walker/commands/watch.py +0 -85
  278. walker/embedded_params.py +0 -2
  279. walker/k8s_utils/cassandra_clusters.py +0 -48
  280. walker/k8s_utils/cassandra_nodes.py +0 -26
  281. walker/k8s_utils/pods.py +0 -211
  282. walker/repl.py +0 -165
  283. walker/repl_commands.py +0 -58
  284. walker/repl_state.py +0 -211
  285. walker/sso/authn_ad.py +0 -94
  286. walker/sso/idp.py +0 -150
  287. walker/sso/idp_login.py +0 -29
  288. walker/sso/sso_config.py +0 -45
  289. walker/utils.py +0 -194
  290. walker/version.py +0 -5
  291. {walker → adam}/checks/__init__.py +0 -0
  292. {walker → adam}/checks/check_context.py +0 -0
  293. {walker → adam}/checks/issue.py +0 -0
  294. {walker → adam}/cli_group.py +0 -0
  295. {walker → adam}/columns/__init__.py +0 -0
  296. {walker/commands → adam/commands/audit}/__init__.py +0 -0
  297. {walker/commands/frontend → adam/commands/cql}/__init__.py +0 -0
  298. {walker/commands/medusa → adam/commands/deploy}/__init__.py +0 -0
  299. {walker/commands/postgres → adam/commands/devices}/__init__.py +0 -0
  300. {walker/commands/reaper → adam/commands/export}/__init__.py +0 -0
  301. {walker/commands/repair → adam/commands/medusa}/__init__.py +0 -0
  302. {walker → adam}/commands/nodetool_commands.py +0 -0
  303. {walker/commands/show → adam/commands/postgres}/__init__.py +0 -0
  304. {walker/k8s_utils → adam/commands/reaper}/__init__.py +0 -0
  305. {walker/sso → adam/commands/repair}/__init__.py +0 -0
  306. /walker/medusa_show_restorejobs.py → /adam/commands/show/__init__.py +0 -0
  307. {walker → adam}/repl_session.py +0 -0
  308. {kaqing-1.77.0.dist-info → kaqing-2.0.171.dist-info}/WHEEL +0 -0
@@ -0,0 +1,42 @@
1
+ from adam.commands import extract_options
2
+ from adam.commands.command import Command
3
+ from adam.commands.cql.utils_cql import cassandra
4
+ from adam.config import Config
5
+ from adam.repl_state import ReplState, RequiredState
6
+
7
+ class ShowStorage(Command):
8
+ COMMAND = 'show storage'
9
+
10
+ # the singleton pattern
11
+ def __new__(cls, *args, **kwargs):
12
+ if not hasattr(cls, 'instance'): cls.instance = super(ShowStorage, 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 ShowStorage.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
+ with self.validate(args, state) as (args, state):
30
+ with extract_options(args, ['-s', '--show']) as (args, show_out):
31
+ cols = Config().get('storage.columns', 'pod,volume_root,volume_cassandra,snapshots,data,compactions')
32
+ header = Config().get('storage.header', 'POD_NAME,VOLUME /,VOLUME CASS,SNAPSHOTS,DATA,COMPACTIONS')
33
+ with cassandra(state) as pods:
34
+ pods.show_table(cols, header, show_out=show_out)
35
+
36
+ return state
37
+
38
+ def completion(self, state: ReplState):
39
+ return super().completion(state, {'-s': None})
40
+
41
+ def help(self, _: ReplState):
42
+ return f'{ShowStorage.COMMAND} [-s]\t show storage overview -s show commands on nodes'
adam/commands/watch.py ADDED
@@ -0,0 +1,82 @@
1
+ import threading
2
+ import time
3
+ from kubernetes import client
4
+ from typing import List
5
+
6
+ from adam.commands.command import Command
7
+ from adam.commands.commands_utils import show_pods, show_rollout
8
+ from adam.config import Config
9
+ from adam.utils_k8s.statefulsets import StatefulSets
10
+ from adam.repl_state import ReplState, RequiredState
11
+ from adam.utils import log2
12
+
13
+ class Watch(Command):
14
+ COMMAND = 'watch cassandra pods'
15
+
16
+ # the singleton pattern
17
+ def __new__(cls, *args, **kwargs):
18
+ if not hasattr(cls, 'instance'): cls.instance = super(Watch, cls).__new__(cls)
19
+
20
+ return cls.instance
21
+
22
+ def __init__(self, successor: Command=None):
23
+ super().__init__(successor)
24
+
25
+ def command(self):
26
+ return Watch.COMMAND
27
+
28
+ def required(self):
29
+ return RequiredState.NAMESPACE
30
+
31
+ def run(self, cmd: str, state: ReplState):
32
+ if not(args := self.args(cmd)):
33
+ return super().run(cmd, state)
34
+
35
+ with self.validate(args, state) as (args, state):
36
+ pods = StatefulSets.pods(state.sts, state.namespace)
37
+ if not pods:
38
+ log2("No pods are found.")
39
+ return state
40
+
41
+ stop_event = threading.Event()
42
+ thread = threading.Thread(target=self.loop, args=(stop_event, state.sts, pods, state.namespace), daemon=True)
43
+ thread.start()
44
+
45
+ try:
46
+ log2(f"Press Ctrl+C to break.")
47
+
48
+ time.sleep(Config().get('watch.timeout', 3600 * 1))
49
+ except KeyboardInterrupt:
50
+ pass
51
+
52
+ log2("Stopping watch...")
53
+ stop_event.set()
54
+ thread.join()
55
+
56
+ return state
57
+
58
+ def loop(self, stop_flag: threading.Event, sts: str, pods: List[client.V1Pod], ns: str):
59
+ show_pods(pods, ns)
60
+ show_rollout(sts, ns)
61
+
62
+ cnt = Config().get('watch.interval', 10)
63
+ while not stop_flag.is_set():
64
+ time.sleep(1)
65
+ cnt -= 1
66
+
67
+ if not cnt:
68
+ show_pods(pods, ns)
69
+ show_rollout(sts, ns)
70
+ cnt = Config().get('watch.interval', 10)
71
+
72
+ def completion(self, state: ReplState):
73
+ if sc := super().completion(state):
74
+ if state.sts:
75
+ return sc
76
+
77
+ return super().completion(state, {n: None for n in StatefulSets.list_sts_names()})
78
+
79
+ return {}
80
+
81
+ def help(self, _: ReplState):
82
+ return f'{Watch.COMMAND}\t watch Cassandra pod changes'
@@ -1,17 +1,18 @@
1
- import importlib
2
1
  import os
3
2
  from typing import TypeVar, cast
4
3
  import yaml
5
- from pathlib import Path
6
4
 
7
5
  from . import __version__
8
- from walker.utils import get_deep_keys, log2
6
+ from adam.utils import LogConfig, copy_config_file, get_deep_keys, log2
9
7
 
10
8
  T = TypeVar('T')
11
9
 
12
10
  class Config:
13
11
  EMBEDDED_PARAMS = {}
14
12
 
13
+ LogConfig.is_debug = lambda: Config().is_debug()
14
+ LogConfig.is_debug_timing = lambda: Config().get('debugs.timings', False)
15
+
15
16
  # the singleton pattern
16
17
  def __new__(cls, *args, **kwargs):
17
18
  if not hasattr(cls, 'instance'): cls.instance = super(Config, cls).__new__(cls)
@@ -20,29 +21,16 @@ class Config:
20
21
 
21
22
  def __init__(self, path: str = None, is_user_entry = False):
22
23
  if path:
24
+ self.wait_log_flag = False
23
25
  try:
24
26
  with open(path) as f:
25
27
  self.params = cast(dict[str, any], yaml.safe_load(f))
26
28
  except:
27
- self.copy_config_file(is_user_entry=is_user_entry)
29
+ with open(copy_config_file(f'params.yaml.{__version__}', 'adam.embedded_params', show_out=not is_user_entry)) as f:
30
+ self.params = cast(dict[str, any], yaml.safe_load(f))
28
31
  elif not hasattr(self, 'params'):
29
- self.copy_config_file(is_user_entry=is_user_entry)
30
-
31
- def copy_config_file(self, is_user_entry = False):
32
- dir = f'{Path.home()}/.kaqing'
33
- path = f'{dir}/params.yaml.{__version__}'
34
- if not os.path.exists(path):
35
- os.makedirs(dir, exist_ok=True)
36
- module = importlib.import_module('walker.embedded_params')
37
- with open(path, 'w') as f:
38
- yaml.dump(module.params(), f, default_flow_style=False)
39
- if not is_user_entry:
40
- log2(f'Default params.yaml has been written to {path}.')
41
-
42
- with open(path) as f:
43
- self.params = cast(dict[str, any], yaml.safe_load(f))
44
-
45
- return path
32
+ with open(copy_config_file(f'params.yaml.{__version__}', 'adam.embedded_params', show_out=not is_user_entry)) as f:
33
+ self.params = cast(dict[str, any], yaml.safe_load(f))
46
34
 
47
35
  def action_node_samples(self, action: str, default: T):
48
36
  return self.get(f'{action}.samples', default)
@@ -54,7 +42,7 @@ class Config:
54
42
  return get_deep_keys(self.params)
55
43
 
56
44
  def is_debug(self):
57
- return Config().get('debug.show-out', False)
45
+ return os.getenv('QING_DEV', 'false').lower() == 'true' or Config().get('debug', False)
58
46
 
59
47
  def get(self, key: str, default: T) -> T:
60
48
  # params['nodetool']['status']['max-nodes']
@@ -1,2 +1,2 @@
1
- def apps():
1
+ def config():
2
2
  return {'Echo': [{'echo': {'help': 'echo the message', 'payload': '{"thisArg":{"type":"Echo","message":"{ARG1}"}}', 'ARG1': 'string'}}, {'echoStatic': 'show random message'}], 'InvalidationQueue': [{'countAll': 'show queue counts'}, {'count': 'show queue count'}, {'pause': 'pause queue'}, {'resume': 'resume queue'}, {'isPaused': 'return true if paused'}], 'MapReduceQueue(InvalidationQueue)': None}
@@ -0,0 +1,2 @@
1
+ def config():
2
+ return {'app': {'console-endpoint': 'https://{host}/{env}/{app}/static/console/index.html', 'container-name': 'c3-server', 'cr': {'cluster-regex': '(.*?-.*?)-.*', 'group': 'ops.c3.ai', 'v': 'v2', 'plural': 'c3cassandras'}, 'label': 'c3__app_id-0', 'login': {'admin-group': '{host}/C3.ClusterAdmin', 'ingress': '{app_id}-k8singr-appleader-001', 'timeout': 5, 'session-check-url': 'https://{host}/{env}/{app}/api/8/C3/userSessionToken', 'cache-creds': True, 'cache-username': True, 'url': 'https://{host}/{env}/{app}', 'another': "You're logged in to {has}. However, for this app, you need to log in to {need}.", 'token-server-url': 'http://localhost:{port}', 'password-max-length': 128}, 'strip': '0'}, 'audit': {'endpoint': 'https://4psvtaxlcb.execute-api.us-west-2.amazonaws.com/prod/', 'workers': 3, 'timeout': 10, 'log-audit-queries': False, 'athena': {'auto-repair': {'elapsed_hours': 12}, 'region': 'us-west-2', 'catalog': 'AwsDataCatalog', 'database': 'audit', 'repair-partition-tables': 'audit', 'output': 's3://s3.ops--audit/ddl/results', 'repair-cluster-tables': 'cluster'}}, 'bash': {'workers': 32}, 'cassandra': {'service-name': 'all-pods-service'}, 'cql': {'workers': 32, 'samples': 3, 'secret': {'cluster-regex': '(.*?-.*?)-.*', 'name': '{cluster}-superuser', 'password-item': 'password'}, 'alter-tables': {'excludes': 'system_auth,system_traces,reaper_db,system_distributed,system_views,system,system_schema,system_virtual_schema', 'gc-grace-periods': '3600,86400,864000,7776000', 'batching': True}}, 'export': {'workers': 8, 'csv_dir': '/c3/cassandra/tmp', 'column_counts_query': 'select id, count(id) as columns from {table} group by id order by columns desc limit 10', 'default-importer': 'sqlite', 'sqlite': {'workers': 8, 'columns': '<row-key>', 'local-db-dir': '/tmp/qing-db'}, 'athena': {'workers': 8, 'columns': '<keys>', 'bucket': 'c3.ops--qing'}, 'csv': {'workers': 8, 'columns': '<row-key>'}}, 'checks': {'compactions-threshold': 250, 'cpu-busy-threshold': 98.0, 'cpu-threshold': 0.0, 'cassandra-data-path': '/c3/cassandra', 'root-disk-threshold': 50, 'cassandra-disk-threshold': 50, 'snapshot-size-cmd': "ls /c3/cassandra/data/data/*/*/snapshots | grep snapshots | sed 's/:$//g' | xargs -I {} du -sk {} | awk '{print $1}' | awk '{s+=$1} END {print s}'", 'snapshot-size-threshold': '40G', 'table-sizes-cmd': "ls -Al /c3/cassandra/data/data/ | awk '{print $9}' | sed 's/\\^r//g' | xargs -I {} du -sk /c3/cassandra/data/data/{}"}, 'get-host-id': {'workers': 32}, 'idps': {'ad': {'email-pattern': '.*@c3.ai', 'uri': 'https://login.microsoftonline.com/53ad779a-93e7-485c-ba20-ac8290d7252b/oauth2/v2.0/authorize?response_type=id_token&response_mode=form_post&client_id=00ff94a8-6b0a-4715-98e0-95490012d818&scope=openid+email+profile&redirect_uri=https%3A%2F%2Fplat.c3ci.cloud%2Fc3%2Fc3%2Foidc%2Flogin&nonce={nonce}&state=EMPTY', 'jwks-uri': 'https://login.microsoftonline.com/common/discovery/keys', 'contact': 'Please contact ted.tran@c3.ai.', 'whitelist-file': '/kaqing/members'}, 'okta': {'default': True, 'email-pattern': '.*@c3iot.com', 'uri': 'https://c3energy.okta.com/oauth2/v1/authorize?response_type=id_token&response_mode=form_post&client_id={client_id}&scope=openid+email+profile+groups&redirect_uri=https%3A%2F%2F{host}%2Fc3%2Fc3%2Foidc%2Flogin&nonce={nonce}&state=EMPTY', 'jwks-uri': 'https://c3energy.okta.com/oauth2/v1/keys'}}, 'issues': {'workers': 32}, 'logs': {'path': '/c3/cassandra/logs/system.log'}, 'log-prefix': '/tmp/qing', 'medusa': {'restore-auto-complete': False}, 'nodetool': {'workers': 32, 'samples': 3, 'commands_in_line': 40}, 'pg': {'name-pattern': '^{namespace}.*-k8spg-.*', 'excludes': '.helm., -admin-secret', 'agent': {'name': 'ops-pg-agent', 'just-in-time': False, 'timeout': 86400, 'image': 'seanahnsf/kaqing'}, 'default-db': 'postgres', 'default-schema': 'postgres', 'secret': {'endpoint-key': 'postgres-db-endpoint', 'port-key': 'postgres-db-port', 'username-key': 'postgres-admin-username', 'password-key': 'postgres-admin-password'}}, 'pod': {'name': 'ops', 'image': 'seanahnsf/kaqing-cloud', 'sa': {'name': 'ops', 'proto': 'c3', 'additional-cluster-roles': 'c3aiops-k8ssandra-operator'}, 'label-selector': 'run=ops'}, 'preview': {'rows': 10}, 'processes': {'columns': 'pod,cpu-metrics,mem', 'header': 'POD_NAME,M_CPU(USAGE/LIMIT),MEM/LIMIT'}, 'processes-qing': {'columns': 'pod,cpu,mem', 'header': 'POD_NAME,Q_CPU/TOTAL,MEM/LIMIT'}, 'reaper': {'service-name': 'reaper-service', 'port-forward': {'timeout': 86400, 'local-port': 9001}, 'abort-runs-batch': 10, 'show-runs-batch': 100, 'pod': {'cluster-regex': '(.*?-.*?-.*?-.*?)-.*', 'label-selector': 'k8ssandra.io/reaper={cluster}-reaper'}, 'secret': {'cluster-regex': '(.*?-.*?)-.*', 'name': '{cluster}-reaper-ui', 'password-item': 'password'}}, 'repair': {'log-path': '/home/cassrepair/logs/', 'image': 'ci-registry.c3iot.io/cloudops/cassrepair:2.0.14', 'secret': 'ciregistryc3iotio', 'env': {'interval': 24, 'timeout': 60, 'pr': False, 'runs': 1}}, 'repl': {'start-drive': 'c', 'a': {'auto-enter': 'c3/c3/*'}, 'c': {'auto-enter': 'cluster'}, 'x': {'auto-enter': 'latest'}, 'history': {'push-cat-remote-log-file': True}, 'background-process': {'auto-nohup': True}}, 'status': {'columns': 'status,address,load,tokens,owns,host_id,gossip,compactions', 'header': '--,Address,Load,Tokens,Owns,Host ID,GOSSIP,COMPACTIONS'}, 'storage': {'columns': 'pod,volume_root,volume_cassandra,snapshots,data,compactions', 'header': 'POD_NAME,VOLUME /,VOLUME CASS,SNAPSHOTS,DATA,COMPACTIONS'}, 'watch': {'auto': 'rollout', 'timeout': 3600, 'interval': 10}, 'debug': False, 'debugs': {'timings': False, 'exit-on-error': False, 'show-parallelism': False}}
adam/log.py ADDED
@@ -0,0 +1,47 @@
1
+ from datetime import datetime
2
+ import json
3
+ import os
4
+ import sys
5
+ import click
6
+
7
+ class Log:
8
+ DEBUG = False
9
+
10
+ def is_debug():
11
+ return Log.DEBUG
12
+
13
+ def debug(s: None):
14
+ if Log.DEBUG:
15
+ Log.log2(f'DEBUG {s}')
16
+
17
+ def log(s = None):
18
+ # want to print empty line for False or empty collection
19
+ if s == None:
20
+ print()
21
+ else:
22
+ click.echo(s)
23
+
24
+ def log2(s = None):
25
+ if s:
26
+ click.echo(s, err=True)
27
+ else:
28
+ print(file=sys.stderr)
29
+
30
+ def log_to_file(config: dict[any, any]):
31
+ try:
32
+ base = f"/tmp/logs"
33
+ os.makedirs(base, exist_ok=True)
34
+
35
+ now = datetime.now()
36
+ timestamp_str = now.strftime("%Y%m%d-%H%M%S")
37
+ filename = f"{base}/login.{timestamp_str}.txt"
38
+ with open(filename, 'w') as f:
39
+ if isinstance(config, dict):
40
+ try:
41
+ json.dump(config, f, indent=4)
42
+ except:
43
+ f.write(config)
44
+ else:
45
+ f.write(config)
46
+ except:
47
+ pass
@@ -15,12 +15,14 @@ class PodExecResult:
15
15
  # ]
16
16
  # }
17
17
  # }
18
- def __init__(self, stdout: str, stderr: str, command: str = None, error_output: str = None):
18
+ def __init__(self, stdout: str, stderr: str, command: str = None, error_output: str = None, pod: str = None, log_file: str = None):
19
19
  self.stdout: str = stdout
20
20
  self.stderr: str = stderr
21
21
  self.command: str = command
22
22
  if error_output:
23
23
  self.error = yaml.safe_load(error_output)
24
+ self.pod = pod
25
+ self.log_file = log_file
24
26
 
25
27
  def exit_code(self) -> int:
26
28
  code = 0
@@ -30,4 +32,10 @@ class PodExecResult:
30
32
  except:
31
33
  pass
32
34
 
33
- return code
35
+ return code
36
+
37
+ def __str__(self):
38
+ return f'{"OK" if self.exit_code() == 0 else self.exit_code()} {self.command}'
39
+
40
+ def __audit_extra__(self):
41
+ return self.log_file if self.log_file else None
adam/repl.py ADDED
@@ -0,0 +1,182 @@
1
+ import os
2
+ import time
3
+ import traceback
4
+ from typing import cast
5
+ import click
6
+ from prompt_toolkit.key_binding import KeyBindings
7
+
8
+ from adam.cli_group import cli
9
+ from adam.commands.command import Command, InvalidState
10
+ from adam.commands.command_helpers import ClusterCommandHelper
11
+ from adam.commands.devices.devices import Devices
12
+ from adam.commands.help import Help
13
+ from adam.config import Config
14
+ from adam.utils_audits import Audits
15
+ from adam.utils_k8s.kube_context import KubeContext
16
+ from adam.log import Log
17
+ from adam.repl_commands import ReplCommands
18
+ from adam.repl_session import ReplSession
19
+ from adam.repl_state import ReplState
20
+ from adam.utils import clear_wait_log_flag, debug, deep_merge_dicts, deep_sort_dict, lines_to_tabular, log2, log_timing
21
+ from adam.apps import Apps
22
+ from adam.utils_repl.repl_completer import ReplCompleter
23
+ from . import __version__
24
+
25
+ def enter_repl(state: ReplState):
26
+ if os.getenv('QING_DROPPED', 'false') == 'true':
27
+ log2('You have dropped to bash from another qing instance. Please enter "exit" to go back to qing.')
28
+ return
29
+
30
+ cmd_list: list[Command] = ReplCommands.repl_cmd_list() + [Help()]
31
+ # head with the Chain of Responsibility pattern
32
+ cmds: Command = Command.chain(cmd_list)
33
+ session = ReplSession().prompt_session
34
+
35
+ def prompt_msg():
36
+ msg = state.__str__()
37
+
38
+ return f"{msg}$ " if state.bash_session else f"{msg}> "
39
+
40
+ Log.log2(f'kaqing {__version__}')
41
+
42
+ Devices.device(state).enter(state)
43
+
44
+ kb = KeyBindings()
45
+
46
+ @kb.add('c-c')
47
+ def _(event):
48
+ event.app.current_buffer.text = ''
49
+
50
+ with Audits.offload() as exec:
51
+ # warm up AWS lambda - this log line may timeout and get lost, which is fine
52
+ exec.submit(Audits.log, 'entering kaqing repl', state.namespace, 'z', 0.0)
53
+
54
+ s0 = time.time()
55
+
56
+ # use sorted command list only for auto-completion
57
+ sorted_cmds = sorted(cmd_list, key=lambda cmd: cmd.command())
58
+ while True:
59
+ cmd: str = None
60
+ result = None
61
+ try:
62
+ completer = ReplCompleter.from_nested_dict({})
63
+ if not state.bash_session:
64
+ with log_timing('completion-calcs'):
65
+ completions = {}
66
+ # app commands are available only on a: drive
67
+ if state.device == ReplState.A and state.app_app:
68
+ completions = log_timing('actions', lambda: Apps(path='apps.yaml').commands())
69
+
70
+ for c in sorted_cmds:
71
+ try:
72
+ completions = log_timing(c.command(), lambda: deep_sort_dict(deep_merge_dicts(completions, c.completion(state))))
73
+ except:
74
+ log2(f'* {c.command()} command returned None completions.')
75
+
76
+ # print(json.dumps(completions, indent=4))
77
+ completer = ReplCompleter.from_nested_dict(completions)
78
+
79
+ cmd = session.prompt(prompt_msg(), completer=completer, key_bindings=kb)
80
+ s0 = time.time()
81
+
82
+ if state.bash_session:
83
+ if cmd.strip(' ') == 'exit':
84
+ state.exit_bash()
85
+ continue
86
+
87
+ cmd = f'bash {cmd}'
88
+
89
+ def targetted(state: ReplState, cmd: str):
90
+ if not (cmd.startswith('@') and len(arry := cmd.split(' ')) > 1):
91
+ return state, cmd
92
+
93
+ if state.device == ReplState.A and state.app_app or state.device == ReplState.P:
94
+ state.push()
95
+
96
+ state.app_pod = arry[0].strip('@')
97
+ cmd = ' '.join(arry[1:])
98
+ elif state.device == ReplState.P:
99
+ state.push()
100
+
101
+ state.app_pod = arry[0].strip('@')
102
+ cmd = ' '.join(arry[1:])
103
+ elif state.sts:
104
+ state.push()
105
+
106
+ state.pod = arry[0].strip('@')
107
+ cmd = ' '.join(arry[1:])
108
+
109
+ return (state, cmd)
110
+
111
+ target, cmd = targetted(state, cmd)
112
+ try:
113
+ if cmd and cmd.strip(' ') and not (result := cmds.run(cmd, target)):
114
+ result = try_device_default_action(target, cmds, cmd_list, cmd)
115
+ except InvalidState:
116
+ pass
117
+
118
+ if result and type(result) is ReplState and (s := cast(ReplState, result).export_session) != state.export_session:
119
+ state.export_session = s
120
+
121
+ except EOFError: # Handle Ctrl+D (EOF) for graceful exit
122
+ break
123
+ except Exception as e:
124
+ if Config().get('debugs.exit-on-error', False):
125
+ raise e
126
+ else:
127
+ log2(e)
128
+ debug(traceback.format_exc())
129
+ finally:
130
+ if not state.bash_session:
131
+ state.pop()
132
+
133
+ clear_wait_log_flag()
134
+ if cmd:
135
+ log_timing(f'command {cmd}', s0=s0)
136
+
137
+ # offload audit logging
138
+ if cmd and (state.device != ReplState.L or Config().get('audit.log-audit-queries', False)):
139
+ exec.submit(Audits.log, cmd, state.namespace, state.device, time.time() - s0, get_audit_extra(result))
140
+
141
+ def try_device_default_action(state: ReplState, cmds: Command, cmd_list: list[Command], cmd: str):
142
+ action_taken, result = Devices.device(state).try_fallback_action(cmds, state, cmd)
143
+
144
+ if not action_taken:
145
+ log2(f'* Invalid command: {cmd}')
146
+ log2()
147
+ lines = [c.help(state) for c in cmd_list if c.help(state)]
148
+ log2(lines_to_tabular(lines, separator='\t'))
149
+
150
+ return result
151
+
152
+ def get_audit_extra(result: any):
153
+ if not result:
154
+ return None
155
+
156
+ if type(result) is list:
157
+ extras = set()
158
+
159
+ for r in result:
160
+ if hasattr(r, '__audit_extra__') and (x := r.__audit_extra__()):
161
+ extras.add(x)
162
+
163
+ return ','.join(list(extras))
164
+
165
+ if hasattr(result, '__audit_extra__') and (x := result.__audit_extra__()):
166
+ return x
167
+
168
+ @cli.command(context_settings=dict(ignore_unknown_options=True, allow_extra_args=True), cls=ClusterCommandHelper, help="Enter interactive shell.")
169
+ @click.option('--kubeconfig', '-k', required=False, metavar='path', help='path to kubeconfig file')
170
+ @click.option('--config', default='params.yaml', metavar='path', help='path to kaqing parameters file')
171
+ @click.option('--param', '-v', multiple=True, metavar='<key>=<value>', help='parameter override')
172
+ @click.option('--cluster', '-c', required=False, metavar='statefulset', help='Kubernetes statefulset name')
173
+ @click.option('--namespace', '-n', required=False, metavar='namespace', help='Kubernetes namespace')
174
+ @click.argument('extra_args', nargs=-1, metavar='[cluster]', type=click.UNPROCESSED)
175
+ def repl(kubeconfig: str, config: str, param: list[str], cluster:str, namespace: str, extra_args):
176
+ KubeContext.init_config(kubeconfig)
177
+ if not KubeContext.init_params(config, param):
178
+ return
179
+
180
+ state = ReplState(device=Config().get('repl.start-drive', 'a'), ns_sts=cluster, namespace=namespace, in_repl=True)
181
+ state, _ = state.apply_device_arg(extra_args)
182
+ enter_repl(state)
adam/repl_commands.py ADDED
@@ -0,0 +1,124 @@
1
+ from adam.commands.alter_tables import AlterTables
2
+ from adam.commands.app_cmd import App
3
+ from adam.commands.app_ping import AppPing
4
+ from adam.commands.audit.audit import Audit
5
+ from adam.commands.cat import Cat
6
+ from adam.commands.code import Code
7
+ from adam.commands.deploy.code_start import CodeStart
8
+ from adam.commands.deploy.code_stop import CodeStop
9
+ from adam.commands.deploy.deploy import Deploy
10
+ from adam.commands.deploy.deploy_frontend import DeployFrontend
11
+ from adam.commands.deploy.deploy_pg_agent import DeployPgAgent
12
+ from adam.commands.deploy.deploy_pod import DeployPod
13
+ from adam.commands.deploy.undeploy import Undeploy
14
+ from adam.commands.deploy.undeploy_frontend import UndeployFrontend
15
+ from adam.commands.deploy.undeploy_pg_agent import UndeployPgAgent
16
+ from adam.commands.deploy.undeploy_pod import UndeployPod
17
+ from adam.commands.devices.device_app import DeviceApp
18
+ from adam.commands.devices.device_auit_log import DeviceAuditLog
19
+ from adam.commands.devices.device_cass import DeviceCass
20
+ from adam.commands.devices.device_export import DeviceExport
21
+ from adam.commands.devices.device_postgres import DevicePostgres
22
+ from adam.commands.export.drop_export_database import DropExportDatabase
23
+ from adam.commands.export.export import ExportTables
24
+ from adam.commands.export.import_session import ImportSession
25
+ from adam.commands.export.clean_up_export_sessions import CleanUpExportSessions
26
+ from adam.commands.export.clean_up_all_export_sessions import CleanUpAllExportSessions
27
+ from adam.commands.export.drop_export_databases import DropExportDatabases
28
+ from adam.commands.export.export_select import ExportSelect
29
+ from adam.commands.export.export_use import ExportUse
30
+ from adam.commands.export.export_select_x import ExportSelectX
31
+ from adam.commands.export.show_column_counts import ShowColumnCounts
32
+ from adam.commands.export.show_export_databases import ShowExportDatabases
33
+ from adam.commands.export.show_export_session import ShowExportSession
34
+ from adam.commands.export.show_export_sessions import ShowExportSessions
35
+ from adam.commands.kubectl import Kubectl
36
+ from adam.commands.shell import Shell
37
+ from adam.commands.show.show_app_queues import ShowAppQueues
38
+ from adam.commands.cp import ClipboardCopy
39
+ from adam.commands.bash.bash import Bash
40
+ from adam.commands.cd import Cd
41
+ from adam.commands.check import Check
42
+ from adam.commands.command import Command
43
+ from adam.commands.cql.cqlsh import Cqlsh
44
+ from adam.commands.exit import Exit
45
+ from adam.commands.medusa.medusa import Medusa
46
+ from adam.commands.param_get import GetParam
47
+ from adam.commands.issues import Issues
48
+ from adam.commands.ls import Ls
49
+ from adam.commands.nodetool import NodeTool
50
+ from adam.commands.postgres.postgres import Postgres, PostgresPg
51
+ from adam.commands.preview_table import PreviewTable
52
+ from adam.commands.pwd import Pwd
53
+ from adam.commands.reaper.reaper import Reaper
54
+ from adam.commands.repair.repair import Repair
55
+ from adam.commands.report import Report
56
+ from adam.commands.restart import Restart
57
+ from adam.commands.rollout import RollOut
58
+ from adam.commands.param_set import SetParam
59
+ from adam.commands.show.show import Show
60
+ from adam.commands.show.show_app_actions import ShowAppActions
61
+ from adam.commands.show.show_app_id import ShowAppId
62
+ from adam.commands.show.show_cassandra_status import ShowCassandraStatus
63
+ from adam.commands.show.show_cassandra_version import ShowCassandraVersion
64
+ from adam.commands.show.show_commands import ShowKubectlCommands
65
+ from adam.commands.show.show_host import ShowHost
66
+ from adam.commands.show.show_login import ShowLogin
67
+ from adam.commands.show.show_params import ShowParams
68
+ from adam.commands.show.show_processes import ShowProcesses
69
+ from adam.commands.show.show_cassandra_repairs import ShowCassandraRepairs
70
+ from adam.commands.show.show_storage import ShowStorage
71
+ from adam.commands.show.show_adam import ShowAdam
72
+ from adam.commands.watch import Watch
73
+
74
+ class ReplCommands:
75
+ def repl_cmd_list() -> list[Command]:
76
+ cmds: list[Command] = ReplCommands.navigation() + ReplCommands.cassandra_ops() + ReplCommands.postgres_ops() + \
77
+ ReplCommands.app_ops() + ReplCommands.audit_ops() + ReplCommands.export_ops() + ReplCommands.tools() + ReplCommands.exit()
78
+
79
+ intermediate_cmds: list[Command] = [App(), Audit(), Reaper(), Repair(), Deploy(), Show(), Undeploy()]
80
+ ic = [c.command() for c in intermediate_cmds]
81
+ # 1. dedup commands
82
+ deduped = []
83
+ cs = set()
84
+ for cmd in cmds:
85
+ if cmd.command() not in cs and cmd.command() not in ic:
86
+ deduped.append(cmd)
87
+ cs.add(cmd.command())
88
+ # 2. intermediate commands must be added to the end
89
+ deduped.extend(intermediate_cmds)
90
+
91
+ # Command.print_chain(Command.chain(cmds))
92
+
93
+ return deduped
94
+
95
+ def navigation() -> list[Command]:
96
+ return [Ls(), PreviewTable(), DeviceApp(), DevicePostgres(), DeviceCass(), DeviceAuditLog(), DeviceExport(), Cd(), Cat(), Pwd(), ClipboardCopy(),
97
+ GetParam(), SetParam(), ShowParams(), ShowKubectlCommands(), ShowLogin(), ShowAdam(), ShowHost()]
98
+
99
+ def cassandra_ops() -> list[Command]:
100
+ return [Cqlsh(), ShowCassandraStatus(), ShowCassandraVersion(), ShowCassandraRepairs(), ShowStorage(), ShowProcesses(),
101
+ Check(), Issues(), NodeTool(), Report(), AlterTables(), Bash(),
102
+ ExportTables(), ExportSelect(), ExportUse(), ShowExportDatabases(), ShowColumnCounts(),
103
+ DropExportDatabase(), DropExportDatabases(),
104
+ ShowExportSessions(), ShowExportSession(),
105
+ CleanUpExportSessions(), CleanUpAllExportSessions(), ImportSession()] + \
106
+ Medusa().cmd_list() + [Restart(), RollOut(), Watch()] + Reaper().cmd_list() + Repair().cmd_list()
107
+
108
+ def postgres_ops() -> list[Command]:
109
+ return [Postgres(), DeployPgAgent(), UndeployPgAgent(), PostgresPg()]
110
+
111
+ def app_ops() -> list[Command]:
112
+ return [ShowAppActions(), ShowAppId(), ShowAppQueues(), AppPing(), App()]
113
+
114
+ def audit_ops() -> list[Command]:
115
+ return [Audit()] + Audit().cmd_list()
116
+
117
+ def export_ops() -> list[Command]:
118
+ return [ExportSelectX(), DropExportDatabase(), DropExportDatabases(), ShowColumnCounts()]
119
+
120
+ def tools() -> list[Command]:
121
+ return [Shell(), CodeStart(), CodeStop(), DeployFrontend(), UndeployFrontend(), DeployPod(), UndeployPod(), Kubectl(), Code()]
122
+
123
+ def exit() -> list[Command]:
124
+ return [Exit()]