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/commands/devices.py DELETED
@@ -1,89 +0,0 @@
1
- from adam.commands.command import Command
2
- from adam.repl_state import ReplState
3
-
4
- class DeviceCass(Command):
5
- COMMAND = f'{ReplState.C}:'
6
-
7
- # the singleton pattern
8
- def __new__(cls, *args, **kwargs):
9
- if not hasattr(cls, 'instance'): cls.instance = super(DeviceCass, cls).__new__(cls)
10
-
11
- return cls.instance
12
-
13
- def __init__(self, successor: Command=None):
14
- super().__init__(successor)
15
-
16
- def command(self):
17
- return DeviceCass.COMMAND
18
-
19
- def run(self, cmd: str, state: ReplState):
20
- if not self.args(cmd):
21
- return super().run(cmd, state)
22
-
23
- state.device = ReplState.C
24
-
25
- return state
26
-
27
- def completion(self, state: ReplState):
28
- return super().completion(state)
29
-
30
- def help(self, _: ReplState):
31
- return f'{DeviceCass.COMMAND}\t move to Cassandra Operations device'
32
-
33
- class DevicePostgres(Command):
34
- COMMAND = f'{ReplState.P}:'
35
-
36
- # the singleton pattern
37
- def __new__(cls, *args, **kwargs):
38
- if not hasattr(cls, 'instance'): cls.instance = super(DevicePostgres, cls).__new__(cls)
39
-
40
- return cls.instance
41
-
42
- def __init__(self, successor: Command=None):
43
- super().__init__(successor)
44
-
45
- def command(self):
46
- return DevicePostgres.COMMAND
47
-
48
- def run(self, cmd: str, state: ReplState):
49
- if not self.args(cmd):
50
- return super().run(cmd, state)
51
-
52
- state.device = ReplState.P
53
-
54
- return state
55
-
56
- def completion(self, state: ReplState):
57
- return super().completion(state)
58
-
59
- def help(self, _: ReplState):
60
- return f'{DevicePostgres.COMMAND}\t move to Postgres Operations device'
61
-
62
- class DeviceApp(Command):
63
- COMMAND = f'{ReplState.A}:'
64
-
65
- # the singleton pattern
66
- def __new__(cls, *args, **kwargs):
67
- if not hasattr(cls, 'instance'): cls.instance = super(DeviceApp, cls).__new__(cls)
68
-
69
- return cls.instance
70
-
71
- def __init__(self, successor: Command=None):
72
- super().__init__(successor)
73
-
74
- def command(self):
75
- return DeviceApp.COMMAND
76
-
77
- def run(self, cmd: str, state: ReplState):
78
- if not self.args(cmd):
79
- return super().run(cmd, state)
80
-
81
- state.device = ReplState.A
82
-
83
- return state
84
-
85
- def completion(self, state: ReplState):
86
- return super().completion(state)
87
-
88
- def help(self, _: ReplState):
89
- return f'{DeviceApp.COMMAND}\t move to App Operations device'
@@ -1,60 +0,0 @@
1
- import click
2
-
3
- from adam.commands.command import Command
4
- from adam.commands.command_helpers import ClusterCommandHelper
5
- from .setup_frontend import SetupFrontend
6
- from adam.repl_state import ReplState
7
- from adam.utils import lines_to_tabular, log, log2
8
-
9
- class Setup(Command):
10
- COMMAND = 'setup'
11
- reaper_login = None
12
-
13
- # the singleton pattern
14
- def __new__(cls, *args, **kwargs):
15
- if not hasattr(cls, 'instance'): cls.instance = super(Setup, cls).__new__(cls)
16
-
17
- return cls.instance
18
-
19
- def __init__(self, successor: Command=None):
20
- super().__init__(successor)
21
-
22
- def command(self):
23
- return Setup.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
-
31
- if state.in_repl:
32
- log(lines_to_tabular([c.help(ReplState()) for c in Setup.cmd_list()], separator=':'))
33
-
34
- return 'command-missing'
35
- else:
36
- # head with the Chain of Responsibility pattern
37
- cmds = Command.chain(Setup.cmd_list())
38
- if not cmds.run(cmd, state):
39
- log2('* Command is missing.')
40
- Command.display_help()
41
-
42
- def cmd_list():
43
- return [SetupFrontend()]
44
-
45
- def completion(self, state: ReplState):
46
- if state.sts:
47
- return super().completion(state)
48
-
49
- return {}
50
-
51
- def help(self, _: ReplState):
52
- return None
53
-
54
- class SetupCommandHelper(click.Command):
55
- def get_help(self, ctx: click.Context):
56
- log(super().get_help(ctx))
57
- log()
58
- log('Sub-Commands:')
59
-
60
- log(lines_to_tabular([c.help(ReplState()).replace(f'{Setup.COMMAND} ', ' ', 1) for c in Setup.cmd_list()], separator=':'))
@@ -1,58 +0,0 @@
1
- from adam.app_session import AppSession
2
- from adam.commands.command import Command
3
- from adam.k8s_utils.ingresses import Ingresses
4
- from adam.k8s_utils.services import Services
5
- from adam.repl_state import ReplState, RequiredState
6
- from adam.utils import log2
7
-
8
- class SetupFrontend(Command):
9
- COMMAND = 'setup frontend'
10
-
11
- # the singleton pattern
12
- def __new__(cls, *args, **kwargs):
13
- if not hasattr(cls, 'instance'): cls.instance = super(SetupFrontend, 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 SetupFrontend.COMMAND
22
-
23
- def required(self):
24
- return RequiredState.NAMESPACE
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
- log2('This will support c3/c3 only for demo.')
35
-
36
- app_session: AppSession = AppSession.create('c3', 'c3', state.namespace)
37
- try:
38
- name = 'ops'
39
- port = 7678
40
- Services.create_service(name, state.namespace, port, {"run": "ops"})
41
- Ingresses.create_ingress(name, state.namespace, app_session.host, '/c3/c3/ops($|/)', port, annotations={
42
- 'kubernetes.io/ingress.class': 'nginx',
43
- 'nginx.ingress.kubernetes.io/use-regex': 'true',
44
- 'nginx.ingress.kubernetes.io/rewrite-target': '/'
45
- })
46
- except Exception as e:
47
- if e.status == 409:
48
- log2(f"Error: '{name}' already exists in namespace '{state.namespace}'.")
49
- else:
50
- log2(f"Error creating ingress or service: {e}")
51
-
52
- return state
53
-
54
- def completion(self, _: ReplState):
55
- return {}
56
-
57
- def help(self, _: ReplState):
58
- return f'{SetupFrontend.COMMAND}\t sets up frontend'
@@ -1,61 +0,0 @@
1
- import click
2
-
3
- from adam.commands.command import Command
4
- from adam.commands.command_helpers import ClusterCommandHelper
5
- from adam.commands.frontend.teardown_frontend import TearDownFrontend
6
- from .setup_frontend import SetupFrontend
7
- from adam.repl_state import ReplState
8
- from adam.utils import lines_to_tabular, log, log2
9
-
10
- class TearDown(Command):
11
- COMMAND = 'teardown'
12
- reaper_login = None
13
-
14
- # the singleton pattern
15
- def __new__(cls, *args, **kwargs):
16
- if not hasattr(cls, 'instance'): cls.instance = super(TearDown, 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 TearDown.COMMAND
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
-
32
- if state.in_repl:
33
- log(lines_to_tabular([c.help(ReplState()) for c in TearDown.cmd_list()], separator=':'))
34
-
35
- return 'command-missing'
36
- else:
37
- # head with the Chain of Responsibility pattern
38
- cmds = Command.chain(TearDown.cmd_list())
39
- if not cmds.run(cmd, state):
40
- log2('* Command is missing.')
41
- Command.display_help()
42
-
43
- def cmd_list():
44
- return [TearDownFrontend()]
45
-
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
- class TearDownCommandHelper(click.Command):
56
- 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'{TearDown.COMMAND} ', ' ', 1) for c in TearDown.cmd_list()], separator=':'))
@@ -1,225 +0,0 @@
1
- import functools
2
- import re
3
- import subprocess
4
-
5
- from adam.config import Config
6
- from adam.k8s_utils.kube_context import KubeContext
7
- from adam.k8s_utils.pods import Pods
8
- from adam.k8s_utils.secrets import Secrets
9
- from adam.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,77 +0,0 @@
1
- import os
2
- import signal
3
- import traceback
4
-
5
- from adam.config import Config
6
- from adam.sso.idp import Idp
7
- from adam.app_session import AppSession, IdpLogin
8
- from adam.apps import Apps
9
- from adam.commands.command import Command
10
- from adam.repl_state import ReplState
11
- from adam.utils import log2
12
-
13
- class UserEntry(Command):
14
- COMMAND = 'entry'
15
-
16
- # the singleton pattern
17
- def __new__(cls, *args, **kwargs):
18
- if not hasattr(cls, 'instance'): cls.instance = super(UserEntry, cls).__new__(cls)
19
-
20
- return cls.instance
21
-
22
- def __init__(self, successor: Command=None):
23
- super().__init__(successor)
24
-
25
- def command(self):
26
- return UserEntry.COMMAND
27
-
28
- def run(self, cmd: str, state: ReplState):
29
- def custom_handler(signum, frame):
30
- AppSession.ctrl_c_entered = True
31
-
32
- signal.signal(signal.SIGINT, custom_handler)
33
-
34
- if not(args := self.args(cmd)):
35
- return super().run(cmd, state)
36
-
37
- state, args = self.apply_state(args, state)
38
- args, debug = Command.extract_options(args, 'd')
39
- if debug:
40
- Config().set('debug.show-out', True)
41
-
42
- username: str = None
43
- if len(args) > 0:
44
- username = args[0]
45
-
46
- login: IdpLogin = None
47
- while not login:
48
- try:
49
- if not(host := Apps.app_host('c3', 'c3', state.namespace)):
50
- log2('Cannot locate ingress for app.')
51
- username = None
52
- continue
53
-
54
- if not (login := Idp.login(host, username=username, use_token_from_env=False)):
55
- log2('Invalid username/password. Please try again.')
56
- username = None
57
- except Exception as e:
58
- log2(e)
59
-
60
- Config().debug(traceback.format_exc())
61
-
62
- sh = f'{os.getcwd()}/login.sh'
63
- if not os.path.exists(sh):
64
- sh = f'{os.getcwd()}/docker/login.sh'
65
-
66
- if os.getenv('PASS_DOWN_IDP_TOKEN', "true").lower() == "true":
67
- os.system(f'{sh} {login.shell_user()} {login.ser()}')
68
- else:
69
- os.system(f'{sh} {login.shell_user()}')
70
-
71
- return state
72
-
73
- def completion(self, _: ReplState):
74
- return {}
75
-
76
- def help(self, _: ReplState):
77
- return f'{UserEntry.COMMAND}\t ttyd user entry'