kaqing 2.0.110__py3-none-any.whl → 2.0.214__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 +9 -12
- adam/apps.py +18 -4
- adam/batch.py +19 -19
- adam/checks/check_utils.py +16 -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 +24 -0
- adam/commands/app/app.py +38 -0
- adam/commands/{app_ping.py → app/app_ping.py} +7 -13
- adam/commands/{login.py → app/login.py} +22 -24
- adam/commands/app/show_app_actions.py +49 -0
- adam/commands/{show → app}/show_app_id.py +8 -11
- adam/commands/{show → app}/show_app_queues.py +7 -14
- adam/commands/app/show_login.py +56 -0
- adam/commands/app/utils_app.py +106 -0
- adam/commands/audit/audit.py +22 -40
- adam/commands/audit/audit_repair_tables.py +15 -19
- adam/commands/audit/audit_run.py +15 -22
- adam/commands/audit/completions_l.py +15 -0
- adam/commands/audit/show_last10.py +4 -18
- adam/commands/audit/show_slow10.py +4 -17
- adam/commands/audit/show_top10.py +4 -16
- adam/commands/audit/utils_show_top10.py +15 -3
- adam/commands/bash/__init__.py +5 -0
- adam/commands/bash/bash.py +36 -0
- adam/commands/bash/bash_completer.py +93 -0
- adam/commands/bash/utils_bash.py +16 -0
- adam/commands/cassandra/__init__.py +0 -0
- adam/commands/cassandra/download_cassandra_log.py +45 -0
- adam/commands/{restart.py → cassandra/restart_cluster.py} +12 -26
- adam/commands/cassandra/restart_node.py +51 -0
- adam/commands/cassandra/restart_nodes.py +47 -0
- adam/commands/{rollout.py → cassandra/rollout.py} +20 -25
- adam/commands/cassandra/show_cassandra_repairs.py +37 -0
- adam/commands/cassandra/show_cassandra_status.py +117 -0
- adam/commands/{show → cassandra}/show_cassandra_version.py +5 -18
- adam/commands/cassandra/show_processes.py +50 -0
- adam/commands/cassandra/show_storage.py +44 -0
- adam/commands/{watch.py → cassandra/watch.py} +26 -29
- adam/commands/cli/__init__.py +0 -0
- adam/commands/{cli_commands.py → cli/cli_commands.py} +8 -4
- adam/commands/cli/clipboard_copy.py +86 -0
- adam/commands/cli/show_cli_commands.py +56 -0
- adam/commands/code.py +57 -0
- adam/commands/command.py +211 -40
- adam/commands/commands_utils.py +20 -27
- adam/commands/config/__init__.py +0 -0
- adam/commands/{param_get.py → config/param_get.py} +11 -14
- adam/commands/{param_set.py → config/param_set.py} +8 -12
- adam/commands/{show → config}/show_params.py +2 -5
- adam/commands/cql/alter_tables.py +66 -0
- adam/commands/cql/completions_c.py +29 -0
- adam/commands/cql/cqlsh.py +10 -32
- adam/commands/cql/utils_cql.py +306 -0
- adam/commands/debug/__init__.py +0 -0
- adam/commands/debug/debug.py +22 -0
- adam/commands/debug/debug_completes.py +35 -0
- adam/commands/debug/debug_timings.py +35 -0
- adam/commands/debug/show_offloaded_completes.py +45 -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 +3 -6
- 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 +6 -8
- adam/commands/deploy/undeploy_pod.py +11 -12
- adam/commands/devices/__init__.py +0 -0
- adam/commands/devices/device.py +149 -0
- adam/commands/devices/device_app.py +163 -0
- adam/commands/devices/device_auit_log.py +49 -0
- adam/commands/devices/device_cass.py +179 -0
- adam/commands/devices/device_export.py +87 -0
- adam/commands/devices/device_postgres.py +160 -0
- adam/commands/devices/devices.py +25 -0
- adam/commands/diag/__init__.py +0 -0
- adam/commands/{check.py → diag/check.py} +16 -25
- adam/commands/diag/generate_report.py +52 -0
- adam/commands/diag/issues.py +43 -0
- adam/commands/exit.py +1 -4
- adam/commands/export/__init__.py +0 -0
- adam/commands/export/clean_up_all_export_sessions.py +37 -0
- adam/commands/export/clean_up_export_sessions.py +39 -0
- adam/commands/export/completions_x.py +11 -0
- adam/commands/export/download_export_session.py +40 -0
- adam/commands/export/drop_export_database.py +39 -0
- adam/commands/export/drop_export_databases.py +37 -0
- adam/commands/export/export.py +37 -0
- adam/commands/export/export_databases.py +251 -0
- adam/commands/export/export_select.py +34 -0
- adam/commands/export/export_sessions.py +210 -0
- adam/commands/export/export_use.py +49 -0
- adam/commands/export/export_x_select.py +48 -0
- adam/commands/export/exporter.py +419 -0
- adam/commands/export/import_files.py +44 -0
- adam/commands/export/import_session.py +40 -0
- adam/commands/export/importer.py +81 -0
- adam/commands/export/importer_athena.py +157 -0
- adam/commands/export/importer_sqlite.py +78 -0
- adam/commands/export/show_column_counts.py +45 -0
- adam/commands/export/show_export_databases.py +39 -0
- adam/commands/export/show_export_session.py +39 -0
- adam/commands/export/show_export_sessions.py +37 -0
- adam/commands/export/utils_export.py +366 -0
- adam/commands/fs/__init__.py +0 -0
- adam/commands/fs/cat.py +36 -0
- adam/commands/fs/cat_local.py +42 -0
- adam/commands/fs/cd.py +41 -0
- adam/commands/fs/download_file.py +47 -0
- adam/commands/fs/find_files.py +51 -0
- adam/commands/fs/find_processes.py +76 -0
- adam/commands/fs/head.py +36 -0
- adam/commands/fs/ls.py +41 -0
- adam/commands/fs/ls_local.py +40 -0
- adam/commands/fs/pwd.py +45 -0
- adam/commands/fs/rm.py +18 -0
- adam/commands/fs/rm_downloads.py +39 -0
- adam/commands/fs/rm_logs.py +38 -0
- adam/commands/{shell.py → fs/shell.py} +12 -4
- adam/commands/{show → fs}/show_adam.py +3 -3
- adam/commands/{show → fs}/show_host.py +1 -1
- adam/commands/help.py +5 -3
- adam/commands/intermediate_command.py +52 -0
- adam/commands/kubectl.py +38 -0
- adam/commands/medusa/medusa.py +4 -22
- adam/commands/medusa/medusa_backup.py +20 -27
- adam/commands/medusa/medusa_restore.py +35 -48
- adam/commands/medusa/medusa_show_backupjobs.py +16 -18
- adam/commands/medusa/medusa_show_restorejobs.py +13 -18
- adam/commands/medusa/utils_medusa.py +15 -0
- adam/commands/nodetool/__init__.py +0 -0
- adam/commands/{nodetool.py → nodetool/nodetool.py} +9 -20
- adam/commands/postgres/completions_p.py +22 -0
- adam/commands/postgres/postgres.py +47 -55
- adam/commands/postgres/postgres_databases.py +269 -0
- adam/commands/postgres/postgres_ls.py +5 -9
- adam/commands/postgres/postgres_preview.py +5 -9
- adam/commands/postgres/utils_postgres.py +80 -0
- adam/commands/preview_table.py +8 -44
- adam/commands/reaper/reaper.py +4 -27
- adam/commands/reaper/reaper_forward.py +49 -56
- 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 +8 -33
- adam/commands/reaper/reaper_runs.py +43 -58
- adam/commands/reaper/reaper_runs_abort.py +29 -49
- adam/commands/reaper/reaper_schedule_activate.py +14 -33
- adam/commands/reaper/reaper_schedule_start.py +9 -33
- adam/commands/reaper/reaper_schedule_stop.py +9 -33
- adam/commands/reaper/reaper_schedules.py +4 -14
- adam/commands/reaper/reaper_status.py +8 -16
- adam/commands/reaper/utils_reaper.py +203 -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 -40
- adam/commands/repair/repair_stop.py +5 -12
- adam/commands/show.py +40 -0
- adam/config.py +5 -15
- adam/embedded_params.py +1 -1
- adam/log.py +4 -4
- adam/repl.py +83 -116
- adam/repl_commands.py +86 -45
- adam/repl_session.py +9 -1
- adam/repl_state.py +176 -40
- adam/sql/async_executor.py +62 -0
- adam/sql/lark_completer.py +286 -0
- adam/sql/lark_parser.py +604 -0
- adam/sql/qingl.lark +1076 -0
- adam/sql/sql_completer.py +52 -27
- adam/sql/sql_state_machine.py +131 -19
- adam/sso/authn_ad.py +6 -8
- adam/sso/authn_okta.py +4 -6
- adam/sso/cred_cache.py +4 -9
- adam/sso/idp.py +9 -12
- adam/utils.py +670 -31
- adam/utils_athena.py +145 -0
- adam/utils_audits.py +12 -103
- adam/utils_issues.py +32 -0
- adam/utils_k8s/app_clusters.py +35 -0
- adam/utils_k8s/app_pods.py +41 -0
- adam/utils_k8s/cassandra_clusters.py +35 -20
- adam/utils_k8s/cassandra_nodes.py +15 -6
- 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 +96 -0
- adam/utils_k8s/kube_context.py +3 -6
- adam/{pod_exec_result.py → utils_k8s/pod_exec_result.py} +13 -4
- adam/utils_k8s/pods.py +159 -89
- 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 +6 -14
- adam/utils_local.py +80 -0
- adam/utils_net.py +4 -4
- adam/utils_repl/__init__.py +0 -0
- adam/utils_repl/appendable_completer.py +6 -0
- adam/utils_repl/automata_completer.py +48 -0
- adam/utils_repl/repl_completer.py +93 -0
- adam/utils_repl/state_machine.py +173 -0
- adam/utils_sqlite.py +132 -0
- adam/version.py +1 -1
- {kaqing-2.0.110.dist-info → kaqing-2.0.214.dist-info}/METADATA +1 -1
- kaqing-2.0.214.dist-info/RECORD +272 -0
- kaqing-2.0.214.dist-info/top_level.txt +2 -0
- teddy/__init__.py +0 -0
- teddy/lark_parser.py +436 -0
- teddy/lark_parser2.py +618 -0
- adam/commands/alter_tables.py +0 -81
- adam/commands/app.py +0 -67
- adam/commands/bash.py +0 -150
- adam/commands/cd.py +0 -125
- adam/commands/cp.py +0 -95
- adam/commands/cql/cql_completions.py +0 -15
- adam/commands/cql/cql_utils.py +0 -112
- adam/commands/devices.py +0 -118
- adam/commands/issues.py +0 -75
- adam/commands/logs.py +0 -40
- adam/commands/ls.py +0 -146
- adam/commands/postgres/postgres_context.py +0 -239
- adam/commands/postgres/postgres_utils.py +0 -31
- adam/commands/postgres/psql_completions.py +0 -10
- adam/commands/pwd.py +0 -77
- adam/commands/reaper/reaper_session.py +0 -159
- adam/commands/report.py +0 -63
- adam/commands/show/show.py +0 -54
- adam/commands/show/show_app_actions.py +0 -56
- adam/commands/show/show_cassandra_status.py +0 -128
- adam/commands/show/show_commands.py +0 -61
- adam/commands/show/show_login.py +0 -63
- adam/commands/show/show_processes.py +0 -53
- adam/commands/show/show_repairs.py +0 -47
- adam/commands/show/show_storage.py +0 -52
- kaqing-2.0.110.dist-info/RECORD +0 -187
- kaqing-2.0.110.dist-info/top_level.txt +0 -1
- /adam/commands/{show → app}/__init__.py +0 -0
- /adam/commands/{nodetool_commands.py → nodetool/nodetool_commands.py} +0 -0
- {kaqing-2.0.110.dist-info → kaqing-2.0.214.dist-info}/WHEEL +0 -0
- {kaqing-2.0.110.dist-info → kaqing-2.0.214.dist-info}/entry_points.txt +0 -0
adam/commands/issues.py
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
from adam.checks.check_result import CheckResult
|
|
2
|
-
from adam.checks.check_utils import run_checks
|
|
3
|
-
from adam.checks.issue import Issue
|
|
4
|
-
from adam.commands.command import Command
|
|
5
|
-
from adam.repl_session import ReplSession
|
|
6
|
-
from adam.repl_state import ReplState
|
|
7
|
-
from adam.utils import lines_to_tabular, log, log2
|
|
8
|
-
|
|
9
|
-
class Issues(Command):
|
|
10
|
-
COMMAND = 'issues'
|
|
11
|
-
|
|
12
|
-
# the singleton pattern
|
|
13
|
-
def __new__(cls, *args, **kwargs):
|
|
14
|
-
if not hasattr(cls, 'instance'): cls.instance = super(Issues, cls).__new__(cls)
|
|
15
|
-
|
|
16
|
-
return cls.instance
|
|
17
|
-
|
|
18
|
-
def __init__(self, successor: Command=None):
|
|
19
|
-
super().__init__(successor)
|
|
20
|
-
|
|
21
|
-
def command(self):
|
|
22
|
-
return Issues.COMMAND
|
|
23
|
-
|
|
24
|
-
def required(self):
|
|
25
|
-
return ReplState.NON_L
|
|
26
|
-
|
|
27
|
-
def run(self, cmd: str, state: ReplState):
|
|
28
|
-
if not(args := self.args(cmd)):
|
|
29
|
-
return super().run(cmd, state)
|
|
30
|
-
|
|
31
|
-
state, args = self.apply_state(args, state)
|
|
32
|
-
if not self.validate_state(state):
|
|
33
|
-
return state
|
|
34
|
-
|
|
35
|
-
args, show = Command.extract_options(args, ['-s', '--show'])
|
|
36
|
-
|
|
37
|
-
results = run_checks(state.sts, state.namespace, state.pod, show_output=show)
|
|
38
|
-
|
|
39
|
-
issues = CheckResult.collect_issues(results)
|
|
40
|
-
Issues.show_issues(issues, in_repl=state.in_repl)
|
|
41
|
-
|
|
42
|
-
return issues if issues else 'issues'
|
|
43
|
-
|
|
44
|
-
def show(check_results: list[CheckResult], in_repl = False):
|
|
45
|
-
Issues.show_issues(CheckResult.collect_issues(check_results), in_repl=in_repl)
|
|
46
|
-
|
|
47
|
-
def show_issues(issues: list[Issue], in_repl = False):
|
|
48
|
-
if not issues:
|
|
49
|
-
log2('No issues found.')
|
|
50
|
-
else:
|
|
51
|
-
suggested = 0
|
|
52
|
-
log2(f'* {len(issues)} issues found.')
|
|
53
|
-
lines = []
|
|
54
|
-
for i, issue in enumerate(issues, start=1):
|
|
55
|
-
lines.append(f"{i}||{issue.category}||{issue.desc}")
|
|
56
|
-
lines.append(f"||statefulset||{issue.statefulset}@{issue.namespace}")
|
|
57
|
-
lines.append(f"||pod||{issue.pod}@{issue.namespace}")
|
|
58
|
-
if issue.details:
|
|
59
|
-
lines.append(f"||details||{issue.details}")
|
|
60
|
-
|
|
61
|
-
if issue.suggestion:
|
|
62
|
-
lines.append(f'||suggestion||{issue.suggestion}')
|
|
63
|
-
if in_repl:
|
|
64
|
-
ReplSession().prompt_session.history.append_string(issue.suggestion)
|
|
65
|
-
suggested += 1
|
|
66
|
-
log(lines_to_tabular(lines, separator='||'))
|
|
67
|
-
if suggested:
|
|
68
|
-
log2()
|
|
69
|
-
log2(f'* {suggested} suggested commands are added to history. Press <Up> arrow to access them.')
|
|
70
|
-
|
|
71
|
-
def completion(self, _: ReplState):
|
|
72
|
-
return {Issues.COMMAND: None}
|
|
73
|
-
|
|
74
|
-
def help(self, _: ReplState):
|
|
75
|
-
return f'{Issues.COMMAND}\t find all issues'
|
adam/commands/logs.py
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
from adam.commands.command import Command
|
|
2
|
-
from adam.config import Config
|
|
3
|
-
from adam.utils_k8s.cassandra_nodes import CassandraNodes
|
|
4
|
-
from adam.repl_state import ReplState, RequiredState
|
|
5
|
-
|
|
6
|
-
class Logs(Command):
|
|
7
|
-
COMMAND = 'logs'
|
|
8
|
-
|
|
9
|
-
# the singleton pattern
|
|
10
|
-
def __new__(cls, *args, **kwargs):
|
|
11
|
-
if not hasattr(cls, 'instance'): cls.instance = super(Logs, cls).__new__(cls)
|
|
12
|
-
|
|
13
|
-
return cls.instance
|
|
14
|
-
|
|
15
|
-
def __init__(self, successor: Command=None):
|
|
16
|
-
super().__init__(successor)
|
|
17
|
-
|
|
18
|
-
def command(self):
|
|
19
|
-
return Logs.COMMAND
|
|
20
|
-
|
|
21
|
-
def required(self):
|
|
22
|
-
return RequiredState.POD
|
|
23
|
-
|
|
24
|
-
def run(self, cmd: str, state: ReplState):
|
|
25
|
-
if not(args := self.args(cmd)):
|
|
26
|
-
return super().run(cmd, state)
|
|
27
|
-
|
|
28
|
-
state, args = self.apply_state(args, state)
|
|
29
|
-
if not self.validate_state(state):
|
|
30
|
-
return state
|
|
31
|
-
|
|
32
|
-
path = Config().get('logs.path', '/c3/cassandra/logs/system.log')
|
|
33
|
-
return CassandraNodes.exec(state.pod, state.namespace, f'cat {path}')
|
|
34
|
-
|
|
35
|
-
def completion(self, _: ReplState):
|
|
36
|
-
# available only on cli
|
|
37
|
-
return {}
|
|
38
|
-
|
|
39
|
-
def help(self, _: ReplState):
|
|
40
|
-
return f'{Logs.COMMAND}\t show cassandra system log'
|
adam/commands/ls.py
DELETED
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
import copy
|
|
2
|
-
|
|
3
|
-
from adam.commands.command import Command
|
|
4
|
-
from adam.commands.commands_utils import show_pods, show_rollout
|
|
5
|
-
from adam.commands.cql.cqlsh import Cqlsh
|
|
6
|
-
from adam.commands.postgres.postgres_utils import pg_database_names, pg_table_names
|
|
7
|
-
from adam.commands.postgres.postgres_context import PostgresContext
|
|
8
|
-
from adam.config import Config
|
|
9
|
-
from adam.utils_k8s.custom_resources import CustomResources
|
|
10
|
-
from adam.utils_k8s.ingresses import Ingresses
|
|
11
|
-
from adam.utils_k8s.kube_context import KubeContext
|
|
12
|
-
from adam.utils_k8s.statefulsets import StatefulSets
|
|
13
|
-
from adam.pod_exec_result import PodExecResult
|
|
14
|
-
from adam.repl_state import ReplState
|
|
15
|
-
from adam.utils import lines_to_tabular, log, log2
|
|
16
|
-
from adam.apps import Apps
|
|
17
|
-
from adam.utils_audits import Audits
|
|
18
|
-
|
|
19
|
-
class Ls(Command):
|
|
20
|
-
COMMAND = 'ls'
|
|
21
|
-
|
|
22
|
-
# the singleton pattern
|
|
23
|
-
def __new__(cls, *args, **kwargs):
|
|
24
|
-
if not hasattr(cls, 'instance'): cls.instance = super(Ls, cls).__new__(cls)
|
|
25
|
-
|
|
26
|
-
return cls.instance
|
|
27
|
-
|
|
28
|
-
def __init__(self, successor: Command=None):
|
|
29
|
-
super().__init__(successor)
|
|
30
|
-
|
|
31
|
-
def command(self):
|
|
32
|
-
return Ls.COMMAND
|
|
33
|
-
|
|
34
|
-
def run(self, cmd: str, state: ReplState):
|
|
35
|
-
if not(args := self.args(cmd)):
|
|
36
|
-
return super().run(cmd, state)
|
|
37
|
-
|
|
38
|
-
state, args = self.apply_state(args, state)
|
|
39
|
-
|
|
40
|
-
if len(args) > 0:
|
|
41
|
-
arg = args[0]
|
|
42
|
-
if arg in ['p:', 'c:'] and arg != f'{state.device}:':
|
|
43
|
-
state = copy.copy(state)
|
|
44
|
-
state.device = arg.replace(':', '')
|
|
45
|
-
|
|
46
|
-
if state.device == ReplState.P:
|
|
47
|
-
if state.pg_path:
|
|
48
|
-
pg: PostgresContext = PostgresContext.apply(state.namespace, state.pg_path)
|
|
49
|
-
if pg.db:
|
|
50
|
-
self.show_pg_tables(pg)
|
|
51
|
-
else:
|
|
52
|
-
self.show_pg_databases(pg)
|
|
53
|
-
else:
|
|
54
|
-
self.show_pg_hosts(state)
|
|
55
|
-
elif state.device == ReplState.A:
|
|
56
|
-
if state.app_env:
|
|
57
|
-
def line(n: str, ns: str):
|
|
58
|
-
host = Ingresses.get_host(Config().get('app.login.ingress', '{app_id}-k8singr-appleader-001').replace('{app_id}', f'{ns}-{n}'), ns)
|
|
59
|
-
if not host:
|
|
60
|
-
return None
|
|
61
|
-
|
|
62
|
-
endpoint = Config().get('app.login.url', 'https://{host}/{env}/{app}').replace('{host}', host).replace('{env}', state.app_env).replace('{app}', 'c3')
|
|
63
|
-
if not endpoint:
|
|
64
|
-
return None
|
|
65
|
-
|
|
66
|
-
return f"{n.split('-')[1]},{Ingresses.get_host(f'{ns}-{n}-k8singr-appleader-001', ns)},{endpoint}"
|
|
67
|
-
|
|
68
|
-
svcs = [l for l in [line(n, ns) for n, ns in Apps.apps(state.app_env)] if l]
|
|
69
|
-
|
|
70
|
-
log(lines_to_tabular(svcs, 'APP,HOST,ENDPOINT', separator=','))
|
|
71
|
-
else:
|
|
72
|
-
svcs = [n for n, ns in Apps.envs()]
|
|
73
|
-
|
|
74
|
-
log(lines_to_tabular(svcs, 'ENV', separator=','))
|
|
75
|
-
elif state.device == ReplState.L:
|
|
76
|
-
self.show_audit_log_tables()
|
|
77
|
-
else:
|
|
78
|
-
if state.pod:
|
|
79
|
-
r: PodExecResult = Cqlsh().run(f'cql describe tables', state)
|
|
80
|
-
if r.stderr:
|
|
81
|
-
log(r.stderr)
|
|
82
|
-
log(r.stdout)
|
|
83
|
-
elif state.sts and state.namespace:
|
|
84
|
-
show_pods(StatefulSets.pods(state.sts, state.namespace), state.namespace, show_namespace=not KubeContext.in_cluster_namespace())
|
|
85
|
-
show_rollout(state.sts, state.namespace)
|
|
86
|
-
else:
|
|
87
|
-
self.show_statefulsets()
|
|
88
|
-
|
|
89
|
-
return state
|
|
90
|
-
|
|
91
|
-
def show_statefulsets(self):
|
|
92
|
-
ss = StatefulSets.list_sts_names()
|
|
93
|
-
if len(ss) == 0:
|
|
94
|
-
log2('No Cassandra clusters found.')
|
|
95
|
-
return
|
|
96
|
-
|
|
97
|
-
app_ids = CustomResources.get_app_ids()
|
|
98
|
-
list = []
|
|
99
|
-
for s in ss:
|
|
100
|
-
cr_name = CustomResources.get_cr_name(s)
|
|
101
|
-
app_id = 'Unknown'
|
|
102
|
-
if cr_name in app_ids:
|
|
103
|
-
app_id = app_ids[cr_name]
|
|
104
|
-
list.append(f"{s} {app_id}")
|
|
105
|
-
|
|
106
|
-
header = 'STATEFULSET_NAME@NAMESPACE APP_ID'
|
|
107
|
-
if KubeContext.in_cluster_namespace():
|
|
108
|
-
header = 'STATEFULSET_NAME APP_ID'
|
|
109
|
-
log(lines_to_tabular(list, header))
|
|
110
|
-
|
|
111
|
-
def show_pg_hosts(self, state: ReplState):
|
|
112
|
-
if state.namespace:
|
|
113
|
-
def line(pg: PostgresContext):
|
|
114
|
-
return f'{pg.path()},{pg.endpoint()}:{pg.port()},{pg.username()},{pg.password()}'
|
|
115
|
-
|
|
116
|
-
lines = [line(PostgresContext.apply(state.namespace, pg)) for pg in PostgresContext.hosts(state.namespace)]
|
|
117
|
-
|
|
118
|
-
log(lines_to_tabular(lines, 'NAME,ENDPOINT,USERNAME,PASSWORD', separator=','))
|
|
119
|
-
else:
|
|
120
|
-
def line(pg: PostgresContext):
|
|
121
|
-
return f'{pg.path()},{pg.namespace},{pg.endpoint()}:{pg.port()},{pg.username()},{pg.password()}'
|
|
122
|
-
|
|
123
|
-
lines = [line(PostgresContext.apply(state.namespace, pg)) for pg in PostgresContext.hosts(state.namespace)]
|
|
124
|
-
|
|
125
|
-
log(lines_to_tabular(lines, 'NAME,NAMESPACE,ENDPOINT,USERNAME,PASSWORD', separator=','))
|
|
126
|
-
|
|
127
|
-
def show_pg_databases(self, pg: PostgresContext):
|
|
128
|
-
log(lines_to_tabular(pg_database_names(pg.namespace, pg.path()), 'DATABASE', separator=','))
|
|
129
|
-
|
|
130
|
-
def show_pg_tables(self, pg: PostgresContext):
|
|
131
|
-
log(lines_to_tabular(pg_table_names(pg.namespace, pg.path()), 'NAME', separator=','))
|
|
132
|
-
|
|
133
|
-
def show_audit_log_tables(self):
|
|
134
|
-
log(lines_to_tabular(Audits.audit_table_names(), 'NAME', separator=','))
|
|
135
|
-
|
|
136
|
-
def completion(self, state: ReplState):
|
|
137
|
-
if state.device == ReplState.C:
|
|
138
|
-
if state.pod:
|
|
139
|
-
return super().completion(state)
|
|
140
|
-
elif not state.sts:
|
|
141
|
-
return {Ls.COMMAND: {n: None for n in StatefulSets.list_sts_names()}}
|
|
142
|
-
|
|
143
|
-
return super().completion(state)
|
|
144
|
-
|
|
145
|
-
def help(self, _: ReplState):
|
|
146
|
-
return f'{Ls.COMMAND} [device:]\t list apps, envs, clusters, nodes, pg hosts or pg databases'
|
|
@@ -1,239 +0,0 @@
|
|
|
1
|
-
import functools
|
|
2
|
-
import re
|
|
3
|
-
import subprocess
|
|
4
|
-
|
|
5
|
-
from adam.config import Config
|
|
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
|
-
from adam.utils import log2
|
|
10
|
-
|
|
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
|
-
|
|
33
|
-
def __init__(self, ns: str, path: str):
|
|
34
|
-
self.namespace = ns
|
|
35
|
-
self.conn_details = None
|
|
36
|
-
self.host = None
|
|
37
|
-
self.db = None
|
|
38
|
-
|
|
39
|
-
if path:
|
|
40
|
-
tks = path.split('/')
|
|
41
|
-
hn = tks[0].split('@')
|
|
42
|
-
self.host = hn[0]
|
|
43
|
-
if len(hn) > 1 and not ns:
|
|
44
|
-
self.namespace = hn[1]
|
|
45
|
-
|
|
46
|
-
if len(tks) > 1:
|
|
47
|
-
self.db = tks[1]
|
|
48
|
-
|
|
49
|
-
def path(self):
|
|
50
|
-
if not self.host:
|
|
51
|
-
return None
|
|
52
|
-
|
|
53
|
-
d = self.host
|
|
54
|
-
if not self.db:
|
|
55
|
-
return d
|
|
56
|
-
|
|
57
|
-
return f'{self.host}/{self.db}'
|
|
58
|
-
|
|
59
|
-
def hosts(ns: str):
|
|
60
|
-
return PostgresContext.hosts_for_namespace(ns)
|
|
61
|
-
|
|
62
|
-
@functools.lru_cache()
|
|
63
|
-
def hosts_for_namespace(ns: str):
|
|
64
|
-
ss = Secrets.list_secrets(ns, name_pattern=Config().get('pg.name-pattern', '^{namespace}.*k8spg.*'))
|
|
65
|
-
|
|
66
|
-
def excludes(name: str):
|
|
67
|
-
exs = Config().get('pg.excludes', '.helm., -admin-secret')
|
|
68
|
-
if exs:
|
|
69
|
-
for ex in exs.split(','):
|
|
70
|
-
if ex.strip(' ') in name:
|
|
71
|
-
return True
|
|
72
|
-
|
|
73
|
-
return False
|
|
74
|
-
|
|
75
|
-
return [s for s in ss if not excludes(s)]
|
|
76
|
-
|
|
77
|
-
def databases(self):
|
|
78
|
-
dbs = []
|
|
79
|
-
# List of databases
|
|
80
|
-
# Name | Owner | Encoding | Collate | Ctype | ICU Locale | Locale Provider | Access privileges
|
|
81
|
-
# ---------------------------------------+----------+----------+-------------+-------------+------------+-----------------+-----------------------
|
|
82
|
-
# postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | libc |
|
|
83
|
-
# stgawsscpsr_c3_c3 | postgres | UTF8 | C | C | | libc |
|
|
84
|
-
# template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | libc | =c/postgres +
|
|
85
|
-
# | | | | | | | postgres=CTc/postgres
|
|
86
|
-
# (48 rows)
|
|
87
|
-
if r := self.run_sql('\l', show_out=False):
|
|
88
|
-
s = 0
|
|
89
|
-
for line in r.stdout.split('\n'):
|
|
90
|
-
line: str = line.strip(' \r')
|
|
91
|
-
if s == 0:
|
|
92
|
-
if 'List of databases' in line:
|
|
93
|
-
s = 1
|
|
94
|
-
elif s == 1:
|
|
95
|
-
if 'Name' in line and 'Owner' in line and 'Encoding' in line:
|
|
96
|
-
s = 2
|
|
97
|
-
elif s == 2:
|
|
98
|
-
if line.startswith('---------'):
|
|
99
|
-
s = 3
|
|
100
|
-
elif s == 3:
|
|
101
|
-
groups = re.match(r'^\s*(\S*)\s*\|\s*(\S*)\s*\|.*', line)
|
|
102
|
-
if groups and groups[1] != '|':
|
|
103
|
-
dbs.append({'name': groups[1], 'owner': groups[2]})
|
|
104
|
-
|
|
105
|
-
return dbs
|
|
106
|
-
|
|
107
|
-
def tables(self):
|
|
108
|
-
dbs = []
|
|
109
|
-
# List of relations
|
|
110
|
-
# Schema | Name | Type | Owner
|
|
111
|
-
# ----------+------------------------------------------------------------+-------+---------------
|
|
112
|
-
# postgres | c3_2_admin_aclpriv | table | postgres
|
|
113
|
-
# postgres | c3_2_admin_aclpriv_a | table | postgres
|
|
114
|
-
if r := self.run_sql('\dt', show_out=False):
|
|
115
|
-
s = 0
|
|
116
|
-
for line in r.stdout.split('\n'):
|
|
117
|
-
line: str = line.strip(' \r')
|
|
118
|
-
if s == 0:
|
|
119
|
-
if 'List of relations' in line:
|
|
120
|
-
s = 1
|
|
121
|
-
elif s == 1:
|
|
122
|
-
if 'Schema' in line and 'Name' in line and 'Type' in line:
|
|
123
|
-
s = 2
|
|
124
|
-
elif s == 2:
|
|
125
|
-
if line.startswith('---------'):
|
|
126
|
-
s = 3
|
|
127
|
-
elif s == 3:
|
|
128
|
-
groups = re.match(r'^\s*(\S*)\s*\|\s*(\S*)\s*\|.*', line)
|
|
129
|
-
if groups and groups[1] != '|':
|
|
130
|
-
dbs.append({'schema': groups[1], 'name': groups[2]})
|
|
131
|
-
|
|
132
|
-
return dbs
|
|
133
|
-
|
|
134
|
-
def run_sql(self, sql: str, show_out = True):
|
|
135
|
-
db = self.db if self.db else PostgresContext.default_db()
|
|
136
|
-
|
|
137
|
-
if KubeContext.in_cluster():
|
|
138
|
-
cmd1 = f'env PGPASSWORD={self.password()} psql -h {self.endpoint()} -p {self.port()} -U {self.username()} {db} --pset pager=off -c'
|
|
139
|
-
log2(f'{cmd1} "{sql}"')
|
|
140
|
-
# remove double quotes from the sql argument
|
|
141
|
-
cmd = cmd1.split(' ') + [sql]
|
|
142
|
-
r = subprocess.run(cmd, capture_output=True, text=True)
|
|
143
|
-
if show_out:
|
|
144
|
-
log2(r.stdout)
|
|
145
|
-
log2(r.stderr)
|
|
146
|
-
|
|
147
|
-
return r
|
|
148
|
-
else:
|
|
149
|
-
ns = self.namespace
|
|
150
|
-
pod_name = Config().get('pg.agent.name', 'ops-pg-agent')
|
|
151
|
-
|
|
152
|
-
if Config().get('pg.agent.just-in-time', False):
|
|
153
|
-
if not PostgresContext.deploy_pg_agent(pod_name, ns):
|
|
154
|
-
return
|
|
155
|
-
|
|
156
|
-
real_pod_name = pod_name
|
|
157
|
-
try:
|
|
158
|
-
# try with dedicated pg agent pod name configured
|
|
159
|
-
Pods.get(ns, pod_name)
|
|
160
|
-
except:
|
|
161
|
-
try:
|
|
162
|
-
# try with the ops pod
|
|
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}"'
|
|
170
|
-
|
|
171
|
-
return Pods.exec(real_pod_name, pod_name, ns, cmd, show_out=show_out)
|
|
172
|
-
|
|
173
|
-
def deploy_pg_agent(pod_name: str, ns: str) -> str:
|
|
174
|
-
image = Config().get('pg.agent.image', 'seanahnsf/kaqing')
|
|
175
|
-
timeout = Config().get('pg.agent.timeout', 3600)
|
|
176
|
-
try:
|
|
177
|
-
Pods.create(ns, pod_name, image, ['sleep', f'{timeout}'], env={'NAMESPACE': ns}, sa_name='c3')
|
|
178
|
-
except Exception as e:
|
|
179
|
-
if e.status == 409:
|
|
180
|
-
if Pods.completed(ns, pod_name):
|
|
181
|
-
try:
|
|
182
|
-
Pods.delete(pod_name, ns)
|
|
183
|
-
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
|
-
|
|
187
|
-
return
|
|
188
|
-
else:
|
|
189
|
-
log2("Exception when calling BatchV1Api->create_pod: %s\n" % e)
|
|
190
|
-
|
|
191
|
-
return
|
|
192
|
-
|
|
193
|
-
Pods.wait_for_running(ns, pod_name)
|
|
194
|
-
|
|
195
|
-
return pod_name
|
|
196
|
-
|
|
197
|
-
def undeploy_pg_agent(pod_name: str, ns: str):
|
|
198
|
-
Pods.delete(pod_name, ns, grace_period_seconds=0)
|
|
199
|
-
|
|
200
|
-
def endpoint(self):
|
|
201
|
-
if not self.conn_details:
|
|
202
|
-
self.conn_details = Secrets.get_data(self.namespace, self.host)
|
|
203
|
-
|
|
204
|
-
endpoint_key = Config().get('pg.secret.endpoint-key', 'postgres-db-endpoint')
|
|
205
|
-
|
|
206
|
-
return self.conn_details[endpoint_key] if endpoint_key in self.conn_details else ''
|
|
207
|
-
|
|
208
|
-
def port(self):
|
|
209
|
-
if not self.conn_details:
|
|
210
|
-
self.conn_details = Secrets.get_data(self.namespace, self.host)
|
|
211
|
-
|
|
212
|
-
port_key = Config().get('pg.secret.port-key', 'postgres-db-port')
|
|
213
|
-
|
|
214
|
-
return self.conn_details[port_key] if port_key in self.conn_details else ''
|
|
215
|
-
|
|
216
|
-
def username(self):
|
|
217
|
-
if not self.conn_details:
|
|
218
|
-
self.conn_details = Secrets.get_data(self.namespace, self.host)
|
|
219
|
-
|
|
220
|
-
username_key = Config().get('pg.secret.username-key', 'postgres-admin-username')
|
|
221
|
-
|
|
222
|
-
return self.conn_details[username_key] if username_key in self.conn_details else ''
|
|
223
|
-
|
|
224
|
-
def password(self):
|
|
225
|
-
if not self.conn_details:
|
|
226
|
-
self.conn_details = Secrets.get_data(self.namespace, self.host)
|
|
227
|
-
|
|
228
|
-
password_key = Config().get('pg.secret.password-key', 'postgres-admin-password')
|
|
229
|
-
|
|
230
|
-
return self.conn_details[password_key] if password_key in self.conn_details else ''
|
|
231
|
-
|
|
232
|
-
def default_db():
|
|
233
|
-
return Config().get('pg.default-db', 'postgres')
|
|
234
|
-
|
|
235
|
-
def default_owner():
|
|
236
|
-
return Config().get('pg.default-owner', 'postgres')
|
|
237
|
-
|
|
238
|
-
def default_schema():
|
|
239
|
-
return Config().get('pg.default-schema', 'postgres')
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import functools
|
|
2
|
-
|
|
3
|
-
from adam.commands.postgres.postgres_context import PostgresContext
|
|
4
|
-
from adam.config import Config
|
|
5
|
-
|
|
6
|
-
TestPG = [False]
|
|
7
|
-
|
|
8
|
-
@functools.lru_cache()
|
|
9
|
-
def pg_database_names(ns: str, pg_path: str):
|
|
10
|
-
if TestPG[0]:
|
|
11
|
-
return ['azops88_c3ai_c3']
|
|
12
|
-
|
|
13
|
-
Config().wait_log('Inspecting Postgres Databases...')
|
|
14
|
-
|
|
15
|
-
pg = PostgresContext.apply(ns, pg_path)
|
|
16
|
-
return [db['name'] for db in pg.databases() if db['owner'] == PostgresContext.default_owner()]
|
|
17
|
-
|
|
18
|
-
@functools.lru_cache()
|
|
19
|
-
def pg_table_names(ns: str, pg_path: str):
|
|
20
|
-
if TestPG[0]:
|
|
21
|
-
return ['C3_2_XYZ1']
|
|
22
|
-
|
|
23
|
-
Config().wait_log('Inspecting Postgres Database...')
|
|
24
|
-
return [table['name'] for table in pg_tables(ns, pg_path) if table['schema'] == PostgresContext.default_schema()]
|
|
25
|
-
|
|
26
|
-
def pg_tables(ns: str, pg_path: str):
|
|
27
|
-
pg = PostgresContext.apply(ns, pg_path)
|
|
28
|
-
if pg.db:
|
|
29
|
-
return pg.tables()
|
|
30
|
-
|
|
31
|
-
return []
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
from adam.commands.postgres.postgres_utils import pg_table_names
|
|
2
|
-
from adam.sql.sql_completer import SqlCompleter
|
|
3
|
-
|
|
4
|
-
def psql_completions(ns: str, pg_path: str):
|
|
5
|
-
return {
|
|
6
|
-
'\h': None,
|
|
7
|
-
'\d': None,
|
|
8
|
-
'\dt': None,
|
|
9
|
-
'\du': None
|
|
10
|
-
} | SqlCompleter(lambda: pg_table_names(ns, pg_path)).completions_for_nesting()
|
adam/commands/pwd.py
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
from adam.app_session import AppSession
|
|
2
|
-
from adam.commands.command import Command
|
|
3
|
-
from adam.commands.postgres.postgres_context import PostgresContext
|
|
4
|
-
from adam.repl_state import ReplState
|
|
5
|
-
from adam.utils import lines_to_tabular, log
|
|
6
|
-
|
|
7
|
-
class Pwd(Command):
|
|
8
|
-
COMMAND = 'pwd'
|
|
9
|
-
|
|
10
|
-
# the singleton pattern
|
|
11
|
-
def __new__(cls, *args, **kwargs):
|
|
12
|
-
if not hasattr(cls, 'instance'): cls.instance = super(Pwd, cls).__new__(cls)
|
|
13
|
-
|
|
14
|
-
return cls.instance
|
|
15
|
-
|
|
16
|
-
def __init__(self, successor: Command=None):
|
|
17
|
-
super().__init__(successor)
|
|
18
|
-
|
|
19
|
-
def command(self):
|
|
20
|
-
return Pwd.COMMAND
|
|
21
|
-
|
|
22
|
-
def run(self, cmd: str, state: ReplState):
|
|
23
|
-
if not(args := self.args(cmd)):
|
|
24
|
-
return super().run(cmd, state)
|
|
25
|
-
|
|
26
|
-
state, _ = self.apply_state(args, state)
|
|
27
|
-
|
|
28
|
-
def device_line(state: ReplState, device: str):
|
|
29
|
-
words = []
|
|
30
|
-
|
|
31
|
-
if device == ReplState.P:
|
|
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 == ReplState.L:
|
|
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
|
-
f'',
|
|
66
|
-
f'HOST\t{host}',
|
|
67
|
-
f'NAMESPACE\t{state.namespace if state.namespace else "/"}',
|
|
68
|
-
], 'DEVICE\tLOCATION', separator='\t'))
|
|
69
|
-
log()
|
|
70
|
-
|
|
71
|
-
return state
|
|
72
|
-
|
|
73
|
-
def completion(self, state: ReplState):
|
|
74
|
-
return super().completion(state)
|
|
75
|
-
|
|
76
|
-
def help(self, _: ReplState):
|
|
77
|
-
return f'{Pwd.COMMAND}\t print current working directories'
|