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