vantage6 4.9.1__py3-none-any.whl → 4.10.0__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.
- tests_cli/test_node_cli.py +6 -0
- tests_cli/test_server_cli.py +2 -2
- tests_cli/test_wizard.py +5 -5
- vantage6/cli/__init__.py +1 -1
- vantage6/cli/_version.py +1 -1
- vantage6/cli/algorithm/create.py +26 -8
- vantage6/cli/algorithm/update.py +5 -1
- vantage6/cli/algostore/attach.py +10 -6
- vantage6/cli/algostore/list.py +1 -1
- vantage6/cli/algostore/new.py +7 -1
- vantage6/cli/algostore/start.py +2 -2
- vantage6/cli/algostore/stop.py +1 -1
- vantage6/cli/common/utils.py +18 -7
- vantage6/cli/configuration_manager.py +1 -0
- vantage6/cli/configuration_wizard.py +60 -50
- vantage6/cli/context/algorithm_store.py +1 -1
- vantage6/cli/context/node.py +1 -1
- vantage6/cli/dev/create.py +8 -6
- vantage6/cli/dev/remove.py +18 -1
- vantage6/cli/node/attach.py +7 -3
- vantage6/cli/node/clean.py +6 -2
- vantage6/cli/node/common/__init__.py +21 -4
- vantage6/cli/node/new.py +5 -1
- vantage6/cli/node/restart.py +7 -3
- vantage6/cli/node/set_api_key.py +5 -1
- vantage6/cli/node/start.py +13 -5
- vantage6/cli/node/stop.py +7 -3
- vantage6/cli/node/version.py +7 -3
- vantage6/cli/server/attach.py +9 -5
- vantage6/cli/server/import_.py +4 -1
- vantage6/cli/server/list.py +1 -1
- vantage6/cli/server/new.py +5 -1
- vantage6/cli/server/shell.py +1 -1
- vantage6/cli/server/start.py +6 -3
- vantage6/cli/server/stop.py +9 -5
- vantage6/cli/server/version.py +2 -2
- vantage6/cli/template/algo_store_config.j2 +1 -1
- vantage6/cli/template/server_config.j2 +1 -1
- vantage6/cli/test/feature_tester.py +10 -3
- vantage6/cli/utils.py +5 -1
- {vantage6-4.9.1.dist-info → vantage6-4.10.0.dist-info}/METADATA +4 -4
- vantage6-4.10.0.dist-info/RECORD +76 -0
- vantage6-4.9.1.dist-info/RECORD +0 -76
- {vantage6-4.9.1.dist-info → vantage6-4.10.0.dist-info}/WHEEL +0 -0
- {vantage6-4.9.1.dist-info → vantage6-4.10.0.dist-info}/entry_points.txt +0 -0
- {vantage6-4.9.1.dist-info → vantage6-4.10.0.dist-info}/top_level.txt +0 -0
tests_cli/test_node_cli.py
CHANGED
|
@@ -244,9 +244,15 @@ class NodeCLITest(unittest.TestCase):
|
|
|
244
244
|
|
|
245
245
|
runner = CliRunner()
|
|
246
246
|
|
|
247
|
+
# Should fail when starting node with non-existing database CSV file
|
|
247
248
|
with runner.isolated_filesystem():
|
|
248
249
|
result = runner.invoke(cli_node_start, ["--name", "some-name"])
|
|
250
|
+
self.assertEqual(result.exit_code, 1)
|
|
249
251
|
|
|
252
|
+
# now do it with a SQL database which doesn't have to be an existing file
|
|
253
|
+
ctx.databases = [{"label": "some_label", "uri": "data.db", "type": "sql"}]
|
|
254
|
+
with runner.isolated_filesystem():
|
|
255
|
+
result = runner.invoke(cli_node_start, ["--name", "some-name"])
|
|
250
256
|
self.assertEqual(result.exit_code, 0)
|
|
251
257
|
|
|
252
258
|
def _setup_stop_test(self, containers):
|
tests_cli/test_server_cli.py
CHANGED
|
@@ -132,7 +132,7 @@ class ServerCLITest(unittest.TestCase):
|
|
|
132
132
|
"""Stop server without errors."""
|
|
133
133
|
|
|
134
134
|
container1 = MagicMock()
|
|
135
|
-
container1.name = f"{APPNAME}-iknl-system-{InstanceType.SERVER}"
|
|
135
|
+
container1.name = f"{APPNAME}-iknl-system-{InstanceType.SERVER.value}"
|
|
136
136
|
containers.containers.list.return_value = [container1]
|
|
137
137
|
|
|
138
138
|
runner = CliRunner()
|
|
@@ -146,7 +146,7 @@ class ServerCLITest(unittest.TestCase):
|
|
|
146
146
|
def test_attach(self, containers, sleep):
|
|
147
147
|
"""Attach log to the console without errors."""
|
|
148
148
|
container1 = MagicMock()
|
|
149
|
-
container1.name = f"{APPNAME}-iknl-system-{InstanceType.SERVER}"
|
|
149
|
+
container1.name = f"{APPNAME}-iknl-system-{InstanceType.SERVER.value}"
|
|
150
150
|
containers.list.return_value = [container1]
|
|
151
151
|
|
|
152
152
|
sleep.side_effect = KeyboardInterrupt("Boom!")
|
tests_cli/test_wizard.py
CHANGED
|
@@ -33,8 +33,8 @@ class WizardTest(unittest.TestCase):
|
|
|
33
33
|
"""An error is printed when docker is not running"""
|
|
34
34
|
|
|
35
35
|
with patch(f"{module_path}.q") as q:
|
|
36
|
-
q.
|
|
37
|
-
q.confirm.return_value.
|
|
36
|
+
q.unsafe_prompt.side_effect = self.prompts
|
|
37
|
+
q.confirm.return_value.unsafe_ask.side_effect = [
|
|
38
38
|
True, # add a database
|
|
39
39
|
False, # don't enable two-factor authentication
|
|
40
40
|
True, # add VPN server
|
|
@@ -79,8 +79,8 @@ class WizardTest(unittest.TestCase):
|
|
|
79
79
|
|
|
80
80
|
def test_server_wizard(self):
|
|
81
81
|
with patch(f"{module_path}.q") as q:
|
|
82
|
-
q.
|
|
83
|
-
q.confirm.return_value.
|
|
82
|
+
q.unsafe_prompt.side_effect = self.prompts
|
|
83
|
+
q.confirm.return_value.unsafe_ask.side_effect = [
|
|
84
84
|
True,
|
|
85
85
|
True,
|
|
86
86
|
True,
|
|
@@ -134,7 +134,7 @@ class WizardTest(unittest.TestCase):
|
|
|
134
134
|
available_configurations.return_value = [[config], []]
|
|
135
135
|
|
|
136
136
|
with patch(f"{module_path}.q") as q:
|
|
137
|
-
q.select.return_value.
|
|
137
|
+
q.select.return_value.unsafe_ask.return_value = "vtg6"
|
|
138
138
|
name = select_configuration_questionaire(InstanceType.NODE, True)
|
|
139
139
|
|
|
140
140
|
self.assertEqual(name, "vtg6")
|
vantage6/cli/__init__.py
CHANGED
vantage6/cli/_version.py
CHANGED
|
@@ -7,7 +7,7 @@ with open(os.path.join(here, "__build__")) as fp:
|
|
|
7
7
|
__build__ = json.load(fp)
|
|
8
8
|
|
|
9
9
|
# Module version
|
|
10
|
-
version_info = (4,
|
|
10
|
+
version_info = (4, 10, 0, "final", __build__, 0)
|
|
11
11
|
|
|
12
12
|
# Module version stage suffix map
|
|
13
13
|
_specifier_ = {"alpha": "a", "beta": "b", "candidate": "rc", "final": ""}
|
vantage6/cli/algorithm/create.py
CHANGED
|
@@ -33,14 +33,11 @@ def cli_algorithm_create(name: str, directory: str) -> dict:
|
|
|
33
33
|
can be used to build an appropriate Docker image that can be used as a
|
|
34
34
|
vantage6 algorithm.
|
|
35
35
|
"""
|
|
36
|
-
|
|
37
|
-
name =
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
directory = q.text(
|
|
42
|
-
"Directory to put the algorithm in:", default=default_dir
|
|
43
|
-
).ask()
|
|
36
|
+
try:
|
|
37
|
+
name, directory = _get_user_input(name, directory)
|
|
38
|
+
except KeyboardInterrupt:
|
|
39
|
+
info("Aborted by user!")
|
|
40
|
+
return
|
|
44
41
|
|
|
45
42
|
# Create the template. The `unsafe` flag is used to allow running a Python script
|
|
46
43
|
# after creating the template that cleans up some things.
|
|
@@ -49,3 +46,24 @@ def cli_algorithm_create(name: str, directory: str) -> dict:
|
|
|
49
46
|
)
|
|
50
47
|
info("Template created!")
|
|
51
48
|
info(f"You can find your new algorithm in: {directory}")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _get_user_input(name: str, directory: str) -> None:
|
|
52
|
+
"""Get user input for the algorithm creation
|
|
53
|
+
|
|
54
|
+
Parameters
|
|
55
|
+
----------
|
|
56
|
+
name : str
|
|
57
|
+
Name for the new algorithm
|
|
58
|
+
directory : str
|
|
59
|
+
Directory to put the algorithm into
|
|
60
|
+
"""
|
|
61
|
+
if not name:
|
|
62
|
+
name = q.text("Name of your new algorithm:").unsafe_ask()
|
|
63
|
+
|
|
64
|
+
if not directory:
|
|
65
|
+
default_dir = str(Path(os.getcwd()) / name)
|
|
66
|
+
directory = q.text(
|
|
67
|
+
"Directory to put the algorithm in:", default=default_dir
|
|
68
|
+
).unsafe_ask()
|
|
69
|
+
return name, directory
|
vantage6/cli/algorithm/update.py
CHANGED
|
@@ -34,7 +34,11 @@ def cli_algorithm_update(directory: str, change_answers: bool) -> dict:
|
|
|
34
34
|
"""
|
|
35
35
|
if not directory:
|
|
36
36
|
default_dir = str(Path(os.getcwd()))
|
|
37
|
-
|
|
37
|
+
try:
|
|
38
|
+
directory = q.text("Algorithm directory:", default=default_dir).unsafe_ask()
|
|
39
|
+
except KeyboardInterrupt:
|
|
40
|
+
info("Aborted by user!")
|
|
41
|
+
return
|
|
38
42
|
|
|
39
43
|
info("Updating template...")
|
|
40
44
|
try:
|
vantage6/cli/algostore/attach.py
CHANGED
|
@@ -25,18 +25,22 @@ def cli_algo_store_attach(name: str, system_folders: bool) -> None:
|
|
|
25
25
|
client = docker.from_env()
|
|
26
26
|
|
|
27
27
|
running_servers = client.containers.list(
|
|
28
|
-
filters={"label": f"{APPNAME}-type={InstanceType.ALGORITHM_STORE}"}
|
|
28
|
+
filters={"label": f"{APPNAME}-type={InstanceType.ALGORITHM_STORE.value}"}
|
|
29
29
|
)
|
|
30
30
|
running_server_names = [container.name for container in running_servers]
|
|
31
31
|
|
|
32
32
|
if not name:
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
try:
|
|
34
|
+
name = q.select(
|
|
35
|
+
"Select the algorithm store you wish to attach:",
|
|
36
|
+
choices=running_server_names,
|
|
37
|
+
).unsafe_ask()
|
|
38
|
+
except KeyboardInterrupt:
|
|
39
|
+
error("Aborted by user!")
|
|
40
|
+
return
|
|
37
41
|
else:
|
|
38
42
|
post_fix = "system" if system_folders else "user"
|
|
39
|
-
name = f"{APPNAME}-{name}-{post_fix}-{InstanceType.ALGORITHM_STORE}"
|
|
43
|
+
name = f"{APPNAME}-{name}-{post_fix}-{InstanceType.ALGORITHM_STORE.value}"
|
|
40
44
|
|
|
41
45
|
if name in running_server_names:
|
|
42
46
|
container = client.containers.get(name)
|
vantage6/cli/algostore/list.py
CHANGED
vantage6/cli/algostore/new.py
CHANGED
|
@@ -45,7 +45,13 @@ def cli_algo_store_new(name: str, system_folders: bool) -> None:
|
|
|
45
45
|
exit(1)
|
|
46
46
|
|
|
47
47
|
# create config in ctx location
|
|
48
|
-
|
|
48
|
+
try:
|
|
49
|
+
cfg_file = configuration_wizard(
|
|
50
|
+
InstanceType.ALGORITHM_STORE, name, system_folders
|
|
51
|
+
)
|
|
52
|
+
except KeyboardInterrupt:
|
|
53
|
+
error("Configuration creation aborted.")
|
|
54
|
+
exit(1)
|
|
49
55
|
info(f"New configuration created: {Fore.GREEN}{cfg_file}{Style.RESET_ALL}")
|
|
50
56
|
|
|
51
57
|
flag = "" if system_folders else "--user"
|
vantage6/cli/algostore/start.py
CHANGED
|
@@ -54,7 +54,7 @@ def cli_algo_store_start(
|
|
|
54
54
|
Start the algorithm store server.
|
|
55
55
|
"""
|
|
56
56
|
info("Starting algorithm store...")
|
|
57
|
-
docker_client = check_for_start(ctx, InstanceType.ALGORITHM_STORE)
|
|
57
|
+
docker_client = check_for_start(ctx, InstanceType.ALGORITHM_STORE.value)
|
|
58
58
|
|
|
59
59
|
image = get_image(image, ctx, "algorithm-store", DEFAULT_ALGO_STORE_IMAGE)
|
|
60
60
|
|
|
@@ -91,7 +91,7 @@ def cli_algo_store_start(
|
|
|
91
91
|
mounts=mounts,
|
|
92
92
|
detach=True,
|
|
93
93
|
labels={
|
|
94
|
-
f"{APPNAME}-type": InstanceType.ALGORITHM_STORE,
|
|
94
|
+
f"{APPNAME}-type": InstanceType.ALGORITHM_STORE.value,
|
|
95
95
|
"name": ctx.config_file_name,
|
|
96
96
|
},
|
|
97
97
|
environment=environment_vars,
|
vantage6/cli/algostore/stop.py
CHANGED
|
@@ -23,7 +23,7 @@ def cli_algo_store_stop(ctx: AlgorithmStoreContext, all_stores: bool):
|
|
|
23
23
|
client = docker.from_env()
|
|
24
24
|
|
|
25
25
|
running_stores = client.containers.list(
|
|
26
|
-
filters={"label": f"{APPNAME}-type={InstanceType.ALGORITHM_STORE}"}
|
|
26
|
+
filters={"label": f"{APPNAME}-type={InstanceType.ALGORITHM_STORE.value}"}
|
|
27
27
|
)
|
|
28
28
|
|
|
29
29
|
if not running_stores:
|
vantage6/cli/common/utils.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import enum
|
|
1
2
|
import questionary as q
|
|
2
3
|
from colorama import Fore, Style
|
|
3
4
|
import click
|
|
@@ -38,10 +39,14 @@ def get_server_name(
|
|
|
38
39
|
f"{instance_type}s that are running"
|
|
39
40
|
)
|
|
40
41
|
exit(1)
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
try:
|
|
43
|
+
name = q.select(
|
|
44
|
+
f"Select the {instance_type} you wish to inspect:",
|
|
45
|
+
choices=running_server_names,
|
|
46
|
+
).unsafe_ask()
|
|
47
|
+
except KeyboardInterrupt:
|
|
48
|
+
error("Aborted by user!")
|
|
49
|
+
exit(1)
|
|
45
50
|
else:
|
|
46
51
|
post_fix = "system" if system_folders else "user"
|
|
47
52
|
name = f"{APPNAME}-{name}-{post_fix}"
|
|
@@ -83,7 +88,11 @@ def get_server_configuration_list(instance_type: InstanceType.SERVER) -> None:
|
|
|
83
88
|
client = docker.from_env()
|
|
84
89
|
ctx_class = select_context_class(instance_type)
|
|
85
90
|
|
|
86
|
-
|
|
91
|
+
instance_type_value = (
|
|
92
|
+
instance_type.value if isinstance(instance_type, enum.Enum) else instance_type
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
running_server_names = get_running_servers(client, instance_type_value)
|
|
87
96
|
header = "\nName" + (21 * " ") + "Status" + (10 * " ") + "System/User"
|
|
88
97
|
|
|
89
98
|
click.echo(header)
|
|
@@ -97,7 +106,8 @@ def get_server_configuration_list(instance_type: InstanceType.SERVER) -> None:
|
|
|
97
106
|
for config in configs:
|
|
98
107
|
status = (
|
|
99
108
|
running
|
|
100
|
-
if f"{APPNAME}-{config.name}-system-{
|
|
109
|
+
if f"{APPNAME}-{config.name}-system-{instance_type_value}"
|
|
110
|
+
in running_server_names
|
|
101
111
|
else stopped
|
|
102
112
|
)
|
|
103
113
|
click.echo(f"{config.name:25}" f"{status:25} System ")
|
|
@@ -107,7 +117,8 @@ def get_server_configuration_list(instance_type: InstanceType.SERVER) -> None:
|
|
|
107
117
|
for config in configs:
|
|
108
118
|
status = (
|
|
109
119
|
running
|
|
110
|
-
if f"{APPNAME}-{config.name}-user-{
|
|
120
|
+
if f"{APPNAME}-{config.name}-user-{instance_type_value}"
|
|
121
|
+
in running_server_names
|
|
111
122
|
else stopped
|
|
112
123
|
)
|
|
113
124
|
click.echo(f"{config.name:25}" f"{status:25} User ")
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import questionary as q
|
|
2
|
-
|
|
3
1
|
from pathlib import Path
|
|
4
2
|
|
|
3
|
+
import questionary as q
|
|
4
|
+
|
|
5
5
|
from vantage6.common import generate_apikey
|
|
6
6
|
from vantage6.common.globals import (
|
|
7
7
|
DATABASE_TYPES,
|
|
@@ -36,7 +36,7 @@ def node_configuration_questionaire(dirs: dict, instance_name: str) -> dict:
|
|
|
36
36
|
dict
|
|
37
37
|
Dictionary with the new node configuration
|
|
38
38
|
"""
|
|
39
|
-
config = q.
|
|
39
|
+
config = q.unsafe_prompt(
|
|
40
40
|
[
|
|
41
41
|
{"type": "text", "name": "api_key", "message": "Enter given api-key:"},
|
|
42
42
|
{
|
|
@@ -57,7 +57,7 @@ def node_configuration_questionaire(dirs: dict, instance_name: str) -> dict:
|
|
|
57
57
|
else str(Ports.DEV_SERVER.value)
|
|
58
58
|
)
|
|
59
59
|
|
|
60
|
-
config = config | q.
|
|
60
|
+
config = config | q.unsafe_prompt(
|
|
61
61
|
[
|
|
62
62
|
{
|
|
63
63
|
"type": "text",
|
|
@@ -81,8 +81,8 @@ def node_configuration_questionaire(dirs: dict, instance_name: str) -> dict:
|
|
|
81
81
|
)
|
|
82
82
|
|
|
83
83
|
config["databases"] = list()
|
|
84
|
-
while q.confirm("Do you want to add a database?").
|
|
85
|
-
db_label = q.
|
|
84
|
+
while q.confirm("Do you want to add a database?").unsafe_ask():
|
|
85
|
+
db_label = q.unsafe_prompt(
|
|
86
86
|
[
|
|
87
87
|
{
|
|
88
88
|
"type": "text",
|
|
@@ -92,10 +92,10 @@ def node_configuration_questionaire(dirs: dict, instance_name: str) -> dict:
|
|
|
92
92
|
}
|
|
93
93
|
]
|
|
94
94
|
)
|
|
95
|
-
db_path = q.
|
|
95
|
+
db_path = q.unsafe_prompt(
|
|
96
96
|
[{"type": "text", "name": "uri", "message": "Database URI:"}]
|
|
97
97
|
)
|
|
98
|
-
db_type = q.select("Database type:", choices=DATABASE_TYPES).
|
|
98
|
+
db_type = q.select("Database type:", choices=DATABASE_TYPES).unsafe_ask()
|
|
99
99
|
|
|
100
100
|
config["databases"].append(
|
|
101
101
|
{"label": db_label.get("label"), "uri": db_path.get("uri"), "type": db_type}
|
|
@@ -103,18 +103,18 @@ def node_configuration_questionaire(dirs: dict, instance_name: str) -> dict:
|
|
|
103
103
|
|
|
104
104
|
is_add_vpn = q.confirm(
|
|
105
105
|
"Do you want to connect to a VPN server?", default=False
|
|
106
|
-
).
|
|
106
|
+
).unsafe_ask()
|
|
107
107
|
if is_add_vpn:
|
|
108
108
|
config["vpn_subnet"] = q.text(
|
|
109
109
|
message="Subnet of the VPN server you want to connect to:",
|
|
110
110
|
default="10.76.0.0/16",
|
|
111
|
-
).
|
|
111
|
+
).unsafe_ask()
|
|
112
112
|
|
|
113
113
|
is_policies = q.confirm(
|
|
114
114
|
"Do you want to limit the algorithms allowed to run on your node? This "
|
|
115
115
|
"should always be done for production scenarios.",
|
|
116
116
|
default=True,
|
|
117
|
-
).
|
|
117
|
+
).unsafe_ask()
|
|
118
118
|
policies = {}
|
|
119
119
|
if is_policies:
|
|
120
120
|
info(
|
|
@@ -124,12 +124,12 @@ def node_configuration_questionaire(dirs: dict, instance_name: str) -> dict:
|
|
|
124
124
|
)
|
|
125
125
|
ask_single_algorithms = q.confirm(
|
|
126
126
|
"Do you want to enter a list of allowed algorithms?"
|
|
127
|
-
).
|
|
127
|
+
).unsafe_ask()
|
|
128
128
|
if ask_single_algorithms:
|
|
129
129
|
policies[NodePolicy.ALLOWED_ALGORITHMS.value] = _get_allowed_algorithms()
|
|
130
130
|
ask_algorithm_stores = q.confirm(
|
|
131
131
|
"Do you want to allow algorithms from specific algorithm stores?"
|
|
132
|
-
).
|
|
132
|
+
).unsafe_ask()
|
|
133
133
|
if ask_algorithm_stores:
|
|
134
134
|
policies[NodePolicy.ALLOWED_ALGORITHM_STORES.value] = (
|
|
135
135
|
_get_allowed_algorithm_stores()
|
|
@@ -141,7 +141,7 @@ def node_configuration_questionaire(dirs: dict, instance_name: str) -> dict:
|
|
|
141
141
|
"stores? If not, algorithms will be allowed if they are in either the "
|
|
142
142
|
"list of allowed algorithms or one of the allowed algorithm stores.",
|
|
143
143
|
default=True,
|
|
144
|
-
).
|
|
144
|
+
).unsafe_ask()
|
|
145
145
|
policies["allow_either_whitelist_or_store"] = not require_both_whitelists
|
|
146
146
|
if policies:
|
|
147
147
|
config["policies"] = policies
|
|
@@ -149,7 +149,7 @@ def node_configuration_questionaire(dirs: dict, instance_name: str) -> dict:
|
|
|
149
149
|
res = q.select(
|
|
150
150
|
"Which level of logging would you like?",
|
|
151
151
|
choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL", "NOTSET"],
|
|
152
|
-
).
|
|
152
|
+
).unsafe_ask()
|
|
153
153
|
|
|
154
154
|
config["logging"] = {
|
|
155
155
|
"level": res,
|
|
@@ -178,7 +178,7 @@ def node_configuration_questionaire(dirs: dict, instance_name: str) -> dict:
|
|
|
178
178
|
"If you continue, you should provide your collaboration "
|
|
179
179
|
"settings manually."
|
|
180
180
|
)
|
|
181
|
-
if q.confirm("Do you want to abort?", default=True).
|
|
181
|
+
if q.confirm("Do you want to abort?", default=True).unsafe_ask():
|
|
182
182
|
exit(0)
|
|
183
183
|
|
|
184
184
|
if client.whoami is not None:
|
|
@@ -190,11 +190,13 @@ def node_configuration_questionaire(dirs: dict, instance_name: str) -> dict:
|
|
|
190
190
|
f"Encryption is {'enabled' if encryption else 'disabled'}"
|
|
191
191
|
f" for this collaboration. Accept?",
|
|
192
192
|
default=True,
|
|
193
|
-
).
|
|
193
|
+
).unsafe_ask()
|
|
194
194
|
else:
|
|
195
|
-
encryption = q.confirm("Enable encryption?", default=True).
|
|
195
|
+
encryption = q.confirm("Enable encryption?", default=True).unsafe_ask()
|
|
196
196
|
|
|
197
|
-
private_key =
|
|
197
|
+
private_key = (
|
|
198
|
+
"" if not encryption else q.text("Path to private key file:").unsafe_ask()
|
|
199
|
+
)
|
|
198
200
|
|
|
199
201
|
config["encryption"] = {
|
|
200
202
|
"enabled": encryption is True or encryption == "true",
|
|
@@ -219,24 +221,22 @@ def _get_allowed_algorithms() -> list[str]:
|
|
|
219
221
|
"use strings to provide one algorithm at a time."
|
|
220
222
|
)
|
|
221
223
|
info("Examples:")
|
|
222
|
-
|
|
223
|
-
# flake8: noqa: W605
|
|
224
|
-
info("^harbor2\.vantage6\.ai/demo/average$ Allow the demo average algorithm")
|
|
224
|
+
info(r"^harbor2\.vantage6\.ai/demo/average$ Allow the demo average algorithm")
|
|
225
225
|
info(
|
|
226
|
-
"^harbor2\.vantage6\.ai/algorithms/.* Allow all algorithms from "
|
|
226
|
+
r"^harbor2\.vantage6\.ai/algorithms/.* Allow all algorithms from "
|
|
227
227
|
"harbor2.vantage6.ai/algorithms"
|
|
228
228
|
)
|
|
229
229
|
info(
|
|
230
|
-
"^harbor2\.vantage6\.ai/demo/average@sha256:82becede...$ Allow a "
|
|
230
|
+
r"^harbor2\.vantage6\.ai/demo/average@sha256:82becede...$ Allow a "
|
|
231
231
|
"specific hash of average algorithm"
|
|
232
232
|
)
|
|
233
233
|
allowed_algorithms = []
|
|
234
234
|
while True:
|
|
235
|
-
algo = q.text(message="Enter your algorithm expression:").
|
|
235
|
+
algo = q.text(message="Enter your algorithm expression:").unsafe_ask()
|
|
236
236
|
allowed_algorithms.append(algo)
|
|
237
237
|
if not q.confirm(
|
|
238
238
|
"Do you want to add another algorithm expression?", default=True
|
|
239
|
-
).
|
|
239
|
+
).unsafe_ask():
|
|
240
240
|
break
|
|
241
241
|
return allowed_algorithms
|
|
242
242
|
|
|
@@ -261,16 +261,16 @@ def _get_allowed_algorithm_stores() -> list[str]:
|
|
|
261
261
|
"community store"
|
|
262
262
|
)
|
|
263
263
|
info(
|
|
264
|
-
"^https://*\.vantage6\.ai$ Allow all algorithms from any "
|
|
264
|
+
r"^https://*\.vantage6\.ai$ Allow all algorithms from any "
|
|
265
265
|
"store hosted on vantage6.ai"
|
|
266
266
|
)
|
|
267
267
|
allowed_algorithm_stores = []
|
|
268
268
|
while True:
|
|
269
|
-
store = q.text(message="Enter the URL of the algorithm store:").
|
|
269
|
+
store = q.text(message="Enter the URL of the algorithm store:").unsafe_ask()
|
|
270
270
|
allowed_algorithm_stores.append(store)
|
|
271
271
|
if not q.confirm(
|
|
272
272
|
"Do you want to add another algorithm store?", default=True
|
|
273
|
-
).
|
|
273
|
+
).unsafe_ask():
|
|
274
274
|
break
|
|
275
275
|
return allowed_algorithm_stores
|
|
276
276
|
|
|
@@ -292,7 +292,7 @@ def _get_common_server_config(instance_type: InstanceType, instance_name: str) -
|
|
|
292
292
|
dict
|
|
293
293
|
Dictionary with new (partial) server configuration
|
|
294
294
|
"""
|
|
295
|
-
config = q.
|
|
295
|
+
config = q.unsafe_prompt(
|
|
296
296
|
[
|
|
297
297
|
{
|
|
298
298
|
"type": "text",
|
|
@@ -315,7 +315,7 @@ def _get_common_server_config(instance_type: InstanceType, instance_name: str) -
|
|
|
315
315
|
)
|
|
316
316
|
|
|
317
317
|
config.update(
|
|
318
|
-
q.
|
|
318
|
+
q.unsafe_prompt(
|
|
319
319
|
[
|
|
320
320
|
{
|
|
321
321
|
"type": "text",
|
|
@@ -336,7 +336,7 @@ def _get_common_server_config(instance_type: InstanceType, instance_name: str) -
|
|
|
336
336
|
res = q.select(
|
|
337
337
|
"Which level of logging would you like?",
|
|
338
338
|
choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL", "NOTSET"],
|
|
339
|
-
).
|
|
339
|
+
).unsafe_ask()
|
|
340
340
|
|
|
341
341
|
config["logging"] = {
|
|
342
342
|
"level": res,
|
|
@@ -378,11 +378,11 @@ def server_configuration_questionaire(instance_name: str) -> dict:
|
|
|
378
378
|
|
|
379
379
|
config = _get_common_server_config(InstanceType.SERVER, instance_name)
|
|
380
380
|
|
|
381
|
-
constant_jwt_secret = q.confirm("Do you want a constant JWT secret?").
|
|
381
|
+
constant_jwt_secret = q.confirm("Do you want a constant JWT secret?").unsafe_ask()
|
|
382
382
|
if constant_jwt_secret:
|
|
383
383
|
config["jwt_secret_key"] = generate_apikey()
|
|
384
384
|
|
|
385
|
-
is_mfa = q.confirm("Do you want to enforce two-factor authentication?").
|
|
385
|
+
is_mfa = q.confirm("Do you want to enforce two-factor authentication?").unsafe_ask()
|
|
386
386
|
if is_mfa:
|
|
387
387
|
config["two_factor_auth"] = is_mfa
|
|
388
388
|
|
|
@@ -393,11 +393,13 @@ def server_configuration_questionaire(instance_name: str) -> dict:
|
|
|
393
393
|
"server url. If you are running a production server, this is the "
|
|
394
394
|
"url that users will connect to.",
|
|
395
395
|
default=current_server_url,
|
|
396
|
-
).
|
|
396
|
+
).unsafe_ask()
|
|
397
397
|
|
|
398
|
-
is_add_vpn = q.confirm(
|
|
398
|
+
is_add_vpn = q.confirm(
|
|
399
|
+
"Do you want to add a VPN server?", default=False
|
|
400
|
+
).unsafe_ask()
|
|
399
401
|
if is_add_vpn:
|
|
400
|
-
vpn_config = q.
|
|
402
|
+
vpn_config = q.unsafe_prompt(
|
|
401
403
|
[
|
|
402
404
|
{
|
|
403
405
|
"type": "text",
|
|
@@ -434,12 +436,14 @@ def server_configuration_questionaire(instance_name: str) -> dict:
|
|
|
434
436
|
)
|
|
435
437
|
config["vpn_server"] = vpn_config
|
|
436
438
|
|
|
437
|
-
is_add_rabbitmq = q.confirm(
|
|
439
|
+
is_add_rabbitmq = q.confirm(
|
|
440
|
+
"Do you want to add a RabbitMQ message queue?"
|
|
441
|
+
).unsafe_ask()
|
|
438
442
|
if is_add_rabbitmq:
|
|
439
|
-
rabbit_uri = q.text(message="Enter the URI for your RabbitMQ:").
|
|
443
|
+
rabbit_uri = q.text(message="Enter the URI for your RabbitMQ:").unsafe_ask()
|
|
440
444
|
run_rabbit_locally = q.confirm(
|
|
441
445
|
"Do you want to run RabbitMQ locally? (Use only for testing)"
|
|
442
|
-
).
|
|
446
|
+
).unsafe_ask()
|
|
443
447
|
config["rabbitmq"] = {
|
|
444
448
|
"uri": rabbit_uri,
|
|
445
449
|
"start_with_server": run_rabbit_locally,
|
|
@@ -449,7 +453,7 @@ def server_configuration_questionaire(instance_name: str) -> dict:
|
|
|
449
453
|
is_add_community_store = q.confirm(
|
|
450
454
|
"Do you want to make the algorithms from the community algorithm store "
|
|
451
455
|
"available to your users?"
|
|
452
|
-
).
|
|
456
|
+
).unsafe_ask()
|
|
453
457
|
algorithm_stores = []
|
|
454
458
|
if is_add_community_store:
|
|
455
459
|
algorithm_stores.append(
|
|
@@ -457,14 +461,14 @@ def server_configuration_questionaire(instance_name: str) -> dict:
|
|
|
457
461
|
)
|
|
458
462
|
add_more_stores = q.confirm(
|
|
459
463
|
"Do you want to add more algorithm stores?", default=False
|
|
460
|
-
).
|
|
464
|
+
).unsafe_ask()
|
|
461
465
|
while add_more_stores:
|
|
462
|
-
store_name = q.text(message="Enter the name of the store:").
|
|
463
|
-
store_url = q.text(message="Enter the URL of the store:").
|
|
466
|
+
store_name = q.text(message="Enter the name of the store:").unsafe_ask()
|
|
467
|
+
store_url = q.text(message="Enter the URL of the store:").unsafe_ask()
|
|
464
468
|
algorithm_stores.append({"name": store_name, "url": store_url})
|
|
465
469
|
add_more_stores = q.confirm(
|
|
466
470
|
"Do you want to add more algorithm stores?", default=False
|
|
467
|
-
).
|
|
471
|
+
).unsafe_ask()
|
|
468
472
|
config["algorithm_stores"] = algorithm_stores
|
|
469
473
|
|
|
470
474
|
return config
|
|
@@ -496,12 +500,12 @@ def algo_store_configuration_questionaire(instance_name: str) -> dict:
|
|
|
496
500
|
"What is the Vantage6 server linked to the algorithm store? "
|
|
497
501
|
"Provide the link to the server endpoint.",
|
|
498
502
|
default=default_v6_server_uri,
|
|
499
|
-
).
|
|
503
|
+
).unsafe_ask()
|
|
500
504
|
|
|
501
505
|
root_username = q.text(
|
|
502
506
|
"What is the username of the root user?",
|
|
503
507
|
default=default_root_username,
|
|
504
|
-
).
|
|
508
|
+
).unsafe_ask()
|
|
505
509
|
|
|
506
510
|
config["root_user"] = {
|
|
507
511
|
"v6_server_uri": v6_server_uri,
|
|
@@ -514,7 +518,7 @@ def algo_store_configuration_questionaire(instance_name: str) -> dict:
|
|
|
514
518
|
"Do you want to open the algorithm store to the public? This will allow anyone "
|
|
515
519
|
"to view the algorithms, but they cannot modify them.",
|
|
516
520
|
default=False,
|
|
517
|
-
).
|
|
521
|
+
).unsafe_ask()
|
|
518
522
|
if is_open:
|
|
519
523
|
open_algos_policy = "public"
|
|
520
524
|
else:
|
|
@@ -523,7 +527,7 @@ def algo_store_configuration_questionaire(instance_name: str) -> dict:
|
|
|
523
527
|
"the algorithms in the store? If not allowing this, you will have to assign"
|
|
524
528
|
" the appropriate permissions to each user individually.",
|
|
525
529
|
default=True,
|
|
526
|
-
).
|
|
530
|
+
).unsafe_ask()
|
|
527
531
|
open_algos_policy = "whitelisted" if is_open_to_whitelist else "private"
|
|
528
532
|
config["policies"]["algorithm_view"] = open_algos_policy
|
|
529
533
|
|
|
@@ -612,4 +616,10 @@ def select_configuration_questionaire(type_: InstanceType, system_folders: bool)
|
|
|
612
616
|
raise Exception("No configurations could be found!")
|
|
613
617
|
|
|
614
618
|
# pop the question
|
|
615
|
-
|
|
619
|
+
try:
|
|
620
|
+
return q.select(
|
|
621
|
+
"Select the configuration you want to use:", choices=choices
|
|
622
|
+
).unsafe_ask()
|
|
623
|
+
except KeyboardInterrupt:
|
|
624
|
+
error("Aborted by user!")
|
|
625
|
+
exit(1)
|
|
@@ -53,7 +53,7 @@ class AlgorithmStoreContext(BaseServerContext):
|
|
|
53
53
|
str
|
|
54
54
|
Server's docker container name
|
|
55
55
|
"""
|
|
56
|
-
return f"{APPNAME}-{self.name}-{self.scope}-{ServerType.ALGORITHM_STORE}"
|
|
56
|
+
return f"{APPNAME}-{self.name}-{self.scope}-{ServerType.ALGORITHM_STORE.value}"
|
|
57
57
|
|
|
58
58
|
@classmethod
|
|
59
59
|
def from_external_config_file(
|
vantage6/cli/context/node.py
CHANGED
|
@@ -132,7 +132,7 @@ class NodeContext(AppContext):
|
|
|
132
132
|
Path
|
|
133
133
|
Path to the data folder
|
|
134
134
|
"""
|
|
135
|
-
return AppContext.type_data_folder(InstanceType.NODE, system_folders)
|
|
135
|
+
return AppContext.type_data_folder(InstanceType.NODE.value, system_folders)
|
|
136
136
|
|
|
137
137
|
@property
|
|
138
138
|
def databases(self) -> dict:
|
vantage6/cli/dev/create.py
CHANGED
|
@@ -8,7 +8,7 @@ from jinja2 import Environment, FileSystemLoader
|
|
|
8
8
|
from colorama import Fore, Style
|
|
9
9
|
|
|
10
10
|
from vantage6.common.globals import APPNAME, InstanceType, Ports
|
|
11
|
-
from vantage6.common import info, error, generate_apikey
|
|
11
|
+
from vantage6.common import ensure_config_dir_writable, info, error, generate_apikey
|
|
12
12
|
|
|
13
13
|
import vantage6.cli.dev.data as data_dir
|
|
14
14
|
from vantage6.cli.context.algorithm_store import AlgorithmStoreContext
|
|
@@ -114,13 +114,15 @@ def create_node_config_file(
|
|
|
114
114
|
}
|
|
115
115
|
)
|
|
116
116
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
except Exception as e:
|
|
121
|
-
error(f"Could not write node configuration file: {e}")
|
|
117
|
+
# Check that we can write the node config
|
|
118
|
+
if not ensure_config_dir_writable():
|
|
119
|
+
error("Cannot write configuration file. Exiting...")
|
|
122
120
|
exit(1)
|
|
123
121
|
|
|
122
|
+
Path(full_path).parent.mkdir(parents=True, exist_ok=True)
|
|
123
|
+
with open(full_path, "x", encoding="utf-8") as f:
|
|
124
|
+
f.write(node_config)
|
|
125
|
+
|
|
124
126
|
info(
|
|
125
127
|
f"Spawned node for organization {Fore.GREEN}{config['org_id']}"
|
|
126
128
|
f"{Style.RESET_ALL}"
|