kaqing 2.0.14__py3-none-any.whl → 2.0.189__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 +20 -6
- adam/batch.py +16 -6
- adam/checks/check_utils.py +19 -49
- adam/checks/compactionstats.py +1 -1
- adam/checks/cpu.py +9 -3
- adam/checks/cpu_metrics.py +52 -0
- adam/checks/disk.py +3 -4
- adam/checks/gossip.py +1 -1
- adam/checks/memory.py +3 -3
- adam/checks/status.py +1 -1
- 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/alter_tables.py +66 -0
- adam/commands/app/app.py +38 -0
- adam/commands/{app_ping.py → app/app_ping.py} +8 -14
- adam/commands/app/show_app_actions.py +49 -0
- adam/commands/{show → app}/show_app_id.py +9 -12
- adam/commands/{show → app}/show_app_queues.py +8 -14
- adam/commands/app/utils_app.py +106 -0
- adam/commands/audit/__init__.py +0 -0
- adam/commands/audit/audit.py +67 -0
- adam/commands/audit/audit_repair_tables.py +72 -0
- adam/commands/audit/audit_run.py +50 -0
- adam/commands/audit/completions_l.py +15 -0
- adam/commands/audit/show_last10.py +36 -0
- adam/commands/audit/show_slow10.py +36 -0
- adam/commands/audit/show_top10.py +36 -0
- adam/commands/audit/utils_show_top10.py +71 -0
- 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/cat.py +36 -0
- adam/commands/cd.py +14 -88
- adam/commands/check.py +18 -21
- adam/commands/cli_commands.py +11 -7
- adam/commands/clipboard_copy.py +87 -0
- adam/commands/code.py +57 -0
- adam/commands/command.py +220 -19
- adam/commands/commands_utils.py +28 -31
- adam/commands/cql/__init__.py +0 -0
- adam/commands/cql/completions_c.py +28 -0
- adam/commands/{cqlsh.py → cql/cqlsh.py} +13 -32
- adam/commands/cql/utils_cql.py +305 -0
- adam/commands/deploy/code_start.py +7 -10
- adam/commands/deploy/code_stop.py +4 -21
- adam/commands/deploy/code_utils.py +5 -5
- adam/commands/deploy/deploy.py +4 -40
- adam/commands/deploy/deploy_frontend.py +15 -18
- adam/commands/deploy/deploy_pg_agent.py +4 -7
- adam/commands/deploy/deploy_pod.py +74 -77
- adam/commands/deploy/deploy_utils.py +16 -26
- adam/commands/deploy/undeploy.py +4 -40
- adam/commands/deploy/undeploy_frontend.py +5 -8
- adam/commands/deploy/undeploy_pg_agent.py +7 -8
- adam/commands/deploy/undeploy_pod.py +16 -17
- 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/download_file.py +47 -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 +246 -0
- adam/commands/export/export_select.py +34 -0
- adam/commands/export/export_sessions.py +209 -0
- adam/commands/export/export_use.py +49 -0
- adam/commands/export/export_x_select.py +48 -0
- adam/commands/export/exporter.py +332 -0
- adam/commands/export/import_files.py +44 -0
- adam/commands/export/import_session.py +44 -0
- adam/commands/export/importer.py +81 -0
- adam/commands/export/importer_athena.py +148 -0
- adam/commands/export/importer_sqlite.py +67 -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 +344 -0
- adam/commands/find_files.py +51 -0
- adam/commands/find_processes.py +76 -0
- adam/commands/head.py +36 -0
- adam/commands/help.py +14 -9
- adam/commands/intermediate_command.py +52 -0
- adam/commands/issues.py +14 -40
- adam/commands/kubectl.py +38 -0
- adam/commands/login.py +26 -25
- adam/commands/logs.py +5 -7
- adam/commands/ls.py +11 -115
- adam/commands/medusa/medusa.py +4 -46
- adam/commands/medusa/medusa_backup.py +22 -29
- adam/commands/medusa/medusa_restore.py +51 -49
- adam/commands/medusa/medusa_show_backupjobs.py +20 -21
- adam/commands/medusa/medusa_show_restorejobs.py +16 -21
- adam/commands/medusa/utils_medusa.py +15 -0
- adam/commands/nodetool.py +8 -17
- adam/commands/param_get.py +11 -14
- adam/commands/param_set.py +9 -13
- adam/commands/postgres/completions_p.py +22 -0
- adam/commands/postgres/postgres.py +49 -73
- adam/commands/postgres/postgres_databases.py +270 -0
- adam/commands/postgres/postgres_ls.py +4 -8
- adam/commands/postgres/postgres_preview.py +5 -9
- adam/commands/postgres/utils_postgres.py +79 -0
- adam/commands/preview_table.py +10 -69
- adam/commands/pwd.py +14 -43
- adam/commands/reaper/reaper.py +6 -49
- 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 +8 -15
- 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 -46
- adam/commands/repair/repair_log.py +6 -12
- adam/commands/repair/repair_run.py +29 -36
- adam/commands/repair/repair_scan.py +33 -41
- adam/commands/repair/repair_stop.py +6 -13
- adam/commands/report.py +25 -21
- adam/commands/restart.py +27 -28
- adam/commands/rollout.py +20 -25
- adam/commands/shell.py +12 -4
- adam/commands/show/show.py +15 -46
- adam/commands/show/show_adam.py +3 -3
- adam/commands/show/show_cassandra_repairs.py +37 -0
- adam/commands/show/show_cassandra_status.py +48 -52
- adam/commands/show/show_cassandra_version.py +5 -18
- adam/commands/show/show_cli_commands.py +56 -0
- adam/commands/show/show_host.py +33 -0
- adam/commands/show/show_login.py +23 -27
- adam/commands/show/show_params.py +2 -5
- adam/commands/show/show_processes.py +18 -21
- adam/commands/show/show_storage.py +11 -20
- adam/commands/watch.py +27 -30
- adam/config.py +8 -6
- adam/embedded_params.py +1 -1
- adam/log.py +4 -4
- adam/pod_exec_result.py +13 -5
- adam/repl.py +136 -120
- adam/repl_commands.py +66 -24
- adam/repl_session.py +8 -1
- adam/repl_state.py +343 -73
- adam/sql/__init__.py +0 -0
- adam/sql/lark_completer.py +284 -0
- adam/sql/lark_parser.py +604 -0
- adam/sql/sql_completer.py +118 -0
- adam/sql/sql_state_machine.py +630 -0
- adam/sql/term_completer.py +76 -0
- adam/sso/authn_ad.py +7 -9
- adam/sso/authn_okta.py +4 -6
- adam/sso/cred_cache.py +4 -6
- adam/sso/idp.py +10 -13
- adam/utils.py +539 -11
- adam/utils_athena.py +145 -0
- adam/utils_audits.py +102 -0
- adam/utils_issues.py +32 -0
- adam/utils_k8s/__init__.py +0 -0
- adam/utils_k8s/app_clusters.py +28 -0
- adam/utils_k8s/app_pods.py +36 -0
- adam/utils_k8s/cassandra_clusters.py +44 -0
- adam/{k8s_utils → utils_k8s}/cassandra_nodes.py +12 -5
- adam/{k8s_utils → utils_k8s}/custom_resources.py +16 -17
- adam/{k8s_utils → utils_k8s}/deployment.py +2 -2
- adam/{k8s_utils → utils_k8s}/ingresses.py +2 -2
- adam/{k8s_utils → utils_k8s}/jobs.py +7 -11
- adam/utils_k8s/k8s.py +96 -0
- adam/{k8s_utils → utils_k8s}/kube_context.py +3 -3
- adam/{k8s_utils → utils_k8s}/pods.py +132 -83
- adam/{k8s_utils → utils_k8s}/secrets.py +7 -3
- adam/{k8s_utils → utils_k8s}/service_accounts.py +5 -4
- adam/{k8s_utils → utils_k8s}/services.py +2 -2
- adam/{k8s_utils → utils_k8s}/statefulsets.py +9 -16
- adam/utils_local.py +4 -0
- adam/utils_net.py +24 -0
- 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 +172 -0
- adam/utils_repl/state_machine.py +173 -0
- adam/utils_sqlite.py +137 -0
- adam/version.py +1 -1
- {kaqing-2.0.14.dist-info → kaqing-2.0.189.dist-info}/METADATA +1 -1
- kaqing-2.0.189.dist-info/RECORD +253 -0
- kaqing-2.0.189.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/app.py +0 -67
- adam/commands/bash.py +0 -87
- adam/commands/cp.py +0 -95
- adam/commands/cql_utils.py +0 -53
- adam/commands/devices.py +0 -89
- adam/commands/postgres/postgres_session.py +0 -247
- adam/commands/reaper/reaper_session.py +0 -159
- adam/commands/show/show_app_actions.py +0 -53
- adam/commands/show/show_commands.py +0 -61
- adam/commands/show/show_repairs.py +0 -47
- adam/k8s_utils/cassandra_clusters.py +0 -48
- kaqing-2.0.14.dist-info/RECORD +0 -167
- kaqing-2.0.14.dist-info/top_level.txt +0 -1
- /adam/{k8s_utils → commands/app}/__init__.py +0 -0
- /adam/{k8s_utils → utils_k8s}/config_maps.py +0 -0
- /adam/{k8s_utils → utils_k8s}/volumes.py +0 -0
- {kaqing-2.0.14.dist-info → kaqing-2.0.189.dist-info}/WHEEL +0 -0
- {kaqing-2.0.14.dist-info → kaqing-2.0.189.dist-info}/entry_points.txt +0 -0
adam/repl_commands.py
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
|
-
from adam.commands.
|
|
2
|
-
from adam.commands.
|
|
1
|
+
from adam.commands.alter_tables import AlterTables
|
|
2
|
+
from adam.commands.app.app import App
|
|
3
|
+
from adam.commands.app.app_ping import AppPing
|
|
4
|
+
from adam.commands.app.show_app_actions import ShowAppActions
|
|
5
|
+
from adam.commands.app.show_app_id import ShowAppId
|
|
6
|
+
from adam.commands.app.show_app_queues import ShowAppQueues
|
|
7
|
+
from adam.commands.audit.audit import Audit
|
|
8
|
+
from adam.commands.cat import Cat
|
|
9
|
+
from adam.commands.code import Code
|
|
10
|
+
from adam.commands.download_file import DownloadFile
|
|
3
11
|
from adam.commands.deploy.code_start import CodeStart
|
|
4
12
|
from adam.commands.deploy.code_stop import CodeStop
|
|
5
13
|
from adam.commands.deploy.deploy import Deploy
|
|
@@ -10,22 +18,44 @@ from adam.commands.deploy.undeploy import Undeploy
|
|
|
10
18
|
from adam.commands.deploy.undeploy_frontend import UndeployFrontend
|
|
11
19
|
from adam.commands.deploy.undeploy_pg_agent import UndeployPgAgent
|
|
12
20
|
from adam.commands.deploy.undeploy_pod import UndeployPod
|
|
21
|
+
from adam.commands.devices.device_app import DeviceApp
|
|
22
|
+
from adam.commands.devices.device_auit_log import DeviceAuditLog
|
|
23
|
+
from adam.commands.devices.device_cass import DeviceCass
|
|
24
|
+
from adam.commands.devices.device_export import DeviceExport
|
|
25
|
+
from adam.commands.devices.device_postgres import DevicePostgres
|
|
26
|
+
from adam.commands.export.download_export_session import DownloadExportSession
|
|
27
|
+
from adam.commands.export.drop_export_database import DropExportDatabase
|
|
28
|
+
from adam.commands.export.export import ExportTables
|
|
29
|
+
from adam.commands.export.import_files import ImportCSVFiles
|
|
30
|
+
from adam.commands.export.import_session import ImportSession
|
|
31
|
+
from adam.commands.export.clean_up_export_sessions import CleanUpExportSessions
|
|
32
|
+
from adam.commands.export.clean_up_all_export_sessions import CleanUpAllExportSessions
|
|
33
|
+
from adam.commands.export.drop_export_databases import DropExportDatabases
|
|
34
|
+
from adam.commands.export.export_x_select import ExportXSelect
|
|
35
|
+
from adam.commands.export.export_use import ExportUse
|
|
36
|
+
from adam.commands.export.export_select import ExportSelect
|
|
37
|
+
from adam.commands.export.show_column_counts import ShowColumnCounts
|
|
38
|
+
from adam.commands.export.show_export_databases import ShowExportDatabases
|
|
39
|
+
from adam.commands.export.show_export_session import ShowExportSession
|
|
40
|
+
from adam.commands.export.show_export_sessions import ShowExportSessions
|
|
41
|
+
from adam.commands.find_files import FindLocalFiles
|
|
42
|
+
from adam.commands.find_processes import FindProcesses
|
|
43
|
+
from adam.commands.head import Head
|
|
44
|
+
from adam.commands.kubectl import Kubectl
|
|
13
45
|
from adam.commands.shell import Shell
|
|
14
|
-
from adam.commands.
|
|
15
|
-
from adam.commands.
|
|
16
|
-
from adam.commands.bash import Bash
|
|
46
|
+
from adam.commands.clipboard_copy import ClipboardCopy
|
|
47
|
+
from adam.commands.bash.bash import Bash
|
|
17
48
|
from adam.commands.cd import Cd
|
|
18
49
|
from adam.commands.check import Check
|
|
19
50
|
from adam.commands.command import Command
|
|
20
|
-
from adam.commands.cqlsh import Cqlsh
|
|
21
|
-
from adam.commands.devices import DeviceApp, DeviceCass, DevicePostgres
|
|
51
|
+
from adam.commands.cql.cqlsh import Cqlsh
|
|
22
52
|
from adam.commands.exit import Exit
|
|
23
53
|
from adam.commands.medusa.medusa import Medusa
|
|
24
54
|
from adam.commands.param_get import GetParam
|
|
25
55
|
from adam.commands.issues import Issues
|
|
26
56
|
from adam.commands.ls import Ls
|
|
27
57
|
from adam.commands.nodetool import NodeTool
|
|
28
|
-
from adam.commands.postgres.postgres import Postgres
|
|
58
|
+
from adam.commands.postgres.postgres import Postgres, PostgresPg
|
|
29
59
|
from adam.commands.preview_table import PreviewTable
|
|
30
60
|
from adam.commands.pwd import Pwd
|
|
31
61
|
from adam.commands.reaper.reaper import Reaper
|
|
@@ -35,25 +65,24 @@ from adam.commands.restart import Restart
|
|
|
35
65
|
from adam.commands.rollout import RollOut
|
|
36
66
|
from adam.commands.param_set import SetParam
|
|
37
67
|
from adam.commands.show.show import Show
|
|
38
|
-
from adam.commands.show.show_app_actions import ShowAppActions
|
|
39
|
-
from adam.commands.show.show_app_id import ShowAppId
|
|
40
68
|
from adam.commands.show.show_cassandra_status import ShowCassandraStatus
|
|
41
69
|
from adam.commands.show.show_cassandra_version import ShowCassandraVersion
|
|
42
|
-
from adam.commands.show.
|
|
70
|
+
from adam.commands.show.show_cli_commands import ShowKubectlCommands
|
|
71
|
+
from adam.commands.show.show_host import ShowHost
|
|
43
72
|
from adam.commands.show.show_login import ShowLogin
|
|
44
73
|
from adam.commands.show.show_params import ShowParams
|
|
45
74
|
from adam.commands.show.show_processes import ShowProcesses
|
|
46
|
-
from adam.commands.show.
|
|
75
|
+
from adam.commands.show.show_cassandra_repairs import ShowCassandraRepairs
|
|
47
76
|
from adam.commands.show.show_storage import ShowStorage
|
|
48
77
|
from adam.commands.show.show_adam import ShowAdam
|
|
49
78
|
from adam.commands.watch import Watch
|
|
50
79
|
|
|
51
80
|
class ReplCommands:
|
|
52
81
|
def repl_cmd_list() -> list[Command]:
|
|
53
|
-
cmds: list[Command] = ReplCommands.navigation() + ReplCommands.
|
|
54
|
-
ReplCommands.
|
|
82
|
+
cmds: list[Command] = ReplCommands.navigation() + ReplCommands.cassandra_ops() + ReplCommands.postgres_ops() + \
|
|
83
|
+
ReplCommands.app_ops() + ReplCommands.audit_ops() + ReplCommands.export_ops() + ReplCommands.tools() + ReplCommands.exit()
|
|
55
84
|
|
|
56
|
-
intermediate_cmds: list[Command] = [App(), Reaper(), Repair(), Deploy(), Show(), Undeploy()]
|
|
85
|
+
intermediate_cmds: list[Command] = [App(), Audit(), Reaper(), Repair(), Deploy(), Show(), Undeploy()]
|
|
57
86
|
ic = [c.command() for c in intermediate_cmds]
|
|
58
87
|
# 1. dedup commands
|
|
59
88
|
deduped = []
|
|
@@ -70,20 +99,33 @@ class ReplCommands:
|
|
|
70
99
|
return deduped
|
|
71
100
|
|
|
72
101
|
def navigation() -> list[Command]:
|
|
73
|
-
return [Ls(), PreviewTable(), DeviceApp(), DevicePostgres(), DeviceCass(),
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
def cassandra_check() -> list[Command]:
|
|
77
|
-
return [ShowCassandraStatus(), ShowCassandraVersion(), ShowRepairs(), ShowStorage(), ShowProcesses(), Check(), Issues(), NodeTool(), Report()]
|
|
102
|
+
return [Ls(), PreviewTable(), DeviceApp(), DevicePostgres(), DeviceCass(), DeviceAuditLog(), DeviceExport(),
|
|
103
|
+
Cd(), Cat(), Head(), DownloadFile(), FindLocalFiles(), FindProcesses(), Pwd(), ClipboardCopy(),
|
|
104
|
+
GetParam(), SetParam(), ShowParams(), ShowKubectlCommands(), ShowLogin(), ShowAdam(), ShowHost()]
|
|
78
105
|
|
|
79
106
|
def cassandra_ops() -> list[Command]:
|
|
80
|
-
return
|
|
107
|
+
return [Cqlsh(), ShowCassandraStatus(), ShowCassandraVersion(), ShowCassandraRepairs(), ShowStorage(), ShowProcesses(),
|
|
108
|
+
Check(), Issues(), NodeTool(), Report(), AlterTables(), Bash(),
|
|
109
|
+
ExportTables(), ExportXSelect(), ExportUse(), ShowExportDatabases(), ShowColumnCounts(),
|
|
110
|
+
DropExportDatabase(), DropExportDatabases(),
|
|
111
|
+
ShowExportSessions(), ShowExportSession(), DownloadExportSession(),
|
|
112
|
+
CleanUpExportSessions(), CleanUpAllExportSessions(), ImportSession(), ImportCSVFiles()] + \
|
|
113
|
+
Medusa().cmd_list() + [Restart(), RollOut(), Watch()] + Reaper().cmd_list() + Repair().cmd_list()
|
|
81
114
|
|
|
82
|
-
def
|
|
83
|
-
return [
|
|
115
|
+
def postgres_ops() -> list[Command]:
|
|
116
|
+
return [Postgres(), DeployPgAgent(), UndeployPgAgent(), PostgresPg()]
|
|
84
117
|
|
|
85
|
-
def
|
|
118
|
+
def app_ops() -> list[Command]:
|
|
86
119
|
return [ShowAppActions(), ShowAppId(), ShowAppQueues(), AppPing(), App()]
|
|
87
120
|
|
|
121
|
+
def audit_ops() -> list[Command]:
|
|
122
|
+
return [Audit()] + Audit().cmd_list()
|
|
123
|
+
|
|
124
|
+
def export_ops() -> list[Command]:
|
|
125
|
+
return [ExportSelect(), DropExportDatabase(), DropExportDatabases(), ShowColumnCounts()]
|
|
126
|
+
|
|
127
|
+
def tools() -> list[Command]:
|
|
128
|
+
return [Shell(), CodeStart(), CodeStop(), DeployFrontend(), UndeployFrontend(), DeployPod(), UndeployPod(), Kubectl(), Code()]
|
|
129
|
+
|
|
88
130
|
def exit() -> list[Command]:
|
|
89
131
|
return [Exit()]
|
adam/repl_session.py
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from prompt_toolkit import PromptSession
|
|
2
2
|
from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
|
|
3
3
|
|
|
4
|
+
from adam.config import Config
|
|
5
|
+
|
|
4
6
|
class ReplSession:
|
|
5
7
|
# the singleton pattern
|
|
6
8
|
def __new__(cls, *args, **kwargs):
|
|
@@ -10,4 +12,9 @@ class ReplSession:
|
|
|
10
12
|
|
|
11
13
|
def __init__(self):
|
|
12
14
|
if not hasattr(self, 'prompt_session'):
|
|
13
|
-
self.prompt_session = PromptSession(auto_suggest=AutoSuggestFromHistory())
|
|
15
|
+
self.prompt_session = PromptSession(auto_suggest=AutoSuggestFromHistory())
|
|
16
|
+
|
|
17
|
+
def append_history(self, entry: str):
|
|
18
|
+
if entry and Config().get('repl.history.push-cat-remote-log-file', True):
|
|
19
|
+
if self.prompt_session:
|
|
20
|
+
self.prompt_session.history.append_string(entry)
|
adam/repl_state.py
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
import copy
|
|
1
|
+
from copy import copy
|
|
2
2
|
from enum import Enum
|
|
3
|
-
|
|
4
|
-
from
|
|
5
|
-
|
|
6
|
-
from adam.
|
|
7
|
-
from adam.
|
|
8
|
-
from adam.
|
|
3
|
+
import re
|
|
4
|
+
from typing import Callable
|
|
5
|
+
|
|
6
|
+
from adam.utils_k8s.app_clusters import AppClusters
|
|
7
|
+
from adam.utils_k8s.app_pods import AppPods
|
|
8
|
+
from adam.utils_k8s.cassandra_clusters import CassandraClusters
|
|
9
|
+
from adam.utils_k8s.cassandra_nodes import CassandraNodes
|
|
10
|
+
from adam.utils_k8s.kube_context import KubeContext
|
|
11
|
+
from adam.utils_k8s.secrets import Secrets
|
|
9
12
|
from adam.utils import display_help, log2, random_alphanumeric
|
|
10
13
|
|
|
11
14
|
class BashSession:
|
|
@@ -16,25 +19,8 @@ class BashSession:
|
|
|
16
19
|
def pwd(self, state: 'ReplState'):
|
|
17
20
|
command = f'cat /tmp/.qing-{self.session_id}'
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
elif state.sts:
|
|
22
|
-
rs = CassandraClusters.exec(state.sts, state.namespace, command, action='bash', show_out=False)
|
|
23
|
-
|
|
24
|
-
dir = None
|
|
25
|
-
for r in rs:
|
|
26
|
-
if r.exit_code(): # if fails to read the session file, ignore
|
|
27
|
-
continue
|
|
28
|
-
|
|
29
|
-
dir0 = r.stdout.strip(' \r\n')
|
|
30
|
-
if dir:
|
|
31
|
-
if dir != dir0:
|
|
32
|
-
log2('Inconsitent working dir found across multiple pods.')
|
|
33
|
-
return None
|
|
34
|
-
else:
|
|
35
|
-
dir = dir0
|
|
36
|
-
|
|
37
|
-
return dir
|
|
22
|
+
with device(state) as pods:
|
|
23
|
+
return pods.exec(command, action='bash', show_out=False)
|
|
38
24
|
|
|
39
25
|
class RequiredState(Enum):
|
|
40
26
|
CLUSTER = 'cluster'
|
|
@@ -43,16 +29,22 @@ class RequiredState(Enum):
|
|
|
43
29
|
NAMESPACE = 'namespace'
|
|
44
30
|
PG_DATABASE = 'pg_database'
|
|
45
31
|
APP_APP = 'app_app'
|
|
32
|
+
EXPORT_DB = 'export_db'
|
|
46
33
|
|
|
47
34
|
class ReplState:
|
|
48
35
|
A = 'a'
|
|
49
36
|
C = 'c'
|
|
37
|
+
L = 'l'
|
|
50
38
|
P = 'p'
|
|
39
|
+
X = 'x'
|
|
40
|
+
|
|
41
|
+
ANY = [A, C, L, P, X]
|
|
42
|
+
NON_L = [A, C, P, X]
|
|
51
43
|
|
|
52
44
|
def __init__(self, device: str = None,
|
|
53
45
|
sts: str = None, pod: str = None, namespace: str = None, ns_sts: str = None,
|
|
54
46
|
pg_path: str = None,
|
|
55
|
-
app_env: str = None, app_app: str = None,
|
|
47
|
+
app_env: str = None, app_app: str = None, app_pod: str = None,
|
|
56
48
|
in_repl = False, bash_session: BashSession = None, remote_dir = None):
|
|
57
49
|
self.namespace = KubeContext.in_cluster_namespace()
|
|
58
50
|
|
|
@@ -62,12 +54,16 @@ class ReplState:
|
|
|
62
54
|
self.pg_path = pg_path
|
|
63
55
|
self.app_env = app_env
|
|
64
56
|
self.app_app = app_app
|
|
57
|
+
self.app_pod = app_pod
|
|
65
58
|
if namespace:
|
|
66
59
|
self.namespace = namespace
|
|
67
60
|
self.in_repl = in_repl
|
|
68
61
|
self.bash_session = bash_session
|
|
69
62
|
self.remote_dir = remote_dir
|
|
70
|
-
self.
|
|
63
|
+
self.original_state: ReplState = None
|
|
64
|
+
self.pod_targetted = False
|
|
65
|
+
|
|
66
|
+
self.export_session: str = None
|
|
71
67
|
|
|
72
68
|
if ns_sts:
|
|
73
69
|
nn = ns_sts.split('@')
|
|
@@ -82,13 +78,51 @@ class ReplState:
|
|
|
82
78
|
def __hash__(self):
|
|
83
79
|
return hash((self.sts, self.pod))
|
|
84
80
|
|
|
85
|
-
def
|
|
81
|
+
def __str__(self):
|
|
82
|
+
msg = ''
|
|
83
|
+
if self.device == ReplState.P:
|
|
84
|
+
msg = f'{ReplState.P}:'
|
|
85
|
+
host, database = self.pg_host_n_database()
|
|
86
|
+
if database:
|
|
87
|
+
msg += database
|
|
88
|
+
elif host:
|
|
89
|
+
msg += host
|
|
90
|
+
elif self.device == ReplState.A:
|
|
91
|
+
msg = f'{ReplState.A}:'
|
|
92
|
+
if self.app_env:
|
|
93
|
+
msg += self.app_env
|
|
94
|
+
if self.app_app:
|
|
95
|
+
msg += f'/{self.app_app}'
|
|
96
|
+
if self.app_pod:
|
|
97
|
+
# azops88-c3-c3-k8sdeploy-appleader-001-79957cf5b6-9k4bw
|
|
98
|
+
group = re.match(r".*?-.*?-.*?-.*?-(.*?-.*?)-.*", self.app_pod)
|
|
99
|
+
msg += '/' + group[1]
|
|
100
|
+
elif self.device == ReplState.L:
|
|
101
|
+
msg = f'{ReplState.L}:'
|
|
102
|
+
elif self.device == ReplState.X:
|
|
103
|
+
msg = f'{ReplState.X}:'
|
|
104
|
+
if self.export_session:
|
|
105
|
+
msg += self.export_session
|
|
106
|
+
else:
|
|
107
|
+
msg = f'{ReplState.C}:'
|
|
108
|
+
if self.pod:
|
|
109
|
+
# cs-d0767a536f-cs-d0767a536f-default-sts-0
|
|
110
|
+
group = re.match(r".*?-.*?-(.*)", self.pod)
|
|
111
|
+
msg += group[1]
|
|
112
|
+
elif self.sts:
|
|
113
|
+
# cs-d0767a536f-cs-d0767a536f-default-sts
|
|
114
|
+
group = re.match(r".*?-.*?-(.*)", self.sts)
|
|
115
|
+
msg += group[1]
|
|
116
|
+
|
|
117
|
+
return msg
|
|
118
|
+
|
|
119
|
+
def apply_args(self, args: list[str], cmd: list[str] = None, resolve_pg = True, args_to_check = 6) -> tuple['ReplState', list[str]]:
|
|
86
120
|
state = self
|
|
87
121
|
|
|
88
122
|
new_args = []
|
|
89
123
|
for index, arg in enumerate(args):
|
|
90
|
-
if index <
|
|
91
|
-
state = copy
|
|
124
|
+
if index < args_to_check:
|
|
125
|
+
state = copy(state)
|
|
92
126
|
|
|
93
127
|
s, n = KubeContext.is_sts_name(arg)
|
|
94
128
|
if s:
|
|
@@ -120,92 +154,328 @@ class ReplState:
|
|
|
120
154
|
|
|
121
155
|
return (state, new_args)
|
|
122
156
|
|
|
123
|
-
def
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
157
|
+
def apply_device_arg(self, args: list[str], cmd: list[str] = None) -> tuple['ReplState', list[str]]:
|
|
158
|
+
state = self
|
|
159
|
+
|
|
160
|
+
new_args = []
|
|
161
|
+
for index, arg in enumerate(args):
|
|
162
|
+
if index < 6:
|
|
163
|
+
state = copy(state)
|
|
164
|
+
|
|
165
|
+
groups = re.match(r'^([a|c|l|p|x]):(.*)$', arg)
|
|
166
|
+
if groups:
|
|
167
|
+
if groups[1] == 'p':
|
|
168
|
+
state.device = 'p'
|
|
169
|
+
state.pg_path = groups[2]
|
|
170
|
+
elif groups[1] == 'c':
|
|
171
|
+
state.device = 'c'
|
|
172
|
+
if path := groups[2]:
|
|
173
|
+
p_and_ns = path.split('@')
|
|
174
|
+
sts_and_pod = p_and_ns[0].split('/')
|
|
175
|
+
state.sts = sts_and_pod[0]
|
|
176
|
+
if len(sts_and_pod) > 1:
|
|
177
|
+
state.pod = sts_and_pod[1]
|
|
178
|
+
if len(p_and_ns) > 1:
|
|
179
|
+
state.namespace = p_and_ns[1]
|
|
180
|
+
elif ns := KubeContext.in_cluster_namespace():
|
|
181
|
+
state.namespace = ns
|
|
182
|
+
elif groups[1] == 'l':
|
|
183
|
+
state.device = 'l'
|
|
184
|
+
elif groups[1] == 'x':
|
|
185
|
+
state.device = 'x'
|
|
186
|
+
else:
|
|
187
|
+
state.device = 'a'
|
|
188
|
+
if path := groups[2]:
|
|
189
|
+
env_and_app = path.split('/')
|
|
190
|
+
state.app_env = env_and_app[0]
|
|
191
|
+
if len(env_and_app) > 1:
|
|
192
|
+
state.app_app = env_and_app[1]
|
|
193
|
+
else:
|
|
194
|
+
new_args.append(arg)
|
|
195
|
+
else:
|
|
196
|
+
new_args.append(arg)
|
|
197
|
+
|
|
198
|
+
if cmd:
|
|
199
|
+
new_args = new_args[len(cmd):]
|
|
200
|
+
|
|
201
|
+
return (state, new_args)
|
|
202
|
+
|
|
203
|
+
def validate(self, required: list[RequiredState] = [], show_err = True):
|
|
204
|
+
if not required:
|
|
205
|
+
return True
|
|
206
|
+
|
|
207
|
+
def default_err():
|
|
208
|
+
if self.in_repl:
|
|
209
|
+
log2(f'Not a valid command on {self.device}: drive.')
|
|
210
|
+
else:
|
|
211
|
+
log2('* on a wrong device.')
|
|
212
|
+
log2()
|
|
213
|
+
display_help()
|
|
214
|
+
|
|
215
|
+
if type(required) is not list:
|
|
216
|
+
valid, err = self._validate(required)
|
|
217
|
+
if valid:
|
|
218
|
+
return True
|
|
219
|
+
|
|
220
|
+
if show_err:
|
|
221
|
+
if err:
|
|
222
|
+
err()
|
|
223
|
+
else:
|
|
224
|
+
default_err()
|
|
225
|
+
|
|
226
|
+
return False
|
|
227
|
+
|
|
228
|
+
devices = [r for r in required if r in [ReplState.L, ReplState.A, ReplState.C, ReplState.P, ReplState.X]]
|
|
229
|
+
non_devices = [r for r in required if r not in [ReplState.L, ReplState.A, ReplState.C, ReplState.P, ReplState.X]]
|
|
230
|
+
|
|
231
|
+
first_error: Callable = None
|
|
232
|
+
for r in non_devices:
|
|
233
|
+
valid, err = self._validate(r)
|
|
234
|
+
if valid:
|
|
235
|
+
return True
|
|
236
|
+
|
|
237
|
+
if not first_error:
|
|
238
|
+
first_error = err
|
|
239
|
+
|
|
240
|
+
if devices:
|
|
241
|
+
valid, err = self._validate_device(devices)
|
|
242
|
+
if valid:
|
|
243
|
+
return True
|
|
244
|
+
|
|
245
|
+
if not first_error:
|
|
246
|
+
first_error = err
|
|
247
|
+
|
|
248
|
+
if show_err and first_error:
|
|
249
|
+
if first_error:
|
|
250
|
+
first_error()
|
|
251
|
+
else:
|
|
252
|
+
default_err()
|
|
253
|
+
|
|
254
|
+
return False
|
|
255
|
+
|
|
256
|
+
def _validate(self, required: RequiredState):
|
|
257
|
+
if required == RequiredState.CLUSTER:
|
|
258
|
+
if self.device != ReplState.C:
|
|
259
|
+
return (False, None)
|
|
260
|
+
|
|
261
|
+
if not self.namespace or not self.sts:
|
|
262
|
+
def error():
|
|
127
263
|
if self.in_repl:
|
|
128
264
|
log2('cd to a Cassandra cluster first.')
|
|
129
265
|
else:
|
|
130
266
|
log2('* Cassandra cluster is missing.')
|
|
131
267
|
log2()
|
|
132
268
|
display_help()
|
|
269
|
+
return (False, error)
|
|
270
|
+
|
|
271
|
+
elif required == RequiredState.POD:
|
|
272
|
+
if self.device != ReplState.C:
|
|
273
|
+
return (False, None)
|
|
133
274
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
if not self.namespace or not self.pod:
|
|
275
|
+
if not self.namespace or not self.pod:
|
|
276
|
+
def error():
|
|
137
277
|
if self.in_repl:
|
|
138
278
|
log2('cd to a pod first.')
|
|
139
279
|
else:
|
|
140
280
|
log2('* Pod is missing.')
|
|
141
281
|
log2()
|
|
142
282
|
display_help()
|
|
283
|
+
return (False, error)
|
|
143
284
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
285
|
+
elif required == RequiredState.CLUSTER_OR_POD:
|
|
286
|
+
if self.device != ReplState.C:
|
|
287
|
+
return (False, None)
|
|
288
|
+
|
|
289
|
+
if not self.namespace or not self.sts and not self.pod:
|
|
290
|
+
def error():
|
|
147
291
|
if self.in_repl:
|
|
148
292
|
log2('cd to a Cassandra cluster first.')
|
|
149
293
|
else:
|
|
150
294
|
log2('* Cassandra cluster or pod is missing.')
|
|
151
295
|
log2()
|
|
152
296
|
display_help()
|
|
297
|
+
return (False, error)
|
|
298
|
+
|
|
299
|
+
elif required == RequiredState.NAMESPACE:
|
|
300
|
+
if self.device != ReplState.C:
|
|
301
|
+
return (False, None)
|
|
153
302
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
if not self.namespace:
|
|
303
|
+
if not self.namespace:
|
|
304
|
+
def error():
|
|
157
305
|
if self.in_repl:
|
|
158
306
|
log2('Namespace is required.')
|
|
159
307
|
else:
|
|
160
308
|
log2('* namespace is missing.')
|
|
161
309
|
log2()
|
|
162
310
|
display_help()
|
|
311
|
+
return (False, error)
|
|
312
|
+
|
|
313
|
+
elif required == RequiredState.PG_DATABASE:
|
|
314
|
+
if self.device != ReplState.P:
|
|
315
|
+
return (False, None)
|
|
316
|
+
|
|
317
|
+
_, database = self.pg_host_n_database()
|
|
318
|
+
if not database:
|
|
319
|
+
def error():
|
|
320
|
+
if self.in_repl:
|
|
321
|
+
log2('cd to a database first.')
|
|
322
|
+
else:
|
|
323
|
+
log2('* database is missing.')
|
|
324
|
+
log2()
|
|
325
|
+
display_help()
|
|
326
|
+
return (False, error)
|
|
163
327
|
|
|
164
|
-
|
|
328
|
+
elif required == RequiredState.APP_APP:
|
|
329
|
+
if self.device != ReplState.A:
|
|
330
|
+
return (False, None)
|
|
331
|
+
|
|
332
|
+
if not self.app_app:
|
|
333
|
+
def error():
|
|
334
|
+
if self.in_repl:
|
|
335
|
+
log2('cd to an app first.')
|
|
336
|
+
else:
|
|
337
|
+
log2('* app is missing.')
|
|
338
|
+
log2()
|
|
339
|
+
display_help()
|
|
340
|
+
return (False, error)
|
|
341
|
+
|
|
342
|
+
elif required == RequiredState.EXPORT_DB:
|
|
343
|
+
if self.device not in [ReplState.C, ReplState.X]:
|
|
344
|
+
return (False, None)
|
|
345
|
+
|
|
346
|
+
if not self.export_session:
|
|
347
|
+
def error():
|
|
348
|
+
if self.in_repl:
|
|
349
|
+
if self.device == ReplState.C:
|
|
350
|
+
log2("Select an export database first with 'use' command.")
|
|
351
|
+
else:
|
|
352
|
+
log2('cd to an export database first.')
|
|
353
|
+
else:
|
|
354
|
+
log2('* export database is missing.')
|
|
355
|
+
log2()
|
|
356
|
+
display_help()
|
|
357
|
+
return (False, error)
|
|
165
358
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
if not pg.db:
|
|
359
|
+
elif required in [ReplState.L, ReplState.A, ReplState.C, ReplState.P, ReplState.X] and self.device != required:
|
|
360
|
+
def error():
|
|
169
361
|
if self.in_repl:
|
|
170
|
-
log2('
|
|
362
|
+
log2(f'Switch to {required}: first.')
|
|
171
363
|
else:
|
|
172
|
-
log2('*
|
|
364
|
+
log2('* on a wrong device.')
|
|
173
365
|
log2()
|
|
174
366
|
display_help()
|
|
367
|
+
return (False, error)
|
|
175
368
|
|
|
176
|
-
|
|
369
|
+
return (True, None)
|
|
177
370
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
371
|
+
def _validate_device(self, devices: list[RequiredState]):
|
|
372
|
+
if self.device not in devices:
|
|
373
|
+
def error():
|
|
374
|
+
if self.in_repl:
|
|
375
|
+
log2(f'Not a valid command on {self.device}: drive.')
|
|
376
|
+
else:
|
|
377
|
+
log2('* on a wrong device.')
|
|
378
|
+
log2()
|
|
379
|
+
display_help()
|
|
380
|
+
return (False, error)
|
|
187
381
|
|
|
188
|
-
return True
|
|
382
|
+
return (True, None)
|
|
189
383
|
|
|
190
384
|
def user_pass(self, secret_path = 'cql.secret'):
|
|
191
385
|
return Secrets.get_user_pass(self.pod if self.pod else self.sts, self.namespace, secret_path=secret_path)
|
|
192
386
|
|
|
193
387
|
def enter_bash(self, bash_session: BashSession):
|
|
388
|
+
self.push()
|
|
389
|
+
|
|
194
390
|
self.bash_session = bash_session
|
|
195
|
-
if self.device != ReplState.C:
|
|
196
|
-
self.device = ReplState.C
|
|
197
|
-
log2(f'Moved to {ReplState.C}: automatically. Will move back to {ReplState.P}: when you exit the bash session.')
|
|
198
391
|
|
|
199
392
|
def exit_bash(self):
|
|
200
|
-
|
|
201
|
-
self.device = self.bash_session.device
|
|
202
|
-
|
|
393
|
+
self.pop()
|
|
203
394
|
self.bash_session = None
|
|
204
395
|
|
|
205
|
-
def
|
|
206
|
-
if not self.
|
|
207
|
-
|
|
208
|
-
self.
|
|
396
|
+
def push(self, pod_targetted=False):
|
|
397
|
+
if not self.original_state:
|
|
398
|
+
self.original_state = copy(self)
|
|
399
|
+
self.pod_targetted = pod_targetted
|
|
400
|
+
|
|
401
|
+
def pop(self):
|
|
402
|
+
if o := self.original_state:
|
|
403
|
+
self.device = o.device
|
|
404
|
+
self.sts = o.sts
|
|
405
|
+
self.pod = o.pod
|
|
406
|
+
self.pg_path = o.pg_path
|
|
407
|
+
self.app_env = o.app_env
|
|
408
|
+
self.app_app = o.app_app
|
|
409
|
+
self.app_pod = o.app_pod
|
|
410
|
+
# self.export_session = o.export_session
|
|
411
|
+
self.namespace = o.namespace
|
|
412
|
+
|
|
413
|
+
self.original_state = None
|
|
414
|
+
self.pod_targetted = False
|
|
415
|
+
|
|
416
|
+
def pg_host_n_database(self):
|
|
417
|
+
host = None
|
|
418
|
+
database = None
|
|
419
|
+
|
|
420
|
+
if self.pg_path:
|
|
421
|
+
host_n_db = self.pg_path.split('/')
|
|
422
|
+
host = host_n_db[0]
|
|
423
|
+
if len(host_n_db) > 1:
|
|
424
|
+
database = host_n_db[1]
|
|
425
|
+
|
|
426
|
+
return host, database
|
|
427
|
+
|
|
428
|
+
def with_no_pod(self):
|
|
429
|
+
state1 = copy(self)
|
|
430
|
+
state1.pod = None
|
|
431
|
+
|
|
432
|
+
return state1
|
|
433
|
+
|
|
434
|
+
class DevicePodService:
|
|
435
|
+
def __init__(self, handler: 'DeviceExecHandler'):
|
|
436
|
+
self.handler = handler
|
|
437
|
+
|
|
438
|
+
def exec(self, command: str, action='bash', show_out = True):
|
|
439
|
+
state = self.handler.state
|
|
440
|
+
|
|
441
|
+
rs = None
|
|
442
|
+
if state.device == ReplState.A and state.app_app:
|
|
443
|
+
if state.app_pod:
|
|
444
|
+
rs = [AppPods.exec(state.app_pod, state.namespace, command, show_out=show_out)]
|
|
445
|
+
else:
|
|
446
|
+
pods = AppPods.pod_names(state.namespace, state.app_env, state.app_app)
|
|
447
|
+
rs = AppClusters.exec(pods, state.namespace, command, show_out=show_out)
|
|
448
|
+
elif state.pod:
|
|
449
|
+
rs = [CassandraNodes.exec(state.pod, state.namespace, command, show_out=show_out)]
|
|
450
|
+
elif state.sts:
|
|
451
|
+
rs = CassandraClusters.exec(state.sts, state.namespace, command, action=action, show_out=show_out)
|
|
452
|
+
# assume that pg-agent or ops pod is single pod
|
|
453
|
+
|
|
454
|
+
dir = None
|
|
455
|
+
if rs:
|
|
456
|
+
for r in rs:
|
|
457
|
+
if r.exit_code(): # if fails to read the session file, ignore
|
|
458
|
+
continue
|
|
459
|
+
|
|
460
|
+
dir0 = r.stdout.strip(' \r\n')
|
|
461
|
+
if dir:
|
|
462
|
+
if dir != dir0:
|
|
463
|
+
log2('Inconsitent working dir found across multiple pods.')
|
|
464
|
+
return None
|
|
465
|
+
else:
|
|
466
|
+
dir = dir0
|
|
467
|
+
|
|
468
|
+
return dir
|
|
469
|
+
|
|
470
|
+
class DeviceExecHandler:
|
|
471
|
+
def __init__(self, state: ReplState):
|
|
472
|
+
self.state = state
|
|
473
|
+
|
|
474
|
+
def __enter__(self):
|
|
475
|
+
return DevicePodService(self)
|
|
476
|
+
|
|
477
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
478
|
+
return False
|
|
209
479
|
|
|
210
|
-
|
|
211
|
-
|
|
480
|
+
def device(state: ReplState):
|
|
481
|
+
return DeviceExecHandler(state)
|
adam/sql/__init__.py
ADDED
|
File without changes
|