kaqing 2.0.171__py3-none-any.whl → 2.0.204__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 +7 -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 +98 -36
- 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.204.dist-info}/METADATA +1 -1
- kaqing-2.0.204.dist-info/RECORD +277 -0
- kaqing-2.0.204.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.204.dist-info}/WHEEL +0 -0
- {kaqing-2.0.171.dist-info → kaqing-2.0.204.dist-info}/entry_points.txt +0 -0
|
@@ -1,36 +1,45 @@
|
|
|
1
1
|
import functools
|
|
2
2
|
|
|
3
|
-
from adam.commands.postgres.
|
|
3
|
+
from adam.commands.postgres.postgres_databases import PostgresDatabases, pg_path
|
|
4
4
|
from adam.repl_state import ReplState
|
|
5
5
|
from adam.utils import log2, wait_log
|
|
6
6
|
from adam.utils_k8s.pods import Pods
|
|
7
7
|
|
|
8
8
|
TestPG = [False]
|
|
9
9
|
|
|
10
|
+
def direct_dirs(state: ReplState) -> list[str]:
|
|
11
|
+
with pg_path(state) as (host, database):
|
|
12
|
+
if database:
|
|
13
|
+
return ['..']
|
|
14
|
+
elif host:
|
|
15
|
+
return ['..'] + pg_database_names(state)
|
|
16
|
+
else:
|
|
17
|
+
return PostgresDatabases.host_names(state.namespace)
|
|
18
|
+
|
|
19
|
+
def pg_database_names(state: ReplState):
|
|
20
|
+
# cache on pg_path
|
|
21
|
+
return _pg_database_names(state, state.pg_path)
|
|
22
|
+
|
|
10
23
|
@functools.lru_cache()
|
|
11
|
-
def
|
|
24
|
+
def _pg_database_names(state: ReplState, pg_path: str):
|
|
12
25
|
if TestPG[0]:
|
|
13
26
|
return ['azops88_c3ai_c3']
|
|
14
27
|
|
|
15
28
|
wait_log('Inspecting Postgres Databases...')
|
|
16
29
|
|
|
17
|
-
|
|
18
|
-
|
|
30
|
+
return [db['name'] for db in PostgresDatabases.databases(state, default_owner=True)]
|
|
31
|
+
|
|
32
|
+
def pg_table_names(state: ReplState):
|
|
33
|
+
# cache on pg_path
|
|
34
|
+
return _pg_table_names(state, state.pg_path)
|
|
19
35
|
|
|
20
36
|
@functools.lru_cache()
|
|
21
|
-
def
|
|
37
|
+
def _pg_table_names(state: ReplState, pg_path: str):
|
|
22
38
|
if TestPG[0]:
|
|
23
39
|
return ['C3_2_XYZ1']
|
|
24
40
|
|
|
25
41
|
wait_log('Inspecting Postgres Database...')
|
|
26
|
-
return [table['name'] for table in
|
|
27
|
-
|
|
28
|
-
def pg_tables(ns: str, pg_path: str):
|
|
29
|
-
pg = PostgresContext.apply(ns, pg_path)
|
|
30
|
-
if pg.db:
|
|
31
|
-
return pg.tables()
|
|
32
|
-
|
|
33
|
-
return []
|
|
42
|
+
return [table['name'] for table in PostgresDatabases.tables(state, default_schema=True)]
|
|
34
43
|
|
|
35
44
|
class PostgresPodService:
|
|
36
45
|
def __init__(self, handler: 'PostgresExecHandler'):
|
|
@@ -39,22 +48,26 @@ class PostgresPodService:
|
|
|
39
48
|
def exec(self, command: str, show_out=True):
|
|
40
49
|
state = self.handler.state
|
|
41
50
|
|
|
42
|
-
pod, container =
|
|
51
|
+
pod, container = PostgresDatabases.pod_and_container(state.namespace)
|
|
43
52
|
if not pod:
|
|
44
53
|
log2('Cannot locate postgres agent or ops pod.')
|
|
45
54
|
return state
|
|
46
55
|
|
|
47
56
|
return Pods.exec(pod, container, state.namespace, command, show_out=show_out)
|
|
48
57
|
|
|
49
|
-
def sql(self, args: list[str],
|
|
58
|
+
def sql(self, args: list[str], backgrounded=False):
|
|
50
59
|
state = self.handler.state
|
|
51
60
|
|
|
52
|
-
|
|
61
|
+
query = args
|
|
62
|
+
if isinstance(args, list):
|
|
63
|
+
query = ' '.join(args)
|
|
64
|
+
|
|
65
|
+
PostgresDatabases.run_sql(state, query, backgrounded=backgrounded)
|
|
53
66
|
|
|
54
67
|
class PostgresExecHandler:
|
|
55
|
-
def __init__(self, state: ReplState,
|
|
68
|
+
def __init__(self, state: ReplState, backgrounded=False):
|
|
56
69
|
self.state = state
|
|
57
|
-
self.
|
|
70
|
+
self.backgrounded = backgrounded
|
|
58
71
|
|
|
59
72
|
def __enter__(self):
|
|
60
73
|
return PostgresPodService(self)
|
|
@@ -62,5 +75,5 @@ class PostgresExecHandler:
|
|
|
62
75
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
63
76
|
return False
|
|
64
77
|
|
|
65
|
-
def postgres(state: ReplState,
|
|
66
|
-
return PostgresExecHandler(state,
|
|
78
|
+
def postgres(state: ReplState, backgrounded=False):
|
|
79
|
+
return PostgresExecHandler(state, backgrounded=backgrounded)
|
adam/commands/preview_table.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from adam.commands import validate_args
|
|
1
2
|
from adam.commands.command import Command
|
|
2
3
|
from adam.commands.devices.devices import Devices
|
|
3
4
|
from adam.repl_state import ReplState, RequiredState
|
|
@@ -18,14 +19,15 @@ class PreviewTable(Command):
|
|
|
18
19
|
return PreviewTable.COMMAND
|
|
19
20
|
|
|
20
21
|
def required(self):
|
|
21
|
-
return [RequiredState.CLUSTER_OR_POD, RequiredState.PG_DATABASE, ReplState.L]
|
|
22
|
+
return [RequiredState.CLUSTER_OR_POD, RequiredState.PG_DATABASE, ReplState.L, RequiredState.EXPORT_DB]
|
|
22
23
|
|
|
23
24
|
def run(self, cmd: str, state: ReplState):
|
|
24
25
|
if not(args := self.args(cmd)):
|
|
25
26
|
return super().run(cmd, state)
|
|
26
27
|
|
|
27
28
|
with self.validate(args, state) as (args, state):
|
|
28
|
-
|
|
29
|
+
with validate_args(args, state, at_least=1) as table:
|
|
30
|
+
Devices.of(state).preview(table, state)
|
|
29
31
|
|
|
30
32
|
return state
|
|
31
33
|
|
adam/commands/pwd.py
CHANGED
|
@@ -2,7 +2,7 @@ from adam.app_session import AppSession
|
|
|
2
2
|
from adam.commands.command import Command
|
|
3
3
|
from adam.commands.devices.devices import Devices
|
|
4
4
|
from adam.repl_state import ReplState
|
|
5
|
-
from adam.utils import
|
|
5
|
+
from adam.utils import tabulize, log, log_exc
|
|
6
6
|
|
|
7
7
|
class Pwd(Command):
|
|
8
8
|
COMMAND = 'pwd'
|
|
@@ -25,17 +25,15 @@ class Pwd(Command):
|
|
|
25
25
|
|
|
26
26
|
with self.validate(args, state) as (_, state):
|
|
27
27
|
host = "unknown"
|
|
28
|
-
|
|
28
|
+
with log_exc():
|
|
29
29
|
app_session: AppSession = AppSession.create('c3', 'c3')
|
|
30
30
|
host = app_session.host
|
|
31
|
-
except:
|
|
32
|
-
pass
|
|
33
31
|
|
|
34
|
-
|
|
32
|
+
tabulize([device.pwd(state) for device in Devices.all()] + [
|
|
35
33
|
f'',
|
|
36
34
|
f'HOST\t{host}',
|
|
37
35
|
f'NAMESPACE\t{state.namespace if state.namespace else "/"}',
|
|
38
|
-
], 'DEVICE\tLOCATION', separator='\t')
|
|
36
|
+
], header='DEVICE\tLOCATION', separator='\t')
|
|
39
37
|
log()
|
|
40
38
|
|
|
41
39
|
return state
|
|
@@ -8,7 +8,7 @@ from adam.commands.reaper.utils_reaper import Reapers, port_forwarding
|
|
|
8
8
|
from adam.config import Config
|
|
9
9
|
from adam.repl_session import ReplSession
|
|
10
10
|
from adam.repl_state import ReplState, RequiredState
|
|
11
|
-
from adam.utils import
|
|
11
|
+
from adam.utils import tabulize, log2
|
|
12
12
|
|
|
13
13
|
class ReaperForward(Command):
|
|
14
14
|
COMMAND = 'reaper forward'
|
|
@@ -56,7 +56,7 @@ class ReaperForward(Command):
|
|
|
56
56
|
'reaper-password': spec["password"]
|
|
57
57
|
}
|
|
58
58
|
log2()
|
|
59
|
-
|
|
59
|
+
tabulize(d.items(), lambda a: f'{a[0]},{a[1]}', separator=',')
|
|
60
60
|
|
|
61
61
|
for k, v in d.items():
|
|
62
62
|
ReplSession().prompt_session.history.append_string(f'cp {k}')
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from adam.commands import validate_args
|
|
1
2
|
from adam.commands.command import Command
|
|
2
3
|
from adam.commands.reaper.utils_reaper import reaper
|
|
3
4
|
from adam.repl_state import ReplState, RequiredState
|
|
@@ -26,19 +27,12 @@ class ReaperRunAbort(Command):
|
|
|
26
27
|
return super().run(cmd, state)
|
|
27
28
|
|
|
28
29
|
with self.validate(args, state) as (args, state):
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
else:
|
|
33
|
-
Command.display_help()
|
|
30
|
+
with validate_args(args, state, name='run id') as run_id:
|
|
31
|
+
with reaper(state) as http:
|
|
32
|
+
http.put(f'repair_run/{run_id}/state/ABORTED')
|
|
34
33
|
|
|
35
34
|
return state
|
|
36
35
|
|
|
37
|
-
with reaper(state) as http:
|
|
38
|
-
http.put(f'repair_run/{args[0]}/state/ABORTED')
|
|
39
|
-
|
|
40
|
-
return state
|
|
41
|
-
|
|
42
36
|
def completion(self, state: ReplState):
|
|
43
37
|
return super().completion(state)
|
|
44
38
|
|
|
@@ -2,7 +2,7 @@ from adam.commands.command import Command
|
|
|
2
2
|
from adam.commands.reaper.utils_reaper import reaper
|
|
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, tabulize, log, log2
|
|
6
6
|
|
|
7
7
|
class ReaperRuns(Command):
|
|
8
8
|
COMMAND = 'reaper show runs'
|
|
@@ -54,7 +54,7 @@ class ReaperRuns(Command):
|
|
|
54
54
|
|
|
55
55
|
runs = response.json()
|
|
56
56
|
if runs:
|
|
57
|
-
|
|
57
|
+
tabulize(sorted([line(run) for run in runs], reverse=True), header=header, separator=",")
|
|
58
58
|
else:
|
|
59
59
|
log2('No running runs found.')
|
|
60
60
|
log2()
|
|
@@ -66,7 +66,7 @@ class ReaperRuns(Command):
|
|
|
66
66
|
|
|
67
67
|
runs = response.json()
|
|
68
68
|
if runs:
|
|
69
|
-
|
|
69
|
+
tabulize(sorted([line(run) for run in runs], reverse=True), header=header, separator=",")
|
|
70
70
|
else:
|
|
71
71
|
log2('No runs found.')
|
|
72
72
|
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
from adam.commands import validate_args
|
|
1
2
|
from adam.commands.command import Command
|
|
2
3
|
from adam.commands.reaper.utils_reaper import Reapers, reaper
|
|
3
4
|
from adam.repl_state import ReplState, RequiredState
|
|
4
|
-
|
|
5
|
+
|
|
6
|
+
import nest_asyncio
|
|
7
|
+
nest_asyncio.apply()
|
|
8
|
+
|
|
9
|
+
import asyncio
|
|
5
10
|
|
|
6
11
|
class ReaperScheduleActivate(Command):
|
|
7
12
|
COMMAND = 'reaper activate schedule'
|
|
@@ -26,20 +31,15 @@ class ReaperScheduleActivate(Command):
|
|
|
26
31
|
return super().run(cmd, state)
|
|
27
32
|
|
|
28
33
|
with self.validate(args, state) as (args, state):
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
schedule_id = args[0]
|
|
35
|
-
with reaper(state) as http:
|
|
36
|
-
http.put(f'repair_schedule/{schedule_id}?state=ACTIVE')
|
|
37
|
-
Reapers.show_schedule(state, schedule_id)
|
|
34
|
+
with validate_args(args, state, name='schedule') as schedule_id:
|
|
35
|
+
with reaper(state) as http:
|
|
36
|
+
http.put(f'repair_schedule/{schedule_id}?state=ACTIVE')
|
|
37
|
+
Reapers.show_schedule(state, schedule_id)
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
return schedule_id
|
|
40
40
|
|
|
41
41
|
def completion(self, state: ReplState):
|
|
42
|
-
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')
|
|
43
43
|
|
|
44
44
|
def help(self, _: ReplState):
|
|
45
45
|
return f'{ReaperScheduleActivate.COMMAND} <schedule-id>\t resume reaper schedule'
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
from adam.commands import validate_args
|
|
1
2
|
from adam.commands.command import Command
|
|
2
3
|
from adam.commands.reaper.utils_reaper import Reapers, reaper
|
|
3
4
|
from adam.repl_state import ReplState, RequiredState
|
|
4
|
-
from adam.utils import log2
|
|
5
5
|
|
|
6
6
|
class ReaperScheduleStart(Command):
|
|
7
7
|
COMMAND = 'reaper start schedule'
|
|
@@ -26,20 +26,15 @@ class ReaperScheduleStart(Command):
|
|
|
26
26
|
return super().run(cmd, state)
|
|
27
27
|
|
|
28
28
|
with self.validate(args, state) as (args, state):
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
with validate_args(args, state, name='schedule') as schedule_id:
|
|
30
|
+
with reaper(state) as http:
|
|
31
|
+
http.post(f'repair_schedule/start/{schedule_id}')
|
|
32
|
+
Reapers.show_schedule(state, schedule_id)
|
|
31
33
|
|
|
32
|
-
return
|
|
33
|
-
|
|
34
|
-
schedule_id = args[0]
|
|
35
|
-
with reaper(state) as http:
|
|
36
|
-
http.post(f'repair_schedule/start/{schedule_id}')
|
|
37
|
-
Reapers.show_schedule(state, schedule_id)
|
|
38
|
-
|
|
39
|
-
return schedule_id
|
|
34
|
+
return schedule_id
|
|
40
35
|
|
|
41
36
|
def completion(self, state: ReplState):
|
|
42
|
-
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')
|
|
43
38
|
|
|
44
39
|
def help(self, _: ReplState):
|
|
45
40
|
return f'{ReaperScheduleStart.COMMAND} <schedule-id>\t start reaper runs for schedule'
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
from adam.commands import validate_args
|
|
1
2
|
from adam.commands.command import Command
|
|
2
3
|
from adam.commands.reaper.utils_reaper import Reapers, reaper
|
|
3
4
|
from adam.repl_state import ReplState, RequiredState
|
|
4
|
-
from adam.utils import log2
|
|
5
5
|
|
|
6
6
|
class ReaperScheduleStop(Command):
|
|
7
7
|
COMMAND = 'reaper stop schedule'
|
|
@@ -26,20 +26,15 @@ class ReaperScheduleStop(Command):
|
|
|
26
26
|
return super().run(cmd, state)
|
|
27
27
|
|
|
28
28
|
with self.validate(args, state) as (args, state):
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
with validate_args(args, state, name='schedule') as schedule_id:
|
|
30
|
+
with reaper(state) as http:
|
|
31
|
+
http.put(f'repair_schedule/{schedule_id}?state=PAUSED')
|
|
32
|
+
Reapers.show_schedule(state, schedule_id)
|
|
31
33
|
|
|
32
|
-
return
|
|
33
|
-
|
|
34
|
-
with reaper(state) as http:
|
|
35
|
-
schedule_id = args[0]
|
|
36
|
-
http.put(f'repair_schedule/{schedule_id}?state=PAUSED')
|
|
37
|
-
Reapers.show_schedule(state, schedule_id)
|
|
38
|
-
|
|
39
|
-
return schedule_id
|
|
34
|
+
return schedule_id
|
|
40
35
|
|
|
41
36
|
def completion(self, state: ReplState):
|
|
42
|
-
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')
|
|
43
38
|
|
|
44
39
|
def help(self, _: ReplState):
|
|
45
40
|
return f'{ReaperScheduleStop.COMMAND} <schedule-id>\t pause reaper schedule'
|
|
@@ -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
|
|
10
|
+
from adam.utils import tabulize, log2, wait_log
|
|
11
11
|
from adam.utils_k8s.k8s import port_forwarding
|
|
12
12
|
|
|
13
13
|
class ReaperService:
|
|
@@ -100,7 +100,8 @@ class Reapers:
|
|
|
100
100
|
# forced refresh of schedule list
|
|
101
101
|
if not filter:
|
|
102
102
|
Reapers.schedules_ids_by_cluster[state.sts] = [schedule['id'] for schedule in schedules]
|
|
103
|
-
|
|
103
|
+
|
|
104
|
+
tabulize(schedules, lambda s: f"{s['id']} {s['state']} {s['cluster_name']} {s['keyspace_name']}", header='ID STATE CLUSTER KEYSPACE', to=2)
|
|
104
105
|
|
|
105
106
|
def schedule_ids(state: ReplState, show_output = True, filter: Callable[[list[dict]], dict] = None):
|
|
106
107
|
schedules = Reapers.list_schedules(state, show_output=show_output, filter=filter)
|
|
@@ -117,9 +118,6 @@ class Reapers:
|
|
|
117
118
|
|
|
118
119
|
return res
|
|
119
120
|
|
|
120
|
-
def show_schedules_tabular(schedules: list[dict]):
|
|
121
|
-
log2(lines_to_tabular([f"{schedule['id']} {schedule['state']} {schedule['cluster_name']} {schedule['keyspace_name']}" for schedule in schedules], 'ID STATE CLUSTER KEYSPACE'))
|
|
122
|
-
|
|
123
121
|
def list_reaper_pods(sts_name: str, namespace: str) -> List[client.V1Pod]:
|
|
124
122
|
v1 = client.CoreV1Api()
|
|
125
123
|
|
|
@@ -193,4 +191,13 @@ class Reapers:
|
|
|
193
191
|
if is_service:
|
|
194
192
|
return Reapers.svc_name()
|
|
195
193
|
else:
|
|
196
|
-
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')
|
|
@@ -31,10 +31,7 @@ class RepairLog(Command):
|
|
|
31
31
|
return state
|
|
32
32
|
|
|
33
33
|
def completion(self, state: ReplState):
|
|
34
|
-
|
|
35
|
-
return super().completion(state)
|
|
36
|
-
|
|
37
|
-
return {}
|
|
34
|
+
return super().completion(state)
|
|
38
35
|
|
|
39
36
|
def help(self, _: ReplState):
|
|
40
37
|
return f'{RepairLog.COMMAND}\t get repair job logs'
|
|
@@ -6,7 +6,7 @@ from adam.repl_state import ReplState, RequiredState
|
|
|
6
6
|
from adam.config import Config
|
|
7
7
|
from adam.commands.reaper.reaper_runs_abort import ReaperRunsAbort
|
|
8
8
|
from adam.commands.reaper.reaper_schedule_stop import ReaperScheduleStop
|
|
9
|
-
from adam.utils import log2
|
|
9
|
+
from adam.utils import log2, log_exc
|
|
10
10
|
|
|
11
11
|
class RepairRun(Command):
|
|
12
12
|
COMMAND = 'repair run'
|
|
@@ -35,14 +35,12 @@ class RepairRun(Command):
|
|
|
35
35
|
if len(args) == 1:
|
|
36
36
|
replace = args[0] == 'replace'
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
with log_exc():
|
|
39
39
|
log2("Stopping all reaper schedules...")
|
|
40
40
|
for schedule_id in Reapers.cached_schedule_ids(state):
|
|
41
41
|
ReaperScheduleStop().run(f'reaper stop schedule {schedule_id}', state)
|
|
42
42
|
log2("Aborting all reaper runs...")
|
|
43
43
|
state = ReaperRunsAbort().run('reaper abort runs', state)
|
|
44
|
-
except:
|
|
45
|
-
pass
|
|
46
44
|
|
|
47
45
|
image = Config().get('repair.image', 'ci-registry.c3iot.io/cloudops/cassrepair:2.0.11')
|
|
48
46
|
secret = Config().get('repair.secret', 'ciregistryc3iotio')
|
|
@@ -61,10 +59,7 @@ class RepairRun(Command):
|
|
|
61
59
|
return state
|
|
62
60
|
|
|
63
61
|
def completion(self, state: ReplState):
|
|
64
|
-
|
|
65
|
-
return super().completion(state)
|
|
66
|
-
|
|
67
|
-
return {}
|
|
62
|
+
return super().completion(state)
|
|
68
63
|
|
|
69
64
|
def help(self, _: ReplState):
|
|
70
65
|
return f'{RepairRun.COMMAND} [replace]\t start a repair job, default not replacing'
|
|
@@ -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
|
|
@@ -62,10 +60,7 @@ class RepairScan(Command):
|
|
|
62
60
|
return state
|
|
63
61
|
|
|
64
62
|
def completion(self, state: ReplState):
|
|
65
|
-
|
|
66
|
-
return super().completion(state)
|
|
67
|
-
|
|
68
|
-
return {}
|
|
63
|
+
return super().completion(state)
|
|
69
64
|
|
|
70
65
|
def help(self, _: ReplState):
|
|
71
66
|
return f'{RepairScan.COMMAND} [n]\t 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'
|
|
@@ -32,10 +31,7 @@ class RepairStop(Command):
|
|
|
32
31
|
return state
|
|
33
32
|
|
|
34
33
|
def completion(self, state: ReplState):
|
|
35
|
-
|
|
36
|
-
return super().completion(state)
|
|
37
|
-
|
|
38
|
-
return {}
|
|
34
|
+
return super().completion(state)
|
|
39
35
|
|
|
40
36
|
def help(self, _: ReplState):
|
|
41
37
|
return f'{RepairStop.COMMAND}\t delete a repair job'
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from adam.commands import extract_options
|
|
2
|
+
from adam.commands.command import Command
|
|
3
|
+
from adam.utils_k8s.pods import Pods
|
|
4
|
+
from adam.utils_k8s.statefulsets import StatefulSets
|
|
5
|
+
from adam.repl_state import ReplState, RequiredState
|
|
6
|
+
from adam.utils import log2
|
|
7
|
+
|
|
8
|
+
class RestartCluster(Command):
|
|
9
|
+
COMMAND = 'restart cluster'
|
|
10
|
+
|
|
11
|
+
# the singleton pattern
|
|
12
|
+
def __new__(cls, *args, **kwargs):
|
|
13
|
+
if not hasattr(cls, 'instance'): cls.instance = super(RestartCluster, 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 RestartCluster.COMMAND
|
|
22
|
+
|
|
23
|
+
def required(self):
|
|
24
|
+
return RequiredState.CLUSTER
|
|
25
|
+
|
|
26
|
+
def run(self, cmd: str, state: ReplState):
|
|
27
|
+
if not(args := self.args(cmd)):
|
|
28
|
+
return super().run(cmd, state)
|
|
29
|
+
|
|
30
|
+
with self.validate(args, state) as (args, state):
|
|
31
|
+
with extract_options(args, '--force') as (args, forced):
|
|
32
|
+
if not forced:
|
|
33
|
+
log2('Please add --force for restarting all nodes in a cluster.')
|
|
34
|
+
|
|
35
|
+
return 'force-needed'
|
|
36
|
+
|
|
37
|
+
log2(f'Restarting all pods from {state.sts}...')
|
|
38
|
+
for pod_name in StatefulSets.pod_names(state.sts, state.namespace):
|
|
39
|
+
Pods.delete(pod_name, state.namespace)
|
|
40
|
+
|
|
41
|
+
return state
|
|
42
|
+
|
|
43
|
+
def completion(self, state: ReplState):
|
|
44
|
+
return super().completion(state, {'--force': None})
|
|
45
|
+
|
|
46
|
+
def help(self, _: ReplState):
|
|
47
|
+
return f"{RestartCluster.COMMAND} --force\t restart all the nodes in the cluster"
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from adam.commands import extract_options
|
|
2
|
+
from adam.commands.command import Command
|
|
3
|
+
from adam.commands.devices.devices import Devices
|
|
4
|
+
from adam.utils_k8s.pods import Pods
|
|
5
|
+
from adam.repl_state import ReplState, RequiredState
|
|
6
|
+
from adam.utils import log2
|
|
7
|
+
|
|
8
|
+
class RestartNode(Command):
|
|
9
|
+
COMMAND = 'restart node'
|
|
10
|
+
|
|
11
|
+
# the singleton pattern
|
|
12
|
+
def __new__(cls, *args, **kwargs):
|
|
13
|
+
if not hasattr(cls, 'instance'): cls.instance = super(RestartNode, 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 RestartNode.COMMAND
|
|
22
|
+
|
|
23
|
+
def required(self):
|
|
24
|
+
return RequiredState.POD
|
|
25
|
+
|
|
26
|
+
def run(self, cmd: str, state: ReplState):
|
|
27
|
+
if not(args := self.args(cmd)):
|
|
28
|
+
return super().run(cmd, state)
|
|
29
|
+
|
|
30
|
+
with self.validate(args, state) as (args, state):
|
|
31
|
+
if not state.pod:
|
|
32
|
+
log2("'pod' is required")
|
|
33
|
+
|
|
34
|
+
return 'pod-needed'
|
|
35
|
+
|
|
36
|
+
with extract_options(args, '--force') as (args, forced):
|
|
37
|
+
if not forced:
|
|
38
|
+
log2('Please add --force for restarting pod.')
|
|
39
|
+
|
|
40
|
+
return 'force-needed'
|
|
41
|
+
|
|
42
|
+
log2(f'Restarting {state.pod}...')
|
|
43
|
+
Pods.delete(state.pod, state.namespace)
|
|
44
|
+
|
|
45
|
+
return state
|
|
46
|
+
|
|
47
|
+
def completion(self, state: ReplState):
|
|
48
|
+
return super().completion(state, {'--force': None}, pods=Devices.of(state).pods(state, '-'))
|
|
49
|
+
|
|
50
|
+
def help(self, _: ReplState):
|
|
51
|
+
return f"{RestartNode.COMMAND} --force\t restart the node"
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from adam.commands import extract_options, validate_args
|
|
2
|
+
from adam.commands.command import Command
|
|
3
|
+
from adam.utils_k8s.pods import Pods
|
|
4
|
+
from adam.utils_k8s.statefulsets import StatefulSets
|
|
5
|
+
from adam.repl_state import ReplState, RequiredState
|
|
6
|
+
from adam.utils import log2
|
|
7
|
+
|
|
8
|
+
class RestartNodes(Command):
|
|
9
|
+
COMMAND = 'restart nodes'
|
|
10
|
+
|
|
11
|
+
# the singleton pattern
|
|
12
|
+
def __new__(cls, *args, **kwargs):
|
|
13
|
+
if not hasattr(cls, 'instance'): cls.instance = super(RestartNodes, 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 RestartNodes.COMMAND
|
|
22
|
+
|
|
23
|
+
def required(self):
|
|
24
|
+
return RequiredState.CLUSTER
|
|
25
|
+
|
|
26
|
+
def run(self, cmd: str, state: ReplState):
|
|
27
|
+
if not(args := self.args(cmd)):
|
|
28
|
+
return super().run(cmd, state)
|
|
29
|
+
|
|
30
|
+
with self.validate(args, state, apply=False) as (args, state):
|
|
31
|
+
with extract_options(args, '--force') as (args, forced):
|
|
32
|
+
with validate_args(args, state, name='pod name'):
|
|
33
|
+
if not forced:
|
|
34
|
+
log2('Please add --force for restarting nodes.')
|
|
35
|
+
|
|
36
|
+
return 'force-needed'
|
|
37
|
+
|
|
38
|
+
for arg in args:
|
|
39
|
+
Pods.delete(arg, state.namespace)
|
|
40
|
+
|
|
41
|
+
return state
|
|
42
|
+
|
|
43
|
+
def completion(self, state: ReplState):
|
|
44
|
+
return super().completion(state, lambda: {p: {'--force': None} for p in StatefulSets.pod_names(state.sts, state.namespace)})
|
|
45
|
+
|
|
46
|
+
def help(self, _: ReplState):
|
|
47
|
+
return f"{RestartNodes.COMMAND} <pod-name>... --force\t restart Cassandra nodes"
|
adam/commands/shell.py
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import os
|
|
2
2
|
|
|
3
|
+
from adam.commands import validate_args
|
|
3
4
|
from adam.commands.command import Command
|
|
4
5
|
from adam.repl_state import ReplState
|
|
6
|
+
from adam.utils import log2
|
|
5
7
|
|
|
6
8
|
class Shell(Command):
|
|
7
9
|
COMMAND = ':sh'
|
|
@@ -22,8 +24,13 @@ class Shell(Command):
|
|
|
22
24
|
if not(args := self.args(cmd)):
|
|
23
25
|
return super().run(cmd, state)
|
|
24
26
|
|
|
25
|
-
with self.validate(args, state):
|
|
26
|
-
|
|
27
|
+
with self.validate(args, state) as (args, _):
|
|
28
|
+
with validate_args(args, state, at_least=0) as args_str:
|
|
29
|
+
if args_str:
|
|
30
|
+
os.system(args_str)
|
|
31
|
+
log2()
|
|
32
|
+
else:
|
|
33
|
+
os.system('QING_DROPPED=true bash')
|
|
27
34
|
|
|
28
35
|
return state
|
|
29
36
|
|