meerschaum 1.7.1__py3-none-any.whl → 1.7.3__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 (31) hide show
  1. meerschaum/_internal/arguments/_parser.py +1 -1
  2. meerschaum/actions/api.py +3 -2
  3. meerschaum/actions/stack.py +5 -9
  4. meerschaum/api/dash/components.py +2 -2
  5. meerschaum/api/routes/_misc.py +27 -1
  6. meerschaum/config/__init__.py +4 -4
  7. meerschaum/config/_edit.py +10 -20
  8. meerschaum/config/_read_config.py +11 -12
  9. meerschaum/config/_sync.py +44 -75
  10. meerschaum/config/_version.py +1 -1
  11. meerschaum/config/stack/__init__.py +31 -21
  12. meerschaum/config/static/__init__.py +7 -2
  13. meerschaum/connectors/api/_actions.py +2 -2
  14. meerschaum/connectors/api/_login.py +2 -2
  15. meerschaum/connectors/api/_misc.py +6 -26
  16. meerschaum/connectors/api/_plugins.py +4 -5
  17. meerschaum/connectors/api/_users.py +14 -14
  18. meerschaum/connectors/parse.py +2 -2
  19. meerschaum/connectors/sql/_users.py +1 -1
  20. meerschaum/core/User/_User.py +7 -3
  21. meerschaum/utils/venv/_Venv.py +2 -0
  22. meerschaum/utils/venv/__init__.py +14 -9
  23. meerschaum-1.7.3.dist-info/METADATA +500 -0
  24. {meerschaum-1.7.1.dist-info → meerschaum-1.7.3.dist-info}/RECORD +30 -30
  25. {meerschaum-1.7.1.dist-info → meerschaum-1.7.3.dist-info}/WHEEL +1 -1
  26. meerschaum-1.7.1.dist-info/METADATA +0 -499
  27. {meerschaum-1.7.1.dist-info → meerschaum-1.7.3.dist-info}/LICENSE +0 -0
  28. {meerschaum-1.7.1.dist-info → meerschaum-1.7.3.dist-info}/NOTICE +0 -0
  29. {meerschaum-1.7.1.dist-info → meerschaum-1.7.3.dist-info}/entry_points.txt +0 -0
  30. {meerschaum-1.7.1.dist-info → meerschaum-1.7.3.dist-info}/top_level.txt +0 -0
  31. {meerschaum-1.7.1.dist-info → meerschaum-1.7.3.dist-info}/zip-safe +0 -0
@@ -270,7 +270,7 @@ groups['api'].add_argument(
270
270
  help = "Start the API in secure mode, only allowing `admin` users to execute actions.",
271
271
  )
272
272
  groups['api'].add_argument(
273
- '--no-auth', '--noauth', action='store_true',
273
+ '--no-auth', '--noauth', '--insecure', action='store_true',
274
274
  help = 'When starting the API, do not require authentication. WARNING: This is dangerous!',
275
275
  )
276
276
  groups['api'].add_argument(
meerschaum/actions/api.py CHANGED
@@ -157,7 +157,6 @@ def _api_start(
157
157
  from meerschaum.connectors.parse import parse_instance_keys
158
158
  from meerschaum.utils.pool import get_pool
159
159
  import shutil
160
- import os
161
160
  from copy import deepcopy
162
161
 
163
162
  if action is None:
@@ -276,6 +275,7 @@ def _api_start(
276
275
  env_dict = {
277
276
  MRSM_SERVER_ID: SERVER_ID,
278
277
  MRSM_RUNTIME: 'api',
278
+ MRSM_CONFIG: json.loads(os.environ.get(MRSM_CONFIG, '{}')),
279
279
  }
280
280
  for env_var in get_env_vars():
281
281
  if env_var in env_dict:
@@ -319,7 +319,8 @@ def _api_start(
319
319
  ]
320
320
  for key, val in env_dict.items():
321
321
  gunicorn_args += [
322
- '--env', key + '=' + (json.dumps(val) if isinstance(val, dict) else val)
322
+ '--env', key + "="
323
+ + (json.dumps(val) if isinstance(val, (dict, list)) else val)
323
324
  ]
324
325
  if workers is not None:
325
326
  gunicorn_args += ['--workers', str(workers)]
@@ -43,6 +43,7 @@ def stack(
43
43
  attempt_import, run_python_package, venv_contains_package,
44
44
  pip_install,
45
45
  )
46
+ from meerschaum.config._sync import sync_files
46
47
  from meerschaum.config import get_config
47
48
  from meerschaum.utils.debug import dprint
48
49
  from meerschaum.utils.warnings import warn
@@ -73,9 +74,10 @@ def stack(
73
74
  if not path.exists():
74
75
  bootstrap = True
75
76
  break
76
- ### if bootstrap flag was set, create files
77
77
  if bootstrap:
78
78
  write_stack(debug=debug)
79
+ else:
80
+ sync_files(['stack'])
79
81
 
80
82
  compose_command = ['up']
81
83
  ### default: alias stack as docker-compose
@@ -125,14 +127,8 @@ def stack(
125
127
  warn(f"Unable to install `pyyaml` into venv '{_compose_venv}'.")
126
128
 
127
129
  cmd_list = [
128
- _arg for _arg in (
129
- settings_list
130
- + compose_command
131
- + (
132
- sysargs[2:] if len(sysargs) > 2 and not sub_args
133
- else sub_args
134
- )
135
- )
130
+ _arg
131
+ for _arg in (settings_list + sysargs[1:])
136
132
  if _arg != '--debug'
137
133
  ]
138
134
  if debug:
@@ -10,7 +10,7 @@ from __future__ import annotations
10
10
  from meerschaum.utils.venv import Venv
11
11
  from meerschaum.utils.packages import attempt_import, import_dcc, import_html
12
12
  from meerschaum.utils.typing import SuccessTuple, List
13
- from meerschaum.config.static import _static_config
13
+ from meerschaum.config.static import STATIC_CONFIG
14
14
  from meerschaum.utils.misc import remove_ansi
15
15
  from meerschaum.actions import get_shell
16
16
  from meerschaum.api import endpoints, CHECK_UPDATE
@@ -154,7 +154,7 @@ def alert_from_success_tuple(success: SuccessTuple) -> dbc.Alert:
154
154
  id = 'success-alert',
155
155
  dismissable = True,
156
156
  fade = True,
157
- is_open = not (success[1] in _static_config()['system']['success']['ignore']),
157
+ is_open = not (success[1] in STATIC_CONFIG['system']['success']['ignore']),
158
158
  color = 'success' if success[0] else 'danger',
159
159
  )
160
160
  )
@@ -16,10 +16,14 @@ from meerschaum.api import (
16
16
  private, no_auth, manager
17
17
  )
18
18
  import fastapi
19
- from starlette.responses import FileResponse
19
+ from starlette.responses import FileResponse, JSONResponse
20
+ from meerschaum.connectors.poll import _wrap_retry_connect
20
21
 
21
22
  @app.get(endpoints['favicon'], tags=['Misc'])
22
23
  def get_favicon() -> Any:
24
+ """
25
+ Return the favicon file.
26
+ """
23
27
  from meerschaum.config._paths import API_STATIC_PATH
24
28
  return FileResponse(os.path.join(API_STATIC_PATH, 'ico', 'logo.ico'))
25
29
 
@@ -30,6 +34,9 @@ def get_chaining_status(
30
34
  fastapi.Depends(manager) if private else None
31
35
  ),
32
36
  ) -> bool:
37
+ """
38
+ Return whether this API instance may be chained.
39
+ """
33
40
  return check_allow_chaining()
34
41
 
35
42
 
@@ -39,6 +46,9 @@ def get_instance_info(
39
46
  fastapi.Depends(manager) if private else None
40
47
  ),
41
48
  ) -> Dict[str, Union[str, int]]:
49
+ """
50
+ Return information about this API instance.
51
+ """
42
52
  from meerschaum import __version__ as version
43
53
  num_plugins = len(get_api_connector().get_plugins(debug=debug))
44
54
  num_users = len(get_api_connector().get_users(debug=debug))
@@ -50,6 +60,22 @@ def get_instance_info(
50
60
  'num_pipes': num_pipes,
51
61
  }
52
62
 
63
+
64
+ @app.get(endpoints['healthcheck'], tags=['Misc'])
65
+ def get_healtheck() -> Dict[str, Any]:
66
+ """
67
+ Return a success message to confirm this API is reachable.
68
+ """
69
+ conn = get_api_connector()
70
+ success = _wrap_retry_connect(
71
+ conn.meta,
72
+ max_retries = 1,
73
+ )
74
+ message = "Success" if success else "Failed to connect to instance connector."
75
+ status_code = 200 if success else 503
76
+ return JSONResponse({"success": success, "message": message}, status_code=status_code)
77
+
78
+
53
79
  if debug:
54
80
  @app.get('/id', tags=['Misc'])
55
81
  def get_ids(
@@ -45,12 +45,13 @@ def _config(
45
45
  if config is None or reload:
46
46
  with _locks['config']:
47
47
  config = {}
48
+
48
49
  if keys and keys[0] not in config:
49
50
  from meerschaum.config._sync import sync_files as _sync_files
50
51
  key_config = read_config(
51
- keys=[keys[0]],
52
- substitute=substitute,
53
- write_missing=write_missing,
52
+ keys = [keys[0]],
53
+ substitute = substitute,
54
+ write_missing = write_missing,
54
55
  )
55
56
  if keys[0] in key_config:
56
57
  config[keys[0]] = key_config[keys[0]]
@@ -232,7 +233,6 @@ def get_config(
232
233
  )
233
234
  )
234
235
  if patch and keys[0] != symlinks_key:
235
- # print("Updating configuration, please wait...")
236
236
  if write_missing:
237
237
  write_config(config, debug=debug)
238
238
 
@@ -71,7 +71,7 @@ def write_config(
71
71
  if directory is None:
72
72
  from meerschaum.config._paths import CONFIG_DIR_PATH
73
73
  directory = CONFIG_DIR_PATH
74
- from meerschaum.config.static import _static_config
74
+ from meerschaum.config.static import STATIC_CONFIG
75
75
  from meerschaum.config._default import default_header_comment
76
76
  from meerschaum.config._patch import apply_patch_to_config
77
77
  from meerschaum.config._read_config import get_keyfile_path
@@ -84,14 +84,14 @@ def write_config(
84
84
  cf = _config()
85
85
  config_dict = cf
86
86
 
87
- default_filetype = _static_config()['config']['default_filetype']
87
+ default_filetype = STATIC_CONFIG['config']['default_filetype']
88
88
  filetype_dumpers = {
89
89
  'yml' : yaml.dump,
90
90
  'yaml' : yaml.dump,
91
91
  'json' : json.dump,
92
92
  }
93
93
 
94
- symlinks_key = _static_config()['config']['symlinks_key']
94
+ symlinks_key = STATIC_CONFIG['config']['symlinks_key']
95
95
  symlinks = config_dict.pop(symlinks_key) if symlinks_key in config_dict else {}
96
96
  config_dict = apply_patch_to_config(config_dict, symlinks)
97
97
 
@@ -148,27 +148,17 @@ def write_config(
148
148
  return True
149
149
 
150
150
  def general_write_yaml_config(
151
- files : Optional[Dict[str, pathlib.Path]] = None,
152
- debug : bool = False
151
+ files: Optional[Dict[pathlib.Path, Dict[str, Any]]] = None,
152
+ debug: bool = False
153
153
  ):
154
- """Write configuration dictionaries to file paths with optional headers.
155
-
156
- files : dict
157
- Dictionary of paths -> dict or tuple of format (dict, header).
158
- If item is a tuple, the header will be written at the top of the file.
154
+ """
155
+ Write configuration dictionaries to file paths with optional headers.
159
156
 
160
157
  Parameters
161
158
  ----------
162
- files : Optional[Dict[str :
163
-
164
- pathlib.Path]] :
165
- (Default value = None)
166
- debug : bool :
167
- (Default value = False)
168
-
169
- Returns
170
- -------
171
-
159
+ files: Optional[Dict[str, pathlib.Path]], default None
160
+ Dictionary of paths -> dict or tuple of format (dict, header).
161
+ If item is a tuple, the header will be written at the top of the file.
172
162
  """
173
163
 
174
164
  from meerschaum.utils.debug import dprint
@@ -46,7 +46,7 @@ def read_config(
46
46
  from meerschaum.utils.packages import attempt_import
47
47
  from meerschaum.utils.yaml import yaml, _yaml
48
48
  from meerschaum.config._paths import CONFIG_DIR_PATH
49
- from meerschaum.config.static import _static_config
49
+ from meerschaum.config.static import STATIC_CONFIG
50
50
  from meerschaum.config._patch import apply_patch_to_config
51
51
  if directory is None:
52
52
  directory = CONFIG_DIR_PATH
@@ -57,11 +57,11 @@ def read_config(
57
57
  return default_config
58
58
 
59
59
  ### Each key corresponds to a YAML or JSON file.
60
- symlinks_key = _static_config()['config']['symlinks_key']
60
+ symlinks_key = STATIC_CONFIG['config']['symlinks_key']
61
61
  config = {}
62
62
  config_to_write = {}
63
63
 
64
- default_filetype = _static_config()['config']['default_filetype']
64
+ default_filetype = STATIC_CONFIG['config']['default_filetype']
65
65
  filetype_loaders = {
66
66
  'yml' : yaml.load,
67
67
  'yaml' : yaml.load,
@@ -187,7 +187,6 @@ def read_config(
187
187
  print(f"Unable to parse {filename}!")
188
188
  import traceback
189
189
  traceback.print_exc()
190
- # print(e)
191
190
  input(f"Press [Enter] to open '{filename}' and fix formatting errors.")
192
191
  from meerschaum.utils.misc import edit_file
193
192
  edit_file(filepath)
@@ -363,8 +362,8 @@ def search_and_substitute_config(
363
362
  s[_keys[-1]] = _pattern
364
363
 
365
364
  from meerschaum.config._patch import apply_patch_to_config
366
- from meerschaum.config.static import _static_config
367
- symlinks_key = _static_config()['config']['symlinks_key']
365
+ from meerschaum.config.static import STATIC_CONFIG
366
+ symlinks_key = STATIC_CONFIG['config']['symlinks_key']
368
367
  if symlinks_key not in parsed_config:
369
368
  parsed_config[symlinks_key] = {}
370
369
  parsed_config[symlinks_key] = apply_patch_to_config(parsed_config[symlinks_key], symlinks)
@@ -403,16 +402,16 @@ def get_keyfile_path(
403
402
  os.path.join(
404
403
  directory,
405
404
  read_config(
406
- keys=[key],
407
- with_filenames=True,
408
- write_missing=False,
409
- substitute=False,
405
+ keys = [key],
406
+ with_filenames = True,
407
+ write_missing = False,
408
+ substitute = False,
410
409
  )[1][0]
411
410
  )
412
411
  )
413
412
  except IndexError as e:
414
413
  if create_new:
415
- from meerschaum.config.static import _static_config
416
- default_filetype = _static_config()['config']['default_filetype']
414
+ from meerschaum.config.static import STATIC_CONFIG
415
+ default_filetype = STATIC_CONFIG['config']['default_filetype']
417
416
  return pathlib.Path(os.path.join(directory, key + '.' + default_filetype))
418
417
  return None
@@ -10,7 +10,6 @@ from __future__ import annotations
10
10
  from meerschaum.utils.typing import Optional, List, Tuple
11
11
 
12
12
  def sync_yaml_configs(
13
- config_path: pathlib.Path,
14
13
  keys: List[str],
15
14
  sub_path: pathlib.Path,
16
15
  substitute: bool = True,
@@ -19,46 +18,24 @@ def sync_yaml_configs(
19
18
  ) -> None:
20
19
  """Synchronize sub-configuration with main configuration file.
21
20
 
22
- NOTE: This function might need refactoring to work better with the new
23
- `read_config` system.
24
-
25
21
  Parameters
26
22
  ----------
27
- config_path :
28
- Not sure if this is necessary.
29
- keys :
23
+ keys: List[str]
30
24
  The config keys to read via `get_config()`.
31
- sub_path :
25
+
26
+ sub_path: pathlib.Path
32
27
  The derivative file to write.
33
- substitute :
28
+
29
+ substitute: bool, default True
34
30
  If `True`, parse `MRSM{}` syntax and substitute values.
35
31
  See `get_config()` for more information.
36
- Defaults to `True`.
37
- permissions :
32
+
33
+ permissions: Optional[int], default None
38
34
  If not `None`, set permissions of the derivative file.
39
- Defaults to `None`.
40
- replace_tuples :
35
+
36
+ replace_tuples: Optional[List[Tuple[str]]], default None
41
37
  If provided, iterate through a list of tuples,
42
38
  replacing the old string (index 0) with the new string (index 1).
43
- Defaults to `None`.
44
- config_path: pathlib.Path :
45
-
46
- keys: List[str] :
47
-
48
- sub_path: pathlib.Path :
49
-
50
- substitute: bool :
51
- (Default value = True)
52
- permissions: Optional[int] :
53
- (Default value = None)
54
- replace_tuples: Optional[List[Tuple[str :
55
-
56
- str]]] :
57
- (Default value = None)
58
-
59
- Returns
60
- -------
61
-
62
39
  """
63
40
  import os, sys
64
41
  try:
@@ -68,22 +45,12 @@ def sync_yaml_configs(
68
45
  from meerschaum.config._patch import apply_patch_to_config
69
46
  import meerschaum.config
70
47
  from meerschaum.utils.packages import reload_package
71
- from meerschaum.config._read_config import search_and_substitute_config
72
- if not os.path.isfile(config_path) or not os.path.isfile(sub_path):
73
- return
74
-
75
- def _read_config(path):
76
- """Read YAML file with header comment
77
-
78
- Parameters
79
- ----------
80
- path :
81
-
48
+ from meerschaum.config._read_config import search_and_substitute_config, get_keyfile_path
82
49
 
83
- Returns
84
- -------
85
-
86
- """
50
+ def _read_yaml_config(path):
51
+ """Read YAML file with header comment."""
52
+ if not path.exists():
53
+ return "", {}
87
54
  header_comment = ""
88
55
  with open(path, 'r') as f:
89
56
  if _yaml is not None:
@@ -98,58 +65,60 @@ def sync_yaml_configs(
98
65
  header_comment += line
99
66
  return header_comment, config
100
67
 
101
- config_header, config = _read_config(config_path)
102
- sub_header, sub_config = _read_config(sub_path)
103
-
104
68
  from meerschaum.config import get_config
69
+ config_path = get_keyfile_path(keys[0], create_new=True)
105
70
  c = get_config(*keys, substitute=substitute, sync_files=False)
71
+
72
+ config_header, config = _read_yaml_config(config_path)
73
+ sub_header, sub_config = _read_yaml_config(sub_path)
74
+
106
75
  if substitute:
107
76
  sub_config = search_and_substitute_config(sub_config)
108
77
 
109
- if c != sub_config:
110
- config_time = os.path.getmtime(config_path)
111
- sub_time = os.path.getmtime(sub_path)
112
-
113
- sub_config = c
114
- new_config_text = yaml.dump(c, sort_keys=False)
115
- if replace_tuples:
116
- for replace_tuple in replace_tuples:
117
- new_config_text = new_config_text.replace(replace_tuple[0], replace_tuple[1])
118
- new_header = sub_header
119
- new_path = sub_path
120
-
121
- ### write changes
122
- with open(new_path, 'w+') as f:
123
- f.write(new_header)
124
- f.write(new_config_text)
78
+ sub_config = c
79
+ new_config_text = yaml.dump(c, sort_keys=False)
80
+ if replace_tuples:
81
+ for replace_tuple in replace_tuples:
82
+ new_config_text = new_config_text.replace(replace_tuple[0], replace_tuple[1])
83
+ new_header = sub_header
84
+ new_path = sub_path
85
+
86
+ ### write changes
87
+ with open(new_path, 'w+') as f:
88
+ f.write(new_header)
89
+ f.write(new_config_text)
125
90
  if permissions is not None:
126
91
  os.chmod(new_path, permissions)
127
92
 
128
93
  def sync_files(keys: Optional[List[str]] = None):
129
94
  if keys is None:
130
95
  keys = []
96
+
131
97
  def _stack():
132
98
  import os
133
- from meerschaum.config._paths import CONFIG_DIR_PATH, STACK_ENV_PATH, STACK_COMPOSE_PATH
134
- from meerschaum.config._paths import STACK_COMPOSE_FILENAME, STACK_ENV_FILENAME
135
- from meerschaum.config._paths import GRAFANA_DATASOURCE_PATH, GRAFANA_DASHBOARD_PATH
136
- from meerschaum.config._paths import MOSQUITTO_CONFIG_PATH
99
+ from meerschaum.config._paths import (
100
+ CONFIG_DIR_PATH,
101
+ STACK_ENV_PATH,
102
+ STACK_COMPOSE_PATH,
103
+ STACK_COMPOSE_FILENAME,
104
+ STACK_ENV_FILENAME,
105
+ GRAFANA_DATASOURCE_PATH,
106
+ GRAFANA_DASHBOARD_PATH,
107
+ )
108
+ from meerschaum.config.static import STATIC_CONFIG
137
109
 
138
110
  sync_yaml_configs(
139
- CONFIG_DIR_PATH / 'stack.yaml',
140
111
  ['stack', STACK_COMPOSE_FILENAME],
141
112
  STACK_COMPOSE_PATH,
142
113
  substitute = True,
143
- replace_tuples = [('$', '$$')],
114
+ replace_tuples = [('$', '$$'), ('<DOLLAR>', '$')],
144
115
  )
145
116
  sync_yaml_configs(
146
- CONFIG_DIR_PATH / 'stack.yaml',
147
117
  ['stack', 'grafana', 'datasource'],
148
118
  GRAFANA_DATASOURCE_PATH,
149
119
  substitute = True,
150
120
  )
151
121
  sync_yaml_configs(
152
- CONFIG_DIR_PATH / 'stack.yaml',
153
122
  ['stack', 'grafana', 'dashboard'],
154
123
  GRAFANA_DASHBOARD_PATH,
155
124
  substitute = True,
@@ -157,7 +126,7 @@ def sync_files(keys: Optional[List[str]] = None):
157
126
 
158
127
 
159
128
  key_functions = {
160
- 'stack' : _stack,
129
+ 'stack': _stack,
161
130
  }
162
131
  if keys is None:
163
132
  keys = list(key_functions.keys())
@@ -2,4 +2,4 @@
2
2
  Specify the Meerschaum release version.
3
3
  """
4
4
 
5
- __version__ = "1.7.1"
5
+ __version__ = "1.7.3"
@@ -29,11 +29,11 @@ db_base = "MRSM{meerschaum:connectors:sql:main:database}"
29
29
  db_hostname = "db"
30
30
  db_host = 'MRSM{stack:' + str(STACK_COMPOSE_FILENAME) + ':services:db:hostname}'
31
31
  api_port = "MRSM{meerschaum:connectors:api:main:port}"
32
- api_host = "meerschaum_api"
32
+ api_host = "api"
33
33
 
34
34
  env_dict = {
35
35
  'COMPOSE_PROJECT_NAME' : 'mrsm',
36
- 'TIMESCALEDB_VERSION' : 'latest-pg14-oss',
36
+ 'TIMESCALEDB_VERSION' : 'latest-pg15-oss',
37
37
  'POSTGRES_USER' : f'{db_user}',
38
38
  'POSTGRES_PASSWORD' : f'{db_pass}',
39
39
  'POSTGRES_DB' : f'{db_base}',
@@ -54,13 +54,25 @@ env_dict['MEERSCHAUM_API_CONFIG'] = json.dumps(
54
54
  '"MRSM{!meerschaum}"', 'MRSM{!meerschaum}',
55
55
  )
56
56
 
57
+ volumes = {
58
+ 'api_root': '/meerschaum',
59
+ 'meerschaum_db_data': '/var/lib/postgresql/data',
60
+ 'grafana_storage': '/var/lib/grafana',
61
+ }
62
+ networks = {
63
+ 'frontend': None,
64
+ 'backend': None,
65
+ }
57
66
  env_dict['MEERSCHAUM_API_PATCH'] = json.dumps(
58
67
  {
59
- 'meerschaum' : {
60
- 'connectors' : {
61
- 'sql' : {
62
- 'main' : {
63
- 'host' : db_host,
68
+ 'meerschaum': {
69
+ 'connectors': {
70
+ 'sql': {
71
+ 'main': {
72
+ 'host': db_host,
73
+ },
74
+ 'local': {
75
+ 'database': volumes['api_root'] + '/sqlite/mrsm_local.db'
64
76
  },
65
77
  },
66
78
  },
@@ -82,15 +94,6 @@ compose_header = """
82
94
  ##############################################################
83
95
  """
84
96
 
85
- volumes = {
86
- 'api_root' : '/meerschaum',
87
- 'meerschaum_db_data' : '/var/lib/postgresql/data',
88
- 'grafana_storage' : '/var/lib/grafana',
89
- }
90
- networks = {
91
- 'frontend' : None,
92
- 'backend' : None,
93
- }
94
97
 
95
98
  default_docker_compose_config = {
96
99
  'version': '3.9',
@@ -98,16 +101,15 @@ default_docker_compose_config = {
98
101
  'db': {
99
102
  'environment': {
100
103
  'TIMESCALEDB_TELEMETRY': 'off',
101
- 'POSTGRES_USER': '$POSTGRES_USER',
102
- 'POSTGRES_DB': '$POSTGRES_DB',
103
- 'POSTGRES_PASSWORD': '$POSTGRES_PASSWORD',
104
+ 'POSTGRES_USER': '<DOLLAR>POSTGRES_USER',
105
+ 'POSTGRES_DB': '<DOLLAR>POSTGRES_DB',
106
+ 'POSTGRES_PASSWORD': '<DOLLAR>POSTGRES_PASSWORD',
104
107
  'ALLOW_IP_RANGE': env_dict['ALLOW_IP_RANGE'],
105
108
  },
106
109
  'command': 'postgres -c max_connections=1000 -c shared_buffers=1024MB',
107
110
  'healthcheck': {
108
111
  'test': [
109
- 'CMD-SHELL', 'pg_isready',
110
- '-U', '$POSTGRES_USER', '-d', '$POSTGRES_DB',
112
+ 'CMD-SHELL', 'pg_isready -d <DOLLAR>POSTGRES_DB -U <DOLLAR>POSTGRES_USER',
111
113
  ],
112
114
  'interval': '5s',
113
115
  'timeout': '3s',
@@ -136,6 +138,14 @@ default_docker_compose_config = {
136
138
  'backend',
137
139
  ],
138
140
  'command': f'start api --production --port {api_port}',
141
+ 'healthcheck': {
142
+ 'test': [
143
+ 'CMD', 'curl', '--fail', f'http://localhost:{api_port}/healthcheck',
144
+ ],
145
+ 'interval': '5s',
146
+ 'timeout': '3s',
147
+ 'retries': 3
148
+ },
139
149
  'environment': {
140
150
  'MRSM_CONFIG': env_dict['MEERSCHAUM_API_CONFIG'],
141
151
  'MRSM_PATCH': env_dict['MEERSCHAUM_API_PATCH'],
@@ -8,12 +8,13 @@ Insert non-user-editable configuration files here.
8
8
 
9
9
  import os
10
10
  import uuid
11
+ from typing import Dict, Any
11
12
  from meerschaum.utils.misc import generate_password
12
13
 
13
14
  __all__ = ['STATIC_CONFIG']
14
15
 
15
- SERVER_ID = os.environ.get('MRSM_SERVER_ID', generate_password(6))
16
- STATIC_CONFIG = {
16
+ SERVER_ID: str = os.environ.get('MRSM_SERVER_ID', generate_password(6))
17
+ STATIC_CONFIG: Dict[str, Any] = {
17
18
  'api': {
18
19
  'endpoints': {
19
20
  'index': '/',
@@ -32,6 +33,7 @@ STATIC_CONFIG = {
32
33
  'webterm': '/webterm',
33
34
  'webterm_websocket': '/websocket',
34
35
  'info': '/info',
36
+ 'healthcheck': '/healthcheck',
35
37
  },
36
38
  'oauth': {
37
39
  'token_expires_minutes': 720,
@@ -83,6 +85,9 @@ STATIC_CONFIG = {
83
85
  'connectors': {
84
86
  'default_label': 'main',
85
87
  },
88
+ 'stack': {
89
+ 'dollar_standin': '<DOLLAR>', ### Temporary replacement for docker-compose.yaml.
90
+ },
86
91
  'users': {
87
92
  'password_hash': {
88
93
  'schemes': [
@@ -50,7 +50,7 @@ def do_action(
50
50
  """
51
51
  import sys, json
52
52
  from meerschaum.utils.debug import dprint
53
- from meerschaum.config.static import _static_config
53
+ from meerschaum.config.static import STATIC_CONFIG
54
54
  from meerschaum.utils.misc import json_serialize_datetime
55
55
  if action is None:
56
56
  action = []
@@ -67,7 +67,7 @@ def do_action(
67
67
 
68
68
  root_action = json_dict['action'][0]
69
69
  del json_dict['action'][0]
70
- r_url = f"{_static_config()['api']['endpoints']['actions']}/{root_action}"
70
+ r_url = f"{STATIC_CONFIG['api']['endpoints']['actions']}/{root_action}"
71
71
 
72
72
  if debug:
73
73
  from meerschaum.utils.formatting import pprint
@@ -18,7 +18,7 @@ def login(
18
18
  """Log in and set the session token."""
19
19
  from meerschaum.utils.warnings import warn as _warn, info, error
20
20
  from meerschaum.core import User
21
- from meerschaum.config.static import _static_config
21
+ from meerschaum.config.static import STATIC_CONFIG
22
22
  import json, datetime
23
23
  try:
24
24
  login_data = {
@@ -28,7 +28,7 @@ def login(
28
28
  except AttributeError:
29
29
  return False, f"Please login with the command `login {self}`."
30
30
  response = self.post(
31
- _static_config()['api']['endpoints']['login'],
31
+ STATIC_CONFIG['api']['endpoints']['login'],
32
32
  data = login_data,
33
33
  use_token = False,
34
34
  debug = debug