kaqing 2.0.115__py3-none-any.whl → 2.0.172__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of kaqing might be problematic. Click here for more details.

Files changed (187) hide show
  1. adam/__init__.py +0 -2
  2. adam/app_session.py +8 -11
  3. adam/batch.py +3 -3
  4. adam/checks/check_utils.py +14 -46
  5. adam/checks/cpu.py +7 -1
  6. adam/checks/cpu_metrics.py +52 -0
  7. adam/checks/disk.py +2 -3
  8. adam/columns/columns.py +3 -1
  9. adam/columns/cpu.py +3 -1
  10. adam/columns/cpu_metrics.py +22 -0
  11. adam/columns/memory.py +3 -4
  12. adam/commands/__init__.py +18 -0
  13. adam/commands/alter_tables.py +43 -47
  14. adam/commands/audit/audit.py +24 -25
  15. adam/commands/audit/audit_repair_tables.py +14 -17
  16. adam/commands/audit/audit_run.py +15 -23
  17. adam/commands/audit/show_last10.py +10 -13
  18. adam/commands/audit/show_slow10.py +10 -13
  19. adam/commands/audit/show_top10.py +10 -14
  20. adam/commands/audit/utils_show_top10.py +2 -3
  21. adam/commands/bash/__init__.py +5 -0
  22. adam/commands/bash/bash.py +8 -96
  23. adam/commands/bash/utils_bash.py +16 -0
  24. adam/commands/cat.py +14 -19
  25. adam/commands/cd.py +12 -100
  26. adam/commands/check.py +20 -21
  27. adam/commands/cli_commands.py +2 -3
  28. adam/commands/code.py +20 -23
  29. adam/commands/command.py +123 -39
  30. adam/commands/commands_utils.py +8 -17
  31. adam/commands/cp.py +33 -39
  32. adam/commands/cql/cql_completions.py +28 -10
  33. adam/commands/cql/cqlsh.py +10 -30
  34. adam/commands/cql/utils_cql.py +343 -0
  35. adam/commands/deploy/code_start.py +7 -10
  36. adam/commands/deploy/code_stop.py +4 -21
  37. adam/commands/deploy/code_utils.py +3 -3
  38. adam/commands/deploy/deploy.py +4 -27
  39. adam/commands/deploy/deploy_frontend.py +14 -17
  40. adam/commands/deploy/deploy_pg_agent.py +2 -5
  41. adam/commands/deploy/deploy_pod.py +65 -73
  42. adam/commands/deploy/deploy_utils.py +14 -24
  43. adam/commands/deploy/undeploy.py +4 -27
  44. adam/commands/deploy/undeploy_frontend.py +4 -7
  45. adam/commands/deploy/undeploy_pg_agent.py +5 -7
  46. adam/commands/deploy/undeploy_pod.py +11 -12
  47. adam/commands/devices/__init__.py +0 -0
  48. adam/commands/devices/device.py +118 -0
  49. adam/commands/devices/device_app.py +173 -0
  50. adam/commands/devices/device_auit_log.py +49 -0
  51. adam/commands/devices/device_cass.py +185 -0
  52. adam/commands/devices/device_export.py +86 -0
  53. adam/commands/devices/device_postgres.py +144 -0
  54. adam/commands/devices/devices.py +25 -0
  55. adam/commands/exit.py +1 -4
  56. adam/commands/export/clean_up_all_export_sessions.py +37 -0
  57. adam/commands/export/clean_up_export_sessions.py +51 -0
  58. adam/commands/export/drop_export_database.py +55 -0
  59. adam/commands/export/drop_export_databases.py +43 -0
  60. adam/commands/export/export.py +19 -26
  61. adam/commands/export/export_databases.py +174 -0
  62. adam/commands/export/export_handlers.py +71 -0
  63. adam/commands/export/export_select.py +48 -22
  64. adam/commands/export/export_select_x.py +54 -0
  65. adam/commands/export/export_use.py +19 -23
  66. adam/commands/export/exporter.py +353 -0
  67. adam/commands/export/import_session.py +40 -0
  68. adam/commands/export/importer.py +67 -0
  69. adam/commands/export/importer_athena.py +77 -0
  70. adam/commands/export/importer_sqlite.py +39 -0
  71. adam/commands/export/show_column_counts.py +54 -0
  72. adam/commands/export/show_export_databases.py +36 -0
  73. adam/commands/export/show_export_session.py +48 -0
  74. adam/commands/export/show_export_sessions.py +44 -0
  75. adam/commands/export/utils_export.py +223 -162
  76. adam/commands/help.py +1 -1
  77. adam/commands/intermediate_command.py +49 -0
  78. adam/commands/issues.py +11 -43
  79. adam/commands/kubectl.py +3 -6
  80. adam/commands/login.py +22 -24
  81. adam/commands/logs.py +3 -6
  82. adam/commands/ls.py +11 -128
  83. adam/commands/medusa/medusa.py +4 -22
  84. adam/commands/medusa/medusa_backup.py +20 -24
  85. adam/commands/medusa/medusa_restore.py +29 -33
  86. adam/commands/medusa/medusa_show_backupjobs.py +14 -18
  87. adam/commands/medusa/medusa_show_restorejobs.py +11 -18
  88. adam/commands/nodetool.py +6 -15
  89. adam/commands/param_get.py +11 -12
  90. adam/commands/param_set.py +9 -10
  91. adam/commands/postgres/postgres.py +41 -34
  92. adam/commands/postgres/postgres_context.py +57 -24
  93. adam/commands/postgres/postgres_ls.py +4 -8
  94. adam/commands/postgres/postgres_preview.py +5 -9
  95. adam/commands/postgres/psql_completions.py +1 -1
  96. adam/commands/postgres/utils_postgres.py +66 -0
  97. adam/commands/preview_table.py +5 -44
  98. adam/commands/pwd.py +14 -47
  99. adam/commands/reaper/reaper.py +4 -27
  100. adam/commands/reaper/reaper_forward.py +48 -55
  101. adam/commands/reaper/reaper_forward_session.py +6 -0
  102. adam/commands/reaper/reaper_forward_stop.py +10 -16
  103. adam/commands/reaper/reaper_restart.py +7 -14
  104. adam/commands/reaper/reaper_run_abort.py +11 -30
  105. adam/commands/reaper/reaper_runs.py +42 -57
  106. adam/commands/reaper/reaper_runs_abort.py +29 -49
  107. adam/commands/reaper/reaper_schedule_activate.py +11 -30
  108. adam/commands/reaper/reaper_schedule_start.py +10 -29
  109. adam/commands/reaper/reaper_schedule_stop.py +10 -29
  110. adam/commands/reaper/reaper_schedules.py +4 -14
  111. adam/commands/reaper/reaper_status.py +8 -16
  112. adam/commands/reaper/utils_reaper.py +196 -0
  113. adam/commands/repair/repair.py +4 -22
  114. adam/commands/repair/repair_log.py +5 -11
  115. adam/commands/repair/repair_run.py +27 -34
  116. adam/commands/repair/repair_scan.py +32 -38
  117. adam/commands/repair/repair_stop.py +5 -11
  118. adam/commands/report.py +27 -29
  119. adam/commands/restart.py +25 -26
  120. adam/commands/rollout.py +19 -24
  121. adam/commands/shell.py +10 -4
  122. adam/commands/show/show.py +10 -25
  123. adam/commands/show/show_cassandra_repairs.py +35 -0
  124. adam/commands/show/show_cassandra_status.py +32 -43
  125. adam/commands/show/show_cassandra_version.py +5 -18
  126. adam/commands/show/show_commands.py +19 -24
  127. adam/commands/show/show_host.py +1 -1
  128. adam/commands/show/show_login.py +20 -27
  129. adam/commands/show/show_processes.py +15 -19
  130. adam/commands/show/show_storage.py +10 -20
  131. adam/commands/watch.py +26 -29
  132. adam/config.py +5 -14
  133. adam/embedded_params.py +1 -1
  134. adam/log.py +4 -4
  135. adam/pod_exec_result.py +3 -3
  136. adam/repl.py +40 -103
  137. adam/repl_commands.py +32 -16
  138. adam/repl_state.py +57 -28
  139. adam/sql/sql_completer.py +44 -28
  140. adam/sql/sql_state_machine.py +89 -28
  141. adam/sso/authn_ad.py +6 -8
  142. adam/sso/authn_okta.py +4 -6
  143. adam/sso/cred_cache.py +3 -5
  144. adam/sso/idp.py +9 -12
  145. adam/utils.py +435 -6
  146. adam/utils_athena.py +57 -37
  147. adam/utils_audits.py +12 -14
  148. adam/utils_issues.py +32 -0
  149. adam/utils_k8s/app_clusters.py +13 -18
  150. adam/utils_k8s/app_pods.py +2 -0
  151. adam/utils_k8s/cassandra_clusters.py +22 -19
  152. adam/utils_k8s/cassandra_nodes.py +2 -2
  153. adam/utils_k8s/custom_resources.py +16 -17
  154. adam/utils_k8s/ingresses.py +2 -2
  155. adam/utils_k8s/jobs.py +7 -11
  156. adam/utils_k8s/k8s.py +87 -0
  157. adam/utils_k8s/pods.py +40 -77
  158. adam/utils_k8s/secrets.py +4 -4
  159. adam/utils_k8s/service_accounts.py +5 -4
  160. adam/utils_k8s/services.py +2 -2
  161. adam/utils_k8s/statefulsets.py +1 -12
  162. adam/utils_net.py +4 -4
  163. adam/utils_repl/__init__.py +0 -0
  164. adam/utils_repl/automata_completer.py +48 -0
  165. adam/utils_repl/repl_completer.py +46 -0
  166. adam/utils_repl/state_machine.py +173 -0
  167. adam/utils_sqlite.py +137 -0
  168. adam/version.py +1 -1
  169. {kaqing-2.0.115.dist-info → kaqing-2.0.172.dist-info}/METADATA +1 -1
  170. kaqing-2.0.172.dist-info/RECORD +230 -0
  171. adam/commands/app.py +0 -67
  172. adam/commands/app_ping.py +0 -44
  173. adam/commands/cql/cql_utils.py +0 -204
  174. adam/commands/devices.py +0 -147
  175. adam/commands/export/export_on_x.py +0 -76
  176. adam/commands/export/export_rmdbs.py +0 -65
  177. adam/commands/postgres/postgres_utils.py +0 -31
  178. adam/commands/reaper/reaper_session.py +0 -159
  179. adam/commands/show/show_app_actions.py +0 -56
  180. adam/commands/show/show_app_id.py +0 -47
  181. adam/commands/show/show_app_queues.py +0 -45
  182. adam/commands/show/show_repairs.py +0 -47
  183. adam/utils_export.py +0 -42
  184. kaqing-2.0.115.dist-info/RECORD +0 -203
  185. {kaqing-2.0.115.dist-info → kaqing-2.0.172.dist-info}/WHEEL +0 -0
  186. {kaqing-2.0.115.dist-info → kaqing-2.0.172.dist-info}/entry_points.txt +0 -0
  187. {kaqing-2.0.115.dist-info → kaqing-2.0.172.dist-info}/top_level.txt +0 -0
adam/repl_state.py CHANGED
@@ -20,31 +20,8 @@ class BashSession:
20
20
  def pwd(self, state: 'ReplState'):
21
21
  command = f'cat /tmp/.qing-{self.session_id}'
22
22
 
23
- if state.device == ReplState.A and state.app_app:
24
- if state.app_pod:
25
- rs = [AppPods.exec(state.app_pod, state.namespace, command, show_out=False)]
26
- else:
27
- pods = AppPods.pod_names(state.namespace, state.app_env, state.app_pod)
28
- rs = AppClusters.exec(pods, state.namespace, command, show_out=False)
29
- elif state.pod:
30
- rs = [CassandraNodes.exec(state.pod, state.namespace, command, show_out=False)]
31
- elif state.sts:
32
- rs = CassandraClusters.exec(state.sts, state.namespace, command, action='bash', show_out=False)
33
-
34
- dir = None
35
- for r in rs:
36
- if r.exit_code(): # if fails to read the session file, ignore
37
- continue
38
-
39
- dir0 = r.stdout.strip(' \r\n')
40
- if dir:
41
- if dir != dir0:
42
- log2('Inconsitent working dir found across multiple pods.')
43
- return None
44
- else:
45
- dir = dir0
46
-
47
- return dir
23
+ with device(state) as pods:
24
+ return pods.exec(command, action='bash', show_out=False)
48
25
 
49
26
  class RequiredState(Enum):
50
27
  CLUSTER = 'cluster'
@@ -124,6 +101,8 @@ class ReplState:
124
101
  msg = f'{ReplState.L}:'
125
102
  elif self.device == ReplState.X:
126
103
  msg = f'{ReplState.X}:'
104
+ if self.export_session:
105
+ msg += self.export_session
127
106
  else:
128
107
  msg = f'{ReplState.C}:'
129
108
  if self.pod:
@@ -361,13 +340,13 @@ class ReplState:
361
340
  return (False, error)
362
341
 
363
342
  elif required == RequiredState.EXPORT_DB:
364
- if self.device != ReplState.X:
343
+ if self.device not in [ReplState.C, ReplState.X]:
365
344
  return (False, None)
366
345
 
367
346
  if not self.export_session:
368
347
  def error():
369
348
  if self.in_repl:
370
- log2('use an export database first.')
349
+ log2("Select an export database first with 'use' command.")
371
350
  else:
372
351
  log2('* export database is missing.')
373
352
  log2()
@@ -424,6 +403,56 @@ class ReplState:
424
403
  self.app_env = o.app_env
425
404
  self.app_app = o.app_app
426
405
  self.app_pod = o.app_pod
406
+ # self.export_session = o.export_session
427
407
  self.namespace = o.namespace
428
408
 
429
- self.original_state = None
409
+ self.original_state = None
410
+
411
+ class DevicePodService:
412
+ def __init__(self, handler: 'DeviceExecHandler'):
413
+ self.handler = handler
414
+
415
+ def exec(self, command: str, action='bash', show_out = True):
416
+ state = self.handler.state
417
+
418
+ rs = None
419
+ if state.device == ReplState.A and state.app_app:
420
+ if state.app_pod:
421
+ rs = [AppPods.exec(state.app_pod, state.namespace, command, show_out=show_out)]
422
+ else:
423
+ pods = AppPods.pod_names(state.namespace, state.app_env, state.app_app)
424
+ rs = AppClusters.exec(pods, state.namespace, command, show_out=show_out)
425
+ elif state.pod:
426
+ rs = [CassandraNodes.exec(state.pod, state.namespace, command, show_out=show_out)]
427
+ elif state.sts:
428
+ rs = CassandraClusters.exec(state.sts, state.namespace, command, action=action, show_out=show_out)
429
+ # assume that pg-agent or ops pod is single pod
430
+
431
+ dir = None
432
+ if rs:
433
+ for r in rs:
434
+ if r.exit_code(): # if fails to read the session file, ignore
435
+ continue
436
+
437
+ dir0 = r.stdout.strip(' \r\n')
438
+ if dir:
439
+ if dir != dir0:
440
+ log2('Inconsitent working dir found across multiple pods.')
441
+ return None
442
+ else:
443
+ dir = dir0
444
+
445
+ return dir
446
+
447
+ class DeviceExecHandler:
448
+ def __init__(self, state: ReplState):
449
+ self.state = state
450
+
451
+ def __enter__(self):
452
+ return DevicePodService(self)
453
+
454
+ def __exit__(self, exc_type, exc_val, exc_tb):
455
+ return False
456
+
457
+ def device(state: ReplState):
458
+ return DeviceExecHandler(state)
adam/sql/sql_completer.py CHANGED
@@ -1,7 +1,8 @@
1
+ from enum import Enum
1
2
  from typing import Callable
2
3
 
3
4
  import sqlparse
4
- from sqlparse.sql import Statement, Token
5
+ from sqlparse.sql import Token
5
6
 
6
7
  from adam.sql.term_completer import TermCompleter
7
8
  from adam.utils_repl.automata_completer import AutomataCompleter
@@ -15,38 +16,39 @@ __all__ = [
15
16
  def default_columns(x: list[str]):
16
17
  return 'id,x.,y.,z.'.split(',')
17
18
 
19
+ class SqlVariant(Enum):
20
+ SQL = 'sql'
21
+ CQL = 'cql'
22
+ ATHENA = 'athena'
23
+
18
24
  class SqlCompleter(AutomataCompleter[Token]):
19
25
  def tokens(self, text: str) -> list[Token]:
20
26
  tokens = []
21
27
 
22
28
  stmts = sqlparse.parse(text)
23
- if not stmts:
24
- tokens = []
25
- else:
26
- statement: Statement = stmts[0]
27
- tokens = statement.tokens
29
+ if stmts:
30
+ for stmt in stmts:
31
+ tokens.extend(stmt.tokens)
28
32
 
29
33
  return tokens
30
34
 
31
35
  def __init__(self,
32
36
  tables: Callable[[], list[str]],
33
37
  dml: str = None,
34
- columns: Callable[[list[str]], list[str]] = default_columns,
35
- partition_columns: Callable[[list[str]], list[str]] = lambda x: [],
36
- table_props: Callable[[], dict[str,list[str]]] = lambda: [],
37
- variant = 'sql',
38
+ expandables: dict = {},
39
+ variant: SqlVariant = SqlVariant.SQL,
38
40
  debug = False):
39
41
  machine = SqlStateMachine(debug=debug)
40
- if variant == 'cql':
42
+ if variant == SqlVariant.CQL:
41
43
  machine = CqlStateMachine(debug=debug)
42
- elif variant == 'athena':
44
+ elif variant == SqlVariant.ATHENA:
43
45
  machine = AthenaStateMachine(debug=debug)
44
46
  super().__init__(machine, dml, debug)
45
47
 
46
48
  self.tables = tables
47
- self.columns = columns
48
- self.partition_columns = partition_columns
49
- self.table_props = table_props
49
+ if 'columns' not in expandables:
50
+ expandables['columns'] = default_columns
51
+ self.expandables = expandables
50
52
  self.variant = variant
51
53
  self.debug = debug
52
54
 
@@ -63,40 +65,54 @@ class SqlCompleter(AutomataCompleter[Token]):
63
65
  def _terms(self, state: State, word: str) -> list[str]:
64
66
  terms = []
65
67
 
66
- if word == 'tables':
68
+ if word.startswith('`') and word.endswith('`'):
69
+ terms.append(word.strip('`'))
70
+ elif word == 'tables':
67
71
  terms.extend(self.tables())
68
- elif word == '`tables`':
69
- terms.append('tables')
70
72
  elif word == 'columns':
71
73
  if 'last_name' in state.context and (n := state.context['last_name']):
72
74
  if 'last_namespace' in state.context and (ns := state.context['last_namespace']):
73
75
  n = f'{ns}.{n}'
74
- terms.extend(self.columns([n]))
76
+ terms.extend(self._call_expandable(word, [n]))
75
77
  else:
76
- terms.extend(self.columns([]))
78
+ terms.extend(self._call_expandable(word, []))
77
79
  elif word == 'partition-columns':
78
- terms.extend(self.partition_columns([]))
80
+ terms.extend(self._call_expandable(word, []))
79
81
  elif word == 'table-props':
80
- terms.extend(self.table_props().keys())
82
+ terms.extend(self._call_expandable(word).keys())
81
83
  elif word == 'table-prop-values':
82
84
  if 'last_name' in state.context and state.context['last_name']:
83
- terms.extend(self.table_props()[state.context['last_name']])
85
+ table_props = self._call_expandable('table-props')
86
+ terms.extend(table_props[state.context['last_name']])
84
87
  elif word == 'single':
85
88
  terms.append("'")
86
89
  elif word == 'comma':
87
90
  terms.append(",")
91
+ elif word in self.machine.expandable_names():
92
+ terms.extend(self._call_expandable(word))
88
93
  else:
89
94
  terms.append(word)
90
95
 
91
96
  return terms
92
97
 
98
+ def _call_expandable(self, name: str, *args):
99
+ if name in self.expandables:
100
+ c = self.expandables[name]
101
+ if args:
102
+ return c(args)
103
+ else:
104
+ return c()
105
+
106
+ return []
107
+
93
108
  def completions_for_nesting(self, dml: str = None):
94
109
  if dml:
95
- return {dml: SqlCompleter(self.tables, dml, columns=self.columns, partition_columns=self.partition_columns,
96
- table_props=self.table_props, variant=self.variant)}
110
+ return {dml: SqlCompleter(self.tables, dml, expandables=self.expandables, variant=self.variant)}
97
111
 
98
112
  return {
99
- word : SqlCompleter(self.tables, word, columns=self.columns, partition_columns=self.partition_columns,
100
- table_props=self.table_props, variant=self.variant)
113
+ word: SqlCompleter(self.tables, word, expandables=self.expandables, variant=self.variant)
101
114
  for word in self.machine.suggestions[''].strip(' ').split(',')
102
- }
115
+ }
116
+
117
+ def __str__(self):
118
+ return f'{self.variant}, {self.first_term}'
@@ -2,6 +2,7 @@ from typing import Callable
2
2
  from sqlparse.sql import Token
3
3
  from sqlparse import tokens as TOKEN
4
4
 
5
+ from adam.utils import log_exc
5
6
  from adam.utils_repl.state_machine import StateMachine, State
6
7
 
7
8
  __all__ = [
@@ -76,8 +77,8 @@ SQL_SPEC = [
76
77
  '- > ; > ',
77
78
  'select_from_sq_ > as > select_from_x_as ^ as',
78
79
  'select_from_x_comma_ > name|audit > select_from_x ^ tables',
79
- 'select_from_x_ ^ as,where,inner join,left outer join,right outer join,full outer join,group by,order by,limit',
80
- 'select_from_x_as_x_ > , > select_from_x_comma_ ^ where,inner join,left outer join,right outer join,full outer join,group by,order by,limit',
80
+ 'select_from_x_ ^ as,where,inner join,left outer join,right outer join,full outer join,group by,order by,limit,&',
81
+ 'select_from_x_as_x_ > , > select_from_x_comma_ ^ where,inner join,left outer join,right outer join,full outer join,group by,order by,limit,&',
81
82
  '- > as > select_from_x_as',
82
83
  '- > where > select_where',
83
84
  '- > order > select_order',
@@ -96,6 +97,7 @@ SQL_SPEC = [
96
97
  '- > full > select_from_x_full',
97
98
  '- > full outer join > select_join',
98
99
  '- > ; > ',
100
+ '- > & > select_from_x$',
99
101
  'select_from_x_as_ > name > select_from_x_as_x ^ x,y,z',
100
102
  'select_from_x_as_x > , > select_from_x_as_x_comma_',
101
103
  '- > ; > ',
@@ -118,34 +120,38 @@ SQL_SPEC = [
118
120
  'select_where_a_not_op > name|single|num > select_where_sc ^ single',
119
121
  'select_where_a_op > name|single|num > select_where_sc ^ single',
120
122
  'select_where_sc > ; > ',
121
- 'select_where_sc_ > and|or > select_where ^ and,or,order by,group by,limit',
123
+ 'select_where_sc_ > and|or > select_where ^ and,or,order by,group by,limit,&',
122
124
  '- > group > select_group',
123
125
  '- > group by > select_group_by',
124
126
  '- > order > select_order',
125
127
  '- > order by > select_order_by',
126
128
  '- > limit > select_where_sc_limit',
127
129
  '- > ; > ',
130
+ '- > & > select_from_x$',
128
131
  'select_group_ > by > select_group_by ^ by',
129
132
  'select_group_by_ > name > select_group_by_a ^ columns',
130
133
  'select_group_by_a > , > select_group_by_a_comma_ ^ columns',
131
134
  '- > ; > ',
132
135
  'select_group_by_a_comma_ > name > select_group_by_a ^ columns',
133
- 'select_group_by_a_ > limit > select_where_sc_limit ^ limit,order by',
136
+ 'select_group_by_a_ > limit > select_where_sc_limit ^ limit,order by,&',
134
137
  '- > order > select_order',
135
138
  '- > order by > select_order_by',
136
139
  '- > ; > ',
140
+ '- > & > select_from_x$',
137
141
  'select_order_ > by > select_order_by ^ by',
138
142
  'select_order_by_ > name > select_order_by_a ^ columns',
139
143
  'select_order_by_a > , > select_order_by_a_comma_',
140
144
  '- > ; > ',
141
145
  'select_order_by_a_comma_ > name > select_order_by_a ^ columns',
142
- 'select_order_by_a_ > desc|asc > select_order_by_a_desc ^ desc,asc,limit',
146
+ 'select_order_by_a_ > desc|asc > select_order_by_a_desc ^ desc,asc,limit,&',
143
147
  '- > limit > select_where_sc_limit',
144
148
  '- > ; > ',
149
+ '- > & > select_from_x$',
145
150
  'select_order_by_a_desc > , > select_order_by_a_comma_',
146
151
  '- > ; > ',
147
- 'select_order_by_a_desc_ > limit > select_where_sc_limit ^ limit',
152
+ 'select_order_by_a_desc_ > limit > select_where_sc_limit ^ limit,&',
148
153
  '- > ; > ',
154
+ '- > & > select_from_x$',
149
155
  'select_where_sc_limit_ > num > select_where_sc_limit_num ^ 1',
150
156
  'select_where_sc_limit_num > ; > ',
151
157
  'select_where_sc_limit_num_rp__ > as > select_from_x_as ^ as',
@@ -201,7 +207,9 @@ SQL_SPEC = [
201
207
  'insert_values > ( > insert_values_lp_',
202
208
  'insert_values_lp_ > name|single|num > insert_values_lp_v ^ single',
203
209
  'insert_values_lp_v > , > insert_values_lp_v_comma_',
210
+ '- > ) > insert_values_lp_v_rp_',
204
211
  'insert_values_lp_v_comma_ > name|single|num > insert_values_lp_v',
212
+ 'insert_values_lp_v_rp__ > & > insert_values_lp_v_rp_$ ^ &',
205
213
 
206
214
  # <update_statement> ::= UPDATE <table_name>
207
215
  # SET <set_clause_list>
@@ -222,8 +230,9 @@ SQL_SPEC = [
222
230
  'update_set_a_op > name|single|num > update_set_sc ^ single',
223
231
  'update_set_sc > , > update_set_sc_comma_',
224
232
  'update_set_sc_comma_ > name > update_set_a ^ id',
225
- 'update_set_sc_ > , > update_set_sc_comma_ ^ where',
233
+ 'update_set_sc_ > , > update_set_sc_comma_ ^ where,&',
226
234
  '- > where > update_where',
235
+ '- > & > update_set_sc$ ^ &',
227
236
  'update_where_ > name > update_where_a ^ id',
228
237
  'update_where_a > comparison > update_where_a_op',
229
238
  'update_where_a_ > comparison > update_where_a_op ^ =,<,<=,>,>=,<>,like,not,in',
@@ -240,7 +249,7 @@ SQL_SPEC = [
240
249
  'update_where_a_in_lp_a_comma_ > name|single|num > update_where_a_in_lp_a ^ single',
241
250
  'update_where_a_not_op > name|single|num > update_where_sc ^ single',
242
251
  'update_where_a_op > name|single|num > update_where_sc ^ single',
243
- 'update_where_sc_ > and|or > update_where ^ and,or',
252
+ 'update_where_sc_ > and|or > update_where ^ and,or,&',
244
253
 
245
254
  # <delete_statement> ::= DELETE FROM <table_name> [ WHERE <search_condition> ]
246
255
 
@@ -335,10 +344,10 @@ SQL_KEYWORDS = [
335
344
  'describe', 'preview'
336
345
  ]
337
346
 
338
- EXPANDABLE_NAMES = {'tables', 'columns', 'partition-columns', 'table-props', 'table-props-values'}
347
+ EXPANDABLE_NAMES = {'keyspaces', 'tables', 'columns', 'partition-columns', 'table-props', 'table-props-values'}
339
348
 
340
349
  CQL_SPEC = SQL_SPEC + [
341
- ' > select > select ^ select,insert,update,delete,alter,describe,preview,consistency',
350
+ ' > select > select ^ select,insert,update,delete,alter,describe,preview,consistency,export,import,drop,clean',
342
351
 
343
352
  # ALTER TABLE [ <keyspace_name> . ] <table_name>
344
353
  # ( ALTER <column_name> TYPE <cql_type>
@@ -357,7 +366,7 @@ CQL_SPEC = SQL_SPEC + [
357
366
  'alter_table_with_p_op_v_ > --include-reaper > alter_table_with_p_op_v_$ ^ --include-reaper',
358
367
 
359
368
  ' > describe > describe',
360
- 'describe_ > table > desc_table ^ table,`tables`,keyspace,keyspaces,schema',
369
+ 'describe_ > table > desc_table ^ table,`tables`,keyspace,`keyspaces`,schema',
361
370
  '- > tables > desc_tables',
362
371
  '- > keyspace > desc_keyspace',
363
372
  '- > keyspaces > desc_keyspaces',
@@ -365,20 +374,24 @@ CQL_SPEC = SQL_SPEC + [
365
374
  'desc_table_ > name > desc_table_t ^ tables',
366
375
  'desc_table_t_ > & > desc_table_t_$ ^ &',
367
376
  'desc_tables_ > & > desc_tables_$ ^ &',
368
- 'desc_keyspace_ > name > desc_keyspace_k',
377
+ 'desc_keyspace_ > name > desc_keyspace_k ^ keyspaces',
369
378
  'desc_keyspace_k_ > & > desc_keyspace_k_$ ^ &',
370
379
  'desc_schema_ > & > desc_schema_$ ^ &',
371
380
 
372
381
  ' > export > export',
373
- 'export_ > name > export_table ^ with,tables',
382
+ 'export_ > name > export_table ^ *,tables',
383
+ '- > * > export_all',
384
+ 'export_all_ > in > export_in ^ in,with',
374
385
  '- > with > export_with',
375
386
  'export_table > ( > export_table_lp_ ^ (,comma,with,tables',
376
- '- > , > export',
387
+ '- > , > export_table_comma_',
377
388
  '- > . > export_table ^ tables',
378
- 'export_table_ > ( > export_table_lp_ ^ as,(,comma,with consistency',
379
- '- > , > export',
389
+ 'export_table_ > ( > export_table_lp_ ^ as,(,comma,with consistency,to',
390
+ '- > , > export_table_comma_',
380
391
  '- > as > export_as',
381
392
  '- > with > export_with',
393
+ '- > to > export_table_to',
394
+ 'export_table_comma_ > name > export_table ^ tables',
382
395
  'export_table_lp_ > name > export_table_lp_a ^ columns',
383
396
  'export_table_lp_a > , > export_table_lp_a_comma_',
384
397
  '- > ) > export_table_lp_a_comma_rp_',
@@ -387,25 +400,56 @@ CQL_SPEC = SQL_SPEC + [
387
400
  '- > , > export ^ with consistency',
388
401
  '- > with > export_with',
389
402
  'export_as_ > name > export_as_f',
390
- 'export_as_f > , > export',
391
- 'export_as_f_ > , > export ^ with consistency',
403
+ 'export_as_f > , > export_table_comma_',
404
+ 'export_as_f_ > , > export_table_comma_ ^ with consistency,to',
392
405
  '- > with > export_with',
406
+ '- > to > export_table_to',
407
+ 'export_in_ > name > export_in_k ^ keyspaces',
408
+ 'export_in_k_ > with > export_with ^ with consistency',
393
409
  'export_with_ > consistency > export_with_consistency ^ consistency',
394
410
  'export_with_consistency_ > quorum|all|serial|one|each_quorum|local_quorum|any|local_one|two|three|local_serial > export_with_quorum ^ quorum,all,serial,one,each_quorum,local_quorum,any,local_one,two,three,local_serial',
411
+ 'export_table_to_ > athena|sqlite|csv > export_table_to$ ^ athena,sqlite,csv',
412
+
413
+ ' > import > import',
414
+ 'import_ > session > import_session ^ session',
415
+ 'import_session_ > name > import_session_s ^ export-sessions-incomplete',
416
+ 'import_session_s_ > to > import_session_to ^ to',
417
+ 'import_session_to_ > athena|sqlite > import_session_to$ ^ athena,sqlite',
395
418
 
396
419
  ' > consistency > consistency',
397
420
  'consistency_ > quorum|all|serial|one|each_quorum|local_quorum|any|local_one|two|three|local_serial > consistency_quorum ^ quorum,all,serial,one,each_quorum,local_quorum,any,local_one,two,three,local_serial',
398
- 'consistency_quorum > ; > '
421
+ 'consistency_quorum > ; > ',
422
+
423
+ ' > drop > drop',
424
+ 'drop_ > all > drop_all ^ all export databases,export database',
425
+ '- > export > drop_export',
426
+ 'drop_all_ > export > drop_all_export ^ export databases',
427
+ 'drop_all_export_ > databases > drop_all_dbs ^ databases',
428
+ 'drop_export_ > database > drop_export_db ^ database',
429
+ 'drop_export_db_ > name > drop_export_db$ ^ export-dbs',
430
+
431
+ ' > clean > clean',
432
+ 'clean_ > up > clean_up ^ up all export sessions,up export session',
433
+ 'clean_up_ > all > clean_up_all ^ all export sessions,export sessions',
434
+ '- > export > clean_up_export',
435
+ 'clean_up_all_ > export > clean_up_all_export ^ export sessions',
436
+ 'clean_up_all_export_ > sessions > clean_up_all_sessions ^ sessions',
437
+ 'clean_up_export_ > sessions > clean_up_export_sessions ^ sessions',
438
+ 'clean_up_export_sessions_ > name > clean_up_export_sessions$ ^ export-sessions',
399
439
  ]
400
440
 
401
441
  CQL_KEYWORDS = SQL_KEYWORDS + [
402
- 'schema', 'keyspace', 'keyspaces', 'tables', 'export', 'consistency',
403
- 'quorum', 'all', 'serial', 'one', 'each_quorum', 'local_quorum', 'any', 'local_one', 'two', 'three', 'local_serial', 'to'
442
+ 'schema', 'keyspace', 'keyspaces', 'tables', 'export', 'copy', 'consistency',
443
+ 'quorum', 'all', 'serial', 'one', 'each_quorum', 'local_quorum', 'any', 'local_one', 'two', 'three', 'local_serial', 'to',
444
+ 'database', 'databases', 'session', 'sessions', 'clean', 'up', 'athena', 'sqlite', 'csv', 'import'
404
445
  ]
405
446
 
447
+ CQL_EXPANDABLE_NAMES = EXPANDABLE_NAMES | {
448
+ 'export-dbs', 'export-sessions', 'export-sessions-incomplete'
449
+ }
450
+
406
451
  ATHENA_SPEC = SQL_SPEC + [
407
- ' > select > select ^ select,insert,update,delete,alter,describe,preview',
408
- ' > &select > select ^ select,insert,update,delete,alter,describe,preview',
452
+ ' > select > select ^ select,insert,update,delete,alter,describe,preview,drop',
409
453
 
410
454
  'alter_table_t_ > add > alter_table_add ^ add partition,drop partition',
411
455
  'alter_table_add_ > partition > alter_partition ^ partition',
@@ -421,13 +465,26 @@ ATHENA_SPEC = SQL_SPEC + [
421
465
  'describe_ > name > desc_t ^ tables',
422
466
  'desc_t_ > name > desc_t_',
423
467
 
424
- 'repair'
468
+ 'repair',
469
+
470
+ ' > drop > drop',
471
+ 'drop_ > all > drop_all ^ all export databases,export database',
472
+ '- > export > drop_export',
473
+ 'drop_all_ > export > drop_all_export ^ export databases',
474
+ 'drop_all_export_ > databases > drop_all_dbs ^ databases',
475
+ 'drop_export_ > database > drop_export_db ^ database',
476
+ 'drop_export_db_ > name > drop_export_db$ ^ export-dbs',
425
477
  ]
426
478
 
427
479
  ATHENA_KEYWORDS = SQL_KEYWORDS + [
428
- 'partition', '&select'
480
+ 'partition',
481
+ 'database', 'databases', 'session', 'sessions', 'clean', 'up', 'all', 'export'
429
482
  ]
430
483
 
484
+ ATHENA_EXPANDABLE_NAMES = EXPANDABLE_NAMES | {
485
+ 'export-dbs'
486
+ }
487
+
431
488
  class SqlStateMachine(StateMachine[Token]):
432
489
  def __init__(self, indent=0, push_level = 0, debug = False):
433
490
  super().__init__(indent, push_level, debug)
@@ -498,7 +555,7 @@ class SqlStateMachine(StateMachine[Token]):
498
555
  elif token.ttype == TOKEN.Operator.Comparison:
499
556
  it = 'comparison'
500
557
 
501
- try:
558
+ with log_exc(False):
502
559
  # print(f'\n{state.to_s} > {it} > ', end='')
503
560
  if comeback_state:
504
561
  state = comeback_state
@@ -509,8 +566,6 @@ class SqlStateMachine(StateMachine[Token]):
509
566
 
510
567
  if last_name:
511
568
  state.context['last_name'] = last_name
512
- except:
513
- pass
514
569
 
515
570
  return state
516
571
 
@@ -552,6 +607,9 @@ class CqlStateMachine(SqlStateMachine):
552
607
  def keywords(self):
553
608
  return CQL_KEYWORDS
554
609
 
610
+ def expandable_names(self):
611
+ return CQL_EXPANDABLE_NAMES
612
+
555
613
  class AthenaStateMachine(SqlStateMachine):
556
614
  def __init__(self, indent=0, push_level = 0, debug = False):
557
615
  super().__init__(indent, push_level, debug)
@@ -561,3 +619,6 @@ class AthenaStateMachine(SqlStateMachine):
561
619
 
562
620
  def keywords(self):
563
621
  return ATHENA_KEYWORDS
622
+
623
+ def expandable_names(self):
624
+ return ATHENA_EXPANDABLE_NAMES
adam/sso/authn_ad.py CHANGED
@@ -1,6 +1,5 @@
1
1
  import json
2
2
  import re
3
- import traceback
4
3
  import jwt
5
4
  import requests
6
5
  from urllib.parse import urlparse, parse_qs
@@ -8,6 +7,7 @@ from urllib.parse import urlparse, parse_qs
8
7
  from adam.log import Log
9
8
  from adam.sso.authenticator import Authenticator
10
9
  from adam.sso.id_token import IdToken
10
+ from adam.utils import debug, log_exc
11
11
  from .idp_login import IdpLogin
12
12
  from adam.config import Config
13
13
 
@@ -33,7 +33,7 @@ class AdAuthenticator(Authenticator):
33
33
 
34
34
  session = requests.Session()
35
35
  r = session.get(idp_uri)
36
- Config().debug(f'{r.status_code} {idp_uri}')
36
+ debug(f'{r.status_code} {idp_uri}')
37
37
 
38
38
  config = self.validate_and_return_config(r)
39
39
 
@@ -52,7 +52,7 @@ class AdAuthenticator(Authenticator):
52
52
  r = session.post(login_uri, data=body, headers={
53
53
  'Content-Type': 'application/x-www-form-urlencoded'
54
54
  })
55
- Config().debug(f'{r.status_code} {login_uri}')
55
+ debug(f'{r.status_code} {login_uri}')
56
56
 
57
57
  config = self.validate_and_return_config(r)
58
58
 
@@ -69,7 +69,7 @@ class AdAuthenticator(Authenticator):
69
69
  r = session.post(kmsi_uri, data=body, headers={
70
70
  'Content-Type': 'application/x-www-form-urlencoded'
71
71
  })
72
- Config().debug(f'{r.status_code} {kmsi_uri}')
72
+ debug(f'{r.status_code} {kmsi_uri}')
73
73
 
74
74
  if (config := self.extract_config_object(r.text)):
75
75
  if 'sErrorCode' in config and config['sErrorCode'] == '50058':
@@ -101,7 +101,7 @@ class AdAuthenticator(Authenticator):
101
101
 
102
102
  def validate_and_return_config(self, r: requests.Response):
103
103
  if r.status_code < 200 or r.status_code >= 300:
104
- Config().debug(r.text)
104
+ debug(r.text)
105
105
 
106
106
  return None
107
107
 
@@ -138,7 +138,7 @@ class AdAuthenticator(Authenticator):
138
138
 
139
139
  def parse_id_token(self, id_token: str) -> IdToken:
140
140
  jwks_url = Config().get('idps.ad.jwks-uri', '')
141
- try:
141
+ with log_exc():
142
142
  jwks_client = jwt.PyJWKClient(jwks_url, cache_jwk_set=True, lifespan=360)
143
143
  signing_key = jwks_client.get_signing_key_from_jwt(id_token)
144
144
  data = jwt.decode(
@@ -163,7 +163,5 @@ class AdAuthenticator(Authenticator):
163
163
  nbf=data['nbf'] if 'nbf' in data else 0,
164
164
  exp=data['exp'] if 'exp' in data else 0
165
165
  )
166
- except:
167
- Config().debug(traceback.format_exc())
168
166
 
169
167
  return None
adam/sso/authn_okta.py CHANGED
@@ -8,7 +8,7 @@ from adam.sso.id_token import IdToken
8
8
 
9
9
  from .idp_login import IdpLogin
10
10
  from adam.config import Config
11
- from adam.utils import log2
11
+ from adam.utils import debug, log2, log_exc
12
12
 
13
13
  class OktaException(Exception):
14
14
  pass
@@ -49,7 +49,7 @@ class OktaAuthenticator(Authenticator):
49
49
 
50
50
  session = requests.Session()
51
51
  response = session.post(authn_uri, headers=headers, data=json.dumps(payload))
52
- Config().debug(f'{response.status_code} {authn_uri}')
52
+ debug(f'{response.status_code} {authn_uri}')
53
53
  auth_response = response.json()
54
54
 
55
55
  if 'sessionToken' not in auth_response:
@@ -59,7 +59,7 @@ class OktaAuthenticator(Authenticator):
59
59
 
60
60
  url = f'{idp_uri}&sessionToken={session_token}'
61
61
  r = session.get(url)
62
- Config().debug(f'{r.status_code} {url}')
62
+ debug(f'{r.status_code} {url}')
63
63
 
64
64
  id_token = OktaAuthenticator().extract(r.text, r'.*name=\"id_token\" value=\"(.*?)\".*')
65
65
  if not id_token:
@@ -95,7 +95,7 @@ class OktaAuthenticator(Authenticator):
95
95
  return None
96
96
 
97
97
  jwks_url = Config().get('idps.okta.jwks-uri', 'https://c3energy.okta.com/oauth2/v1/keys')
98
- try:
98
+ with log_exc():
99
99
  jwks_client = jwt.PyJWKClient(jwks_url, cache_jwk_set=True, lifespan=360)
100
100
  signing_key = jwks_client.get_signing_key_from_jwt(id_token)
101
101
  data = jwt.decode(
@@ -121,7 +121,5 @@ class OktaAuthenticator(Authenticator):
121
121
  nbf=data['nbf'] if 'nbf' in data else 0,
122
122
  exp=data['exp'] if 'exp' in data else 0
123
123
  )
124
- except:
125
- pass
126
124
 
127
125
  return None