kaqing 2.0.184__py3-none-any.whl → 2.0.227__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/checks/compactionstats.py +2 -1
- adam/checks/cpu.py +2 -1
- adam/checks/disk.py +6 -5
- adam/checks/gossip.py +2 -1
- adam/checks/memory.py +2 -1
- adam/checks/status.py +2 -1
- adam/commands/app/app.py +4 -4
- adam/commands/app/app_ping.py +2 -2
- adam/commands/{login.py → app/login.py} +2 -2
- adam/commands/app/show_app_actions.py +3 -3
- adam/commands/app/show_app_id.py +2 -2
- adam/commands/app/show_app_queues.py +2 -2
- adam/commands/{show → app}/show_login.py +3 -3
- adam/commands/app/utils_app.py +9 -1
- adam/commands/audit/audit.py +8 -24
- adam/commands/audit/audit_repair_tables.py +3 -3
- adam/commands/audit/audit_run.py +3 -3
- adam/commands/audit/completions_l.py +15 -0
- adam/commands/audit/show_last10.py +2 -3
- adam/commands/audit/show_slow10.py +2 -2
- adam/commands/audit/show_top10.py +2 -2
- adam/commands/bash/bash.py +3 -3
- 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} +3 -3
- adam/commands/{show → cassandra}/show_cassandra_repairs.py +7 -5
- adam/commands/{show → cassandra}/show_cassandra_status.py +24 -17
- adam/commands/{show → cassandra}/show_cassandra_version.py +2 -2
- adam/commands/cassandra/show_processes.py +50 -0
- adam/commands/cassandra/show_storage.py +44 -0
- adam/commands/{watch.py → cassandra/watch.py} +2 -2
- 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} +4 -4
- adam/commands/{show/show_commands.py → cli/show_cli_commands.py} +5 -5
- adam/commands/code.py +2 -2
- adam/commands/command.py +54 -14
- adam/commands/commands_utils.py +14 -6
- adam/commands/config/__init__.py +0 -0
- adam/commands/{param_get.py → config/param_get.py} +2 -2
- adam/commands/{param_set.py → config/param_set.py} +2 -2
- adam/commands/{show → config}/show_params.py +3 -3
- adam/commands/{alter_tables.py → cql/alter_tables.py} +3 -3
- adam/commands/cql/completions_c.py +29 -0
- adam/commands/cql/cqlsh.py +4 -8
- adam/commands/cql/utils_cql.py +36 -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/deploy/code_start.py +2 -2
- adam/commands/deploy/code_stop.py +2 -2
- adam/commands/deploy/deploy_frontend.py +2 -2
- adam/commands/deploy/deploy_pg_agent.py +2 -2
- adam/commands/deploy/deploy_pod.py +2 -2
- adam/commands/deploy/undeploy_frontend.py +2 -2
- adam/commands/deploy/undeploy_pg_agent.py +2 -2
- adam/commands/deploy/undeploy_pod.py +2 -2
- adam/commands/devices/device.py +37 -11
- adam/commands/devices/device_app.py +7 -7
- adam/commands/devices/device_auit_log.py +2 -2
- adam/commands/devices/device_cass.py +6 -6
- adam/commands/devices/device_export.py +7 -4
- adam/commands/devices/device_postgres.py +19 -9
- adam/commands/devices/devices.py +1 -1
- adam/commands/diag/__init__.py +0 -0
- adam/commands/{check.py → diag/check.py} +3 -3
- adam/commands/diag/generate_report.py +52 -0
- adam/commands/{issues.py → diag/issues.py} +3 -2
- adam/commands/exit.py +2 -2
- adam/commands/export/clean_up_all_export_sessions.py +2 -2
- adam/commands/export/clean_up_export_sessions.py +2 -2
- adam/commands/export/completions_x.py +11 -0
- adam/commands/export/download_export_session.py +5 -5
- adam/commands/export/drop_export_database.py +2 -2
- adam/commands/export/drop_export_databases.py +2 -2
- adam/commands/export/export.py +3 -19
- adam/commands/export/export_databases.py +20 -11
- adam/commands/export/export_select.py +9 -34
- adam/commands/export/export_sessions.py +13 -11
- adam/commands/export/export_use.py +6 -6
- adam/commands/export/export_x_select.py +48 -0
- adam/commands/export/exporter.py +140 -53
- adam/commands/export/import_files.py +3 -7
- adam/commands/export/import_session.py +2 -6
- adam/commands/export/importer.py +12 -13
- adam/commands/export/importer_athena.py +15 -35
- adam/commands/export/importer_sqlite.py +19 -8
- adam/commands/export/show_column_counts.py +11 -12
- adam/commands/export/show_export_databases.py +4 -4
- adam/commands/export/show_export_session.py +5 -5
- adam/commands/export/show_export_sessions.py +4 -4
- adam/commands/export/utils_export.py +40 -25
- adam/commands/fs/__init__.py +0 -0
- adam/commands/{cat.py → fs/cat.py} +4 -4
- adam/commands/fs/cat_local.py +42 -0
- adam/commands/{cd.py → fs/cd.py} +4 -4
- adam/commands/{download_file.py → fs/download_file.py} +7 -7
- adam/commands/{find_files.py → fs/find_files.py} +7 -7
- adam/commands/{find_processes.py → fs/find_processes.py} +14 -22
- adam/commands/{head.py → fs/head.py} +5 -5
- adam/commands/fs/head_local.py +46 -0
- adam/commands/{ls.py → fs/ls.py} +4 -4
- adam/commands/fs/ls_local.py +40 -0
- adam/commands/{pwd.py → fs/pwd.py} +2 -2
- adam/commands/fs/rm.py +18 -0
- adam/commands/fs/rm_downloads.py +39 -0
- adam/commands/fs/rm_logs.py +44 -0
- adam/commands/fs/rm_logs_local.py +38 -0
- adam/commands/{shell.py → fs/shell.py} +2 -2
- adam/commands/{show → fs}/show_adam.py +3 -3
- adam/commands/{show → fs}/show_host.py +2 -2
- adam/commands/fs/show_last_results.py +39 -0
- adam/commands/fs/tail.py +36 -0
- adam/commands/fs/tail_local.py +46 -0
- adam/commands/fs/utils_fs.py +192 -0
- adam/commands/help.py +2 -2
- adam/commands/intermediate_command.py +3 -0
- adam/commands/kubectl.py +2 -2
- adam/commands/medusa/medusa_backup.py +2 -2
- adam/commands/medusa/medusa_restore.py +4 -18
- adam/commands/medusa/medusa_show_backupjobs.py +2 -2
- adam/commands/medusa/medusa_show_restorejobs.py +2 -2
- adam/commands/medusa/utils_medusa.py +15 -0
- adam/commands/nodetool/__init__.py +0 -0
- adam/commands/nodetool/nodetool.py +87 -0
- adam/commands/nodetool/utils_nodetool.py +44 -0
- adam/commands/postgres/completions_p.py +22 -0
- adam/commands/postgres/postgres.py +10 -20
- adam/commands/postgres/postgres_databases.py +3 -3
- adam/commands/postgres/postgres_ls.py +3 -3
- adam/commands/postgres/postgres_preview.py +2 -2
- adam/commands/postgres/utils_postgres.py +12 -2
- adam/commands/preview_table.py +3 -4
- adam/commands/reaper/reaper_forward.py +2 -2
- adam/commands/reaper/reaper_forward_stop.py +2 -2
- adam/commands/reaper/reaper_restart.py +2 -2
- adam/commands/reaper/reaper_run_abort.py +2 -2
- adam/commands/reaper/reaper_runs.py +14 -12
- adam/commands/reaper/reaper_runs_abort.py +2 -2
- adam/commands/reaper/reaper_schedule_activate.py +8 -4
- adam/commands/reaper/reaper_schedule_start.py +3 -4
- adam/commands/reaper/reaper_schedule_stop.py +3 -4
- adam/commands/reaper/reaper_schedules.py +2 -2
- adam/commands/reaper/reaper_status.py +2 -2
- adam/commands/reaper/utils_reaper.py +41 -6
- adam/commands/repair/repair_log.py +2 -2
- adam/commands/repair/repair_run.py +2 -2
- adam/commands/repair/repair_scan.py +2 -4
- adam/commands/repair/repair_stop.py +2 -3
- adam/commands/{show/show.py → show.py} +12 -11
- adam/config.py +4 -5
- adam/embedded_params.py +1 -1
- adam/repl.py +24 -10
- adam/repl_commands.py +68 -45
- adam/repl_session.py +16 -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 +1075 -0
- adam/sso/cred_cache.py +2 -5
- adam/utils.py +259 -82
- adam/utils_async_job.py +73 -0
- adam/utils_k8s/app_clusters.py +11 -4
- adam/utils_k8s/app_pods.py +10 -5
- adam/utils_k8s/cassandra_clusters.py +19 -7
- adam/utils_k8s/cassandra_nodes.py +16 -6
- 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 +189 -29
- 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.227.dist-info}/METADATA +1 -1
- kaqing-2.0.227.dist-info/RECORD +280 -0
- kaqing-2.0.227.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/nodetool.py +0 -69
- 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
- adam/commands/show/show_storage.py +0 -42
- kaqing-2.0.184.dist-info/RECORD +0 -244
- kaqing-2.0.184.dist-info/top_level.txt +0 -1
- /adam/commands/{show → cassandra}/__init__.py +0 -0
- /adam/commands/{nodetool_commands.py → nodetool/nodetool_commands.py} +0 -0
- {kaqing-2.0.184.dist-info → kaqing-2.0.227.dist-info}/WHEEL +0 -0
- {kaqing-2.0.184.dist-info → kaqing-2.0.227.dist-info}/entry_points.txt +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from adam.commands.command import Command
|
|
2
|
-
from adam.commands.ls import Ls
|
|
2
|
+
from adam.commands.fs.ls import Ls
|
|
3
3
|
from adam.repl_state import ReplState, RequiredState
|
|
4
4
|
|
|
5
5
|
class PostgresLs(Command):
|
|
@@ -37,5 +37,5 @@ class PostgresLs(Command):
|
|
|
37
37
|
|
|
38
38
|
return {}
|
|
39
39
|
|
|
40
|
-
def help(self,
|
|
41
|
-
return
|
|
40
|
+
def help(self, state: ReplState):
|
|
41
|
+
return super().help(state, 'list postgres hosts, databases or tables')
|
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
import functools
|
|
2
2
|
|
|
3
|
-
from adam.commands.postgres.postgres_databases import PostgresDatabases
|
|
3
|
+
from adam.commands.postgres.postgres_databases import PostgresDatabases, pg_path
|
|
4
|
+
from adam.config import Config
|
|
4
5
|
from adam.repl_state import ReplState
|
|
5
6
|
from adam.utils import log2, wait_log
|
|
6
7
|
from adam.utils_k8s.pods import Pods
|
|
7
8
|
|
|
8
9
|
TestPG = [False]
|
|
9
10
|
|
|
11
|
+
def direct_dirs(state: ReplState) -> list[str]:
|
|
12
|
+
with pg_path(state) as (host, database):
|
|
13
|
+
if database:
|
|
14
|
+
return ['..']
|
|
15
|
+
elif host:
|
|
16
|
+
return ['..'] + pg_database_names(state)
|
|
17
|
+
else:
|
|
18
|
+
return PostgresDatabases.host_names(state.namespace)
|
|
19
|
+
|
|
10
20
|
def pg_database_names(state: ReplState):
|
|
11
21
|
# cache on pg_path
|
|
12
22
|
return _pg_database_names(state, state.pg_path)
|
|
@@ -53,7 +63,7 @@ class PostgresPodService:
|
|
|
53
63
|
if isinstance(args, list):
|
|
54
64
|
query = ' '.join(args)
|
|
55
65
|
|
|
56
|
-
PostgresDatabases.run_sql(state, query, backgrounded=backgrounded)
|
|
66
|
+
PostgresDatabases.run_sql(state, query, show_out=Config().is_debug(), backgrounded=backgrounded)
|
|
57
67
|
|
|
58
68
|
class PostgresExecHandler:
|
|
59
69
|
def __init__(self, state: ReplState, backgrounded=False):
|
adam/commands/preview_table.py
CHANGED
|
@@ -27,13 +27,12 @@ class PreviewTable(Command):
|
|
|
27
27
|
|
|
28
28
|
with self.validate(args, state) as (args, state):
|
|
29
29
|
with validate_args(args, state, at_least=1) as table:
|
|
30
|
-
Devices.
|
|
30
|
+
Devices.of(state).preview(table, state)
|
|
31
31
|
|
|
32
32
|
return state
|
|
33
33
|
|
|
34
34
|
def completion(self, _: ReplState):
|
|
35
|
-
# taken care of by the sql completer
|
|
36
35
|
return {}
|
|
37
36
|
|
|
38
|
-
def help(self,
|
|
39
|
-
return
|
|
37
|
+
def help(self, state: ReplState):
|
|
38
|
+
return super().help(state, 'preview table', args='TABLE')
|
|
@@ -89,5 +89,5 @@ class ReaperForward(Command):
|
|
|
89
89
|
def completion(self, state: ReplState):
|
|
90
90
|
return super().completion(state)
|
|
91
91
|
|
|
92
|
-
def help(self,
|
|
93
|
-
return
|
|
92
|
+
def help(self, state: ReplState):
|
|
93
|
+
return super().help(state, 'port-forward to reaper')
|
|
@@ -39,5 +39,5 @@ class ReaperForwardStop(Command):
|
|
|
39
39
|
def completion(self, state: ReplState):
|
|
40
40
|
return super().completion(state)
|
|
41
41
|
|
|
42
|
-
def help(self,
|
|
43
|
-
return
|
|
42
|
+
def help(self, state: ReplState):
|
|
43
|
+
return super().help(state, 'stop port-forward to reaper')
|
|
@@ -36,5 +36,5 @@ class ReaperRestart(Command):
|
|
|
36
36
|
def completion(self, state: ReplState):
|
|
37
37
|
return super().completion(state)
|
|
38
38
|
|
|
39
|
-
def help(self,
|
|
40
|
-
return
|
|
39
|
+
def help(self, state: ReplState):
|
|
40
|
+
return super().help(state, 'restart reaper')
|
|
@@ -36,5 +36,5 @@ class ReaperRunAbort(Command):
|
|
|
36
36
|
def completion(self, state: ReplState):
|
|
37
37
|
return super().completion(state)
|
|
38
38
|
|
|
39
|
-
def help(self,
|
|
40
|
-
return
|
|
39
|
+
def help(self, state: ReplState):
|
|
40
|
+
return super().help(state, 'abort reaper run', args='<run-id>')
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
from adam.commands.command import Command
|
|
2
|
-
from adam.commands.reaper.utils_reaper import reaper
|
|
2
|
+
from adam.commands.reaper.utils_reaper import reaper, Reapers
|
|
3
3
|
from adam.config import Config
|
|
4
4
|
from adam.repl_state import ReplState, RequiredState
|
|
5
|
-
from adam.utils import convert_seconds, epoch,
|
|
5
|
+
from adam.utils import convert_seconds, epoch, log2
|
|
6
6
|
|
|
7
7
|
class ReaperRuns(Command):
|
|
8
8
|
COMMAND = 'reaper show runs'
|
|
@@ -52,10 +52,11 @@ class ReaperRuns(Command):
|
|
|
52
52
|
'limit': Config().get('reaper.show-runs-batch', 10)
|
|
53
53
|
})
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
if not Reapers.tabulize_runs(state, response):
|
|
56
|
+
# runs = response.json()
|
|
57
|
+
# if runs:
|
|
58
|
+
# tabulize(sorted([line(run) for run in runs], reverse=True), header=header, separator=",")
|
|
59
|
+
# else:
|
|
59
60
|
log2('No running runs found.')
|
|
60
61
|
log2()
|
|
61
62
|
|
|
@@ -64,10 +65,11 @@ class ReaperRuns(Command):
|
|
|
64
65
|
'limit': Config().get('reaper.show-runs-batch', 10)
|
|
65
66
|
})
|
|
66
67
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
if not Reapers.tabulize_runs(state, response):
|
|
69
|
+
# runs = response.json()
|
|
70
|
+
# if runs:
|
|
71
|
+
# tabulize(sorted([line(run) for run in runs], reverse=True), header=header, separator=",")
|
|
72
|
+
# else:
|
|
71
73
|
log2('No runs found.')
|
|
72
74
|
|
|
73
75
|
return state
|
|
@@ -78,5 +80,5 @@ class ReaperRuns(Command):
|
|
|
78
80
|
|
|
79
81
|
return {}
|
|
80
82
|
|
|
81
|
-
def help(self,
|
|
82
|
-
return
|
|
83
|
+
def help(self, state: ReplState):
|
|
84
|
+
return super().help(state, 'show reaper runs')
|
|
@@ -59,5 +59,5 @@ class ReaperRunsAbort(Command):
|
|
|
59
59
|
def completion(self, state: ReplState):
|
|
60
60
|
return super().completion(state)
|
|
61
61
|
|
|
62
|
-
def help(self,
|
|
63
|
-
return
|
|
62
|
+
def help(self, state: ReplState):
|
|
63
|
+
return super().help(state, 'abort all running reaper runs')
|
|
@@ -2,7 +2,11 @@ from adam.commands import validate_args
|
|
|
2
2
|
from adam.commands.command import Command
|
|
3
3
|
from adam.commands.reaper.utils_reaper import Reapers, reaper
|
|
4
4
|
from adam.repl_state import ReplState, RequiredState
|
|
5
|
-
|
|
5
|
+
|
|
6
|
+
import nest_asyncio
|
|
7
|
+
nest_asyncio.apply()
|
|
8
|
+
|
|
9
|
+
import asyncio
|
|
6
10
|
|
|
7
11
|
class ReaperScheduleActivate(Command):
|
|
8
12
|
COMMAND = 'reaper activate schedule'
|
|
@@ -35,7 +39,7 @@ class ReaperScheduleActivate(Command):
|
|
|
35
39
|
return schedule_id
|
|
36
40
|
|
|
37
41
|
def completion(self, state: ReplState):
|
|
38
|
-
return super().completion(state, lambda: {id: None for id in Reapers.cached_schedule_ids(state)})
|
|
42
|
+
return super().completion(state, lambda: {id: None for id in Reapers.cached_schedule_ids(state)}, auto_key='reaper.schedules')
|
|
39
43
|
|
|
40
|
-
def help(self,
|
|
41
|
-
return
|
|
44
|
+
def help(self, state: ReplState):
|
|
45
|
+
return super().help(state, 'resume reaper schedule', args='<schedule-id>')
|
|
@@ -2,7 +2,6 @@ from adam.commands import validate_args
|
|
|
2
2
|
from adam.commands.command import Command
|
|
3
3
|
from adam.commands.reaper.utils_reaper import Reapers, reaper
|
|
4
4
|
from adam.repl_state import ReplState, RequiredState
|
|
5
|
-
from adam.utils import log2
|
|
6
5
|
|
|
7
6
|
class ReaperScheduleStart(Command):
|
|
8
7
|
COMMAND = 'reaper start schedule'
|
|
@@ -35,7 +34,7 @@ class ReaperScheduleStart(Command):
|
|
|
35
34
|
return schedule_id
|
|
36
35
|
|
|
37
36
|
def completion(self, state: ReplState):
|
|
38
|
-
return super().completion(state, lambda: {id: None for id in Reapers.cached_schedule_ids(state)})
|
|
37
|
+
return super().completion(state, lambda: {id: None for id in Reapers.cached_schedule_ids(state)}, auto_key='reaper.schedules')
|
|
39
38
|
|
|
40
|
-
def help(self,
|
|
41
|
-
return
|
|
39
|
+
def help(self, state: ReplState):
|
|
40
|
+
return super().help(state, 'start reaper runs for schedule', args='<schedule-id>')
|
|
@@ -2,7 +2,6 @@ from adam.commands import validate_args
|
|
|
2
2
|
from adam.commands.command import Command
|
|
3
3
|
from adam.commands.reaper.utils_reaper import Reapers, reaper
|
|
4
4
|
from adam.repl_state import ReplState, RequiredState
|
|
5
|
-
from adam.utils import log2
|
|
6
5
|
|
|
7
6
|
class ReaperScheduleStop(Command):
|
|
8
7
|
COMMAND = 'reaper stop schedule'
|
|
@@ -35,7 +34,7 @@ class ReaperScheduleStop(Command):
|
|
|
35
34
|
return schedule_id
|
|
36
35
|
|
|
37
36
|
def completion(self, state: ReplState):
|
|
38
|
-
return super().completion(state, lambda: {id: None for id in Reapers.cached_schedule_ids(state)})
|
|
37
|
+
return super().completion(state, lambda: {id: None for id in Reapers.cached_schedule_ids(state)}, auto_key='reaper.schedules')
|
|
39
38
|
|
|
40
|
-
def help(self,
|
|
41
|
-
return
|
|
39
|
+
def help(self, state: ReplState):
|
|
40
|
+
return super().help(state, 'pause reaper schedule', args='<schedule-id>')
|
|
@@ -32,5 +32,5 @@ class ReaperSchedules(Command):
|
|
|
32
32
|
def completion(self, state: ReplState):
|
|
33
33
|
return super().completion(state)
|
|
34
34
|
|
|
35
|
-
def help(self,
|
|
36
|
-
return
|
|
35
|
+
def help(self, state: ReplState):
|
|
36
|
+
return super().help(state, 'show reaper schedules')
|
|
@@ -52,5 +52,5 @@ class ReaperStatus(Command):
|
|
|
52
52
|
def completion(self, state: ReplState):
|
|
53
53
|
return super().completion(state)
|
|
54
54
|
|
|
55
|
-
def help(self,
|
|
56
|
-
return
|
|
55
|
+
def help(self, state: ReplState):
|
|
56
|
+
return super().help(state, 'show reaper status')
|
|
@@ -7,7 +7,7 @@ import re
|
|
|
7
7
|
import requests
|
|
8
8
|
from adam.config import Config
|
|
9
9
|
from adam.repl_state import ReplState
|
|
10
|
-
from adam.utils import tabulize, log2, wait_log
|
|
10
|
+
from adam.utils import Color, convert_seconds, epoch, tabulize, log2, wait_log
|
|
11
11
|
from adam.utils_k8s.k8s import port_forwarding
|
|
12
12
|
|
|
13
13
|
class ReaperService:
|
|
@@ -41,7 +41,7 @@ class ReaperLogginHandler:
|
|
|
41
41
|
self.svc.headers = Reapers.cookie_header(self.svc.state, self.svc.local_addr, self.svc.remote_addr, show_output=self.svc.show_out)
|
|
42
42
|
|
|
43
43
|
if self.svc.show_out and self.method:
|
|
44
|
-
log2(f'{self.method} {self.svc.remote_addr}/{self.path}')
|
|
44
|
+
log2(f'{self.method} {self.svc.remote_addr}/{self.path}', text_color=Color.gray)
|
|
45
45
|
|
|
46
46
|
return (f'http://{self.svc.local_addr}/{self.path}', self.svc.headers)
|
|
47
47
|
|
|
@@ -139,12 +139,12 @@ class Reapers:
|
|
|
139
139
|
'username':user,
|
|
140
140
|
'password':pw})
|
|
141
141
|
if show_output:
|
|
142
|
-
log2(f'POST {remote_addr}/login')
|
|
143
|
-
log2(f'
|
|
142
|
+
log2(f'POST {remote_addr}/login', text_color=Color.gray)
|
|
143
|
+
log2(f' username={user}&password={pw}', text_color=Color.gray)
|
|
144
144
|
|
|
145
145
|
if int(response.status_code / 100) != 2:
|
|
146
146
|
if show_output:
|
|
147
|
-
log2("login failed")
|
|
147
|
+
log2("login failed", text_color=Color.gray)
|
|
148
148
|
return None
|
|
149
149
|
|
|
150
150
|
return response.headers['Set-Cookie']
|
|
@@ -191,4 +191,39 @@ class Reapers:
|
|
|
191
191
|
if is_service:
|
|
192
192
|
return Reapers.svc_name()
|
|
193
193
|
else:
|
|
194
|
-
return Reapers.pod_name(state)
|
|
194
|
+
return Reapers.pod_name(state)
|
|
195
|
+
|
|
196
|
+
def schedules_auto_completion(ids: callable):
|
|
197
|
+
auto = Config().get('reaper.schedules-auto-complete', 'off')
|
|
198
|
+
|
|
199
|
+
leaf = None
|
|
200
|
+
if auto == 'on':
|
|
201
|
+
leaf = {id: None for id in ids()}
|
|
202
|
+
|
|
203
|
+
return (leaf, auto == 'lazy')
|
|
204
|
+
|
|
205
|
+
def tabulize_runs(state: ReplState, response: dict) -> dict[str, any]:
|
|
206
|
+
header = 'ID,START,DURATION,STATE,CLUSTER,KEYSPACE,TABLES,REPAIRED'
|
|
207
|
+
|
|
208
|
+
def line(run):
|
|
209
|
+
id = run['id']
|
|
210
|
+
state = run['state']
|
|
211
|
+
start_time = run['start_time']
|
|
212
|
+
end_time = run['end_time']
|
|
213
|
+
duration = '-'
|
|
214
|
+
if state == 'DONE' and end_time:
|
|
215
|
+
hours, minutes, seconds = convert_seconds(epoch(end_time) - epoch(start_time))
|
|
216
|
+
if hours:
|
|
217
|
+
duration = f"{hours:2d}h {minutes:2d}m {seconds:2d}s"
|
|
218
|
+
elif minutes:
|
|
219
|
+
duration = f"{minutes:2d}m {seconds:2d}s"
|
|
220
|
+
else:
|
|
221
|
+
duration = f"{seconds:2d}s"
|
|
222
|
+
|
|
223
|
+
return f"{id},{start_time},{duration},{state},{run['cluster_name']},{run['keyspace_name']},{len(run['column_families'])},{run['segments_repaired']}/{run['total_segments']}"
|
|
224
|
+
|
|
225
|
+
runs = response.json()
|
|
226
|
+
if runs:
|
|
227
|
+
tabulize(sorted([line(run) for run in runs], reverse=True), header=header, separator=",")
|
|
228
|
+
|
|
229
|
+
return runs
|
|
@@ -33,5 +33,5 @@ class RepairLog(Command):
|
|
|
33
33
|
def completion(self, state: ReplState):
|
|
34
34
|
return super().completion(state)
|
|
35
35
|
|
|
36
|
-
def help(self,
|
|
37
|
-
return
|
|
36
|
+
def help(self, state: ReplState):
|
|
37
|
+
return super().help(state, 'get repair job logs')
|
|
@@ -61,5 +61,5 @@ class RepairRun(Command):
|
|
|
61
61
|
def completion(self, state: ReplState):
|
|
62
62
|
return super().completion(state)
|
|
63
63
|
|
|
64
|
-
def help(self,
|
|
65
|
-
return
|
|
64
|
+
def help(self, state: ReplState):
|
|
65
|
+
return super().help(state, 'start a repair job, default not replacing', args='[replace]')
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import time
|
|
2
|
-
|
|
3
1
|
from adam.commands.command import Command
|
|
4
2
|
from adam.utils_k8s.pods import Pods
|
|
5
3
|
from adam.repl_state import ReplState, RequiredState
|
|
@@ -64,5 +62,5 @@ class RepairScan(Command):
|
|
|
64
62
|
def completion(self, state: ReplState):
|
|
65
63
|
return super().completion(state)
|
|
66
64
|
|
|
67
|
-
def help(self,
|
|
68
|
-
return
|
|
65
|
+
def help(self, state: ReplState):
|
|
66
|
+
return super().help(state, 'scan last n days repair log, default 7 days')
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
from adam.commands.command import Command
|
|
2
2
|
from adam.utils_k8s.jobs import Jobs
|
|
3
3
|
from adam.repl_state import ReplState, RequiredState
|
|
4
|
-
from adam.config import Config
|
|
5
4
|
|
|
6
5
|
class RepairStop(Command):
|
|
7
6
|
COMMAND = 'repair stop'
|
|
@@ -34,5 +33,5 @@ class RepairStop(Command):
|
|
|
34
33
|
def completion(self, state: ReplState):
|
|
35
34
|
return super().completion(state)
|
|
36
35
|
|
|
37
|
-
def help(self,
|
|
38
|
-
return
|
|
36
|
+
def help(self, state: ReplState):
|
|
37
|
+
return super().help(state, 'delete a repair job')
|
|
@@ -3,19 +3,20 @@ import click
|
|
|
3
3
|
from adam.commands.app.show_app_actions import ShowAppActions
|
|
4
4
|
from adam.commands.app.show_app_id import ShowAppId
|
|
5
5
|
from adam.commands.app.show_app_queues import ShowAppQueues
|
|
6
|
+
from adam.commands.cassandra.show_cassandra_repairs import ShowCassandraRepairs
|
|
7
|
+
from adam.commands.cassandra.show_cassandra_status import ShowCassandraStatus
|
|
8
|
+
from adam.commands.cassandra.show_cassandra_version import ShowCassandraVersion
|
|
9
|
+
from adam.commands.cassandra.show_processes import ShowProcesses
|
|
10
|
+
from adam.commands.cassandra.show_storage import ShowStorage
|
|
11
|
+
from adam.commands.cli.show_cli_commands import ShowKubectlCommands
|
|
12
|
+
from adam.commands.config.show_params import ShowParams
|
|
13
|
+
from adam.commands.debug.show_offloaded_completes import ShowOffloadedCompletes
|
|
14
|
+
from adam.commands.fs.show_adam import ShowAdam
|
|
6
15
|
from adam.commands.intermediate_command import IntermediateCommand
|
|
7
16
|
from adam.commands.medusa.medusa_show_backupjobs import MedusaShowBackupJobs
|
|
8
17
|
from adam.commands.medusa.medusa_show_restorejobs import MedusaShowRestoreJobs
|
|
9
|
-
from adam.commands.
|
|
10
|
-
from adam.commands.
|
|
11
|
-
from .show_params import ShowParams
|
|
12
|
-
from .show_cassandra_status import ShowCassandraStatus
|
|
13
|
-
from .show_cassandra_version import ShowCassandraVersion
|
|
14
|
-
from .show_commands import ShowKubectlCommands
|
|
15
|
-
from .show_processes import ShowProcesses
|
|
16
|
-
from .show_cassandra_repairs import ShowCassandraRepairs
|
|
17
|
-
from .show_storage import ShowStorage
|
|
18
|
-
from .show_adam import ShowAdam
|
|
18
|
+
from adam.commands.fs.show_host import ShowHost
|
|
19
|
+
from adam.commands.app.show_login import ShowLogin
|
|
19
20
|
|
|
20
21
|
class Show(IntermediateCommand):
|
|
21
22
|
COMMAND = 'show'
|
|
@@ -30,7 +31,7 @@ class Show(IntermediateCommand):
|
|
|
30
31
|
return Show.COMMAND
|
|
31
32
|
|
|
32
33
|
def cmd_list(self):
|
|
33
|
-
return [ShowAppActions(), ShowAppId(), ShowAppQueues(), ShowHost(), ShowLogin(), ShowKubectlCommands(),
|
|
34
|
+
return [ShowAppActions(), ShowAppId(), ShowAppQueues(), ShowOffloadedCompletes(), ShowHost(), ShowLogin(), ShowKubectlCommands(),
|
|
34
35
|
ShowParams(), ShowProcesses(), ShowCassandraRepairs(), ShowStorage(), ShowAdam(),
|
|
35
36
|
ShowCassandraStatus(), ShowCassandraVersion(), MedusaShowRestoreJobs(), MedusaShowBackupJobs()]
|
|
36
37
|
|
adam/config.py
CHANGED
|
@@ -3,16 +3,13 @@ from typing import TypeVar, cast
|
|
|
3
3
|
import yaml
|
|
4
4
|
|
|
5
5
|
from . import __version__
|
|
6
|
-
from adam.utils import
|
|
6
|
+
from adam.utils import ConfigHolder, ConfigReadable, copy_config_file, get_deep_keys, log2
|
|
7
7
|
|
|
8
8
|
T = TypeVar('T')
|
|
9
9
|
|
|
10
|
-
class Config:
|
|
10
|
+
class Config(ConfigReadable):
|
|
11
11
|
EMBEDDED_PARAMS = {}
|
|
12
12
|
|
|
13
|
-
LogConfig.is_debug = lambda: Config().is_debug()
|
|
14
|
-
LogConfig.is_debug_timing = lambda: Config().get('debugs.timings', False)
|
|
15
|
-
|
|
16
13
|
# the singleton pattern
|
|
17
14
|
def __new__(cls, *args, **kwargs):
|
|
18
15
|
if not hasattr(cls, 'instance'): cls.instance = super(Config, cls).__new__(cls)
|
|
@@ -28,6 +25,8 @@ class Config:
|
|
|
28
25
|
except:
|
|
29
26
|
with open(copy_config_file(f'params.yaml.{__version__}', 'adam.embedded_params', show_out=not is_user_entry)) as f:
|
|
30
27
|
self.params = cast(dict[str, any], yaml.safe_load(f))
|
|
28
|
+
|
|
29
|
+
ConfigHolder().config = self
|
|
31
30
|
elif not hasattr(self, 'params'):
|
|
32
31
|
with open(copy_config_file(f'params.yaml.{__version__}', 'adam.embedded_params', show_out=not is_user_entry)) as f:
|
|
33
32
|
self.params = cast(dict[str, any], yaml.safe_load(f))
|
adam/embedded_params.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
def config():
|
|
2
|
-
return {'app': {'console-endpoint': 'https://{host}/{env}/{app}/static/console/index.html', 'container-name': 'c3-server', 'cr': {'cluster-regex': '(.*?-.*?)-.*', 'group': 'ops.c3.ai', 'v': 'v2', 'plural': 'c3cassandras'}, 'label': 'c3__app_id-0', 'login': {'admin-group': '{host}/C3.ClusterAdmin', 'ingress': '{app_id}-k8singr-appleader-001', 'timeout': 5, 'session-check-url': 'https://{host}/{env}/{app}/api/8/C3/userSessionToken', 'cache-creds': True, 'cache-username': True, 'url': 'https://{host}/{env}/{app}', 'another': "You're logged in to {has}. However, for this app, you need to log in to {need}.", 'token-server-url': 'http://localhost:{port}', 'password-max-length': 128}, 'strip': '0'}, 'audit': {'endpoint': 'https://4psvtaxlcb.execute-api.us-west-2.amazonaws.com/prod/', 'workers': 3, 'timeout': 10, 'log-audit-queries': False, 'athena': {'auto-repair': {'elapsed_hours': 12}, 'region': 'us-west-2', 'catalog': 'AwsDataCatalog', 'database': 'audit', 'repair-partition-tables': 'audit', 'output': 's3://s3.ops--audit/ddl/results', 'repair-cluster-tables': 'cluster'}, 'queries': {'last10': "SELECT * FROM audit\nWHERE drive <> 'z' and ({date_condition})\nORDER BY ts DESC LIMIT {limit}", 'slow10': "SELECT * FROM audit\nWHERE drive <> 'z' and ({date_condition})\nORDER BY CAST(duration AS REAL) DESC LIMIT {limit}", 'top10': "SELECT min(c) AS cluster, line, COUNT(*) AS cnt, avg(CAST(duration AS REAL)) AS duration\nFROM audit WHERE drive <> 'z' and ({date_condition})\nGROUP BY line ORDER BY cnt DESC LIMIT {limit}"}}, 'bash': {'workers': 32}, 'cassandra': {'service-name': 'all-pods-service'}, 'cql': {'workers': 32, 'samples': 3, 'secret': {'cluster-regex': '(.*?-.*?)-.*', 'name': '{cluster}-superuser', 'password-item': 'password'}, 'alter-tables': {'excludes': 'system_auth,system_traces,reaper_db,system_distributed,system_views,system,system_schema,system_virtual_schema', 'gc-grace-periods': '3600,86400,864000,7776000', 'batching': True}}, 'checks': {'compactions-threshold': 250, 'cpu-busy-threshold': 98.0, 'cpu-threshold': 0.0, 'cassandra-data-path': '/c3/cassandra', 'root-disk-threshold': 50, 'cassandra-disk-threshold': 50, 'snapshot-size-cmd': "ls /c3/cassandra/data/data/*/*/snapshots | grep snapshots | sed 's/:$//g' | xargs -I {} du -sk {} | awk '{print $1}' | awk '{s+=$1} END {print s}'", 'snapshot-size-threshold': '40G', 'table-sizes-cmd': "ls -Al /c3/cassandra/data/data/ | awk '{print $9}' | sed 's/\\^r//g' | xargs -I {} du -sk /c3/cassandra/data/data/{}"}, 'download': {'workers': 8}, 'export': {'workers': 8, 'csv_dir': '/c3/cassandra/tmp', 'column_counts_query': 'select id, count(id) as columns from {table} group by id order by columns desc limit 10', 'default-importer': 'sqlite', 'sqlite': {'workers': 8, 'columns': '<row-key>', 'local-db-dir': '/tmp/qing-db'}, 'athena': {'workers': 8, 'columns': '<keys>', 'bucket': 'c3.ops--qing'}, 'csv': {'workers': 8, 'columns': '<row-key>'}, 'log-
|
|
2
|
+
return {'app': {'console-endpoint': 'https://{host}/{env}/{app}/static/console/index.html', 'container-name': 'c3-server', 'cr': {'cluster-regex': '(.*?-.*?)-.*', 'group': 'ops.c3.ai', 'v': 'v2', 'plural': 'c3cassandras'}, 'label': 'c3__app_id-0', 'login': {'admin-group': '{host}/C3.ClusterAdmin', 'ingress': '{app_id}-k8singr-appleader-001', 'timeout': 5, 'session-check-url': 'https://{host}/{env}/{app}/api/8/C3/userSessionToken', 'cache-creds': True, 'cache-username': True, 'url': 'https://{host}/{env}/{app}', 'another': "You're logged in to {has}. However, for this app, you need to log in to {need}.", 'token-server-url': 'http://localhost:{port}', 'password-max-length': 128}, 'strip': '0'}, 'audit': {'endpoint': 'https://4psvtaxlcb.execute-api.us-west-2.amazonaws.com/prod/', 'workers': 3, 'timeout': 10, 'log-audit-queries': False, 'athena': {'auto-repair': {'elapsed_hours': 12}, 'region': 'us-west-2', 'catalog': 'AwsDataCatalog', 'database': 'audit', 'repair-partition-tables': 'audit', 'output': 's3://s3.ops--audit/ddl/results', 'repair-cluster-tables': 'cluster'}, 'queries': {'last10': "SELECT * FROM audit\nWHERE drive <> 'z' and ({date_condition})\nORDER BY ts DESC LIMIT {limit}", 'slow10': "SELECT * FROM audit\nWHERE drive <> 'z' and ({date_condition})\nORDER BY CAST(duration AS REAL) DESC LIMIT {limit}", 'top10': "SELECT min(c) AS cluster, line, COUNT(*) AS cnt, avg(CAST(duration AS REAL)) AS duration\nFROM audit WHERE drive <> 'z' and ({date_condition})\nGROUP BY line ORDER BY cnt DESC LIMIT {limit}"}}, 'bash': {'workers': 32}, 'cassandra': {'service-name': 'all-pods-service'}, 'cql': {'workers': 32, 'samples': 3, 'secret': {'cluster-regex': '(.*?-.*?)-.*', 'name': '{cluster}-superuser', 'password-item': 'password'}, 'alter-tables': {'excludes': 'system_auth,system_traces,reaper_db,system_distributed,system_views,system,system_schema,system_virtual_schema', 'gc-grace-periods': '3600,86400,864000,7776000', 'batching': True}}, 'checks': {'compactions-threshold': 250, 'cpu-busy-threshold': 98.0, 'cpu-threshold': 0.0, 'cassandra-data-path': '/c3/cassandra', 'root-disk-threshold': 50, 'cassandra-disk-threshold': 50, 'snapshot-size-cmd': "ls /c3/cassandra/data/data/*/*/snapshots | grep snapshots | sed 's/:$//g' | xargs -I {} du -sk {} | awk '{print $1}' | awk '{s+=$1} END {print s}'", 'snapshot-size-threshold': '40G', 'table-sizes-cmd': "ls -Al /c3/cassandra/data/data/ | awk '{print $9}' | sed 's/\\^r//g' | xargs -I {} du -sk /c3/cassandra/data/data/{}"}, 'download': {'workers': 8}, 'export': {'workers': 8, 'csv_dir': '/c3/cassandra/tmp', 'column_counts_query': 'select id, count(id) as columns from {table} group by id order by columns desc limit 10', 'default-importer': 'sqlite', 'sqlite': {'workers': 8, 'columns': '<row-key>', 'local-db-dir': '/tmp/qing-db/q/export/db'}, 'athena': {'workers': 8, 'columns': '<keys>', 'bucket': 'c3.ops--qing'}, 'csv': {'workers': 8, 'columns': '<row-key>'}, 'log-dir': '/tmp/qing-db/q/export/logs', 'remote': {'log-dir': '/tmp/q/export/logs'}}, 'get-host-id': {'workers': 32}, 'idps': {'ad': {'email-pattern': '.*@c3.ai', 'uri': 'https://login.microsoftonline.com/53ad779a-93e7-485c-ba20-ac8290d7252b/oauth2/v2.0/authorize?response_type=id_token&response_mode=form_post&client_id=00ff94a8-6b0a-4715-98e0-95490012d818&scope=openid+email+profile&redirect_uri=https%3A%2F%2Fplat.c3ci.cloud%2Fc3%2Fc3%2Foidc%2Flogin&nonce={nonce}&state=EMPTY', 'jwks-uri': 'https://login.microsoftonline.com/common/discovery/keys', 'contact': 'Please contact ted.tran@c3.ai.', 'whitelist-file': '/kaqing/members'}, 'okta': {'default': True, 'email-pattern': '.*@c3iot.com', 'uri': 'https://c3energy.okta.com/oauth2/v1/authorize?response_type=id_token&response_mode=form_post&client_id={client_id}&scope=openid+email+profile+groups&redirect_uri=https%3A%2F%2F{host}%2Fc3%2Fc3%2Foidc%2Flogin&nonce={nonce}&state=EMPTY', 'jwks-uri': 'https://c3energy.okta.com/oauth2/v1/keys'}}, 'issues': {'workers': 32}, 'job': {'log-to-pods': True}, 'local-qing-dir': '/tmp/qing-db/q', 'local-downloads-dir': '/tmp/qing-db/q/downloads', 'logs': {'path': '/c3/cassandra/logs/system.log'}, 'log-dir': '/tmp/qing-db/q/logs', 'nodetool': {'workers': 96, 'commands_in_line': 40, 'grace-period-after-abort': 10, 'status': {'workers': 32, 'samples': 3, 'commands_in_line': 40}}, 'pg': {'name-pattern': '^{namespace}.*-k8spg-.*', 'excludes': '.helm., -admin-secret', 'agent': {'name': 'ops-pg-agent', 'just-in-time': False, 'timeout': 86400, 'image': 'seanahnsf/kaqing'}, 'default-db': 'postgres', 'default-schema': 'postgres', 'secret': {'endpoint-key': 'postgres-db-endpoint', 'port-key': 'postgres-db-port', 'username-key': 'postgres-admin-username', 'password-key': 'postgres-admin-password'}}, 'pod': {'name': 'ops', 'image': 'seanahnsf/kaqing-cloud', 'sa': {'name': 'ops', 'proto': 'c3', 'additional-cluster-roles': 'c3aiops-k8ssandra-operator'}, 'label-selector': 'run=ops'}, 'preview': {'rows': 10}, 'processes': {'columns': 'pod,cpu-metrics,mem', 'header': 'POD_NAME,M_CPU(USAGE/LIMIT),MEM/LIMIT'}, 'processes-mpstat': {'columns': 'pod,cpu,mem', 'header': 'POD_NAME,Q_CPU/TOTAL,MEM/LIMIT'}, 'reaper': {'service-name': 'reaper-service', 'port-forward': {'timeout': 86400, 'local-port': 9001}, 'abort-runs-batch': 10, 'show-runs-batch': 100, 'pod': {'cluster-regex': '(.*?-.*?-.*?-.*?)-.*', 'label-selector': 'k8ssandra.io/reaper={cluster}-reaper'}, 'secret': {'cluster-regex': '(.*?-.*?)-.*', 'name': '{cluster}-reaper-ui', 'password-item': 'password'}}, 'repair': {'log-path': '/home/cassrepair/logs/', 'image': 'ci-registry.c3iot.io/cloudops/cassrepair:2.0.14', 'secret': 'ciregistryc3iotio', 'env': {'interval': 24, 'timeout': 60, 'pr': False, 'runs': 1}}, 'repl': {'start-drive': 'c', 'a': {'auto-enter': 'c3/c3'}, 'c': {'auto-enter': 'cluster'}, 'x': {'auto-enter': 'latest'}, 'history': {'push-cat-log-file': True, 'push-cat-remote-log-file': True}, 'background-process': {'auto-nohup': True}}, 'status': {'columns': 'status,address,load,tokens,owns,host_id,gossip,compactions', 'header': '--,Address,Load,Tokens,Owns,Host ID,GOSSIP,COMPACTIONS'}, 'storage': {'columns': 'pod,volume_root,volume_cassandra,snapshots,data,compactions', 'header': 'POD_NAME,VOLUME /,VOLUME CASS,SNAPSHOTS,DATA,COMPACTIONS'}, 'watch': {'auto': 'rollout', 'timeout': 3600, 'interval': 10}, 'auto-complete': {'c': {'tables': 'lazy', 'table-props-value': 'jit'}, 'x': {'tables': 'lazy'}, 'cli': {'cp': 'jit'}, 'export': {'databases': 'jit'}, 'medusa': {'backups': 'jit'}, 'reaper': {'schedules': 'jit'}}, 'debug': False, 'debugs': {'complete': False, 'timings': False, 'exit-on-error': False}}
|
adam/repl.py
CHANGED
|
@@ -3,6 +3,7 @@ import time
|
|
|
3
3
|
from typing import cast
|
|
4
4
|
import click
|
|
5
5
|
from prompt_toolkit.key_binding import KeyBindings
|
|
6
|
+
from prompt_toolkit import HTML
|
|
6
7
|
|
|
7
8
|
from adam.cli_group import cli
|
|
8
9
|
from adam.commands.command import Command, InvalidArgumentsException, InvalidStateException
|
|
@@ -10,17 +11,23 @@ from adam.commands.command_helpers import ClusterCommandHelper
|
|
|
10
11
|
from adam.commands.devices.devices import Devices
|
|
11
12
|
from adam.commands.help import Help
|
|
12
13
|
from adam.config import Config
|
|
14
|
+
from adam.sql.async_executor import AsyncExecutor
|
|
13
15
|
from adam.utils_audits import Audits
|
|
14
16
|
from adam.utils_k8s.kube_context import KubeContext
|
|
15
17
|
from adam.log import Log
|
|
16
18
|
from adam.repl_commands import ReplCommands
|
|
17
19
|
from adam.repl_session import ReplSession
|
|
18
20
|
from adam.repl_state import ReplState
|
|
19
|
-
from adam.utils import clear_wait_log_flag, debug_trace,
|
|
21
|
+
from adam.utils import CommandLog, clear_wait_log_flag, debug_trace, deep_sort_dict, tabulize, log2, log_exc, log_timing
|
|
20
22
|
from adam.apps import Apps
|
|
21
|
-
from adam.utils_repl.repl_completer import ReplCompleter
|
|
23
|
+
from adam.utils_repl.repl_completer import ReplCompleter, merge_completions
|
|
22
24
|
from . import __version__
|
|
23
25
|
|
|
26
|
+
import nest_asyncio
|
|
27
|
+
nest_asyncio.apply()
|
|
28
|
+
|
|
29
|
+
import asyncio
|
|
30
|
+
|
|
24
31
|
def enter_repl(state: ReplState):
|
|
25
32
|
if os.getenv('QING_DROPPED', 'false') == 'true':
|
|
26
33
|
log2('You have dropped to bash from another qing instance. Please enter "exit" to go back to qing.')
|
|
@@ -38,7 +45,7 @@ def enter_repl(state: ReplState):
|
|
|
38
45
|
|
|
39
46
|
Log.log2(f'kaqing {__version__}')
|
|
40
47
|
|
|
41
|
-
Devices.
|
|
48
|
+
Devices.of(state).enter(state)
|
|
42
49
|
|
|
43
50
|
kb = KeyBindings()
|
|
44
51
|
|
|
@@ -55,6 +62,8 @@ def enter_repl(state: ReplState):
|
|
|
55
62
|
# use sorted command list only for auto-completion
|
|
56
63
|
sorted_cmds = sorted(cmd_list, key=lambda cmd: cmd.command())
|
|
57
64
|
while True:
|
|
65
|
+
AsyncExecutor.reset()
|
|
66
|
+
|
|
58
67
|
cmd: str = None
|
|
59
68
|
result = None
|
|
60
69
|
try:
|
|
@@ -68,12 +77,12 @@ def enter_repl(state: ReplState):
|
|
|
68
77
|
|
|
69
78
|
for c in sorted_cmds:
|
|
70
79
|
with log_exc(f'* {c.command()} command returned None completions.'):
|
|
71
|
-
completions = log_timing(c.command(), lambda: deep_sort_dict(
|
|
80
|
+
completions = log_timing(c.command(), lambda: deep_sort_dict(merge_completions(completions, c.completion(state))))
|
|
72
81
|
|
|
73
82
|
# print(json.dumps(completions, indent=4))
|
|
74
83
|
completer = ReplCompleter.from_nested_dict(completions)
|
|
75
84
|
|
|
76
|
-
cmd = session.prompt(prompt_msg(), completer=completer, key_bindings=kb)
|
|
85
|
+
cmd = session.prompt(HTML(f'<ansibrightblue>{prompt_msg()}</ansibrightblue>'), completer=completer, key_bindings=kb)
|
|
77
86
|
s0 = time.time()
|
|
78
87
|
|
|
79
88
|
if state.bash_session:
|
|
@@ -88,17 +97,17 @@ def enter_repl(state: ReplState):
|
|
|
88
97
|
return state, cmd
|
|
89
98
|
|
|
90
99
|
if state.device == ReplState.A and state.app_app or state.device == ReplState.P:
|
|
91
|
-
state.push()
|
|
100
|
+
state.push(pod_targetted=True)
|
|
92
101
|
|
|
93
102
|
state.app_pod = arry[0].strip('@')
|
|
94
103
|
cmd = ' '.join(arry[1:])
|
|
95
104
|
elif state.device == ReplState.P:
|
|
96
|
-
state.push()
|
|
105
|
+
state.push(pod_targetted=True)
|
|
97
106
|
|
|
98
107
|
state.app_pod = arry[0].strip('@')
|
|
99
108
|
cmd = ' '.join(arry[1:])
|
|
100
109
|
elif state.sts:
|
|
101
|
-
state.push()
|
|
110
|
+
state.push(pod_targetted=True)
|
|
102
111
|
|
|
103
112
|
state.pod = arry[0].strip('@')
|
|
104
113
|
cmd = ' '.join(arry[1:])
|
|
@@ -137,8 +146,10 @@ def enter_repl(state: ReplState):
|
|
|
137
146
|
if cmd and (state.device != ReplState.L or Config().get('audit.log-audit-queries', False)):
|
|
138
147
|
exec.submit(Audits.log, cmd, state.namespace, state.device, time.time() - s0, get_audit_extra(result))
|
|
139
148
|
|
|
149
|
+
CommandLog.close_log_file()
|
|
150
|
+
|
|
140
151
|
def try_device_default_action(state: ReplState, cmds: Command, cmd_list: list[Command], cmd: str):
|
|
141
|
-
action_taken, result = Devices.
|
|
152
|
+
action_taken, result = Devices.of(state).try_fallback_action(cmds, state, cmd)
|
|
142
153
|
|
|
143
154
|
if not action_taken:
|
|
144
155
|
log2(f'* Invalid command: {cmd}')
|
|
@@ -175,6 +186,9 @@ def repl(kubeconfig: str, config: str, param: list[str], cluster:str, namespace:
|
|
|
175
186
|
if not KubeContext.init_params(config, param):
|
|
176
187
|
return
|
|
177
188
|
|
|
178
|
-
state = ReplState(
|
|
189
|
+
state = ReplState(ns_sts=cluster, namespace=namespace, in_repl=True)
|
|
179
190
|
state, _ = state.apply_device_arg(extra_args)
|
|
191
|
+
if not state.device:
|
|
192
|
+
state.device=Config().get('repl.start-drive', 'a')
|
|
193
|
+
|
|
180
194
|
enter_repl(state)
|