kaqing 2.0.200__py3-none-any.whl → 2.0.213__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 (65) hide show
  1. adam/batch.py +1 -1
  2. adam/commands/app/utils_app.py +1 -1
  3. adam/commands/cql/completions_c.py +1 -1
  4. adam/commands/cql/utils_cql.py +14 -13
  5. adam/commands/devices/device.py +1 -1
  6. adam/commands/download_cassandra_log.py +2 -2
  7. adam/commands/export/export_databases.py +13 -8
  8. adam/commands/export/export_sessions.py +12 -11
  9. adam/commands/export/exporter.py +140 -53
  10. adam/commands/export/import_session.py +0 -4
  11. adam/commands/export/importer.py +11 -11
  12. adam/commands/export/importer_athena.py +15 -6
  13. adam/commands/export/importer_sqlite.py +19 -8
  14. adam/commands/export/utils_export.py +37 -15
  15. adam/commands/fs/__init__.py +0 -0
  16. adam/commands/{os/cat.py → fs/cat_local.py} +15 -9
  17. adam/commands/{os → fs}/download_file.py +1 -1
  18. adam/commands/{os → fs}/find_files.py +4 -4
  19. adam/commands/{shell.py → fs/ls_local.py} +12 -13
  20. adam/commands/fs/rm.py +18 -0
  21. adam/commands/fs/rm_downloads.py +39 -0
  22. adam/commands/fs/rm_logs.py +38 -0
  23. adam/commands/postgres/postgres_databases.py +1 -1
  24. adam/commands/postgres/postgres_ls.py +1 -1
  25. adam/commands/postgres/utils_postgres.py +2 -1
  26. adam/commands/show/show_cassandra_status.py +3 -10
  27. adam/commands/show/show_processes.py +1 -1
  28. adam/commands/show/show_storage.py +2 -1
  29. adam/embedded_params.py +1 -1
  30. adam/repl_commands.py +16 -13
  31. adam/sso/cred_cache.py +2 -5
  32. adam/utils.py +122 -71
  33. adam/utils_k8s/app_clusters.py +10 -3
  34. adam/utils_k8s/app_pods.py +9 -3
  35. adam/utils_k8s/cassandra_clusters.py +4 -4
  36. adam/utils_k8s/cassandra_nodes.py +13 -7
  37. adam/{pod_exec_result.py → utils_k8s/pod_exec_result.py} +8 -2
  38. adam/utils_k8s/pods.py +34 -29
  39. adam/utils_local.py +78 -2
  40. adam/utils_repl/repl_completer.py +6 -2
  41. adam/utils_sqlite.py +3 -8
  42. adam/version.py +1 -1
  43. {kaqing-2.0.200.dist-info → kaqing-2.0.213.dist-info}/METADATA +1 -1
  44. {kaqing-2.0.200.dist-info → kaqing-2.0.213.dist-info}/RECORD +53 -61
  45. adam/commands/alter_tables.py +0 -66
  46. adam/commands/cassandra/download_cassandra_log.py +0 -45
  47. adam/commands/cassandra/nodetool.py +0 -64
  48. adam/commands/cassandra/nodetool_commands.py +0 -120
  49. adam/commands/cassandra/restart_cluster.py +0 -47
  50. adam/commands/cassandra/restart_node.py +0 -51
  51. adam/commands/cassandra/restart_nodes.py +0 -47
  52. adam/commands/cassandra/rollout.py +0 -88
  53. adam/commands/download_file.py +0 -47
  54. adam/commands/find_files.py +0 -51
  55. adam/commands/os/find_processes.py +0 -76
  56. adam/commands/os/head.py +0 -36
  57. /adam/commands/{cat.py → fs/cat.py} +0 -0
  58. /adam/commands/{cd.py → fs/cd.py} +0 -0
  59. /adam/commands/{find_processes.py → fs/find_processes.py} +0 -0
  60. /adam/commands/{head.py → fs/head.py} +0 -0
  61. /adam/commands/{ls.py → fs/ls.py} +0 -0
  62. /adam/commands/{os → fs}/shell.py +0 -0
  63. {kaqing-2.0.200.dist-info → kaqing-2.0.213.dist-info}/WHEEL +0 -0
  64. {kaqing-2.0.200.dist-info → kaqing-2.0.213.dist-info}/entry_points.txt +0 -0
  65. {kaqing-2.0.200.dist-info → kaqing-2.0.213.dist-info}/top_level.txt +0 -0
@@ -19,9 +19,16 @@ class AthenaImporter(Importer):
19
19
  def prefix(self):
20
20
  return 'e'
21
21
 
22
- def import_from_csv(self, state: ReplState, from_session: str,
23
- keyspace: str, table: str, target_table: str, columns: str,
24
- multi_tables = True, create_db = False):
22
+ def import_from_csv(self,
23
+ state: ReplState,
24
+ from_session: str,
25
+ keyspace: str,
26
+ table: str,
27
+ target_table: str,
28
+ columns: str,
29
+ multi_tables = True,
30
+ create_db = False,
31
+ job_log: str = None):
25
32
  csv_file = self.csv_file(from_session, table, target_table)
26
33
  pod = state.pod
27
34
  namespace = state.namespace
@@ -47,12 +54,14 @@ class AthenaImporter(Importer):
47
54
  return to, to_session
48
55
  finally:
49
56
  if succeeded:
50
- self.remove_csv(state, from_session, table, target_table, multi_tables)
57
+ self.remove_csv(state, from_session, table, target_table, multi_tables, job_log=job_log)
51
58
  Athena.clear_cache()
52
59
 
53
- if not multi_tables:
60
+ if multi_tables:
61
+ log2(f'[{to_session}] {keyspace}.{target_table} OK', file=job_log)
62
+ else:
54
63
  with export_db(state) as dbs:
55
- dbs.sql(f'select * from {database}.{target_table} limit 10')
64
+ dbs.sql(f'select * from {keyspace}.{target_table} limit 10', backgrounded=True, export_log=job_log)
56
65
 
57
66
  def import_from_local_csv(self, state: ReplState,
58
67
  keyspace: str, table: str, csv_file: str, multi_tables = True, create_db = False):
@@ -1,9 +1,10 @@
1
+ from typing import TextIO
1
2
  import pandas
2
3
 
3
4
  from adam.commands.export.export_databases import export_db
4
5
  from adam.commands.export.importer import Importer
5
6
  from adam.repl_state import ReplState
6
- from adam.utils import GeneratorStream, bytes_generator_from_file, ing
7
+ from adam.utils import GeneratorStream, bytes_generator_from_file, ing, log2
7
8
  from adam.utils_k8s.pods import Pods
8
9
  from adam.utils_sqlite import SQLite, sqlite
9
10
 
@@ -11,9 +12,17 @@ class SqliteImporter(Importer):
11
12
  def prefix(self):
12
13
  return 's'
13
14
 
14
- def import_from_csv(self, state: ReplState, from_session: str,
15
- keyspace: str, table: str, target_table: str, columns: str,
16
- multi_tables = True, create_db = False):
15
+ def import_from_csv(self,
16
+ state: ReplState,
17
+ from_session: str,
18
+ keyspace: str,
19
+ table: str,
20
+ target_table: str,
21
+ columns: str,
22
+ multi_tables = True,
23
+ create_db = False,
24
+ job_log: str = None):
25
+
17
26
  csv_file = self.csv_file(from_session, table, target_table)
18
27
  pod = state.pod
19
28
  namespace = state.namespace
@@ -21,7 +30,7 @@ class SqliteImporter(Importer):
21
30
 
22
31
  succeeded = False
23
32
  try:
24
- with ing(f'[{to_session}] Uploading to Sqlite', suppress_log=multi_tables):
33
+ with ing(f'[{to_session}] Uploading to Sqlite', suppress_log=multi_tables, job_log=job_log):
25
34
  # create a connection to single keyspace
26
35
  with sqlite(to_session, keyspace) as conn:
27
36
  bytes = Pods.read_file(pod, 'cassandra', namespace, csv_file)
@@ -35,12 +44,14 @@ class SqliteImporter(Importer):
35
44
  return to, to_session
36
45
  finally:
37
46
  if succeeded:
38
- self.remove_csv(state, from_session, table, target_table, multi_tables)
47
+ self.remove_csv(state, from_session, table, target_table, multi_tables, job_log=job_log)
39
48
  SQLite.clear_cache()
40
49
 
41
- if not multi_tables:
50
+ if multi_tables:
51
+ log2(f'[{to_session}] {keyspace}.{target_table} OK', file=job_log)
52
+ else:
42
53
  with export_db(state) as dbs:
43
- dbs.sql(f'select * from {keyspace}.{target_table} limit 10')
54
+ dbs.sql(f'select * from {keyspace}.{target_table} limit 10', backgrounded=True, export_log=job_log)
44
55
 
45
56
  def import_from_local_csv(self, state: ReplState,
46
57
  keyspace: str, table: str, csv_file: str, multi_tables = True, create_db = False):
@@ -1,12 +1,13 @@
1
1
  import io
2
+ import os
2
3
  import re
3
4
 
4
5
  from adam.config import Config
5
- from adam.pod_exec_result import PodExecResult
6
+ from adam.utils import ExecResult, creating_dir, log2
6
7
  from adam.repl_state import ReplState
7
8
  from adam.utils_k8s.cassandra_nodes import CassandraNodes
8
- from adam.utils_k8s.pods import log_prefix
9
9
  from adam.utils_k8s.statefulsets import StatefulSets
10
+ from adam.utils_local import local_exec
10
11
 
11
12
  class ImportSpec:
12
13
  def __init__(self, table_name: str, session: str = None, files: list[str] = None, importer: str = None):
@@ -196,7 +197,7 @@ class ExportTableStatus:
196
197
  statuses: list[ExportTableStatus] = []
197
198
 
198
199
  status_in_whole = 'done'
199
- log_files: list[str] = find_files(pod, namespace, f'{log_prefix()}-{export_session}_*.log*')
200
+ log_files: list[str] = find_files(pod, namespace, f'{export_log_dir()}/{export_session}_*.log*')
200
201
 
201
202
  for log_file in log_files:
202
203
  status: ExportTableStatus = ExportTableStatus.from_log_file(pod, namespace, export_session, log_file)
@@ -211,7 +212,7 @@ class ExportTableStatus:
211
212
  def get_csv_files_n_table(target_table: str):
212
213
  db = f'{copy_session}_{target_table}'
213
214
  csv_file = f'{csv_dir()}/{db}/*.csv'
214
- csv_files: list[str] = find_files(pod, namespace, csv_file)
215
+ csv_files: list[str] = find_files(pod, namespace, csv_file, remote=True)
215
216
  if csv_files:
216
217
  table = target_table
217
218
  m = re.match(f'{csv_dir()}/{db}/(.*).csv', csv_files[0])
@@ -221,7 +222,7 @@ class ExportTableStatus:
221
222
 
222
223
  return csv_files, target_table
223
224
 
224
- m = re.match(f'{log_prefix()}-{copy_session}_(.*?)\.(.*?)\.log(.*)', log_file)
225
+ m = re.match(f'{export_log_dir()}/{copy_session}_(.*?)\.(.*?)\.log(.*)', log_file)
225
226
  if m:
226
227
  keyspace = m.group(1)
227
228
  target_table = m.group(2)
@@ -234,7 +235,8 @@ class ExportTableStatus:
234
235
 
235
236
  # 4 rows exported to 1 files in 0 day, 0 hour, 0 minute, and 1.335 seconds.
236
237
  pattern = 'rows exported to'
237
- r: PodExecResult = CassandraNodes.exec(pod, namespace, f"grep '{pattern}' {log_file}", show_out=Config().is_debug(), shell='bash')
238
+ r: ExecResult = local_exec(['grep', pattern, log_file], show_out=Config().is_debug())
239
+
238
240
  if r.exit_code() == 0:
239
241
  csv_files, table = get_csv_files_n_table(target_table)
240
242
  if csv_files:
@@ -246,17 +248,26 @@ class ExportTableStatus:
246
248
 
247
249
  return ExportTableStatus(None, None, 'unknown')
248
250
 
249
- def csv_dir():
250
- return Config().get('export.csv_dir', '/c3/cassandra/tmp')
251
-
252
- def find_files(pod: str, namespace: str, pattern: str, mmin: int = 0):
253
- if mmin:
254
- r = CassandraNodes.exec(pod, namespace, f'find {pattern} -mmin -{mmin}', show_out=Config().is_debug(), shell='bash')
251
+ def find_files(pod: str, namespace: str, pattern: str, mmin: int = 0, remote = False):
252
+ stdout = ''
253
+ if not remote:
254
+ # find . -maxdepth 1 -type f -name '*'
255
+ dir = os.path.dirname(pattern)
256
+ base = os.path.basename(pattern)
257
+ cmd = ['find', dir, '-name', base]
258
+ if mmin:
259
+ cmd += ['-mmin', f'-{mmin}']
260
+
261
+ stdout = local_exec(cmd, show_out=Config().is_debug()).stdout
255
262
  else:
256
- r = CassandraNodes.exec(pod, namespace, f'find {pattern}', show_out=Config().is_debug(), shell='bash')
263
+ cmd = f'find {pattern}'
264
+ if mmin:
265
+ cmd = f'{cmd} -mmin -{mmin}'
266
+
267
+ stdout = CassandraNodes.exec(pod, namespace, cmd, show_out=Config().is_debug(), shell='bash').stdout
257
268
 
258
269
  log_files = []
259
- for line in r.stdout.split('\n'):
270
+ for line in stdout.split('\n'):
260
271
  line = line.strip(' \r')
261
272
  if line:
262
273
  log_files.append(line)
@@ -341,4 +352,15 @@ class PodPushHandler:
341
352
  return False
342
353
 
343
354
  def state_with_pod(state: ReplState, pod: str = None):
344
- return PodPushHandler(state, pod=pod)
355
+ return PodPushHandler(state, pod=pod)
356
+
357
+ def os_system_exec(cmd: str, show_out = False):
358
+ if show_out: log2(cmd)
359
+
360
+ os.system(cmd)
361
+
362
+ def csv_dir():
363
+ return Config().get('export.csv_dir', '/c3/cassandra/tmp')
364
+
365
+ def export_log_dir():
366
+ return creating_dir(Config().get('export.log-dir', '/tmp/qing-db/q/export/logs'))
File without changes
@@ -1,14 +1,17 @@
1
+ import os
2
+
1
3
  from adam.commands import validate_args
2
4
  from adam.commands.command import Command
3
- from adam.commands.devices.devices import Devices
4
5
  from adam.repl_state import ReplState, RequiredState
6
+ from adam.utils import log2
7
+ from adam.utils_local import find_local_files
5
8
 
6
- class Cat(Command):
7
- COMMAND = 'cat'
9
+ class CatLocal(Command):
10
+ COMMAND = ':cat'
8
11
 
9
12
  # the singleton pattern
10
13
  def __new__(cls, *args, **kwargs):
11
- if not hasattr(cls, 'instance'): cls.instance = super(Cat, cls).__new__(cls)
14
+ if not hasattr(cls, 'instance'): cls.instance = super(CatLocal, cls).__new__(cls)
12
15
 
13
16
  return cls.instance
14
17
 
@@ -16,7 +19,7 @@ class Cat(Command):
16
19
  super().__init__(successor)
17
20
 
18
21
  def command(self):
19
- return Cat.COMMAND
22
+ return CatLocal.COMMAND
20
23
 
21
24
  def required(self):
22
25
  return [RequiredState.CLUSTER_OR_POD, RequiredState.APP_APP, ReplState.P]
@@ -26,11 +29,14 @@ class Cat(Command):
26
29
  return super().run(cmd, state)
27
30
 
28
31
  with self.validate(args, state) as (args, state):
29
- with validate_args(args, state, name='file'):
30
- return Devices.of(state).bash(state, state, cmd.split(' '))
32
+ with validate_args(args, state, name='file') as args:
33
+ os.system(f'cat {args}')
34
+ log2()
35
+
36
+ return state
31
37
 
32
38
  def completion(self, state: ReplState):
33
- return super().completion(state, lambda: {f: None for f in Devices.of(state).files(state)}, pods=Devices.of(state).pods(state, '-'), auto='jit')
39
+ return super().completion(state, lambda: {n: None for n in find_local_files(file_type='f', max_depth=1)}, auto='jit')
34
40
 
35
41
  def help(self, _: ReplState):
36
- return f'{Cat.COMMAND} file [&]\t run cat command on the pod'
42
+ return f'{CatLocal.COMMAND} file\t run cat command on local system'
@@ -2,7 +2,7 @@ from adam.commands import validate_args
2
2
  from adam.commands.command import Command
3
3
  from adam.commands.devices.devices import Devices
4
4
  from adam.config import Config
5
- from adam.pod_exec_result import PodExecResult
5
+ from adam.utils_k8s.pod_exec_result import PodExecResult
6
6
  from adam.repl_state import ReplState, RequiredState
7
7
  from adam.utils import log2
8
8
  from adam.utils_k8s.pods import Pods
@@ -3,10 +3,10 @@ import os
3
3
  from adam.commands.command import Command
4
4
  from adam.repl_state import ReplState
5
5
  from adam.utils import log2
6
- from adam.utils_local import local_tmp_dir
6
+ from adam.utils_local import local_qing_dir
7
7
 
8
8
  class FindLocalFiles(Command):
9
- COMMAND = 'find local'
9
+ COMMAND = ':find file'
10
10
 
11
11
  # the singleton pattern
12
12
  def __new__(cls, *args, **kwargs):
@@ -28,9 +28,9 @@ class FindLocalFiles(Command):
28
28
  cmd = 'find'
29
29
 
30
30
  if not args:
31
- cmd = f'find {local_tmp_dir()}'
31
+ cmd = f'find {local_qing_dir()}'
32
32
  elif len(args) == 1:
33
- cmd = f"find {local_tmp_dir()} -name '{args[0]}'"
33
+ cmd = f"find {local_qing_dir()} -name '{args[0]}'"
34
34
  else:
35
35
  new_args = [f"'{arg}'" if '*' in arg else arg for arg in args]
36
36
  cmd = 'find ' + ' '.join(new_args)
@@ -1,16 +1,16 @@
1
1
  import os
2
2
 
3
- from adam.commands import validate_args
4
3
  from adam.commands.command import Command
5
4
  from adam.repl_state import ReplState
6
5
  from adam.utils import log2
6
+ from adam.utils_local import local_qing_dir
7
7
 
8
- class Shell(Command):
9
- COMMAND = ':sh'
8
+ class LsLocal(Command):
9
+ COMMAND = ':ls'
10
10
 
11
11
  # the singleton pattern
12
12
  def __new__(cls, *args, **kwargs):
13
- if not hasattr(cls, 'instance'): cls.instance = super(Shell, cls).__new__(cls)
13
+ if not hasattr(cls, 'instance'): cls.instance = super(LsLocal, cls).__new__(cls)
14
14
 
15
15
  return cls.instance
16
16
 
@@ -18,19 +18,18 @@ class Shell(Command):
18
18
  super().__init__(successor)
19
19
 
20
20
  def command(self):
21
- return Shell.COMMAND
21
+ return LsLocal.COMMAND
22
22
 
23
23
  def run(self, cmd: str, state: ReplState):
24
24
  if not(args := self.args(cmd)):
25
25
  return super().run(cmd, state)
26
26
 
27
- with self.validate(args, state) as (args, _):
28
- with validate_args(args, state, at_least=0) as args_str:
29
- if args_str:
30
- os.system(args_str)
31
- log2()
32
- else:
33
- os.system('QING_DROPPED=true bash')
27
+ with self.validate(args, state) as (args, state):
28
+ if args:
29
+ os.system(f'ls {args}')
30
+ else:
31
+ os.system(f'ls {local_qing_dir()}')
32
+ log2()
34
33
 
35
34
  return state
36
35
 
@@ -38,4 +37,4 @@ class Shell(Command):
38
37
  return super().completion(state)
39
38
 
40
39
  def help(self, _: ReplState):
41
- return f'{Shell.COMMAND}\t drop down to shell'
40
+ return f'{LsLocal.COMMAND} [dir]\t list files on local system'
adam/commands/fs/rm.py ADDED
@@ -0,0 +1,18 @@
1
+ from adam.commands.fs.rm_downloads import RmDownloads
2
+ from adam.commands.fs.rm_logs import RmLogs
3
+ from adam.commands.intermediate_command import IntermediateCommand
4
+
5
+ class RmLocal(IntermediateCommand):
6
+ COMMAND = ':rm'
7
+
8
+ # the singleton pattern
9
+ def __new__(cls, *args, **kwargs):
10
+ if not hasattr(cls, 'instance'): cls.instance = super(RmLocal, cls).__new__(cls)
11
+
12
+ return cls.instance
13
+
14
+ def command(self):
15
+ return RmLocal.COMMAND
16
+
17
+ def cmd_list(self):
18
+ return [RmDownloads(), RmLogs()]
@@ -0,0 +1,39 @@
1
+ import os
2
+
3
+ from adam.commands.command import Command
4
+ from adam.repl_state import ReplState
5
+ from adam.utils import log2
6
+ from adam.utils_local import local_downloads_dir
7
+
8
+ class RmDownloads(Command):
9
+ COMMAND = ':rm downloads'
10
+
11
+ # the singleton pattern
12
+ def __new__(cls, *args, **kwargs):
13
+ if not hasattr(cls, 'instance'): cls.instance = super(RmDownloads, 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 RmDownloads.COMMAND
22
+
23
+ def run(self, cmd: str, state: ReplState):
24
+ if not(args := self.args(cmd)):
25
+ return super().run(cmd, state)
26
+
27
+ with self.validate(args, state) as (args, state):
28
+ cmd = f'rm -rf {local_downloads_dir()}/*'
29
+ log2(cmd)
30
+ os.system(cmd)
31
+ log2()
32
+
33
+ return state
34
+
35
+ def completion(self, state: ReplState):
36
+ return super().completion(state)
37
+
38
+ def help(self, _: ReplState):
39
+ return f'{RmDownloads.COMMAND}\t remove all downloads files under {local_downloads_dir()}'
@@ -0,0 +1,38 @@
1
+ import os
2
+
3
+ from adam.commands.command import Command
4
+ from adam.repl_state import ReplState
5
+ from adam.utils import log2, log_dir
6
+
7
+ class RmLogs(Command):
8
+ COMMAND = ':rm logs'
9
+
10
+ # the singleton pattern
11
+ def __new__(cls, *args, **kwargs):
12
+ if not hasattr(cls, 'instance'): cls.instance = super(RmLogs, 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 RmLogs.COMMAND
21
+
22
+ def run(self, cmd: str, state: ReplState):
23
+ if not(args := self.args(cmd)):
24
+ return super().run(cmd, state)
25
+
26
+ with self.validate(args, state) as (args, state):
27
+ cmd = f'rm -rf {log_dir()}/*'
28
+ log2(cmd)
29
+ os.system(cmd)
30
+ log2()
31
+
32
+ return state
33
+
34
+ def completion(self, state: ReplState):
35
+ return super().completion(state)
36
+
37
+ def help(self, _: ReplState):
38
+ return f'{RmLogs.COMMAND}\t remove all qing log files under {log_dir()}'
@@ -145,7 +145,7 @@ class PostgresDatabases:
145
145
 
146
146
  r = Pods.exec(pod_name, container_name, state.namespace, cmd, show_out=show_out, backgrounded=backgrounded, env_prefix=env_prefix)
147
147
  if r and r.log_file:
148
- ReplSession().append_history(f'@{r.pod} cat {r.log_file}')
148
+ ReplSession().append_history(f':cat {r.log_file}')
149
149
 
150
150
  return r
151
151
 
@@ -1,5 +1,5 @@
1
1
  from adam.commands.command import Command
2
- from adam.commands.ls import Ls
2
+ from adam.commands.fs.ls import Ls
3
3
  from adam.repl_state import ReplState, RequiredState
4
4
 
5
5
  class PostgresLs(Command):
@@ -1,6 +1,7 @@
1
1
  import functools
2
2
 
3
3
  from adam.commands.postgres.postgres_databases import PostgresDatabases, pg_path
4
+ from adam.config import Config
4
5
  from adam.repl_state import ReplState
5
6
  from adam.utils import log2, wait_log
6
7
  from adam.utils_k8s.pods import Pods
@@ -62,7 +63,7 @@ class PostgresPodService:
62
63
  if isinstance(args, list):
63
64
  query = ' '.join(args)
64
65
 
65
- PostgresDatabases.run_sql(state, query, backgrounded=backgrounded)
66
+ PostgresDatabases.run_sql(state, query, show_out=Config().is_debug(), backgrounded=backgrounded)
66
67
 
67
68
  class PostgresExecHandler:
68
69
  def __init__(self, state: ReplState, backgrounded=False):
@@ -8,13 +8,14 @@ from adam.checks.gossip import Gossip
8
8
  from adam.columns.columns import Columns
9
9
  from adam.commands import extract_options, extract_trailing_options
10
10
  from adam.commands.command import Command
11
+ from adam.commands.commands_utils import write_to_kaqing_log_file
11
12
  from adam.commands.cql.utils_cql import cassandra
12
13
  from adam.config import Config
13
14
  from adam.repl_session import ReplSession
14
15
  from adam.utils_issues import IssuesUtils
15
16
  from adam.utils_k8s.statefulsets import StatefulSets
16
17
  from adam.repl_state import ReplState, RequiredState
17
- from adam.utils import SORT, tabulize, log2, log_exc
18
+ from adam.utils import SORT, log_dir, tabulize, log2, log_exc
18
19
  from adam.checks.status import parse_nodetool_status
19
20
 
20
21
  class ShowCassandraStatus(Command):
@@ -105,15 +106,7 @@ class ShowCassandraStatus(Command):
105
106
  r = tabulize(status, lambda s: ','.join([c.host_value(check_results, s) for c in columns]), header=header, separator=',', sorted=SORT, to = 0 if backgrounded else 1)
106
107
 
107
108
  if backgrounded:
108
- log_prefix = Config().get('log-prefix', '/tmp/qing')
109
- log_file = f'{log_prefix}-{datetime.now().strftime("%d%H%M%S")}.log'
110
-
111
- with open(log_file, 'w') as f:
112
- f.write(r)
113
-
114
- ReplSession().append_history(f':sh cat {log_file}')
115
-
116
- r = log_file
109
+ r = write_to_kaqing_log_file(r)
117
110
 
118
111
  IssuesUtils.show(check_results)
119
112
 
@@ -37,7 +37,7 @@ class ShowProcesses(Command):
37
37
  header = Config().get('processes-qing.header', 'POD_NAME,Q_CPU/TOTAL,MEM/LIMIT')
38
38
 
39
39
  with cassandra(state) as pods:
40
- pods.display_table(cols, header, show_out=show_out, backgrounded=backgrounded)
40
+ pods.display_table(cols, header, show_out=show_out, backgrounded=backgrounded, msg='Checking processes')
41
41
 
42
42
  return state
43
43
 
@@ -3,6 +3,7 @@ from adam.commands.command import Command
3
3
  from adam.commands.cql.utils_cql import cassandra
4
4
  from adam.config import Config
5
5
  from adam.repl_state import ReplState, RequiredState
6
+ from adam.utils import ing
6
7
 
7
8
  class ShowStorage(Command):
8
9
  COMMAND = 'show storage'
@@ -32,7 +33,7 @@ class ShowStorage(Command):
32
33
  cols = Config().get('storage.columns', 'pod,volume_root,volume_cassandra,snapshots,data,compactions')
33
34
  header = Config().get('storage.header', 'POD_NAME,VOLUME /,VOLUME CASS,SNAPSHOTS,DATA,COMPACTIONS')
34
35
  with cassandra(state) as pods:
35
- pods.display_table(cols, header, show_out=show_out, backgrounded=backgrounded)
36
+ pods.display_table(cols, header, show_out=show_out, backgrounded=backgrounded, msg='Checking storage')
36
37
 
37
38
  return state
38
39
 
adam/embedded_params.py CHANGED
@@ -1,2 +1,2 @@
1
1
  def config():
2
- return {'app': {'console-endpoint': 'https://{host}/{env}/{app}/static/console/index.html', 'container-name': 'c3-server', 'cr': {'cluster-regex': '(.*?-.*?)-.*', 'group': 'ops.c3.ai', 'v': 'v2', 'plural': 'c3cassandras'}, 'label': 'c3__app_id-0', 'login': {'admin-group': '{host}/C3.ClusterAdmin', 'ingress': '{app_id}-k8singr-appleader-001', 'timeout': 5, 'session-check-url': 'https://{host}/{env}/{app}/api/8/C3/userSessionToken', 'cache-creds': True, 'cache-username': True, 'url': 'https://{host}/{env}/{app}', 'another': "You're logged in to {has}. However, for this app, you need to log in to {need}.", 'token-server-url': 'http://localhost:{port}', 'password-max-length': 128}, 'strip': '0'}, 'audit': {'endpoint': 'https://4psvtaxlcb.execute-api.us-west-2.amazonaws.com/prod/', 'workers': 3, 'timeout': 10, 'log-audit-queries': False, 'athena': {'auto-repair': {'elapsed_hours': 12}, 'region': 'us-west-2', 'catalog': 'AwsDataCatalog', 'database': 'audit', 'repair-partition-tables': 'audit', 'output': 's3://s3.ops--audit/ddl/results', 'repair-cluster-tables': 'cluster'}, 'queries': {'last10': "SELECT * FROM audit\nWHERE drive <> 'z' and ({date_condition})\nORDER BY ts DESC LIMIT {limit}", 'slow10': "SELECT * FROM audit\nWHERE drive <> 'z' and ({date_condition})\nORDER BY CAST(duration AS REAL) DESC LIMIT {limit}", 'top10': "SELECT min(c) AS cluster, line, COUNT(*) AS cnt, avg(CAST(duration AS REAL)) AS duration\nFROM audit WHERE drive <> 'z' and ({date_condition})\nGROUP BY line ORDER BY cnt DESC LIMIT {limit}"}}, 'bash': {'workers': 32}, 'cassandra': {'service-name': 'all-pods-service'}, 'cql': {'workers': 32, 'samples': 3, 'secret': {'cluster-regex': '(.*?-.*?)-.*', 'name': '{cluster}-superuser', 'password-item': 'password'}, 'alter-tables': {'excludes': 'system_auth,system_traces,reaper_db,system_distributed,system_views,system,system_schema,system_virtual_schema', 'gc-grace-periods': '3600,86400,864000,7776000', 'batching': True}}, 'checks': {'compactions-threshold': 250, 'cpu-busy-threshold': 98.0, 'cpu-threshold': 0.0, 'cassandra-data-path': '/c3/cassandra', 'root-disk-threshold': 50, 'cassandra-disk-threshold': 50, 'snapshot-size-cmd': "ls /c3/cassandra/data/data/*/*/snapshots | grep snapshots | sed 's/:$//g' | xargs -I {} du -sk {} | awk '{print $1}' | awk '{s+=$1} END {print s}'", 'snapshot-size-threshold': '40G', 'table-sizes-cmd': "ls -Al /c3/cassandra/data/data/ | awk '{print $9}' | sed 's/\\^r//g' | xargs -I {} du -sk /c3/cassandra/data/data/{}"}, 'download': {'workers': 8}, 'export': {'workers': 8, 'csv_dir': '/c3/cassandra/tmp', 'column_counts_query': 'select id, count(id) as columns from {table} group by id order by columns desc limit 10', 'default-importer': 'sqlite', 'sqlite': {'workers': 8, 'columns': '<row-key>', 'local-db-dir': '/tmp/qing-db'}, 'athena': {'workers': 8, 'columns': '<keys>', 'bucket': 'c3.ops--qing'}, 'csv': {'workers': 8, 'columns': '<row-key>'}, 'log-prefix': '/tmp/qing'}, 'get-host-id': {'workers': 32}, 'idps': {'ad': {'email-pattern': '.*@c3.ai', 'uri': 'https://login.microsoftonline.com/53ad779a-93e7-485c-ba20-ac8290d7252b/oauth2/v2.0/authorize?response_type=id_token&response_mode=form_post&client_id=00ff94a8-6b0a-4715-98e0-95490012d818&scope=openid+email+profile&redirect_uri=https%3A%2F%2Fplat.c3ci.cloud%2Fc3%2Fc3%2Foidc%2Flogin&nonce={nonce}&state=EMPTY', 'jwks-uri': 'https://login.microsoftonline.com/common/discovery/keys', 'contact': 'Please contact ted.tran@c3.ai.', 'whitelist-file': '/kaqing/members'}, 'okta': {'default': True, 'email-pattern': '.*@c3iot.com', 'uri': 'https://c3energy.okta.com/oauth2/v1/authorize?response_type=id_token&response_mode=form_post&client_id={client_id}&scope=openid+email+profile+groups&redirect_uri=https%3A%2F%2F{host}%2Fc3%2Fc3%2Foidc%2Flogin&nonce={nonce}&state=EMPTY', 'jwks-uri': 'https://c3energy.okta.com/oauth2/v1/keys'}}, 'issues': {'workers': 32}, 'local-tmp-dir': '/tmp/qing-db', 'logs': {'path': '/c3/cassandra/logs/system.log'}, 'log-prefix': '/tmp/qing', 'nodetool': {'workers': 96, 'commands_in_line': 40, 'status': {'workers': 32, 'samples': 3, 'commands_in_line': 40}}, 'pg': {'name-pattern': '^{namespace}.*-k8spg-.*', 'excludes': '.helm., -admin-secret', 'agent': {'name': 'ops-pg-agent', 'just-in-time': False, 'timeout': 86400, 'image': 'seanahnsf/kaqing'}, 'default-db': 'postgres', 'default-schema': 'postgres', 'secret': {'endpoint-key': 'postgres-db-endpoint', 'port-key': 'postgres-db-port', 'username-key': 'postgres-admin-username', 'password-key': 'postgres-admin-password'}}, 'pod': {'name': 'ops', 'image': 'seanahnsf/kaqing-cloud', 'sa': {'name': 'ops', 'proto': 'c3', 'additional-cluster-roles': 'c3aiops-k8ssandra-operator'}, 'label-selector': 'run=ops'}, 'preview': {'rows': 10}, 'processes': {'columns': 'pod,cpu-metrics,mem', 'header': 'POD_NAME,M_CPU(USAGE/LIMIT),MEM/LIMIT'}, 'processes-qing': {'columns': 'pod,cpu,mem', 'header': 'POD_NAME,Q_CPU/TOTAL,MEM/LIMIT'}, 'reaper': {'service-name': 'reaper-service', 'port-forward': {'timeout': 86400, 'local-port': 9001}, 'abort-runs-batch': 10, 'show-runs-batch': 100, 'pod': {'cluster-regex': '(.*?-.*?-.*?-.*?)-.*', 'label-selector': 'k8ssandra.io/reaper={cluster}-reaper'}, 'secret': {'cluster-regex': '(.*?-.*?)-.*', 'name': '{cluster}-reaper-ui', 'password-item': 'password'}}, 'repair': {'log-path': '/home/cassrepair/logs/', 'image': 'ci-registry.c3iot.io/cloudops/cassrepair:2.0.14', 'secret': 'ciregistryc3iotio', 'env': {'interval': 24, 'timeout': 60, 'pr': False, 'runs': 1}}, 'repl': {'start-drive': 'c', 'a': {'auto-enter': 'c3/c3'}, 'c': {'auto-enter': 'cluster'}, 'x': {'auto-enter': 'latest'}, 'history': {'push-cat-log-file': True, 'push-cat-remote-log-file': True}, 'background-process': {'auto-nohup': True, 'via-sh': True}}, 'status': {'columns': 'status,address,load,tokens,owns,host_id,gossip,compactions', 'header': '--,Address,Load,Tokens,Owns,Host ID,GOSSIP,COMPACTIONS'}, 'storage': {'columns': 'pod,volume_root,volume_cassandra,snapshots,data,compactions', 'header': 'POD_NAME,VOLUME /,VOLUME CASS,SNAPSHOTS,DATA,COMPACTIONS'}, 'watch': {'auto': 'rollout', 'timeout': 3600, 'interval': 10}, 'auto-complete': {'c': {'tables': 'lazy'}, 'x': {'tables': 'lazy'}, 'cli': {'cp': 'jit'}, 'export': {'databases': 'jit'}, 'medusa': {'backups': 'jit'}, 'reaper': {'schedules': 'jit'}}, 'debug': False, 'debugs': {'complete': False, 'timings': False, 'exit-on-error': False}}
2
+ return {'app': {'console-endpoint': 'https://{host}/{env}/{app}/static/console/index.html', 'container-name': 'c3-server', 'cr': {'cluster-regex': '(.*?-.*?)-.*', 'group': 'ops.c3.ai', 'v': 'v2', 'plural': 'c3cassandras'}, 'label': 'c3__app_id-0', 'login': {'admin-group': '{host}/C3.ClusterAdmin', 'ingress': '{app_id}-k8singr-appleader-001', 'timeout': 5, 'session-check-url': 'https://{host}/{env}/{app}/api/8/C3/userSessionToken', 'cache-creds': True, 'cache-username': True, 'url': 'https://{host}/{env}/{app}', 'another': "You're logged in to {has}. However, for this app, you need to log in to {need}.", 'token-server-url': 'http://localhost:{port}', 'password-max-length': 128}, 'strip': '0'}, 'audit': {'endpoint': 'https://4psvtaxlcb.execute-api.us-west-2.amazonaws.com/prod/', 'workers': 3, 'timeout': 10, 'log-audit-queries': False, 'athena': {'auto-repair': {'elapsed_hours': 12}, 'region': 'us-west-2', 'catalog': 'AwsDataCatalog', 'database': 'audit', 'repair-partition-tables': 'audit', 'output': 's3://s3.ops--audit/ddl/results', 'repair-cluster-tables': 'cluster'}, 'queries': {'last10': "SELECT * FROM audit\nWHERE drive <> 'z' and ({date_condition})\nORDER BY ts DESC LIMIT {limit}", 'slow10': "SELECT * FROM audit\nWHERE drive <> 'z' and ({date_condition})\nORDER BY CAST(duration AS REAL) DESC LIMIT {limit}", 'top10': "SELECT min(c) AS cluster, line, COUNT(*) AS cnt, avg(CAST(duration AS REAL)) AS duration\nFROM audit WHERE drive <> 'z' and ({date_condition})\nGROUP BY line ORDER BY cnt DESC LIMIT {limit}"}}, 'bash': {'workers': 32}, 'cassandra': {'service-name': 'all-pods-service'}, 'cql': {'workers': 32, 'samples': 3, 'secret': {'cluster-regex': '(.*?-.*?)-.*', 'name': '{cluster}-superuser', 'password-item': 'password'}, 'alter-tables': {'excludes': 'system_auth,system_traces,reaper_db,system_distributed,system_views,system,system_schema,system_virtual_schema', 'gc-grace-periods': '3600,86400,864000,7776000', 'batching': True}}, 'checks': {'compactions-threshold': 250, 'cpu-busy-threshold': 98.0, 'cpu-threshold': 0.0, 'cassandra-data-path': '/c3/cassandra', 'root-disk-threshold': 50, 'cassandra-disk-threshold': 50, 'snapshot-size-cmd': "ls /c3/cassandra/data/data/*/*/snapshots | grep snapshots | sed 's/:$//g' | xargs -I {} du -sk {} | awk '{print $1}' | awk '{s+=$1} END {print s}'", 'snapshot-size-threshold': '40G', 'table-sizes-cmd': "ls -Al /c3/cassandra/data/data/ | awk '{print $9}' | sed 's/\\^r//g' | xargs -I {} du -sk /c3/cassandra/data/data/{}"}, 'download': {'workers': 8}, 'export': {'workers': 8, 'csv_dir': '/c3/cassandra/tmp', 'column_counts_query': 'select id, count(id) as columns from {table} group by id order by columns desc limit 10', 'default-importer': 'sqlite', 'sqlite': {'workers': 8, 'columns': '<row-key>', 'local-db-dir': '/tmp/qing-db/q/export/db'}, 'athena': {'workers': 8, 'columns': '<keys>', 'bucket': 'c3.ops--qing'}, 'csv': {'workers': 8, 'columns': '<row-key>'}, 'log-dir': '/tmp/qing-db/q/export/logs'}, 'get-host-id': {'workers': 32}, 'idps': {'ad': {'email-pattern': '.*@c3.ai', 'uri': 'https://login.microsoftonline.com/53ad779a-93e7-485c-ba20-ac8290d7252b/oauth2/v2.0/authorize?response_type=id_token&response_mode=form_post&client_id=00ff94a8-6b0a-4715-98e0-95490012d818&scope=openid+email+profile&redirect_uri=https%3A%2F%2Fplat.c3ci.cloud%2Fc3%2Fc3%2Foidc%2Flogin&nonce={nonce}&state=EMPTY', 'jwks-uri': 'https://login.microsoftonline.com/common/discovery/keys', 'contact': 'Please contact ted.tran@c3.ai.', 'whitelist-file': '/kaqing/members'}, 'okta': {'default': True, 'email-pattern': '.*@c3iot.com', 'uri': 'https://c3energy.okta.com/oauth2/v1/authorize?response_type=id_token&response_mode=form_post&client_id={client_id}&scope=openid+email+profile+groups&redirect_uri=https%3A%2F%2F{host}%2Fc3%2Fc3%2Foidc%2Flogin&nonce={nonce}&state=EMPTY', 'jwks-uri': 'https://c3energy.okta.com/oauth2/v1/keys'}}, 'issues': {'workers': 32}, 'local-qing-dir': '/tmp/qing-db/q', 'local-downloads-dir': '/tmp/qing-db/q/downloads', 'logs': {'path': '/c3/cassandra/logs/system.log'}, 'log-dir': '/tmp/qing-db/q/logs', 'nodetool': {'workers': 96, 'commands_in_line': 40, 'status': {'workers': 32, 'samples': 3, 'commands_in_line': 40}}, 'pg': {'name-pattern': '^{namespace}.*-k8spg-.*', 'excludes': '.helm., -admin-secret', 'agent': {'name': 'ops-pg-agent', 'just-in-time': False, 'timeout': 86400, 'image': 'seanahnsf/kaqing'}, 'default-db': 'postgres', 'default-schema': 'postgres', 'secret': {'endpoint-key': 'postgres-db-endpoint', 'port-key': 'postgres-db-port', 'username-key': 'postgres-admin-username', 'password-key': 'postgres-admin-password'}}, 'pod': {'name': 'ops', 'image': 'seanahnsf/kaqing-cloud', 'sa': {'name': 'ops', 'proto': 'c3', 'additional-cluster-roles': 'c3aiops-k8ssandra-operator'}, 'label-selector': 'run=ops'}, 'preview': {'rows': 10}, 'processes': {'columns': 'pod,cpu-metrics,mem', 'header': 'POD_NAME,M_CPU(USAGE/LIMIT),MEM/LIMIT'}, 'processes-qing': {'columns': 'pod,cpu,mem', 'header': 'POD_NAME,Q_CPU/TOTAL,MEM/LIMIT'}, 'reaper': {'service-name': 'reaper-service', 'port-forward': {'timeout': 86400, 'local-port': 9001}, 'abort-runs-batch': 10, 'show-runs-batch': 100, 'pod': {'cluster-regex': '(.*?-.*?-.*?-.*?)-.*', 'label-selector': 'k8ssandra.io/reaper={cluster}-reaper'}, 'secret': {'cluster-regex': '(.*?-.*?)-.*', 'name': '{cluster}-reaper-ui', 'password-item': 'password'}}, 'repair': {'log-path': '/home/cassrepair/logs/', 'image': 'ci-registry.c3iot.io/cloudops/cassrepair:2.0.14', 'secret': 'ciregistryc3iotio', 'env': {'interval': 24, 'timeout': 60, 'pr': False, 'runs': 1}}, 'repl': {'start-drive': 'c', 'a': {'auto-enter': 'c3/c3'}, 'c': {'auto-enter': 'cluster'}, 'x': {'auto-enter': 'latest'}, 'history': {'push-cat-log-file': True, 'push-cat-remote-log-file': True}, 'background-process': {'auto-nohup': True}}, 'status': {'columns': 'status,address,load,tokens,owns,host_id,gossip,compactions', 'header': '--,Address,Load,Tokens,Owns,Host ID,GOSSIP,COMPACTIONS'}, 'storage': {'columns': 'pod,volume_root,volume_cassandra,snapshots,data,compactions', 'header': 'POD_NAME,VOLUME /,VOLUME CASS,SNAPSHOTS,DATA,COMPACTIONS'}, 'watch': {'auto': 'rollout', 'timeout': 3600, 'interval': 10}, 'auto-complete': {'c': {'tables': 'lazy'}, 'x': {'tables': 'lazy'}, 'cli': {'cp': 'jit'}, 'export': {'databases': 'jit'}, 'medusa': {'backups': 'jit'}, 'reaper': {'schedules': 'jit'}}, 'debug': False, 'debugs': {'complete': False, 'timings': False, 'exit-on-error': False}}