kaqing 2.0.104__tar.gz → 2.0.106__tar.gz

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 (193) hide show
  1. {kaqing-2.0.104 → kaqing-2.0.106}/PKG-INFO +1 -1
  2. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/audit/audit.py +12 -9
  3. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/audit/audit_repair_tables.py +6 -7
  4. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/audit/audit_run.py +9 -6
  5. kaqing-2.0.106/adam/commands/audit/show_last10.py +52 -0
  6. kaqing-2.0.106/adam/commands/audit/show_slow10.py +52 -0
  7. kaqing-2.0.106/adam/commands/audit/show_top10.py +52 -0
  8. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/ls.py +2 -2
  9. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/preview_table.py +3 -3
  10. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/show/show.py +3 -1
  11. kaqing-2.0.106/adam/embedded_params.py +2 -0
  12. {kaqing-2.0.104 → kaqing-2.0.106}/adam/repl.py +4 -47
  13. {kaqing-2.0.104 → kaqing-2.0.106}/adam/repl_commands.py +2 -2
  14. {kaqing-2.0.104 → kaqing-2.0.106}/adam/sql/sql_state_machine.py +9 -9
  15. kaqing-2.0.106/adam/utils_audits.py +192 -0
  16. kaqing-2.0.106/adam/version.py +5 -0
  17. {kaqing-2.0.104 → kaqing-2.0.106}/kaqing.egg-info/PKG-INFO +1 -1
  18. {kaqing-2.0.104 → kaqing-2.0.106}/kaqing.egg-info/SOURCES.txt +4 -1
  19. {kaqing-2.0.104 → kaqing-2.0.106}/setup.py +1 -1
  20. kaqing-2.0.104/adam/embedded_params.py +0 -2
  21. kaqing-2.0.104/adam/utils_athena.py +0 -162
  22. kaqing-2.0.104/adam/version.py +0 -5
  23. {kaqing-2.0.104 → kaqing-2.0.106}/README +0 -0
  24. {kaqing-2.0.104 → kaqing-2.0.106}/adam/__init__.py +0 -0
  25. {kaqing-2.0.104 → kaqing-2.0.106}/adam/app_session.py +0 -0
  26. {kaqing-2.0.104 → kaqing-2.0.106}/adam/apps.py +0 -0
  27. {kaqing-2.0.104 → kaqing-2.0.106}/adam/batch.py +0 -0
  28. {kaqing-2.0.104 → kaqing-2.0.106}/adam/checks/__init__.py +0 -0
  29. {kaqing-2.0.104 → kaqing-2.0.106}/adam/checks/check.py +0 -0
  30. {kaqing-2.0.104 → kaqing-2.0.106}/adam/checks/check_context.py +0 -0
  31. {kaqing-2.0.104 → kaqing-2.0.106}/adam/checks/check_result.py +0 -0
  32. {kaqing-2.0.104 → kaqing-2.0.106}/adam/checks/check_utils.py +0 -0
  33. {kaqing-2.0.104 → kaqing-2.0.106}/adam/checks/compactionstats.py +0 -0
  34. {kaqing-2.0.104 → kaqing-2.0.106}/adam/checks/cpu.py +0 -0
  35. {kaqing-2.0.104 → kaqing-2.0.106}/adam/checks/disk.py +0 -0
  36. {kaqing-2.0.104 → kaqing-2.0.106}/adam/checks/gossip.py +0 -0
  37. {kaqing-2.0.104 → kaqing-2.0.106}/adam/checks/issue.py +0 -0
  38. {kaqing-2.0.104 → kaqing-2.0.106}/adam/checks/memory.py +0 -0
  39. {kaqing-2.0.104 → kaqing-2.0.106}/adam/checks/status.py +0 -0
  40. {kaqing-2.0.104 → kaqing-2.0.106}/adam/cli.py +0 -0
  41. {kaqing-2.0.104 → kaqing-2.0.106}/adam/cli_group.py +0 -0
  42. {kaqing-2.0.104 → kaqing-2.0.106}/adam/columns/__init__.py +0 -0
  43. {kaqing-2.0.104 → kaqing-2.0.106}/adam/columns/column.py +0 -0
  44. {kaqing-2.0.104 → kaqing-2.0.106}/adam/columns/columns.py +0 -0
  45. {kaqing-2.0.104 → kaqing-2.0.106}/adam/columns/compactions.py +0 -0
  46. {kaqing-2.0.104 → kaqing-2.0.106}/adam/columns/cpu.py +0 -0
  47. {kaqing-2.0.104 → kaqing-2.0.106}/adam/columns/dir_data.py +0 -0
  48. {kaqing-2.0.104 → kaqing-2.0.106}/adam/columns/dir_snapshots.py +0 -0
  49. {kaqing-2.0.104 → kaqing-2.0.106}/adam/columns/gossip.py +0 -0
  50. {kaqing-2.0.104 → kaqing-2.0.106}/adam/columns/host_id.py +0 -0
  51. {kaqing-2.0.104 → kaqing-2.0.106}/adam/columns/memory.py +0 -0
  52. {kaqing-2.0.104 → kaqing-2.0.106}/adam/columns/node_address.py +0 -0
  53. {kaqing-2.0.104 → kaqing-2.0.106}/adam/columns/node_load.py +0 -0
  54. {kaqing-2.0.104 → kaqing-2.0.106}/adam/columns/node_owns.py +0 -0
  55. {kaqing-2.0.104 → kaqing-2.0.106}/adam/columns/node_status.py +0 -0
  56. {kaqing-2.0.104 → kaqing-2.0.106}/adam/columns/node_tokens.py +0 -0
  57. {kaqing-2.0.104 → kaqing-2.0.106}/adam/columns/node_utils.py +0 -0
  58. {kaqing-2.0.104 → kaqing-2.0.106}/adam/columns/pod_name.py +0 -0
  59. {kaqing-2.0.104 → kaqing-2.0.106}/adam/columns/volume_cassandra.py +0 -0
  60. {kaqing-2.0.104 → kaqing-2.0.106}/adam/columns/volume_root.py +0 -0
  61. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/__init__.py +0 -0
  62. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/alter_tables.py +0 -0
  63. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/app.py +0 -0
  64. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/app_ping.py +0 -0
  65. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/audit/__init__.py +0 -0
  66. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/bash.py +0 -0
  67. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/cd.py +0 -0
  68. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/check.py +0 -0
  69. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/cli_commands.py +0 -0
  70. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/command.py +0 -0
  71. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/command_helpers.py +0 -0
  72. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/commands_utils.py +0 -0
  73. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/cp.py +0 -0
  74. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/cql/__init__.py +0 -0
  75. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/cql/cql_completions.py +0 -0
  76. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/cql/cql_utils.py +0 -0
  77. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/cql/cqlsh.py +0 -0
  78. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/deploy/__init__.py +0 -0
  79. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/deploy/code_start.py +0 -0
  80. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/deploy/code_stop.py +0 -0
  81. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/deploy/code_utils.py +0 -0
  82. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/deploy/deploy.py +0 -0
  83. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/deploy/deploy_frontend.py +0 -0
  84. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/deploy/deploy_pg_agent.py +0 -0
  85. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/deploy/deploy_pod.py +0 -0
  86. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/deploy/deploy_utils.py +0 -0
  87. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/deploy/undeploy.py +0 -0
  88. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/deploy/undeploy_frontend.py +0 -0
  89. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/deploy/undeploy_pg_agent.py +0 -0
  90. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/deploy/undeploy_pod.py +0 -0
  91. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/devices.py +0 -0
  92. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/exit.py +0 -0
  93. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/help.py +0 -0
  94. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/issues.py +0 -0
  95. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/login.py +0 -0
  96. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/logs.py +0 -0
  97. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/medusa/__init__.py +0 -0
  98. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/medusa/medusa.py +0 -0
  99. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/medusa/medusa_backup.py +0 -0
  100. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/medusa/medusa_restore.py +0 -0
  101. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/medusa/medusa_show_backupjobs.py +0 -0
  102. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/medusa/medusa_show_restorejobs.py +0 -0
  103. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/nodetool.py +0 -0
  104. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/nodetool_commands.py +0 -0
  105. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/param_get.py +0 -0
  106. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/param_set.py +0 -0
  107. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/postgres/__init__.py +0 -0
  108. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/postgres/postgres.py +0 -0
  109. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/postgres/postgres_context.py +0 -0
  110. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/postgres/postgres_ls.py +0 -0
  111. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/postgres/postgres_preview.py +0 -0
  112. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/postgres/postgres_utils.py +0 -0
  113. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/postgres/psql_completions.py +0 -0
  114. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/pwd.py +0 -0
  115. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/reaper/__init__.py +0 -0
  116. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/reaper/reaper.py +0 -0
  117. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/reaper/reaper_forward.py +0 -0
  118. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/reaper/reaper_forward_stop.py +0 -0
  119. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/reaper/reaper_restart.py +0 -0
  120. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/reaper/reaper_run_abort.py +0 -0
  121. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/reaper/reaper_runs.py +0 -0
  122. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/reaper/reaper_runs_abort.py +0 -0
  123. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/reaper/reaper_schedule_activate.py +0 -0
  124. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/reaper/reaper_schedule_start.py +0 -0
  125. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/reaper/reaper_schedule_stop.py +0 -0
  126. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/reaper/reaper_schedules.py +0 -0
  127. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/reaper/reaper_session.py +0 -0
  128. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/reaper/reaper_status.py +0 -0
  129. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/repair/__init__.py +0 -0
  130. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/repair/repair.py +0 -0
  131. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/repair/repair_log.py +0 -0
  132. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/repair/repair_run.py +0 -0
  133. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/repair/repair_scan.py +0 -0
  134. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/repair/repair_stop.py +0 -0
  135. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/report.py +0 -0
  136. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/restart.py +0 -0
  137. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/rollout.py +0 -0
  138. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/shell.py +0 -0
  139. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/show/__init__.py +0 -0
  140. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/show/show_adam.py +0 -0
  141. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/show/show_app_actions.py +0 -0
  142. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/show/show_app_id.py +0 -0
  143. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/show/show_app_queues.py +0 -0
  144. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/show/show_cassandra_status.py +0 -0
  145. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/show/show_cassandra_version.py +0 -0
  146. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/show/show_commands.py +0 -0
  147. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/show/show_host.py +0 -0
  148. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/show/show_login.py +0 -0
  149. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/show/show_params.py +0 -0
  150. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/show/show_processes.py +0 -0
  151. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/show/show_repairs.py +0 -0
  152. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/show/show_storage.py +0 -0
  153. {kaqing-2.0.104 → kaqing-2.0.106}/adam/commands/watch.py +0 -0
  154. {kaqing-2.0.104 → kaqing-2.0.106}/adam/config.py +0 -0
  155. {kaqing-2.0.104 → kaqing-2.0.106}/adam/embedded_apps.py +0 -0
  156. {kaqing-2.0.104 → kaqing-2.0.106}/adam/log.py +0 -0
  157. {kaqing-2.0.104 → kaqing-2.0.106}/adam/pod_exec_result.py +0 -0
  158. {kaqing-2.0.104 → kaqing-2.0.106}/adam/repl_session.py +0 -0
  159. {kaqing-2.0.104 → kaqing-2.0.106}/adam/repl_state.py +0 -0
  160. {kaqing-2.0.104 → kaqing-2.0.106}/adam/sql/__init__.py +0 -0
  161. {kaqing-2.0.104 → kaqing-2.0.106}/adam/sql/sql_completer.py +0 -0
  162. {kaqing-2.0.104 → kaqing-2.0.106}/adam/sql/term_completer.py +0 -0
  163. {kaqing-2.0.104 → kaqing-2.0.106}/adam/sso/__init__.py +0 -0
  164. {kaqing-2.0.104 → kaqing-2.0.106}/adam/sso/authenticator.py +0 -0
  165. {kaqing-2.0.104 → kaqing-2.0.106}/adam/sso/authn_ad.py +0 -0
  166. {kaqing-2.0.104 → kaqing-2.0.106}/adam/sso/authn_okta.py +0 -0
  167. {kaqing-2.0.104 → kaqing-2.0.106}/adam/sso/cred_cache.py +0 -0
  168. {kaqing-2.0.104 → kaqing-2.0.106}/adam/sso/id_token.py +0 -0
  169. {kaqing-2.0.104 → kaqing-2.0.106}/adam/sso/idp.py +0 -0
  170. {kaqing-2.0.104 → kaqing-2.0.106}/adam/sso/idp_login.py +0 -0
  171. {kaqing-2.0.104 → kaqing-2.0.106}/adam/sso/idp_session.py +0 -0
  172. {kaqing-2.0.104 → kaqing-2.0.106}/adam/sso/sso_config.py +0 -0
  173. {kaqing-2.0.104 → kaqing-2.0.106}/adam/utils.py +0 -0
  174. {kaqing-2.0.104 → kaqing-2.0.106}/adam/utils_k8s/__init__.py +0 -0
  175. {kaqing-2.0.104 → kaqing-2.0.106}/adam/utils_k8s/cassandra_clusters.py +0 -0
  176. {kaqing-2.0.104 → kaqing-2.0.106}/adam/utils_k8s/cassandra_nodes.py +0 -0
  177. {kaqing-2.0.104 → kaqing-2.0.106}/adam/utils_k8s/config_maps.py +0 -0
  178. {kaqing-2.0.104 → kaqing-2.0.106}/adam/utils_k8s/custom_resources.py +0 -0
  179. {kaqing-2.0.104 → kaqing-2.0.106}/adam/utils_k8s/deployment.py +0 -0
  180. {kaqing-2.0.104 → kaqing-2.0.106}/adam/utils_k8s/ingresses.py +0 -0
  181. {kaqing-2.0.104 → kaqing-2.0.106}/adam/utils_k8s/jobs.py +0 -0
  182. {kaqing-2.0.104 → kaqing-2.0.106}/adam/utils_k8s/kube_context.py +0 -0
  183. {kaqing-2.0.104 → kaqing-2.0.106}/adam/utils_k8s/pods.py +0 -0
  184. {kaqing-2.0.104 → kaqing-2.0.106}/adam/utils_k8s/secrets.py +0 -0
  185. {kaqing-2.0.104 → kaqing-2.0.106}/adam/utils_k8s/service_accounts.py +0 -0
  186. {kaqing-2.0.104 → kaqing-2.0.106}/adam/utils_k8s/services.py +0 -0
  187. {kaqing-2.0.104 → kaqing-2.0.106}/adam/utils_k8s/statefulsets.py +0 -0
  188. {kaqing-2.0.104 → kaqing-2.0.106}/adam/utils_k8s/volumes.py +0 -0
  189. {kaqing-2.0.104 → kaqing-2.0.106}/adam/utils_net.py +0 -0
  190. {kaqing-2.0.104 → kaqing-2.0.106}/kaqing.egg-info/dependency_links.txt +0 -0
  191. {kaqing-2.0.104 → kaqing-2.0.106}/kaqing.egg-info/entry_points.txt +0 -0
  192. {kaqing-2.0.104 → kaqing-2.0.106}/kaqing.egg-info/top_level.txt +0 -0
  193. {kaqing-2.0.104 → kaqing-2.0.106}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: kaqing
3
- Version: 2.0.104
3
+ Version: 2.0.106
4
4
  Summary: UNKNOWN
5
5
  Home-page: UNKNOWN
6
6
  License: UNKNOWN
@@ -2,12 +2,15 @@ import click
2
2
 
3
3
  from adam.commands.audit.audit_repair_tables import AuditRepairTables
4
4
  from adam.commands.audit.audit_run import AuditRun
5
+ from adam.commands.audit.show_last10 import ShowLast10
6
+ from adam.commands.audit.show_slow10 import ShowSlow10
7
+ from adam.commands.audit.show_top10 import ShowTop10
5
8
  from adam.commands.command import Command
6
9
  from adam.config import Config
7
10
  from adam.repl_state import ReplState
8
11
  from adam.sql.sql_completer import SqlCompleter
9
12
  from adam.utils import log2
10
- from adam.utils_athena import audit_column_names, audit_table_names, run_audit_query
13
+ from adam.utils_audits import Audits
11
14
 
12
15
  class Audit(Command):
13
16
  COMMAND = 'audit'
@@ -42,7 +45,7 @@ class Audit(Command):
42
45
  else:
43
46
  log2(sql)
44
47
 
45
- run_audit_query(sql)
48
+ Audits.run_audit_query(sql)
46
49
 
47
50
  return state
48
51
 
@@ -52,23 +55,23 @@ class Audit(Command):
52
55
  Config().wait_log(f'Inspecting audit database schema...')
53
56
  self.schema_read = True
54
57
  # warm up the caches first time when l: drive is accessed
55
- audit_column_names()
56
- audit_column_names(partition_cols_only=True)
58
+ Audits.audit_column_names()
59
+ Audits.audit_column_names(partition_cols_only=True)
57
60
 
58
61
  return super().completion(state) | SqlCompleter(
59
- lambda: audit_table_names(),
60
- columns=lambda table: audit_column_names(),
61
- partition_columns=lambda table: audit_column_names(partition_cols_only=True),
62
+ lambda: Audits.audit_table_names(),
63
+ columns=lambda table: Audits.audit_column_names(),
64
+ partition_columns=lambda table: Audits.audit_column_names(partition_cols_only=True),
62
65
  variant='athena'
63
66
  ).completions_for_nesting()
64
67
 
65
68
  return {}
66
69
 
67
70
  def cmd_list():
68
- return [AuditRepairTables(), AuditRun()]
71
+ return [AuditRepairTables(), AuditRun(), ShowLast10(), ShowSlow10(), ShowTop10()]
69
72
 
70
73
  def help(self, _: ReplState):
71
- return f'[{Audit.COMMAND}] <sql-statements>\t run SQL queries on Authena audit database'
74
+ return f'[{Audit.COMMAND}] [<sql-statements>]\t run SQL queries on Authena audit database'
72
75
 
73
76
  class AuditCommandHelper(click.Command):
74
77
  def get_help(self, ctx: click.Context):
@@ -1,12 +1,11 @@
1
1
  import concurrent
2
2
  import time
3
- import requests
4
3
 
5
4
  from adam.commands.command import Command
6
5
  from adam.config import Config
7
6
  from adam.repl_state import ReplState
8
7
  from adam.utils import log, log2
9
- from adam.utils_athena import AuditMeta, audit_query, get_meta, put_meta, run_audit_query
8
+ from adam.utils_audits import AuditMeta, Audits
10
9
 
11
10
  class AuditRepairTables(Command):
12
11
  COMMAND = 'audit repair'
@@ -34,7 +33,7 @@ class AuditRepairTables(Command):
34
33
  if args:
35
34
  tables = args
36
35
 
37
- meta = get_meta()
36
+ meta = Audits.get_meta()
38
37
  self.repair(tables, meta)
39
38
 
40
39
  return state
@@ -53,8 +52,8 @@ class AuditRepairTables(Command):
53
52
  def auto_repair(self, hours: int):
54
53
  self.auto_repaired = True
55
54
 
56
- meta = get_meta()
57
- if meta.checked_in + hours * 60 * 60 < time.time():
55
+ meta: AuditMeta = Audits.get_meta()
56
+ if meta.partitions_last_checked + hours * 60 * 60 < time.time():
58
57
  tables = Config().get('audit.athena.repair-partition-tables', 'audit').split(',')
59
58
  self.repair(tables, meta, show_sql=True)
60
59
  log2(f'Audit tables have been auto-repaired.')
@@ -65,8 +64,8 @@ class AuditRepairTables(Command):
65
64
  if show_sql:
66
65
  log(f'MSCK REPAIR TABLE {table}')
67
66
 
68
- executor.submit(run_audit_query, f'MSCK REPAIR TABLE {table}', None,)
69
- executor.submit(put_meta, 'check-in', meta,)
67
+ executor.submit(Audits.run_audit_query, f'MSCK REPAIR TABLE {table}', None,)
68
+ executor.submit(Audits.put_meta, Audits.PARTITIONS_ADDED, meta,)
70
69
 
71
70
  def help(self, _: ReplState):
72
71
  return f"{AuditRepairTables.COMMAND} \t run MSCK REPAIR command for new partition discovery"
@@ -1,8 +1,10 @@
1
+ import concurrent
2
+
1
3
  from adam.commands.command import Command
2
4
  from adam.config import Config
3
5
  from adam.repl_state import ReplState
4
6
  from adam.utils import log2
5
- from adam.utils_athena import AuditMeta, find_new_clusters, get_meta, put_meta, run_audit_query
7
+ from adam.utils_audits import AuditMeta, Audits
6
8
 
7
9
  class AuditRun(Command):
8
10
  COMMAND = 'audit run'
@@ -26,14 +28,15 @@ class AuditRun(Command):
26
28
 
27
29
  state, args = self.apply_state(args, state)
28
30
 
29
- meta: AuditMeta = get_meta()
30
- clusters = find_new_clusters(meta.cluster_last_checked)
31
+ meta: AuditMeta = Audits.get_meta()
32
+ clusters = Audits.find_new_clusters(meta.cluster_last_checked)
33
+ Audits.put_meta(Audits.ADD_CLUSTERS, meta, clusters=clusters)
31
34
  if clusters:
32
- put_meta('add-clusters', meta, clusters=clusters)
33
35
  log2(f'Added {len(clusters)} new clusters.')
34
36
  tables = Config().get('audit.athena.repair-cluster-tables', 'cluster').split(',')
35
- for table in tables:
36
- run_audit_query(f'MSCK REPAIR TABLE {table}')
37
+ with concurrent.futures.ThreadPoolExecutor(max_workers=Config().get('audit.workers', 3)) as executor:
38
+ for table in tables:
39
+ executor.submit(Audits.run_audit_query, f'MSCK REPAIR TABLE {table}', None,)
37
40
  else:
38
41
  log2(f'No new clusters were found.')
39
42
 
@@ -0,0 +1,52 @@
1
+ from datetime import datetime, timedelta
2
+
3
+ from adam.commands.command import Command
4
+ from adam.repl_state import ReplState
5
+ from adam.utils import log2
6
+ from adam.utils_audits import Audits
7
+
8
+ class ShowLast10(Command):
9
+ COMMAND = 'show last'
10
+
11
+ # the singleton pattern
12
+ def __new__(cls, *args, **kwargs):
13
+ if not hasattr(cls, 'instance'): cls.instance = super(ShowLast10, 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 ShowLast10.COMMAND
22
+
23
+ def run(self, cmd: str, state: ReplState):
24
+ if not(args := self.args(cmd)):
25
+ return super().run(cmd, state)
26
+
27
+ state, args = self.apply_state(args, state)
28
+ limit = 10
29
+ if args:
30
+ try:
31
+ limit = int(args[0])
32
+ except:
33
+ pass
34
+
35
+ query = '\n '.join([
36
+ "SELECT * FROM audit",
37
+ f"WHERE drive <> 'z' and ({Audits.date_from(datetime.now() - timedelta(days=30))})",
38
+ f"ORDER BY ts DESC LIMIT {limit};"])
39
+ log2(query)
40
+ log2()
41
+ Audits.run_audit_query(query)
42
+
43
+ return state
44
+
45
+ def completion(self, state: ReplState):
46
+ if state.device == ReplState.L:
47
+ return super().completion(state, {'10': None})
48
+
49
+ return {}
50
+
51
+ def help(self, _: ReplState):
52
+ return f'{ShowLast10.COMMAND} [limit]\t show last <limit> audit lines'
@@ -0,0 +1,52 @@
1
+ from datetime import datetime, timedelta
2
+
3
+ from adam.commands.command import Command
4
+ from adam.repl_state import ReplState
5
+ from adam.utils import log2
6
+ from adam.utils_audits import Audits
7
+
8
+ class ShowSlow10(Command):
9
+ COMMAND = 'show slow'
10
+
11
+ # the singleton pattern
12
+ def __new__(cls, *args, **kwargs):
13
+ if not hasattr(cls, 'instance'): cls.instance = super(ShowSlow10, 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 ShowSlow10.COMMAND
22
+
23
+ def run(self, cmd: str, state: ReplState):
24
+ if not(args := self.args(cmd)):
25
+ return super().run(cmd, state)
26
+
27
+ state, args = self.apply_state(args, state)
28
+ limit = 10
29
+ if args:
30
+ try:
31
+ limit = int(args[0])
32
+ except:
33
+ pass
34
+
35
+ query = '\n '.join([
36
+ "SELECT * FROM audit",
37
+ f"WHERE drive <> 'z' and ({Audits.date_from(datetime.now() - timedelta(days=30))})",
38
+ f"ORDER BY CAST(duration AS REAL) DESC LIMIT {limit};"])
39
+ log2(query)
40
+ log2()
41
+ Audits.run_audit_query(query)
42
+
43
+ return state
44
+
45
+ def completion(self, state: ReplState):
46
+ if state.device == ReplState.L:
47
+ return super().completion(state, {'10': None})
48
+
49
+ return {}
50
+
51
+ def help(self, _: ReplState):
52
+ return f'{ShowSlow10.COMMAND} [limit]\t show slow <limit> audit lines'
@@ -0,0 +1,52 @@
1
+ from datetime import datetime, timedelta
2
+
3
+ from adam.commands.command import Command
4
+ from adam.repl_state import ReplState
5
+ from adam.utils import log2
6
+ from adam.utils_audits import Audits
7
+
8
+ class ShowTop10(Command):
9
+ COMMAND = 'show top'
10
+
11
+ # the singleton pattern
12
+ def __new__(cls, *args, **kwargs):
13
+ if not hasattr(cls, 'instance'): cls.instance = super(ShowTop10, 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 ShowTop10.COMMAND
22
+
23
+ def run(self, cmd: str, state: ReplState):
24
+ if not(args := self.args(cmd)):
25
+ return super().run(cmd, state)
26
+
27
+ state, args = self.apply_state(args, state)
28
+ limit = 10
29
+ if args:
30
+ try:
31
+ limit = int(args[0])
32
+ except:
33
+ pass
34
+
35
+ query = '\n '.join([
36
+ "SELECT min(c) AS cluster, line, COUNT(*) AS cnt, avg(CAST(duration AS REAL)) AS duration",
37
+ f"FROM audit WHERE drive <> 'z' and ({Audits.date_from(datetime.now() - timedelta(days=30))})",
38
+ f"GROUP BY line ORDER BY cnt DESC LIMIT {limit};"])
39
+ log2(query)
40
+ log2()
41
+ Audits.run_audit_query(query)
42
+
43
+ return state
44
+
45
+ def completion(self, state: ReplState):
46
+ if state.device == ReplState.L:
47
+ return super().completion(state, {'10': None})
48
+
49
+ return {}
50
+
51
+ def help(self, _: ReplState):
52
+ return f'{ShowTop10.COMMAND} [limit]\t show top <limit> audit lines'
@@ -14,7 +14,7 @@ from adam.pod_exec_result import PodExecResult
14
14
  from adam.repl_state import ReplState
15
15
  from adam.utils import lines_to_tabular, log, log2
16
16
  from adam.apps import Apps
17
- from adam.utils_athena import audit_table_names
17
+ from adam.utils_audits import Audits
18
18
 
19
19
  class Ls(Command):
20
20
  COMMAND = 'ls'
@@ -131,7 +131,7 @@ class Ls(Command):
131
131
  log(lines_to_tabular(pg_table_names(pg.namespace, pg.path()), 'NAME', separator=','))
132
132
 
133
133
  def show_audit_log_tables(self):
134
- log(lines_to_tabular(audit_table_names(), 'NAME', separator=','))
134
+ log(lines_to_tabular(Audits.audit_table_names(), 'NAME', separator=','))
135
135
 
136
136
  def completion(self, state: ReplState):
137
137
  if state.pod:
@@ -4,7 +4,7 @@ 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
  from adam.utils import lines_to_tabular, log, log2
7
- from adam.utils_athena import audit_table_names, run_audit_query
7
+ from adam.utils_audits import Audits
8
8
 
9
9
  class PreviewTable(Command):
10
10
  COMMAND = 'preview'
@@ -43,7 +43,7 @@ class PreviewTable(Command):
43
43
  lines = [db["name"] for db in pg.tables() if db["schema"] == PostgresContext.default_schema()]
44
44
  log(lines_to_tabular(lines, separator=','))
45
45
  elif state.device == ReplState.L:
46
- log(lines_to_tabular(audit_table_names(), separator=','))
46
+ log(lines_to_tabular(Audits.audit_table_names(), separator=','))
47
47
  else:
48
48
  log(lines_to_tabular(cassandra_table_names(state), separator=','))
49
49
 
@@ -66,7 +66,7 @@ class PreviewTable(Command):
66
66
  if state.device == ReplState.P:
67
67
  PostgresContext.apply(state.namespace, state.pg_path).run_sql(f'select * from {table} limit {rows}')
68
68
  elif state.device == ReplState.L:
69
- run_audit_query(f'select * from {table} limit {rows}')
69
+ Audits.run_audit_query(f'select * from {table} limit {rows}')
70
70
  else:
71
71
  run_cql(state, f'select * from {table} limit {rows}', show_out=True, use_single_quotes=True, on_any=True)
72
72
 
@@ -1,5 +1,6 @@
1
1
  import click
2
2
 
3
+ from adam.commands.audit.show_last10 import ShowLast10
3
4
  from adam.commands.command import Command
4
5
  from adam.commands.medusa.medusa_show_backupjobs import MedusaShowBackupJobs
5
6
  from adam.commands.medusa.medusa_show_restorejobs import MedusaShowRestoreJobs
@@ -42,7 +43,8 @@ class Show(Command):
42
43
  def cmd_list():
43
44
  return [ShowAppActions(), ShowAppId(), ShowAppQueues(), ShowHost(), ShowLogin(), ShowKubectlCommands(),
44
45
  ShowParams(), ShowProcesses(), ShowRepairs(), ShowStorage(), ShowAdam(),
45
- ShowCassandraStatus(), ShowCassandraVersion(), MedusaShowRestoreJobs(), MedusaShowBackupJobs()]
46
+ ShowCassandraStatus(), ShowCassandraVersion(), MedusaShowRestoreJobs(), MedusaShowBackupJobs(),
47
+ ShowLast10()]
46
48
 
47
49
  def completion(self, state: ReplState):
48
50
  return super().completion(state)
@@ -0,0 +1,2 @@
1
+ def config():
2
+ return {'app': {'console-endpoint': 'https://{host}/{env}/{app}/static/console/index.html', 'cr': {'cluster-regex': '(.*?-.*?)-.*', 'group': 'ops.c3.ai', 'v': 'v2', 'plural': 'c3cassandras'}, 'label': 'c3__app_id-0', 'login': {'admin-group': '{host}/C3.ClusterAdmin', 'ingress': '{app_id}-k8singr-appleader-001', 'timeout': 5, 'session-check-url': 'https://{host}/{env}/{app}/api/8/C3/userSessionToken', 'cache-creds': True, 'cache-username': True, 'url': 'https://{host}/{env}/{app}', 'another': "You're logged in to {has}. However, for this app, you need to log in to {need}.", 'token-server-url': 'http://localhost:{port}', 'password-max-length': 128}, 'strip': '0'}, 'audit': {'endpoint': 'https://4psvtaxlcb.execute-api.us-west-2.amazonaws.com/prod/', 'workers': 3, 'timeout': 10, 'log-audit-queries': False, 'athena': {'auto-repair': {'elapsed_hours': 12}, 'region': 'us-west-2', 'catalog': 'AwsDataCatalog', 'database': 'audit', 'repair-partition-tables': 'audit', 'output': 's3://s3.ops--audit/ddl/results', 'repair-cluster-tables': 'cluster'}}, 'bash': {'workers': 32}, 'cassandra': {'service-name': 'all-pods-service'}, 'cql': {'workers': 32, 'samples': 3, 'secret': {'cluster-regex': '(.*?-.*?)-.*', 'name': '{cluster}-superuser', 'password-item': 'password'}, 'alter-tables': {'excludes': 'system_auth,system_traces,reaper_db,system_distributed,system_views,system,system_schema,system_virtual_schema', 'gc-grace-periods': '3600,86400,864000,7776000', 'batching': True}}, 'checks': {'compactions-threshold': 250, 'cpu-busy-threshold': 98.0, 'cpu-threshold': 0.0, 'cassandra-data-path': '/c3/cassandra', 'root-disk-threshold': 50, 'cassandra-disk-threshold': 50, 'snapshot-size-cmd': "ls /c3/cassandra/data/data/*/*/snapshots | grep snapshots | sed 's/:$//g' | xargs -I {} du -sk {} | awk '{print $1}' | awk '{s+=$1} END {print s}'", 'snapshot-size-threshold': '40G', 'table-sizes-cmd': "ls -Al /c3/cassandra/data/data/ | awk '{print $9}' | sed 's/\\^r//g' | xargs -I {} du -sk /c3/cassandra/data/data/{}"}, 'get-host-id': {'workers': 32}, 'idps': {'ad': {'email-pattern': '.*@c3.ai', 'uri': 'https://login.microsoftonline.com/53ad779a-93e7-485c-ba20-ac8290d7252b/oauth2/v2.0/authorize?response_type=id_token&response_mode=form_post&client_id=00ff94a8-6b0a-4715-98e0-95490012d818&scope=openid+email+profile&redirect_uri=https%3A%2F%2Fplat.c3ci.cloud%2Fc3%2Fc3%2Foidc%2Flogin&nonce={nonce}&state=EMPTY', 'jwks-uri': 'https://login.microsoftonline.com/common/discovery/keys', 'contact': 'Please contact ted.tran@c3.ai.', 'whitelist-file': '/kaqing/members'}, 'okta': {'default': True, 'email-pattern': '.*@c3iot.com', 'uri': 'https://c3energy.okta.com/oauth2/v1/authorize?response_type=id_token&response_mode=form_post&client_id={client_id}&scope=openid+email+profile+groups&redirect_uri=https%3A%2F%2F{host}%2Fc3%2Fc3%2Foidc%2Flogin&nonce={nonce}&state=EMPTY', 'jwks-uri': 'https://c3energy.okta.com/oauth2/v1/keys'}}, 'issues': {'workers': 32}, 'logs': {'path': '/c3/cassandra/logs/system.log'}, 'medusa': {'restore-auto-complete': False}, 'nodetool': {'workers': 32, 'samples': 3, 'commands_in_line': 40}, 'pg': {'name-pattern': '^{namespace}.*-k8spg-.*', 'excludes': '.helm., -admin-secret', 'agent': {'name': 'ops-pg-agent', 'just-in-time': False, 'timeout': 86400, 'image': 'seanahnsf/kaqing'}, 'default-db': 'postgres', 'default-schema': 'postgres', 'secret': {'endpoint-key': 'postgres-db-endpoint', 'port-key': 'postgres-db-port', 'username-key': 'postgres-admin-username', 'password-key': 'postgres-admin-password'}}, 'pod': {'name': 'ops', 'image': 'seanahnsf/kaqing-cloud', 'sa': {'name': 'ops', 'proto': 'c3', 'additional-cluster-roles': 'c3aiops-k8ssandra-operator'}, 'label-selector': 'run=ops'}, 'preview': {'rows': 10}, 'processes': {'columns': 'pod,cpu,mem', 'header': 'POD_NAME,CPU,MEM/LIMIT'}, 'reaper': {'service-name': 'reaper-service', 'port-forward': {'timeout': 86400, 'local-port': 9001}, 'abort-runs-batch': 10, 'show-runs-batch': 100, 'pod': {'cluster-regex': '(.*?-.*?-.*?-.*?)-.*', 'label-selector': 'k8ssandra.io/reaper={cluster}-reaper'}, 'secret': {'cluster-regex': '(.*?-.*?)-.*', 'name': '{cluster}-reaper-ui', 'password-item': 'password'}}, 'repair': {'log-path': '/home/cassrepair/logs/', 'image': 'ci-registry.c3iot.io/cloudops/cassrepair:2.0.14', 'secret': 'ciregistryc3iotio', 'env': {'interval': 24, 'timeout': 60, 'pr': False, 'runs': 1}}, 'repl': {'start-drive': 'a', 'a': {'auto-enter': 'c3/c3'}, 'c': {'auto-enter': 'cluster'}, 'history': {'push-cat-remote-log-file': True}, 'background-process': {'auto-nohup': True}}, 'status': {'columns': 'status,address,load,tokens,owns,host_id,gossip,compactions', 'header': '--,Address,Load,Tokens,Owns,Host ID,GOSSIP,COMPACTIONS'}, 'storage': {'columns': 'pod,volume_root,volume_cassandra,snapshots,data,compactions', 'header': 'POD_NAME,VOLUME /,VOLUME CASS,SNAPSHOTS,DATA,COMPACTIONS'}, 'watch': {'auto': 'rollout', 'timeout': 3600, 'interval': 10}, 'debug': False, 'debugs': {'timings': False, 'exit-on-error': False, 'show-parallelism': False}}
@@ -15,6 +15,7 @@ from adam.commands.command_helpers import ClusterCommandHelper
15
15
  from adam.commands.help import Help
16
16
  from adam.commands.postgres.postgres_context import PostgresContext
17
17
  from adam.config import Config
18
+ from adam.utils_audits import Audits
18
19
  from adam.utils_k8s.kube_context import KubeContext
19
20
  from adam.utils_k8s.statefulsets import StatefulSets
20
21
  from adam.log import Log
@@ -106,7 +107,7 @@ def enter_repl(state: ReplState):
106
107
 
107
108
  with concurrent.futures.ThreadPoolExecutor(max_workers=Config().get('audit.workers', 3)) as executor:
108
109
  # warm up AWS lambda - this log line may timeout and get lost, which is fine
109
- executor.submit(audit_log, 'entering kaqing repl', state)
110
+ executor.submit(Audits.log, 'entering kaqing repl', state.namespace, 'z', 0.0)
110
111
 
111
112
  # use sorted command list only for auto-completion
112
113
  sorted_cmds = sorted(cmd_list, key=lambda cmd: cmd.command())
@@ -141,34 +142,8 @@ def enter_repl(state: ReplState):
141
142
  cmd = f'bash {cmd}'
142
143
 
143
144
  if cmd and cmd.strip(' ') and not cmds.run(cmd, state):
144
- try_device_default_action(state, cmds, cmd_list, cmd)
145
145
  # not served by any command in the chain; try SQL query or C3 action
146
- # c_sql_tried = False
147
- # if state.device == ReplState.P:
148
- # pg = PostgresSession(state.namespace, state.pg_path)
149
- # if pg.db:
150
- # c_sql_tried = True
151
- # cmd = f'pg {cmd}'
152
- # cmds.run(cmd, state)
153
- # elif state.device == ReplState.A:
154
- # if state.app_app:
155
- # c_sql_tried = True
156
- # cmd = f'app {cmd}'
157
- # cmds.run(cmd, state)
158
- # elif state.device == ReplState.L:
159
- # c_sql_tried = True
160
- # cmd = f'audit {cmd}'
161
- # cmds.run(cmd, state)
162
- # elif state.sts:
163
- # c_sql_tried = True
164
- # cmd = f'cql {cmd}'
165
- # cmds.run(cmd, state)
166
-
167
- # if not c_sql_tried:
168
- # log2(f'* Invalid command: {cmd}')
169
- # log2()
170
- # lines = [c.help(state) for c in cmd_list if c.help(state)]
171
- # log2(lines_to_tabular(lines, separator='\t'))
146
+ try_device_default_action(state, cmds, cmd_list, cmd)
172
147
  except EOFError: # Handle Ctrl+D (EOF) for graceful exit
173
148
  break
174
149
  except Exception as e:
@@ -184,7 +159,7 @@ def enter_repl(state: ReplState):
184
159
 
185
160
  # offload audit logging
186
161
  if cmd and (state.device != ReplState.L or Config().get('audit.log-audit-queries', False)):
187
- executor.submit(audit_log, cmd, state)
162
+ executor.submit(Audits.log, cmd, state.namespace, state.device, time.time() - s0)
188
163
 
189
164
  def try_device_default_action(state: ReplState, cmds: Command, cmd_list: list[Command], cmd: str):
190
165
  c_sql_tried = False
@@ -214,24 +189,6 @@ def try_device_default_action(state: ReplState, cmds: Command, cmd_list: list[Co
214
189
  lines = [c.help(state) for c in cmd_list if c.help(state)]
215
190
  log2(lines_to_tabular(lines, separator='\t'))
216
191
 
217
- def audit_log(cmd: str, state: ReplState):
218
- payload = {
219
- 'cluster': state.namespace if state.namespace else 'NA',
220
- 'ts': time.time(),
221
- 'host': get_my_host(),
222
- 'user': getpass.getuser(),
223
- 'line': cmd.replace('"', '""').replace('\n', ' '),
224
- }
225
- audit_endpoint = Config().get("audit.endpoint", "https://4psvtaxlcb.execute-api.us-west-2.amazonaws.com/prod/")
226
- try:
227
- response = requests.post(audit_endpoint, json=payload, timeout=Config().get("audit.timeout", 10))
228
- if response.status_code in [200, 201]:
229
- Config().debug(response.text)
230
- else:
231
- log2(f"Error: {response.status_code} {response.text}")
232
- except requests.exceptions.Timeout as e:
233
- log2(f"Timeout occurred: {e}")
234
-
235
192
  @cli.command(context_settings=dict(ignore_unknown_options=True, allow_extra_args=True), cls=ClusterCommandHelper, help="Enter interactive shell.")
236
193
  @click.option('--kubeconfig', '-k', required=False, metavar='path', help='path to kubeconfig file')
237
194
  @click.option('--config', default='params.yaml', metavar='path', help='path to kaqing parameters file')
@@ -58,7 +58,7 @@ class ReplCommands:
58
58
  cmds: list[Command] = ReplCommands.navigation() + ReplCommands.cassandra_check() + ReplCommands.cassandra_ops() + \
59
59
  ReplCommands.tools() + ReplCommands.app() + ReplCommands.exit()
60
60
 
61
- intermediate_cmds: list[Command] = [App(), Reaper(), Repair(), Deploy(), Show(), Undeploy()]
61
+ intermediate_cmds: list[Command] = [App(), Audit(), Reaper(), Repair(), Deploy(), Show(), Undeploy()]
62
62
  ic = [c.command() for c in intermediate_cmds]
63
63
  # 1. dedup commands
64
64
  deduped = []
@@ -86,7 +86,7 @@ class ReplCommands:
86
86
 
87
87
  def tools() -> list[Command]:
88
88
  return [Cqlsh(), Postgres(), Bash(), Shell(), CodeStart(), CodeStop(), DeployFrontend(), UndeployFrontend(),
89
- DeployPod(), UndeployPod(), DeployPgAgent(), UndeployPgAgent(), AuditRepairTables(), AuditRun(), Audit()]
89
+ DeployPod(), UndeployPod(), DeployPgAgent(), UndeployPgAgent(), Audit()] + Audit.cmd_list()
90
90
 
91
91
  def app() -> list[Command]:
92
92
  return [ShowAppActions(), ShowAppId(), ShowAppQueues(), AppPing(), App()]
@@ -299,14 +299,14 @@ SQL_SPEC = [
299
299
  # | FOREIGN KEY ( <column name list> ) REFERENCES <referenced table> ( <referenced column list> )
300
300
  # | CHECK ( <search condition> )
301
301
 
302
- ' > alter > alter',
303
- 'alter_ > table > alter_table ^ table',
304
- 'alter_table_ > name|audit > alter_table_t ^ tables',
305
- 'alter_table_t_ > add > alter_table_add ^ add,add constraint,drop column,drop constraint,rename to',
306
- '- > drop > alter_table_drop',
307
-
308
- ' > preview > preview',
309
- 'preview_ > name|audit > preview_t ^ tables',
302
+ ' > alter > alter',
303
+ 'alter_ > table > alter_table ^ table',
304
+ 'alter_table_ > name|audit|cluster > alter_table_t ^ tables',
305
+ 'alter_table_t_ > add > alter_table_add ^ add,add constraint,drop column,drop constraint,rename to',
306
+ '- > drop > alter_table_drop',
307
+
308
+ ' > preview > preview',
309
+ 'preview_ > name|audit > preview_t ^ tables',
310
310
  ]
311
311
 
312
312
  SQL_KEYWORDS = [
@@ -317,7 +317,7 @@ SQL_KEYWORDS = [
317
317
  'insert', 'into', 'values',
318
318
  'update', 'where', 'set',
319
319
  'delete',
320
- 'audit',
320
+ 'audit', 'cluster',
321
321
  'alter', 'table', 'tables', 'add', 'drop', 'with',
322
322
  'describe'
323
323
  ]