kaqing 2.0.83__py3-none-any.whl → 2.0.85__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/batch.py +10 -0
- adam/commands/audit/__init__.py +0 -0
- adam/commands/audit/audit.py +60 -0
- adam/commands/audit/audit_repair_tables.py +42 -0
- adam/commands/cd.py +3 -1
- adam/commands/command.py +7 -4
- adam/commands/devices.py +29 -0
- adam/commands/ls.py +6 -0
- adam/commands/pwd.py +3 -0
- adam/embedded_params.py +1 -1
- adam/repl.py +17 -5
- adam/repl_commands.py +5 -3
- adam/repl_state.py +4 -1
- adam/sql/state_machine.py +3 -2
- adam/utils_athena.py +62 -0
- adam/version.py +1 -1
- {kaqing-2.0.83.dist-info → kaqing-2.0.85.dist-info}/METADATA +1 -1
- {kaqing-2.0.83.dist-info → kaqing-2.0.85.dist-info}/RECORD +21 -17
- {kaqing-2.0.83.dist-info → kaqing-2.0.85.dist-info}/WHEEL +0 -0
- {kaqing-2.0.83.dist-info → kaqing-2.0.85.dist-info}/entry_points.txt +0 -0
- {kaqing-2.0.83.dist-info → kaqing-2.0.85.dist-info}/top_level.txt +0 -0
adam/batch.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import click
|
|
2
2
|
|
|
3
|
+
from adam.commands.audit.audit import Audit, AuditCommandHelper
|
|
3
4
|
from adam.commands.bash import Bash
|
|
4
5
|
from adam.commands.check import Check, CheckCommandHelper
|
|
5
6
|
from adam.commands.cp import ClipboardCopy, CopyCommandHelper
|
|
@@ -29,6 +30,15 @@ from adam.repl import enter_repl
|
|
|
29
30
|
from adam.repl_state import ReplState
|
|
30
31
|
from adam.cli_group import cli
|
|
31
32
|
|
|
33
|
+
@cli.command(context_settings=dict(ignore_unknown_options=True, allow_extra_args=True), cls=AuditCommandHelper, help='Run audit functions.')
|
|
34
|
+
@click.option('--kubeconfig', '-k', required=False, metavar='path', help='path to kubeconfig file')
|
|
35
|
+
@click.option('--config', default='params.yaml', metavar='path', help='path to kaqing parameters file')
|
|
36
|
+
@click.option('--param', '-v', multiple=True, metavar='<key>=<value>', help='parameter override')
|
|
37
|
+
@click.argument('extra_args', nargs=-1, metavar='repair', type=click.UNPROCESSED)
|
|
38
|
+
def audit(kubeconfig: str, config: str, param: list[str], extra_args):
|
|
39
|
+
run_command(Audit(), kubeconfig, config, param, None, None, None, extra_args)
|
|
40
|
+
|
|
41
|
+
|
|
32
42
|
@cli.command(context_settings=dict(ignore_unknown_options=True, allow_extra_args=True), cls=ClusterOrPodCommandHelper, help='Run a single bash command.')
|
|
33
43
|
@click.option('--kubeconfig', '-k', required=False, metavar='path', help='path to kubeconfig file')
|
|
34
44
|
@click.option('--config', default='params.yaml', metavar='path', help='path to kaqing parameters file')
|
|
File without changes
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import click
|
|
2
|
+
|
|
3
|
+
from adam.commands.audit.audit_repair_tables import AuditRepairTables
|
|
4
|
+
from adam.commands.command import Command
|
|
5
|
+
from adam.repl_state import ReplState
|
|
6
|
+
from adam.sql.sql_completer import SqlCompleter
|
|
7
|
+
from adam.utils import log2
|
|
8
|
+
from adam.utils_athena import audit_table_names, run_audit_query
|
|
9
|
+
|
|
10
|
+
class Audit(Command):
|
|
11
|
+
COMMAND = 'audit'
|
|
12
|
+
|
|
13
|
+
# the singleton pattern
|
|
14
|
+
def __new__(cls, *args, **kwargs):
|
|
15
|
+
if not hasattr(cls, 'instance'): cls.instance = super(Audit, cls).__new__(cls)
|
|
16
|
+
|
|
17
|
+
return cls.instance
|
|
18
|
+
|
|
19
|
+
def __init__(self, successor: Command=None):
|
|
20
|
+
super().__init__(successor)
|
|
21
|
+
|
|
22
|
+
def command(self):
|
|
23
|
+
return Audit.COMMAND
|
|
24
|
+
|
|
25
|
+
def run(self, cmd: str, state: ReplState):
|
|
26
|
+
if not(args := self.args(cmd)):
|
|
27
|
+
return super().run(cmd, state)
|
|
28
|
+
|
|
29
|
+
state, args = self.apply_state(args, state)
|
|
30
|
+
|
|
31
|
+
r = None
|
|
32
|
+
if len(args) > 0:
|
|
33
|
+
r = super().intermediate_run(cmd, state, args, Audit.cmd_list(), display_help=False)
|
|
34
|
+
|
|
35
|
+
if not r or isinstance(r, str) and r == 'command-missing':
|
|
36
|
+
sql = 'select * from audit order by ts desc limit 10'
|
|
37
|
+
if args:
|
|
38
|
+
sql = ' '.join(args)
|
|
39
|
+
else:
|
|
40
|
+
log2(sql)
|
|
41
|
+
|
|
42
|
+
run_audit_query(sql)
|
|
43
|
+
|
|
44
|
+
return state
|
|
45
|
+
|
|
46
|
+
def completion(self, state: ReplState):
|
|
47
|
+
if state.device == ReplState.L:
|
|
48
|
+
return super().completion(state) | SqlCompleter.completions(lambda: audit_table_names())
|
|
49
|
+
|
|
50
|
+
return {}
|
|
51
|
+
|
|
52
|
+
def cmd_list():
|
|
53
|
+
return [AuditRepairTables()]
|
|
54
|
+
|
|
55
|
+
def help(self, _: ReplState):
|
|
56
|
+
return f"{Audit.COMMAND} \t run AWS Athena query on audit database"
|
|
57
|
+
|
|
58
|
+
class AuditCommandHelper(click.Command):
|
|
59
|
+
def get_help(self, ctx: click.Context):
|
|
60
|
+
Command.intermediate_help(super().get_help(ctx), Audit.COMMAND, Audit.cmd_list(), show_cluster_help=False)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from adam.commands.command import Command
|
|
2
|
+
from adam.repl_state import ReplState
|
|
3
|
+
from adam.utils_athena import run_audit_query
|
|
4
|
+
|
|
5
|
+
class AuditRepairTables(Command):
|
|
6
|
+
COMMAND = 'audit repair'
|
|
7
|
+
|
|
8
|
+
# the singleton pattern
|
|
9
|
+
def __new__(cls, *args, **kwargs):
|
|
10
|
+
if not hasattr(cls, 'instance'): cls.instance = super(AuditRepairTables, cls).__new__(cls)
|
|
11
|
+
|
|
12
|
+
return cls.instance
|
|
13
|
+
|
|
14
|
+
def __init__(self, successor: Command=None):
|
|
15
|
+
super().__init__(successor)
|
|
16
|
+
|
|
17
|
+
def command(self):
|
|
18
|
+
return AuditRepairTables.COMMAND
|
|
19
|
+
|
|
20
|
+
def run(self, cmd: str, state: ReplState):
|
|
21
|
+
if not(args := self.args(cmd)):
|
|
22
|
+
return super().run(cmd, state)
|
|
23
|
+
|
|
24
|
+
state, args = self.apply_state(args, state)
|
|
25
|
+
|
|
26
|
+
tables = ['audit']
|
|
27
|
+
if args:
|
|
28
|
+
tables = args
|
|
29
|
+
|
|
30
|
+
for table in tables:
|
|
31
|
+
run_audit_query(f'MSCK REPAIR TABLE {table}')
|
|
32
|
+
|
|
33
|
+
return state
|
|
34
|
+
|
|
35
|
+
def completion(self, state: ReplState):
|
|
36
|
+
if state.device == ReplState.L:
|
|
37
|
+
return super().completion(state)
|
|
38
|
+
|
|
39
|
+
return {}
|
|
40
|
+
|
|
41
|
+
def help(self, _: ReplState):
|
|
42
|
+
return f"{AuditRepairTables.COMMAND} \t run MSCK REPAIR command for new partition discovery"
|
adam/commands/cd.py
CHANGED
|
@@ -59,6 +59,8 @@ class Cd(Command):
|
|
|
59
59
|
state.app_env = dir.split('@')[0]
|
|
60
60
|
else:
|
|
61
61
|
state.app_app = dir
|
|
62
|
+
elif state.device == ReplState.L:
|
|
63
|
+
pass
|
|
62
64
|
else:
|
|
63
65
|
if dir == '':
|
|
64
66
|
state.sts = None
|
|
@@ -103,7 +105,7 @@ class Cd(Command):
|
|
|
103
105
|
return {Cd.COMMAND: {'..': None} | {app[0].split('-')[1]: None for app in Apps.apps(state.app_env)}}
|
|
104
106
|
else:
|
|
105
107
|
return {Cd.COMMAND: {'..': None} | {env[0]: None for env in Apps.envs()}}
|
|
106
|
-
|
|
108
|
+
elif state.device == ReplState.C:
|
|
107
109
|
if state.pod:
|
|
108
110
|
return {Cd.COMMAND: {'..': None}}
|
|
109
111
|
elif state.sts:
|
adam/commands/command.py
CHANGED
|
@@ -104,19 +104,22 @@ class Command:
|
|
|
104
104
|
cmd = s
|
|
105
105
|
print()
|
|
106
106
|
|
|
107
|
-
def intermediate_run(self, cmd: str, state: ReplState, args: list[str], cmds: list['Command'], separator='\t'):
|
|
107
|
+
def intermediate_run(self, cmd: str, state: ReplState, args: list[str], cmds: list['Command'], separator='\t', display_help=True):
|
|
108
108
|
state, _ = self.apply_state(args, state)
|
|
109
109
|
|
|
110
110
|
if state.in_repl:
|
|
111
|
-
|
|
111
|
+
if display_help:
|
|
112
|
+
log(lines_to_tabular([c.help(state) for c in cmds], separator=separator))
|
|
112
113
|
|
|
113
114
|
return 'command-missing'
|
|
114
115
|
else:
|
|
115
116
|
# head with the Chain of Responsibility pattern
|
|
116
117
|
cmds = Command.chain(cmds)
|
|
117
118
|
if not cmds.run(cmd, state):
|
|
118
|
-
|
|
119
|
-
|
|
119
|
+
if display_help:
|
|
120
|
+
log2('* Command is missing.')
|
|
121
|
+
Command.display_help()
|
|
122
|
+
return 'command-missing'
|
|
120
123
|
|
|
121
124
|
return state
|
|
122
125
|
|
adam/commands/devices.py
CHANGED
|
@@ -1,6 +1,35 @@
|
|
|
1
1
|
from adam.commands.command import Command
|
|
2
2
|
from adam.repl_state import ReplState
|
|
3
3
|
|
|
4
|
+
class DeviceAuditLog(Command):
|
|
5
|
+
COMMAND = f'{ReplState.L}:'
|
|
6
|
+
|
|
7
|
+
# the singleton pattern
|
|
8
|
+
def __new__(cls, *args, **kwargs):
|
|
9
|
+
if not hasattr(cls, 'instance'): cls.instance = super(DeviceAuditLog, cls).__new__(cls)
|
|
10
|
+
|
|
11
|
+
return cls.instance
|
|
12
|
+
|
|
13
|
+
def __init__(self, successor: Command=None):
|
|
14
|
+
super().__init__(successor)
|
|
15
|
+
|
|
16
|
+
def command(self):
|
|
17
|
+
return DeviceAuditLog.COMMAND
|
|
18
|
+
|
|
19
|
+
def run(self, cmd: str, state: ReplState):
|
|
20
|
+
if not self.args(cmd):
|
|
21
|
+
return super().run(cmd, state)
|
|
22
|
+
|
|
23
|
+
state.device = ReplState.L
|
|
24
|
+
|
|
25
|
+
return state
|
|
26
|
+
|
|
27
|
+
def completion(self, state: ReplState):
|
|
28
|
+
return super().completion(state)
|
|
29
|
+
|
|
30
|
+
def help(self, _: ReplState):
|
|
31
|
+
return f'{DeviceAuditLog.COMMAND}\t move to Audit Log Operations device'
|
|
32
|
+
|
|
4
33
|
class DeviceCass(Command):
|
|
5
34
|
COMMAND = f'{ReplState.C}:'
|
|
6
35
|
|
adam/commands/ls.py
CHANGED
|
@@ -14,6 +14,7 @@ from adam.pod_exec_result import PodExecResult
|
|
|
14
14
|
from adam.repl_state import ReplState
|
|
15
15
|
from adam.utils import lines_to_tabular, log, log2
|
|
16
16
|
from adam.apps import Apps
|
|
17
|
+
from adam.utils_athena import audit_table_names
|
|
17
18
|
|
|
18
19
|
class Ls(Command):
|
|
19
20
|
COMMAND = 'ls'
|
|
@@ -71,6 +72,8 @@ class Ls(Command):
|
|
|
71
72
|
svcs = [n for n, ns in Apps.envs()]
|
|
72
73
|
|
|
73
74
|
log(lines_to_tabular(svcs, 'ENV', separator=','))
|
|
75
|
+
elif state.device == ReplState.L:
|
|
76
|
+
self.show_audit_log_tables()
|
|
74
77
|
else:
|
|
75
78
|
if state.pod:
|
|
76
79
|
r: PodExecResult = Cqlsh().run(f'cql describe tables', state)
|
|
@@ -127,6 +130,9 @@ class Ls(Command):
|
|
|
127
130
|
def show_pg_tables(self, pg: PostgresSession):
|
|
128
131
|
log(lines_to_tabular(pg_table_names(pg.namespace, pg.directory()), 'NAME', separator=','))
|
|
129
132
|
|
|
133
|
+
def show_audit_log_tables(self):
|
|
134
|
+
log(lines_to_tabular(audit_table_names(), 'NAME', separator=','))
|
|
135
|
+
|
|
130
136
|
def completion(self, state: ReplState):
|
|
131
137
|
if state.pod:
|
|
132
138
|
return {}
|
adam/commands/pwd.py
CHANGED
|
@@ -40,6 +40,8 @@ class Pwd(Command):
|
|
|
40
40
|
words.append(f'env/{state.app_env}')
|
|
41
41
|
if state.app_app:
|
|
42
42
|
words.append(f'app/{state.app_app}')
|
|
43
|
+
elif device == ReplState.L:
|
|
44
|
+
pass
|
|
43
45
|
else:
|
|
44
46
|
if state.sts:
|
|
45
47
|
words.append(f'sts/{state.sts}')
|
|
@@ -58,6 +60,7 @@ class Pwd(Command):
|
|
|
58
60
|
log(lines_to_tabular([
|
|
59
61
|
device_line(state, ReplState.A),
|
|
60
62
|
device_line(state, ReplState.C),
|
|
63
|
+
device_line(state, ReplState.L),
|
|
61
64
|
device_line(state, ReplState.P),
|
|
62
65
|
f'',
|
|
63
66
|
f'HOST\t{host}',
|
adam/embedded_params.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
def config():
|
|
2
|
-
return {'app': {'console-endpoint': 'https://{host}/{env}/{app}/static/console/index.html', 'cr': {'cluster-regex': '(.*?-.*?)-.*', 'group': 'ops.c3.ai', 'v': 'v2', 'plural': 'c3cassandras'}, 'label': 'c3__app_id-0', 'login': {'admin-group': '{host}/C3.ClusterAdmin', 'ingress': '{app_id}-k8singr-appleader-001', 'timeout': 5, 'session-check-url': 'https://{host}/{env}/{app}/api/8/C3/userSessionToken', 'cache-creds': True, 'cache-username': True, 'url': 'https://{host}/{env}/{app}', 'another': "You're logged in to {has}. However, for this app, you need to log in to {need}.", 'token-server-url': 'http://localhost:{port}', 'password-max-length': 128}, 'strip': '0'}, 'audit': {'endpoint': 'https://4psvtaxlcb.execute-api.us-west-2.amazonaws.com/prod/', 'workers': 3, 'timeout': 10}, '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/{}"}, 'get-host-id': {'workers': 32}, 'idps': {'ad': {'email-pattern': '.*@c3.ai', 'uri': 'https://login.microsoftonline.com/53ad779a-93e7-485c-ba20-ac8290d7252b/oauth2/v2.0/authorize?response_type=id_token&response_mode=form_post&client_id=00ff94a8-6b0a-4715-98e0-95490012d818&scope=openid+email+profile&redirect_uri=https%3A%2F%2Fplat.c3ci.cloud%2Fc3%2Fc3%2Foidc%2Flogin&nonce={nonce}&state=EMPTY', 'jwks-uri': 'https://login.microsoftonline.com/common/discovery/keys', 'contact': 'Please contact ted.tran@c3.ai.', 'whitelist-file': '/kaqing/members'}, 'okta': {'default': True, 'email-pattern': '.*@c3iot.com', 'uri': 'https://c3energy.okta.com/oauth2/v1/authorize?response_type=id_token&response_mode=form_post&client_id={client_id}&scope=openid+email+profile+groups&redirect_uri=https%3A%2F%2F{host}%2Fc3%2Fc3%2Foidc%2Flogin&nonce={nonce}&state=EMPTY', 'jwks-uri': 'https://c3energy.okta.com/oauth2/v1/keys'}}, 'issues': {'workers': 32}, 'logs': {'path': '/c3/cassandra/logs/system.log'}, 'medusa': {'restore-auto-complete': False}, 'nodetool': {'workers': 32, 'samples': 3, 'commands_in_line': 40}, 'pg': {'name-pattern': '^{namespace}.*-k8spg-.*', 'excludes': '.helm., -admin-secret', 'agent': {'name': 'ops-pg-agent', 'just-in-time': False, 'timeout': 86400, 'image': 'seanahnsf/kaqing'}, 'default-db': 'postgres', 'default-schema': 'postgres', 'secret': {'endpoint-key': 'postgres-db-endpoint', 'port-key': 'postgres-db-port', 'username-key': 'postgres-admin-username', 'password-key': 'postgres-admin-password'}}, 'pod': {'name': 'ops', 'image': 'seanahnsf/kaqing-cloud', 'sa': {'name': 'ops', 'proto': 'c3', 'additional-cluster-roles': 'c3aiops-k8ssandra-operator'}, 'label-selector': 'run=ops'}, 'preview': {'rows': 10}, 'processes': {'columns': 'pod,cpu,mem', 'header': 'POD_NAME,CPU,MEM/LIMIT'}, 'reaper': {'service-name': 'reaper-service', 'port-forward': {'timeout': 86400, 'local-port': 9001}, 'abort-runs-batch': 10, 'show-runs-batch': 100, 'pod': {'cluster-regex': '(.*?-.*?-.*?-.*?)-.*', 'label-selector': 'k8ssandra.io/reaper={cluster}-reaper'}, 'secret': {'cluster-regex': '(.*?-.*?)-.*', 'name': '{cluster}-reaper-ui', 'password-item': 'password'}}, 'repair': {'log-path': '/home/cassrepair/logs/', 'image': 'ci-registry.c3iot.io/cloudops/cassrepair:2.0.14', 'secret': 'ciregistryc3iotio', 'env': {'interval': 24, 'timeout': 60, 'pr': False, 'runs': 1}}, 'repl': {'start-drive': 'a', 'auto-enter-app': 'c3/c3', 'auto-enter-only-cluster': 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}}
|
|
2
|
+
return {'app': {'console-endpoint': 'https://{host}/{env}/{app}/static/console/index.html', 'cr': {'cluster-regex': '(.*?-.*?)-.*', 'group': 'ops.c3.ai', 'v': 'v2', 'plural': 'c3cassandras'}, 'label': 'c3__app_id-0', 'login': {'admin-group': '{host}/C3.ClusterAdmin', 'ingress': '{app_id}-k8singr-appleader-001', 'timeout': 5, 'session-check-url': 'https://{host}/{env}/{app}/api/8/C3/userSessionToken', 'cache-creds': True, 'cache-username': True, 'url': 'https://{host}/{env}/{app}', 'another': "You're logged in to {has}. However, for this app, you need to log in to {need}.", 'token-server-url': 'http://localhost:{port}', 'password-max-length': 128}, 'strip': '0'}, 'audit': {'endpoint': 'https://4psvtaxlcb.execute-api.us-west-2.amazonaws.com/prod/', 'workers': 3, 'timeout': 10, 'athena': {'region': 'us-west-2', 'catalog': 'AwsDataCatalog', 'database': 'audit', 'output': 's3://s3.ops--audit/ddl/results'}}, '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/{}"}, 'get-host-id': {'workers': 32}, 'idps': {'ad': {'email-pattern': '.*@c3.ai', 'uri': 'https://login.microsoftonline.com/53ad779a-93e7-485c-ba20-ac8290d7252b/oauth2/v2.0/authorize?response_type=id_token&response_mode=form_post&client_id=00ff94a8-6b0a-4715-98e0-95490012d818&scope=openid+email+profile&redirect_uri=https%3A%2F%2Fplat.c3ci.cloud%2Fc3%2Fc3%2Foidc%2Flogin&nonce={nonce}&state=EMPTY', 'jwks-uri': 'https://login.microsoftonline.com/common/discovery/keys', 'contact': 'Please contact ted.tran@c3.ai.', 'whitelist-file': '/kaqing/members'}, 'okta': {'default': True, 'email-pattern': '.*@c3iot.com', 'uri': 'https://c3energy.okta.com/oauth2/v1/authorize?response_type=id_token&response_mode=form_post&client_id={client_id}&scope=openid+email+profile+groups&redirect_uri=https%3A%2F%2F{host}%2Fc3%2Fc3%2Foidc%2Flogin&nonce={nonce}&state=EMPTY', 'jwks-uri': 'https://c3energy.okta.com/oauth2/v1/keys'}}, 'issues': {'workers': 32}, 'logs': {'path': '/c3/cassandra/logs/system.log'}, 'medusa': {'restore-auto-complete': False}, 'nodetool': {'workers': 32, 'samples': 3, 'commands_in_line': 40}, 'pg': {'name-pattern': '^{namespace}.*-k8spg-.*', 'excludes': '.helm., -admin-secret', 'agent': {'name': 'ops-pg-agent', 'just-in-time': False, 'timeout': 86400, 'image': 'seanahnsf/kaqing'}, 'default-db': 'postgres', 'default-schema': 'postgres', 'secret': {'endpoint-key': 'postgres-db-endpoint', 'port-key': 'postgres-db-port', 'username-key': 'postgres-admin-username', 'password-key': 'postgres-admin-password'}}, 'pod': {'name': 'ops', 'image': 'seanahnsf/kaqing-cloud', 'sa': {'name': 'ops', 'proto': 'c3', 'additional-cluster-roles': 'c3aiops-k8ssandra-operator'}, 'label-selector': 'run=ops'}, 'preview': {'rows': 10}, 'processes': {'columns': 'pod,cpu,mem', 'header': 'POD_NAME,CPU,MEM/LIMIT'}, 'reaper': {'service-name': 'reaper-service', 'port-forward': {'timeout': 86400, 'local-port': 9001}, 'abort-runs-batch': 10, 'show-runs-batch': 100, 'pod': {'cluster-regex': '(.*?-.*?-.*?-.*?)-.*', 'label-selector': 'k8ssandra.io/reaper={cluster}-reaper'}, 'secret': {'cluster-regex': '(.*?-.*?)-.*', 'name': '{cluster}-reaper-ui', 'password-item': 'password'}}, 'repair': {'log-path': '/home/cassrepair/logs/', 'image': 'ci-registry.c3iot.io/cloudops/cassrepair:2.0.14', 'secret': 'ciregistryc3iotio', 'env': {'interval': 24, 'timeout': 60, 'pr': False, 'runs': 1}}, 'repl': {'start-drive': 'a', 'auto-enter-app': 'c3/c3', 'auto-enter-only-cluster': 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/repl.py
CHANGED
|
@@ -51,6 +51,8 @@ def enter_repl(state: ReplState):
|
|
|
51
51
|
msg += state.app_env
|
|
52
52
|
if state.app_app:
|
|
53
53
|
msg += f'/{state.app_app}'
|
|
54
|
+
elif state.device == ReplState.L:
|
|
55
|
+
msg = f'{ReplState.L}:'
|
|
54
56
|
else:
|
|
55
57
|
msg = f'{ReplState.C}:'
|
|
56
58
|
if state.pod:
|
|
@@ -97,6 +99,9 @@ def enter_repl(state: ReplState):
|
|
|
97
99
|
event.app.current_buffer.text = ''
|
|
98
100
|
|
|
99
101
|
with concurrent.futures.ThreadPoolExecutor(max_workers=Config().get('audit.workers', 3)) as executor:
|
|
102
|
+
# warm up AWS lambda - this log line may timeout and get lost, which is fine
|
|
103
|
+
executor.submit(audit_log, 'entering kaqing repl', state)
|
|
104
|
+
|
|
100
105
|
# use sorted command list only for auto-completion
|
|
101
106
|
sorted_cmds = sorted(cmd_list, key=lambda cmd: cmd.command())
|
|
102
107
|
while True:
|
|
@@ -142,6 +147,10 @@ def enter_repl(state: ReplState):
|
|
|
142
147
|
c_sql_tried = True
|
|
143
148
|
cmd = f'app {cmd}'
|
|
144
149
|
cmds.run(cmd, state)
|
|
150
|
+
elif state.device == ReplState.L:
|
|
151
|
+
c_sql_tried = True
|
|
152
|
+
cmd = f'audit {cmd}'
|
|
153
|
+
cmds.run(cmd, state)
|
|
145
154
|
elif state.sts:
|
|
146
155
|
c_sql_tried = True
|
|
147
156
|
cmd = f'cql {cmd}'
|
|
@@ -178,11 +187,14 @@ def audit_log(cmd: str, state: ReplState):
|
|
|
178
187
|
'line': cmd.replace('"', '""').replace('\n', ' '),
|
|
179
188
|
}
|
|
180
189
|
audit_endpoint = Config().get("audit.endpoint", "https://4psvtaxlcb.execute-api.us-west-2.amazonaws.com/prod/")
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
190
|
+
try:
|
|
191
|
+
response = requests.post(audit_endpoint, json=payload, timeout=Config().get("audit.timeout", 10))
|
|
192
|
+
if response.status_code in [200, 201]:
|
|
193
|
+
Config().debug(response.text)
|
|
194
|
+
else:
|
|
195
|
+
log2(f"Error: {response.status_code} {response.text}")
|
|
196
|
+
except requests.exceptions.Timeout as e:
|
|
197
|
+
log2(f"Timeout occurred: {e}")
|
|
186
198
|
|
|
187
199
|
@cli.command(context_settings=dict(ignore_unknown_options=True, allow_extra_args=True), cls=ClusterCommandHelper, help="Enter interactive shell.")
|
|
188
200
|
@click.option('--kubeconfig', '-k', required=False, metavar='path', help='path to kubeconfig file')
|
adam/repl_commands.py
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from adam.commands.alter_tables import AlterTables
|
|
2
2
|
from adam.commands.app import App
|
|
3
3
|
from adam.commands.app_ping import AppPing
|
|
4
|
+
from adam.commands.audit.audit import Audit
|
|
5
|
+
from adam.commands.audit.audit_repair_tables import AuditRepairTables
|
|
4
6
|
from adam.commands.deploy.code_start import CodeStart
|
|
5
7
|
from adam.commands.deploy.code_stop import CodeStop
|
|
6
8
|
from adam.commands.deploy.deploy import Deploy
|
|
@@ -24,7 +26,7 @@ from adam.commands.cd import Cd
|
|
|
24
26
|
from adam.commands.check import Check
|
|
25
27
|
from adam.commands.command import Command
|
|
26
28
|
from adam.commands.cql.cqlsh import Cqlsh
|
|
27
|
-
from adam.commands.devices import DeviceApp, DeviceCass, DevicePostgres
|
|
29
|
+
from adam.commands.devices import DeviceApp, DeviceAuditLog, DeviceCass, DevicePostgres
|
|
28
30
|
from adam.commands.exit import Exit
|
|
29
31
|
from adam.commands.medusa.medusa import Medusa
|
|
30
32
|
from adam.commands.param_get import GetParam
|
|
@@ -77,7 +79,7 @@ class ReplCommands:
|
|
|
77
79
|
return deduped
|
|
78
80
|
|
|
79
81
|
def navigation() -> list[Command]:
|
|
80
|
-
return [Ls(), PreviewTable(), DeviceApp(), DevicePostgres(), DeviceCass(), Cd(), Pwd(), ClipboardCopy(),
|
|
82
|
+
return [Ls(), PreviewTable(), DeviceApp(), DevicePostgres(), DeviceCass(), DeviceAuditLog(), Cd(), Pwd(), ClipboardCopy(),
|
|
81
83
|
GetParam(), SetParam(), ShowParams(), ShowKubectlCommands(), ShowLogin(), ShowAdam(), ShowHost()]
|
|
82
84
|
|
|
83
85
|
def cassandra_check() -> list[Command]:
|
|
@@ -89,7 +91,7 @@ class ReplCommands:
|
|
|
89
91
|
|
|
90
92
|
def tools() -> list[Command]:
|
|
91
93
|
return [Cqlsh(), Postgres(), Bash(), Shell(), CodeStart(), CodeStop(), DeployFrontend(), UndeployFrontend(),
|
|
92
|
-
DeployPod(), UndeployPod(), DeployPgAgent(), UndeployPgAgent()]
|
|
94
|
+
DeployPod(), UndeployPod(), DeployPgAgent(), UndeployPgAgent(), AuditRepairTables(), Audit()]
|
|
93
95
|
|
|
94
96
|
def app() -> list[Command]:
|
|
95
97
|
return [ShowAppActions(), ShowAppId(), ShowAppQueues(), AppPing(), App()]
|
adam/repl_state.py
CHANGED
|
@@ -48,6 +48,7 @@ class RequiredState(Enum):
|
|
|
48
48
|
class ReplState:
|
|
49
49
|
A = 'a'
|
|
50
50
|
C = 'c'
|
|
51
|
+
L = 'l'
|
|
51
52
|
P = 'p'
|
|
52
53
|
|
|
53
54
|
def __init__(self, device: str = None,
|
|
@@ -129,7 +130,7 @@ class ReplState:
|
|
|
129
130
|
if index < 6:
|
|
130
131
|
state = copy.copy(state)
|
|
131
132
|
|
|
132
|
-
groups = re.match(r'^([a|c|p]):(.*)$', arg)
|
|
133
|
+
groups = re.match(r'^([a|c|l|p]):(.*)$', arg)
|
|
133
134
|
if groups:
|
|
134
135
|
if groups[1] == 'p':
|
|
135
136
|
state.device = 'p'
|
|
@@ -146,6 +147,8 @@ class ReplState:
|
|
|
146
147
|
state.namespace = p_and_ns[1]
|
|
147
148
|
elif ns := KubeContext.in_cluster_namespace():
|
|
148
149
|
state.namespace = ns
|
|
150
|
+
elif groups[1] == 'l':
|
|
151
|
+
state.device = 'l'
|
|
149
152
|
else:
|
|
150
153
|
state.device = 'a'
|
|
151
154
|
if path := groups[2]:
|
adam/sql/state_machine.py
CHANGED
|
@@ -134,7 +134,7 @@ SPEC = [
|
|
|
134
134
|
'select_a > , > select_a_comma_',
|
|
135
135
|
'select_a_comma_ > name|* > select_a ^ *',
|
|
136
136
|
'select_a_ > from > select_from ^ from',
|
|
137
|
-
'select_from_ > name
|
|
137
|
+
'select_from_ > name|audit > select_from_x ^ (select,tables',
|
|
138
138
|
'- > ( > select_from_lp_',
|
|
139
139
|
'- < ) > select_from_sq',
|
|
140
140
|
'select_from_lp_ > select > select',
|
|
@@ -269,7 +269,8 @@ KEYWORDS = [
|
|
|
269
269
|
'left join', 'right outer join', 'right join', 'full join', 'full outer join',
|
|
270
270
|
'insert', 'into', 'values',
|
|
271
271
|
'update', 'where', 'set',
|
|
272
|
-
'delete'
|
|
272
|
+
'delete',
|
|
273
|
+
'audit'
|
|
273
274
|
]
|
|
274
275
|
|
|
275
276
|
class StateTo:
|
adam/utils_athena.py
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import functools
|
|
2
|
+
import time
|
|
3
|
+
import boto3
|
|
4
|
+
|
|
5
|
+
from adam.config import Config
|
|
6
|
+
from adam.utils import lines_to_tabular, log, log2
|
|
7
|
+
|
|
8
|
+
@functools.lru_cache()
|
|
9
|
+
def audit_table_names():
|
|
10
|
+
region_name = Config().get('audit.athena.region', 'us-west-2')
|
|
11
|
+
database_name = Config().get('audit.athena.database', 'audit')
|
|
12
|
+
catalog_name = Config().get('audit.athena.catalog', 'AwsDataCatalog')
|
|
13
|
+
|
|
14
|
+
athena_client = boto3.client('athena', region_name=region_name)
|
|
15
|
+
paginator = athena_client.get_paginator('list_table_metadata')
|
|
16
|
+
|
|
17
|
+
table_names = []
|
|
18
|
+
for page in paginator.paginate(CatalogName=catalog_name, DatabaseName=database_name):
|
|
19
|
+
for table_metadata in page.get('TableMetadataList', []):
|
|
20
|
+
table_names.append(table_metadata['Name'])
|
|
21
|
+
|
|
22
|
+
return table_names
|
|
23
|
+
|
|
24
|
+
def run_audit_query(sql: str):
|
|
25
|
+
athena_client = boto3.client('athena')
|
|
26
|
+
|
|
27
|
+
database_name = Config().get('audit.athena.database', 'audit')
|
|
28
|
+
s3_output_location = Config().get('audit.athena.output', 's3://s3.ops--audit/ddl/results')
|
|
29
|
+
|
|
30
|
+
response = athena_client.start_query_execution(
|
|
31
|
+
QueryString=sql,
|
|
32
|
+
QueryExecutionContext={
|
|
33
|
+
'Database': database_name
|
|
34
|
+
},
|
|
35
|
+
ResultConfiguration={
|
|
36
|
+
'OutputLocation': s3_output_location
|
|
37
|
+
}
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
query_execution_id = response['QueryExecutionId']
|
|
41
|
+
|
|
42
|
+
while True:
|
|
43
|
+
query_status = athena_client.get_query_execution(QueryExecutionId=query_execution_id)
|
|
44
|
+
state = query_status['QueryExecution']['Status']['State']
|
|
45
|
+
if state in ['SUCCEEDED', 'FAILED', 'CANCELLED']:
|
|
46
|
+
break
|
|
47
|
+
time.sleep(1)
|
|
48
|
+
|
|
49
|
+
if state == 'SUCCEEDED':
|
|
50
|
+
results_response = athena_client.get_query_results(QueryExecutionId=query_execution_id)
|
|
51
|
+
if results_response['ResultSet']['Rows']:
|
|
52
|
+
column_info = results_response['ResultSet']['Rows'][0]['Data']
|
|
53
|
+
columns = [col.get('VarCharValue') for col in column_info]
|
|
54
|
+
lines = []
|
|
55
|
+
for row in results_response['ResultSet']['Rows'][1:]:
|
|
56
|
+
row_data = [col.get('VarCharValue') for col in row['Data']]
|
|
57
|
+
lines.append('\t'.join(row_data))
|
|
58
|
+
|
|
59
|
+
log(lines_to_tabular(lines, header='\t'.join(columns), separator='\t'))
|
|
60
|
+
else:
|
|
61
|
+
log2(f"Query failed or was cancelled. State: {state}")
|
|
62
|
+
log2(f"Reason: {query_status['QueryExecution']['Status'].get('StateChangeReason')}")
|
adam/version.py
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
adam/__init__.py,sha256=oVw1FNd9HZPJ7wm6BNn5ybyNGJLjJ8kopMeBiwgMaOI,59
|
|
2
2
|
adam/app_session.py,sha256=Klypm4JYHOlovaRCHAZ2P_Mj_nheMlcQgX403R0TJGk,6969
|
|
3
3
|
adam/apps.py,sha256=UTpUJBAMRFvR8kJZwileGC0UmPvsOjJ_AgvWoGmnIFI,6701
|
|
4
|
-
adam/batch.py,sha256=
|
|
4
|
+
adam/batch.py,sha256=JIrYtZA797yg6F6KoP5rLjrmj_wCMVs_HkBB8CAiBJc,25251
|
|
5
5
|
adam/cli.py,sha256=03pIZdomAu7IL-GSP6Eun_PKwwISShRAmfx6eVRPGC0,458
|
|
6
6
|
adam/cli_group.py,sha256=W3zy1BghCtVcEXizq8fBH-93ZRVVwgAyGPzy0sHno1Y,593
|
|
7
7
|
adam/config.py,sha256=hDxd86MbKVVKoHhTT077L3YRKYcr0i6xVADLlnoE684,2818
|
|
8
8
|
adam/embedded_apps.py,sha256=lKPx63mKzJbNmwz0rgL4gF76M9fDGxraYTtNAIGnZ_s,419
|
|
9
|
-
adam/embedded_params.py,sha256=
|
|
9
|
+
adam/embedded_params.py,sha256=TGZ6j51c8jMjzDbzn4LU01fKZD9BfCfubQFfRNsk3ss,4831
|
|
10
10
|
adam/log.py,sha256=gg5DK52wLPc9cjykeh0WFHyAk1qI3HEpGaAK8W2dzXY,1146
|
|
11
11
|
adam/pod_exec_result.py,sha256=nq0xnCNOpUGBSijGF0H-YNrwBc9vUQs4DkvLMIFS5LQ,951
|
|
12
|
-
adam/repl.py,sha256=
|
|
13
|
-
adam/repl_commands.py,sha256=
|
|
12
|
+
adam/repl.py,sha256=gZlakdkKYreK6BQ2NvmTjvIDGVzTkNrmRbP4ZE8fEEI,9323
|
|
13
|
+
adam/repl_commands.py,sha256=1AFE8AJoyQdJd0tlcwtMnwMjV5G7jL9MDkxJZxdo150,4963
|
|
14
14
|
adam/repl_session.py,sha256=uIogcvWBh7wd8QQ-p_JgLsyJ8YJgINw5vOd6JIsd7Vo,472
|
|
15
|
-
adam/repl_state.py,sha256=
|
|
15
|
+
adam/repl_state.py,sha256=dXyGlWXcSsfCjrYwMhU44PVn_oThSZ8dhJ5HCVE8-qU,8743
|
|
16
16
|
adam/utils.py,sha256=sbsNZP3qGJtb6fXCa4dDXHry5ay9ev583cCZIQzy07s,7382
|
|
17
|
+
adam/utils_athena.py,sha256=_E-Ik-rgpIhDhpwlllH3qlyI3P_8Jcw9b9qSj2Ql2UM,2319
|
|
17
18
|
adam/utils_net.py,sha256=65fhBnWMCkhGtyHqz95qcHaCo35q-WX1RBkkXG8dKpI,416
|
|
18
|
-
adam/version.py,sha256=
|
|
19
|
+
adam/version.py,sha256=SfFdSx99xjv6dmyMa6T5bmSm3TNRAiaI4-KWzbffs6Q,139
|
|
19
20
|
adam/checks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
20
21
|
adam/checks/check.py,sha256=Qopr3huYcMu2bzQgb99dEUYjFzkjKHRI76S6KA9b9Rk,702
|
|
21
22
|
adam/checks/check_context.py,sha256=FEHkQ32jY1EDopQ2uYWqy9v7aEEX1orLpJWhopwAlh4,402
|
|
@@ -52,31 +53,34 @@ adam/commands/alter_tables.py,sha256=Q5vXHE4_1_6v6wtYwqST7_QwpXINb1xq0Sm448Z2Y7Q
|
|
|
52
53
|
adam/commands/app.py,sha256=7alV8wK801t67_rUe6EmhtHJTl-6K7fGCm6Uz1dDgpM,1963
|
|
53
54
|
adam/commands/app_ping.py,sha256=Xk7cfefphXM2w-UvpnhNUTZ3BU38f0deehUb2FEyLCI,1337
|
|
54
55
|
adam/commands/bash.py,sha256=1O9cCl9JHQdttqNAgdB44rO0NjCqHzHv4psAEQMJcjw,2714
|
|
55
|
-
adam/commands/cd.py,sha256=
|
|
56
|
+
adam/commands/cd.py,sha256=GyNyJnbxX7afrk7xwvXDhEtSdWnAgnz0dpDJXO2dO7w,4728
|
|
56
57
|
adam/commands/check.py,sha256=853FPfgTMGxQXI_5UaPAtzaSWB_BvEVm48EkJhsHe4w,2181
|
|
57
58
|
adam/commands/cli_commands.py,sha256=PEEyrG9yz7RAEZwHbbuFpyE3fVi8vrIWbr0d1H0Gp9o,3620
|
|
58
|
-
adam/commands/command.py,sha256=
|
|
59
|
+
adam/commands/command.py,sha256=w3AthcMShBfhVzRfFq3LhXN76pRNVAuqt5vdMkxHFls,4064
|
|
59
60
|
adam/commands/command_helpers.py,sha256=leOJJK1UXczNTJHN9TGMCbIpUpmpreULvQ-TvnsYS7w,1134
|
|
60
61
|
adam/commands/commands_utils.py,sha256=ShUcxtDSd9B3NM0GDj3NBvKdmjCGY8qXgeUJpzNF63E,3122
|
|
61
62
|
adam/commands/cp.py,sha256=dyQViRDPNqsKRkxPb7WyEVIBNw7YB6IfYa2q3VtfzyA,3107
|
|
62
|
-
adam/commands/devices.py,sha256=
|
|
63
|
+
adam/commands/devices.py,sha256=ygpvjYa_NcezM_hctGOAAuBEHiDJtLtJNlOcLGvFJAc,3184
|
|
63
64
|
adam/commands/exit.py,sha256=5MWUAmzYBlsrp0CoiTDB13SUkX9Ya18UlGeOIPia6TA,798
|
|
64
65
|
adam/commands/help.py,sha256=Ey3R1X8w_CMhdADI0t8dSQ28euhDHheJm7NermiGni4,1645
|
|
65
66
|
adam/commands/issues.py,sha256=VS-PC7e-2lywsa-lbmoUX8IY77OPGzFudwbw1g8XmQc,2599
|
|
66
67
|
adam/commands/login.py,sha256=bj95WWIF7mJDJhnyS9T8xvaZUGL37dj7GlH8TgmODbk,1877
|
|
67
68
|
adam/commands/logs.py,sha256=T-O9DYXmWEm4G1I5SM6MwyeRwq2aT-WMqNW0XA2MWmo,1165
|
|
68
|
-
adam/commands/ls.py,sha256=
|
|
69
|
+
adam/commands/ls.py,sha256=aNBIoUUCFxWMJ9O6IV6qbw5XRHmaQqOD6dgjMf9EWkU,5766
|
|
69
70
|
adam/commands/nodetool.py,sha256=HV9yDzMhRjS4lw6UfV7Hc1pcmeSx5a1jU6cAEKSZ1Bg,2334
|
|
70
71
|
adam/commands/nodetool_commands.py,sha256=5IgWC3rmeDD1cgwqQjiiWzi-wJpJ3n_8pAzz_9phXuk,2635
|
|
71
72
|
adam/commands/param_get.py,sha256=kPAAppK2T0tEFRnSIVFLDPIIGHhgLA7drJhn8TRyvvE,1305
|
|
72
73
|
adam/commands/param_set.py,sha256=QDIuqfU80aWCB16OK49yf7XRaRTWwiLkwMsJuVikq9I,1271
|
|
73
74
|
adam/commands/preview_table.py,sha256=5im47Uk6RclgkZD-Ci0lBs1eosnfvBtKt2lgsb_bohs,3068
|
|
74
|
-
adam/commands/pwd.py,sha256=
|
|
75
|
+
adam/commands/pwd.py,sha256=izzMhIcbHjky2VA-84w5pt4nQDDUqahg3t34qy5yxMM,2446
|
|
75
76
|
adam/commands/report.py,sha256=Ky45LIzSlB_X4V12JZWjU3SA2u4_FKRencRTq7psOWU,1944
|
|
76
77
|
adam/commands/restart.py,sha256=Hik1t5rjH2ATZv4tzwrGB3e44b3dNuATgY327_Nb8Bs,2044
|
|
77
78
|
adam/commands/rollout.py,sha256=52_4ijna3v-8Oug12et43DRHFDNhiN34p6xLTQmhdbQ,2959
|
|
78
79
|
adam/commands/shell.py,sha256=wY_PIx7Lt6vuxhFArlfxdEnBbrouCJ3yNHhFn17DEqw,848
|
|
79
80
|
adam/commands/watch.py,sha256=mmBFpB8T1V7zrNs5b2YNyDDztMym_ILPDdkrbdAXTas,2438
|
|
81
|
+
adam/commands/audit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
82
|
+
adam/commands/audit/audit.py,sha256=xLXwDSYYTuVr_O5gDo87Wa4qSR71zjnj1Q6vN8dF_dE,1864
|
|
83
|
+
adam/commands/audit/audit_repair_tables.py,sha256=5Glsy29md3KH_4_smuVBeu6c4zygICPK8Jiv-fNRC38,1186
|
|
80
84
|
adam/commands/cql/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
81
85
|
adam/commands/cql/cql_completions.py,sha256=dXe51NTWEJis76587IWSn9Av-cjC0J6KMaxlBKfF4wM,411
|
|
82
86
|
adam/commands/cql/cql_table_completer.py,sha256=Tth6lmZ1eCEbJeAVZojTx594ttQeeVf-OjhhkSLyRnI,312
|
|
@@ -167,7 +171,7 @@ adam/k8s_utils/statefulsets.py,sha256=5g7KxGRHgEewT8rnZneDTaJDylUf-dHH2edWJEoorr
|
|
|
167
171
|
adam/k8s_utils/volumes.py,sha256=RIBmlOSWM3V3QVXLCFT0owVOyh4rGG1ETp521a-6ndo,1137
|
|
168
172
|
adam/sql/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
169
173
|
adam/sql/sql_completer.py,sha256=R5boj_bdHlzeJkGEy7XQDz_qtE-VF1yjg8pXn5zYGJA,2510
|
|
170
|
-
adam/sql/state_machine.py,sha256=
|
|
174
|
+
adam/sql/state_machine.py,sha256=6wOCVE86S6pPJhLvJudbYhBbKDqOmpcY2lAEK75pbm4,23200
|
|
171
175
|
adam/sql/term_completer.py,sha256=bNnHAVf9NZl52xS_BQpikbOK39gDBJADnT9gSvG0iqI,2539
|
|
172
176
|
adam/sso/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
173
177
|
adam/sso/authenticator.py,sha256=BCm16L9zf5aLU47-sTCnudn2zLPwd8M2wwRminJfsqw,615
|
|
@@ -179,8 +183,8 @@ adam/sso/idp.py,sha256=fvcwUw_URTgsO6ySaqTIw0zQT2qRO1IPSGhf6rPtybo,5804
|
|
|
179
183
|
adam/sso/idp_login.py,sha256=QAtCUeDTVWliJy40RK_oac8Vgybr13xH8wzeBoxPaa8,1754
|
|
180
184
|
adam/sso/idp_session.py,sha256=9BUHNRf70u4rVKrVY1HKPOEmOviXvkjam8WJxmXSKIM,1735
|
|
181
185
|
adam/sso/sso_config.py,sha256=5N8WZgIJQBtHUy585XLRWKjpU87_v6QluyNK9E27D5s,2459
|
|
182
|
-
kaqing-2.0.
|
|
183
|
-
kaqing-2.0.
|
|
184
|
-
kaqing-2.0.
|
|
185
|
-
kaqing-2.0.
|
|
186
|
-
kaqing-2.0.
|
|
186
|
+
kaqing-2.0.85.dist-info/METADATA,sha256=H9R7Qb1ZTmYMDrzCFBJziK45RLM3IDkx82kFaDk1kpE,132
|
|
187
|
+
kaqing-2.0.85.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
|
|
188
|
+
kaqing-2.0.85.dist-info/entry_points.txt,sha256=SkzhuQJUWsXOzHeZ5TgQ2c3_g53UGK23zzJU_JTZOZI,39
|
|
189
|
+
kaqing-2.0.85.dist-info/top_level.txt,sha256=8_2PZkwBb-xDcnc8a2rAbQeJhXKXskc7zTP7pSPa1fw,5
|
|
190
|
+
kaqing-2.0.85.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|