vantage6-node 4.15.1__tar.gz → 4.15.2__tar.gz
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.
- {vantage6_node-4.15.1 → vantage6_node-4.15.2}/PKG-INFO +4 -4
- vantage6_node-4.15.2/tests/docker/test_docker_manager.py +140 -0
- {vantage6_node-4.15.1 → vantage6_node-4.15.2}/vantage6/node/_version.py +1 -1
- {vantage6_node-4.15.1 → vantage6_node-4.15.2}/vantage6/node/docker/docker_manager.py +58 -33
- {vantage6_node-4.15.1 → vantage6_node-4.15.2}/vantage6_node.egg-info/PKG-INFO +4 -4
- {vantage6_node-4.15.1 → vantage6_node-4.15.2}/vantage6_node.egg-info/SOURCES.txt +1 -0
- {vantage6_node-4.15.1 → vantage6_node-4.15.2}/vantage6_node.egg-info/requires.txt +3 -3
- {vantage6_node-4.15.1 → vantage6_node-4.15.2}/setup.cfg +0 -0
- {vantage6_node-4.15.1 → vantage6_node-4.15.2}/setup.py +0 -0
- {vantage6_node-4.15.1 → vantage6_node-4.15.2}/tests/__init__.py +0 -0
- {vantage6_node-4.15.1 → vantage6_node-4.15.2}/tests/docker/__init__.py +0 -0
- {vantage6_node-4.15.1 → vantage6_node-4.15.2}/tests/test_ssh_tunnel.py +0 -0
- {vantage6_node-4.15.1 → vantage6_node-4.15.2}/vantage6/node/__build__ +0 -0
- {vantage6_node-4.15.1 → vantage6_node-4.15.2}/vantage6/node/__init__.py +0 -0
- {vantage6_node-4.15.1 → vantage6_node-4.15.2}/vantage6/node/cli/__init__.py +0 -0
- {vantage6_node-4.15.1 → vantage6_node-4.15.2}/vantage6/node/cli/node.py +0 -0
- {vantage6_node-4.15.1 → vantage6_node-4.15.2}/vantage6/node/context.py +0 -0
- {vantage6_node-4.15.1 → vantage6_node-4.15.2}/vantage6/node/docker/docker_base.py +0 -0
- {vantage6_node-4.15.1 → vantage6_node-4.15.2}/vantage6/node/docker/exceptions.py +0 -0
- {vantage6_node-4.15.1 → vantage6_node-4.15.2}/vantage6/node/docker/squid.py +0 -0
- {vantage6_node-4.15.1 → vantage6_node-4.15.2}/vantage6/node/docker/ssh_tunnel.py +0 -0
- {vantage6_node-4.15.1 → vantage6_node-4.15.2}/vantage6/node/docker/task_manager.py +0 -0
- {vantage6_node-4.15.1 → vantage6_node-4.15.2}/vantage6/node/docker/utils.py +0 -0
- {vantage6_node-4.15.1 → vantage6_node-4.15.2}/vantage6/node/docker/vpn_manager.py +0 -0
- {vantage6_node-4.15.1 → vantage6_node-4.15.2}/vantage6/node/globals.py +0 -0
- {vantage6_node-4.15.1 → vantage6_node-4.15.2}/vantage6/node/proxy_server.py +0 -0
- {vantage6_node-4.15.1 → vantage6_node-4.15.2}/vantage6/node/socket.py +0 -0
- {vantage6_node-4.15.1 → vantage6_node-4.15.2}/vantage6/node/util/__init__.py +0 -0
- {vantage6_node-4.15.1 → vantage6_node-4.15.2}/vantage6/node/util/colorer.py +0 -0
- {vantage6_node-4.15.1 → vantage6_node-4.15.2}/vantage6_node.egg-info/dependency_links.txt +0 -0
- {vantage6_node-4.15.1 → vantage6_node-4.15.2}/vantage6_node.egg-info/entry_points.txt +0 -0
- {vantage6_node-4.15.1 → vantage6_node-4.15.2}/vantage6_node.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: vantage6_node
|
|
3
|
-
Version: 4.15.
|
|
3
|
+
Version: 4.15.2
|
|
4
4
|
Summary: vantage6 node
|
|
5
5
|
Home-page: https://github.com/vantage6/vantage6
|
|
6
6
|
Requires-Python: >=3.10
|
|
@@ -13,9 +13,9 @@ Requires-Dist: python-socketio==5.15.0
|
|
|
13
13
|
Requires-Dist: requests==2.33.1
|
|
14
14
|
Requires-Dist: psutil==5.9.0
|
|
15
15
|
Requires-Dist: nvidia-ml-py==12.535.133
|
|
16
|
-
Requires-Dist: vantage6==4.15.
|
|
17
|
-
Requires-Dist: vantage6-client==4.15.
|
|
18
|
-
Requires-Dist: vantage6-algorithm-tools==4.15.
|
|
16
|
+
Requires-Dist: vantage6==4.15.2
|
|
17
|
+
Requires-Dist: vantage6-client==4.15.2
|
|
18
|
+
Requires-Dist: vantage6-algorithm-tools==4.15.2
|
|
19
19
|
Provides-Extra: dev
|
|
20
20
|
Requires-Dist: coverage==6.4.4; extra == "dev"
|
|
21
21
|
Requires-Dist: python-coveralls==2.9.3; extra == "dev"
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
from unittest.mock import MagicMock
|
|
3
|
+
|
|
4
|
+
from vantage6.common.globals import NodePolicy
|
|
5
|
+
|
|
6
|
+
from vantage6.node.docker.docker_manager import DockerManager
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class TestIsDockerImageAllowed(unittest.TestCase):
|
|
10
|
+
"""
|
|
11
|
+
Tests for DockerManager.is_docker_image_allowed().
|
|
12
|
+
|
|
13
|
+
DockerManager.__init__ connects to the Docker daemon, so these tests bypass it
|
|
14
|
+
(via __new__) and set up only the attributes is_docker_image_allowed() actually
|
|
15
|
+
reads: `_policies` and `client` (`log` is already a class attribute, so it's
|
|
16
|
+
available for free). This keeps `_is_regex_pattern` (a real staticmethod on the
|
|
17
|
+
class) working, unlike a fully mocked `self` would.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def setUp(self):
|
|
21
|
+
self.manager = DockerManager.__new__(DockerManager)
|
|
22
|
+
self.manager.client = MagicMock()
|
|
23
|
+
self.manager._policies = {}
|
|
24
|
+
|
|
25
|
+
@staticmethod
|
|
26
|
+
def _task_info(store_id: int | None = None) -> dict:
|
|
27
|
+
task_info = {"init_org": {"id": 1}, "init_user": {"id": 1}}
|
|
28
|
+
if store_id is not None:
|
|
29
|
+
task_info["algorithm_store"] = {"id": store_id}
|
|
30
|
+
return task_info
|
|
31
|
+
|
|
32
|
+
def test_allowed_algorithms_exact_match(self):
|
|
33
|
+
"""Baseline regression check for the (unchanged) allowed_algorithms policy."""
|
|
34
|
+
self.manager._policies = {
|
|
35
|
+
NodePolicy.ALLOWED_ALGORITHMS: ["some/image:tag"]
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
self.assertTrue(
|
|
39
|
+
self.manager.is_docker_image_allowed("some/image:tag", self._task_info())
|
|
40
|
+
)
|
|
41
|
+
self.assertFalse(
|
|
42
|
+
self.manager.is_docker_image_allowed(
|
|
43
|
+
"some/other-image:tag", self._task_info()
|
|
44
|
+
)
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
def test_allowed_algorithm_stores_verified(self):
|
|
48
|
+
"""
|
|
49
|
+
The store URL is whitelisted and the store itself confirms the image is a
|
|
50
|
+
registered, approved algorithm there - the image is allowed.
|
|
51
|
+
"""
|
|
52
|
+
self.manager._policies = {
|
|
53
|
+
NodePolicy.ALLOWED_ALGORITHM_STORES: ["https://store.example"]
|
|
54
|
+
}
|
|
55
|
+
self.manager.client.algorithm_store.get.return_value = {
|
|
56
|
+
"url": "https://store.example"
|
|
57
|
+
}
|
|
58
|
+
self.manager.client.algorithm_store.get_algorithm.return_value = {
|
|
59
|
+
"image": "some/image:tag",
|
|
60
|
+
"digest": "abc123",
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
self.assertTrue(
|
|
64
|
+
self.manager.is_docker_image_allowed(
|
|
65
|
+
"some/image:tag", self._task_info(store_id=1)
|
|
66
|
+
)
|
|
67
|
+
)
|
|
68
|
+
self.manager.client.algorithm_store.get_algorithm.assert_called_once_with(
|
|
69
|
+
"some/image:tag"
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
def test_allowed_algorithm_stores_not_confirmed_by_store(self):
|
|
73
|
+
"""
|
|
74
|
+
The store URL is whitelisted, but the store does not confirm the image is
|
|
75
|
+
registered/approved there (e.g. it genuinely isn't, the store hasn't been
|
|
76
|
+
upgraded to support node requests, or it could not be reached) - the image
|
|
77
|
+
is denied. This is the fix for GHSA-j43v-wwjr-9grj: previously the store URL
|
|
78
|
+
match alone was enough.
|
|
79
|
+
"""
|
|
80
|
+
self.manager._policies = {
|
|
81
|
+
NodePolicy.ALLOWED_ALGORITHM_STORES: ["https://store.example"]
|
|
82
|
+
}
|
|
83
|
+
self.manager.client.algorithm_store.get.return_value = {
|
|
84
|
+
"url": "https://store.example"
|
|
85
|
+
}
|
|
86
|
+
self.manager.client.algorithm_store.get_algorithm.return_value = None
|
|
87
|
+
|
|
88
|
+
self.assertFalse(
|
|
89
|
+
self.manager.is_docker_image_allowed(
|
|
90
|
+
"some/image:tag", self._task_info(store_id=1)
|
|
91
|
+
)
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
def test_allowed_algorithm_stores_url_not_whitelisted(self):
|
|
95
|
+
"""
|
|
96
|
+
The store's URL isn't on the whitelist at all - the image is denied without
|
|
97
|
+
even asking the store to verify the image (no wasted network call).
|
|
98
|
+
"""
|
|
99
|
+
self.manager._policies = {
|
|
100
|
+
NodePolicy.ALLOWED_ALGORITHM_STORES: ["https://trusted.example"]
|
|
101
|
+
}
|
|
102
|
+
self.manager.client.algorithm_store.get.return_value = {
|
|
103
|
+
"url": "https://untrusted.example"
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
self.assertFalse(
|
|
107
|
+
self.manager.is_docker_image_allowed(
|
|
108
|
+
"some/image:tag", self._task_info(store_id=1)
|
|
109
|
+
)
|
|
110
|
+
)
|
|
111
|
+
self.manager.client.algorithm_store.get_algorithm.assert_not_called()
|
|
112
|
+
|
|
113
|
+
def test_allow_either_whitelist_or_store(self):
|
|
114
|
+
"""
|
|
115
|
+
Baseline regression check: with allow_either_whitelist_or_store, an image
|
|
116
|
+
that fails the allowed_algorithms whitelist but is confirmed by the
|
|
117
|
+
(whitelisted) store is still allowed.
|
|
118
|
+
"""
|
|
119
|
+
self.manager._policies = {
|
|
120
|
+
NodePolicy.ALLOWED_ALGORITHMS: ["some/other-image:tag"],
|
|
121
|
+
NodePolicy.ALLOWED_ALGORITHM_STORES: ["https://store.example"],
|
|
122
|
+
"allow_either_whitelist_or_store": True,
|
|
123
|
+
}
|
|
124
|
+
self.manager.client.algorithm_store.get.return_value = {
|
|
125
|
+
"url": "https://store.example"
|
|
126
|
+
}
|
|
127
|
+
self.manager.client.algorithm_store.get_algorithm.return_value = {
|
|
128
|
+
"image": "some/image:tag",
|
|
129
|
+
"digest": "abc123",
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
self.assertTrue(
|
|
133
|
+
self.manager.is_docker_image_allowed(
|
|
134
|
+
"some/image:tag", self._task_info(store_id=1)
|
|
135
|
+
)
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
if __name__ == "__main__":
|
|
140
|
+
unittest.main()
|
|
@@ -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, 15,
|
|
10
|
+
version_info = (4, 15, 2, "final", __build__, 0)
|
|
11
11
|
|
|
12
12
|
# Module version stage suffix map
|
|
13
13
|
_specifier_ = {"alpha": "a", "beta": "b", "candidate": "rc", "final": ""}
|
|
@@ -7,25 +7,27 @@ for creating docker networks, docker volumes, start containers and retrieve
|
|
|
7
7
|
results from finished containers.
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
|
-
import os
|
|
11
|
-
from socket import SocketIO
|
|
12
|
-
import time
|
|
13
10
|
import logging
|
|
14
|
-
import
|
|
11
|
+
import os
|
|
15
12
|
import re
|
|
16
13
|
import shutil
|
|
17
|
-
|
|
18
|
-
from typing import NamedTuple
|
|
14
|
+
import time
|
|
19
15
|
from pathlib import Path
|
|
16
|
+
from socket import SocketIO
|
|
17
|
+
from typing import NamedTuple
|
|
20
18
|
|
|
21
|
-
|
|
22
|
-
from vantage6.
|
|
19
|
+
import docker
|
|
20
|
+
from vantage6.algorithm.tools.wrappers import get_column_names
|
|
21
|
+
from vantage6.cli.context.node import NodeContext
|
|
22
|
+
from vantage6.common import get_database_config, logger_name
|
|
23
|
+
from vantage6.common.client.node_client import NodeClient
|
|
23
24
|
from vantage6.common.docker.addons import (
|
|
24
25
|
get_container,
|
|
25
26
|
get_digest,
|
|
26
27
|
get_image_name_wo_tag,
|
|
27
28
|
running_in_docker,
|
|
28
29
|
)
|
|
30
|
+
from vantage6.common.docker.network_manager import NetworkManager
|
|
29
31
|
from vantage6.common.globals import (
|
|
30
32
|
APPNAME,
|
|
31
33
|
BASIC_PROCESSING_IMAGE,
|
|
@@ -33,22 +35,18 @@ from vantage6.common.globals import (
|
|
|
33
35
|
NodePolicy,
|
|
34
36
|
)
|
|
35
37
|
from vantage6.common.task_status import TaskStatus, has_task_failed
|
|
36
|
-
from vantage6.common.docker.network_manager import NetworkManager
|
|
37
|
-
from vantage6.algorithm.tools.wrappers import get_column_names
|
|
38
|
-
from vantage6.cli.context.node import NodeContext
|
|
39
38
|
from vantage6.node.context import DockerNodeContext
|
|
40
39
|
from vantage6.node.docker.docker_base import DockerBaseManager
|
|
41
|
-
from vantage6.node.docker.vpn_manager import VPNManager
|
|
42
|
-
from vantage6.node.docker.task_manager import DockerTaskManager
|
|
43
|
-
from vantage6.node.docker.squid import Squid
|
|
44
|
-
from vantage6.common.client.node_client import NodeClient
|
|
45
40
|
from vantage6.node.docker.exceptions import (
|
|
46
|
-
UnknownAlgorithmStartFail,
|
|
47
|
-
PermanentAlgorithmStartFail,
|
|
48
41
|
AlgorithmContainerNotFound,
|
|
42
|
+
PermanentAlgorithmStartFail,
|
|
43
|
+
UnknownAlgorithmStartFail,
|
|
49
44
|
)
|
|
50
|
-
from vantage6.node.
|
|
45
|
+
from vantage6.node.docker.squid import Squid
|
|
46
|
+
from vantage6.node.docker.task_manager import DockerTaskManager
|
|
51
47
|
from vantage6.node.docker.utils import login_to_registries
|
|
48
|
+
from vantage6.node.docker.vpn_manager import VPNManager
|
|
49
|
+
from vantage6.node.globals import DEFAULT_REQUIRE_ALGO_IMAGE_PULL
|
|
52
50
|
|
|
53
51
|
log = logging.getLogger(logger_name(__name__))
|
|
54
52
|
|
|
@@ -414,7 +412,7 @@ class DockerManager(DockerBaseManager):
|
|
|
414
412
|
)
|
|
415
413
|
if evaluated_img.startswith(BASIC_PROCESSING_IMAGE):
|
|
416
414
|
if not allow_basics:
|
|
417
|
-
self.log.
|
|
415
|
+
self.log.warning(
|
|
418
416
|
"A task was sent with a basics algorithm that "
|
|
419
417
|
"this node does not allow to run."
|
|
420
418
|
)
|
|
@@ -515,20 +513,47 @@ class DockerManager(DockerBaseManager):
|
|
|
515
513
|
except Exception:
|
|
516
514
|
store_id = None
|
|
517
515
|
if store_id:
|
|
518
|
-
|
|
519
|
-
store_from_task =
|
|
516
|
+
store_info = self.client.algorithm_store.get(store_id)
|
|
517
|
+
store_from_task = store_info["url"]
|
|
520
518
|
# check if the store matches any of the regex cases
|
|
521
519
|
if isinstance(allowed_stores, str):
|
|
522
520
|
allowed_stores = [allowed_stores]
|
|
523
|
-
|
|
524
|
-
|
|
521
|
+
store_url_whitelisted = False
|
|
522
|
+
for allowed_store in allowed_stores:
|
|
523
|
+
if not self._is_regex_pattern(allowed_store):
|
|
525
524
|
# check if string matches exactly
|
|
526
|
-
if
|
|
527
|
-
|
|
525
|
+
if allowed_store == store_from_task:
|
|
526
|
+
store_url_whitelisted = True
|
|
528
527
|
else:
|
|
529
|
-
expr_ = re.compile(
|
|
528
|
+
expr_ = re.compile(allowed_store)
|
|
530
529
|
if expr_.match(store_from_task):
|
|
531
|
-
|
|
530
|
+
store_url_whitelisted = True
|
|
531
|
+
|
|
532
|
+
if store_url_whitelisted:
|
|
533
|
+
# The store's URL is whitelisted, but that alone does not prove
|
|
534
|
+
# that the evaluated image is actually a registered, approved
|
|
535
|
+
# algorithm in that store - the server is the one asserting that
|
|
536
|
+
# association, and the server is not fully trusted here.
|
|
537
|
+
# Re-verify directly with the store itself instead of trusting
|
|
538
|
+
# the server's claim.
|
|
539
|
+
# `store_info['url']` is the full base URL the store was
|
|
540
|
+
# registered with, including its API path (default `/api`, but
|
|
541
|
+
# configurable per store) - nothing needs to be appended here.
|
|
542
|
+
self.client.algorithm_store.url = store_info["url"]
|
|
543
|
+
self.client.algorithm_store.store_id = store_id
|
|
544
|
+
algorithm = self.client.algorithm_store.get_algorithm(evaluated_img)
|
|
545
|
+
if algorithm:
|
|
546
|
+
store_whitelisted = True
|
|
547
|
+
else:
|
|
548
|
+
self.log.warning(
|
|
549
|
+
"Algorithm store %s did not confirm that image %s is a "
|
|
550
|
+
"registered, approved algorithm there. Denying the "
|
|
551
|
+
"allowed_algorithm_stores policy for this image. This "
|
|
552
|
+
"can also happen if the algorithm store does not yet "
|
|
553
|
+
"support node verification requests.",
|
|
554
|
+
store_from_task,
|
|
555
|
+
evaluated_img,
|
|
556
|
+
)
|
|
532
557
|
|
|
533
558
|
allowed_from_whitelist = not allowed_algorithms or algorithm_whitelisted
|
|
534
559
|
allowed_from_store = not allowed_stores or store_whitelisted
|
|
@@ -587,11 +612,11 @@ class DockerManager(DockerBaseManager):
|
|
|
587
612
|
"}",
|
|
588
613
|
"|",
|
|
589
614
|
"+",
|
|
590
|
-
"\.",
|
|
615
|
+
r"\.",
|
|
591
616
|
]
|
|
592
617
|
# Use common characters used in regular expressions as a proxy
|
|
593
618
|
# for if this string is in fact a regex.
|
|
594
|
-
return any(
|
|
619
|
+
return any(c in pattern for c in common_regex_chars)
|
|
595
620
|
|
|
596
621
|
def is_running(self, run_id: int) -> bool:
|
|
597
622
|
"""
|
|
@@ -910,7 +935,7 @@ class DockerManager(DockerBaseManager):
|
|
|
910
935
|
)
|
|
911
936
|
)
|
|
912
937
|
else:
|
|
913
|
-
self.log.
|
|
938
|
+
self.log.warning(
|
|
914
939
|
"Received instruction to kill run_id="
|
|
915
940
|
f"{container_to_kill['run_id']}, but it was not "
|
|
916
941
|
"found running on this node."
|
|
@@ -940,18 +965,18 @@ class DockerManager(DockerBaseManager):
|
|
|
940
965
|
killed_runs = self.kill_selected_tasks(org_id=org_id, kill_list=kill_list)
|
|
941
966
|
else:
|
|
942
967
|
# received instruction to kill all tasks on this node
|
|
943
|
-
self.log.
|
|
968
|
+
self.log.warning(
|
|
944
969
|
"Received instruction from server to kill all algorithms "
|
|
945
970
|
"running on this node. Executing that now..."
|
|
946
971
|
)
|
|
947
972
|
killed_runs = self.cleanup_tasks()
|
|
948
973
|
if len(killed_runs):
|
|
949
|
-
self.log.
|
|
974
|
+
self.log.warning(
|
|
950
975
|
"Killed the following run ids as instructed via socket:"
|
|
951
976
|
f" {', '.join([str(r.run_id) for r in killed_runs])}"
|
|
952
977
|
)
|
|
953
978
|
else:
|
|
954
|
-
self.log.
|
|
979
|
+
self.log.warning("Instructed to kill tasks but none were running")
|
|
955
980
|
return killed_runs
|
|
956
981
|
|
|
957
982
|
def get_column_names(self, label: str, type_: str) -> list[str]:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: vantage6_node
|
|
3
|
-
Version: 4.15.
|
|
3
|
+
Version: 4.15.2
|
|
4
4
|
Summary: vantage6 node
|
|
5
5
|
Home-page: https://github.com/vantage6/vantage6
|
|
6
6
|
Requires-Python: >=3.10
|
|
@@ -13,9 +13,9 @@ Requires-Dist: python-socketio==5.15.0
|
|
|
13
13
|
Requires-Dist: requests==2.33.1
|
|
14
14
|
Requires-Dist: psutil==5.9.0
|
|
15
15
|
Requires-Dist: nvidia-ml-py==12.535.133
|
|
16
|
-
Requires-Dist: vantage6==4.15.
|
|
17
|
-
Requires-Dist: vantage6-client==4.15.
|
|
18
|
-
Requires-Dist: vantage6-algorithm-tools==4.15.
|
|
16
|
+
Requires-Dist: vantage6==4.15.2
|
|
17
|
+
Requires-Dist: vantage6-client==4.15.2
|
|
18
|
+
Requires-Dist: vantage6-algorithm-tools==4.15.2
|
|
19
19
|
Provides-Extra: dev
|
|
20
20
|
Requires-Dist: coverage==6.4.4; extra == "dev"
|
|
21
21
|
Requires-Dist: python-coveralls==2.9.3; extra == "dev"
|
|
@@ -6,9 +6,9 @@ python-socketio==5.15.0
|
|
|
6
6
|
requests==2.33.1
|
|
7
7
|
psutil==5.9.0
|
|
8
8
|
nvidia-ml-py==12.535.133
|
|
9
|
-
vantage6==4.15.
|
|
10
|
-
vantage6-client==4.15.
|
|
11
|
-
vantage6-algorithm-tools==4.15.
|
|
9
|
+
vantage6==4.15.2
|
|
10
|
+
vantage6-client==4.15.2
|
|
11
|
+
vantage6-algorithm-tools==4.15.2
|
|
12
12
|
|
|
13
13
|
[dev]
|
|
14
14
|
coverage==6.4.4
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|