kaqing 2.0.115__py3-none-any.whl → 2.0.172__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.
- adam/__init__.py +0 -2
- adam/app_session.py +8 -11
- adam/batch.py +3 -3
- adam/checks/check_utils.py +14 -46
- adam/checks/cpu.py +7 -1
- adam/checks/cpu_metrics.py +52 -0
- adam/checks/disk.py +2 -3
- adam/columns/columns.py +3 -1
- adam/columns/cpu.py +3 -1
- adam/columns/cpu_metrics.py +22 -0
- adam/columns/memory.py +3 -4
- adam/commands/__init__.py +18 -0
- adam/commands/alter_tables.py +43 -47
- adam/commands/audit/audit.py +24 -25
- adam/commands/audit/audit_repair_tables.py +14 -17
- adam/commands/audit/audit_run.py +15 -23
- adam/commands/audit/show_last10.py +10 -13
- adam/commands/audit/show_slow10.py +10 -13
- adam/commands/audit/show_top10.py +10 -14
- adam/commands/audit/utils_show_top10.py +2 -3
- adam/commands/bash/__init__.py +5 -0
- adam/commands/bash/bash.py +8 -96
- adam/commands/bash/utils_bash.py +16 -0
- adam/commands/cat.py +14 -19
- adam/commands/cd.py +12 -100
- adam/commands/check.py +20 -21
- adam/commands/cli_commands.py +2 -3
- adam/commands/code.py +20 -23
- adam/commands/command.py +123 -39
- adam/commands/commands_utils.py +8 -17
- adam/commands/cp.py +33 -39
- adam/commands/cql/cql_completions.py +28 -10
- adam/commands/cql/cqlsh.py +10 -30
- adam/commands/cql/utils_cql.py +343 -0
- adam/commands/deploy/code_start.py +7 -10
- adam/commands/deploy/code_stop.py +4 -21
- adam/commands/deploy/code_utils.py +3 -3
- adam/commands/deploy/deploy.py +4 -27
- adam/commands/deploy/deploy_frontend.py +14 -17
- adam/commands/deploy/deploy_pg_agent.py +2 -5
- adam/commands/deploy/deploy_pod.py +65 -73
- adam/commands/deploy/deploy_utils.py +14 -24
- adam/commands/deploy/undeploy.py +4 -27
- adam/commands/deploy/undeploy_frontend.py +4 -7
- adam/commands/deploy/undeploy_pg_agent.py +5 -7
- adam/commands/deploy/undeploy_pod.py +11 -12
- adam/commands/devices/__init__.py +0 -0
- adam/commands/devices/device.py +118 -0
- adam/commands/devices/device_app.py +173 -0
- adam/commands/devices/device_auit_log.py +49 -0
- adam/commands/devices/device_cass.py +185 -0
- adam/commands/devices/device_export.py +86 -0
- adam/commands/devices/device_postgres.py +144 -0
- adam/commands/devices/devices.py +25 -0
- adam/commands/exit.py +1 -4
- adam/commands/export/clean_up_all_export_sessions.py +37 -0
- adam/commands/export/clean_up_export_sessions.py +51 -0
- adam/commands/export/drop_export_database.py +55 -0
- adam/commands/export/drop_export_databases.py +43 -0
- adam/commands/export/export.py +19 -26
- adam/commands/export/export_databases.py +174 -0
- adam/commands/export/export_handlers.py +71 -0
- adam/commands/export/export_select.py +48 -22
- adam/commands/export/export_select_x.py +54 -0
- adam/commands/export/export_use.py +19 -23
- adam/commands/export/exporter.py +353 -0
- adam/commands/export/import_session.py +40 -0
- adam/commands/export/importer.py +67 -0
- adam/commands/export/importer_athena.py +77 -0
- adam/commands/export/importer_sqlite.py +39 -0
- adam/commands/export/show_column_counts.py +54 -0
- adam/commands/export/show_export_databases.py +36 -0
- adam/commands/export/show_export_session.py +48 -0
- adam/commands/export/show_export_sessions.py +44 -0
- adam/commands/export/utils_export.py +223 -162
- adam/commands/help.py +1 -1
- adam/commands/intermediate_command.py +49 -0
- adam/commands/issues.py +11 -43
- adam/commands/kubectl.py +3 -6
- adam/commands/login.py +22 -24
- adam/commands/logs.py +3 -6
- adam/commands/ls.py +11 -128
- adam/commands/medusa/medusa.py +4 -22
- adam/commands/medusa/medusa_backup.py +20 -24
- adam/commands/medusa/medusa_restore.py +29 -33
- adam/commands/medusa/medusa_show_backupjobs.py +14 -18
- adam/commands/medusa/medusa_show_restorejobs.py +11 -18
- adam/commands/nodetool.py +6 -15
- adam/commands/param_get.py +11 -12
- adam/commands/param_set.py +9 -10
- adam/commands/postgres/postgres.py +41 -34
- adam/commands/postgres/postgres_context.py +57 -24
- adam/commands/postgres/postgres_ls.py +4 -8
- adam/commands/postgres/postgres_preview.py +5 -9
- adam/commands/postgres/psql_completions.py +1 -1
- adam/commands/postgres/utils_postgres.py +66 -0
- adam/commands/preview_table.py +5 -44
- adam/commands/pwd.py +14 -47
- adam/commands/reaper/reaper.py +4 -27
- adam/commands/reaper/reaper_forward.py +48 -55
- adam/commands/reaper/reaper_forward_session.py +6 -0
- adam/commands/reaper/reaper_forward_stop.py +10 -16
- adam/commands/reaper/reaper_restart.py +7 -14
- adam/commands/reaper/reaper_run_abort.py +11 -30
- adam/commands/reaper/reaper_runs.py +42 -57
- adam/commands/reaper/reaper_runs_abort.py +29 -49
- adam/commands/reaper/reaper_schedule_activate.py +11 -30
- adam/commands/reaper/reaper_schedule_start.py +10 -29
- adam/commands/reaper/reaper_schedule_stop.py +10 -29
- adam/commands/reaper/reaper_schedules.py +4 -14
- adam/commands/reaper/reaper_status.py +8 -16
- adam/commands/reaper/utils_reaper.py +196 -0
- adam/commands/repair/repair.py +4 -22
- adam/commands/repair/repair_log.py +5 -11
- adam/commands/repair/repair_run.py +27 -34
- adam/commands/repair/repair_scan.py +32 -38
- adam/commands/repair/repair_stop.py +5 -11
- adam/commands/report.py +27 -29
- adam/commands/restart.py +25 -26
- adam/commands/rollout.py +19 -24
- adam/commands/shell.py +10 -4
- adam/commands/show/show.py +10 -25
- adam/commands/show/show_cassandra_repairs.py +35 -0
- adam/commands/show/show_cassandra_status.py +32 -43
- adam/commands/show/show_cassandra_version.py +5 -18
- adam/commands/show/show_commands.py +19 -24
- adam/commands/show/show_host.py +1 -1
- adam/commands/show/show_login.py +20 -27
- adam/commands/show/show_processes.py +15 -19
- adam/commands/show/show_storage.py +10 -20
- adam/commands/watch.py +26 -29
- adam/config.py +5 -14
- adam/embedded_params.py +1 -1
- adam/log.py +4 -4
- adam/pod_exec_result.py +3 -3
- adam/repl.py +40 -103
- adam/repl_commands.py +32 -16
- adam/repl_state.py +57 -28
- adam/sql/sql_completer.py +44 -28
- adam/sql/sql_state_machine.py +89 -28
- adam/sso/authn_ad.py +6 -8
- adam/sso/authn_okta.py +4 -6
- adam/sso/cred_cache.py +3 -5
- adam/sso/idp.py +9 -12
- adam/utils.py +435 -6
- adam/utils_athena.py +57 -37
- adam/utils_audits.py +12 -14
- adam/utils_issues.py +32 -0
- adam/utils_k8s/app_clusters.py +13 -18
- adam/utils_k8s/app_pods.py +2 -0
- adam/utils_k8s/cassandra_clusters.py +22 -19
- adam/utils_k8s/cassandra_nodes.py +2 -2
- adam/utils_k8s/custom_resources.py +16 -17
- adam/utils_k8s/ingresses.py +2 -2
- adam/utils_k8s/jobs.py +7 -11
- adam/utils_k8s/k8s.py +87 -0
- adam/utils_k8s/pods.py +40 -77
- adam/utils_k8s/secrets.py +4 -4
- adam/utils_k8s/service_accounts.py +5 -4
- adam/utils_k8s/services.py +2 -2
- adam/utils_k8s/statefulsets.py +1 -12
- adam/utils_net.py +4 -4
- adam/utils_repl/__init__.py +0 -0
- adam/utils_repl/automata_completer.py +48 -0
- adam/utils_repl/repl_completer.py +46 -0
- adam/utils_repl/state_machine.py +173 -0
- adam/utils_sqlite.py +137 -0
- adam/version.py +1 -1
- {kaqing-2.0.115.dist-info → kaqing-2.0.172.dist-info}/METADATA +1 -1
- kaqing-2.0.172.dist-info/RECORD +230 -0
- adam/commands/app.py +0 -67
- adam/commands/app_ping.py +0 -44
- adam/commands/cql/cql_utils.py +0 -204
- adam/commands/devices.py +0 -147
- adam/commands/export/export_on_x.py +0 -76
- adam/commands/export/export_rmdbs.py +0 -65
- adam/commands/postgres/postgres_utils.py +0 -31
- adam/commands/reaper/reaper_session.py +0 -159
- adam/commands/show/show_app_actions.py +0 -56
- adam/commands/show/show_app_id.py +0 -47
- adam/commands/show/show_app_queues.py +0 -45
- adam/commands/show/show_repairs.py +0 -47
- adam/utils_export.py +0 -42
- kaqing-2.0.115.dist-info/RECORD +0 -203
- {kaqing-2.0.115.dist-info → kaqing-2.0.172.dist-info}/WHEEL +0 -0
- {kaqing-2.0.115.dist-info → kaqing-2.0.172.dist-info}/entry_points.txt +0 -0
- {kaqing-2.0.115.dist-info → kaqing-2.0.172.dist-info}/top_level.txt +0 -0
adam/commands/param_set.py
CHANGED
|
@@ -22,20 +22,19 @@ class SetParam(Command):
|
|
|
22
22
|
if not(args := self.args(cmd)):
|
|
23
23
|
return super().run(cmd, state)
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
with self.validate(args, state) as (args, state):
|
|
26
|
+
if len(args) < 2:
|
|
27
|
+
log2('set <key> <value>')
|
|
26
28
|
|
|
27
|
-
|
|
28
|
-
log2('set <key> <value>')
|
|
29
|
+
return 'invalid args'
|
|
29
30
|
|
|
30
|
-
|
|
31
|
+
key = args[0]
|
|
32
|
+
value = args[1]
|
|
33
|
+
Config().set(key, value)
|
|
31
34
|
|
|
32
|
-
|
|
33
|
-
value = args[1]
|
|
34
|
-
Config().set(key, value)
|
|
35
|
+
log(Config().get(key, None))
|
|
35
36
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
return value
|
|
37
|
+
return value
|
|
39
38
|
|
|
40
39
|
def completion(self, _: ReplState):
|
|
41
40
|
return {SetParam.COMMAND: {key: ({'true': None, 'false': None} if Config().get(key, None) in [True, False] else None) for key in Config().keys()}}
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import click
|
|
2
2
|
|
|
3
|
+
from adam.commands import extract_trailing_options
|
|
3
4
|
from adam.commands.command import Command
|
|
5
|
+
from adam.commands.intermediate_command import IntermediateCommand
|
|
4
6
|
from adam.commands.postgres.psql_completions import psql_completions
|
|
5
|
-
from adam.commands.postgres.
|
|
7
|
+
from adam.commands.postgres.utils_postgres import pg_table_names, postgres
|
|
6
8
|
from .postgres_ls import PostgresLs
|
|
7
9
|
from .postgres_preview import PostgresPreview
|
|
8
10
|
from .postgres_context import PostgresContext
|
|
9
11
|
from adam.repl_state import ReplState
|
|
10
12
|
from adam.utils import log, log2
|
|
11
13
|
|
|
12
|
-
class Postgres(
|
|
14
|
+
class Postgres(IntermediateCommand):
|
|
13
15
|
COMMAND = 'pg'
|
|
14
|
-
reaper_login = None
|
|
15
16
|
|
|
16
17
|
# the singleton pattern
|
|
17
18
|
def __new__(cls, *args, **kwargs):
|
|
@@ -29,40 +30,36 @@ class Postgres(Command):
|
|
|
29
30
|
if not(args := self.args(cmd)):
|
|
30
31
|
return super().run(cmd, state)
|
|
31
32
|
|
|
32
|
-
|
|
33
|
+
with self.validate(args, state) as (args, state):
|
|
34
|
+
with extract_trailing_options(args, '&') as (args, backgrounded):
|
|
35
|
+
if not args:
|
|
36
|
+
if state.in_repl:
|
|
37
|
+
log2('Please use SQL statement. e.g. pg \l')
|
|
38
|
+
else:
|
|
39
|
+
log2('* Command or SQL statements is missing.')
|
|
40
|
+
Command.display_help()
|
|
33
41
|
|
|
34
|
-
|
|
35
|
-
if state.in_repl:
|
|
36
|
-
log2('Please use SQL statement. e.g. pg \l')
|
|
37
|
-
else:
|
|
38
|
-
log2('* Command or SQL statements is missing.')
|
|
39
|
-
Command.display_help()
|
|
42
|
+
return 'command-missing'
|
|
40
43
|
|
|
41
|
-
|
|
44
|
+
if not state.pg_path:
|
|
45
|
+
if state.in_repl:
|
|
46
|
+
log2('Enter "use <pg-name>" first.')
|
|
47
|
+
else:
|
|
48
|
+
log2('* pg-name is missing.')
|
|
42
49
|
|
|
43
|
-
|
|
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)
|
|
50
|
-
|
|
51
|
-
return state
|
|
52
|
-
|
|
53
|
-
def cmd_list():
|
|
54
|
-
return [PostgresLs(), PostgresPreview()]
|
|
50
|
+
return state
|
|
55
51
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
52
|
+
if state.in_repl:
|
|
53
|
+
with postgres(state) as pod:
|
|
54
|
+
pod.sql(args, background=backgrounded)
|
|
55
|
+
elif not self.run_subcommand(cmd, state):
|
|
56
|
+
with postgres(state) as pod:
|
|
57
|
+
pod.sql(args, background=backgrounded)
|
|
62
58
|
|
|
63
|
-
|
|
59
|
+
return state
|
|
64
60
|
|
|
65
|
-
|
|
61
|
+
def cmd_list(self):
|
|
62
|
+
return [PostgresLs(), PostgresPreview(), PostgresPg()]
|
|
66
63
|
|
|
67
64
|
def completion(self, state: ReplState):
|
|
68
65
|
if state.device != state.P:
|
|
@@ -86,12 +83,22 @@ class Postgres(Command):
|
|
|
86
83
|
return {}
|
|
87
84
|
|
|
88
85
|
def help(self, _: ReplState):
|
|
89
|
-
return f'<sql-statements
|
|
86
|
+
return f'<sql-statements> [&]\t run queries on Postgres databases'
|
|
90
87
|
|
|
91
88
|
class PostgresCommandHelper(click.Command):
|
|
92
89
|
def get_help(self, ctx: click.Context):
|
|
93
|
-
|
|
90
|
+
IntermediateCommand.intermediate_help(super().get_help(ctx), Postgres.COMMAND, Postgres().cmd_list(), show_cluster_help=True)
|
|
94
91
|
log('PG-Name: Kubernetes secret for Postgres credentials')
|
|
95
92
|
log(' e.g. stgawsscpsr-c3-c3-k8spg-cs-001')
|
|
96
93
|
log('Database: Postgres database name within a host')
|
|
97
|
-
log(' e.g. stgawsscpsr_c3_c3')
|
|
94
|
+
log(' e.g. stgawsscpsr_c3_c3')
|
|
95
|
+
|
|
96
|
+
# No action body, only for a help entry and auto-completion
|
|
97
|
+
class PostgresPg(Command):
|
|
98
|
+
COMMAND = 'pg'
|
|
99
|
+
|
|
100
|
+
def command(self):
|
|
101
|
+
return PostgresPg.COMMAND
|
|
102
|
+
|
|
103
|
+
def help(self, _: ReplState):
|
|
104
|
+
return f'pg <sql-statements>\t run queries on Postgres databases'
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
+
from datetime import datetime
|
|
1
2
|
import functools
|
|
2
3
|
import re
|
|
3
4
|
import subprocess
|
|
4
5
|
|
|
5
6
|
from adam.config import Config
|
|
7
|
+
from adam.repl_session import ReplSession
|
|
6
8
|
from adam.utils_k8s.kube_context import KubeContext
|
|
7
9
|
from adam.utils_k8s.pods import Pods
|
|
8
10
|
from adam.utils_k8s.secrets import Secrets
|
|
9
|
-
from adam.utils import log2
|
|
11
|
+
from adam.utils import log2, log_exc
|
|
10
12
|
|
|
11
13
|
class PostgresContext:
|
|
12
14
|
def apply(namespace: str, path: str, arg: str = None) -> 'PostgresContext':
|
|
@@ -131,7 +133,7 @@ class PostgresContext:
|
|
|
131
133
|
|
|
132
134
|
return dbs
|
|
133
135
|
|
|
134
|
-
def run_sql(self, sql: str, show_out = True):
|
|
136
|
+
def run_sql(self, sql: str, show_out = True, background = False):
|
|
135
137
|
db = self.db if self.db else PostgresContext.default_db()
|
|
136
138
|
|
|
137
139
|
if KubeContext.in_cluster():
|
|
@@ -139,36 +141,69 @@ class PostgresContext:
|
|
|
139
141
|
log2(f'{cmd1} "{sql}"')
|
|
140
142
|
# remove double quotes from the sql argument
|
|
141
143
|
cmd = cmd1.split(' ') + [sql]
|
|
142
|
-
|
|
144
|
+
|
|
145
|
+
r = subprocess.run(cmd, capture_output=not background, text=True)
|
|
143
146
|
if show_out:
|
|
144
147
|
log2(r.stdout)
|
|
145
148
|
log2(r.stderr)
|
|
146
149
|
|
|
147
150
|
return r
|
|
148
151
|
else:
|
|
149
|
-
|
|
150
|
-
|
|
152
|
+
pod_name, container_name = PostgresContext.pod_and_container(self.namespace)
|
|
153
|
+
if not pod_name:
|
|
154
|
+
return
|
|
155
|
+
|
|
156
|
+
# ns = self.namespace
|
|
157
|
+
# pod_name = Config().get('pg.agent.name', 'ops-pg-agent')
|
|
158
|
+
|
|
159
|
+
# if Config().get('pg.agent.just-in-time', False):
|
|
160
|
+
# if not PostgresContext.deploy_pg_agent(pod_name, ns):
|
|
161
|
+
# return
|
|
162
|
+
|
|
163
|
+
# real_pod_name = pod_name
|
|
164
|
+
# try:
|
|
165
|
+
# # try with dedicated pg agent pod name configured
|
|
166
|
+
# Pods.get(ns, pod_name)
|
|
167
|
+
# except:
|
|
168
|
+
# try:
|
|
169
|
+
# # try with the ops pod
|
|
170
|
+
# pod_name = Config().get('pod.name', 'ops')
|
|
171
|
+
# real_pod_name = Pods.get_with_selector(ns, label_selector = Config().get('pod.label-selector', 'run=ops')).metadata.name
|
|
172
|
+
# except:
|
|
173
|
+
# log2(f"Could not locate {pod_name} pod.")
|
|
174
|
+
# return None
|
|
175
|
+
|
|
176
|
+
cmd = f'psql -h {self.endpoint()} -p {self.port()} -U {self.username()} {db} --pset pager=off -c "{sql}"'
|
|
177
|
+
env_prefix = f'PGPASSWORD="{self.password()}"'
|
|
178
|
+
|
|
179
|
+
r = Pods.exec(pod_name, container_name, self.namespace, cmd, show_out=show_out, background=background, env_prefix=env_prefix)
|
|
180
|
+
if r and Config().get('repl.history.push-cat-remote-log-file', True):
|
|
181
|
+
if r.log_file and ReplSession().prompt_session:
|
|
182
|
+
ReplSession().prompt_session.history.append_string(f'@{r.pod} cat {r.log_file}')
|
|
183
|
+
|
|
184
|
+
return r
|
|
185
|
+
|
|
186
|
+
def pod_and_container(ns: str):
|
|
187
|
+
container_name = Config().get('pg.agent.name', 'ops-pg-agent')
|
|
151
188
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
189
|
+
if Config().get('pg.agent.just-in-time', False):
|
|
190
|
+
if not PostgresContext.deploy_pg_agent(container_name, ns):
|
|
191
|
+
return None
|
|
155
192
|
|
|
156
|
-
|
|
193
|
+
pod_name = container_name
|
|
194
|
+
try:
|
|
195
|
+
# try with dedicated pg agent pod name configured
|
|
196
|
+
Pods.get(ns, container_name)
|
|
197
|
+
except:
|
|
157
198
|
try:
|
|
158
|
-
# try with
|
|
159
|
-
|
|
199
|
+
# try with the ops pod
|
|
200
|
+
container_name = Config().get('pod.name', 'ops')
|
|
201
|
+
pod_name = Pods.get_with_selector(ns, label_selector = Config().get('pod.label-selector', 'run=ops')).metadata.name
|
|
160
202
|
except:
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
pod_name = Config().get('pod.name', 'ops')
|
|
164
|
-
real_pod_name = Pods.get_with_selector(ns, label_selector = Config().get('pod.label-selector', 'run=ops')).metadata.name
|
|
165
|
-
except:
|
|
166
|
-
log2(f"Could not locate {pod_name} pod.")
|
|
167
|
-
return None
|
|
168
|
-
|
|
169
|
-
cmd = f'PGPASSWORD="{self.password()}" psql -h {self.endpoint()} -p {self.port()} -U {self.username()} {db} --pset pager=off -c "{sql}"'
|
|
203
|
+
log2(f"Could not locate {container_name} pod.")
|
|
204
|
+
return None
|
|
170
205
|
|
|
171
|
-
|
|
206
|
+
return pod_name, container_name
|
|
172
207
|
|
|
173
208
|
def deploy_pg_agent(pod_name: str, ns: str) -> str:
|
|
174
209
|
image = Config().get('pg.agent.image', 'seanahnsf/kaqing')
|
|
@@ -178,11 +213,9 @@ class PostgresContext:
|
|
|
178
213
|
except Exception as e:
|
|
179
214
|
if e.status == 409:
|
|
180
215
|
if Pods.completed(ns, pod_name):
|
|
181
|
-
|
|
216
|
+
with log_exc(lambda e2: "Exception when calling BatchV1Api->create_pod: %s\n" % e2):
|
|
182
217
|
Pods.delete(pod_name, ns)
|
|
183
218
|
Pods.create(ns, pod_name, image, ['sleep', f'{timeout}'], env={'NAMESPACE': ns}, sa_name='c3')
|
|
184
|
-
except Exception as e2:
|
|
185
|
-
log2("Exception when calling BatchV1Api->create_pod: %s\n" % e2)
|
|
186
219
|
|
|
187
220
|
return
|
|
188
221
|
else:
|
|
@@ -4,7 +4,6 @@ from adam.repl_state import ReplState, RequiredState
|
|
|
4
4
|
|
|
5
5
|
class PostgresLs(Command):
|
|
6
6
|
COMMAND = 'pg ls'
|
|
7
|
-
reaper_login = None
|
|
8
7
|
|
|
9
8
|
# the singleton pattern
|
|
10
9
|
def __new__(cls, *args, **kwargs):
|
|
@@ -25,15 +24,12 @@ class PostgresLs(Command):
|
|
|
25
24
|
if not(args := self.args(cmd)):
|
|
26
25
|
return super().run(cmd, state)
|
|
27
26
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
return state
|
|
31
|
-
|
|
32
|
-
state.device = ReplState.P
|
|
27
|
+
with self.validate(args, state) as (args, state):
|
|
28
|
+
state.device = ReplState.P
|
|
33
29
|
|
|
34
|
-
|
|
30
|
+
Ls().run('ls', state)
|
|
35
31
|
|
|
36
|
-
|
|
32
|
+
return state
|
|
37
33
|
|
|
38
34
|
def completion(self, state: ReplState):
|
|
39
35
|
if state.sts:
|
|
@@ -4,7 +4,6 @@ from adam.repl_state import ReplState, RequiredState
|
|
|
4
4
|
|
|
5
5
|
class PostgresPreview(Command):
|
|
6
6
|
COMMAND = 'pg preview'
|
|
7
|
-
reaper_login = None
|
|
8
7
|
|
|
9
8
|
# the singleton pattern
|
|
10
9
|
def __new__(cls, *args, **kwargs):
|
|
@@ -19,21 +18,18 @@ class PostgresPreview(Command):
|
|
|
19
18
|
return PostgresPreview.COMMAND
|
|
20
19
|
|
|
21
20
|
def required(self):
|
|
22
|
-
return RequiredState.
|
|
21
|
+
return RequiredState.PG_DATABASE
|
|
23
22
|
|
|
24
23
|
def run(self, cmd: str, state: ReplState):
|
|
25
24
|
if not(args := self.args(cmd)):
|
|
26
25
|
return super().run(cmd, state)
|
|
27
26
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
return state
|
|
31
|
-
|
|
32
|
-
state.device = ReplState.P
|
|
27
|
+
with self.validate(args, state) as (args, state):
|
|
28
|
+
state.device = ReplState.P
|
|
33
29
|
|
|
34
|
-
|
|
30
|
+
PreviewTable().run(f'preview {" ".join(args)}', state)
|
|
35
31
|
|
|
36
|
-
|
|
32
|
+
return state
|
|
37
33
|
|
|
38
34
|
def completion(self, state: ReplState):
|
|
39
35
|
if state.sts:
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import functools
|
|
2
|
+
|
|
3
|
+
from adam.commands.postgres.postgres_context import PostgresContext
|
|
4
|
+
from adam.repl_state import ReplState
|
|
5
|
+
from adam.utils import log2, wait_log
|
|
6
|
+
from adam.utils_k8s.pods import Pods
|
|
7
|
+
|
|
8
|
+
TestPG = [False]
|
|
9
|
+
|
|
10
|
+
@functools.lru_cache()
|
|
11
|
+
def pg_database_names(ns: str, pg_path: str):
|
|
12
|
+
if TestPG[0]:
|
|
13
|
+
return ['azops88_c3ai_c3']
|
|
14
|
+
|
|
15
|
+
wait_log('Inspecting Postgres Databases...')
|
|
16
|
+
|
|
17
|
+
pg = PostgresContext.apply(ns, pg_path)
|
|
18
|
+
return [db['name'] for db in pg.databases() if db['owner'] == PostgresContext.default_owner()]
|
|
19
|
+
|
|
20
|
+
@functools.lru_cache()
|
|
21
|
+
def pg_table_names(ns: str, pg_path: str):
|
|
22
|
+
if TestPG[0]:
|
|
23
|
+
return ['C3_2_XYZ1']
|
|
24
|
+
|
|
25
|
+
wait_log('Inspecting Postgres Database...')
|
|
26
|
+
return [table['name'] for table in pg_tables(ns, pg_path) if table['schema'] == PostgresContext.default_schema()]
|
|
27
|
+
|
|
28
|
+
def pg_tables(ns: str, pg_path: str):
|
|
29
|
+
pg = PostgresContext.apply(ns, pg_path)
|
|
30
|
+
if pg.db:
|
|
31
|
+
return pg.tables()
|
|
32
|
+
|
|
33
|
+
return []
|
|
34
|
+
|
|
35
|
+
class PostgresPodService:
|
|
36
|
+
def __init__(self, handler: 'PostgresExecHandler'):
|
|
37
|
+
self.handler = handler
|
|
38
|
+
|
|
39
|
+
def exec(self, command: str, show_out=True):
|
|
40
|
+
state = self.handler.state
|
|
41
|
+
|
|
42
|
+
pod, container = PostgresContext.pod_and_container(state.namespace)
|
|
43
|
+
if not pod:
|
|
44
|
+
log2('Cannot locate postgres agent or ops pod.')
|
|
45
|
+
return state
|
|
46
|
+
|
|
47
|
+
return Pods.exec(pod, container, state.namespace, command, show_out=show_out)
|
|
48
|
+
|
|
49
|
+
def sql(self, args: list[str], background=False):
|
|
50
|
+
state = self.handler.state
|
|
51
|
+
|
|
52
|
+
PostgresContext.apply(state.namespace, state.pg_path).run_sql(' '.join(args), background=background)
|
|
53
|
+
|
|
54
|
+
class PostgresExecHandler:
|
|
55
|
+
def __init__(self, state: ReplState, background=False):
|
|
56
|
+
self.state = state
|
|
57
|
+
self.background = background
|
|
58
|
+
|
|
59
|
+
def __enter__(self):
|
|
60
|
+
return PostgresPodService(self)
|
|
61
|
+
|
|
62
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
63
|
+
return False
|
|
64
|
+
|
|
65
|
+
def postgres(state: ReplState, background=False):
|
|
66
|
+
return PostgresExecHandler(state, background=background)
|
adam/commands/preview_table.py
CHANGED
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
from adam.commands.command import Command
|
|
2
|
-
from adam.commands.
|
|
3
|
-
from adam.commands.postgres.postgres_context import PostgresContext
|
|
4
|
-
from adam.config import Config
|
|
2
|
+
from adam.commands.devices.devices import Devices
|
|
5
3
|
from adam.repl_state import ReplState, RequiredState
|
|
6
|
-
from adam.utils import lines_to_tabular, log, log2
|
|
7
|
-
from adam.utils_athena import Athena
|
|
8
|
-
from adam.utils_audits import Audits
|
|
9
4
|
|
|
10
5
|
class PreviewTable(Command):
|
|
11
6
|
COMMAND = 'preview'
|
|
@@ -29,47 +24,13 @@ class PreviewTable(Command):
|
|
|
29
24
|
if not(args := self.args(cmd)):
|
|
30
25
|
return super().run(cmd, state)
|
|
31
26
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
return state
|
|
35
|
-
|
|
36
|
-
if not args:
|
|
37
|
-
def show_tables():
|
|
38
|
-
if state.device == ReplState.P:
|
|
39
|
-
pg = PostgresContext.apply(state.namespace, state.pg_path)
|
|
40
|
-
lines = [db["name"] for db in pg.tables() if db["schema"] == PostgresContext.default_schema()]
|
|
41
|
-
log(lines_to_tabular(lines, separator=','))
|
|
42
|
-
elif state.device == ReplState.L:
|
|
43
|
-
log(lines_to_tabular(Athena.table_names(), separator=','))
|
|
44
|
-
else:
|
|
45
|
-
log(lines_to_tabular(cassandra_table_names(state), separator=','))
|
|
46
|
-
|
|
47
|
-
if state.in_repl:
|
|
48
|
-
log2('Table is required.')
|
|
49
|
-
log2()
|
|
50
|
-
log2('Tables:')
|
|
51
|
-
show_tables()
|
|
52
|
-
else:
|
|
53
|
-
log2('* Table is missing.')
|
|
54
|
-
show_tables()
|
|
55
|
-
|
|
56
|
-
Command.display_help()
|
|
27
|
+
with self.validate(args, state) as (args, state):
|
|
28
|
+
Devices.device(state).preview(args[0] if args else None, state)
|
|
57
29
|
|
|
58
|
-
return
|
|
59
|
-
|
|
60
|
-
table = args[0]
|
|
61
|
-
|
|
62
|
-
rows = Config().get('preview.rows', 10)
|
|
63
|
-
if state.device == ReplState.P:
|
|
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}')
|
|
67
|
-
else:
|
|
68
|
-
run_cql(state, f'select * from {table} limit {rows}', show_out=True, use_single_quotes=True, on_any=True)
|
|
69
|
-
|
|
70
|
-
return state
|
|
30
|
+
return state
|
|
71
31
|
|
|
72
32
|
def completion(self, _: ReplState):
|
|
33
|
+
# taken care of by the sql completer
|
|
73
34
|
return {}
|
|
74
35
|
|
|
75
36
|
def help(self, _: ReplState):
|
adam/commands/pwd.py
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
from adam.app_session import AppSession
|
|
2
2
|
from adam.commands.command import Command
|
|
3
|
-
from adam.commands.
|
|
3
|
+
from adam.commands.devices.devices import Devices
|
|
4
4
|
from adam.repl_state import ReplState
|
|
5
|
-
from adam.utils import lines_to_tabular, log
|
|
5
|
+
from adam.utils import lines_to_tabular, log, log_exc
|
|
6
6
|
|
|
7
7
|
class Pwd(Command):
|
|
8
8
|
COMMAND = 'pwd'
|
|
@@ -23,53 +23,20 @@ class Pwd(Command):
|
|
|
23
23
|
if not(args := self.args(cmd)):
|
|
24
24
|
return super().run(cmd, state)
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
with self.validate(args, state) as (_, state):
|
|
27
|
+
host = "unknown"
|
|
28
|
+
with log_exc():
|
|
29
|
+
app_session: AppSession = AppSession.create('c3', 'c3')
|
|
30
|
+
host = app_session.host
|
|
27
31
|
|
|
28
|
-
|
|
29
|
-
|
|
32
|
+
log(lines_to_tabular([device.pwd(state) for device in Devices.all()] + [
|
|
33
|
+
f'',
|
|
34
|
+
f'HOST\t{host}',
|
|
35
|
+
f'NAMESPACE\t{state.namespace if state.namespace else "/"}',
|
|
36
|
+
], 'DEVICE\tLOCATION', separator='\t'))
|
|
37
|
+
log()
|
|
30
38
|
|
|
31
|
-
|
|
32
|
-
pg: PostgresContext = PostgresContext.apply(state.namespace, state.pg_path)
|
|
33
|
-
|
|
34
|
-
if pg.host:
|
|
35
|
-
words.append(f'host/{pg.host}')
|
|
36
|
-
if pg.db:
|
|
37
|
-
words.append(f'database/{pg.db}')
|
|
38
|
-
elif device == ReplState.A:
|
|
39
|
-
if state.app_env:
|
|
40
|
-
words.append(f'env/{state.app_env}')
|
|
41
|
-
if state.app_app:
|
|
42
|
-
words.append(f'app/{state.app_app}')
|
|
43
|
-
elif device in [ReplState.L, ReplState.X]:
|
|
44
|
-
pass
|
|
45
|
-
else:
|
|
46
|
-
if state.sts:
|
|
47
|
-
words.append(f'sts/{state.sts}')
|
|
48
|
-
if state.pod:
|
|
49
|
-
words.append(f'pod/{state.pod}')
|
|
50
|
-
|
|
51
|
-
return '\t'.join([f'{device}:>'] + (words if words else ['/']))
|
|
52
|
-
|
|
53
|
-
host = "unknown"
|
|
54
|
-
try:
|
|
55
|
-
app_session: AppSession = AppSession.create('c3', 'c3')
|
|
56
|
-
host = app_session.host
|
|
57
|
-
except:
|
|
58
|
-
pass
|
|
59
|
-
|
|
60
|
-
log(lines_to_tabular([
|
|
61
|
-
device_line(state, ReplState.A),
|
|
62
|
-
device_line(state, ReplState.C),
|
|
63
|
-
device_line(state, ReplState.L),
|
|
64
|
-
device_line(state, ReplState.P),
|
|
65
|
-
device_line(state, ReplState.X),
|
|
66
|
-
f'',
|
|
67
|
-
f'HOST\t{host}',
|
|
68
|
-
f'NAMESPACE\t{state.namespace if state.namespace else "/"}',
|
|
69
|
-
], 'DEVICE\tLOCATION', separator='\t'))
|
|
70
|
-
log()
|
|
71
|
-
|
|
72
|
-
return state
|
|
39
|
+
return state
|
|
73
40
|
|
|
74
41
|
def completion(self, state: ReplState):
|
|
75
42
|
return super().completion(state)
|
adam/commands/reaper/reaper.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import click
|
|
2
2
|
|
|
3
|
-
from adam.commands.
|
|
3
|
+
from adam.commands.intermediate_command import IntermediateCommand
|
|
4
4
|
from .reaper_forward import ReaperForward
|
|
5
5
|
from .reaper_forward_stop import ReaperForwardStop
|
|
6
6
|
from .reaper_restart import ReaperRestart
|
|
@@ -12,11 +12,9 @@ from .reaper_schedule_start import ReaperScheduleStart
|
|
|
12
12
|
from .reaper_schedule_stop import ReaperScheduleStop
|
|
13
13
|
from .reaper_schedules import ReaperSchedules
|
|
14
14
|
from .reaper_status import ReaperStatus
|
|
15
|
-
from adam.repl_state import ReplState, RequiredState
|
|
16
15
|
|
|
17
|
-
class Reaper(
|
|
16
|
+
class Reaper(IntermediateCommand):
|
|
18
17
|
COMMAND = 'reaper'
|
|
19
|
-
reaper_login = None
|
|
20
18
|
|
|
21
19
|
# the singleton pattern
|
|
22
20
|
def __new__(cls, *args, **kwargs):
|
|
@@ -24,35 +22,14 @@ class Reaper(Command):
|
|
|
24
22
|
|
|
25
23
|
return cls.instance
|
|
26
24
|
|
|
27
|
-
def __init__(self, successor: Command=None):
|
|
28
|
-
super().__init__(successor)
|
|
29
|
-
|
|
30
25
|
def command(self):
|
|
31
26
|
return Reaper.COMMAND
|
|
32
27
|
|
|
33
|
-
def
|
|
34
|
-
return RequiredState.CLUSTER
|
|
35
|
-
|
|
36
|
-
def run(self, cmd: str, state: ReplState):
|
|
37
|
-
if not(args := self.args(cmd)):
|
|
38
|
-
return super().run(cmd, state)
|
|
39
|
-
|
|
40
|
-
if not self.validate_state(state):
|
|
41
|
-
return state
|
|
42
|
-
|
|
43
|
-
return super().intermediate_run(cmd, state, args, Reaper.cmd_list())
|
|
44
|
-
|
|
45
|
-
def cmd_list():
|
|
28
|
+
def cmd_list(self):
|
|
46
29
|
return [ReaperSchedules(), ReaperScheduleStop(), ReaperScheduleActivate(), ReaperScheduleStart(),
|
|
47
30
|
ReaperForwardStop(), ReaperForward(), ReaperRunAbort(), ReaperRunsAbort(), ReaperRestart(),
|
|
48
31
|
ReaperRuns(), ReaperStatus()]
|
|
49
32
|
|
|
50
|
-
def completion(self, state: ReplState):
|
|
51
|
-
if state.sts:
|
|
52
|
-
return super().completion(state)
|
|
53
|
-
|
|
54
|
-
return {}
|
|
55
|
-
|
|
56
33
|
class ReaperCommandHelper(click.Command):
|
|
57
34
|
def get_help(self, ctx: click.Context):
|
|
58
|
-
|
|
35
|
+
IntermediateCommand.intermediate_help(super().get_help(ctx), Reaper.COMMAND, Reaper().cmd_list(), show_cluster_help=True)
|