kaqing 2.0.98__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/__init__.py +0 -2
- adam/app_session.py +9 -12
- adam/apps.py +18 -4
- adam/batch.py +11 -25
- adam/checks/check_utils.py +16 -46
- adam/checks/cpu.py +7 -1
- adam/checks/cpu_metrics.py +52 -0
- adam/checks/disk.py +2 -3
- adam/columns/columns.py +3 -1
- adam/columns/cpu.py +3 -1
- adam/columns/cpu_metrics.py +22 -0
- adam/columns/memory.py +3 -4
- adam/commands/__init__.py +24 -0
- adam/commands/alter_tables.py +37 -63
- adam/commands/app/app.py +38 -0
- adam/commands/{app_ping.py → app/app_ping.py} +8 -14
- adam/commands/app/show_app_actions.py +49 -0
- adam/commands/{show → app}/show_app_id.py +8 -11
- adam/commands/{show → app}/show_app_queues.py +8 -14
- adam/commands/app/utils_app.py +106 -0
- adam/commands/audit/audit.py +31 -35
- adam/commands/audit/audit_repair_tables.py +26 -48
- adam/commands/audit/audit_run.py +50 -0
- adam/commands/audit/completions_l.py +15 -0
- adam/commands/audit/show_last10.py +36 -0
- adam/commands/audit/show_slow10.py +36 -0
- adam/commands/audit/show_top10.py +36 -0
- adam/commands/audit/utils_show_top10.py +71 -0
- adam/commands/bash/__init__.py +5 -0
- adam/commands/bash/bash.py +36 -0
- adam/commands/bash/bash_completer.py +93 -0
- adam/commands/bash/utils_bash.py +16 -0
- adam/commands/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/{restart.py → cassandra/restart_cluster.py} +12 -26
- 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 +36 -0
- adam/commands/cd.py +14 -92
- adam/commands/check.py +18 -21
- adam/commands/cli_commands.py +8 -4
- adam/commands/clipboard_copy.py +87 -0
- adam/commands/code.py +57 -0
- adam/commands/command.py +212 -39
- adam/commands/commands_utils.py +20 -28
- adam/commands/cql/alter_tables.py +66 -0
- adam/commands/cql/completions_c.py +29 -0
- adam/commands/cql/cqlsh.py +10 -29
- adam/commands/cql/utils_cql.py +305 -0
- 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/code_start.py +7 -10
- adam/commands/deploy/code_stop.py +4 -21
- adam/commands/deploy/code_utils.py +3 -3
- adam/commands/deploy/deploy.py +4 -21
- adam/commands/deploy/deploy_frontend.py +14 -17
- adam/commands/deploy/deploy_pg_agent.py +3 -6
- adam/commands/deploy/deploy_pod.py +65 -73
- adam/commands/deploy/deploy_utils.py +14 -24
- adam/commands/deploy/undeploy.py +4 -21
- adam/commands/deploy/undeploy_frontend.py +4 -7
- adam/commands/deploy/undeploy_pg_agent.py +6 -8
- adam/commands/deploy/undeploy_pod.py +11 -12
- adam/commands/devices/__init__.py +0 -0
- adam/commands/devices/device.py +149 -0
- adam/commands/devices/device_app.py +163 -0
- adam/commands/devices/device_auit_log.py +49 -0
- adam/commands/devices/device_cass.py +179 -0
- adam/commands/devices/device_export.py +87 -0
- adam/commands/devices/device_postgres.py +160 -0
- adam/commands/devices/devices.py +25 -0
- adam/commands/download_cassandra_log.py +45 -0
- adam/commands/download_file.py +47 -0
- adam/commands/exit.py +1 -4
- adam/commands/export/__init__.py +0 -0
- adam/commands/export/clean_up_all_export_sessions.py +37 -0
- adam/commands/export/clean_up_export_sessions.py +39 -0
- adam/commands/export/completions_x.py +11 -0
- adam/commands/export/download_export_session.py +40 -0
- adam/commands/export/drop_export_database.py +39 -0
- adam/commands/export/drop_export_databases.py +37 -0
- adam/commands/export/export.py +37 -0
- adam/commands/export/export_databases.py +247 -0
- adam/commands/export/export_select.py +34 -0
- adam/commands/export/export_sessions.py +211 -0
- adam/commands/export/export_use.py +49 -0
- adam/commands/export/export_x_select.py +48 -0
- adam/commands/export/exporter.py +361 -0
- adam/commands/export/import_files.py +44 -0
- adam/commands/export/import_session.py +44 -0
- adam/commands/export/importer.py +82 -0
- adam/commands/export/importer_athena.py +150 -0
- adam/commands/export/importer_sqlite.py +69 -0
- adam/commands/export/show_column_counts.py +45 -0
- adam/commands/export/show_export_databases.py +39 -0
- adam/commands/export/show_export_session.py +39 -0
- adam/commands/export/show_export_sessions.py +37 -0
- adam/commands/export/utils_export.py +366 -0
- 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 +12 -8
- adam/commands/intermediate_command.py +52 -0
- adam/commands/issues.py +14 -40
- adam/commands/kubectl.py +38 -0
- adam/commands/login.py +26 -25
- adam/commands/ls.py +11 -116
- adam/commands/medusa/medusa.py +4 -22
- adam/commands/medusa/medusa_backup.py +20 -27
- adam/commands/medusa/medusa_restore.py +35 -48
- adam/commands/medusa/medusa_show_backupjobs.py +17 -18
- adam/commands/medusa/medusa_show_restorejobs.py +13 -18
- adam/commands/medusa/utils_medusa.py +15 -0
- adam/commands/nodetool.py +8 -19
- 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 +11 -14
- adam/commands/param_set.py +8 -12
- adam/commands/postgres/completions_p.py +22 -0
- adam/commands/postgres/postgres.py +47 -55
- adam/commands/postgres/postgres_databases.py +269 -0
- adam/commands/postgres/postgres_ls.py +4 -8
- adam/commands/postgres/postgres_preview.py +5 -9
- adam/commands/postgres/utils_postgres.py +79 -0
- adam/commands/preview_table.py +10 -61
- adam/commands/pwd.py +14 -46
- adam/commands/reaper/reaper.py +4 -24
- adam/commands/reaper/reaper_forward.py +49 -56
- adam/commands/reaper/reaper_forward_session.py +6 -0
- adam/commands/reaper/reaper_forward_stop.py +10 -16
- adam/commands/reaper/reaper_restart.py +7 -14
- adam/commands/reaper/reaper_run_abort.py +8 -33
- adam/commands/reaper/reaper_runs.py +43 -58
- adam/commands/reaper/reaper_runs_abort.py +29 -49
- adam/commands/reaper/reaper_schedule_activate.py +14 -33
- adam/commands/reaper/reaper_schedule_start.py +9 -33
- adam/commands/reaper/reaper_schedule_stop.py +9 -33
- adam/commands/reaper/reaper_schedules.py +4 -14
- adam/commands/reaper/reaper_status.py +8 -16
- adam/commands/reaper/utils_reaper.py +203 -0
- adam/commands/repair/repair.py +4 -22
- adam/commands/repair/repair_log.py +5 -11
- adam/commands/repair/repair_run.py +27 -34
- adam/commands/repair/repair_scan.py +32 -40
- adam/commands/repair/repair_stop.py +5 -12
- adam/commands/restart_cluster.py +47 -0
- adam/commands/restart_node.py +51 -0
- adam/commands/restart_nodes.py +47 -0
- adam/commands/rollout.py +19 -24
- adam/commands/shell.py +12 -4
- adam/commands/show/show.py +10 -23
- adam/commands/show/show_adam.py +3 -3
- adam/commands/show/show_cassandra_repairs.py +37 -0
- adam/commands/show/show_cassandra_status.py +47 -51
- adam/commands/show/show_cassandra_version.py +5 -18
- adam/commands/show/show_cli_commands.py +56 -0
- adam/commands/show/show_host.py +1 -1
- adam/commands/show/show_login.py +23 -27
- adam/commands/show/show_params.py +2 -5
- adam/commands/show/show_processes.py +18 -21
- adam/commands/show/show_storage.py +11 -20
- adam/commands/watch.py +26 -29
- adam/config.py +5 -15
- adam/embedded_params.py +1 -1
- adam/log.py +4 -4
- adam/repl.py +105 -133
- adam/repl_commands.py +68 -28
- adam/repl_session.py +9 -1
- adam/repl_state.py +300 -62
- 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 +104 -64
- adam/sql/sql_state_machine.py +630 -0
- adam/sql/term_completer.py +3 -0
- adam/sso/authn_ad.py +6 -8
- adam/sso/authn_okta.py +4 -6
- adam/sso/cred_cache.py +3 -5
- adam/sso/idp.py +9 -12
- adam/utils.py +640 -10
- adam/utils_athena.py +140 -87
- adam/utils_audits.py +102 -0
- adam/utils_issues.py +32 -0
- adam/utils_k8s/app_clusters.py +28 -0
- adam/utils_k8s/app_pods.py +35 -0
- adam/utils_k8s/cassandra_clusters.py +34 -21
- adam/utils_k8s/cassandra_nodes.py +9 -6
- adam/utils_k8s/custom_resources.py +16 -17
- adam/utils_k8s/ingresses.py +2 -2
- adam/utils_k8s/jobs.py +7 -11
- adam/utils_k8s/k8s.py +96 -0
- adam/utils_k8s/kube_context.py +3 -6
- adam/{pod_exec_result.py → utils_k8s/pod_exec_result.py} +11 -5
- adam/utils_k8s/pods.py +146 -75
- adam/utils_k8s/secrets.py +4 -4
- adam/utils_k8s/service_accounts.py +5 -4
- adam/utils_k8s/services.py +2 -2
- adam/utils_k8s/statefulsets.py +6 -14
- adam/utils_local.py +42 -0
- adam/utils_net.py +4 -4
- adam/utils_repl/__init__.py +0 -0
- adam/utils_repl/appendable_completer.py +6 -0
- adam/utils_repl/automata_completer.py +48 -0
- adam/utils_repl/repl_completer.py +89 -0
- adam/utils_repl/state_machine.py +173 -0
- adam/utils_sqlite.py +137 -0
- adam/version.py +1 -1
- {kaqing-2.0.98.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/app.py +0 -67
- adam/commands/bash.py +0 -92
- adam/commands/cp.py +0 -95
- adam/commands/cql/cql_completions.py +0 -11
- adam/commands/cql/cql_table_completer.py +0 -8
- adam/commands/cql/cql_utils.py +0 -115
- adam/commands/describe/describe.py +0 -47
- adam/commands/describe/describe_keyspace.py +0 -60
- adam/commands/describe/describe_keyspaces.py +0 -49
- adam/commands/describe/describe_schema.py +0 -49
- adam/commands/describe/describe_table.py +0 -60
- adam/commands/describe/describe_tables.py +0 -49
- adam/commands/devices.py +0 -118
- adam/commands/logs.py +0 -39
- adam/commands/postgres/postgres_session.py +0 -240
- adam/commands/postgres/postgres_utils.py +0 -31
- adam/commands/postgres/psql_completions.py +0 -10
- adam/commands/postgres/psql_table_completer.py +0 -11
- adam/commands/reaper/reaper_session.py +0 -159
- adam/commands/report.py +0 -57
- adam/commands/show/show_app_actions.py +0 -53
- adam/commands/show/show_commands.py +0 -61
- adam/commands/show/show_repairs.py +0 -47
- adam/sql/state_machine.py +0 -460
- kaqing-2.0.98.dist-info/RECORD +0 -191
- kaqing-2.0.98.dist-info/top_level.txt +0 -1
- /adam/commands/{describe → app}/__init__.py +0 -0
- {kaqing-2.0.98.dist-info → kaqing-2.0.203.dist-info}/WHEEL +0 -0
- {kaqing-2.0.98.dist-info → kaqing-2.0.203.dist-info}/entry_points.txt +0 -0
|
@@ -1,16 +1,17 @@
|
|
|
1
|
+
from functools import partial
|
|
1
2
|
import threading
|
|
2
3
|
import time
|
|
3
4
|
|
|
4
5
|
from adam.commands.command import Command
|
|
5
|
-
from .
|
|
6
|
+
from adam.commands.reaper.reaper_forward_session import ReaperForwardSession
|
|
7
|
+
from adam.commands.reaper.utils_reaper import Reapers, port_forwarding
|
|
6
8
|
from adam.config import Config
|
|
7
9
|
from adam.repl_session import ReplSession
|
|
8
10
|
from adam.repl_state import ReplState, RequiredState
|
|
9
|
-
from adam.utils import
|
|
11
|
+
from adam.utils import tabulize, log2
|
|
10
12
|
|
|
11
13
|
class ReaperForward(Command):
|
|
12
14
|
COMMAND = 'reaper forward'
|
|
13
|
-
reaper_login = None
|
|
14
15
|
|
|
15
16
|
# the singleton pattern
|
|
16
17
|
def __new__(cls, *args, **kwargs):
|
|
@@ -31,70 +32,62 @@ class ReaperForward(Command):
|
|
|
31
32
|
if not(args := self.args(cmd)):
|
|
32
33
|
return super().run(cmd, state)
|
|
33
34
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
with self.validate(args, state) as (args, state):
|
|
36
|
+
if not Reapers.pod_name(state):
|
|
37
|
+
return state
|
|
37
38
|
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
spec = Reapers.reaper_spec(state)
|
|
40
|
+
if state.in_repl:
|
|
41
|
+
if ReaperForwardSession.is_forwarding:
|
|
42
|
+
log2("Another port-forward is already running.")
|
|
40
43
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
d = {
|
|
56
|
-
'reaper-ui': spec["web-uri"],
|
|
57
|
-
'reaper-username': spec["username"],
|
|
58
|
-
'reaper-password': spec["password"]
|
|
59
|
-
}
|
|
60
|
-
log2()
|
|
61
|
-
log2(lines_to_tabular([f'{k},{v}' for k, v in d.items()], separator=','))
|
|
62
|
-
|
|
63
|
-
for k, v in d.items():
|
|
64
|
-
ReplSession().prompt_session.history.append_string(f'cp {k}')
|
|
65
|
-
log2()
|
|
66
|
-
log2(f'Use <Up> arrow key to copy the values to clipboard.')
|
|
67
|
-
else:
|
|
68
|
-
try:
|
|
69
|
-
log2(f'Click: {spec["web-uri"]}')
|
|
70
|
-
log2(f'username: {spec["username"]}')
|
|
71
|
-
log2(f'password: {spec["password"]}')
|
|
44
|
+
return "already-running"
|
|
45
|
+
|
|
46
|
+
# make it a daemon to exit with a Ctrl-D
|
|
47
|
+
thread = threading.Thread(target=self.loop, args=(state,), daemon=True)
|
|
48
|
+
thread.start()
|
|
49
|
+
|
|
50
|
+
while not ReaperForwardSession.is_forwarding:
|
|
51
|
+
time.sleep(1)
|
|
52
|
+
|
|
53
|
+
d = {
|
|
54
|
+
'reaper-ui': spec["web-uri"],
|
|
55
|
+
'reaper-username': spec["username"],
|
|
56
|
+
'reaper-password': spec["password"]
|
|
57
|
+
}
|
|
72
58
|
log2()
|
|
73
|
-
|
|
59
|
+
tabulize(d.items(), lambda a: f'{a[0]},{a[1]}', separator=',')
|
|
74
60
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
61
|
+
for k, v in d.items():
|
|
62
|
+
ReplSession().prompt_session.history.append_string(f'cp {k}')
|
|
63
|
+
log2()
|
|
64
|
+
log2(f'Use <Up> arrow key to copy the values to clipboard.')
|
|
65
|
+
else:
|
|
66
|
+
try:
|
|
67
|
+
log2(f'Click: {spec["web-uri"]}')
|
|
68
|
+
log2(f'username: {spec["username"]}')
|
|
69
|
+
log2(f'password: {spec["password"]}')
|
|
70
|
+
log2()
|
|
71
|
+
log2(f"Press Ctrl+C to break.")
|
|
72
|
+
|
|
73
|
+
time.sleep(Config().get('reaper.port-forward.timeout', 3600 * 24))
|
|
74
|
+
except KeyboardInterrupt:
|
|
75
|
+
pass
|
|
78
76
|
|
|
79
|
-
|
|
77
|
+
return state
|
|
80
78
|
|
|
81
|
-
def loop(self, state: ReplState
|
|
82
|
-
|
|
83
|
-
|
|
79
|
+
def loop(self, state: ReplState):
|
|
80
|
+
with port_forwarding(state, Reapers.local_port(), partial(Reapers.svc_or_pod, state), Reapers.target_port()):
|
|
81
|
+
ReaperForwardSession.is_forwarding = True
|
|
84
82
|
try:
|
|
85
|
-
while not
|
|
83
|
+
while not ReaperForwardSession.stopping.is_set():
|
|
86
84
|
time.sleep(1)
|
|
87
85
|
finally:
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
return reaper.port_forwarded(state, 'webui', body)
|
|
86
|
+
ReaperForwardSession.stopping.clear()
|
|
87
|
+
ReaperForwardSession.is_forwarding = False
|
|
92
88
|
|
|
93
89
|
def completion(self, state: ReplState):
|
|
94
|
-
|
|
95
|
-
return super().completion(state)
|
|
96
|
-
|
|
97
|
-
return {}
|
|
90
|
+
return super().completion(state)
|
|
98
91
|
|
|
99
92
|
def help(self, _: ReplState):
|
|
100
93
|
return f'{ReaperForward.COMMAND}\t port-forward to reaper'
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
from adam.commands.command import Command
|
|
2
|
-
from .
|
|
2
|
+
from adam.commands.reaper.reaper_forward_session import ReaperForwardSession
|
|
3
|
+
from adam.commands.reaper.utils_reaper import Reapers
|
|
3
4
|
from adam.repl_state import ReplState, RequiredState
|
|
4
5
|
from adam.utils import log2
|
|
5
6
|
|
|
6
7
|
class ReaperForwardStop(Command):
|
|
7
8
|
COMMAND = 'reaper forward stop'
|
|
8
|
-
reaper_login = None
|
|
9
9
|
|
|
10
10
|
# the singleton pattern
|
|
11
11
|
def __new__(cls, *args, **kwargs):
|
|
@@ -26,24 +26,18 @@ class ReaperForwardStop(Command):
|
|
|
26
26
|
if not(args := self.args(cmd)):
|
|
27
27
|
return super().run(cmd, state)
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if not ReaperSession.create(state):
|
|
34
|
-
return state
|
|
29
|
+
with self.validate(args, state) as (args, state):
|
|
30
|
+
if not Reapers.pod_name(state):
|
|
31
|
+
return state
|
|
35
32
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
ReaperForwardSession.is_forwarding = False
|
|
34
|
+
ReaperForwardSession.stopping.set()
|
|
35
|
+
log2("Stopped reaper forward session.")
|
|
39
36
|
|
|
40
|
-
|
|
37
|
+
return state
|
|
41
38
|
|
|
42
39
|
def completion(self, state: ReplState):
|
|
43
|
-
|
|
44
|
-
return super().completion(state)
|
|
45
|
-
|
|
46
|
-
return {}
|
|
40
|
+
return super().completion(state)
|
|
47
41
|
|
|
48
42
|
def help(self, _: ReplState):
|
|
49
43
|
return f'{ReaperForwardStop.COMMAND}\t stop port-forward to reaper'
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
from adam.commands.command import Command
|
|
2
|
+
from adam.commands.reaper.utils_reaper import Reapers
|
|
2
3
|
from adam.utils_k8s.pods import Pods
|
|
3
|
-
from .reaper_session import ReaperSession
|
|
4
4
|
from adam.repl_state import ReplState, RequiredState
|
|
5
5
|
|
|
6
6
|
class ReaperRestart(Command):
|
|
7
7
|
COMMAND = 'reaper restart'
|
|
8
|
-
reaper_login = None
|
|
9
8
|
|
|
10
9
|
# the singleton pattern
|
|
11
10
|
def __new__(cls, *args, **kwargs):
|
|
@@ -26,22 +25,16 @@ class ReaperRestart(Command):
|
|
|
26
25
|
if not(args := self.args(cmd)):
|
|
27
26
|
return super().run(cmd, state)
|
|
28
27
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if not(reaper := ReaperSession.create(state)):
|
|
34
|
-
return state
|
|
28
|
+
with self.validate(args, state) as (args, state):
|
|
29
|
+
if not (pod := Reapers.pod_name(state)):
|
|
30
|
+
return state
|
|
35
31
|
|
|
36
|
-
|
|
32
|
+
Pods.delete(pod, state.namespace)
|
|
37
33
|
|
|
38
|
-
|
|
34
|
+
return state
|
|
39
35
|
|
|
40
36
|
def completion(self, state: ReplState):
|
|
41
|
-
|
|
42
|
-
return super().completion(state)
|
|
43
|
-
|
|
44
|
-
return {}
|
|
37
|
+
return super().completion(state)
|
|
45
38
|
|
|
46
39
|
def help(self, _: ReplState):
|
|
47
40
|
return f'{ReaperRestart.COMMAND}\t restart reaper'
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
from adam.commands import validate_args
|
|
3
2
|
from adam.commands.command import Command
|
|
4
|
-
from .
|
|
3
|
+
from adam.commands.reaper.utils_reaper import reaper
|
|
5
4
|
from adam.repl_state import ReplState, RequiredState
|
|
6
5
|
from adam.utils import log2
|
|
7
6
|
|
|
8
7
|
class ReaperRunAbort(Command):
|
|
9
8
|
COMMAND = 'reaper abort run'
|
|
10
|
-
reaper_login = None
|
|
11
9
|
|
|
12
10
|
# the singleton pattern
|
|
13
11
|
def __new__(cls, *args, **kwargs):
|
|
@@ -28,38 +26,15 @@ class ReaperRunAbort(Command):
|
|
|
28
26
|
if not(args := self.args(cmd)):
|
|
29
27
|
return super().run(cmd, state)
|
|
30
28
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
if not args:
|
|
36
|
-
if state.in_repl:
|
|
37
|
-
log2('Specify run id to abort.')
|
|
38
|
-
else:
|
|
39
|
-
Command.display_help()
|
|
40
|
-
|
|
41
|
-
return state
|
|
42
|
-
|
|
43
|
-
if not(reaper := ReaperSession.create(state)):
|
|
44
|
-
return state
|
|
29
|
+
with self.validate(args, state) as (args, state):
|
|
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')
|
|
45
33
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
return state
|
|
49
|
-
|
|
50
|
-
def stop_run(self, state: ReplState, reaper: ReaperSession, run_id: str):
|
|
51
|
-
def body(uri: str, headers: dict[str, str]):
|
|
52
|
-
return requests.put(uri, headers=headers)
|
|
53
|
-
|
|
54
|
-
# PAUSED, RUNNING, ABORTED
|
|
55
|
-
# PUT /repair_run/{id}/state/{state}
|
|
56
|
-
reaper.port_forwarded(state, f'repair_run/{run_id}/state/ABORTED', body, method='PUT')
|
|
34
|
+
return state
|
|
57
35
|
|
|
58
36
|
def completion(self, state: ReplState):
|
|
59
|
-
|
|
60
|
-
return super().completion(state)
|
|
61
|
-
|
|
62
|
-
return {}
|
|
37
|
+
return super().completion(state)
|
|
63
38
|
|
|
64
39
|
def help(self, _: ReplState):
|
|
65
40
|
return f'{ReaperRunAbort.COMMAND} <run-id>\t abort reaper run'
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
import requests
|
|
2
|
-
|
|
3
1
|
from adam.commands.command import Command
|
|
4
|
-
from .
|
|
2
|
+
from adam.commands.reaper.utils_reaper import reaper
|
|
5
3
|
from adam.config import Config
|
|
6
4
|
from adam.repl_state import ReplState, RequiredState
|
|
7
|
-
from adam.utils import convert_seconds, epoch,
|
|
5
|
+
from adam.utils import convert_seconds, epoch, tabulize, log, log2
|
|
8
6
|
|
|
9
7
|
class ReaperRuns(Command):
|
|
10
8
|
COMMAND = 'reaper show runs'
|
|
11
|
-
reaper_login = None
|
|
12
9
|
|
|
13
10
|
# the singleton pattern
|
|
14
11
|
def __new__(cls, *args, **kwargs):
|
|
@@ -29,63 +26,51 @@ class ReaperRuns(Command):
|
|
|
29
26
|
if not(args := self.args(cmd)):
|
|
30
27
|
return super().run(cmd, state)
|
|
31
28
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
29
|
+
with self.validate(args, state) as (args, state):
|
|
30
|
+
header = 'ID,START,DURATION,STATE,CLUSTER,KEYSPACE,TABLES,REPAIRED'
|
|
31
|
+
|
|
32
|
+
def line(run):
|
|
33
|
+
id = run['id']
|
|
34
|
+
state = run['state']
|
|
35
|
+
start_time = run['start_time']
|
|
36
|
+
end_time = run['end_time']
|
|
37
|
+
duration = '-'
|
|
38
|
+
if state == 'DONE' and end_time:
|
|
39
|
+
hours, minutes, seconds = convert_seconds(epoch(end_time) - epoch(start_time))
|
|
40
|
+
if hours:
|
|
41
|
+
duration = f"{hours:2d}h {minutes:2d}m {seconds:2d}s"
|
|
42
|
+
elif minutes:
|
|
43
|
+
duration = f"{minutes:2d}m {seconds:2d}s"
|
|
44
|
+
else:
|
|
45
|
+
duration = f"{seconds:2d}s"
|
|
46
|
+
|
|
47
|
+
return f"{id},{start_time},{duration},{state},{run['cluster_name']},{run['keyspace_name']},{len(run['column_families'])},{run['segments_repaired']}/{run['total_segments']}"
|
|
48
|
+
|
|
49
|
+
with reaper(state) as http:
|
|
50
|
+
response = http.get('repair_run?state=RUNNING', params={
|
|
51
|
+
'cluster_name': 'all',
|
|
52
|
+
'limit': Config().get('reaper.show-runs-batch', 10)
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
runs = response.json()
|
|
56
|
+
if runs:
|
|
57
|
+
tabulize(sorted([line(run) for run in runs], reverse=True), header=header, separator=",")
|
|
61
58
|
else:
|
|
62
|
-
|
|
59
|
+
log2('No running runs found.')
|
|
60
|
+
log2()
|
|
63
61
|
|
|
64
|
-
|
|
62
|
+
response = http.get('repair_run?state=PAUSED,ABORTED,DONE', params={
|
|
63
|
+
'cluster_name': 'all',
|
|
64
|
+
'limit': Config().get('reaper.show-runs-batch', 10)
|
|
65
|
+
})
|
|
65
66
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
header = 'Start,Duration,State,Cluster,Keyspace,Tables,Repaired'
|
|
72
|
-
|
|
73
|
-
runs = response.json()
|
|
74
|
-
if runs:
|
|
75
|
-
log(lines_to_tabular(sorted([line(run) for run in runs], reverse=True), header, separator=","))
|
|
76
|
-
else:
|
|
77
|
-
log2('No running runs found.')
|
|
78
|
-
log2()
|
|
79
|
-
|
|
80
|
-
response = reaper.port_forwarded(state, 'repair_run?state=PAUSED,ABORTED,DONE', body, method='GET')
|
|
81
|
-
if not response:
|
|
82
|
-
return
|
|
67
|
+
runs = response.json()
|
|
68
|
+
if runs:
|
|
69
|
+
tabulize(sorted([line(run) for run in runs], reverse=True), header=header, separator=",")
|
|
70
|
+
else:
|
|
71
|
+
log2('No runs found.')
|
|
83
72
|
|
|
84
|
-
|
|
85
|
-
if runs:
|
|
86
|
-
log(lines_to_tabular(sorted([line(run) for run in runs], reverse=True), header, separator=","))
|
|
87
|
-
else:
|
|
88
|
-
log2('No runs found.')
|
|
73
|
+
return state
|
|
89
74
|
|
|
90
75
|
def completion(self, state: ReplState):
|
|
91
76
|
if state.sts:
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
import requests
|
|
2
|
-
|
|
3
1
|
from adam.commands.command import Command
|
|
4
|
-
from .
|
|
2
|
+
from adam.commands.reaper.utils_reaper import reaper
|
|
5
3
|
from adam.config import Config
|
|
6
4
|
from adam.repl_state import ReplState, RequiredState
|
|
7
5
|
from adam.utils import log2
|
|
8
6
|
|
|
9
7
|
class ReaperRunsAbort(Command):
|
|
10
8
|
COMMAND = 'reaper abort runs'
|
|
11
|
-
reaper_login = None
|
|
12
9
|
|
|
13
10
|
# the singleton pattern
|
|
14
11
|
def __new__(cls, *args, **kwargs):
|
|
@@ -29,55 +26,38 @@ class ReaperRunsAbort(Command):
|
|
|
29
26
|
if not(args := self.args(cmd)):
|
|
30
27
|
return super().run(cmd, state)
|
|
31
28
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
with self.validate(args, state) as (args, state):
|
|
30
|
+
with reaper(state) as http:
|
|
31
|
+
# PAUSED, RUNNING, ABORTED
|
|
32
|
+
aborted = 0
|
|
33
|
+
|
|
34
|
+
while True == True:
|
|
35
|
+
response = http.get('repair_run?state=RUNNING', params={
|
|
36
|
+
'cluster_name': 'all',
|
|
37
|
+
'limit': Config().get('reaper.abort-runs-batch', 10)
|
|
38
|
+
})
|
|
39
|
+
if not response:
|
|
40
|
+
break
|
|
41
|
+
|
|
42
|
+
runs = response.json()
|
|
43
|
+
if not runs:
|
|
44
|
+
break
|
|
45
|
+
|
|
46
|
+
for run in runs:
|
|
47
|
+
run_id = run['id']
|
|
48
|
+
# PUT /repair_run/{id}/state/{state}
|
|
49
|
+
http.put(f'repair_run/{run_id}/state/ABORTED')
|
|
50
|
+
aborted += 1
|
|
51
|
+
|
|
52
|
+
if aborted:
|
|
53
|
+
log2(f'Aborted {aborted} runs in total.')
|
|
54
|
+
else:
|
|
55
|
+
log2('No running repair runs found.')
|
|
35
56
|
|
|
36
|
-
if not(reaper := ReaperSession.create(state)):
|
|
37
57
|
return state
|
|
38
58
|
|
|
39
|
-
self.stop_runs(state, reaper)
|
|
40
|
-
|
|
41
|
-
return state
|
|
42
|
-
|
|
43
|
-
def stop_runs(self, state: ReplState, reaper: ReaperSession):
|
|
44
|
-
def body_list(uri: str, headers: dict[str, str]):
|
|
45
|
-
return requests.get(uri, headers=headers, params={
|
|
46
|
-
'cluster_name': 'all',
|
|
47
|
-
'limit': Config().get('reaper.abort-runs-batch', 10)
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
def body_abort(uri: str, headers: dict[str, str]):
|
|
51
|
-
return requests.put(uri, headers=headers)
|
|
52
|
-
|
|
53
|
-
# PAUSED, RUNNING, ABORTED
|
|
54
|
-
aborted = 0
|
|
55
|
-
while True == True:
|
|
56
|
-
response = reaper.port_forwarded(state, 'repair_run?state=RUNNING', body_list, method='GET')
|
|
57
|
-
if not response:
|
|
58
|
-
break
|
|
59
|
-
|
|
60
|
-
runs = response.json()
|
|
61
|
-
if not runs:
|
|
62
|
-
break
|
|
63
|
-
|
|
64
|
-
for run in runs:
|
|
65
|
-
run_id = run['id']
|
|
66
|
-
# PUT /repair_run/{id}/state/{state}
|
|
67
|
-
reaper.port_forwarded(state, f'repair_run/{run_id}/state/ABORTED', body_abort, method='PUT')
|
|
68
|
-
log2(f'Aborted {len(runs)} runs.')
|
|
69
|
-
aborted += 1
|
|
70
|
-
|
|
71
|
-
if aborted:
|
|
72
|
-
log2(f'Aborted {aborted} runs in total.')
|
|
73
|
-
else:
|
|
74
|
-
log2('No running repair runs found.')
|
|
75
|
-
|
|
76
59
|
def completion(self, state: ReplState):
|
|
77
|
-
|
|
78
|
-
return super().completion(state)
|
|
79
|
-
|
|
80
|
-
return {}
|
|
60
|
+
return super().completion(state)
|
|
81
61
|
|
|
82
62
|
def help(self, _: ReplState):
|
|
83
63
|
return f'{ReaperRunsAbort.COMMAND}\t abort all running reaper runs'
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
from adam.commands import validate_args
|
|
3
2
|
from adam.commands.command import Command
|
|
4
|
-
from .
|
|
3
|
+
from adam.commands.reaper.utils_reaper import Reapers, reaper
|
|
5
4
|
from adam.repl_state import ReplState, RequiredState
|
|
6
|
-
|
|
5
|
+
|
|
6
|
+
import nest_asyncio
|
|
7
|
+
nest_asyncio.apply()
|
|
8
|
+
|
|
9
|
+
import asyncio
|
|
7
10
|
|
|
8
11
|
class ReaperScheduleActivate(Command):
|
|
9
12
|
COMMAND = 'reaper activate schedule'
|
|
10
|
-
reaper_login = None
|
|
11
13
|
|
|
12
14
|
# the singleton pattern
|
|
13
15
|
def __new__(cls, *args, **kwargs):
|
|
@@ -28,37 +30,16 @@ class ReaperScheduleActivate(Command):
|
|
|
28
30
|
if not(args := self.args(cmd)):
|
|
29
31
|
return super().run(cmd, state)
|
|
30
32
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
log2('Specify schedule to activate.')
|
|
37
|
-
|
|
38
|
-
return state
|
|
39
|
-
|
|
40
|
-
schedule_id = args[0]
|
|
41
|
-
if not(reaper := ReaperSession.create(state)):
|
|
42
|
-
return state
|
|
33
|
+
with self.validate(args, state) as (args, state):
|
|
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)
|
|
43
38
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return schedule_id
|
|
47
|
-
|
|
48
|
-
def activate_schedule(self, state: ReplState, reaper: ReaperSession, schedule_id: str):
|
|
49
|
-
def body(uri: str, headers: dict[str, str]):
|
|
50
|
-
return requests.put(uri, headers=headers)
|
|
51
|
-
|
|
52
|
-
reaper.port_forwarded(state, f'repair_schedule/{schedule_id}?state=ACTIVE', body, method='PUT')
|
|
53
|
-
reaper.show_schedule(state, schedule_id)
|
|
39
|
+
return schedule_id
|
|
54
40
|
|
|
55
41
|
def completion(self, state: ReplState):
|
|
56
|
-
|
|
57
|
-
leaf = {id: None for id in ReaperSession.cached_schedule_ids(state)}
|
|
58
|
-
|
|
59
|
-
return super().completion(state, leaf)
|
|
60
|
-
|
|
61
|
-
return {}
|
|
42
|
+
return super().completion(state, lambda: {id: None for id in Reapers.cached_schedule_ids(state)}, auto_key='reaper.schedules')
|
|
62
43
|
|
|
63
44
|
def help(self, _: ReplState):
|
|
64
45
|
return f'{ReaperScheduleActivate.COMMAND} <schedule-id>\t resume reaper schedule'
|
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
from adam.commands import validate_args
|
|
3
2
|
from adam.commands.command import Command
|
|
4
|
-
from .
|
|
3
|
+
from adam.commands.reaper.utils_reaper import Reapers, reaper
|
|
5
4
|
from adam.repl_state import ReplState, RequiredState
|
|
6
|
-
from adam.utils import log2
|
|
7
5
|
|
|
8
6
|
class ReaperScheduleStart(Command):
|
|
9
7
|
COMMAND = 'reaper start schedule'
|
|
10
|
-
reaper_login = None
|
|
11
8
|
|
|
12
9
|
# the singleton pattern
|
|
13
10
|
def __new__(cls, *args, **kwargs):
|
|
@@ -28,37 +25,16 @@ class ReaperScheduleStart(Command):
|
|
|
28
25
|
if not(args := self.args(cmd)):
|
|
29
26
|
return super().run(cmd, state)
|
|
30
27
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
log2('Specify schedule to activate.')
|
|
37
|
-
|
|
38
|
-
return state
|
|
39
|
-
|
|
40
|
-
schedule_id = args[0]
|
|
41
|
-
if not(reaper := ReaperSession.create(state)):
|
|
42
|
-
return schedule_id
|
|
43
|
-
|
|
44
|
-
self.start_schedule(state, reaper, schedule_id)
|
|
28
|
+
with self.validate(args, state) as (args, state):
|
|
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)
|
|
45
33
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
def start_schedule(self, state: ReplState, reaper: ReaperSession, schedule_id: str):
|
|
49
|
-
def body(uri: str, headers: dict[str, str]):
|
|
50
|
-
return requests.post(uri, headers=headers)
|
|
51
|
-
|
|
52
|
-
reaper.port_forwarded(state, f'repair_schedule/start/{schedule_id}', body, method='POST')
|
|
53
|
-
reaper.show_schedule(state, schedule_id)
|
|
34
|
+
return schedule_id
|
|
54
35
|
|
|
55
36
|
def completion(self, state: ReplState):
|
|
56
|
-
|
|
57
|
-
leaf = {id: None for id in ReaperSession.cached_schedule_ids(state)}
|
|
58
|
-
|
|
59
|
-
return super().completion(state, leaf)
|
|
60
|
-
|
|
61
|
-
return {}
|
|
37
|
+
return super().completion(state, lambda: {id: None for id in Reapers.cached_schedule_ids(state)}, auto_key='reaper.schedules')
|
|
62
38
|
|
|
63
39
|
def help(self, _: ReplState):
|
|
64
40
|
return f'{ReaperScheduleStart.COMMAND} <schedule-id>\t start reaper runs for schedule'
|