kaqing 2.0.214__py3-none-any.whl → 2.0.227__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/checks/compactionstats.py +2 -1
- adam/checks/cpu.py +2 -1
- adam/checks/disk.py +6 -5
- adam/checks/gossip.py +2 -1
- adam/checks/memory.py +2 -1
- adam/checks/status.py +2 -1
- adam/commands/app/app.py +2 -2
- adam/commands/app/app_ping.py +2 -2
- adam/commands/app/login.py +2 -2
- adam/commands/app/show_app_actions.py +2 -2
- adam/commands/app/show_app_id.py +2 -2
- adam/commands/app/show_app_queues.py +2 -2
- adam/commands/app/show_login.py +2 -2
- adam/commands/audit/audit.py +3 -5
- adam/commands/audit/audit_repair_tables.py +2 -2
- adam/commands/audit/audit_run.py +2 -2
- adam/commands/audit/show_last10.py +2 -2
- adam/commands/audit/show_slow10.py +2 -2
- adam/commands/audit/show_top10.py +2 -2
- adam/commands/bash/bash.py +2 -2
- adam/commands/cassandra/download_cassandra_log.py +2 -2
- adam/commands/cassandra/restart_cluster.py +2 -2
- adam/commands/cassandra/restart_node.py +2 -2
- adam/commands/cassandra/restart_nodes.py +2 -2
- adam/commands/cassandra/rollout.py +2 -2
- adam/commands/cassandra/show_cassandra_repairs.py +2 -2
- adam/commands/cassandra/show_cassandra_status.py +2 -2
- adam/commands/cassandra/show_cassandra_version.py +2 -2
- adam/commands/cassandra/show_processes.py +6 -6
- adam/commands/cassandra/show_storage.py +2 -2
- adam/commands/cassandra/watch.py +2 -2
- adam/commands/cli/clipboard_copy.py +2 -2
- adam/commands/cli/show_cli_commands.py +3 -3
- adam/commands/code.py +2 -2
- adam/commands/command.py +32 -5
- adam/commands/config/param_get.py +2 -2
- adam/commands/config/param_set.py +2 -2
- adam/commands/config/show_params.py +2 -2
- adam/commands/cql/alter_tables.py +2 -2
- adam/commands/cql/cqlsh.py +2 -2
- adam/commands/cql/utils_cql.py +13 -3
- adam/commands/debug/debug_completes.py +2 -2
- adam/commands/debug/debug_timings.py +2 -2
- adam/commands/debug/show_offloaded_completes.py +2 -2
- adam/commands/deploy/code_start.py +2 -2
- adam/commands/deploy/code_stop.py +2 -2
- adam/commands/deploy/deploy_frontend.py +2 -2
- adam/commands/deploy/deploy_pg_agent.py +2 -2
- adam/commands/deploy/deploy_pod.py +2 -2
- adam/commands/deploy/undeploy_frontend.py +2 -2
- adam/commands/deploy/undeploy_pg_agent.py +2 -2
- adam/commands/deploy/undeploy_pod.py +2 -2
- adam/commands/devices/device.py +7 -7
- adam/commands/devices/device_app.py +6 -6
- adam/commands/devices/device_auit_log.py +2 -2
- adam/commands/devices/device_cass.py +6 -6
- adam/commands/devices/device_export.py +2 -2
- adam/commands/devices/device_postgres.py +6 -6
- adam/commands/diag/check.py +2 -2
- adam/commands/diag/generate_report.py +2 -2
- adam/commands/diag/issues.py +3 -2
- adam/commands/exit.py +2 -2
- adam/commands/export/clean_up_all_export_sessions.py +2 -2
- adam/commands/export/clean_up_export_sessions.py +2 -2
- adam/commands/export/download_export_session.py +4 -5
- adam/commands/export/drop_export_database.py +2 -2
- adam/commands/export/drop_export_databases.py +2 -2
- adam/commands/export/export.py +3 -3
- adam/commands/export/export_databases.py +3 -0
- adam/commands/export/export_select.py +2 -2
- adam/commands/export/export_sessions.py +10 -9
- adam/commands/export/export_use.py +3 -3
- adam/commands/export/export_x_select.py +2 -2
- adam/commands/export/exporter.py +11 -11
- adam/commands/export/import_files.py +3 -7
- adam/commands/export/import_session.py +2 -2
- adam/commands/export/importer.py +6 -7
- adam/commands/export/show_column_counts.py +2 -3
- adam/commands/export/show_export_databases.py +3 -4
- adam/commands/export/show_export_session.py +4 -4
- adam/commands/export/show_export_sessions.py +3 -3
- adam/commands/export/utils_export.py +25 -33
- adam/commands/fs/cat.py +2 -2
- adam/commands/fs/cat_local.py +2 -2
- adam/commands/fs/cd.py +2 -2
- adam/commands/fs/download_file.py +2 -2
- adam/commands/fs/find_files.py +3 -3
- adam/commands/fs/find_processes.py +12 -20
- adam/commands/fs/head.py +4 -4
- adam/commands/fs/head_local.py +46 -0
- adam/commands/fs/ls.py +2 -2
- adam/commands/fs/ls_local.py +2 -2
- adam/commands/fs/pwd.py +2 -2
- adam/commands/fs/rm.py +2 -2
- adam/commands/fs/rm_downloads.py +2 -2
- adam/commands/fs/rm_logs.py +13 -7
- adam/commands/fs/rm_logs_local.py +38 -0
- adam/commands/fs/shell.py +2 -2
- adam/commands/fs/show_adam.py +2 -2
- adam/commands/fs/show_host.py +2 -2
- adam/commands/fs/show_last_results.py +39 -0
- adam/commands/fs/tail.py +36 -0
- adam/commands/fs/tail_local.py +46 -0
- adam/commands/fs/utils_fs.py +192 -0
- adam/commands/help.py +2 -2
- adam/commands/kubectl.py +2 -2
- adam/commands/medusa/medusa_backup.py +2 -2
- adam/commands/medusa/medusa_restore.py +2 -2
- adam/commands/medusa/medusa_show_backupjobs.py +2 -2
- adam/commands/medusa/medusa_show_restorejobs.py +2 -2
- adam/commands/nodetool/nodetool.py +30 -7
- adam/commands/nodetool/utils_nodetool.py +44 -0
- adam/commands/postgres/postgres.py +3 -6
- adam/commands/postgres/postgres_ls.py +2 -2
- adam/commands/postgres/postgres_preview.py +2 -2
- adam/commands/preview_table.py +2 -3
- adam/commands/reaper/reaper_forward.py +2 -2
- adam/commands/reaper/reaper_forward_stop.py +2 -2
- adam/commands/reaper/reaper_restart.py +2 -2
- adam/commands/reaper/reaper_run_abort.py +2 -2
- adam/commands/reaper/reaper_runs.py +14 -12
- adam/commands/reaper/reaper_runs_abort.py +2 -2
- adam/commands/reaper/reaper_schedule_activate.py +2 -2
- adam/commands/reaper/reaper_schedule_start.py +2 -2
- adam/commands/reaper/reaper_schedule_stop.py +2 -2
- adam/commands/reaper/reaper_schedules.py +2 -2
- adam/commands/reaper/reaper_status.py +2 -2
- adam/commands/reaper/utils_reaper.py +31 -5
- adam/commands/repair/repair_log.py +2 -2
- adam/commands/repair/repair_run.py +2 -2
- adam/commands/repair/repair_scan.py +2 -2
- adam/commands/repair/repair_stop.py +2 -2
- adam/embedded_params.py +1 -1
- adam/repl.py +2 -1
- adam/repl_commands.py +25 -10
- adam/repl_session.py +10 -3
- adam/sql/qingl.lark +58 -59
- adam/utils.py +48 -8
- adam/utils_async_job.py +73 -0
- adam/utils_k8s/cassandra_clusters.py +15 -7
- adam/utils_k8s/cassandra_nodes.py +5 -4
- adam/utils_k8s/pods.py +152 -51
- adam/version.py +1 -1
- {kaqing-2.0.214.dist-info → kaqing-2.0.227.dist-info}/METADATA +1 -1
- kaqing-2.0.227.dist-info/RECORD +280 -0
- kaqing-2.0.214.dist-info/RECORD +0 -272
- {kaqing-2.0.214.dist-info → kaqing-2.0.227.dist-info}/WHEEL +0 -0
- {kaqing-2.0.214.dist-info → kaqing-2.0.227.dist-info}/entry_points.txt +0 -0
- {kaqing-2.0.214.dist-info → kaqing-2.0.227.dist-info}/top_level.txt +0 -0
|
@@ -33,5 +33,5 @@ class RepairStop(Command):
|
|
|
33
33
|
def completion(self, state: ReplState):
|
|
34
34
|
return super().completion(state)
|
|
35
35
|
|
|
36
|
-
def help(self,
|
|
37
|
-
return
|
|
36
|
+
def help(self, state: ReplState):
|
|
37
|
+
return super().help(state, 'delete a repair job')
|
adam/embedded_params.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
def config():
|
|
2
|
-
return {'app': {'console-endpoint': 'https://{host}/{env}/{app}/static/console/index.html', 'container-name': 'c3-server', 'cr': {'cluster-regex': '(.*?-.*?)-.*', 'group': 'ops.c3.ai', 'v': 'v2', 'plural': 'c3cassandras'}, 'label': 'c3__app_id-0', 'login': {'admin-group': '{host}/C3.ClusterAdmin', 'ingress': '{app_id}-k8singr-appleader-001', 'timeout': 5, 'session-check-url': 'https://{host}/{env}/{app}/api/8/C3/userSessionToken', 'cache-creds': True, 'cache-username': True, 'url': 'https://{host}/{env}/{app}', 'another': "You're logged in to {has}. However, for this app, you need to log in to {need}.", 'token-server-url': 'http://localhost:{port}', 'password-max-length': 128}, 'strip': '0'}, 'audit': {'endpoint': 'https://4psvtaxlcb.execute-api.us-west-2.amazonaws.com/prod/', 'workers': 3, 'timeout': 10, 'log-audit-queries': False, 'athena': {'auto-repair': {'elapsed_hours': 12}, 'region': 'us-west-2', 'catalog': 'AwsDataCatalog', 'database': 'audit', 'repair-partition-tables': 'audit', 'output': 's3://s3.ops--audit/ddl/results', 'repair-cluster-tables': 'cluster'}, 'queries': {'last10': "SELECT * FROM audit\nWHERE drive <> 'z' and ({date_condition})\nORDER BY ts DESC LIMIT {limit}", 'slow10': "SELECT * FROM audit\nWHERE drive <> 'z' and ({date_condition})\nORDER BY CAST(duration AS REAL) DESC LIMIT {limit}", 'top10': "SELECT min(c) AS cluster, line, COUNT(*) AS cnt, avg(CAST(duration AS REAL)) AS duration\nFROM audit WHERE drive <> 'z' and ({date_condition})\nGROUP BY line ORDER BY cnt DESC LIMIT {limit}"}}, 'bash': {'workers': 32}, 'cassandra': {'service-name': 'all-pods-service'}, 'cql': {'workers': 32, 'samples': 3, 'secret': {'cluster-regex': '(.*?-.*?)-.*', 'name': '{cluster}-superuser', 'password-item': 'password'}, 'alter-tables': {'excludes': 'system_auth,system_traces,reaper_db,system_distributed,system_views,system,system_schema,system_virtual_schema', 'gc-grace-periods': '3600,86400,864000,7776000', 'batching': True}}, 'checks': {'compactions-threshold': 250, 'cpu-busy-threshold': 98.0, 'cpu-threshold': 0.0, 'cassandra-data-path': '/c3/cassandra', 'root-disk-threshold': 50, 'cassandra-disk-threshold': 50, 'snapshot-size-cmd': "ls /c3/cassandra/data/data/*/*/snapshots | grep snapshots | sed 's/:$//g' | xargs -I {} du -sk {} | awk '{print $1}' | awk '{s+=$1} END {print s}'", 'snapshot-size-threshold': '40G', 'table-sizes-cmd': "ls -Al /c3/cassandra/data/data/ | awk '{print $9}' | sed 's/\\^r//g' | xargs -I {} du -sk /c3/cassandra/data/data/{}"}, 'download': {'workers': 8}, 'export': {'workers': 8, 'csv_dir': '/c3/cassandra/tmp', 'column_counts_query': 'select id, count(id) as columns from {table} group by id order by columns desc limit 10', 'default-importer': 'sqlite', 'sqlite': {'workers': 8, 'columns': '<row-key>', 'local-db-dir': '/tmp/qing-db/q/export/db'}, 'athena': {'workers': 8, 'columns': '<keys>', 'bucket': 'c3.ops--qing'}, 'csv': {'workers': 8, 'columns': '<row-key>'}, 'log-dir': '/tmp/qing-db/q/export/logs'}, 'get-host-id': {'workers': 32}, 'idps': {'ad': {'email-pattern': '.*@c3.ai', 'uri': 'https://login.microsoftonline.com/53ad779a-93e7-485c-ba20-ac8290d7252b/oauth2/v2.0/authorize?response_type=id_token&response_mode=form_post&client_id=00ff94a8-6b0a-4715-98e0-95490012d818&scope=openid+email+profile&redirect_uri=https%3A%2F%2Fplat.c3ci.cloud%2Fc3%2Fc3%2Foidc%2Flogin&nonce={nonce}&state=EMPTY', 'jwks-uri': 'https://login.microsoftonline.com/common/discovery/keys', 'contact': 'Please contact ted.tran@c3.ai.', 'whitelist-file': '/kaqing/members'}, 'okta': {'default': True, 'email-pattern': '.*@c3iot.com', 'uri': 'https://c3energy.okta.com/oauth2/v1/authorize?response_type=id_token&response_mode=form_post&client_id={client_id}&scope=openid+email+profile+groups&redirect_uri=https%3A%2F%2F{host}%2Fc3%2Fc3%2Foidc%2Flogin&nonce={nonce}&state=EMPTY', 'jwks-uri': 'https://c3energy.okta.com/oauth2/v1/keys'}}, 'issues': {'workers': 32}, 'local-qing-dir': '/tmp/qing-db/q', 'local-downloads-dir': '/tmp/qing-db/q/downloads', 'logs': {'path': '/c3/cassandra/logs/system.log'}, 'log-dir': '/tmp/qing-db/q/logs', 'nodetool': {'workers': 96, 'commands_in_line': 40, 'status': {'workers': 32, 'samples': 3, 'commands_in_line': 40}}, 'pg': {'name-pattern': '^{namespace}.*-k8spg-.*', 'excludes': '.helm., -admin-secret', 'agent': {'name': 'ops-pg-agent', 'just-in-time': False, 'timeout': 86400, 'image': 'seanahnsf/kaqing'}, 'default-db': 'postgres', 'default-schema': 'postgres', 'secret': {'endpoint-key': 'postgres-db-endpoint', 'port-key': 'postgres-db-port', 'username-key': 'postgres-admin-username', 'password-key': 'postgres-admin-password'}}, 'pod': {'name': 'ops', 'image': 'seanahnsf/kaqing-cloud', 'sa': {'name': 'ops', 'proto': 'c3', 'additional-cluster-roles': 'c3aiops-k8ssandra-operator'}, 'label-selector': 'run=ops'}, 'preview': {'rows': 10}, 'processes': {'columns': 'pod,cpu-metrics,mem', 'header': 'POD_NAME,M_CPU(USAGE/LIMIT),MEM/LIMIT'}, 'processes-
|
|
2
|
+
return {'app': {'console-endpoint': 'https://{host}/{env}/{app}/static/console/index.html', 'container-name': 'c3-server', 'cr': {'cluster-regex': '(.*?-.*?)-.*', 'group': 'ops.c3.ai', 'v': 'v2', 'plural': 'c3cassandras'}, 'label': 'c3__app_id-0', 'login': {'admin-group': '{host}/C3.ClusterAdmin', 'ingress': '{app_id}-k8singr-appleader-001', 'timeout': 5, 'session-check-url': 'https://{host}/{env}/{app}/api/8/C3/userSessionToken', 'cache-creds': True, 'cache-username': True, 'url': 'https://{host}/{env}/{app}', 'another': "You're logged in to {has}. However, for this app, you need to log in to {need}.", 'token-server-url': 'http://localhost:{port}', 'password-max-length': 128}, 'strip': '0'}, 'audit': {'endpoint': 'https://4psvtaxlcb.execute-api.us-west-2.amazonaws.com/prod/', 'workers': 3, 'timeout': 10, 'log-audit-queries': False, 'athena': {'auto-repair': {'elapsed_hours': 12}, 'region': 'us-west-2', 'catalog': 'AwsDataCatalog', 'database': 'audit', 'repair-partition-tables': 'audit', 'output': 's3://s3.ops--audit/ddl/results', 'repair-cluster-tables': 'cluster'}, 'queries': {'last10': "SELECT * FROM audit\nWHERE drive <> 'z' and ({date_condition})\nORDER BY ts DESC LIMIT {limit}", 'slow10': "SELECT * FROM audit\nWHERE drive <> 'z' and ({date_condition})\nORDER BY CAST(duration AS REAL) DESC LIMIT {limit}", 'top10': "SELECT min(c) AS cluster, line, COUNT(*) AS cnt, avg(CAST(duration AS REAL)) AS duration\nFROM audit WHERE drive <> 'z' and ({date_condition})\nGROUP BY line ORDER BY cnt DESC LIMIT {limit}"}}, 'bash': {'workers': 32}, 'cassandra': {'service-name': 'all-pods-service'}, 'cql': {'workers': 32, 'samples': 3, 'secret': {'cluster-regex': '(.*?-.*?)-.*', 'name': '{cluster}-superuser', 'password-item': 'password'}, 'alter-tables': {'excludes': 'system_auth,system_traces,reaper_db,system_distributed,system_views,system,system_schema,system_virtual_schema', 'gc-grace-periods': '3600,86400,864000,7776000', 'batching': True}}, 'checks': {'compactions-threshold': 250, 'cpu-busy-threshold': 98.0, 'cpu-threshold': 0.0, 'cassandra-data-path': '/c3/cassandra', 'root-disk-threshold': 50, 'cassandra-disk-threshold': 50, 'snapshot-size-cmd': "ls /c3/cassandra/data/data/*/*/snapshots | grep snapshots | sed 's/:$//g' | xargs -I {} du -sk {} | awk '{print $1}' | awk '{s+=$1} END {print s}'", 'snapshot-size-threshold': '40G', 'table-sizes-cmd': "ls -Al /c3/cassandra/data/data/ | awk '{print $9}' | sed 's/\\^r//g' | xargs -I {} du -sk /c3/cassandra/data/data/{}"}, 'download': {'workers': 8}, 'export': {'workers': 8, 'csv_dir': '/c3/cassandra/tmp', 'column_counts_query': 'select id, count(id) as columns from {table} group by id order by columns desc limit 10', 'default-importer': 'sqlite', 'sqlite': {'workers': 8, 'columns': '<row-key>', 'local-db-dir': '/tmp/qing-db/q/export/db'}, 'athena': {'workers': 8, 'columns': '<keys>', 'bucket': 'c3.ops--qing'}, 'csv': {'workers': 8, 'columns': '<row-key>'}, 'log-dir': '/tmp/qing-db/q/export/logs', 'remote': {'log-dir': '/tmp/q/export/logs'}}, '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}, 'job': {'log-to-pods': True}, 'local-qing-dir': '/tmp/qing-db/q', 'local-downloads-dir': '/tmp/qing-db/q/downloads', 'logs': {'path': '/c3/cassandra/logs/system.log'}, 'log-dir': '/tmp/qing-db/q/logs', 'nodetool': {'workers': 96, 'commands_in_line': 40, 'grace-period-after-abort': 10, 'status': {'workers': 32, 'samples': 3, 'commands_in_line': 40}}, 'pg': {'name-pattern': '^{namespace}.*-k8spg-.*', 'excludes': '.helm., -admin-secret', 'agent': {'name': 'ops-pg-agent', 'just-in-time': False, 'timeout': 86400, 'image': 'seanahnsf/kaqing'}, 'default-db': 'postgres', 'default-schema': 'postgres', 'secret': {'endpoint-key': 'postgres-db-endpoint', 'port-key': 'postgres-db-port', 'username-key': 'postgres-admin-username', 'password-key': 'postgres-admin-password'}}, 'pod': {'name': 'ops', 'image': 'seanahnsf/kaqing-cloud', 'sa': {'name': 'ops', 'proto': 'c3', 'additional-cluster-roles': 'c3aiops-k8ssandra-operator'}, 'label-selector': 'run=ops'}, 'preview': {'rows': 10}, 'processes': {'columns': 'pod,cpu-metrics,mem', 'header': 'POD_NAME,M_CPU(USAGE/LIMIT),MEM/LIMIT'}, 'processes-mpstat': {'columns': 'pod,cpu,mem', 'header': 'POD_NAME,Q_CPU/TOTAL,MEM/LIMIT'}, 'reaper': {'service-name': 'reaper-service', 'port-forward': {'timeout': 86400, 'local-port': 9001}, 'abort-runs-batch': 10, 'show-runs-batch': 100, 'pod': {'cluster-regex': '(.*?-.*?-.*?-.*?)-.*', 'label-selector': 'k8ssandra.io/reaper={cluster}-reaper'}, 'secret': {'cluster-regex': '(.*?-.*?)-.*', 'name': '{cluster}-reaper-ui', 'password-item': 'password'}}, 'repair': {'log-path': '/home/cassrepair/logs/', 'image': 'ci-registry.c3iot.io/cloudops/cassrepair:2.0.14', 'secret': 'ciregistryc3iotio', 'env': {'interval': 24, 'timeout': 60, 'pr': False, 'runs': 1}}, 'repl': {'start-drive': 'c', 'a': {'auto-enter': 'c3/c3'}, 'c': {'auto-enter': 'cluster'}, 'x': {'auto-enter': 'latest'}, 'history': {'push-cat-log-file': True, 'push-cat-remote-log-file': True}, 'background-process': {'auto-nohup': True}}, 'status': {'columns': 'status,address,load,tokens,owns,host_id,gossip,compactions', 'header': '--,Address,Load,Tokens,Owns,Host ID,GOSSIP,COMPACTIONS'}, 'storage': {'columns': 'pod,volume_root,volume_cassandra,snapshots,data,compactions', 'header': 'POD_NAME,VOLUME /,VOLUME CASS,SNAPSHOTS,DATA,COMPACTIONS'}, 'watch': {'auto': 'rollout', 'timeout': 3600, 'interval': 10}, 'auto-complete': {'c': {'tables': 'lazy', 'table-props-value': 'jit'}, 'x': {'tables': 'lazy'}, 'cli': {'cp': 'jit'}, 'export': {'databases': 'jit'}, 'medusa': {'backups': 'jit'}, 'reaper': {'schedules': 'jit'}}, 'debug': False, 'debugs': {'complete': False, 'timings': False, 'exit-on-error': False}}
|
adam/repl.py
CHANGED
|
@@ -3,6 +3,7 @@ import time
|
|
|
3
3
|
from typing import cast
|
|
4
4
|
import click
|
|
5
5
|
from prompt_toolkit.key_binding import KeyBindings
|
|
6
|
+
from prompt_toolkit import HTML
|
|
6
7
|
|
|
7
8
|
from adam.cli_group import cli
|
|
8
9
|
from adam.commands.command import Command, InvalidArgumentsException, InvalidStateException
|
|
@@ -81,7 +82,7 @@ def enter_repl(state: ReplState):
|
|
|
81
82
|
# print(json.dumps(completions, indent=4))
|
|
82
83
|
completer = ReplCompleter.from_nested_dict(completions)
|
|
83
84
|
|
|
84
|
-
cmd = session.prompt(prompt_msg(), completer=completer, key_bindings=kb)
|
|
85
|
+
cmd = session.prompt(HTML(f'<ansibrightblue>{prompt_msg()}</ansibrightblue>'), completer=completer, key_bindings=kb)
|
|
85
86
|
s0 = time.time()
|
|
86
87
|
|
|
87
88
|
if state.bash_session:
|
adam/repl_commands.py
CHANGED
|
@@ -61,8 +61,13 @@ from adam.commands.export.show_export_sessions import ShowExportSessions
|
|
|
61
61
|
from adam.commands.fs.find_files import FindLocalFiles
|
|
62
62
|
from adam.commands.fs.find_processes import FindProcesses
|
|
63
63
|
from adam.commands.fs.head import Head
|
|
64
|
+
from adam.commands.fs.head_local import HeadLocal
|
|
64
65
|
from adam.commands.fs.ls_local import LsLocal
|
|
65
66
|
from adam.commands.fs.rm import RmLocal
|
|
67
|
+
from adam.commands.fs.rm_logs import RmLogs
|
|
68
|
+
from adam.commands.fs.show_last_results import ShowLastResults
|
|
69
|
+
from adam.commands.fs.tail import Tail
|
|
70
|
+
from adam.commands.fs.tail_local import TailLocal
|
|
66
71
|
from adam.commands.kubectl import Kubectl
|
|
67
72
|
from adam.commands.fs.shell import Shell
|
|
68
73
|
from adam.commands.bash.bash import Bash
|
|
@@ -107,18 +112,28 @@ class ReplCommands:
|
|
|
107
112
|
return deduped
|
|
108
113
|
|
|
109
114
|
def navigation() -> list[Command]:
|
|
110
|
-
return [
|
|
111
|
-
|
|
112
|
-
|
|
115
|
+
return [Cd(), Cat(), CatLocal(), ClipboardCopy(),
|
|
116
|
+
DeviceApp(), DevicePostgres(), DeviceCass(), DeviceAuditLog(), DeviceExport(),
|
|
117
|
+
DownloadFile(), FindLocalFiles(), FindProcesses(), GetParam(),
|
|
118
|
+
Head(), HeadLocal(), Ls(), LsLocal(), PreviewTable(), Pwd(), RmLogs(),
|
|
119
|
+
SetParam(), ShowAdam(), ShowHost(), ShowKubectlCommands(), ShowLastResults(),
|
|
120
|
+
ShowLogin(), ShowOffloadedCompletes(), ShowParams(),
|
|
121
|
+
Tail(), TailLocal()] + \
|
|
122
|
+
RmLocal().cmd_list()
|
|
113
123
|
|
|
114
124
|
def cassandra_ops() -> list[Command]:
|
|
115
|
-
return [
|
|
116
|
-
|
|
117
|
-
ExportTables(), ExportXSelect(), ExportUse(),
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
125
|
+
return [AlterTables(), Bash(), Check(), CleanUpExportSessions(), CleanUpAllExportSessions(), Cqlsh(),
|
|
126
|
+
DownloadCassandraLog(), DropExportDatabase(), DropExportDatabases(), DownloadExportSession(),
|
|
127
|
+
ExportTables(), ExportXSelect(), ExportUse(),
|
|
128
|
+
GenerateReport(), ImportSession(), ImportCSVFiles(), Issues(), NodeTool(),
|
|
129
|
+
RestartNodes(), RestartNode(), RestartCluster(), RollOut(),
|
|
130
|
+
ShowCassandraStatus(), ShowCassandraVersion(), ShowCassandraRepairs(), ShowColumnCounts(),
|
|
131
|
+
ShowStorage(), ShowExportDatabases(), ShowExportSessions(), ShowExportSession(), ShowProcesses(),
|
|
132
|
+
Watch()] + \
|
|
133
|
+
Debug().cmd_list() + \
|
|
134
|
+
Medusa().cmd_list() + \
|
|
135
|
+
Reaper().cmd_list() + \
|
|
136
|
+
Repair().cmd_list()
|
|
122
137
|
|
|
123
138
|
def postgres_ops() -> list[Command]:
|
|
124
139
|
return [Postgres(), DeployPgAgent(), UndeployPgAgent(), PostgresPg()]
|
adam/repl_session.py
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
from typing import Union
|
|
1
2
|
from prompt_toolkit import PromptSession
|
|
2
3
|
from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
|
|
3
4
|
|
|
4
5
|
from adam.config import Config
|
|
5
|
-
from adam.utils import ConfigHolder
|
|
6
|
+
from adam.utils import ConfigHolder, LogFile
|
|
6
7
|
|
|
7
8
|
class ReplSession:
|
|
8
9
|
# the singleton pattern
|
|
@@ -16,6 +17,12 @@ class ReplSession:
|
|
|
16
17
|
self.prompt_session = PromptSession(auto_suggest=AutoSuggestFromHistory())
|
|
17
18
|
ConfigHolder().append_command_history = self.append_history
|
|
18
19
|
|
|
19
|
-
def append_history(self, entry: str):
|
|
20
|
-
if entry
|
|
20
|
+
def append_history(self, entry: Union[str, LogFile]):
|
|
21
|
+
if not entry:
|
|
22
|
+
return
|
|
23
|
+
|
|
24
|
+
if self.prompt_session and Config().get('repl.history.push-cat-remote-log-file', True):
|
|
25
|
+
if isinstance(entry, LogFile):
|
|
26
|
+
entry = entry.to_command()
|
|
27
|
+
|
|
21
28
|
self.prompt_session.history.append_string(entry)
|
adam/sql/qingl.lark
CHANGED
|
@@ -4,19 +4,18 @@ start: statement_sequence
|
|
|
4
4
|
WHITESPACE: (" " | /\t/ | /\n/ | /\r/ )+
|
|
5
5
|
%ignore WHITESPACE
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
|
12
|
-
|
|
|
13
|
-
|
|
|
14
|
-
| utility_statement
|
|
7
|
+
statement_sequence: statement ( ";" statement )* ";"?
|
|
8
|
+
|
|
9
|
+
statement: dcl_statement "&"?
|
|
10
|
+
| ddl_statement "&"?
|
|
11
|
+
| dml_statement "&"?
|
|
12
|
+
| dql_statement "&"?
|
|
13
|
+
# | utility_statement "&"?
|
|
15
14
|
| qing_statement
|
|
16
15
|
|
|
17
16
|
ddl_statement: create_statement
|
|
18
17
|
| drop_statement
|
|
19
|
-
| other_statement
|
|
18
|
+
# | other_statement
|
|
20
19
|
|
|
21
20
|
# --------------------- SEAN added -------------------
|
|
22
21
|
|
|
@@ -27,8 +26,8 @@ host_name: IDENTIFIER
|
|
|
27
26
|
|
|
28
27
|
# --------------------- p: -------------------
|
|
29
28
|
|
|
30
|
-
qing_p_statement: preview_table_statement
|
|
31
|
-
| alter_table_statement
|
|
29
|
+
qing_p_statement: preview_table_statement "&"?
|
|
30
|
+
| alter_table_statement "&"?
|
|
32
31
|
|
|
33
32
|
preview_table_statement: "PREVIEW"i path
|
|
34
33
|
alter_table_statement: "ALTER"i "TABLE"i keyspace_ref (add_column_action | drop_column_action | modify_column_action | rename_table_action | add_constraint_action)
|
|
@@ -50,11 +49,11 @@ column_name_list: column_name ("," column_name)*
|
|
|
50
49
|
|
|
51
50
|
# --------------------- c: -------------------
|
|
52
51
|
|
|
53
|
-
qing_c_statement: preview_table_statement
|
|
54
|
-
| alter_cql_table_statement
|
|
55
|
-
| alter_tables_statement
|
|
56
|
-
| describe_statement
|
|
57
|
-
| consistency_statement
|
|
52
|
+
qing_c_statement: preview_table_statement "&"?
|
|
53
|
+
| alter_cql_table_statement "&"?
|
|
54
|
+
| alter_tables_statement "&"?
|
|
55
|
+
| describe_statement "&"?
|
|
56
|
+
| consistency_statement "&"?
|
|
58
57
|
| drop_export_db_statement
|
|
59
58
|
| use_export_db_statement
|
|
60
59
|
| "SHOW"i show_c_subcommand
|
|
@@ -117,9 +116,9 @@ download_session_statement: "DOWNLOAD"i "EXPORT"i "SESSION"i export_session_name
|
|
|
117
116
|
|
|
118
117
|
# --------------------- l: -------------------
|
|
119
118
|
|
|
120
|
-
qing_l_statement: preview_table_statement
|
|
121
|
-
| alter_athena_table_statement
|
|
122
|
-
| describe_table_statement
|
|
119
|
+
qing_l_statement: preview_table_statement "&"?
|
|
120
|
+
| alter_athena_table_statement "&"?
|
|
121
|
+
| describe_table_statement "&"?
|
|
123
122
|
| "AUDIT"i ("REPAIR"i | "RUN"i)?
|
|
124
123
|
| show_topn_statement
|
|
125
124
|
|
|
@@ -139,8 +138,8 @@ topn_window: IDENTIFIER
|
|
|
139
138
|
|
|
140
139
|
# --------------------- x: -------------------
|
|
141
140
|
|
|
142
|
-
qing_x_statement: preview_table_statement
|
|
143
|
-
| describe_table_statement
|
|
141
|
+
qing_x_statement: preview_table_statement "&"?
|
|
142
|
+
| describe_table_statement "&"?
|
|
144
143
|
| drop_export_db_statement
|
|
145
144
|
|
|
146
145
|
qing_x0_statement: drop_export_db_statement
|
|
@@ -162,9 +161,9 @@ drop_statement: drop_scope
|
|
|
162
161
|
| drop_index
|
|
163
162
|
| drop_function
|
|
164
163
|
|
|
165
|
-
other_statement: alter_index
|
|
166
|
-
| build_index
|
|
167
|
-
| execute_function
|
|
164
|
+
# other_statement: alter_index
|
|
165
|
+
# | build_index
|
|
166
|
+
# | execute_function
|
|
168
167
|
|
|
169
168
|
create_scope: "CREATE"i "SCOPE"i ( namespace_ref ":" )? bucket_ref "." scope_ref if_not_exists?
|
|
170
169
|
|
|
@@ -219,10 +218,10 @@ index_partition: "PARTITION"i "BY"i "HASH"i LPAREN partition_key_expr \
|
|
|
219
218
|
|
|
220
219
|
partition_key_expr: expr
|
|
221
220
|
|
|
222
|
-
alter_index: "ALTER"i "INDEX"i ( ( index_path "." index_name ) | ( index_name "ON"i keyspace_ref ) \
|
|
223
|
-
index_using? index_with )
|
|
221
|
+
# alter_index: "ALTER"i "INDEX"i ( ( index_path "." index_name ) | ( index_name "ON"i keyspace_ref ) \
|
|
222
|
+
# index_using? index_with )
|
|
224
223
|
|
|
225
|
-
build_index: "BUILD"i "INDEX"i "ON"i keyspace_ref LPAREN index_term ( "," index_term )* RPAREN index_using?
|
|
224
|
+
# build_index: "BUILD"i "INDEX"i "ON"i keyspace_ref LPAREN index_term ( "," index_term )* RPAREN index_using?
|
|
226
225
|
|
|
227
226
|
index_term: index_name | subquery_expr
|
|
228
227
|
|
|
@@ -283,11 +282,11 @@ sequence_with: "WITH"i expr
|
|
|
283
282
|
|
|
284
283
|
drop_function: "DROP"i "FUNCTION"i function_ref if_exists?
|
|
285
284
|
|
|
286
|
-
execute_function: "EXECUTE"i "FUNCTION"i function_ref LPAREN ( expr ( "," expr )* )? RPAREN
|
|
285
|
+
# execute_function: "EXECUTE"i "FUNCTION"i function_ref LPAREN ( expr ( "," expr )* )? RPAREN
|
|
287
286
|
|
|
288
287
|
dml_statement: delete_statement
|
|
289
288
|
| insert_statement
|
|
290
|
-
| merge_statement
|
|
289
|
+
# | merge_statement
|
|
291
290
|
| update_statement
|
|
292
291
|
| upsert_statement
|
|
293
292
|
|
|
@@ -307,44 +306,44 @@ insert_select: LPAREN "PRIMARY"i? "KEY"i key_expr ( "," "VALUE"i value_expr )? \
|
|
|
307
306
|
|
|
308
307
|
options: obj
|
|
309
308
|
|
|
310
|
-
merge_statement: "MERGE"i "INTO"i ( ansi_merge | lookup_merge ) limit_clause? returning_clause?
|
|
309
|
+
# merge_statement: "MERGE"i "INTO"i ( ansi_merge | lookup_merge ) limit_clause? returning_clause?
|
|
311
310
|
|
|
312
|
-
ansi_merge: target_keyspace use_index_clause "USING"i ansi_merge_source \
|
|
313
|
-
ansi_merge_predicate ansi_merge_actions
|
|
311
|
+
# ansi_merge: target_keyspace use_index_clause "USING"i ansi_merge_source \
|
|
312
|
+
# ansi_merge_predicate ansi_merge_actions
|
|
314
313
|
|
|
315
|
-
ansi_merge_source: ( merge_source_keyspace | merge_source_subquery | merge_source_expr ) \
|
|
316
|
-
ansi_join_hints?
|
|
314
|
+
# ansi_merge_source: ( merge_source_keyspace | merge_source_subquery | merge_source_expr ) \
|
|
315
|
+
# ansi_join_hints?
|
|
317
316
|
|
|
318
|
-
ansi_merge_predicate: "ON"i expr
|
|
317
|
+
# ansi_merge_predicate: "ON"i expr
|
|
319
318
|
|
|
320
|
-
ansi_merge_actions: merge_update? merge_delete? ansi_merge_insert?
|
|
319
|
+
# ansi_merge_actions: merge_update? merge_delete? ansi_merge_insert?
|
|
321
320
|
|
|
322
|
-
ansi_merge_insert: "WHEN"i "NOT"i "MATCHED"i "THEN"i "INSERT"i LPAREN "KEY"i? key_expr \
|
|
323
|
-
( "," "VALUE"i? value_expr )? ( "," "OPTIONS"i? options )? RPAREN where_clause?
|
|
321
|
+
# ansi_merge_insert: "WHEN"i "NOT"i "MATCHED"i "THEN"i "INSERT"i LPAREN "KEY"i? key_expr \
|
|
322
|
+
# ( "," "VALUE"i? value_expr )? ( "," "OPTIONS"i? options )? RPAREN where_clause?
|
|
324
323
|
|
|
325
324
|
|
|
326
|
-
lookup_merge: target_keyspace "USING"i lookup_merge_source lookup_merge_predicate \
|
|
327
|
-
lookup_merge_actions
|
|
325
|
+
# lookup_merge: target_keyspace "USING"i lookup_merge_source lookup_merge_predicate \
|
|
326
|
+
# lookup_merge_actions
|
|
328
327
|
|
|
329
|
-
lookup_merge_source: ( merge_source_keyspace use_clause? )
|
|
330
|
-
| merge_source_subquery
|
|
331
|
-
| merge_source_expr
|
|
328
|
+
# lookup_merge_source: ( merge_source_keyspace use_clause? )
|
|
329
|
+
# | merge_source_subquery
|
|
330
|
+
# | merge_source_expr
|
|
332
331
|
|
|
333
|
-
lookup_merge_predicate: "ON"i "PRIMARY"i? "KEY"i expr
|
|
332
|
+
# lookup_merge_predicate: "ON"i "PRIMARY"i? "KEY"i expr
|
|
334
333
|
|
|
335
|
-
lookup_merge_actions: merge_update? merge_delete? lookup_merge_insert?
|
|
334
|
+
# lookup_merge_actions: merge_update? merge_delete? lookup_merge_insert?
|
|
336
335
|
|
|
337
|
-
lookup_merge_insert: "WHEN"i "NOT"i "MATCHED"i "THEN"i "INSERT"i expr where_clause?
|
|
336
|
+
# lookup_merge_insert: "WHEN"i "NOT"i "MATCHED"i "THEN"i "INSERT"i expr where_clause?
|
|
338
337
|
|
|
339
|
-
merge_source_keyspace: keyspace_ref ( "AS"i? alias )?
|
|
338
|
+
# merge_source_keyspace: keyspace_ref ( "AS"i? alias )?
|
|
340
339
|
|
|
341
|
-
merge_source_subquery: subquery_expr "AS"i? alias
|
|
340
|
+
# merge_source_subquery: subquery_expr "AS"i? alias
|
|
342
341
|
|
|
343
|
-
merge_source_expr: expr ( "AS"i? alias )?
|
|
342
|
+
# merge_source_expr: expr ( "AS"i? alias )?
|
|
344
343
|
|
|
345
|
-
merge_update: "WHEN"i "MATCHED"i "THEN"i "UPDATE"i set_clause? unset_clause? where_clause?
|
|
344
|
+
# merge_update: "WHEN"i "MATCHED"i "THEN"i "UPDATE"i set_clause? unset_clause? where_clause?
|
|
346
345
|
|
|
347
|
-
merge_delete: "WHEN"i "MATCHED"i "THEN"i "DELETE"i where_clause?
|
|
346
|
+
# merge_delete: "WHEN"i "MATCHED"i "THEN"i "DELETE"i where_clause?
|
|
348
347
|
|
|
349
348
|
update_statement: "UPDATE"i target_keyspace use_keys_clause? set_clause? unset_clause? \
|
|
350
349
|
where_clause? limit_clause? returning_clause?
|
|
@@ -373,7 +372,7 @@ key_expr: expr
|
|
|
373
372
|
value_expr: expr
|
|
374
373
|
|
|
375
374
|
dql_statement: select_statement
|
|
376
|
-
| infer_statement
|
|
375
|
+
# | infer_statement
|
|
377
376
|
| update_statistics
|
|
378
377
|
|
|
379
378
|
select_statement: select_term ( set_op select_term )* order_by_clause? limit_clause? offset_clause?
|
|
@@ -1006,16 +1005,16 @@ commit_transaction: "COMMIT"i ( "WORK"i | "TRAN"i | "TRANSACTION"i )?
|
|
|
1006
1005
|
|
|
1007
1006
|
savepointname: identifier_ref
|
|
1008
1007
|
|
|
1009
|
-
utility_statement: advise_statement | explain_statement
|
|
1008
|
+
# utility_statement: advise_statement | explain_statement
|
|
1010
1009
|
|
|
1011
|
-
advise_statement: "ADVISE"i "INDEX"i? ( select_statement
|
|
1012
|
-
| update_statement
|
|
1013
|
-
| delete_statement
|
|
1014
|
-
| merge_statement )
|
|
1010
|
+
# advise_statement: "ADVISE"i "INDEX"i? ( select_statement
|
|
1011
|
+
# | update_statement
|
|
1012
|
+
# | delete_statement
|
|
1013
|
+
# | merge_statement )
|
|
1015
1014
|
|
|
1016
|
-
explain_statement: "INFER"i ( "COLLECTION"i | "KEYSPACE"i )? keyspace_ref ( "WITH"i options )?
|
|
1015
|
+
# explain_statement: "INFER"i ( "COLLECTION"i | "KEYSPACE"i )? keyspace_ref ( "WITH"i options )?
|
|
1017
1016
|
|
|
1018
|
-
infer_statement: "INFER"i ( "COLLECTION"i | "KEYSPACE"i )? keyspace_ref ( "WITH"i options )?
|
|
1017
|
+
# infer_statement: "INFER"i ( "COLLECTION"i | "KEYSPACE"i )? keyspace_ref ( "WITH"i options )?
|
|
1019
1018
|
|
|
1020
1019
|
name: identifier_ref
|
|
1021
1020
|
|
adam/utils.py
CHANGED
|
@@ -4,22 +4,23 @@ from contextlib import redirect_stdout
|
|
|
4
4
|
import copy
|
|
5
5
|
import csv
|
|
6
6
|
from datetime import datetime
|
|
7
|
+
import html
|
|
7
8
|
import importlib
|
|
8
9
|
import io
|
|
9
|
-
import json
|
|
10
10
|
import os
|
|
11
11
|
from pathlib import Path
|
|
12
12
|
import random
|
|
13
13
|
import string
|
|
14
14
|
import threading
|
|
15
15
|
import traceback
|
|
16
|
-
from typing import Callable, Iterator,
|
|
16
|
+
from typing import Callable, Iterator, TypeVar, Union
|
|
17
17
|
from dateutil import parser
|
|
18
18
|
import subprocess
|
|
19
19
|
import sys
|
|
20
20
|
import time
|
|
21
21
|
import click
|
|
22
22
|
import yaml
|
|
23
|
+
from prompt_toolkit import print_formatted_text, HTML
|
|
23
24
|
from prompt_toolkit.completion import Completer
|
|
24
25
|
|
|
25
26
|
from . import __version__
|
|
@@ -28,6 +29,9 @@ T = TypeVar('T')
|
|
|
28
29
|
|
|
29
30
|
log_state = threading.local()
|
|
30
31
|
|
|
32
|
+
class Color:
|
|
33
|
+
gray = 'gray'
|
|
34
|
+
|
|
31
35
|
class ConfigReadable:
|
|
32
36
|
def is_debug() -> bool:
|
|
33
37
|
pass
|
|
@@ -117,19 +121,21 @@ def convert_seconds(total_seconds_float):
|
|
|
117
121
|
def epoch(timestamp_string: str):
|
|
118
122
|
return parser.parse(timestamp_string).timestamp()
|
|
119
123
|
|
|
120
|
-
def log(s = None):
|
|
124
|
+
def log(s = None, text_color: str = None):
|
|
121
125
|
if not loggable():
|
|
122
126
|
return False
|
|
123
127
|
|
|
124
128
|
# want to print empty line for False or empty collection
|
|
125
129
|
if s == None:
|
|
126
130
|
print()
|
|
131
|
+
elif text_color:
|
|
132
|
+
print_formatted_text(HTML(f'<ansi{text_color}>{html.escape(s)}</ansi{text_color}>'))
|
|
127
133
|
else:
|
|
128
134
|
click.echo(s)
|
|
129
135
|
|
|
130
136
|
return True
|
|
131
137
|
|
|
132
|
-
def log2(s = None, nl = True, file: str = None):
|
|
138
|
+
def log2(s = None, nl = True, file: str = None, text_color: str = None):
|
|
133
139
|
if not loggable():
|
|
134
140
|
return False
|
|
135
141
|
|
|
@@ -139,12 +145,16 @@ def log2(s = None, nl = True, file: str = None):
|
|
|
139
145
|
f.write(s)
|
|
140
146
|
if nl:
|
|
141
147
|
f.write('\n')
|
|
148
|
+
elif text_color:
|
|
149
|
+
print_formatted_text(HTML(f'<ansi{text_color}>{html.escape(s)}</ansi{text_color}>'))
|
|
142
150
|
else:
|
|
143
151
|
click.echo(s, err=True, nl=nl)
|
|
144
152
|
else:
|
|
145
153
|
if file:
|
|
146
154
|
with open(file, 'at') as f:
|
|
147
155
|
f.write('\n')
|
|
156
|
+
elif text_color:
|
|
157
|
+
print_formatted_text(HTML(f'<ansi{text_color}>{html.escape(s)}</ansi{text_color}>'), file=sys.stderr)
|
|
148
158
|
else:
|
|
149
159
|
print(file=sys.stderr)
|
|
150
160
|
|
|
@@ -304,15 +314,14 @@ def is_lambda(func):
|
|
|
304
314
|
|
|
305
315
|
def debug(s = None):
|
|
306
316
|
if ConfigHolder().config.is_debug():
|
|
307
|
-
log2(f'DEBUG {s}')
|
|
317
|
+
log2(f'DEBUG {s}', text_color=Color.gray)
|
|
308
318
|
|
|
309
319
|
def debug_complete(s = None):
|
|
310
320
|
CommandLog.log(f'DEBUG {s}', config=ConfigHolder().config.get('debugs.complete', 'off'))
|
|
311
321
|
|
|
312
322
|
def debug_trace():
|
|
313
323
|
if ConfigHolder().config.is_debug():
|
|
314
|
-
|
|
315
|
-
log2(traceback.format_exc())
|
|
324
|
+
log2(traceback.format_exc(), text_color=Color.gray)
|
|
316
325
|
|
|
317
326
|
def in_docker() -> bool:
|
|
318
327
|
if os.path.exists('/.dockerenv'):
|
|
@@ -809,6 +818,12 @@ def kaqing_log_file_name(suffix = 'log'):
|
|
|
809
818
|
def log_dir():
|
|
810
819
|
return creating_dir(ConfigHolder().config.get('log-dir', '/tmp/qing-db/q/logs'))
|
|
811
820
|
|
|
821
|
+
def log_to_pods():
|
|
822
|
+
return ConfigHolder().config.get('job.log-to-pods', True)
|
|
823
|
+
|
|
824
|
+
def pod_log_dir():
|
|
825
|
+
return ConfigHolder().config.get('pod-log-dir', '/tmp/q/logs')
|
|
826
|
+
|
|
812
827
|
class LogFileHandler:
|
|
813
828
|
def __init__(self, suffix = 'log', condition=True):
|
|
814
829
|
self.suffix = suffix
|
|
@@ -850,7 +865,7 @@ class CommandLog:
|
|
|
850
865
|
except:
|
|
851
866
|
pass
|
|
852
867
|
elif config == 'on':
|
|
853
|
-
log2(line)
|
|
868
|
+
log2(line, text_color=Color.gray)
|
|
854
869
|
|
|
855
870
|
def close_log_file():
|
|
856
871
|
if CommandLog.log_file:
|
|
@@ -880,3 +895,28 @@ def creating_dir(dir):
|
|
|
880
895
|
os.makedirs(dir, exist_ok=True)
|
|
881
896
|
|
|
882
897
|
return dir
|
|
898
|
+
|
|
899
|
+
class LogFile(str):
|
|
900
|
+
def __init__(self, s: str):
|
|
901
|
+
super().__init__()
|
|
902
|
+
|
|
903
|
+
def __repr__(self):
|
|
904
|
+
return super().__repr__()
|
|
905
|
+
|
|
906
|
+
def to_command(self, cmd: str = ':tail'):
|
|
907
|
+
return f'{cmd} {self}'
|
|
908
|
+
|
|
909
|
+
class PodLogFile(LogFile):
|
|
910
|
+
def __new__(cls, value, pod: str, size: str = None):
|
|
911
|
+
return super().__new__(cls, value)
|
|
912
|
+
|
|
913
|
+
def __init__(self, value, pod: str, size: str = None):
|
|
914
|
+
super().__init__(value)
|
|
915
|
+
self.pod = pod
|
|
916
|
+
self.size = size
|
|
917
|
+
|
|
918
|
+
def __repr__(self):
|
|
919
|
+
return super().__repr__()
|
|
920
|
+
|
|
921
|
+
def to_command(self, cmd: str = 'tail'):
|
|
922
|
+
return f'@{self.pod} {cmd} {self}'
|
adam/utils_async_job.py
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
import re
|
|
3
|
+
import traceback
|
|
4
|
+
|
|
5
|
+
from adam.utils import log_dir
|
|
6
|
+
|
|
7
|
+
class AsyncJobs:
|
|
8
|
+
_last_id: str = None
|
|
9
|
+
_last_command: str = None
|
|
10
|
+
|
|
11
|
+
def log_file(command: str, pod_name: str = None, job_id: str = None, pod_suffix: str = None, err = False, dir: str = None):
|
|
12
|
+
try:
|
|
13
|
+
if not job_id:
|
|
14
|
+
job_id = AsyncJobs.new_id()
|
|
15
|
+
|
|
16
|
+
AsyncJobs._last_id = job_id
|
|
17
|
+
AsyncJobs._last_command = command
|
|
18
|
+
|
|
19
|
+
AsyncJobs.write_last_command(job_id, command)
|
|
20
|
+
|
|
21
|
+
cmd_name = ''
|
|
22
|
+
if command.startswith('nodetool '):
|
|
23
|
+
command = command.strip(' &')
|
|
24
|
+
cmd_name = f".{'_'.join(command.split(' ')[5:])}"
|
|
25
|
+
|
|
26
|
+
if pod_suffix is None:
|
|
27
|
+
pod_suffix = '{pod}'
|
|
28
|
+
if pod_name:
|
|
29
|
+
pod_suffix = pod_name
|
|
30
|
+
if groups := re.match(r'.*-(.*)', pod_name):
|
|
31
|
+
pod_suffix = f'-{groups[1]}'
|
|
32
|
+
|
|
33
|
+
if not dir:
|
|
34
|
+
dir = log_dir()
|
|
35
|
+
|
|
36
|
+
return f'{dir}/{job_id}{cmd_name}{pod_suffix}.{"err" if err else "log"}'
|
|
37
|
+
except:
|
|
38
|
+
traceback.print_exc()
|
|
39
|
+
|
|
40
|
+
def new_id(dt: datetime = None):
|
|
41
|
+
if not dt:
|
|
42
|
+
dt = datetime.now()
|
|
43
|
+
|
|
44
|
+
id = dt.strftime("%d%H%M%S")
|
|
45
|
+
AsyncJobs._last_id = id
|
|
46
|
+
|
|
47
|
+
return id
|
|
48
|
+
|
|
49
|
+
def last_command():
|
|
50
|
+
last_id = AsyncJobs._last_id
|
|
51
|
+
last_command = AsyncJobs._last_command
|
|
52
|
+
|
|
53
|
+
if not last_id or not last_command:
|
|
54
|
+
l0, l1 = AsyncJobs.read_last_command()
|
|
55
|
+
if not last_id:
|
|
56
|
+
last_id = l0
|
|
57
|
+
if not last_command:
|
|
58
|
+
last_command = l1
|
|
59
|
+
|
|
60
|
+
return last_id, last_command
|
|
61
|
+
|
|
62
|
+
def write_last_command(job_id: str, command: str):
|
|
63
|
+
with open(f'{log_dir()}/last', 'wt') as f:
|
|
64
|
+
f.write(job_id)
|
|
65
|
+
f.write('\n')
|
|
66
|
+
f.write(command)
|
|
67
|
+
|
|
68
|
+
def read_last_command():
|
|
69
|
+
with open(f'{log_dir()}/last', 'rt') as f:
|
|
70
|
+
job_id = f.readline().strip(' \r\n')
|
|
71
|
+
command = f.readline().strip(' \r\n')
|
|
72
|
+
|
|
73
|
+
return job_id, command
|
|
@@ -2,9 +2,10 @@ import sys
|
|
|
2
2
|
from typing import TypeVar
|
|
3
3
|
|
|
4
4
|
from adam.config import Config
|
|
5
|
+
from adam.utils_async_job import AsyncJobs
|
|
5
6
|
from adam.utils_k8s.cassandra_nodes import CassandraNodes
|
|
6
7
|
from adam.utils_k8s.pod_exec_result import PodExecResult
|
|
7
|
-
from adam.utils import log, log2
|
|
8
|
+
from adam.utils import log, log2, log_to_pods, pod_log_dir
|
|
8
9
|
from adam.utils_k8s.pods import Pods
|
|
9
10
|
from adam.utils_k8s.statefulsets import StatefulSets
|
|
10
11
|
|
|
@@ -22,23 +23,30 @@ class CassandraClusters:
|
|
|
22
23
|
shell = '/bin/sh',
|
|
23
24
|
backgrounded = False,
|
|
24
25
|
log_file = None,
|
|
25
|
-
history=True
|
|
26
|
+
history=True,
|
|
27
|
+
text_color: str = None) -> list[PodExecResult]:
|
|
26
28
|
|
|
27
29
|
pods = StatefulSets.pod_names(sts, namespace)
|
|
28
30
|
samples = 1 if on_any else sys.maxsize
|
|
29
31
|
if (backgrounded or command.endswith(' &')) and not log_file:
|
|
30
|
-
|
|
32
|
+
pod_suffix = None
|
|
33
|
+
dir = None
|
|
34
|
+
if log_to_pods():
|
|
35
|
+
pod_suffix = ''
|
|
36
|
+
dir = pod_log_dir()
|
|
37
|
+
|
|
38
|
+
log_file = AsyncJobs.log_file(command, job_id=AsyncJobs.new_id(), pod_suffix=pod_suffix, dir=dir)
|
|
31
39
|
|
|
32
40
|
msg = 'd`Running|Ran ' + action + ' command onto {size} pods'
|
|
33
41
|
with Pods.parallelize(pods, max_workers, samples, msg, action=action) as exec:
|
|
34
|
-
results: list[PodExecResult] = exec.map(lambda pod: CassandraNodes.exec(pod, namespace, command, False, False, shell, backgrounded, log_file, history))
|
|
42
|
+
results: list[PodExecResult] = exec.map(lambda pod: CassandraNodes.exec(pod, namespace, command, False, False, shell, backgrounded, log_file, history, text_color))
|
|
35
43
|
for result in results:
|
|
36
44
|
if show_out and not Config().is_debug():
|
|
37
|
-
log(result.command)
|
|
45
|
+
log(result.command, text_color=text_color)
|
|
38
46
|
if result.stdout:
|
|
39
|
-
log(result.stdout)
|
|
47
|
+
log(result.stdout, text_color=text_color)
|
|
40
48
|
if result.stderr:
|
|
41
|
-
log2(result.stderr)
|
|
49
|
+
log2(result.stderr, text_color=text_color)
|
|
42
50
|
|
|
43
51
|
return results
|
|
44
52
|
|
|
@@ -14,13 +14,14 @@ class CassandraNodes:
|
|
|
14
14
|
shell = '/bin/sh',
|
|
15
15
|
backgrounded = False,
|
|
16
16
|
log_file = None,
|
|
17
|
-
history = True
|
|
18
|
-
|
|
17
|
+
history = True,
|
|
18
|
+
text_color: str = None) -> PodExecResult:
|
|
19
|
+
r: PodExecResult = Pods.exec(pod_name, "cassandra", namespace, command, show_out = show_out, throw_err = throw_err, shell = shell, backgrounded = backgrounded, log_file=log_file, text_color=text_color)
|
|
19
20
|
|
|
20
21
|
if history and r and r.log_file:
|
|
21
|
-
entry = f':
|
|
22
|
+
# entry = f':tail {r.log_file}'
|
|
22
23
|
|
|
23
|
-
ReplSession().append_history(
|
|
24
|
+
ReplSession().append_history(r.log_file)
|
|
24
25
|
|
|
25
26
|
return r
|
|
26
27
|
|