kaqing 2.0.14__py3-none-any.whl → 2.0.145__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/apps.py +2 -2
- adam/batch.py +13 -3
- adam/checks/check_utils.py +4 -4
- adam/checks/compactionstats.py +1 -1
- adam/checks/cpu.py +2 -2
- adam/checks/disk.py +1 -1
- adam/checks/gossip.py +1 -1
- adam/checks/memory.py +3 -3
- adam/checks/status.py +1 -1
- adam/commands/alter_tables.py +81 -0
- adam/commands/app.py +3 -3
- adam/commands/app_ping.py +2 -2
- adam/commands/audit/audit.py +86 -0
- adam/commands/audit/audit_repair_tables.py +77 -0
- adam/commands/audit/audit_run.py +58 -0
- adam/commands/audit/show_last10.py +51 -0
- adam/commands/audit/show_slow10.py +50 -0
- adam/commands/audit/show_top10.py +48 -0
- adam/commands/audit/utils_show_top10.py +59 -0
- adam/commands/bash/__init__.py +0 -0
- adam/commands/bash/bash.py +133 -0
- adam/commands/bash/bash_completer.py +93 -0
- adam/commands/cat.py +56 -0
- adam/commands/cd.py +12 -82
- adam/commands/check.py +6 -0
- adam/commands/cli_commands.py +3 -3
- adam/commands/code.py +60 -0
- adam/commands/command.py +48 -12
- adam/commands/commands_utils.py +4 -5
- adam/commands/cql/__init__.py +0 -0
- adam/commands/cql/cql_completions.py +28 -0
- adam/commands/cql/cql_utils.py +209 -0
- adam/commands/{cqlsh.py → cql/cqlsh.py} +15 -10
- adam/commands/deploy/code_utils.py +2 -2
- adam/commands/deploy/deploy.py +8 -21
- adam/commands/deploy/deploy_frontend.py +1 -1
- adam/commands/deploy/deploy_pg_agent.py +3 -3
- adam/commands/deploy/deploy_pod.py +28 -27
- adam/commands/deploy/deploy_utils.py +16 -26
- adam/commands/deploy/undeploy.py +8 -21
- adam/commands/deploy/undeploy_frontend.py +1 -1
- adam/commands/deploy/undeploy_pg_agent.py +5 -3
- adam/commands/deploy/undeploy_pod.py +12 -10
- adam/commands/devices/__init__.py +0 -0
- adam/commands/devices/device.py +27 -0
- adam/commands/devices/device_app.py +146 -0
- adam/commands/devices/device_auit_log.py +43 -0
- adam/commands/devices/device_cass.py +145 -0
- adam/commands/devices/device_export.py +86 -0
- adam/commands/devices/device_postgres.py +109 -0
- adam/commands/devices/devices.py +25 -0
- adam/commands/export/__init__.py +0 -0
- adam/commands/export/clean_up_export_session.py +53 -0
- adam/commands/export/clean_up_export_sessions.py +40 -0
- adam/commands/export/drop_export_database.py +58 -0
- adam/commands/export/drop_export_databases.py +46 -0
- adam/commands/export/export.py +83 -0
- adam/commands/export/export_databases.py +170 -0
- adam/commands/export/export_select.py +85 -0
- adam/commands/export/export_select_x.py +54 -0
- adam/commands/export/export_use.py +55 -0
- adam/commands/export/exporter.py +364 -0
- adam/commands/export/import_session.py +68 -0
- adam/commands/export/importer.py +67 -0
- adam/commands/export/importer_athena.py +80 -0
- adam/commands/export/importer_sqlite.py +47 -0
- adam/commands/export/show_column_counts.py +63 -0
- adam/commands/export/show_export_databases.py +39 -0
- adam/commands/export/show_export_session.py +51 -0
- adam/commands/export/show_export_sessions.py +47 -0
- adam/commands/export/utils_export.py +291 -0
- adam/commands/help.py +12 -7
- adam/commands/issues.py +6 -0
- adam/commands/kubectl.py +41 -0
- adam/commands/login.py +7 -4
- adam/commands/logs.py +2 -1
- adam/commands/ls.py +4 -107
- adam/commands/medusa/medusa.py +2 -26
- adam/commands/medusa/medusa_backup.py +2 -2
- adam/commands/medusa/medusa_restore.py +3 -4
- adam/commands/medusa/medusa_show_backupjobs.py +4 -3
- adam/commands/medusa/medusa_show_restorejobs.py +3 -3
- adam/commands/nodetool.py +9 -4
- adam/commands/param_set.py +1 -1
- adam/commands/postgres/postgres.py +42 -43
- adam/commands/postgres/{postgres_session.py → postgres_context.py} +43 -42
- adam/commands/postgres/postgres_utils.py +31 -0
- adam/commands/postgres/psql_completions.py +10 -0
- adam/commands/preview_table.py +18 -40
- adam/commands/pwd.py +2 -28
- adam/commands/reaper/reaper.py +4 -24
- adam/commands/reaper/reaper_restart.py +1 -1
- adam/commands/reaper/reaper_session.py +2 -2
- adam/commands/repair/repair.py +3 -27
- adam/commands/repair/repair_log.py +1 -1
- adam/commands/repair/repair_run.py +2 -2
- adam/commands/repair/repair_scan.py +1 -1
- adam/commands/repair/repair_stop.py +1 -1
- adam/commands/report.py +6 -0
- adam/commands/restart.py +2 -2
- adam/commands/rollout.py +1 -1
- adam/commands/show/show.py +11 -26
- adam/commands/show/show_app_actions.py +3 -0
- adam/commands/show/show_app_id.py +1 -1
- adam/commands/show/show_app_queues.py +3 -2
- adam/commands/show/show_cassandra_status.py +3 -3
- adam/commands/show/show_cassandra_version.py +3 -3
- adam/commands/show/show_host.py +33 -0
- adam/commands/show/show_login.py +3 -0
- adam/commands/show/show_processes.py +1 -1
- adam/commands/show/show_repairs.py +2 -2
- adam/commands/show/show_storage.py +1 -1
- adam/commands/watch.py +1 -1
- adam/config.py +16 -3
- adam/embedded_params.py +1 -1
- adam/pod_exec_result.py +10 -2
- adam/repl.py +127 -117
- adam/repl_commands.py +51 -16
- adam/repl_state.py +276 -55
- adam/sql/__init__.py +0 -0
- adam/sql/sql_completer.py +120 -0
- adam/sql/sql_state_machine.py +617 -0
- adam/sql/term_completer.py +76 -0
- adam/sso/authn_ad.py +1 -1
- adam/sso/cred_cache.py +1 -1
- adam/sso/idp.py +1 -1
- adam/utils.py +83 -2
- adam/utils_athena.py +145 -0
- adam/utils_audits.py +102 -0
- adam/utils_k8s/__init__.py +0 -0
- adam/utils_k8s/app_clusters.py +33 -0
- adam/utils_k8s/app_pods.py +31 -0
- adam/{k8s_utils → utils_k8s}/cassandra_clusters.py +6 -21
- adam/{k8s_utils → utils_k8s}/cassandra_nodes.py +12 -5
- adam/{k8s_utils → utils_k8s}/deployment.py +2 -2
- adam/{k8s_utils → utils_k8s}/kube_context.py +1 -1
- adam/{k8s_utils → utils_k8s}/pods.py +119 -26
- adam/{k8s_utils → utils_k8s}/secrets.py +4 -0
- adam/{k8s_utils → utils_k8s}/statefulsets.py +5 -4
- adam/utils_net.py +24 -0
- adam/utils_repl/__init__.py +0 -0
- adam/utils_repl/automata_completer.py +48 -0
- adam/utils_repl/repl_completer.py +46 -0
- adam/utils_repl/state_machine.py +173 -0
- adam/utils_sqlite.py +101 -0
- adam/version.py +1 -1
- {kaqing-2.0.14.dist-info → kaqing-2.0.145.dist-info}/METADATA +1 -1
- kaqing-2.0.145.dist-info/RECORD +227 -0
- adam/commands/bash.py +0 -87
- adam/commands/cql_utils.py +0 -53
- adam/commands/devices.py +0 -89
- kaqing-2.0.14.dist-info/RECORD +0 -167
- /adam/{k8s_utils → commands/audit}/__init__.py +0 -0
- /adam/{k8s_utils → utils_k8s}/config_maps.py +0 -0
- /adam/{k8s_utils → utils_k8s}/custom_resources.py +0 -0
- /adam/{k8s_utils → utils_k8s}/ingresses.py +0 -0
- /adam/{k8s_utils → utils_k8s}/jobs.py +0 -0
- /adam/{k8s_utils → utils_k8s}/service_accounts.py +0 -0
- /adam/{k8s_utils → utils_k8s}/services.py +0 -0
- /adam/{k8s_utils → utils_k8s}/volumes.py +0 -0
- {kaqing-2.0.14.dist-info → kaqing-2.0.145.dist-info}/WHEEL +0 -0
- {kaqing-2.0.14.dist-info → kaqing-2.0.145.dist-info}/entry_points.txt +0 -0
- {kaqing-2.0.14.dist-info → kaqing-2.0.145.dist-info}/top_level.txt +0 -0
adam/embedded_params.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
def config():
|
|
2
|
-
return {'app': {'console-endpoint': 'https://{host}/{env}/{app}/static/console/index.html', 'cr': {'cluster-regex': '(.*?-.*?)-.*', 'group': 'ops.c3.ai', 'v': 'v2', 'plural': 'c3cassandras'}, 'label': 'c3__app_id-0', 'login': {'admin-group': '{host}/C3.ClusterAdmin', 'ingress': '{app_id}-k8singr-appleader-001', 'timeout': 5, 'session-check-url': 'https://{host}/{env}/{app}/api/8/C3/userSessionToken', 'cache-creds': True, 'cache-username': True, 'url': 'https://{host}/{env}/{app}', 'another': "You're logged in to {has}. However, for this app, you need to log in to {need}.", 'token-server-url': 'http://localhost:{port}', 'password-max-length': 128}, 'strip': '0'}, 'bash': {'workers': 32}, 'cassandra': {'service-name': 'all-pods-service'}, 'cql': {'workers': 32, 'samples': 3, 'secret': {'cluster-regex': '(.*?-.*?)-.*', 'name': '{cluster}-superuser', 'password-item': 'password'}}, 'checks': {'compactions-threshold': 250, 'cpu-busy-threshold': 98.0, 'cpu-threshold': 0.0, 'cassandra-data-path': '/c3/cassandra', 'root-disk-threshold': 50, 'cassandra-disk-threshold': 50, 'snapshot-size-cmd': "ls /c3/cassandra/data/data/*/*/snapshots | grep snapshots | sed 's/:$//g' | xargs -I {} du -sk {} | awk '{print $1}' | awk '{s+=$1} END {print s}'", 'snapshot-size-threshold': '40G', 'table-sizes-cmd': "ls -Al /c3/cassandra/data/data/ | awk '{print $9}' | sed 's/\\^r//g' | xargs -I {} du -sk /c3/cassandra/data/data/{}"}, 'get-host-id': {'workers': 32}, 'idps': {'ad': {'email-pattern': '.*@c3.ai', 'uri': 'https://login.microsoftonline.com/53ad779a-93e7-485c-ba20-ac8290d7252b/oauth2/v2.0/authorize?response_type=id_token&response_mode=form_post&client_id=00ff94a8-6b0a-4715-98e0-95490012d818&scope=openid+email+profile&redirect_uri=https%3A%2F%2Fplat.c3ci.cloud%2Fc3%2Fc3%2Foidc%2Flogin&nonce={nonce}&state=EMPTY', 'jwks-uri': 'https://login.microsoftonline.com/common/discovery/keys', 'contact': 'Please contact ted.tran@c3.ai.', 'whitelist-file': '/kaqing/members'}, 'okta': {'default': True, 'email-pattern': '.*@c3iot.com', 'uri': 'https://c3energy.okta.com/oauth2/v1/authorize?response_type=id_token&response_mode=form_post&client_id={client_id}&scope=openid+email+profile+groups&redirect_uri=https%3A%2F%2F{host}%2Fc3%2Fc3%2Foidc%2Flogin&nonce={nonce}&state=EMPTY', 'jwks-uri': 'https://c3energy.okta.com/oauth2/v1/keys'}}, 'issues': {'workers': 32}, 'logs': {'path': '/c3/cassandra/logs/system.log'}, 'medusa': {'restore-auto-complete': False}, 'nodetool': {'workers': 32, 'samples': 3, 'commands_in_line': 40}, 'pg': {'name-pattern': '^{namespace}.*-k8spg-.*', 'excludes': '.helm., -admin-secret', 'agent': {'name': 'ops-pg-agent', 'just-in-time': False, 'timeout': 86400, 'image': 'seanahnsf/kaqing'}, 'default-db': 'postgres', 'default-schema': 'postgres', 'secret': {'endpoint-key': 'postgres-db-endpoint', 'port-key': 'postgres-db-port', 'username-key': 'postgres-admin-username', 'password-key': 'postgres-admin-password'}}, 'pod': {'name': 'ops', 'image': 'seanahnsf/kaqing-cloud', 'sa': {'name': 'ops', 'proto': 'c3', 'additional-cluster-roles': 'c3aiops-k8ssandra-operator'}, 'label-selector': 'run=ops'}, 'preview': {'rows': 10}, 'processes': {'columns': 'pod,cpu,mem', 'header': 'POD_NAME,CPU,MEM/LIMIT'}, 'reaper': {'service-name': 'reaper-service', 'port-forward': {'timeout': 86400, 'local-port': 9001}, 'abort-runs-batch': 10, 'show-runs-batch': 100, 'pod': {'cluster-regex': '(.*?-.*?-.*?-.*?)-.*', 'label-selector': 'k8ssandra.io/reaper={cluster}-reaper'}, 'secret': {'cluster-regex': '(.*?-.*?)-.*', 'name': '{cluster}-reaper-ui', 'password-item': 'password'}}, 'repair': {'log-path': '/home/cassrepair/logs/', 'image': 'ci-registry.c3iot.io/cloudops/cassrepair:2.0.
|
|
2
|
+
return {'app': {'console-endpoint': 'https://{host}/{env}/{app}/static/console/index.html', 'container-name': 'c3-server', 'cr': {'cluster-regex': '(.*?-.*?)-.*', 'group': 'ops.c3.ai', 'v': 'v2', 'plural': 'c3cassandras'}, 'label': 'c3__app_id-0', 'login': {'admin-group': '{host}/C3.ClusterAdmin', 'ingress': '{app_id}-k8singr-appleader-001', 'timeout': 5, 'session-check-url': 'https://{host}/{env}/{app}/api/8/C3/userSessionToken', 'cache-creds': True, 'cache-username': True, 'url': 'https://{host}/{env}/{app}', 'another': "You're logged in to {has}. However, for this app, you need to log in to {need}.", 'token-server-url': 'http://localhost:{port}', 'password-max-length': 128}, 'strip': '0'}, 'audit': {'endpoint': 'https://4psvtaxlcb.execute-api.us-west-2.amazonaws.com/prod/', 'workers': 3, 'timeout': 10, 'log-audit-queries': False, 'athena': {'auto-repair': {'elapsed_hours': 12}, 'region': 'us-west-2', 'catalog': 'AwsDataCatalog', 'database': 'audit', 'repair-partition-tables': 'audit', 'output': 's3://s3.ops--audit/ddl/results', 'repair-cluster-tables': 'cluster'}}, 'bash': {'workers': 32}, 'cassandra': {'service-name': 'all-pods-service'}, 'cql': {'workers': 32, 'samples': 3, 'secret': {'cluster-regex': '(.*?-.*?)-.*', 'name': '{cluster}-superuser', 'password-item': 'password'}, 'alter-tables': {'excludes': 'system_auth,system_traces,reaper_db,system_distributed,system_views,system,system_schema,system_virtual_schema', 'gc-grace-periods': '3600,86400,864000,7776000', 'batching': True}}, 'export': {'workers': 8, 'csv_dir': '/c3/cassandra/tmp', 'default-importer': 'sqlite', 'sqlite': {'workers': 8, 'columns': '<row-key>', 'local-db-dir': '/tmp/qing-db', 'column_counts_query': 'select id, count(id) as columns from {table} group by id order by columns desc limit 10'}, 'athena': {'workers': 8, 'columns': '<keys>', 'bucket': 'c3.ops--qing', 'column_counts_query': 'select id, count(id) as columns from {table} group by id order by columns desc limit 10'}, 'csv': {'workers': 8, 'columns': '<row-key>'}}, 'checks': {'compactions-threshold': 250, 'cpu-busy-threshold': 98.0, 'cpu-threshold': 0.0, 'cassandra-data-path': '/c3/cassandra', 'root-disk-threshold': 50, 'cassandra-disk-threshold': 50, 'snapshot-size-cmd': "ls /c3/cassandra/data/data/*/*/snapshots | grep snapshots | sed 's/:$//g' | xargs -I {} du -sk {} | awk '{print $1}' | awk '{s+=$1} END {print s}'", 'snapshot-size-threshold': '40G', 'table-sizes-cmd': "ls -Al /c3/cassandra/data/data/ | awk '{print $9}' | sed 's/\\^r//g' | xargs -I {} du -sk /c3/cassandra/data/data/{}"}, 'get-host-id': {'workers': 32}, 'idps': {'ad': {'email-pattern': '.*@c3.ai', 'uri': 'https://login.microsoftonline.com/53ad779a-93e7-485c-ba20-ac8290d7252b/oauth2/v2.0/authorize?response_type=id_token&response_mode=form_post&client_id=00ff94a8-6b0a-4715-98e0-95490012d818&scope=openid+email+profile&redirect_uri=https%3A%2F%2Fplat.c3ci.cloud%2Fc3%2Fc3%2Foidc%2Flogin&nonce={nonce}&state=EMPTY', 'jwks-uri': 'https://login.microsoftonline.com/common/discovery/keys', 'contact': 'Please contact ted.tran@c3.ai.', 'whitelist-file': '/kaqing/members'}, 'okta': {'default': True, 'email-pattern': '.*@c3iot.com', 'uri': 'https://c3energy.okta.com/oauth2/v1/authorize?response_type=id_token&response_mode=form_post&client_id={client_id}&scope=openid+email+profile+groups&redirect_uri=https%3A%2F%2F{host}%2Fc3%2Fc3%2Foidc%2Flogin&nonce={nonce}&state=EMPTY', 'jwks-uri': 'https://c3energy.okta.com/oauth2/v1/keys'}}, 'issues': {'workers': 32}, 'logs': {'path': '/c3/cassandra/logs/system.log'}, 'log-prefix': '/tmp/qing', 'medusa': {'restore-auto-complete': False}, 'nodetool': {'workers': 32, 'samples': 3, 'commands_in_line': 40}, 'pg': {'name-pattern': '^{namespace}.*-k8spg-.*', 'excludes': '.helm., -admin-secret', 'agent': {'name': 'ops-pg-agent', 'just-in-time': False, 'timeout': 86400, 'image': 'seanahnsf/kaqing'}, 'default-db': 'postgres', 'default-schema': 'postgres', 'secret': {'endpoint-key': 'postgres-db-endpoint', 'port-key': 'postgres-db-port', 'username-key': 'postgres-admin-username', 'password-key': 'postgres-admin-password'}}, 'pod': {'name': 'ops', 'image': 'seanahnsf/kaqing-cloud', 'sa': {'name': 'ops', 'proto': 'c3', 'additional-cluster-roles': 'c3aiops-k8ssandra-operator'}, 'label-selector': 'run=ops'}, 'preview': {'rows': 10}, 'processes': {'columns': 'pod,cpu,mem', 'header': 'POD_NAME,CPU,MEM/LIMIT'}, 'reaper': {'service-name': 'reaper-service', 'port-forward': {'timeout': 86400, 'local-port': 9001}, 'abort-runs-batch': 10, 'show-runs-batch': 100, 'pod': {'cluster-regex': '(.*?-.*?-.*?-.*?)-.*', 'label-selector': 'k8ssandra.io/reaper={cluster}-reaper'}, 'secret': {'cluster-regex': '(.*?-.*?)-.*', 'name': '{cluster}-reaper-ui', 'password-item': 'password'}}, 'repair': {'log-path': '/home/cassrepair/logs/', 'image': 'ci-registry.c3iot.io/cloudops/cassrepair:2.0.14', 'secret': 'ciregistryc3iotio', 'env': {'interval': 24, 'timeout': 60, 'pr': False, 'runs': 1}}, 'repl': {'start-drive': 'c', 'a': {'auto-enter': 'c3/c3/*'}, 'c': {'auto-enter': 'cluster'}, 'x': {'auto-enter': 'latest'}, 'history': {'push-cat-remote-log-file': True}, 'background-process': {'auto-nohup': True}}, 'status': {'columns': 'status,address,load,tokens,owns,host_id,gossip,compactions', 'header': '--,Address,Load,Tokens,Owns,Host ID,GOSSIP,COMPACTIONS'}, 'storage': {'columns': 'pod,volume_root,volume_cassandra,snapshots,data,compactions', 'header': 'POD_NAME,VOLUME /,VOLUME CASS,SNAPSHOTS,DATA,COMPACTIONS'}, 'watch': {'auto': 'rollout', 'timeout': 3600, 'interval': 10}, 'debug': False, 'debugs': {'timings': False, 'exit-on-error': False, 'show-parallelism': False}}
|
adam/pod_exec_result.py
CHANGED
|
@@ -15,12 +15,14 @@ class PodExecResult:
|
|
|
15
15
|
# ]
|
|
16
16
|
# }
|
|
17
17
|
# }
|
|
18
|
-
def __init__(self, stdout: str, stderr: str, command: str = None, error_output: str = None):
|
|
18
|
+
def __init__(self, stdout: str, stderr: str, command: str = None, error_output: str = None, pod: str = None, log_file: str = None):
|
|
19
19
|
self.stdout: str = stdout
|
|
20
20
|
self.stderr: str = stderr
|
|
21
21
|
self.command: str = command
|
|
22
22
|
if error_output:
|
|
23
23
|
self.error = yaml.safe_load(error_output)
|
|
24
|
+
self.pod = pod
|
|
25
|
+
self.log_file = log_file
|
|
24
26
|
|
|
25
27
|
def exit_code(self) -> int:
|
|
26
28
|
code = 0
|
|
@@ -30,4 +32,10 @@ class PodExecResult:
|
|
|
30
32
|
except:
|
|
31
33
|
pass
|
|
32
34
|
|
|
33
|
-
return code
|
|
35
|
+
return code
|
|
36
|
+
|
|
37
|
+
def __str__(self):
|
|
38
|
+
return f'{"OK" if self.exit_code() == 0 else self.exit_code()} {self.command}'
|
|
39
|
+
|
|
40
|
+
def __audit_extra__(self):
|
|
41
|
+
return self.log_file if self.log_file else None
|
adam/repl.py
CHANGED
|
@@ -1,25 +1,28 @@
|
|
|
1
1
|
import os
|
|
2
|
-
import re
|
|
3
2
|
import time
|
|
4
3
|
import traceback
|
|
4
|
+
from typing import cast
|
|
5
5
|
import click
|
|
6
|
-
|
|
6
|
+
import concurrent
|
|
7
7
|
from prompt_toolkit.key_binding import KeyBindings
|
|
8
8
|
|
|
9
9
|
from adam.cli_group import cli
|
|
10
10
|
from adam.commands.command import Command
|
|
11
11
|
from adam.commands.command_helpers import ClusterCommandHelper
|
|
12
|
+
from adam.commands.devices.devices import Devices
|
|
12
13
|
from adam.commands.help import Help
|
|
13
|
-
from adam.commands.postgres.postgres_session import PostgresSession
|
|
14
14
|
from adam.config import Config
|
|
15
|
-
from adam.
|
|
16
|
-
from adam.
|
|
15
|
+
from adam.utils_audits import Audits
|
|
16
|
+
from adam.utils_k8s.app_pods import AppPods
|
|
17
|
+
from adam.utils_k8s.kube_context import KubeContext
|
|
18
|
+
from adam.utils_k8s.statefulsets import StatefulSets
|
|
17
19
|
from adam.log import Log
|
|
18
20
|
from adam.repl_commands import ReplCommands
|
|
19
21
|
from adam.repl_session import ReplSession
|
|
20
22
|
from adam.repl_state import ReplState
|
|
21
|
-
from adam.utils import deep_merge_dicts, lines_to_tabular, log2
|
|
23
|
+
from adam.utils import deep_merge_dicts, deep_sort_dict, lines_to_tabular, log2
|
|
22
24
|
from adam.apps import Apps
|
|
25
|
+
from adam.utils_repl.repl_completer import ReplCompleter
|
|
23
26
|
from . import __version__
|
|
24
27
|
|
|
25
28
|
def enter_repl(state: ReplState):
|
|
@@ -33,54 +36,13 @@ def enter_repl(state: ReplState):
|
|
|
33
36
|
session = ReplSession().prompt_session
|
|
34
37
|
|
|
35
38
|
def prompt_msg():
|
|
36
|
-
msg =
|
|
37
|
-
if state.device == ReplState.P:
|
|
38
|
-
msg = f'{ReplState.P}:'
|
|
39
|
-
pg = PostgresSession(state.namespace, state.pg_path) if state.pg_path else None
|
|
40
|
-
if pg and pg.db:
|
|
41
|
-
msg += pg.db
|
|
42
|
-
elif pg and pg.host:
|
|
43
|
-
msg += pg.host
|
|
44
|
-
elif state.device == ReplState.A:
|
|
45
|
-
msg = f'{ReplState.A}:'
|
|
46
|
-
if state.app_env:
|
|
47
|
-
msg += state.app_env
|
|
48
|
-
if state.app_app:
|
|
49
|
-
msg += f'/{state.app_app}'
|
|
50
|
-
else:
|
|
51
|
-
msg = f'{ReplState.C}:'
|
|
52
|
-
if state.pod:
|
|
53
|
-
# cs-d0767a536f-cs-d0767a536f-default-sts-0
|
|
54
|
-
group = re.match(r".*?-.*?-(.*)", state.pod)
|
|
55
|
-
msg += group[1]
|
|
56
|
-
elif state.sts:
|
|
57
|
-
# cs-d0767a536f-cs-d0767a536f-default-sts
|
|
58
|
-
group = re.match(r".*?-.*?-(.*)", state.sts)
|
|
59
|
-
msg += group[1]
|
|
39
|
+
msg = state.__str__()
|
|
60
40
|
|
|
61
41
|
return f"{msg}$ " if state.bash_session else f"{msg}> "
|
|
62
42
|
|
|
63
43
|
Log.log2(f'kaqing {__version__}')
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if state.device == ReplState.C:
|
|
67
|
-
if not ss:
|
|
68
|
-
raise Exception("no Cassandra clusters found")
|
|
69
|
-
elif len(ss) == 1 and Config().get('repl.auto-enter-only-cluster', True):
|
|
70
|
-
cluster = ss[0]
|
|
71
|
-
state.sts = cluster[0]
|
|
72
|
-
state.namespace = cluster[1]
|
|
73
|
-
state.wait_log(f'Moving to the only Cassandra cluster: {state.sts}@{state.namespace}...')
|
|
74
|
-
elif state.device == ReplState.A:
|
|
75
|
-
if app := Config().get('repl.auto-enter-app', 'c3/c3'):
|
|
76
|
-
if app != 'no':
|
|
77
|
-
ea = app.split('/')
|
|
78
|
-
state.app_env = ea[0]
|
|
79
|
-
if len(ea) > 1:
|
|
80
|
-
state.app_app = ea[1]
|
|
81
|
-
state.wait_log(f'Moving to {state.app_env}/{state.app_app}...')
|
|
82
|
-
else:
|
|
83
|
-
state.wait_log(f'Moving to {state.app_env}...')
|
|
44
|
+
|
|
45
|
+
Devices.device(state).enter(state)
|
|
84
46
|
|
|
85
47
|
kb = KeyBindings()
|
|
86
48
|
|
|
@@ -88,72 +50,120 @@ def enter_repl(state: ReplState):
|
|
|
88
50
|
def _(event):
|
|
89
51
|
event.app.current_buffer.text = ''
|
|
90
52
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
cmd =
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
if
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
53
|
+
with concurrent.futures.ThreadPoolExecutor(max_workers=Config().get('audit.workers', 3)) as executor:
|
|
54
|
+
# warm up AWS lambda - this log line may timeout and get lost, which is fine
|
|
55
|
+
executor.submit(Audits.log, 'entering kaqing repl', state.namespace, 'z', 0.0)
|
|
56
|
+
|
|
57
|
+
s0 = time.time()
|
|
58
|
+
|
|
59
|
+
# use sorted command list only for auto-completion
|
|
60
|
+
sorted_cmds = sorted(cmd_list, key=lambda cmd: cmd.command())
|
|
61
|
+
while True:
|
|
62
|
+
result = None
|
|
63
|
+
try:
|
|
64
|
+
completer = ReplCompleter.from_nested_dict({})
|
|
65
|
+
if not state.bash_session:
|
|
66
|
+
completions = {}
|
|
67
|
+
# app commands are available only on a: drive
|
|
68
|
+
if state.device == ReplState.A and state.app_app:
|
|
69
|
+
completions = Apps(path='apps.yaml').commands()
|
|
70
|
+
|
|
71
|
+
for cmd in sorted_cmds:
|
|
72
|
+
s1 = time.time()
|
|
73
|
+
try:
|
|
74
|
+
completions = deep_sort_dict(deep_merge_dicts(completions, cmd.completion(state)))
|
|
75
|
+
finally:
|
|
76
|
+
if Config().get('debugs.timings', False):
|
|
77
|
+
log2(f'Timing auto-completion-calc {cmd.command()}: {time.time() - s1:.2f}')
|
|
78
|
+
|
|
79
|
+
# print(json.dumps(completions, indent=4))
|
|
80
|
+
completer = ReplCompleter.from_nested_dict(completions)
|
|
81
|
+
|
|
82
|
+
cmd = session.prompt(prompt_msg(), completer=completer, key_bindings=kb)
|
|
83
|
+
s0 = time.time()
|
|
84
|
+
|
|
85
|
+
if state.bash_session:
|
|
86
|
+
if cmd.strip(' ') == 'exit':
|
|
87
|
+
state.exit_bash()
|
|
88
|
+
continue
|
|
89
|
+
|
|
90
|
+
cmd = f'bash {cmd}'
|
|
91
|
+
|
|
92
|
+
def targetted(state: ReplState, cmd: str):
|
|
93
|
+
if not (cmd.startswith('@') and len(arry := cmd.split(' ')) > 1):
|
|
94
|
+
return state, cmd
|
|
95
|
+
|
|
96
|
+
if state.device == ReplState.A and state.app_app or state.device == ReplState.P:
|
|
97
|
+
state.push()
|
|
98
|
+
|
|
99
|
+
state.app_pod = arry[0].strip('@')
|
|
100
|
+
cmd = ' '.join(arry[1:])
|
|
101
|
+
elif state.device == ReplState.P:
|
|
102
|
+
state.push()
|
|
103
|
+
|
|
104
|
+
state.app_pod = arry[0].strip('@')
|
|
105
|
+
cmd = ' '.join(arry[1:])
|
|
106
|
+
elif state.sts:
|
|
107
|
+
state.push()
|
|
108
|
+
|
|
109
|
+
state.pod = arry[0].strip('@')
|
|
110
|
+
cmd = ' '.join(arry[1:])
|
|
111
|
+
|
|
112
|
+
return (state, cmd)
|
|
113
|
+
|
|
114
|
+
target, cmd = targetted(state, cmd)
|
|
115
|
+
if cmd and cmd.strip(' ') and not (result := cmds.run(cmd, target)):
|
|
116
|
+
result = try_device_default_action(target, cmds, cmd_list, cmd)
|
|
117
|
+
|
|
118
|
+
if result and type(result) is ReplState and (s := cast(ReplState, result).export_session) != state.export_session:
|
|
119
|
+
state.export_session = s
|
|
120
|
+
|
|
121
|
+
except EOFError: # Handle Ctrl+D (EOF) for graceful exit
|
|
122
|
+
break
|
|
123
|
+
except Exception as e:
|
|
124
|
+
if Config().get('debugs.exit-on-error', False):
|
|
125
|
+
raise e
|
|
126
|
+
else:
|
|
127
|
+
log2(e)
|
|
128
|
+
Config().debug(traceback.format_exc())
|
|
129
|
+
finally:
|
|
130
|
+
if not state.bash_session:
|
|
131
|
+
state.pop()
|
|
132
|
+
|
|
133
|
+
Config().clear_wait_log_flag()
|
|
134
|
+
if Config().get('debugs.timings', False) and 'cmd' in locals() and 's0' in locals():
|
|
135
|
+
log2(f'Timing command {cmd}: {time.time() - s0:.2f}')
|
|
136
|
+
|
|
137
|
+
# offload audit logging
|
|
138
|
+
if cmd and (state.device != ReplState.L or Config().get('audit.log-audit-queries', False)):
|
|
139
|
+
executor.submit(Audits.log, cmd, state.namespace, state.device, time.time() - s0, get_audit_extra(result))
|
|
140
|
+
|
|
141
|
+
def try_device_default_action(state: ReplState, cmds: Command, cmd_list: list[Command], cmd: str):
|
|
142
|
+
default_action_tried, result = Devices.device(state).try_fallback_action(cmds, state, cmd)
|
|
143
|
+
|
|
144
|
+
if not default_action_tried:
|
|
145
|
+
log2(f'* Invalid command: {cmd}')
|
|
146
|
+
log2()
|
|
147
|
+
lines = [c.help(state) for c in cmd_list if c.help(state)]
|
|
148
|
+
log2(lines_to_tabular(lines, separator='\t'))
|
|
149
|
+
|
|
150
|
+
return result
|
|
151
|
+
|
|
152
|
+
def get_audit_extra(result: any):
|
|
153
|
+
if not result:
|
|
154
|
+
return None
|
|
155
|
+
|
|
156
|
+
if type(result) is list:
|
|
157
|
+
extras = set()
|
|
158
|
+
|
|
159
|
+
for r in result:
|
|
160
|
+
if hasattr(r, '__audit_extra__') and (x := r.__audit_extra__()):
|
|
161
|
+
extras.add(x)
|
|
162
|
+
|
|
163
|
+
return ','.join(list(extras))
|
|
164
|
+
|
|
165
|
+
if hasattr(result, '__audit_extra__') and (x := result.__audit_extra__()):
|
|
166
|
+
return x
|
|
157
167
|
|
|
158
168
|
@cli.command(context_settings=dict(ignore_unknown_options=True, allow_extra_args=True), cls=ClusterCommandHelper, help="Enter interactive shell.")
|
|
159
169
|
@click.option('--kubeconfig', '-k', required=False, metavar='path', help='path to kubeconfig file')
|
|
@@ -168,5 +178,5 @@ def repl(kubeconfig: str, config: str, param: list[str], cluster:str, namespace:
|
|
|
168
178
|
return
|
|
169
179
|
|
|
170
180
|
state = ReplState(device=Config().get('repl.start-drive', 'a'), ns_sts=cluster, namespace=namespace, in_repl=True)
|
|
171
|
-
state, _ = state.
|
|
181
|
+
state, _ = state.apply_device_arg(extra_args)
|
|
172
182
|
enter_repl(state)
|
adam/repl_commands.py
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
from adam.commands.alter_tables import AlterTables
|
|
1
2
|
from adam.commands.app import App
|
|
2
3
|
from adam.commands.app_ping import AppPing
|
|
4
|
+
from adam.commands.audit.audit import Audit
|
|
5
|
+
from adam.commands.cat import Cat
|
|
6
|
+
from adam.commands.code import Code
|
|
3
7
|
from adam.commands.deploy.code_start import CodeStart
|
|
4
8
|
from adam.commands.deploy.code_stop import CodeStop
|
|
5
9
|
from adam.commands.deploy.deploy import Deploy
|
|
@@ -10,22 +14,40 @@ from adam.commands.deploy.undeploy import Undeploy
|
|
|
10
14
|
from adam.commands.deploy.undeploy_frontend import UndeployFrontend
|
|
11
15
|
from adam.commands.deploy.undeploy_pg_agent import UndeployPgAgent
|
|
12
16
|
from adam.commands.deploy.undeploy_pod import UndeployPod
|
|
17
|
+
from adam.commands.devices.device_app import DeviceApp
|
|
18
|
+
from adam.commands.devices.device_auit_log import DeviceAuditLog
|
|
19
|
+
from adam.commands.devices.device_cass import DeviceCass
|
|
20
|
+
from adam.commands.devices.device_export import DeviceExport
|
|
21
|
+
from adam.commands.devices.device_postgres import DevicePostgres
|
|
22
|
+
from adam.commands.export.drop_export_database import DropExportDatabase
|
|
23
|
+
from adam.commands.export.export import ExportTables
|
|
24
|
+
from adam.commands.export.import_session import ImportSession
|
|
25
|
+
from adam.commands.export.clean_up_export_session import CleanUpExportSession
|
|
26
|
+
from adam.commands.export.clean_up_export_sessions import CleanUpExportSessions
|
|
27
|
+
from adam.commands.export.drop_export_databases import DropExportDatabases
|
|
28
|
+
from adam.commands.export.export_select import ExportSelect
|
|
29
|
+
from adam.commands.export.export_use import ExportUse
|
|
30
|
+
from adam.commands.export.export_select_x import ExportSelectX
|
|
31
|
+
from adam.commands.export.show_column_counts import ShowColumnCounts
|
|
32
|
+
from adam.commands.export.show_export_databases import ShowExportDatabases
|
|
33
|
+
from adam.commands.export.show_export_session import ShowExportSession
|
|
34
|
+
from adam.commands.export.show_export_sessions import ShowExportSessions
|
|
35
|
+
from adam.commands.kubectl import Kubectl
|
|
13
36
|
from adam.commands.shell import Shell
|
|
14
37
|
from adam.commands.show.show_app_queues import ShowAppQueues
|
|
15
38
|
from adam.commands.cp import ClipboardCopy
|
|
16
|
-
from adam.commands.bash import Bash
|
|
39
|
+
from adam.commands.bash.bash import Bash
|
|
17
40
|
from adam.commands.cd import Cd
|
|
18
41
|
from adam.commands.check import Check
|
|
19
42
|
from adam.commands.command import Command
|
|
20
|
-
from adam.commands.cqlsh import Cqlsh
|
|
21
|
-
from adam.commands.devices import DeviceApp, DeviceCass, DevicePostgres
|
|
43
|
+
from adam.commands.cql.cqlsh import Cqlsh
|
|
22
44
|
from adam.commands.exit import Exit
|
|
23
45
|
from adam.commands.medusa.medusa import Medusa
|
|
24
46
|
from adam.commands.param_get import GetParam
|
|
25
47
|
from adam.commands.issues import Issues
|
|
26
48
|
from adam.commands.ls import Ls
|
|
27
49
|
from adam.commands.nodetool import NodeTool
|
|
28
|
-
from adam.commands.postgres.postgres import Postgres
|
|
50
|
+
from adam.commands.postgres.postgres import Postgres, PostgresPg
|
|
29
51
|
from adam.commands.preview_table import PreviewTable
|
|
30
52
|
from adam.commands.pwd import Pwd
|
|
31
53
|
from adam.commands.reaper.reaper import Reaper
|
|
@@ -40,6 +62,7 @@ from adam.commands.show.show_app_id import ShowAppId
|
|
|
40
62
|
from adam.commands.show.show_cassandra_status import ShowCassandraStatus
|
|
41
63
|
from adam.commands.show.show_cassandra_version import ShowCassandraVersion
|
|
42
64
|
from adam.commands.show.show_commands import ShowKubectlCommands
|
|
65
|
+
from adam.commands.show.show_host import ShowHost
|
|
43
66
|
from adam.commands.show.show_login import ShowLogin
|
|
44
67
|
from adam.commands.show.show_params import ShowParams
|
|
45
68
|
from adam.commands.show.show_processes import ShowProcesses
|
|
@@ -50,10 +73,10 @@ from adam.commands.watch import Watch
|
|
|
50
73
|
|
|
51
74
|
class ReplCommands:
|
|
52
75
|
def repl_cmd_list() -> list[Command]:
|
|
53
|
-
cmds: list[Command] = ReplCommands.navigation() + ReplCommands.
|
|
54
|
-
ReplCommands.
|
|
76
|
+
cmds: list[Command] = ReplCommands.navigation() + ReplCommands.cassandra_ops() + ReplCommands.postgres_ops() + \
|
|
77
|
+
ReplCommands.app_ops() + ReplCommands.audit_ops() + ReplCommands.export_ops() + ReplCommands.tools() + ReplCommands.exit()
|
|
55
78
|
|
|
56
|
-
intermediate_cmds: list[Command] = [App(), Reaper(), Repair(), Deploy(), Show(), Undeploy()]
|
|
79
|
+
intermediate_cmds: list[Command] = [App(), Audit(), Reaper(), Repair(), Deploy(), Show(), Undeploy()]
|
|
57
80
|
ic = [c.command() for c in intermediate_cmds]
|
|
58
81
|
# 1. dedup commands
|
|
59
82
|
deduped = []
|
|
@@ -70,20 +93,32 @@ class ReplCommands:
|
|
|
70
93
|
return deduped
|
|
71
94
|
|
|
72
95
|
def navigation() -> list[Command]:
|
|
73
|
-
return [Ls(), PreviewTable(), DeviceApp(), DevicePostgres(), DeviceCass(), Cd(), Pwd(), ClipboardCopy(),
|
|
74
|
-
GetParam(), SetParam(), ShowParams(), ShowKubectlCommands(), ShowLogin(), ShowAdam()]
|
|
75
|
-
|
|
76
|
-
def cassandra_check() -> list[Command]:
|
|
77
|
-
return [ShowCassandraStatus(), ShowCassandraVersion(), ShowRepairs(), ShowStorage(), ShowProcesses(), Check(), Issues(), NodeTool(), Report()]
|
|
96
|
+
return [Ls(), PreviewTable(), DeviceApp(), DevicePostgres(), DeviceCass(), DeviceAuditLog(), DeviceExport(), Cd(), Cat(), Pwd(), ClipboardCopy(),
|
|
97
|
+
GetParam(), SetParam(), ShowParams(), ShowKubectlCommands(), ShowLogin(), ShowAdam(), ShowHost()]
|
|
78
98
|
|
|
79
99
|
def cassandra_ops() -> list[Command]:
|
|
80
|
-
return
|
|
100
|
+
return [Cqlsh(), ShowCassandraStatus(), ShowCassandraVersion(), ShowRepairs(), ShowStorage(), ShowProcesses(),
|
|
101
|
+
Check(), Issues(), NodeTool(), Report(), AlterTables(), Bash(),
|
|
102
|
+
ExportTables(), ExportSelect(), ExportUse(), ShowExportDatabases(), ShowColumnCounts(),
|
|
103
|
+
DropExportDatabase(), DropExportDatabases(),
|
|
104
|
+
ShowExportSessions(), ShowExportSession(),
|
|
105
|
+
CleanUpExportSession(), CleanUpExportSessions(), ImportSession()] + \
|
|
106
|
+
Medusa.cmd_list() + [Restart(), RollOut(), Watch()] + Reaper.cmd_list() + Repair.cmd_list()
|
|
81
107
|
|
|
82
|
-
def
|
|
83
|
-
return [
|
|
108
|
+
def postgres_ops() -> list[Command]:
|
|
109
|
+
return [Postgres(), DeployPgAgent(), UndeployPgAgent(), PostgresPg()]
|
|
84
110
|
|
|
85
|
-
def
|
|
111
|
+
def app_ops() -> list[Command]:
|
|
86
112
|
return [ShowAppActions(), ShowAppId(), ShowAppQueues(), AppPing(), App()]
|
|
87
113
|
|
|
114
|
+
def audit_ops() -> list[Command]:
|
|
115
|
+
return [Audit()] + Audit.cmd_list()
|
|
116
|
+
|
|
117
|
+
def export_ops() -> list[Command]:
|
|
118
|
+
return [ExportSelectX(), DropExportDatabase(), DropExportDatabases(), ShowColumnCounts()]
|
|
119
|
+
|
|
120
|
+
def tools() -> list[Command]:
|
|
121
|
+
return [Shell(), CodeStart(), CodeStop(), DeployFrontend(), UndeployFrontend(), DeployPod(), UndeployPod(), Kubectl(), Code()]
|
|
122
|
+
|
|
88
123
|
def exit() -> list[Command]:
|
|
89
124
|
return [Exit()]
|