vantage6 5.0.0a35__py3-none-any.whl → 5.0.0a37__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 (84) hide show
  1. vantage6/cli/algorithm/generate_algorithm_json.py +9 -10
  2. vantage6/cli/algorithm/update.py +1 -1
  3. vantage6/cli/algostore/attach.py +1 -0
  4. vantage6/cli/algostore/files.py +3 -2
  5. vantage6/cli/algostore/list.py +0 -3
  6. vantage6/cli/algostore/new.py +3 -2
  7. vantage6/cli/algostore/start.py +14 -3
  8. vantage6/cli/algostore/stop.py +3 -0
  9. vantage6/cli/auth/attach.py +60 -0
  10. vantage6/cli/auth/files.py +16 -0
  11. vantage6/cli/auth/list.py +13 -0
  12. vantage6/cli/auth/new.py +81 -0
  13. vantage6/cli/auth/remove.py +31 -0
  14. vantage6/cli/auth/start.py +94 -0
  15. vantage6/cli/auth/stop.py +67 -0
  16. vantage6/cli/cli.py +56 -5
  17. vantage6/cli/common/decorator.py +24 -5
  18. vantage6/cli/common/new.py +27 -7
  19. vantage6/cli/common/start.py +49 -41
  20. vantage6/cli/common/stop.py +23 -5
  21. vantage6/cli/common/utils.py +25 -0
  22. vantage6/cli/config.py +10 -2
  23. vantage6/cli/{configuration_wizard.py → configuration_create.py} +28 -15
  24. vantage6/cli/configuration_manager.py +97 -17
  25. vantage6/cli/context/__init__.py +10 -5
  26. vantage6/cli/context/algorithm_store.py +11 -5
  27. vantage6/cli/context/auth.py +125 -0
  28. vantage6/cli/context/base_server.py +0 -4
  29. vantage6/cli/context/node.py +25 -8
  30. vantage6/cli/context/server.py +18 -6
  31. vantage6/cli/dev/clean.py +28 -0
  32. vantage6/cli/dev/common.py +34 -0
  33. vantage6/cli/dev/rebuild.py +39 -0
  34. vantage6/cli/dev/start.py +36 -0
  35. vantage6/cli/dev/stop.py +23 -0
  36. vantage6/cli/globals.py +5 -1
  37. vantage6/cli/node/common/__init__.py +26 -10
  38. vantage6/cli/node/list.py +5 -4
  39. vantage6/cli/node/new.py +13 -6
  40. vantage6/cli/node/set_api_key.py +1 -1
  41. vantage6/cli/node/start.py +19 -4
  42. vantage6/cli/node/stop.py +153 -7
  43. vantage6/cli/node/task_cleanup/__init__.py +153 -0
  44. vantage6/cli/node/version.py +5 -4
  45. vantage6/cli/prometheus/monitoring_manager.py +5 -3
  46. vantage6/cli/sandbox/config/base.py +101 -0
  47. vantage6/cli/sandbox/config/core.py +300 -0
  48. vantage6/cli/sandbox/config/node.py +314 -0
  49. vantage6/cli/sandbox/data/olympic_athletes_2016.csv +2425 -0
  50. vantage6/cli/sandbox/new.py +207 -0
  51. vantage6/cli/sandbox/populate/__init__.py +173 -0
  52. vantage6/cli/sandbox/populate/helpers/connect_store.py +203 -0
  53. vantage6/cli/sandbox/populate/helpers/delete_fixtures.py +67 -0
  54. vantage6/cli/sandbox/populate/helpers/load_fixtures.py +476 -0
  55. vantage6/cli/sandbox/populate/helpers/utils.py +35 -0
  56. vantage6/cli/sandbox/remove.py +173 -0
  57. vantage6/cli/sandbox/start.py +341 -0
  58. vantage6/cli/sandbox/stop.py +106 -0
  59. vantage6/cli/server/attach.py +1 -0
  60. vantage6/cli/server/common/__init__.py +6 -33
  61. vantage6/cli/server/import_.py +137 -119
  62. vantage6/cli/server/new.py +22 -7
  63. vantage6/cli/server/start.py +10 -1
  64. vantage6/cli/server/stop.py +2 -0
  65. vantage6/cli/template/auth_config.j2 +253 -0
  66. vantage6/cli/template/node_config.j2 +8 -8
  67. vantage6/cli/template/node_config_nonk8s.j2 +33 -0
  68. vantage6/cli/template/server_config.j2 +10 -7
  69. vantage6/cli/test/common/diagnostic_runner.py +5 -3
  70. vantage6/cli/use/namespace.py +2 -1
  71. vantage6/cli/utils.py +33 -1
  72. {vantage6-5.0.0a35.dist-info → vantage6-5.0.0a37.dist-info}/METADATA +4 -4
  73. vantage6-5.0.0a37.dist-info/RECORD +97 -0
  74. vantage6/cli/dev/create.py +0 -693
  75. vantage6/cli/dev/remove.py +0 -112
  76. vantage6/cli/rabbitmq/__init__.py +0 -0
  77. vantage6/cli/rabbitmq/definitions.py +0 -26
  78. vantage6/cli/rabbitmq/queue_manager.py +0 -218
  79. vantage6/cli/rabbitmq/rabbitmq.config +0 -8
  80. vantage6/cli/server/shell.py +0 -54
  81. vantage6-5.0.0a35.dist-info/RECORD +0 -75
  82. /vantage6/cli/{dev → sandbox}/data/km_dataset.csv +0 -0
  83. {vantage6-5.0.0a35.dist-info → vantage6-5.0.0a37.dist-info}/WHEEL +0 -0
  84. {vantage6-5.0.0a35.dist-info → vantage6-5.0.0a37.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,341 @@
1
+ import subprocess
2
+ import time
3
+ from pathlib import Path
4
+
5
+ import click
6
+ from colorama import Fore, Style
7
+
8
+ from vantage6.common import error, info
9
+ from vantage6.common.globals import HTTP_LOCALHOST, InstanceType, Ports
10
+
11
+ from vantage6.client import Client
12
+ from vantage6.client.utils import LogLevel
13
+
14
+ from vantage6.cli.common.decorator import click_insert_context
15
+ from vantage6.cli.common.utils import select_context_and_namespace
16
+ from vantage6.cli.context.auth import AuthContext
17
+ from vantage6.cli.context.node import NodeContext
18
+ from vantage6.cli.context.server import ServerContext
19
+ from vantage6.cli.sandbox.config.node import NodeDataset, NodeSandboxConfigManager
20
+ from vantage6.cli.sandbox.populate import populate_server_sandbox
21
+ from vantage6.cli.server.start import cli_server_start
22
+
23
+
24
+ @click.command()
25
+ @click.option("--context", default=None, help="Kubernetes context to use")
26
+ @click.option("--namespace", default=None, help="Kubernetes namespace to use")
27
+ @click.option(
28
+ "--local-chart-dir",
29
+ type=click.Path(exists=True),
30
+ default=None,
31
+ help="Local chart repository to use.",
32
+ )
33
+ @click.option(
34
+ "--re-initialize",
35
+ is_flag=True,
36
+ default=False,
37
+ help="Re-initialize the sandbox. This will repopulate the server and create new "
38
+ "node configurations.",
39
+ )
40
+ @click.option(
41
+ "--num-nodes",
42
+ type=int,
43
+ default=3,
44
+ help="Generate this number of nodes in the development network. Only used if "
45
+ "--re-initialize flag is provided.",
46
+ )
47
+ @click.option(
48
+ "--extra-node-config",
49
+ type=click.Path("rb"),
50
+ default=None,
51
+ help="YAML File with additional node configuration. This will be "
52
+ "appended to each of the node configuration files. Only used if --re-initialize "
53
+ "flag is provided",
54
+ )
55
+ @click.option(
56
+ "--add-dataset",
57
+ type=(str, click.Path()),
58
+ default=None,
59
+ multiple=True,
60
+ help="Add a dataset to the nodes. The first argument is the label of the database, "
61
+ "the second is the path to the dataset file. Only used if the --re-initialize flag "
62
+ "is provided.",
63
+ )
64
+ @click.option(
65
+ "--data-dir",
66
+ "custom_data_dir",
67
+ type=click.Path(exists=True),
68
+ default=None,
69
+ help="Path to a custom data directory to use. This option is especially useful "
70
+ "on WSL because of mount issues for default directories. Only used if the "
71
+ "--re-initialize flag is provided.",
72
+ )
73
+ @click_insert_context(type_=InstanceType.SERVER, is_sandbox=True)
74
+ @click.pass_context
75
+ def cli_sandbox_start(
76
+ click_ctx: click.Context,
77
+ ctx: ServerContext,
78
+ context: str | None,
79
+ namespace: str | None,
80
+ local_chart_dir: Path | None,
81
+ re_initialize: bool,
82
+ num_nodes: int,
83
+ extra_node_config: Path | None,
84
+ add_dataset: tuple[str, Path] | None,
85
+ custom_data_dir: Path | None,
86
+ ) -> None:
87
+ """
88
+ Start a sandbox environment.
89
+ """
90
+ context, namespace = select_context_and_namespace(
91
+ context=context,
92
+ namespace=namespace,
93
+ )
94
+
95
+ # TODO if re-initalize is specified, we must remove the existing node configs
96
+ execute_sandbox_start(
97
+ click_ctx=click_ctx,
98
+ ctx=ctx,
99
+ server_name=ctx.name,
100
+ context=context,
101
+ namespace=namespace,
102
+ num_nodes=num_nodes,
103
+ initialize=re_initialize,
104
+ extra_node_config=extra_node_config,
105
+ add_dataset=add_dataset,
106
+ custom_data_dir=custom_data_dir,
107
+ local_chart_dir=local_chart_dir,
108
+ )
109
+
110
+
111
+ def execute_sandbox_start(
112
+ click_ctx: click.Context,
113
+ ctx: ServerContext,
114
+ server_name: str,
115
+ context: str,
116
+ namespace: str,
117
+ num_nodes: int,
118
+ initialize: bool,
119
+ node_image: str | None = None,
120
+ k8s_node_name: str | None = None,
121
+ extra_node_config: Path | None = None,
122
+ add_dataset: tuple[str, Path] | None = None,
123
+ custom_data_dir: Path | None = None,
124
+ local_chart_dir: str | None = None,
125
+ ) -> None:
126
+ if k8s_node_name is None:
127
+ k8s_node_name = ctx.config["database"]["k8sNodeName"]
128
+
129
+ # First we need to start the keycloak service
130
+ cmd = [
131
+ "v6",
132
+ "auth",
133
+ "start",
134
+ "--name",
135
+ f"{server_name}-auth.sandbox",
136
+ "--user",
137
+ "--context",
138
+ context,
139
+ "--namespace",
140
+ namespace,
141
+ "--sandbox",
142
+ ]
143
+ if local_chart_dir:
144
+ cmd.extend(["--local-chart-dir", local_chart_dir])
145
+ subprocess.run(cmd, check=True)
146
+ # Note: the CLI auth start function is blocking until the auth service is ready,
147
+ # so no need to wait for it to be ready here.
148
+
149
+ # run the store. The store is started before the server so that the server can
150
+ # couple to the store on startup.
151
+ info("Starting algorithm store...")
152
+ cmd = [
153
+ "v6",
154
+ "algorithm-store",
155
+ "start",
156
+ "--name",
157
+ f"{ctx.name}-store.sandbox",
158
+ "--user",
159
+ "--context",
160
+ context,
161
+ "--namespace",
162
+ namespace,
163
+ "--sandbox",
164
+ ]
165
+ if local_chart_dir:
166
+ cmd.extend(["--local-chart-dir", local_chart_dir])
167
+ subprocess.run(cmd, check=True)
168
+
169
+ # Then we need to start the server
170
+ info("Starting vantage6 server")
171
+ click_ctx.invoke(
172
+ cli_server_start,
173
+ ctx=ctx,
174
+ name=ctx.name,
175
+ system_folders=False,
176
+ namespace=namespace,
177
+ context=context,
178
+ attach=False,
179
+ local_chart_dir=local_chart_dir,
180
+ )
181
+
182
+ server_url = f"{ctx.config['server']['baseUrl']}{ctx.config['server']['apiPath']}"
183
+ _wait_for_server_to_be_ready(server_url)
184
+
185
+ # Then we need to populate the server
186
+ if initialize:
187
+ node_config_names = _initialize_sandbox(
188
+ server_url=server_url,
189
+ server_name=server_name,
190
+ num_nodes=num_nodes,
191
+ ctx=ctx,
192
+ node_image=node_image,
193
+ extra_node_config=extra_node_config,
194
+ add_dataset=add_dataset,
195
+ context=context,
196
+ namespace=namespace,
197
+ k8s_node_name=k8s_node_name,
198
+ custom_data_dir=custom_data_dir,
199
+ )
200
+ else:
201
+ node_configs, _ = NodeContext.available_configurations(
202
+ system_folders=False, is_sandbox=True
203
+ )
204
+ node_config_names = [
205
+ config.name
206
+ for config in node_configs
207
+ if config.name.startswith(f"{server_name}-node-")
208
+ ]
209
+
210
+ # Then start the nodes
211
+ info("Starting nodes")
212
+ for node_config_name in node_config_names:
213
+ cmd = [
214
+ "v6",
215
+ "node",
216
+ "start",
217
+ "--name",
218
+ node_config_name,
219
+ "--sandbox",
220
+ ]
221
+ if local_chart_dir:
222
+ cmd.extend(["--local-chart-dir", local_chart_dir])
223
+ subprocess.run(cmd, check=True)
224
+
225
+ # Print the authentication credentials
226
+ _print_auth_credentials(server_name)
227
+
228
+
229
+ def _initialize_sandbox(
230
+ server_url: str,
231
+ server_name: str,
232
+ num_nodes: int,
233
+ ctx: ServerContext,
234
+ node_image: str | None,
235
+ extra_node_config: Path | None,
236
+ add_dataset: tuple[str, Path] | None,
237
+ context: str,
238
+ namespace: str,
239
+ k8s_node_name: str,
240
+ custom_data_dir: Path | None,
241
+ ) -> list[str]:
242
+ info("Populating server")
243
+ node_details = populate_server_sandbox(
244
+ server_url=server_url,
245
+ auth_url=f"{HTTP_LOCALHOST}:{Ports.DEV_AUTH}",
246
+ number_of_nodes=num_nodes,
247
+ )
248
+
249
+ api_keys = [node["api_key"] for node in node_details]
250
+ node_names = [node["name"] for node in node_details]
251
+
252
+ extra_dataset = (
253
+ NodeDataset(
254
+ label=add_dataset[0],
255
+ path=add_dataset[1],
256
+ )
257
+ if add_dataset is not None and add_dataset != ()
258
+ else None
259
+ )
260
+
261
+ # Create node config files from the nodes that were just registered in the server
262
+ node_config_manager = NodeSandboxConfigManager(
263
+ server_name=server_name,
264
+ api_keys=api_keys,
265
+ node_names=node_names,
266
+ server_port=ctx.config["server"]["port"],
267
+ node_image=node_image,
268
+ extra_node_config=extra_node_config,
269
+ extra_dataset=extra_dataset,
270
+ context=context,
271
+ namespace=namespace,
272
+ k8s_node_name=k8s_node_name,
273
+ custom_data_dir=custom_data_dir,
274
+ )
275
+ node_config_manager.generate_node_configs()
276
+
277
+ return node_config_manager.node_config_names
278
+
279
+
280
+ def _print_auth_credentials(server_name: str) -> None:
281
+ """
282
+ Find user credentials to print, from the auth config file
283
+
284
+ Parameters
285
+ ----------
286
+ server_name : str
287
+ Name of the server.
288
+ """
289
+ auth_ctx = AuthContext(
290
+ instance_name=f"{server_name}-auth",
291
+ system_folders=False,
292
+ is_sandbox=True,
293
+ )
294
+ auth_config = auth_ctx.config
295
+
296
+ try:
297
+ admin_user = auth_config["keycloak"]["keycloakConfigCli"]["configuration"][
298
+ "realm"
299
+ ]["users"][0]
300
+ username = admin_user["username"]
301
+ password = admin_user["credentials"][0]["value"]
302
+ info("You can login with the following credentials:")
303
+ info(f"Username: {Fore.GREEN}{username}{Style.RESET_ALL}")
304
+ info(f"Password: {Fore.GREEN}{password}{Style.RESET_ALL}")
305
+ except KeyError:
306
+ # No user found, skip printing credentials
307
+ pass
308
+
309
+
310
+ def _wait_for_server_to_be_ready(server_url: str) -> None:
311
+ """
312
+ Wait for the server to be initialized.
313
+
314
+ Parameters
315
+ ----------
316
+ server_url : str
317
+ URL of the server.
318
+ """
319
+ client = Client(
320
+ # TODO replace default API path global
321
+ server_url=server_url,
322
+ auth_url=f"{HTTP_LOCALHOST}:{Ports.DEV_AUTH}",
323
+ log_level=LogLevel.ERROR,
324
+ )
325
+ max_retries = 100
326
+ wait_time = 3
327
+ ready = False
328
+ for _ in range(max_retries):
329
+ try:
330
+ result = client.util.get_server_health()
331
+ if result and result.get("api"):
332
+ info("Server is ready.")
333
+ ready = True
334
+ break
335
+ except Exception:
336
+ info("Waiting for server to be ready...")
337
+ time.sleep(wait_time)
338
+
339
+ if not ready:
340
+ error("Server did not become ready in time. Exiting...")
341
+ exit(1)
@@ -0,0 +1,106 @@
1
+ import subprocess
2
+
3
+ import click
4
+
5
+ from vantage6.common import error
6
+ from vantage6.common.globals import InstanceType
7
+
8
+ from vantage6.cli.common.utils import (
9
+ find_running_service_names,
10
+ select_context_and_namespace,
11
+ select_running_service,
12
+ )
13
+ from vantage6.cli.context import get_context
14
+ from vantage6.cli.context.node import NodeContext
15
+ from vantage6.cli.server.stop import cli_server_stop
16
+
17
+
18
+ @click.command()
19
+ @click.option("-n", "--name", default=None, help="Name of the configuration.")
20
+ @click.option("--context", default=None, help="Kubernetes context to use")
21
+ @click.option("--namespace", default=None, help="Kubernetes namespace to use")
22
+ @click.pass_context
23
+ def cli_sandbox_stop(
24
+ click_ctx: click.Context,
25
+ name: str | None,
26
+ context: str | None,
27
+ namespace: str | None,
28
+ ) -> None:
29
+ """
30
+ Stop a sandbox environment.
31
+ """
32
+ context, namespace = select_context_and_namespace(
33
+ context=context,
34
+ namespace=namespace,
35
+ )
36
+
37
+ running_services = find_running_service_names(
38
+ instance_type=InstanceType.SERVER,
39
+ only_system_folders=False,
40
+ only_user_folders=False,
41
+ context=context,
42
+ namespace=namespace,
43
+ sandbox=True,
44
+ )
45
+
46
+ if not running_services:
47
+ error("No running sandbox services found.")
48
+ return
49
+
50
+ if not name:
51
+ selected_service = select_running_service(running_services, InstanceType.SERVER)
52
+ name = selected_service.split("-")[-3]
53
+ else:
54
+ ctx = get_context(InstanceType.SERVER, name, False, is_sandbox=True)
55
+ name = ctx.name
56
+
57
+ # stop the sandbox nodes
58
+ nodes_user_folder, _ = NodeContext.available_configurations(False, is_sandbox=True)
59
+ for node in nodes_user_folder:
60
+ if node.name.startswith(f"{name}-node-"):
61
+ cmd = [
62
+ "v6",
63
+ "node",
64
+ "stop",
65
+ "--name",
66
+ node.name,
67
+ "--sandbox",
68
+ "--context",
69
+ context,
70
+ "--namespace",
71
+ namespace,
72
+ ]
73
+ subprocess.run(cmd, check=True)
74
+
75
+ # # Stop all server services
76
+ click_ctx.invoke(
77
+ cli_server_stop,
78
+ name=name,
79
+ context=context,
80
+ namespace=namespace,
81
+ system_folders=False,
82
+ all_servers=False,
83
+ is_sandbox=True,
84
+ )
85
+
86
+ # TODO: stop the auth service
87
+ cmd = [
88
+ "v6",
89
+ "auth",
90
+ "stop",
91
+ "--name",
92
+ f"{name}-auth.sandbox",
93
+ "--sandbox",
94
+ ]
95
+ subprocess.run(cmd, check=True)
96
+
97
+ # stop the algorithm store
98
+ cmd = [
99
+ "v6",
100
+ "algorithm-store",
101
+ "stop",
102
+ "--name",
103
+ f"{name}-store.sandbox",
104
+ "--sandbox",
105
+ ]
106
+ subprocess.run(cmd, check=True)
@@ -1,6 +1,7 @@
1
1
  import click
2
2
 
3
3
  from vantage6.common import info
4
+
4
5
  from vantage6.cli.common.utils import attach_logs
5
6
 
6
7
 
@@ -1,16 +1,11 @@
1
- from docker.client import DockerClient
2
1
  from colorama import Fore, Style
3
2
 
4
- from vantage6.common import error, info
5
- from vantage6.common.globals import APPNAME
6
- from vantage6.common.docker.addons import remove_container, get_container
3
+ from vantage6.common import error
7
4
  from vantage6.common.context import AppContext
8
5
 
9
- from vantage6.cli.context.server import ServerContext
10
-
11
6
 
12
7
  def get_server_context(
13
- name: str, system_folders: bool, ctx_class: AppContext
8
+ name: str, system_folders: bool, ctx_class: AppContext, is_sandbox: bool = False
14
9
  ) -> AppContext:
15
10
  """
16
11
  Load the server context from the configuration file.
@@ -23,13 +18,14 @@ def get_server_context(
23
18
  Wether to use system folders or if False, the user folders
24
19
  ctx_class : AppContext
25
20
  Context class to be used. Derivative of AppContext class
26
-
21
+ is_sandbox : bool
22
+ Whether the configuration is a sandbox configuration, by default False
27
23
  Returns
28
24
  -------
29
25
  ServerContext
30
26
  Server context object
31
27
  """
32
- if not ctx_class.config_exists(name, system_folders):
28
+ if not ctx_class.config_exists(name, system_folders, is_sandbox=is_sandbox):
33
29
  scope = "system" if system_folders else "user"
34
30
  error(
35
31
  f"Configuration {Fore.RED}{name}{Style.RESET_ALL} does not "
@@ -40,29 +36,6 @@ def get_server_context(
40
36
  # We do not want to log this here, we do this in the container and not on
41
37
  # the host. We only want CLI logging here.
42
38
  ctx_class.LOGGING_ENABLED = False
43
-
44
39
  # create server context, and initialize db
45
- ctx = ctx_class(name, system_folders=system_folders)
46
-
40
+ ctx = ctx_class(name, system_folders=system_folders, is_sandbox=is_sandbox)
47
41
  return ctx
48
-
49
-
50
- def stop_ui(client: DockerClient, ctx: ServerContext) -> None:
51
- """
52
- Check if the UI container is running, and if so, stop and remove it.
53
-
54
- Parameters
55
- ----------
56
- client : DockerClient
57
- Docker client
58
- ctx : ServerContext
59
- Server context object
60
- """
61
- ui_container_name = f"{APPNAME}-{ctx.name}-{ctx.scope}-ui"
62
- ui_container = get_container(client, name=ui_container_name)
63
- if ui_container:
64
- remove_container(ui_container, kill=True)
65
- info(
66
- f"Stopped the {Fore.GREEN}{ui_container_name}"
67
- f"{Style.RESET_ALL} User Interface container."
68
- )