kaqing 2.0.98__py3-none-any.whl → 2.0.203__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 (254) 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 +11 -25
  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/alter_tables.py +37 -63
  15. adam/commands/app/app.py +38 -0
  16. adam/commands/{app_ping.py → app/app_ping.py} +8 -14
  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 +8 -14
  20. adam/commands/app/utils_app.py +106 -0
  21. adam/commands/audit/audit.py +31 -35
  22. adam/commands/audit/audit_repair_tables.py +26 -48
  23. adam/commands/audit/audit_run.py +50 -0
  24. adam/commands/audit/completions_l.py +15 -0
  25. adam/commands/audit/show_last10.py +36 -0
  26. adam/commands/audit/show_slow10.py +36 -0
  27. adam/commands/audit/show_top10.py +36 -0
  28. adam/commands/audit/utils_show_top10.py +71 -0
  29. adam/commands/bash/__init__.py +5 -0
  30. adam/commands/bash/bash.py +36 -0
  31. adam/commands/bash/bash_completer.py +93 -0
  32. adam/commands/bash/utils_bash.py +16 -0
  33. adam/commands/cassandra/__init__.py +0 -0
  34. adam/commands/cassandra/download_cassandra_log.py +45 -0
  35. adam/commands/cassandra/nodetool.py +64 -0
  36. adam/commands/cassandra/nodetool_commands.py +120 -0
  37. adam/commands/{restart.py → cassandra/restart_cluster.py} +12 -26
  38. adam/commands/cassandra/restart_node.py +51 -0
  39. adam/commands/cassandra/restart_nodes.py +47 -0
  40. adam/commands/cassandra/rollout.py +88 -0
  41. adam/commands/cat.py +36 -0
  42. adam/commands/cd.py +14 -92
  43. adam/commands/check.py +18 -21
  44. adam/commands/cli_commands.py +8 -4
  45. adam/commands/clipboard_copy.py +87 -0
  46. adam/commands/code.py +57 -0
  47. adam/commands/command.py +212 -39
  48. adam/commands/commands_utils.py +20 -28
  49. adam/commands/cql/alter_tables.py +66 -0
  50. adam/commands/cql/completions_c.py +29 -0
  51. adam/commands/cql/cqlsh.py +10 -29
  52. adam/commands/cql/utils_cql.py +305 -0
  53. adam/commands/debug/__init__.py +0 -0
  54. adam/commands/debug/debug.py +22 -0
  55. adam/commands/debug/debug_completes.py +35 -0
  56. adam/commands/debug/debug_timings.py +35 -0
  57. adam/commands/deploy/code_start.py +7 -10
  58. adam/commands/deploy/code_stop.py +4 -21
  59. adam/commands/deploy/code_utils.py +3 -3
  60. adam/commands/deploy/deploy.py +4 -21
  61. adam/commands/deploy/deploy_frontend.py +14 -17
  62. adam/commands/deploy/deploy_pg_agent.py +3 -6
  63. adam/commands/deploy/deploy_pod.py +65 -73
  64. adam/commands/deploy/deploy_utils.py +14 -24
  65. adam/commands/deploy/undeploy.py +4 -21
  66. adam/commands/deploy/undeploy_frontend.py +4 -7
  67. adam/commands/deploy/undeploy_pg_agent.py +6 -8
  68. adam/commands/deploy/undeploy_pod.py +11 -12
  69. adam/commands/devices/__init__.py +0 -0
  70. adam/commands/devices/device.py +149 -0
  71. adam/commands/devices/device_app.py +163 -0
  72. adam/commands/devices/device_auit_log.py +49 -0
  73. adam/commands/devices/device_cass.py +179 -0
  74. adam/commands/devices/device_export.py +87 -0
  75. adam/commands/devices/device_postgres.py +160 -0
  76. adam/commands/devices/devices.py +25 -0
  77. adam/commands/download_cassandra_log.py +45 -0
  78. adam/commands/download_file.py +47 -0
  79. adam/commands/exit.py +1 -4
  80. adam/commands/export/__init__.py +0 -0
  81. adam/commands/export/clean_up_all_export_sessions.py +37 -0
  82. adam/commands/export/clean_up_export_sessions.py +39 -0
  83. adam/commands/export/completions_x.py +11 -0
  84. adam/commands/export/download_export_session.py +40 -0
  85. adam/commands/export/drop_export_database.py +39 -0
  86. adam/commands/export/drop_export_databases.py +37 -0
  87. adam/commands/export/export.py +37 -0
  88. adam/commands/export/export_databases.py +247 -0
  89. adam/commands/export/export_select.py +34 -0
  90. adam/commands/export/export_sessions.py +211 -0
  91. adam/commands/export/export_use.py +49 -0
  92. adam/commands/export/export_x_select.py +48 -0
  93. adam/commands/export/exporter.py +361 -0
  94. adam/commands/export/import_files.py +44 -0
  95. adam/commands/export/import_session.py +44 -0
  96. adam/commands/export/importer.py +82 -0
  97. adam/commands/export/importer_athena.py +150 -0
  98. adam/commands/export/importer_sqlite.py +69 -0
  99. adam/commands/export/show_column_counts.py +45 -0
  100. adam/commands/export/show_export_databases.py +39 -0
  101. adam/commands/export/show_export_session.py +39 -0
  102. adam/commands/export/show_export_sessions.py +37 -0
  103. adam/commands/export/utils_export.py +366 -0
  104. adam/commands/find_files.py +51 -0
  105. adam/commands/find_processes.py +76 -0
  106. adam/commands/generate_report.py +52 -0
  107. adam/commands/head.py +36 -0
  108. adam/commands/help.py +12 -8
  109. adam/commands/intermediate_command.py +52 -0
  110. adam/commands/issues.py +14 -40
  111. adam/commands/kubectl.py +38 -0
  112. adam/commands/login.py +26 -25
  113. adam/commands/ls.py +11 -116
  114. adam/commands/medusa/medusa.py +4 -22
  115. adam/commands/medusa/medusa_backup.py +20 -27
  116. adam/commands/medusa/medusa_restore.py +35 -48
  117. adam/commands/medusa/medusa_show_backupjobs.py +17 -18
  118. adam/commands/medusa/medusa_show_restorejobs.py +13 -18
  119. adam/commands/medusa/utils_medusa.py +15 -0
  120. adam/commands/nodetool.py +8 -19
  121. adam/commands/os/__init__.py +0 -0
  122. adam/commands/os/cat.py +36 -0
  123. adam/commands/os/download_file.py +47 -0
  124. adam/commands/os/find_files.py +51 -0
  125. adam/commands/os/find_processes.py +76 -0
  126. adam/commands/os/head.py +36 -0
  127. adam/commands/os/shell.py +41 -0
  128. adam/commands/param_get.py +11 -14
  129. adam/commands/param_set.py +8 -12
  130. adam/commands/postgres/completions_p.py +22 -0
  131. adam/commands/postgres/postgres.py +47 -55
  132. adam/commands/postgres/postgres_databases.py +269 -0
  133. adam/commands/postgres/postgres_ls.py +4 -8
  134. adam/commands/postgres/postgres_preview.py +5 -9
  135. adam/commands/postgres/utils_postgres.py +79 -0
  136. adam/commands/preview_table.py +10 -61
  137. adam/commands/pwd.py +14 -46
  138. adam/commands/reaper/reaper.py +4 -24
  139. adam/commands/reaper/reaper_forward.py +49 -56
  140. adam/commands/reaper/reaper_forward_session.py +6 -0
  141. adam/commands/reaper/reaper_forward_stop.py +10 -16
  142. adam/commands/reaper/reaper_restart.py +7 -14
  143. adam/commands/reaper/reaper_run_abort.py +8 -33
  144. adam/commands/reaper/reaper_runs.py +43 -58
  145. adam/commands/reaper/reaper_runs_abort.py +29 -49
  146. adam/commands/reaper/reaper_schedule_activate.py +14 -33
  147. adam/commands/reaper/reaper_schedule_start.py +9 -33
  148. adam/commands/reaper/reaper_schedule_stop.py +9 -33
  149. adam/commands/reaper/reaper_schedules.py +4 -14
  150. adam/commands/reaper/reaper_status.py +8 -16
  151. adam/commands/reaper/utils_reaper.py +203 -0
  152. adam/commands/repair/repair.py +4 -22
  153. adam/commands/repair/repair_log.py +5 -11
  154. adam/commands/repair/repair_run.py +27 -34
  155. adam/commands/repair/repair_scan.py +32 -40
  156. adam/commands/repair/repair_stop.py +5 -12
  157. adam/commands/restart_cluster.py +47 -0
  158. adam/commands/restart_node.py +51 -0
  159. adam/commands/restart_nodes.py +47 -0
  160. adam/commands/rollout.py +19 -24
  161. adam/commands/shell.py +12 -4
  162. adam/commands/show/show.py +10 -23
  163. adam/commands/show/show_adam.py +3 -3
  164. adam/commands/show/show_cassandra_repairs.py +37 -0
  165. adam/commands/show/show_cassandra_status.py +47 -51
  166. adam/commands/show/show_cassandra_version.py +5 -18
  167. adam/commands/show/show_cli_commands.py +56 -0
  168. adam/commands/show/show_host.py +1 -1
  169. adam/commands/show/show_login.py +23 -27
  170. adam/commands/show/show_params.py +2 -5
  171. adam/commands/show/show_processes.py +18 -21
  172. adam/commands/show/show_storage.py +11 -20
  173. adam/commands/watch.py +26 -29
  174. adam/config.py +5 -15
  175. adam/embedded_params.py +1 -1
  176. adam/log.py +4 -4
  177. adam/repl.py +105 -133
  178. adam/repl_commands.py +68 -28
  179. adam/repl_session.py +9 -1
  180. adam/repl_state.py +300 -62
  181. adam/sql/async_executor.py +44 -0
  182. adam/sql/lark_completer.py +286 -0
  183. adam/sql/lark_parser.py +604 -0
  184. adam/sql/qingl.lark +1076 -0
  185. adam/sql/sql_completer.py +104 -64
  186. adam/sql/sql_state_machine.py +630 -0
  187. adam/sql/term_completer.py +3 -0
  188. adam/sso/authn_ad.py +6 -8
  189. adam/sso/authn_okta.py +4 -6
  190. adam/sso/cred_cache.py +3 -5
  191. adam/sso/idp.py +9 -12
  192. adam/utils.py +640 -10
  193. adam/utils_athena.py +140 -87
  194. adam/utils_audits.py +102 -0
  195. adam/utils_issues.py +32 -0
  196. adam/utils_k8s/app_clusters.py +28 -0
  197. adam/utils_k8s/app_pods.py +35 -0
  198. adam/utils_k8s/cassandra_clusters.py +34 -21
  199. adam/utils_k8s/cassandra_nodes.py +9 -6
  200. adam/utils_k8s/custom_resources.py +16 -17
  201. adam/utils_k8s/ingresses.py +2 -2
  202. adam/utils_k8s/jobs.py +7 -11
  203. adam/utils_k8s/k8s.py +96 -0
  204. adam/utils_k8s/kube_context.py +3 -6
  205. adam/{pod_exec_result.py → utils_k8s/pod_exec_result.py} +11 -5
  206. adam/utils_k8s/pods.py +146 -75
  207. adam/utils_k8s/secrets.py +4 -4
  208. adam/utils_k8s/service_accounts.py +5 -4
  209. adam/utils_k8s/services.py +2 -2
  210. adam/utils_k8s/statefulsets.py +6 -14
  211. adam/utils_local.py +42 -0
  212. adam/utils_net.py +4 -4
  213. adam/utils_repl/__init__.py +0 -0
  214. adam/utils_repl/appendable_completer.py +6 -0
  215. adam/utils_repl/automata_completer.py +48 -0
  216. adam/utils_repl/repl_completer.py +89 -0
  217. adam/utils_repl/state_machine.py +173 -0
  218. adam/utils_sqlite.py +137 -0
  219. adam/version.py +1 -1
  220. {kaqing-2.0.98.dist-info → kaqing-2.0.203.dist-info}/METADATA +1 -1
  221. kaqing-2.0.203.dist-info/RECORD +277 -0
  222. kaqing-2.0.203.dist-info/top_level.txt +2 -0
  223. teddy/__init__.py +0 -0
  224. teddy/lark_parser.py +436 -0
  225. teddy/lark_parser2.py +618 -0
  226. adam/commands/app.py +0 -67
  227. adam/commands/bash.py +0 -92
  228. adam/commands/cp.py +0 -95
  229. adam/commands/cql/cql_completions.py +0 -11
  230. adam/commands/cql/cql_table_completer.py +0 -8
  231. adam/commands/cql/cql_utils.py +0 -115
  232. adam/commands/describe/describe.py +0 -47
  233. adam/commands/describe/describe_keyspace.py +0 -60
  234. adam/commands/describe/describe_keyspaces.py +0 -49
  235. adam/commands/describe/describe_schema.py +0 -49
  236. adam/commands/describe/describe_table.py +0 -60
  237. adam/commands/describe/describe_tables.py +0 -49
  238. adam/commands/devices.py +0 -118
  239. adam/commands/logs.py +0 -39
  240. adam/commands/postgres/postgres_session.py +0 -240
  241. adam/commands/postgres/postgres_utils.py +0 -31
  242. adam/commands/postgres/psql_completions.py +0 -10
  243. adam/commands/postgres/psql_table_completer.py +0 -11
  244. adam/commands/reaper/reaper_session.py +0 -159
  245. adam/commands/report.py +0 -57
  246. adam/commands/show/show_app_actions.py +0 -53
  247. adam/commands/show/show_commands.py +0 -61
  248. adam/commands/show/show_repairs.py +0 -47
  249. adam/sql/state_machine.py +0 -460
  250. kaqing-2.0.98.dist-info/RECORD +0 -191
  251. kaqing-2.0.98.dist-info/top_level.txt +0 -1
  252. /adam/commands/{describe → app}/__init__.py +0 -0
  253. {kaqing-2.0.98.dist-info → kaqing-2.0.203.dist-info}/WHEEL +0 -0
  254. {kaqing-2.0.98.dist-info → kaqing-2.0.203.dist-info}/entry_points.txt +0 -0
@@ -1,16 +1,17 @@
1
+ from functools import partial
1
2
  import threading
2
3
  import time
3
4
 
4
5
  from adam.commands.command import Command
5
- from .reaper_session import ReaperSession
6
+ from adam.commands.reaper.reaper_forward_session import ReaperForwardSession
7
+ from adam.commands.reaper.utils_reaper import Reapers, port_forwarding
6
8
  from adam.config import Config
7
9
  from adam.repl_session import ReplSession
8
10
  from adam.repl_state import ReplState, RequiredState
9
- from adam.utils import lines_to_tabular, log2
11
+ from adam.utils import tabulize, log2
10
12
 
11
13
  class ReaperForward(Command):
12
14
  COMMAND = 'reaper forward'
13
- reaper_login = None
14
15
 
15
16
  # the singleton pattern
16
17
  def __new__(cls, *args, **kwargs):
@@ -31,70 +32,62 @@ class ReaperForward(Command):
31
32
  if not(args := self.args(cmd)):
32
33
  return super().run(cmd, state)
33
34
 
34
- state, args = self.apply_state(args, state)
35
- if not self.validate_state(state):
36
- return state
35
+ with self.validate(args, state) as (args, state):
36
+ if not Reapers.pod_name(state):
37
+ return state
37
38
 
38
- if not(reaper := ReaperSession.create(state)):
39
- return state
39
+ spec = Reapers.reaper_spec(state)
40
+ if state.in_repl:
41
+ if ReaperForwardSession.is_forwarding:
42
+ log2("Another port-forward is already running.")
40
43
 
41
- spec = reaper.reaper_spec(state)
42
- if state.in_repl:
43
- if ReaperSession.is_forwarding:
44
- log2("Another port-forward is already running.")
45
-
46
- return "already-running"
47
-
48
- # make it a daemon to exit with a Ctrl-D
49
- thread = threading.Thread(target=self.loop, args=(state, reaper), daemon=True)
50
- thread.start()
51
-
52
- while not ReaperSession.is_forwarding:
53
- time.sleep(1)
54
-
55
- d = {
56
- 'reaper-ui': spec["web-uri"],
57
- 'reaper-username': spec["username"],
58
- 'reaper-password': spec["password"]
59
- }
60
- log2()
61
- log2(lines_to_tabular([f'{k},{v}' for k, v in d.items()], separator=','))
62
-
63
- for k, v in d.items():
64
- ReplSession().prompt_session.history.append_string(f'cp {k}')
65
- log2()
66
- log2(f'Use <Up> arrow key to copy the values to clipboard.')
67
- else:
68
- try:
69
- log2(f'Click: {spec["web-uri"]}')
70
- log2(f'username: {spec["username"]}')
71
- log2(f'password: {spec["password"]}')
44
+ return "already-running"
45
+
46
+ # make it a daemon to exit with a Ctrl-D
47
+ thread = threading.Thread(target=self.loop, args=(state,), daemon=True)
48
+ thread.start()
49
+
50
+ while not ReaperForwardSession.is_forwarding:
51
+ time.sleep(1)
52
+
53
+ d = {
54
+ 'reaper-ui': spec["web-uri"],
55
+ 'reaper-username': spec["username"],
56
+ 'reaper-password': spec["password"]
57
+ }
72
58
  log2()
73
- log2(f"Press Ctrl+C to break.")
59
+ tabulize(d.items(), lambda a: f'{a[0]},{a[1]}', separator=',')
74
60
 
75
- time.sleep(Config().get('reaper.port-forward.timeout', 3600 * 24))
76
- except KeyboardInterrupt:
77
- pass
61
+ for k, v in d.items():
62
+ ReplSession().prompt_session.history.append_string(f'cp {k}')
63
+ log2()
64
+ log2(f'Use <Up> arrow key to copy the values to clipboard.')
65
+ else:
66
+ try:
67
+ log2(f'Click: {spec["web-uri"]}')
68
+ log2(f'username: {spec["username"]}')
69
+ log2(f'password: {spec["password"]}')
70
+ log2()
71
+ log2(f"Press Ctrl+C to break.")
72
+
73
+ time.sleep(Config().get('reaper.port-forward.timeout', 3600 * 24))
74
+ except KeyboardInterrupt:
75
+ pass
78
76
 
79
- return state
77
+ return state
80
78
 
81
- def loop(self, state: ReplState, reaper: ReaperSession):
82
- def body(uri: str, _: dict[str, str]):
83
- ReaperSession.is_forwarding = True
79
+ def loop(self, state: ReplState):
80
+ with port_forwarding(state, Reapers.local_port(), partial(Reapers.svc_or_pod, state), Reapers.target_port()):
81
+ ReaperForwardSession.is_forwarding = True
84
82
  try:
85
- while not ReaperSession.stopping.is_set():
83
+ while not ReaperForwardSession.stopping.is_set():
86
84
  time.sleep(1)
87
85
  finally:
88
- ReaperSession.stopping.clear()
89
- ReaperSession.is_forwarding = False
90
-
91
- return reaper.port_forwarded(state, 'webui', body)
86
+ ReaperForwardSession.stopping.clear()
87
+ ReaperForwardSession.is_forwarding = False
92
88
 
93
89
  def completion(self, state: ReplState):
94
- if state.sts:
95
- return super().completion(state)
96
-
97
- return {}
90
+ return super().completion(state)
98
91
 
99
92
  def help(self, _: ReplState):
100
93
  return f'{ReaperForward.COMMAND}\t port-forward to reaper'
@@ -0,0 +1,6 @@
1
+ import threading
2
+
3
+ class ReaperForwardSession:
4
+ is_forwarding = False
5
+ stopping = threading.Event()
6
+ schedules_ids_by_cluster: dict[str, list[str]] = {}
@@ -1,11 +1,11 @@
1
1
  from adam.commands.command import Command
2
- from .reaper_session import ReaperSession
2
+ from adam.commands.reaper.reaper_forward_session import ReaperForwardSession
3
+ from adam.commands.reaper.utils_reaper import Reapers
3
4
  from adam.repl_state import ReplState, RequiredState
4
5
  from adam.utils import log2
5
6
 
6
7
  class ReaperForwardStop(Command):
7
8
  COMMAND = 'reaper forward stop'
8
- reaper_login = None
9
9
 
10
10
  # the singleton pattern
11
11
  def __new__(cls, *args, **kwargs):
@@ -26,24 +26,18 @@ class ReaperForwardStop(Command):
26
26
  if not(args := self.args(cmd)):
27
27
  return super().run(cmd, state)
28
28
 
29
- state, args = self.apply_state(args, state)
30
- if not self.validate_state(state):
31
- return state
32
-
33
- if not ReaperSession.create(state):
34
- return state
29
+ with self.validate(args, state) as (args, state):
30
+ if not Reapers.pod_name(state):
31
+ return state
35
32
 
36
- ReaperSession.is_forwarding = False
37
- ReaperSession.stopping.set()
38
- log2("Stopped reaper forward session.")
33
+ ReaperForwardSession.is_forwarding = False
34
+ ReaperForwardSession.stopping.set()
35
+ log2("Stopped reaper forward session.")
39
36
 
40
- return state
37
+ return state
41
38
 
42
39
  def completion(self, state: ReplState):
43
- if state.sts:
44
- return super().completion(state)
45
-
46
- return {}
40
+ return super().completion(state)
47
41
 
48
42
  def help(self, _: ReplState):
49
43
  return f'{ReaperForwardStop.COMMAND}\t stop port-forward to reaper'
@@ -1,11 +1,10 @@
1
1
  from adam.commands.command import Command
2
+ from adam.commands.reaper.utils_reaper import Reapers
2
3
  from adam.utils_k8s.pods import Pods
3
- from .reaper_session import ReaperSession
4
4
  from adam.repl_state import ReplState, RequiredState
5
5
 
6
6
  class ReaperRestart(Command):
7
7
  COMMAND = 'reaper restart'
8
- reaper_login = None
9
8
 
10
9
  # the singleton pattern
11
10
  def __new__(cls, *args, **kwargs):
@@ -26,22 +25,16 @@ class ReaperRestart(Command):
26
25
  if not(args := self.args(cmd)):
27
26
  return super().run(cmd, state)
28
27
 
29
- state, args = self.apply_state(args, state)
30
- if not self.validate_state(state):
31
- return state
32
-
33
- if not(reaper := ReaperSession.create(state)):
34
- return state
28
+ with self.validate(args, state) as (args, state):
29
+ if not (pod := Reapers.pod_name(state)):
30
+ return state
35
31
 
36
- Pods.delete(reaper.pod, state.namespace)
32
+ Pods.delete(pod, state.namespace)
37
33
 
38
- return state
34
+ return state
39
35
 
40
36
  def completion(self, state: ReplState):
41
- if state.sts:
42
- return super().completion(state)
43
-
44
- return {}
37
+ return super().completion(state)
45
38
 
46
39
  def help(self, _: ReplState):
47
40
  return f'{ReaperRestart.COMMAND}\t restart reaper'
@@ -1,13 +1,11 @@
1
- import requests
2
-
1
+ from adam.commands import validate_args
3
2
  from adam.commands.command import Command
4
- from .reaper_session import ReaperSession
3
+ from adam.commands.reaper.utils_reaper import reaper
5
4
  from adam.repl_state import ReplState, RequiredState
6
5
  from adam.utils import log2
7
6
 
8
7
  class ReaperRunAbort(Command):
9
8
  COMMAND = 'reaper abort run'
10
- reaper_login = None
11
9
 
12
10
  # the singleton pattern
13
11
  def __new__(cls, *args, **kwargs):
@@ -28,38 +26,15 @@ class ReaperRunAbort(Command):
28
26
  if not(args := self.args(cmd)):
29
27
  return super().run(cmd, state)
30
28
 
31
- state, args = self.apply_state(args, state)
32
- if not self.validate_state(state):
33
- return state
34
-
35
- if not args:
36
- if state.in_repl:
37
- log2('Specify run id to abort.')
38
- else:
39
- Command.display_help()
40
-
41
- return state
42
-
43
- if not(reaper := ReaperSession.create(state)):
44
- return state
29
+ with self.validate(args, state) as (args, state):
30
+ with validate_args(args, state, name='run id') as run_id:
31
+ with reaper(state) as http:
32
+ http.put(f'repair_run/{run_id}/state/ABORTED')
45
33
 
46
- self.stop_run(state, reaper, args[0])
47
-
48
- return state
49
-
50
- def stop_run(self, state: ReplState, reaper: ReaperSession, run_id: str):
51
- def body(uri: str, headers: dict[str, str]):
52
- return requests.put(uri, headers=headers)
53
-
54
- # PAUSED, RUNNING, ABORTED
55
- # PUT /repair_run/{id}/state/{state}
56
- reaper.port_forwarded(state, f'repair_run/{run_id}/state/ABORTED', body, method='PUT')
34
+ return state
57
35
 
58
36
  def completion(self, state: ReplState):
59
- if state.sts:
60
- return super().completion(state)
61
-
62
- return {}
37
+ return super().completion(state)
63
38
 
64
39
  def help(self, _: ReplState):
65
40
  return f'{ReaperRunAbort.COMMAND} <run-id>\t abort reaper run'
@@ -1,14 +1,11 @@
1
- import requests
2
-
3
1
  from adam.commands.command import Command
4
- from .reaper_session import ReaperSession
2
+ from adam.commands.reaper.utils_reaper import reaper
5
3
  from adam.config import Config
6
4
  from adam.repl_state import ReplState, RequiredState
7
- from adam.utils import convert_seconds, epoch, lines_to_tabular, log, log2
5
+ from adam.utils import convert_seconds, epoch, tabulize, log, log2
8
6
 
9
7
  class ReaperRuns(Command):
10
8
  COMMAND = 'reaper show runs'
11
- reaper_login = None
12
9
 
13
10
  # the singleton pattern
14
11
  def __new__(cls, *args, **kwargs):
@@ -29,63 +26,51 @@ class ReaperRuns(Command):
29
26
  if not(args := self.args(cmd)):
30
27
  return super().run(cmd, state)
31
28
 
32
- state, args = self.apply_state(args, state)
33
- if not self.validate_state(state):
34
- return state
35
-
36
- if not(reaper := ReaperSession.create(state)):
37
- return state
38
-
39
- self.show_runs(state, reaper)
40
-
41
- return state
42
-
43
- def show_runs(self, state: ReplState, reaper: ReaperSession):
44
- def body(uri: str, headers: dict[str, str]):
45
- return requests.get(uri, headers=headers, params={
46
- 'cluster_name': 'all',
47
- 'limit': Config().get('reaper.show-runs-batch', 10)
48
- })
49
-
50
- def line(run):
51
- state = run['state']
52
- start_time = run['start_time']
53
- end_time = run['end_time']
54
- duration = '-'
55
- if state == 'DONE' and end_time:
56
- hours, minutes, seconds = convert_seconds(epoch(end_time) - epoch(start_time))
57
- if hours:
58
- duration = f"{hours:2d}h {minutes:2d}m {seconds:2d}s"
59
- elif minutes:
60
- duration = f"{minutes:2d}m {seconds:2d}s"
29
+ with self.validate(args, state) as (args, state):
30
+ header = 'ID,START,DURATION,STATE,CLUSTER,KEYSPACE,TABLES,REPAIRED'
31
+
32
+ def line(run):
33
+ id = run['id']
34
+ state = run['state']
35
+ start_time = run['start_time']
36
+ end_time = run['end_time']
37
+ duration = '-'
38
+ if state == 'DONE' and end_time:
39
+ hours, minutes, seconds = convert_seconds(epoch(end_time) - epoch(start_time))
40
+ if hours:
41
+ duration = f"{hours:2d}h {minutes:2d}m {seconds:2d}s"
42
+ elif minutes:
43
+ duration = f"{minutes:2d}m {seconds:2d}s"
44
+ else:
45
+ duration = f"{seconds:2d}s"
46
+
47
+ return f"{id},{start_time},{duration},{state},{run['cluster_name']},{run['keyspace_name']},{len(run['column_families'])},{run['segments_repaired']}/{run['total_segments']}"
48
+
49
+ with reaper(state) as http:
50
+ response = http.get('repair_run?state=RUNNING', params={
51
+ 'cluster_name': 'all',
52
+ 'limit': Config().get('reaper.show-runs-batch', 10)
53
+ })
54
+
55
+ runs = response.json()
56
+ if runs:
57
+ tabulize(sorted([line(run) for run in runs], reverse=True), header=header, separator=",")
61
58
  else:
62
- duration = f"{seconds:2d}s"
59
+ log2('No running runs found.')
60
+ log2()
63
61
 
64
- return f"{start_time},{duration},{state},{run['cluster_name']},{run['keyspace_name']},{len(run['column_families'])},{run['segments_repaired']}/{run['total_segments']}"
62
+ response = http.get('repair_run?state=PAUSED,ABORTED,DONE', params={
63
+ 'cluster_name': 'all',
64
+ 'limit': Config().get('reaper.show-runs-batch', 10)
65
+ })
65
66
 
66
- # PAUSED, RUNNING, ABORTED
67
- response = reaper.port_forwarded(state, 'repair_run?state=RUNNING', body, method='GET')
68
- if not response:
69
- return
70
-
71
- header = 'Start,Duration,State,Cluster,Keyspace,Tables,Repaired'
72
-
73
- runs = response.json()
74
- if runs:
75
- log(lines_to_tabular(sorted([line(run) for run in runs], reverse=True), header, separator=","))
76
- else:
77
- log2('No running runs found.')
78
- log2()
79
-
80
- response = reaper.port_forwarded(state, 'repair_run?state=PAUSED,ABORTED,DONE', body, method='GET')
81
- if not response:
82
- return
67
+ runs = response.json()
68
+ if runs:
69
+ tabulize(sorted([line(run) for run in runs], reverse=True), header=header, separator=",")
70
+ else:
71
+ log2('No runs found.')
83
72
 
84
- runs = response.json()
85
- if runs:
86
- log(lines_to_tabular(sorted([line(run) for run in runs], reverse=True), header, separator=","))
87
- else:
88
- log2('No runs found.')
73
+ return state
89
74
 
90
75
  def completion(self, state: ReplState):
91
76
  if state.sts:
@@ -1,14 +1,11 @@
1
- import requests
2
-
3
1
  from adam.commands.command import Command
4
- from .reaper_session import ReaperSession
2
+ from adam.commands.reaper.utils_reaper import reaper
5
3
  from adam.config import Config
6
4
  from adam.repl_state import ReplState, RequiredState
7
5
  from adam.utils import log2
8
6
 
9
7
  class ReaperRunsAbort(Command):
10
8
  COMMAND = 'reaper abort runs'
11
- reaper_login = None
12
9
 
13
10
  # the singleton pattern
14
11
  def __new__(cls, *args, **kwargs):
@@ -29,55 +26,38 @@ class ReaperRunsAbort(Command):
29
26
  if not(args := self.args(cmd)):
30
27
  return super().run(cmd, state)
31
28
 
32
- state, args = self.apply_state(args, state)
33
- if not self.validate_state(state):
34
- return state
29
+ with self.validate(args, state) as (args, state):
30
+ with reaper(state) as http:
31
+ # PAUSED, RUNNING, ABORTED
32
+ aborted = 0
33
+
34
+ while True == True:
35
+ response = http.get('repair_run?state=RUNNING', params={
36
+ 'cluster_name': 'all',
37
+ 'limit': Config().get('reaper.abort-runs-batch', 10)
38
+ })
39
+ if not response:
40
+ break
41
+
42
+ runs = response.json()
43
+ if not runs:
44
+ break
45
+
46
+ for run in runs:
47
+ run_id = run['id']
48
+ # PUT /repair_run/{id}/state/{state}
49
+ http.put(f'repair_run/{run_id}/state/ABORTED')
50
+ aborted += 1
51
+
52
+ if aborted:
53
+ log2(f'Aborted {aborted} runs in total.')
54
+ else:
55
+ log2('No running repair runs found.')
35
56
 
36
- if not(reaper := ReaperSession.create(state)):
37
57
  return state
38
58
 
39
- self.stop_runs(state, reaper)
40
-
41
- return state
42
-
43
- def stop_runs(self, state: ReplState, reaper: ReaperSession):
44
- def body_list(uri: str, headers: dict[str, str]):
45
- return requests.get(uri, headers=headers, params={
46
- 'cluster_name': 'all',
47
- 'limit': Config().get('reaper.abort-runs-batch', 10)
48
- })
49
-
50
- def body_abort(uri: str, headers: dict[str, str]):
51
- return requests.put(uri, headers=headers)
52
-
53
- # PAUSED, RUNNING, ABORTED
54
- aborted = 0
55
- while True == True:
56
- response = reaper.port_forwarded(state, 'repair_run?state=RUNNING', body_list, method='GET')
57
- if not response:
58
- break
59
-
60
- runs = response.json()
61
- if not runs:
62
- break
63
-
64
- for run in runs:
65
- run_id = run['id']
66
- # PUT /repair_run/{id}/state/{state}
67
- reaper.port_forwarded(state, f'repair_run/{run_id}/state/ABORTED', body_abort, method='PUT')
68
- log2(f'Aborted {len(runs)} runs.')
69
- aborted += 1
70
-
71
- if aborted:
72
- log2(f'Aborted {aborted} runs in total.')
73
- else:
74
- log2('No running repair runs found.')
75
-
76
59
  def completion(self, state: ReplState):
77
- if state.sts:
78
- return super().completion(state)
79
-
80
- return {}
60
+ return super().completion(state)
81
61
 
82
62
  def help(self, _: ReplState):
83
63
  return f'{ReaperRunsAbort.COMMAND}\t abort all running reaper runs'
@@ -1,13 +1,15 @@
1
- import requests
2
-
1
+ from adam.commands import validate_args
3
2
  from adam.commands.command import Command
4
- from .reaper_session import ReaperSession
3
+ from adam.commands.reaper.utils_reaper import Reapers, reaper
5
4
  from adam.repl_state import ReplState, RequiredState
6
- from adam.utils import log2
5
+
6
+ import nest_asyncio
7
+ nest_asyncio.apply()
8
+
9
+ import asyncio
7
10
 
8
11
  class ReaperScheduleActivate(Command):
9
12
  COMMAND = 'reaper activate schedule'
10
- reaper_login = None
11
13
 
12
14
  # the singleton pattern
13
15
  def __new__(cls, *args, **kwargs):
@@ -28,37 +30,16 @@ class ReaperScheduleActivate(Command):
28
30
  if not(args := self.args(cmd)):
29
31
  return super().run(cmd, state)
30
32
 
31
- state, args = self.apply_state(args, state)
32
- if not self.validate_state(state):
33
- return state
34
-
35
- if not args:
36
- log2('Specify schedule to activate.')
37
-
38
- return state
39
-
40
- schedule_id = args[0]
41
- if not(reaper := ReaperSession.create(state)):
42
- return state
33
+ with self.validate(args, state) as (args, state):
34
+ with validate_args(args, state, name='schedule') as schedule_id:
35
+ with reaper(state) as http:
36
+ http.put(f'repair_schedule/{schedule_id}?state=ACTIVE')
37
+ Reapers.show_schedule(state, schedule_id)
43
38
 
44
- self.activate_schedule(state, reaper, schedule_id)
45
-
46
- return schedule_id
47
-
48
- def activate_schedule(self, state: ReplState, reaper: ReaperSession, schedule_id: str):
49
- def body(uri: str, headers: dict[str, str]):
50
- return requests.put(uri, headers=headers)
51
-
52
- reaper.port_forwarded(state, f'repair_schedule/{schedule_id}?state=ACTIVE', body, method='PUT')
53
- reaper.show_schedule(state, schedule_id)
39
+ return schedule_id
54
40
 
55
41
  def completion(self, state: ReplState):
56
- if state.sts:
57
- leaf = {id: None for id in ReaperSession.cached_schedule_ids(state)}
58
-
59
- return super().completion(state, leaf)
60
-
61
- return {}
42
+ return super().completion(state, lambda: {id: None for id in Reapers.cached_schedule_ids(state)}, auto_key='reaper.schedules')
62
43
 
63
44
  def help(self, _: ReplState):
64
45
  return f'{ReaperScheduleActivate.COMMAND} <schedule-id>\t resume reaper schedule'
@@ -1,13 +1,10 @@
1
- import requests
2
-
1
+ from adam.commands import validate_args
3
2
  from adam.commands.command import Command
4
- from .reaper_session import ReaperSession
3
+ from adam.commands.reaper.utils_reaper import Reapers, reaper
5
4
  from adam.repl_state import ReplState, RequiredState
6
- from adam.utils import log2
7
5
 
8
6
  class ReaperScheduleStart(Command):
9
7
  COMMAND = 'reaper start schedule'
10
- reaper_login = None
11
8
 
12
9
  # the singleton pattern
13
10
  def __new__(cls, *args, **kwargs):
@@ -28,37 +25,16 @@ class ReaperScheduleStart(Command):
28
25
  if not(args := self.args(cmd)):
29
26
  return super().run(cmd, state)
30
27
 
31
- state, args = self.apply_state(args, state)
32
- if not self.validate_state(state):
33
- return state
34
-
35
- if not args:
36
- log2('Specify schedule to activate.')
37
-
38
- return state
39
-
40
- schedule_id = args[0]
41
- if not(reaper := ReaperSession.create(state)):
42
- return schedule_id
43
-
44
- self.start_schedule(state, reaper, schedule_id)
28
+ with self.validate(args, state) as (args, state):
29
+ with validate_args(args, state, name='schedule') as schedule_id:
30
+ with reaper(state) as http:
31
+ http.post(f'repair_schedule/start/{schedule_id}')
32
+ Reapers.show_schedule(state, schedule_id)
45
33
 
46
- return schedule_id
47
-
48
- def start_schedule(self, state: ReplState, reaper: ReaperSession, schedule_id: str):
49
- def body(uri: str, headers: dict[str, str]):
50
- return requests.post(uri, headers=headers)
51
-
52
- reaper.port_forwarded(state, f'repair_schedule/start/{schedule_id}', body, method='POST')
53
- reaper.show_schedule(state, schedule_id)
34
+ return schedule_id
54
35
 
55
36
  def completion(self, state: ReplState):
56
- if state.sts:
57
- leaf = {id: None for id in ReaperSession.cached_schedule_ids(state)}
58
-
59
- return super().completion(state, leaf)
60
-
61
- return {}
37
+ return super().completion(state, lambda: {id: None for id in Reapers.cached_schedule_ids(state)}, auto_key='reaper.schedules')
62
38
 
63
39
  def help(self, _: ReplState):
64
40
  return f'{ReaperScheduleStart.COMMAND} <schedule-id>\t start reaper runs for schedule'