kaqing 1.98.15__py3-none-any.whl → 2.0.145__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 (180) hide show
  1. adam/app_session.py +1 -1
  2. adam/apps.py +2 -2
  3. adam/batch.py +30 -31
  4. adam/checks/check_utils.py +4 -4
  5. adam/checks/compactionstats.py +1 -1
  6. adam/checks/cpu.py +2 -2
  7. adam/checks/disk.py +1 -1
  8. adam/checks/gossip.py +1 -1
  9. adam/checks/memory.py +3 -3
  10. adam/checks/status.py +1 -1
  11. adam/commands/alter_tables.py +81 -0
  12. adam/commands/app.py +3 -3
  13. adam/commands/app_ping.py +2 -2
  14. adam/commands/audit/audit.py +86 -0
  15. adam/commands/audit/audit_repair_tables.py +77 -0
  16. adam/commands/audit/audit_run.py +58 -0
  17. adam/commands/audit/show_last10.py +51 -0
  18. adam/commands/audit/show_slow10.py +50 -0
  19. adam/commands/audit/show_top10.py +48 -0
  20. adam/commands/audit/utils_show_top10.py +59 -0
  21. adam/commands/bash/bash.py +133 -0
  22. adam/commands/bash/bash_completer.py +93 -0
  23. adam/commands/cat.py +56 -0
  24. adam/commands/cd.py +12 -82
  25. adam/commands/check.py +6 -0
  26. adam/commands/cli_commands.py +3 -3
  27. adam/commands/code.py +60 -0
  28. adam/commands/command.py +48 -12
  29. adam/commands/commands_utils.py +4 -5
  30. adam/commands/cql/cql_completions.py +28 -0
  31. adam/commands/cql/cql_utils.py +209 -0
  32. adam/commands/{cqlsh.py → cql/cqlsh.py} +15 -10
  33. adam/commands/deploy/__init__.py +0 -0
  34. adam/commands/{frontend → deploy}/code_start.py +1 -1
  35. adam/commands/{frontend → deploy}/code_stop.py +1 -1
  36. adam/commands/{frontend → deploy}/code_utils.py +2 -2
  37. adam/commands/deploy/deploy.py +48 -0
  38. adam/commands/deploy/deploy_frontend.py +52 -0
  39. adam/commands/deploy/deploy_pg_agent.py +38 -0
  40. adam/commands/deploy/deploy_pod.py +110 -0
  41. adam/commands/deploy/deploy_utils.py +29 -0
  42. adam/commands/deploy/undeploy.py +48 -0
  43. adam/commands/deploy/undeploy_frontend.py +41 -0
  44. adam/commands/deploy/undeploy_pg_agent.py +42 -0
  45. adam/commands/deploy/undeploy_pod.py +51 -0
  46. adam/commands/devices/__init__.py +0 -0
  47. adam/commands/devices/device.py +27 -0
  48. adam/commands/devices/device_app.py +146 -0
  49. adam/commands/devices/device_auit_log.py +43 -0
  50. adam/commands/devices/device_cass.py +145 -0
  51. adam/commands/devices/device_export.py +86 -0
  52. adam/commands/devices/device_postgres.py +109 -0
  53. adam/commands/devices/devices.py +25 -0
  54. adam/commands/export/__init__.py +0 -0
  55. adam/commands/export/clean_up_export_session.py +53 -0
  56. adam/commands/{frontend/teardown_frontend.py → export/clean_up_export_sessions.py} +9 -11
  57. adam/commands/export/drop_export_database.py +58 -0
  58. adam/commands/export/drop_export_databases.py +46 -0
  59. adam/commands/export/export.py +83 -0
  60. adam/commands/export/export_databases.py +170 -0
  61. adam/commands/export/export_select.py +85 -0
  62. adam/commands/export/export_select_x.py +54 -0
  63. adam/commands/export/export_use.py +55 -0
  64. adam/commands/export/exporter.py +364 -0
  65. adam/commands/export/import_session.py +68 -0
  66. adam/commands/export/importer.py +67 -0
  67. adam/commands/export/importer_athena.py +80 -0
  68. adam/commands/export/importer_sqlite.py +47 -0
  69. adam/commands/export/show_column_counts.py +63 -0
  70. adam/commands/export/show_export_databases.py +39 -0
  71. adam/commands/export/show_export_session.py +51 -0
  72. adam/commands/export/show_export_sessions.py +47 -0
  73. adam/commands/export/utils_export.py +291 -0
  74. adam/commands/help.py +12 -7
  75. adam/commands/issues.py +6 -0
  76. adam/commands/kubectl.py +41 -0
  77. adam/commands/login.py +9 -5
  78. adam/commands/logs.py +2 -1
  79. adam/commands/ls.py +4 -107
  80. adam/commands/medusa/medusa.py +2 -26
  81. adam/commands/medusa/medusa_backup.py +2 -2
  82. adam/commands/medusa/medusa_restore.py +3 -4
  83. adam/commands/medusa/medusa_show_backupjobs.py +4 -3
  84. adam/commands/medusa/medusa_show_restorejobs.py +3 -3
  85. adam/commands/nodetool.py +9 -4
  86. adam/commands/param_set.py +1 -1
  87. adam/commands/postgres/postgres.py +42 -43
  88. adam/commands/postgres/postgres_context.py +248 -0
  89. adam/commands/postgres/postgres_preview.py +0 -1
  90. adam/commands/postgres/postgres_utils.py +31 -0
  91. adam/commands/postgres/psql_completions.py +10 -0
  92. adam/commands/preview_table.py +18 -40
  93. adam/commands/pwd.py +2 -28
  94. adam/commands/reaper/reaper.py +4 -24
  95. adam/commands/reaper/reaper_restart.py +1 -1
  96. adam/commands/reaper/reaper_session.py +2 -2
  97. adam/commands/repair/repair.py +3 -27
  98. adam/commands/repair/repair_log.py +1 -1
  99. adam/commands/repair/repair_run.py +2 -2
  100. adam/commands/repair/repair_scan.py +2 -7
  101. adam/commands/repair/repair_stop.py +1 -1
  102. adam/commands/report.py +6 -0
  103. adam/commands/restart.py +2 -2
  104. adam/commands/rollout.py +1 -1
  105. adam/commands/shell.py +33 -0
  106. adam/commands/show/show.py +11 -26
  107. adam/commands/show/show_app_actions.py +3 -0
  108. adam/commands/show/show_app_id.py +1 -1
  109. adam/commands/show/show_app_queues.py +3 -2
  110. adam/commands/show/show_cassandra_status.py +3 -3
  111. adam/commands/show/show_cassandra_version.py +3 -3
  112. adam/commands/show/show_commands.py +4 -1
  113. adam/commands/show/show_host.py +33 -0
  114. adam/commands/show/show_login.py +3 -0
  115. adam/commands/show/show_processes.py +1 -1
  116. adam/commands/show/show_repairs.py +2 -2
  117. adam/commands/show/show_storage.py +1 -1
  118. adam/commands/watch.py +1 -1
  119. adam/config.py +16 -3
  120. adam/embedded_params.py +1 -1
  121. adam/pod_exec_result.py +10 -2
  122. adam/repl.py +132 -117
  123. adam/repl_commands.py +62 -18
  124. adam/repl_state.py +276 -55
  125. adam/sql/__init__.py +0 -0
  126. adam/sql/sql_completer.py +120 -0
  127. adam/sql/sql_state_machine.py +617 -0
  128. adam/sql/term_completer.py +76 -0
  129. adam/sso/authenticator.py +1 -1
  130. adam/sso/authn_ad.py +36 -56
  131. adam/sso/authn_okta.py +6 -32
  132. adam/sso/cred_cache.py +1 -1
  133. adam/sso/idp.py +74 -9
  134. adam/sso/idp_login.py +2 -2
  135. adam/sso/idp_session.py +10 -7
  136. adam/utils.py +85 -4
  137. adam/utils_athena.py +145 -0
  138. adam/utils_audits.py +102 -0
  139. adam/utils_k8s/__init__.py +0 -0
  140. adam/utils_k8s/app_clusters.py +33 -0
  141. adam/utils_k8s/app_pods.py +31 -0
  142. adam/{k8s_utils → utils_k8s}/cassandra_clusters.py +6 -21
  143. adam/{k8s_utils → utils_k8s}/cassandra_nodes.py +12 -5
  144. adam/utils_k8s/config_maps.py +34 -0
  145. adam/utils_k8s/deployment.py +56 -0
  146. adam/{k8s_utils → utils_k8s}/jobs.py +1 -1
  147. adam/{k8s_utils → utils_k8s}/kube_context.py +1 -1
  148. adam/utils_k8s/pods.py +342 -0
  149. adam/{k8s_utils → utils_k8s}/secrets.py +4 -0
  150. adam/utils_k8s/service_accounts.py +169 -0
  151. adam/{k8s_utils → utils_k8s}/statefulsets.py +5 -4
  152. adam/{k8s_utils → utils_k8s}/volumes.py +9 -0
  153. adam/utils_net.py +24 -0
  154. adam/utils_repl/__init__.py +0 -0
  155. adam/utils_repl/automata_completer.py +48 -0
  156. adam/utils_repl/repl_completer.py +46 -0
  157. adam/utils_repl/state_machine.py +173 -0
  158. adam/utils_sqlite.py +101 -0
  159. adam/version.py +1 -1
  160. {kaqing-1.98.15.dist-info → kaqing-2.0.145.dist-info}/METADATA +1 -1
  161. kaqing-2.0.145.dist-info/RECORD +227 -0
  162. adam/commands/bash.py +0 -87
  163. adam/commands/cql_utils.py +0 -53
  164. adam/commands/devices.py +0 -89
  165. adam/commands/frontend/setup.py +0 -60
  166. adam/commands/frontend/setup_frontend.py +0 -58
  167. adam/commands/frontend/teardown.py +0 -61
  168. adam/commands/postgres/postgres_session.py +0 -225
  169. adam/commands/user_entry.py +0 -77
  170. adam/k8s_utils/pods.py +0 -211
  171. kaqing-1.98.15.dist-info/RECORD +0 -160
  172. /adam/commands/{frontend → audit}/__init__.py +0 -0
  173. /adam/{k8s_utils → commands/bash}/__init__.py +0 -0
  174. /adam/{medusa_show_restorejobs.py → commands/cql/__init__.py} +0 -0
  175. /adam/{k8s_utils → utils_k8s}/custom_resources.py +0 -0
  176. /adam/{k8s_utils → utils_k8s}/ingresses.py +0 -0
  177. /adam/{k8s_utils → utils_k8s}/services.py +0 -0
  178. {kaqing-1.98.15.dist-info → kaqing-2.0.145.dist-info}/WHEEL +0 -0
  179. {kaqing-1.98.15.dist-info → kaqing-2.0.145.dist-info}/entry_points.txt +0 -0
  180. {kaqing-1.98.15.dist-info → kaqing-2.0.145.dist-info}/top_level.txt +0 -0
adam/app_session.py CHANGED
@@ -88,7 +88,7 @@ class AppSession:
88
88
  if not forced and self.app_login:
89
89
  return self.app_login
90
90
 
91
- idp_login: IdpLogin = Idp.login(self.host, idp_uri=idp_uri, forced=forced, use_token_from_env=use_token_from_env, use_cached_creds=use_cached_creds)
91
+ idp_login: IdpLogin = Idp.login(self.host, idp_uri=idp_uri, forced=forced, use_token_from_env=use_token_from_env, use_cached_creds=use_cached_creds, verify=False)
92
92
  if not idp_login:
93
93
  log2(f"Invalid username/password.")
94
94
 
adam/apps.py CHANGED
@@ -5,10 +5,10 @@ from typing import cast
5
5
  import yaml
6
6
 
7
7
  from adam.config import Config
8
- from adam.k8s_utils.ingresses import Ingresses
8
+ from adam.utils_k8s.ingresses import Ingresses
9
9
 
10
10
  from . import __version__
11
- from adam.k8s_utils.services import Services
11
+ from adam.utils_k8s.services import Services
12
12
  from adam.utils import copy_config_file
13
13
 
14
14
  class AppAction:
adam/batch.py CHANGED
@@ -1,13 +1,14 @@
1
1
  import click
2
2
 
3
- from adam.commands.bash import Bash
3
+ from adam.commands.audit.audit import Audit, AuditCommandHelper
4
+ from adam.commands.bash.bash import Bash
4
5
  from adam.commands.check import Check, CheckCommandHelper
5
6
  from adam.commands.cp import ClipboardCopy, CopyCommandHelper
6
7
  from adam.commands.command import Command
7
8
  from adam.commands.command_helpers import ClusterCommandHelper, ClusterOrPodCommandHelper, PodCommandHelper
8
- from adam.commands.cqlsh import CqlCommandHelper, Cqlsh
9
- from adam.commands.frontend.setup import Setup, SetupCommandHelper
10
- from adam.commands.frontend.teardown import TearDown, TearDownCommandHelper
9
+ from adam.commands.cql.cqlsh import CqlCommandHelper, Cqlsh
10
+ from adam.commands.deploy.deploy import Deploy, DeployCommandHelper
11
+ from adam.commands.deploy.undeploy import Undeploy, UndeployCommandHelper
11
12
  from adam.commands.issues import Issues
12
13
  from adam.commands.login import Login
13
14
  from adam.commands.logs import Logs
@@ -22,13 +23,21 @@ from adam.commands.report import Report
22
23
  from adam.commands.restart import Restart
23
24
  from adam.commands.rollout import RollOut
24
25
  from adam.commands.show.show import Show, ShowCommandHelper
25
- from adam.commands.user_entry import UserEntry
26
26
  from adam.commands.watch import Watch
27
- from adam.k8s_utils.kube_context import KubeContext
27
+ from adam.utils_k8s.kube_context import KubeContext
28
28
  from adam.repl import enter_repl
29
29
  from adam.repl_state import ReplState
30
30
  from adam.cli_group import cli
31
31
 
32
+ @cli.command(context_settings=dict(ignore_unknown_options=True, allow_extra_args=True), cls=AuditCommandHelper, help='Run audit functions.')
33
+ @click.option('--kubeconfig', '-k', required=False, metavar='path', help='path to kubeconfig file')
34
+ @click.option('--config', default='params.yaml', metavar='path', help='path to kaqing parameters file')
35
+ @click.option('--param', '-v', multiple=True, metavar='<key>=<value>', help='parameter override')
36
+ @click.argument('extra_args', nargs=-1, metavar='repair', type=click.UNPROCESSED)
37
+ def audit(kubeconfig: str, config: str, param: list[str], extra_args):
38
+ run_command(Audit(), kubeconfig, config, param, None, None, None, extra_args)
39
+
40
+
32
41
  @cli.command(context_settings=dict(ignore_unknown_options=True, allow_extra_args=True), cls=ClusterOrPodCommandHelper, help='Run a single bash command.')
33
42
  @click.option('--kubeconfig', '-k', required=False, metavar='path', help='path to kubeconfig file')
34
43
  @click.option('--config', default='params.yaml', metavar='path', help='path to kaqing parameters file')
@@ -77,6 +86,16 @@ def cql(kubeconfig: str, config: str, param: list[str], cluster: str, namespace:
77
86
  run_command(Cqlsh(), kubeconfig, config, param, cluster, namespace, pod, extra_args)
78
87
 
79
88
 
89
+ @cli.command(context_settings=dict(ignore_unknown_options=True, allow_extra_args=True), cls=DeployCommandHelper, help='Setup.')
90
+ @click.option('--kubeconfig', '-k', required=False, metavar='path', help='path to kubeconfig file')
91
+ @click.option('--config', default='params.yaml', metavar='path', help='path to kaqing parameters file')
92
+ @click.option('--param', '-v', multiple=True, metavar='<key>=<value>', help='parameter override')
93
+ @click.option('--namespace', '-n', required=False, metavar='namespace', help='Kubernetes namespace')
94
+ @click.argument('extra_args', nargs=-1, metavar='<pod>', type=click.UNPROCESSED)
95
+ def deploy(kubeconfig: str, config: str, param: list[str], namespace: str, extra_args):
96
+ run_command(Deploy(), kubeconfig, config, param, None, namespace, None, extra_args)
97
+
98
+
80
99
  @cli.command(context_settings=dict(ignore_unknown_options=True, allow_extra_args=True), cls=ClusterOrPodCommandHelper, help="Print Qing's issues.")
81
100
  @click.option('--kubeconfig', '-k', required=False, metavar='path', help='path to kubeconfig file')
82
101
  @click.option('--config', default='params.yaml', metavar='path', help='path to kaqing parameters file')
@@ -90,7 +109,7 @@ def issues(kubeconfig: str, config: str, param: list[str], cluster: str, namespa
90
109
  run_command(Issues(), kubeconfig, config, param, cluster, namespace, pod, ('-s',) + extra_args if show else extra_args)
91
110
 
92
111
 
93
- @cli.command(context_settings=dict(ignore_unknown_options=True, allow_extra_args=True), cls=PodCommandHelper, help='Get cassandra log.')
112
+ @cli.command(context_settings=dict(ignore_unknown_options=True, allow_extra_args=True), cls=PodCommandHelper, help='SSO login.')
94
113
  @click.option('--kubeconfig', '-k', required=False, metavar='path', help='path to kubeconfig file')
95
114
  @click.option('--config', default='params.yaml', metavar='path', help='path to kaqing parameters file')
96
115
  @click.option('--param', '-v', multiple=True, metavar='<key>=<value>', help='parameter override')
@@ -229,16 +248,6 @@ def rollout(kubeconfig: str, config: str, param: list[str], cluster: str, namesp
229
248
  run_command(RollOut(), kubeconfig, config, param, cluster, namespace, None, extra_args)
230
249
 
231
250
 
232
- @cli.command(context_settings=dict(ignore_unknown_options=True, allow_extra_args=True), cls=SetupCommandHelper, help='Setup.')
233
- @click.option('--kubeconfig', '-k', required=False, metavar='path', help='path to kubeconfig file')
234
- @click.option('--config', default='params.yaml', metavar='path', help='path to kaqing parameters file')
235
- @click.option('--param', '-v', multiple=True, metavar='<key>=<value>', help='parameter override')
236
- @click.option('--namespace', '-n', required=False, metavar='namespace', help='Kubernetes namespace')
237
- @click.argument('extra_args', nargs=-1, metavar='<pod>', type=click.UNPROCESSED)
238
- def setup(kubeconfig: str, config: str, param: list[str], namespace: str, extra_args):
239
- run_command(Setup(), kubeconfig, config, param, None, namespace, None, extra_args)
240
-
241
-
242
251
  @cli.command(context_settings=dict(ignore_unknown_options=True, allow_extra_args=True), cls=ShowCommandHelper, help='Show configuration or kubectl commands.')
243
252
  @click.option('--kubeconfig', '-k', required=False, metavar='path', help='path to kubeconfig file')
244
253
  @click.option('--config', default='params.yaml', metavar='path', help='path to kaqing parameters file')
@@ -251,24 +260,14 @@ def show(kubeconfig: str, config: str, param: list[str], cluster: str, namespace
251
260
  run_command(Show(), kubeconfig, config, param, cluster, namespace, pod, extra_args)
252
261
 
253
262
 
254
- @cli.command(context_settings=dict(ignore_unknown_options=True, allow_extra_args=True), cls=TearDownCommandHelper, help='Teardown.')
255
- @click.option('--kubeconfig', '-k', required=False, metavar='path', help='path to kubeconfig file')
256
- @click.option('--config', default='params.yaml', metavar='path', help='path to kaqing parameters file')
257
- @click.option('--param', '-v', multiple=True, metavar='<key>=<value>', help='parameter override')
258
- @click.option('--namespace', '-n', required=False, metavar='namespace', help='Kubernetes namespace')
259
- @click.argument('extra_args', nargs=-1, metavar='<pod>', type=click.UNPROCESSED)
260
- def teardown(kubeconfig: str, config: str, param: list[str], namespace: str, extra_args):
261
- run_command(TearDown(), kubeconfig, config, param, None, namespace, None, extra_args)
262
-
263
-
264
- @cli.command(context_settings=dict(ignore_unknown_options=True, allow_extra_args=True), cls=PodCommandHelper, help='Get cassandra log.')
263
+ @cli.command(context_settings=dict(ignore_unknown_options=True, allow_extra_args=True), cls=UndeployCommandHelper, help='Undeploy.')
265
264
  @click.option('--kubeconfig', '-k', required=False, metavar='path', help='path to kubeconfig file')
266
265
  @click.option('--config', default='params.yaml', metavar='path', help='path to kaqing parameters file')
267
266
  @click.option('--param', '-v', multiple=True, metavar='<key>=<value>', help='parameter override')
268
267
  @click.option('--namespace', '-n', required=False, metavar='namespace', help='Kubernetes namespace')
269
268
  @click.argument('extra_args', nargs=-1, metavar='<pod>', type=click.UNPROCESSED)
270
- def entry(kubeconfig: str, config: str, param: list[str], namespace: str, extra_args):
271
- run_command(UserEntry(), kubeconfig, config, param, None, namespace, None, extra_args)
269
+ def undeploy(kubeconfig: str, config: str, param: list[str], namespace: str, extra_args):
270
+ run_command(Undeploy(), kubeconfig, config, param, None, namespace, None, extra_args)
272
271
 
273
272
 
274
273
  @cli.command(context_settings=dict(ignore_unknown_options=True, allow_extra_args=True), cls=ClusterOrPodCommandHelper, help='Watch pods in cluster.')
@@ -283,7 +282,7 @@ def watch(kubeconfig: str, config: str, param: list[str], cluster: str, namespac
283
282
 
284
283
 
285
284
  def run_command(cmd: Command, kubeconfig: str, config: str, params: list[str], cluster:str, namespace: str, pod: str, extra_args):
286
- is_user_entry = cmd.command() == UserEntry().command()
285
+ is_user_entry = False
287
286
 
288
287
  KubeContext.init_config(kubeconfig, is_user_entry=is_user_entry)
289
288
  if not KubeContext.init_params(config, params, is_user_entry=is_user_entry):
@@ -13,10 +13,10 @@ from adam.checks.issue import Issue
13
13
  from adam.checks.memory import Memory
14
14
  from adam.checks.status import Status
15
15
  from adam.config import Config
16
- from adam.k8s_utils.cassandra_nodes import CassandraNodes
17
- from adam.k8s_utils.kube_context import KubeContext
18
- from adam.k8s_utils.secrets import Secrets
19
- from adam.k8s_utils.statefulsets import StatefulSets
16
+ from adam.utils_k8s.cassandra_nodes import CassandraNodes
17
+ from adam.utils_k8s.kube_context import KubeContext
18
+ from adam.utils_k8s.secrets import Secrets
19
+ from adam.utils_k8s.statefulsets import StatefulSets
20
20
  from adam.utils import elapsed_time, log2
21
21
 
22
22
  def all_checks() -> list[Check]:
@@ -5,7 +5,7 @@ from adam.checks.check_context import CheckContext
5
5
  from adam.checks.check_result import CheckResult
6
6
  from adam.checks.issue import Issue
7
7
  from adam.config import Config
8
- from adam.k8s_utils.cassandra_nodes import CassandraNodes
8
+ from adam.utils_k8s.cassandra_nodes import CassandraNodes
9
9
 
10
10
  class CompactionStats(Check):
11
11
  def name(self):
adam/checks/cpu.py CHANGED
@@ -5,8 +5,8 @@ from adam.checks.check_context import CheckContext
5
5
  from adam.checks.check_result import CheckResult
6
6
  from adam.checks.issue import Issue
7
7
  from adam.config import Config
8
- from adam.k8s_utils.cassandra_nodes import CassandraNodes
9
- from adam.k8s_utils.custom_resources import CustomResources
8
+ from adam.utils_k8s.cassandra_nodes import CassandraNodes
9
+ from adam.utils_k8s.custom_resources import CustomResources
10
10
 
11
11
  class Cpu(Check):
12
12
  def name(self):
adam/checks/disk.py CHANGED
@@ -6,7 +6,7 @@ from adam.checks.check_context import CheckContext
6
6
  from adam.checks.check_result import CheckResult
7
7
  from adam.checks.issue import Issue
8
8
  from adam.config import Config
9
- from adam.k8s_utils.cassandra_nodes import CassandraNodes
9
+ from adam.utils_k8s.cassandra_nodes import CassandraNodes
10
10
 
11
11
  class Disk(Check):
12
12
  def name(self):
adam/checks/gossip.py CHANGED
@@ -4,7 +4,7 @@ from adam.checks.check import Check
4
4
  from adam.checks.check_context import CheckContext
5
5
  from adam.checks.check_result import CheckResult
6
6
  from adam.checks.issue import Issue
7
- from adam.k8s_utils.cassandra_nodes import CassandraNodes
7
+ from adam.utils_k8s.cassandra_nodes import CassandraNodes
8
8
 
9
9
  class Gossip(Check):
10
10
  def name(self):
adam/checks/memory.py CHANGED
@@ -2,9 +2,9 @@ from adam.checks.check import Check
2
2
  from adam.checks.check_context import CheckContext
3
3
  from adam.checks.check_result import CheckResult
4
4
  from adam.checks.issue import Issue
5
- from adam.k8s_utils.cassandra_nodes import CassandraNodes
6
- from adam.k8s_utils.custom_resources import CustomResources
7
- from adam.k8s_utils.pods import Pods
5
+ from adam.utils_k8s.cassandra_nodes import CassandraNodes
6
+ from adam.utils_k8s.custom_resources import CustomResources
7
+ from adam.utils_k8s.pods import Pods
8
8
 
9
9
  class Memory(Check):
10
10
  def name(self):
adam/checks/status.py CHANGED
@@ -4,7 +4,7 @@ from adam.checks.check import Check
4
4
  from adam.checks.check_context import CheckContext
5
5
  from adam.checks.check_result import CheckResult
6
6
  from adam.checks.issue import Issue
7
- from adam.k8s_utils.cassandra_nodes import CassandraNodes
7
+ from adam.utils_k8s.cassandra_nodes import CassandraNodes
8
8
 
9
9
  class Status(Check):
10
10
  def name(self):
@@ -0,0 +1,81 @@
1
+ from adam.commands.command import Command
2
+ from adam.commands.cql.cql_utils import cassandra_tables as get_tables, run_cql
3
+ from adam.config import Config
4
+ from adam.repl_state import ReplState, RequiredState
5
+ from adam.utils import log2
6
+
7
+ class AlterTables(Command):
8
+ COMMAND = 'alter tables with'
9
+
10
+ # the singleton pattern
11
+ def __new__(cls, *args, **kwargs):
12
+ if not hasattr(cls, 'instance'): cls.instance = super(AlterTables, cls).__new__(cls)
13
+
14
+ return cls.instance
15
+
16
+ def __init__(self, successor: Command=None):
17
+ super().__init__(successor)
18
+
19
+ def required(self):
20
+ return RequiredState.CLUSTER
21
+
22
+ def command(self):
23
+ return AlterTables.COMMAND
24
+
25
+ def run(self, cmd: str, state: ReplState):
26
+ if not(args := self.args(cmd)):
27
+ return super().run(cmd, state)
28
+
29
+ state, args = self.apply_state(args, state)
30
+ if not self.validate_state(state):
31
+ return state
32
+
33
+ if not args:
34
+ if state.in_repl:
35
+ log2('Please enter gc grace in seconds. e.g. alter gc-grace-seconds 3600')
36
+ else:
37
+ log2('* gc grace second is missing.')
38
+ log2()
39
+ Command.display_help()
40
+
41
+ return 'missing-arg'
42
+
43
+ args, include_reaper = Command.extract_options(args, '--include-reaper')
44
+ arg_str = ' '.join(args)
45
+
46
+ excludes = [e.strip(' \r\n') for e in Config().get(
47
+ 'cql.alter-tables.excludes',
48
+ 'system_auth,system_traces,reaper_db,system_distributed,system_views,system,system_schema,system_virtual_schema').split(',')]
49
+ batching = Config().get('cql.alter-tables.batching', True)
50
+ tables = get_tables(state, on_any=True)
51
+ for k, v in tables.items():
52
+ if k not in excludes or k == 'reaper_db' and include_reaper:
53
+ if batching:
54
+ # alter table <table_name> with GC_GRACE_SECONDS = <timeout>;
55
+ cql = ';\n'.join([f'alter table {k}.{t} with {arg_str}' for t in v])
56
+ try:
57
+ run_cql(state, cql, [], show_out=Config().is_debug(), on_any=True)
58
+ except Exception as e:
59
+ log2(e)
60
+ continue
61
+ else:
62
+ for t in v:
63
+ try:
64
+ # alter table <table_name> with GC_GRACE_SECONDS = <timeout>;
65
+ cql = f'alter table {k}.{t} with {arg_str}'
66
+ run_cql(state, cql, [], show_out=Config().is_debug(), on_any=True)
67
+ except Exception as e:
68
+ log2(e)
69
+ continue
70
+
71
+ log2(f'{len(v)} tables altered in {k}.')
72
+
73
+ # do not continue to cql route
74
+ return state
75
+
76
+ def completion(self, _: ReplState) -> dict[str, any]:
77
+ # auto completion is taken care of by sql completer
78
+ return {}
79
+
80
+ def help(self, _: ReplState) -> str:
81
+ return f'{AlterTables.COMMAND} <param = value> [--include-reaper] \t alter schema on all tables'
adam/commands/app.py CHANGED
@@ -22,14 +22,14 @@ class App(Command):
22
22
  return App.COMMAND
23
23
 
24
24
  def required(self):
25
- return RequiredState.CLUSTER_OR_POD
25
+ return RequiredState.APP_APP
26
26
 
27
27
  def run(self, cmd: str, state: ReplState):
28
28
  if not(args := self.args(cmd)):
29
29
  return super().run(cmd, state)
30
30
 
31
31
  state, args = self.apply_state(args, state)
32
- if not self.validate_state(state, app_required=RequiredState.APP_APP):
32
+ if not self.validate_state(state):
33
33
  return state
34
34
 
35
35
  args, forced = Command.extract_options(args, '--force')
@@ -64,4 +64,4 @@ class App(Command):
64
64
  return {}
65
65
 
66
66
  def help(self, _: ReplState):
67
- return f"{App.COMMAND} [--force]\t post app API query with type and function"
67
+ return f"<AppType>.<AppAction> <args> [--force]\t post app action; check with 'show app actions' command"
adam/commands/app_ping.py CHANGED
@@ -18,14 +18,14 @@ class AppPing(Command):
18
18
  return AppPing.COMMAND
19
19
 
20
20
  def required(self):
21
- return RequiredState.CLUSTER_OR_POD
21
+ return RequiredState.APP_APP
22
22
 
23
23
  def run(self, cmd: str, state: ReplState):
24
24
  if not(args := self.args(cmd)):
25
25
  return super().run(cmd, state)
26
26
 
27
27
  state, args = self.apply_state(args, state)
28
- if not self.validate_state(state, app_required=RequiredState.APP_APP):
28
+ if not self.validate_state(state):
29
29
  return state
30
30
 
31
31
  _, forced = Command.extract_options(args, '--force')
@@ -0,0 +1,86 @@
1
+ import click
2
+
3
+ from adam.commands.audit.audit_repair_tables import AuditRepairTables
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
8
+ from adam.commands.audit.utils_show_top10 import show_top10_completions_for_nesting
9
+ from adam.commands.command import Command
10
+ from adam.config import Config
11
+ from adam.repl_state import ReplState
12
+ from adam.sql.sql_completer import SqlCompleter, SqlVariant
13
+ from adam.utils import log2
14
+ from adam.utils_athena import Athena
15
+ from adam.utils_audits import Audits
16
+
17
+ class Audit(Command):
18
+ COMMAND = 'audit'
19
+
20
+ # the singleton pattern
21
+ def __new__(cls, *args, **kwargs):
22
+ if not hasattr(cls, 'instance'): cls.instance = super(Audit, cls).__new__(cls)
23
+
24
+ return cls.instance
25
+
26
+ def __init__(self, successor: Command=None):
27
+ super().__init__(successor)
28
+ self.schema_read = False
29
+
30
+ def command(self):
31
+ return Audit.COMMAND
32
+
33
+ def required(self):
34
+ return ReplState.L
35
+
36
+ def run(self, cmd: str, state: ReplState):
37
+ if not(args := self.args(cmd)):
38
+ return super().run(cmd, state)
39
+
40
+ state, args = self.apply_state(args, state)
41
+ if not self.validate_state(state):
42
+ return state
43
+
44
+ r = None
45
+ if len(args) > 0:
46
+ r = super().intermediate_run(cmd, state, args, Audit.cmd_list(), display_help=False)
47
+
48
+ if not r or isinstance(r, str) and r == 'command-missing':
49
+ sql = 'select * from audit order by ts desc limit 10'
50
+ if args:
51
+ sql = ' '.join(args)
52
+ else:
53
+ log2(sql)
54
+
55
+ Athena.run_query(sql)
56
+
57
+ return state
58
+
59
+ def completion(self, state: ReplState):
60
+ if state.device == ReplState.L:
61
+ if not self.schema_read:
62
+ Config().wait_log(f'Inspecting audit database schema...')
63
+ self.schema_read = True
64
+ # warm up the caches first time when l: drive is accessed
65
+ Athena.table_names()
66
+ Athena.column_names()
67
+ Athena.column_names(partition_cols_only=True)
68
+
69
+ return super().completion(state) | show_top10_completions_for_nesting() | SqlCompleter(
70
+ lambda: Athena.table_names(),
71
+ columns=lambda table: Athena.column_names(),
72
+ partition_columns=lambda table: Athena.column_names(partition_cols_only=True),
73
+ variant=SqlVariant.ATHENA
74
+ ).completions_for_nesting()
75
+
76
+ return {}
77
+
78
+ def cmd_list():
79
+ return [AuditRepairTables(), AuditRun(), ShowLast10(), ShowSlow10(), ShowTop10()]
80
+
81
+ def help(self, _: ReplState):
82
+ return f'[{Audit.COMMAND}] [<sql-statements>]\t run SQL queries on Authena audit database'
83
+
84
+ class AuditCommandHelper(click.Command):
85
+ def get_help(self, ctx: click.Context):
86
+ Command.intermediate_help(super().get_help(ctx), Audit.COMMAND, Audit.cmd_list(), show_cluster_help=False)
@@ -0,0 +1,77 @@
1
+ import concurrent
2
+ import time
3
+
4
+ from adam.commands.command import Command
5
+ from adam.config import Config
6
+ from adam.repl_state import ReplState
7
+ from adam.utils import log, log2
8
+ from adam.utils_athena import Athena
9
+ from adam.utils_audits import AuditMeta, Audits
10
+
11
+ class AuditRepairTables(Command):
12
+ COMMAND = 'audit repair'
13
+
14
+ # the singleton pattern
15
+ def __new__(cls, *args, **kwargs):
16
+ if not hasattr(cls, 'instance'): cls.instance = super(AuditRepairTables, cls).__new__(cls)
17
+
18
+ return cls.instance
19
+
20
+ def __init__(self, successor: Command=None):
21
+ super().__init__(successor)
22
+ self.auto_repaired = False
23
+
24
+ def command(self):
25
+ return AuditRepairTables.COMMAND
26
+
27
+ def required(self):
28
+ return ReplState.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
+ state, args = self.apply_state(args, state)
35
+ if not self.validate_state(state):
36
+ return state
37
+
38
+ tables = Config().get('audit.athena.repair-partition-tables', 'audit').split(',')
39
+ if args:
40
+ tables = args
41
+
42
+ meta = Audits.get_meta()
43
+ self.repair(tables, meta)
44
+
45
+ return state
46
+
47
+ def completion(self, state: ReplState):
48
+ if state.device == ReplState.L:
49
+ if not self.auto_repaired:
50
+ if hours := Config().get('audit.athena.auto-repair.elapsed_hours', 12):
51
+ with concurrent.futures.ThreadPoolExecutor(max_workers=Config().get('audit.workers', 3)) as executor:
52
+ executor.submit(self.auto_repair, hours,)
53
+
54
+ return super().completion(state)
55
+
56
+ return {}
57
+
58
+ def auto_repair(self, hours: int):
59
+ self.auto_repaired = True
60
+
61
+ meta: AuditMeta = Audits.get_meta()
62
+ if meta.partitions_last_checked + hours * 60 * 60 < time.time():
63
+ tables = Config().get('audit.athena.repair-partition-tables', 'audit').split(',')
64
+ self.repair(tables, meta, show_sql=True)
65
+ log2(f'Audit tables have been auto-repaired.')
66
+
67
+ def repair(self, tables: list[str], meta: AuditMeta, show_sql = False):
68
+ with concurrent.futures.ThreadPoolExecutor(max_workers=Config().get('audit.workers', 3)) as executor:
69
+ for table in tables:
70
+ if show_sql:
71
+ log(f'MSCK REPAIR TABLE {table}')
72
+
73
+ executor.submit(Athena.run_query, f'MSCK REPAIR TABLE {table}', None,)
74
+ executor.submit(Audits.put_meta, Audits.PARTITIONS_ADDED, meta,)
75
+
76
+ def help(self, _: ReplState):
77
+ return f"{AuditRepairTables.COMMAND} \t run MSCK REPAIR command for new partition discovery"
@@ -0,0 +1,58 @@
1
+ import concurrent
2
+
3
+ from adam.commands.command import Command
4
+ from adam.config import Config
5
+ from adam.repl_state import ReplState
6
+ from adam.utils import log2
7
+ from adam.utils_athena import Athena
8
+ from adam.utils_audits import AuditMeta, Audits
9
+
10
+ class AuditRun(Command):
11
+ COMMAND = 'audit run'
12
+
13
+ # the singleton pattern
14
+ def __new__(cls, *args, **kwargs):
15
+ if not hasattr(cls, 'instance'): cls.instance = super(AuditRun, cls).__new__(cls)
16
+
17
+ return cls.instance
18
+
19
+ def __init__(self, successor: Command=None):
20
+ super().__init__(successor)
21
+ self.auto_repaired = False
22
+
23
+ def command(self):
24
+ return AuditRun.COMMAND
25
+
26
+ def required(self):
27
+ return ReplState.L
28
+
29
+ def run(self, cmd: str, state: ReplState):
30
+ if not(args := self.args(cmd)):
31
+ return super().run(cmd, state)
32
+
33
+ state, args = self.apply_state(args, state)
34
+ if not self.validate_state(state):
35
+ return state
36
+
37
+ meta: AuditMeta = Audits.get_meta()
38
+ clusters = Audits.find_new_clusters(meta.cluster_last_checked)
39
+ Audits.put_meta(Audits.ADD_CLUSTERS, meta, clusters=clusters)
40
+ if clusters:
41
+ log2(f'Added {len(clusters)} new clusters.')
42
+ tables = Config().get('audit.athena.repair-cluster-tables', 'cluster').split(',')
43
+ with concurrent.futures.ThreadPoolExecutor(max_workers=Config().get('audit.workers', 3)) as executor:
44
+ for table in tables:
45
+ executor.submit(Athena.run_query, f'MSCK REPAIR TABLE {table}', None,)
46
+ else:
47
+ log2(f'No new clusters were found.')
48
+
49
+ return state
50
+
51
+ def completion(self, state: ReplState):
52
+ if state.device == ReplState.L:
53
+ return super().completion(state)
54
+
55
+ return {}
56
+
57
+ def help(self, _: ReplState):
58
+ return f"{AuditRun.COMMAND} \t run"
@@ -0,0 +1,51 @@
1
+ from adam.commands.audit.utils_show_top10 import extract_limit_and_duration
2
+ from adam.commands.command import Command
3
+ from adam.repl_state import ReplState
4
+ from adam.utils import log2
5
+ from adam.utils_athena import Athena
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 required(self):
24
+ return ReplState.L
25
+
26
+ def run(self, cmd: str, state: ReplState):
27
+ if not(args := self.args(cmd)):
28
+ return super().run(cmd, state)
29
+
30
+ state, args = self.apply_state(args, state)
31
+ if not self.validate_state(state):
32
+ return state
33
+
34
+ limit, date_condition = extract_limit_and_duration(args)
35
+
36
+ query = '\n '.join([
37
+ "SELECT * FROM audit",
38
+ f"WHERE drive <> 'z' and ({date_condition})",
39
+ f"ORDER BY ts DESC LIMIT {limit};"])
40
+ log2(query)
41
+ log2()
42
+ Athena.run_query(query)
43
+
44
+ return state
45
+
46
+ def completion(self, _: ReplState):
47
+
48
+ return {}
49
+
50
+ def help(self, _: ReplState):
51
+ return f'{ShowLast10.COMMAND} [limit]\t show last <limit> audit lines'