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
adam/commands/app.py DELETED
@@ -1,67 +0,0 @@
1
- import json
2
-
3
- from adam.apps import Apps
4
- from adam.commands.command import Command
5
- from adam.repl_state import ReplState, RequiredState
6
- from adam.app_session import AppSession
7
- from adam.utils import log2
8
-
9
- class App(Command):
10
- COMMAND = 'app'
11
-
12
- # the singleton pattern
13
- def __new__(cls, *args, **kwargs):
14
- if not hasattr(cls, 'instance'): cls.instance = super(App, cls).__new__(cls)
15
-
16
- return cls.instance
17
-
18
- def __init__(self, successor: Command=None):
19
- super().__init__(successor)
20
-
21
- def command(self):
22
- return App.COMMAND
23
-
24
- def required(self):
25
- return RequiredState.APP_APP
26
-
27
- def run(self, cmd: str, state: ReplState):
28
- if not(args := self.args(cmd)):
29
- return super().run(cmd, state)
30
-
31
- state, args = self.apply_state(args, state)
32
- if not self.validate_state(state):
33
- return state
34
-
35
- args, forced = Command.extract_options(args, '--force')
36
-
37
- if not args:
38
- return 'arg missing'
39
-
40
- t_f = args[0].split('.')
41
- if len(t_f) < 2:
42
- return 'arg missing'
43
-
44
- payload, valid = Apps().payload(t_f[0], t_f[1], args[1:] if len(args) > 1 else [])
45
- if not valid:
46
- log2('Missing one or more action arguments.')
47
- return state
48
-
49
- if payload:
50
- try:
51
- payload = json.loads(payload)
52
- except json.decoder.JSONDecodeError as e:
53
- log2(f'Invalid json argument: {e}')
54
- return state
55
-
56
- AppSession.run(state.app_env, state.app_app, state.namespace, t_f[0], t_f[1], payload=payload, forced=forced)
57
-
58
- return state
59
-
60
- def completion(self, state: ReplState):
61
- if state.app_app:
62
- return super().completion(state, {'--force': None})
63
-
64
- return {}
65
-
66
- def help(self, _: ReplState):
67
- return f"{App.COMMAND} [--force]\t post app API query with type and function"
adam/commands/bash.py DELETED
@@ -1,150 +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.pod_exec_result import PodExecResult
5
- from adam.repl_state import BashSession, ReplState, RequiredState
6
- from adam.utils_repl.automata_completer import AutomataCompleter
7
- from adam.utils_repl.state_machine import StateMachine
8
-
9
- class Bash(Command):
10
- COMMAND = 'bash'
11
-
12
- # the singleton pattern
13
- def __new__(cls, *args, **kwargs):
14
- if not hasattr(cls, 'instance'): cls.instance = super(Bash, cls).__new__(cls)
15
-
16
- return cls.instance
17
-
18
- def __init__(self, successor: Command=None):
19
- super().__init__(successor)
20
-
21
- def command(self):
22
- return Bash.COMMAND
23
-
24
- def required(self):
25
- return RequiredState.CLUSTER_OR_POD
26
-
27
- def run(self, cmd: str, s0: ReplState):
28
- if not(args := self.args(cmd)):
29
- return super().run(cmd, s0)
30
-
31
- state, args = self.apply_state(args, s0, args_to_check=2)
32
- if not self.validate_state(state):
33
- return state
34
-
35
- if state.in_repl:
36
- if s0.sts != state.sts or s0.pod != state.pod:
37
- r = self.exec_with_dir(state, args)
38
- else:
39
- r = self.exec_with_dir(s0, args)
40
-
41
- if not r:
42
- state.exit_bash()
43
-
44
- return 'inconsistent pwd'
45
-
46
- return r
47
- else:
48
- command = ' '.join(args)
49
-
50
- if state.pod:
51
- CassandraNodes.exec(state.pod, state.namespace, command, show_out=True)
52
- elif state.sts:
53
- CassandraClusters.exec(state.sts, state.namespace, command, action='bash', show_out=True)
54
-
55
- return state
56
-
57
- def exec_with_dir(self, state: ReplState, args: list[str]) -> list[PodExecResult]:
58
- session_just_created = False
59
- if not args:
60
- session_just_created = True
61
- session = BashSession(state.device)
62
- state.enter_bash(session)
63
-
64
- if state.bash_session:
65
- if args != ['pwd']:
66
- if args:
67
- args.append('&&')
68
- args.extend(['pwd', '>', f'/tmp/.qing-{state.bash_session.session_id}'])
69
-
70
- if not session_just_created:
71
- if pwd := state.bash_session.pwd(state):
72
- args = ['cd', pwd, '&&'] + args
73
-
74
- command = ' '.join(args)
75
-
76
- rs = []
77
-
78
- if state.pod:
79
- rs = [CassandraNodes.exec(state.pod, state.namespace, command,
80
- show_out=not session_just_created, shell='bash')]
81
- elif state.sts:
82
- rs = CassandraClusters.exec(state.sts, state.namespace, command, action='bash',
83
- show_out=not session_just_created, shell='bash')
84
-
85
- return rs
86
-
87
- def completion(self, state: ReplState):
88
- if state.pod or state.sts:
89
- return {Bash.COMMAND: AutomataCompleter(BashStateMachine())}
90
-
91
- return {}
92
-
93
- def help(self, _: ReplState):
94
- return f'{Bash.COMMAND} [bash-commands]\t run bash on the Cassandra nodes'
95
-
96
- BASH_SPEC = [
97
- # <command> ::= <simple_command> | <pipeline> | <conditional_command>
98
- # <simple_command> ::= <word> <argument>* <redirection>*
99
- # <pipeline> ::= <command> '|' <command>
100
- # <conditional_command> ::= <command> '&&' <command> | <command> '||' <command>
101
- # <word> ::= <letter> <letter_or_digit>*
102
- # <argument> ::= <word>
103
- # <redirection> ::= '>' <filename> | '<' <filename>
104
- # <filename> ::= <word>
105
- # <letter> ::= 'a' | 'b' | ... | 'z' | 'A' | 'B' | ... | 'Z'
106
- # <digit> ::= '0' | '1' | ... | '9'
107
- # <letter_or_digit> ::= <letter> | <digit>
108
-
109
- ' > word > word',
110
- 'word > word > word ^ |,>,2>,<,&,&&,||',
111
- '- > pipe > word_pipe',
112
- '- > _rdr0_ > word_rdr0',
113
- '- > _rdr1_ > word_rdr1',
114
- '- > _rdr2_ > word_rdr2',
115
- '- > & > word_bg ^ |,>,2>,<,&,&&,||',
116
- '- > &&|_or_ > word',
117
- 'word_a > word > word',
118
- 'word_pipe > word > word',
119
- 'word_rdr0 > word > word_rdr0_f',
120
- 'word_rdr1 > word > word_rdr1_f',
121
- 'word_rdr2 > word > word_rdr2_f',
122
- 'word_rdr1_f > pipe > word_pipe ^ |,2>,<,&,&&,||',
123
- '- > _rdr2_ > word_rdr2',
124
- '- > _rdr0_ > word_rdr0',
125
- 'word_rdr2_f > pipe > word_pipe ^ |,<,&,&&,||',
126
- '- > _rdr0_ > word_rdr0',
127
- '- > & > word_bg ^ |,>,2>,<,&,&&,||',
128
- '- > &&|_or_ > word',
129
- 'word_rdr0_f > pipe > word_pipe ^ |,&,&&,||',
130
- '- > & > word_bg ^ |,>,2>,<,&,&&,||',
131
- '- > &&|_or_ > word',
132
- 'word_bg > &&|_or_ > ^ &&,||',
133
- ]
134
-
135
- BASH_KEYWORDS = [
136
- '&',
137
- '&&',
138
- '|',
139
- '||',
140
- '>',
141
- '2>',
142
- '>>',
143
- '<'
144
- ]
145
- class BashStateMachine(StateMachine[str]):
146
- def spec(self) -> str:
147
- return BASH_SPEC
148
-
149
- def keywords(self) -> list[str]:
150
- return BASH_KEYWORDS
adam/commands/cd.py DELETED
@@ -1,125 +0,0 @@
1
- from adam.commands.command import Command
2
- from adam.commands.postgres.postgres_utils import pg_database_names
3
- from adam.commands.postgres.postgres_context import PostgresContext
4
- from adam.utils_k8s.cassandra_clusters import CassandraClusters
5
- from adam.utils_k8s.kube_context import KubeContext
6
- from adam.utils_k8s.statefulsets import StatefulSets
7
- from adam.repl_state import ReplState
8
- from adam.utils import log2
9
- from adam.apps import Apps
10
-
11
- class Cd(Command):
12
- COMMAND = 'cd'
13
-
14
- # the singleton pattern
15
- def __new__(cls, *args, **kwargs):
16
- if not hasattr(cls, 'instance'): cls.instance = super(Cd, cls).__new__(cls)
17
-
18
- return cls.instance
19
-
20
- def __init__(self, successor: Command=None):
21
- super().__init__(successor)
22
-
23
- def command(self):
24
- return Cd.COMMAND
25
-
26
- def required(self):
27
- return ReplState.NON_L
28
-
29
- def run(self, cmd: str, state: ReplState):
30
- if not(args := self.args(cmd)):
31
- return super().run(cmd, state)
32
-
33
- if not self.validate_state(state):
34
- return state
35
-
36
- if len(args) < 2:
37
- return state
38
-
39
- arg = args[1]
40
- for dir in arg.split('/'):
41
- if state.device == ReplState.P:
42
- if dir == '':
43
- state.pg_path = None
44
- else:
45
- context: PostgresContext = PostgresContext.apply(state.namespace, state.pg_path, arg=dir)
46
- # patch up state.namespace from pg cd
47
- if not state.namespace and context.namespace:
48
- state.namespace = context.namespace
49
- state.pg_path = context.path()
50
- elif state.device == ReplState.A:
51
- if dir == '':
52
- state.app_env = None
53
- state.app_app = None
54
- elif dir == '..':
55
- if state.app_app:
56
- state.app_app = None
57
- else:
58
- state.app_env = None
59
- else:
60
- if not state.app_env:
61
- tks = dir.split('@')
62
- if len(tks) > 1:
63
- state.namespace = tks[1]
64
-
65
- state.app_env = dir.split('@')[0]
66
- else:
67
- state.app_app = dir
68
- elif state.device == ReplState.L:
69
- pass
70
- else:
71
- if dir == '':
72
- state.sts = None
73
- state.pod = None
74
- elif dir == '..':
75
- if state.pod:
76
- state.pod = None
77
- else:
78
- state.sts = None
79
- else:
80
- if not state.sts:
81
- ss_and_ns = dir.split('@')
82
- state.sts = ss_and_ns[0]
83
- if len(ss_and_ns) > 1:
84
- state.namespace = ss_and_ns[1]
85
- elif not state.pod:
86
- p, _ = KubeContext.is_pod_name(dir)
87
- if p:
88
- state.pod = p
89
- else:
90
- names = CassandraClusters.pod_names_by_host_id(state.sts, state.namespace);
91
- if dir in names:
92
- state.pod = names[dir]
93
- else:
94
- log2('Not a valid pod name or host id.')
95
-
96
- return state
97
-
98
- def completion(self, state: ReplState):
99
- if state.device == ReplState.P:
100
- pg: PostgresContext = PostgresContext.apply(state.namespace, state.pg_path) if state.pg_path else None
101
- if pg and pg.db:
102
- return {Cd.COMMAND: {'..': None}}
103
- elif pg and pg.host:
104
- return {Cd.COMMAND: {'..': None} | {p: None for p in pg_database_names(state.namespace, pg.path())}}
105
- else:
106
- return {Cd.COMMAND: {p: None for p in PostgresContext.hosts(state.namespace)}}
107
- elif state.device == ReplState.A:
108
- if state.app_app:
109
- return {Cd.COMMAND: {'..': None}}
110
- elif state.app_env:
111
- return {Cd.COMMAND: {'..': None} | {app[0].split('-')[1]: None for app in Apps.apps(state.app_env)}}
112
- else:
113
- return {Cd.COMMAND: {'..': None} | {env[0]: None for env in Apps.envs()}}
114
- elif state.device == ReplState.C:
115
- if state.pod:
116
- return {Cd.COMMAND: {'..': None}}
117
- elif state.sts:
118
- return {Cd.COMMAND: {'..': None} | {p: None for p in StatefulSets.pod_names(state.sts, state.namespace)}}
119
- else:
120
- return {Cd.COMMAND: {p: None for p in StatefulSets.list_sts_names()}}
121
-
122
- return {}
123
-
124
- def help(self, _: ReplState):
125
- return f'{Cd.COMMAND} <path> | .. \t move around'
adam/commands/cp.py DELETED
@@ -1,95 +0,0 @@
1
- import click
2
- import pyperclip
3
-
4
- from adam.commands.command import Command
5
- from adam.commands.command_helpers import ClusterOrPodCommandHelper
6
- from adam.commands.cli_commands import CliCommands
7
- from adam.repl_state import ReplState, RequiredState
8
- from adam.utils import lines_to_tabular, log, log2
9
-
10
- class ClipboardCopy(Command):
11
- COMMAND = 'cp'
12
-
13
- # the singleton pattern
14
- def __new__(cls, *args, **kwargs):
15
- if not hasattr(cls, 'instance'): cls.instance = super(ClipboardCopy, 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 ClipboardCopy.COMMAND
24
-
25
- def required(self):
26
- return RequiredState.CLUSTER_OR_POD
27
-
28
- def run(self, cmd: str, state: ReplState):
29
- if not(args := self.args(cmd)):
30
- return super().run(cmd, state)
31
-
32
- state, args = self.apply_state(args, state)
33
- if not self.validate_state(state):
34
- return state
35
-
36
- if len(args) < 1:
37
- if state.in_repl:
38
- log2('Key is required.')
39
- log2()
40
- log2('Keys:')
41
- log2(lines_to_tabular([f'{k},{v}' for k, v in CliCommands.values(state, collapse=True).items()], separator=','))
42
- else:
43
- log2('* Key is missing.')
44
- Command.display_help()
45
-
46
- return 'command-missing'
47
-
48
- key = args[0]
49
- if not key in CliCommands.values(state):
50
- if state.in_repl:
51
- log2('Key is required.')
52
- log2()
53
- log2('Keys:')
54
- log2(lines_to_tabular([f'{k},{v}' for k, v in CliCommands.values(state, collapse=True).items()], separator=','))
55
- else:
56
- log2('* Invalid key')
57
- Command.display_help()
58
-
59
- return 'command-invalid'
60
-
61
- value = CliCommands.values(state)[key]
62
- pyperclip.copy(value)
63
- log2('The following line has been copied to clipboard. Use <Ctrl-V> to use it.')
64
- log2(f' {value}')
65
-
66
- return 'value-copied'
67
-
68
- def completion(self, state: ReplState):
69
- if state.sts:
70
- return {ClipboardCopy.COMMAND: {key: None for key in CliCommands.values(state).keys()}}
71
-
72
- return {}
73
-
74
- def help(self, _: ReplState):
75
- return f"{ClipboardCopy.COMMAND} <key>\t copy a value to clipboard for conveninence"
76
-
77
- class CopyCommandHelper(click.Command):
78
- def lines(self):
79
- return [
80
- 'node-exec-?: kubectl exec command to the Cassandra pod',
81
- 'reaper-exec: kubectl exec command to the Reaper pod',
82
- 'reaper-forward: kubectl port-forward command to the Reaper pod',
83
- 'reaper-ui: uri to Reaper ui',
84
- 'reaper-username: Reaper user name',
85
- 'reaper-password: Reaper password',
86
- ]
87
-
88
- def get_help(self, ctx: click.Context):
89
- log(super().get_help(ctx))
90
- log()
91
- log('Keys:')
92
-
93
- log(lines_to_tabular(self.lines(), separator=':'))
94
- log()
95
- ClusterOrPodCommandHelper.cluter_or_pod_help()
@@ -1,15 +0,0 @@
1
- from adam.commands.cql.cql_utils import cassandra_table_names
2
- from adam.config import Config
3
- from adam.repl_state import ReplState
4
- from adam.sql.sql_completer import SqlCompleter
5
-
6
- def cql_completions(state: ReplState) -> dict[str, any]:
7
- ps = Config().get('cql.alter-tables.gc-grace-periods', '3600,86400,864000,7776000').split(',')
8
- return {
9
- 'describe': {
10
- 'keyspaces': None,
11
- 'table': {t: None for t in cassandra_table_names(state)},
12
- 'tables': None},
13
- } | SqlCompleter(lambda: cassandra_table_names(state), table_props=lambda: {
14
- 'GC_GRACE_SECONDS': ps
15
- }, variant='cql').completions_for_nesting()
@@ -1,112 +0,0 @@
1
- import functools
2
- import re
3
-
4
- from adam.config import Config
5
- from adam.utils_k8s.cassandra_clusters import CassandraClusters
6
- from adam.utils_k8s.cassandra_nodes import CassandraNodes
7
- from adam.utils_k8s.secrets import Secrets
8
- from adam.pod_exec_result import PodExecResult
9
- from adam.repl_state import ReplState
10
- from adam.utils import log2
11
-
12
- @functools.lru_cache()
13
- def keyspaces(state: ReplState, on_any=False):
14
- if state.pod:
15
- Config().wait_log(f'Inspecting Cassandra Keyspaces on {state.pod}...')
16
- else:
17
- Config().wait_log(f'Inspecting Cassandra Keyspaces...')
18
-
19
- r: list[PodExecResult] = run_cql(state, 'describe keyspaces', show_out=False, on_any=on_any)
20
- if not r:
21
- log2('No pod is available')
22
- return []
23
-
24
- return parse_cql_desc_keyspaces(r.stdout if state.pod else r[0].stdout)
25
-
26
- def cassandra_table_names(state: ReplState):
27
- return [f'{k}.{t}' for k, ts in tables(state, on_any=True).items() for t in ts]
28
-
29
- @functools.lru_cache()
30
- def tables(state: ReplState, on_any=False) -> dict[str, list[str]]:
31
- r: list[PodExecResult] = run_cql(state, 'describe tables', show_out=False, on_any=on_any)
32
- if not r:
33
- log2('No pod is available')
34
- return {}
35
-
36
- return parse_cql_desc_tables(r.stdout if state.pod else r[0].stdout)
37
-
38
- def run_cql(state: ReplState, cql: str, opts: list = [], show_out = False, use_single_quotes = False, on_any = False, background=False) -> list[PodExecResult]:
39
- user, pw = Secrets.get_user_pass(state.sts if state.sts else state.pod, state.namespace, secret_path='cql.secret')
40
- if use_single_quotes:
41
- command = f"cqlsh -u {user} -p {pw} {' '.join(opts)} -e '{cql}'"
42
- else:
43
- command = f'cqlsh -u {user} -p {pw} {" ".join(opts)} -e "{cql}"'
44
-
45
- if state.pod:
46
- return CassandraNodes.exec(state.pod, state.namespace, command, show_out=show_out, background=background)
47
- else:
48
- return CassandraClusters.exec(state.sts, state.namespace, command, show_out=show_out, action='cql', on_any=on_any, background=background)
49
-
50
- def parse_cql_desc_tables(out: str):
51
- # Keyspace data_endpoint_auth
52
- # ---------------------------
53
- # "token"
54
-
55
- # Keyspace reaper_db
56
- # ------------------
57
- # repair_run schema_migration
58
- # repair_run_by_cluster schema_migration_leader
59
-
60
- # Keyspace system
61
- tables_by_keyspace: dict[str, list[str]] = {}
62
- keyspace = None
63
- state = 's0'
64
- for line in out.split('\n'):
65
- if state == 's0':
66
- groups = re.match(r'^Keyspace (.*)$', line)
67
- if groups:
68
- keyspace = groups[1].strip(' \r')
69
- state = 's1'
70
- elif state == 's1':
71
- if line.startswith('---'):
72
- state = 's2'
73
- elif state == 's2':
74
- if not line.strip(' \r'):
75
- state = 's0'
76
- else:
77
- for table in line.split(' '):
78
- if t := table.strip(' \r'):
79
- if not keyspace in tables_by_keyspace:
80
- tables_by_keyspace[keyspace] = []
81
- tables_by_keyspace[keyspace].append(t)
82
-
83
- return tables_by_keyspace
84
-
85
- def parse_cql_desc_keyspaces(out: str) -> list[str]:
86
- #
87
- # Warning: Cannot create directory at `/home/cassandra/.cassandra`. Command history will not be saved. Please check what was the environment property CQL_HISTORY set to.
88
- #
89
- #
90
- # Warning: Using a password on the command line interface can be insecure.
91
- # Recommendation: use the credentials file to securely provide the password.
92
- #
93
- #
94
- # azops88_db system_auth system_traces
95
- # reaper_db system_distributed system_views
96
- # system system_schema system_virtual_schema
97
- #
98
- kses = []
99
- for line in out.split('\n'):
100
- line = line.strip(' \r')
101
- if not line:
102
- continue
103
- if line.startswith('Warning:'):
104
- continue
105
- if line.startswith('Recommendation:'):
106
- continue
107
-
108
- for ks in line.split(' '):
109
- if s := ks.strip(' \r\t'):
110
- kses.append(s)
111
-
112
- return kses
adam/commands/devices.py DELETED
@@ -1,118 +0,0 @@
1
- from adam.commands.command import Command
2
- from adam.repl_state import ReplState
3
-
4
- class DeviceAuditLog(Command):
5
- COMMAND = f'{ReplState.L}:'
6
-
7
- # the singleton pattern
8
- def __new__(cls, *args, **kwargs):
9
- if not hasattr(cls, 'instance'): cls.instance = super(DeviceAuditLog, cls).__new__(cls)
10
-
11
- return cls.instance
12
-
13
- def __init__(self, successor: Command=None):
14
- super().__init__(successor)
15
-
16
- def command(self):
17
- return DeviceAuditLog.COMMAND
18
-
19
- def run(self, cmd: str, state: ReplState):
20
- if not self.args(cmd):
21
- return super().run(cmd, state)
22
-
23
- state.device = ReplState.L
24
-
25
- return state
26
-
27
- def completion(self, state: ReplState):
28
- return super().completion(state)
29
-
30
- def help(self, _: ReplState):
31
- return f'{DeviceAuditLog.COMMAND}\t move to Audit Log Operations device'
32
-
33
- class DeviceCass(Command):
34
- COMMAND = f'{ReplState.C}:'
35
-
36
- # the singleton pattern
37
- def __new__(cls, *args, **kwargs):
38
- if not hasattr(cls, 'instance'): cls.instance = super(DeviceCass, cls).__new__(cls)
39
-
40
- return cls.instance
41
-
42
- def __init__(self, successor: Command=None):
43
- super().__init__(successor)
44
-
45
- def command(self):
46
- return DeviceCass.COMMAND
47
-
48
- def run(self, cmd: str, state: ReplState):
49
- if not self.args(cmd):
50
- return super().run(cmd, state)
51
-
52
- state.device = ReplState.C
53
-
54
- return state
55
-
56
- def completion(self, state: ReplState):
57
- return super().completion(state)
58
-
59
- def help(self, _: ReplState):
60
- return f'{DeviceCass.COMMAND}\t move to Cassandra Operations device'
61
-
62
- class DevicePostgres(Command):
63
- COMMAND = f'{ReplState.P}:'
64
-
65
- # the singleton pattern
66
- def __new__(cls, *args, **kwargs):
67
- if not hasattr(cls, 'instance'): cls.instance = super(DevicePostgres, cls).__new__(cls)
68
-
69
- return cls.instance
70
-
71
- def __init__(self, successor: Command=None):
72
- super().__init__(successor)
73
-
74
- def command(self):
75
- return DevicePostgres.COMMAND
76
-
77
- def run(self, cmd: str, state: ReplState):
78
- if not self.args(cmd):
79
- return super().run(cmd, state)
80
-
81
- state.device = ReplState.P
82
-
83
- return state
84
-
85
- def completion(self, state: ReplState):
86
- return super().completion(state)
87
-
88
- def help(self, _: ReplState):
89
- return f'{DevicePostgres.COMMAND}\t move to Postgres Operations device'
90
-
91
- class DeviceApp(Command):
92
- COMMAND = f'{ReplState.A}:'
93
-
94
- # the singleton pattern
95
- def __new__(cls, *args, **kwargs):
96
- if not hasattr(cls, 'instance'): cls.instance = super(DeviceApp, cls).__new__(cls)
97
-
98
- return cls.instance
99
-
100
- def __init__(self, successor: Command=None):
101
- super().__init__(successor)
102
-
103
- def command(self):
104
- return DeviceApp.COMMAND
105
-
106
- def run(self, cmd: str, state: ReplState):
107
- if not self.args(cmd):
108
- return super().run(cmd, state)
109
-
110
- state.device = ReplState.A
111
-
112
- return state
113
-
114
- def completion(self, state: ReplState):
115
- return super().completion(state)
116
-
117
- def help(self, _: ReplState):
118
- return f'{DeviceApp.COMMAND}\t move to App Operations device'