kaqing 2.0.52__py3-none-any.whl → 2.0.184__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 +15 -19
- 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 +37 -63
- 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 +98 -0
- adam/commands/audit/audit.py +81 -0
- adam/commands/audit/audit_repair_tables.py +72 -0
- adam/commands/audit/audit_run.py +50 -0
- adam/commands/audit/show_last10.py +37 -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 -89
- adam/commands/check.py +18 -21
- adam/commands/cli_commands.py +5 -6
- adam/commands/clipboard_copy.py +86 -0
- adam/commands/code.py +57 -0
- adam/commands/command.py +197 -35
- adam/commands/commands_utils.py +15 -31
- adam/commands/cql/cql_completions.py +29 -8
- adam/commands/cql/cqlsh.py +12 -27
- adam/commands/cql/utils_cql.py +297 -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 -21
- adam/commands/deploy/deploy_frontend.py +14 -17
- adam/commands/deploy/deploy_pg_agent.py +3 -6
- adam/commands/deploy/deploy_pod.py +71 -79
- adam/commands/deploy/deploy_utils.py +16 -26
- adam/commands/deploy/undeploy.py +4 -21
- adam/commands/deploy/undeploy_frontend.py +4 -7
- adam/commands/deploy/undeploy_pg_agent.py +6 -8
- adam/commands/deploy/undeploy_pod.py +15 -16
- adam/commands/devices/__init__.py +0 -0
- adam/commands/devices/device.py +123 -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 +84 -0
- adam/commands/devices/device_postgres.py +150 -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/download_export_session.py +39 -0
- adam/commands/export/drop_export_database.py +39 -0
- adam/commands/export/drop_export_databases.py +37 -0
- adam/commands/export/export.py +53 -0
- adam/commands/export/export_databases.py +245 -0
- adam/commands/export/export_select.py +59 -0
- adam/commands/export/export_select_x.py +54 -0
- adam/commands/export/export_sessions.py +209 -0
- adam/commands/export/export_use.py +49 -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 +177 -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 +38 -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 +343 -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 +49 -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 -110
- adam/commands/medusa/medusa.py +4 -22
- adam/commands/medusa/medusa_backup.py +22 -29
- adam/commands/medusa/medusa_restore.py +40 -39
- adam/commands/medusa/medusa_show_backupjobs.py +19 -20
- adam/commands/medusa/medusa_show_restorejobs.py +15 -20
- adam/commands/nodetool.py +11 -15
- adam/commands/param_get.py +11 -14
- adam/commands/param_set.py +8 -12
- adam/commands/postgres/postgres.py +45 -46
- adam/commands/postgres/postgres_databases.py +269 -0
- adam/commands/postgres/postgres_ls.py +4 -8
- adam/commands/postgres/postgres_preview.py +5 -9
- adam/commands/postgres/psql_completions.py +4 -3
- adam/commands/postgres/utils_postgres.py +70 -0
- adam/commands/preview_table.py +10 -61
- adam/commands/pwd.py +14 -43
- adam/commands/reaper/reaper.py +4 -24
- 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 +9 -32
- adam/commands/reaper/reaper_schedule_start.py +9 -32
- adam/commands/reaper/reaper_schedule_stop.py +9 -32
- adam/commands/reaper/reaper_schedules.py +4 -14
- adam/commands/reaper/reaper_status.py +8 -16
- adam/commands/reaper/utils_reaper.py +194 -0
- adam/commands/repair/repair.py +4 -22
- adam/commands/repair/repair_log.py +6 -12
- adam/commands/repair/repair_run.py +29 -36
- adam/commands/repair/repair_scan.py +33 -39
- adam/commands/repair/repair_stop.py +6 -12
- 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 +11 -23
- adam/commands/show/show_adam.py +3 -3
- adam/commands/show/show_cassandra_repairs.py +35 -0
- adam/commands/show/show_cassandra_status.py +34 -52
- adam/commands/show/show_cassandra_version.py +5 -18
- adam/commands/show/show_commands.py +20 -25
- 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 +16 -20
- adam/commands/show/show_storage.py +10 -20
- adam/commands/watch.py +27 -30
- adam/config.py +7 -15
- adam/embedded_params.py +1 -1
- adam/log.py +4 -4
- adam/pod_exec_result.py +13 -5
- adam/repl.py +126 -119
- adam/repl_commands.py +63 -29
- adam/repl_state.py +320 -71
- adam/sql/sql_completer.py +98 -383
- adam/sql/sql_state_machine.py +630 -0
- adam/sql/term_completer.py +14 -4
- adam/sso/authn_ad.py +6 -8
- adam/sso/authn_okta.py +4 -6
- adam/sso/cred_cache.py +4 -6
- adam/sso/idp.py +10 -13
- adam/utils.py +511 -10
- 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 +11 -4
- 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 +87 -0
- adam/{k8s_utils → utils_k8s}/kube_context.py +2 -2
- adam/{k8s_utils → utils_k8s}/pods.py +109 -74
- 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 +3 -14
- adam/utils_local.py +4 -0
- adam/utils_net.py +24 -0
- 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.52.dist-info → kaqing-2.0.184.dist-info}/METADATA +1 -1
- kaqing-2.0.184.dist-info/RECORD +244 -0
- adam/commands/app.py +0 -67
- adam/commands/bash.py +0 -87
- adam/commands/cp.py +0 -95
- adam/commands/cql/cql_table_completer.py +0 -8
- adam/commands/cql/cql_utils.py +0 -109
- adam/commands/describe/describe.py +0 -46
- adam/commands/describe/describe_keyspace.py +0 -60
- adam/commands/describe/describe_keyspaces.py +0 -50
- adam/commands/describe/describe_table.py +0 -60
- adam/commands/describe/describe_tables.py +0 -50
- adam/commands/devices.py +0 -89
- adam/commands/postgres/postgres_session.py +0 -240
- adam/commands/postgres/postgres_utils.py +0 -31
- adam/commands/postgres/psql_table_completer.py +0 -11
- adam/commands/reaper/reaper_session.py +0 -159
- adam/commands/show/show_app_actions.py +0 -53
- adam/commands/show/show_repairs.py +0 -47
- adam/k8s_utils/cassandra_clusters.py +0 -35
- adam/sql/sql_utils.py +0 -5
- kaqing-2.0.52.dist-info/RECORD +0 -184
- /adam/commands/{describe → app}/__init__.py +0 -0
- /adam/{k8s_utils → commands/audit}/__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.52.dist-info → kaqing-2.0.184.dist-info}/WHEEL +0 -0
- {kaqing-2.0.52.dist-info → kaqing-2.0.184.dist-info}/entry_points.txt +0 -0
- {kaqing-2.0.52.dist-info → kaqing-2.0.184.dist-info}/top_level.txt +0 -0
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,15 @@ 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
|
-
|
|
63
|
+
self.original_state: ReplState = None
|
|
64
|
+
|
|
65
|
+
self.export_session: str = None
|
|
71
66
|
|
|
72
67
|
if ns_sts:
|
|
73
68
|
nn = ns_sts.split('@')
|
|
@@ -82,13 +77,51 @@ class ReplState:
|
|
|
82
77
|
def __hash__(self):
|
|
83
78
|
return hash((self.sts, self.pod))
|
|
84
79
|
|
|
85
|
-
def
|
|
80
|
+
def __str__(self):
|
|
81
|
+
msg = ''
|
|
82
|
+
if self.device == ReplState.P:
|
|
83
|
+
msg = f'{ReplState.P}:'
|
|
84
|
+
host, database = self.pg_host_n_database()
|
|
85
|
+
if database:
|
|
86
|
+
msg += database
|
|
87
|
+
elif host:
|
|
88
|
+
msg += host
|
|
89
|
+
elif self.device == ReplState.A:
|
|
90
|
+
msg = f'{ReplState.A}:'
|
|
91
|
+
if self.app_env:
|
|
92
|
+
msg += self.app_env
|
|
93
|
+
if self.app_app:
|
|
94
|
+
msg += f'/{self.app_app}'
|
|
95
|
+
if self.app_pod:
|
|
96
|
+
# azops88-c3-c3-k8sdeploy-appleader-001-79957cf5b6-9k4bw
|
|
97
|
+
group = re.match(r".*?-.*?-.*?-.*?-(.*?-.*?)-.*", self.app_pod)
|
|
98
|
+
msg += '/' + group[1]
|
|
99
|
+
elif self.device == ReplState.L:
|
|
100
|
+
msg = f'{ReplState.L}:'
|
|
101
|
+
elif self.device == ReplState.X:
|
|
102
|
+
msg = f'{ReplState.X}:'
|
|
103
|
+
if self.export_session:
|
|
104
|
+
msg += self.export_session
|
|
105
|
+
else:
|
|
106
|
+
msg = f'{ReplState.C}:'
|
|
107
|
+
if self.pod:
|
|
108
|
+
# cs-d0767a536f-cs-d0767a536f-default-sts-0
|
|
109
|
+
group = re.match(r".*?-.*?-(.*)", self.pod)
|
|
110
|
+
msg += group[1]
|
|
111
|
+
elif self.sts:
|
|
112
|
+
# cs-d0767a536f-cs-d0767a536f-default-sts
|
|
113
|
+
group = re.match(r".*?-.*?-(.*)", self.sts)
|
|
114
|
+
msg += group[1]
|
|
115
|
+
|
|
116
|
+
return msg
|
|
117
|
+
|
|
118
|
+
def apply_args(self, args: list[str], cmd: list[str] = None, resolve_pg = True, args_to_check = 6) -> tuple['ReplState', list[str]]:
|
|
86
119
|
state = self
|
|
87
120
|
|
|
88
121
|
new_args = []
|
|
89
122
|
for index, arg in enumerate(args):
|
|
90
|
-
if index <
|
|
91
|
-
state = copy
|
|
123
|
+
if index < args_to_check:
|
|
124
|
+
state = copy(state)
|
|
92
125
|
|
|
93
126
|
s, n = KubeContext.is_sts_name(arg)
|
|
94
127
|
if s:
|
|
@@ -126,10 +159,36 @@ class ReplState:
|
|
|
126
159
|
new_args = []
|
|
127
160
|
for index, arg in enumerate(args):
|
|
128
161
|
if index < 6:
|
|
129
|
-
state = copy
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
162
|
+
state = copy(state)
|
|
163
|
+
|
|
164
|
+
groups = re.match(r'^([a|c|l|p|x]):(.*)$', arg)
|
|
165
|
+
if groups:
|
|
166
|
+
if groups[1] == 'p':
|
|
167
|
+
state.device = 'p'
|
|
168
|
+
state.pg_path = groups[2]
|
|
169
|
+
elif groups[1] == 'c':
|
|
170
|
+
state.device = 'c'
|
|
171
|
+
if path := groups[2]:
|
|
172
|
+
p_and_ns = path.split('@')
|
|
173
|
+
sts_and_pod = p_and_ns[0].split('/')
|
|
174
|
+
state.sts = sts_and_pod[0]
|
|
175
|
+
if len(sts_and_pod) > 1:
|
|
176
|
+
state.pod = sts_and_pod[1]
|
|
177
|
+
if len(p_and_ns) > 1:
|
|
178
|
+
state.namespace = p_and_ns[1]
|
|
179
|
+
elif ns := KubeContext.in_cluster_namespace():
|
|
180
|
+
state.namespace = ns
|
|
181
|
+
elif groups[1] == 'l':
|
|
182
|
+
state.device = 'l'
|
|
183
|
+
elif groups[1] == 'x':
|
|
184
|
+
state.device = 'x'
|
|
185
|
+
else:
|
|
186
|
+
state.device = 'a'
|
|
187
|
+
if path := groups[2]:
|
|
188
|
+
env_and_app = path.split('/')
|
|
189
|
+
state.app_env = env_and_app[0]
|
|
190
|
+
if len(env_and_app) > 1:
|
|
191
|
+
state.app_app = env_and_app[1]
|
|
133
192
|
else:
|
|
134
193
|
new_args.append(arg)
|
|
135
194
|
else:
|
|
@@ -140,84 +199,274 @@ class ReplState:
|
|
|
140
199
|
|
|
141
200
|
return (state, new_args)
|
|
142
201
|
|
|
143
|
-
def validate(self, required: RequiredState =
|
|
144
|
-
if not
|
|
145
|
-
|
|
146
|
-
|
|
202
|
+
def validate(self, required: list[RequiredState] = [], show_err = True):
|
|
203
|
+
if not required:
|
|
204
|
+
return True
|
|
205
|
+
|
|
206
|
+
def default_err():
|
|
207
|
+
if self.in_repl:
|
|
208
|
+
log2(f'Not a valid command on {self.device}: drive.')
|
|
209
|
+
else:
|
|
210
|
+
log2('* on a wrong device.')
|
|
211
|
+
log2()
|
|
212
|
+
display_help()
|
|
213
|
+
|
|
214
|
+
if type(required) is not list:
|
|
215
|
+
valid, err = self._validate(required)
|
|
216
|
+
if valid:
|
|
217
|
+
return True
|
|
218
|
+
|
|
219
|
+
if show_err:
|
|
220
|
+
if err:
|
|
221
|
+
err()
|
|
222
|
+
else:
|
|
223
|
+
default_err()
|
|
224
|
+
|
|
225
|
+
return False
|
|
226
|
+
|
|
227
|
+
devices = [r for r in required if r in [ReplState.L, ReplState.A, ReplState.C, ReplState.P, ReplState.X]]
|
|
228
|
+
non_devices = [r for r in required if r not in [ReplState.L, ReplState.A, ReplState.C, ReplState.P, ReplState.X]]
|
|
229
|
+
|
|
230
|
+
first_error: Callable = None
|
|
231
|
+
for r in non_devices:
|
|
232
|
+
valid, err = self._validate(r)
|
|
233
|
+
if valid:
|
|
234
|
+
return True
|
|
235
|
+
|
|
236
|
+
if not first_error:
|
|
237
|
+
first_error = err
|
|
238
|
+
|
|
239
|
+
if devices:
|
|
240
|
+
valid, err = self._validate_device(devices)
|
|
241
|
+
if valid:
|
|
242
|
+
return True
|
|
243
|
+
|
|
244
|
+
if not first_error:
|
|
245
|
+
first_error = err
|
|
246
|
+
|
|
247
|
+
if show_err and first_error:
|
|
248
|
+
if first_error:
|
|
249
|
+
first_error()
|
|
250
|
+
else:
|
|
251
|
+
default_err()
|
|
252
|
+
|
|
253
|
+
return False
|
|
254
|
+
|
|
255
|
+
def _validate(self, required: RequiredState):
|
|
256
|
+
if required == RequiredState.CLUSTER:
|
|
257
|
+
if self.device != ReplState.C:
|
|
258
|
+
return (False, None)
|
|
259
|
+
|
|
260
|
+
if not self.namespace or not self.sts:
|
|
261
|
+
def error():
|
|
147
262
|
if self.in_repl:
|
|
148
263
|
log2('cd to a Cassandra cluster first.')
|
|
149
264
|
else:
|
|
150
265
|
log2('* Cassandra cluster is missing.')
|
|
151
266
|
log2()
|
|
152
267
|
display_help()
|
|
268
|
+
return (False, error)
|
|
269
|
+
|
|
270
|
+
elif required == RequiredState.POD:
|
|
271
|
+
if self.device != ReplState.C:
|
|
272
|
+
return (False, None)
|
|
153
273
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
if not self.namespace or not self.pod:
|
|
274
|
+
if not self.namespace or not self.pod:
|
|
275
|
+
def error():
|
|
157
276
|
if self.in_repl:
|
|
158
277
|
log2('cd to a pod first.')
|
|
159
278
|
else:
|
|
160
279
|
log2('* Pod is missing.')
|
|
161
280
|
log2()
|
|
162
281
|
display_help()
|
|
282
|
+
return (False, error)
|
|
163
283
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
284
|
+
elif required == RequiredState.CLUSTER_OR_POD:
|
|
285
|
+
if self.device != ReplState.C:
|
|
286
|
+
return (False, None)
|
|
287
|
+
|
|
288
|
+
if not self.namespace or not self.sts and not self.pod:
|
|
289
|
+
def error():
|
|
167
290
|
if self.in_repl:
|
|
168
291
|
log2('cd to a Cassandra cluster first.')
|
|
169
292
|
else:
|
|
170
293
|
log2('* Cassandra cluster or pod is missing.')
|
|
171
294
|
log2()
|
|
172
295
|
display_help()
|
|
296
|
+
return (False, error)
|
|
297
|
+
|
|
298
|
+
elif required == RequiredState.NAMESPACE:
|
|
299
|
+
if self.device != ReplState.C:
|
|
300
|
+
return (False, None)
|
|
173
301
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
if not self.namespace:
|
|
302
|
+
if not self.namespace:
|
|
303
|
+
def error():
|
|
177
304
|
if self.in_repl:
|
|
178
305
|
log2('Namespace is required.')
|
|
179
306
|
else:
|
|
180
307
|
log2('* namespace is missing.')
|
|
181
308
|
log2()
|
|
182
309
|
display_help()
|
|
310
|
+
return (False, error)
|
|
183
311
|
|
|
184
|
-
|
|
312
|
+
elif required == RequiredState.PG_DATABASE:
|
|
313
|
+
if self.device != ReplState.P:
|
|
314
|
+
return (False, None)
|
|
185
315
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
316
|
+
_, database = self.pg_host_n_database()
|
|
317
|
+
if not database:
|
|
318
|
+
def error():
|
|
319
|
+
if self.in_repl:
|
|
320
|
+
log2('cd to a database first.')
|
|
321
|
+
else:
|
|
322
|
+
log2('* database is missing.')
|
|
323
|
+
log2()
|
|
324
|
+
display_help()
|
|
325
|
+
return (False, error)
|
|
326
|
+
|
|
327
|
+
elif required == RequiredState.APP_APP:
|
|
328
|
+
if self.device != ReplState.A:
|
|
329
|
+
return (False, None)
|
|
330
|
+
|
|
331
|
+
if not self.app_app:
|
|
332
|
+
def error():
|
|
333
|
+
if self.in_repl:
|
|
334
|
+
log2('cd to an app first.')
|
|
335
|
+
else:
|
|
336
|
+
log2('* app is missing.')
|
|
337
|
+
log2()
|
|
338
|
+
display_help()
|
|
339
|
+
return (False, error)
|
|
340
|
+
|
|
341
|
+
elif required == RequiredState.EXPORT_DB:
|
|
342
|
+
if self.device not in [ReplState.C, ReplState.X]:
|
|
343
|
+
return (False, None)
|
|
344
|
+
|
|
345
|
+
if not self.export_session:
|
|
346
|
+
def error():
|
|
347
|
+
if self.in_repl:
|
|
348
|
+
if self.device == ReplState.C:
|
|
349
|
+
log2("Select an export database first with 'use' command.")
|
|
350
|
+
else:
|
|
351
|
+
log2('cd to an export database first.')
|
|
352
|
+
else:
|
|
353
|
+
log2('* export database is missing.')
|
|
354
|
+
log2()
|
|
355
|
+
display_help()
|
|
356
|
+
return (False, error)
|
|
357
|
+
|
|
358
|
+
elif required in [ReplState.L, ReplState.A, ReplState.C, ReplState.P, ReplState.X] and self.device != required:
|
|
359
|
+
def error():
|
|
189
360
|
if self.in_repl:
|
|
190
|
-
log2('
|
|
361
|
+
log2(f'Switch to {required}: first.')
|
|
191
362
|
else:
|
|
192
|
-
log2('*
|
|
363
|
+
log2('* on a wrong device.')
|
|
193
364
|
log2()
|
|
194
365
|
display_help()
|
|
366
|
+
return (False, error)
|
|
195
367
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
if app_required == RequiredState.APP_APP and not self.app_app:
|
|
199
|
-
if self.in_repl:
|
|
200
|
-
log2('cd to an app first.')
|
|
201
|
-
else:
|
|
202
|
-
log2('* app is missing.')
|
|
203
|
-
log2()
|
|
204
|
-
display_help()
|
|
368
|
+
return (True, None)
|
|
205
369
|
|
|
206
|
-
|
|
370
|
+
def _validate_device(self, devices: list[RequiredState]):
|
|
371
|
+
if self.device not in devices:
|
|
372
|
+
def error():
|
|
373
|
+
if self.in_repl:
|
|
374
|
+
log2(f'Not a valid command on {self.device}: drive.')
|
|
375
|
+
else:
|
|
376
|
+
log2('* on a wrong device.')
|
|
377
|
+
log2()
|
|
378
|
+
display_help()
|
|
379
|
+
return (False, error)
|
|
207
380
|
|
|
208
|
-
return True
|
|
381
|
+
return (True, None)
|
|
209
382
|
|
|
210
383
|
def user_pass(self, secret_path = 'cql.secret'):
|
|
211
384
|
return Secrets.get_user_pass(self.pod if self.pod else self.sts, self.namespace, secret_path=secret_path)
|
|
212
385
|
|
|
213
386
|
def enter_bash(self, bash_session: BashSession):
|
|
387
|
+
self.push()
|
|
388
|
+
|
|
214
389
|
self.bash_session = bash_session
|
|
215
|
-
if self.device != ReplState.C:
|
|
216
|
-
self.device = ReplState.C
|
|
217
|
-
log2(f'Moved to {ReplState.C}: automatically. Will move back to {ReplState.P}: when you exit the bash session.')
|
|
218
390
|
|
|
219
391
|
def exit_bash(self):
|
|
220
|
-
|
|
221
|
-
|
|
392
|
+
self.pop()
|
|
393
|
+
self.bash_session = None
|
|
394
|
+
|
|
395
|
+
def push(self):
|
|
396
|
+
if not self.original_state:
|
|
397
|
+
self.original_state = copy(self)
|
|
398
|
+
|
|
399
|
+
def pop(self):
|
|
400
|
+
if o := self.original_state:
|
|
401
|
+
self.device = o.device
|
|
402
|
+
self.sts = o.sts
|
|
403
|
+
self.pod = o.pod
|
|
404
|
+
self.pg_path = o.pg_path
|
|
405
|
+
self.app_env = o.app_env
|
|
406
|
+
self.app_app = o.app_app
|
|
407
|
+
self.app_pod = o.app_pod
|
|
408
|
+
# self.export_session = o.export_session
|
|
409
|
+
self.namespace = o.namespace
|
|
410
|
+
|
|
411
|
+
self.original_state = None
|
|
412
|
+
|
|
413
|
+
def pg_host_n_database(self):
|
|
414
|
+
host = None
|
|
415
|
+
database = None
|
|
416
|
+
|
|
417
|
+
if self.pg_path:
|
|
418
|
+
host_n_db = self.pg_path.split('/')
|
|
419
|
+
host = host_n_db[0]
|
|
420
|
+
if len(host_n_db) > 1:
|
|
421
|
+
database = host_n_db[1]
|
|
422
|
+
|
|
423
|
+
return host, database
|
|
424
|
+
|
|
425
|
+
class DevicePodService:
|
|
426
|
+
def __init__(self, handler: 'DeviceExecHandler'):
|
|
427
|
+
self.handler = handler
|
|
428
|
+
|
|
429
|
+
def exec(self, command: str, action='bash', show_out = True):
|
|
430
|
+
state = self.handler.state
|
|
431
|
+
|
|
432
|
+
rs = None
|
|
433
|
+
if state.device == ReplState.A and state.app_app:
|
|
434
|
+
if state.app_pod:
|
|
435
|
+
rs = [AppPods.exec(state.app_pod, state.namespace, command, show_out=show_out)]
|
|
436
|
+
else:
|
|
437
|
+
pods = AppPods.pod_names(state.namespace, state.app_env, state.app_app)
|
|
438
|
+
rs = AppClusters.exec(pods, state.namespace, command, show_out=show_out)
|
|
439
|
+
elif state.pod:
|
|
440
|
+
rs = [CassandraNodes.exec(state.pod, state.namespace, command, show_out=show_out)]
|
|
441
|
+
elif state.sts:
|
|
442
|
+
rs = CassandraClusters.exec(state.sts, state.namespace, command, action=action, show_out=show_out)
|
|
443
|
+
# assume that pg-agent or ops pod is single pod
|
|
444
|
+
|
|
445
|
+
dir = None
|
|
446
|
+
if rs:
|
|
447
|
+
for r in rs:
|
|
448
|
+
if r.exit_code(): # if fails to read the session file, ignore
|
|
449
|
+
continue
|
|
450
|
+
|
|
451
|
+
dir0 = r.stdout.strip(' \r\n')
|
|
452
|
+
if dir:
|
|
453
|
+
if dir != dir0:
|
|
454
|
+
log2('Inconsitent working dir found across multiple pods.')
|
|
455
|
+
return None
|
|
456
|
+
else:
|
|
457
|
+
dir = dir0
|
|
458
|
+
|
|
459
|
+
return dir
|
|
460
|
+
|
|
461
|
+
class DeviceExecHandler:
|
|
462
|
+
def __init__(self, state: ReplState):
|
|
463
|
+
self.state = state
|
|
464
|
+
|
|
465
|
+
def __enter__(self):
|
|
466
|
+
return DevicePodService(self)
|
|
467
|
+
|
|
468
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
469
|
+
return False
|
|
222
470
|
|
|
223
|
-
|
|
471
|
+
def device(state: ReplState):
|
|
472
|
+
return DeviceExecHandler(state)
|