kaqing 2.0.172__py3-none-any.whl → 2.0.186__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/app_session.py +2 -2
- adam/apps.py +18 -4
- adam/batch.py +1 -1
- adam/checks/check_utils.py +3 -1
- adam/commands/__init__.py +8 -2
- adam/commands/alter_tables.py +24 -35
- adam/commands/app/__init__.py +0 -0
- adam/commands/app/app.py +38 -0
- adam/commands/app/app_ping.py +38 -0
- adam/commands/app/show_app_actions.py +49 -0
- adam/commands/app/show_app_id.py +44 -0
- adam/commands/app/show_app_queues.py +38 -0
- adam/commands/app/utils_app.py +106 -0
- adam/commands/audit/audit.py +9 -27
- adam/commands/audit/audit_repair_tables.py +5 -7
- adam/commands/audit/audit_run.py +1 -1
- adam/commands/audit/completions_l.py +15 -0
- adam/commands/audit/show_last10.py +2 -14
- adam/commands/audit/show_slow10.py +2 -13
- adam/commands/audit/show_top10.py +2 -11
- adam/commands/audit/utils_show_top10.py +14 -1
- adam/commands/bash/bash.py +1 -1
- adam/commands/cat.py +5 -19
- adam/commands/cd.py +6 -8
- adam/commands/check.py +10 -18
- adam/commands/cli_commands.py +6 -1
- adam/commands/{cp.py → clipboard_copy.py} +34 -36
- adam/commands/code.py +2 -2
- adam/commands/command.py +94 -10
- adam/commands/commands_utils.py +19 -12
- adam/commands/cql/completions_c.py +28 -0
- adam/commands/cql/cqlsh.py +3 -7
- adam/commands/cql/utils_cql.py +22 -60
- adam/commands/deploy/deploy_pg_agent.py +2 -2
- adam/commands/deploy/undeploy_pg_agent.py +2 -2
- adam/commands/devices/device.py +39 -8
- adam/commands/devices/device_app.py +19 -29
- adam/commands/devices/device_auit_log.py +3 -3
- adam/commands/devices/device_cass.py +17 -23
- adam/commands/devices/device_export.py +12 -11
- adam/commands/devices/device_postgres.py +79 -63
- adam/commands/download_file.py +47 -0
- adam/commands/export/clean_up_all_export_sessions.py +3 -3
- adam/commands/export/clean_up_export_sessions.py +7 -19
- adam/commands/export/completions_x.py +11 -0
- adam/commands/export/download_export_session.py +40 -0
- adam/commands/export/drop_export_database.py +6 -22
- adam/commands/export/drop_export_databases.py +3 -9
- adam/commands/export/export.py +1 -17
- adam/commands/export/export_databases.py +93 -21
- adam/commands/export/export_select.py +8 -68
- adam/commands/export/export_sessions.py +209 -0
- adam/commands/export/export_use.py +13 -16
- adam/commands/export/export_x_select.py +48 -0
- adam/commands/export/exporter.py +108 -129
- adam/commands/export/import_files.py +44 -0
- adam/commands/export/import_session.py +10 -6
- adam/commands/export/importer.py +19 -5
- adam/commands/export/importer_athena.py +112 -41
- adam/commands/export/importer_sqlite.py +47 -19
- adam/commands/export/show_column_counts.py +11 -20
- adam/commands/export/show_export_databases.py +5 -2
- adam/commands/export/show_export_session.py +6 -15
- adam/commands/export/show_export_sessions.py +4 -11
- adam/commands/export/utils_export.py +46 -16
- adam/commands/find_files.py +51 -0
- adam/commands/find_processes.py +76 -0
- adam/commands/head.py +36 -0
- adam/commands/help.py +2 -2
- adam/commands/intermediate_command.py +6 -3
- adam/commands/ls.py +1 -1
- adam/commands/medusa/medusa_backup.py +13 -16
- adam/commands/medusa/medusa_restore.py +39 -32
- adam/commands/medusa/medusa_show_backupjobs.py +6 -4
- adam/commands/medusa/medusa_show_restorejobs.py +5 -3
- adam/commands/medusa/utils_medusa.py +15 -0
- adam/commands/nodetool.py +3 -8
- adam/commands/param_get.py +10 -12
- adam/commands/param_set.py +7 -10
- adam/commands/postgres/completions_p.py +22 -0
- adam/commands/postgres/postgres.py +25 -40
- adam/commands/postgres/postgres_databases.py +270 -0
- adam/commands/postgres/utils_postgres.py +33 -20
- adam/commands/preview_table.py +4 -2
- adam/commands/pwd.py +3 -3
- adam/commands/reaper/reaper_forward.py +2 -2
- adam/commands/reaper/reaper_run_abort.py +4 -10
- adam/commands/reaper/reaper_runs.py +3 -3
- adam/commands/reaper/reaper_schedule_activate.py +12 -12
- adam/commands/reaper/reaper_schedule_start.py +7 -12
- adam/commands/reaper/reaper_schedule_stop.py +7 -12
- adam/commands/reaper/utils_reaper.py +13 -6
- adam/commands/repair/repair_scan.py +0 -2
- adam/commands/repair/repair_stop.py +0 -1
- adam/commands/shell.py +7 -5
- adam/commands/show/show.py +1 -1
- adam/commands/show/show_adam.py +3 -3
- adam/commands/show/show_cassandra_repairs.py +5 -3
- adam/commands/show/show_cassandra_status.py +27 -20
- adam/commands/show/{show_commands.py → show_cli_commands.py} +2 -2
- adam/commands/show/show_login.py +2 -2
- adam/commands/show/show_params.py +2 -5
- adam/commands/show/show_processes.py +15 -14
- adam/commands/show/show_storage.py +9 -8
- adam/config.py +1 -0
- adam/embedded_params.py +1 -1
- adam/repl.py +20 -11
- adam/repl_commands.py +16 -9
- adam/repl_session.py +8 -1
- adam/repl_state.py +33 -10
- adam/sql/lark_completer.py +280 -0
- adam/sql/lark_parser.py +604 -0
- adam/sql/sql_state_machine.py +8 -2
- adam/utils.py +116 -29
- adam/utils_athena.py +7 -8
- adam/utils_issues.py +2 -2
- adam/utils_k8s/app_clusters.py +2 -2
- adam/utils_k8s/app_pods.py +5 -2
- adam/utils_k8s/cassandra_clusters.py +11 -3
- adam/utils_k8s/cassandra_nodes.py +2 -2
- adam/utils_k8s/k8s.py +14 -5
- adam/utils_k8s/kube_context.py +2 -2
- adam/utils_k8s/pods.py +23 -5
- adam/utils_k8s/statefulsets.py +5 -2
- adam/utils_local.py +4 -0
- adam/utils_repl/appendable_completer.py +6 -0
- adam/utils_repl/repl_completer.py +128 -2
- adam/utils_sqlite.py +14 -14
- adam/version.py +1 -1
- {kaqing-2.0.172.dist-info → kaqing-2.0.186.dist-info}/METADATA +1 -1
- kaqing-2.0.186.dist-info/RECORD +250 -0
- adam/commands/cql/cql_completions.py +0 -33
- adam/commands/export/export_handlers.py +0 -71
- adam/commands/export/export_select_x.py +0 -54
- adam/commands/postgres/postgres_context.py +0 -272
- adam/commands/postgres/psql_completions.py +0 -10
- kaqing-2.0.172.dist-info/RECORD +0 -230
- {kaqing-2.0.172.dist-info → kaqing-2.0.186.dist-info}/WHEEL +0 -0
- {kaqing-2.0.172.dist-info → kaqing-2.0.186.dist-info}/entry_points.txt +0 -0
- {kaqing-2.0.172.dist-info → kaqing-2.0.186.dist-info}/top_level.txt +0 -0
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
from adam.commands import extract_options, extract_sequence
|
|
1
|
+
from adam.commands import extract_options, extract_sequence, extract_trailing_options
|
|
2
2
|
from adam.commands.command import Command
|
|
3
|
-
from adam.commands.commands_utils import show_table
|
|
4
3
|
from adam.commands.cql.utils_cql import cassandra
|
|
5
4
|
from adam.config import Config
|
|
6
|
-
from adam.utils_k8s.statefulsets import StatefulSets
|
|
7
5
|
from adam.repl_state import ReplState, RequiredState
|
|
8
6
|
|
|
9
7
|
class ShowProcesses(Command):
|
|
@@ -29,21 +27,24 @@ class ShowProcesses(Command):
|
|
|
29
27
|
return super().run(cmd, state)
|
|
30
28
|
|
|
31
29
|
with self.validate(args, state) as (args, state):
|
|
32
|
-
with
|
|
33
|
-
with
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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')
|
|
39
38
|
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
with cassandra(state) as pods:
|
|
40
|
+
pods.display_table(cols, header, show_out=show_out, backgrounded=backgrounded)
|
|
42
41
|
|
|
43
|
-
|
|
42
|
+
return state
|
|
44
43
|
|
|
45
44
|
def completion(self, state: ReplState):
|
|
46
|
-
|
|
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})
|
|
47
48
|
|
|
48
49
|
def help(self, _: ReplState):
|
|
49
50
|
return f'{ShowProcesses.COMMAND} [with recipe qing|metrics] [-s]\t show process overview -s show commands on nodes'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from adam.commands import extract_options
|
|
1
|
+
from adam.commands import extract_options, extract_trailing_options
|
|
2
2
|
from adam.commands.command import Command
|
|
3
3
|
from adam.commands.cql.utils_cql import cassandra
|
|
4
4
|
from adam.config import Config
|
|
@@ -27,16 +27,17 @@ class ShowStorage(Command):
|
|
|
27
27
|
return super().run(cmd, state)
|
|
28
28
|
|
|
29
29
|
with self.validate(args, state) as (args, state):
|
|
30
|
-
with
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
with extract_trailing_options(args, '&') as (args, backgrounded):
|
|
31
|
+
with extract_options(args, ['-s', '--show']) as (args, show_out):
|
|
32
|
+
cols = Config().get('storage.columns', 'pod,volume_root,volume_cassandra,snapshots,data,compactions')
|
|
33
|
+
header = Config().get('storage.header', 'POD_NAME,VOLUME /,VOLUME CASS,SNAPSHOTS,DATA,COMPACTIONS')
|
|
34
|
+
with cassandra(state) as pods:
|
|
35
|
+
pods.display_table(cols, header, show_out=show_out, backgrounded=backgrounded)
|
|
35
36
|
|
|
36
|
-
|
|
37
|
+
return state
|
|
37
38
|
|
|
38
39
|
def completion(self, state: ReplState):
|
|
39
|
-
return super().completion(state, {'-s': None})
|
|
40
|
+
return super().completion(state, {'-s': {'&': None}, '&': None})
|
|
40
41
|
|
|
41
42
|
def help(self, _: ReplState):
|
|
42
43
|
return f'{ShowStorage.COMMAND} [-s]\t show storage overview -s show commands on nodes'
|
adam/config.py
CHANGED
|
@@ -11,6 +11,7 @@ class Config:
|
|
|
11
11
|
EMBEDDED_PARAMS = {}
|
|
12
12
|
|
|
13
13
|
LogConfig.is_debug = lambda: Config().is_debug()
|
|
14
|
+
LogConfig.is_debug_complete = lambda: Config().get('debugs.complete', False)
|
|
14
15
|
LogConfig.is_debug_timing = lambda: Config().get('debugs.timings', False)
|
|
15
16
|
|
|
16
17
|
# the singleton pattern
|
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'}}, '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}}, '
|
|
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'}, 'athena': {'workers': 8, 'columns': '<keys>', 'bucket': 'c3.ops--qing'}, 'csv': {'workers': 8, 'columns': '<row-key>'}, 'log-prefix': '/tmp/qing'}, '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-tmp-dir': '/tmp/qing-db', 'logs': {'path': '/c3/cassandra/logs/system.log'}, 'log-prefix': '/tmp/qing', '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-qing': {'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'}, 'x': {'tables': 'lazy'}, 'cli': {'cp': 'jit'}, 'export': {'databases': 'jit'}, 'medusa': {'backups': 'jit'}, 'reaper': {'schedules': 'lazy'}}, 'debug': False, 'debugs': {'timings': False, 'exit-on-error': False, 'show-parallelism': False}}
|
adam/repl.py
CHANGED
|
@@ -5,7 +5,7 @@ import click
|
|
|
5
5
|
from prompt_toolkit.key_binding import KeyBindings
|
|
6
6
|
|
|
7
7
|
from adam.cli_group import cli
|
|
8
|
-
from adam.commands.command import Command,
|
|
8
|
+
from adam.commands.command import Command, InvalidArgumentsException, InvalidStateException
|
|
9
9
|
from adam.commands.command_helpers import ClusterCommandHelper
|
|
10
10
|
from adam.commands.devices.devices import Devices
|
|
11
11
|
from adam.commands.help import Help
|
|
@@ -16,11 +16,16 @@ from adam.log import Log
|
|
|
16
16
|
from adam.repl_commands import ReplCommands
|
|
17
17
|
from adam.repl_session import ReplSession
|
|
18
18
|
from adam.repl_state import ReplState
|
|
19
|
-
from adam.utils import clear_wait_log_flag,
|
|
19
|
+
from adam.utils import clear_wait_log_flag, debug_trace, deep_sort_dict, tabulize, log2, log_exc, log_timing
|
|
20
20
|
from adam.apps import Apps
|
|
21
|
-
from adam.utils_repl.repl_completer import ReplCompleter
|
|
21
|
+
from adam.utils_repl.repl_completer import ReplCompleter, merge_completions
|
|
22
22
|
from . import __version__
|
|
23
23
|
|
|
24
|
+
import nest_asyncio
|
|
25
|
+
nest_asyncio.apply()
|
|
26
|
+
|
|
27
|
+
import asyncio
|
|
28
|
+
|
|
24
29
|
def enter_repl(state: ReplState):
|
|
25
30
|
if os.getenv('QING_DROPPED', 'false') == 'true':
|
|
26
31
|
log2('You have dropped to bash from another qing instance. Please enter "exit" to go back to qing.')
|
|
@@ -68,7 +73,7 @@ def enter_repl(state: ReplState):
|
|
|
68
73
|
|
|
69
74
|
for c in sorted_cmds:
|
|
70
75
|
with log_exc(f'* {c.command()} command returned None completions.'):
|
|
71
|
-
completions = log_timing(c.command(), lambda: deep_sort_dict(
|
|
76
|
+
completions = log_timing(c.command(), lambda: deep_sort_dict(merge_completions(completions, c.completion(state))))
|
|
72
77
|
|
|
73
78
|
# print(json.dumps(completions, indent=4))
|
|
74
79
|
completer = ReplCompleter.from_nested_dict(completions)
|
|
@@ -88,17 +93,17 @@ def enter_repl(state: ReplState):
|
|
|
88
93
|
return state, cmd
|
|
89
94
|
|
|
90
95
|
if state.device == ReplState.A and state.app_app or state.device == ReplState.P:
|
|
91
|
-
state.push()
|
|
96
|
+
state.push(pod_targetted=True)
|
|
92
97
|
|
|
93
98
|
state.app_pod = arry[0].strip('@')
|
|
94
99
|
cmd = ' '.join(arry[1:])
|
|
95
100
|
elif state.device == ReplState.P:
|
|
96
|
-
state.push()
|
|
101
|
+
state.push(pod_targetted=True)
|
|
97
102
|
|
|
98
103
|
state.app_pod = arry[0].strip('@')
|
|
99
104
|
cmd = ' '.join(arry[1:])
|
|
100
105
|
elif state.sts:
|
|
101
|
-
state.push()
|
|
106
|
+
state.push(pod_targetted=True)
|
|
102
107
|
|
|
103
108
|
state.pod = arry[0].strip('@')
|
|
104
109
|
cmd = ' '.join(arry[1:])
|
|
@@ -109,7 +114,9 @@ def enter_repl(state: ReplState):
|
|
|
109
114
|
try:
|
|
110
115
|
if cmd and cmd.strip(' ') and not (result := cmds.run(cmd, target)):
|
|
111
116
|
result = try_device_default_action(target, cmds, cmd_list, cmd)
|
|
112
|
-
except
|
|
117
|
+
except InvalidStateException:
|
|
118
|
+
pass
|
|
119
|
+
except InvalidArgumentsException:
|
|
113
120
|
pass
|
|
114
121
|
|
|
115
122
|
if result and type(result) is ReplState and (s := cast(ReplState, result).export_session) != state.export_session:
|
|
@@ -141,8 +148,7 @@ def try_device_default_action(state: ReplState, cmds: Command, cmd_list: list[Co
|
|
|
141
148
|
if not action_taken:
|
|
142
149
|
log2(f'* Invalid command: {cmd}')
|
|
143
150
|
log2()
|
|
144
|
-
|
|
145
|
-
log2(lines_to_tabular(lines, separator='\t'))
|
|
151
|
+
tabulize([c.help(state) for c in cmd_list if c.help(state)], separator='\t', to=2)
|
|
146
152
|
|
|
147
153
|
return result
|
|
148
154
|
|
|
@@ -174,6 +180,9 @@ def repl(kubeconfig: str, config: str, param: list[str], cluster:str, namespace:
|
|
|
174
180
|
if not KubeContext.init_params(config, param):
|
|
175
181
|
return
|
|
176
182
|
|
|
177
|
-
state = ReplState(
|
|
183
|
+
state = ReplState(ns_sts=cluster, namespace=namespace, in_repl=True)
|
|
178
184
|
state, _ = state.apply_device_arg(extra_args)
|
|
185
|
+
if not state.device:
|
|
186
|
+
state.device=Config().get('repl.start-drive', 'a')
|
|
187
|
+
|
|
179
188
|
enter_repl(state)
|
adam/repl_commands.py
CHANGED
|
@@ -7,6 +7,7 @@ from adam.commands.app.show_app_queues import ShowAppQueues
|
|
|
7
7
|
from adam.commands.audit.audit import Audit
|
|
8
8
|
from adam.commands.cat import Cat
|
|
9
9
|
from adam.commands.code import Code
|
|
10
|
+
from adam.commands.download_file import DownloadFile
|
|
10
11
|
from adam.commands.deploy.code_start import CodeStart
|
|
11
12
|
from adam.commands.deploy.code_stop import CodeStop
|
|
12
13
|
from adam.commands.deploy.deploy import Deploy
|
|
@@ -22,22 +23,27 @@ from adam.commands.devices.device_auit_log import DeviceAuditLog
|
|
|
22
23
|
from adam.commands.devices.device_cass import DeviceCass
|
|
23
24
|
from adam.commands.devices.device_export import DeviceExport
|
|
24
25
|
from adam.commands.devices.device_postgres import DevicePostgres
|
|
26
|
+
from adam.commands.export.download_export_session import DownloadExportSession
|
|
25
27
|
from adam.commands.export.drop_export_database import DropExportDatabase
|
|
26
28
|
from adam.commands.export.export import ExportTables
|
|
29
|
+
from adam.commands.export.import_files import ImportCSVFiles
|
|
27
30
|
from adam.commands.export.import_session import ImportSession
|
|
28
31
|
from adam.commands.export.clean_up_export_sessions import CleanUpExportSessions
|
|
29
32
|
from adam.commands.export.clean_up_all_export_sessions import CleanUpAllExportSessions
|
|
30
33
|
from adam.commands.export.drop_export_databases import DropExportDatabases
|
|
31
|
-
from adam.commands.export.
|
|
34
|
+
from adam.commands.export.export_x_select import ExportXSelect
|
|
32
35
|
from adam.commands.export.export_use import ExportUse
|
|
33
|
-
from adam.commands.export.
|
|
36
|
+
from adam.commands.export.export_select import ExportSelect
|
|
34
37
|
from adam.commands.export.show_column_counts import ShowColumnCounts
|
|
35
38
|
from adam.commands.export.show_export_databases import ShowExportDatabases
|
|
36
39
|
from adam.commands.export.show_export_session import ShowExportSession
|
|
37
40
|
from adam.commands.export.show_export_sessions import ShowExportSessions
|
|
41
|
+
from adam.commands.find_files import FindLocalFiles
|
|
42
|
+
from adam.commands.find_processes import FindProcesses
|
|
43
|
+
from adam.commands.head import Head
|
|
38
44
|
from adam.commands.kubectl import Kubectl
|
|
39
45
|
from adam.commands.shell import Shell
|
|
40
|
-
from adam.commands.
|
|
46
|
+
from adam.commands.clipboard_copy import ClipboardCopy
|
|
41
47
|
from adam.commands.bash.bash import Bash
|
|
42
48
|
from adam.commands.cd import Cd
|
|
43
49
|
from adam.commands.check import Check
|
|
@@ -61,7 +67,7 @@ from adam.commands.param_set import SetParam
|
|
|
61
67
|
from adam.commands.show.show import Show
|
|
62
68
|
from adam.commands.show.show_cassandra_status import ShowCassandraStatus
|
|
63
69
|
from adam.commands.show.show_cassandra_version import ShowCassandraVersion
|
|
64
|
-
from adam.commands.show.
|
|
70
|
+
from adam.commands.show.show_cli_commands import ShowKubectlCommands
|
|
65
71
|
from adam.commands.show.show_host import ShowHost
|
|
66
72
|
from adam.commands.show.show_login import ShowLogin
|
|
67
73
|
from adam.commands.show.show_params import ShowParams
|
|
@@ -93,16 +99,17 @@ class ReplCommands:
|
|
|
93
99
|
return deduped
|
|
94
100
|
|
|
95
101
|
def navigation() -> list[Command]:
|
|
96
|
-
return [Ls(), PreviewTable(), DeviceApp(), DevicePostgres(), DeviceCass(), DeviceAuditLog(), DeviceExport(),
|
|
102
|
+
return [Ls(), PreviewTable(), DeviceApp(), DevicePostgres(), DeviceCass(), DeviceAuditLog(), DeviceExport(),
|
|
103
|
+
Cd(), Cat(), Head(), DownloadFile(), FindLocalFiles(), FindProcesses(), Pwd(), ClipboardCopy(),
|
|
97
104
|
GetParam(), SetParam(), ShowParams(), ShowKubectlCommands(), ShowLogin(), ShowAdam(), ShowHost()]
|
|
98
105
|
|
|
99
106
|
def cassandra_ops() -> list[Command]:
|
|
100
107
|
return [Cqlsh(), ShowCassandraStatus(), ShowCassandraVersion(), ShowCassandraRepairs(), ShowStorage(), ShowProcesses(),
|
|
101
108
|
Check(), Issues(), NodeTool(), Report(), AlterTables(), Bash(),
|
|
102
|
-
ExportTables(),
|
|
109
|
+
ExportTables(), ExportXSelect(), ExportUse(), ShowExportDatabases(), ShowColumnCounts(),
|
|
103
110
|
DropExportDatabase(), DropExportDatabases(),
|
|
104
|
-
ShowExportSessions(), ShowExportSession(),
|
|
105
|
-
CleanUpExportSessions(), CleanUpAllExportSessions(), ImportSession()] + \
|
|
111
|
+
ShowExportSessions(), ShowExportSession(), DownloadExportSession(),
|
|
112
|
+
CleanUpExportSessions(), CleanUpAllExportSessions(), ImportSession(), ImportCSVFiles()] + \
|
|
106
113
|
Medusa().cmd_list() + [Restart(), RollOut(), Watch()] + Reaper().cmd_list() + Repair().cmd_list()
|
|
107
114
|
|
|
108
115
|
def postgres_ops() -> list[Command]:
|
|
@@ -115,7 +122,7 @@ class ReplCommands:
|
|
|
115
122
|
return [Audit()] + Audit().cmd_list()
|
|
116
123
|
|
|
117
124
|
def export_ops() -> list[Command]:
|
|
118
|
-
return [
|
|
125
|
+
return [ExportSelect(), DropExportDatabase(), DropExportDatabases(), ShowColumnCounts()]
|
|
119
126
|
|
|
120
127
|
def tools() -> list[Command]:
|
|
121
128
|
return [Shell(), CodeStart(), CodeStop(), DeployFrontend(), UndeployFrontend(), DeployPod(), UndeployPod(), Kubectl(), Code()]
|
adam/repl_session.py
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from prompt_toolkit import PromptSession
|
|
2
2
|
from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
|
|
3
3
|
|
|
4
|
+
from adam.config import Config
|
|
5
|
+
|
|
4
6
|
class ReplSession:
|
|
5
7
|
# the singleton pattern
|
|
6
8
|
def __new__(cls, *args, **kwargs):
|
|
@@ -10,4 +12,9 @@ class ReplSession:
|
|
|
10
12
|
|
|
11
13
|
def __init__(self):
|
|
12
14
|
if not hasattr(self, 'prompt_session'):
|
|
13
|
-
self.prompt_session = PromptSession(auto_suggest=AutoSuggestFromHistory())
|
|
15
|
+
self.prompt_session = PromptSession(auto_suggest=AutoSuggestFromHistory())
|
|
16
|
+
|
|
17
|
+
def append_history(self, entry: str):
|
|
18
|
+
if entry and Config().get('repl.history.push-cat-remote-log-file', True):
|
|
19
|
+
if self.prompt_session:
|
|
20
|
+
self.prompt_session.history.append_string(entry)
|
adam/repl_state.py
CHANGED
|
@@ -3,7 +3,6 @@ from enum import Enum
|
|
|
3
3
|
import re
|
|
4
4
|
from typing import Callable
|
|
5
5
|
|
|
6
|
-
from adam.commands.postgres.postgres_context import PostgresContext
|
|
7
6
|
from adam.utils_k8s.app_clusters import AppClusters
|
|
8
7
|
from adam.utils_k8s.app_pods import AppPods
|
|
9
8
|
from adam.utils_k8s.cassandra_clusters import CassandraClusters
|
|
@@ -62,6 +61,7 @@ class ReplState:
|
|
|
62
61
|
self.bash_session = bash_session
|
|
63
62
|
self.remote_dir = remote_dir
|
|
64
63
|
self.original_state: ReplState = None
|
|
64
|
+
self.pod_targetted = False
|
|
65
65
|
|
|
66
66
|
self.export_session: str = None
|
|
67
67
|
|
|
@@ -82,11 +82,11 @@ class ReplState:
|
|
|
82
82
|
msg = ''
|
|
83
83
|
if self.device == ReplState.P:
|
|
84
84
|
msg = f'{ReplState.P}:'
|
|
85
|
-
|
|
86
|
-
if
|
|
87
|
-
msg +=
|
|
88
|
-
elif
|
|
89
|
-
msg +=
|
|
85
|
+
host, database = self.pg_host_n_database()
|
|
86
|
+
if database:
|
|
87
|
+
msg += database
|
|
88
|
+
elif host:
|
|
89
|
+
msg += host
|
|
90
90
|
elif self.device == ReplState.A:
|
|
91
91
|
msg = f'{ReplState.A}:'
|
|
92
92
|
if self.app_env:
|
|
@@ -314,8 +314,8 @@ class ReplState:
|
|
|
314
314
|
if self.device != ReplState.P:
|
|
315
315
|
return (False, None)
|
|
316
316
|
|
|
317
|
-
|
|
318
|
-
if not
|
|
317
|
+
_, database = self.pg_host_n_database()
|
|
318
|
+
if not database:
|
|
319
319
|
def error():
|
|
320
320
|
if self.in_repl:
|
|
321
321
|
log2('cd to a database first.')
|
|
@@ -346,7 +346,10 @@ class ReplState:
|
|
|
346
346
|
if not self.export_session:
|
|
347
347
|
def error():
|
|
348
348
|
if self.in_repl:
|
|
349
|
-
|
|
349
|
+
if self.device == ReplState.C:
|
|
350
|
+
log2("Select an export database first with 'use' command.")
|
|
351
|
+
else:
|
|
352
|
+
log2('cd to an export database first.')
|
|
350
353
|
else:
|
|
351
354
|
log2('* export database is missing.')
|
|
352
355
|
log2()
|
|
@@ -390,9 +393,10 @@ class ReplState:
|
|
|
390
393
|
self.pop()
|
|
391
394
|
self.bash_session = None
|
|
392
395
|
|
|
393
|
-
def push(self):
|
|
396
|
+
def push(self, pod_targetted=False):
|
|
394
397
|
if not self.original_state:
|
|
395
398
|
self.original_state = copy(self)
|
|
399
|
+
self.pod_targetted = pod_targetted
|
|
396
400
|
|
|
397
401
|
def pop(self):
|
|
398
402
|
if o := self.original_state:
|
|
@@ -407,6 +411,25 @@ class ReplState:
|
|
|
407
411
|
self.namespace = o.namespace
|
|
408
412
|
|
|
409
413
|
self.original_state = None
|
|
414
|
+
self.pod_targetted = False
|
|
415
|
+
|
|
416
|
+
def pg_host_n_database(self):
|
|
417
|
+
host = None
|
|
418
|
+
database = None
|
|
419
|
+
|
|
420
|
+
if self.pg_path:
|
|
421
|
+
host_n_db = self.pg_path.split('/')
|
|
422
|
+
host = host_n_db[0]
|
|
423
|
+
if len(host_n_db) > 1:
|
|
424
|
+
database = host_n_db[1]
|
|
425
|
+
|
|
426
|
+
return host, database
|
|
427
|
+
|
|
428
|
+
def with_no_pod(self):
|
|
429
|
+
state1 = copy(self)
|
|
430
|
+
state1.pod = None
|
|
431
|
+
|
|
432
|
+
return state1
|
|
410
433
|
|
|
411
434
|
class DevicePodService:
|
|
412
435
|
def __init__(self, handler: 'DeviceExecHandler'):
|