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.
- vantage6/cli/algorithm/generate_algorithm_json.py +0 -1
- vantage6/cli/algostore/attach.py +28 -3
- vantage6/cli/algostore/list.py +2 -2
- vantage6/cli/algostore/new.py +3 -2
- vantage6/cli/algostore/start.py +25 -6
- vantage6/cli/algostore/stop.py +3 -0
- vantage6/cli/algostore/version.py +62 -0
- vantage6/cli/auth/attach.py +1 -1
- vantage6/cli/auth/list.py +2 -2
- vantage6/cli/auth/new.py +3 -2
- vantage6/cli/auth/remove.py +58 -0
- vantage6/cli/auth/start.py +27 -9
- vantage6/cli/auth/stop.py +3 -0
- vantage6/cli/cli.py +21 -0
- vantage6/cli/common/attach.py +114 -0
- vantage6/cli/common/decorator.py +25 -4
- vantage6/cli/common/list.py +68 -0
- vantage6/cli/common/new.py +27 -7
- vantage6/cli/common/remove.py +18 -0
- vantage6/cli/common/start.py +48 -40
- vantage6/cli/common/stop.py +16 -4
- vantage6/cli/common/utils.py +65 -74
- vantage6/cli/common/version.py +82 -0
- vantage6/cli/config.py +10 -2
- vantage6/cli/{configuration_wizard.py → configuration_create.py} +22 -14
- vantage6/cli/configuration_manager.py +70 -21
- vantage6/cli/context/__init__.py +10 -5
- vantage6/cli/context/algorithm_store.py +13 -7
- vantage6/cli/context/auth.py +23 -5
- vantage6/cli/context/node.py +25 -8
- vantage6/cli/context/server.py +18 -6
- vantage6/cli/globals.py +1 -0
- vantage6/cli/node/attach.py +27 -3
- vantage6/cli/node/common/__init__.py +26 -10
- vantage6/cli/node/common/task_cleanup.py +153 -0
- vantage6/cli/node/list.py +3 -44
- vantage6/cli/node/new.py +13 -6
- vantage6/cli/node/set_api_key.py +1 -1
- vantage6/cli/node/start.py +30 -7
- vantage6/cli/node/stop.py +151 -7
- vantage6/cli/node/version.py +96 -33
- vantage6/cli/sandbox/config/base.py +109 -0
- vantage6/cli/sandbox/config/core.py +300 -0
- vantage6/cli/sandbox/config/node.py +311 -0
- vantage6/cli/sandbox/data/km_dataset.csv +2401 -0
- vantage6/cli/sandbox/data/olympic_athletes_2016.csv +2425 -0
- vantage6/cli/sandbox/new.py +207 -0
- vantage6/cli/sandbox/populate/__init__.py +173 -0
- vantage6/cli/sandbox/populate/helpers/connect_store.py +203 -0
- vantage6/cli/sandbox/populate/helpers/delete_fixtures.py +67 -0
- vantage6/cli/sandbox/populate/helpers/load_fixtures.py +476 -0
- vantage6/cli/sandbox/populate/helpers/utils.py +35 -0
- vantage6/cli/sandbox/remove.py +155 -0
- vantage6/cli/sandbox/start.py +349 -0
- vantage6/cli/sandbox/stop.py +106 -0
- vantage6/cli/server/attach.py +28 -3
- vantage6/cli/server/common/__init__.py +5 -6
- vantage6/cli/server/import_.py +137 -119
- vantage6/cli/server/list.py +2 -2
- vantage6/cli/server/new.py +5 -3
- vantage6/cli/server/start.py +21 -4
- vantage6/cli/server/stop.py +2 -0
- vantage6/cli/server/version.py +31 -18
- vantage6/cli/template/algo_store_config.j2 +3 -0
- vantage6/cli/template/auth_config.j2 +24 -1
- vantage6/cli/template/node_config.j2 +2 -0
- vantage6/cli/template/server_config.j2 +10 -7
- vantage6/cli/use/context.py +8 -1
- vantage6/cli/use/namespace.py +10 -7
- vantage6/cli/utils.py +33 -1
- vantage6/cli/utils_kubernetes.py +270 -0
- {vantage6-5.0.0a36.dist-info → vantage6-5.0.0a38.dist-info}/METADATA +4 -4
- vantage6-5.0.0a38.dist-info/RECORD +102 -0
- vantage6/cli/rabbitmq/__init__.py +0 -0
- vantage6/cli/rabbitmq/definitions.py +0 -26
- vantage6/cli/rabbitmq/queue_manager.py +0 -220
- vantage6/cli/rabbitmq/rabbitmq.config +0 -8
- vantage6-5.0.0a36.dist-info/RECORD +0 -86
- {vantage6-5.0.0a36.dist-info → vantage6-5.0.0a38.dist-info}/WHEEL +0 -0
- {vantage6-5.0.0a36.dist-info → vantage6-5.0.0a38.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
from colorama import Fore, Style
|
|
5
|
+
|
|
6
|
+
from vantage6.common import error
|
|
7
|
+
from vantage6.common.globals import Ports
|
|
8
|
+
|
|
9
|
+
from vantage6.cli.common.utils import select_context_and_namespace
|
|
10
|
+
from vantage6.cli.context.server import ServerContext
|
|
11
|
+
from vantage6.cli.sandbox.config.core import CoreSandboxConfigManager
|
|
12
|
+
from vantage6.cli.sandbox.start import execute_sandbox_start
|
|
13
|
+
from vantage6.cli.server.common import get_server_context
|
|
14
|
+
from vantage6.cli.utils import prompt_config_name
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@click.command()
|
|
18
|
+
@click.option(
|
|
19
|
+
"-n", "--name", default=None, type=str, help="Name for your development setup"
|
|
20
|
+
)
|
|
21
|
+
@click.option(
|
|
22
|
+
"--num-nodes",
|
|
23
|
+
type=int,
|
|
24
|
+
default=3,
|
|
25
|
+
help="Generate this number of nodes in the development network",
|
|
26
|
+
)
|
|
27
|
+
@click.option(
|
|
28
|
+
"-p",
|
|
29
|
+
"--server-port",
|
|
30
|
+
type=int,
|
|
31
|
+
default=Ports.DEV_SERVER.value,
|
|
32
|
+
help=f"Port to run the server on. Default is {Ports.DEV_SERVER}.",
|
|
33
|
+
)
|
|
34
|
+
@click.option(
|
|
35
|
+
"--ui-port",
|
|
36
|
+
type=int,
|
|
37
|
+
default=Ports.DEV_UI.value,
|
|
38
|
+
help=f"Port to run the UI on. Default is {Ports.DEV_UI}.",
|
|
39
|
+
)
|
|
40
|
+
@click.option(
|
|
41
|
+
"--algorithm-store-port",
|
|
42
|
+
type=int,
|
|
43
|
+
default=Ports.DEV_ALGO_STORE.value,
|
|
44
|
+
help=f"Port to run the algorithm store on. Default is {Ports.DEV_ALGO_STORE}.",
|
|
45
|
+
)
|
|
46
|
+
@click.option(
|
|
47
|
+
"--server-image",
|
|
48
|
+
type=str,
|
|
49
|
+
default=None,
|
|
50
|
+
help="Server docker image to use when setting up resources for "
|
|
51
|
+
"the development server",
|
|
52
|
+
)
|
|
53
|
+
@click.option(
|
|
54
|
+
"--ui-image",
|
|
55
|
+
type=str,
|
|
56
|
+
default=None,
|
|
57
|
+
help="UI docker image to specify in configuration files. Will be used on startup of"
|
|
58
|
+
" the network",
|
|
59
|
+
)
|
|
60
|
+
@click.option(
|
|
61
|
+
"--store-image",
|
|
62
|
+
type=str,
|
|
63
|
+
default=None,
|
|
64
|
+
help="Algorithm store docker image to use when setting up resources for "
|
|
65
|
+
"the development algorithm store",
|
|
66
|
+
)
|
|
67
|
+
@click.option(
|
|
68
|
+
"--node-image",
|
|
69
|
+
type=str,
|
|
70
|
+
default=None,
|
|
71
|
+
help="Node docker image to use when setting up resources for the development node",
|
|
72
|
+
)
|
|
73
|
+
@click.option(
|
|
74
|
+
"--extra-server-config",
|
|
75
|
+
type=click.Path(exists=True),
|
|
76
|
+
default=None,
|
|
77
|
+
help="YAML File with additional server "
|
|
78
|
+
"configuration. This will be appended to the server "
|
|
79
|
+
"configuration file",
|
|
80
|
+
)
|
|
81
|
+
@click.option(
|
|
82
|
+
"--extra-node-config",
|
|
83
|
+
type=click.Path("rb"),
|
|
84
|
+
default=None,
|
|
85
|
+
help="YAML File with additional node configuration. This will be"
|
|
86
|
+
" appended to each of the node configuration files",
|
|
87
|
+
)
|
|
88
|
+
@click.option(
|
|
89
|
+
"--extra-store-config",
|
|
90
|
+
type=click.Path("rb"),
|
|
91
|
+
default=None,
|
|
92
|
+
help="YAML File with additional algorithm store configuration. This will be"
|
|
93
|
+
" appended to the algorithm store configuration file",
|
|
94
|
+
)
|
|
95
|
+
@click.option(
|
|
96
|
+
"--extra-auth-config",
|
|
97
|
+
type=click.Path("rb"),
|
|
98
|
+
default=None,
|
|
99
|
+
help="YAML File with additional auth configuration. This will be"
|
|
100
|
+
" appended to the auth configuration file",
|
|
101
|
+
)
|
|
102
|
+
@click.option(
|
|
103
|
+
"--add-dataset",
|
|
104
|
+
type=(str, click.Path()),
|
|
105
|
+
default=None,
|
|
106
|
+
multiple=True,
|
|
107
|
+
help="Add a dataset to the nodes. The first argument is the label of the database, "
|
|
108
|
+
"the second is the path to the dataset file.",
|
|
109
|
+
)
|
|
110
|
+
@click.option("--context", default=None, help="Kubernetes context to use")
|
|
111
|
+
@click.option("--namespace", default=None, help="Kubernetes namespace to use")
|
|
112
|
+
@click.option(
|
|
113
|
+
"--k8s-node-name", default="docker-desktop", help="Kubernetes node name to use"
|
|
114
|
+
)
|
|
115
|
+
@click.option(
|
|
116
|
+
"--data-dir",
|
|
117
|
+
type=click.Path(exists=True),
|
|
118
|
+
default=None,
|
|
119
|
+
help="Path to a custom data directory to use. This option is especially useful "
|
|
120
|
+
"on WSL because of mount issues for default directories",
|
|
121
|
+
)
|
|
122
|
+
@click.option(
|
|
123
|
+
"--local-chart-dir",
|
|
124
|
+
type=click.Path(exists=True),
|
|
125
|
+
default=None,
|
|
126
|
+
help="Local chart repository to use.",
|
|
127
|
+
)
|
|
128
|
+
@click.pass_context
|
|
129
|
+
def cli_new_sandbox(
|
|
130
|
+
click_ctx: click.Context,
|
|
131
|
+
name: str,
|
|
132
|
+
num_nodes: int,
|
|
133
|
+
server_port: int,
|
|
134
|
+
ui_port: int,
|
|
135
|
+
algorithm_store_port: int,
|
|
136
|
+
server_image: str | None,
|
|
137
|
+
ui_image: str | None,
|
|
138
|
+
store_image: str | None,
|
|
139
|
+
node_image: str | None,
|
|
140
|
+
extra_server_config: Path | None,
|
|
141
|
+
extra_node_config: Path | None,
|
|
142
|
+
extra_store_config: Path | None,
|
|
143
|
+
extra_auth_config: Path | None,
|
|
144
|
+
add_dataset: tuple[str, Path] | None,
|
|
145
|
+
context: str | None,
|
|
146
|
+
namespace: str | None,
|
|
147
|
+
k8s_node_name: str,
|
|
148
|
+
data_dir: str | None,
|
|
149
|
+
local_chart_dir: Path | None,
|
|
150
|
+
) -> None:
|
|
151
|
+
"""
|
|
152
|
+
Create a sandbox environment.
|
|
153
|
+
"""
|
|
154
|
+
|
|
155
|
+
# Prompt for the k8s namespace and context
|
|
156
|
+
context, namespace = select_context_and_namespace(
|
|
157
|
+
context=context,
|
|
158
|
+
namespace=namespace,
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
if data_dir is not None:
|
|
162
|
+
data_dir = Path(data_dir)
|
|
163
|
+
if not data_dir.exists():
|
|
164
|
+
error(f"Data directory {data_dir} does not exist!")
|
|
165
|
+
exit(1)
|
|
166
|
+
|
|
167
|
+
server_name = prompt_config_name(name)
|
|
168
|
+
if ServerContext.config_exists(server_name, False, is_sandbox=True):
|
|
169
|
+
error(f"Configuration {Fore.RED}{server_name}{Style.RESET_ALL} already exists!")
|
|
170
|
+
exit(1)
|
|
171
|
+
|
|
172
|
+
sb_config_manager = CoreSandboxConfigManager(
|
|
173
|
+
server_name=server_name,
|
|
174
|
+
server_port=server_port,
|
|
175
|
+
ui_port=ui_port,
|
|
176
|
+
algorithm_store_port=algorithm_store_port,
|
|
177
|
+
server_image=server_image,
|
|
178
|
+
ui_image=ui_image,
|
|
179
|
+
store_image=store_image,
|
|
180
|
+
extra_server_config=extra_server_config,
|
|
181
|
+
extra_store_config=extra_store_config,
|
|
182
|
+
extra_auth_config=extra_auth_config,
|
|
183
|
+
context=context,
|
|
184
|
+
namespace=namespace,
|
|
185
|
+
k8s_node_name=k8s_node_name,
|
|
186
|
+
custom_data_dir=data_dir,
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
sb_config_manager.generate_server_configs()
|
|
190
|
+
|
|
191
|
+
ctx = get_server_context(server_name, False, ServerContext, is_sandbox=True)
|
|
192
|
+
|
|
193
|
+
execute_sandbox_start(
|
|
194
|
+
click_ctx=click_ctx,
|
|
195
|
+
ctx=ctx,
|
|
196
|
+
server_name=server_name,
|
|
197
|
+
context=context,
|
|
198
|
+
namespace=namespace,
|
|
199
|
+
num_nodes=num_nodes,
|
|
200
|
+
initialize=True,
|
|
201
|
+
node_image=node_image,
|
|
202
|
+
k8s_node_name=k8s_node_name,
|
|
203
|
+
extra_node_config=extra_node_config,
|
|
204
|
+
add_dataset=add_dataset,
|
|
205
|
+
custom_data_dir=data_dir,
|
|
206
|
+
local_chart_dir=local_chart_dir,
|
|
207
|
+
)
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Script to populate the server with basic fixtures.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import time
|
|
6
|
+
import traceback
|
|
7
|
+
from logging import info
|
|
8
|
+
|
|
9
|
+
from vantage6.common import error
|
|
10
|
+
|
|
11
|
+
from vantage6.client import Client
|
|
12
|
+
from vantage6.client.utils import LogLevel
|
|
13
|
+
|
|
14
|
+
from vantage6.cli.sandbox.populate.helpers.connect_store import connect_store
|
|
15
|
+
from vantage6.cli.sandbox.populate.helpers.delete_fixtures import delete_fixtures
|
|
16
|
+
from vantage6.cli.sandbox.populate.helpers.load_fixtures import create_fixtures
|
|
17
|
+
from vantage6.cli.sandbox.populate.helpers.utils import NodeConfigCreationDetails
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def populate_server_dev(
|
|
21
|
+
server_url: str,
|
|
22
|
+
auth_url: str,
|
|
23
|
+
number_of_nodes: int,
|
|
24
|
+
node_config_creation_details: NodeConfigCreationDetails,
|
|
25
|
+
) -> str | None:
|
|
26
|
+
"""
|
|
27
|
+
Populate the server with basic fixtures.
|
|
28
|
+
|
|
29
|
+
Parameters
|
|
30
|
+
----------
|
|
31
|
+
server_url : str
|
|
32
|
+
The URL of the server to connect to.
|
|
33
|
+
auth_url : str
|
|
34
|
+
The URL of the auth service to connect to.
|
|
35
|
+
number_of_nodes : int
|
|
36
|
+
The number of nodes to create.
|
|
37
|
+
node_config_creation_details : NodeConfigCreationDetails | None
|
|
38
|
+
The details of the node config creation. If None, the node configs will not be
|
|
39
|
+
created.
|
|
40
|
+
clear_dev_folders : bool
|
|
41
|
+
Whether to clear everything inthe dev directory before creating the new
|
|
42
|
+
resources.
|
|
43
|
+
create_node_configs: bool
|
|
44
|
+
Whether to create the node configs. Default is True.
|
|
45
|
+
|
|
46
|
+
Returns
|
|
47
|
+
-------
|
|
48
|
+
str | None
|
|
49
|
+
A report of the creation process, or None if an error occurred.
|
|
50
|
+
|
|
51
|
+
Raises
|
|
52
|
+
------
|
|
53
|
+
Exception
|
|
54
|
+
If connection/authentication to the server fails.
|
|
55
|
+
"""
|
|
56
|
+
client = _initalize_client(server_url, auth_url)
|
|
57
|
+
|
|
58
|
+
# Create new resources in the server
|
|
59
|
+
# Delete existing resources in the server first, before creating new ones.
|
|
60
|
+
try:
|
|
61
|
+
report_deletion = delete_fixtures(client)
|
|
62
|
+
report_creation = create_fixtures(
|
|
63
|
+
client,
|
|
64
|
+
number_of_nodes,
|
|
65
|
+
node_config_creation_details=node_config_creation_details,
|
|
66
|
+
clear_dev_folders=True,
|
|
67
|
+
)
|
|
68
|
+
report_store = connect_store(client)
|
|
69
|
+
|
|
70
|
+
return report_deletion + "\n" + report_creation + "\n" + report_store
|
|
71
|
+
|
|
72
|
+
except Exception:
|
|
73
|
+
error("=" * 80)
|
|
74
|
+
error("Failed to populate server")
|
|
75
|
+
error(traceback.format_exc())
|
|
76
|
+
error("=" * 80)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def populate_server_sandbox(
|
|
80
|
+
server_url: str,
|
|
81
|
+
auth_url: str,
|
|
82
|
+
number_of_nodes: int,
|
|
83
|
+
) -> dict:
|
|
84
|
+
"""
|
|
85
|
+
Populate sandbox server with basic resources.
|
|
86
|
+
|
|
87
|
+
Parameters
|
|
88
|
+
----------
|
|
89
|
+
server_url : str
|
|
90
|
+
The URL of the server to connect to.
|
|
91
|
+
auth_url : str
|
|
92
|
+
The URL of the auth service to connect to.
|
|
93
|
+
number_of_nodes : int
|
|
94
|
+
The number of nodes to create.
|
|
95
|
+
|
|
96
|
+
Returns
|
|
97
|
+
-------
|
|
98
|
+
dict
|
|
99
|
+
A dictionary containing the report of the creation process.
|
|
100
|
+
|
|
101
|
+
Raises
|
|
102
|
+
------
|
|
103
|
+
Exception
|
|
104
|
+
If connection/authentication to the server fails.
|
|
105
|
+
"""
|
|
106
|
+
client = _initalize_client(server_url, auth_url)
|
|
107
|
+
|
|
108
|
+
try:
|
|
109
|
+
delete_fixtures(client)
|
|
110
|
+
report_creation = create_fixtures(
|
|
111
|
+
client,
|
|
112
|
+
number_of_nodes,
|
|
113
|
+
clear_dev_folders=False,
|
|
114
|
+
return_as_dict=True,
|
|
115
|
+
)
|
|
116
|
+
connect_store(client)
|
|
117
|
+
except Exception:
|
|
118
|
+
error("=" * 80)
|
|
119
|
+
error("Failed to populate server")
|
|
120
|
+
error(traceback.format_exc())
|
|
121
|
+
error("=" * 80)
|
|
122
|
+
exit(1)
|
|
123
|
+
|
|
124
|
+
# return the details of the created nodes so that config files can be created
|
|
125
|
+
return report_creation["nodes"]["created"]
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def _initalize_client(server_url, auth_url) -> Client:
|
|
129
|
+
"""
|
|
130
|
+
Initialize an authenticated client to the server.
|
|
131
|
+
|
|
132
|
+
The server may not be ready yet, so we retry until it is.
|
|
133
|
+
|
|
134
|
+
Parameters
|
|
135
|
+
----------
|
|
136
|
+
server_url : str
|
|
137
|
+
The URL of the server to connect to.
|
|
138
|
+
auth_url : str
|
|
139
|
+
The URL of the auth service to connect to.
|
|
140
|
+
|
|
141
|
+
Returns
|
|
142
|
+
-------
|
|
143
|
+
Client
|
|
144
|
+
An authenticated client to the server.
|
|
145
|
+
"""
|
|
146
|
+
client = Client(
|
|
147
|
+
server_url=server_url,
|
|
148
|
+
auth_url=auth_url,
|
|
149
|
+
log_level=LogLevel.ERROR,
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
info("Waiting for authentication...")
|
|
153
|
+
max_attempts = 120
|
|
154
|
+
attempt = 1
|
|
155
|
+
|
|
156
|
+
while attempt <= max_attempts:
|
|
157
|
+
try:
|
|
158
|
+
print(".", end="", flush=True)
|
|
159
|
+
client.authenticate()
|
|
160
|
+
info("Successfully authenticated with server!")
|
|
161
|
+
break
|
|
162
|
+
except Exception as e:
|
|
163
|
+
if attempt == max_attempts:
|
|
164
|
+
error(
|
|
165
|
+
f"Failed to authenticate after {max_attempts} attempts. "
|
|
166
|
+
"Server may not be online."
|
|
167
|
+
)
|
|
168
|
+
raise e
|
|
169
|
+
|
|
170
|
+
time.sleep(5)
|
|
171
|
+
attempt += 1
|
|
172
|
+
|
|
173
|
+
return client
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Development script to connect the server to the local store.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import time
|
|
6
|
+
from http import HTTPStatus
|
|
7
|
+
|
|
8
|
+
import requests
|
|
9
|
+
|
|
10
|
+
from vantage6.common import error, info
|
|
11
|
+
from vantage6.common.enum import AlgorithmStepType
|
|
12
|
+
|
|
13
|
+
from vantage6.client import Client
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _wait_for_store_to_be_online(
|
|
17
|
+
local_store_url: str, local_store_api_path: str
|
|
18
|
+
) -> None:
|
|
19
|
+
"""
|
|
20
|
+
Wait for the store to be online.
|
|
21
|
+
|
|
22
|
+
Parameters
|
|
23
|
+
---------
|
|
24
|
+
client: Client
|
|
25
|
+
The client to use to connect to the server.
|
|
26
|
+
local_store_url: str
|
|
27
|
+
The URL of the local store.
|
|
28
|
+
local_store_api_path: str
|
|
29
|
+
The API path of the local store.
|
|
30
|
+
"""
|
|
31
|
+
info(
|
|
32
|
+
f"Waiting for store to be online at {local_store_url}{local_store_api_path}..."
|
|
33
|
+
)
|
|
34
|
+
max_retries = 100
|
|
35
|
+
wait_time = 3
|
|
36
|
+
ready = False
|
|
37
|
+
for _ in range(max_retries):
|
|
38
|
+
try:
|
|
39
|
+
result = requests.get(f"{local_store_url}{local_store_api_path}/version")
|
|
40
|
+
if result.status_code == HTTPStatus.OK:
|
|
41
|
+
ready = True
|
|
42
|
+
break
|
|
43
|
+
except Exception:
|
|
44
|
+
info(f"Store not ready yet, waiting {wait_time} seconds...")
|
|
45
|
+
time.sleep(wait_time)
|
|
46
|
+
|
|
47
|
+
if not ready:
|
|
48
|
+
error("Store did not become ready in time. Exiting...")
|
|
49
|
+
exit(1)
|
|
50
|
+
else:
|
|
51
|
+
info("Store is online!")
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def connect_store(client: Client) -> str:
|
|
55
|
+
"""
|
|
56
|
+
Connect the server to the local store.
|
|
57
|
+
|
|
58
|
+
Parameters
|
|
59
|
+
---------
|
|
60
|
+
client: Client
|
|
61
|
+
The client to use to connect to the server.
|
|
62
|
+
dev_dir: Path
|
|
63
|
+
The directory to use to store the development data.
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
existing_stores = client.store.list().get("data", [])
|
|
67
|
+
summary = "=== Store Connection Summary ===\n"
|
|
68
|
+
|
|
69
|
+
# URL should be retrieved from the store, see issue:
|
|
70
|
+
# https://github.com/vantage6/vantage6/issues/1824
|
|
71
|
+
local_store_url = "http://localhost:7602"
|
|
72
|
+
local_store_api_path = "/store"
|
|
73
|
+
client.store.store_id = 1
|
|
74
|
+
|
|
75
|
+
_wait_for_store_to_be_online(local_store_url, local_store_api_path)
|
|
76
|
+
|
|
77
|
+
# note that the store is already coupled to the server in the sandbox/devspace
|
|
78
|
+
# config. To find the store, either check that it is a localhost URL or that it
|
|
79
|
+
# contains "svc.cluster.local" (which is for local k8s services)
|
|
80
|
+
try:
|
|
81
|
+
store = next(s for s in existing_stores if s["url"] == local_store_url)
|
|
82
|
+
client.store.set(store["id"])
|
|
83
|
+
except StopIteration:
|
|
84
|
+
error(
|
|
85
|
+
"Local algorithm store not found. Please register its resources manually."
|
|
86
|
+
)
|
|
87
|
+
return
|
|
88
|
+
|
|
89
|
+
# register also the other users in the local store
|
|
90
|
+
users_in_store = client.store.user.list()["data"]
|
|
91
|
+
all_users = client.user.list()["data"]
|
|
92
|
+
for user in all_users:
|
|
93
|
+
if user["keycloak_id"] not in [u["keycloak_id"] for u in users_in_store]:
|
|
94
|
+
summary += f"Registering user {user['username']} in local store\n"
|
|
95
|
+
client.store.user.register(username=user["username"], roles=[1])
|
|
96
|
+
|
|
97
|
+
# Remove existing algorithm
|
|
98
|
+
# This is broken, see issue: https://github.com/vantage6/vantage6/issues/1824
|
|
99
|
+
algorithms = client.algorithm.list(name="session basic example")["data"]
|
|
100
|
+
if len(algorithms) > 0:
|
|
101
|
+
summary += f"Removing existing algorithm {algorithms[0]['name']}\n"
|
|
102
|
+
client.algorithm.delete(id_=algorithms[0]["id"])
|
|
103
|
+
|
|
104
|
+
# Download the algorithm store from the github repo. This ensures that the data is
|
|
105
|
+
# always up to date.
|
|
106
|
+
try:
|
|
107
|
+
url = (
|
|
108
|
+
"https://raw.githubusercontent.com/vantage6/v6-session-basics/"
|
|
109
|
+
"main/algorithm_store.json"
|
|
110
|
+
)
|
|
111
|
+
response = requests.get(url, timeout=10)
|
|
112
|
+
response.raise_for_status()
|
|
113
|
+
algorithm_json = response.json()
|
|
114
|
+
function_metadata = algorithm_json["functions"]
|
|
115
|
+
except requests.exceptions.RequestException as e:
|
|
116
|
+
# Fallback to local file if download fails
|
|
117
|
+
print(f"Warning: Could not download algorithm store from GitHub: {e}")
|
|
118
|
+
print("Not putting the algorithm in the store.")
|
|
119
|
+
function_metadata = []
|
|
120
|
+
|
|
121
|
+
summary += "Creating Session Basics algorithm\n"
|
|
122
|
+
client.algorithm.create(
|
|
123
|
+
name="Session Basics",
|
|
124
|
+
description="A set of basic algorithms for a session management",
|
|
125
|
+
image="harbor2.vantage6.ai/algorithms/session-basics:latest",
|
|
126
|
+
vantage6_version="5.0.0",
|
|
127
|
+
code_url="https://github.com/vantage6-ai/v6-session-basics",
|
|
128
|
+
partitioning="horizontal",
|
|
129
|
+
functions=function_metadata or [],
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
# TODO: v5+ get this json data by downloading it from the github repo - that ensures
|
|
133
|
+
# that the data is always up to date.
|
|
134
|
+
summary += "Creating Network Diagnostics algorithm\n"
|
|
135
|
+
client.algorithm.create(
|
|
136
|
+
name="Network Diagnostics",
|
|
137
|
+
description=(
|
|
138
|
+
"Functions to diagnose network policies, that is, to what extent the "
|
|
139
|
+
"jobs running on a V6 Node could have access to the internal k8s network "
|
|
140
|
+
"or to the outside world."
|
|
141
|
+
),
|
|
142
|
+
image="ghcr.io/hcadavid/v6-sessions-k8s-diagnostics:latest",
|
|
143
|
+
vantage6_version="5.0.0",
|
|
144
|
+
code_url="https://github.com/hcadavid/v6-sessions-k8s-diagnostics",
|
|
145
|
+
partitioning="horizontal",
|
|
146
|
+
functions=[
|
|
147
|
+
{
|
|
148
|
+
"name": "network_status",
|
|
149
|
+
"display_name": "Get the network diagnostics performed on a given node",
|
|
150
|
+
"standalone": True,
|
|
151
|
+
"description": "Get the network diagnostics performed on a given node",
|
|
152
|
+
"ui_visualizations": [],
|
|
153
|
+
"step_type": AlgorithmStepType.FEDERATED_COMPUTE.value,
|
|
154
|
+
"arguments": [
|
|
155
|
+
{
|
|
156
|
+
"has_default_value": True,
|
|
157
|
+
"name": "sleep_time",
|
|
158
|
+
"display_name": "Delay ",
|
|
159
|
+
"description": (
|
|
160
|
+
"Delay in seconds before finishing the the diagnostics "
|
|
161
|
+
"task (useful to keep the POD running and access it to "
|
|
162
|
+
"perform further tests) "
|
|
163
|
+
),
|
|
164
|
+
"type": "integer",
|
|
165
|
+
"default_value": "1",
|
|
166
|
+
"is_frontend_only": False,
|
|
167
|
+
}
|
|
168
|
+
],
|
|
169
|
+
"databases": [],
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
"name": "central_network_diagnostics",
|
|
173
|
+
"display_name": (
|
|
174
|
+
"Get the network diagnostics performed on all the nodes"
|
|
175
|
+
),
|
|
176
|
+
"standalone": True,
|
|
177
|
+
"description": (
|
|
178
|
+
"Get the network diagnostics performed on all the nodes within a "
|
|
179
|
+
"collaboration"
|
|
180
|
+
),
|
|
181
|
+
"ui_visualizations": [],
|
|
182
|
+
"step_type": AlgorithmStepType.CENTRAL_COMPUTE.value,
|
|
183
|
+
"arguments": [
|
|
184
|
+
{
|
|
185
|
+
"has_default_value": True,
|
|
186
|
+
"name": "sleep_time",
|
|
187
|
+
"display_name": "Delay ",
|
|
188
|
+
"description": (
|
|
189
|
+
"Delay in seconds before finishing the the diagnostics "
|
|
190
|
+
"task (useful to keep the PODs running on all the nodes "
|
|
191
|
+
"to access them and perform further inspections) "
|
|
192
|
+
),
|
|
193
|
+
"type": "integer",
|
|
194
|
+
"default_value": "1",
|
|
195
|
+
"is_frontend_only": False,
|
|
196
|
+
}
|
|
197
|
+
],
|
|
198
|
+
"databases": [],
|
|
199
|
+
},
|
|
200
|
+
],
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
return summary
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Development script to delete all entities from the server
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from vantage6.client import Client
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def delete_fixtures(client: Client) -> str:
|
|
9
|
+
"""
|
|
10
|
+
Delete all entities from the server.
|
|
11
|
+
|
|
12
|
+
Arguments
|
|
13
|
+
---------
|
|
14
|
+
client: Client
|
|
15
|
+
The client to use to delete the entities.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
# Track deletion counts
|
|
19
|
+
deletion_counts = {}
|
|
20
|
+
|
|
21
|
+
# Delete sessions & dataframes
|
|
22
|
+
sessions = client.session.list(per_page=999)["data"]
|
|
23
|
+
for session in sessions:
|
|
24
|
+
client.session.delete(session["id"], delete_dependents=True)
|
|
25
|
+
deletion_counts["sessions"] = len(sessions)
|
|
26
|
+
|
|
27
|
+
# Delete tasks and nodes
|
|
28
|
+
for client_subclass_name in ("task", "node"):
|
|
29
|
+
client_subclass = getattr(client, client_subclass_name)
|
|
30
|
+
entities = client_subclass.list(per_page=999)["data"]
|
|
31
|
+
for entity in entities:
|
|
32
|
+
client_subclass.delete(entity["id"])
|
|
33
|
+
deletion_counts[f"{client_subclass_name}s"] = len(entities)
|
|
34
|
+
|
|
35
|
+
# Delete collaborations
|
|
36
|
+
collabs = client.collaboration.list(per_page=999, scope="global")["data"]
|
|
37
|
+
for collab in collabs:
|
|
38
|
+
client.collaboration.delete(collab["id"])
|
|
39
|
+
deletion_counts["collaborations"] = len(collabs)
|
|
40
|
+
|
|
41
|
+
# Delete users (excluding admin)
|
|
42
|
+
users = client.user.list(per_page=999)["data"]
|
|
43
|
+
deleted_users = 0
|
|
44
|
+
for user in users:
|
|
45
|
+
if user["username"] == "admin":
|
|
46
|
+
continue
|
|
47
|
+
client.user.delete(user["id"])
|
|
48
|
+
deleted_users += 1
|
|
49
|
+
deletion_counts["users"] = deleted_users
|
|
50
|
+
|
|
51
|
+
# Delete organizations (excluding the default organization with id 1)
|
|
52
|
+
orgs = client.organization.list(per_page=999)["data"]
|
|
53
|
+
deleted_orgs = 0
|
|
54
|
+
for org in orgs:
|
|
55
|
+
if org["id"] == 1:
|
|
56
|
+
continue
|
|
57
|
+
client.organization.delete(org["id"])
|
|
58
|
+
deleted_orgs += 1
|
|
59
|
+
deletion_counts["organizations"] = deleted_orgs
|
|
60
|
+
|
|
61
|
+
# Create summary string
|
|
62
|
+
summary = "=== Deletion Summary ===\n"
|
|
63
|
+
for entity_type, count in deletion_counts.items():
|
|
64
|
+
summary += f"Deleted {count} {entity_type}\n"
|
|
65
|
+
summary += "======================="
|
|
66
|
+
print(summary)
|
|
67
|
+
return summary
|