kaqing 2.0.145__py3-none-any.whl → 2.0.172__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of kaqing might be problematic. Click here for more details.
- adam/__init__.py +0 -2
- adam/app_session.py +8 -11
- adam/batch.py +3 -3
- adam/checks/check_utils.py +14 -46
- adam/checks/cpu.py +7 -1
- adam/checks/cpu_metrics.py +52 -0
- adam/checks/disk.py +2 -3
- adam/columns/columns.py +3 -1
- adam/columns/cpu.py +3 -1
- adam/columns/cpu_metrics.py +22 -0
- adam/columns/memory.py +3 -4
- adam/commands/__init__.py +18 -0
- adam/commands/alter_tables.py +43 -47
- adam/commands/audit/audit.py +22 -23
- adam/commands/audit/audit_repair_tables.py +14 -17
- adam/commands/audit/audit_run.py +15 -23
- adam/commands/audit/show_last10.py +10 -13
- adam/commands/audit/show_slow10.py +10 -13
- adam/commands/audit/show_top10.py +10 -13
- adam/commands/audit/utils_show_top10.py +2 -3
- adam/commands/bash/__init__.py +5 -0
- adam/commands/bash/bash.py +7 -104
- adam/commands/bash/utils_bash.py +16 -0
- adam/commands/cat.py +13 -19
- adam/commands/cd.py +8 -10
- adam/commands/check.py +20 -21
- adam/commands/cli_commands.py +2 -3
- adam/commands/code.py +20 -23
- adam/commands/command.py +120 -39
- adam/commands/commands_utils.py +8 -17
- adam/commands/cp.py +33 -39
- adam/commands/cql/cql_completions.py +9 -4
- adam/commands/cql/cqlsh.py +10 -30
- adam/commands/cql/{cql_utils.py → utils_cql.py} +149 -15
- adam/commands/deploy/code_start.py +7 -10
- adam/commands/deploy/code_stop.py +4 -21
- adam/commands/deploy/code_utils.py +3 -3
- adam/commands/deploy/deploy.py +4 -27
- adam/commands/deploy/deploy_frontend.py +14 -17
- adam/commands/deploy/deploy_pg_agent.py +2 -5
- adam/commands/deploy/deploy_pod.py +64 -68
- adam/commands/deploy/undeploy.py +4 -27
- adam/commands/deploy/undeploy_frontend.py +4 -7
- adam/commands/deploy/undeploy_pg_agent.py +4 -7
- adam/commands/deploy/undeploy_pod.py +9 -12
- adam/commands/devices/device.py +93 -2
- adam/commands/devices/device_app.py +37 -10
- adam/commands/devices/device_auit_log.py +8 -2
- adam/commands/devices/device_cass.py +47 -7
- adam/commands/devices/device_export.py +2 -2
- adam/commands/devices/device_postgres.py +41 -6
- adam/commands/exit.py +1 -4
- adam/commands/export/clean_up_all_export_sessions.py +37 -0
- adam/commands/export/clean_up_export_sessions.py +18 -7
- adam/commands/export/drop_export_database.py +15 -18
- adam/commands/export/drop_export_databases.py +6 -9
- adam/commands/export/export.py +8 -38
- adam/commands/export/export_databases.py +16 -12
- adam/commands/export/export_handlers.py +71 -0
- adam/commands/export/export_select.py +33 -24
- adam/commands/export/export_use.py +12 -15
- adam/commands/export/exporter.py +37 -48
- adam/commands/export/import_session.py +4 -32
- adam/commands/export/importer_athena.py +4 -7
- adam/commands/export/importer_sqlite.py +19 -27
- adam/commands/export/show_column_counts.py +13 -22
- adam/commands/export/show_export_databases.py +3 -6
- adam/commands/export/show_export_session.py +10 -13
- adam/commands/export/show_export_sessions.py +8 -11
- adam/commands/export/utils_export.py +24 -1
- adam/commands/intermediate_command.py +49 -0
- adam/commands/issues.py +11 -43
- adam/commands/kubectl.py +3 -6
- adam/commands/login.py +22 -24
- adam/commands/logs.py +3 -6
- adam/commands/ls.py +8 -9
- adam/commands/medusa/medusa.py +4 -22
- adam/commands/medusa/medusa_backup.py +20 -24
- adam/commands/medusa/medusa_restore.py +29 -33
- adam/commands/medusa/medusa_show_backupjobs.py +14 -18
- adam/commands/medusa/medusa_show_restorejobs.py +11 -18
- adam/commands/nodetool.py +6 -15
- adam/commands/param_get.py +11 -12
- adam/commands/param_set.py +9 -10
- adam/commands/postgres/postgres.py +29 -37
- adam/commands/postgres/postgres_context.py +47 -23
- adam/commands/postgres/postgres_ls.py +4 -8
- adam/commands/postgres/postgres_preview.py +5 -9
- adam/commands/postgres/psql_completions.py +1 -1
- adam/commands/postgres/utils_postgres.py +66 -0
- adam/commands/preview_table.py +5 -44
- adam/commands/pwd.py +13 -16
- adam/commands/reaper/reaper.py +4 -27
- adam/commands/reaper/reaper_forward.py +48 -55
- adam/commands/reaper/reaper_forward_session.py +6 -0
- adam/commands/reaper/reaper_forward_stop.py +10 -16
- adam/commands/reaper/reaper_restart.py +7 -14
- adam/commands/reaper/reaper_run_abort.py +11 -30
- adam/commands/reaper/reaper_runs.py +42 -57
- adam/commands/reaper/reaper_runs_abort.py +29 -49
- adam/commands/reaper/reaper_schedule_activate.py +11 -30
- adam/commands/reaper/reaper_schedule_start.py +10 -29
- adam/commands/reaper/reaper_schedule_stop.py +10 -29
- adam/commands/reaper/reaper_schedules.py +4 -14
- adam/commands/reaper/reaper_status.py +8 -16
- adam/commands/reaper/utils_reaper.py +196 -0
- adam/commands/repair/repair.py +4 -22
- adam/commands/repair/repair_log.py +5 -11
- adam/commands/repair/repair_run.py +27 -34
- adam/commands/repair/repair_scan.py +32 -38
- adam/commands/repair/repair_stop.py +5 -11
- adam/commands/report.py +27 -29
- adam/commands/restart.py +25 -26
- adam/commands/rollout.py +19 -24
- adam/commands/shell.py +10 -4
- adam/commands/show/show.py +10 -26
- adam/commands/show/show_cassandra_repairs.py +35 -0
- adam/commands/show/show_cassandra_status.py +32 -43
- adam/commands/show/show_cassandra_version.py +5 -18
- adam/commands/show/show_commands.py +19 -24
- adam/commands/show/show_host.py +1 -1
- adam/commands/show/show_login.py +20 -27
- adam/commands/show/show_processes.py +15 -19
- adam/commands/show/show_storage.py +10 -20
- adam/commands/watch.py +26 -29
- adam/config.py +4 -16
- adam/embedded_params.py +1 -1
- adam/log.py +4 -4
- adam/pod_exec_result.py +3 -3
- adam/repl.py +29 -32
- adam/repl_commands.py +11 -11
- adam/repl_state.py +52 -26
- adam/sql/sql_completer.py +4 -6
- adam/sql/sql_state_machine.py +21 -14
- adam/sso/authn_ad.py +6 -8
- adam/sso/authn_okta.py +4 -6
- adam/sso/cred_cache.py +3 -5
- adam/sso/idp.py +9 -12
- adam/utils.py +393 -33
- adam/utils_athena.py +14 -13
- adam/utils_audits.py +12 -12
- adam/utils_issues.py +32 -0
- adam/utils_k8s/app_clusters.py +13 -18
- adam/utils_k8s/app_pods.py +2 -0
- adam/utils_k8s/cassandra_clusters.py +21 -18
- adam/utils_k8s/custom_resources.py +16 -17
- adam/utils_k8s/ingresses.py +2 -2
- adam/utils_k8s/jobs.py +7 -11
- adam/utils_k8s/k8s.py +87 -0
- adam/utils_k8s/pods.py +14 -76
- adam/utils_k8s/secrets.py +4 -4
- adam/utils_k8s/service_accounts.py +5 -4
- adam/utils_k8s/services.py +2 -2
- adam/utils_k8s/statefulsets.py +1 -12
- adam/utils_repl/state_machine.py +3 -3
- adam/utils_sqlite.py +78 -42
- adam/version.py +1 -1
- {kaqing-2.0.145.dist-info → kaqing-2.0.172.dist-info}/METADATA +1 -1
- kaqing-2.0.172.dist-info/RECORD +230 -0
- adam/commands/app.py +0 -67
- adam/commands/app_ping.py +0 -44
- adam/commands/export/clean_up_export_session.py +0 -53
- adam/commands/postgres/postgres_utils.py +0 -31
- adam/commands/reaper/reaper_session.py +0 -159
- adam/commands/show/show_app_actions.py +0 -56
- adam/commands/show/show_app_id.py +0 -47
- adam/commands/show/show_app_queues.py +0 -45
- adam/commands/show/show_repairs.py +0 -47
- kaqing-2.0.145.dist-info/RECORD +0 -227
- {kaqing-2.0.145.dist-info → kaqing-2.0.172.dist-info}/WHEEL +0 -0
- {kaqing-2.0.145.dist-info → kaqing-2.0.172.dist-info}/entry_points.txt +0 -0
- {kaqing-2.0.145.dist-info → kaqing-2.0.172.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', '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'
|
|
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', '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'}, '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-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}, 'debug': False, 'debugs': {'timings': False, 'exit-on-error': False, 'show-parallelism': False}}
|
adam/log.py
CHANGED
|
@@ -4,6 +4,8 @@ import os
|
|
|
4
4
|
import sys
|
|
5
5
|
import click
|
|
6
6
|
|
|
7
|
+
from adam.utils import log_exc
|
|
8
|
+
|
|
7
9
|
class Log:
|
|
8
10
|
DEBUG = False
|
|
9
11
|
|
|
@@ -28,7 +30,7 @@ class Log:
|
|
|
28
30
|
print(file=sys.stderr)
|
|
29
31
|
|
|
30
32
|
def log_to_file(config: dict[any, any]):
|
|
31
|
-
|
|
33
|
+
with log_exc():
|
|
32
34
|
base = f"/tmp/logs"
|
|
33
35
|
os.makedirs(base, exist_ok=True)
|
|
34
36
|
|
|
@@ -42,6 +44,4 @@ class Log:
|
|
|
42
44
|
except:
|
|
43
45
|
f.write(config)
|
|
44
46
|
else:
|
|
45
|
-
f.write(config)
|
|
46
|
-
except:
|
|
47
|
-
pass
|
|
47
|
+
f.write(config)
|
adam/pod_exec_result.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import yaml
|
|
2
2
|
|
|
3
|
+
from adam.utils import log_exc
|
|
4
|
+
|
|
3
5
|
class PodExecResult:
|
|
4
6
|
# {
|
|
5
7
|
# 'metadata': {},
|
|
@@ -27,10 +29,8 @@ class PodExecResult:
|
|
|
27
29
|
def exit_code(self) -> int:
|
|
28
30
|
code = 0
|
|
29
31
|
|
|
30
|
-
|
|
32
|
+
with log_exc(False):
|
|
31
33
|
code = self.error['details']['causes'][0]['message']
|
|
32
|
-
except:
|
|
33
|
-
pass
|
|
34
34
|
|
|
35
35
|
return code
|
|
36
36
|
|
adam/repl.py
CHANGED
|
@@ -1,26 +1,22 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import time
|
|
3
|
-
import traceback
|
|
4
3
|
from typing import cast
|
|
5
4
|
import click
|
|
6
|
-
import concurrent
|
|
7
5
|
from prompt_toolkit.key_binding import KeyBindings
|
|
8
6
|
|
|
9
7
|
from adam.cli_group import cli
|
|
10
|
-
from adam.commands.command import Command
|
|
8
|
+
from adam.commands.command import Command, InvalidState
|
|
11
9
|
from adam.commands.command_helpers import ClusterCommandHelper
|
|
12
10
|
from adam.commands.devices.devices import Devices
|
|
13
11
|
from adam.commands.help import Help
|
|
14
12
|
from adam.config import Config
|
|
15
13
|
from adam.utils_audits import Audits
|
|
16
|
-
from adam.utils_k8s.app_pods import AppPods
|
|
17
14
|
from adam.utils_k8s.kube_context import KubeContext
|
|
18
|
-
from adam.utils_k8s.statefulsets import StatefulSets
|
|
19
15
|
from adam.log import Log
|
|
20
16
|
from adam.repl_commands import ReplCommands
|
|
21
17
|
from adam.repl_session import ReplSession
|
|
22
18
|
from adam.repl_state import ReplState
|
|
23
|
-
from adam.utils import deep_merge_dicts, deep_sort_dict, lines_to_tabular, log2
|
|
19
|
+
from adam.utils import clear_wait_log_flag, debug, debug_trace, deep_merge_dicts, deep_sort_dict, lines_to_tabular, log2, log_exc, log_timing
|
|
24
20
|
from adam.apps import Apps
|
|
25
21
|
from adam.utils_repl.repl_completer import ReplCompleter
|
|
26
22
|
from . import __version__
|
|
@@ -50,34 +46,32 @@ def enter_repl(state: ReplState):
|
|
|
50
46
|
def _(event):
|
|
51
47
|
event.app.current_buffer.text = ''
|
|
52
48
|
|
|
53
|
-
with
|
|
49
|
+
with Audits.offload() as exec:
|
|
54
50
|
# warm up AWS lambda - this log line may timeout and get lost, which is fine
|
|
55
|
-
|
|
51
|
+
exec.submit(Audits.log, 'entering kaqing repl', state.namespace, 'z', 0.0)
|
|
56
52
|
|
|
57
53
|
s0 = time.time()
|
|
58
54
|
|
|
59
55
|
# use sorted command list only for auto-completion
|
|
60
56
|
sorted_cmds = sorted(cmd_list, key=lambda cmd: cmd.command())
|
|
61
57
|
while True:
|
|
58
|
+
cmd: str = None
|
|
62
59
|
result = None
|
|
63
60
|
try:
|
|
64
61
|
completer = ReplCompleter.from_nested_dict({})
|
|
65
62
|
if not state.bash_session:
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
# print(json.dumps(completions, indent=4))
|
|
80
|
-
completer = ReplCompleter.from_nested_dict(completions)
|
|
63
|
+
with log_timing('completion-calcs'):
|
|
64
|
+
completions = {}
|
|
65
|
+
# app commands are available only on a: drive
|
|
66
|
+
if state.device == ReplState.A and state.app_app:
|
|
67
|
+
completions = log_timing('actions', lambda: Apps(path='apps.yaml').commands())
|
|
68
|
+
|
|
69
|
+
for c in sorted_cmds:
|
|
70
|
+
with log_exc(f'* {c.command()} command returned None completions.'):
|
|
71
|
+
completions = log_timing(c.command(), lambda: deep_sort_dict(deep_merge_dicts(completions, c.completion(state))))
|
|
72
|
+
|
|
73
|
+
# print(json.dumps(completions, indent=4))
|
|
74
|
+
completer = ReplCompleter.from_nested_dict(completions)
|
|
81
75
|
|
|
82
76
|
cmd = session.prompt(prompt_msg(), completer=completer, key_bindings=kb)
|
|
83
77
|
s0 = time.time()
|
|
@@ -112,8 +106,11 @@ def enter_repl(state: ReplState):
|
|
|
112
106
|
return (state, cmd)
|
|
113
107
|
|
|
114
108
|
target, cmd = targetted(state, cmd)
|
|
115
|
-
|
|
116
|
-
|
|
109
|
+
try:
|
|
110
|
+
if cmd and cmd.strip(' ') and not (result := cmds.run(cmd, target)):
|
|
111
|
+
result = try_device_default_action(target, cmds, cmd_list, cmd)
|
|
112
|
+
except InvalidState:
|
|
113
|
+
pass
|
|
117
114
|
|
|
118
115
|
if result and type(result) is ReplState and (s := cast(ReplState, result).export_session) != state.export_session:
|
|
119
116
|
state.export_session = s
|
|
@@ -125,23 +122,23 @@ def enter_repl(state: ReplState):
|
|
|
125
122
|
raise e
|
|
126
123
|
else:
|
|
127
124
|
log2(e)
|
|
128
|
-
|
|
125
|
+
debug_trace()
|
|
129
126
|
finally:
|
|
130
127
|
if not state.bash_session:
|
|
131
128
|
state.pop()
|
|
132
129
|
|
|
133
|
-
|
|
134
|
-
if
|
|
135
|
-
|
|
130
|
+
clear_wait_log_flag()
|
|
131
|
+
if cmd:
|
|
132
|
+
log_timing(f'command {cmd}', s0=s0)
|
|
136
133
|
|
|
137
134
|
# offload audit logging
|
|
138
135
|
if cmd and (state.device != ReplState.L or Config().get('audit.log-audit-queries', False)):
|
|
139
|
-
|
|
136
|
+
exec.submit(Audits.log, cmd, state.namespace, state.device, time.time() - s0, get_audit_extra(result))
|
|
140
137
|
|
|
141
138
|
def try_device_default_action(state: ReplState, cmds: Command, cmd_list: list[Command], cmd: str):
|
|
142
|
-
|
|
139
|
+
action_taken, result = Devices.device(state).try_fallback_action(cmds, state, cmd)
|
|
143
140
|
|
|
144
|
-
if not
|
|
141
|
+
if not action_taken:
|
|
145
142
|
log2(f'* Invalid command: {cmd}')
|
|
146
143
|
log2()
|
|
147
144
|
lines = [c.help(state) for c in cmd_list if c.help(state)]
|
adam/repl_commands.py
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
from adam.commands.alter_tables import AlterTables
|
|
2
|
-
from adam.commands.app import App
|
|
3
|
-
from adam.commands.app_ping import AppPing
|
|
2
|
+
from adam.commands.app.app import App
|
|
3
|
+
from adam.commands.app.app_ping import AppPing
|
|
4
|
+
from adam.commands.app.show_app_actions import ShowAppActions
|
|
5
|
+
from adam.commands.app.show_app_id import ShowAppId
|
|
6
|
+
from adam.commands.app.show_app_queues import ShowAppQueues
|
|
4
7
|
from adam.commands.audit.audit import Audit
|
|
5
8
|
from adam.commands.cat import Cat
|
|
6
9
|
from adam.commands.code import Code
|
|
@@ -22,8 +25,8 @@ from adam.commands.devices.device_postgres import DevicePostgres
|
|
|
22
25
|
from adam.commands.export.drop_export_database import DropExportDatabase
|
|
23
26
|
from adam.commands.export.export import ExportTables
|
|
24
27
|
from adam.commands.export.import_session import ImportSession
|
|
25
|
-
from adam.commands.export.clean_up_export_session import CleanUpExportSession
|
|
26
28
|
from adam.commands.export.clean_up_export_sessions import CleanUpExportSessions
|
|
29
|
+
from adam.commands.export.clean_up_all_export_sessions import CleanUpAllExportSessions
|
|
27
30
|
from adam.commands.export.drop_export_databases import DropExportDatabases
|
|
28
31
|
from adam.commands.export.export_select import ExportSelect
|
|
29
32
|
from adam.commands.export.export_use import ExportUse
|
|
@@ -34,7 +37,6 @@ from adam.commands.export.show_export_session import ShowExportSession
|
|
|
34
37
|
from adam.commands.export.show_export_sessions import ShowExportSessions
|
|
35
38
|
from adam.commands.kubectl import Kubectl
|
|
36
39
|
from adam.commands.shell import Shell
|
|
37
|
-
from adam.commands.show.show_app_queues import ShowAppQueues
|
|
38
40
|
from adam.commands.cp import ClipboardCopy
|
|
39
41
|
from adam.commands.bash.bash import Bash
|
|
40
42
|
from adam.commands.cd import Cd
|
|
@@ -57,8 +59,6 @@ from adam.commands.restart import Restart
|
|
|
57
59
|
from adam.commands.rollout import RollOut
|
|
58
60
|
from adam.commands.param_set import SetParam
|
|
59
61
|
from adam.commands.show.show import Show
|
|
60
|
-
from adam.commands.show.show_app_actions import ShowAppActions
|
|
61
|
-
from adam.commands.show.show_app_id import ShowAppId
|
|
62
62
|
from adam.commands.show.show_cassandra_status import ShowCassandraStatus
|
|
63
63
|
from adam.commands.show.show_cassandra_version import ShowCassandraVersion
|
|
64
64
|
from adam.commands.show.show_commands import ShowKubectlCommands
|
|
@@ -66,7 +66,7 @@ from adam.commands.show.show_host import ShowHost
|
|
|
66
66
|
from adam.commands.show.show_login import ShowLogin
|
|
67
67
|
from adam.commands.show.show_params import ShowParams
|
|
68
68
|
from adam.commands.show.show_processes import ShowProcesses
|
|
69
|
-
from adam.commands.show.
|
|
69
|
+
from adam.commands.show.show_cassandra_repairs import ShowCassandraRepairs
|
|
70
70
|
from adam.commands.show.show_storage import ShowStorage
|
|
71
71
|
from adam.commands.show.show_adam import ShowAdam
|
|
72
72
|
from adam.commands.watch import Watch
|
|
@@ -97,13 +97,13 @@ class ReplCommands:
|
|
|
97
97
|
GetParam(), SetParam(), ShowParams(), ShowKubectlCommands(), ShowLogin(), ShowAdam(), ShowHost()]
|
|
98
98
|
|
|
99
99
|
def cassandra_ops() -> list[Command]:
|
|
100
|
-
return [Cqlsh(), ShowCassandraStatus(), ShowCassandraVersion(),
|
|
100
|
+
return [Cqlsh(), ShowCassandraStatus(), ShowCassandraVersion(), ShowCassandraRepairs(), ShowStorage(), ShowProcesses(),
|
|
101
101
|
Check(), Issues(), NodeTool(), Report(), AlterTables(), Bash(),
|
|
102
102
|
ExportTables(), ExportSelect(), ExportUse(), ShowExportDatabases(), ShowColumnCounts(),
|
|
103
103
|
DropExportDatabase(), DropExportDatabases(),
|
|
104
104
|
ShowExportSessions(), ShowExportSession(),
|
|
105
|
-
|
|
106
|
-
Medusa.cmd_list() + [Restart(), RollOut(), Watch()] + Reaper.cmd_list() + Repair.cmd_list()
|
|
105
|
+
CleanUpExportSessions(), CleanUpAllExportSessions(), ImportSession()] + \
|
|
106
|
+
Medusa().cmd_list() + [Restart(), RollOut(), Watch()] + Reaper().cmd_list() + Repair().cmd_list()
|
|
107
107
|
|
|
108
108
|
def postgres_ops() -> list[Command]:
|
|
109
109
|
return [Postgres(), DeployPgAgent(), UndeployPgAgent(), PostgresPg()]
|
|
@@ -112,7 +112,7 @@ class ReplCommands:
|
|
|
112
112
|
return [ShowAppActions(), ShowAppId(), ShowAppQueues(), AppPing(), App()]
|
|
113
113
|
|
|
114
114
|
def audit_ops() -> list[Command]:
|
|
115
|
-
return [Audit()] + Audit.cmd_list()
|
|
115
|
+
return [Audit()] + Audit().cmd_list()
|
|
116
116
|
|
|
117
117
|
def export_ops() -> list[Command]:
|
|
118
118
|
return [ExportSelectX(), DropExportDatabase(), DropExportDatabases(), ShowColumnCounts()]
|
adam/repl_state.py
CHANGED
|
@@ -20,31 +20,8 @@ class BashSession:
|
|
|
20
20
|
def pwd(self, state: 'ReplState'):
|
|
21
21
|
command = f'cat /tmp/.qing-{self.session_id}'
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
rs = [AppPods.exec(state.app_pod, state.namespace, command, show_out=False)]
|
|
26
|
-
else:
|
|
27
|
-
pods = AppPods.pod_names(state.namespace, state.app_env, state.app_pod)
|
|
28
|
-
rs = AppClusters.exec(pods, state.namespace, command, show_out=False)
|
|
29
|
-
elif state.pod:
|
|
30
|
-
rs = [CassandraNodes.exec(state.pod, state.namespace, command, show_out=False)]
|
|
31
|
-
elif state.sts:
|
|
32
|
-
rs = CassandraClusters.exec(state.sts, state.namespace, command, action='bash', show_out=False)
|
|
33
|
-
|
|
34
|
-
dir = None
|
|
35
|
-
for r in rs:
|
|
36
|
-
if r.exit_code(): # if fails to read the session file, ignore
|
|
37
|
-
continue
|
|
38
|
-
|
|
39
|
-
dir0 = r.stdout.strip(' \r\n')
|
|
40
|
-
if dir:
|
|
41
|
-
if dir != dir0:
|
|
42
|
-
log2('Inconsitent working dir found across multiple pods.')
|
|
43
|
-
return None
|
|
44
|
-
else:
|
|
45
|
-
dir = dir0
|
|
46
|
-
|
|
47
|
-
return dir
|
|
23
|
+
with device(state) as pods:
|
|
24
|
+
return pods.exec(command, action='bash', show_out=False)
|
|
48
25
|
|
|
49
26
|
class RequiredState(Enum):
|
|
50
27
|
CLUSTER = 'cluster'
|
|
@@ -429,4 +406,53 @@ class ReplState:
|
|
|
429
406
|
# self.export_session = o.export_session
|
|
430
407
|
self.namespace = o.namespace
|
|
431
408
|
|
|
432
|
-
self.original_state = None
|
|
409
|
+
self.original_state = None
|
|
410
|
+
|
|
411
|
+
class DevicePodService:
|
|
412
|
+
def __init__(self, handler: 'DeviceExecHandler'):
|
|
413
|
+
self.handler = handler
|
|
414
|
+
|
|
415
|
+
def exec(self, command: str, action='bash', show_out = True):
|
|
416
|
+
state = self.handler.state
|
|
417
|
+
|
|
418
|
+
rs = None
|
|
419
|
+
if state.device == ReplState.A and state.app_app:
|
|
420
|
+
if state.app_pod:
|
|
421
|
+
rs = [AppPods.exec(state.app_pod, state.namespace, command, show_out=show_out)]
|
|
422
|
+
else:
|
|
423
|
+
pods = AppPods.pod_names(state.namespace, state.app_env, state.app_app)
|
|
424
|
+
rs = AppClusters.exec(pods, state.namespace, command, show_out=show_out)
|
|
425
|
+
elif state.pod:
|
|
426
|
+
rs = [CassandraNodes.exec(state.pod, state.namespace, command, show_out=show_out)]
|
|
427
|
+
elif state.sts:
|
|
428
|
+
rs = CassandraClusters.exec(state.sts, state.namespace, command, action=action, show_out=show_out)
|
|
429
|
+
# assume that pg-agent or ops pod is single pod
|
|
430
|
+
|
|
431
|
+
dir = None
|
|
432
|
+
if rs:
|
|
433
|
+
for r in rs:
|
|
434
|
+
if r.exit_code(): # if fails to read the session file, ignore
|
|
435
|
+
continue
|
|
436
|
+
|
|
437
|
+
dir0 = r.stdout.strip(' \r\n')
|
|
438
|
+
if dir:
|
|
439
|
+
if dir != dir0:
|
|
440
|
+
log2('Inconsitent working dir found across multiple pods.')
|
|
441
|
+
return None
|
|
442
|
+
else:
|
|
443
|
+
dir = dir0
|
|
444
|
+
|
|
445
|
+
return dir
|
|
446
|
+
|
|
447
|
+
class DeviceExecHandler:
|
|
448
|
+
def __init__(self, state: ReplState):
|
|
449
|
+
self.state = state
|
|
450
|
+
|
|
451
|
+
def __enter__(self):
|
|
452
|
+
return DevicePodService(self)
|
|
453
|
+
|
|
454
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
455
|
+
return False
|
|
456
|
+
|
|
457
|
+
def device(state: ReplState):
|
|
458
|
+
return DeviceExecHandler(state)
|
adam/sql/sql_completer.py
CHANGED
|
@@ -2,7 +2,7 @@ from enum import Enum
|
|
|
2
2
|
from typing import Callable
|
|
3
3
|
|
|
4
4
|
import sqlparse
|
|
5
|
-
from sqlparse.sql import
|
|
5
|
+
from sqlparse.sql import Token
|
|
6
6
|
|
|
7
7
|
from adam.sql.term_completer import TermCompleter
|
|
8
8
|
from adam.utils_repl.automata_completer import AutomataCompleter
|
|
@@ -26,11 +26,9 @@ class SqlCompleter(AutomataCompleter[Token]):
|
|
|
26
26
|
tokens = []
|
|
27
27
|
|
|
28
28
|
stmts = sqlparse.parse(text)
|
|
29
|
-
if
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
statement: Statement = stmts[0]
|
|
33
|
-
tokens = statement.tokens
|
|
29
|
+
if stmts:
|
|
30
|
+
for stmt in stmts:
|
|
31
|
+
tokens.extend(stmt.tokens)
|
|
34
32
|
|
|
35
33
|
return tokens
|
|
36
34
|
|
adam/sql/sql_state_machine.py
CHANGED
|
@@ -2,6 +2,7 @@ from typing import Callable
|
|
|
2
2
|
from sqlparse.sql import Token
|
|
3
3
|
from sqlparse import tokens as TOKEN
|
|
4
4
|
|
|
5
|
+
from adam.utils import log_exc
|
|
5
6
|
from adam.utils_repl.state_machine import StateMachine, State
|
|
6
7
|
|
|
7
8
|
__all__ = [
|
|
@@ -76,8 +77,8 @@ SQL_SPEC = [
|
|
|
76
77
|
'- > ; > ',
|
|
77
78
|
'select_from_sq_ > as > select_from_x_as ^ as',
|
|
78
79
|
'select_from_x_comma_ > name|audit > select_from_x ^ tables',
|
|
79
|
-
'select_from_x_ ^ as,where,inner join,left outer join,right outer join,full outer join,group by,order by,limit',
|
|
80
|
-
'select_from_x_as_x_ > , > select_from_x_comma_ ^ where,inner join,left outer join,right outer join,full outer join,group by,order by,limit',
|
|
80
|
+
'select_from_x_ ^ as,where,inner join,left outer join,right outer join,full outer join,group by,order by,limit,&',
|
|
81
|
+
'select_from_x_as_x_ > , > select_from_x_comma_ ^ where,inner join,left outer join,right outer join,full outer join,group by,order by,limit,&',
|
|
81
82
|
'- > as > select_from_x_as',
|
|
82
83
|
'- > where > select_where',
|
|
83
84
|
'- > order > select_order',
|
|
@@ -96,6 +97,7 @@ SQL_SPEC = [
|
|
|
96
97
|
'- > full > select_from_x_full',
|
|
97
98
|
'- > full outer join > select_join',
|
|
98
99
|
'- > ; > ',
|
|
100
|
+
'- > & > select_from_x$',
|
|
99
101
|
'select_from_x_as_ > name > select_from_x_as_x ^ x,y,z',
|
|
100
102
|
'select_from_x_as_x > , > select_from_x_as_x_comma_',
|
|
101
103
|
'- > ; > ',
|
|
@@ -118,34 +120,38 @@ SQL_SPEC = [
|
|
|
118
120
|
'select_where_a_not_op > name|single|num > select_where_sc ^ single',
|
|
119
121
|
'select_where_a_op > name|single|num > select_where_sc ^ single',
|
|
120
122
|
'select_where_sc > ; > ',
|
|
121
|
-
'select_where_sc_ > and|or > select_where ^ and,or,order by,group by,limit',
|
|
123
|
+
'select_where_sc_ > and|or > select_where ^ and,or,order by,group by,limit,&',
|
|
122
124
|
'- > group > select_group',
|
|
123
125
|
'- > group by > select_group_by',
|
|
124
126
|
'- > order > select_order',
|
|
125
127
|
'- > order by > select_order_by',
|
|
126
128
|
'- > limit > select_where_sc_limit',
|
|
127
129
|
'- > ; > ',
|
|
130
|
+
'- > & > select_from_x$',
|
|
128
131
|
'select_group_ > by > select_group_by ^ by',
|
|
129
132
|
'select_group_by_ > name > select_group_by_a ^ columns',
|
|
130
133
|
'select_group_by_a > , > select_group_by_a_comma_ ^ columns',
|
|
131
134
|
'- > ; > ',
|
|
132
135
|
'select_group_by_a_comma_ > name > select_group_by_a ^ columns',
|
|
133
|
-
'select_group_by_a_ > limit > select_where_sc_limit ^ limit,order by',
|
|
136
|
+
'select_group_by_a_ > limit > select_where_sc_limit ^ limit,order by,&',
|
|
134
137
|
'- > order > select_order',
|
|
135
138
|
'- > order by > select_order_by',
|
|
136
139
|
'- > ; > ',
|
|
140
|
+
'- > & > select_from_x$',
|
|
137
141
|
'select_order_ > by > select_order_by ^ by',
|
|
138
142
|
'select_order_by_ > name > select_order_by_a ^ columns',
|
|
139
143
|
'select_order_by_a > , > select_order_by_a_comma_',
|
|
140
144
|
'- > ; > ',
|
|
141
145
|
'select_order_by_a_comma_ > name > select_order_by_a ^ columns',
|
|
142
|
-
'select_order_by_a_ > desc|asc > select_order_by_a_desc ^ desc,asc,limit',
|
|
146
|
+
'select_order_by_a_ > desc|asc > select_order_by_a_desc ^ desc,asc,limit,&',
|
|
143
147
|
'- > limit > select_where_sc_limit',
|
|
144
148
|
'- > ; > ',
|
|
149
|
+
'- > & > select_from_x$',
|
|
145
150
|
'select_order_by_a_desc > , > select_order_by_a_comma_',
|
|
146
151
|
'- > ; > ',
|
|
147
|
-
'select_order_by_a_desc_ > limit > select_where_sc_limit ^ limit',
|
|
152
|
+
'select_order_by_a_desc_ > limit > select_where_sc_limit ^ limit,&',
|
|
148
153
|
'- > ; > ',
|
|
154
|
+
'- > & > select_from_x$',
|
|
149
155
|
'select_where_sc_limit_ > num > select_where_sc_limit_num ^ 1',
|
|
150
156
|
'select_where_sc_limit_num > ; > ',
|
|
151
157
|
'select_where_sc_limit_num_rp__ > as > select_from_x_as ^ as',
|
|
@@ -201,7 +207,9 @@ SQL_SPEC = [
|
|
|
201
207
|
'insert_values > ( > insert_values_lp_',
|
|
202
208
|
'insert_values_lp_ > name|single|num > insert_values_lp_v ^ single',
|
|
203
209
|
'insert_values_lp_v > , > insert_values_lp_v_comma_',
|
|
210
|
+
'- > ) > insert_values_lp_v_rp_',
|
|
204
211
|
'insert_values_lp_v_comma_ > name|single|num > insert_values_lp_v',
|
|
212
|
+
'insert_values_lp_v_rp__ > & > insert_values_lp_v_rp_$ ^ &',
|
|
205
213
|
|
|
206
214
|
# <update_statement> ::= UPDATE <table_name>
|
|
207
215
|
# SET <set_clause_list>
|
|
@@ -222,8 +230,9 @@ SQL_SPEC = [
|
|
|
222
230
|
'update_set_a_op > name|single|num > update_set_sc ^ single',
|
|
223
231
|
'update_set_sc > , > update_set_sc_comma_',
|
|
224
232
|
'update_set_sc_comma_ > name > update_set_a ^ id',
|
|
225
|
-
'update_set_sc_ > , > update_set_sc_comma_ ^ where',
|
|
233
|
+
'update_set_sc_ > , > update_set_sc_comma_ ^ where,&',
|
|
226
234
|
'- > where > update_where',
|
|
235
|
+
'- > & > update_set_sc$ ^ &',
|
|
227
236
|
'update_where_ > name > update_where_a ^ id',
|
|
228
237
|
'update_where_a > comparison > update_where_a_op',
|
|
229
238
|
'update_where_a_ > comparison > update_where_a_op ^ =,<,<=,>,>=,<>,like,not,in',
|
|
@@ -240,7 +249,7 @@ SQL_SPEC = [
|
|
|
240
249
|
'update_where_a_in_lp_a_comma_ > name|single|num > update_where_a_in_lp_a ^ single',
|
|
241
250
|
'update_where_a_not_op > name|single|num > update_where_sc ^ single',
|
|
242
251
|
'update_where_a_op > name|single|num > update_where_sc ^ single',
|
|
243
|
-
'update_where_sc_ > and|or > update_where ^ and,or',
|
|
252
|
+
'update_where_sc_ > and|or > update_where ^ and,or,&',
|
|
244
253
|
|
|
245
254
|
# <delete_statement> ::= DELETE FROM <table_name> [ WHERE <search_condition> ]
|
|
246
255
|
|
|
@@ -421,12 +430,12 @@ CQL_SPEC = SQL_SPEC + [
|
|
|
421
430
|
|
|
422
431
|
' > clean > clean',
|
|
423
432
|
'clean_ > up > clean_up ^ up all export sessions,up export session',
|
|
424
|
-
'clean_up_ > all > clean_up_all ^ all export sessions,export
|
|
433
|
+
'clean_up_ > all > clean_up_all ^ all export sessions,export sessions',
|
|
425
434
|
'- > export > clean_up_export',
|
|
426
435
|
'clean_up_all_ > export > clean_up_all_export ^ export sessions',
|
|
427
436
|
'clean_up_all_export_ > sessions > clean_up_all_sessions ^ sessions',
|
|
428
|
-
'clean_up_export_ >
|
|
429
|
-
'
|
|
437
|
+
'clean_up_export_ > sessions > clean_up_export_sessions ^ sessions',
|
|
438
|
+
'clean_up_export_sessions_ > name > clean_up_export_sessions$ ^ export-sessions',
|
|
430
439
|
]
|
|
431
440
|
|
|
432
441
|
CQL_KEYWORDS = SQL_KEYWORDS + [
|
|
@@ -546,7 +555,7 @@ class SqlStateMachine(StateMachine[Token]):
|
|
|
546
555
|
elif token.ttype == TOKEN.Operator.Comparison:
|
|
547
556
|
it = 'comparison'
|
|
548
557
|
|
|
549
|
-
|
|
558
|
+
with log_exc(False):
|
|
550
559
|
# print(f'\n{state.to_s} > {it} > ', end='')
|
|
551
560
|
if comeback_state:
|
|
552
561
|
state = comeback_state
|
|
@@ -557,8 +566,6 @@ class SqlStateMachine(StateMachine[Token]):
|
|
|
557
566
|
|
|
558
567
|
if last_name:
|
|
559
568
|
state.context['last_name'] = last_name
|
|
560
|
-
except:
|
|
561
|
-
pass
|
|
562
569
|
|
|
563
570
|
return state
|
|
564
571
|
|
adam/sso/authn_ad.py
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import re
|
|
3
|
-
import traceback
|
|
4
3
|
import jwt
|
|
5
4
|
import requests
|
|
6
5
|
from urllib.parse import urlparse, parse_qs
|
|
@@ -8,6 +7,7 @@ from urllib.parse import urlparse, parse_qs
|
|
|
8
7
|
from adam.log import Log
|
|
9
8
|
from adam.sso.authenticator import Authenticator
|
|
10
9
|
from adam.sso.id_token import IdToken
|
|
10
|
+
from adam.utils import debug, log_exc
|
|
11
11
|
from .idp_login import IdpLogin
|
|
12
12
|
from adam.config import Config
|
|
13
13
|
|
|
@@ -33,7 +33,7 @@ class AdAuthenticator(Authenticator):
|
|
|
33
33
|
|
|
34
34
|
session = requests.Session()
|
|
35
35
|
r = session.get(idp_uri)
|
|
36
|
-
|
|
36
|
+
debug(f'{r.status_code} {idp_uri}')
|
|
37
37
|
|
|
38
38
|
config = self.validate_and_return_config(r)
|
|
39
39
|
|
|
@@ -52,7 +52,7 @@ class AdAuthenticator(Authenticator):
|
|
|
52
52
|
r = session.post(login_uri, data=body, headers={
|
|
53
53
|
'Content-Type': 'application/x-www-form-urlencoded'
|
|
54
54
|
})
|
|
55
|
-
|
|
55
|
+
debug(f'{r.status_code} {login_uri}')
|
|
56
56
|
|
|
57
57
|
config = self.validate_and_return_config(r)
|
|
58
58
|
|
|
@@ -69,7 +69,7 @@ class AdAuthenticator(Authenticator):
|
|
|
69
69
|
r = session.post(kmsi_uri, data=body, headers={
|
|
70
70
|
'Content-Type': 'application/x-www-form-urlencoded'
|
|
71
71
|
})
|
|
72
|
-
|
|
72
|
+
debug(f'{r.status_code} {kmsi_uri}')
|
|
73
73
|
|
|
74
74
|
if (config := self.extract_config_object(r.text)):
|
|
75
75
|
if 'sErrorCode' in config and config['sErrorCode'] == '50058':
|
|
@@ -101,7 +101,7 @@ class AdAuthenticator(Authenticator):
|
|
|
101
101
|
|
|
102
102
|
def validate_and_return_config(self, r: requests.Response):
|
|
103
103
|
if r.status_code < 200 or r.status_code >= 300:
|
|
104
|
-
|
|
104
|
+
debug(r.text)
|
|
105
105
|
|
|
106
106
|
return None
|
|
107
107
|
|
|
@@ -138,7 +138,7 @@ class AdAuthenticator(Authenticator):
|
|
|
138
138
|
|
|
139
139
|
def parse_id_token(self, id_token: str) -> IdToken:
|
|
140
140
|
jwks_url = Config().get('idps.ad.jwks-uri', '')
|
|
141
|
-
|
|
141
|
+
with log_exc():
|
|
142
142
|
jwks_client = jwt.PyJWKClient(jwks_url, cache_jwk_set=True, lifespan=360)
|
|
143
143
|
signing_key = jwks_client.get_signing_key_from_jwt(id_token)
|
|
144
144
|
data = jwt.decode(
|
|
@@ -163,7 +163,5 @@ class AdAuthenticator(Authenticator):
|
|
|
163
163
|
nbf=data['nbf'] if 'nbf' in data else 0,
|
|
164
164
|
exp=data['exp'] if 'exp' in data else 0
|
|
165
165
|
)
|
|
166
|
-
except:
|
|
167
|
-
Config().debug(traceback.format_exc())
|
|
168
166
|
|
|
169
167
|
return None
|
adam/sso/authn_okta.py
CHANGED
|
@@ -8,7 +8,7 @@ from adam.sso.id_token import IdToken
|
|
|
8
8
|
|
|
9
9
|
from .idp_login import IdpLogin
|
|
10
10
|
from adam.config import Config
|
|
11
|
-
from adam.utils import log2
|
|
11
|
+
from adam.utils import debug, log2, log_exc
|
|
12
12
|
|
|
13
13
|
class OktaException(Exception):
|
|
14
14
|
pass
|
|
@@ -49,7 +49,7 @@ class OktaAuthenticator(Authenticator):
|
|
|
49
49
|
|
|
50
50
|
session = requests.Session()
|
|
51
51
|
response = session.post(authn_uri, headers=headers, data=json.dumps(payload))
|
|
52
|
-
|
|
52
|
+
debug(f'{response.status_code} {authn_uri}')
|
|
53
53
|
auth_response = response.json()
|
|
54
54
|
|
|
55
55
|
if 'sessionToken' not in auth_response:
|
|
@@ -59,7 +59,7 @@ class OktaAuthenticator(Authenticator):
|
|
|
59
59
|
|
|
60
60
|
url = f'{idp_uri}&sessionToken={session_token}'
|
|
61
61
|
r = session.get(url)
|
|
62
|
-
|
|
62
|
+
debug(f'{r.status_code} {url}')
|
|
63
63
|
|
|
64
64
|
id_token = OktaAuthenticator().extract(r.text, r'.*name=\"id_token\" value=\"(.*?)\".*')
|
|
65
65
|
if not id_token:
|
|
@@ -95,7 +95,7 @@ class OktaAuthenticator(Authenticator):
|
|
|
95
95
|
return None
|
|
96
96
|
|
|
97
97
|
jwks_url = Config().get('idps.okta.jwks-uri', 'https://c3energy.okta.com/oauth2/v1/keys')
|
|
98
|
-
|
|
98
|
+
with log_exc():
|
|
99
99
|
jwks_client = jwt.PyJWKClient(jwks_url, cache_jwk_set=True, lifespan=360)
|
|
100
100
|
signing_key = jwks_client.get_signing_key_from_jwt(id_token)
|
|
101
101
|
data = jwt.decode(
|
|
@@ -121,7 +121,5 @@ class OktaAuthenticator(Authenticator):
|
|
|
121
121
|
nbf=data['nbf'] if 'nbf' in data else 0,
|
|
122
122
|
exp=data['exp'] if 'exp' in data else 0
|
|
123
123
|
)
|
|
124
|
-
except:
|
|
125
|
-
pass
|
|
126
124
|
|
|
127
125
|
return None
|