kaqing 2.0.171__py3-none-any.whl → 2.0.203__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.
- adam/app_session.py +5 -10
- adam/apps.py +18 -4
- adam/batch.py +7 -7
- adam/checks/check_utils.py +3 -1
- adam/checks/disk.py +2 -3
- adam/columns/memory.py +3 -4
- adam/commands/__init__.py +15 -6
- adam/commands/alter_tables.py +26 -41
- adam/commands/app/__init__.py +0 -0
- adam/commands/{app_cmd.py → app/app.py} +2 -2
- adam/commands/{show → app}/show_app_actions.py +7 -15
- adam/commands/{show → app}/show_app_queues.py +1 -4
- adam/{utils_app.py → commands/app/utils_app.py} +9 -1
- adam/commands/audit/audit.py +9 -26
- adam/commands/audit/audit_repair_tables.py +5 -7
- adam/commands/audit/audit_run.py +1 -1
- adam/commands/audit/completions_l.py +15 -0
- adam/commands/audit/show_last10.py +2 -14
- adam/commands/audit/show_slow10.py +2 -13
- adam/commands/audit/show_top10.py +2 -11
- adam/commands/audit/utils_show_top10.py +15 -3
- adam/commands/bash/bash.py +1 -1
- adam/commands/bash/utils_bash.py +1 -1
- adam/commands/cassandra/__init__.py +0 -0
- adam/commands/cassandra/download_cassandra_log.py +45 -0
- adam/commands/cassandra/nodetool.py +64 -0
- adam/commands/cassandra/nodetool_commands.py +120 -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/cassandra/rollout.py +88 -0
- adam/commands/cat.py +5 -19
- adam/commands/cd.py +7 -9
- adam/commands/check.py +10 -18
- adam/commands/cli_commands.py +6 -1
- adam/commands/{cp.py → clipboard_copy.py} +34 -36
- adam/commands/code.py +2 -2
- adam/commands/command.py +139 -22
- adam/commands/commands_utils.py +14 -12
- adam/commands/cql/alter_tables.py +66 -0
- adam/commands/cql/completions_c.py +29 -0
- adam/commands/cql/cqlsh.py +3 -7
- adam/commands/cql/utils_cql.py +23 -61
- 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/deploy/deploy_pg_agent.py +2 -2
- adam/commands/deploy/deploy_pod.py +2 -4
- adam/commands/deploy/undeploy_pg_agent.py +2 -2
- adam/commands/devices/device.py +40 -9
- adam/commands/devices/device_app.py +19 -29
- adam/commands/devices/device_auit_log.py +3 -3
- adam/commands/devices/device_cass.py +17 -23
- adam/commands/devices/device_export.py +12 -11
- adam/commands/devices/device_postgres.py +79 -63
- adam/commands/devices/devices.py +1 -1
- adam/commands/download_cassandra_log.py +45 -0
- adam/commands/download_file.py +47 -0
- adam/commands/export/clean_up_all_export_sessions.py +3 -3
- adam/commands/export/clean_up_export_sessions.py +7 -19
- adam/commands/export/completions_x.py +11 -0
- adam/commands/export/download_export_session.py +40 -0
- adam/commands/export/drop_export_database.py +6 -22
- adam/commands/export/drop_export_databases.py +3 -9
- adam/commands/export/export.py +1 -17
- adam/commands/export/export_databases.py +109 -32
- adam/commands/export/export_select.py +8 -55
- adam/commands/export/export_sessions.py +211 -0
- adam/commands/export/export_use.py +13 -16
- adam/commands/export/export_x_select.py +48 -0
- adam/commands/export/exporter.py +176 -167
- adam/commands/export/import_files.py +44 -0
- adam/commands/export/import_session.py +10 -6
- adam/commands/export/importer.py +24 -9
- adam/commands/export/importer_athena.py +114 -44
- adam/commands/export/importer_sqlite.py +45 -23
- adam/commands/export/show_column_counts.py +11 -20
- adam/commands/export/show_export_databases.py +5 -2
- adam/commands/export/show_export_session.py +6 -15
- adam/commands/export/show_export_sessions.py +4 -11
- adam/commands/export/utils_export.py +79 -27
- adam/commands/find_files.py +51 -0
- adam/commands/find_processes.py +76 -0
- adam/commands/generate_report.py +52 -0
- adam/commands/head.py +36 -0
- adam/commands/help.py +2 -2
- adam/commands/intermediate_command.py +6 -3
- adam/commands/login.py +3 -6
- adam/commands/ls.py +2 -2
- adam/commands/medusa/medusa_backup.py +13 -16
- adam/commands/medusa/medusa_restore.py +26 -37
- adam/commands/medusa/medusa_show_backupjobs.py +7 -7
- adam/commands/medusa/medusa_show_restorejobs.py +6 -6
- adam/commands/medusa/utils_medusa.py +15 -0
- adam/commands/nodetool.py +3 -8
- adam/commands/os/__init__.py +0 -0
- adam/commands/os/cat.py +36 -0
- adam/commands/os/download_file.py +47 -0
- adam/commands/os/find_files.py +51 -0
- adam/commands/os/find_processes.py +76 -0
- adam/commands/os/head.py +36 -0
- adam/commands/os/shell.py +41 -0
- adam/commands/param_get.py +10 -12
- adam/commands/param_set.py +7 -10
- adam/commands/postgres/completions_p.py +22 -0
- adam/commands/postgres/postgres.py +25 -40
- adam/commands/postgres/postgres_databases.py +269 -0
- adam/commands/postgres/utils_postgres.py +33 -20
- adam/commands/preview_table.py +4 -2
- adam/commands/pwd.py +4 -6
- adam/commands/reaper/reaper_forward.py +2 -2
- adam/commands/reaper/reaper_run_abort.py +4 -10
- adam/commands/reaper/reaper_runs.py +3 -3
- adam/commands/reaper/reaper_schedule_activate.py +12 -12
- adam/commands/reaper/reaper_schedule_start.py +7 -12
- adam/commands/reaper/reaper_schedule_stop.py +7 -12
- adam/commands/reaper/utils_reaper.py +13 -6
- adam/commands/repair/repair_log.py +1 -4
- adam/commands/repair/repair_run.py +3 -8
- adam/commands/repair/repair_scan.py +1 -6
- adam/commands/repair/repair_stop.py +1 -5
- adam/commands/restart_cluster.py +47 -0
- adam/commands/restart_node.py +51 -0
- adam/commands/restart_nodes.py +47 -0
- adam/commands/shell.py +9 -2
- adam/commands/show/show.py +4 -4
- adam/commands/show/show_adam.py +3 -3
- adam/commands/show/show_cassandra_repairs.py +5 -6
- adam/commands/show/show_cassandra_status.py +29 -29
- adam/commands/show/show_cassandra_version.py +1 -4
- adam/commands/show/{show_commands.py → show_cli_commands.py} +3 -6
- adam/commands/show/show_login.py +3 -9
- adam/commands/show/show_params.py +2 -5
- adam/commands/show/show_processes.py +15 -16
- adam/commands/show/show_storage.py +9 -8
- adam/config.py +4 -5
- adam/embedded_params.py +1 -1
- adam/log.py +4 -4
- adam/repl.py +26 -18
- adam/repl_commands.py +32 -20
- adam/repl_session.py +9 -1
- adam/repl_state.py +39 -10
- adam/sql/async_executor.py +44 -0
- adam/sql/lark_completer.py +286 -0
- adam/sql/lark_parser.py +604 -0
- adam/sql/qingl.lark +1076 -0
- adam/sql/sql_completer.py +4 -6
- adam/sql/sql_state_machine.py +25 -13
- adam/sso/authn_ad.py +2 -5
- adam/sso/authn_okta.py +2 -4
- adam/sso/cred_cache.py +2 -5
- adam/sso/idp.py +8 -11
- adam/utils.py +299 -105
- adam/utils_athena.py +18 -18
- adam/utils_audits.py +3 -7
- adam/utils_issues.py +2 -2
- adam/utils_k8s/app_clusters.py +4 -4
- adam/utils_k8s/app_pods.py +8 -6
- adam/utils_k8s/cassandra_clusters.py +16 -5
- adam/utils_k8s/cassandra_nodes.py +9 -6
- adam/utils_k8s/custom_resources.py +11 -17
- adam/utils_k8s/jobs.py +7 -11
- adam/utils_k8s/k8s.py +14 -5
- adam/utils_k8s/kube_context.py +3 -6
- adam/{pod_exec_result.py → utils_k8s/pod_exec_result.py} +4 -4
- adam/utils_k8s/pods.py +85 -23
- adam/utils_k8s/statefulsets.py +5 -2
- adam/utils_local.py +42 -0
- adam/utils_repl/appendable_completer.py +6 -0
- adam/utils_repl/repl_completer.py +45 -2
- adam/utils_repl/state_machine.py +3 -3
- adam/utils_sqlite.py +58 -30
- adam/version.py +1 -1
- {kaqing-2.0.171.dist-info → kaqing-2.0.203.dist-info}/METADATA +1 -1
- kaqing-2.0.203.dist-info/RECORD +277 -0
- kaqing-2.0.203.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 -33
- adam/commands/export/export_handlers.py +0 -71
- adam/commands/export/export_select_x.py +0 -54
- adam/commands/logs.py +0 -37
- adam/commands/postgres/postgres_context.py +0 -274
- adam/commands/postgres/psql_completions.py +0 -10
- adam/commands/report.py +0 -61
- adam/commands/restart.py +0 -60
- kaqing-2.0.171.dist-info/RECORD +0 -236
- kaqing-2.0.171.dist-info/top_level.txt +0 -1
- /adam/commands/{app_ping.py → app/app_ping.py} +0 -0
- /adam/commands/{show → app}/show_app_id.py +0 -0
- {kaqing-2.0.171.dist-info → kaqing-2.0.203.dist-info}/WHEEL +0 -0
- {kaqing-2.0.171.dist-info → kaqing-2.0.203.dist-info}/entry_points.txt +0 -0
adam/commands/show/show.py
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import click
|
|
2
2
|
|
|
3
|
+
from adam.commands.app.show_app_actions import ShowAppActions
|
|
4
|
+
from adam.commands.app.show_app_id import ShowAppId
|
|
5
|
+
from adam.commands.app.show_app_queues import ShowAppQueues
|
|
3
6
|
from adam.commands.intermediate_command import IntermediateCommand
|
|
4
7
|
from adam.commands.medusa.medusa_show_backupjobs import MedusaShowBackupJobs
|
|
5
8
|
from adam.commands.medusa.medusa_show_restorejobs import MedusaShowRestoreJobs
|
|
6
|
-
from adam.commands.show.show_app_actions import ShowAppActions
|
|
7
|
-
from adam.commands.show.show_app_queues import ShowAppQueues
|
|
8
9
|
from adam.commands.show.show_host import ShowHost
|
|
9
10
|
from adam.commands.show.show_login import ShowLogin
|
|
10
11
|
from .show_params import ShowParams
|
|
11
|
-
from .show_app_id import ShowAppId
|
|
12
12
|
from .show_cassandra_status import ShowCassandraStatus
|
|
13
13
|
from .show_cassandra_version import ShowCassandraVersion
|
|
14
|
-
from .
|
|
14
|
+
from .show_cli_commands import ShowKubectlCommands
|
|
15
15
|
from .show_processes import ShowProcesses
|
|
16
16
|
from .show_cassandra_repairs import ShowCassandraRepairs
|
|
17
17
|
from .show_storage import ShowStorage
|
adam/commands/show/show_adam.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import sys
|
|
2
2
|
import os
|
|
3
3
|
|
|
4
|
-
from adam.utils import
|
|
4
|
+
from adam.utils import tabulize, log2
|
|
5
5
|
|
|
6
6
|
current_dir = os.path.dirname(os.path.abspath(__file__))
|
|
7
7
|
|
|
@@ -34,10 +34,10 @@ class ShowAdam(Command):
|
|
|
34
34
|
|
|
35
35
|
package = os.path.dirname(os.path.abspath(__file__))
|
|
36
36
|
package = package.split('/adam/')[0] + '/adam'
|
|
37
|
-
|
|
37
|
+
tabulize([
|
|
38
38
|
f'version\t{__version__}',
|
|
39
39
|
f'source\t{package}'
|
|
40
|
-
], separator='\t')
|
|
40
|
+
], separator='\t', to=2)
|
|
41
41
|
|
|
42
42
|
return state
|
|
43
43
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from adam.commands import extract_trailing_options
|
|
1
2
|
from adam.commands.command import Command
|
|
2
3
|
from adam.commands.cql.utils_cql import cassandra
|
|
3
4
|
from adam.repl_state import ReplState, RequiredState
|
|
@@ -25,14 +26,12 @@ class ShowCassandraRepairs(Command):
|
|
|
25
26
|
return super().run(cmd, state)
|
|
26
27
|
|
|
27
28
|
with self.validate(args, state) as (args, state):
|
|
28
|
-
with
|
|
29
|
-
|
|
29
|
+
with extract_trailing_options(args, '&') as (args, backgrounded):
|
|
30
|
+
with cassandra(state) as pods:
|
|
31
|
+
return pods.nodetool('repair_admin list', backgrounded=backgrounded)
|
|
30
32
|
|
|
31
33
|
def completion(self, state: ReplState):
|
|
32
|
-
|
|
33
|
-
return super().completion(state)
|
|
34
|
-
|
|
35
|
-
return {}
|
|
34
|
+
return super().completion(state, {'&': None})
|
|
36
35
|
|
|
37
36
|
def help(self, _: ReplState):
|
|
38
37
|
return f'{ShowCassandraRepairs.COMMAND}\t show Cassandra repairs'
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from datetime import datetime
|
|
1
2
|
import sys
|
|
2
3
|
|
|
3
4
|
from adam.checks.check_result import CheckResult
|
|
@@ -5,14 +6,15 @@ from adam.checks.check_utils import run_checks
|
|
|
5
6
|
from adam.checks.compactionstats import CompactionStats
|
|
6
7
|
from adam.checks.gossip import Gossip
|
|
7
8
|
from adam.columns.columns import Columns
|
|
8
|
-
from adam.commands import extract_options
|
|
9
|
+
from adam.commands import extract_options, extract_trailing_options
|
|
9
10
|
from adam.commands.command import Command
|
|
10
11
|
from adam.commands.cql.utils_cql import cassandra
|
|
11
12
|
from adam.config import Config
|
|
13
|
+
from adam.repl_session import ReplSession
|
|
12
14
|
from adam.utils_issues import IssuesUtils
|
|
13
15
|
from adam.utils_k8s.statefulsets import StatefulSets
|
|
14
16
|
from adam.repl_state import ReplState, RequiredState
|
|
15
|
-
from adam.utils import
|
|
17
|
+
from adam.utils import SORT, tabulize, log2, log_exc
|
|
16
18
|
from adam.checks.status import parse_nodetool_status
|
|
17
19
|
|
|
18
20
|
class ShowCassandraStatus(Command):
|
|
@@ -38,32 +40,31 @@ class ShowCassandraStatus(Command):
|
|
|
38
40
|
return super().run(cmd, state)
|
|
39
41
|
|
|
40
42
|
with self.validate(args, state) as (args, state):
|
|
41
|
-
with
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
with extract_trailing_options(args, '&') as (args, backgrounded):
|
|
44
|
+
with extract_options(args, ['-s', '--show']) as (args, show_out):
|
|
45
|
+
if state.namespace and state.pod:
|
|
46
|
+
self.show_single_pod(state, show_out=show_out, backgrounded=backgrounded)
|
|
47
|
+
elif state.namespace and state.sts:
|
|
48
|
+
self.merge(state, Config().get('nodetool.samples', sys.maxsize), show_output=show_out, backgrounded=backgrounded)
|
|
46
49
|
|
|
47
|
-
|
|
50
|
+
return state
|
|
48
51
|
|
|
49
|
-
def show_single_pod(self, state: ReplState, show_out = False):
|
|
50
|
-
|
|
52
|
+
def show_single_pod(self, state: ReplState, show_out = False, backgrounded = False):
|
|
53
|
+
with log_exc(True):
|
|
51
54
|
with cassandra(state) as pods:
|
|
52
55
|
result = pods.nodetool('status', show_out=False)
|
|
53
56
|
status = parse_nodetool_status(result.stdout)
|
|
54
57
|
check_results = run_checks(cluster=state.sts, namespace=state.namespace, checks=[CompactionStats(), Gossip()], show_out=show_out)
|
|
55
|
-
self.show_table(status, check_results)
|
|
56
|
-
except Exception as e:
|
|
57
|
-
log2(e)
|
|
58
|
+
self.show_table(status, check_results, backgrounded=backgrounded)
|
|
58
59
|
|
|
59
|
-
def merge(self, state: ReplState, samples: int, show_output=False):
|
|
60
|
+
def merge(self, state: ReplState, samples: int, show_output=False, backgrounded = False):
|
|
60
61
|
statuses: list[list[dict]] = []
|
|
61
62
|
|
|
62
63
|
pod_names = StatefulSets.pod_names(state.sts, state.namespace)
|
|
63
64
|
for pod_name in pod_names:
|
|
64
65
|
pod_name = pod_name.split('(')[0]
|
|
65
66
|
|
|
66
|
-
|
|
67
|
+
with log_exc(True):
|
|
67
68
|
with cassandra(state, pod=pod_name) as pods:
|
|
68
69
|
result = pods.nodetool('status', show_out=False)
|
|
69
70
|
status = parse_nodetool_status(result.stdout)
|
|
@@ -71,13 +72,11 @@ class ShowCassandraStatus(Command):
|
|
|
71
72
|
statuses.append(status)
|
|
72
73
|
if samples <= len(statuses) and len(pod_names) != len(statuses):
|
|
73
74
|
break
|
|
74
|
-
except Exception as e:
|
|
75
|
-
log2(e)
|
|
76
75
|
|
|
77
76
|
combined_status = self.merge_status(statuses)
|
|
78
77
|
log2(f'Showing merged status from {len(statuses)}/{len(pod_names)} nodes...')
|
|
79
78
|
check_results = run_checks(cluster=state.sts, namespace=state.namespace, checks=[CompactionStats(), Gossip()], show_out=show_output)
|
|
80
|
-
self.show_table(combined_status, check_results)
|
|
79
|
+
self.show_table(combined_status, check_results, backgrounded=backgrounded)
|
|
81
80
|
|
|
82
81
|
return combined_status
|
|
83
82
|
|
|
@@ -98,27 +97,28 @@ class ShowCassandraStatus(Command):
|
|
|
98
97
|
|
|
99
98
|
return combined
|
|
100
99
|
|
|
101
|
-
def show_table(self, status: list[dict[str, any]], check_results: list[CheckResult]):
|
|
100
|
+
def show_table(self, status: list[dict[str, any]], check_results: list[CheckResult], backgrounded=False):
|
|
102
101
|
cols = Config().get('status.columns', 'status,address,load,tokens,owns,host_id,gossip,compactions')
|
|
103
102
|
header = Config().get('status.header', '--,Address,Load,Tokens,Owns,Host ID,GOSSIP,COMPACTIONS')
|
|
104
103
|
columns = Columns.create_columns(cols)
|
|
105
104
|
|
|
106
|
-
|
|
107
|
-
cells = [c.host_value(check_results, status) for c in columns]
|
|
108
|
-
return ','.join(cells)
|
|
105
|
+
r = tabulize(status, lambda s: ','.join([c.host_value(check_results, s) for c in columns]), header=header, separator=',', sorted=SORT, to = 0 if backgrounded else 1)
|
|
109
106
|
|
|
110
|
-
|
|
111
|
-
|
|
107
|
+
if backgrounded:
|
|
108
|
+
log_prefix = Config().get('log-prefix', '/tmp/qing')
|
|
109
|
+
log_file = f'{log_prefix}-{datetime.now().strftime("%d%H%M%S")}.log'
|
|
112
110
|
|
|
113
|
-
|
|
111
|
+
with open(log_file, 'w') as f:
|
|
112
|
+
f.write(r)
|
|
113
|
+
|
|
114
|
+
ReplSession().append_history(f':sh cat {log_file}')
|
|
115
|
+
|
|
116
|
+
r = log_file
|
|
114
117
|
|
|
115
118
|
IssuesUtils.show(check_results)
|
|
116
119
|
|
|
117
120
|
def completion(self, state: ReplState):
|
|
118
|
-
|
|
119
|
-
return super().completion(state, {'-s': None})
|
|
120
|
-
|
|
121
|
-
return {}
|
|
121
|
+
return super().completion(state, {'-s': {'&': None}, '&': None})
|
|
122
122
|
|
|
123
123
|
def help(self, _: ReplState):
|
|
124
124
|
return f'{ShowCassandraStatus.COMMAND} [-s]\t show merged nodetool status -s show commands on nodes'
|
|
@@ -29,10 +29,7 @@ class ShowCassandraVersion(Command):
|
|
|
29
29
|
return pods.cql('show version', show_out=True, on_any=True)
|
|
30
30
|
|
|
31
31
|
def completion(self, state: ReplState):
|
|
32
|
-
|
|
33
|
-
return super().completion(state)
|
|
34
|
-
|
|
35
|
-
return {}
|
|
32
|
+
return super().completion(state)
|
|
36
33
|
|
|
37
34
|
def help(self, _: ReplState):
|
|
38
35
|
return f'{ShowCassandraVersion.COMMAND}\t show Cassandra version'
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from adam.commands.command import Command
|
|
2
2
|
from adam.commands.cli_commands import CliCommands
|
|
3
3
|
from adam.repl_state import ReplState, RequiredState
|
|
4
|
-
from adam.utils import
|
|
4
|
+
from adam.utils import tabulize, log
|
|
5
5
|
|
|
6
6
|
class ShowKubectlCommands(Command):
|
|
7
7
|
COMMAND = 'show cli-commands'
|
|
@@ -22,7 +22,7 @@ class ShowKubectlCommands(Command):
|
|
|
22
22
|
return RequiredState.CLUSTER_OR_POD
|
|
23
23
|
|
|
24
24
|
def run(self, cmd: str, state: ReplState):
|
|
25
|
-
if not self.args(cmd):
|
|
25
|
+
if not (args := self.args(cmd)):
|
|
26
26
|
return super().run(cmd, state)
|
|
27
27
|
|
|
28
28
|
with self.validate(args, state) as (args, state):
|
|
@@ -45,14 +45,11 @@ class ShowKubectlCommands(Command):
|
|
|
45
45
|
|
|
46
46
|
cmds += [f'{k},{v0}' for k, v0 in v.items() if k.startswith('pg-')]
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
tabulize(cmds, separator=',')
|
|
49
49
|
|
|
50
50
|
return cmds
|
|
51
51
|
|
|
52
52
|
def completion(self, state: ReplState):
|
|
53
|
-
if not state.sts:
|
|
54
|
-
return {}
|
|
55
|
-
|
|
56
53
|
return super().completion(state)
|
|
57
54
|
|
|
58
55
|
def help(self, _: ReplState):
|
adam/commands/show/show_login.py
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import time
|
|
2
|
-
import traceback
|
|
3
2
|
|
|
4
3
|
from adam.apps import Apps
|
|
5
|
-
from adam.config import Config
|
|
6
4
|
from adam.sso.idp import Idp
|
|
7
5
|
from adam.sso.idp_login import IdpLogin
|
|
8
6
|
from adam.commands.command import Command
|
|
9
7
|
from adam.repl_state import ReplState
|
|
10
|
-
from adam.utils import duration,
|
|
8
|
+
from adam.utils import duration, tabulize, log, log2, log_exc
|
|
11
9
|
|
|
12
10
|
class ShowLogin(Command):
|
|
13
11
|
COMMAND = 'show login'
|
|
@@ -33,7 +31,7 @@ class ShowLogin(Command):
|
|
|
33
31
|
|
|
34
32
|
with self.validate(args, state) as (args, state):
|
|
35
33
|
login: IdpLogin = None
|
|
36
|
-
|
|
34
|
+
with log_exc(True):
|
|
37
35
|
if not(host := Apps.app_host('c3', 'c3', state.namespace)):
|
|
38
36
|
log2('Cannot locate ingress for app.')
|
|
39
37
|
return state
|
|
@@ -47,11 +45,7 @@ class ShowLogin(Command):
|
|
|
47
45
|
f'IDP expires in\t{duration(time.time(), it.exp)}',
|
|
48
46
|
f'IDP Groups\t{",".join(it.groups)}'
|
|
49
47
|
]
|
|
50
|
-
|
|
51
|
-
except Exception as e:
|
|
52
|
-
log2(e)
|
|
53
|
-
if Config().is_debug():
|
|
54
|
-
log2(traceback.format_exc())
|
|
48
|
+
tabulize(lines, separator='\t')
|
|
55
49
|
|
|
56
50
|
return state
|
|
57
51
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from adam.commands.command import Command
|
|
2
2
|
from adam.config import Config
|
|
3
3
|
from adam.repl_state import ReplState
|
|
4
|
-
from adam.utils import
|
|
4
|
+
from adam.utils import tabulize
|
|
5
5
|
|
|
6
6
|
class ShowParams(Command):
|
|
7
7
|
COMMAND = 'show params'
|
|
@@ -22,10 +22,7 @@ class ShowParams(Command):
|
|
|
22
22
|
if not self.args(cmd):
|
|
23
23
|
return super().run(cmd, state)
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
log(lines_to_tabular(lines, separator='\t'))
|
|
27
|
-
|
|
28
|
-
return lines
|
|
25
|
+
return tabulize(Config().keys(), lambda k: f'{k}\t{Config().get(k, None)}', separator='\t')
|
|
29
26
|
|
|
30
27
|
def completion(self, state: ReplState):
|
|
31
28
|
return super().completion(state)
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
from adam.commands import extract_options
|
|
1
|
+
from adam.commands import extract_options, extract_sequence, extract_trailing_options
|
|
2
2
|
from adam.commands.command import Command
|
|
3
|
-
from adam.commands.commands_utils import show_table
|
|
4
3
|
from adam.commands.cql.utils_cql import cassandra
|
|
5
4
|
from adam.config import Config
|
|
6
|
-
from adam.utils_k8s.statefulsets import StatefulSets
|
|
7
5
|
from adam.repl_state import ReplState, RequiredState
|
|
8
6
|
|
|
9
7
|
class ShowProcesses(Command):
|
|
@@ -29,23 +27,24 @@ class ShowProcesses(Command):
|
|
|
29
27
|
return super().run(cmd, state)
|
|
30
28
|
|
|
31
29
|
with self.validate(args, state) as (args, state):
|
|
32
|
-
with
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
with extract_trailing_options(args, '&') as (args, backgrounded):
|
|
31
|
+
with extract_options(args, ['-s', '--show']) as (args, show_out):
|
|
32
|
+
with extract_sequence(args, ['with', 'recipe', '=', 'qing']) as (_, recipe_qing):
|
|
33
|
+
cols = Config().get('processes.columns', 'pod,cpu-metrics,mem')
|
|
34
|
+
header = Config().get('processes.header', 'POD_NAME,M_CPU(USAGE/LIMIT),MEM/LIMIT')
|
|
35
|
+
if recipe_qing:
|
|
36
|
+
cols = Config().get('processes-qing.columns', 'pod,cpu,mem')
|
|
37
|
+
header = Config().get('processes-qing.header', 'POD_NAME,Q_CPU/TOTAL,MEM/LIMIT')
|
|
35
38
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
if set(recipe_qing) == set(qing_args):
|
|
39
|
-
cols = Config().get('processes-qing.columns', 'pod,cpu,mem')
|
|
40
|
-
header = Config().get('processes-qing.header', 'POD_NAME,Q_CPU/TOTAL,MEM/LIMIT')
|
|
39
|
+
with cassandra(state) as pods:
|
|
40
|
+
pods.display_table(cols, header, show_out=show_out, backgrounded=backgrounded)
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
pods.show_table(cols, header, show_out=show_out)
|
|
44
|
-
|
|
45
|
-
return state
|
|
42
|
+
return state
|
|
46
43
|
|
|
47
44
|
def completion(self, state: ReplState):
|
|
48
|
-
|
|
45
|
+
recipes = ['metrics', 'qing']
|
|
46
|
+
return super().completion(state, {'with': {'recipe': {'=': {r: {'-s': {'&': None}, '&': None} for r in recipes}}}, '-s': {'&': None}, '&': None})
|
|
47
|
+
# return super().completion(state, {'with': {'recipe': {'=': {'metrics': {'-s': {'&': None}, '&': None}, 'qing': {'-s': {'&': None}}}}}, '-s': {'&': None}, '&': None})
|
|
49
48
|
|
|
50
49
|
def help(self, _: ReplState):
|
|
51
50
|
return f'{ShowProcesses.COMMAND} [with recipe qing|metrics] [-s]\t show process overview -s show commands on nodes'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from adam.commands import extract_options
|
|
1
|
+
from adam.commands import extract_options, extract_trailing_options
|
|
2
2
|
from adam.commands.command import Command
|
|
3
3
|
from adam.commands.cql.utils_cql import cassandra
|
|
4
4
|
from adam.config import Config
|
|
@@ -27,16 +27,17 @@ class ShowStorage(Command):
|
|
|
27
27
|
return super().run(cmd, state)
|
|
28
28
|
|
|
29
29
|
with self.validate(args, state) as (args, state):
|
|
30
|
-
with
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
with extract_trailing_options(args, '&') as (args, backgrounded):
|
|
31
|
+
with extract_options(args, ['-s', '--show']) as (args, show_out):
|
|
32
|
+
cols = Config().get('storage.columns', 'pod,volume_root,volume_cassandra,snapshots,data,compactions')
|
|
33
|
+
header = Config().get('storage.header', 'POD_NAME,VOLUME /,VOLUME CASS,SNAPSHOTS,DATA,COMPACTIONS')
|
|
34
|
+
with cassandra(state) as pods:
|
|
35
|
+
pods.display_table(cols, header, show_out=show_out, backgrounded=backgrounded)
|
|
35
36
|
|
|
36
|
-
|
|
37
|
+
return state
|
|
37
38
|
|
|
38
39
|
def completion(self, state: ReplState):
|
|
39
|
-
return super().completion(state, {'-s': None})
|
|
40
|
+
return super().completion(state, {'-s': {'&': None}, '&': None})
|
|
40
41
|
|
|
41
42
|
def help(self, _: ReplState):
|
|
42
43
|
return f'{ShowStorage.COMMAND} [-s]\t show storage overview -s show commands on nodes'
|
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'}}, '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}}, '
|
|
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-prefix': '/tmp/qing'}, '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}, 'local-tmp-dir': '/tmp/qing-db', 'logs': {'path': '/c3/cassandra/logs/system.log'}, 'log-prefix': '/tmp/qing', 'nodetool': {'workers': 96, 'commands_in_line': 40, '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-qing': {'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, 'via-sh': True, 'via-sh-excludes': ''}}, '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'}, '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/log.py
CHANGED
|
@@ -4,6 +4,8 @@ import os
|
|
|
4
4
|
import sys
|
|
5
5
|
import click
|
|
6
6
|
|
|
7
|
+
from adam.utils import log_exc
|
|
8
|
+
|
|
7
9
|
class Log:
|
|
8
10
|
DEBUG = False
|
|
9
11
|
|
|
@@ -28,7 +30,7 @@ class Log:
|
|
|
28
30
|
print(file=sys.stderr)
|
|
29
31
|
|
|
30
32
|
def log_to_file(config: dict[any, any]):
|
|
31
|
-
|
|
33
|
+
with log_exc():
|
|
32
34
|
base = f"/tmp/logs"
|
|
33
35
|
os.makedirs(base, exist_ok=True)
|
|
34
36
|
|
|
@@ -42,6 +44,4 @@ class Log:
|
|
|
42
44
|
except:
|
|
43
45
|
f.write(config)
|
|
44
46
|
else:
|
|
45
|
-
f.write(config)
|
|
46
|
-
except:
|
|
47
|
-
pass
|
|
47
|
+
f.write(config)
|
adam/repl.py
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import time
|
|
3
|
-
import traceback
|
|
4
3
|
from typing import cast
|
|
5
4
|
import click
|
|
6
5
|
from prompt_toolkit.key_binding import KeyBindings
|
|
7
6
|
|
|
8
7
|
from adam.cli_group import cli
|
|
9
|
-
from adam.commands.command import Command,
|
|
8
|
+
from adam.commands.command import Command, InvalidArgumentsException, InvalidStateException
|
|
10
9
|
from adam.commands.command_helpers import ClusterCommandHelper
|
|
11
10
|
from adam.commands.devices.devices import Devices
|
|
12
11
|
from adam.commands.help import Help
|
|
@@ -17,11 +16,16 @@ from adam.log import Log
|
|
|
17
16
|
from adam.repl_commands import ReplCommands
|
|
18
17
|
from adam.repl_session import ReplSession
|
|
19
18
|
from adam.repl_state import ReplState
|
|
20
|
-
from adam.utils import
|
|
19
|
+
from adam.utils import CommandLog, clear_wait_log_flag, debug_trace, deep_sort_dict, tabulize, log2, log_exc, log_timing
|
|
21
20
|
from adam.apps import Apps
|
|
22
|
-
from adam.utils_repl.repl_completer import ReplCompleter
|
|
21
|
+
from adam.utils_repl.repl_completer import ReplCompleter, merge_completions
|
|
23
22
|
from . import __version__
|
|
24
23
|
|
|
24
|
+
import nest_asyncio
|
|
25
|
+
nest_asyncio.apply()
|
|
26
|
+
|
|
27
|
+
import asyncio
|
|
28
|
+
|
|
25
29
|
def enter_repl(state: ReplState):
|
|
26
30
|
if os.getenv('QING_DROPPED', 'false') == 'true':
|
|
27
31
|
log2('You have dropped to bash from another qing instance. Please enter "exit" to go back to qing.')
|
|
@@ -39,7 +43,7 @@ def enter_repl(state: ReplState):
|
|
|
39
43
|
|
|
40
44
|
Log.log2(f'kaqing {__version__}')
|
|
41
45
|
|
|
42
|
-
Devices.
|
|
46
|
+
Devices.of(state).enter(state)
|
|
43
47
|
|
|
44
48
|
kb = KeyBindings()
|
|
45
49
|
|
|
@@ -68,10 +72,8 @@ def enter_repl(state: ReplState):
|
|
|
68
72
|
completions = log_timing('actions', lambda: Apps(path='apps.yaml').commands())
|
|
69
73
|
|
|
70
74
|
for c in sorted_cmds:
|
|
71
|
-
|
|
72
|
-
completions = log_timing(c.command(), lambda: deep_sort_dict(
|
|
73
|
-
except:
|
|
74
|
-
log2(f'* {c.command()} command returned None completions.')
|
|
75
|
+
with log_exc(f'* {c.command()} command returned None completions.'):
|
|
76
|
+
completions = log_timing(c.command(), lambda: deep_sort_dict(merge_completions(completions, c.completion(state))))
|
|
75
77
|
|
|
76
78
|
# print(json.dumps(completions, indent=4))
|
|
77
79
|
completer = ReplCompleter.from_nested_dict(completions)
|
|
@@ -91,17 +93,17 @@ def enter_repl(state: ReplState):
|
|
|
91
93
|
return state, cmd
|
|
92
94
|
|
|
93
95
|
if state.device == ReplState.A and state.app_app or state.device == ReplState.P:
|
|
94
|
-
state.push()
|
|
96
|
+
state.push(pod_targetted=True)
|
|
95
97
|
|
|
96
98
|
state.app_pod = arry[0].strip('@')
|
|
97
99
|
cmd = ' '.join(arry[1:])
|
|
98
100
|
elif state.device == ReplState.P:
|
|
99
|
-
state.push()
|
|
101
|
+
state.push(pod_targetted=True)
|
|
100
102
|
|
|
101
103
|
state.app_pod = arry[0].strip('@')
|
|
102
104
|
cmd = ' '.join(arry[1:])
|
|
103
105
|
elif state.sts:
|
|
104
|
-
state.push()
|
|
106
|
+
state.push(pod_targetted=True)
|
|
105
107
|
|
|
106
108
|
state.pod = arry[0].strip('@')
|
|
107
109
|
cmd = ' '.join(arry[1:])
|
|
@@ -112,7 +114,9 @@ def enter_repl(state: ReplState):
|
|
|
112
114
|
try:
|
|
113
115
|
if cmd and cmd.strip(' ') and not (result := cmds.run(cmd, target)):
|
|
114
116
|
result = try_device_default_action(target, cmds, cmd_list, cmd)
|
|
115
|
-
except
|
|
117
|
+
except InvalidStateException:
|
|
118
|
+
pass
|
|
119
|
+
except InvalidArgumentsException:
|
|
116
120
|
pass
|
|
117
121
|
|
|
118
122
|
if result and type(result) is ReplState and (s := cast(ReplState, result).export_session) != state.export_session:
|
|
@@ -125,7 +129,7 @@ def enter_repl(state: ReplState):
|
|
|
125
129
|
raise e
|
|
126
130
|
else:
|
|
127
131
|
log2(e)
|
|
128
|
-
|
|
132
|
+
debug_trace()
|
|
129
133
|
finally:
|
|
130
134
|
if not state.bash_session:
|
|
131
135
|
state.pop()
|
|
@@ -138,14 +142,15 @@ def enter_repl(state: ReplState):
|
|
|
138
142
|
if cmd and (state.device != ReplState.L or Config().get('audit.log-audit-queries', False)):
|
|
139
143
|
exec.submit(Audits.log, cmd, state.namespace, state.device, time.time() - s0, get_audit_extra(result))
|
|
140
144
|
|
|
145
|
+
CommandLog.close_log_file()
|
|
146
|
+
|
|
141
147
|
def try_device_default_action(state: ReplState, cmds: Command, cmd_list: list[Command], cmd: str):
|
|
142
|
-
action_taken, result = Devices.
|
|
148
|
+
action_taken, result = Devices.of(state).try_fallback_action(cmds, state, cmd)
|
|
143
149
|
|
|
144
150
|
if not action_taken:
|
|
145
151
|
log2(f'* Invalid command: {cmd}')
|
|
146
152
|
log2()
|
|
147
|
-
|
|
148
|
-
log2(lines_to_tabular(lines, separator='\t'))
|
|
153
|
+
tabulize([c.help(state) for c in cmd_list if c.help(state)], separator='\t', to=2)
|
|
149
154
|
|
|
150
155
|
return result
|
|
151
156
|
|
|
@@ -177,6 +182,9 @@ def repl(kubeconfig: str, config: str, param: list[str], cluster:str, namespace:
|
|
|
177
182
|
if not KubeContext.init_params(config, param):
|
|
178
183
|
return
|
|
179
184
|
|
|
180
|
-
state = ReplState(
|
|
185
|
+
state = ReplState(ns_sts=cluster, namespace=namespace, in_repl=True)
|
|
181
186
|
state, _ = state.apply_device_arg(extra_args)
|
|
187
|
+
if not state.device:
|
|
188
|
+
state.device=Config().get('repl.start-drive', 'a')
|
|
189
|
+
|
|
182
190
|
enter_repl(state)
|