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
@@ -0,0 +1,36 @@
1
+ from adam.commands import validate_args
2
+ from adam.commands.command import Command
3
+ from adam.commands.devices.devices import Devices
4
+ from adam.repl_state import ReplState, RequiredState
5
+
6
+ class Head(Command):
7
+ COMMAND = 'head'
8
+
9
+ # the singleton pattern
10
+ def __new__(cls, *args, **kwargs):
11
+ if not hasattr(cls, 'instance'): cls.instance = super(Head, 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 Head.COMMAND
20
+
21
+ def required(self):
22
+ return [RequiredState.CLUSTER_OR_POD, RequiredState.APP_APP, ReplState.P]
23
+
24
+ def run(self, cmd: str, state: ReplState):
25
+ if not(args := self.args(cmd)):
26
+ return super().run(cmd, state)
27
+
28
+ with self.validate(args, state) as (args, state):
29
+ with validate_args(args, state, name='file'):
30
+ return Devices.of(state).bash(state, state, cmd.split(' '))
31
+
32
+ def completion(self, state: ReplState):
33
+ return super().completion(state, lambda: {f: None for f in Devices.of(state).files(state)}, pods=Devices.of(state).pods(state, '-'), auto='jit')
34
+
35
+ def help(self, _: ReplState):
36
+ return f'{Head.COMMAND} file [&]\t run head command on the pod'
adam/commands/fs/ls.py ADDED
@@ -0,0 +1,41 @@
1
+ import copy
2
+
3
+ from adam.commands.command import Command
4
+ from adam.commands.devices.devices import Devices
5
+ from adam.repl_state import ReplState
6
+
7
+ class Ls(Command):
8
+ COMMAND = 'ls'
9
+
10
+ # the singleton pattern
11
+ def __new__(cls, *args, **kwargs):
12
+ if not hasattr(cls, 'instance'): cls.instance = super(Ls, 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 Ls.COMMAND
21
+
22
+ def run(self, cmd: str, state: ReplState):
23
+ if not(args := self.args(cmd)):
24
+ return super().run(cmd, state)
25
+
26
+ with self.validate(args, state) as (args, state):
27
+ if len(args) > 0:
28
+ arg = args[0]
29
+ if arg in ['p:', 'c:'] and arg != f'{state.device}:':
30
+ state = copy.copy(state)
31
+ state.device = arg.replace(':', '')
32
+
33
+ Devices.of(state).ls(cmd, state)
34
+
35
+ return state
36
+
37
+ def completion(self, state: ReplState):
38
+ return super().completion(state, {'&': None}, pods=Devices.of(state).pods(state, '-'))
39
+
40
+ def help(self, _: ReplState):
41
+ return f'{Ls.COMMAND} [device:]\t list apps, envs, clusters, nodes, pg hosts/databases or export databases'
@@ -0,0 +1,40 @@
1
+ import os
2
+
3
+ from adam.commands.command import Command
4
+ from adam.repl_state import ReplState
5
+ from adam.utils import log2
6
+ from adam.utils_local import local_qing_dir
7
+
8
+ class LsLocal(Command):
9
+ COMMAND = ':ls'
10
+
11
+ # the singleton pattern
12
+ def __new__(cls, *args, **kwargs):
13
+ if not hasattr(cls, 'instance'): cls.instance = super(LsLocal, 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 LsLocal.COMMAND
22
+
23
+ def run(self, cmd: str, state: ReplState):
24
+ if not(args := self.args(cmd)):
25
+ return super().run(cmd, state)
26
+
27
+ with self.validate(args, state) as (args, state):
28
+ if args:
29
+ os.system(f'ls {args}')
30
+ else:
31
+ os.system(f'ls {local_qing_dir()}')
32
+ log2()
33
+
34
+ return state
35
+
36
+ def completion(self, state: ReplState):
37
+ return super().completion(state)
38
+
39
+ def help(self, _: ReplState):
40
+ return f'{LsLocal.COMMAND} [dir]\t list files on local system'
@@ -0,0 +1,45 @@
1
+ from adam.app_session import AppSession
2
+ from adam.commands.command import Command
3
+ from adam.commands.devices.devices import Devices
4
+ from adam.repl_state import ReplState
5
+ from adam.utils import tabulize, log, log_exc
6
+
7
+ class Pwd(Command):
8
+ COMMAND = 'pwd'
9
+
10
+ # the singleton pattern
11
+ def __new__(cls, *args, **kwargs):
12
+ if not hasattr(cls, 'instance'): cls.instance = super(Pwd, 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 Pwd.COMMAND
21
+
22
+ def run(self, cmd: str, state: ReplState):
23
+ if not(args := self.args(cmd)):
24
+ return super().run(cmd, state)
25
+
26
+ with self.validate(args, state) as (_, state):
27
+ host = "unknown"
28
+ with log_exc():
29
+ app_session: AppSession = AppSession.create('c3', 'c3')
30
+ host = app_session.host
31
+
32
+ tabulize([device.pwd(state) for device in Devices.all()] + [
33
+ f'',
34
+ f'HOST\t{host}',
35
+ f'NAMESPACE\t{state.namespace if state.namespace else "/"}',
36
+ ], header='DEVICE\tLOCATION', separator='\t')
37
+ log()
38
+
39
+ return state
40
+
41
+ def completion(self, state: ReplState):
42
+ return super().completion(state)
43
+
44
+ def help(self, _: ReplState):
45
+ return f'{Pwd.COMMAND}\t print current working directories'
adam/commands/fs/rm.py ADDED
@@ -0,0 +1,18 @@
1
+ from adam.commands.fs.rm_downloads import RmDownloads
2
+ from adam.commands.fs.rm_logs import RmLogs
3
+ from adam.commands.intermediate_command import IntermediateCommand
4
+
5
+ class RmLocal(IntermediateCommand):
6
+ COMMAND = ':rm'
7
+
8
+ # the singleton pattern
9
+ def __new__(cls, *args, **kwargs):
10
+ if not hasattr(cls, 'instance'): cls.instance = super(RmLocal, cls).__new__(cls)
11
+
12
+ return cls.instance
13
+
14
+ def command(self):
15
+ return RmLocal.COMMAND
16
+
17
+ def cmd_list(self):
18
+ return [RmDownloads(), RmLogs()]
@@ -0,0 +1,39 @@
1
+ import os
2
+
3
+ from adam.commands.command import Command
4
+ from adam.repl_state import ReplState
5
+ from adam.utils import log2
6
+ from adam.utils_local import local_downloads_dir
7
+
8
+ class RmDownloads(Command):
9
+ COMMAND = ':rm downloads'
10
+
11
+ # the singleton pattern
12
+ def __new__(cls, *args, **kwargs):
13
+ if not hasattr(cls, 'instance'): cls.instance = super(RmDownloads, 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 RmDownloads.COMMAND
22
+
23
+ def run(self, cmd: str, state: ReplState):
24
+ if not(args := self.args(cmd)):
25
+ return super().run(cmd, state)
26
+
27
+ with self.validate(args, state) as (args, state):
28
+ cmd = f'rm -rf {local_downloads_dir()}/*'
29
+ log2(cmd)
30
+ os.system(cmd)
31
+ log2()
32
+
33
+ return state
34
+
35
+ def completion(self, state: ReplState):
36
+ return super().completion(state)
37
+
38
+ def help(self, _: ReplState):
39
+ return f'{RmDownloads.COMMAND}\t remove all downloads files under {local_downloads_dir()}'
@@ -0,0 +1,38 @@
1
+ import os
2
+
3
+ from adam.commands.command import Command
4
+ from adam.repl_state import ReplState
5
+ from adam.utils import log2, log_dir
6
+
7
+ class RmLogs(Command):
8
+ COMMAND = ':rm logs'
9
+
10
+ # the singleton pattern
11
+ def __new__(cls, *args, **kwargs):
12
+ if not hasattr(cls, 'instance'): cls.instance = super(RmLogs, 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 RmLogs.COMMAND
21
+
22
+ def run(self, cmd: str, state: ReplState):
23
+ if not(args := self.args(cmd)):
24
+ return super().run(cmd, state)
25
+
26
+ with self.validate(args, state) as (args, state):
27
+ cmd = f'rm -rf {log_dir()}/*'
28
+ log2(cmd)
29
+ os.system(cmd)
30
+ log2()
31
+
32
+ return state
33
+
34
+ def completion(self, state: ReplState):
35
+ return super().completion(state)
36
+
37
+ def help(self, _: ReplState):
38
+ return f'{RmLogs.COMMAND}\t remove all qing log files under {log_dir()}'
@@ -1,7 +1,9 @@
1
1
  import os
2
2
 
3
+ from adam.commands import validate_args
3
4
  from adam.commands.command import Command
4
5
  from adam.repl_state import ReplState
6
+ from adam.utils import log2
5
7
 
6
8
  class Shell(Command):
7
9
  COMMAND = ':sh'
@@ -18,13 +20,19 @@ class Shell(Command):
18
20
  def command(self):
19
21
  return Shell.COMMAND
20
22
 
21
- def run(self, cmd: str, s0: ReplState):
23
+ def run(self, cmd: str, state: ReplState):
22
24
  if not(args := self.args(cmd)):
23
- return super().run(cmd, s0)
25
+ return super().run(cmd, state)
24
26
 
25
- _, args = self.apply_state(args, s0)
27
+ with self.validate(args, state) as (args, _):
28
+ with validate_args(args, state, at_least=0) as args_str:
29
+ if args_str:
30
+ os.system(args_str)
31
+ log2()
32
+ else:
33
+ os.system('QING_DROPPED=true bash')
26
34
 
27
- os.system('QING_DROPPED=true bash')
35
+ return state
28
36
 
29
37
  def completion(self, state: ReplState):
30
38
  return super().completion(state)
@@ -1,7 +1,7 @@
1
1
  import sys
2
2
  import os
3
3
 
4
- from adam.utils import lines_to_tabular, log2
4
+ from adam.utils import tabulize
5
5
 
6
6
  current_dir = os.path.dirname(os.path.abspath(__file__))
7
7
 
@@ -34,10 +34,10 @@ class ShowAdam(Command):
34
34
 
35
35
  package = os.path.dirname(os.path.abspath(__file__))
36
36
  package = package.split('/adam/')[0] + '/adam'
37
- log2(lines_to_tabular([
37
+ tabulize([
38
38
  f'version\t{__version__}',
39
39
  f'source\t{package}'
40
- ], separator='\t'))
40
+ ], separator='\t', to=2)
41
41
 
42
42
  return state
43
43
 
@@ -19,7 +19,7 @@ class ShowHost(Command):
19
19
  return ShowHost.COMMAND
20
20
 
21
21
  def run(self, cmd: str, state: ReplState):
22
- if not(args := self.args(cmd)):
22
+ if not self.args(cmd):
23
23
  return super().run(cmd, state)
24
24
 
25
25
  log(get_my_host())
adam/commands/help.py CHANGED
@@ -1,7 +1,7 @@
1
1
  from adam.commands.command import Command
2
2
  from adam.repl_commands import ReplCommands
3
3
  from adam.repl_state import ReplState
4
- from adam.utils import lines_to_tabular, log
4
+ from adam.utils import tabulize, log
5
5
 
6
6
  class Help(Command):
7
7
  COMMAND = 'help'
@@ -28,7 +28,7 @@ class Help(Command):
28
28
 
29
29
  lines = []
30
30
  lines.append('NAVIGATION')
31
- lines.append(' a: | c: | l: | p:\t switch to another operational device: App, Cassandra, Audit or Postgres')
31
+ lines.append(' a: | c: | l: | p: | x:\t switch to another operational device: App, Cassandra, Audit, Postgres or Export')
32
32
  lines.extend(section(ReplCommands.navigation()))
33
33
  lines.append('CASSANDRA')
34
34
  lines.extend(section(ReplCommands.cassandra_ops()))
@@ -36,6 +36,8 @@ class Help(Command):
36
36
  lines.extend(section(ReplCommands.postgres_ops()))
37
37
  lines.append('APP')
38
38
  lines.extend(section(ReplCommands.app_ops()))
39
+ lines.append('EXPORT DB')
40
+ lines.extend(section(ReplCommands.export_ops()))
39
41
  lines.append('AUDIT')
40
42
  lines.extend(section(ReplCommands.audit_ops()))
41
43
  lines.append('TOOLS')
@@ -43,7 +45,7 @@ class Help(Command):
43
45
  lines.append('')
44
46
  lines.extend(section(ReplCommands.exit()))
45
47
 
46
- log(lines_to_tabular(lines, separator='\t'))
48
+ tabulize(lines, separator='\t')
47
49
 
48
50
  return lines
49
51
 
@@ -0,0 +1,52 @@
1
+ from abc import abstractmethod
2
+
3
+ from adam.commands.command import Command
4
+ from adam.commands.command_helpers import ClusterCommandHelper
5
+ from adam.repl_state import ReplState
6
+ from adam.utils import tabulize, log, log2
7
+
8
+ class IntermediateCommand(Command):
9
+ def run(self, cmd: str, state: ReplState):
10
+ if not(args := self.args(cmd)):
11
+ return super().run(cmd, state)
12
+
13
+ return self.intermediate_run(cmd, state, args, self.cmd_list())
14
+
15
+ def completion(self, state: ReplState):
16
+ return {}
17
+
18
+ @abstractmethod
19
+ def cmd_list(self):
20
+ pass
21
+
22
+ def intermediate_run(self, cmd: str, state: ReplState, args: list[str], cmds: list['Command'], separator='\t', display_help=True):
23
+ state, _ = self.apply_state(args, state)
24
+
25
+ if state.in_repl:
26
+ if display_help:
27
+ tabulize(cmds, lambda c: c.help(state), separator=separator)
28
+
29
+ return 'command-missing'
30
+ else:
31
+ # head with the Chain of Responsibility pattern
32
+ if not self.run_subcommand(cmd, state):
33
+ if display_help:
34
+ log2('* Command is missing.')
35
+ Command.display_help()
36
+ return 'command-missing'
37
+
38
+ return state
39
+
40
+ def run_subcommand(self, cmd: str, state: ReplState):
41
+ cmds = Command.chain(self.cmd_list())
42
+ return cmds.run(cmd, state)
43
+
44
+ def intermediate_help(super_help: str, cmd: str, cmd_list: list['Command'], separator='\t', show_cluster_help=False):
45
+ log(super_help)
46
+ log()
47
+ log('Sub-Commands:')
48
+
49
+ tabulize(cmd_list, lambda c: c.help(ReplState()).replace(f'{cmd} ', ' ', 1), separator=separator)
50
+ if show_cluster_help:
51
+ log()
52
+ ClusterCommandHelper.cluster_help()
@@ -0,0 +1,38 @@
1
+ import subprocess
2
+
3
+ from adam.commands.command import Command
4
+ from adam.repl_state import ReplState, RequiredState
5
+
6
+ class Kubectl(Command):
7
+ COMMAND = 'k'
8
+
9
+ # the singleton pattern
10
+ def __new__(cls, *args, **kwargs):
11
+ if not hasattr(cls, 'instance'): cls.instance = super(Kubectl, 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 Kubectl.COMMAND
20
+
21
+ def required(self):
22
+ return RequiredState.NAMESPACE
23
+
24
+ def run(self, cmd: str, state: ReplState):
25
+ if not(args := self.args(cmd)):
26
+ return super().run(cmd, state)
27
+
28
+ with self.validate(args, state) as (args, state):
29
+ subprocess.run(["kubectl"] + args)
30
+
31
+ return state
32
+
33
+ def completion(self, state: ReplState):
34
+ return super().completion(state)
35
+
36
+
37
+ def help(self, _: ReplState):
38
+ return f'{Kubectl.COMMAND} \t run a kubectl command'
@@ -1,13 +1,13 @@
1
1
  import click
2
2
 
3
3
  from adam.commands.command import Command
4
+ from adam.commands.intermediate_command import IntermediateCommand
4
5
  from .medusa_backup import MedusaBackup
5
6
  from .medusa_restore import MedusaRestore
6
7
  from .medusa_show_backupjobs import MedusaShowBackupJobs
7
8
  from .medusa_show_restorejobs import MedusaShowRestoreJobs
8
- from adam.repl_state import ReplState, RequiredState
9
9
 
10
- class Medusa(Command):
10
+ class Medusa(IntermediateCommand):
11
11
  COMMAND = 'medusa'
12
12
 
13
13
  # the singleton pattern
@@ -16,30 +16,12 @@ class Medusa(Command):
16
16
 
17
17
  return cls.instance
18
18
 
19
- def __init__(self, successor: Command=None):
20
- super().__init__(successor)
21
-
22
19
  def command(self):
23
20
  return Medusa.COMMAND
24
21
 
25
- def required(self):
26
- return RequiredState.CLUSTER
27
-
28
- def run(self, cmd: str, state: ReplState):
29
- if not(args := self.args(cmd)):
30
- return super().run(cmd, state)
31
-
32
- return super().intermediate_run(cmd, state, args, Medusa.cmd_list())
33
-
34
- def cmd_list():
22
+ def cmd_list(self):
35
23
  return [MedusaBackup(), MedusaRestore(), MedusaShowBackupJobs(), MedusaShowRestoreJobs()]
36
24
 
37
- def completion(self, state: ReplState):
38
- if state.sts:
39
- return super().completion(state)
40
-
41
- return {}
42
-
43
25
  class MedusaCommandHelper(click.Command):
44
26
  def get_help(self, ctx: click.Context):
45
- Command.intermediate_help(super().get_help(ctx), Medusa.COMMAND, Medusa.cmd_list(), show_cluster_help=True)
27
+ IntermediateCommand.intermediate_help(super().get_help(ctx), Medusa.COMMAND, Medusa().cmd_list(), show_cluster_help=True)
@@ -1,13 +1,12 @@
1
1
  from datetime import datetime
2
- import re
3
2
 
3
+ from adam.commands import validate_args
4
4
  from adam.commands.command import Command
5
5
  from adam.utils_k8s.statefulsets import StatefulSets
6
6
  from adam.repl_state import ReplState, RequiredState
7
7
  from adam.utils_k8s.custom_resources import CustomResources
8
8
  from adam.utils import log2
9
9
 
10
-
11
10
  class MedusaBackup(Command):
12
11
  COMMAND = 'backup'
13
12
 
@@ -29,33 +28,27 @@ class MedusaBackup(Command):
29
28
  def run(self, cmd: str, state: ReplState):
30
29
  if not(args := self.args(cmd)):
31
30
  return super().run(cmd, state)
32
- state, args = self.apply_state(args, state)
33
- if not self.validate_state(state):
34
- return state
35
-
36
- ns = state.namespace
37
- sts = state.sts
38
- now_dtformat = datetime.now().strftime("%Y-%m-%d.%H.%M.%S")
39
- bkname = 'medusa-' + now_dtformat + 'full-backup-' + sts
40
- if len(args) == 1:
41
- bkname = str(args[0])
42
- groups = re.match(r'^(.*?-.*?-).*', sts)
43
- dc = StatefulSets.get_datacenter(state.sts, ns)
44
- if not dc:
45
- return state
46
-
47
- try:
48
- CustomResources.create_medusa_backupjob(bkname, dc, ns)
49
- except Exception as e:
50
- log2("Exception: MedusaBackup failed: %s\n" % e)
51
-
52
- return state
53
31
 
54
- def completion(self, state: ReplState):
55
- if state.sts:
56
- return super().completion(state)
32
+ with self.validate(args, state) as (args, state):
33
+ ns = state.namespace
34
+ sts = state.sts
35
+ now_dtformat = datetime.now().strftime("%Y-%m-%d.%H.%M.%S")
36
+ with validate_args(args, state, default='medusa-' + now_dtformat + 'full-backup-' + sts) as bkname:
37
+ dc = StatefulSets.get_datacenter(state.sts, ns)
38
+ if not dc:
39
+ return state
40
+
41
+ try:
42
+ CustomResources.create_medusa_backupjob(bkname, dc, ns)
43
+ except Exception as e:
44
+ log2("Exception: MedusaBackup failed: %s\n" % e)
45
+ finally:
46
+ CustomResources.clear_caches()
57
47
 
58
- return {}
48
+ return state
49
+
50
+ def completion(self, state: ReplState):
51
+ return super().completion(state)
59
52
 
60
53
  def help(self, _: ReplState):
61
54
  return f'{MedusaBackup.COMMAND}\t start a backup job'