kaqing 2.0.184__py3-none-any.whl → 2.0.227__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 (205) hide show
  1. adam/app_session.py +1 -1
  2. adam/batch.py +15 -15
  3. adam/checks/compactionstats.py +2 -1
  4. adam/checks/cpu.py +2 -1
  5. adam/checks/disk.py +6 -5
  6. adam/checks/gossip.py +2 -1
  7. adam/checks/memory.py +2 -1
  8. adam/checks/status.py +2 -1
  9. adam/commands/app/app.py +4 -4
  10. adam/commands/app/app_ping.py +2 -2
  11. adam/commands/{login.py → app/login.py} +2 -2
  12. adam/commands/app/show_app_actions.py +3 -3
  13. adam/commands/app/show_app_id.py +2 -2
  14. adam/commands/app/show_app_queues.py +2 -2
  15. adam/commands/{show → app}/show_login.py +3 -3
  16. adam/commands/app/utils_app.py +9 -1
  17. adam/commands/audit/audit.py +8 -24
  18. adam/commands/audit/audit_repair_tables.py +3 -3
  19. adam/commands/audit/audit_run.py +3 -3
  20. adam/commands/audit/completions_l.py +15 -0
  21. adam/commands/audit/show_last10.py +2 -3
  22. adam/commands/audit/show_slow10.py +2 -2
  23. adam/commands/audit/show_top10.py +2 -2
  24. adam/commands/bash/bash.py +3 -3
  25. adam/commands/bash/utils_bash.py +1 -1
  26. adam/commands/cassandra/download_cassandra_log.py +45 -0
  27. adam/commands/cassandra/restart_cluster.py +47 -0
  28. adam/commands/cassandra/restart_node.py +51 -0
  29. adam/commands/cassandra/restart_nodes.py +47 -0
  30. adam/commands/{rollout.py → cassandra/rollout.py} +3 -3
  31. adam/commands/{show → cassandra}/show_cassandra_repairs.py +7 -5
  32. adam/commands/{show → cassandra}/show_cassandra_status.py +24 -17
  33. adam/commands/{show → cassandra}/show_cassandra_version.py +2 -2
  34. adam/commands/cassandra/show_processes.py +50 -0
  35. adam/commands/cassandra/show_storage.py +44 -0
  36. adam/commands/{watch.py → cassandra/watch.py} +2 -2
  37. adam/commands/cli/__init__.py +0 -0
  38. adam/commands/{cli_commands.py → cli/cli_commands.py} +6 -1
  39. adam/commands/{clipboard_copy.py → cli/clipboard_copy.py} +4 -4
  40. adam/commands/{show/show_commands.py → cli/show_cli_commands.py} +5 -5
  41. adam/commands/code.py +2 -2
  42. adam/commands/command.py +54 -14
  43. adam/commands/commands_utils.py +14 -6
  44. adam/commands/config/__init__.py +0 -0
  45. adam/commands/{param_get.py → config/param_get.py} +2 -2
  46. adam/commands/{param_set.py → config/param_set.py} +2 -2
  47. adam/commands/{show → config}/show_params.py +3 -3
  48. adam/commands/{alter_tables.py → cql/alter_tables.py} +3 -3
  49. adam/commands/cql/completions_c.py +29 -0
  50. adam/commands/cql/cqlsh.py +4 -8
  51. adam/commands/cql/utils_cql.py +36 -17
  52. adam/commands/debug/__init__.py +0 -0
  53. adam/commands/debug/debug.py +22 -0
  54. adam/commands/debug/debug_completes.py +35 -0
  55. adam/commands/debug/debug_timings.py +35 -0
  56. adam/commands/debug/show_offloaded_completes.py +45 -0
  57. adam/commands/deploy/code_start.py +2 -2
  58. adam/commands/deploy/code_stop.py +2 -2
  59. adam/commands/deploy/deploy_frontend.py +2 -2
  60. adam/commands/deploy/deploy_pg_agent.py +2 -2
  61. adam/commands/deploy/deploy_pod.py +2 -2
  62. adam/commands/deploy/undeploy_frontend.py +2 -2
  63. adam/commands/deploy/undeploy_pg_agent.py +2 -2
  64. adam/commands/deploy/undeploy_pod.py +2 -2
  65. adam/commands/devices/device.py +37 -11
  66. adam/commands/devices/device_app.py +7 -7
  67. adam/commands/devices/device_auit_log.py +2 -2
  68. adam/commands/devices/device_cass.py +6 -6
  69. adam/commands/devices/device_export.py +7 -4
  70. adam/commands/devices/device_postgres.py +19 -9
  71. adam/commands/devices/devices.py +1 -1
  72. adam/commands/diag/__init__.py +0 -0
  73. adam/commands/{check.py → diag/check.py} +3 -3
  74. adam/commands/diag/generate_report.py +52 -0
  75. adam/commands/{issues.py → diag/issues.py} +3 -2
  76. adam/commands/exit.py +2 -2
  77. adam/commands/export/clean_up_all_export_sessions.py +2 -2
  78. adam/commands/export/clean_up_export_sessions.py +2 -2
  79. adam/commands/export/completions_x.py +11 -0
  80. adam/commands/export/download_export_session.py +5 -5
  81. adam/commands/export/drop_export_database.py +2 -2
  82. adam/commands/export/drop_export_databases.py +2 -2
  83. adam/commands/export/export.py +3 -19
  84. adam/commands/export/export_databases.py +20 -11
  85. adam/commands/export/export_select.py +9 -34
  86. adam/commands/export/export_sessions.py +13 -11
  87. adam/commands/export/export_use.py +6 -6
  88. adam/commands/export/export_x_select.py +48 -0
  89. adam/commands/export/exporter.py +140 -53
  90. adam/commands/export/import_files.py +3 -7
  91. adam/commands/export/import_session.py +2 -6
  92. adam/commands/export/importer.py +12 -13
  93. adam/commands/export/importer_athena.py +15 -35
  94. adam/commands/export/importer_sqlite.py +19 -8
  95. adam/commands/export/show_column_counts.py +11 -12
  96. adam/commands/export/show_export_databases.py +4 -4
  97. adam/commands/export/show_export_session.py +5 -5
  98. adam/commands/export/show_export_sessions.py +4 -4
  99. adam/commands/export/utils_export.py +40 -25
  100. adam/commands/fs/__init__.py +0 -0
  101. adam/commands/{cat.py → fs/cat.py} +4 -4
  102. adam/commands/fs/cat_local.py +42 -0
  103. adam/commands/{cd.py → fs/cd.py} +4 -4
  104. adam/commands/{download_file.py → fs/download_file.py} +7 -7
  105. adam/commands/{find_files.py → fs/find_files.py} +7 -7
  106. adam/commands/{find_processes.py → fs/find_processes.py} +14 -22
  107. adam/commands/{head.py → fs/head.py} +5 -5
  108. adam/commands/fs/head_local.py +46 -0
  109. adam/commands/{ls.py → fs/ls.py} +4 -4
  110. adam/commands/fs/ls_local.py +40 -0
  111. adam/commands/{pwd.py → fs/pwd.py} +2 -2
  112. adam/commands/fs/rm.py +18 -0
  113. adam/commands/fs/rm_downloads.py +39 -0
  114. adam/commands/fs/rm_logs.py +44 -0
  115. adam/commands/fs/rm_logs_local.py +38 -0
  116. adam/commands/{shell.py → fs/shell.py} +2 -2
  117. adam/commands/{show → fs}/show_adam.py +3 -3
  118. adam/commands/{show → fs}/show_host.py +2 -2
  119. adam/commands/fs/show_last_results.py +39 -0
  120. adam/commands/fs/tail.py +36 -0
  121. adam/commands/fs/tail_local.py +46 -0
  122. adam/commands/fs/utils_fs.py +192 -0
  123. adam/commands/help.py +2 -2
  124. adam/commands/intermediate_command.py +3 -0
  125. adam/commands/kubectl.py +2 -2
  126. adam/commands/medusa/medusa_backup.py +2 -2
  127. adam/commands/medusa/medusa_restore.py +4 -18
  128. adam/commands/medusa/medusa_show_backupjobs.py +2 -2
  129. adam/commands/medusa/medusa_show_restorejobs.py +2 -2
  130. adam/commands/medusa/utils_medusa.py +15 -0
  131. adam/commands/nodetool/__init__.py +0 -0
  132. adam/commands/nodetool/nodetool.py +87 -0
  133. adam/commands/nodetool/utils_nodetool.py +44 -0
  134. adam/commands/postgres/completions_p.py +22 -0
  135. adam/commands/postgres/postgres.py +10 -20
  136. adam/commands/postgres/postgres_databases.py +3 -3
  137. adam/commands/postgres/postgres_ls.py +3 -3
  138. adam/commands/postgres/postgres_preview.py +2 -2
  139. adam/commands/postgres/utils_postgres.py +12 -2
  140. adam/commands/preview_table.py +3 -4
  141. adam/commands/reaper/reaper_forward.py +2 -2
  142. adam/commands/reaper/reaper_forward_stop.py +2 -2
  143. adam/commands/reaper/reaper_restart.py +2 -2
  144. adam/commands/reaper/reaper_run_abort.py +2 -2
  145. adam/commands/reaper/reaper_runs.py +14 -12
  146. adam/commands/reaper/reaper_runs_abort.py +2 -2
  147. adam/commands/reaper/reaper_schedule_activate.py +8 -4
  148. adam/commands/reaper/reaper_schedule_start.py +3 -4
  149. adam/commands/reaper/reaper_schedule_stop.py +3 -4
  150. adam/commands/reaper/reaper_schedules.py +2 -2
  151. adam/commands/reaper/reaper_status.py +2 -2
  152. adam/commands/reaper/utils_reaper.py +41 -6
  153. adam/commands/repair/repair_log.py +2 -2
  154. adam/commands/repair/repair_run.py +2 -2
  155. adam/commands/repair/repair_scan.py +2 -4
  156. adam/commands/repair/repair_stop.py +2 -3
  157. adam/commands/{show/show.py → show.py} +12 -11
  158. adam/config.py +4 -5
  159. adam/embedded_params.py +1 -1
  160. adam/repl.py +24 -10
  161. adam/repl_commands.py +68 -45
  162. adam/repl_session.py +16 -1
  163. adam/repl_state.py +16 -1
  164. adam/sql/async_executor.py +62 -0
  165. adam/sql/lark_completer.py +286 -0
  166. adam/sql/lark_parser.py +604 -0
  167. adam/sql/qingl.lark +1075 -0
  168. adam/sso/cred_cache.py +2 -5
  169. adam/utils.py +259 -82
  170. adam/utils_async_job.py +73 -0
  171. adam/utils_k8s/app_clusters.py +11 -4
  172. adam/utils_k8s/app_pods.py +10 -5
  173. adam/utils_k8s/cassandra_clusters.py +19 -7
  174. adam/utils_k8s/cassandra_nodes.py +16 -6
  175. adam/utils_k8s/k8s.py +9 -0
  176. adam/utils_k8s/kube_context.py +1 -4
  177. adam/{pod_exec_result.py → utils_k8s/pod_exec_result.py} +8 -2
  178. adam/utils_k8s/pods.py +189 -29
  179. adam/utils_k8s/statefulsets.py +5 -2
  180. adam/utils_local.py +78 -2
  181. adam/utils_repl/appendable_completer.py +6 -0
  182. adam/utils_repl/repl_completer.py +51 -4
  183. adam/utils_sqlite.py +3 -8
  184. adam/version.py +1 -1
  185. {kaqing-2.0.184.dist-info → kaqing-2.0.227.dist-info}/METADATA +1 -1
  186. kaqing-2.0.227.dist-info/RECORD +280 -0
  187. kaqing-2.0.227.dist-info/top_level.txt +2 -0
  188. teddy/__init__.py +0 -0
  189. teddy/lark_parser.py +436 -0
  190. teddy/lark_parser2.py +618 -0
  191. adam/commands/cql/cql_completions.py +0 -32
  192. adam/commands/export/export_select_x.py +0 -54
  193. adam/commands/logs.py +0 -37
  194. adam/commands/nodetool.py +0 -69
  195. adam/commands/postgres/psql_completions.py +0 -11
  196. adam/commands/report.py +0 -61
  197. adam/commands/restart.py +0 -60
  198. adam/commands/show/show_processes.py +0 -49
  199. adam/commands/show/show_storage.py +0 -42
  200. kaqing-2.0.184.dist-info/RECORD +0 -244
  201. kaqing-2.0.184.dist-info/top_level.txt +0 -1
  202. /adam/commands/{show → cassandra}/__init__.py +0 -0
  203. /adam/commands/{nodetool_commands.py → nodetool/nodetool_commands.py} +0 -0
  204. {kaqing-2.0.184.dist-info → kaqing-2.0.227.dist-info}/WHEEL +0 -0
  205. {kaqing-2.0.184.dist-info → kaqing-2.0.227.dist-info}/entry_points.txt +0 -0
@@ -5,7 +5,7 @@ from adam.checks.check_utils import all_checks, checks_from_csv, run_checks
5
5
  from adam.commands import extract_options, validate_args
6
6
  from adam.commands.command import Command
7
7
  from adam.commands.command_helpers import ClusterOrPodCommandHelper
8
- from adam.commands.issues import Issues
8
+ from adam.commands.diag.issues import Issues
9
9
  from adam.repl_state import ReplState
10
10
  from adam.utils import tabulize, log
11
11
  from adam.utils_issues import IssuesUtils
@@ -49,8 +49,8 @@ class Check(Issues):
49
49
  def completion(self, _: ReplState):
50
50
  return {Check.COMMAND: {check.name(): {'-s': None} for check in all_checks()}}
51
51
 
52
- def help(self, _: ReplState):
53
- return f'{Check.COMMAND} <check-name> [-s]\t run a single check'
52
+ def help(self, state: ReplState):
53
+ return super().help(state, 'run a single check -s show processing details', args='<check-name> [-s]')
54
54
 
55
55
  class CheckCommandHelper(click.Command):
56
56
  def get_help(self, ctx: click.Context):
@@ -0,0 +1,52 @@
1
+ import click
2
+ import json
3
+
4
+ from adam.checks.check_result import CheckResult
5
+ from adam.checks.check_utils import run_checks
6
+ from adam.commands import extract_options
7
+ from adam.commands.command import Command
8
+ from adam.commands.commands_utils import kaqing_log_file
9
+ from adam.repl_state import ReplState
10
+ from adam.utils import log2
11
+
12
+ class GenerateReport(Command):
13
+ COMMAND = 'generate report'
14
+
15
+ # the singleton pattern
16
+ def __new__(cls, *args, **kwargs):
17
+ if not hasattr(cls, 'instance'): cls.instance = super(GenerateReport, cls).__new__(cls)
18
+
19
+ return cls.instance
20
+
21
+ def __init__(self, successor: Command=None):
22
+ super().__init__(successor)
23
+
24
+ def command(self):
25
+ return GenerateReport.COMMAND
26
+
27
+ def required(self):
28
+ return ReplState.NON_L
29
+
30
+ def run(self, cmd: str, state: ReplState):
31
+ if not(args := self.args(cmd)):
32
+ return super().run(cmd, state)
33
+
34
+ with self.validate(args, state) as (args, state):
35
+ with extract_options(args, ['-s', '--show']) as (args, show_out):
36
+ results = run_checks(state.sts, state.namespace, state.pod, show_out=show_out)
37
+ output = CheckResult.report(results)
38
+
39
+ if state.in_repl:
40
+ with kaqing_log_file() as json_file:
41
+ json.dump(output, json_file, indent=2)
42
+ log2(f'Report stored in {json_file.name}.')
43
+ else:
44
+ click.echo(json.dumps(output, indent=2))
45
+
46
+ return output
47
+
48
+ def completion(self, state: ReplState):
49
+ return super().completion(state, {'-s': None})
50
+
51
+ def help(self, state: ReplState):
52
+ return super().help(state, 'generate report -s show processing details', args='[-s]')
@@ -39,5 +39,6 @@ class Issues(Command):
39
39
  def completion(self, state: ReplState):
40
40
  return super().completion(state, {'-s': None})
41
41
 
42
- def help(self, _: ReplState):
43
- return f'{Issues.COMMAND} [-s]\t find all issues'
42
+ def help(self, state: ReplState, desc: str = None, args: str = None):
43
+ args1 = args if args else '[-s]'
44
+ return super().help(state, 'find all issues -s show processing details', args=args1)
adam/commands/exit.py CHANGED
@@ -25,5 +25,5 @@ class Exit(Command):
25
25
  def completion(self, state: ReplState):
26
26
  return {Exit.COMMAND: None}
27
27
 
28
- def help(self, _: ReplState):
29
- return f'{Exit.COMMAND}\t exit kaqing <Ctrl-D>'
28
+ def help(self, state: ReplState):
29
+ return super().help(state, 'exit kaqing <Ctrl-D>')
@@ -33,5 +33,5 @@ class CleanUpAllExportSessions(Command):
33
33
  def completion(self, _: ReplState):
34
34
  return {}
35
35
 
36
- def help(self, _: ReplState):
37
- return f'{CleanUpAllExportSessions.COMMAND}\t clean up all export sessions'
36
+ def help(self, state: ReplState):
37
+ return super().help(state, 'clean up all export sessions')
@@ -35,5 +35,5 @@ class CleanUpExportSessions(Command):
35
35
  def completion(self, _: ReplState):
36
36
  return {}
37
37
 
38
- def help(self, _: ReplState):
39
- return f'{CleanUpExportSessions.COMMAND} <export-session-name,...>\t clean up export sessions'
38
+ def help(self, state: ReplState):
39
+ return super().help(state, 'clean up export sessions', args='<export-session-name>,...')
@@ -0,0 +1,11 @@
1
+ from adam.commands.export.export_databases import ExportDatabases
2
+ from adam.repl_state import ReplState
3
+ from adam.sql.lark_completer import LarkCompleter
4
+ from adam.utils_athena import Athena
5
+
6
+ def completions_x(state: ReplState):
7
+ return LarkCompleter(expandables={
8
+ 'tables': lambda x: ExportDatabases.table_names(state.export_session),
9
+ 'export-databases': lambda x: ExportDatabases.database_names(),
10
+ 'columns': lambda x: Athena.column_names(database=state.export_session, function='export'),
11
+ }, variant=ReplState.X).completions_for_nesting()
@@ -1,6 +1,6 @@
1
1
  from adam.commands import validate_args
2
2
  from adam.commands.command import Command
3
- from adam.commands.export.export_sessions import ExportSessions, export_session
3
+ from adam.commands.export.export_sessions import export_session
4
4
  from adam.repl_state import ReplState, RequiredState
5
5
 
6
6
  class DownloadExportSession(Command):
@@ -32,8 +32,8 @@ class DownloadExportSession(Command):
32
32
 
33
33
  return state
34
34
 
35
- def completion(self, state: ReplState):
36
- return super().completion(state, {session: None for session in ExportSessions.export_session_names(state.sts, state.pod, state.namespace, export_state='pending_import')})
35
+ def completion(self, _: ReplState):
36
+ return {}
37
37
 
38
- def help(self, _: ReplState):
39
- return f'{DownloadExportSession.COMMAND} <export-session-name>\t download csv files in export session'
38
+ def help(self, state: ReplState):
39
+ return super().help(state, 'download csv files in export session', args='<export-session-name>')
@@ -35,5 +35,5 @@ class DropExportDatabase(Command):
35
35
  def completion(self, _: ReplState):
36
36
  return {}
37
37
 
38
- def help(self, _: ReplState):
39
- return f'{DropExportDatabase.COMMAND} <export-database-name>\t drop export database'
38
+ def help(self, state: ReplState):
39
+ return super().help(state, 'drop export database', args='<export-database-name>')
@@ -33,5 +33,5 @@ class DropExportDatabases(Command):
33
33
  def completion(self, _: ReplState):
34
34
  return {}
35
35
 
36
- def help(self, _: ReplState):
37
- return f'{DropExportDatabases.COMMAND}\t drop all export databases'
36
+ def help(self, state: ReplState):
37
+ return super().help(state, 'drop all export databases')
@@ -1,12 +1,7 @@
1
1
  from adam.commands import extract_options
2
2
  from adam.commands.command import Command
3
- from adam.commands.cql.utils_cql import cassandra_keyspaces, cassandra_table_names
4
- from adam.commands.export.export_databases import ExportDatabases
5
3
  from adam.commands.export.exporter import export
6
4
  from adam.repl_state import ReplState, RequiredState
7
- from adam.sql.sql_completer import SqlCompleter, SqlVariant
8
- from adam.utils import log
9
- from adam.utils_k8s.statefulsets import StatefulSets
10
5
 
11
6
  class ExportTables(Command):
12
7
  COMMAND = 'export'
@@ -35,19 +30,8 @@ class ExportTables(Command):
35
30
  with export(state) as exporter:
36
31
  return exporter.export(args, export_only=export_only)
37
32
 
38
- def completion(self, state: ReplState):
39
- def sc():
40
- return SqlCompleter(lambda: cassandra_table_names(state), expandables={
41
- 'dml':'export',
42
- 'columns': lambda table: ['id', '*'],
43
- 'keyspaces': lambda: cassandra_keyspaces(state),
44
- 'export-dbs': lambda: ExportDatabases.database_names(),
45
- }, variant=SqlVariant.CQL)
46
-
47
- if super().completion(state):
48
- return {f'@{p}': {ExportTables.COMMAND: sc()} for p in StatefulSets.pod_names(state.sts, state.namespace)}
49
-
33
+ def completion(self, _: ReplState):
50
34
  return {}
51
35
 
52
- def help(self, _: ReplState):
53
- return f'{ExportTables.COMMAND} [* [in KEYSPACE]] | [TABLE] [as target-name] [with consistency <level>]\t export tables to Sqlite, Athena or CSV file'
36
+ def help(self, state: ReplState):
37
+ return super().help(state, 'export tables to Sqlite, Athena or CSV file', args='TABLE...')
@@ -1,14 +1,16 @@
1
1
  from collections.abc import Callable
2
2
  from datetime import datetime
3
+ from functools import partial
3
4
  import os
4
5
  import boto3
5
6
 
6
7
  from adam.commands.export.export_sessions import ExportSessions
7
8
  from adam.commands.export.importer import Importer
9
+ from adam.commands.export.utils_export import export_log_dir
8
10
  from adam.config import Config
9
11
  from adam.repl_session import ReplSession
10
12
  from adam.repl_state import ReplState
11
- from adam.utils import debug, tabulize, log2, ing, log_exc
13
+ from adam.utils import debug, log_timing, tabulize, log2, ing, log_exc
12
14
  from adam.utils_athena import Athena
13
15
  from adam.utils_sqlite import SQLite
14
16
 
@@ -31,7 +33,7 @@ class ExportDatabases:
31
33
 
32
34
  if Config().get('repl.history.push-cat-log-file', True):
33
35
  if log_file and ReplSession().prompt_session:
34
- ReplSession().prompt_session.history.append_string(f':sh cat {log_file}')
36
+ ReplSession().prompt_session.history.append_string(f':cat {log_file}')
35
37
 
36
38
  return cnt
37
39
 
@@ -111,7 +113,8 @@ class ExportDatabases:
111
113
  return list({n.split('_')[0] for n in SQLite.database_names()})
112
114
 
113
115
  def export_database_names():
114
- return list({n.split('_')[0] for n in Athena.database_names(LIKE)})
116
+ with log_timing('ExportDatabases.Athena.database_names'):
117
+ return list({n.split('_')[0] for n in Athena.database_names(LIKE)})
115
118
 
116
119
  def database_names_with_keyspace_cnt(importer: str = None):
117
120
  r = {}
@@ -191,20 +194,26 @@ class ExportDatabaseService:
191
194
  def __init__(self, handler: 'ExportDatabaseHandler'):
192
195
  self.handler = handler
193
196
 
194
- def sql(self, query: str, database: str = None, backgrounded = False):
197
+ def sql(self, query: str, database: str = None, backgrounded = False, export_log: str = None):
195
198
  if not database:
196
199
  database = self.handler.state.export_session
197
200
 
198
- def output(out: str):
199
- log_prefix = Config().get('export.log-prefix', '/tmp/qing')
200
- log_file = f'{log_prefix}-{datetime.now().strftime("%d%H%M%S")}-export.log'
201
-
202
- with open(log_file, 'w') as f:
201
+ def output(export_log: str, out: str):
202
+ # serving for 1. export log or 2. job log for the sampling select 10 rows afterward
203
+ flag = 'at'
204
+ if not export_log:
205
+ export_log = f'{export_log_dir()}/{datetime.now().strftime("%d%H%M%S")}-export.log'
206
+ flag = 'w'
207
+
208
+ with open(export_log, flag) as f:
209
+ if flag == 'at':
210
+ f.write(query)
211
+ f.write('\n')
203
212
  f.write(out)
204
213
 
205
- return log_file
214
+ return export_log
206
215
 
207
- ExportDatabases.run_query(query, database, output = output if backgrounded else None, show_query = not backgrounded)
216
+ ExportDatabases.run_query(query, database, output = partial(output, export_log) if backgrounded else None, show_query = not backgrounded)
208
217
 
209
218
  def drop(self, database: str):
210
219
  state = self.handler.state
@@ -1,12 +1,10 @@
1
- from adam.commands import extract_trailing_options, validate_args
2
1
  from adam.commands.command import Command
3
- from adam.commands.export.export_databases import ExportDatabases, export_db
2
+ from adam.commands.export.completions_x import completions_x
4
3
  from adam.repl_state import ReplState, RequiredState
5
- from adam.sql.sql_completer import SqlCompleter, SqlVariant
6
- from adam.utils_athena import Athena
7
4
 
5
+ # No action body, only for a help entry and auto-completion
8
6
  class ExportSelect(Command):
9
- COMMAND = '.select'
7
+ COMMAND = 'select_on_x'
10
8
 
11
9
  # the singleton pattern
12
10
  def __new__(cls, *args, **kwargs):
@@ -23,37 +21,14 @@ class ExportSelect(Command):
23
21
  def required(self):
24
22
  return RequiredState.EXPORT_DB
25
23
 
26
- def run(self, cmd: str, state: ReplState):
27
- if not(args := self.args(cmd)):
28
- return super().run(cmd, state)
29
-
30
- with self.validate(args, state) as (args, state):
31
- with extract_trailing_options(args, '&') as (args, backgrounded):
32
- with validate_args(args, state, name='SQL statement') as query:
33
- with export_db(state) as dbs:
34
- dbs.sql(f'select {query}', backgrounded=backgrounded)
35
-
36
- return state
37
-
38
24
  def completion(self, state: ReplState):
39
- if not state.export_session:
25
+ if state.device != ReplState.X:
40
26
  return {}
41
27
 
42
- db = state.export_session
43
-
44
- # warm up the caches first time when x: drive is accessed
45
- ExportDatabases.table_names(db)
46
- Athena.column_names(database=db, function='export')
47
- Athena.column_names(partition_cols_only=True, database=db, function='export')
28
+ if state.export_session:
29
+ return completions_x(state)
48
30
 
49
- return {ExportSelect.COMMAND: SqlCompleter(
50
- lambda: ExportDatabases.table_names(db),
51
- dml='select',
52
- expandables={
53
- 'columns':lambda table: Athena.column_names(database=db, function='export'),
54
- },
55
- variant=SqlVariant.ATHENA
56
- )}
31
+ return {}
57
32
 
58
- def help(self, _: ReplState):
59
- return f'.<sql-select-statements>\t run queries on export database'
33
+ def help(self, state: ReplState):
34
+ return super().help(state, 'run queries on export database', command='<sql-select-statements>')
@@ -3,14 +3,14 @@ import os
3
3
  import re
4
4
 
5
5
  from adam.commands.export.importer import Importer
6
- from adam.commands.export.utils_export import ExportTableStatus, csv_dir, find_files
6
+ from adam.commands.export.utils_export import ExportTableStatus, csv_dir, fs_exec, table_log_dir
7
7
  from adam.config import Config
8
8
  from adam.repl_state import ReplState
9
- from adam.utils import log2, tabulize, log, parallelize
9
+ from adam.utils import log2, log_to_pods, tabulize, log, parallelize
10
10
  from adam.utils_k8s.cassandra_nodes import CassandraNodes
11
- from adam.utils_k8s.pods import Pods, log_prefix
11
+ from adam.utils_k8s.pods import Pods
12
12
  from adam.utils_k8s.statefulsets import StatefulSets
13
- from adam.utils_local import local_tmp_dir
13
+ from adam.utils_local import local_downloads_dir
14
14
 
15
15
  class ExportSessions:
16
16
  def clear_export_session_cache():
@@ -36,13 +36,13 @@ class ExportSessions:
36
36
 
37
37
  prefix = Importer.prefix_from_importer(importer)
38
38
 
39
- log_files: list[str] = find_files(pod, namespace, f'{log_prefix()}-{prefix}*_*.log*')
39
+ log_files: list[str] = Pods.find_files(pod, 'cassandra', namespace, f'{table_log_dir(pod, namespace)}/{prefix}*_*.log*', remote=log_to_pods())
40
40
 
41
41
  if not log_files:
42
42
  return {}
43
43
 
44
44
  for log_file in log_files[:limit]:
45
- m = re.match(f'{log_prefix()}-(.*?)_.*\.log?(.*)', log_file)
45
+ m = re.match(f'{table_log_dir(pod, namespace)}/([ces].*?)_.*\.log?(.*)', log_file)
46
46
  if m:
47
47
  s = m.group(1)
48
48
  state = m.group(2) # '', '.pending_import', '.done'
@@ -66,7 +66,8 @@ class ExportSessions:
66
66
  pod = StatefulSets.pod_names(sts, namespace)[0]
67
67
 
68
68
  CassandraNodes.exec(pod, namespace, f'rm -rf {csv_dir()}/*', show_out=Config().is_debug(), shell='bash')
69
- CassandraNodes.exec(pod, namespace, f'rm -rf {log_prefix()}-*.log*', show_out=Config().is_debug(), shell='bash')
69
+ cmd = f'rm -rf {table_log_dir(pod, namespace)}/*.log*'
70
+ fs_exec(pod, namespace, cmd, show_out=Config().is_debug())
70
71
 
71
72
  return True
72
73
 
@@ -102,17 +103,18 @@ class ExportSessions:
102
103
  csv_cnt = 0
103
104
  log_cnt = 0
104
105
 
105
- log_files: list[str] = find_files(pod, namespace, f'{log_prefix()}-{session}_*.log*')
106
+ log_files: list[str] = Pods.find_files(pod, 'cassandra', namespace, f'{table_log_dir(pod, namespace)}/{session}_*.log*', remote=log_to_pods())
106
107
 
107
108
  for log_file in log_files:
108
- m = re.match(f'{log_prefix()}-{session}_(.*?)\.(.*?)\.log.*', log_file)
109
+ m = re.match(f'{table_log_dir(pod, namespace)}/{session}_(.*?)\.(.*?)\.log.*', log_file)
109
110
  if m:
110
111
  table = m.group(2)
111
112
 
112
113
  CassandraNodes.exec(pod, namespace, f'rm -rf {csv_dir()}/{session}_{table}', show_out=not multi_tables, shell='bash')
113
114
  csv_cnt += 1
114
115
 
115
- CassandraNodes.exec(pod, namespace, f'rm -rf {log_file}', show_out=not multi_tables, shell='bash')
116
+ cmd = f'rm -rf {log_file}'
117
+ fs_exec(pod, namespace, cmd, show_out=not multi_tables)
116
118
  log_cnt += 1
117
119
 
118
120
  return csv_cnt, log_cnt
@@ -142,7 +144,7 @@ class ExportSessions:
142
144
  def download_csv(table):
143
145
  from_path: str = table.csv_file
144
146
 
145
- to_path = from_path.replace(csv_dir(), local_tmp_dir())
147
+ to_path = from_path.replace(csv_dir(), local_downloads_dir())
146
148
  os.makedirs(os.path.dirname(to_path), exist_ok=True)
147
149
  Pods.download_file(pod, 'cassandra', namespace, from_path, to_path)
148
150
 
@@ -1,6 +1,6 @@
1
1
  from adam.commands import validate_args
2
2
  from adam.commands.command import Command
3
- from adam.commands.export.export_databases import ExportDatabases, export_db
3
+ from adam.commands.export.export_databases import export_db
4
4
  from adam.repl_state import ReplState
5
5
  from adam.utils import log2
6
6
 
@@ -20,7 +20,7 @@ class ExportUse(Command):
20
20
  return ExportUse.COMMAND
21
21
 
22
22
  def required(self):
23
- return [ReplState.C, ReplState.X]
23
+ return [ReplState.C]
24
24
 
25
25
  def run(self, cmd: str, state: ReplState):
26
26
  if not(args := self.args(cmd)):
@@ -42,8 +42,8 @@ class ExportUse(Command):
42
42
 
43
43
  return state
44
44
 
45
- def completion(self, state: ReplState):
46
- return super().completion(state, {n: None for n in ExportDatabases.database_names()})
45
+ def completion(self, _: ReplState):
46
+ return {}
47
47
 
48
- def help(self, _: ReplState):
49
- return f'{ExportUse.COMMAND} <export-database-name>\t use export database'
48
+ def help(self, state: ReplState):
49
+ return super().help(state, 'use export database', args='<export-database-name>')
@@ -0,0 +1,48 @@
1
+ from adam.commands import extract_trailing_options, validate_args
2
+ from adam.commands.command import Command
3
+ from adam.commands.export.completions_x import completions_x
4
+ from adam.commands.export.export_databases import export_db
5
+ from adam.repl_state import ReplState, RequiredState
6
+
7
+ class ExportXSelect(Command):
8
+ COMMAND = 'xelect'
9
+
10
+ # the singleton pattern
11
+ def __new__(cls, *args, **kwargs):
12
+ if not hasattr(cls, 'instance'): cls.instance = super(ExportXSelect, 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 ExportXSelect.COMMAND
21
+
22
+ def required(self):
23
+ return RequiredState.EXPORT_DB
24
+
25
+ def run(self, cmd: str, state: ReplState):
26
+ if not(args := self.args(cmd)):
27
+ return super().run(cmd, state)
28
+
29
+ with self.validate(args, state) as (args, state):
30
+ with extract_trailing_options(args, '&') as (args, backgrounded):
31
+ with validate_args(args, state, name='SQL statement') as query:
32
+ with export_db(state) as dbs:
33
+ dbs.sql(f'select {query}', backgrounded=backgrounded)
34
+
35
+ return state
36
+
37
+ def completion(self, state: ReplState):
38
+ if state.device != ReplState.C:
39
+ return {}
40
+
41
+ if not state.export_session:
42
+ return {}
43
+
44
+ # add only xelect completions to c: drive from lark
45
+ return {ExportXSelect.COMMAND: completions_x(state)[ExportXSelect.COMMAND]}
46
+
47
+ def help(self, state: ReplState):
48
+ return super().help(state, 'run queries on export database', command='xelect...')