vantage6 5.0.0a33__py3-none-any.whl → 5.0.0a35__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/algostore/new.py +106 -47
- vantage6/cli/algostore/remove.py +18 -34
- vantage6/cli/algostore/start.py +36 -67
- vantage6/cli/algostore/stop.py +43 -46
- vantage6/cli/cli.py +31 -33
- vantage6/cli/common/new.py +85 -0
- vantage6/cli/common/remove.py +54 -0
- vantage6/cli/common/start.py +36 -213
- vantage6/cli/common/stop.py +78 -0
- vantage6/cli/common/utils.py +253 -16
- vantage6/cli/configuration_manager.py +90 -12
- vantage6/cli/configuration_wizard.py +49 -414
- vantage6/cli/context/algorithm_store.py +7 -6
- vantage6/cli/context/base_server.py +22 -30
- vantage6/cli/context/node.py +14 -17
- vantage6/cli/context/server.py +16 -7
- vantage6/cli/globals.py +29 -8
- vantage6/cli/node/attach.py +1 -0
- vantage6/cli/node/common/__init__.py +1 -1
- vantage6/cli/node/create_private_key.py +9 -6
- vantage6/cli/node/files.py +12 -25
- vantage6/cli/node/new.py +348 -28
- vantage6/cli/node/remove.py +14 -90
- vantage6/cli/node/restart.py +30 -51
- vantage6/cli/node/set_api_key.py +7 -4
- vantage6/cli/node/start.py +81 -304
- vantage6/cli/node/stop.py +36 -96
- vantage6/cli/server/import_.py +1 -2
- vantage6/cli/server/list.py +0 -3
- vantage6/cli/server/new.py +72 -42
- vantage6/cli/server/remove.py +12 -33
- vantage6/cli/server/shell.py +1 -1
- vantage6/cli/server/start.py +22 -20
- vantage6/cli/server/stop.py +37 -17
- vantage6/cli/template/algo_store_config.j2 +195 -22
- vantage6/cli/template/node_config.j2 +336 -33
- vantage6/cli/template/server_config.j2 +255 -33
- vantage6/cli/utils.py +0 -2
- {vantage6-5.0.0a33.dist-info → vantage6-5.0.0a35.dist-info}/METADATA +4 -4
- vantage6-5.0.0a35.dist-info/RECORD +75 -0
- vantage6/cli/node/clean.py +0 -46
- vantage6/cli/template/server_import_config.j2 +0 -31
- vantage6-5.0.0a33.dist-info/RECORD +0 -75
- {vantage6-5.0.0a33.dist-info → vantage6-5.0.0a35.dist-info}/WHEEL +0 -0
- {vantage6-5.0.0a33.dist-info → vantage6-5.0.0a35.dist-info}/entry_points.txt +0 -0
|
@@ -1,289 +1,26 @@
|
|
|
1
|
-
import os
|
|
2
1
|
from pathlib import Path
|
|
3
|
-
from typing import Any
|
|
4
2
|
|
|
5
3
|
import questionary as q
|
|
6
4
|
|
|
7
|
-
from vantage6.common import error, info
|
|
8
|
-
from vantage6.common.client.node_client import NodeClient
|
|
5
|
+
from vantage6.common import error, info
|
|
9
6
|
from vantage6.common.context import AppContext
|
|
10
7
|
from vantage6.common.globals import (
|
|
11
|
-
DATABASE_TYPES,
|
|
12
8
|
DEFAULT_API_PATH,
|
|
13
9
|
InstanceType,
|
|
14
|
-
NodePolicy,
|
|
15
10
|
Ports,
|
|
16
|
-
RequiredNodeEnvVars,
|
|
17
11
|
)
|
|
18
12
|
|
|
19
|
-
from vantage6.cli.config import CliConfig
|
|
20
13
|
from vantage6.cli.configuration_manager import (
|
|
14
|
+
AlgorithmStoreConfigurationManager,
|
|
21
15
|
NodeConfigurationManager,
|
|
22
16
|
ServerConfigurationManager,
|
|
23
17
|
)
|
|
24
18
|
from vantage6.cli.context import select_context_class
|
|
25
19
|
|
|
26
20
|
|
|
27
|
-
def
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
Parameters
|
|
32
|
-
----------
|
|
33
|
-
dirs : dict
|
|
34
|
-
Dictionary with the directories of the node instance.
|
|
35
|
-
instance_name : str
|
|
36
|
-
Name of the node instance.
|
|
37
|
-
|
|
38
|
-
Returns
|
|
39
|
-
-------
|
|
40
|
-
dict
|
|
41
|
-
Dictionary with the new node configuration
|
|
42
|
-
"""
|
|
43
|
-
config = q.unsafe_prompt(
|
|
44
|
-
[
|
|
45
|
-
{"type": "text", "name": "api_key", "message": "Enter given api-key:"},
|
|
46
|
-
{
|
|
47
|
-
"type": "text",
|
|
48
|
-
"name": "server_url",
|
|
49
|
-
"message": "The base-URL of the server:",
|
|
50
|
-
"default": "http://localhost",
|
|
51
|
-
},
|
|
52
|
-
]
|
|
53
|
-
)
|
|
54
|
-
# remove trailing slash from server_url if entered by user
|
|
55
|
-
config["server_url"] = config["server_url"].rstrip("/")
|
|
56
|
-
|
|
57
|
-
# set default port to the https port if server_url is https
|
|
58
|
-
default_port = (
|
|
59
|
-
str(Ports.HTTPS)
|
|
60
|
-
if config["server_url"].startswith("https")
|
|
61
|
-
else str(Ports.DEV_SERVER)
|
|
62
|
-
)
|
|
63
|
-
|
|
64
|
-
config = config | q.unsafe_prompt(
|
|
65
|
-
[
|
|
66
|
-
{
|
|
67
|
-
"type": "text",
|
|
68
|
-
"name": "port",
|
|
69
|
-
"message": "Enter port to which the server listens:",
|
|
70
|
-
"default": default_port,
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
"type": "text",
|
|
74
|
-
"name": "api_path",
|
|
75
|
-
"message": "Path of the api:",
|
|
76
|
-
"default": "/api",
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
"type": "text",
|
|
80
|
-
"name": "task_dir",
|
|
81
|
-
"message": "Task directory path:",
|
|
82
|
-
"default": str(dirs["data"]),
|
|
83
|
-
},
|
|
84
|
-
]
|
|
85
|
-
)
|
|
86
|
-
|
|
87
|
-
config["databases"] = list()
|
|
88
|
-
while q.confirm("Do you want to add a database?").unsafe_ask():
|
|
89
|
-
db_label = q.unsafe_prompt(
|
|
90
|
-
[
|
|
91
|
-
{
|
|
92
|
-
"type": "text",
|
|
93
|
-
"name": "label",
|
|
94
|
-
"message": "Enter unique label for the database:",
|
|
95
|
-
"default": "default",
|
|
96
|
-
}
|
|
97
|
-
]
|
|
98
|
-
)
|
|
99
|
-
db_path = q.unsafe_prompt(
|
|
100
|
-
[{"type": "text", "name": "uri", "message": "Database URI:"}]
|
|
101
|
-
)
|
|
102
|
-
db_type = q.select("Database type:", choices=DATABASE_TYPES).unsafe_ask()
|
|
103
|
-
|
|
104
|
-
config["databases"].append(
|
|
105
|
-
{"label": db_label.get("label"), "uri": db_path.get("uri"), "type": db_type}
|
|
106
|
-
)
|
|
107
|
-
|
|
108
|
-
is_add_vpn = q.confirm(
|
|
109
|
-
"Do you want to connect to a VPN server?", default=False
|
|
110
|
-
).unsafe_ask()
|
|
111
|
-
if is_add_vpn:
|
|
112
|
-
config["vpn_subnet"] = q.text(
|
|
113
|
-
message="Subnet of the VPN server you want to connect to:",
|
|
114
|
-
default="10.76.0.0/16",
|
|
115
|
-
).unsafe_ask()
|
|
116
|
-
|
|
117
|
-
is_policies = q.confirm(
|
|
118
|
-
"Do you want to limit the algorithms allowed to run on your node? This "
|
|
119
|
-
"should always be done for production scenarios.",
|
|
120
|
-
default=True,
|
|
121
|
-
).unsafe_ask()
|
|
122
|
-
policies = {}
|
|
123
|
-
if is_policies:
|
|
124
|
-
info(
|
|
125
|
-
"You can limit the algorithms that can run on your node in two ways: by "
|
|
126
|
-
"allowing specific algorithms or by allowing all algorithms in a given "
|
|
127
|
-
"algorithm store."
|
|
128
|
-
)
|
|
129
|
-
ask_single_algorithms = q.confirm(
|
|
130
|
-
"Do you want to enter a list of allowed algorithms?"
|
|
131
|
-
).unsafe_ask()
|
|
132
|
-
if ask_single_algorithms:
|
|
133
|
-
policies[NodePolicy.ALLOWED_ALGORITHMS.value] = _get_allowed_algorithms()
|
|
134
|
-
ask_algorithm_stores = q.confirm(
|
|
135
|
-
"Do you want to allow algorithms from specific algorithm stores?"
|
|
136
|
-
).unsafe_ask()
|
|
137
|
-
if ask_algorithm_stores:
|
|
138
|
-
policies[NodePolicy.ALLOWED_ALGORITHM_STORES.value] = (
|
|
139
|
-
_get_allowed_algorithm_stores()
|
|
140
|
-
)
|
|
141
|
-
if ask_single_algorithms and ask_algorithm_stores:
|
|
142
|
-
require_both_whitelists = q.confirm(
|
|
143
|
-
"Do you want to allow only algorithms that are both in the list of "
|
|
144
|
-
"allowed algorithms *AND* are part of one of the allowed algorithm "
|
|
145
|
-
"stores? If not, algorithms will be allowed if they are in either the "
|
|
146
|
-
"list of allowed algorithms or one of the allowed algorithm stores.",
|
|
147
|
-
default=True,
|
|
148
|
-
).unsafe_ask()
|
|
149
|
-
policies["allow_either_whitelist_or_store"] = not require_both_whitelists
|
|
150
|
-
if policies:
|
|
151
|
-
config["policies"] = policies
|
|
152
|
-
|
|
153
|
-
res = q.select(
|
|
154
|
-
"Which level of logging would you like?",
|
|
155
|
-
choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL", "NOTSET"],
|
|
156
|
-
).unsafe_ask()
|
|
157
|
-
|
|
158
|
-
config["logging"] = {
|
|
159
|
-
"level": res,
|
|
160
|
-
"use_console": True,
|
|
161
|
-
"backup_count": 5,
|
|
162
|
-
"max_size": 1024,
|
|
163
|
-
"format": "%(asctime)s - %(name)-14s - %(levelname)-8s - %(message)s",
|
|
164
|
-
"datefmt": "%Y-%m-%d %H:%M:%S",
|
|
165
|
-
"loggers": [
|
|
166
|
-
{"name": "urllib3", "level": "warning"},
|
|
167
|
-
{"name": "requests", "level": "warning"},
|
|
168
|
-
{"name": "engineio.client", "level": "warning"},
|
|
169
|
-
{"name": "docker.utils.config", "level": "warning"},
|
|
170
|
-
{"name": "docker.auth", "level": "warning"},
|
|
171
|
-
],
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
# Check if we can login to the server to retrieve collaboration settings
|
|
175
|
-
client = NodeClient(
|
|
176
|
-
instance_name,
|
|
177
|
-
config["api_key"],
|
|
178
|
-
server_url=f"{config['server_url']}:{config['port']}{config['api_path']}",
|
|
179
|
-
auth_url=os.environ.get(RequiredNodeEnvVars.KEYCLOAK_URL.value),
|
|
180
|
-
)
|
|
181
|
-
try:
|
|
182
|
-
client.authenticate()
|
|
183
|
-
except Exception as e:
|
|
184
|
-
error(f"Could not authenticate with server: {e}")
|
|
185
|
-
error("Please check (1) your API key and (2) if your server is online")
|
|
186
|
-
warning(
|
|
187
|
-
"If you continue, you should provide your collaboration settings manually."
|
|
188
|
-
)
|
|
189
|
-
if q.confirm("Do you want to abort?", default=True).unsafe_ask():
|
|
190
|
-
exit(0)
|
|
191
|
-
|
|
192
|
-
if client.whoami is not None:
|
|
193
|
-
encryption = client.is_encrypted_collaboration()
|
|
194
|
-
# TODO when we build collaboration policies, update this to provide
|
|
195
|
-
# the node admin with a list of all policies, and whether or not
|
|
196
|
-
# to accept them
|
|
197
|
-
q.confirm(
|
|
198
|
-
f"Encryption is {'enabled' if encryption else 'disabled'}"
|
|
199
|
-
f" for this collaboration. Accept?",
|
|
200
|
-
default=True,
|
|
201
|
-
).unsafe_ask()
|
|
202
|
-
else:
|
|
203
|
-
encryption = q.confirm("Enable encryption?", default=True).unsafe_ask()
|
|
204
|
-
|
|
205
|
-
private_key = (
|
|
206
|
-
"" if not encryption else q.text("Path to private key file:").unsafe_ask()
|
|
207
|
-
)
|
|
208
|
-
|
|
209
|
-
config["encryption"] = {
|
|
210
|
-
"enabled": encryption is True or encryption == "true",
|
|
211
|
-
"private_key": private_key,
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
return config
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
def _get_allowed_algorithms() -> list[str]:
|
|
218
|
-
"""
|
|
219
|
-
Prompt the user for the allowed algorithms on their node
|
|
220
|
-
|
|
221
|
-
Returns
|
|
222
|
-
-------
|
|
223
|
-
list[str]
|
|
224
|
-
List of allowed algorithms or regular expressions to match them
|
|
225
|
-
"""
|
|
226
|
-
info("Below you can add algorithms that are allowed to run on your node.")
|
|
227
|
-
info(
|
|
228
|
-
"You can use regular expressions to match multiple algorithms, or you can "
|
|
229
|
-
"use strings to provide one algorithm at a time."
|
|
230
|
-
)
|
|
231
|
-
info("Examples:")
|
|
232
|
-
info(r"^harbor2\.vantage6\.ai/demo/average$ Allow the demo average algorithm")
|
|
233
|
-
info(
|
|
234
|
-
r"^harbor2\.vantage6\.ai/algorithms/.* Allow all algorithms from "
|
|
235
|
-
"harbor2.vantage6.ai/algorithms"
|
|
236
|
-
)
|
|
237
|
-
info(
|
|
238
|
-
r"^harbor2\.vantage6\.ai/demo/average@sha256:82becede...$ Allow a "
|
|
239
|
-
"specific hash of average algorithm"
|
|
240
|
-
)
|
|
241
|
-
allowed_algorithms = []
|
|
242
|
-
while True:
|
|
243
|
-
algo = q.text(message="Enter your algorithm expression:").unsafe_ask()
|
|
244
|
-
allowed_algorithms.append(algo)
|
|
245
|
-
if not q.confirm(
|
|
246
|
-
"Do you want to add another algorithm expression?", default=True
|
|
247
|
-
).unsafe_ask():
|
|
248
|
-
break
|
|
249
|
-
return allowed_algorithms
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
def _get_allowed_algorithm_stores() -> list[str]:
|
|
253
|
-
"""
|
|
254
|
-
Prompt the user for the allowed algorithm stores on their node
|
|
255
|
-
|
|
256
|
-
Returns
|
|
257
|
-
-------
|
|
258
|
-
list[str]
|
|
259
|
-
List of allowed algorithm stores
|
|
260
|
-
"""
|
|
261
|
-
info("Below you can add algorithm stores that are allowed to run on your node.")
|
|
262
|
-
info(
|
|
263
|
-
"You can use regular expressions to match multiple algorithm stores, or you can"
|
|
264
|
-
" use strings to provide one algorithm store at a time."
|
|
265
|
-
)
|
|
266
|
-
info("Examples:")
|
|
267
|
-
info(
|
|
268
|
-
"https://store.cotopaxi.vantage6.ai Allow all algorithms from the "
|
|
269
|
-
"community store"
|
|
270
|
-
)
|
|
271
|
-
info(
|
|
272
|
-
r"^https://*\.vantage6\.ai$ Allow all algorithms from any "
|
|
273
|
-
"store hosted on vantage6.ai"
|
|
274
|
-
)
|
|
275
|
-
allowed_algorithm_stores = []
|
|
276
|
-
while True:
|
|
277
|
-
store = q.text(message="Enter the URL of the algorithm store:").unsafe_ask()
|
|
278
|
-
allowed_algorithm_stores.append(store)
|
|
279
|
-
if not q.confirm(
|
|
280
|
-
"Do you want to add another algorithm store?", default=True
|
|
281
|
-
).unsafe_ask():
|
|
282
|
-
break
|
|
283
|
-
return allowed_algorithm_stores
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
def _get_common_server_config(instance_type: InstanceType, instance_name: str) -> dict:
|
|
21
|
+
def add_common_server_config(
|
|
22
|
+
config: dict, instance_type: InstanceType, instance_name: str
|
|
23
|
+
) -> dict:
|
|
287
24
|
"""
|
|
288
25
|
Part of the questionaire that is common to all server types (vantage6
|
|
289
26
|
server and algorithm store server).
|
|
@@ -300,52 +37,26 @@ def _get_common_server_config(instance_type: InstanceType, instance_name: str) -
|
|
|
300
37
|
dict
|
|
301
38
|
Dictionary with new (partial) server configuration
|
|
302
39
|
"""
|
|
303
|
-
|
|
304
|
-
[
|
|
305
|
-
{
|
|
306
|
-
"type": "text",
|
|
307
|
-
"name": "description",
|
|
308
|
-
"message": "Enter a human-readable description:",
|
|
309
|
-
},
|
|
310
|
-
{"type": "text", "name": "ip", "message": "ip:", "default": "0.0.0.0"},
|
|
311
|
-
{
|
|
312
|
-
"type": "text",
|
|
313
|
-
"name": "port",
|
|
314
|
-
"message": "Enter port to which the server listens:",
|
|
315
|
-
"default": (
|
|
316
|
-
str(Ports.DEV_SERVER)
|
|
317
|
-
if instance_type == InstanceType.SERVER
|
|
318
|
-
else str(Ports.DEV_ALGO_STORE)
|
|
319
|
-
),
|
|
320
|
-
},
|
|
321
|
-
]
|
|
40
|
+
backend_config = (
|
|
41
|
+
config["server"] if instance_type == InstanceType.SERVER else config["store"]
|
|
322
42
|
)
|
|
323
43
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
},
|
|
333
|
-
{
|
|
334
|
-
"type": "select",
|
|
335
|
-
"name": "allow_drop_all",
|
|
336
|
-
"message": "Allowed to drop all tables: ",
|
|
337
|
-
"choices": ["True", "False"],
|
|
338
|
-
},
|
|
339
|
-
]
|
|
340
|
-
)
|
|
341
|
-
)
|
|
44
|
+
backend_config["port"] = q.text(
|
|
45
|
+
"Enter port to which the server listens:",
|
|
46
|
+
default=(
|
|
47
|
+
str(Ports.DEV_SERVER)
|
|
48
|
+
if instance_type == InstanceType.SERVER
|
|
49
|
+
else str(Ports.DEV_ALGO_STORE)
|
|
50
|
+
),
|
|
51
|
+
).unsafe_ask()
|
|
342
52
|
|
|
343
53
|
res = q.select(
|
|
344
54
|
"Which level of logging would you like?",
|
|
345
|
-
choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"
|
|
55
|
+
choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
|
|
56
|
+
default="INFO",
|
|
346
57
|
).unsafe_ask()
|
|
347
58
|
|
|
348
|
-
|
|
59
|
+
backend_config["logging"] = {
|
|
349
60
|
"level": res,
|
|
350
61
|
"file": f"{instance_name}.log",
|
|
351
62
|
"use_console": True,
|
|
@@ -359,54 +70,10 @@ def _get_common_server_config(instance_type: InstanceType, instance_name: str) -
|
|
|
359
70
|
{"name": "socketio.server", "level": "warning"},
|
|
360
71
|
{"name": "engineio.server", "level": "warning"},
|
|
361
72
|
{"name": "sqlalchemy.engine", "level": "warning"},
|
|
362
|
-
{"name": "requests_oauthlib.oauth2_session", "level": "warning"},
|
|
363
73
|
],
|
|
364
74
|
}
|
|
365
75
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
return config
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
def server_configuration_questionaire(
|
|
372
|
-
instance_name: str,
|
|
373
|
-
) -> dict[str, Any]:
|
|
374
|
-
"""
|
|
375
|
-
Kubernetes-specific questionnaire to generate Helm values for server.
|
|
376
|
-
|
|
377
|
-
Parameters
|
|
378
|
-
----------
|
|
379
|
-
instance_name : str
|
|
380
|
-
Name of the server instance
|
|
381
|
-
|
|
382
|
-
Returns
|
|
383
|
-
-------
|
|
384
|
-
dict[str, Any]
|
|
385
|
-
dictionary with Helm values for the server configuration
|
|
386
|
-
"""
|
|
387
|
-
# Get active kube namespace
|
|
388
|
-
cli_config = CliConfig()
|
|
389
|
-
kube_namespace = cli_config.get_last_namespace()
|
|
390
|
-
|
|
391
|
-
# Initialize config with basic structure
|
|
392
|
-
config = {"server": {}, "database": {}, "ui": {}}
|
|
393
|
-
|
|
394
|
-
# === Server settings ===
|
|
395
|
-
config["server"]["description"] = q.text(
|
|
396
|
-
"Enter a human-readable description:",
|
|
397
|
-
default=f"Vantage6 server {instance_name}",
|
|
398
|
-
).unsafe_ask()
|
|
399
|
-
|
|
400
|
-
config["server"]["image"] = q.text(
|
|
401
|
-
"Server Docker image:",
|
|
402
|
-
default="harbor2.vantage6.ai/infrastructure/server:latest",
|
|
403
|
-
).unsafe_ask()
|
|
404
|
-
|
|
405
|
-
# === UI settings ===
|
|
406
|
-
config["ui"]["image"] = q.text(
|
|
407
|
-
"UI Docker image:",
|
|
408
|
-
default="harbor2.vantage6.ai/infrastructure/ui:latest",
|
|
409
|
-
).unsafe_ask()
|
|
76
|
+
backend_config["api_path"] = DEFAULT_API_PATH
|
|
410
77
|
|
|
411
78
|
# === Database settings ===
|
|
412
79
|
config["database"]["volumePath"] = q.text(
|
|
@@ -419,80 +86,47 @@ def server_configuration_questionaire(
|
|
|
419
86
|
default="docker-desktop",
|
|
420
87
|
).unsafe_ask()
|
|
421
88
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
# === Other settings ===
|
|
427
|
-
log_level = q.select(
|
|
428
|
-
"Which level of logging would you like?",
|
|
429
|
-
choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
|
|
430
|
-
default="INFO",
|
|
89
|
+
is_production = q.confirm(
|
|
90
|
+
"Do you want to use production settings for this server? If not, the server will "
|
|
91
|
+
"be configured to be more suitable for development or testing purposes.",
|
|
92
|
+
default=True,
|
|
431
93
|
).unsafe_ask()
|
|
432
94
|
|
|
433
|
-
|
|
95
|
+
if is_production:
|
|
96
|
+
config = _add_production_server_config(config)
|
|
434
97
|
|
|
435
|
-
return config
|
|
98
|
+
return config, is_production
|
|
436
99
|
|
|
437
100
|
|
|
438
|
-
def
|
|
101
|
+
def _add_production_server_config(config: dict) -> dict:
|
|
439
102
|
"""
|
|
440
|
-
|
|
441
|
-
instance.
|
|
103
|
+
Add the production server configuration to the config
|
|
442
104
|
|
|
443
105
|
Parameters
|
|
444
106
|
----------
|
|
445
|
-
|
|
446
|
-
|
|
107
|
+
config : dict
|
|
108
|
+
The config to add the production server configuration to
|
|
447
109
|
|
|
448
110
|
Returns
|
|
449
111
|
-------
|
|
450
112
|
dict
|
|
451
|
-
|
|
113
|
+
The config with the production server configuration added
|
|
452
114
|
"""
|
|
453
|
-
|
|
115
|
+
info("For production environments, it is recommended to use an external database.")
|
|
116
|
+
info("Please provide the URI of the external database.")
|
|
117
|
+
info("Example: postgresql://username:password@localhost:5432/vantage6")
|
|
454
118
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
"What is the Vantage6 server linked to the algorithm store? "
|
|
460
|
-
"Provide the link to the server endpoint.",
|
|
461
|
-
default=default_v6_server_uri,
|
|
462
|
-
).unsafe_ask()
|
|
463
|
-
|
|
464
|
-
root_username = q.text(
|
|
465
|
-
"What is the username of the root user?",
|
|
466
|
-
default=default_root_username,
|
|
119
|
+
config["database"]["external"] = True
|
|
120
|
+
config["database"]["uri"] = q.text(
|
|
121
|
+
"Database URI:",
|
|
122
|
+
default="postgresql://vantage6:vantage6@localhost:5432/vantage6",
|
|
467
123
|
).unsafe_ask()
|
|
468
124
|
|
|
469
|
-
config["root_user"] = {
|
|
470
|
-
"v6_server_uri": v6_server_uri,
|
|
471
|
-
"username": root_username,
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
# ask about openness of the algorithm store
|
|
475
|
-
is_open = q.confirm(
|
|
476
|
-
"Do you want to open the algorithm store to the public? This will allow anyone "
|
|
477
|
-
"to view the algorithms, but they cannot modify them.",
|
|
478
|
-
default=False,
|
|
479
|
-
).unsafe_ask()
|
|
480
|
-
if is_open:
|
|
481
|
-
open_algos_policy = "public"
|
|
482
|
-
else:
|
|
483
|
-
is_open_to_whitelist = q.confirm(
|
|
484
|
-
"Do you want to allow all authenticated users to access "
|
|
485
|
-
"the algorithms in the store? If not allowing this, you will have to assign"
|
|
486
|
-
" the appropriate permissions to each user individually.",
|
|
487
|
-
default=True,
|
|
488
|
-
).unsafe_ask()
|
|
489
|
-
open_algos_policy = "authenticated" if is_open_to_whitelist else "private"
|
|
490
|
-
config["policies"]["algorithm_view"] = open_algos_policy
|
|
491
|
-
|
|
492
125
|
return config
|
|
493
126
|
|
|
494
127
|
|
|
495
128
|
def configuration_wizard(
|
|
129
|
+
questionnaire_function: callable,
|
|
496
130
|
type_: InstanceType,
|
|
497
131
|
instance_name: str,
|
|
498
132
|
system_folders: bool,
|
|
@@ -502,6 +136,8 @@ def configuration_wizard(
|
|
|
502
136
|
|
|
503
137
|
Parameters
|
|
504
138
|
----------
|
|
139
|
+
questionnaire_function : callable
|
|
140
|
+
Function to generate the configuration
|
|
505
141
|
type_ : InstanceType
|
|
506
142
|
Type of the instance to create a configuration for
|
|
507
143
|
instance_name : str
|
|
@@ -519,21 +155,20 @@ def configuration_wizard(
|
|
|
519
155
|
|
|
520
156
|
# invoke questionaire to create configuration file
|
|
521
157
|
if type_ == InstanceType.NODE:
|
|
522
|
-
|
|
523
|
-
config = node_configuration_questionaire(dirs, instance_name)
|
|
524
|
-
elif type_ == InstanceType.SERVER:
|
|
525
|
-
conf_manager = ServerConfigurationManager
|
|
526
|
-
config = server_configuration_questionaire(
|
|
527
|
-
instance_name=instance_name,
|
|
528
|
-
)
|
|
158
|
+
config = questionnaire_function(dirs, instance_name)
|
|
529
159
|
else:
|
|
530
|
-
|
|
531
|
-
config = algo_store_configuration_questionaire(instance_name)
|
|
160
|
+
config = questionnaire_function(instance_name)
|
|
532
161
|
|
|
533
162
|
# in the case of an environment we need to add it to the current
|
|
534
163
|
# configuration. In the case of application we can simply overwrite this
|
|
535
164
|
# key (although there might be environments present)
|
|
536
165
|
config_file = Path(dirs.get("config")) / (instance_name + ".yaml")
|
|
166
|
+
if type_ == InstanceType.NODE:
|
|
167
|
+
conf_manager = NodeConfigurationManager
|
|
168
|
+
elif type_ == InstanceType.SERVER:
|
|
169
|
+
conf_manager = ServerConfigurationManager
|
|
170
|
+
else:
|
|
171
|
+
conf_manager = AlgorithmStoreConfigurationManager
|
|
537
172
|
|
|
538
173
|
if Path(config_file).exists():
|
|
539
174
|
config_manager = conf_manager.from_file(config_file)
|
|
@@ -3,11 +3,10 @@ from __future__ import annotations
|
|
|
3
3
|
from vantage6.common.globals import APPNAME, InstanceType
|
|
4
4
|
|
|
5
5
|
from vantage6.cli import __version__
|
|
6
|
-
from vantage6.cli.configuration_manager import
|
|
6
|
+
from vantage6.cli.configuration_manager import AlgorithmStoreConfigurationManager
|
|
7
7
|
from vantage6.cli.context.base_server import BaseServerContext
|
|
8
8
|
from vantage6.cli.globals import (
|
|
9
9
|
DEFAULT_SERVER_SYSTEM_FOLDERS as S_FOL,
|
|
10
|
-
AlgoStoreGlobals,
|
|
11
10
|
ServerType,
|
|
12
11
|
)
|
|
13
12
|
|
|
@@ -25,7 +24,7 @@ class AlgorithmStoreContext(BaseServerContext):
|
|
|
25
24
|
System wide or user configuration, by default S_FOL
|
|
26
25
|
"""
|
|
27
26
|
|
|
28
|
-
INST_CONFIG_MANAGER =
|
|
27
|
+
INST_CONFIG_MANAGER = AlgorithmStoreConfigurationManager
|
|
29
28
|
|
|
30
29
|
def __init__(self, instance_name: str, system_folders: bool = S_FOL):
|
|
31
30
|
super().__init__(
|
|
@@ -44,7 +43,7 @@ class AlgorithmStoreContext(BaseServerContext):
|
|
|
44
43
|
str
|
|
45
44
|
string representation of the database uri
|
|
46
45
|
"""
|
|
47
|
-
return super().get_database_uri(
|
|
46
|
+
return super().get_database_uri()
|
|
48
47
|
|
|
49
48
|
@property
|
|
50
49
|
def docker_container_name(self) -> str:
|
|
@@ -60,7 +59,7 @@ class AlgorithmStoreContext(BaseServerContext):
|
|
|
60
59
|
|
|
61
60
|
@classmethod
|
|
62
61
|
def from_external_config_file(
|
|
63
|
-
cls, path: str, system_folders: bool = S_FOL
|
|
62
|
+
cls, path: str, system_folders: bool = S_FOL, in_container: bool = False
|
|
64
63
|
) -> AlgorithmStoreContext:
|
|
65
64
|
"""
|
|
66
65
|
Create a server context from an external configuration file. External
|
|
@@ -73,6 +72,8 @@ class AlgorithmStoreContext(BaseServerContext):
|
|
|
73
72
|
Path of the configuration file
|
|
74
73
|
system_folders : bool, optional
|
|
75
74
|
System wide or user configuration, by default S_FOL
|
|
75
|
+
in_container : bool, optional
|
|
76
|
+
Whether the application is running inside a container, by default False
|
|
76
77
|
|
|
77
78
|
Returns
|
|
78
79
|
-------
|
|
@@ -82,8 +83,8 @@ class AlgorithmStoreContext(BaseServerContext):
|
|
|
82
83
|
return super().from_external_config_file(
|
|
83
84
|
path,
|
|
84
85
|
ServerType.ALGORITHM_STORE,
|
|
85
|
-
AlgoStoreGlobals.CONFIG_NAME_ENV_VAR.value,
|
|
86
86
|
system_folders,
|
|
87
|
+
in_container,
|
|
87
88
|
)
|
|
88
89
|
|
|
89
90
|
@classmethod
|