kaqing 2.0.110__py3-none-any.whl → 2.0.214__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of kaqing might be problematic. Click here for more details.
- adam/__init__.py +0 -2
- adam/app_session.py +9 -12
- adam/apps.py +18 -4
- adam/batch.py +19 -19
- 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/app/app.py +38 -0
- adam/commands/{app_ping.py → app/app_ping.py} +7 -13
- adam/commands/{login.py → app/login.py} +22 -24
- 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 +7 -14
- adam/commands/app/show_login.py +56 -0
- adam/commands/app/utils_app.py +106 -0
- adam/commands/audit/audit.py +22 -40
- adam/commands/audit/audit_repair_tables.py +15 -19
- adam/commands/audit/audit_run.py +15 -22
- adam/commands/audit/completions_l.py +15 -0
- adam/commands/audit/show_last10.py +4 -18
- adam/commands/audit/show_slow10.py +4 -17
- adam/commands/audit/show_top10.py +4 -16
- adam/commands/audit/utils_show_top10.py +15 -3
- 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/{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/{rollout.py → cassandra/rollout.py} +20 -25
- adam/commands/cassandra/show_cassandra_repairs.py +37 -0
- adam/commands/cassandra/show_cassandra_status.py +117 -0
- adam/commands/{show → cassandra}/show_cassandra_version.py +5 -18
- adam/commands/cassandra/show_processes.py +50 -0
- adam/commands/cassandra/show_storage.py +44 -0
- adam/commands/{watch.py → cassandra/watch.py} +26 -29
- adam/commands/cli/__init__.py +0 -0
- adam/commands/{cli_commands.py → cli/cli_commands.py} +8 -4
- adam/commands/cli/clipboard_copy.py +86 -0
- adam/commands/cli/show_cli_commands.py +56 -0
- adam/commands/code.py +57 -0
- adam/commands/command.py +211 -40
- adam/commands/commands_utils.py +20 -27
- adam/commands/config/__init__.py +0 -0
- adam/commands/{param_get.py → config/param_get.py} +11 -14
- adam/commands/{param_set.py → config/param_set.py} +8 -12
- adam/commands/{show → config}/show_params.py +2 -5
- adam/commands/cql/alter_tables.py +66 -0
- adam/commands/cql/completions_c.py +29 -0
- adam/commands/cql/cqlsh.py +10 -32
- adam/commands/cql/utils_cql.py +306 -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/debug/show_offloaded_completes.py +45 -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 -27
- 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 -27
- 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/diag/__init__.py +0 -0
- adam/commands/{check.py → diag/check.py} +16 -25
- adam/commands/diag/generate_report.py +52 -0
- adam/commands/diag/issues.py +43 -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 +251 -0
- adam/commands/export/export_select.py +34 -0
- adam/commands/export/export_sessions.py +210 -0
- adam/commands/export/export_use.py +49 -0
- adam/commands/export/export_x_select.py +48 -0
- adam/commands/export/exporter.py +419 -0
- adam/commands/export/import_files.py +44 -0
- adam/commands/export/import_session.py +40 -0
- adam/commands/export/importer.py +81 -0
- adam/commands/export/importer_athena.py +157 -0
- adam/commands/export/importer_sqlite.py +78 -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/fs/__init__.py +0 -0
- adam/commands/fs/cat.py +36 -0
- adam/commands/fs/cat_local.py +42 -0
- adam/commands/fs/cd.py +41 -0
- adam/commands/fs/download_file.py +47 -0
- adam/commands/fs/find_files.py +51 -0
- adam/commands/fs/find_processes.py +76 -0
- adam/commands/fs/head.py +36 -0
- adam/commands/fs/ls.py +41 -0
- adam/commands/fs/ls_local.py +40 -0
- adam/commands/fs/pwd.py +45 -0
- adam/commands/fs/rm.py +18 -0
- adam/commands/fs/rm_downloads.py +39 -0
- adam/commands/fs/rm_logs.py +38 -0
- adam/commands/{shell.py → fs/shell.py} +12 -4
- adam/commands/{show → fs}/show_adam.py +3 -3
- adam/commands/{show → fs}/show_host.py +1 -1
- adam/commands/help.py +5 -3
- adam/commands/intermediate_command.py +52 -0
- adam/commands/kubectl.py +38 -0
- 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 +16 -18
- adam/commands/medusa/medusa_show_restorejobs.py +13 -18
- adam/commands/medusa/utils_medusa.py +15 -0
- adam/commands/nodetool/__init__.py +0 -0
- adam/commands/{nodetool.py → nodetool/nodetool.py} +9 -20
- 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 +5 -9
- adam/commands/postgres/postgres_preview.py +5 -9
- adam/commands/postgres/utils_postgres.py +80 -0
- adam/commands/preview_table.py +8 -44
- adam/commands/reaper/reaper.py +4 -27
- 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/show.py +40 -0
- adam/config.py +5 -15
- adam/embedded_params.py +1 -1
- adam/log.py +4 -4
- adam/repl.py +83 -116
- adam/repl_commands.py +86 -45
- adam/repl_session.py +9 -1
- adam/repl_state.py +176 -40
- adam/sql/async_executor.py +62 -0
- adam/sql/lark_completer.py +286 -0
- adam/sql/lark_parser.py +604 -0
- adam/sql/qingl.lark +1076 -0
- adam/sql/sql_completer.py +52 -27
- adam/sql/sql_state_machine.py +131 -19
- adam/sso/authn_ad.py +6 -8
- adam/sso/authn_okta.py +4 -6
- adam/sso/cred_cache.py +4 -9
- adam/sso/idp.py +9 -12
- adam/utils.py +670 -31
- adam/utils_athena.py +145 -0
- adam/utils_audits.py +12 -103
- adam/utils_issues.py +32 -0
- adam/utils_k8s/app_clusters.py +35 -0
- adam/utils_k8s/app_pods.py +41 -0
- adam/utils_k8s/cassandra_clusters.py +35 -20
- adam/utils_k8s/cassandra_nodes.py +15 -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} +13 -4
- adam/utils_k8s/pods.py +159 -89
- 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 +80 -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 +93 -0
- adam/utils_repl/state_machine.py +173 -0
- adam/utils_sqlite.py +132 -0
- adam/version.py +1 -1
- {kaqing-2.0.110.dist-info → kaqing-2.0.214.dist-info}/METADATA +1 -1
- kaqing-2.0.214.dist-info/RECORD +272 -0
- kaqing-2.0.214.dist-info/top_level.txt +2 -0
- teddy/__init__.py +0 -0
- teddy/lark_parser.py +436 -0
- teddy/lark_parser2.py +618 -0
- adam/commands/alter_tables.py +0 -81
- adam/commands/app.py +0 -67
- adam/commands/bash.py +0 -150
- adam/commands/cd.py +0 -125
- adam/commands/cp.py +0 -95
- adam/commands/cql/cql_completions.py +0 -15
- adam/commands/cql/cql_utils.py +0 -112
- adam/commands/devices.py +0 -118
- adam/commands/issues.py +0 -75
- adam/commands/logs.py +0 -40
- adam/commands/ls.py +0 -146
- adam/commands/postgres/postgres_context.py +0 -239
- adam/commands/postgres/postgres_utils.py +0 -31
- adam/commands/postgres/psql_completions.py +0 -10
- adam/commands/pwd.py +0 -77
- adam/commands/reaper/reaper_session.py +0 -159
- adam/commands/report.py +0 -63
- adam/commands/show/show.py +0 -54
- adam/commands/show/show_app_actions.py +0 -56
- adam/commands/show/show_cassandra_status.py +0 -128
- adam/commands/show/show_commands.py +0 -61
- adam/commands/show/show_login.py +0 -63
- adam/commands/show/show_processes.py +0 -53
- adam/commands/show/show_repairs.py +0 -47
- adam/commands/show/show_storage.py +0 -52
- kaqing-2.0.110.dist-info/RECORD +0 -187
- kaqing-2.0.110.dist-info/top_level.txt +0 -1
- /adam/commands/{show → app}/__init__.py +0 -0
- /adam/commands/{nodetool_commands.py → nodetool/nodetool_commands.py} +0 -0
- {kaqing-2.0.110.dist-info → kaqing-2.0.214.dist-info}/WHEEL +0 -0
- {kaqing-2.0.110.dist-info → kaqing-2.0.214.dist-info}/entry_points.txt +0 -0
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
from adam.commands.command import Command
|
|
2
|
-
from adam.
|
|
3
|
-
from adam.utils_k8s.cassandra_nodes import CassandraNodes
|
|
4
|
-
from adam.utils_k8s.secrets import Secrets
|
|
2
|
+
from adam.commands.cql.utils_cql import cassandra
|
|
5
3
|
from adam.repl_state import ReplState, RequiredState
|
|
6
4
|
|
|
7
5
|
class ShowCassandraVersion(Command):
|
|
@@ -26,23 +24,12 @@ class ShowCassandraVersion(Command):
|
|
|
26
24
|
if not(args := self.args(cmd)):
|
|
27
25
|
return super().run(cmd, state)
|
|
28
26
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
user, pw = Secrets.get_user_pass(state.sts if state.sts else state.pod, state.namespace, secret_path='cql.secret')
|
|
34
|
-
command = f'cqlsh -u {user} -p {pw} -e "show version"'
|
|
35
|
-
|
|
36
|
-
if state.pod:
|
|
37
|
-
return CassandraNodes.exec(state.pod, state.namespace, command)
|
|
38
|
-
else:
|
|
39
|
-
return CassandraClusters.exec(state.sts, state.namespace, command, action='cql')
|
|
27
|
+
with self.validate(args, state) as (_, state):
|
|
28
|
+
with cassandra(state) as pods:
|
|
29
|
+
return pods.cql('show version', show_out=True, on_any=True)
|
|
40
30
|
|
|
41
31
|
def completion(self, state: ReplState):
|
|
42
|
-
|
|
43
|
-
return super().completion(state)
|
|
44
|
-
|
|
45
|
-
return {}
|
|
32
|
+
return super().completion(state)
|
|
46
33
|
|
|
47
34
|
def help(self, _: ReplState):
|
|
48
35
|
return f'{ShowCassandraVersion.COMMAND}\t show Cassandra version'
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
from adam.commands import extract_options, extract_sequence, extract_trailing_options
|
|
2
|
+
from adam.commands.command import Command
|
|
3
|
+
from adam.commands.cql.utils_cql import cassandra
|
|
4
|
+
from adam.config import Config
|
|
5
|
+
from adam.repl_state import ReplState, RequiredState
|
|
6
|
+
|
|
7
|
+
class ShowProcesses(Command):
|
|
8
|
+
COMMAND = 'show processes'
|
|
9
|
+
|
|
10
|
+
# the singleton pattern
|
|
11
|
+
def __new__(cls, *args, **kwargs):
|
|
12
|
+
if not hasattr(cls, 'instance'): cls.instance = super(ShowProcesses, cls).__new__(cls)
|
|
13
|
+
|
|
14
|
+
return cls.instance
|
|
15
|
+
|
|
16
|
+
def __init__(self, successor: Command=None):
|
|
17
|
+
super().__init__(successor)
|
|
18
|
+
|
|
19
|
+
def command(self):
|
|
20
|
+
return ShowProcesses.COMMAND
|
|
21
|
+
|
|
22
|
+
def required(self):
|
|
23
|
+
return RequiredState.CLUSTER_OR_POD
|
|
24
|
+
|
|
25
|
+
def run(self, cmd: str, state: ReplState):
|
|
26
|
+
if not(args := self.args(cmd)):
|
|
27
|
+
return super().run(cmd, state)
|
|
28
|
+
|
|
29
|
+
with self.validate(args, state) as (args, state):
|
|
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')
|
|
38
|
+
|
|
39
|
+
with cassandra(state) as pods:
|
|
40
|
+
pods.display_table(cols, header, show_out=show_out, backgrounded=backgrounded, msg='Checking processes')
|
|
41
|
+
|
|
42
|
+
return state
|
|
43
|
+
|
|
44
|
+
def completion(self, state: ReplState):
|
|
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})
|
|
48
|
+
|
|
49
|
+
def help(self, _: ReplState):
|
|
50
|
+
return f'{ShowProcesses.COMMAND} [with recipe qing|metrics] [-s]\t show process overview -s show commands on nodes'
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
from adam.commands import extract_options, extract_trailing_options
|
|
2
|
+
from adam.commands.command import Command
|
|
3
|
+
from adam.commands.cql.utils_cql import cassandra
|
|
4
|
+
from adam.config import Config
|
|
5
|
+
from adam.repl_state import ReplState, RequiredState
|
|
6
|
+
from adam.utils import ing
|
|
7
|
+
|
|
8
|
+
class ShowStorage(Command):
|
|
9
|
+
COMMAND = 'show storage'
|
|
10
|
+
|
|
11
|
+
# the singleton pattern
|
|
12
|
+
def __new__(cls, *args, **kwargs):
|
|
13
|
+
if not hasattr(cls, 'instance'): cls.instance = super(ShowStorage, 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 ShowStorage.COMMAND
|
|
22
|
+
|
|
23
|
+
def required(self):
|
|
24
|
+
return RequiredState.CLUSTER_OR_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
|
+
with extract_trailing_options(args, '&') as (args, backgrounded):
|
|
32
|
+
with extract_options(args, ['-s', '--show']) as (args, show_out):
|
|
33
|
+
cols = Config().get('storage.columns', 'pod,volume_root,volume_cassandra,snapshots,data,compactions')
|
|
34
|
+
header = Config().get('storage.header', 'POD_NAME,VOLUME /,VOLUME CASS,SNAPSHOTS,DATA,COMPACTIONS')
|
|
35
|
+
with cassandra(state) as pods:
|
|
36
|
+
pods.display_table(cols, header, show_out=show_out, backgrounded=backgrounded, msg='Checking storage')
|
|
37
|
+
|
|
38
|
+
return state
|
|
39
|
+
|
|
40
|
+
def completion(self, state: ReplState):
|
|
41
|
+
return super().completion(state, {'-s': {'&': None}, '&': None})
|
|
42
|
+
|
|
43
|
+
def help(self, _: ReplState):
|
|
44
|
+
return f'{ShowStorage.COMMAND} [-s]\t show storage overview -s show commands on nodes'
|
|
@@ -8,10 +8,10 @@ from adam.commands.commands_utils import show_pods, show_rollout
|
|
|
8
8
|
from adam.config import Config
|
|
9
9
|
from adam.utils_k8s.statefulsets import StatefulSets
|
|
10
10
|
from adam.repl_state import ReplState, RequiredState
|
|
11
|
-
from adam.utils import
|
|
11
|
+
from adam.utils import log2
|
|
12
12
|
|
|
13
13
|
class Watch(Command):
|
|
14
|
-
COMMAND = 'watch'
|
|
14
|
+
COMMAND = 'watch cassandra pods'
|
|
15
15
|
|
|
16
16
|
# the singleton pattern
|
|
17
17
|
def __new__(cls, *args, **kwargs):
|
|
@@ -26,37 +26,34 @@ class Watch(Command):
|
|
|
26
26
|
return Watch.COMMAND
|
|
27
27
|
|
|
28
28
|
def required(self):
|
|
29
|
-
return RequiredState.
|
|
29
|
+
return RequiredState.NAMESPACE
|
|
30
30
|
|
|
31
31
|
def run(self, cmd: str, state: ReplState):
|
|
32
32
|
if not(args := self.args(cmd)):
|
|
33
33
|
return super().run(cmd, state)
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
if not pods:
|
|
41
|
-
log2("No pods are found.")
|
|
42
|
-
return state
|
|
35
|
+
with self.validate(args, state) as (args, state):
|
|
36
|
+
pods = StatefulSets.pods(state.sts, state.namespace)
|
|
37
|
+
if not pods:
|
|
38
|
+
log2("No pods are found.")
|
|
39
|
+
return state
|
|
43
40
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
41
|
+
stop_event = threading.Event()
|
|
42
|
+
thread = threading.Thread(target=self.loop, args=(stop_event, state.sts, pods, state.namespace), daemon=True)
|
|
43
|
+
thread.start()
|
|
47
44
|
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
try:
|
|
46
|
+
log2(f"Press Ctrl+C to break.")
|
|
50
47
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
48
|
+
time.sleep(Config().get('watch.timeout', 3600 * 1))
|
|
49
|
+
except KeyboardInterrupt:
|
|
50
|
+
pass
|
|
54
51
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
52
|
+
log2("Stopping watch...")
|
|
53
|
+
stop_event.set()
|
|
54
|
+
thread.join()
|
|
58
55
|
|
|
59
|
-
|
|
56
|
+
return state
|
|
60
57
|
|
|
61
58
|
def loop(self, stop_flag: threading.Event, sts: str, pods: List[client.V1Pod], ns: str):
|
|
62
59
|
show_pods(pods, ns)
|
|
@@ -73,13 +70,13 @@ class Watch(Command):
|
|
|
73
70
|
cnt = Config().get('watch.interval', 10)
|
|
74
71
|
|
|
75
72
|
def completion(self, state: ReplState):
|
|
76
|
-
if state
|
|
77
|
-
|
|
73
|
+
if sc := super().completion(state):
|
|
74
|
+
if state.sts:
|
|
75
|
+
return sc
|
|
78
76
|
|
|
79
|
-
|
|
80
|
-
return {Watch.COMMAND: {n: None for n in StatefulSets.list_sts_names()}}
|
|
77
|
+
return super().completion(state, {n: None for n in StatefulSets.list_sts_names()})
|
|
81
78
|
|
|
82
|
-
return {
|
|
79
|
+
return {}
|
|
83
80
|
|
|
84
81
|
def help(self, _: ReplState):
|
|
85
|
-
return f'{Watch.COMMAND}\t watch pod changes'
|
|
82
|
+
return f'{Watch.COMMAND}\t watch Cassandra pod changes'
|
|
File without changes
|
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
import functools
|
|
2
2
|
import re
|
|
3
3
|
|
|
4
|
-
from adam.commands.reaper.
|
|
4
|
+
from adam.commands.reaper.utils_reaper import Reapers
|
|
5
5
|
from adam.config import Config
|
|
6
|
+
from adam.utils import log_timing
|
|
6
7
|
from adam.utils_k8s.kube_context import KubeContext
|
|
7
8
|
from adam.utils_k8s.secrets import Secrets
|
|
8
9
|
from adam.utils_k8s.statefulsets import StatefulSets
|
|
9
10
|
from adam.repl_state import ReplState
|
|
10
11
|
|
|
11
12
|
class CliCommands:
|
|
12
|
-
@functools.lru_cache()
|
|
13
13
|
def values(state: ReplState, collapse = False):
|
|
14
|
+
with log_timing('CliCommands.values'):
|
|
15
|
+
return CliCommands._values(state, collapse)
|
|
16
|
+
|
|
17
|
+
@functools.lru_cache()
|
|
18
|
+
def _values(state: ReplState, collapse = False):
|
|
14
19
|
# node-exec-?, nodetool-?, cql-?, reaper-exec, reaper-forward, reaper-ui, reaper-usernae, reaper-password
|
|
15
20
|
d = {}
|
|
16
21
|
|
|
@@ -66,8 +71,7 @@ class CliCommands:
|
|
|
66
71
|
return key.replace(f'{state.namespace}-', '').replace('-k8spg-cs-001', '')
|
|
67
72
|
d |= {f'pg-{reduce_key(k)}': f'PGPASSWORD={v["postgres-admin-password"]} psql -h {v["postgres-db-endpoint"]} -p {v["postgres-db-port"]} -U {v["postgres-admin-username"]} postgres' for k, v in data.items()}
|
|
68
73
|
|
|
69
|
-
if
|
|
70
|
-
reaper = r.reaper_spec(state)
|
|
74
|
+
if reaper := Reapers.reaper_spec(state):
|
|
71
75
|
d |= {
|
|
72
76
|
'reaper-exec': reaper["exec"],
|
|
73
77
|
'reaper-forward': reaper["forward"],
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
from functools import partial
|
|
2
|
+
import click
|
|
3
|
+
import pyperclip
|
|
4
|
+
|
|
5
|
+
from adam.commands import validate_args
|
|
6
|
+
from adam.commands.cli.cli_commands import CliCommands
|
|
7
|
+
from adam.commands.command import Command, InvalidArgumentsException
|
|
8
|
+
from adam.commands.command_helpers import ClusterOrPodCommandHelper
|
|
9
|
+
from adam.repl_state import ReplState, RequiredState
|
|
10
|
+
from adam.utils import tabulize, log, log2
|
|
11
|
+
|
|
12
|
+
class ClipboardCopy(Command):
|
|
13
|
+
COMMAND = 'cli cp'
|
|
14
|
+
|
|
15
|
+
# the singleton pattern
|
|
16
|
+
def __new__(cls, *args, **kwargs):
|
|
17
|
+
if not hasattr(cls, 'instance'): cls.instance = super(ClipboardCopy, cls).__new__(cls)
|
|
18
|
+
|
|
19
|
+
return cls.instance
|
|
20
|
+
|
|
21
|
+
def __init__(self, successor: Command=None):
|
|
22
|
+
super().__init__(successor)
|
|
23
|
+
|
|
24
|
+
def command(self):
|
|
25
|
+
return ClipboardCopy.COMMAND
|
|
26
|
+
|
|
27
|
+
def required(self):
|
|
28
|
+
return RequiredState.CLUSTER_OR_POD
|
|
29
|
+
|
|
30
|
+
def run(self, cmd: str, state: ReplState):
|
|
31
|
+
if not(args := self.args(cmd)):
|
|
32
|
+
return super().run(cmd, state)
|
|
33
|
+
|
|
34
|
+
with self.validate(args, state) as (args, state):
|
|
35
|
+
def display_keys(missing = False):
|
|
36
|
+
if missing:
|
|
37
|
+
log2('Key is required.')
|
|
38
|
+
else:
|
|
39
|
+
log2('Key is invalid.')
|
|
40
|
+
log2()
|
|
41
|
+
tabulize(CliCommands.values(state, collapse=True).items(),
|
|
42
|
+
lambda a: f'{a[0]},{a[1]}',
|
|
43
|
+
header='KEY,VALUE',
|
|
44
|
+
separator=',',
|
|
45
|
+
to=2)
|
|
46
|
+
|
|
47
|
+
with validate_args(args, state, name='key', msg=partial(display_keys, True)) as key:
|
|
48
|
+
if not key in CliCommands.values(state):
|
|
49
|
+
if state.in_repl:
|
|
50
|
+
display_keys(False)
|
|
51
|
+
else:
|
|
52
|
+
log2('* Invalid key')
|
|
53
|
+
Command.display_help()
|
|
54
|
+
|
|
55
|
+
raise InvalidArgumentsException()
|
|
56
|
+
|
|
57
|
+
value = CliCommands.values(state)[key]
|
|
58
|
+
pyperclip.copy(value)
|
|
59
|
+
log2('The following line has been copied to clipboard. Use <Ctrl-V> to use it.')
|
|
60
|
+
log2(f' {value}')
|
|
61
|
+
|
|
62
|
+
return state
|
|
63
|
+
|
|
64
|
+
def completion(self, state: ReplState):
|
|
65
|
+
return super().completion(state, lambda: {key: None for key in CliCommands.values(state).keys()}, auto_key='cli.cp-auto-complete')
|
|
66
|
+
|
|
67
|
+
def help(self, _: ReplState):
|
|
68
|
+
return f"{ClipboardCopy.COMMAND} <key>\t copy a value to clipboard for conveninence"
|
|
69
|
+
|
|
70
|
+
class CopyCommandHelper(click.Command):
|
|
71
|
+
def lines(self):
|
|
72
|
+
return [
|
|
73
|
+
'node-exec-?: kubectl exec command to the Cassandra pod',
|
|
74
|
+
'reaper-exec: kubectl exec command to the Reaper pod',
|
|
75
|
+
'reaper-forward: kubectl port-forward command to the Reaper pod',
|
|
76
|
+
'reaper-ui: uri to Reaper ui',
|
|
77
|
+
'reaper-username: Reaper user name',
|
|
78
|
+
'reaper-password: Reaper password',
|
|
79
|
+
]
|
|
80
|
+
|
|
81
|
+
def get_help(self, ctx: click.Context):
|
|
82
|
+
log(super().get_help(ctx))
|
|
83
|
+
log()
|
|
84
|
+
tabulize(self.lines(), header='KEY:DESC', separator=':')
|
|
85
|
+
log()
|
|
86
|
+
ClusterOrPodCommandHelper.cluter_or_pod_help()
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
from adam.commands.cli.cli_commands import CliCommands
|
|
2
|
+
from adam.commands.command import Command
|
|
3
|
+
from adam.repl_state import ReplState, RequiredState
|
|
4
|
+
from adam.utils import tabulize, log
|
|
5
|
+
|
|
6
|
+
class ShowKubectlCommands(Command):
|
|
7
|
+
COMMAND = 'show cli-commands'
|
|
8
|
+
|
|
9
|
+
# the singleton pattern
|
|
10
|
+
def __new__(cls, *args, **kwargs):
|
|
11
|
+
if not hasattr(cls, 'instance'): cls.instance = super(ShowKubectlCommands, cls).__new__(cls)
|
|
12
|
+
|
|
13
|
+
return cls.instance
|
|
14
|
+
|
|
15
|
+
def __init__(self, successor: Command=None):
|
|
16
|
+
super().__init__(successor)
|
|
17
|
+
|
|
18
|
+
def command(self):
|
|
19
|
+
return ShowKubectlCommands.COMMAND
|
|
20
|
+
|
|
21
|
+
def required(self):
|
|
22
|
+
return RequiredState.CLUSTER_OR_POD
|
|
23
|
+
|
|
24
|
+
def run(self, cmd: str, state: ReplState):
|
|
25
|
+
if not (args := self.args(cmd)):
|
|
26
|
+
return super().run(cmd, state)
|
|
27
|
+
|
|
28
|
+
with self.validate(args, state) as (args, state):
|
|
29
|
+
v = CliCommands.values(state, collapse=True)
|
|
30
|
+
# node-exec-?, nodetool-?, cql-?, reaper-exec, reaper-forward, reaper-ui, reaper-username, reaper-password
|
|
31
|
+
cmds = [
|
|
32
|
+
f'bash,{v["node-exec-?"]}',
|
|
33
|
+
f'nodetool,{v["nodetool-?"]}',
|
|
34
|
+
f'cql,{v["cql-?"]}',
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
if 'reaper-exec' in v:
|
|
38
|
+
cmds += [
|
|
39
|
+
f'reaper,{v["reaper-exec"]}',
|
|
40
|
+
f',{v["reaper-forward"]} * should be run from your laptop',
|
|
41
|
+
f',{v["reaper-ui"]}',
|
|
42
|
+
f',{v["reaper-username"]}',
|
|
43
|
+
f',{v["reaper-password"]}',
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
cmds += [f'{k},{v0}' for k, v0 in v.items() if k.startswith('pg-')]
|
|
47
|
+
|
|
48
|
+
tabulize(cmds, separator=',')
|
|
49
|
+
|
|
50
|
+
return cmds
|
|
51
|
+
|
|
52
|
+
def completion(self, state: ReplState):
|
|
53
|
+
return super().completion(state)
|
|
54
|
+
|
|
55
|
+
def help(self, _: ReplState):
|
|
56
|
+
return f"{ShowKubectlCommands.COMMAND}\t show kubectl commands"
|
adam/commands/code.py
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import code
|
|
2
|
+
from functools import partial
|
|
3
|
+
|
|
4
|
+
from adam.commands.command import Command
|
|
5
|
+
from adam.commands.cql.utils_cql import cassandra_table_names, run_cql
|
|
6
|
+
from adam.repl_state import ReplState, RequiredState
|
|
7
|
+
from adam.utils import tabulize
|
|
8
|
+
from adam.utils_k8s.statefulsets import StatefulSets
|
|
9
|
+
|
|
10
|
+
class Code(Command):
|
|
11
|
+
COMMAND = 'python'
|
|
12
|
+
|
|
13
|
+
# the singleton pattern
|
|
14
|
+
def __new__(cls, *args, **kwargs):
|
|
15
|
+
if not hasattr(cls, 'instance'): cls.instance = super(Code, cls).__new__(cls)
|
|
16
|
+
|
|
17
|
+
return cls.instance
|
|
18
|
+
|
|
19
|
+
def __init__(self, successor: Command=None):
|
|
20
|
+
super().__init__(successor)
|
|
21
|
+
|
|
22
|
+
def command(self):
|
|
23
|
+
return Code.COMMAND
|
|
24
|
+
|
|
25
|
+
def required(self):
|
|
26
|
+
return RequiredState.NAMESPACE
|
|
27
|
+
|
|
28
|
+
def run(self, cmd: str, state: ReplState):
|
|
29
|
+
if not(args := self.args(cmd)):
|
|
30
|
+
return super().run(cmd, state)
|
|
31
|
+
|
|
32
|
+
with self.validate(args, state) as (args, state):
|
|
33
|
+
sts = state.sts
|
|
34
|
+
pod = state.pod
|
|
35
|
+
pods = StatefulSets.pod_names(state.sts, state.namespace)
|
|
36
|
+
tables = cassandra_table_names(state)
|
|
37
|
+
cql = partial(run_cql, state, show_out=True)
|
|
38
|
+
|
|
39
|
+
my_local = globals() | locals()
|
|
40
|
+
# my_local = globals() | {'StatefulSets': StatefulSets} | locals()
|
|
41
|
+
lines = [
|
|
42
|
+
'sts: StatefulSet name',
|
|
43
|
+
'pod: Pod name',
|
|
44
|
+
'pods: Pod names in the current StatefulSet',
|
|
45
|
+
'tables: Cassandra tables names in the current StatefulSet',
|
|
46
|
+
"cql('select...'): run cql statement"
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
code.interact(local=my_local, banner=tabulize(lines, header='Variables', separator=':'))
|
|
50
|
+
|
|
51
|
+
return state
|
|
52
|
+
|
|
53
|
+
def completion(self, state: ReplState):
|
|
54
|
+
return super().completion(state)
|
|
55
|
+
|
|
56
|
+
def help(self, _: ReplState):
|
|
57
|
+
return f'{Code.COMMAND} \t invoke interactive Python shell'
|