kaqing 1.77.0__py3-none-any.whl → 2.0.171__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.
Files changed (308) hide show
  1. adam/__init__.py +1 -0
  2. adam/app_session.py +182 -0
  3. {walker → adam}/apps.py +8 -24
  4. {walker → adam}/batch.py +54 -97
  5. {walker → adam}/checks/check.py +3 -3
  6. {walker → adam}/checks/check_result.py +1 -1
  7. adam/checks/check_utils.py +65 -0
  8. {walker → adam}/checks/compactionstats.py +6 -6
  9. {walker → adam}/checks/cpu.py +14 -8
  10. adam/checks/cpu_metrics.py +52 -0
  11. {walker → adam}/checks/disk.py +6 -6
  12. {walker → adam}/checks/gossip.py +5 -5
  13. {walker → adam}/checks/memory.py +7 -7
  14. {walker → adam}/checks/status.py +5 -5
  15. {walker → adam}/cli.py +3 -3
  16. {walker → adam}/columns/column.py +1 -1
  17. adam/columns/columns.py +45 -0
  18. {walker → adam}/columns/compactions.py +5 -5
  19. {walker → adam}/columns/cpu.py +6 -4
  20. adam/columns/cpu_metrics.py +22 -0
  21. {walker → adam}/columns/dir_data.py +3 -3
  22. {walker → adam}/columns/dir_snapshots.py +3 -3
  23. {walker → adam}/columns/gossip.py +5 -5
  24. {walker → adam}/columns/host_id.py +3 -3
  25. {walker → adam}/columns/memory.py +3 -3
  26. {walker → adam}/columns/node_address.py +3 -3
  27. {walker → adam}/columns/node_load.py +3 -3
  28. {walker → adam}/columns/node_owns.py +3 -3
  29. {walker → adam}/columns/node_status.py +3 -3
  30. {walker → adam}/columns/node_tokens.py +3 -3
  31. {walker → adam}/columns/node_utils.py +2 -2
  32. {walker → adam}/columns/pod_name.py +2 -2
  33. {walker → adam}/columns/volume_cassandra.py +4 -4
  34. {walker → adam}/columns/volume_root.py +3 -3
  35. adam/commands/__init__.py +15 -0
  36. adam/commands/alter_tables.py +81 -0
  37. adam/commands/app_cmd.py +38 -0
  38. {walker → adam}/commands/app_ping.py +10 -16
  39. adam/commands/audit/audit.py +84 -0
  40. adam/commands/audit/audit_repair_tables.py +74 -0
  41. adam/commands/audit/audit_run.py +50 -0
  42. adam/commands/audit/show_last10.py +48 -0
  43. adam/commands/audit/show_slow10.py +47 -0
  44. adam/commands/audit/show_top10.py +45 -0
  45. adam/commands/audit/utils_show_top10.py +59 -0
  46. adam/commands/bash/__init__.py +5 -0
  47. adam/commands/bash/bash.py +36 -0
  48. adam/commands/bash/bash_completer.py +93 -0
  49. adam/commands/bash/utils_bash.py +16 -0
  50. adam/commands/cat.py +50 -0
  51. adam/commands/cd.py +43 -0
  52. adam/commands/check.py +73 -0
  53. {walker → adam}/commands/cli_commands.py +7 -8
  54. adam/commands/code.py +57 -0
  55. adam/commands/command.py +190 -0
  56. {walker → adam}/commands/command_helpers.py +1 -1
  57. {walker → adam}/commands/commands_utils.py +15 -25
  58. adam/commands/cp.py +89 -0
  59. adam/commands/cql/cql_completions.py +33 -0
  60. {walker/commands → adam/commands/cql}/cqlsh.py +20 -35
  61. adam/commands/cql/utils_cql.py +343 -0
  62. {walker/commands/frontend → adam/commands/deploy}/code_start.py +11 -14
  63. adam/commands/deploy/code_stop.py +40 -0
  64. {walker/commands/frontend → adam/commands/deploy}/code_utils.py +7 -9
  65. adam/commands/deploy/deploy.py +25 -0
  66. adam/commands/deploy/deploy_frontend.py +49 -0
  67. adam/commands/deploy/deploy_pg_agent.py +35 -0
  68. adam/commands/deploy/deploy_pod.py +108 -0
  69. adam/commands/deploy/deploy_utils.py +29 -0
  70. adam/commands/deploy/undeploy.py +25 -0
  71. adam/commands/deploy/undeploy_frontend.py +38 -0
  72. adam/commands/deploy/undeploy_pg_agent.py +39 -0
  73. adam/commands/deploy/undeploy_pod.py +48 -0
  74. adam/commands/devices/device.py +118 -0
  75. adam/commands/devices/device_app.py +173 -0
  76. adam/commands/devices/device_auit_log.py +49 -0
  77. adam/commands/devices/device_cass.py +185 -0
  78. adam/commands/devices/device_export.py +86 -0
  79. adam/commands/devices/device_postgres.py +144 -0
  80. adam/commands/devices/devices.py +25 -0
  81. {walker → adam}/commands/exit.py +3 -6
  82. adam/commands/export/clean_up_all_export_sessions.py +37 -0
  83. adam/commands/export/clean_up_export_sessions.py +51 -0
  84. adam/commands/export/drop_export_database.py +55 -0
  85. adam/commands/export/drop_export_databases.py +43 -0
  86. adam/commands/export/export.py +53 -0
  87. adam/commands/export/export_databases.py +170 -0
  88. adam/commands/export/export_handlers.py +71 -0
  89. adam/commands/export/export_select.py +81 -0
  90. adam/commands/export/export_select_x.py +54 -0
  91. adam/commands/export/export_use.py +52 -0
  92. adam/commands/export/exporter.py +352 -0
  93. adam/commands/export/import_session.py +40 -0
  94. adam/commands/export/importer.py +67 -0
  95. adam/commands/export/importer_athena.py +80 -0
  96. adam/commands/export/importer_sqlite.py +47 -0
  97. adam/commands/export/show_column_counts.py +54 -0
  98. adam/commands/export/show_export_databases.py +36 -0
  99. adam/commands/export/show_export_session.py +48 -0
  100. adam/commands/export/show_export_sessions.py +44 -0
  101. adam/commands/export/utils_export.py +314 -0
  102. {walker → adam}/commands/help.py +17 -12
  103. adam/commands/intermediate_command.py +49 -0
  104. adam/commands/issues.py +43 -0
  105. adam/commands/kubectl.py +38 -0
  106. adam/commands/login.py +70 -0
  107. {walker → adam}/commands/logs.py +8 -10
  108. adam/commands/ls.py +41 -0
  109. adam/commands/medusa/medusa.py +27 -0
  110. adam/commands/medusa/medusa_backup.py +57 -0
  111. adam/commands/medusa/medusa_restore.py +83 -0
  112. adam/commands/medusa/medusa_show_backupjobs.py +51 -0
  113. adam/commands/medusa/medusa_show_restorejobs.py +47 -0
  114. {walker → adam}/commands/nodetool.py +17 -21
  115. {walker → adam}/commands/param_get.py +15 -16
  116. adam/commands/param_set.py +43 -0
  117. adam/commands/postgres/postgres.py +104 -0
  118. adam/commands/postgres/postgres_context.py +274 -0
  119. {walker → adam}/commands/postgres/postgres_ls.py +7 -11
  120. {walker → adam}/commands/postgres/postgres_preview.py +8 -13
  121. adam/commands/postgres/psql_completions.py +10 -0
  122. adam/commands/postgres/utils_postgres.py +66 -0
  123. adam/commands/preview_table.py +37 -0
  124. adam/commands/pwd.py +47 -0
  125. adam/commands/reaper/reaper.py +35 -0
  126. adam/commands/reaper/reaper_forward.py +93 -0
  127. adam/commands/reaper/reaper_forward_session.py +6 -0
  128. {walker → adam}/commands/reaper/reaper_forward_stop.py +13 -19
  129. {walker → adam}/commands/reaper/reaper_restart.py +10 -17
  130. adam/commands/reaper/reaper_run_abort.py +46 -0
  131. adam/commands/reaper/reaper_runs.py +82 -0
  132. adam/commands/reaper/reaper_runs_abort.py +63 -0
  133. adam/commands/reaper/reaper_schedule_activate.py +45 -0
  134. adam/commands/reaper/reaper_schedule_start.py +45 -0
  135. adam/commands/reaper/reaper_schedule_stop.py +45 -0
  136. {walker → adam}/commands/reaper/reaper_schedules.py +6 -16
  137. {walker → adam}/commands/reaper/reaper_status.py +11 -19
  138. adam/commands/reaper/utils_reaper.py +196 -0
  139. adam/commands/repair/repair.py +26 -0
  140. {walker → adam}/commands/repair/repair_log.py +7 -10
  141. adam/commands/repair/repair_run.py +70 -0
  142. adam/commands/repair/repair_scan.py +71 -0
  143. {walker → adam}/commands/repair/repair_stop.py +8 -11
  144. adam/commands/report.py +61 -0
  145. adam/commands/restart.py +60 -0
  146. {walker → adam}/commands/rollout.py +25 -30
  147. adam/commands/shell.py +34 -0
  148. adam/commands/show/show.py +39 -0
  149. walker/commands/show/show_version.py → adam/commands/show/show_adam.py +14 -10
  150. adam/commands/show/show_app_actions.py +57 -0
  151. {walker → adam}/commands/show/show_app_id.py +12 -15
  152. {walker → adam}/commands/show/show_app_queues.py +9 -12
  153. adam/commands/show/show_cassandra_repairs.py +38 -0
  154. adam/commands/show/show_cassandra_status.py +124 -0
  155. {walker → adam}/commands/show/show_cassandra_version.py +6 -16
  156. adam/commands/show/show_commands.py +59 -0
  157. walker/commands/show/show_storage.py → adam/commands/show/show_host.py +11 -13
  158. adam/commands/show/show_login.py +62 -0
  159. {walker → adam}/commands/show/show_params.py +4 -4
  160. adam/commands/show/show_processes.py +51 -0
  161. adam/commands/show/show_storage.py +42 -0
  162. adam/commands/watch.py +82 -0
  163. {walker → adam}/config.py +10 -22
  164. {walker → adam}/embedded_apps.py +1 -1
  165. adam/embedded_params.py +2 -0
  166. adam/log.py +47 -0
  167. {walker → adam}/pod_exec_result.py +10 -2
  168. adam/repl.py +182 -0
  169. adam/repl_commands.py +124 -0
  170. adam/repl_state.py +458 -0
  171. adam/sql/__init__.py +0 -0
  172. adam/sql/sql_completer.py +120 -0
  173. adam/sql/sql_state_machine.py +618 -0
  174. adam/sql/term_completer.py +76 -0
  175. adam/sso/__init__.py +0 -0
  176. {walker → adam}/sso/authenticator.py +5 -1
  177. adam/sso/authn_ad.py +170 -0
  178. {walker → adam}/sso/authn_okta.py +39 -22
  179. adam/sso/cred_cache.py +60 -0
  180. adam/sso/id_token.py +23 -0
  181. adam/sso/idp.py +143 -0
  182. adam/sso/idp_login.py +50 -0
  183. adam/sso/idp_session.py +55 -0
  184. adam/sso/sso_config.py +63 -0
  185. adam/utils.py +679 -0
  186. adam/utils_app.py +98 -0
  187. adam/utils_athena.py +145 -0
  188. adam/utils_audits.py +106 -0
  189. adam/utils_issues.py +32 -0
  190. adam/utils_k8s/__init__.py +0 -0
  191. adam/utils_k8s/app_clusters.py +28 -0
  192. adam/utils_k8s/app_pods.py +33 -0
  193. adam/utils_k8s/cassandra_clusters.py +36 -0
  194. adam/utils_k8s/cassandra_nodes.py +33 -0
  195. adam/utils_k8s/config_maps.py +34 -0
  196. {walker/k8s_utils → adam/utils_k8s}/custom_resources.py +7 -2
  197. adam/utils_k8s/deployment.py +56 -0
  198. {walker/k8s_utils → adam/utils_k8s}/ingresses.py +3 -4
  199. {walker/k8s_utils → adam/utils_k8s}/jobs.py +3 -3
  200. adam/utils_k8s/k8s.py +87 -0
  201. {walker/k8s_utils → adam/utils_k8s}/kube_context.py +4 -4
  202. adam/utils_k8s/pods.py +290 -0
  203. {walker/k8s_utils → adam/utils_k8s}/secrets.py +8 -4
  204. adam/utils_k8s/service_accounts.py +170 -0
  205. {walker/k8s_utils → adam/utils_k8s}/services.py +3 -4
  206. {walker/k8s_utils → adam/utils_k8s}/statefulsets.py +6 -16
  207. {walker/k8s_utils → adam/utils_k8s}/volumes.py +10 -1
  208. adam/utils_net.py +24 -0
  209. adam/utils_repl/__init__.py +0 -0
  210. adam/utils_repl/automata_completer.py +48 -0
  211. adam/utils_repl/repl_completer.py +46 -0
  212. adam/utils_repl/state_machine.py +173 -0
  213. adam/utils_sqlite.py +109 -0
  214. adam/version.py +5 -0
  215. {kaqing-1.77.0.dist-info → kaqing-2.0.171.dist-info}/METADATA +1 -1
  216. kaqing-2.0.171.dist-info/RECORD +236 -0
  217. kaqing-2.0.171.dist-info/entry_points.txt +3 -0
  218. kaqing-2.0.171.dist-info/top_level.txt +1 -0
  219. kaqing-1.77.0.dist-info/RECORD +0 -159
  220. kaqing-1.77.0.dist-info/entry_points.txt +0 -3
  221. kaqing-1.77.0.dist-info/top_level.txt +0 -1
  222. walker/__init__.py +0 -3
  223. walker/app_session.py +0 -168
  224. walker/checks/check_utils.py +0 -97
  225. walker/columns/columns.py +0 -43
  226. walker/commands/add_user.py +0 -68
  227. walker/commands/app.py +0 -67
  228. walker/commands/bash.py +0 -87
  229. walker/commands/cd.py +0 -115
  230. walker/commands/check.py +0 -68
  231. walker/commands/command.py +0 -104
  232. walker/commands/cp.py +0 -95
  233. walker/commands/cql_utils.py +0 -53
  234. walker/commands/devices.py +0 -89
  235. walker/commands/frontend/code_stop.py +0 -57
  236. walker/commands/frontend/setup.py +0 -60
  237. walker/commands/frontend/setup_frontend.py +0 -58
  238. walker/commands/frontend/teardown.py +0 -61
  239. walker/commands/frontend/teardown_frontend.py +0 -42
  240. walker/commands/issues.py +0 -69
  241. walker/commands/login.py +0 -72
  242. walker/commands/ls.py +0 -145
  243. walker/commands/medusa/medusa.py +0 -69
  244. walker/commands/medusa/medusa_backup.py +0 -61
  245. walker/commands/medusa/medusa_restore.py +0 -86
  246. walker/commands/medusa/medusa_show_backupjobs.py +0 -52
  247. walker/commands/medusa/medusa_show_restorejobs.py +0 -52
  248. walker/commands/param_set.py +0 -44
  249. walker/commands/postgres/postgres.py +0 -113
  250. walker/commands/postgres/postgres_session.py +0 -225
  251. walker/commands/preview_table.py +0 -98
  252. walker/commands/processes.py +0 -53
  253. walker/commands/pwd.py +0 -64
  254. walker/commands/reaper/reaper.py +0 -78
  255. walker/commands/reaper/reaper_forward.py +0 -100
  256. walker/commands/reaper/reaper_run_abort.py +0 -65
  257. walker/commands/reaper/reaper_runs.py +0 -97
  258. walker/commands/reaper/reaper_runs_abort.py +0 -83
  259. walker/commands/reaper/reaper_schedule_activate.py +0 -64
  260. walker/commands/reaper/reaper_schedule_start.py +0 -64
  261. walker/commands/reaper/reaper_schedule_stop.py +0 -64
  262. walker/commands/reaper/reaper_session.py +0 -159
  263. walker/commands/repair/repair.py +0 -68
  264. walker/commands/repair/repair_run.py +0 -72
  265. walker/commands/repair/repair_scan.py +0 -79
  266. walker/commands/report.py +0 -57
  267. walker/commands/restart.py +0 -61
  268. walker/commands/show/show.py +0 -72
  269. walker/commands/show/show_app_actions.py +0 -53
  270. walker/commands/show/show_cassandra_status.py +0 -35
  271. walker/commands/show/show_commands.py +0 -58
  272. walker/commands/show/show_processes.py +0 -35
  273. walker/commands/show/show_repairs.py +0 -47
  274. walker/commands/status.py +0 -128
  275. walker/commands/storage.py +0 -52
  276. walker/commands/user_entry.py +0 -69
  277. walker/commands/watch.py +0 -85
  278. walker/embedded_params.py +0 -2
  279. walker/k8s_utils/cassandra_clusters.py +0 -48
  280. walker/k8s_utils/cassandra_nodes.py +0 -26
  281. walker/k8s_utils/pods.py +0 -211
  282. walker/repl.py +0 -165
  283. walker/repl_commands.py +0 -58
  284. walker/repl_state.py +0 -211
  285. walker/sso/authn_ad.py +0 -94
  286. walker/sso/idp.py +0 -150
  287. walker/sso/idp_login.py +0 -29
  288. walker/sso/sso_config.py +0 -45
  289. walker/utils.py +0 -194
  290. walker/version.py +0 -5
  291. {walker → adam}/checks/__init__.py +0 -0
  292. {walker → adam}/checks/check_context.py +0 -0
  293. {walker → adam}/checks/issue.py +0 -0
  294. {walker → adam}/cli_group.py +0 -0
  295. {walker → adam}/columns/__init__.py +0 -0
  296. {walker/commands → adam/commands/audit}/__init__.py +0 -0
  297. {walker/commands/frontend → adam/commands/cql}/__init__.py +0 -0
  298. {walker/commands/medusa → adam/commands/deploy}/__init__.py +0 -0
  299. {walker/commands/postgres → adam/commands/devices}/__init__.py +0 -0
  300. {walker/commands/reaper → adam/commands/export}/__init__.py +0 -0
  301. {walker/commands/repair → adam/commands/medusa}/__init__.py +0 -0
  302. {walker → adam}/commands/nodetool_commands.py +0 -0
  303. {walker/commands/show → adam/commands/postgres}/__init__.py +0 -0
  304. {walker/k8s_utils → adam/commands/reaper}/__init__.py +0 -0
  305. {walker/sso → adam/commands/repair}/__init__.py +0 -0
  306. /walker/medusa_show_restorejobs.py → /adam/commands/show/__init__.py +0 -0
  307. {walker → adam}/repl_session.py +0 -0
  308. {kaqing-1.77.0.dist-info → kaqing-2.0.171.dist-info}/WHEEL +0 -0
@@ -1,225 +0,0 @@
1
- import functools
2
- import re
3
- import subprocess
4
-
5
- from walker.config import Config
6
- from walker.k8s_utils.kube_context import KubeContext
7
- from walker.k8s_utils.pods import Pods
8
- from walker.k8s_utils.secrets import Secrets
9
- from walker.utils import log2
10
-
11
- class PostgresSession:
12
- def __init__(self, ns: str, path: str):
13
- self.namespace = ns
14
- self.conn_details = None
15
- self.host = None
16
- self.db = None
17
-
18
- if path:
19
- tks = path.split('/')
20
- hn = tks[0].split('@')
21
- self.host = hn[0]
22
- if len(hn) > 1 and not ns:
23
- self.namespace = hn[1]
24
-
25
- if len(tks) > 1:
26
- self.db = tks[1]
27
-
28
- # work for databases()
29
- def __eq__(self, other: 'PostgresSession'):
30
- return self.host == other.host
31
-
32
- def __hash__(self):
33
- return hash(self.host)
34
-
35
- def find_namespace(self, arg: str):
36
- if arg:
37
- tks = arg.split('@')
38
- if len(tks) > 1:
39
- return tks[1]
40
-
41
- return None
42
-
43
- def directory(self, arg: str = None):
44
- if arg:
45
- if arg == '..':
46
- if self.db:
47
- self.db = None
48
- else:
49
- self.host = None
50
- else:
51
- tks = arg.split('@')
52
- arg = tks[0]
53
- if not self.host:
54
- self.host = arg
55
- else:
56
- self.db = arg
57
-
58
- if not self.host:
59
- return None
60
-
61
- d = self.host
62
- if not self.db:
63
- return d
64
-
65
- return f'{self.host}/{self.db}'
66
-
67
- def hosts(ns: str):
68
- return PostgresSession.hosts_for_namespace(ns)
69
-
70
- @functools.lru_cache()
71
- def hosts_for_namespace(ns: str):
72
- ss = Secrets.list_secrets(ns, name_pattern=Config().get('pg.name-pattern', '^{namespace}.*k8spg.*'))
73
-
74
- def excludes(name: str):
75
- exs = Config().get('pg.excludes', '.helm., -admin-secret')
76
- if exs:
77
- for ex in exs.split(','):
78
- if ex.strip(' ') in name:
79
- return True
80
-
81
- return False
82
-
83
- return [s for s in ss if not excludes(s)]
84
-
85
- @functools.lru_cache()
86
- def databases(self):
87
- dbs = []
88
- # List of databases
89
- # Name | Owner | Encoding | Collate | Ctype | ICU Locale | Locale Provider | Access privileges
90
- # ---------------------------------------+----------+----------+-------------+-------------+------------+-----------------+-----------------------
91
- # postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | libc |
92
- # stgawsscpsr_c3_c3 | postgres | UTF8 | C | C | | libc |
93
- # template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | libc | =c/postgres +
94
- # | | | | | | | postgres=CTc/postgres
95
- # (48 rows)
96
- r = self.run_sql('\l', show_out=False)
97
- s = 0
98
- for line in r.stdout.split('\n'):
99
- line: str = line.strip(' \r')
100
- if s == 0:
101
- if 'List of databases' in line:
102
- s = 1
103
- elif s == 1:
104
- if 'Name' in line and 'Owner' in line and 'Encoding' in line:
105
- s = 2
106
- elif s == 2:
107
- if line.startswith('---------'):
108
- s = 3
109
- elif s == 3:
110
- groups = re.match(r'^\s*(\S*)\s*\|\s*(\S*)\s*\|.*', line)
111
- if groups and groups[1] != '|':
112
- dbs.append({'name': groups[1], 'owner': groups[2]})
113
-
114
- return dbs
115
-
116
- def tables(self):
117
- dbs = []
118
- # List of relations
119
- # Schema | Name | Type | Owner
120
- # ----------+------------------------------------------------------------+-------+---------------
121
- # postgres | c3_2_admin_aclpriv | table | postgres
122
- # postgres | c3_2_admin_aclpriv_a | table | postgres
123
- r = self.run_sql('\dt', show_out=False)
124
- s = 0
125
- for line in r.stdout.split('\n'):
126
- line: str = line.strip(' \r')
127
- if s == 0:
128
- if 'List of relations' in line:
129
- s = 1
130
- elif s == 1:
131
- if 'Schema' in line and 'Name' in line and 'Type' in line:
132
- s = 2
133
- elif s == 2:
134
- if line.startswith('---------'):
135
- s = 3
136
- elif s == 3:
137
- groups = re.match(r'^\s*(\S*)\s*\|\s*(\S*)\s*\|.*', line)
138
- if groups and groups[1] != '|':
139
- dbs.append({'schema': groups[1], 'name': groups[2]})
140
-
141
- return dbs
142
-
143
- def run_sql(self, sql: str, show_out = True):
144
- db = self.db if self.db else PostgresSession.default_db()
145
-
146
- if KubeContext.in_cluster():
147
- cmd1 = f'env PGPASSWORD={self.password()} psql -h {self.endpoint()} -p {self.port()} -U {self.username()} {db} --pset pager=off -c'
148
- log2(f'{cmd1} "{sql}"')
149
- # remove double quotes from the sql argument
150
- cmd = cmd1.split(' ') + [sql]
151
- r = subprocess.run(cmd, capture_output=True, text=True)
152
- if show_out:
153
- log2(r.stdout)
154
- log2(r.stderr)
155
-
156
- return r
157
- else:
158
- ns = self.namespace
159
- image = Config().get('pg.agent.image', 'seanahnsf/kaqing')
160
- pod_name = Config().get('pg.agent.name', 'kaqing-agent')
161
- timeout = Config().get('pg.agent.timeout', 3600)
162
-
163
- try:
164
- Pods.create(ns, pod_name, image, ['sleep', f'{timeout}'], env={'NAMESPACE': ns}, sa_name='c3')
165
- except Exception as e:
166
- if e.status == 409:
167
- if Pods.completed(ns, pod_name):
168
- try:
169
- Pods.delete(pod_name, ns)
170
- Pods.create(ns, pod_name, image, ['sleep', f'{timeout}'], env={'NAMESPACE': ns}, sa_name='c3')
171
- except Exception as e2:
172
- log2("Exception when calling BatchV1Api->create_pod: %s\n" % e2)
173
-
174
- return
175
- else:
176
- log2("Exception when calling BatchV1Api->create_pod: %s\n" % e)
177
-
178
- return
179
-
180
- Pods.wait_for_running(ns, pod_name)
181
-
182
- cmd = f'PGPASSWORD="{self.password()}" psql -h {self.endpoint()} -p {self.port()} -U {self.username()} {db} --pset pager=off -c "{sql}"'
183
-
184
- return Pods.exec(pod_name, pod_name, ns, cmd, show_out=show_out)
185
-
186
- def endpoint(self):
187
- if not self.conn_details:
188
- self.conn_details = Secrets.get_data(self.namespace, self.host)
189
-
190
- endpoint_key = Config().get('pg.secret.endpoint-key', 'postgres-db-endpoint')
191
-
192
- return self.conn_details[endpoint_key] if endpoint_key in self.conn_details else ''
193
-
194
- def port(self):
195
- if not self.conn_details:
196
- self.conn_details = Secrets.get_data(self.namespace, self.host)
197
-
198
- port_key = Config().get('pg.secret.port-key', 'postgres-db-port')
199
-
200
- return self.conn_details[port_key] if port_key in self.conn_details else ''
201
-
202
- def username(self):
203
- if not self.conn_details:
204
- self.conn_details = Secrets.get_data(self.namespace, self.host)
205
-
206
- username_key = Config().get('pg.secret.username-key', 'postgres-admin-username')
207
-
208
- return self.conn_details[username_key] if username_key in self.conn_details else ''
209
-
210
- def password(self):
211
- if not self.conn_details:
212
- self.conn_details = Secrets.get_data(self.namespace, self.host)
213
-
214
- password_key = Config().get('pg.secret.password-key', 'postgres-admin-password')
215
-
216
- return self.conn_details[password_key] if password_key in self.conn_details else ''
217
-
218
- def default_db():
219
- return Config().get('pg.default-db', 'postgres')
220
-
221
- def default_owner():
222
- return Config().get('pg.default-owner', 'postgres')
223
-
224
- def default_schema():
225
- return Config().get('pg.default-schema', 'postgres')
@@ -1,98 +0,0 @@
1
- import functools
2
-
3
- from walker.commands.command import Command
4
- from walker.commands.cql_utils import parse_cql_desc_tables, run_cql
5
- from walker.commands.postgres.postgres_session import PostgresSession
6
- from walker.config import Config
7
- from walker.pod_exec_result import PodExecResult
8
- from walker.repl_state import ReplState, RequiredState
9
- from walker.utils import lines_to_tabular, log, log2
10
-
11
- class PreviewTable(Command):
12
- COMMAND = 'preview'
13
-
14
- # the singleton pattern
15
- def __new__(cls, *args, **kwargs):
16
- if not hasattr(cls, 'instance'): cls.instance = super(PreviewTable, cls).__new__(cls)
17
-
18
- return cls.instance
19
-
20
- def __init__(self, successor: Command=None):
21
- super().__init__(successor)
22
-
23
- def command(self):
24
- return PreviewTable.COMMAND
25
-
26
- def required(self):
27
- return RequiredState.CLUSTER_OR_POD
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 state.device == ReplState.P:
35
- if not self.validate_state(state, RequiredState.PG_DATABASE):
36
- return state
37
- else:
38
- if not self.validate_state(state):
39
- return state
40
-
41
- if not args:
42
- def show_tables():
43
- if state.device == ReplState.P:
44
- pg = PostgresSession(state.namespace, state.pg_path)
45
- lines = [db["name"] for db in pg.tables() if db["schema"] == PostgresSession.default_schema()]
46
- log(lines_to_tabular(lines, separator=','))
47
- else:
48
- run_cql(state, f'describe tables', show_out=True)
49
-
50
- if state.in_repl:
51
- log2('Table is required.')
52
- log2()
53
- log2('Tables:')
54
- show_tables()
55
- else:
56
- log2('* Table is missing.')
57
- show_tables()
58
-
59
- Command.display_help()
60
-
61
- return 'command-missing'
62
-
63
- table = args[0]
64
-
65
- rows = Config().get('preview.rows', 10)
66
- if state.device == ReplState.P:
67
- PostgresSession(state.namespace, state.pg_path).run_sql(f'select * from {table} limit {rows}')
68
- else:
69
- run_cql(state, f'select * from {table} limit {rows}', show_out=True, use_single_quotes=True)
70
-
71
- return state
72
-
73
- def completion(self, state: ReplState):
74
- if state.device == ReplState.P:
75
- if tables := PreviewTable.pg_tables(state.namespace, state.pg_path):
76
- return {PreviewTable.COMMAND: {db["name"]: None for db in tables if db["schema"] == PostgresSession.default_schema()}}
77
- else:
78
- if state.pod:
79
- tables = PreviewTable.cql_tables(state)
80
- return {PreviewTable.COMMAND: {f'{k}.{t}': None for k, ts in tables.items() for t in ts}}
81
-
82
- return {}
83
-
84
- def help(self, _: ReplState):
85
- return f'{PreviewTable.COMMAND} TABLE\t preview table'
86
-
87
- @functools.lru_cache()
88
- def cql_tables(state: ReplState):
89
- r: PodExecResult = run_cql(state, 'describe tables', show_out=False)
90
- return parse_cql_desc_tables(r.stdout)
91
-
92
- @functools.lru_cache()
93
- def pg_tables(ns: str, pg_path: str):
94
- pg = PostgresSession(ns, pg_path)
95
- if pg.db:
96
- return pg.tables()
97
-
98
- return None
@@ -1,53 +0,0 @@
1
- from walker.commands.command import Command
2
- from walker.commands.commands_utils import show_table
3
- from walker.config import Config
4
- from walker.k8s_utils.statefulsets import StatefulSets
5
- from walker.repl_state import ReplState, RequiredState
6
-
7
- class Processes(Command):
8
- COMMAND = 'processes'
9
-
10
- # the singleton pattern
11
- def __new__(cls, *args, **kwargs):
12
- if not hasattr(cls, 'instance'): cls.instance = super(Processes, cls).__new__(cls)
13
-
14
- return cls.instance
15
-
16
- def __init__(self, successor: Command=None):
17
- super().__init__(successor)
18
-
19
- def command(self):
20
- return Processes.COMMAND
21
-
22
- def required(self):
23
- return RequiredState.CLUSTER_OR_POD
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
- args, show_output = Command.extract_options(args, ['-s', '--show'])
34
-
35
- cols = Config().get('processes.columns', 'pod,cpu,mem')
36
- header = Config().get('processes.header', 'POD_NAME,CPU,MEM/LIMIT')
37
-
38
- if state.pod:
39
- show_table(state, [state.pod], cols, header, show_output=show_output)
40
- elif state.sts:
41
- pod_names = [pod.metadata.name for pod in StatefulSets.pods(state.sts, state.namespace)]
42
- show_table(state, pod_names, cols, header, show_output=show_output)
43
-
44
- return state
45
-
46
- def completion(self, state: ReplState):
47
- if not state.sts:
48
- return {}
49
-
50
- return {Processes.COMMAND: None}
51
-
52
- def help(self, _: ReplState):
53
- return f'{Processes.COMMAND} [-s]\t show process overview -s show commands on nodes'
walker/commands/pwd.py DELETED
@@ -1,64 +0,0 @@
1
- from walker.commands.command import Command
2
- from walker.commands.postgres.postgres_session import PostgresSession
3
- from walker.repl_state import ReplState
4
- from walker.utils import lines_to_tabular, log
5
-
6
- class Pwd(Command):
7
- COMMAND = 'pwd'
8
-
9
- # the singleton pattern
10
- def __new__(cls, *args, **kwargs):
11
- if not hasattr(cls, 'instance'): cls.instance = super(Pwd, cls).__new__(cls)
12
-
13
- return cls.instance
14
-
15
- def __init__(self, successor: Command=None):
16
- super().__init__(successor)
17
-
18
- def command(self):
19
- return Pwd.COMMAND
20
-
21
- def run(self, cmd: str, state: ReplState):
22
- if not(args := self.args(cmd)):
23
- return super().run(cmd, state)
24
-
25
- state, args = self.apply_state(args, state)
26
-
27
- def device_line(state: ReplState, device: str):
28
- words = []
29
-
30
- if device == ReplState.P:
31
- pg = PostgresSession(state.namespace, state.pg_path)
32
-
33
- if pg.host:
34
- words.append(f'host/{pg.host}')
35
- if pg.db:
36
- words.append(f'database/{pg.db}')
37
- elif device == ReplState.A:
38
- if state.app_env:
39
- words.append(f'env/{state.app_env}')
40
- if state.app_app:
41
- words.append(f'app/{state.app_app}')
42
- else:
43
- if state.sts:
44
- words.append(f'sts/{state.sts}')
45
- if state.pod:
46
- words.append(f'pod/{state.pod}')
47
-
48
- return '\t'.join([f'{device}:>'] + (words if words else ['/']))
49
-
50
- log(lines_to_tabular([
51
- device_line(state, ReplState.A),
52
- device_line(state, ReplState.C),
53
- device_line(state, ReplState.P),
54
- f'NAMESPACE\t{state.namespace if state.namespace else "/"}'
55
- ], 'DEVICE\tLOCATION', separator='\t'))
56
- log()
57
-
58
- return state
59
-
60
- def completion(self, state: ReplState):
61
- return super().completion(state)
62
-
63
- def help(self, _: ReplState):
64
- return f'{Pwd.COMMAND}\t print current working directories'
@@ -1,78 +0,0 @@
1
- import click
2
-
3
- from walker.commands.command import Command
4
- from walker.commands.command_helpers import ClusterCommandHelper
5
- from .reaper_forward import ReaperForward
6
- from .reaper_forward_stop import ReaperForwardStop
7
- from .reaper_restart import ReaperRestart
8
- from .reaper_run_abort import ReaperRunAbort
9
- from .reaper_runs import ReaperRuns
10
- from .reaper_runs_abort import ReaperRunsAbort
11
- from .reaper_schedule_activate import ReaperScheduleActivate
12
- from .reaper_schedule_start import ReaperScheduleStart
13
- from .reaper_schedule_stop import ReaperScheduleStop
14
- from .reaper_schedules import ReaperSchedules
15
- from .reaper_status import ReaperStatus
16
- from walker.repl_state import ReplState, RequiredState
17
- from walker.utils import lines_to_tabular, log, log2
18
-
19
- class Reaper(Command):
20
- COMMAND = 'reaper'
21
- reaper_login = None
22
-
23
- # the singleton pattern
24
- def __new__(cls, *args, **kwargs):
25
- if not hasattr(cls, 'instance'): cls.instance = super(Reaper, cls).__new__(cls)
26
-
27
- return cls.instance
28
-
29
- def __init__(self, successor: Command=None):
30
- super().__init__(successor)
31
-
32
- def command(self):
33
- return Reaper.COMMAND
34
-
35
- def required(self):
36
- return RequiredState.CLUSTER
37
-
38
- def run(self, cmd: str, state: ReplState):
39
- if not(args := self.args(cmd)):
40
- return super().run(cmd, state)
41
-
42
- state, args = self.apply_state(args, state)
43
- if not self.validate_state(state):
44
- return state
45
-
46
- if state.in_repl:
47
- log(lines_to_tabular([c.help(ReplState()) for c in Reaper.cmd_list()], separator=':'))
48
-
49
- return 'command-missing'
50
- else:
51
- # head with the Chain of Responsibility pattern
52
- cmds = Command.chain(Reaper.cmd_list())
53
- if not cmds.run(cmd, state):
54
- log2('* Command is missing.')
55
- Command.display_help()
56
-
57
- def cmd_list():
58
- return [ReaperSchedules(), ReaperScheduleStop(), ReaperScheduleActivate(), ReaperScheduleStart(),
59
- ReaperForwardStop(), ReaperForward(), ReaperRunAbort(), ReaperRunsAbort(), ReaperRestart(), ReaperRuns(), ReaperStatus()]
60
-
61
- def completion(self, state: ReplState):
62
- if state.sts:
63
- return super().completion(state)
64
-
65
- return {}
66
-
67
- def help(self, _: ReplState):
68
- return None
69
-
70
- class ReaperCommandHelper(click.Command):
71
- def get_help(self, ctx: click.Context):
72
- log(super().get_help(ctx))
73
- log()
74
- log('Sub-Commands:')
75
-
76
- log(lines_to_tabular([c.help(ReplState()).replace(f'{Reaper.COMMAND} ', ' ', 1) for c in Reaper.cmd_list()], separator=':'))
77
- log()
78
- ClusterCommandHelper.cluster_help()
@@ -1,100 +0,0 @@
1
- import threading
2
- import time
3
-
4
- from walker.commands.command import Command
5
- from .reaper_session import ReaperSession
6
- from walker.config import Config
7
- from walker.repl_session import ReplSession
8
- from walker.repl_state import ReplState, RequiredState
9
- from walker.utils import lines_to_tabular, log2
10
-
11
- class ReaperForward(Command):
12
- COMMAND = 'reaper forward'
13
- reaper_login = None
14
-
15
- # the singleton pattern
16
- def __new__(cls, *args, **kwargs):
17
- if not hasattr(cls, 'instance'): cls.instance = super(ReaperForward, cls).__new__(cls)
18
-
19
- return cls.instance
20
-
21
- def __init__(self, successor: Command=None):
22
- super().__init__(successor)
23
-
24
- def command(self):
25
- return ReaperForward.COMMAND
26
-
27
- def required(self):
28
- return RequiredState.CLUSTER
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
- if not(reaper := ReaperSession.create(state)):
39
- return state
40
-
41
- spec = reaper.reaper_spec(state)
42
- if state.in_repl:
43
- if ReaperSession.is_forwarding:
44
- log2("Another port-forward is already running.")
45
-
46
- return "already-running"
47
-
48
- # make it a daemon to exit with a Ctrl-D
49
- thread = threading.Thread(target=self.loop, args=(state, reaper), daemon=True)
50
- thread.start()
51
-
52
- while not ReaperSession.is_forwarding:
53
- time.sleep(1)
54
-
55
- d = {
56
- 'reaper-ui': spec["web-uri"],
57
- 'reaper-username': spec["username"],
58
- 'reaper-password': spec["password"]
59
- }
60
- log2()
61
- log2(lines_to_tabular([f'{k},{v}' for k, v in d.items()], separator=','))
62
-
63
- for k, v in d.items():
64
- ReplSession().prompt_session.history.append_string(f'cp {k}')
65
- log2()
66
- log2(f'Use <Up> arrow key to copy the values to clipboard.')
67
- else:
68
- try:
69
- log2(f'Click: {spec["web-uri"]}')
70
- log2(f'username: {spec["username"]}')
71
- log2(f'password: {spec["password"]}')
72
- log2()
73
- log2(f"Press Ctrl+C to break.")
74
-
75
- time.sleep(Config().get('reaper.port-forward.timeout', 3600 * 24))
76
- except KeyboardInterrupt:
77
- pass
78
-
79
- return state
80
-
81
- def loop(self, state: ReplState, reaper: ReaperSession):
82
- def body(uri: str, _: dict[str, str]):
83
- ReaperSession.is_forwarding = True
84
- try:
85
- while not ReaperSession.stopping.is_set():
86
- time.sleep(1)
87
- finally:
88
- ReaperSession.stopping.clear()
89
- ReaperSession.is_forwarding = False
90
-
91
- return reaper.port_forwarded(state, 'webui', body)
92
-
93
- def completion(self, state: ReplState):
94
- if state.sts:
95
- return super().completion(state)
96
-
97
- return {}
98
-
99
- def help(self, _: ReplState):
100
- return f'{ReaperForward.COMMAND}\t port-forward to reaper'
@@ -1,65 +0,0 @@
1
- import requests
2
-
3
- from walker.commands.command import Command
4
- from .reaper_session import ReaperSession
5
- from walker.repl_state import ReplState, RequiredState
6
- from walker.utils import log2
7
-
8
- class ReaperRunAbort(Command):
9
- COMMAND = 'reaper abort run'
10
- reaper_login = None
11
-
12
- # the singleton pattern
13
- def __new__(cls, *args, **kwargs):
14
- if not hasattr(cls, 'instance'): cls.instance = super(ReaperRunAbort, cls).__new__(cls)
15
-
16
- return cls.instance
17
-
18
- def __init__(self, successor: Command=None):
19
- super().__init__(successor)
20
-
21
- def command(self):
22
- return ReaperRunAbort.COMMAND
23
-
24
- def required(self):
25
- return RequiredState.CLUSTER
26
-
27
- def run(self, cmd: str, state: ReplState):
28
- if not(args := self.args(cmd)):
29
- return super().run(cmd, state)
30
-
31
- state, args = self.apply_state(args, state)
32
- if not self.validate_state(state):
33
- return state
34
-
35
- if not args:
36
- if state.in_repl:
37
- log2('Specify run id to abort.')
38
- else:
39
- Command.display_help()
40
-
41
- return state
42
-
43
- if not(reaper := ReaperSession.create(state)):
44
- return state
45
-
46
- self.stop_run(state, reaper, args[0])
47
-
48
- return state
49
-
50
- def stop_run(self, state: ReplState, reaper: ReaperSession, run_id: str):
51
- def body(uri: str, headers: dict[str, str]):
52
- return requests.put(uri, headers=headers)
53
-
54
- # PAUSED, RUNNING, ABORTED
55
- # PUT /repair_run/{id}/state/{state}
56
- reaper.port_forwarded(state, f'repair_run/{run_id}/state/ABORTED', body, method='PUT')
57
-
58
- def completion(self, state: ReplState):
59
- if state.sts:
60
- return super().completion(state)
61
-
62
- return {}
63
-
64
- def help(self, _: ReplState):
65
- return f'{ReaperRunAbort.COMMAND} <run-id>\t abort reaper run'