vantage6 5.0.0a38__tar.gz → 5.0.0a41__tar.gz

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 (109) hide show
  1. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/PKG-INFO +3 -3
  2. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/pyproject.toml +3 -3
  3. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/algorithm/generate_algorithm_json.py +2 -1
  4. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/common/decorator.py +4 -3
  5. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/common/new.py +3 -2
  6. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/common/stop.py +3 -2
  7. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/configuration_create.py +3 -2
  8. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/node/common/__init__.py +31 -6
  9. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/node/create_private_key.py +11 -10
  10. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/node/set_api_key.py +12 -6
  11. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/server/import_.py +85 -17
  12. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/template/node_config.j2 +1 -1
  13. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/.gitignore +0 -0
  14. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/Makefile +0 -0
  15. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/README.md +0 -0
  16. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/tests_cli/__init__.py +0 -0
  17. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/tests_cli/test_client_script.py +0 -0
  18. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/tests_cli/test_example.py +0 -0
  19. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/tests_cli/test_node_cli.py +0 -0
  20. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/tests_cli/test_server_cli.py +0 -0
  21. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/tests_cli/test_wizard.py +0 -0
  22. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/__init__.py +0 -0
  23. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/algorithm/create.py +0 -0
  24. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/algorithm/update.py +0 -0
  25. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/algostore/attach.py +0 -0
  26. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/algostore/files.py +0 -0
  27. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/algostore/list.py +0 -0
  28. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/algostore/new.py +0 -0
  29. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/algostore/remove.py +0 -0
  30. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/algostore/start.py +0 -0
  31. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/algostore/stop.py +0 -0
  32. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/algostore/version.py +0 -0
  33. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/auth/attach.py +0 -0
  34. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/auth/files.py +0 -0
  35. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/auth/list.py +0 -0
  36. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/auth/new.py +0 -0
  37. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/auth/remove.py +0 -0
  38. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/auth/start.py +0 -0
  39. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/auth/stop.py +0 -0
  40. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/cli.py +0 -0
  41. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/common/attach.py +0 -0
  42. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/common/list.py +0 -0
  43. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/common/remove.py +0 -0
  44. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/common/start.py +0 -0
  45. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/common/utils.py +0 -0
  46. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/common/version.py +0 -0
  47. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/config.py +0 -0
  48. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/configuration_manager.py +0 -0
  49. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/context/__init__.py +0 -0
  50. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/context/algorithm_store.py +0 -0
  51. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/context/auth.py +0 -0
  52. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/context/base_server.py +0 -0
  53. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/context/node.py +0 -0
  54. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/context/server.py +0 -0
  55. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/dev/clean.py +0 -0
  56. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/dev/common.py +0 -0
  57. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/dev/rebuild.py +0 -0
  58. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/dev/start.py +0 -0
  59. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/dev/stop.py +0 -0
  60. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/globals.py +0 -0
  61. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/node/attach.py +0 -0
  62. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/node/common/task_cleanup.py +0 -0
  63. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/node/files.py +0 -0
  64. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/node/list.py +0 -0
  65. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/node/new.py +0 -0
  66. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/node/remove.py +0 -0
  67. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/node/restart.py +0 -0
  68. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/node/start.py +0 -0
  69. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/node/stop.py +0 -0
  70. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/node/version.py +0 -0
  71. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/prometheus/monitoring_manager.py +0 -0
  72. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/prometheus/prometheus.yml +0 -0
  73. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/sandbox/config/base.py +0 -0
  74. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/sandbox/config/core.py +0 -0
  75. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/sandbox/config/node.py +0 -0
  76. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/sandbox/data/km_dataset.csv +0 -0
  77. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/sandbox/data/olympic_athletes_2016.csv +0 -0
  78. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/sandbox/new.py +0 -0
  79. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/sandbox/populate/__init__.py +0 -0
  80. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/sandbox/populate/helpers/connect_store.py +0 -0
  81. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/sandbox/populate/helpers/delete_fixtures.py +0 -0
  82. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/sandbox/populate/helpers/load_fixtures.py +0 -0
  83. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/sandbox/populate/helpers/utils.py +0 -0
  84. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/sandbox/remove.py +0 -0
  85. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/sandbox/start.py +0 -0
  86. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/sandbox/stop.py +0 -0
  87. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/server/attach.py +0 -0
  88. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/server/common/__init__.py +0 -0
  89. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/server/files.py +0 -0
  90. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/server/list.py +0 -0
  91. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/server/new.py +0 -0
  92. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/server/remove.py +0 -0
  93. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/server/start.py +0 -0
  94. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/server/stop.py +0 -0
  95. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/server/version.py +0 -0
  96. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/template/algo_store_config.j2 +0 -0
  97. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/template/auth_config.j2 +0 -0
  98. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/template/node_config_nonk8s.j2 +0 -0
  99. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/template/server_config.j2 +0 -0
  100. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/test/algo_test_scripts/algo_test_arguments.py +0 -0
  101. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/test/algo_test_scripts/algo_test_script.py +0 -0
  102. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/test/client_script.py +0 -0
  103. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/test/common/diagnostic_runner.py +0 -0
  104. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/test/feature_tester.py +0 -0
  105. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/test/integration_test.py +0 -0
  106. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/use/context.py +0 -0
  107. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/use/namespace.py +0 -0
  108. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/utils.py +0 -0
  109. {vantage6-5.0.0a38 → vantage6-5.0.0a41}/vantage6/cli/utils_kubernetes.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vantage6
3
- Version: 5.0.0a38
3
+ Version: 5.0.0a41
4
4
  Summary: vantage6 command line interface
5
5
  Author: Vantage6 Team
6
6
  Maintainer-email: Frank Martin <f.martin@iknl.nl>, Bart van Beusekom <b.vanbeusekom@iknl.nl>
@@ -18,8 +18,8 @@ Requires-Dist: questionary==2.1.1
18
18
  Requires-Dist: rich==13.5.2
19
19
  Requires-Dist: schema==0.7.5
20
20
  Requires-Dist: sqlalchemy==2.0.37
21
- Requires-Dist: vantage6-client==5.0.0a38
22
- Requires-Dist: vantage6-common==5.0.0a38
21
+ Requires-Dist: vantage6-client==5.0.0a41
22
+ Requires-Dist: vantage6-common==5.0.0a41
23
23
  Provides-Extra: dev
24
24
  Requires-Dist: black; extra == 'dev'
25
25
  Requires-Dist: coverage==7.10.2; extra == 'dev'
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "vantage6"
7
- version = "5.0.0a38"
7
+ version = "5.0.0a41"
8
8
  description = "vantage6 command line interface"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
@@ -29,8 +29,8 @@ dependencies = [
29
29
  "rich==13.5.2",
30
30
  "schema==0.7.5",
31
31
  "sqlalchemy==2.0.37",
32
- "vantage6-common==5.0.0a38",
33
- "vantage6-client==5.0.0a38",
32
+ "vantage6-common==5.0.0a41",
33
+ "vantage6-client==5.0.0a41",
34
34
  ]
35
35
 
36
36
  [project.optional-dependencies]
@@ -3,6 +3,7 @@ import inspect
3
3
  import json
4
4
  import os
5
5
  import sys
6
+ from collections.abc import Callable
6
7
  from inspect import getmembers, isfunction, ismodule, signature
7
8
  from pathlib import Path
8
9
  from types import ModuleType, UnionType
@@ -62,7 +63,7 @@ class FunctionArgumentType(StrEnumBase):
62
63
  class Function:
63
64
  """Class to handle a function and its JSON representation"""
64
65
 
65
- def __init__(self, func: callable):
66
+ def __init__(self, func: Callable):
66
67
  self.func = func
67
68
  self.name = func.__name__
68
69
  self.signature = signature(func)
@@ -1,3 +1,4 @@
1
+ from collections.abc import Callable
1
2
  from functools import wraps
2
3
  from pathlib import Path
3
4
 
@@ -17,7 +18,7 @@ def click_insert_context(
17
18
  include_system_folders: bool = False,
18
19
  is_sandbox: bool = False,
19
20
  sandbox_param: str | None = None,
20
- ) -> callable:
21
+ ) -> Callable:
21
22
  """
22
23
  Supply the Click function with an additional context parameter. The context
23
24
  is passed to the function as the first argument.
@@ -49,7 +50,7 @@ def click_insert_context(
49
50
  >>> pass
50
51
  """
51
52
 
52
- def protection_decorator(func: callable) -> callable:
53
+ def protection_decorator(func: Callable) -> Callable:
53
54
  @click.option("-n", "--name", default=None, help="Name of the configuration.")
54
55
  @click.option(
55
56
  "-c",
@@ -73,7 +74,7 @@ def click_insert_context(
73
74
  @wraps(func)
74
75
  def decorator(
75
76
  name: str, config: str, system_folders: bool, *args, **kwargs
76
- ) -> callable:
77
+ ) -> Callable:
77
78
  """
78
79
  Decorator function that adds the context to the function.
79
80
 
@@ -1,3 +1,4 @@
1
+ from collections.abc import Callable
1
2
  from pathlib import Path
2
3
 
3
4
  from colorama import Fore, Style
@@ -13,7 +14,7 @@ from vantage6.cli.utils import check_config_name_allowed, prompt_config_name
13
14
 
14
15
 
15
16
  def new(
16
- config_producing_func: callable,
17
+ config_producing_func: Callable,
17
18
  config_producing_func_args: tuple,
18
19
  name: str,
19
20
  system_folders: bool,
@@ -27,7 +28,7 @@ def new(
27
28
 
28
29
  Parameters
29
30
  ----------
30
- config_producing_func : callable
31
+ config_producing_func : Callable
31
32
  Function to generate the configuration
32
33
  config_producing_func_args : tuple
33
34
  Arguments to pass to the config producing function
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import subprocess
4
+ from collections.abc import Callable
4
5
 
5
6
  from colorama import Fore, Style
6
7
 
@@ -19,7 +20,7 @@ from vantage6.cli.utils import validate_input_cmd_args
19
20
 
20
21
 
21
22
  def execute_stop(
22
- stop_function: callable,
23
+ stop_function: Callable,
23
24
  instance_type: InstanceType,
24
25
  infra_component: InfraComponentName,
25
26
  stop_all: bool,
@@ -35,7 +36,7 @@ def execute_stop(
35
36
 
36
37
  Parameters
37
38
  ----------
38
- stop_function : callable
39
+ stop_function : Callable
39
40
  The function to stop the service.
40
41
  instance_type : InstanceType
41
42
  The instance type of the service.
@@ -1,3 +1,4 @@
1
+ from collections.abc import Callable
1
2
  from pathlib import Path
2
3
 
3
4
  import questionary as q
@@ -127,7 +128,7 @@ def _add_production_server_config(config: dict) -> dict:
127
128
 
128
129
 
129
130
  def make_configuration(
130
- config_producing_func: callable,
131
+ config_producing_func: Callable,
131
132
  config_producing_func_args: tuple,
132
133
  type_: InstanceType,
133
134
  instance_name: str,
@@ -139,7 +140,7 @@ def make_configuration(
139
140
 
140
141
  Parameters
141
142
  ----------
142
- config_producing_func : callable
143
+ config_producing_func : Callable
143
144
  Function to generate the configuration
144
145
  config_producing_func_args : tuple
145
146
  Arguments to pass to the config producing function
@@ -12,6 +12,7 @@ from vantage6.common.globals import (
12
12
  APPNAME,
13
13
  HTTP_LOCALHOST,
14
14
  InstanceType,
15
+ Ports,
15
16
  RequiredNodeEnvVars,
16
17
  )
17
18
 
@@ -21,6 +22,16 @@ from vantage6.cli.configuration_create import select_configuration_questionnaire
21
22
  from vantage6.cli.context.node import NodeContext
22
23
 
23
24
 
25
+ def _convert_k8s_url_to_localhost(url: str) -> str:
26
+ """
27
+ Convert a Kubernetes URL to a localhost URL.
28
+ """
29
+ if "svc.cluster.local" in url:
30
+ port_and_api_path = url.split(":")[-1]
31
+ return f"{HTTP_LOCALHOST}:{port_and_api_path}"
32
+ return url
33
+
34
+
24
35
  def create_client(ctx: NodeContext) -> UserClient:
25
36
  """
26
37
  Create a client instance.
@@ -34,17 +45,31 @@ def create_client(ctx: NodeContext) -> UserClient:
34
45
  UserClient
35
46
  vantage6 client
36
47
  """
37
- host = ctx.config["server_url"]
48
+ host = ctx.config["node"]["server"]["url"]
49
+ port = ctx.config["node"]["server"]["port"]
50
+ api_path = ctx.config["node"]["server"]["path"]
38
51
  # if the server is run locally, we need to use localhost here instead of
39
52
  # the host address of docker
40
53
  if host in ["http://host.docker.internal", "http://172.17.0.1"]:
41
54
  host = HTTP_LOCALHOST
42
- port = ctx.config["port"]
43
- api_path = ctx.config["api_path"]
44
- info(f"Connecting to server at '{host}:{port}{api_path}'")
55
+
56
+ url = f"{host}:{port}{api_path}"
57
+
58
+ auth_url = ctx.config.get("node", {}).get("keycloakUrl", None) or os.environ.get(
59
+ RequiredNodeEnvVars.KEYCLOAK_URL.value
60
+ )
61
+ # append the port to the auth URL as it is not included in the config
62
+ auth_url = f"{auth_url}:{Ports.DEV_AUTH.value}"
63
+
64
+ # if the server is a Kubernetes address, we need to use localhost because here
65
+ # we are connecting from the CLI outside the cluster
66
+ url = _convert_k8s_url_to_localhost(url)
67
+ auth_url = _convert_k8s_url_to_localhost(auth_url)
68
+
69
+ info(f"Connecting to server at '{url}' using auth URL '{auth_url}'")
45
70
  return UserClient(
46
- server_url=f"{host}:{port}{api_path}",
47
- auth_url=os.environ.get(RequiredNodeEnvVars.KEYCLOAK_URL.value),
71
+ server_url=url,
72
+ auth_url=auth_url,
48
73
  log_level="warn",
49
74
  )
50
75
 
@@ -11,10 +11,12 @@ from vantage6.common import (
11
11
  warning,
12
12
  )
13
13
  from vantage6.common.encryption import RSACryptor
14
+ from vantage6.common.globals import InstanceType
14
15
 
16
+ from vantage6.cli.configuration_create import select_configuration_questionnaire
15
17
  from vantage6.cli.context.node import NodeContext
16
18
  from vantage6.cli.globals import DEFAULT_NODE_SYSTEM_FOLDERS as N_FOL
17
- from vantage6.cli.node.common import create_client_and_authenticate, select_node
19
+ from vantage6.cli.node.common import create_client_and_authenticate
18
20
 
19
21
 
20
22
  @click.command()
@@ -80,12 +82,13 @@ def cli_node_create_private_key(
80
82
  if config:
81
83
  name = Path(config).stem
82
84
  ctx = NodeContext(name, system_folders, config)
83
- else:
84
- # retrieve context
85
- name = select_node(name, system_folders)
86
-
87
- # Create node context
88
- ctx = NodeContext(name, system_folders)
85
+ elif not name:
86
+ try:
87
+ name = select_configuration_questionnaire(InstanceType.NODE, system_folders)
88
+ except Exception:
89
+ error("No configurations could be found!")
90
+ exit(1)
91
+ ctx = NodeContext(name, system_folders)
89
92
 
90
93
  # Authenticate with the server to obtain organization name if it wasn't
91
94
  # provided
@@ -138,9 +141,7 @@ def cli_node_create_private_key(
138
141
 
139
142
  # update config file
140
143
  info("Updating configuration")
141
- # TODO v5+ this probably messes up the current config as the template is used...
142
- # Fix when reimplementing this in v5
143
- ctx.config["encryption"]["private_key"] = str(file_)
144
+ ctx.config["node"]["encryption"]["private_key"] = str(file_)
144
145
  ctx.config_manager.put(ctx.config)
145
146
  ctx.config_manager.save(ctx.config_file)
146
147
 
@@ -2,11 +2,14 @@ import click
2
2
  import questionary as q
3
3
 
4
4
  from vantage6.common import ensure_config_dir_writable, error, info
5
+ from vantage6.common.globals import InstanceType
5
6
 
6
- from vantage6.cli.configuration_create import NodeConfigurationManager
7
+ from vantage6.cli.configuration_create import (
8
+ NodeConfigurationManager,
9
+ select_configuration_questionnaire,
10
+ )
7
11
  from vantage6.cli.context.node import NodeContext
8
12
  from vantage6.cli.globals import DEFAULT_NODE_SYSTEM_FOLDERS as N_FOL
9
- from vantage6.cli.node.common import select_node
10
13
 
11
14
 
12
15
  @click.command()
@@ -31,7 +34,12 @@ def cli_node_set_api_key(name: str, api_key: str, system_folders: bool) -> None:
31
34
  Put a new API key into the node configuration file
32
35
  """
33
36
  # select node name
34
- name = select_node(name, system_folders)
37
+ if not name:
38
+ try:
39
+ name = select_configuration_questionnaire(InstanceType.NODE, system_folders)
40
+ except Exception:
41
+ error("No configurations could be found!")
42
+ exit(1)
35
43
 
36
44
  # Check that we can write in the config folder
37
45
  if not ensure_config_dir_writable(system_folders):
@@ -50,9 +58,7 @@ def cli_node_set_api_key(name: str, api_key: str, system_folders: bool) -> None:
50
58
  conf_mgr = NodeConfigurationManager.from_file(ctx.config_file)
51
59
 
52
60
  # set new api key, and save the file
53
- ctx.config["api_key"] = api_key
54
- # TODO v5+ this probably messes up the current config as the template is used...
55
- # Fix when reimplementing this in v5
61
+ ctx.config["node"]["apiKey"] = api_key
56
62
  conf_mgr.put(ctx.config)
57
63
  conf_mgr.save(ctx.config_file)
58
64
  info(f"Your new API key has been uploaded to the config file {ctx.config_file}.")
@@ -1,6 +1,7 @@
1
1
  import click
2
2
  import requests
3
3
  import yaml
4
+ from marshmallow import Schema, ValidationError, fields, post_load
4
5
 
5
6
  from vantage6.common import error, info
6
7
  from vantage6.common.globals import (
@@ -64,7 +65,8 @@ def cli_server_import(ctx: ServerContext, file: str, drop_all: bool) -> None:
64
65
  info("Loading and validating import file")
65
66
  with open(file, "r") as f:
66
67
  import_data = yaml.safe_load(f)
67
- # TODO: validate import file
68
+
69
+ _check_import_file(import_data)
68
70
 
69
71
  client = UserClient(
70
72
  server_url=f"{ctx.config['server']['baseUrl']}{ctx.config['server']['apiPath']}",
@@ -77,7 +79,9 @@ def cli_server_import(ctx: ServerContext, file: str, drop_all: bool) -> None:
77
79
  info("Authenticate using admin credentials (opens browser for login)")
78
80
  client.authenticate()
79
81
 
80
- # TODO: validate that the user has the correct permissions to import data
82
+ # Note: we do not validate that the user has the correct permissions to import data.
83
+ # As the user has access to the `v6 server import` command, they already have
84
+ # access to the server+database.
81
85
 
82
86
  if drop_all:
83
87
  info("Dropping all existing data")
@@ -91,11 +95,12 @@ def cli_server_import(ctx: ServerContext, file: str, drop_all: bool) -> None:
91
95
  for organization in import_data["organizations"]:
92
96
  org = client.organization.create(
93
97
  name=organization["name"],
94
- address1=organization["address1"] or "",
95
- address2=organization["address2"] or "",
96
- zipcode=organization["zipcode"] or "",
97
- country=organization["country"] or "",
98
- domain=organization["domain"] or "",
98
+ address1=organization.get("address1", ""),
99
+ address2=organization.get("address2", ""),
100
+ zipcode=str(organization.get("zipcode", "")),
101
+ country=organization.get("country", ""),
102
+ domain=organization.get("domain", ""),
103
+ public_key=organization.get("public_key", ""),
99
104
  )
100
105
  organizations.append(org)
101
106
 
@@ -152,16 +157,79 @@ def _drop_all(client: UserClient) -> None:
152
157
  info(f"Deleting collaboration {collaboration['name']}")
153
158
  client.collaboration.delete(collaboration["id"], delete_dependents=True)
154
159
 
155
- # TODO: For some reason, the `delete_dependents` parameter is not working for users,
156
- # so we delete them here first.
157
- while users := [u for u in client.user.list()["data"] if u["username"] != "admin"]:
158
- for user in users:
159
- info(f"Deleting user {user['username']}")
160
- client.user.delete(user["id"])
161
-
162
- while orgs := [
163
- o for o in client.organization.list()["data"] if o["name"] != "root"
164
- ]:
160
+ # remove all organizations but keep the root organization
161
+ while orgs := [o for o in client.organization.list()["data"] if o["id"] != 1]:
165
162
  for org in orgs:
166
163
  info(f"Deleting organization {org['name']}")
167
164
  client.organization.delete(org["id"], delete_dependents=True)
165
+
166
+
167
+ class StrOrInt(fields.Field):
168
+ """Field that can be a string or an integer"""
169
+
170
+ def _serialize(self, value, attr, obj, **kwargs):
171
+ if isinstance(value, str):
172
+ return value
173
+ elif isinstance(value, int):
174
+ return str(value)
175
+ else:
176
+ raise ValidationError("Value must be a string or an integer")
177
+
178
+
179
+ class UserSchema(Schema):
180
+ username = fields.Str(required=True)
181
+ password = fields.Str(required=True)
182
+
183
+
184
+ class OrganizationSchema(Schema):
185
+ name = fields.Str(required=True)
186
+ address1 = fields.Str(missing="")
187
+ address2 = fields.Str(missing="")
188
+ zipcode = StrOrInt(missing="")
189
+ country = fields.Str(missing="")
190
+ domain = fields.Str(missing="")
191
+ public_key = fields.Str(missing="")
192
+ users = fields.List(fields.Nested(UserSchema), missing=[])
193
+
194
+
195
+ class ParticipantSchema(Schema):
196
+ name = fields.Str(required=True)
197
+
198
+
199
+ class CollaborationSchema(Schema):
200
+ name = fields.Str(required=True)
201
+ participants = fields.List(fields.Nested(ParticipantSchema), required=True)
202
+ encrypted = fields.Bool(missing=False)
203
+
204
+
205
+ class ImportDataSchema(Schema):
206
+ organizations = fields.List(fields.Nested(OrganizationSchema), missing=[])
207
+ collaborations = fields.List(fields.Nested(CollaborationSchema), missing=[])
208
+
209
+ @post_load
210
+ def validate_participants_exist(self, data, **kwargs):
211
+ """Validate that all participants exist in organizations"""
212
+ org_names = {org["name"] for org in data.get("organizations", [])}
213
+
214
+ for collaboration in data.get("collaborations", []):
215
+ for participant in collaboration.get("participants", []):
216
+ if participant["name"] not in org_names:
217
+ raise ValidationError(
218
+ f"Participant {participant['name']} not found in organizations",
219
+ field_name="collaborations",
220
+ )
221
+ return data
222
+
223
+
224
+ def _check_import_file(import_data: dict) -> dict:
225
+ """
226
+ Validate import file using Marshmallow schemas.
227
+ Returns the validated and cleaned data.
228
+ """
229
+ schema = ImportDataSchema()
230
+ try:
231
+ return schema.load(import_data)
232
+ except ValidationError as err:
233
+ # Handle validation errors gracefully
234
+ error(f"Validation error: {err.messages}")
235
+ exit(1)
@@ -90,7 +90,7 @@ node:
90
90
  enabled: {{ node.encryption.enabled | default(false) }}
91
91
 
92
92
  # Location to the private key file. Required if encryption is enabled.
93
- {% if node.encryption.enabled | default(false) %}
93
+ {% if node.encryption.private_key is defined and node.encryption.private_key != '' %}
94
94
  private_key: {{ node.encryption.private_key | default('/path/to/private_key.pem') }}
95
95
  {% else %}
96
96
  # private_key: /path/to/private_key.pem
File without changes
File without changes
File without changes