kaqing 1.98.15__py3-none-any.whl → 2.0.145__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 (180) hide show
  1. adam/app_session.py +1 -1
  2. adam/apps.py +2 -2
  3. adam/batch.py +30 -31
  4. adam/checks/check_utils.py +4 -4
  5. adam/checks/compactionstats.py +1 -1
  6. adam/checks/cpu.py +2 -2
  7. adam/checks/disk.py +1 -1
  8. adam/checks/gossip.py +1 -1
  9. adam/checks/memory.py +3 -3
  10. adam/checks/status.py +1 -1
  11. adam/commands/alter_tables.py +81 -0
  12. adam/commands/app.py +3 -3
  13. adam/commands/app_ping.py +2 -2
  14. adam/commands/audit/audit.py +86 -0
  15. adam/commands/audit/audit_repair_tables.py +77 -0
  16. adam/commands/audit/audit_run.py +58 -0
  17. adam/commands/audit/show_last10.py +51 -0
  18. adam/commands/audit/show_slow10.py +50 -0
  19. adam/commands/audit/show_top10.py +48 -0
  20. adam/commands/audit/utils_show_top10.py +59 -0
  21. adam/commands/bash/bash.py +133 -0
  22. adam/commands/bash/bash_completer.py +93 -0
  23. adam/commands/cat.py +56 -0
  24. adam/commands/cd.py +12 -82
  25. adam/commands/check.py +6 -0
  26. adam/commands/cli_commands.py +3 -3
  27. adam/commands/code.py +60 -0
  28. adam/commands/command.py +48 -12
  29. adam/commands/commands_utils.py +4 -5
  30. adam/commands/cql/cql_completions.py +28 -0
  31. adam/commands/cql/cql_utils.py +209 -0
  32. adam/commands/{cqlsh.py → cql/cqlsh.py} +15 -10
  33. adam/commands/deploy/__init__.py +0 -0
  34. adam/commands/{frontend → deploy}/code_start.py +1 -1
  35. adam/commands/{frontend → deploy}/code_stop.py +1 -1
  36. adam/commands/{frontend → deploy}/code_utils.py +2 -2
  37. adam/commands/deploy/deploy.py +48 -0
  38. adam/commands/deploy/deploy_frontend.py +52 -0
  39. adam/commands/deploy/deploy_pg_agent.py +38 -0
  40. adam/commands/deploy/deploy_pod.py +110 -0
  41. adam/commands/deploy/deploy_utils.py +29 -0
  42. adam/commands/deploy/undeploy.py +48 -0
  43. adam/commands/deploy/undeploy_frontend.py +41 -0
  44. adam/commands/deploy/undeploy_pg_agent.py +42 -0
  45. adam/commands/deploy/undeploy_pod.py +51 -0
  46. adam/commands/devices/__init__.py +0 -0
  47. adam/commands/devices/device.py +27 -0
  48. adam/commands/devices/device_app.py +146 -0
  49. adam/commands/devices/device_auit_log.py +43 -0
  50. adam/commands/devices/device_cass.py +145 -0
  51. adam/commands/devices/device_export.py +86 -0
  52. adam/commands/devices/device_postgres.py +109 -0
  53. adam/commands/devices/devices.py +25 -0
  54. adam/commands/export/__init__.py +0 -0
  55. adam/commands/export/clean_up_export_session.py +53 -0
  56. adam/commands/{frontend/teardown_frontend.py → export/clean_up_export_sessions.py} +9 -11
  57. adam/commands/export/drop_export_database.py +58 -0
  58. adam/commands/export/drop_export_databases.py +46 -0
  59. adam/commands/export/export.py +83 -0
  60. adam/commands/export/export_databases.py +170 -0
  61. adam/commands/export/export_select.py +85 -0
  62. adam/commands/export/export_select_x.py +54 -0
  63. adam/commands/export/export_use.py +55 -0
  64. adam/commands/export/exporter.py +364 -0
  65. adam/commands/export/import_session.py +68 -0
  66. adam/commands/export/importer.py +67 -0
  67. adam/commands/export/importer_athena.py +80 -0
  68. adam/commands/export/importer_sqlite.py +47 -0
  69. adam/commands/export/show_column_counts.py +63 -0
  70. adam/commands/export/show_export_databases.py +39 -0
  71. adam/commands/export/show_export_session.py +51 -0
  72. adam/commands/export/show_export_sessions.py +47 -0
  73. adam/commands/export/utils_export.py +291 -0
  74. adam/commands/help.py +12 -7
  75. adam/commands/issues.py +6 -0
  76. adam/commands/kubectl.py +41 -0
  77. adam/commands/login.py +9 -5
  78. adam/commands/logs.py +2 -1
  79. adam/commands/ls.py +4 -107
  80. adam/commands/medusa/medusa.py +2 -26
  81. adam/commands/medusa/medusa_backup.py +2 -2
  82. adam/commands/medusa/medusa_restore.py +3 -4
  83. adam/commands/medusa/medusa_show_backupjobs.py +4 -3
  84. adam/commands/medusa/medusa_show_restorejobs.py +3 -3
  85. adam/commands/nodetool.py +9 -4
  86. adam/commands/param_set.py +1 -1
  87. adam/commands/postgres/postgres.py +42 -43
  88. adam/commands/postgres/postgres_context.py +248 -0
  89. adam/commands/postgres/postgres_preview.py +0 -1
  90. adam/commands/postgres/postgres_utils.py +31 -0
  91. adam/commands/postgres/psql_completions.py +10 -0
  92. adam/commands/preview_table.py +18 -40
  93. adam/commands/pwd.py +2 -28
  94. adam/commands/reaper/reaper.py +4 -24
  95. adam/commands/reaper/reaper_restart.py +1 -1
  96. adam/commands/reaper/reaper_session.py +2 -2
  97. adam/commands/repair/repair.py +3 -27
  98. adam/commands/repair/repair_log.py +1 -1
  99. adam/commands/repair/repair_run.py +2 -2
  100. adam/commands/repair/repair_scan.py +2 -7
  101. adam/commands/repair/repair_stop.py +1 -1
  102. adam/commands/report.py +6 -0
  103. adam/commands/restart.py +2 -2
  104. adam/commands/rollout.py +1 -1
  105. adam/commands/shell.py +33 -0
  106. adam/commands/show/show.py +11 -26
  107. adam/commands/show/show_app_actions.py +3 -0
  108. adam/commands/show/show_app_id.py +1 -1
  109. adam/commands/show/show_app_queues.py +3 -2
  110. adam/commands/show/show_cassandra_status.py +3 -3
  111. adam/commands/show/show_cassandra_version.py +3 -3
  112. adam/commands/show/show_commands.py +4 -1
  113. adam/commands/show/show_host.py +33 -0
  114. adam/commands/show/show_login.py +3 -0
  115. adam/commands/show/show_processes.py +1 -1
  116. adam/commands/show/show_repairs.py +2 -2
  117. adam/commands/show/show_storage.py +1 -1
  118. adam/commands/watch.py +1 -1
  119. adam/config.py +16 -3
  120. adam/embedded_params.py +1 -1
  121. adam/pod_exec_result.py +10 -2
  122. adam/repl.py +132 -117
  123. adam/repl_commands.py +62 -18
  124. adam/repl_state.py +276 -55
  125. adam/sql/__init__.py +0 -0
  126. adam/sql/sql_completer.py +120 -0
  127. adam/sql/sql_state_machine.py +617 -0
  128. adam/sql/term_completer.py +76 -0
  129. adam/sso/authenticator.py +1 -1
  130. adam/sso/authn_ad.py +36 -56
  131. adam/sso/authn_okta.py +6 -32
  132. adam/sso/cred_cache.py +1 -1
  133. adam/sso/idp.py +74 -9
  134. adam/sso/idp_login.py +2 -2
  135. adam/sso/idp_session.py +10 -7
  136. adam/utils.py +85 -4
  137. adam/utils_athena.py +145 -0
  138. adam/utils_audits.py +102 -0
  139. adam/utils_k8s/__init__.py +0 -0
  140. adam/utils_k8s/app_clusters.py +33 -0
  141. adam/utils_k8s/app_pods.py +31 -0
  142. adam/{k8s_utils → utils_k8s}/cassandra_clusters.py +6 -21
  143. adam/{k8s_utils → utils_k8s}/cassandra_nodes.py +12 -5
  144. adam/utils_k8s/config_maps.py +34 -0
  145. adam/utils_k8s/deployment.py +56 -0
  146. adam/{k8s_utils → utils_k8s}/jobs.py +1 -1
  147. adam/{k8s_utils → utils_k8s}/kube_context.py +1 -1
  148. adam/utils_k8s/pods.py +342 -0
  149. adam/{k8s_utils → utils_k8s}/secrets.py +4 -0
  150. adam/utils_k8s/service_accounts.py +169 -0
  151. adam/{k8s_utils → utils_k8s}/statefulsets.py +5 -4
  152. adam/{k8s_utils → utils_k8s}/volumes.py +9 -0
  153. adam/utils_net.py +24 -0
  154. adam/utils_repl/__init__.py +0 -0
  155. adam/utils_repl/automata_completer.py +48 -0
  156. adam/utils_repl/repl_completer.py +46 -0
  157. adam/utils_repl/state_machine.py +173 -0
  158. adam/utils_sqlite.py +101 -0
  159. adam/version.py +1 -1
  160. {kaqing-1.98.15.dist-info → kaqing-2.0.145.dist-info}/METADATA +1 -1
  161. kaqing-2.0.145.dist-info/RECORD +227 -0
  162. adam/commands/bash.py +0 -87
  163. adam/commands/cql_utils.py +0 -53
  164. adam/commands/devices.py +0 -89
  165. adam/commands/frontend/setup.py +0 -60
  166. adam/commands/frontend/setup_frontend.py +0 -58
  167. adam/commands/frontend/teardown.py +0 -61
  168. adam/commands/postgres/postgres_session.py +0 -225
  169. adam/commands/user_entry.py +0 -77
  170. adam/k8s_utils/pods.py +0 -211
  171. kaqing-1.98.15.dist-info/RECORD +0 -160
  172. /adam/commands/{frontend → audit}/__init__.py +0 -0
  173. /adam/{k8s_utils → commands/bash}/__init__.py +0 -0
  174. /adam/{medusa_show_restorejobs.py → commands/cql/__init__.py} +0 -0
  175. /adam/{k8s_utils → utils_k8s}/custom_resources.py +0 -0
  176. /adam/{k8s_utils → utils_k8s}/ingresses.py +0 -0
  177. /adam/{k8s_utils → utils_k8s}/services.py +0 -0
  178. {kaqing-1.98.15.dist-info → kaqing-2.0.145.dist-info}/WHEEL +0 -0
  179. {kaqing-1.98.15.dist-info → kaqing-2.0.145.dist-info}/entry_points.txt +0 -0
  180. {kaqing-1.98.15.dist-info → kaqing-2.0.145.dist-info}/top_level.txt +0 -0
adam/commands/help.py CHANGED
@@ -23,20 +23,25 @@ class Help(Command):
23
23
  return super().run(cmd, state)
24
24
 
25
25
  def section(cmds : list[ReplCommands]):
26
- return [f' {c.help(state)}' for c in cmds if c.help(state)]
26
+ sorted_cmds = sorted(cmds, key=lambda cmd: cmd.command())
27
+ return [f' {c.help(state)}' for c in sorted_cmds if c.help(state)]
27
28
 
28
29
  lines = []
29
30
  lines.append('NAVIGATION')
30
- lines.append(' a: | c: | p:\t switch to another operational device: App, Cassandra or Postgres')
31
+ lines.append(' a: | c: | l: | p: | x:\t switch to another operational device: App, Cassandra, Audit, Postgres or Export')
31
32
  lines.extend(section(ReplCommands.navigation()))
32
- lines.append('CHECK CASSANDRA')
33
- lines.extend(section(ReplCommands.cassandra_check()))
34
- lines.append('CASSANDRA OPERATIONS')
33
+ lines.append('CASSANDRA')
35
34
  lines.extend(section(ReplCommands.cassandra_ops()))
35
+ lines.append('POSTGRES')
36
+ lines.extend(section(ReplCommands.postgres_ops()))
37
+ lines.append('APP')
38
+ lines.extend(section(ReplCommands.app_ops()))
39
+ lines.append('EXPORT DB')
40
+ lines.extend(section(ReplCommands.export_ops()))
41
+ lines.append('AUDIT')
42
+ lines.extend(section(ReplCommands.audit_ops()))
36
43
  lines.append('TOOLS')
37
44
  lines.extend(section(ReplCommands.tools()))
38
- lines.append('APP')
39
- lines.extend(section(ReplCommands.app()))
40
45
  lines.append('')
41
46
  lines.extend(section(ReplCommands.exit()))
42
47
 
adam/commands/issues.py CHANGED
@@ -21,11 +21,17 @@ class Issues(Command):
21
21
  def command(self):
22
22
  return Issues.COMMAND
23
23
 
24
+ def required(self):
25
+ return ReplState.NON_L
26
+
24
27
  def run(self, cmd: str, state: ReplState):
25
28
  if not(args := self.args(cmd)):
26
29
  return super().run(cmd, state)
27
30
 
28
31
  state, args = self.apply_state(args, state)
32
+ if not self.validate_state(state):
33
+ return state
34
+
29
35
  args, show = Command.extract_options(args, ['-s', '--show'])
30
36
 
31
37
  results = run_checks(state.sts, state.namespace, state.pod, show_output=show)
@@ -0,0 +1,41 @@
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
+ state, args = self.apply_state(args, state)
29
+ if not self.validate_state(state):
30
+ return state
31
+
32
+ subprocess.run(["kubectl"] + args)
33
+
34
+ return state
35
+
36
+ def completion(self, state: ReplState):
37
+ return super().completion(state)
38
+
39
+
40
+ def help(self, _: ReplState):
41
+ return f'{Kubectl.COMMAND} \t run a kubectl command'
adam/commands/login.py CHANGED
@@ -1,3 +1,4 @@
1
+ import os
1
2
  import signal
2
3
  import traceback
3
4
 
@@ -7,7 +8,7 @@ from adam.config import Config
7
8
  from adam.sso.idp import Idp
8
9
  from adam.sso.idp_login import IdpLogin
9
10
  from adam.commands.command import Command
10
- from adam.repl_state import ReplState
11
+ from adam.repl_state import ReplState, RequiredState
11
12
  from adam.utils import log, log2
12
13
 
13
14
  class Login(Command):
@@ -25,6 +26,9 @@ class Login(Command):
25
26
  def command(self):
26
27
  return Login.COMMAND
27
28
 
29
+ def required(self):
30
+ return ReplState.NON_L
31
+
28
32
  def run(self, cmd: str, state: ReplState):
29
33
  def custom_handler(signum, frame):
30
34
  AppSession.ctrl_c_entered = True
@@ -37,9 +41,9 @@ class Login(Command):
37
41
  state, args = self.apply_state(args, state)
38
42
  args, debug = Command.extract_options(args, ['d'])
39
43
  if debug:
40
- Config().set('debug.show-out', True)
44
+ Config().set('debug', True)
41
45
 
42
- username: str = None
46
+ username: str = os.getenv('USERNAME')
43
47
  if len(args) > 0:
44
48
  username = args[0]
45
49
 
@@ -58,8 +62,8 @@ class Login(Command):
58
62
 
59
63
  return state
60
64
 
61
- def completion(self, _: ReplState):
62
- return {}
65
+ def completion(self, state: ReplState):
66
+ return super().completion(state)
63
67
 
64
68
  def help(self, _: ReplState):
65
69
  return f'{Login.COMMAND}\t SSO login'
adam/commands/logs.py CHANGED
@@ -1,6 +1,6 @@
1
1
  from adam.commands.command import Command
2
2
  from adam.config import Config
3
- from adam.k8s_utils.cassandra_nodes import CassandraNodes
3
+ from adam.utils_k8s.cassandra_nodes import CassandraNodes
4
4
  from adam.repl_state import ReplState, RequiredState
5
5
 
6
6
  class Logs(Command):
@@ -33,6 +33,7 @@ class Logs(Command):
33
33
  return CassandraNodes.exec(state.pod, state.namespace, f'cat {path}')
34
34
 
35
35
  def completion(self, _: ReplState):
36
+ # available only on cli
36
37
  return {}
37
38
 
38
39
  def help(self, _: ReplState):
adam/commands/ls.py CHANGED
@@ -1,20 +1,8 @@
1
1
  import copy
2
- import re
3
2
 
4
3
  from adam.commands.command import Command
5
- from adam.commands.commands_utils import show_pods, show_rollout
6
- from adam.commands.cqlsh import Cqlsh
7
- from adam.commands.postgres.postgres_session import PostgresSession
8
- from adam.config import Config
9
- from adam.k8s_utils.custom_resources import CustomResources
10
- from adam.k8s_utils.ingresses import Ingresses
11
- from adam.k8s_utils.kube_context import KubeContext
12
- from adam.k8s_utils.services import Services
13
- from adam.k8s_utils.statefulsets import StatefulSets
14
- from adam.pod_exec_result import PodExecResult
4
+ from adam.commands.devices.devices import Devices
15
5
  from adam.repl_state import ReplState
16
- from adam.utils import lines_to_tabular, log, log2
17
- from adam.apps import Apps
18
6
 
19
7
  class Ls(Command):
20
8
  COMMAND = 'ls'
@@ -43,103 +31,12 @@ class Ls(Command):
43
31
  state = copy.copy(state)
44
32
  state.device = arg.replace(':', '')
45
33
 
46
- if state.device == ReplState.P:
47
- if state.pg_path:
48
- pg = PostgresSession(state.namespace, state.pg_path)
49
- if pg.db:
50
- self.show_pg_tables(pg)
51
- else:
52
- self.show_pg_databases(pg)
53
- else:
54
- self.show_pg_hosts(state)
55
- elif state.device == ReplState.A:
56
- if state.app_env:
57
- def line(n: str, ns: str):
58
- host = Ingresses.get_host(Config().get('app.login.ingress', '{app_id}-k8singr-appleader-001').replace('{app_id}', f'{ns}-{n}'), ns)
59
- if not host:
60
- return None
61
-
62
- endpoint = Config().get('app.login.url', 'https://{host}/{env}/{app}').replace('{host}', host).replace('{env}', state.app_env).replace('{app}', 'c3')
63
- if not endpoint:
64
- return None
65
-
66
- return f"{n.split('-')[1]},{Ingresses.get_host(f'{ns}-{n}-k8singr-appleader-001', ns)},{endpoint}"
67
-
68
- svcs = [l for l in [line(n, ns) for n, ns in Apps.apps(state.app_env)] if l]
69
-
70
- log(lines_to_tabular(svcs, 'APP,HOST,ENDPOINT', separator=','))
71
- else:
72
- svcs = [n for n, ns in Apps.envs()]
73
-
74
- log(lines_to_tabular(svcs, 'ENV', separator=','))
75
- else:
76
- if state.pod:
77
- r: PodExecResult = Cqlsh().run(f'cql describe tables', state)
78
- if r.stderr:
79
- log(r.stderr)
80
- log(r.stdout)
81
- elif state.sts and state.namespace:
82
- show_pods(StatefulSets.pods(state.sts, state.namespace), state.namespace, show_namespace=not KubeContext.in_cluster_namespace())
83
- show_rollout(state.sts, state.namespace)
84
- else:
85
- self.show_statefulsets()
34
+ Devices.device(state).ls(cmd, state)
86
35
 
87
36
  return state
88
37
 
89
- def show_statefulsets(self):
90
- ss = StatefulSets.list_sts_names(show_namespace=not KubeContext.in_cluster_namespace())
91
- if len(ss) == 0:
92
- log2('No cassandra statefulsets found.')
93
- return
94
-
95
- app_ids = CustomResources.get_app_ids()
96
- list = []
97
- for s in ss:
98
- cr_name = CustomResources.get_cr_name(s)
99
- app_id = 'Unknown'
100
- if cr_name in app_ids:
101
- app_id = app_ids[cr_name]
102
- list.append(f"{s} {app_id}")
103
-
104
- header = 'STATEFULSET_NAME@NAMESPACE APP_ID'
105
- if KubeContext.in_cluster_namespace():
106
- header = 'STATEFULSET_NAME APP_ID'
107
- log(lines_to_tabular(list, header))
108
-
109
- def show_pg_hosts(self, state: ReplState):
110
- if state.namespace:
111
- def line(pg: PostgresSession):
112
- return f'{pg.directory()},{pg.endpoint()}:{pg.port()},{pg.username()},{pg.password()}'
113
-
114
- lines = [line(PostgresSession(state.namespace, pg)) for pg in PostgresSession.hosts(state.namespace)]
115
-
116
- log(lines_to_tabular(lines, 'NAME,ENDPOINT,USERNAME,PASSWORD', separator=','))
117
- else:
118
- def line(pg: PostgresSession):
119
- return f'{pg.directory()},{pg.namespace},{pg.endpoint()}:{pg.port()},{pg.username()},{pg.password()}'
120
-
121
- lines = [line(PostgresSession(state.namespace, pg)) for pg in PostgresSession.hosts(state.namespace)]
122
-
123
- log(lines_to_tabular(lines, 'NAME,NAMESPACE,ENDPOINT,USERNAME,PASSWORD', separator=','))
124
-
125
- def show_pg_databases(self, pg: PostgresSession):
126
- lines = [db["name"] for db in pg.databases() if db["owner"] == PostgresSession.default_owner()]
127
-
128
- log(lines_to_tabular(lines, 'DATABASE', separator=','))
129
-
130
- def show_pg_tables(self, pg: PostgresSession):
131
- lines = [db["name"] for db in pg.tables() if db["schema"] == PostgresSession.default_schema()]
132
-
133
- log(lines_to_tabular(lines, 'NAME', separator=','))
134
-
135
38
  def completion(self, state: ReplState):
136
- if state.pod:
137
- return {}
138
-
139
- if not state.sts:
140
- return {Ls.COMMAND: {n: None for n in StatefulSets.list_sts_names()}}
141
-
142
- return {Ls.COMMAND: None}
39
+ return Devices.device(state).ls_completion(Ls.COMMAND, state, default = super().completion(state))
143
40
 
144
41
  def help(self, _: ReplState):
145
- return f'{Ls.COMMAND} [device:]\t list apps, envs, clusters, nodes, pg hosts or pg databases'
42
+ return f'{Ls.COMMAND} [device:]\t list apps, envs, clusters, nodes, pg hosts/databases or export databases'
@@ -1,13 +1,11 @@
1
1
  import click
2
2
 
3
3
  from adam.commands.command import Command
4
- from adam.commands.command_helpers import ClusterCommandHelper
5
4
  from .medusa_backup import MedusaBackup
6
5
  from .medusa_restore import MedusaRestore
7
6
  from .medusa_show_backupjobs import MedusaShowBackupJobs
8
7
  from .medusa_show_restorejobs import MedusaShowRestoreJobs
9
8
  from adam.repl_state import ReplState, RequiredState
10
- from adam.utils import lines_to_tabular, log, log2
11
9
 
12
10
  class Medusa(Command):
13
11
  COMMAND = 'medusa'
@@ -31,20 +29,7 @@ class Medusa(Command):
31
29
  if not(args := self.args(cmd)):
32
30
  return super().run(cmd, state)
33
31
 
34
- state, args = self.apply_state(args, state)
35
- if not self.validate_state(state):
36
- return state
37
-
38
- if state.in_repl:
39
- log(lines_to_tabular([c.help(ReplState()) for c in Medusa.cmd_list()], separator=':'))
40
-
41
- return 'command-missing'
42
- else:
43
- # head with the Chain of Responsibility pattern
44
- cmds = Command.chain(Medusa.cmd_list())
45
- if not cmds.run(cmd, state):
46
- log2('* Command is missing.')
47
- Command.display_help()
32
+ return super().intermediate_run(cmd, state, args, Medusa.cmd_list())
48
33
 
49
34
  def cmd_list():
50
35
  return [MedusaBackup(), MedusaRestore(), MedusaShowBackupJobs(), MedusaShowRestoreJobs()]
@@ -55,15 +40,6 @@ class Medusa(Command):
55
40
 
56
41
  return {}
57
42
 
58
- def help(self, _: ReplState):
59
- return None
60
-
61
43
  class MedusaCommandHelper(click.Command):
62
44
  def get_help(self, ctx: click.Context):
63
- log(super().get_help(ctx))
64
- log()
65
- log('Sub-Commands:')
66
-
67
- log(lines_to_tabular([c.help(ReplState()).replace(f'{Medusa.COMMAND} ', ' ', 1) for c in Medusa.cmd_list()], separator=':'))
68
- log()
69
- ClusterCommandHelper.cluster_help()
45
+ Command.intermediate_help(super().get_help(ctx), Medusa.COMMAND, Medusa.cmd_list(), show_cluster_help=True)
@@ -2,9 +2,9 @@ from datetime import datetime
2
2
  import re
3
3
 
4
4
  from adam.commands.command import Command
5
- from adam.k8s_utils.statefulsets import StatefulSets
5
+ from adam.utils_k8s.statefulsets import StatefulSets
6
6
  from adam.repl_state import ReplState, RequiredState
7
- from adam.k8s_utils.custom_resources import CustomResources
7
+ from adam.utils_k8s.custom_resources import CustomResources
8
8
  from adam.utils import log2
9
9
 
10
10
 
@@ -1,9 +1,9 @@
1
1
  from datetime import datetime
2
2
 
3
3
  from adam.commands.command import Command
4
- from adam.k8s_utils.statefulsets import StatefulSets
4
+ from adam.utils_k8s.statefulsets import StatefulSets
5
5
  from adam.repl_state import ReplState, RequiredState
6
- from adam.k8s_utils.custom_resources import CustomResources
6
+ from adam.utils_k8s.custom_resources import CustomResources
7
7
  from adam.config import Config
8
8
  from adam.utils import lines_to_tabular, log2
9
9
 
@@ -59,8 +59,7 @@ class MedusaRestore(Command):
59
59
  now_dtformat = datetime.now().strftime("%Y-%m-%d.%H.%M.%S")
60
60
  rtname = 'medusa-' + now_dtformat + '-restore-from-' + bkname
61
61
  try:
62
- print('SEAN doing')
63
- # CustomResources.create_medusa_restorejob(rtname, bkname, dc, ns)
62
+ CustomResources.create_medusa_restorejob(rtname, bkname, dc, ns)
64
63
  except Exception as e:
65
64
  log2("Exception: MedusaRestore failed: %s\n" % e)
66
65
 
@@ -1,7 +1,7 @@
1
1
  from adam.commands.command import Command
2
- from adam.k8s_utils.statefulsets import StatefulSets
2
+ from adam.utils_k8s.statefulsets import StatefulSets
3
3
  from adam.repl_state import ReplState, RequiredState
4
- from adam.k8s_utils.custom_resources import CustomResources
4
+ from adam.utils_k8s.custom_resources import CustomResources
5
5
  from adam.utils import lines_to_tabular, log2
6
6
 
7
7
 
@@ -29,6 +29,7 @@ class MedusaShowBackupJobs(Command):
29
29
  state, args = self.apply_state(args, state)
30
30
  if not self.validate_state(state):
31
31
  return state
32
+
32
33
  ns = state.namespace
33
34
  dc = StatefulSets.get_datacenter(state.sts, ns)
34
35
  if not dc:
@@ -49,4 +50,4 @@ class MedusaShowBackupJobs(Command):
49
50
  return {}
50
51
 
51
52
  def help(self, _: ReplState):
52
- return f'{MedusaShowBackupJobs.COMMAND}\t start a restore job'
53
+ return f'{MedusaShowBackupJobs.COMMAND}\t show Medusa backups'
@@ -1,7 +1,7 @@
1
1
  from adam.commands.command import Command
2
- from adam.k8s_utils.statefulsets import StatefulSets
2
+ from adam.utils_k8s.statefulsets import StatefulSets
3
3
  from adam.repl_state import ReplState, RequiredState
4
- from adam.k8s_utils.custom_resources import CustomResources
4
+ from adam.utils_k8s.custom_resources import CustomResources
5
5
  from adam.utils import lines_to_tabular, log2
6
6
 
7
7
  class MedusaShowRestoreJobs(Command):
@@ -49,4 +49,4 @@ class MedusaShowRestoreJobs(Command):
49
49
  return {}
50
50
 
51
51
  def help(self, _: ReplState):
52
- return f'{MedusaShowRestoreJobs.COMMAND}\t start a restore job'
52
+ return f'{MedusaShowRestoreJobs.COMMAND}\t show Medusa restores'
adam/commands/nodetool.py CHANGED
@@ -4,10 +4,11 @@ from adam.commands.command import Command
4
4
  from adam.commands.command_helpers import ClusterOrPodCommandHelper
5
5
  from adam.commands.nodetool_commands import NODETOOL_COMMANDS
6
6
  from adam.config import Config
7
- from adam.k8s_utils.cassandra_clusters import CassandraClusters
8
- from adam.k8s_utils.cassandra_nodes import CassandraNodes
7
+ from adam.utils_k8s.cassandra_clusters import CassandraClusters
8
+ from adam.utils_k8s.cassandra_nodes import CassandraNodes
9
9
  from adam.repl_state import ReplState, RequiredState
10
10
  from adam.utils import log
11
+ from adam.utils_k8s.statefulsets import StatefulSets
11
12
 
12
13
  class NodeTool(Command):
13
14
  COMMAND = 'nodetool'
@@ -43,14 +44,18 @@ class NodeTool(Command):
43
44
  elif state.sts:
44
45
  return CassandraClusters.exec(state.sts, state.namespace, command, action='nodetool', show_out=True)
45
46
 
47
+ return state
48
+
46
49
  def completion(self, state: ReplState):
47
50
  if state.pod or state.sts:
48
- return {NodeTool.COMMAND: {'help': None} | {c: None for c in NODETOOL_COMMANDS}}
51
+ d = {c: {'&': None} for c in NODETOOL_COMMANDS}
52
+ return {NodeTool.COMMAND: {'help': None} | d} | \
53
+ {f'@{p}': {NodeTool.COMMAND: d} for p in StatefulSets.pod_names(state.sts, state.namespace)}
49
54
 
50
55
  return {}
51
56
 
52
57
  def help(self, _: ReplState):
53
- return f'{NodeTool.COMMAND} <sub-command>\t run nodetool with arguments'
58
+ return f'{NodeTool.COMMAND} <sub-command> [&]\t run nodetool with arguments'
54
59
 
55
60
  class NodeToolCommandHelper(click.Command):
56
61
  def get_help(self, ctx: click.Context):
@@ -38,7 +38,7 @@ class SetParam(Command):
38
38
  return value
39
39
 
40
40
  def completion(self, _: ReplState):
41
- return {SetParam.COMMAND: {key: None for key in Config().keys()}}
41
+ return {SetParam.COMMAND: {key: ({'true': None, 'false': None} if Config().get(key, None) in [True, False] else None) for key in Config().keys()}}
42
42
 
43
43
  def help(self, _: ReplState):
44
44
  return f"{SetParam.COMMAND} <key> <value>\t sets a Kaqing parameter to a different value"
@@ -1,12 +1,13 @@
1
1
  import click
2
2
 
3
3
  from adam.commands.command import Command
4
- from adam.commands.command_helpers import ClusterCommandHelper
4
+ from adam.commands.postgres.psql_completions import psql_completions
5
+ from adam.commands.postgres.postgres_utils import pg_table_names
5
6
  from .postgres_ls import PostgresLs
6
7
  from .postgres_preview import PostgresPreview
7
- from .postgres_session import PostgresSession
8
+ from .postgres_context import PostgresContext
8
9
  from adam.repl_state import ReplState
9
- from adam.utils import lines_to_tabular, log, log2
10
+ from adam.utils import log, log2
10
11
 
11
12
  class Postgres(Command):
12
13
  COMMAND = 'pg'
@@ -30,35 +31,27 @@ class Postgres(Command):
30
31
 
31
32
  state, args = self.apply_state(args, state)
32
33
 
33
- if state.in_repl:
34
- if not args:
34
+ if not args:
35
+ if state.in_repl:
35
36
  log2('Please use SQL statement. e.g. pg \l')
36
-
37
- return 'command-missing'
38
37
  else:
39
- self.run_sql(state, args)
40
- else:
41
- if not args:
42
38
  log2('* Command or SQL statements is missing.')
43
39
  Command.display_help()
44
40
 
45
- return 'command-missing'
46
- else:
47
- # head with the Chain of Responsibility pattern
48
- cmds = Command.chain(Postgres.cmd_list())
49
- if not cmds.run(cmd, state) :
50
- if not args:
51
- log2('* Command or SQL statements is missing.')
52
- Command.display_help()
41
+ return 'command-missing'
53
42
 
54
- return 'command-missing'
55
- else:
56
- self.run_sql(state, args)
43
+ if state.in_repl:
44
+ self.run_sql(state, args)
45
+ else:
46
+ # head with the Chain of Responsibility pattern
47
+ cmds = Command.chain(Postgres.cmd_list())
48
+ if not cmds.run(cmd, state) :
49
+ self.run_sql(state, args)
57
50
 
58
51
  return state
59
52
 
60
53
  def cmd_list():
61
- return [PostgresLs(), PostgresPreview()]
54
+ return [PostgresLs(), PostgresPreview(), PostgresPg()]
62
55
 
63
56
  def run_sql(self, state: ReplState, args: list[str]):
64
57
  if not state.pg_path:
@@ -69,21 +62,23 @@ class Postgres(Command):
69
62
 
70
63
  return state
71
64
 
72
- PostgresSession(state.namespace, state.pg_path).run_sql(' '.join(args))
65
+ background = False
66
+ if args and args[-1] == '&':
67
+ args = args[:-1]
68
+ background = True
69
+
70
+ PostgresContext.apply(state.namespace, state.pg_path).run_sql(' '.join(args), background=background)
73
71
 
74
72
  def completion(self, state: ReplState):
73
+ if state.device != state.P:
74
+ # conflicts with cql completions
75
+ return {}
76
+
75
77
  leaf = {}
76
- if PostgresSession(state.namespace, state.pg_path).db:
77
- leaf = {
78
- '\h': None,
79
- '\d': None,
80
- '\dt': None,
81
- '\du': None,
82
- 'delete': {'from': None},
83
- 'insert': {'into': None},
84
- 'select': None,
85
- 'update': None,
86
- }
78
+ session = PostgresContext.apply(state.namespace, state.pg_path)
79
+ if session.db:
80
+ if pg_table_names(state.namespace, state.pg_path):
81
+ leaf = psql_completions(state.namespace, state.pg_path)
87
82
  elif state.pg_path:
88
83
  leaf = {
89
84
  '\h': None,
@@ -96,18 +91,22 @@ class Postgres(Command):
96
91
  return {}
97
92
 
98
93
  def help(self, _: ReplState):
99
- return f'[{Postgres.COMMAND}] <sql-statements>\t run psql with queries'
94
+ return f'<sql-statements> [&]\t run queries on Postgres databases'
100
95
 
101
96
  class PostgresCommandHelper(click.Command):
102
97
  def get_help(self, ctx: click.Context):
103
- log(super().get_help(ctx))
104
- log()
105
- log('Sub-Commands:')
106
-
107
- log(lines_to_tabular([c.help(ReplState()).replace(f'{Postgres.COMMAND} ', ' ', 1) for c in Postgres.cmd_list()], separator='\t'))
108
- log()
109
- ClusterCommandHelper.cluster_help()
98
+ Command.intermediate_help(super().get_help(ctx), Postgres.COMMAND, Postgres.cmd_list(), show_cluster_help=True)
110
99
  log('PG-Name: Kubernetes secret for Postgres credentials')
111
100
  log(' e.g. stgawsscpsr-c3-c3-k8spg-cs-001')
112
101
  log('Database: Postgres database name within a host')
113
- log(' e.g. stgawsscpsr_c3_c3')
102
+ log(' e.g. stgawsscpsr_c3_c3')
103
+
104
+ # No action body, only for a help entry and auto-completion
105
+ class PostgresPg(Command):
106
+ COMMAND = 'pg'
107
+
108
+ def command(self):
109
+ return PostgresPg.COMMAND
110
+
111
+ def help(self, _: ReplState):
112
+ return f'pg <sql-statements>\t run queries on Postgres databases'