kaqing 2.0.184__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/app_session.py +1 -1
- adam/batch.py +15 -15
- adam/commands/app/app.py +2 -2
- adam/commands/app/show_app_actions.py +1 -1
- adam/commands/{show → app}/show_login.py +1 -1
- adam/commands/app/utils_app.py +9 -1
- adam/commands/audit/audit.py +6 -20
- adam/commands/audit/audit_repair_tables.py +1 -1
- adam/commands/audit/audit_run.py +1 -1
- adam/commands/audit/completions_l.py +15 -0
- adam/commands/audit/show_last10.py +0 -1
- adam/commands/bash/bash.py +1 -1
- adam/commands/bash/utils_bash.py +1 -1
- adam/commands/cassandra/download_cassandra_log.py +45 -0
- adam/commands/cassandra/restart_cluster.py +47 -0
- adam/commands/cassandra/restart_node.py +51 -0
- adam/commands/cassandra/restart_nodes.py +47 -0
- adam/commands/{rollout.py → cassandra/rollout.py} +1 -1
- adam/commands/{show → cassandra}/show_cassandra_repairs.py +5 -3
- adam/commands/{show → cassandra}/show_cassandra_status.py +22 -15
- adam/commands/cassandra/show_processes.py +50 -0
- adam/commands/{show → cassandra}/show_storage.py +10 -8
- adam/commands/cli/__init__.py +0 -0
- adam/commands/{cli_commands.py → cli/cli_commands.py} +6 -1
- adam/commands/{clipboard_copy.py → cli/clipboard_copy.py} +2 -2
- adam/commands/{show/show_commands.py → cli/show_cli_commands.py} +2 -2
- adam/commands/command.py +22 -9
- adam/commands/commands_utils.py +14 -6
- adam/commands/config/__init__.py +0 -0
- adam/commands/{show → config}/show_params.py +1 -1
- adam/commands/{alter_tables.py → cql/alter_tables.py} +1 -1
- adam/commands/cql/completions_c.py +29 -0
- adam/commands/cql/cqlsh.py +2 -6
- adam/commands/cql/utils_cql.py +26 -17
- 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/devices/device.py +30 -4
- adam/commands/devices/device_app.py +1 -1
- adam/commands/devices/device_export.py +5 -2
- adam/commands/devices/device_postgres.py +13 -3
- adam/commands/devices/devices.py +1 -1
- adam/commands/diag/__init__.py +0 -0
- adam/commands/{check.py → diag/check.py} +1 -1
- adam/commands/diag/generate_report.py +52 -0
- adam/commands/export/completions_x.py +11 -0
- adam/commands/export/download_export_session.py +2 -1
- adam/commands/export/export.py +0 -16
- adam/commands/export/export_databases.py +16 -10
- adam/commands/export/export_select.py +8 -33
- adam/commands/export/export_sessions.py +12 -11
- adam/commands/export/export_use.py +3 -3
- adam/commands/export/export_x_select.py +48 -0
- adam/commands/export/exporter.py +140 -53
- adam/commands/export/import_files.py +2 -2
- adam/commands/export/import_session.py +0 -4
- adam/commands/export/importer.py +11 -11
- adam/commands/export/importer_athena.py +15 -35
- adam/commands/export/importer_sqlite.py +19 -8
- adam/commands/export/show_column_counts.py +10 -10
- adam/commands/export/show_export_databases.py +2 -1
- adam/commands/export/show_export_session.py +1 -1
- adam/commands/export/show_export_sessions.py +1 -1
- adam/commands/export/utils_export.py +38 -15
- adam/commands/fs/__init__.py +0 -0
- adam/commands/{cat.py → fs/cat.py} +2 -2
- adam/commands/fs/cat_local.py +42 -0
- adam/commands/{cd.py → fs/cd.py} +2 -2
- adam/commands/{download_file.py → fs/download_file.py} +5 -5
- adam/commands/{find_files.py → fs/find_files.py} +4 -4
- adam/commands/{find_processes.py → fs/find_processes.py} +3 -3
- adam/commands/{head.py → fs/head.py} +2 -2
- adam/commands/{ls.py → fs/ls.py} +2 -2
- adam/commands/fs/ls_local.py +40 -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/{show → fs}/show_adam.py +1 -1
- adam/commands/intermediate_command.py +3 -0
- adam/commands/medusa/medusa_restore.py +2 -16
- adam/commands/medusa/utils_medusa.py +15 -0
- adam/commands/nodetool/__init__.py +0 -0
- adam/commands/{nodetool.py → nodetool/nodetool.py} +3 -8
- adam/commands/postgres/completions_p.py +22 -0
- adam/commands/postgres/postgres.py +7 -14
- adam/commands/postgres/postgres_databases.py +3 -3
- adam/commands/postgres/postgres_ls.py +1 -1
- adam/commands/postgres/utils_postgres.py +12 -2
- adam/commands/preview_table.py +1 -1
- adam/commands/reaper/reaper_schedule_activate.py +6 -2
- adam/commands/reaper/reaper_schedule_start.py +1 -2
- adam/commands/reaper/reaper_schedule_stop.py +1 -2
- adam/commands/reaper/utils_reaper.py +10 -1
- adam/commands/repair/repair_scan.py +0 -2
- adam/commands/repair/repair_stop.py +0 -1
- adam/commands/{show/show.py → show.py} +12 -11
- adam/config.py +4 -5
- adam/embedded_params.py +1 -1
- adam/repl.py +22 -9
- adam/repl_commands.py +50 -42
- adam/repl_session.py +9 -1
- adam/repl_state.py +16 -1
- 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/sso/cred_cache.py +2 -5
- adam/utils.py +216 -79
- adam/utils_k8s/app_clusters.py +11 -4
- adam/utils_k8s/app_pods.py +10 -5
- adam/utils_k8s/cassandra_clusters.py +8 -4
- adam/utils_k8s/cassandra_nodes.py +14 -5
- adam/utils_k8s/k8s.py +9 -0
- adam/utils_k8s/kube_context.py +1 -4
- adam/{pod_exec_result.py → utils_k8s/pod_exec_result.py} +8 -2
- adam/utils_k8s/pods.py +83 -24
- adam/utils_k8s/statefulsets.py +5 -2
- adam/utils_local.py +78 -2
- adam/utils_repl/appendable_completer.py +6 -0
- adam/utils_repl/repl_completer.py +51 -4
- adam/utils_sqlite.py +3 -8
- adam/version.py +1 -1
- {kaqing-2.0.184.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/cql/cql_completions.py +0 -32
- adam/commands/export/export_select_x.py +0 -54
- adam/commands/logs.py +0 -37
- adam/commands/postgres/psql_completions.py +0 -11
- adam/commands/report.py +0 -61
- adam/commands/restart.py +0 -60
- adam/commands/show/show_processes.py +0 -49
- kaqing-2.0.184.dist-info/RECORD +0 -244
- kaqing-2.0.184.dist-info/top_level.txt +0 -1
- /adam/commands/{login.py → app/login.py} +0 -0
- /adam/commands/{show → cassandra}/__init__.py +0 -0
- /adam/commands/{show → cassandra}/show_cassandra_version.py +0 -0
- /adam/commands/{watch.py → cassandra/watch.py} +0 -0
- /adam/commands/{param_get.py → config/param_get.py} +0 -0
- /adam/commands/{param_set.py → config/param_set.py} +0 -0
- /adam/commands/{issues.py → diag/issues.py} +0 -0
- /adam/commands/{pwd.py → fs/pwd.py} +0 -0
- /adam/commands/{shell.py → fs/shell.py} +0 -0
- /adam/commands/{show → fs}/show_host.py +0 -0
- /adam/commands/{nodetool_commands.py → nodetool/nodetool_commands.py} +0 -0
- {kaqing-2.0.184.dist-info → kaqing-2.0.214.dist-info}/WHEEL +0 -0
- {kaqing-2.0.184.dist-info → kaqing-2.0.214.dist-info}/entry_points.txt +0 -0
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import io
|
|
2
|
+
import os
|
|
2
3
|
import re
|
|
3
4
|
|
|
4
5
|
from adam.config import Config
|
|
5
|
-
from adam.
|
|
6
|
+
from adam.utils import ExecResult, creating_dir, log2
|
|
6
7
|
from adam.repl_state import ReplState
|
|
7
8
|
from adam.utils_k8s.cassandra_nodes import CassandraNodes
|
|
8
|
-
from adam.utils_k8s.pods import log_prefix
|
|
9
9
|
from adam.utils_k8s.statefulsets import StatefulSets
|
|
10
|
+
from adam.utils_local import local_exec
|
|
10
11
|
|
|
11
12
|
class ImportSpec:
|
|
12
13
|
def __init__(self, table_name: str, session: str = None, files: list[str] = None, importer: str = None):
|
|
@@ -196,7 +197,7 @@ class ExportTableStatus:
|
|
|
196
197
|
statuses: list[ExportTableStatus] = []
|
|
197
198
|
|
|
198
199
|
status_in_whole = 'done'
|
|
199
|
-
log_files: list[str] = find_files(pod, namespace, f'{
|
|
200
|
+
log_files: list[str] = find_files(pod, namespace, f'{export_log_dir()}/{export_session}_*.log*')
|
|
200
201
|
|
|
201
202
|
for log_file in log_files:
|
|
202
203
|
status: ExportTableStatus = ExportTableStatus.from_log_file(pod, namespace, export_session, log_file)
|
|
@@ -211,7 +212,7 @@ class ExportTableStatus:
|
|
|
211
212
|
def get_csv_files_n_table(target_table: str):
|
|
212
213
|
db = f'{copy_session}_{target_table}'
|
|
213
214
|
csv_file = f'{csv_dir()}/{db}/*.csv'
|
|
214
|
-
csv_files: list[str] = find_files(pod, namespace, csv_file)
|
|
215
|
+
csv_files: list[str] = find_files(pod, namespace, csv_file, remote=True)
|
|
215
216
|
if csv_files:
|
|
216
217
|
table = target_table
|
|
217
218
|
m = re.match(f'{csv_dir()}/{db}/(.*).csv', csv_files[0])
|
|
@@ -221,7 +222,7 @@ class ExportTableStatus:
|
|
|
221
222
|
|
|
222
223
|
return csv_files, target_table
|
|
223
224
|
|
|
224
|
-
m = re.match(f'{
|
|
225
|
+
m = re.match(f'{export_log_dir()}/{copy_session}_(.*?)\.(.*?)\.log(.*)', log_file)
|
|
225
226
|
if m:
|
|
226
227
|
keyspace = m.group(1)
|
|
227
228
|
target_table = m.group(2)
|
|
@@ -234,7 +235,8 @@ class ExportTableStatus:
|
|
|
234
235
|
|
|
235
236
|
# 4 rows exported to 1 files in 0 day, 0 hour, 0 minute, and 1.335 seconds.
|
|
236
237
|
pattern = 'rows exported to'
|
|
237
|
-
r:
|
|
238
|
+
r: ExecResult = local_exec(['grep', pattern, log_file], show_out=Config().is_debug())
|
|
239
|
+
|
|
238
240
|
if r.exit_code() == 0:
|
|
239
241
|
csv_files, table = get_csv_files_n_table(target_table)
|
|
240
242
|
if csv_files:
|
|
@@ -246,17 +248,26 @@ class ExportTableStatus:
|
|
|
246
248
|
|
|
247
249
|
return ExportTableStatus(None, None, 'unknown')
|
|
248
250
|
|
|
249
|
-
def
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
251
|
+
def find_files(pod: str, namespace: str, pattern: str, mmin: int = 0, remote = False):
|
|
252
|
+
stdout = ''
|
|
253
|
+
if not remote:
|
|
254
|
+
# find . -maxdepth 1 -type f -name '*'
|
|
255
|
+
dir = os.path.dirname(pattern)
|
|
256
|
+
base = os.path.basename(pattern)
|
|
257
|
+
cmd = ['find', dir, '-name', base]
|
|
258
|
+
if mmin:
|
|
259
|
+
cmd += ['-mmin', f'-{mmin}']
|
|
260
|
+
|
|
261
|
+
stdout = local_exec(cmd, show_out=Config().is_debug()).stdout
|
|
255
262
|
else:
|
|
256
|
-
|
|
263
|
+
cmd = f'find {pattern}'
|
|
264
|
+
if mmin:
|
|
265
|
+
cmd = f'{cmd} -mmin -{mmin}'
|
|
266
|
+
|
|
267
|
+
stdout = CassandraNodes.exec(pod, namespace, cmd, show_out=Config().is_debug(), shell='bash').stdout
|
|
257
268
|
|
|
258
269
|
log_files = []
|
|
259
|
-
for line in
|
|
270
|
+
for line in stdout.split('\n'):
|
|
260
271
|
line = line.strip(' \r')
|
|
261
272
|
if line:
|
|
262
273
|
log_files.append(line)
|
|
@@ -325,6 +336,7 @@ class PodPushHandler:
|
|
|
325
336
|
state = self.state
|
|
326
337
|
|
|
327
338
|
if not state.pod:
|
|
339
|
+
self.pushed = True
|
|
328
340
|
state.push()
|
|
329
341
|
|
|
330
342
|
if not self.pod:
|
|
@@ -340,4 +352,15 @@ class PodPushHandler:
|
|
|
340
352
|
return False
|
|
341
353
|
|
|
342
354
|
def state_with_pod(state: ReplState, pod: str = None):
|
|
343
|
-
return PodPushHandler(state, pod=pod)
|
|
355
|
+
return PodPushHandler(state, pod=pod)
|
|
356
|
+
|
|
357
|
+
def os_system_exec(cmd: str, show_out = False):
|
|
358
|
+
if show_out: log2(cmd)
|
|
359
|
+
|
|
360
|
+
os.system(cmd)
|
|
361
|
+
|
|
362
|
+
def csv_dir():
|
|
363
|
+
return Config().get('export.csv_dir', '/c3/cassandra/tmp')
|
|
364
|
+
|
|
365
|
+
def export_log_dir():
|
|
366
|
+
return creating_dir(Config().get('export.log-dir', '/tmp/qing-db/q/export/logs'))
|
|
File without changes
|
|
@@ -27,10 +27,10 @@ class Cat(Command):
|
|
|
27
27
|
|
|
28
28
|
with self.validate(args, state) as (args, state):
|
|
29
29
|
with validate_args(args, state, name='file'):
|
|
30
|
-
return Devices.
|
|
30
|
+
return Devices.of(state).bash(state, state, cmd.split(' '))
|
|
31
31
|
|
|
32
32
|
def completion(self, state: ReplState):
|
|
33
|
-
return super().completion(state, pods=Devices.
|
|
33
|
+
return super().completion(state, lambda: {f: None for f in Devices.of(state).files(state)}, pods=Devices.of(state).pods(state, '-'), auto='jit')
|
|
34
34
|
|
|
35
35
|
def help(self, _: ReplState):
|
|
36
36
|
return f'{Cat.COMMAND} file [&]\t run cat command on the pod'
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
from adam.commands import validate_args
|
|
4
|
+
from adam.commands.command import Command
|
|
5
|
+
from adam.repl_state import ReplState, RequiredState
|
|
6
|
+
from adam.utils import log2
|
|
7
|
+
from adam.utils_local import find_local_files
|
|
8
|
+
|
|
9
|
+
class CatLocal(Command):
|
|
10
|
+
COMMAND = ':cat'
|
|
11
|
+
|
|
12
|
+
# the singleton pattern
|
|
13
|
+
def __new__(cls, *args, **kwargs):
|
|
14
|
+
if not hasattr(cls, 'instance'): cls.instance = super(CatLocal, 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 CatLocal.COMMAND
|
|
23
|
+
|
|
24
|
+
def required(self):
|
|
25
|
+
return [RequiredState.CLUSTER_OR_POD, RequiredState.APP_APP, ReplState.P]
|
|
26
|
+
|
|
27
|
+
def run(self, cmd: str, state: ReplState):
|
|
28
|
+
if not(args := self.args(cmd)):
|
|
29
|
+
return super().run(cmd, state)
|
|
30
|
+
|
|
31
|
+
with self.validate(args, state) as (args, state):
|
|
32
|
+
with validate_args(args, state, name='file') as args:
|
|
33
|
+
os.system(f'cat {args}')
|
|
34
|
+
log2()
|
|
35
|
+
|
|
36
|
+
return state
|
|
37
|
+
|
|
38
|
+
def completion(self, state: ReplState):
|
|
39
|
+
return super().completion(state, lambda: {n: None for n in find_local_files(file_type='f', max_depth=1)}, auto='jit')
|
|
40
|
+
|
|
41
|
+
def help(self, _: ReplState):
|
|
42
|
+
return f'{CatLocal.COMMAND} file\t run cat command on local system'
|
adam/commands/{cd.py → fs/cd.py}
RENAMED
|
@@ -28,14 +28,14 @@ class Cd(Command):
|
|
|
28
28
|
|
|
29
29
|
with self.validate(args, state, apply=False) as (args, state):
|
|
30
30
|
with validate_args(args, state, name='directory') as arg_str:
|
|
31
|
-
device: Device = Devices.
|
|
31
|
+
device: Device = Devices.of(state)
|
|
32
32
|
for dir in arg_str.split('/'):
|
|
33
33
|
device.cd(dir, state)
|
|
34
34
|
|
|
35
35
|
return state
|
|
36
36
|
|
|
37
37
|
def completion(self, state: ReplState):
|
|
38
|
-
return Devices.
|
|
38
|
+
return Devices.of(state).cd_completion(Cd.COMMAND, state, default = {})
|
|
39
39
|
|
|
40
40
|
def help(self, _: ReplState):
|
|
41
41
|
return f'{Cd.COMMAND} <path> | .. \t move around on the operational device hierarchy'
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from adam.commands import validate_args
|
|
2
2
|
from adam.commands.command import Command
|
|
3
3
|
from adam.commands.devices.devices import Devices
|
|
4
|
+
from adam.config import Config
|
|
5
|
+
from adam.utils_k8s.pod_exec_result import PodExecResult
|
|
4
6
|
from adam.repl_state import ReplState, RequiredState
|
|
5
7
|
from adam.utils import log2
|
|
6
8
|
from adam.utils_k8s.pods import Pods
|
|
@@ -29,8 +31,8 @@ class DownloadFile(Command):
|
|
|
29
31
|
|
|
30
32
|
with self.validate(args, state) as (args, state):
|
|
31
33
|
with validate_args(args, state, name='file'):
|
|
32
|
-
to_file = Pods.download_file(state.pod,
|
|
33
|
-
Devices.
|
|
34
|
+
to_file = Pods.download_file(Devices.of(state).pod(state),
|
|
35
|
+
Devices.of(state).default_container(state),
|
|
34
36
|
state.namespace,
|
|
35
37
|
args[0],
|
|
36
38
|
args[1] if len(args) > 1 else None)
|
|
@@ -39,9 +41,7 @@ class DownloadFile(Command):
|
|
|
39
41
|
return state
|
|
40
42
|
|
|
41
43
|
def completion(self, state: ReplState):
|
|
42
|
-
return super().completion(state, pods=Devices.
|
|
43
|
-
|
|
44
|
-
return {}
|
|
44
|
+
return super().completion(state, lambda: {f: None for f in Devices.of(state).files(state)}, pods=Devices.of(state).pods(state, '-'), auto='jit')
|
|
45
45
|
|
|
46
46
|
def help(self, _: ReplState):
|
|
47
47
|
return f'{DownloadFile.COMMAND} from-file [to-file]\t download file from pod'
|
|
@@ -3,10 +3,10 @@ import os
|
|
|
3
3
|
from adam.commands.command import Command
|
|
4
4
|
from adam.repl_state import ReplState
|
|
5
5
|
from adam.utils import log2
|
|
6
|
-
from adam.utils_local import
|
|
6
|
+
from adam.utils_local import local_qing_dir
|
|
7
7
|
|
|
8
8
|
class FindLocalFiles(Command):
|
|
9
|
-
COMMAND = 'find
|
|
9
|
+
COMMAND = ':find file'
|
|
10
10
|
|
|
11
11
|
# the singleton pattern
|
|
12
12
|
def __new__(cls, *args, **kwargs):
|
|
@@ -28,9 +28,9 @@ class FindLocalFiles(Command):
|
|
|
28
28
|
cmd = 'find'
|
|
29
29
|
|
|
30
30
|
if not args:
|
|
31
|
-
cmd = f'find {
|
|
31
|
+
cmd = f'find {local_qing_dir()}'
|
|
32
32
|
elif len(args) == 1:
|
|
33
|
-
cmd = f"find {
|
|
33
|
+
cmd = f"find {local_qing_dir()} -name '{args[0]}'"
|
|
34
34
|
else:
|
|
35
35
|
new_args = [f"'{arg}'" if '*' in arg else arg for arg in args]
|
|
36
36
|
cmd = 'find ' + ' '.join(new_args)
|
|
@@ -32,7 +32,7 @@ class FindProcesses(Command):
|
|
|
32
32
|
with validate_args(args, state, name='words to look for'):
|
|
33
33
|
arg = ' | '.join([f'grep {a}' for a in args])
|
|
34
34
|
awk = "awk '{ print $1, $2, $8, $NF }'"
|
|
35
|
-
rs = Devices.
|
|
35
|
+
rs = Devices.of(state).bash(state, state, f"ps -ef | grep -v grep | {arg} | {awk}".split(' '))
|
|
36
36
|
|
|
37
37
|
lines: list[list[str]] = []
|
|
38
38
|
for r in rs:
|
|
@@ -62,10 +62,10 @@ class FindProcesses(Command):
|
|
|
62
62
|
|
|
63
63
|
pod = pid_n_pod[1]
|
|
64
64
|
|
|
65
|
-
log2(f'@{pod} kill -9 {pid}')
|
|
65
|
+
log2(f'@{pod} bash kill -9 {pid}')
|
|
66
66
|
|
|
67
67
|
with state_with_pod(state, pod) as state1:
|
|
68
|
-
Devices.
|
|
68
|
+
Devices.of(state).bash(state, state1, ['kill', '-9', pid])
|
|
69
69
|
|
|
70
70
|
return rs
|
|
71
71
|
|
|
@@ -27,10 +27,10 @@ class Head(Command):
|
|
|
27
27
|
|
|
28
28
|
with self.validate(args, state) as (args, state):
|
|
29
29
|
with validate_args(args, state, name='file'):
|
|
30
|
-
return Devices.
|
|
30
|
+
return Devices.of(state).bash(state, state, cmd.split(' '))
|
|
31
31
|
|
|
32
32
|
def completion(self, state: ReplState):
|
|
33
|
-
return super().completion(state, pods=Devices.
|
|
33
|
+
return super().completion(state, lambda: {f: None for f in Devices.of(state).files(state)}, pods=Devices.of(state).pods(state, '-'), auto='jit')
|
|
34
34
|
|
|
35
35
|
def help(self, _: ReplState):
|
|
36
36
|
return f'{Head.COMMAND} file [&]\t run head command on the pod'
|
adam/commands/{ls.py → fs/ls.py}
RENAMED
|
@@ -30,12 +30,12 @@ class Ls(Command):
|
|
|
30
30
|
state = copy.copy(state)
|
|
31
31
|
state.device = arg.replace(':', '')
|
|
32
32
|
|
|
33
|
-
Devices.
|
|
33
|
+
Devices.of(state).ls(cmd, state)
|
|
34
34
|
|
|
35
35
|
return state
|
|
36
36
|
|
|
37
37
|
def completion(self, state: ReplState):
|
|
38
|
-
return
|
|
38
|
+
return super().completion(state, {'&': None}, pods=Devices.of(state).pods(state, '-'))
|
|
39
39
|
|
|
40
40
|
def help(self, _: ReplState):
|
|
41
41
|
return f'{Ls.COMMAND} [device:]\t list apps, envs, clusters, nodes, pg hosts/databases or export databases'
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
from adam.commands.command import Command
|
|
4
|
+
from adam.repl_state import ReplState
|
|
5
|
+
from adam.utils import log2
|
|
6
|
+
from adam.utils_local import local_qing_dir
|
|
7
|
+
|
|
8
|
+
class LsLocal(Command):
|
|
9
|
+
COMMAND = ':ls'
|
|
10
|
+
|
|
11
|
+
# the singleton pattern
|
|
12
|
+
def __new__(cls, *args, **kwargs):
|
|
13
|
+
if not hasattr(cls, 'instance'): cls.instance = super(LsLocal, cls).__new__(cls)
|
|
14
|
+
|
|
15
|
+
return cls.instance
|
|
16
|
+
|
|
17
|
+
def __init__(self, successor: Command=None):
|
|
18
|
+
super().__init__(successor)
|
|
19
|
+
|
|
20
|
+
def command(self):
|
|
21
|
+
return LsLocal.COMMAND
|
|
22
|
+
|
|
23
|
+
def run(self, cmd: str, state: ReplState):
|
|
24
|
+
if not(args := self.args(cmd)):
|
|
25
|
+
return super().run(cmd, state)
|
|
26
|
+
|
|
27
|
+
with self.validate(args, state) as (args, state):
|
|
28
|
+
if args:
|
|
29
|
+
os.system(f'ls {args}')
|
|
30
|
+
else:
|
|
31
|
+
os.system(f'ls {local_qing_dir()}')
|
|
32
|
+
log2()
|
|
33
|
+
|
|
34
|
+
return state
|
|
35
|
+
|
|
36
|
+
def completion(self, state: ReplState):
|
|
37
|
+
return super().completion(state)
|
|
38
|
+
|
|
39
|
+
def help(self, _: ReplState):
|
|
40
|
+
return f'{LsLocal.COMMAND} [dir]\t list files on local system'
|
adam/commands/fs/rm.py
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from adam.commands.fs.rm_downloads import RmDownloads
|
|
2
|
+
from adam.commands.fs.rm_logs import RmLogs
|
|
3
|
+
from adam.commands.intermediate_command import IntermediateCommand
|
|
4
|
+
|
|
5
|
+
class RmLocal(IntermediateCommand):
|
|
6
|
+
COMMAND = ':rm'
|
|
7
|
+
|
|
8
|
+
# the singleton pattern
|
|
9
|
+
def __new__(cls, *args, **kwargs):
|
|
10
|
+
if not hasattr(cls, 'instance'): cls.instance = super(RmLocal, cls).__new__(cls)
|
|
11
|
+
|
|
12
|
+
return cls.instance
|
|
13
|
+
|
|
14
|
+
def command(self):
|
|
15
|
+
return RmLocal.COMMAND
|
|
16
|
+
|
|
17
|
+
def cmd_list(self):
|
|
18
|
+
return [RmDownloads(), RmLogs()]
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
from adam.commands.command import Command
|
|
4
|
+
from adam.repl_state import ReplState
|
|
5
|
+
from adam.utils import log2
|
|
6
|
+
from adam.utils_local import local_downloads_dir
|
|
7
|
+
|
|
8
|
+
class RmDownloads(Command):
|
|
9
|
+
COMMAND = ':rm downloads'
|
|
10
|
+
|
|
11
|
+
# the singleton pattern
|
|
12
|
+
def __new__(cls, *args, **kwargs):
|
|
13
|
+
if not hasattr(cls, 'instance'): cls.instance = super(RmDownloads, cls).__new__(cls)
|
|
14
|
+
|
|
15
|
+
return cls.instance
|
|
16
|
+
|
|
17
|
+
def __init__(self, successor: Command=None):
|
|
18
|
+
super().__init__(successor)
|
|
19
|
+
|
|
20
|
+
def command(self):
|
|
21
|
+
return RmDownloads.COMMAND
|
|
22
|
+
|
|
23
|
+
def run(self, cmd: str, state: ReplState):
|
|
24
|
+
if not(args := self.args(cmd)):
|
|
25
|
+
return super().run(cmd, state)
|
|
26
|
+
|
|
27
|
+
with self.validate(args, state) as (args, state):
|
|
28
|
+
cmd = f'rm -rf {local_downloads_dir()}/*'
|
|
29
|
+
log2(cmd)
|
|
30
|
+
os.system(cmd)
|
|
31
|
+
log2()
|
|
32
|
+
|
|
33
|
+
return state
|
|
34
|
+
|
|
35
|
+
def completion(self, state: ReplState):
|
|
36
|
+
return super().completion(state)
|
|
37
|
+
|
|
38
|
+
def help(self, _: ReplState):
|
|
39
|
+
return f'{RmDownloads.COMMAND}\t remove all downloads files under {local_downloads_dir()}'
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
from adam.commands.command import Command
|
|
4
|
+
from adam.repl_state import ReplState
|
|
5
|
+
from adam.utils import log2, log_dir
|
|
6
|
+
|
|
7
|
+
class RmLogs(Command):
|
|
8
|
+
COMMAND = ':rm logs'
|
|
9
|
+
|
|
10
|
+
# the singleton pattern
|
|
11
|
+
def __new__(cls, *args, **kwargs):
|
|
12
|
+
if not hasattr(cls, 'instance'): cls.instance = super(RmLogs, 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 RmLogs.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
|
+
with self.validate(args, state) as (args, state):
|
|
27
|
+
cmd = f'rm -rf {log_dir()}/*'
|
|
28
|
+
log2(cmd)
|
|
29
|
+
os.system(cmd)
|
|
30
|
+
log2()
|
|
31
|
+
|
|
32
|
+
return state
|
|
33
|
+
|
|
34
|
+
def completion(self, state: ReplState):
|
|
35
|
+
return super().completion(state)
|
|
36
|
+
|
|
37
|
+
def help(self, _: ReplState):
|
|
38
|
+
return f'{RmLogs.COMMAND}\t remove all qing log files under {log_dir()}'
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
from collections.abc import Callable
|
|
2
1
|
from datetime import datetime
|
|
3
2
|
from functools import partial
|
|
4
3
|
|
|
5
4
|
from adam.commands import validate_args
|
|
6
5
|
from adam.commands.command import Command, InvalidArgumentsException
|
|
6
|
+
from adam.commands.medusa.utils_medusa import medusa_backup_names
|
|
7
7
|
from adam.utils_k8s.statefulsets import StatefulSets
|
|
8
8
|
from adam.repl_state import ReplState, RequiredState
|
|
9
9
|
from adam.utils_k8s.custom_resources import CustomResources
|
|
10
|
-
from adam.config import Config
|
|
11
10
|
from adam.utils import tabulize, log2, log_exc
|
|
12
11
|
|
|
13
12
|
class MedusaRestore(Command):
|
|
@@ -67,20 +66,7 @@ class MedusaRestore(Command):
|
|
|
67
66
|
return state
|
|
68
67
|
|
|
69
68
|
def completion(self, state: ReplState):
|
|
70
|
-
|
|
71
|
-
ns = state.namespace
|
|
72
|
-
dc: str = StatefulSets.get_datacenter(state.sts, ns)
|
|
73
|
-
if not dc:
|
|
74
|
-
return {}
|
|
75
|
-
|
|
76
|
-
if Config().get('medusa.restore-auto-complete', False):
|
|
77
|
-
leaf = {id: None for id in [f"{x['metadata']['name']}" for x in CustomResources.medusa_show_backupjobs(dc, ns)]}
|
|
78
|
-
|
|
79
|
-
return super().completion(state, leaf)
|
|
80
|
-
else:
|
|
81
|
-
return sc
|
|
82
|
-
|
|
83
|
-
return {}
|
|
69
|
+
return super().completion(state, lambda: {id: None for id in medusa_backup_names(state)}, auto_key='medusa.backups')
|
|
84
70
|
|
|
85
71
|
def help(self, _: ReplState):
|
|
86
72
|
return f'{MedusaRestore.COMMAND}\t start a restore job'
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from adam.config import Config
|
|
2
|
+
from adam.repl_state import ReplState
|
|
3
|
+
from adam.utils_k8s.custom_resources import CustomResources
|
|
4
|
+
from adam.utils_k8s.statefulsets import StatefulSets
|
|
5
|
+
|
|
6
|
+
def medusa_backup_names(state: ReplState, warm=False):
|
|
7
|
+
if warm and (auto := Config().get('medusa.restore-auto-complete', 'off')) in ['off', 'jit', 'lazy']:
|
|
8
|
+
return {}
|
|
9
|
+
|
|
10
|
+
ns = state.namespace
|
|
11
|
+
dc: str = StatefulSets.get_datacenter(state.sts, ns)
|
|
12
|
+
if not dc:
|
|
13
|
+
return {}
|
|
14
|
+
|
|
15
|
+
return {id: None for id in [f"{x['metadata']['name']}" for x in CustomResources.medusa_show_backupjobs(dc, ns)]}
|
|
File without changes
|
|
@@ -3,11 +3,11 @@ import click
|
|
|
3
3
|
from adam.commands.command import Command
|
|
4
4
|
from adam.commands.command_helpers import ClusterOrPodCommandHelper
|
|
5
5
|
from adam.commands.cql.utils_cql import cassandra
|
|
6
|
-
from adam.commands.
|
|
6
|
+
from adam.commands.devices.devices import Devices
|
|
7
|
+
from adam.commands.nodetool.nodetool_commands import NODETOOL_COMMANDS
|
|
7
8
|
from adam.config import Config
|
|
8
9
|
from adam.repl_state import ReplState, RequiredState
|
|
9
10
|
from adam.utils import log
|
|
10
|
-
from adam.utils_k8s.statefulsets import StatefulSets
|
|
11
11
|
|
|
12
12
|
class NodeTool(Command):
|
|
13
13
|
COMMAND = 'nodetool'
|
|
@@ -38,12 +38,7 @@ class NodeTool(Command):
|
|
|
38
38
|
return state
|
|
39
39
|
|
|
40
40
|
def completion(self, state: ReplState):
|
|
41
|
-
|
|
42
|
-
d = {c: {'&': None} for c in NODETOOL_COMMANDS}
|
|
43
|
-
return {NodeTool.COMMAND: {'help': None} | d} | \
|
|
44
|
-
{f'@{p}': {NodeTool.COMMAND: d} for p in StatefulSets.pod_names(state.sts, state.namespace)}
|
|
45
|
-
|
|
46
|
-
return {}
|
|
41
|
+
return super().completion(state, {c: {'&': None} for c in NODETOOL_COMMANDS}, pods=Devices.of(state).pods(state, '-'))
|
|
47
42
|
|
|
48
43
|
def help(self, _: ReplState):
|
|
49
44
|
return f'{NodeTool.COMMAND} <sub-command> [&]\t run nodetool with arguments'
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from adam.commands.postgres.postgres_databases import PostgresDatabases
|
|
2
|
+
from adam.commands.postgres.utils_postgres import pg_table_names
|
|
3
|
+
from adam.repl_state import ReplState
|
|
4
|
+
from adam.sql.lark_completer import LarkCompleter
|
|
5
|
+
|
|
6
|
+
def completions_p(state: ReplState):
|
|
7
|
+
return {
|
|
8
|
+
'\h': None,
|
|
9
|
+
'\d': None,
|
|
10
|
+
'\dt': None,
|
|
11
|
+
'\du': None
|
|
12
|
+
} | LarkCompleter(expandables={
|
|
13
|
+
'tables': lambda x: pg_table_names(state),
|
|
14
|
+
'columns': ['id'],
|
|
15
|
+
'hosts': ['@' + PostgresDatabases.pod_and_container(state.namespace)[0]],
|
|
16
|
+
}, variant=ReplState.P).completions_for_nesting()
|
|
17
|
+
|
|
18
|
+
def psql0_completions(state: ReplState):
|
|
19
|
+
return {
|
|
20
|
+
'\h': None,
|
|
21
|
+
'\l': None,
|
|
22
|
+
}
|
|
@@ -4,12 +4,12 @@ from adam.commands import extract_trailing_options, validate_args
|
|
|
4
4
|
from adam.commands.command import Command
|
|
5
5
|
from adam.commands.intermediate_command import IntermediateCommand
|
|
6
6
|
from adam.commands.postgres.postgres_databases import pg_path
|
|
7
|
-
from adam.commands.postgres.
|
|
7
|
+
from adam.commands.postgres.completions_p import psql0_completions, completions_p
|
|
8
8
|
from adam.commands.postgres.utils_postgres import pg_table_names, postgres
|
|
9
9
|
from .postgres_ls import PostgresLs
|
|
10
10
|
from .postgres_preview import PostgresPreview
|
|
11
11
|
from adam.repl_state import ReplState
|
|
12
|
-
from adam.utils import log, log2
|
|
12
|
+
from adam.utils import log, log2, log_timing
|
|
13
13
|
|
|
14
14
|
class Postgres(IntermediateCommand):
|
|
15
15
|
COMMAND = 'pg'
|
|
@@ -55,24 +55,17 @@ class Postgres(IntermediateCommand):
|
|
|
55
55
|
|
|
56
56
|
def completion(self, state: ReplState):
|
|
57
57
|
if state.device != state.P:
|
|
58
|
-
# conflicts with cql completions
|
|
59
58
|
return {}
|
|
60
59
|
|
|
61
|
-
leaf = {}
|
|
62
60
|
with pg_path(state) as (host, database):
|
|
63
61
|
if database:
|
|
64
62
|
if pg_table_names(state):
|
|
65
|
-
|
|
63
|
+
with log_timing('psql_completions'):
|
|
64
|
+
return completions_p(state)
|
|
66
65
|
elif host:
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
if state.pg_path:
|
|
73
|
-
return super().completion(state, leaf) | leaf
|
|
74
|
-
else:
|
|
75
|
-
return {}
|
|
66
|
+
return psql0_completions(state)
|
|
67
|
+
|
|
68
|
+
return {}
|
|
76
69
|
|
|
77
70
|
def help(self, _: ReplState):
|
|
78
71
|
return f'<sql-statements> [&]\t run queries on Postgres databases'
|
|
@@ -144,12 +144,12 @@ class PostgresDatabases:
|
|
|
144
144
|
env_prefix = f'PGPASSWORD="{password}"'
|
|
145
145
|
|
|
146
146
|
r = Pods.exec(pod_name, container_name, state.namespace, cmd, show_out=show_out, backgrounded=backgrounded, env_prefix=env_prefix)
|
|
147
|
-
if r and
|
|
148
|
-
|
|
149
|
-
ReplSession().prompt_session.history.append_string(f'@{r.pod} cat {r.log_file}')
|
|
147
|
+
if r and r.log_file:
|
|
148
|
+
ReplSession().append_history(f':cat {r.log_file}')
|
|
150
149
|
|
|
151
150
|
return r
|
|
152
151
|
|
|
152
|
+
@functools.lru_cache()
|
|
153
153
|
def pod_and_container(namespace: str):
|
|
154
154
|
container_name = Config().get('pg.agent.name', 'ops-pg-agent')
|
|
155
155
|
|