kaqing 2.0.93__py3-none-any.whl → 2.0.115__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 (134) hide show
  1. adam/apps.py +2 -2
  2. adam/batch.py +2 -16
  3. adam/checks/check_utils.py +4 -4
  4. adam/checks/compactionstats.py +1 -1
  5. adam/checks/cpu.py +2 -2
  6. adam/checks/disk.py +1 -1
  7. adam/checks/gossip.py +1 -1
  8. adam/checks/memory.py +3 -3
  9. adam/checks/status.py +1 -1
  10. adam/commands/alter_tables.py +3 -14
  11. adam/commands/app.py +3 -3
  12. adam/commands/app_ping.py +2 -2
  13. adam/commands/audit/audit.py +26 -11
  14. adam/commands/audit/audit_repair_tables.py +39 -4
  15. adam/commands/audit/audit_run.py +58 -0
  16. adam/commands/audit/show_last10.py +51 -0
  17. adam/commands/audit/show_slow10.py +50 -0
  18. adam/commands/audit/show_top10.py +49 -0
  19. adam/commands/audit/utils_show_top10.py +59 -0
  20. adam/commands/bash/bash.py +124 -0
  21. adam/commands/bash/bash_completer.py +93 -0
  22. adam/commands/cat.py +55 -0
  23. adam/commands/cd.py +26 -14
  24. adam/commands/check.py +6 -0
  25. adam/commands/cli_commands.py +3 -3
  26. adam/commands/code.py +60 -0
  27. adam/commands/command.py +9 -4
  28. adam/commands/commands_utils.py +4 -5
  29. adam/commands/cql/cql_completions.py +7 -3
  30. adam/commands/cql/cql_utils.py +103 -11
  31. adam/commands/cql/cqlsh.py +10 -5
  32. adam/commands/deploy/code_utils.py +2 -2
  33. adam/commands/deploy/deploy.py +7 -1
  34. adam/commands/deploy/deploy_pg_agent.py +2 -2
  35. adam/commands/deploy/deploy_pod.py +6 -6
  36. adam/commands/deploy/deploy_utils.py +2 -2
  37. adam/commands/deploy/undeploy.py +7 -1
  38. adam/commands/deploy/undeploy_pg_agent.py +2 -2
  39. adam/commands/deploy/undeploy_pod.py +4 -4
  40. adam/commands/devices.py +29 -0
  41. adam/commands/export/export.py +60 -0
  42. adam/commands/export/export_on_x.py +76 -0
  43. adam/commands/export/export_rmdbs.py +65 -0
  44. adam/commands/export/export_select.py +68 -0
  45. adam/commands/export/export_use.py +56 -0
  46. adam/commands/export/utils_export.py +253 -0
  47. adam/commands/help.py +9 -5
  48. adam/commands/issues.py +6 -0
  49. adam/commands/kubectl.py +41 -0
  50. adam/commands/login.py +6 -3
  51. adam/commands/logs.py +2 -1
  52. adam/commands/ls.py +43 -31
  53. adam/commands/medusa/medusa_backup.py +2 -2
  54. adam/commands/medusa/medusa_restore.py +2 -2
  55. adam/commands/medusa/medusa_show_backupjobs.py +3 -2
  56. adam/commands/medusa/medusa_show_restorejobs.py +2 -2
  57. adam/commands/nodetool.py +11 -16
  58. adam/commands/postgres/postgres.py +4 -4
  59. adam/commands/postgres/{postgres_session.py → postgres_context.py} +29 -30
  60. adam/commands/postgres/postgres_utils.py +5 -5
  61. adam/commands/postgres/psql_completions.py +1 -1
  62. adam/commands/preview_table.py +18 -32
  63. adam/commands/pwd.py +4 -3
  64. adam/commands/reaper/reaper.py +3 -0
  65. adam/commands/reaper/reaper_restart.py +1 -1
  66. adam/commands/reaper/reaper_session.py +1 -1
  67. adam/commands/repair/repair.py +3 -3
  68. adam/commands/repair/repair_log.py +1 -1
  69. adam/commands/repair/repair_run.py +2 -2
  70. adam/commands/repair/repair_scan.py +1 -1
  71. adam/commands/repair/repair_stop.py +1 -1
  72. adam/commands/report.py +6 -0
  73. adam/commands/restart.py +2 -2
  74. adam/commands/rollout.py +1 -1
  75. adam/commands/show/show.py +3 -1
  76. adam/commands/show/show_app_actions.py +3 -0
  77. adam/commands/show/show_app_id.py +1 -1
  78. adam/commands/show/show_app_queues.py +3 -2
  79. adam/commands/show/show_cassandra_status.py +3 -3
  80. adam/commands/show/show_cassandra_version.py +3 -3
  81. adam/commands/show/show_login.py +3 -0
  82. adam/commands/show/show_processes.py +1 -1
  83. adam/commands/show/show_repairs.py +2 -2
  84. adam/commands/show/show_storage.py +1 -1
  85. adam/commands/watch.py +1 -1
  86. adam/config.py +2 -1
  87. adam/embedded_params.py +1 -1
  88. adam/pod_exec_result.py +7 -1
  89. adam/repl.py +125 -99
  90. adam/repl_commands.py +29 -17
  91. adam/repl_state.py +229 -49
  92. adam/sql/sql_completer.py +86 -62
  93. adam/sql/sql_state_machine.py +563 -0
  94. adam/sql/term_completer.py +3 -0
  95. adam/sso/cred_cache.py +1 -1
  96. adam/sso/idp.py +1 -1
  97. adam/utils_athena.py +108 -74
  98. adam/utils_audits.py +104 -0
  99. adam/utils_export.py +42 -0
  100. adam/utils_k8s/__init__.py +0 -0
  101. adam/utils_k8s/app_clusters.py +33 -0
  102. adam/utils_k8s/app_pods.py +31 -0
  103. adam/{k8s_utils → utils_k8s}/cassandra_clusters.py +5 -6
  104. adam/{k8s_utils → utils_k8s}/cassandra_nodes.py +11 -4
  105. adam/{k8s_utils → utils_k8s}/deployment.py +2 -2
  106. adam/{k8s_utils → utils_k8s}/pods.py +54 -11
  107. adam/{k8s_utils → utils_k8s}/statefulsets.py +2 -2
  108. adam/version.py +1 -1
  109. {kaqing-2.0.93.dist-info → kaqing-2.0.115.dist-info}/METADATA +1 -1
  110. kaqing-2.0.115.dist-info/RECORD +203 -0
  111. adam/commands/bash.py +0 -91
  112. adam/commands/cql/cql_table_completer.py +0 -8
  113. adam/commands/describe/describe.py +0 -46
  114. adam/commands/describe/describe_keyspace.py +0 -60
  115. adam/commands/describe/describe_keyspaces.py +0 -50
  116. adam/commands/describe/describe_table.py +0 -60
  117. adam/commands/describe/describe_tables.py +0 -50
  118. adam/commands/postgres/psql_table_completer.py +0 -11
  119. adam/sql/state_machine.py +0 -460
  120. kaqing-2.0.93.dist-info/RECORD +0 -190
  121. /adam/commands/{describe → bash}/__init__.py +0 -0
  122. /adam/{k8s_utils → commands/export}/__init__.py +0 -0
  123. /adam/{k8s_utils → utils_k8s}/config_maps.py +0 -0
  124. /adam/{k8s_utils → utils_k8s}/custom_resources.py +0 -0
  125. /adam/{k8s_utils → utils_k8s}/ingresses.py +0 -0
  126. /adam/{k8s_utils → utils_k8s}/jobs.py +0 -0
  127. /adam/{k8s_utils → utils_k8s}/kube_context.py +0 -0
  128. /adam/{k8s_utils → utils_k8s}/secrets.py +0 -0
  129. /adam/{k8s_utils → utils_k8s}/service_accounts.py +0 -0
  130. /adam/{k8s_utils → utils_k8s}/services.py +0 -0
  131. /adam/{k8s_utils → utils_k8s}/volumes.py +0 -0
  132. {kaqing-2.0.93.dist-info → kaqing-2.0.115.dist-info}/WHEEL +0 -0
  133. {kaqing-2.0.93.dist-info → kaqing-2.0.115.dist-info}/entry_points.txt +0 -0
  134. {kaqing-2.0.93.dist-info → kaqing-2.0.115.dist-info}/top_level.txt +0 -0
@@ -3,12 +3,33 @@ import re
3
3
  import subprocess
4
4
 
5
5
  from adam.config import Config
6
- from adam.k8s_utils.kube_context import KubeContext
7
- from adam.k8s_utils.pods import Pods
8
- from adam.k8s_utils.secrets import Secrets
6
+ from adam.utils_k8s.kube_context import KubeContext
7
+ from adam.utils_k8s.pods import Pods
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,13 +1,11 @@
1
- import functools
2
-
3
1
  from adam.commands.command import Command
4
- from adam.commands.cql.cql_table_completer import CqlTableNameCompleter
5
- from adam.commands.cql.cql_utils import run_cql, table_names, tables
6
- from adam.commands.postgres.postgres_session import PostgresSession
7
- 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
8
4
  from adam.config import Config
9
5
  from adam.repl_state import ReplState, RequiredState
10
6
  from adam.utils import lines_to_tabular, log, log2
7
+ from adam.utils_athena import Athena
8
+ from adam.utils_audits import Audits
11
9
 
12
10
  class PreviewTable(Command):
13
11
  COMMAND = 'preview'
@@ -25,28 +23,26 @@ class PreviewTable(Command):
25
23
  return PreviewTable.COMMAND
26
24
 
27
25
  def required(self):
28
- return RequiredState.CLUSTER_OR_POD
26
+ return [RequiredState.CLUSTER_OR_POD, RequiredState.PG_DATABASE, ReplState.L]
29
27
 
30
28
  def run(self, cmd: str, state: ReplState):
31
29
  if not(args := self.args(cmd)):
32
30
  return super().run(cmd, state)
33
31
 
34
32
  state, args = self.apply_state(args, state)
35
- if state.device == ReplState.P:
36
- if not self.validate_state(state, RequiredState.PG_DATABASE):
37
- return state
38
- else:
39
- if not self.validate_state(state):
40
- return state
33
+ if not self.validate_state(state):
34
+ return state
41
35
 
42
36
  if not args:
43
37
  def show_tables():
44
38
  if state.device == ReplState.P:
45
- pg = PostgresSession(state.namespace, state.pg_path)
46
- lines = [db["name"] for db in pg.tables() if db["schema"] == PostgresSession.default_schema()]
39
+ pg = PostgresContext.apply(state.namespace, state.pg_path)
40
+ lines = [db["name"] for db in pg.tables() if db["schema"] == PostgresContext.default_schema()]
47
41
  log(lines_to_tabular(lines, separator=','))
42
+ elif state.device == ReplState.L:
43
+ log(lines_to_tabular(Athena.table_names(), separator=','))
48
44
  else:
49
- run_cql(state, f'describe tables', show_out=True)
45
+ log(lines_to_tabular(cassandra_table_names(state), separator=','))
50
46
 
51
47
  if state.in_repl:
52
48
  log2('Table is required.')
@@ -65,26 +61,16 @@ class PreviewTable(Command):
65
61
 
66
62
  rows = Config().get('preview.rows', 10)
67
63
  if state.device == ReplState.P:
68
- PostgresSession(state.namespace, state.pg_path).run_sql(f'select * from {table} limit {rows}')
64
+ PostgresContext.apply(state.namespace, state.pg_path).run_sql(f'select * from {table} limit {rows}')
65
+ elif state.device == ReplState.L:
66
+ Athena.run_query(f'select * from {table} limit {rows}')
69
67
  else:
70
- run_cql(state, f'select * from {table} limit {rows}', show_out=True, use_single_quotes=True)
68
+ run_cql(state, f'select * from {table} limit {rows}', show_out=True, use_single_quotes=True, on_any=True)
71
69
 
72
70
  return state
73
71
 
74
- def completion(self, state: ReplState):
75
- if state.device == ReplState.P:
76
- return {PreviewTable.COMMAND: PsqlTableNameCompleter(state.namespace, state.pg_path)}
77
- elif state.sts:
78
- return {PreviewTable.COMMAND: CqlTableNameCompleter(table_names(state))}
79
-
72
+ def completion(self, _: ReplState):
80
73
  return {}
81
74
 
82
75
  def help(self, _: ReplState):
83
- return f'{PreviewTable.COMMAND} TABLE\t preview table'
84
-
85
- @functools.lru_cache()
86
- def cql_tables(state: ReplState):
87
- if state.pod:
88
- return tables(state)
89
-
90
- return tables(state, on_any=True)
76
+ 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}')
@@ -40,7 +40,7 @@ class Pwd(Command):
40
40
  words.append(f'env/{state.app_env}')
41
41
  if state.app_app:
42
42
  words.append(f'app/{state.app_app}')
43
- elif device == ReplState.L:
43
+ elif device in [ReplState.L, ReplState.X]:
44
44
  pass
45
45
  else:
46
46
  if state.sts:
@@ -62,6 +62,7 @@ class Pwd(Command):
62
62
  device_line(state, ReplState.C),
63
63
  device_line(state, ReplState.L),
64
64
  device_line(state, ReplState.P),
65
+ device_line(state, ReplState.X),
65
66
  f'',
66
67
  f'HOST\t{host}',
67
68
  f'NAMESPACE\t{state.namespace if state.namespace else "/"}',
@@ -37,6 +37,9 @@ class Reaper(Command):
37
37
  if not(args := self.args(cmd)):
38
38
  return super().run(cmd, state)
39
39
 
40
+ if not self.validate_state(state):
41
+ return state
42
+
40
43
  return super().intermediate_run(cmd, state, args, Reaper.cmd_list())
41
44
 
42
45
  def cmd_list():
@@ -1,5 +1,5 @@
1
1
  from adam.commands.command import Command
2
- from adam.k8s_utils.pods import Pods
2
+ from adam.utils_k8s.pods import Pods
3
3
  from .reaper_session import ReaperSession
4
4
  from adam.repl_state import ReplState, RequiredState
5
5
 
@@ -7,7 +7,7 @@ import requests
7
7
  from typing import List, cast
8
8
 
9
9
  from adam.config import Config
10
- from adam.k8s_utils.kube_context import KubeContext
10
+ from adam.utils_k8s.kube_context import KubeContext
11
11
  from adam.repl_state import ReplState
12
12
  from adam.utils import lines_to_tabular, log2
13
13
 
@@ -28,6 +28,8 @@ class Repair(Command):
28
28
  def run(self, cmd: str, state: ReplState):
29
29
  if not(args := self.args(cmd)):
30
30
  return super().run(cmd, state)
31
+ if not self.validate_state(state):
32
+ return state
31
33
 
32
34
  return super().intermediate_run(cmd, state, args, Repair.cmd_list())
33
35
 
@@ -35,9 +37,7 @@ class Repair(Command):
35
37
  return [RepairRun(), RepairScan(), RepairStop(), RepairLog()]
36
38
 
37
39
  def completion(self, state: ReplState):
38
- if state.sts:
39
- return super().completion(state)
40
- return {}
40
+ return super().completion(state)
41
41
 
42
42
  class RepairCommandHelper(click.Command):
43
43
  def get_help(self, ctx: click.Context):
@@ -1,5 +1,5 @@
1
1
  from adam.commands.command import Command
2
- from adam.k8s_utils.jobs import Jobs
2
+ from adam.utils_k8s.jobs import Jobs
3
3
  from adam.repl_state import ReplState, RequiredState
4
4
 
5
5
  class RepairLog(Command):
@@ -1,6 +1,6 @@
1
1
  from adam.commands.command import Command
2
- from adam.k8s_utils.jobs import Jobs
3
- from adam.k8s_utils.volumes import Volumes
2
+ from adam.utils_k8s.jobs import Jobs
3
+ from adam.utils_k8s.volumes import Volumes
4
4
  from adam.repl_state import ReplState, RequiredState
5
5
  from adam.config import Config
6
6
  from adam.commands.reaper.reaper_session import ReaperSession
@@ -1,7 +1,7 @@
1
1
  import time
2
2
 
3
3
  from adam.commands.command import Command
4
- from adam.k8s_utils.pods import Pods
4
+ from adam.utils_k8s.pods import Pods
5
5
  from adam.repl_state import ReplState, RequiredState
6
6
  from adam.utils import log2
7
7
  from adam.config import Config
@@ -1,5 +1,5 @@
1
1
  from adam.commands.command import Command
2
- from adam.k8s_utils.jobs import Jobs
2
+ from adam.utils_k8s.jobs import Jobs
3
3
  from adam.repl_state import ReplState, RequiredState
4
4
  from adam.config import Config
5
5
 
adam/commands/report.py CHANGED
@@ -22,12 +22,18 @@ class Report(Command):
22
22
  def command(self):
23
23
  return Report.COMMAND
24
24
 
25
+ def required(self):
26
+ return ReplState.NON_L
27
+
25
28
  def run(self, cmd: str, state: ReplState):
26
29
  if not(args := self.args(cmd)):
27
30
  return super().run(cmd, state)
28
31
 
29
32
  output: dict[str, any] = {}
30
33
  state, args = self.apply_state(args, state)
34
+ if not self.validate_state(state):
35
+ return state
36
+
31
37
  if state.in_repl:
32
38
  args, show = Command.extract_options(args, ['-s', '--show'])
33
39
 
adam/commands/restart.py CHANGED
@@ -1,6 +1,6 @@
1
1
  from adam.commands.command import Command
2
- from adam.k8s_utils.pods import Pods
3
- from adam.k8s_utils.statefulsets import StatefulSets
2
+ from adam.utils_k8s.pods import Pods
3
+ from adam.utils_k8s.statefulsets import StatefulSets
4
4
  from adam.repl_state import ReplState, RequiredState
5
5
  from adam.utils import log2
6
6
 
adam/commands/rollout.py CHANGED
@@ -4,7 +4,7 @@ from kubernetes.client.rest import ApiException
4
4
 
5
5
  from adam.commands.command import Command
6
6
  from adam.commands.watch import Watch
7
- from adam.k8s_utils.statefulsets import StatefulSets
7
+ from adam.utils_k8s.statefulsets import StatefulSets
8
8
  from adam.config import Config
9
9
  from adam.repl_state import ReplState, RequiredState
10
10
  from adam.utils import duration, log2
@@ -1,5 +1,6 @@
1
1
  import click
2
2
 
3
+ from adam.commands.audit.show_last10 import ShowLast10
3
4
  from adam.commands.command import Command
4
5
  from adam.commands.medusa.medusa_show_backupjobs import MedusaShowBackupJobs
5
6
  from adam.commands.medusa.medusa_show_restorejobs import MedusaShowRestoreJobs
@@ -42,7 +43,8 @@ class Show(Command):
42
43
  def cmd_list():
43
44
  return [ShowAppActions(), ShowAppId(), ShowAppQueues(), ShowHost(), ShowLogin(), ShowKubectlCommands(),
44
45
  ShowParams(), ShowProcesses(), ShowRepairs(), ShowStorage(), ShowAdam(),
45
- ShowCassandraStatus(), ShowCassandraVersion(), MedusaShowRestoreJobs(), MedusaShowBackupJobs()]
46
+ ShowCassandraStatus(), ShowCassandraVersion(), MedusaShowRestoreJobs(), MedusaShowBackupJobs(),
47
+ ShowLast10()]
46
48
 
47
49
  def completion(self, state: ReplState):
48
50
  return super().completion(state)
@@ -20,6 +20,9 @@ class ShowAppActions(Command):
20
20
  def command(self):
21
21
  return ShowAppActions.COMMAND
22
22
 
23
+ def required(self):
24
+ return ReplState.A
25
+
23
26
  def run(self, cmd: str, state: ReplState):
24
27
  if not self.args(cmd):
25
28
  return super().run(cmd, state)
@@ -1,5 +1,5 @@
1
1
  from adam.commands.command import Command
2
- from adam.k8s_utils.custom_resources import CustomResources
2
+ from adam.utils_k8s.custom_resources import CustomResources
3
3
  from adam.repl_state import ReplState, RequiredState
4
4
  from adam.utils import log
5
5
 
@@ -18,14 +18,15 @@ class ShowAppQueues(Command):
18
18
  return ShowAppQueues.COMMAND
19
19
 
20
20
  def required(self):
21
- return RequiredState.CLUSTER_OR_POD
21
+ return RequiredState.APP_APP
22
22
 
23
23
  def run(self, cmd: str, state: ReplState):
24
24
  if not(args := self.args(cmd)):
25
25
  return super().run(cmd, state)
26
26
 
27
27
  state, args = self.apply_state(args, state)
28
- if not self.validate_state(state, app_required=RequiredState.APP_APP):
28
+ # if not self.validate_state(state, app_required=RequiredState.APP_APP):
29
+ if not self.validate_state(state):
29
30
  return state
30
31
 
31
32
  _, forced = Command.extract_options(args, '--force')
@@ -8,9 +8,9 @@ from adam.columns.columns import Columns
8
8
  from adam.commands.command import Command
9
9
  from adam.commands.issues import Issues
10
10
  from adam.config import Config
11
- from adam.k8s_utils.cassandra_nodes import CassandraNodes
12
- from adam.k8s_utils.secrets import Secrets
13
- from adam.k8s_utils.statefulsets import StatefulSets
11
+ from adam.utils_k8s.cassandra_nodes import CassandraNodes
12
+ from adam.utils_k8s.secrets import Secrets
13
+ from adam.utils_k8s.statefulsets import StatefulSets
14
14
  from adam.repl_state import ReplState, RequiredState
15
15
  from adam.utils import lines_to_tabular, log, log2
16
16
  from adam.checks.status import parse_nodetool_status
@@ -1,7 +1,7 @@
1
1
  from adam.commands.command import Command
2
- from adam.k8s_utils.cassandra_clusters import CassandraClusters
3
- from adam.k8s_utils.cassandra_nodes import CassandraNodes
4
- from adam.k8s_utils.secrets import Secrets
2
+ from adam.utils_k8s.cassandra_clusters import CassandraClusters
3
+ from adam.utils_k8s.cassandra_nodes import CassandraNodes
4
+ from adam.utils_k8s.secrets import Secrets
5
5
  from adam.repl_state import ReplState, RequiredState
6
6
 
7
7
  class ShowCassandraVersion(Command):
@@ -24,6 +24,9 @@ class ShowLogin(Command):
24
24
  def command(self):
25
25
  return ShowLogin.COMMAND
26
26
 
27
+ def required(self):
28
+ return ReplState.NON_L
29
+
27
30
  def run(self, cmd: str, state: ReplState):
28
31
  if not(args := self.args(cmd)):
29
32
  return super().run(cmd, state)
@@ -1,7 +1,7 @@
1
1
  from adam.commands.command import Command
2
2
  from adam.commands.commands_utils import show_table
3
3
  from adam.config import Config
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
6
 
7
7
  class ShowProcesses(Command):
@@ -1,6 +1,6 @@
1
1
  from adam.commands.command import Command
2
- from adam.k8s_utils.cassandra_clusters import CassandraClusters
3
- from adam.k8s_utils.cassandra_nodes import CassandraNodes
2
+ from adam.utils_k8s.cassandra_clusters import CassandraClusters
3
+ from adam.utils_k8s.cassandra_nodes import CassandraNodes
4
4
  from adam.repl_state import ReplState, RequiredState
5
5
 
6
6
  class ShowRepairs(Command):
@@ -1,7 +1,7 @@
1
1
  from adam.commands.command import Command
2
2
  from adam.commands.commands_utils import show_table
3
3
  from adam.config import Config
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
6
 
7
7
  class ShowStorage(Command):
adam/commands/watch.py CHANGED
@@ -6,7 +6,7 @@ from typing import List
6
6
  from adam.commands.command import Command
7
7
  from adam.commands.commands_utils import show_pods, show_rollout
8
8
  from adam.config import Config
9
- from adam.k8s_utils.statefulsets import StatefulSets
9
+ from adam.utils_k8s.statefulsets import StatefulSets
10
10
  from adam.repl_state import ReplState, RequiredState
11
11
  from adam.utils import convert_seconds, log2
12
12
 
adam/config.py CHANGED
@@ -1,3 +1,4 @@
1
+ import os
1
2
  from typing import TypeVar, cast
2
3
  import yaml
3
4
 
@@ -38,7 +39,7 @@ class Config:
38
39
  return get_deep_keys(self.params)
39
40
 
40
41
  def is_debug(self):
41
- return Config().get('debug', False)
42
+ return os.getenv('QING_DEV', 'false').lower() == 'true' or Config().get('debug', False)
42
43
 
43
44
  def debug(self, s: None):
44
45
  if self.is_debug():
adam/embedded_params.py CHANGED
@@ -1,2 +1,2 @@
1
1
  def config():
2
- return {'app': {'console-endpoint': 'https://{host}/{env}/{app}/static/console/index.html', 'cr': {'cluster-regex': '(.*?-.*?)-.*', 'group': 'ops.c3.ai', 'v': 'v2', 'plural': 'c3cassandras'}, 'label': 'c3__app_id-0', 'login': {'admin-group': '{host}/C3.ClusterAdmin', 'ingress': '{app_id}-k8singr-appleader-001', 'timeout': 5, 'session-check-url': 'https://{host}/{env}/{app}/api/8/C3/userSessionToken', 'cache-creds': True, 'cache-username': True, 'url': 'https://{host}/{env}/{app}', 'another': "You're logged in to {has}. However, for this app, you need to log in to {need}.", 'token-server-url': 'http://localhost:{port}', 'password-max-length': 128}, 'strip': '0'}, 'audit': {'endpoint': 'https://4psvtaxlcb.execute-api.us-west-2.amazonaws.com/prod/', 'workers': 3, 'timeout': 10, 'log-audit-queries': False, 'athena': {'region': 'us-west-2', 'catalog': 'AwsDataCatalog', 'database': 'audit', 'tables': 'audit', 'output': 's3://s3.ops--audit/ddl/results'}}, 'bash': {'workers': 32}, 'cassandra': {'service-name': 'all-pods-service'}, 'cql': {'workers': 32, 'samples': 3, 'secret': {'cluster-regex': '(.*?-.*?)-.*', 'name': '{cluster}-superuser', 'password-item': 'password'}, 'alter-tables': {'excludes': 'system_auth,system_traces,reaper_db,system_distributed,system_views,system,system_schema,system_virtual_schema', 'gc-grace-periods': '3600,86400,864000,7776000', 'batching': True}}, 'checks': {'compactions-threshold': 250, 'cpu-busy-threshold': 98.0, 'cpu-threshold': 0.0, 'cassandra-data-path': '/c3/cassandra', 'root-disk-threshold': 50, 'cassandra-disk-threshold': 50, 'snapshot-size-cmd': "ls /c3/cassandra/data/data/*/*/snapshots | grep snapshots | sed 's/:$//g' | xargs -I {} du -sk {} | awk '{print $1}' | awk '{s+=$1} END {print s}'", 'snapshot-size-threshold': '40G', 'table-sizes-cmd': "ls -Al /c3/cassandra/data/data/ | awk '{print $9}' | sed 's/\\^r//g' | xargs -I {} du -sk /c3/cassandra/data/data/{}"}, 'get-host-id': {'workers': 32}, 'idps': {'ad': {'email-pattern': '.*@c3.ai', 'uri': 'https://login.microsoftonline.com/53ad779a-93e7-485c-ba20-ac8290d7252b/oauth2/v2.0/authorize?response_type=id_token&response_mode=form_post&client_id=00ff94a8-6b0a-4715-98e0-95490012d818&scope=openid+email+profile&redirect_uri=https%3A%2F%2Fplat.c3ci.cloud%2Fc3%2Fc3%2Foidc%2Flogin&nonce={nonce}&state=EMPTY', 'jwks-uri': 'https://login.microsoftonline.com/common/discovery/keys', 'contact': 'Please contact ted.tran@c3.ai.', 'whitelist-file': '/kaqing/members'}, 'okta': {'default': True, 'email-pattern': '.*@c3iot.com', 'uri': 'https://c3energy.okta.com/oauth2/v1/authorize?response_type=id_token&response_mode=form_post&client_id={client_id}&scope=openid+email+profile+groups&redirect_uri=https%3A%2F%2F{host}%2Fc3%2Fc3%2Foidc%2Flogin&nonce={nonce}&state=EMPTY', 'jwks-uri': 'https://c3energy.okta.com/oauth2/v1/keys'}}, 'issues': {'workers': 32}, 'logs': {'path': '/c3/cassandra/logs/system.log'}, 'medusa': {'restore-auto-complete': False}, 'nodetool': {'workers': 32, 'samples': 3, 'commands_in_line': 40}, 'pg': {'name-pattern': '^{namespace}.*-k8spg-.*', 'excludes': '.helm., -admin-secret', 'agent': {'name': 'ops-pg-agent', 'just-in-time': False, 'timeout': 86400, 'image': 'seanahnsf/kaqing'}, 'default-db': 'postgres', 'default-schema': 'postgres', 'secret': {'endpoint-key': 'postgres-db-endpoint', 'port-key': 'postgres-db-port', 'username-key': 'postgres-admin-username', 'password-key': 'postgres-admin-password'}}, 'pod': {'name': 'ops', 'image': 'seanahnsf/kaqing-cloud', 'sa': {'name': 'ops', 'proto': 'c3', 'additional-cluster-roles': 'c3aiops-k8ssandra-operator'}, 'label-selector': 'run=ops'}, 'preview': {'rows': 10}, 'processes': {'columns': 'pod,cpu,mem', 'header': 'POD_NAME,CPU,MEM/LIMIT'}, 'reaper': {'service-name': 'reaper-service', 'port-forward': {'timeout': 86400, 'local-port': 9001}, 'abort-runs-batch': 10, 'show-runs-batch': 100, 'pod': {'cluster-regex': '(.*?-.*?-.*?-.*?)-.*', 'label-selector': 'k8ssandra.io/reaper={cluster}-reaper'}, 'secret': {'cluster-regex': '(.*?-.*?)-.*', 'name': '{cluster}-reaper-ui', 'password-item': 'password'}}, 'repair': {'log-path': '/home/cassrepair/logs/', 'image': 'ci-registry.c3iot.io/cloudops/cassrepair:2.0.14', 'secret': 'ciregistryc3iotio', 'env': {'interval': 24, 'timeout': 60, 'pr': False, 'runs': 1}}, 'repl': {'start-drive': 'a', 'auto-enter-app': 'c3/c3', 'auto-enter-only-cluster': 'cluster', 'history': {'push-cat-remote-log-file': True}}, 'status': {'columns': 'status,address,load,tokens,owns,host_id,gossip,compactions', 'header': '--,Address,Load,Tokens,Owns,Host ID,GOSSIP,COMPACTIONS'}, 'storage': {'columns': 'pod,volume_root,volume_cassandra,snapshots,data,compactions', 'header': 'POD_NAME,VOLUME /,VOLUME CASS,SNAPSHOTS,DATA,COMPACTIONS'}, 'watch': {'auto': 'rollout', 'timeout': 3600, 'interval': 10}, 'debug': False, 'debugs': {'timings': False, 'exit-on-error': False, 'show-parallelism': False}}
2
+ return {'app': {'console-endpoint': 'https://{host}/{env}/{app}/static/console/index.html', 'container-name': 'c3-server', 'cr': {'cluster-regex': '(.*?-.*?)-.*', 'group': 'ops.c3.ai', 'v': 'v2', 'plural': 'c3cassandras'}, 'label': 'c3__app_id-0', 'login': {'admin-group': '{host}/C3.ClusterAdmin', 'ingress': '{app_id}-k8singr-appleader-001', 'timeout': 5, 'session-check-url': 'https://{host}/{env}/{app}/api/8/C3/userSessionToken', 'cache-creds': True, 'cache-username': True, 'url': 'https://{host}/{env}/{app}', 'another': "You're logged in to {has}. However, for this app, you need to log in to {need}.", 'token-server-url': 'http://localhost:{port}', 'password-max-length': 128}, 'strip': '0'}, 'audit': {'endpoint': 'https://4psvtaxlcb.execute-api.us-west-2.amazonaws.com/prod/', 'workers': 3, 'timeout': 10, 'log-audit-queries': False, 'athena': {'auto-repair': {'elapsed_hours': 12}, 'region': 'us-west-2', 'catalog': 'AwsDataCatalog', 'database': 'audit', 'repair-partition-tables': 'audit', 'output': 's3://s3.ops--audit/ddl/results', 'repair-cluster-tables': 'cluster'}}, 'bash': {'workers': 32}, 'cassandra': {'service-name': 'all-pods-service'}, 'cql': {'workers': 32, 'samples': 3, 'secret': {'cluster-regex': '(.*?-.*?)-.*', 'name': '{cluster}-superuser', 'password-item': 'password'}, 'alter-tables': {'excludes': 'system_auth,system_traces,reaper_db,system_distributed,system_views,system,system_schema,system_virtual_schema', 'gc-grace-periods': '3600,86400,864000,7776000', 'batching': True}}, 'export': {'workers': 8, 'temp_dir': '/c3/cassandra/tmp', 'columns': '<keys>'}, 'checks': {'compactions-threshold': 250, 'cpu-busy-threshold': 98.0, 'cpu-threshold': 0.0, 'cassandra-data-path': '/c3/cassandra', 'root-disk-threshold': 50, 'cassandra-disk-threshold': 50, 'snapshot-size-cmd': "ls /c3/cassandra/data/data/*/*/snapshots | grep snapshots | sed 's/:$//g' | xargs -I {} du -sk {} | awk '{print $1}' | awk '{s+=$1} END {print s}'", 'snapshot-size-threshold': '40G', 'table-sizes-cmd': "ls -Al /c3/cassandra/data/data/ | awk '{print $9}' | sed 's/\\^r//g' | xargs -I {} du -sk /c3/cassandra/data/data/{}"}, 'get-host-id': {'workers': 32}, 'idps': {'ad': {'email-pattern': '.*@c3.ai', 'uri': 'https://login.microsoftonline.com/53ad779a-93e7-485c-ba20-ac8290d7252b/oauth2/v2.0/authorize?response_type=id_token&response_mode=form_post&client_id=00ff94a8-6b0a-4715-98e0-95490012d818&scope=openid+email+profile&redirect_uri=https%3A%2F%2Fplat.c3ci.cloud%2Fc3%2Fc3%2Foidc%2Flogin&nonce={nonce}&state=EMPTY', 'jwks-uri': 'https://login.microsoftonline.com/common/discovery/keys', 'contact': 'Please contact ted.tran@c3.ai.', 'whitelist-file': '/kaqing/members'}, 'okta': {'default': True, 'email-pattern': '.*@c3iot.com', 'uri': 'https://c3energy.okta.com/oauth2/v1/authorize?response_type=id_token&response_mode=form_post&client_id={client_id}&scope=openid+email+profile+groups&redirect_uri=https%3A%2F%2F{host}%2Fc3%2Fc3%2Foidc%2Flogin&nonce={nonce}&state=EMPTY', 'jwks-uri': 'https://c3energy.okta.com/oauth2/v1/keys'}}, 'issues': {'workers': 32}, 'logs': {'path': '/c3/cassandra/logs/system.log'}, 'medusa': {'restore-auto-complete': False}, 'nodetool': {'workers': 32, 'samples': 3, 'commands_in_line': 40}, 'pg': {'name-pattern': '^{namespace}.*-k8spg-.*', 'excludes': '.helm., -admin-secret', 'agent': {'name': 'ops-pg-agent', 'just-in-time': False, 'timeout': 86400, 'image': 'seanahnsf/kaqing'}, 'default-db': 'postgres', 'default-schema': 'postgres', 'secret': {'endpoint-key': 'postgres-db-endpoint', 'port-key': 'postgres-db-port', 'username-key': 'postgres-admin-username', 'password-key': 'postgres-admin-password'}}, 'pod': {'name': 'ops', 'image': 'seanahnsf/kaqing-cloud', 'sa': {'name': 'ops', 'proto': 'c3', 'additional-cluster-roles': 'c3aiops-k8ssandra-operator'}, 'label-selector': 'run=ops'}, 'preview': {'rows': 10}, 'processes': {'columns': 'pod,cpu,mem', 'header': 'POD_NAME,CPU,MEM/LIMIT'}, 'reaper': {'service-name': 'reaper-service', 'port-forward': {'timeout': 86400, 'local-port': 9001}, 'abort-runs-batch': 10, 'show-runs-batch': 100, 'pod': {'cluster-regex': '(.*?-.*?-.*?-.*?)-.*', 'label-selector': 'k8ssandra.io/reaper={cluster}-reaper'}, 'secret': {'cluster-regex': '(.*?-.*?)-.*', 'name': '{cluster}-reaper-ui', 'password-item': 'password'}}, 'repair': {'log-path': '/home/cassrepair/logs/', 'image': 'ci-registry.c3iot.io/cloudops/cassrepair:2.0.14', 'secret': 'ciregistryc3iotio', 'env': {'interval': 24, 'timeout': 60, 'pr': False, 'runs': 1}}, 'repl': {'start-drive': 'a', 'a': {'auto-enter': 'c3/c3/*'}, 'c': {'auto-enter': 'cluster'}, 'history': {'push-cat-remote-log-file': True}, 'background-process': {'auto-nohup': True}}, 'status': {'columns': 'status,address,load,tokens,owns,host_id,gossip,compactions', 'header': '--,Address,Load,Tokens,Owns,Host ID,GOSSIP,COMPACTIONS'}, 'storage': {'columns': 'pod,volume_root,volume_cassandra,snapshots,data,compactions', 'header': 'POD_NAME,VOLUME /,VOLUME CASS,SNAPSHOTS,DATA,COMPACTIONS'}, 'watch': {'auto': 'rollout', 'timeout': 3600, 'interval': 10}, 'debug': False, 'debugs': {'timings': False, 'exit-on-error': False, 'show-parallelism': False}}
adam/pod_exec_result.py CHANGED
@@ -32,4 +32,10 @@ class PodExecResult:
32
32
  except:
33
33
  pass
34
34
 
35
- return code
35
+ return code
36
+
37
+ def __str__(self):
38
+ return f'{"OK" if self.exit_code() == 0 else self.exit_code()} {self.command}'
39
+
40
+ def __audit_extra__(self):
41
+ return self.log_file if self.log_file else None