vantage6 5.0.0a21__py3-none-any.whl → 5.0.0a26__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 vantage6 might be problematic. Click here for more details.

Files changed (39) hide show
  1. tests_cli/test_client_script.py +23 -0
  2. vantage6/cli/__build__ +1 -1
  3. vantage6/cli/algorithm/generate_algorithm_json.py +529 -0
  4. vantage6/cli/cli.py +25 -0
  5. vantage6/cli/common/start.py +220 -9
  6. vantage6/cli/common/stop.py +90 -0
  7. vantage6/cli/common/utils.py +8 -7
  8. vantage6/cli/config.py +260 -0
  9. vantage6/cli/configuration_manager.py +3 -11
  10. vantage6/cli/configuration_wizard.py +60 -101
  11. vantage6/cli/context/node.py +34 -45
  12. vantage6/cli/context/server.py +26 -0
  13. vantage6/cli/dev/create.py +78 -17
  14. vantage6/cli/dev/data/km_dataset.csv +2401 -0
  15. vantage6/cli/dev/remove.py +99 -98
  16. vantage6/cli/globals.py +20 -0
  17. vantage6/cli/node/new.py +4 -3
  18. vantage6/cli/node/remove.py +4 -2
  19. vantage6/cli/node/start.py +17 -20
  20. vantage6/cli/prometheus/monitoring_manager.py +146 -0
  21. vantage6/cli/prometheus/prometheus.yml +5 -0
  22. vantage6/cli/server/new.py +25 -6
  23. vantage6/cli/server/start.py +42 -212
  24. vantage6/cli/server/stop.py +35 -105
  25. vantage6/cli/template/algo_store_config.j2 +0 -1
  26. vantage6/cli/template/node_config.j2 +1 -1
  27. vantage6/cli/template/server_import_config.j2 +0 -2
  28. vantage6/cli/test/algo_test_scripts/algo_test_arguments.py +29 -0
  29. vantage6/cli/test/algo_test_scripts/algo_test_script.py +91 -0
  30. vantage6/cli/test/client_script.py +151 -0
  31. vantage6/cli/test/common/diagnostic_runner.py +2 -2
  32. vantage6/cli/use/context.py +46 -0
  33. vantage6/cli/use/namespace.py +55 -0
  34. vantage6/cli/utils.py +70 -4
  35. {vantage6-5.0.0a21.dist-info → vantage6-5.0.0a26.dist-info}/METADATA +5 -8
  36. {vantage6-5.0.0a21.dist-info → vantage6-5.0.0a26.dist-info}/RECORD +39 -27
  37. {vantage6-5.0.0a21.dist-info → vantage6-5.0.0a26.dist-info}/WHEEL +0 -0
  38. {vantage6-5.0.0a21.dist-info → vantage6-5.0.0a26.dist-info}/entry_points.txt +0 -0
  39. {vantage6-5.0.0a21.dist-info → vantage6-5.0.0a26.dist-info}/top_level.txt +0 -0
@@ -1,29 +1,41 @@
1
+ from __future__ import annotations
2
+
3
+ import enum
1
4
  import os
2
- from threading import Thread
5
+ import re
6
+ import subprocess
3
7
  import time
8
+ from os import PathLike
9
+ from pathlib import Path
10
+ from threading import Thread
11
+
4
12
  import docker
5
- import enum
13
+ from colorama import Fore, Style
6
14
  from docker.client import DockerClient
7
15
  from docker.models.containers import Container
8
- from colorama import Fore, Style
9
16
  from sqlalchemy.engine.url import make_url
10
17
 
11
18
  from vantage6.common import error, info, warning
12
19
  from vantage6.common.context import AppContext
20
+ from vantage6.common.docker.addons import check_docker_running, pull_image
13
21
  from vantage6.common.globals import (
22
+ APPNAME,
14
23
  DEFAULT_ALGO_STORE_IMAGE,
24
+ DEFAULT_CHART_REPO,
25
+ DEFAULT_DOCKER_REGISTRY,
15
26
  DEFAULT_NODE_IMAGE,
16
27
  DEFAULT_SERVER_IMAGE,
17
28
  DEFAULT_UI_IMAGE,
18
29
  InstanceType,
19
- APPNAME,
20
- DEFAULT_DOCKER_REGISTRY,
21
30
  )
22
- from vantage6.common.docker.addons import check_docker_running, pull_image
23
- from vantage6.cli.context import AlgorithmStoreContext, ServerContext
31
+
24
32
  from vantage6.cli.common.utils import print_log_worker
25
- from vantage6.cli.utils import check_config_name_allowed
26
- from vantage6.cli.globals import ServerGlobals, AlgoStoreGlobals
33
+ from vantage6.cli.context import AlgorithmStoreContext, ServerContext
34
+ from vantage6.cli.globals import AlgoStoreGlobals, ServerGlobals
35
+ from vantage6.cli.utils import (
36
+ validate_input_cmd_args,
37
+ check_config_name_allowed,
38
+ )
27
39
 
28
40
 
29
41
  def check_for_start(ctx: AppContext, type_: InstanceType) -> DockerClient:
@@ -279,6 +291,8 @@ def mount_database(
279
291
  return mount, environment_vars
280
292
 
281
293
 
294
+ # TODO v5+ remove this function, it is replaced by the `attach_logs` function in
295
+ # `vantage6.cli.common.utils`
282
296
  def attach_logs(container: Container, type_: InstanceType) -> None:
283
297
  """
284
298
  Attach container logs to the console if specified.
@@ -304,3 +318,200 @@ def attach_logs(container: Container, type_: InstanceType) -> None:
304
318
  f"with {Fore.RED}v6 {type_} stop{Style.RESET_ALL}"
305
319
  )
306
320
  exit(0)
321
+
322
+
323
+ def helm_install(
324
+ release_name: str,
325
+ chart_name: str,
326
+ values_file: str | PathLike | None = None,
327
+ context: str | None = None,
328
+ namespace: str | None = None,
329
+ ) -> None:
330
+ """
331
+ Manage the `helm install` command.
332
+
333
+ Parameters
334
+ ----------
335
+ release_name : str
336
+ The name of the Helm release.
337
+ chart_name : str
338
+ The name of the Helm chart.
339
+ values_file : str, optional
340
+ A single values file to use with the `-f` flag.
341
+ context : str, optional
342
+ The Kubernetes context to use.
343
+ namespace : str, optional
344
+ The Kubernetes namespace to use.
345
+ """
346
+ # Input validation
347
+ validate_input_cmd_args(release_name, "release name")
348
+ validate_input_cmd_args(chart_name, "chart name")
349
+
350
+ values_file = Path(values_file) if values_file else None
351
+ if values_file and not values_file.is_file():
352
+ error(f"Helm chart values file does not exist: {values_file}")
353
+ return
354
+
355
+ validate_input_cmd_args(context, "context name", allow_none=True)
356
+ validate_input_cmd_args(namespace, "namespace name", allow_none=True)
357
+
358
+ # Create the command
359
+ command = [
360
+ "helm",
361
+ "install",
362
+ release_name,
363
+ chart_name,
364
+ "--repo",
365
+ DEFAULT_CHART_REPO,
366
+ "--devel", # ensure using latest version including pre-releases
367
+ ]
368
+
369
+ if values_file:
370
+ command.extend(["-f", str(values_file)])
371
+
372
+ if context:
373
+ command.extend(["--kube-context", context])
374
+
375
+ if namespace:
376
+ command.extend(["--namespace", namespace])
377
+
378
+ try:
379
+ subprocess.run(
380
+ command,
381
+ stdout=subprocess.DEVNULL,
382
+ check=True,
383
+ )
384
+ info(
385
+ f"Successfully installed release '{release_name}' using chart '{chart_name}'."
386
+ )
387
+ except subprocess.CalledProcessError as e:
388
+ error(f"Failed to install release '{release_name}': {e.stderr}")
389
+ except FileNotFoundError:
390
+ error(
391
+ "Helm command not found. Please ensure Helm is installed and available in the PATH."
392
+ )
393
+
394
+
395
+ def start_port_forward(
396
+ service_name: str,
397
+ service_port: int,
398
+ port: int,
399
+ ip: str | None,
400
+ context: str | None = None,
401
+ namespace: str | None = None,
402
+ ) -> None:
403
+ """
404
+ Port forward a kubernetes service.
405
+
406
+ Parameters
407
+ ----------
408
+ service_name : str
409
+ The name of the Kubernetes service to port forward.
410
+ service_port : int
411
+ The port on the service to forward.
412
+ port : int
413
+ The port to listen on.
414
+ ip : str | None
415
+ The IP address to listen on. If None, defaults to localhost.
416
+ context : str | None
417
+ The Kubernetes context to use.
418
+ namespace : str | None
419
+ The Kubernetes namespace to use.
420
+ """
421
+ # Input validation
422
+ validate_input_cmd_args(service_name, "service name")
423
+ if not isinstance(service_port, int) or service_port <= 0:
424
+ error(f"Invalid service port: {service_port}. Must be a positive integer.")
425
+ return
426
+
427
+ if not isinstance(port, int) or port <= 0:
428
+ error(f"Invalid local port: {port}. Must be a positive integer.")
429
+ return
430
+
431
+ if ip and not re.match(
432
+ r"^(localhost|[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})$", ip
433
+ ):
434
+ error(f"Invalid IP address: {ip}. Must be a valid IPv4 address or 'localhost'.")
435
+ return
436
+
437
+ validate_input_cmd_args(context, "context name", allow_none=True)
438
+ validate_input_cmd_args(namespace, "namespace name", allow_none=True)
439
+
440
+ # Check if the service is ready before starting port forwarding
441
+ info(f"Waiting for service '{service_name}' to become ready...")
442
+ start_time = time.time()
443
+ timeout = 300 # seconds
444
+ while time.time() - start_time < timeout:
445
+ try:
446
+ result = (
447
+ subprocess.check_output(
448
+ [
449
+ "kubectl",
450
+ "get",
451
+ "endpoints",
452
+ service_name,
453
+ "-o",
454
+ "jsonpath={.subsets[*].addresses[*].ip}",
455
+ ]
456
+ )
457
+ .decode()
458
+ .strip()
459
+ )
460
+
461
+ if result:
462
+ info(f"Service '{service_name}' is ready.")
463
+ break
464
+ except subprocess.CalledProcessError:
465
+ pass # ignore and retry
466
+
467
+ time.sleep(2)
468
+ else:
469
+ error(
470
+ f"Timeout: Service '{service_name}' has no ready endpoints after {timeout} seconds."
471
+ )
472
+ return
473
+
474
+ # Create the port forwarding command
475
+ if not ip:
476
+ ip = "localhost"
477
+
478
+ command = [
479
+ "kubectl",
480
+ "port-forward",
481
+ "--address",
482
+ ip,
483
+ f"service/{service_name}",
484
+ f"{port}:{service_port}",
485
+ ]
486
+
487
+ if context:
488
+ command.extend(["--context", context])
489
+
490
+ if namespace:
491
+ command.extend(["--namespace", namespace])
492
+
493
+ # Start the port forwarding process
494
+ try:
495
+ process = subprocess.Popen(
496
+ command,
497
+ stdout=subprocess.DEVNULL,
498
+ stderr=subprocess.PIPE,
499
+ start_new_session=True, # Start in new session to detach from parent
500
+ )
501
+
502
+ # Give the process a moment to start and check if it's still running
503
+ time.sleep(1)
504
+ if process.poll() is not None:
505
+ # Process has already terminated
506
+ e = process.stderr.read().decode() if process.stderr else "Unknown error"
507
+ error(f"Failed to start port forwarding: {e}")
508
+ return
509
+
510
+ info(
511
+ f"Port forwarding started: {ip}:{port} -> {service_name}:{service_port} "
512
+ f"(PID: {str(process.pid)})"
513
+ )
514
+ return
515
+ except Exception as e:
516
+ error(f"Failed to start port forwarding: {e}")
517
+ return
@@ -0,0 +1,90 @@
1
+ from __future__ import annotations
2
+
3
+ import subprocess
4
+
5
+
6
+ from vantage6.common import error, info, warning
7
+ from vantage6.cli.utils import validate_input_cmd_args
8
+
9
+
10
+ def stop_port_forward(service_name: str) -> None:
11
+ """
12
+ Stop the port forwarding process for a given service name.
13
+
14
+ Parameters
15
+ ----------
16
+ service_name : str
17
+ The name of the service whose port forwarding process should be terminated.
18
+ """
19
+ # Input validation
20
+ validate_input_cmd_args(service_name, "service name")
21
+
22
+ try:
23
+ # Find the process ID (PID) of the port forwarding command
24
+ result = subprocess.run(
25
+ ["pgrep", "-f", f"kubectl port-forward.*{service_name}"],
26
+ check=True,
27
+ text=True,
28
+ capture_output=True,
29
+ )
30
+ pids = result.stdout.strip().splitlines()
31
+
32
+ if not pids:
33
+ warning(f"No port forwarding process found for service '{service_name}'.")
34
+ return
35
+
36
+ for pid in pids:
37
+ subprocess.run(["kill", "-9", pid], check=True)
38
+ info(
39
+ f"Terminated port forwarding process for service '{service_name}' "
40
+ f"(PID: {pid})"
41
+ )
42
+ except subprocess.CalledProcessError as e:
43
+ error(f"Failed to terminate port forwarding: {e}")
44
+
45
+
46
+ def helm_uninstall(
47
+ release_name: str,
48
+ context: str | None = None,
49
+ namespace: str | None = None,
50
+ ) -> None:
51
+ """
52
+ Manage the `helm uninstall` command.
53
+
54
+ Parameters
55
+ ----------
56
+ release_name : str
57
+ The name of the Helm release to uninstall.
58
+ context : str, optional
59
+ The Kubernetes context to use.
60
+ namespace : str, optional
61
+ The Kubernetes namespace to use.
62
+ """
63
+ # Input validation
64
+ validate_input_cmd_args(release_name, "release name")
65
+ validate_input_cmd_args(context, "context name", allow_none=True)
66
+ validate_input_cmd_args(namespace, "namespace name", allow_none=True)
67
+
68
+ # Create the command
69
+ command = ["helm", "uninstall", release_name]
70
+
71
+ if context:
72
+ command.extend(["--kube-context", context])
73
+
74
+ if namespace:
75
+ command.extend(["--namespace", namespace])
76
+
77
+ try:
78
+ subprocess.run(
79
+ command,
80
+ stdout=subprocess.DEVNULL,
81
+ check=True,
82
+ )
83
+ info(f"Successfully uninstalled release '{release_name}'.")
84
+ except subprocess.CalledProcessError as e:
85
+ error(f"Failed to uninstall release '{release_name}': {e.stderr}")
86
+ except FileNotFoundError:
87
+ error(
88
+ "Helm command not found. Please ensure Helm is installed and available in "
89
+ "the PATH."
90
+ )
@@ -1,14 +1,15 @@
1
1
  import enum
2
- import questionary as q
3
- from colorama import Fore, Style
4
- import click
2
+ from subprocess import Popen
5
3
  from typing import Iterable
4
+
5
+ import click
6
6
  import docker
7
- from subprocess import Popen
7
+ import questionary as q
8
+ from colorama import Fore, Style
8
9
 
10
+ from vantage6.common import error, warning
11
+ from vantage6.common.globals import APPNAME, STRING_ENCODING, InstanceType
9
12
 
10
- from vantage6.common import warning, error
11
- from vantage6.common.globals import APPNAME, InstanceType, STRING_ENCODING
12
13
  from vantage6.cli.context import select_context_class
13
14
 
14
15
 
@@ -177,6 +178,6 @@ def attach_logs(*labels: list[str]) -> None:
177
178
  labels : list[str]
178
179
  The labels to attach to
179
180
  """
180
- command = ["devspace", "logs", "--follow", "--label-selector", ",".join(labels)]
181
+ command = ["kubectl", "logs", "--follow", "--selector", ",".join(labels)]
181
182
  process = Popen(command, stdout=None, stderr=None)
182
183
  process.wait()
vantage6/cli/config.py ADDED
@@ -0,0 +1,260 @@
1
+ import os
2
+ from os import PathLike
3
+ from pathlib import Path
4
+
5
+ import questionary
6
+ import yaml
7
+ from colorama import Fore, Style
8
+ from kubernetes import config
9
+
10
+ from vantage6.common import info, warning
11
+
12
+ from vantage6.cli.globals import (
13
+ DEFAULT_CLI_CONFIG_FILE,
14
+ )
15
+
16
+
17
+ class CliConfig:
18
+ """
19
+ A class to manage CLI configuration for Kubernetes context and namespace.
20
+
21
+ The CLI configuration is stored in a `config.yaml` file located at the path
22
+ specified by `DEFAULT_CLI_CONFIG_FILE`.
23
+
24
+ The `config.yaml` file has the following structure:
25
+
26
+ ```yaml
27
+ kube:
28
+ last_context: <last_used_k8s_context>
29
+ last_namespace: <last_used_k8s_namespace>
30
+ ```
31
+
32
+ Attributes
33
+ ----------
34
+ config_path : PathLike
35
+ Path to the configuration file.
36
+ _cached_config : dict or None
37
+ Cached configuration data.
38
+ _cached_mtime : float or None
39
+ Last modification time of the configuration file.
40
+ """
41
+
42
+ def __init__(self, config_path: str | PathLike = DEFAULT_CLI_CONFIG_FILE) -> None:
43
+ """
44
+ Initialize the CliConfig object.
45
+
46
+ Parameters
47
+ ----------
48
+ config_path : str or PathLike, optional
49
+ Path to the configuration file.
50
+ """
51
+ self.config_path: PathLike = Path(config_path)
52
+ self._cached_config: dict | None = None
53
+ self._cached_mtime: float | None = None
54
+
55
+ def _load_config(self) -> dict:
56
+ """
57
+ Load the configuration from the file.
58
+
59
+ Returns
60
+ -------
61
+ dict
62
+ The loaded configuration data.
63
+ """
64
+ if self.config_path.exists():
65
+ with open(self.config_path, "r") as config_file:
66
+ return yaml.safe_load(config_file) or {}
67
+ return {}
68
+
69
+ def _save_config(self, config: dict) -> None:
70
+ """
71
+ Save the configuration to the file.
72
+
73
+ Parameters
74
+ ----------
75
+ config : dict
76
+ The configuration data to save.
77
+ """
78
+ self.config_path.parent.mkdir(parents=True, exist_ok=True)
79
+ with open(self.config_path, "w") as config_file:
80
+ yaml.dump(config, config_file)
81
+
82
+ def _reload_cache_lazy(self) -> None:
83
+ """
84
+ Reload the configuration cache if the file has been modified.
85
+ """
86
+ if self.config_path.exists():
87
+ mtime = os.path.getmtime(self.config_path)
88
+ if self._cached_mtime != mtime:
89
+ self._cached_config = self._load_config()
90
+ self._cached_mtime = mtime
91
+ else:
92
+ self._cached_config = {}
93
+ self._cached_mtime = None
94
+
95
+ def get_last_context(self) -> str | None:
96
+ """
97
+ Get the last used Kubernetes context.
98
+
99
+ Returns
100
+ -------
101
+ str or None
102
+ The last used Kubernetes context, or None if not set.
103
+ """
104
+ self._reload_cache_lazy()
105
+ return self._cached_config.get("kube", {}).get("last_context")
106
+
107
+ def set_last_context(self, context: str) -> None:
108
+ """
109
+ Set the Kubernetes context.
110
+
111
+ Parameters
112
+ ----------
113
+ context : str
114
+ The Kubernetes context to set.
115
+ """
116
+ config = self._load_config()
117
+ if "kube" not in config:
118
+ config["kube"] = {}
119
+
120
+ if config["kube"].get("last_context") != context:
121
+ config["kube"]["last_context"] = context
122
+ self._save_config(config)
123
+ self._reload_cache_lazy()
124
+
125
+ def get_last_namespace(self) -> str | None:
126
+ """
127
+ Get the last used Kubernetes namespace.
128
+
129
+ Returns
130
+ -------
131
+ str or None
132
+ The last used Kubernetes namespace, or None if not set.
133
+ """
134
+ self._reload_cache_lazy()
135
+ return self._cached_config.get("kube", {}).get("last_namespace")
136
+
137
+ def set_last_namespace(self, namespace: str) -> None:
138
+ """
139
+ Set the Kubernetes namespace.
140
+
141
+ Parameters
142
+ ----------
143
+ namespace : str
144
+ The Kubernetes namespace to set.
145
+ """
146
+ config = self._load_config()
147
+ if "kube" not in config:
148
+ config["kube"] = {}
149
+
150
+ if config["kube"].get("last_namespace") != namespace:
151
+ config["kube"]["last_namespace"] = namespace
152
+ self._save_config(config)
153
+ self._reload_cache_lazy()
154
+
155
+ def remove_kube(self) -> None:
156
+ """
157
+ Remove the last used context and namespace.
158
+ """
159
+ if self.config_path.exists():
160
+ config = self._load_config()
161
+ if "kube" in config:
162
+ del config["kube"]
163
+ self._save_config(config)
164
+ self._reload_cache_lazy()
165
+
166
+ def get_active_settings(
167
+ self,
168
+ context: str | None,
169
+ namespace: str | None,
170
+ ) -> tuple[str, str]:
171
+ """
172
+ Get the active Kubernetes context and namespace.
173
+
174
+ Parameters
175
+ ----------
176
+ context : str or None
177
+ The Kubernetes context to use.
178
+ namespace : str or None
179
+ The Kubernetes namespace to use.
180
+
181
+ Returns
182
+ -------
183
+ tuple[str, str]
184
+ A tuple containing the active context and namespace.
185
+ """
186
+ if not context:
187
+ _, active_context = config.list_kube_config_contexts()
188
+ context = active_context["name"]
189
+
190
+ if not namespace:
191
+ namespace = active_context["context"].get("namespace", "default")
192
+
193
+ return context, namespace
194
+
195
+ def compare_changes_config(
196
+ self,
197
+ context: str | None = None,
198
+ namespace: str | None = None,
199
+ ) -> tuple[str, str]:
200
+ """
201
+ Compare active settings with last used settings.
202
+
203
+ Parameters
204
+ ----------
205
+ context : str or None, optional
206
+ The Kubernetes context to use.
207
+ namespace : str or None, optional
208
+ The Kubernetes namespace to use.
209
+
210
+ Returns
211
+ -------
212
+ tuple[str, str]
213
+ A tuple containing the active context and namespace.
214
+ """
215
+
216
+ active_context, active_namespace = self.get_active_settings(context, namespace)
217
+ last_context = self.get_last_context()
218
+ last_namespace = self.get_last_namespace()
219
+
220
+ # compare context
221
+ if not last_context:
222
+ self.set_last_context(context=active_context)
223
+ elif last_context != active_context:
224
+ warning("Are you using the correct context?")
225
+ warning(f"Current context: {Fore.YELLOW}{active_context}{Style.RESET_ALL}")
226
+ warning(f"Last context: {Fore.YELLOW}{last_context}{Style.RESET_ALL}")
227
+
228
+ active_context = questionary.select(
229
+ "Which context do you want to use?",
230
+ choices=[active_context, last_context],
231
+ default=active_context,
232
+ ).ask()
233
+
234
+ if last_context != active_context:
235
+ self.set_last_context(context=active_context)
236
+
237
+ # compare namespace
238
+ if not last_namespace:
239
+ self.set_last_namespace(namespace=active_namespace)
240
+ elif last_namespace != active_namespace:
241
+ warning("Are you using the correct namespace?")
242
+ warning(
243
+ f"Current namespace: {Fore.YELLOW}{active_namespace}{Style.RESET_ALL}"
244
+ )
245
+ warning(
246
+ f"Last namespace: {Fore.YELLOW}{last_namespace}{Style.RESET_ALL}"
247
+ )
248
+
249
+ active_namespace = questionary.select(
250
+ "Which namespace do you want to use?",
251
+ choices=[active_namespace, last_namespace],
252
+ default=active_namespace,
253
+ ).ask()
254
+
255
+ if last_namespace != active_namespace:
256
+ self.set_last_namespace(namespace=active_namespace)
257
+
258
+ info(f"Using context: {Fore.YELLOW}{active_context}{Style.RESET_ALL}")
259
+ info(f"Using namespace: {Fore.YELLOW}{active_namespace}{Style.RESET_ALL}")
260
+ return active_context, active_namespace
@@ -20,17 +20,8 @@ class ServerConfiguration(Configuration):
20
20
  validators.
21
21
  """
22
22
 
23
- VALIDATORS = {
24
- "description": Use(str),
25
- "ip": Use(str),
26
- "port": Use(int),
27
- Optional("api_path"): str,
28
- "uri": Use(str),
29
- "allow_drop_all": Use(bool),
30
- "logging": {**LOGGING_VALIDATORS, "file": Use(str)},
31
- Optional("server_name"): str,
32
- Optional("runs_data_cleanup_days"): Use(int),
33
- }
23
+ # TODO: explore how to validate helm values.yaml files, see issue 2105
24
+ VALIDATORS = {}
34
25
 
35
26
 
36
27
  class NodeConfiguration(Configuration):
@@ -50,6 +41,7 @@ class NodeConfiguration(Configuration):
50
41
  Optional("node_extra_env"): dict,
51
42
  Optional("node_extra_mounts"): [str],
52
43
  Optional("node_extra_hosts"): dict,
44
+ Optional("share_algorithm_logs"): Use(bool),
53
45
  }
54
46
 
55
47