kaqing 2.0.101__py3-none-any.whl → 2.0.103__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 (45) hide show
  1. adam/batch.py +0 -14
  2. adam/commands/audit/audit.py +2 -7
  3. adam/commands/cd.py +8 -8
  4. adam/commands/commands_utils.py +1 -2
  5. adam/commands/cql/cql_completions.py +4 -4
  6. adam/commands/cql/cql_utils.py +6 -9
  7. adam/commands/cql/cqlsh.py +6 -3
  8. adam/commands/deploy/deploy_pg_agent.py +2 -2
  9. adam/commands/deploy/undeploy_pg_agent.py +2 -2
  10. adam/commands/ls.py +12 -12
  11. adam/commands/nodetool.py +1 -1
  12. adam/commands/postgres/postgres.py +3 -3
  13. adam/commands/postgres/{postgres_session.py → postgres_context.py} +26 -27
  14. adam/commands/postgres/postgres_utils.py +5 -5
  15. adam/commands/postgres/psql_completions.py +1 -1
  16. adam/commands/preview_table.py +8 -27
  17. adam/commands/pwd.py +2 -2
  18. adam/repl.py +5 -5
  19. adam/repl_commands.py +2 -4
  20. adam/repl_state.py +2 -2
  21. adam/sql/automata_completer.py +63 -0
  22. adam/sql/sql_completer.py +37 -73
  23. adam/sql/sql_state_machine.py +434 -0
  24. adam/sql/state_machine.py +52 -421
  25. adam/sql/term_completer.py +3 -0
  26. adam/utils_k8s/cassandra_clusters.py +4 -4
  27. adam/utils_k8s/cassandra_nodes.py +2 -2
  28. adam/utils_k8s/pods.py +12 -6
  29. adam/utils_k8s/statefulsets.py +2 -2
  30. adam/version.py +1 -1
  31. {kaqing-2.0.101.dist-info → kaqing-2.0.103.dist-info}/METADATA +1 -1
  32. {kaqing-2.0.101.dist-info → kaqing-2.0.103.dist-info}/RECORD +35 -43
  33. adam/commands/audit/audit_table_completer.py +0 -9
  34. adam/commands/cql/cql_table_completer.py +0 -8
  35. adam/commands/describe/__init__.py +0 -0
  36. adam/commands/describe/describe.py +0 -61
  37. adam/commands/describe/describe_keyspace.py +0 -58
  38. adam/commands/describe/describe_keyspaces.py +0 -46
  39. adam/commands/describe/describe_schema.py +0 -46
  40. adam/commands/describe/describe_table.py +0 -57
  41. adam/commands/describe/describe_tables.py +0 -46
  42. adam/commands/postgres/psql_table_completer.py +0 -11
  43. {kaqing-2.0.101.dist-info → kaqing-2.0.103.dist-info}/WHEEL +0 -0
  44. {kaqing-2.0.101.dist-info → kaqing-2.0.103.dist-info}/entry_points.txt +0 -0
  45. {kaqing-2.0.101.dist-info → kaqing-2.0.103.dist-info}/top_level.txt +0 -0
adam/batch.py CHANGED
@@ -9,7 +9,6 @@ from adam.commands.command_helpers import ClusterCommandHelper, ClusterOrPodComm
9
9
  from adam.commands.cql.cqlsh import CqlCommandHelper, Cqlsh
10
10
  from adam.commands.deploy.deploy import Deploy, DeployCommandHelper
11
11
  from adam.commands.deploy.undeploy import Undeploy, UndeployCommandHelper
12
- from adam.commands.describe.describe import Describe, DescribeCommandHelper
13
12
  from adam.commands.issues import Issues
14
13
  from adam.commands.login import Login
15
14
  from adam.commands.logs import Logs
@@ -97,19 +96,6 @@ def deploy(kubeconfig: str, config: str, param: list[str], namespace: str, extra
97
96
  run_command(Deploy(), kubeconfig, config, param, None, namespace, None, extra_args)
98
97
 
99
98
 
100
- @cli.command(context_settings=dict(ignore_unknown_options=True, allow_extra_args=True), cls=DescribeCommandHelper, help='Describe keyspace(s) or table(s).')
101
- @click.option('--kubeconfig', '-k', required=False, metavar='path', help='path to kubeconfig file')
102
- @click.option('--config', default='params.yaml', metavar='path', help='path to kaqing parameters file')
103
- @click.option('--param', '-v', multiple=True, metavar='<key>=<value>', help='parameter override')
104
- @click.option('--cluster', '-c', required=False, metavar='statefulset', help='Kubernetes statefulset name')
105
- @click.option('--namespace', '-n', required=False, metavar='namespace', help='Kubernetes namespace')
106
- @click.option('--pod', '-p', required=False, metavar='pod', help='Kubernetes pod name')
107
- @click.option('--all-nodes', '-a', is_flag=True, help='execute on all Cassandra nodes')
108
- @click.argument('extra_args', nargs=-1, metavar='<cluster|pod>', type=click.UNPROCESSED)
109
- def describe(kubeconfig: str, config: str, param: list[str], cluster: str, namespace: str, pod: str, all_nodes: bool, extra_args):
110
- run_command(Describe(), kubeconfig, config, param, cluster, namespace, pod, extra_args + ('&',) if all_nodes else extra_args)
111
-
112
-
113
99
  @cli.command(context_settings=dict(ignore_unknown_options=True, allow_extra_args=True), cls=ClusterOrPodCommandHelper, help="Print Qing's issues.")
114
100
  @click.option('--kubeconfig', '-k', required=False, metavar='path', help='path to kubeconfig file')
115
101
  @click.option('--config', default='params.yaml', metavar='path', help='path to kaqing parameters file')
@@ -54,17 +54,12 @@ class Audit(Command):
54
54
  audit_column_names()
55
55
  audit_column_names(partition_cols_only=True)
56
56
 
57
- # def columns(_):
58
- # return audit_column_names()
59
-
60
- return super().completion(state) | SqlCompleter.completions(
57
+ return super().completion(state) | SqlCompleter(
61
58
  lambda: audit_table_names(),
62
59
  columns=lambda table: audit_column_names(),
63
60
  partition_columns=lambda table: audit_column_names(partition_cols_only=True),
64
61
  variant='athena'
65
- )
66
- # | {
67
- # 'desc': {table: None for table in audit_table_names()}}
62
+ ).completions_for_nesting()
68
63
 
69
64
  return {}
70
65
 
adam/commands/cd.py CHANGED
@@ -1,6 +1,6 @@
1
1
  from adam.commands.command import Command
2
2
  from adam.commands.postgres.postgres_utils import pg_database_names
3
- from adam.commands.postgres.postgres_session import PostgresSession
3
+ from adam.commands.postgres.postgres_context import PostgresContext
4
4
  from adam.utils_k8s.cassandra_clusters import CassandraClusters
5
5
  from adam.utils_k8s.kube_context import KubeContext
6
6
  from adam.utils_k8s.statefulsets import StatefulSets
@@ -36,11 +36,11 @@ class Cd(Command):
36
36
  if dir == '':
37
37
  state.pg_path = None
38
38
  else:
39
- session = PostgresSession(state.namespace, state.pg_path)
39
+ context: PostgresContext = PostgresContext.apply(state.namespace, state.pg_path, arg=dir)
40
40
  # patch up state.namespace from pg cd
41
- if not state.namespace and (ns := session.find_namespace(arg)):
42
- state.namespace = ns
43
- state.pg_path = session.directory(arg)
41
+ if not state.namespace and context.namespace:
42
+ state.namespace = context.namespace
43
+ state.pg_path = context.path()
44
44
  elif state.device == ReplState.A:
45
45
  if dir == '':
46
46
  state.app_env = None
@@ -91,13 +91,13 @@ class Cd(Command):
91
91
 
92
92
  def completion(self, state: ReplState):
93
93
  if state.device == ReplState.P:
94
- pg = PostgresSession(state.namespace, state.pg_path) if state.pg_path else None
94
+ pg: PostgresContext = PostgresContext.apply(state.namespace, state.pg_path) if state.pg_path else None
95
95
  if pg and pg.db:
96
96
  return {Cd.COMMAND: {'..': None}}
97
97
  elif pg and pg.host:
98
- return {Cd.COMMAND: {'..': None} | {p: None for p in pg_database_names(state.namespace, pg.directory())}}
98
+ return {Cd.COMMAND: {'..': None} | {p: None for p in pg_database_names(state.namespace, pg.path())}}
99
99
  else:
100
- return {Cd.COMMAND: {p: None for p in PostgresSession.hosts(state.namespace)}}
100
+ return {Cd.COMMAND: {p: None for p in PostgresContext.hosts(state.namespace)}}
101
101
  elif state.device == ReplState.A:
102
102
  if state.app_app:
103
103
  return {Cd.COMMAND: {'..': None}}
@@ -1,5 +1,4 @@
1
1
  from concurrent.futures import ThreadPoolExecutor
2
- import time
3
2
  from kubernetes import client
4
3
  from typing import List
5
4
 
@@ -10,7 +9,7 @@ from adam.utils_k8s.cassandra_nodes import CassandraNodes
10
9
  from adam.utils_k8s.pods import Pods
11
10
  from adam.utils_k8s.statefulsets import StatefulSets
12
11
  from adam.repl_state import ReplState
13
- from adam.utils import convert_seconds, duration, lines_to_tabular, log, log2
12
+ from adam.utils import duration, lines_to_tabular, log, log2
14
13
 
15
14
  def show_pods(pods: List[client.V1Pod], ns: str, show_namespace = True, show_host_id = True):
16
15
  if len(pods) == 0:
@@ -1,4 +1,4 @@
1
- from adam.commands.cql.cql_utils import table_names
1
+ from adam.commands.cql.cql_utils import cassandra_table_names
2
2
  from adam.config import Config
3
3
  from adam.repl_state import ReplState
4
4
  from adam.sql.sql_completer import SqlCompleter
@@ -8,8 +8,8 @@ def cql_completions(state: ReplState) -> dict[str, any]:
8
8
  return {
9
9
  'describe': {
10
10
  'keyspaces': None,
11
- 'table': {t: None for t in table_names(state)},
11
+ 'table': {t: None for t in cassandra_table_names(state)},
12
12
  'tables': None},
13
- } | SqlCompleter.completions(lambda: table_names(state), table_props=lambda: {
13
+ } | SqlCompleter(lambda: cassandra_table_names(state), table_props=lambda: {
14
14
  'GC_GRACE_SECONDS': ps
15
- }, variant='cql')
15
+ }, variant='cql').completions_for_nesting()
@@ -23,32 +23,29 @@ def keyspaces(state: ReplState, on_any=False):
23
23
 
24
24
  return parse_cql_desc_keyspaces(r.stdout if state.pod else r[0].stdout)
25
25
 
26
- def table_names(state: ReplState):
26
+ def cassandra_table_names(state: ReplState):
27
27
  return [f'{k}.{t}' for k, ts in tables(state, on_any=True).items() for t in ts]
28
28
 
29
29
  @functools.lru_cache()
30
- def tables(state: ReplState, on_any=False):
30
+ def tables(state: ReplState, on_any=False) -> dict[str, list[str]]:
31
31
  r: list[PodExecResult] = run_cql(state, 'describe tables', show_out=False, on_any=on_any)
32
32
  if not r:
33
33
  log2('No pod is available')
34
- return []
34
+ return {}
35
35
 
36
36
  return parse_cql_desc_tables(r.stdout if state.pod else r[0].stdout)
37
37
 
38
- def run_cql(state: ReplState, cql: str, opts: list = [], show_out = False, use_single_quotes = False, on_any = False):
38
+ def run_cql(state: ReplState, cql: str, opts: list = [], show_out = False, use_single_quotes = False, on_any = False, background=False):
39
39
  user, pw = Secrets.get_user_pass(state.sts if state.sts else state.pod, state.namespace, secret_path='cql.secret')
40
40
  if use_single_quotes:
41
41
  command = f"cqlsh -u {user} -p {pw} {' '.join(opts)} -e '{cql}'"
42
42
  else:
43
43
  command = f'cqlsh -u {user} -p {pw} {" ".join(opts)} -e "{cql}"'
44
44
 
45
- if not on_any:
46
- command = f'{command} &'
47
-
48
45
  if state.pod:
49
- return CassandraNodes.exec(state.pod, state.namespace, command, show_out=show_out)
46
+ return CassandraNodes.exec(state.pod, state.namespace, command, show_out=show_out, background=background)
50
47
  else:
51
- return CassandraClusters.exec(state.sts, state.namespace, command, show_out=show_out, action='cql', on_any=on_any)
48
+ return CassandraClusters.exec(state.sts, state.namespace, command, show_out=show_out, action='cql', on_any=on_any, background=background)
52
49
 
53
50
  def parse_cql_desc_tables(out: str):
54
51
  # Keyspace data_endpoint_auth
@@ -3,7 +3,7 @@ import click
3
3
  from adam.commands.command import Command
4
4
  from adam.commands.command_helpers import ClusterOrPodCommandHelper
5
5
  from adam.commands.cql.cql_completions import cql_completions
6
- from .cql_utils import run_cql, table_names
6
+ from .cql_utils import run_cql, cassandra_table_names
7
7
  from adam.repl_state import ReplState, RequiredState
8
8
  from adam.utils import log, log2
9
9
 
@@ -33,11 +33,14 @@ class Cqlsh(Command):
33
33
  if not self.validate_state(state):
34
34
  return state
35
35
 
36
+ background = False
36
37
  opts = []
37
38
  cqls = []
38
- for arg in args:
39
+ for index, arg in enumerate(args):
39
40
  if arg.startswith('--'):
40
41
  opts.append(arg)
42
+ elif index == len(args) -1 and arg == '&':
43
+ background = True
41
44
  elif arg != '-e':
42
45
  cqls.append(arg)
43
46
  if not cqls:
@@ -51,7 +54,7 @@ class Cqlsh(Command):
51
54
  return 'no-cql'
52
55
 
53
56
  cql = ' '.join(cqls)
54
- return run_cql(state, cql, opts, show_out=True)
57
+ return run_cql(state, cql, opts, show_out=True, background=background)
55
58
 
56
59
  def completion(self, state: ReplState) -> dict[str, any]:
57
60
  if state.device != state.C:
@@ -1,5 +1,5 @@
1
1
  from adam.commands.command import Command
2
- from adam.commands.postgres.postgres_session import PostgresSession
2
+ from adam.commands.postgres.postgres_context import PostgresContext
3
3
  from adam.config import Config
4
4
  from adam.repl_state import ReplState, RequiredState
5
5
 
@@ -29,7 +29,7 @@ class DeployPgAgent(Command):
29
29
  if not self.validate_state(state):
30
30
  return state
31
31
 
32
- PostgresSession.deploy_pg_agent(Config().get('pg.agent.name', 'ops-pg-agent'), state.namespace)
32
+ PostgresContext.deploy_pg_agent(Config().get('pg.agent.name', 'ops-pg-agent'), state.namespace)
33
33
 
34
34
  def completion(self, state: ReplState):
35
35
  return super().completion(state)
@@ -1,6 +1,6 @@
1
1
  from adam.commands.command import Command
2
2
  from adam.commands.deploy.deploy_utils import deleting
3
- from adam.commands.postgres.postgres_session import PostgresSession
3
+ from adam.commands.postgres.postgres_context import PostgresContext
4
4
  from adam.config import Config
5
5
  from adam.repl_state import ReplState, RequiredState
6
6
 
@@ -30,7 +30,7 @@ class UndeployPgAgent(Command):
30
30
  if not self.validate_state(state):
31
31
  return state
32
32
 
33
- deleting('pod', lambda: PostgresSession.undeploy_pg_agent(Config().get('pg.agent.name', 'ops-pg-agent'), state.namespace))
33
+ deleting('pod', lambda: PostgresContext.undeploy_pg_agent(Config().get('pg.agent.name', 'ops-pg-agent'), state.namespace))
34
34
 
35
35
  return state
36
36
 
adam/commands/ls.py CHANGED
@@ -4,7 +4,7 @@ from adam.commands.command import Command
4
4
  from adam.commands.commands_utils import show_pods, show_rollout
5
5
  from adam.commands.cql.cqlsh import Cqlsh
6
6
  from adam.commands.postgres.postgres_utils import pg_database_names, pg_table_names
7
- from adam.commands.postgres.postgres_session import PostgresSession
7
+ from adam.commands.postgres.postgres_context import PostgresContext
8
8
  from adam.config import Config
9
9
  from adam.utils_k8s.custom_resources import CustomResources
10
10
  from adam.utils_k8s.ingresses import Ingresses
@@ -45,7 +45,7 @@ class Ls(Command):
45
45
 
46
46
  if state.device == ReplState.P:
47
47
  if state.pg_path:
48
- pg = PostgresSession(state.namespace, state.pg_path)
48
+ pg: PostgresContext = PostgresContext.apply(state.namespace, state.pg_path)
49
49
  if pg.db:
50
50
  self.show_pg_tables(pg)
51
51
  else:
@@ -110,25 +110,25 @@ class Ls(Command):
110
110
 
111
111
  def show_pg_hosts(self, state: ReplState):
112
112
  if state.namespace:
113
- def line(pg: PostgresSession):
114
- return f'{pg.directory()},{pg.endpoint()}:{pg.port()},{pg.username()},{pg.password()}'
113
+ def line(pg: PostgresContext):
114
+ return f'{pg.path()},{pg.endpoint()}:{pg.port()},{pg.username()},{pg.password()}'
115
115
 
116
- lines = [line(PostgresSession(state.namespace, pg)) for pg in PostgresSession.hosts(state.namespace)]
116
+ lines = [line(PostgresContext.apply(state.namespace, pg)) for pg in PostgresContext.hosts(state.namespace)]
117
117
 
118
118
  log(lines_to_tabular(lines, 'NAME,ENDPOINT,USERNAME,PASSWORD', separator=','))
119
119
  else:
120
- def line(pg: PostgresSession):
121
- return f'{pg.directory()},{pg.namespace},{pg.endpoint()}:{pg.port()},{pg.username()},{pg.password()}'
120
+ def line(pg: PostgresContext):
121
+ return f'{pg.path()},{pg.namespace},{pg.endpoint()}:{pg.port()},{pg.username()},{pg.password()}'
122
122
 
123
- lines = [line(PostgresSession(state.namespace, pg)) for pg in PostgresSession.hosts(state.namespace)]
123
+ lines = [line(PostgresContext.apply(state.namespace, pg)) for pg in PostgresContext.hosts(state.namespace)]
124
124
 
125
125
  log(lines_to_tabular(lines, 'NAME,NAMESPACE,ENDPOINT,USERNAME,PASSWORD', separator=','))
126
126
 
127
- def show_pg_databases(self, pg: PostgresSession):
128
- log(lines_to_tabular(pg_database_names(pg.namespace, pg.directory()), 'DATABASE', separator=','))
127
+ def show_pg_databases(self, pg: PostgresContext):
128
+ log(lines_to_tabular(pg_database_names(pg.namespace, pg.path()), 'DATABASE', separator=','))
129
129
 
130
- def show_pg_tables(self, pg: PostgresSession):
131
- log(lines_to_tabular(pg_table_names(pg.namespace, pg.directory()), 'NAME', separator=','))
130
+ def show_pg_tables(self, pg: PostgresContext):
131
+ log(lines_to_tabular(pg_table_names(pg.namespace, pg.path()), 'NAME', separator=','))
132
132
 
133
133
  def show_audit_log_tables(self):
134
134
  log(lines_to_tabular(audit_table_names(), 'NAME', separator=','))
adam/commands/nodetool.py CHANGED
@@ -47,7 +47,7 @@ class NodeTool(Command):
47
47
 
48
48
  def completion(self, state: ReplState):
49
49
  if state.pod or state.sts:
50
- return {NodeTool.COMMAND: {'help': None} | {c: None for c in NODETOOL_COMMANDS}}
50
+ return {NodeTool.COMMAND: {'help': None} | {c: {'&': None} for c in NODETOOL_COMMANDS}}
51
51
 
52
52
  return {}
53
53
 
@@ -5,7 +5,7 @@ from adam.commands.postgres.psql_completions import psql_completions
5
5
  from adam.commands.postgres.postgres_utils import pg_table_names
6
6
  from .postgres_ls import PostgresLs
7
7
  from .postgres_preview import PostgresPreview
8
- from .postgres_session import PostgresSession
8
+ from .postgres_context import PostgresContext
9
9
  from adam.repl_state import ReplState
10
10
  from adam.utils import log, log2
11
11
 
@@ -62,7 +62,7 @@ class Postgres(Command):
62
62
 
63
63
  return state
64
64
 
65
- PostgresSession(state.namespace, state.pg_path).run_sql(' '.join(args))
65
+ PostgresContext.apply(state.namespace, state.pg_path).run_sql(' '.join(args))
66
66
 
67
67
  def completion(self, state: ReplState):
68
68
  if state.device != state.P:
@@ -70,7 +70,7 @@ class Postgres(Command):
70
70
  return {}
71
71
 
72
72
  leaf = {}
73
- session = PostgresSession(state.namespace, state.pg_path)
73
+ session = PostgresContext.apply(state.namespace, state.pg_path)
74
74
  if session.db:
75
75
  if pg_table_names(state.namespace, state.pg_path):
76
76
  leaf = psql_completions(state.namespace, state.pg_path)
@@ -8,7 +8,28 @@ from adam.utils_k8s.pods import Pods
8
8
  from adam.utils_k8s.secrets import Secrets
9
9
  from adam.utils import log2
10
10
 
11
- class PostgresSession:
11
+ class PostgresContext:
12
+ def apply(namespace: str, path: str, arg: str = None) -> 'PostgresContext':
13
+ context = PostgresContext(namespace, path)
14
+
15
+ if arg:
16
+ if arg == '..':
17
+ if context.db:
18
+ context.db = None
19
+ else:
20
+ context.host = None
21
+ else:
22
+ tks = arg.split('@')
23
+ if not context.host:
24
+ context.host = tks[0]
25
+ else:
26
+ context.db = tks[0]
27
+
28
+ if not namespace and tks[1]:
29
+ context.namespace = tks[1]
30
+
31
+ return context
32
+
12
33
  def __init__(self, ns: str, path: str):
13
34
  self.namespace = ns
14
35
  self.conn_details = None
@@ -25,29 +46,7 @@ class PostgresSession:
25
46
  if len(tks) > 1:
26
47
  self.db = tks[1]
27
48
 
28
- def find_namespace(self, arg: str):
29
- if arg:
30
- tks = arg.split('@')
31
- if len(tks) > 1:
32
- return tks[1]
33
-
34
- return None
35
-
36
- def directory(self, arg: str = None):
37
- if arg:
38
- if arg == '..':
39
- if self.db:
40
- self.db = None
41
- else:
42
- self.host = None
43
- else:
44
- tks = arg.split('@')
45
- arg = tks[0]
46
- if not self.host:
47
- self.host = arg
48
- else:
49
- self.db = arg
50
-
49
+ def path(self):
51
50
  if not self.host:
52
51
  return None
53
52
 
@@ -58,7 +57,7 @@ class PostgresSession:
58
57
  return f'{self.host}/{self.db}'
59
58
 
60
59
  def hosts(ns: str):
61
- return PostgresSession.hosts_for_namespace(ns)
60
+ return PostgresContext.hosts_for_namespace(ns)
62
61
 
63
62
  @functools.lru_cache()
64
63
  def hosts_for_namespace(ns: str):
@@ -133,7 +132,7 @@ class PostgresSession:
133
132
  return dbs
134
133
 
135
134
  def run_sql(self, sql: str, show_out = True):
136
- db = self.db if self.db else PostgresSession.default_db()
135
+ db = self.db if self.db else PostgresContext.default_db()
137
136
 
138
137
  if KubeContext.in_cluster():
139
138
  cmd1 = f'env PGPASSWORD={self.password()} psql -h {self.endpoint()} -p {self.port()} -U {self.username()} {db} --pset pager=off -c'
@@ -151,7 +150,7 @@ class PostgresSession:
151
150
  pod_name = Config().get('pg.agent.name', 'ops-pg-agent')
152
151
 
153
152
  if Config().get('pg.agent.just-in-time', False):
154
- if not PostgresSession.deploy_pg_agent(pod_name, ns):
153
+ if not PostgresContext.deploy_pg_agent(pod_name, ns):
155
154
  return
156
155
 
157
156
  real_pod_name = pod_name
@@ -1,6 +1,6 @@
1
1
  import functools
2
2
 
3
- from adam.commands.postgres.postgres_session import PostgresSession
3
+ from adam.commands.postgres.postgres_context import PostgresContext
4
4
  from adam.config import Config
5
5
 
6
6
  TestPG = [False]
@@ -12,8 +12,8 @@ def pg_database_names(ns: str, pg_path: str):
12
12
 
13
13
  Config().wait_log('Inspecting Postgres Databases...')
14
14
 
15
- pg = PostgresSession(ns, pg_path)
16
- return [db['name'] for db in pg.databases() if db['owner'] == PostgresSession.default_owner()]
15
+ pg = PostgresContext.apply(ns, pg_path)
16
+ return [db['name'] for db in pg.databases() if db['owner'] == PostgresContext.default_owner()]
17
17
 
18
18
  @functools.lru_cache()
19
19
  def pg_table_names(ns: str, pg_path: str):
@@ -21,10 +21,10 @@ def pg_table_names(ns: str, pg_path: str):
21
21
  return ['C3_2_XYZ1']
22
22
 
23
23
  Config().wait_log('Inspecting Postgres Database...')
24
- return [table['name'] for table in pg_tables(ns, pg_path) if table['schema'] == PostgresSession.default_schema()]
24
+ return [table['name'] for table in pg_tables(ns, pg_path) if table['schema'] == PostgresContext.default_schema()]
25
25
 
26
26
  def pg_tables(ns: str, pg_path: str):
27
- pg = PostgresSession(ns, pg_path)
27
+ pg = PostgresContext.apply(ns, pg_path)
28
28
  if pg.db:
29
29
  return pg.tables()
30
30
 
@@ -7,4 +7,4 @@ def psql_completions(ns: str, pg_path: str):
7
7
  '\d': None,
8
8
  '\dt': None,
9
9
  '\du': None
10
- } | SqlCompleter.completions(lambda: pg_table_names(ns, pg_path))
10
+ } | SqlCompleter(lambda: pg_table_names(ns, pg_path)).completions_for_nesting()
@@ -1,11 +1,6 @@
1
- import functools
2
-
3
- from adam.commands.audit.audit_table_completer import AuditTableNameCompleter
4
1
  from adam.commands.command import Command
5
- from adam.commands.cql.cql_table_completer import CqlTableNameCompleter
6
- from adam.commands.cql.cql_utils import run_cql, table_names, tables
7
- from adam.commands.postgres.postgres_session import PostgresSession
8
- from adam.commands.postgres.psql_table_completer import PsqlTableNameCompleter
2
+ from adam.commands.cql.cql_utils import cassandra_table_names, run_cql
3
+ from adam.commands.postgres.postgres_context import PostgresContext
9
4
  from adam.config import Config
10
5
  from adam.repl_state import ReplState, RequiredState
11
6
  from adam.utils import lines_to_tabular, log, log2
@@ -44,13 +39,13 @@ class PreviewTable(Command):
44
39
  if not args:
45
40
  def show_tables():
46
41
  if state.device == ReplState.P:
47
- pg = PostgresSession(state.namespace, state.pg_path)
48
- lines = [db["name"] for db in pg.tables() if db["schema"] == PostgresSession.default_schema()]
42
+ pg = PostgresContext.apply(state.namespace, state.pg_path)
43
+ lines = [db["name"] for db in pg.tables() if db["schema"] == PostgresContext.default_schema()]
49
44
  log(lines_to_tabular(lines, separator=','))
50
45
  elif state.device == ReplState.L:
51
46
  log(lines_to_tabular(audit_table_names(), separator=','))
52
47
  else:
53
- run_cql(state, f'describe tables', show_out=True, on_any=True)
48
+ log(lines_to_tabular(cassandra_table_names(state), separator=','))
54
49
 
55
50
  if state.in_repl:
56
51
  log2('Table is required.')
@@ -69,7 +64,7 @@ class PreviewTable(Command):
69
64
 
70
65
  rows = Config().get('preview.rows', 10)
71
66
  if state.device == ReplState.P:
72
- PostgresSession(state.namespace, state.pg_path).run_sql(f'select * from {table} limit {rows}')
67
+ PostgresContext.apply(state.namespace, state.pg_path).run_sql(f'select * from {table} limit {rows}')
73
68
  elif state.device == ReplState.L:
74
69
  run_audit_query(f'select * from {table} limit {rows}')
75
70
  else:
@@ -77,22 +72,8 @@ class PreviewTable(Command):
77
72
 
78
73
  return state
79
74
 
80
- def completion(self, state: ReplState):
81
- if state.device == ReplState.P:
82
- return {PreviewTable.COMMAND: PsqlTableNameCompleter(state.namespace, state.pg_path)}
83
- elif state.device == ReplState.L:
84
- return {PreviewTable.COMMAND: AuditTableNameCompleter()}
85
- elif state.sts:
86
- return {PreviewTable.COMMAND: CqlTableNameCompleter(table_names(state))}
87
-
75
+ def completion(self, _: ReplState):
88
76
  return {}
89
77
 
90
78
  def help(self, _: ReplState):
91
- return f'{PreviewTable.COMMAND} TABLE\t preview table'
92
-
93
- @functools.lru_cache()
94
- def cql_tables(state: ReplState):
95
- if state.pod:
96
- return tables(state)
97
-
98
- return tables(state, on_any=True)
79
+ return f'{PreviewTable.COMMAND} TABLE\t preview table'
adam/commands/pwd.py CHANGED
@@ -1,6 +1,6 @@
1
1
  from adam.app_session import AppSession
2
2
  from adam.commands.command import Command
3
- from adam.commands.postgres.postgres_session import PostgresSession
3
+ from adam.commands.postgres.postgres_context import PostgresContext
4
4
  from adam.repl_state import ReplState
5
5
  from adam.utils import lines_to_tabular, log
6
6
 
@@ -29,7 +29,7 @@ class Pwd(Command):
29
29
  words = []
30
30
 
31
31
  if device == ReplState.P:
32
- pg = PostgresSession(state.namespace, state.pg_path)
32
+ pg: PostgresContext = PostgresContext.apply(state.namespace, state.pg_path)
33
33
 
34
34
  if pg.host:
35
35
  words.append(f'host/{pg.host}')
adam/repl.py CHANGED
@@ -13,7 +13,7 @@ from adam.cli_group import cli
13
13
  from adam.commands.command import Command
14
14
  from adam.commands.command_helpers import ClusterCommandHelper
15
15
  from adam.commands.help import Help
16
- from adam.commands.postgres.postgres_session import PostgresSession
16
+ from adam.commands.postgres.postgres_context import PostgresContext
17
17
  from adam.config import Config
18
18
  from adam.utils_k8s.kube_context import KubeContext
19
19
  from adam.utils_k8s.statefulsets import StatefulSets
@@ -40,7 +40,7 @@ def enter_repl(state: ReplState):
40
40
  msg = ''
41
41
  if state.device == ReplState.P:
42
42
  msg = f'{ReplState.P}:'
43
- pg = PostgresSession(state.namespace, state.pg_path) if state.pg_path else None
43
+ pg: PostgresContext = PostgresContext.apply(state.namespace, state.pg_path) if state.pg_path else None
44
44
  if pg and pg.db:
45
45
  msg += pg.db
46
46
  elif pg and pg.host:
@@ -141,7 +141,7 @@ def enter_repl(state: ReplState):
141
141
  cmd = f'bash {cmd}'
142
142
 
143
143
  if cmd and cmd.strip(' ') and not cmds.run(cmd, state):
144
- try_device_default_action(state, cmds, cmd_list)
144
+ try_device_default_action(state, cmds, cmd_list, cmd)
145
145
  # not served by any command in the chain; try SQL query or C3 action
146
146
  # c_sql_tried = False
147
147
  # if state.device == ReplState.P:
@@ -186,10 +186,10 @@ def enter_repl(state: ReplState):
186
186
  if cmd and (state.device != ReplState.L or Config().get('audit.log-audit-queries', False)):
187
187
  executor.submit(audit_log, cmd, state)
188
188
 
189
- def try_device_default_action(state: ReplState, cmds: Command, cmd_list: list[Command]):
189
+ def try_device_default_action(state: ReplState, cmds: Command, cmd_list: list[Command], cmd: str):
190
190
  c_sql_tried = False
191
191
  if state.device == ReplState.P:
192
- pg = PostgresSession(state.namespace, state.pg_path)
192
+ pg: PostgresContext = PostgresContext.apply(state.namespace, state.pg_path)
193
193
  if pg.db:
194
194
  c_sql_tried = True
195
195
  cmd = f'pg {cmd}'
adam/repl_commands.py CHANGED
@@ -13,7 +13,6 @@ from adam.commands.deploy.undeploy import Undeploy
13
13
  from adam.commands.deploy.undeploy_frontend import UndeployFrontend
14
14
  from adam.commands.deploy.undeploy_pg_agent import UndeployPgAgent
15
15
  from adam.commands.deploy.undeploy_pod import UndeployPod
16
- from adam.commands.describe.describe import Describe
17
16
  from adam.commands.shell import Shell
18
17
  from adam.commands.show.show_app_queues import ShowAppQueues
19
18
  from adam.commands.cp import ClipboardCopy
@@ -58,7 +57,7 @@ class ReplCommands:
58
57
  cmds: list[Command] = ReplCommands.navigation() + ReplCommands.cassandra_check() + ReplCommands.cassandra_ops() + \
59
58
  ReplCommands.tools() + ReplCommands.app() + ReplCommands.exit()
60
59
 
61
- intermediate_cmds: list[Command] = [App(), Reaper(), Repair(), Deploy(), Describe(), Show(), Undeploy()]
60
+ intermediate_cmds: list[Command] = [App(), Reaper(), Repair(), Deploy(), Show(), Undeploy()]
62
61
  ic = [c.command() for c in intermediate_cmds]
63
62
  # 1. dedup commands
64
63
  deduped = []
@@ -79,8 +78,7 @@ class ReplCommands:
79
78
  GetParam(), SetParam(), ShowParams(), ShowKubectlCommands(), ShowLogin(), ShowAdam(), ShowHost()]
80
79
 
81
80
  def cassandra_check() -> list[Command]:
82
- return Describe.cmd_list() + [ShowCassandraStatus(),
83
- ShowCassandraVersion(), ShowRepairs(), ShowStorage(), ShowProcesses(), Check(), Issues(), NodeTool(), Report()]
81
+ return [ShowCassandraStatus(), ShowCassandraVersion(), ShowRepairs(), ShowStorage(), ShowProcesses(), Check(), Issues(), NodeTool(), Report()]
84
82
 
85
83
  def cassandra_ops() -> list[Command]:
86
84
  return [AlterTables()] + Medusa.cmd_list() + [Restart(), RollOut(), Watch()] + Reaper.cmd_list() + Repair.cmd_list()
adam/repl_state.py CHANGED
@@ -2,7 +2,7 @@ import copy
2
2
  from enum import Enum
3
3
  import re
4
4
 
5
- from adam.commands.postgres.postgres_session import PostgresSession
5
+ from adam.commands.postgres.postgres_context import PostgresContext
6
6
  from adam.utils_k8s.cassandra_clusters import CassandraClusters
7
7
  from adam.utils_k8s.cassandra_nodes import CassandraNodes
8
8
  from adam.utils_k8s.kube_context import KubeContext
@@ -210,7 +210,7 @@ class ReplState:
210
210
  return False
211
211
 
212
212
  if pg_required == RequiredState.PG_DATABASE:
213
- pg = PostgresSession(self.namespace, self.pg_path)
213
+ pg: PostgresContext = PostgresContext.apply(self.namespace, self.pg_path)
214
214
  if not pg.db:
215
215
  if self.in_repl:
216
216
  log2('cd to a database first.')