kaqing 2.0.14__py3-none-any.whl → 2.0.189__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 (228) hide show
  1. adam/__init__.py +0 -2
  2. adam/app_session.py +9 -12
  3. adam/apps.py +20 -6
  4. adam/batch.py +16 -6
  5. adam/checks/check_utils.py +19 -49
  6. adam/checks/compactionstats.py +1 -1
  7. adam/checks/cpu.py +9 -3
  8. adam/checks/cpu_metrics.py +52 -0
  9. adam/checks/disk.py +3 -4
  10. adam/checks/gossip.py +1 -1
  11. adam/checks/memory.py +3 -3
  12. adam/checks/status.py +1 -1
  13. adam/columns/columns.py +3 -1
  14. adam/columns/cpu.py +3 -1
  15. adam/columns/cpu_metrics.py +22 -0
  16. adam/columns/memory.py +3 -4
  17. adam/commands/__init__.py +24 -0
  18. adam/commands/alter_tables.py +66 -0
  19. adam/commands/app/app.py +38 -0
  20. adam/commands/{app_ping.py → app/app_ping.py} +8 -14
  21. adam/commands/app/show_app_actions.py +49 -0
  22. adam/commands/{show → app}/show_app_id.py +9 -12
  23. adam/commands/{show → app}/show_app_queues.py +8 -14
  24. adam/commands/app/utils_app.py +106 -0
  25. adam/commands/audit/__init__.py +0 -0
  26. adam/commands/audit/audit.py +67 -0
  27. adam/commands/audit/audit_repair_tables.py +72 -0
  28. adam/commands/audit/audit_run.py +50 -0
  29. adam/commands/audit/completions_l.py +15 -0
  30. adam/commands/audit/show_last10.py +36 -0
  31. adam/commands/audit/show_slow10.py +36 -0
  32. adam/commands/audit/show_top10.py +36 -0
  33. adam/commands/audit/utils_show_top10.py +71 -0
  34. adam/commands/bash/__init__.py +5 -0
  35. adam/commands/bash/bash.py +36 -0
  36. adam/commands/bash/bash_completer.py +93 -0
  37. adam/commands/bash/utils_bash.py +16 -0
  38. adam/commands/cat.py +36 -0
  39. adam/commands/cd.py +14 -88
  40. adam/commands/check.py +18 -21
  41. adam/commands/cli_commands.py +11 -7
  42. adam/commands/clipboard_copy.py +87 -0
  43. adam/commands/code.py +57 -0
  44. adam/commands/command.py +220 -19
  45. adam/commands/commands_utils.py +28 -31
  46. adam/commands/cql/__init__.py +0 -0
  47. adam/commands/cql/completions_c.py +28 -0
  48. adam/commands/{cqlsh.py → cql/cqlsh.py} +13 -32
  49. adam/commands/cql/utils_cql.py +305 -0
  50. adam/commands/deploy/code_start.py +7 -10
  51. adam/commands/deploy/code_stop.py +4 -21
  52. adam/commands/deploy/code_utils.py +5 -5
  53. adam/commands/deploy/deploy.py +4 -40
  54. adam/commands/deploy/deploy_frontend.py +15 -18
  55. adam/commands/deploy/deploy_pg_agent.py +4 -7
  56. adam/commands/deploy/deploy_pod.py +74 -77
  57. adam/commands/deploy/deploy_utils.py +16 -26
  58. adam/commands/deploy/undeploy.py +4 -40
  59. adam/commands/deploy/undeploy_frontend.py +5 -8
  60. adam/commands/deploy/undeploy_pg_agent.py +7 -8
  61. adam/commands/deploy/undeploy_pod.py +16 -17
  62. adam/commands/devices/__init__.py +0 -0
  63. adam/commands/devices/device.py +149 -0
  64. adam/commands/devices/device_app.py +163 -0
  65. adam/commands/devices/device_auit_log.py +49 -0
  66. adam/commands/devices/device_cass.py +179 -0
  67. adam/commands/devices/device_export.py +87 -0
  68. adam/commands/devices/device_postgres.py +160 -0
  69. adam/commands/devices/devices.py +25 -0
  70. adam/commands/download_file.py +47 -0
  71. adam/commands/exit.py +1 -4
  72. adam/commands/export/__init__.py +0 -0
  73. adam/commands/export/clean_up_all_export_sessions.py +37 -0
  74. adam/commands/export/clean_up_export_sessions.py +39 -0
  75. adam/commands/export/completions_x.py +11 -0
  76. adam/commands/export/download_export_session.py +40 -0
  77. adam/commands/export/drop_export_database.py +39 -0
  78. adam/commands/export/drop_export_databases.py +37 -0
  79. adam/commands/export/export.py +37 -0
  80. adam/commands/export/export_databases.py +246 -0
  81. adam/commands/export/export_select.py +34 -0
  82. adam/commands/export/export_sessions.py +209 -0
  83. adam/commands/export/export_use.py +49 -0
  84. adam/commands/export/export_x_select.py +48 -0
  85. adam/commands/export/exporter.py +332 -0
  86. adam/commands/export/import_files.py +44 -0
  87. adam/commands/export/import_session.py +44 -0
  88. adam/commands/export/importer.py +81 -0
  89. adam/commands/export/importer_athena.py +148 -0
  90. adam/commands/export/importer_sqlite.py +67 -0
  91. adam/commands/export/show_column_counts.py +45 -0
  92. adam/commands/export/show_export_databases.py +39 -0
  93. adam/commands/export/show_export_session.py +39 -0
  94. adam/commands/export/show_export_sessions.py +37 -0
  95. adam/commands/export/utils_export.py +344 -0
  96. adam/commands/find_files.py +51 -0
  97. adam/commands/find_processes.py +76 -0
  98. adam/commands/head.py +36 -0
  99. adam/commands/help.py +14 -9
  100. adam/commands/intermediate_command.py +52 -0
  101. adam/commands/issues.py +14 -40
  102. adam/commands/kubectl.py +38 -0
  103. adam/commands/login.py +26 -25
  104. adam/commands/logs.py +5 -7
  105. adam/commands/ls.py +11 -115
  106. adam/commands/medusa/medusa.py +4 -46
  107. adam/commands/medusa/medusa_backup.py +22 -29
  108. adam/commands/medusa/medusa_restore.py +51 -49
  109. adam/commands/medusa/medusa_show_backupjobs.py +20 -21
  110. adam/commands/medusa/medusa_show_restorejobs.py +16 -21
  111. adam/commands/medusa/utils_medusa.py +15 -0
  112. adam/commands/nodetool.py +8 -17
  113. adam/commands/param_get.py +11 -14
  114. adam/commands/param_set.py +9 -13
  115. adam/commands/postgres/completions_p.py +22 -0
  116. adam/commands/postgres/postgres.py +49 -73
  117. adam/commands/postgres/postgres_databases.py +270 -0
  118. adam/commands/postgres/postgres_ls.py +4 -8
  119. adam/commands/postgres/postgres_preview.py +5 -9
  120. adam/commands/postgres/utils_postgres.py +79 -0
  121. adam/commands/preview_table.py +10 -69
  122. adam/commands/pwd.py +14 -43
  123. adam/commands/reaper/reaper.py +6 -49
  124. adam/commands/reaper/reaper_forward.py +49 -56
  125. adam/commands/reaper/reaper_forward_session.py +6 -0
  126. adam/commands/reaper/reaper_forward_stop.py +10 -16
  127. adam/commands/reaper/reaper_restart.py +8 -15
  128. adam/commands/reaper/reaper_run_abort.py +8 -33
  129. adam/commands/reaper/reaper_runs.py +43 -58
  130. adam/commands/reaper/reaper_runs_abort.py +29 -49
  131. adam/commands/reaper/reaper_schedule_activate.py +14 -33
  132. adam/commands/reaper/reaper_schedule_start.py +9 -33
  133. adam/commands/reaper/reaper_schedule_stop.py +9 -33
  134. adam/commands/reaper/reaper_schedules.py +4 -14
  135. adam/commands/reaper/reaper_status.py +8 -16
  136. adam/commands/reaper/utils_reaper.py +203 -0
  137. adam/commands/repair/repair.py +4 -46
  138. adam/commands/repair/repair_log.py +6 -12
  139. adam/commands/repair/repair_run.py +29 -36
  140. adam/commands/repair/repair_scan.py +33 -41
  141. adam/commands/repair/repair_stop.py +6 -13
  142. adam/commands/report.py +25 -21
  143. adam/commands/restart.py +27 -28
  144. adam/commands/rollout.py +20 -25
  145. adam/commands/shell.py +12 -4
  146. adam/commands/show/show.py +15 -46
  147. adam/commands/show/show_adam.py +3 -3
  148. adam/commands/show/show_cassandra_repairs.py +37 -0
  149. adam/commands/show/show_cassandra_status.py +48 -52
  150. adam/commands/show/show_cassandra_version.py +5 -18
  151. adam/commands/show/show_cli_commands.py +56 -0
  152. adam/commands/show/show_host.py +33 -0
  153. adam/commands/show/show_login.py +23 -27
  154. adam/commands/show/show_params.py +2 -5
  155. adam/commands/show/show_processes.py +18 -21
  156. adam/commands/show/show_storage.py +11 -20
  157. adam/commands/watch.py +27 -30
  158. adam/config.py +8 -6
  159. adam/embedded_params.py +1 -1
  160. adam/log.py +4 -4
  161. adam/pod_exec_result.py +13 -5
  162. adam/repl.py +136 -120
  163. adam/repl_commands.py +66 -24
  164. adam/repl_session.py +8 -1
  165. adam/repl_state.py +343 -73
  166. adam/sql/__init__.py +0 -0
  167. adam/sql/lark_completer.py +284 -0
  168. adam/sql/lark_parser.py +604 -0
  169. adam/sql/sql_completer.py +118 -0
  170. adam/sql/sql_state_machine.py +630 -0
  171. adam/sql/term_completer.py +76 -0
  172. adam/sso/authn_ad.py +7 -9
  173. adam/sso/authn_okta.py +4 -6
  174. adam/sso/cred_cache.py +4 -6
  175. adam/sso/idp.py +10 -13
  176. adam/utils.py +539 -11
  177. adam/utils_athena.py +145 -0
  178. adam/utils_audits.py +102 -0
  179. adam/utils_issues.py +32 -0
  180. adam/utils_k8s/__init__.py +0 -0
  181. adam/utils_k8s/app_clusters.py +28 -0
  182. adam/utils_k8s/app_pods.py +36 -0
  183. adam/utils_k8s/cassandra_clusters.py +44 -0
  184. adam/{k8s_utils → utils_k8s}/cassandra_nodes.py +12 -5
  185. adam/{k8s_utils → utils_k8s}/custom_resources.py +16 -17
  186. adam/{k8s_utils → utils_k8s}/deployment.py +2 -2
  187. adam/{k8s_utils → utils_k8s}/ingresses.py +2 -2
  188. adam/{k8s_utils → utils_k8s}/jobs.py +7 -11
  189. adam/utils_k8s/k8s.py +96 -0
  190. adam/{k8s_utils → utils_k8s}/kube_context.py +3 -3
  191. adam/{k8s_utils → utils_k8s}/pods.py +132 -83
  192. adam/{k8s_utils → utils_k8s}/secrets.py +7 -3
  193. adam/{k8s_utils → utils_k8s}/service_accounts.py +5 -4
  194. adam/{k8s_utils → utils_k8s}/services.py +2 -2
  195. adam/{k8s_utils → utils_k8s}/statefulsets.py +9 -16
  196. adam/utils_local.py +4 -0
  197. adam/utils_net.py +24 -0
  198. adam/utils_repl/__init__.py +0 -0
  199. adam/utils_repl/appendable_completer.py +6 -0
  200. adam/utils_repl/automata_completer.py +48 -0
  201. adam/utils_repl/repl_completer.py +172 -0
  202. adam/utils_repl/state_machine.py +173 -0
  203. adam/utils_sqlite.py +137 -0
  204. adam/version.py +1 -1
  205. {kaqing-2.0.14.dist-info → kaqing-2.0.189.dist-info}/METADATA +1 -1
  206. kaqing-2.0.189.dist-info/RECORD +253 -0
  207. kaqing-2.0.189.dist-info/top_level.txt +2 -0
  208. teddy/__init__.py +0 -0
  209. teddy/lark_parser.py +436 -0
  210. teddy/lark_parser2.py +618 -0
  211. adam/commands/app.py +0 -67
  212. adam/commands/bash.py +0 -87
  213. adam/commands/cp.py +0 -95
  214. adam/commands/cql_utils.py +0 -53
  215. adam/commands/devices.py +0 -89
  216. adam/commands/postgres/postgres_session.py +0 -247
  217. adam/commands/reaper/reaper_session.py +0 -159
  218. adam/commands/show/show_app_actions.py +0 -53
  219. adam/commands/show/show_commands.py +0 -61
  220. adam/commands/show/show_repairs.py +0 -47
  221. adam/k8s_utils/cassandra_clusters.py +0 -48
  222. kaqing-2.0.14.dist-info/RECORD +0 -167
  223. kaqing-2.0.14.dist-info/top_level.txt +0 -1
  224. /adam/{k8s_utils → commands/app}/__init__.py +0 -0
  225. /adam/{k8s_utils → utils_k8s}/config_maps.py +0 -0
  226. /adam/{k8s_utils → utils_k8s}/volumes.py +0 -0
  227. {kaqing-2.0.14.dist-info → kaqing-2.0.189.dist-info}/WHEEL +0 -0
  228. {kaqing-2.0.14.dist-info → kaqing-2.0.189.dist-info}/entry_points.txt +0 -0
@@ -1,17 +1,18 @@
1
1
  from kubernetes import client
2
- import yaml
3
2
 
3
+ from adam.commands import extract_options
4
4
  from adam.commands.command import Command
5
- from adam.commands.deploy.deploy_utils import creating, deploy_frontend, gen_labels
5
+ from adam.commands.deploy.deploy_utils import deploy_frontend, gen_labels
6
+ from adam.commands.deploy.undeploy_pod import UndeployPod
6
7
  from adam.config import Config
7
- from adam.k8s_utils.config_maps import ConfigMaps
8
- from adam.k8s_utils.deployment import Deployments
9
- from adam.k8s_utils.kube_context import KubeContext
10
- from adam.k8s_utils.pods import Pods
11
- from adam.k8s_utils.service_accounts import ServiceAccounts
12
- from adam.k8s_utils.volumes import ConfigMapMount
8
+ from adam.utils_k8s.config_maps import ConfigMaps
9
+ from adam.utils_k8s.deployment import Deployments
10
+ from adam.utils_k8s.kube_context import KubeContext
11
+ from adam.utils_k8s.pods import Pods
12
+ from adam.utils_k8s.service_accounts import ServiceAccounts
13
+ from adam.utils_k8s.volumes import ConfigMapMount
13
14
  from adam.repl_state import ReplState, RequiredState
14
- from adam.utils import log2
15
+ from adam.utils import ing, log2, log_exc
15
16
 
16
17
  class DeployPod(Command):
17
18
  COMMAND = 'deploy pod'
@@ -35,75 +36,71 @@ class DeployPod(Command):
35
36
  if not(args := self.args(cmd)):
36
37
  return super().run(cmd, state)
37
38
 
38
- state, args = self.apply_state(args, state)
39
- if not self.validate_state(state):
40
- return state
41
-
42
- if KubeContext.in_cluster():
43
- log2('This is doable only from outside of the Kubernetes cluster.')
44
- return state
45
-
46
- sa_name = Config().get('pod.sa.name', 'ops')
47
- sa_proto = Config().get('pod.sa.proto', 'c3')
48
- additional_cluster_roles = Config().get('pod.sa.additional-cluster-roles', 'c3aiops-k8ssandra-operator').split(',')
49
- label_selector = Config().get('pod.label-selector', 'run=ops')
50
- labels = gen_labels(label_selector)
51
-
52
- creating('service account', lambda: ServiceAccounts.replicate(sa_name,
53
- state.namespace,
54
- sa_proto, labels=labels,
55
- add_cluster_roles=additional_cluster_roles))
56
-
57
- settings_filename = 'settings.yaml'
58
- settings_path = f'/kaqing/{settings_filename}'
59
- settings_data = None
60
- try:
61
- with open(settings_filename, 'r') as file:
62
- settings_data = file.read()
63
- except:
64
- try:
65
- with open(settings_path, 'r') as file:
66
- settings_data = file.read()
67
- except:
68
- pass
69
-
70
- if not settings_data:
71
- log2(f'{settings_filename} not found.')
72
- return state
73
-
74
- cm_name = Config().get('pod.cm.name', 'ops')
75
- map_data = {
76
- settings_filename : settings_data
77
- }
78
- creating('config map', lambda: ConfigMaps.create(cm_name,
79
- state.namespace,
80
- map_data,
81
- labels=labels))
82
-
83
- pod_name = Config().get('pod.name', 'ops')
84
- image = Config().get('pod.image', 'seanahnsf/kaqing')
85
- security_context = client.V1SecurityContext(
86
- capabilities=client.V1Capabilities(
87
- add=["SYS_PTRACE"]
88
- )
89
- )
90
- creating('deployment', lambda: Deployments.create(state.namespace,
91
- pod_name,
92
- image,
93
- env={'NAMESPACE': state.namespace},
94
- container_security_context=security_context,
95
- labels=labels,
96
- sa_name=sa_name,
97
- config_map_mount=ConfigMapMount(cm_name, settings_filename, settings_path)))
98
-
99
- uri = deploy_frontend(pod_name, state.namespace, label_selector)
100
-
101
- Pods.wait_for_running(state.namespace, pod_name, msg=f'In moments, ops pod will be available at {uri}.', label_selector=label_selector)
102
-
103
- return state
39
+ with self.validate(args, state) as (args, state):
40
+ with extract_options(args, '--force') as (args, forced):
41
+ if forced:
42
+ UndeployPod().run(UndeployPod.COMMAND, state)
43
+
44
+ if KubeContext.in_cluster():
45
+ log2('This is doable only from outside of the Kubernetes cluster.')
46
+ return state
47
+
48
+ sa_name = Config().get('pod.sa.name', 'ops')
49
+ sa_proto = Config().get('pod.sa.proto', 'c3')
50
+ additional_cluster_roles = Config().get('pod.sa.additional-cluster-roles', 'c3aiops-k8ssandra-operator').split(',')
51
+ label_selector = Config().get('pod.label-selector', 'run=ops')
52
+ labels = gen_labels(label_selector)
53
+
54
+ with ing('Creating service account'):
55
+ ServiceAccounts.replicate(sa_name, state.namespace, sa_proto, labels=labels, add_cluster_roles=additional_cluster_roles)
56
+
57
+ settings_filename = 'settings.yaml'
58
+ settings_path = f'/kaqing/{settings_filename}'
59
+ settings_data = None
60
+ try:
61
+ with open(settings_filename, 'r') as file:
62
+ settings_data = file.read()
63
+ except:
64
+ with log_exc():
65
+ with open(settings_path, 'r') as file:
66
+ settings_data = file.read()
67
+
68
+ if not settings_data:
69
+ log2(f'{settings_filename} not found.')
70
+ return state
71
+
72
+ cm_name = Config().get('pod.cm.name', 'ops')
73
+ map_data = {
74
+ settings_filename : settings_data
75
+ }
76
+ with ing('Creating config map'):
77
+ ConfigMaps.create(cm_name, state.namespace, map_data, labels=labels)
78
+
79
+ pod_name = Config().get('pod.name', 'ops')
80
+ image = Config().get('pod.image', 'seanahnsf/kaqing')
81
+ security_context = client.V1SecurityContext(
82
+ capabilities=client.V1Capabilities(
83
+ add=["SYS_PTRACE"]
84
+ )
85
+ )
86
+ with ing('Creating deployment'):
87
+ Deployments.create(state.namespace,
88
+ pod_name,
89
+ image,
90
+ env={'NAMESPACE': state.namespace},
91
+ container_security_context=security_context,
92
+ labels=labels,
93
+ sa_name=sa_name,
94
+ config_map_mount=ConfigMapMount(cm_name, settings_filename, settings_path))
95
+
96
+ uri = deploy_frontend(pod_name, state.namespace, label_selector)
97
+
98
+ Pods.wait_for_running(state.namespace, pod_name, msg=f'In moments, ops pod will be available at {uri}.', label_selector=label_selector)
99
+
100
+ return state
104
101
 
105
102
  def completion(self, state: ReplState):
106
- return super().completion(state)
103
+ return super().completion(state, {'--force': None})
107
104
 
108
105
  def help(self, _: ReplState):
109
- return f'{DeployPod.COMMAND}\t deploy pod'
106
+ return f'{DeployPod.COMMAND} [--force]\t deploy Ops pod, --force to undeploy first'
@@ -1,39 +1,29 @@
1
- from typing import Callable
2
1
  from adam.app_session import AppSession
3
- from adam.k8s_utils.ingresses import Ingresses
4
- from adam.k8s_utils.services import Services
5
- from adam.utils import log2
2
+ from adam.utils import ing
3
+ from adam.utils_k8s.ingresses import Ingresses
4
+ from adam.utils_k8s.services import Services
6
5
 
7
6
  def deploy_frontend(name: str, namespace: str, label_selector: str):
8
7
  app_session: AppSession = AppSession.create('c3', 'c3', namespace)
9
8
  port = 7678
10
9
  labels = gen_labels(label_selector)
11
- creating('service', lambda: Services.create_service(name, namespace, port, labels, labels=labels))
12
- creating('ingress', lambda: Ingresses.create_ingress(name, namespace, app_session.host, '/c3/c3/ops($|/)', port, annotations={
13
- 'kubernetes.io/ingress.class': 'nginx',
14
- 'nginx.ingress.kubernetes.io/use-regex': 'true',
15
- 'nginx.ingress.kubernetes.io/rewrite-target': '/'
16
- }, labels=labels))
10
+ with ing('Creating service'):
11
+ Services.create_service(name, namespace, port, labels, labels=labels)
12
+ with ing('Creating ingress'):
13
+ Ingresses.create_ingress(name, namespace, app_session.host, '/c3/c3/ops($|/)', port, annotations={
14
+ 'kubernetes.io/ingress.class': 'nginx',
15
+ 'nginx.ingress.kubernetes.io/use-regex': 'true',
16
+ 'nginx.ingress.kubernetes.io/rewrite-target': '/'
17
+ }, labels=labels)
17
18
 
18
19
  return f'https://{app_session.host}/c3/c3/ops'
19
20
 
20
21
  def undeploy_frontend(namespace: str, label_selector: str):
21
- deleting('ingress', lambda: Ingresses.delete_ingresses(namespace, label_selector=label_selector))
22
- deleting('service', lambda: Services.delete_services(namespace, label_selector=label_selector))
22
+ with ing('Deleting ingress'):
23
+ Ingresses.delete_ingresses(namespace, label_selector=label_selector)
24
+ with ing('Deleting service'):
25
+ Services.delete_services(namespace, label_selector=label_selector)
23
26
 
24
27
  def gen_labels(label_selector: str):
25
28
  kv = label_selector.split('=')
26
- return {kv[0]: kv[1]}
27
-
28
- def creating(name: str, body: Callable[[], None]):
29
- log2(f'Creating {name}...', nl=False)
30
- body()
31
- log2(' OK')
32
-
33
- def deleting(name: str, body: Callable[[], None]):
34
- try:
35
- log2(f'Deleting {name}...', nl=False)
36
- body()
37
- log2(' OK')
38
- except Exception as e:
39
- log2(e)
29
+ return {kv[0]: kv[1]}
@@ -1,15 +1,12 @@
1
1
  import click
2
2
 
3
- from adam.commands.command import Command
4
3
  from adam.commands.deploy.undeploy_frontend import UndeployFrontend
5
4
  from adam.commands.deploy.undeploy_pg_agent import UndeployPgAgent
6
5
  from adam.commands.deploy.undeploy_pod import UndeployPod
7
- from adam.repl_state import ReplState
8
- from adam.utils import lines_to_tabular, log, log2
6
+ from adam.commands.intermediate_command import IntermediateCommand
9
7
 
10
- class Undeploy(Command):
8
+ class Undeploy(IntermediateCommand):
11
9
  COMMAND = 'undeploy'
12
- reaper_login = None
13
10
 
14
11
  # the singleton pattern
15
12
  def __new__(cls, *args, **kwargs):
@@ -17,45 +14,12 @@ class Undeploy(Command):
17
14
 
18
15
  return cls.instance
19
16
 
20
- def __init__(self, successor: Command=None):
21
- super().__init__(successor)
22
-
23
17
  def command(self):
24
18
  return Undeploy.COMMAND
25
19
 
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
-
32
- if state.in_repl:
33
- log(lines_to_tabular([c.help(ReplState()) for c in Undeploy.cmd_list()], separator=':'))
34
-
35
- return 'command-missing'
36
- else:
37
- # head with the Chain of Responsibility pattern
38
- cmds = Command.chain(Undeploy.cmd_list())
39
- if not cmds.run(cmd, state):
40
- log2('* Command is missing.')
41
- Command.display_help()
42
-
43
- def cmd_list():
20
+ def cmd_list(self):
44
21
  return [UndeployFrontend(), UndeployPod(), UndeployPgAgent()]
45
22
 
46
- def completion(self, state: ReplState):
47
- if state.sts:
48
- return super().completion(state)
49
-
50
- return {}
51
-
52
- def help(self, _: ReplState):
53
- return None
54
-
55
23
  class UndeployCommandHelper(click.Command):
56
24
  def get_help(self, ctx: click.Context):
57
- log(super().get_help(ctx))
58
- log()
59
- log('Sub-Commands:')
60
-
61
- log(lines_to_tabular([c.help(ReplState()).replace(f'{Undeploy.COMMAND} ', ' ', 1) for c in Undeploy.cmd_list()], separator=':'))
25
+ IntermediateCommand.intermediate_help(super().get_help(ctx), Undeploy.COMMAND, Undeploy().cmd_list())
@@ -25,17 +25,14 @@ class UndeployFrontend(Command):
25
25
  if not(args := self.args(cmd)):
26
26
  return super().run(cmd, state)
27
27
 
28
- state, args = self.apply_state(args, state)
29
- if not self.validate_state(state):
30
- return state
31
-
32
- label_selector = Config().get('pod.label-selector', 'run=ops')
33
- undeploy_frontend(state.namespace, label_selector)
28
+ with self.validate(args, state) as (args, state):
29
+ label_selector = Config().get('pod.label-selector', 'run=ops')
30
+ undeploy_frontend(state.namespace, label_selector)
34
31
 
35
- return state
32
+ return state
36
33
 
37
34
  def completion(self, state: ReplState):
38
35
  return super().completion(state)
39
36
 
40
37
  def help(self, _: ReplState):
41
- return f'{UndeployFrontend.COMMAND}\t undeploy frontend'
38
+ return f'{UndeployFrontend.COMMAND}\t undeploy Web frontend'
@@ -1,7 +1,8 @@
1
1
  from adam.commands.command import Command
2
- from adam.commands.postgres.postgres_session import PostgresSession
2
+ from adam.commands.postgres.postgres_databases import PostgresDatabases
3
3
  from adam.config import Config
4
4
  from adam.repl_state import ReplState, RequiredState
5
+ from adam.utils import ing
5
6
 
6
7
  class UndeployPgAgent(Command):
7
8
  COMMAND = 'undeploy pg-agent'
@@ -25,16 +26,14 @@ class UndeployPgAgent(Command):
25
26
  if not(args := self.args(cmd)):
26
27
  return super().run(cmd, state)
27
28
 
28
- state, args = self.apply_state(args, state)
29
- if not self.validate_state(state):
30
- return state
31
-
32
- PostgresSession.undeploy_pg_agent(Config().get('pg.agent.name', 'ops-pg-agent'), state.namespace)
29
+ with self.validate(args, state) as (args, state):
30
+ with ing('Deleting pod'):
31
+ PostgresDatabases.undeploy_pg_agent(Config().get('pg.agent.name', 'ops-pg-agent'), state.namespace)
33
32
 
34
- return state
33
+ return state
35
34
 
36
35
  def completion(self, state: ReplState):
37
36
  return super().completion(state)
38
37
 
39
38
  def help(self, _: ReplState):
40
- return f'{UndeployPgAgent.COMMAND}\t undeploy postgres agent'
39
+ return f'{UndeployPgAgent.COMMAND}\t undeploy Postgres agent'
@@ -1,10 +1,11 @@
1
1
  from adam.commands.command import Command
2
- from adam.commands.deploy.deploy_utils import undeploy_frontend, deleting
2
+ from adam.commands.deploy.deploy_utils import undeploy_frontend
3
3
  from adam.config import Config
4
- from adam.k8s_utils.config_maps import ConfigMaps
5
- from adam.k8s_utils.deployment import Deployments
6
- from adam.k8s_utils.pods import Pods
7
- from adam.k8s_utils.service_accounts import ServiceAccounts
4
+ from adam.utils import ing
5
+ from adam.utils_k8s.config_maps import ConfigMaps
6
+ from adam.utils_k8s.deployment import Deployments
7
+ from adam.utils_k8s.pods import Pods
8
+ from adam.utils_k8s.service_accounts import ServiceAccounts
8
9
  from adam.repl_state import ReplState, RequiredState
9
10
 
10
11
  class UndeployPod(Command):
@@ -29,21 +30,19 @@ class UndeployPod(Command):
29
30
  if not(args := self.args(cmd)):
30
31
  return super().run(cmd, state)
31
32
 
32
- state, args = self.apply_state(args, state)
33
- if not self.validate_state(state):
34
- return state
35
-
36
- label_selector = Config().get('pod.label-selector', 'run=ops')
37
- deleting('service account', lambda: ServiceAccounts.delete(state.namespace, label_selector=label_selector))
38
- deleting('config map', lambda: ConfigMaps.delete_with_selector(state.namespace, label_selector))
39
- deleting('deployment', lambda: Deployments.delete_with_selector(state.namespace, label_selector, grace_period_seconds=0))
40
- deleting('pod', lambda: Pods.delete_with_selector(state.namespace, label_selector, grace_period_seconds=0))
41
- undeploy_frontend(state.namespace, label_selector)
33
+ with self.validate(args, state) as (args, state):
34
+ label_selector = Config().get('pod.label-selector', 'run=ops')
35
+ with ing('Deleting service account'):
36
+ ServiceAccounts.delete(state.namespace, label_selector=label_selector)
37
+ with ing('Deleting config map'): ConfigMaps.delete_with_selector(state.namespace, label_selector)
38
+ with ing('Deleting deployment'): Deployments.delete_with_selector(state.namespace, label_selector, grace_period_seconds=0)
39
+ with ing('Deleting pod'): Pods.delete_with_selector(state.namespace, label_selector, grace_period_seconds=0)
40
+ undeploy_frontend(state.namespace, label_selector)
42
41
 
43
- return state
42
+ return state
44
43
 
45
44
  def completion(self, state: ReplState):
46
45
  return super().completion(state)
47
46
 
48
47
  def help(self, _: ReplState):
49
- return f'{UndeployPod.COMMAND}\t undeploy pod'
48
+ return f'{UndeployPod.COMMAND}\t undeploy Ops pod'
File without changes
@@ -0,0 +1,149 @@
1
+ from abc import abstractmethod
2
+
3
+ from adam.commands.command import Command
4
+ from adam.config import Config
5
+ from adam.pod_exec_result import PodExecResult
6
+ from adam.repl_state import BashSession, ReplState
7
+ from adam.utils import log2
8
+ from adam.utils_k8s.pods import Pods
9
+
10
+ class Device:
11
+ def pods(self, state: ReplState, me: str = None) -> tuple[list[str], str]:
12
+ return self.pod_names(state), me if me else self.pod(state)
13
+
14
+ def default_pod(self, state: ReplState) -> tuple[list[str], str]:
15
+ if me := self.pod(state):
16
+ return me
17
+
18
+ if pods := self.pod_names(state):
19
+ return pods[0]
20
+
21
+ return None
22
+
23
+ def pod(self, state: ReplState) -> str:
24
+ return None
25
+
26
+ def pod_names(self, state: ReplState) -> list[str]:
27
+ return []
28
+
29
+ def default_container(self, state: ReplState) -> str:
30
+ return None
31
+
32
+ @abstractmethod
33
+ def ls(self, cmd: str, state: ReplState):
34
+ pass
35
+
36
+ def ls_completion(self, cmd: str, state: ReplState, default: dict = {}):
37
+ return default
38
+
39
+ def cd(self, dir: str, state: ReplState):
40
+ pass
41
+
42
+ def cd_completion(self, cmd: str, state: ReplState, default: dict = {}):
43
+ return default
44
+
45
+ def direct_dirs(self, cmd: str, state: ReplState, default: dict = {}) -> list[str]:
46
+ return []
47
+
48
+ @abstractmethod
49
+ def pwd(self, state: ReplState):
50
+ pass
51
+
52
+ def try_fallback_action(self, chain: Command, state: ReplState, cmd: str):
53
+ return False, None
54
+
55
+ def enter(self, state: ReplState):
56
+ pass
57
+
58
+ def preview(self, table: str, state: ReplState):
59
+ if not table:
60
+ if state.in_repl:
61
+ log2('Table is required.')
62
+ log2()
63
+ log2('Tables:')
64
+ self.show_tables(state)
65
+ else:
66
+ log2('* Table is missing.')
67
+ self.show_tables(state)
68
+
69
+ Command.display_help()
70
+
71
+ return 'command-missing'
72
+
73
+ rows = Config().get('preview.rows', 10)
74
+ self.show_table_preview(state, table, rows)
75
+
76
+ return state
77
+
78
+ @abstractmethod
79
+ def show_tables(self, state: ReplState):
80
+ pass
81
+
82
+ @abstractmethod
83
+ def show_table_preview(self, state: ReplState, table: str, rows: int):
84
+ pass
85
+
86
+ def bash(self, s0: ReplState, s1: ReplState, args: list[str]):
87
+ if s1.in_repl:
88
+ if self.bash_target_changed(s0, s1):
89
+ r = self._exec_with_dir(s1, args)
90
+ else:
91
+ r = self._exec_with_dir(s0, args)
92
+
93
+ if not r:
94
+ s1.exit_bash()
95
+
96
+ return 'inconsistent pwd'
97
+
98
+ return r
99
+ else:
100
+ self.exec_no_dir(' '.join(args), s1)
101
+
102
+ return s1
103
+
104
+ def _exec_with_dir(self, state: ReplState, args: list[str]) -> list[PodExecResult]:
105
+ session_just_created = False
106
+ if not args:
107
+ session_just_created = True
108
+ session = BashSession(state.device)
109
+ state.enter_bash(session)
110
+
111
+ if state.bash_session:
112
+ if args != ['pwd']:
113
+ if args:
114
+ args.append('&&')
115
+ args.extend(['pwd', '>', f'/tmp/.qing-{state.bash_session.session_id}'])
116
+
117
+ if not session_just_created:
118
+ if pwd := state.bash_session.pwd(state):
119
+ args = ['cd', pwd, '&&'] + args
120
+
121
+ return self.exec_with_dir(' '.join(args), session_just_created, state)
122
+
123
+ @abstractmethod
124
+ def bash_target_changed(self, s0: ReplState, s1: ReplState):
125
+ pass
126
+
127
+ @abstractmethod
128
+ def exec_no_dir(self, command: str, state: ReplState):
129
+ pass
130
+
131
+ @abstractmethod
132
+ def exec_with_dir(self, command: str, session_just_created: bool, state: ReplState):
133
+ pass
134
+
135
+ def bash_completion(self, cmd: str, state: ReplState, default: dict = {}):
136
+ return default
137
+
138
+ def files(self, state: ReplState):
139
+ r: PodExecResult = Pods.exec(self.default_pod(state), self.default_container(state), state.namespace, f'find -maxdepth 1 -type f', show_out=Config().is_debug(), shell='bash')
140
+
141
+ log_files = []
142
+ for line in r.stdout.split('\n'):
143
+ line = line.strip(' \r')
144
+ if line:
145
+ if line.startswith('./'):
146
+ line = line[2:]
147
+ log_files.append(line)
148
+
149
+ return log_files