kaqing 2.0.93__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.

Files changed (134) hide show
  1. adam/apps.py +2 -2
  2. adam/batch.py +2 -16
  3. adam/checks/check_utils.py +4 -4
  4. adam/checks/compactionstats.py +1 -1
  5. adam/checks/cpu.py +2 -2
  6. adam/checks/disk.py +1 -1
  7. adam/checks/gossip.py +1 -1
  8. adam/checks/memory.py +3 -3
  9. adam/checks/status.py +1 -1
  10. adam/commands/alter_tables.py +3 -14
  11. adam/commands/app.py +3 -3
  12. adam/commands/app_ping.py +2 -2
  13. adam/commands/audit/audit.py +26 -11
  14. adam/commands/audit/audit_repair_tables.py +39 -4
  15. adam/commands/audit/audit_run.py +58 -0
  16. adam/commands/audit/show_last10.py +51 -0
  17. adam/commands/audit/show_slow10.py +50 -0
  18. adam/commands/audit/show_top10.py +49 -0
  19. adam/commands/audit/utils_show_top10.py +59 -0
  20. adam/commands/bash/bash.py +124 -0
  21. adam/commands/bash/bash_completer.py +93 -0
  22. adam/commands/cat.py +55 -0
  23. adam/commands/cd.py +26 -14
  24. adam/commands/check.py +6 -0
  25. adam/commands/cli_commands.py +3 -3
  26. adam/commands/code.py +60 -0
  27. adam/commands/command.py +9 -4
  28. adam/commands/commands_utils.py +4 -5
  29. adam/commands/cql/cql_completions.py +7 -3
  30. adam/commands/cql/cql_utils.py +103 -11
  31. adam/commands/cql/cqlsh.py +10 -5
  32. adam/commands/deploy/code_utils.py +2 -2
  33. adam/commands/deploy/deploy.py +7 -1
  34. adam/commands/deploy/deploy_pg_agent.py +2 -2
  35. adam/commands/deploy/deploy_pod.py +6 -6
  36. adam/commands/deploy/deploy_utils.py +2 -2
  37. adam/commands/deploy/undeploy.py +7 -1
  38. adam/commands/deploy/undeploy_pg_agent.py +2 -2
  39. adam/commands/deploy/undeploy_pod.py +4 -4
  40. adam/commands/devices.py +29 -0
  41. adam/commands/export/export.py +60 -0
  42. adam/commands/export/export_on_x.py +76 -0
  43. adam/commands/export/export_rmdbs.py +65 -0
  44. adam/commands/export/export_select.py +68 -0
  45. adam/commands/export/export_use.py +56 -0
  46. adam/commands/export/utils_export.py +253 -0
  47. adam/commands/help.py +9 -5
  48. adam/commands/issues.py +6 -0
  49. adam/commands/kubectl.py +41 -0
  50. adam/commands/login.py +6 -3
  51. adam/commands/logs.py +2 -1
  52. adam/commands/ls.py +43 -31
  53. adam/commands/medusa/medusa_backup.py +2 -2
  54. adam/commands/medusa/medusa_restore.py +2 -2
  55. adam/commands/medusa/medusa_show_backupjobs.py +3 -2
  56. adam/commands/medusa/medusa_show_restorejobs.py +2 -2
  57. adam/commands/nodetool.py +11 -16
  58. adam/commands/postgres/postgres.py +4 -4
  59. adam/commands/postgres/{postgres_session.py → postgres_context.py} +29 -30
  60. adam/commands/postgres/postgres_utils.py +5 -5
  61. adam/commands/postgres/psql_completions.py +1 -1
  62. adam/commands/preview_table.py +18 -32
  63. adam/commands/pwd.py +4 -3
  64. adam/commands/reaper/reaper.py +3 -0
  65. adam/commands/reaper/reaper_restart.py +1 -1
  66. adam/commands/reaper/reaper_session.py +1 -1
  67. adam/commands/repair/repair.py +3 -3
  68. adam/commands/repair/repair_log.py +1 -1
  69. adam/commands/repair/repair_run.py +2 -2
  70. adam/commands/repair/repair_scan.py +1 -1
  71. adam/commands/repair/repair_stop.py +1 -1
  72. adam/commands/report.py +6 -0
  73. adam/commands/restart.py +2 -2
  74. adam/commands/rollout.py +1 -1
  75. adam/commands/show/show.py +3 -1
  76. adam/commands/show/show_app_actions.py +3 -0
  77. adam/commands/show/show_app_id.py +1 -1
  78. adam/commands/show/show_app_queues.py +3 -2
  79. adam/commands/show/show_cassandra_status.py +3 -3
  80. adam/commands/show/show_cassandra_version.py +3 -3
  81. adam/commands/show/show_login.py +3 -0
  82. adam/commands/show/show_processes.py +1 -1
  83. adam/commands/show/show_repairs.py +2 -2
  84. adam/commands/show/show_storage.py +1 -1
  85. adam/commands/watch.py +1 -1
  86. adam/config.py +2 -1
  87. adam/embedded_params.py +1 -1
  88. adam/pod_exec_result.py +7 -1
  89. adam/repl.py +125 -99
  90. adam/repl_commands.py +29 -17
  91. adam/repl_state.py +229 -49
  92. adam/sql/sql_completer.py +86 -62
  93. adam/sql/sql_state_machine.py +563 -0
  94. adam/sql/term_completer.py +3 -0
  95. adam/sso/cred_cache.py +1 -1
  96. adam/sso/idp.py +1 -1
  97. adam/utils_athena.py +108 -74
  98. adam/utils_audits.py +104 -0
  99. adam/utils_export.py +42 -0
  100. adam/utils_k8s/__init__.py +0 -0
  101. adam/utils_k8s/app_clusters.py +33 -0
  102. adam/utils_k8s/app_pods.py +31 -0
  103. adam/{k8s_utils → utils_k8s}/cassandra_clusters.py +5 -6
  104. adam/{k8s_utils → utils_k8s}/cassandra_nodes.py +11 -4
  105. adam/{k8s_utils → utils_k8s}/deployment.py +2 -2
  106. adam/{k8s_utils → utils_k8s}/pods.py +54 -11
  107. adam/{k8s_utils → utils_k8s}/statefulsets.py +2 -2
  108. adam/version.py +1 -1
  109. {kaqing-2.0.93.dist-info → kaqing-2.0.115.dist-info}/METADATA +1 -1
  110. kaqing-2.0.115.dist-info/RECORD +203 -0
  111. adam/commands/bash.py +0 -91
  112. adam/commands/cql/cql_table_completer.py +0 -8
  113. adam/commands/describe/describe.py +0 -46
  114. adam/commands/describe/describe_keyspace.py +0 -60
  115. adam/commands/describe/describe_keyspaces.py +0 -50
  116. adam/commands/describe/describe_table.py +0 -60
  117. adam/commands/describe/describe_tables.py +0 -50
  118. adam/commands/postgres/psql_table_completer.py +0 -11
  119. adam/sql/state_machine.py +0 -460
  120. kaqing-2.0.93.dist-info/RECORD +0 -190
  121. /adam/commands/{describe → bash}/__init__.py +0 -0
  122. /adam/{k8s_utils → commands/export}/__init__.py +0 -0
  123. /adam/{k8s_utils → utils_k8s}/config_maps.py +0 -0
  124. /adam/{k8s_utils → utils_k8s}/custom_resources.py +0 -0
  125. /adam/{k8s_utils → utils_k8s}/ingresses.py +0 -0
  126. /adam/{k8s_utils → utils_k8s}/jobs.py +0 -0
  127. /adam/{k8s_utils → utils_k8s}/kube_context.py +0 -0
  128. /adam/{k8s_utils → utils_k8s}/secrets.py +0 -0
  129. /adam/{k8s_utils → utils_k8s}/service_accounts.py +0 -0
  130. /adam/{k8s_utils → utils_k8s}/services.py +0 -0
  131. /adam/{k8s_utils → utils_k8s}/volumes.py +0 -0
  132. {kaqing-2.0.93.dist-info → kaqing-2.0.115.dist-info}/WHEEL +0 -0
  133. {kaqing-2.0.93.dist-info → kaqing-2.0.115.dist-info}/entry_points.txt +0 -0
  134. {kaqing-2.0.93.dist-info → kaqing-2.0.115.dist-info}/top_level.txt +0 -0
@@ -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 .cql_utils import run_cql, table_names
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 {Cqlsh.COMMAND: None} | cql_completions(state)
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'[{Cqlsh.COMMAND}] <cql-statements>\t run cqlsh with queries'
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):
@@ -5,8 +5,8 @@ import subprocess
5
5
 
6
6
  from adam.apps import Apps
7
7
  from adam.config import Config
8
- from adam.k8s_utils.ingresses import Ingresses
9
- from adam.k8s_utils.services import Services
8
+ from adam.utils_k8s.ingresses import Ingresses
9
+ from adam.utils_k8s.services import Services
10
10
  from adam.utils import log2, random_alphanumeric
11
11
 
12
12
  def start_user_code(namespace: str):
@@ -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.postgres_session import PostgresSession
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
- PostgresSession.deploy_pg_agent(Config().get('pg.agent.name', 'ops-pg-agent'), state.namespace)
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)
@@ -5,12 +5,12 @@ from adam.commands.command import Command
5
5
  from adam.commands.deploy.deploy_utils import creating, deploy_frontend, gen_labels
6
6
  from adam.commands.deploy.undeploy_pod import UndeployPod
7
7
  from adam.config import Config
8
- from adam.k8s_utils.config_maps import ConfigMaps
9
- from adam.k8s_utils.deployment import Deployments
10
- from adam.k8s_utils.kube_context import KubeContext
11
- from adam.k8s_utils.pods import Pods
12
- from adam.k8s_utils.service_accounts import ServiceAccounts
13
- from adam.k8s_utils.volumes import ConfigMapMount
8
+ from adam.utils_k8s.config_maps import ConfigMaps
9
+ from adam.utils_k8s.deployment import Deployments
10
+ from adam.utils_k8s.kube_context import KubeContext
11
+ from adam.utils_k8s.pods import Pods
12
+ from adam.utils_k8s.service_accounts import ServiceAccounts
13
+ from adam.utils_k8s.volumes import ConfigMapMount
14
14
  from adam.repl_state import ReplState, RequiredState
15
15
  from adam.utils import log2
16
16
 
@@ -1,7 +1,7 @@
1
1
  from typing import Callable
2
2
  from adam.app_session import AppSession
3
- from adam.k8s_utils.ingresses import Ingresses
4
- from adam.k8s_utils.services import Services
3
+ from adam.utils_k8s.ingresses import Ingresses
4
+ from adam.utils_k8s.services import Services
5
5
  from adam.utils import log2
6
6
 
7
7
  def deploy_frontend(name: str, namespace: str, label_selector: str):
@@ -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.postgres_session import PostgresSession
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: PostgresSession.undeploy_pg_agent(Config().get('pg.agent.name', 'ops-pg-agent'), state.namespace))
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
 
@@ -1,10 +1,10 @@
1
1
  from adam.commands.command import Command
2
2
  from adam.commands.deploy.deploy_utils import undeploy_frontend, deleting
3
3
  from adam.config import Config
4
- from adam.k8s_utils.config_maps import ConfigMaps
5
- from adam.k8s_utils.deployment import Deployments
6
- from adam.k8s_utils.pods import Pods
7
- from adam.k8s_utils.service_accounts import ServiceAccounts
4
+ from adam.utils_k8s.config_maps import ConfigMaps
5
+ from adam.utils_k8s.deployment import Deployments
6
+ from adam.utils_k8s.pods import Pods
7
+ from adam.utils_k8s.service_accounts import ServiceAccounts
8
8
  from adam.repl_state import ReplState, RequiredState
9
9
 
10
10
  class UndeployPod(Command):
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
 
@@ -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'