kaqing 2.0.95__py3-none-any.whl → 2.0.115__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 +1 -15
- adam/commands/alter_tables.py +3 -14
- adam/commands/app.py +3 -3
- adam/commands/app_ping.py +2 -2
- adam/commands/audit/audit.py +26 -11
- adam/commands/audit/audit_repair_tables.py +20 -37
- adam/commands/audit/audit_run.py +58 -0
- adam/commands/audit/show_last10.py +51 -0
- adam/commands/audit/show_slow10.py +50 -0
- adam/commands/audit/show_top10.py +49 -0
- adam/commands/audit/utils_show_top10.py +59 -0
- adam/commands/bash/bash.py +124 -0
- adam/commands/bash/bash_completer.py +93 -0
- adam/commands/cat.py +55 -0
- adam/commands/cd.py +23 -11
- adam/commands/check.py +6 -0
- adam/commands/code.py +60 -0
- adam/commands/command.py +9 -4
- adam/commands/commands_utils.py +1 -2
- adam/commands/cql/cql_completions.py +7 -3
- adam/commands/cql/cql_utils.py +100 -8
- adam/commands/cql/cqlsh.py +10 -5
- adam/commands/deploy/deploy.py +7 -1
- adam/commands/deploy/deploy_pg_agent.py +2 -2
- adam/commands/deploy/undeploy.py +7 -1
- adam/commands/deploy/undeploy_pg_agent.py +2 -2
- adam/commands/devices.py +29 -0
- adam/commands/export/__init__.py +0 -0
- adam/commands/export/export.py +60 -0
- adam/commands/export/export_on_x.py +76 -0
- adam/commands/export/export_rmdbs.py +65 -0
- adam/commands/export/export_select.py +68 -0
- adam/commands/export/export_use.py +56 -0
- adam/commands/export/utils_export.py +253 -0
- adam/commands/help.py +9 -5
- adam/commands/issues.py +6 -0
- adam/commands/kubectl.py +41 -0
- adam/commands/login.py +6 -3
- adam/commands/logs.py +1 -0
- adam/commands/ls.py +39 -27
- adam/commands/medusa/medusa_show_backupjobs.py +1 -0
- adam/commands/nodetool.py +5 -2
- adam/commands/postgres/postgres.py +4 -4
- adam/commands/postgres/{postgres_session.py → postgres_context.py} +26 -27
- adam/commands/postgres/postgres_utils.py +5 -5
- adam/commands/postgres/psql_completions.py +1 -1
- adam/commands/preview_table.py +18 -32
- adam/commands/pwd.py +4 -3
- adam/commands/reaper/reaper.py +3 -0
- adam/commands/repair/repair.py +3 -3
- adam/commands/report.py +6 -0
- adam/commands/show/show.py +3 -1
- adam/commands/show/show_app_actions.py +3 -0
- adam/commands/show/show_app_queues.py +3 -2
- adam/commands/show/show_login.py +3 -0
- adam/config.py +1 -1
- adam/embedded_params.py +1 -1
- adam/pod_exec_result.py +7 -1
- adam/repl.py +121 -97
- adam/repl_commands.py +29 -17
- adam/repl_state.py +224 -44
- adam/sql/sql_completer.py +86 -62
- adam/sql/sql_state_machine.py +563 -0
- adam/sql/term_completer.py +3 -0
- adam/utils_athena.py +108 -74
- adam/utils_audits.py +104 -0
- adam/utils_export.py +42 -0
- adam/utils_k8s/app_clusters.py +33 -0
- adam/utils_k8s/app_pods.py +31 -0
- adam/utils_k8s/cassandra_clusters.py +4 -5
- adam/utils_k8s/cassandra_nodes.py +4 -4
- adam/utils_k8s/pods.py +42 -6
- adam/utils_k8s/statefulsets.py +2 -2
- adam/version.py +1 -1
- {kaqing-2.0.95.dist-info → kaqing-2.0.115.dist-info}/METADATA +1 -1
- {kaqing-2.0.95.dist-info → kaqing-2.0.115.dist-info}/RECORD +80 -67
- adam/commands/bash.py +0 -92
- adam/commands/cql/cql_table_completer.py +0 -8
- adam/commands/describe/describe.py +0 -46
- adam/commands/describe/describe_keyspace.py +0 -60
- adam/commands/describe/describe_keyspaces.py +0 -50
- adam/commands/describe/describe_table.py +0 -60
- adam/commands/describe/describe_tables.py +0 -50
- adam/commands/postgres/psql_table_completer.py +0 -11
- adam/sql/state_machine.py +0 -460
- /adam/commands/{describe → bash}/__init__.py +0 -0
- {kaqing-2.0.95.dist-info → kaqing-2.0.115.dist-info}/WHEEL +0 -0
- {kaqing-2.0.95.dist-info → kaqing-2.0.115.dist-info}/entry_points.txt +0 -0
- {kaqing-2.0.95.dist-info → kaqing-2.0.115.dist-info}/top_level.txt +0 -0
adam/commands/cql/cqlsh.py
CHANGED
|
@@ -3,7 +3,8 @@ import click
|
|
|
3
3
|
from adam.commands.command import Command
|
|
4
4
|
from adam.commands.command_helpers import ClusterOrPodCommandHelper
|
|
5
5
|
from adam.commands.cql.cql_completions import cql_completions
|
|
6
|
-
from .
|
|
6
|
+
from adam.utils_k8s.statefulsets import StatefulSets
|
|
7
|
+
from .cql_utils import run_cql
|
|
7
8
|
from adam.repl_state import ReplState, RequiredState
|
|
8
9
|
from adam.utils import log, log2
|
|
9
10
|
|
|
@@ -33,11 +34,14 @@ class Cqlsh(Command):
|
|
|
33
34
|
if not self.validate_state(state):
|
|
34
35
|
return state
|
|
35
36
|
|
|
37
|
+
background = False
|
|
36
38
|
opts = []
|
|
37
39
|
cqls = []
|
|
38
|
-
for arg in args:
|
|
40
|
+
for index, arg in enumerate(args):
|
|
39
41
|
if arg.startswith('--'):
|
|
40
42
|
opts.append(arg)
|
|
43
|
+
elif index == len(args) -1 and arg == '&':
|
|
44
|
+
background = True
|
|
41
45
|
elif arg != '-e':
|
|
42
46
|
cqls.append(arg)
|
|
43
47
|
if not cqls:
|
|
@@ -51,7 +55,7 @@ class Cqlsh(Command):
|
|
|
51
55
|
return 'no-cql'
|
|
52
56
|
|
|
53
57
|
cql = ' '.join(cqls)
|
|
54
|
-
return run_cql(state, cql, opts, show_out=True)
|
|
58
|
+
return run_cql(state, cql, opts, show_out=True, background=background)
|
|
55
59
|
|
|
56
60
|
def completion(self, state: ReplState) -> dict[str, any]:
|
|
57
61
|
if state.device != state.C:
|
|
@@ -59,12 +63,13 @@ class Cqlsh(Command):
|
|
|
59
63
|
return {}
|
|
60
64
|
|
|
61
65
|
if state.sts or state.pod:
|
|
62
|
-
return
|
|
66
|
+
return cql_completions(state) | \
|
|
67
|
+
{f'@{p}': cql_completions(state) for p in StatefulSets.pod_names(state.sts, state.namespace)}
|
|
63
68
|
|
|
64
69
|
return {}
|
|
65
70
|
|
|
66
71
|
def help(self, _: ReplState) -> str:
|
|
67
|
-
return f'
|
|
72
|
+
return f'<cql-statements> [&]\t run cqlsh with queries'
|
|
68
73
|
|
|
69
74
|
class CqlCommandHelper(click.Command):
|
|
70
75
|
def get_help(self, ctx: click.Context):
|
adam/commands/deploy/deploy.py
CHANGED
|
@@ -4,7 +4,7 @@ from adam.commands.command import Command
|
|
|
4
4
|
from adam.commands.deploy.deploy_pg_agent import DeployPgAgent
|
|
5
5
|
from adam.commands.deploy.deploy_pod import DeployPod
|
|
6
6
|
from .deploy_frontend import DeployFrontend
|
|
7
|
-
from adam.repl_state import ReplState
|
|
7
|
+
from adam.repl_state import ReplState, RequiredState
|
|
8
8
|
|
|
9
9
|
class Deploy(Command):
|
|
10
10
|
COMMAND = 'deploy'
|
|
@@ -22,10 +22,16 @@ class Deploy(Command):
|
|
|
22
22
|
def command(self):
|
|
23
23
|
return Deploy.COMMAND
|
|
24
24
|
|
|
25
|
+
def required(self):
|
|
26
|
+
return RequiredState.NAMESPACE
|
|
27
|
+
|
|
25
28
|
def run(self, cmd: str, state: ReplState):
|
|
26
29
|
if not(args := self.args(cmd)):
|
|
27
30
|
return super().run(cmd, state)
|
|
28
31
|
|
|
32
|
+
if not self.validate_state(state):
|
|
33
|
+
return state
|
|
34
|
+
|
|
29
35
|
return super().intermediate_run(cmd, state, args, Deploy.cmd_list())
|
|
30
36
|
|
|
31
37
|
def cmd_list():
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from adam.commands.command import Command
|
|
2
|
-
from adam.commands.postgres.
|
|
2
|
+
from adam.commands.postgres.postgres_context import PostgresContext
|
|
3
3
|
from adam.config import Config
|
|
4
4
|
from adam.repl_state import ReplState, RequiredState
|
|
5
5
|
|
|
@@ -29,7 +29,7 @@ class DeployPgAgent(Command):
|
|
|
29
29
|
if not self.validate_state(state):
|
|
30
30
|
return state
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
PostgresContext.deploy_pg_agent(Config().get('pg.agent.name', 'ops-pg-agent'), state.namespace)
|
|
33
33
|
|
|
34
34
|
def completion(self, state: ReplState):
|
|
35
35
|
return super().completion(state)
|
adam/commands/deploy/undeploy.py
CHANGED
|
@@ -4,7 +4,7 @@ from adam.commands.command import Command
|
|
|
4
4
|
from adam.commands.deploy.undeploy_frontend import UndeployFrontend
|
|
5
5
|
from adam.commands.deploy.undeploy_pg_agent import UndeployPgAgent
|
|
6
6
|
from adam.commands.deploy.undeploy_pod import UndeployPod
|
|
7
|
-
from adam.repl_state import ReplState
|
|
7
|
+
from adam.repl_state import ReplState, RequiredState
|
|
8
8
|
|
|
9
9
|
class Undeploy(Command):
|
|
10
10
|
COMMAND = 'undeploy'
|
|
@@ -22,10 +22,16 @@ class Undeploy(Command):
|
|
|
22
22
|
def command(self):
|
|
23
23
|
return Undeploy.COMMAND
|
|
24
24
|
|
|
25
|
+
def required(self):
|
|
26
|
+
return RequiredState.NAMESPACE
|
|
27
|
+
|
|
25
28
|
def run(self, cmd: str, state: ReplState):
|
|
26
29
|
if not(args := self.args(cmd)):
|
|
27
30
|
return super().run(cmd, state)
|
|
28
31
|
|
|
32
|
+
if not self.validate_state(state):
|
|
33
|
+
return state
|
|
34
|
+
|
|
29
35
|
return super().intermediate_run(cmd, state, args, Undeploy.cmd_list())
|
|
30
36
|
|
|
31
37
|
def cmd_list():
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from adam.commands.command import Command
|
|
2
2
|
from adam.commands.deploy.deploy_utils import deleting
|
|
3
|
-
from adam.commands.postgres.
|
|
3
|
+
from adam.commands.postgres.postgres_context import PostgresContext
|
|
4
4
|
from adam.config import Config
|
|
5
5
|
from adam.repl_state import ReplState, RequiredState
|
|
6
6
|
|
|
@@ -30,7 +30,7 @@ class UndeployPgAgent(Command):
|
|
|
30
30
|
if not self.validate_state(state):
|
|
31
31
|
return state
|
|
32
32
|
|
|
33
|
-
deleting('pod', lambda:
|
|
33
|
+
deleting('pod', lambda: PostgresContext.undeploy_pg_agent(Config().get('pg.agent.name', 'ops-pg-agent'), state.namespace))
|
|
34
34
|
|
|
35
35
|
return state
|
|
36
36
|
|
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 DeviceExport(Command):
|
|
5
|
+
COMMAND = f'{ReplState.X}:'
|
|
6
|
+
|
|
7
|
+
# the singleton pattern
|
|
8
|
+
def __new__(cls, *args, **kwargs):
|
|
9
|
+
if not hasattr(cls, 'instance'): cls.instance = super(DeviceExport, 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 DeviceExport.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.X
|
|
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 Export Database Operations device'
|
|
32
|
+
|
|
4
33
|
class DeviceAuditLog(Command):
|
|
5
34
|
COMMAND = f'{ReplState.L}:'
|
|
6
35
|
|
|
File without changes
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
from adam.commands.export.utils_export import export_tables
|
|
2
|
+
from adam.commands.command import Command
|
|
3
|
+
from adam.commands.cql.cql_utils import cassandra_table_names
|
|
4
|
+
from adam.repl_state import ReplState, RequiredState
|
|
5
|
+
from adam.sql.sql_completer import SqlCompleter
|
|
6
|
+
from adam.utils_k8s.statefulsets import StatefulSets
|
|
7
|
+
|
|
8
|
+
class ExportTables(Command):
|
|
9
|
+
COMMAND = 'export'
|
|
10
|
+
|
|
11
|
+
# the singleton pattern
|
|
12
|
+
def __new__(cls, *args, **kwargs):
|
|
13
|
+
if not hasattr(cls, 'instance'): cls.instance = super(ExportTables, cls).__new__(cls)
|
|
14
|
+
|
|
15
|
+
return cls.instance
|
|
16
|
+
|
|
17
|
+
def __init__(self, successor: Command=None):
|
|
18
|
+
super().__init__(successor)
|
|
19
|
+
|
|
20
|
+
def command(self):
|
|
21
|
+
return ExportTables.COMMAND
|
|
22
|
+
|
|
23
|
+
def required(self):
|
|
24
|
+
return RequiredState.CLUSTER_OR_POD
|
|
25
|
+
|
|
26
|
+
def run(self, cmd: str, state: ReplState):
|
|
27
|
+
if not(args := self.args(cmd)):
|
|
28
|
+
return super().run(cmd, state)
|
|
29
|
+
|
|
30
|
+
state, args = self.apply_state(args, state)
|
|
31
|
+
if not self.validate_state(state):
|
|
32
|
+
return state
|
|
33
|
+
|
|
34
|
+
if not state.pod:
|
|
35
|
+
state.push()
|
|
36
|
+
state.pod = StatefulSets.pod_names(state.sts, state.namespace)[0]
|
|
37
|
+
try:
|
|
38
|
+
export_tables(args, state)
|
|
39
|
+
finally:
|
|
40
|
+
state.pop()
|
|
41
|
+
|
|
42
|
+
return state
|
|
43
|
+
|
|
44
|
+
def completion(self, state: ReplState):
|
|
45
|
+
def sc():
|
|
46
|
+
return SqlCompleter(
|
|
47
|
+
lambda: cassandra_table_names(state),
|
|
48
|
+
dml='export',
|
|
49
|
+
columns = lambda table: ['id', '*'],
|
|
50
|
+
variant='cql'
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
if state.sts:
|
|
54
|
+
return {ExportTables.COMMAND: sc()} | \
|
|
55
|
+
{f'@{p}': {ExportTables.COMMAND: sc()} for p in StatefulSets.pod_names(state.sts, state.namespace)}
|
|
56
|
+
|
|
57
|
+
return {}
|
|
58
|
+
|
|
59
|
+
def help(self, _: ReplState):
|
|
60
|
+
return f'{ExportTables.COMMAND} [TABLE] [as target-name] [with consistency <level>]\t export table'
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
from adam.commands.command import Command
|
|
2
|
+
from adam.repl_state import ReplState, RequiredState
|
|
3
|
+
from adam.sql.sql_completer import SqlCompleter
|
|
4
|
+
from adam.utils import log2
|
|
5
|
+
from adam.utils_athena import Athena
|
|
6
|
+
|
|
7
|
+
class ExportUseX(Command):
|
|
8
|
+
COMMAND = 'use'
|
|
9
|
+
|
|
10
|
+
# the singleton pattern
|
|
11
|
+
def __new__(cls, *args, **kwargs):
|
|
12
|
+
if not hasattr(cls, 'instance'): cls.instance = super(ExportUseX, cls).__new__(cls)
|
|
13
|
+
|
|
14
|
+
return cls.instance
|
|
15
|
+
|
|
16
|
+
def __init__(self, successor: Command=None):
|
|
17
|
+
super().__init__(successor)
|
|
18
|
+
|
|
19
|
+
def command(self):
|
|
20
|
+
return ExportUseX.COMMAND
|
|
21
|
+
|
|
22
|
+
def required(self):
|
|
23
|
+
return ReplState.X
|
|
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
|
+
if not self.validate_state(state):
|
|
31
|
+
return state
|
|
32
|
+
|
|
33
|
+
if not args:
|
|
34
|
+
if state.in_repl:
|
|
35
|
+
log2('Specify database to use.')
|
|
36
|
+
else:
|
|
37
|
+
log2('* database is missing.')
|
|
38
|
+
|
|
39
|
+
Command.display_help()
|
|
40
|
+
|
|
41
|
+
return 'command-missing'
|
|
42
|
+
|
|
43
|
+
state.export_session = args[0].replace('export_', '') if args[0].startswith('export_') else args[0]
|
|
44
|
+
Athena.clear_cache()
|
|
45
|
+
|
|
46
|
+
return state
|
|
47
|
+
|
|
48
|
+
def completion(self, state: ReplState):
|
|
49
|
+
dict = super().completion(state, {n: None for n in Athena.database_names()})
|
|
50
|
+
|
|
51
|
+
if state.export_session:
|
|
52
|
+
db = f'export_{state.export_session}'
|
|
53
|
+
dict = dict | {'select': SqlCompleter(
|
|
54
|
+
lambda: Athena.table_names(database=db, function='export'),
|
|
55
|
+
dml='select',
|
|
56
|
+
columns=lambda table: Athena.column_names(database=db, function='export'),
|
|
57
|
+
variant='athena'
|
|
58
|
+
)}
|
|
59
|
+
|
|
60
|
+
return dict
|
|
61
|
+
|
|
62
|
+
def help(self, _: ReplState):
|
|
63
|
+
return f'{ExportUseX.COMMAND} <export db name>\t use Export Database'
|
|
64
|
+
|
|
65
|
+
# No action body, only for a help entry and auto-completion
|
|
66
|
+
class ExportSelectX(Command):
|
|
67
|
+
COMMAND = 'select'
|
|
68
|
+
|
|
69
|
+
def command(self):
|
|
70
|
+
return ExportSelectX.COMMAND
|
|
71
|
+
|
|
72
|
+
def required(self):
|
|
73
|
+
return RequiredState.EXPORT_DB
|
|
74
|
+
|
|
75
|
+
def help(self, _: ReplState):
|
|
76
|
+
return f'<sql-select-statements>\t run queries on export database'
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import boto3
|
|
2
|
+
|
|
3
|
+
from adam.commands.command import Command
|
|
4
|
+
from adam.commands.export.utils_export import ing
|
|
5
|
+
from adam.config import Config
|
|
6
|
+
from adam.repl_state import ReplState, RequiredState
|
|
7
|
+
from adam.utils import log2
|
|
8
|
+
from adam.utils_athena import Athena
|
|
9
|
+
|
|
10
|
+
class RemoveExportDatabases(Command):
|
|
11
|
+
COMMAND = '&rmdbs'
|
|
12
|
+
|
|
13
|
+
# the singleton pattern
|
|
14
|
+
def __new__(cls, *args, **kwargs):
|
|
15
|
+
if not hasattr(cls, 'instance'): cls.instance = super(RemoveExportDatabases, 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 RemoveExportDatabases.COMMAND
|
|
24
|
+
|
|
25
|
+
def required(self):
|
|
26
|
+
return RequiredState.CLUSTER_OR_POD
|
|
27
|
+
|
|
28
|
+
def run(self, cmd: str, state: ReplState):
|
|
29
|
+
if not(args := self.args(cmd)):
|
|
30
|
+
return super().run(cmd, state)
|
|
31
|
+
|
|
32
|
+
state, args = self.apply_state(args, state)
|
|
33
|
+
if not self.validate_state(state):
|
|
34
|
+
return state
|
|
35
|
+
|
|
36
|
+
dbs = Athena.database_names('export_')
|
|
37
|
+
def drop_all_exports():
|
|
38
|
+
for db in dbs:
|
|
39
|
+
query = f'DROP DATABASE {db} CASCADE'
|
|
40
|
+
if Config().is_debug():
|
|
41
|
+
log2(query)
|
|
42
|
+
Athena.query(query)
|
|
43
|
+
|
|
44
|
+
if Config().is_debug():
|
|
45
|
+
drop_all_exports()
|
|
46
|
+
else:
|
|
47
|
+
ing(f'Droping {len(dbs)} databases', drop_all_exports)
|
|
48
|
+
|
|
49
|
+
def delete_s3_folder():
|
|
50
|
+
s3 = boto3.resource('s3')
|
|
51
|
+
bucket = s3.Bucket('c3.ops--qing')
|
|
52
|
+
bucket.objects.filter(Prefix='export/').delete()
|
|
53
|
+
|
|
54
|
+
if Config().is_debug():
|
|
55
|
+
delete_s3_folder()
|
|
56
|
+
else:
|
|
57
|
+
ing(f'Deleting s3 folder: export', delete_s3_folder)
|
|
58
|
+
|
|
59
|
+
return state
|
|
60
|
+
|
|
61
|
+
def completion(self, state: ReplState):
|
|
62
|
+
return super().completion(state)
|
|
63
|
+
|
|
64
|
+
def help(self, _: ReplState):
|
|
65
|
+
return f'{RemoveExportDatabases.COMMAND}\t remove all export databases'
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
from adam.commands.command import Command
|
|
2
|
+
from adam.repl_state import ReplState, RequiredState
|
|
3
|
+
from adam.sql.sql_completer import SqlCompleter
|
|
4
|
+
from adam.utils import log2
|
|
5
|
+
from adam.utils_athena import Athena
|
|
6
|
+
|
|
7
|
+
class ExportSelect(Command):
|
|
8
|
+
COMMAND = '&select'
|
|
9
|
+
|
|
10
|
+
# the singleton pattern
|
|
11
|
+
def __new__(cls, *args, **kwargs):
|
|
12
|
+
if not hasattr(cls, 'instance'): cls.instance = super(ExportSelect, cls).__new__(cls)
|
|
13
|
+
|
|
14
|
+
return cls.instance
|
|
15
|
+
|
|
16
|
+
def __init__(self, successor: Command=None):
|
|
17
|
+
super().__init__(successor)
|
|
18
|
+
|
|
19
|
+
def command(self):
|
|
20
|
+
return ExportSelect.COMMAND
|
|
21
|
+
|
|
22
|
+
def required(self):
|
|
23
|
+
return [RequiredState.CLUSTER_OR_POD, ReplState.X]
|
|
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
|
+
if not self.validate_state(state):
|
|
31
|
+
return state
|
|
32
|
+
|
|
33
|
+
if not args:
|
|
34
|
+
if state.in_repl:
|
|
35
|
+
log2('Use a SQL statement.')
|
|
36
|
+
else:
|
|
37
|
+
log2('* SQL statement is missing.')
|
|
38
|
+
|
|
39
|
+
Command.display_help()
|
|
40
|
+
|
|
41
|
+
return 'command-missing'
|
|
42
|
+
|
|
43
|
+
query = ' '.join(args)
|
|
44
|
+
|
|
45
|
+
Athena.run_query(f'select {query}', database=f'export_{state.export_session}')
|
|
46
|
+
|
|
47
|
+
return state
|
|
48
|
+
|
|
49
|
+
def completion(self, state: ReplState):
|
|
50
|
+
if not state.export_session:
|
|
51
|
+
return {}
|
|
52
|
+
|
|
53
|
+
db = f'export_{state.export_session}'
|
|
54
|
+
|
|
55
|
+
# warm up the caches first time when x: drive is accessed
|
|
56
|
+
Athena.table_names(database=db, function='export')
|
|
57
|
+
Athena.column_names(database=db, function='export')
|
|
58
|
+
Athena.column_names(partition_cols_only=True, database=db, function='export')
|
|
59
|
+
|
|
60
|
+
return {ExportSelect.COMMAND: SqlCompleter(
|
|
61
|
+
lambda: Athena.table_names(database=db, function='export'),
|
|
62
|
+
dml='select',
|
|
63
|
+
columns=lambda table: Athena.column_names(database=db, function='export'),
|
|
64
|
+
variant='athena'
|
|
65
|
+
)}
|
|
66
|
+
|
|
67
|
+
def help(self, _: ReplState):
|
|
68
|
+
return f'<sql-select-statements>\t run queries on export database'
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
from adam.commands.command import Command
|
|
2
|
+
from adam.commands.export.export_select import ExportSelect
|
|
3
|
+
from adam.config import Config
|
|
4
|
+
from adam.repl_state import ReplState, RequiredState
|
|
5
|
+
from adam.utils import log2
|
|
6
|
+
from adam.utils_athena import Athena
|
|
7
|
+
|
|
8
|
+
class ExportUse(Command):
|
|
9
|
+
COMMAND = '&use'
|
|
10
|
+
|
|
11
|
+
# the singleton pattern
|
|
12
|
+
def __new__(cls, *args, **kwargs):
|
|
13
|
+
if not hasattr(cls, 'instance'): cls.instance = super(ExportUse, cls).__new__(cls)
|
|
14
|
+
|
|
15
|
+
return cls.instance
|
|
16
|
+
|
|
17
|
+
def __init__(self, successor: Command=None):
|
|
18
|
+
super().__init__(successor)
|
|
19
|
+
|
|
20
|
+
def command(self):
|
|
21
|
+
return ExportUse.COMMAND
|
|
22
|
+
|
|
23
|
+
def required(self):
|
|
24
|
+
return RequiredState.CLUSTER_OR_POD
|
|
25
|
+
|
|
26
|
+
def run(self, cmd: str, state: ReplState):
|
|
27
|
+
if not(args := self.args(cmd)):
|
|
28
|
+
return super().run(cmd, state)
|
|
29
|
+
|
|
30
|
+
state, args = self.apply_state(args, state)
|
|
31
|
+
if not self.validate_state(state):
|
|
32
|
+
return state
|
|
33
|
+
|
|
34
|
+
if not args:
|
|
35
|
+
if state.in_repl:
|
|
36
|
+
log2('Specify database to use.')
|
|
37
|
+
else:
|
|
38
|
+
log2('* database is missing.')
|
|
39
|
+
|
|
40
|
+
Command.display_help()
|
|
41
|
+
|
|
42
|
+
return 'command-missing'
|
|
43
|
+
|
|
44
|
+
state.export_session = args[0].replace('export_', '') if args[0].startswith('export_') else args[0]
|
|
45
|
+
Athena.clear_cache()
|
|
46
|
+
|
|
47
|
+
return state
|
|
48
|
+
|
|
49
|
+
def completion(self, state: ReplState):
|
|
50
|
+
# warm up the caches first time when l: drive is accessed
|
|
51
|
+
Athena.database_names()
|
|
52
|
+
|
|
53
|
+
return super().completion(state, {n: None for n in Athena.database_names()})
|
|
54
|
+
|
|
55
|
+
def help(self, _: ReplState):
|
|
56
|
+
return f'{ExportUse.COMMAND} <export db name>\t use Export Database'
|