kaqing 2.0.110__py3-none-any.whl → 2.0.184__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 (204) 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 +5 -5
  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 +33 -48
  15. adam/commands/app/__init__.py +0 -0
  16. adam/commands/app/app.py +38 -0
  17. adam/commands/{app_ping.py → app/app_ping.py} +7 -13
  18. adam/commands/app/show_app_actions.py +49 -0
  19. adam/commands/{show → app}/show_app_id.py +8 -11
  20. adam/commands/{show → app}/show_app_queues.py +7 -14
  21. adam/commands/app/utils_app.py +98 -0
  22. adam/commands/audit/audit.py +27 -31
  23. adam/commands/audit/audit_repair_tables.py +14 -18
  24. adam/commands/audit/audit_run.py +16 -23
  25. adam/commands/audit/show_last10.py +4 -17
  26. adam/commands/audit/show_slow10.py +4 -17
  27. adam/commands/audit/show_top10.py +4 -16
  28. adam/commands/audit/utils_show_top10.py +15 -3
  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/cat.py +36 -0
  34. adam/commands/cd.py +11 -95
  35. adam/commands/check.py +15 -24
  36. adam/commands/cli_commands.py +2 -3
  37. adam/commands/clipboard_copy.py +86 -0
  38. adam/commands/code.py +57 -0
  39. adam/commands/command.py +198 -40
  40. adam/commands/commands_utils.py +12 -27
  41. adam/commands/cql/cql_completions.py +27 -10
  42. adam/commands/cql/cqlsh.py +12 -30
  43. adam/commands/cql/utils_cql.py +297 -0
  44. adam/commands/deploy/code_start.py +7 -10
  45. adam/commands/deploy/code_stop.py +4 -21
  46. adam/commands/deploy/code_utils.py +3 -3
  47. adam/commands/deploy/deploy.py +4 -27
  48. adam/commands/deploy/deploy_frontend.py +14 -17
  49. adam/commands/deploy/deploy_pg_agent.py +3 -6
  50. adam/commands/deploy/deploy_pod.py +65 -73
  51. adam/commands/deploy/deploy_utils.py +14 -24
  52. adam/commands/deploy/undeploy.py +4 -27
  53. adam/commands/deploy/undeploy_frontend.py +4 -7
  54. adam/commands/deploy/undeploy_pg_agent.py +6 -8
  55. adam/commands/deploy/undeploy_pod.py +11 -12
  56. adam/commands/devices/__init__.py +0 -0
  57. adam/commands/devices/device.py +123 -0
  58. adam/commands/devices/device_app.py +163 -0
  59. adam/commands/devices/device_auit_log.py +49 -0
  60. adam/commands/devices/device_cass.py +179 -0
  61. adam/commands/devices/device_export.py +84 -0
  62. adam/commands/devices/device_postgres.py +150 -0
  63. adam/commands/devices/devices.py +25 -0
  64. adam/commands/download_file.py +47 -0
  65. adam/commands/exit.py +1 -4
  66. adam/commands/export/__init__.py +0 -0
  67. adam/commands/export/clean_up_all_export_sessions.py +37 -0
  68. adam/commands/export/clean_up_export_sessions.py +39 -0
  69. adam/commands/export/download_export_session.py +39 -0
  70. adam/commands/export/drop_export_database.py +39 -0
  71. adam/commands/export/drop_export_databases.py +37 -0
  72. adam/commands/export/export.py +53 -0
  73. adam/commands/export/export_databases.py +245 -0
  74. adam/commands/export/export_select.py +59 -0
  75. adam/commands/export/export_select_x.py +54 -0
  76. adam/commands/export/export_sessions.py +209 -0
  77. adam/commands/export/export_use.py +49 -0
  78. adam/commands/export/exporter.py +332 -0
  79. adam/commands/export/import_files.py +44 -0
  80. adam/commands/export/import_session.py +44 -0
  81. adam/commands/export/importer.py +81 -0
  82. adam/commands/export/importer_athena.py +177 -0
  83. adam/commands/export/importer_sqlite.py +67 -0
  84. adam/commands/export/show_column_counts.py +45 -0
  85. adam/commands/export/show_export_databases.py +38 -0
  86. adam/commands/export/show_export_session.py +39 -0
  87. adam/commands/export/show_export_sessions.py +37 -0
  88. adam/commands/export/utils_export.py +343 -0
  89. adam/commands/find_files.py +51 -0
  90. adam/commands/find_processes.py +76 -0
  91. adam/commands/head.py +36 -0
  92. adam/commands/help.py +5 -3
  93. adam/commands/intermediate_command.py +49 -0
  94. adam/commands/issues.py +11 -43
  95. adam/commands/kubectl.py +38 -0
  96. adam/commands/login.py +22 -24
  97. adam/commands/logs.py +3 -6
  98. adam/commands/ls.py +11 -116
  99. adam/commands/medusa/medusa.py +4 -22
  100. adam/commands/medusa/medusa_backup.py +20 -27
  101. adam/commands/medusa/medusa_restore.py +38 -37
  102. adam/commands/medusa/medusa_show_backupjobs.py +16 -18
  103. adam/commands/medusa/medusa_show_restorejobs.py +13 -18
  104. adam/commands/nodetool.py +11 -17
  105. adam/commands/param_get.py +11 -14
  106. adam/commands/param_set.py +8 -12
  107. adam/commands/postgres/postgres.py +45 -46
  108. adam/commands/postgres/postgres_databases.py +269 -0
  109. adam/commands/postgres/postgres_ls.py +4 -8
  110. adam/commands/postgres/postgres_preview.py +5 -9
  111. adam/commands/postgres/psql_completions.py +4 -3
  112. adam/commands/postgres/utils_postgres.py +70 -0
  113. adam/commands/preview_table.py +8 -44
  114. adam/commands/pwd.py +14 -46
  115. adam/commands/reaper/reaper.py +4 -27
  116. adam/commands/reaper/reaper_forward.py +49 -56
  117. adam/commands/reaper/reaper_forward_session.py +6 -0
  118. adam/commands/reaper/reaper_forward_stop.py +10 -16
  119. adam/commands/reaper/reaper_restart.py +7 -14
  120. adam/commands/reaper/reaper_run_abort.py +8 -33
  121. adam/commands/reaper/reaper_runs.py +43 -58
  122. adam/commands/reaper/reaper_runs_abort.py +29 -49
  123. adam/commands/reaper/reaper_schedule_activate.py +9 -32
  124. adam/commands/reaper/reaper_schedule_start.py +9 -32
  125. adam/commands/reaper/reaper_schedule_stop.py +9 -32
  126. adam/commands/reaper/reaper_schedules.py +4 -14
  127. adam/commands/reaper/reaper_status.py +8 -16
  128. adam/commands/reaper/utils_reaper.py +194 -0
  129. adam/commands/repair/repair.py +4 -22
  130. adam/commands/repair/repair_log.py +5 -11
  131. adam/commands/repair/repair_run.py +27 -34
  132. adam/commands/repair/repair_scan.py +32 -38
  133. adam/commands/repair/repair_stop.py +5 -11
  134. adam/commands/report.py +27 -29
  135. adam/commands/restart.py +25 -26
  136. adam/commands/rollout.py +19 -24
  137. adam/commands/shell.py +12 -4
  138. adam/commands/show/show.py +10 -25
  139. adam/commands/show/show_adam.py +3 -3
  140. adam/commands/show/show_cassandra_repairs.py +35 -0
  141. adam/commands/show/show_cassandra_status.py +33 -51
  142. adam/commands/show/show_cassandra_version.py +5 -18
  143. adam/commands/show/show_commands.py +20 -25
  144. adam/commands/show/show_host.py +1 -1
  145. adam/commands/show/show_login.py +20 -27
  146. adam/commands/show/show_params.py +2 -5
  147. adam/commands/show/show_processes.py +15 -19
  148. adam/commands/show/show_storage.py +10 -20
  149. adam/commands/watch.py +26 -29
  150. adam/config.py +5 -14
  151. adam/embedded_params.py +1 -1
  152. adam/log.py +4 -4
  153. adam/pod_exec_result.py +6 -3
  154. adam/repl.py +69 -115
  155. adam/repl_commands.py +52 -19
  156. adam/repl_state.py +161 -40
  157. adam/sql/sql_completer.py +52 -27
  158. adam/sql/sql_state_machine.py +131 -19
  159. adam/sso/authn_ad.py +6 -8
  160. adam/sso/authn_okta.py +4 -6
  161. adam/sso/cred_cache.py +3 -5
  162. adam/sso/idp.py +9 -12
  163. adam/utils.py +511 -9
  164. adam/utils_athena.py +145 -0
  165. adam/utils_audits.py +12 -103
  166. adam/utils_issues.py +32 -0
  167. adam/utils_k8s/app_clusters.py +28 -0
  168. adam/utils_k8s/app_pods.py +36 -0
  169. adam/utils_k8s/cassandra_clusters.py +30 -19
  170. adam/utils_k8s/cassandra_nodes.py +3 -3
  171. adam/utils_k8s/custom_resources.py +16 -17
  172. adam/utils_k8s/ingresses.py +2 -2
  173. adam/utils_k8s/jobs.py +7 -11
  174. adam/utils_k8s/k8s.py +87 -0
  175. adam/utils_k8s/kube_context.py +2 -2
  176. adam/utils_k8s/pods.py +89 -78
  177. adam/utils_k8s/secrets.py +4 -4
  178. adam/utils_k8s/service_accounts.py +5 -4
  179. adam/utils_k8s/services.py +2 -2
  180. adam/utils_k8s/statefulsets.py +1 -12
  181. adam/utils_local.py +4 -0
  182. adam/utils_net.py +4 -4
  183. adam/utils_repl/__init__.py +0 -0
  184. adam/utils_repl/automata_completer.py +48 -0
  185. adam/utils_repl/repl_completer.py +46 -0
  186. adam/utils_repl/state_machine.py +173 -0
  187. adam/utils_sqlite.py +137 -0
  188. adam/version.py +1 -1
  189. {kaqing-2.0.110.dist-info → kaqing-2.0.184.dist-info}/METADATA +1 -1
  190. kaqing-2.0.184.dist-info/RECORD +244 -0
  191. adam/commands/app.py +0 -67
  192. adam/commands/bash.py +0 -150
  193. adam/commands/cp.py +0 -95
  194. adam/commands/cql/cql_utils.py +0 -112
  195. adam/commands/devices.py +0 -118
  196. adam/commands/postgres/postgres_context.py +0 -239
  197. adam/commands/postgres/postgres_utils.py +0 -31
  198. adam/commands/reaper/reaper_session.py +0 -159
  199. adam/commands/show/show_app_actions.py +0 -56
  200. adam/commands/show/show_repairs.py +0 -47
  201. kaqing-2.0.110.dist-info/RECORD +0 -187
  202. {kaqing-2.0.110.dist-info → kaqing-2.0.184.dist-info}/WHEEL +0 -0
  203. {kaqing-2.0.110.dist-info → kaqing-2.0.184.dist-info}/entry_points.txt +0 -0
  204. {kaqing-2.0.110.dist-info → kaqing-2.0.184.dist-info}/top_level.txt +0 -0
@@ -1,12 +1,12 @@
1
1
  from adam.commands.command import Command
2
+ from adam.commands.reaper.utils_reaper import Reapers
2
3
  from adam.utils_k8s.jobs import Jobs
3
4
  from adam.utils_k8s.volumes import Volumes
4
5
  from adam.repl_state import ReplState, RequiredState
5
6
  from adam.config import Config
6
- from adam.commands.reaper.reaper_session import ReaperSession
7
7
  from adam.commands.reaper.reaper_runs_abort import ReaperRunsAbort
8
8
  from adam.commands.reaper.reaper_schedule_stop import ReaperScheduleStop
9
- from adam.utils import log2
9
+ from adam.utils import log2, log_exc
10
10
 
11
11
  class RepairRun(Command):
12
12
  COMMAND = 'repair run'
@@ -30,43 +30,36 @@ class RepairRun(Command):
30
30
  if not(args := self.args(cmd)):
31
31
  return super().run(cmd, state)
32
32
 
33
- state, args = self.apply_state(args, state)
34
- if not self.validate_state(state):
35
- return state
36
-
37
- replace = False
38
- if len(args) == 1:
39
- replace = args[0] == 'replace'
33
+ with self.validate(args, state) as (args, state):
34
+ replace = False
35
+ if len(args) == 1:
36
+ replace = args[0] == 'replace'
40
37
 
41
- log2("Stopping all reaper schedules...")
42
- reaper = ReaperSession.create(state)
43
- schedules = reaper.schedule_ids(state)
44
- for schedule_id in schedules:
45
- ReaperScheduleStop().run(f'reaper stop schedule {schedule_id}', state)
46
- log2("Aborting all reaper runs...")
47
- state = ReaperRunsAbort().run('reaper abort runs', state)
38
+ with log_exc():
39
+ log2("Stopping all reaper schedules...")
40
+ for schedule_id in Reapers.cached_schedule_ids(state):
41
+ ReaperScheduleStop().run(f'reaper stop schedule {schedule_id}', state)
42
+ log2("Aborting all reaper runs...")
43
+ state = ReaperRunsAbort().run('reaper abort runs', state)
48
44
 
49
- image = Config().get('repair.image', 'ci-registry.c3iot.io/cloudops/cassrepair:2.0.11')
50
- secret = Config().get('repair.secret', 'ciregistryc3iotio')
51
- log_path = Config().get('repair.log-path', '/home/cassrepair/logs/')
52
- user, _ = state.user_pass()
53
- ns = state.namespace
54
- env = Config().get('repair.env', {})
55
- env["cluster"] = ns
56
- env_from = {"username": user, "password": user}
57
- pvc_name ='cassrepair-log-' + state.sts
58
- Volumes.create_pvc(pvc_name, 30, ns)
59
- if replace:
60
- Jobs.delete('cassrepair-'+state.sts, ns)
61
- Jobs.create('cassrepair-'+state.sts, ns, image, secret, env, env_from, 'cassrepair', pvc_name, log_path)
45
+ image = Config().get('repair.image', 'ci-registry.c3iot.io/cloudops/cassrepair:2.0.11')
46
+ secret = Config().get('repair.secret', 'ciregistryc3iotio')
47
+ log_path = Config().get('repair.log-path', '/home/cassrepair/logs/')
48
+ user, _ = state.user_pass()
49
+ ns = state.namespace
50
+ env = Config().get('repair.env', {})
51
+ env["cluster"] = ns
52
+ env_from = {"username": user, "password": user}
53
+ pvc_name ='cassrepair-log-' + state.sts
54
+ Volumes.create_pvc(pvc_name, 30, ns)
55
+ if replace:
56
+ Jobs.delete('cassrepair-'+state.sts, ns)
57
+ Jobs.create('cassrepair-'+state.sts, ns, image, secret, env, env_from, 'cassrepair', pvc_name, log_path)
62
58
 
63
- return state
59
+ return state
64
60
 
65
61
  def completion(self, state: ReplState):
66
- if state.sts:
67
- return super().completion(state)
68
-
69
- return {}
62
+ return super().completion(state)
70
63
 
71
64
  def help(self, _: ReplState):
72
65
  return f'{RepairRun.COMMAND} [replace]\t start a repair job, default not replacing'
@@ -28,47 +28,41 @@ class RepairScan(Command):
28
28
  if not(args := self.args(cmd)):
29
29
  return super().run(cmd, state)
30
30
 
31
- state, args = self.apply_state(args, state)
32
- if not self.validate_state(state):
33
- return state
34
-
35
- n = "7"
36
- if len(args) == 1:
37
- n = str(args[0])
38
- image = Config().get('repair.image', 'ci-registry.c3iot.io/cloudops/cassrepair:2.0.11')
39
- secret = Config().get('repair.secret', 'ciregistryc3iotio')
40
- log_path = secret = Config().get('repair.log-path', '/home/cassrepair/logs/')
41
- ns = state.namespace
42
- pvc_name ='cassrepair-log-' + state.sts
43
- pod_name = 'repair-scan'
44
-
45
- try:
46
- Pods.create(ns, pod_name, image, ["sh", "-c", "tail -f /dev/null"],
47
- secret=secret,
48
- env={},
49
- volume_name='cassrepair-log',
50
- pvc_name=pvc_name,
51
- mount_path='/home/cassrepair/logs/')
52
- except Exception as e:
53
- if e.status == 409:
54
- log2(f"Pod {pod_name} already exists")
55
- else:
56
- log2("Exception when calling BatchV1Apii->create_namespaced_job: %s\n" % e)
57
-
58
- Pods.wait_for_running(ns, pod_name, 'Waiting for the scanner pod to start up...')
31
+ with self.validate(args, state) as (args, state):
32
+ n = "7"
33
+ if len(args) == 1:
34
+ n = str(args[0])
35
+ image = Config().get('repair.image', 'ci-registry.c3iot.io/cloudops/cassrepair:2.0.11')
36
+ secret = Config().get('repair.secret', 'ciregistryc3iotio')
37
+ log_path = secret = Config().get('repair.log-path', '/home/cassrepair/logs/')
38
+ ns = state.namespace
39
+ pvc_name ='cassrepair-log-' + state.sts
40
+ pod_name = 'repair-scan'
41
+
42
+ try:
43
+ Pods.create(ns, pod_name, image, ["sh", "-c", "tail -f /dev/null"],
44
+ secret=secret,
45
+ env={},
46
+ volume_name='cassrepair-log',
47
+ pvc_name=pvc_name,
48
+ mount_path='/home/cassrepair/logs/')
49
+ except Exception as e:
50
+ if e.status == 409:
51
+ log2(f"Pod {pod_name} already exists")
52
+ else:
53
+ log2("Exception when calling BatchV1Apii->create_namespaced_job: %s\n" % e)
54
+
55
+ Pods.wait_for_running(ns, pod_name, 'Waiting for the scanner pod to start up...')
56
+
57
+ try:
58
+ Pods.exec(pod_name, pod_name, ns, f"find {log_path} -type f -mtime -{n} -print0 | xargs -0 grep failed")
59
+ finally:
60
+ Pods.delete(pod_name, ns)
59
61
 
60
- try:
61
- Pods.exec(pod_name, pod_name, ns, f"find {log_path} -type f -mtime -{n} -print0 | xargs -0 grep failed")
62
- finally:
63
- Pods.delete(pod_name, ns)
64
-
65
- return state
62
+ return state
66
63
 
67
64
  def completion(self, state: ReplState):
68
- if state.sts:
69
- return super().completion(state)
70
-
71
- return {}
65
+ return super().completion(state)
72
66
 
73
67
  def help(self, _: ReplState):
74
68
  return f'{RepairScan.COMMAND} [n]\t scan last n days repair log, default 7 days'
@@ -25,20 +25,14 @@ class RepairStop(Command):
25
25
  if not(args := self.args(cmd)):
26
26
  return super().run(cmd, state)
27
27
 
28
- state, args = self.apply_state(args, state)
29
- if not self.validate_state(state):
30
- return state
31
-
32
- ns = state.namespace
33
- Jobs.delete('cassrepair-'+state.sts, ns)
28
+ with self.validate(args, state) as (args, state):
29
+ ns = state.namespace
30
+ Jobs.delete('cassrepair-'+state.sts, ns)
34
31
 
35
- return state
32
+ return state
36
33
 
37
34
  def completion(self, state: ReplState):
38
- if state.sts:
39
- return super().completion(state)
40
-
41
- return {}
35
+ return super().completion(state)
42
36
 
43
37
  def help(self, _: ReplState):
44
38
  return f'{RepairStop.COMMAND}\t delete a repair job'
adam/commands/report.py CHANGED
@@ -29,35 +29,33 @@ class Report(Command):
29
29
  if not(args := self.args(cmd)):
30
30
  return super().run(cmd, state)
31
31
 
32
- output: dict[str, any] = {}
33
- state, args = self.apply_state(args, state)
34
- if not self.validate_state(state):
35
- return state
36
-
37
- if state.in_repl:
38
- args, show = Command.extract_options(args, ['-s', '--show'])
39
-
40
- args, redirect = Command.extract_options(args, ['>'])
41
- if not redirect or not args:
42
- log2('Please specify file name: e.g. report > /tmp/report.log')
43
- return 'no-report-destination'
44
-
45
- results = run_checks(state.sts, state.namespace, state.pod, show_output=show)
46
- output = CheckResult.report(results)
47
- with open(args[0], "w") as json_file:
48
- json.dump(output, json_file, indent=2)
49
- log2(f'Report stored in {args[0]}.')
50
- else:
51
- args, show = Command.extract_options(args, ['-s', '--show'])
52
-
53
- results = run_checks(state.sts, state.namespace, state.pod, show_output=show)
54
- output = CheckResult.report(results)
55
- click.echo(json.dumps(output, indent=2))
56
-
57
- return output
58
-
59
- def completion(self, _: ReplState):
60
- return {Report.COMMAND: {">": None}}
32
+ with self.validate(args, state) as (args, state):
33
+ output: dict[str, any] = {}
34
+
35
+ if state.in_repl:
36
+ args, show = Command.extract_options(args, ['-s', '--show'])
37
+
38
+ args, redirect = Command.extract_options(args, ['>'])
39
+ if not redirect or not args:
40
+ log2('Please specify file name: e.g. report > /tmp/report.log')
41
+ return 'no-report-destination'
42
+
43
+ results = run_checks(state.sts, state.namespace, state.pod, show_out=show)
44
+ output = CheckResult.report(results)
45
+ with open(args[0], "w") as json_file:
46
+ json.dump(output, json_file, indent=2)
47
+ log2(f'Report stored in {args[0]}.')
48
+ else:
49
+ args, show = Command.extract_options(args, ['-s', '--show'])
50
+
51
+ results = run_checks(state.sts, state.namespace, state.pod, show_out=show)
52
+ output = CheckResult.report(results)
53
+ click.echo(json.dumps(output, indent=2))
54
+
55
+ return output
56
+
57
+ def completion(self, state: ReplState):
58
+ return super().completion(state, {">": None})
61
59
 
62
60
  def help(self, _: ReplState):
63
61
  return f"{Report.COMMAND} > <file-name>\t generate report"
adam/commands/restart.py CHANGED
@@ -1,3 +1,4 @@
1
+ from adam.commands import extract_options
1
2
  from adam.commands.command import Command
2
3
  from adam.utils_k8s.pods import Pods
3
4
  from adam.utils_k8s.statefulsets import StatefulSets
@@ -26,34 +27,32 @@ class Restart(Command):
26
27
  if not(args := self.args(cmd)):
27
28
  return super().run(cmd, state)
28
29
 
29
- state, args = self.apply_state(args, state)
30
- if not self.validate_state(state):
31
- return state
32
-
33
- args, forced = Command.extract_options(args, '--force')
34
- if not args:
35
- if state.pod:
36
- log2(f'Restarting {state.pod}...')
37
- Pods.delete(state.pod, state.namespace)
38
- else:
39
- if not forced:
40
- log2('Please add --force for restarting all nodes in a cluster.')
41
- return 'force-needed'
42
-
43
- log2(f'Restarting all pods from {state.sts}...')
44
- for pod_name in StatefulSets.pod_names(state.sts, state.namespace):
45
- Pods.delete(pod_name, state.namespace)
46
- else:
47
- for arg in args:
48
- Pods.delete(arg, state.namespace)
49
-
50
- return state
30
+ with self.validate(args, state) as (args, state):
31
+ with extract_options(args, '--force') as (args, forced):
32
+ if not args:
33
+ if state.pod:
34
+ log2(f'Restarting {state.pod}...')
35
+ Pods.delete(state.pod, state.namespace)
36
+ else:
37
+ if not forced:
38
+ log2('Please add --force for restarting all nodes in a cluster.')
39
+ return 'force-needed'
40
+
41
+ log2(f'Restarting all pods from {state.sts}...')
42
+ for pod_name in StatefulSets.pod_names(state.sts, state.namespace):
43
+ Pods.delete(pod_name, state.namespace)
44
+ else:
45
+ for arg in args:
46
+ Pods.delete(arg, state.namespace)
47
+
48
+ return state
51
49
 
52
50
  def completion(self, state: ReplState):
53
- if state.pod:
54
- return {Restart.COMMAND: None}
55
- elif state.sts:
56
- return {Restart.COMMAND: {p: None for p in StatefulSets.pod_names(state.sts, state.namespace)}}
51
+ if super().completion(state):
52
+ if state.pod:
53
+ return {Restart.COMMAND: None}
54
+ elif state.sts:
55
+ return {Restart.COMMAND: {p: None for p in StatefulSets.pod_names(state.sts, state.namespace)}}
57
56
 
58
57
  return {}
59
58
 
adam/commands/rollout.py CHANGED
@@ -2,6 +2,7 @@ import datetime
2
2
  from kubernetes import client
3
3
  from kubernetes.client.rest import ApiException
4
4
 
5
+ from adam.commands import extract_options
5
6
  from adam.commands.command import Command
6
7
  from adam.commands.watch import Watch
7
8
  from adam.utils_k8s.statefulsets import StatefulSets
@@ -31,32 +32,28 @@ class RollOut(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
+ with extract_options(args, '--force') as (args, forced):
37
+ restarted, rollingout = StatefulSets.restarted_at(state.sts, state.namespace)
38
+ if rollingout and not forced:
39
+ log2(f"* Cluster is being rolled out for {duration(restarted)}. Please wait until it's done or use --force.")
37
40
 
38
- args, forced = Command.extract_options(args, '--force')
41
+ return state
39
42
 
40
- restarted, rollingout = StatefulSets.restarted_at(state.sts, state.namespace)
41
- if rollingout and not forced:
42
- log2(f"* Cluster is being rolled out for {duration(restarted)}. Please wait until it's done or use --force.")
43
+ self.rolling_restart(state.sts, state.namespace)
43
44
 
44
- return state
45
+ auto_watch = False
46
+ if (auto_watch_cmds := Config().get('watch.auto', 'rollout')):
47
+ cmds = [c.strip(' ') for c in auto_watch_cmds.split(',')]
48
+ if self.command() in cmds:
49
+ auto_watch = True
50
+ log2('Rolling out cluster with auto watch...')
51
+ Watch().run('watch', state)
45
52
 
46
- self.rolling_restart(state.sts, state.namespace)
53
+ if not auto_watch:
54
+ log2('Rolling out cluster...')
47
55
 
48
- auto_watch = False
49
- if (auto_watch_cmds := Config().get('watch.auto', 'rollout')):
50
- cmds = [c.strip(' ') for c in auto_watch_cmds.split(',')]
51
- if self.command() in cmds:
52
- auto_watch = True
53
- log2('Rolling out cluster with auto watch...')
54
- Watch().run('watch', state)
55
-
56
- if not auto_watch:
57
- log2('Rolling out cluster...')
58
-
59
- return state
56
+ return state
60
57
 
61
58
  def rolling_restart(self, statefulset, namespace):
62
59
  # kubectl rollout restart statefulset <statefulset-name>
@@ -82,9 +79,7 @@ class RollOut(Command):
82
79
  log2("Exception when calling AppsV1Api->read_namespaced_statefulset_status: %s\n" % e)
83
80
 
84
81
  def completion(self, state: ReplState):
85
- if state.pod:
86
- return {}
87
- elif state.sts:
82
+ if super().completion(state):
88
83
  return {RollOut.COMMAND: None}
89
84
 
90
85
  return {}
adam/commands/shell.py CHANGED
@@ -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,25 +1,23 @@
1
1
  import click
2
2
 
3
- from adam.commands.audit.show_last10 import ShowLast10
4
- from adam.commands.command import Command
3
+ from adam.commands.app.show_app_actions import ShowAppActions
4
+ from adam.commands.app.show_app_id import ShowAppId
5
+ from adam.commands.app.show_app_queues import ShowAppQueues
6
+ from adam.commands.intermediate_command import IntermediateCommand
5
7
  from adam.commands.medusa.medusa_show_backupjobs import MedusaShowBackupJobs
6
8
  from adam.commands.medusa.medusa_show_restorejobs import MedusaShowRestoreJobs
7
- from adam.commands.show.show_app_actions import ShowAppActions
8
- from adam.commands.show.show_app_queues import ShowAppQueues
9
9
  from adam.commands.show.show_host import ShowHost
10
10
  from adam.commands.show.show_login import ShowLogin
11
11
  from .show_params import ShowParams
12
- from .show_app_id import ShowAppId
13
12
  from .show_cassandra_status import ShowCassandraStatus
14
13
  from .show_cassandra_version import ShowCassandraVersion
15
14
  from .show_commands import ShowKubectlCommands
16
15
  from .show_processes import ShowProcesses
17
- from .show_repairs import ShowRepairs
16
+ from .show_cassandra_repairs import ShowCassandraRepairs
18
17
  from .show_storage import ShowStorage
19
18
  from .show_adam import ShowAdam
20
- from adam.repl_state import ReplState
21
19
 
22
- class Show(Command):
20
+ class Show(IntermediateCommand):
23
21
  COMMAND = 'show'
24
22
 
25
23
  # the singleton pattern
@@ -28,27 +26,14 @@ class Show(Command):
28
26
 
29
27
  return cls.instance
30
28
 
31
- def __init__(self, successor: Command=None):
32
- super().__init__(successor)
33
-
34
29
  def command(self):
35
30
  return Show.COMMAND
36
31
 
37
- def run(self, cmd: str, state: ReplState):
38
- if not(args := self.args(cmd)):
39
- return super().run(cmd, state)
40
-
41
- return super().intermediate_run(cmd, state, args, Show.cmd_list())
42
-
43
- def cmd_list():
32
+ def cmd_list(self):
44
33
  return [ShowAppActions(), ShowAppId(), ShowAppQueues(), ShowHost(), ShowLogin(), ShowKubectlCommands(),
45
- ShowParams(), ShowProcesses(), ShowRepairs(), ShowStorage(), ShowAdam(),
46
- ShowCassandraStatus(), ShowCassandraVersion(), MedusaShowRestoreJobs(), MedusaShowBackupJobs(),
47
- ShowLast10()]
48
-
49
- def completion(self, state: ReplState):
50
- return super().completion(state)
34
+ ShowParams(), ShowProcesses(), ShowCassandraRepairs(), ShowStorage(), ShowAdam(),
35
+ ShowCassandraStatus(), ShowCassandraVersion(), MedusaShowRestoreJobs(), MedusaShowBackupJobs()]
51
36
 
52
37
  class ShowCommandHelper(click.Command):
53
38
  def get_help(self, ctx: click.Context):
54
- Command.intermediate_help(super().get_help(ctx), Show.COMMAND, Show.cmd_list(), show_cluster_help=True)
39
+ IntermediateCommand.intermediate_help(super().get_help(ctx), Show.COMMAND, Show().cmd_list(), show_cluster_help=True)
@@ -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, log2
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
 
@@ -0,0 +1,35 @@
1
+ from adam.commands.command import Command
2
+ from adam.commands.cql.utils_cql import cassandra
3
+ from adam.repl_state import ReplState, RequiredState
4
+
5
+ class ShowCassandraRepairs(Command):
6
+ COMMAND = 'show cassandra repairs'
7
+
8
+ # the singleton pattern
9
+ def __new__(cls, *args, **kwargs):
10
+ if not hasattr(cls, 'instance'): cls.instance = super(ShowCassandraRepairs, cls).__new__(cls)
11
+
12
+ return cls.instance
13
+
14
+ def __init__(self, successor: Command=None):
15
+ super().__init__(successor)
16
+
17
+ def command(self):
18
+ return ShowCassandraRepairs.COMMAND
19
+
20
+ def required(self):
21
+ return RequiredState.CLUSTER_OR_POD
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
+ with cassandra(state) as pods:
29
+ return pods.nodetool('repair_admin list')
30
+
31
+ def completion(self, state: ReplState):
32
+ return super().completion(state)
33
+
34
+ def help(self, _: ReplState):
35
+ return f'{ShowCassandraRepairs.COMMAND}\t show Cassandra repairs'