diff --git a/CHANGELOG b/CHANGELOG index 28fe419e..fcd128f1 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -137,6 +137,13 @@ * Use parent directory as working directory for project duplication and snapshots. Fixes https://github.com/GNS3/gns3-gui/issues/2909 * Support for "usage" for "Cloud" nodes. Fixes https://github.com/GNS3/gns3-gui/issues/2887 Allow "usage" for all builtin nodes (not exposed in Ui). +## 2.2.34 28/08/2022 + +* Use original $PATH in init.sh for Docker containers. Ref #2069 +* Support pytest-asyncio 0.19.0 +* Upgrade dev dependencies and fix issues after upgrading to pytest-aiohttp v1.0.4 +* Update compute.py + ## 2.2.33.1 21/06/2022 * Add missing file for web-ui v2.2.33 diff --git a/dev-requirements.txt b/dev-requirements.txt index f02ff2a2..6f964e26 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,8 +1,8 @@ -r requirements.txt -pytest==7.0.0 -flake8==4.0.1 -pytest-timeout==2.0.1 -pytest-asyncio==0.16.0 -requests==2.26.0 -httpx==0.21.1 +pytest==7.1.2 +flake8==5.0.4 +pytest-timeout==2.1.0 +pytest-asyncio==0.19.0 +requests==2.28.1 +httpx==0.23.0 diff --git a/gns3server/api/routes/controller/projects.py b/gns3server/api/routes/controller/projects.py index 60a7d8a5..b8797e3c 100644 --- a/gns3server/api/routes/controller/projects.py +++ b/gns3server/api/routes/controller/projects.py @@ -36,7 +36,6 @@ from fastapi.responses import StreamingResponse, FileResponse from websockets.exceptions import ConnectionClosed, WebSocketException from typing import List, Optional from uuid import UUID -from pathlib import Path from gns3server import schemas from gns3server.controller import Controller @@ -46,7 +45,6 @@ from gns3server.controller.import_project import import_project as import_contro from gns3server.controller.export_project import export_project as export_controller_project from gns3server.utils.asyncio import aiozipstream from gns3server.utils.path import is_safe_path -from gns3server.config import Config from gns3server.db.repositories.rbac import RbacRepository from gns3server.db.repositories.templates import TemplatesRepository from gns3server.services.templates import TemplatesService @@ -397,6 +395,24 @@ async def duplicate_project( return new_project.asdict() +@router.post("/{project_id}/lock", status_code=status.HTTP_204_NO_CONTENT) +async def lock_project(project: Project = Depends(dep_project)) -> None: + """ + Lock all drawings and nodes in a given project. + """ + + project.lock() + + +@router.post("/{project_id}/unlock", status_code=status.HTTP_204_NO_CONTENT) +async def unlock_project(project: Project = Depends(dep_project)) -> None: + """ + Unlock all drawings and nodes in a given project. + """ + + project.unlock() + + @router.get("/{project_id}/files/{file_path:path}") async def get_file(file_path: str, project: Project = Depends(dep_project)) -> FileResponse: """ diff --git a/gns3server/appliances/fortianalyzer.gns3a b/gns3server/appliances/fortianalyzer.gns3a index 3e73ea7a..e82a10f4 100644 --- a/gns3server/appliances/fortianalyzer.gns3a +++ b/gns3server/appliances/fortianalyzer.gns3a @@ -27,6 +27,13 @@ "kvm": "allow" }, "images": [ + { + "filename": "FAZ_VM64_KVM-v7.2.1-build1215-FORTINET.out.kvm.qcow2", + "version": "7.2.1", + "md5sum": "c13b6c7678a2fc12ab969fc681ad3af5", + "filesize": 340631552, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, { "filename": "FAZ_VM64_KVM-v6-build2288-FORTINET.out.kvm.qcow2", "version": "6.4.5", @@ -177,6 +184,13 @@ } ], "versions": [ + { + "name": "7.2.1", + "images": { + "hda_disk_image": "FAZ_VM64_KVM-v7.2.1-build1215-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, { "name": "6.4.5", "images": { diff --git a/gns3server/appliances/fortigate.gns3a b/gns3server/appliances/fortigate.gns3a index fb830442..73a6e997 100644 --- a/gns3server/appliances/fortigate.gns3a +++ b/gns3server/appliances/fortigate.gns3a @@ -27,6 +27,13 @@ "kvm": "allow" }, "images": [ + { + "filename": "FGT_VM64_KVM-v7.2.1.F-build1254-FORTINET.out.kvm.qcow2", + "version": "7.2.1", + "md5sum": "e382a1ad5c7c16f49a1c0d3f45e3a3b2", + "filesize": 86704128, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, { "filename": "FGT_VM64_KVM-v6-build1828-FORTINET.out.kvm.qcow2", "version": "6.4.5", @@ -254,6 +261,13 @@ } ], "versions": [ + { + "name": "7.2.1", + "images": { + "hda_disk_image": "FGT_VM64_KVM-v7.2.1.F-build1254-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, { "name": "6.4.5", "images": { diff --git a/gns3server/appliances/fortimail.gns3a b/gns3server/appliances/fortimail.gns3a index 77bc0c35..4d5cf111 100644 --- a/gns3server/appliances/fortimail.gns3a +++ b/gns3server/appliances/fortimail.gns3a @@ -27,6 +27,13 @@ "kvm": "allow" }, "images": [ + { + "filename": "FML_VMKV-64-v721.M-build0364-FORTINET.out.kvm.qcow2", + "version": "7.2.1", + "md5sum": "b7bf13c2fb013693936b45d89dfab1ac", + "filesize": 123535360, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, { "filename": "FML_VMKV-64-v60-build0257-FORTINET.out.kvm.qcow2", "version": "6.2.1", @@ -184,6 +191,13 @@ } ], "versions": [ + { + "name": "7.2.1", + "images": { + "hda_disk_image": "FML_VMKV-64-v721.M-build0364-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, { "name": "6.2.1", "images": { diff --git a/gns3server/appliances/fortimanager.gns3a b/gns3server/appliances/fortimanager.gns3a index ce77ab7f..2f920388 100644 --- a/gns3server/appliances/fortimanager.gns3a +++ b/gns3server/appliances/fortimanager.gns3a @@ -27,6 +27,13 @@ "kvm": "allow" }, "images": [ + { + "filename": "FMG_VM64_KVM-v7.2.1-build1215-FORTINET.out.kvm.qcow2", + "version": "7.2.1", + "md5sum": "1a3eeff1204fa8f4243773f7521e12b5", + "filesize": 242814976, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, { "filename": "FMG_VM64_KVM-v6-build2288-FORTINET.out.kvm.qcow2", "version": "6.4.5", @@ -177,6 +184,13 @@ } ], "versions": [ + { + "name": "7.2.1", + "images": { + "hda_disk_image": "FMG_VM64_KVM-v7.2.1-build1215-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, { "name": "6.4.5", "images": { diff --git a/gns3server/appliances/fortiproxy.gns3a b/gns3server/appliances/fortiproxy.gns3a index 93de1f51..a03f9cce 100644 --- a/gns3server/appliances/fortiproxy.gns3a +++ b/gns3server/appliances/fortiproxy.gns3a @@ -27,6 +27,13 @@ "kvm": "allow" }, "images": [ + { + "filename": "FPX_KVM-v700.M-build0102-FORTINET.out.kvm.qcow2", + "version": "7.0.6", + "md5sum": "ad0a4612580b5a2754cc4e0121a9cf22", + "filesize": 146800640, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, { "filename": "FPX_KVM-v100-build0162-FORTINET.out.kvm.qcow2", "version": "1.1.2", @@ -51,6 +58,13 @@ } ], "versions": [ + { + "name": "7.0.6", + "images": { + "hda_disk_image": "FPX_KVM-v700.M-build0102-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, { "name": "1.1.2", "images": { diff --git a/gns3server/appliances/fortisandbox.gns3a b/gns3server/appliances/fortisandbox.gns3a index 6d352117..6fa98c51 100644 --- a/gns3server/appliances/fortisandbox.gns3a +++ b/gns3server/appliances/fortisandbox.gns3a @@ -28,6 +28,13 @@ "options": "-smp 2" }, "images": [ + { + "filename": "FSA_KVM-v400-build0231-FORTINET.out.kvm.qcow2", + "version": "4.2.2", + "md5sum": "02b7f49e3c04861601a7af26452eed66", + "filesize": 156172304, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, { "filename": "FSA_KVM-v300-build0124-FORTINET.out.kvm.qcow2", "version": "3.1.2", @@ -114,6 +121,13 @@ } ], "versions": [ + { + "name": "4.2.2", + "images": { + "hda_disk_image": "FSA_KVM-v400-build0231-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "FSA-datadrive.qcow2" + } + }, { "name": "3.1.2", "images": { diff --git a/gns3server/appliances/fortiweb.gns3a b/gns3server/appliances/fortiweb.gns3a index a0924bec..6a39036d 100644 --- a/gns3server/appliances/fortiweb.gns3a +++ b/gns3server/appliances/fortiweb.gns3a @@ -27,6 +27,13 @@ "kvm": "allow" }, "images": [ + { + "filename": "FWB_KVM-v700-build0097-FORTINET.out.kvm.qcow2", + "version": "7.0.1", + "md5sum": "a197e9db03ffaf7feb520c8f77f940f7", + "filesize": 257622528, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, { "filename": "FWB_KVM-v600-build0727-FORTINET.out.kvm.qcow2", "version": "6.2.1", @@ -121,6 +128,13 @@ } ], "versions": [ + { + "name": "7.0.1", + "images": { + "hda_disk_image": "FWB_KVM-v700-build0097-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, { "name": "6.2.1", "images": { diff --git a/gns3server/compute/docker/resources/init.sh b/gns3server/compute/docker/resources/init.sh index 8040d025..e21627d7 100755 --- a/gns3server/compute/docker/resources/init.sh +++ b/gns3server/compute/docker/resources/init.sh @@ -20,7 +20,7 @@ # the start command of the container # OLD_PATH="$PATH" -PATH=/gns3/bin:/tmp/gns3/bin:/sbin +PATH=/gns3/bin:/tmp/gns3/bin:/sbin:$PATH # bootstrap busybox commands if [ ! -d /tmp/gns3/bin ]; then diff --git a/gns3server/controller/compute.py b/gns3server/controller/compute.py index 9bc2372f..35f235cc 100644 --- a/gns3server/controller/compute.py +++ b/gns3server/controller/compute.py @@ -375,11 +375,6 @@ class Compute: log.warning(f"Cannot connect to compute '{self._id}': {e}") # Try to reconnect after 5 seconds if server unavailable only if not during tests (otherwise we create a ressource usage bomb) if not hasattr(sys, "_called_from_test") or not sys._called_from_test: - if self.id != "local" and self.id != "vm" and not self._controller.compute_has_open_project(self): - log.warning( - f"Not reconnecting to compute '{self._id}' because there is no project opened on it" - ) - return self._connection_failure += 1 # After 5 failure we close the project using the compute to avoid sync issues if self._connection_failure == 10: diff --git a/gns3server/controller/node.py b/gns3server/controller/node.py index ddb1acba..51a1bee5 100644 --- a/gns3server/controller/node.py +++ b/gns3server/controller/node.py @@ -497,6 +497,7 @@ class Node: "startup_config_content", "private_config_content", "startup_script", + "custom_adapters" ]: if key in self._properties: del self._properties[key] diff --git a/gns3server/controller/project.py b/gns3server/controller/project.py index ff7238b2..37446cae 100644 --- a/gns3server/controller/project.py +++ b/gns3server/controller/project.py @@ -1112,6 +1112,38 @@ class Project: return True return False + @open_required + def lock(self): + """ + Lock all drawings and nodes + """ + + for drawing in self._drawings.values(): + if not drawing.locked: + drawing.locked = True + self.emit_notification("drawing.updated", drawing.asdict()) + for node in self.nodes.values(): + if not node.locked: + node.locked = True + self.emit_notification("node.updated", node.asdict()) + self.dump() + + @open_required + def unlock(self): + """ + Unlock all drawings and nodes + """ + + for drawing in self._drawings.values(): + if drawing.locked: + drawing.locked = False + self.emit_notification("drawing.updated", drawing.asdict()) + for node in self.nodes.values(): + if node.locked: + node.locked = False + self.emit_notification("node.updated", node.asdict()) + self.dump() + def dump(self): """ Dump topology to disk diff --git a/gns3server/schemas/common.py b/gns3server/schemas/common.py index fbbb9b9b..ad6d6866 100644 --- a/gns3server/schemas/common.py +++ b/gns3server/schemas/common.py @@ -43,7 +43,7 @@ class CustomAdapter(BaseModel): """ adapter_number: int - port_name: Optional[str] = None + port_name: str adapter_type: Optional[str] = None mac_address: Optional[str] = Field(None, regex="^([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})$") diff --git a/gns3server/schemas/compute/dynamips_nodes.py b/gns3server/schemas/compute/dynamips_nodes.py index 64bc07c2..585973fd 100644 --- a/gns3server/schemas/compute/dynamips_nodes.py +++ b/gns3server/schemas/compute/dynamips_nodes.py @@ -67,6 +67,7 @@ class DynamipsAdapters(str, Enum): c1700_mb_wic1 = "C1700-MB-WIC1" gt96100_fe = "GT96100-FE" leopard_2fe = "Leopard-2FE" + _ = "" class DynamipsWics(str, Enum): diff --git a/gns3server/version.py b/gns3server/version.py index 67a033ff..c7ef9c10 100644 --- a/gns3server/version.py +++ b/gns3server/version.py @@ -22,8 +22,8 @@ # or negative for a release candidate or beta (after the base version # number has been incremented) -__version__ = "3.0.0a1" -__version_info__ = (3, 0, 0, -99) +__version__ = "3.0.0dev4" +__version_info__ = (3, 0, 0, 99) if "dev" in __version__: try: diff --git a/requirements.txt b/requirements.txt index 9b87724a..21053a13 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,20 +1,20 @@ -uvicorn==0.18.2 -fastapi==0.79.0 +uvicorn==0.18.3 +fastapi==0.81.0 python-multipart==0.0.5 websockets==10.3 aiohttp==3.8.1 async-timeout==4.0.2 aiofiles==0.8.0 Jinja2==3.1.2 -sentry-sdk==1.7.1 +sentry-sdk==1.9.5 psutil==5.9.1 distro==1.7.0 py-cpuinfo==8.0.0 -sqlalchemy==1.4.39 -aiosqlite===0.17.0 +sqlalchemy==1.4.40 +aiosqlite==0.17.0 passlib[bcrypt]==1.7.4 python-jose==3.3.0 email-validator==1.2.1 -watchfiles==0.15.0 +watchfiles==0.16.1 zstandard==0.18.0 setuptools==60.6.0 # don't upgrade because of https://github.com/pypa/setuptools/issues/3084 diff --git a/tests/api/routes/compute/test_cloud_nodes.py b/tests/api/routes/compute/test_cloud_nodes.py index 6ea9f3cc..b29f8a2b 100644 --- a/tests/api/routes/compute/test_cloud_nodes.py +++ b/tests/api/routes/compute/test_cloud_nodes.py @@ -16,6 +16,7 @@ # along with this program. If not, see . import pytest +import pytest_asyncio from fastapi import FastAPI, status from httpx import AsyncClient @@ -27,7 +28,7 @@ from gns3server.compute.project import Project pytestmark = pytest.mark.asyncio -@pytest.fixture(scope="function") +@pytest_asyncio.fixture(scope="function") async def vm(app: FastAPI, compute_client: AsyncClient, compute_project: Project, on_gns3vm) -> dict: with asyncio_patch("gns3server.compute.builtin.nodes.cloud.Cloud._start_ubridge"): diff --git a/tests/api/routes/compute/test_docker_nodes.py b/tests/api/routes/compute/test_docker_nodes.py index cacbcf30..f8c7935e 100644 --- a/tests/api/routes/compute/test_docker_nodes.py +++ b/tests/api/routes/compute/test_docker_nodes.py @@ -16,7 +16,7 @@ # along with this program. If not, see . import pytest -import sys +import pytest_asyncio from fastapi import FastAPI, status from httpx import AsyncClient @@ -55,7 +55,7 @@ def base_params() -> dict: # Docker._instance = None -@pytest.fixture +@pytest_asyncio.fixture async def vm(app: FastAPI, compute_client: AsyncClient, compute_project: Project, base_params: dict) -> dict: with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "nginx"}]): diff --git a/tests/api/routes/compute/test_iou_nodes.py b/tests/api/routes/compute/test_iou_nodes.py index 61309345..d894ac30 100644 --- a/tests/api/routes/compute/test_iou_nodes.py +++ b/tests/api/routes/compute/test_iou_nodes.py @@ -16,9 +16,9 @@ # along with this program. If not, see . import pytest +import pytest_asyncio import os import stat -import sys import uuid from fastapi import FastAPI, status @@ -49,7 +49,7 @@ def base_params(tmpdir, fake_iou_bin) -> dict: return {"application_id": 42, "name": "IOU-TEST-1", "path": "iou.bin"} -@pytest.fixture +@pytest_asyncio.fixture async def vm(app: FastAPI, compute_client: AsyncClient, compute_project: Project, base_params: dict) -> dict: response = await compute_client.post(app.url_path_for("compute:create_iou_node", project_id=compute_project.id), json=base_params) diff --git a/tests/api/routes/compute/test_nat_nodes.py b/tests/api/routes/compute/test_nat_nodes.py index 67913785..0f8b0d69 100644 --- a/tests/api/routes/compute/test_nat_nodes.py +++ b/tests/api/routes/compute/test_nat_nodes.py @@ -16,6 +16,7 @@ # along with this program. If not, see . import pytest +import pytest_asyncio from fastapi import FastAPI, status from httpx import AsyncClient @@ -26,7 +27,7 @@ from gns3server.compute.project import Project pytestmark = pytest.mark.asyncio -@pytest.fixture(scope="function") +@pytest_asyncio.fixture(scope="function") async def vm(app: FastAPI, compute_client: AsyncClient, compute_project: Project, ubridge_path: str, on_gns3vm) -> dict: with asyncio_patch("gns3server.compute.builtin.nodes.nat.Nat._start_ubridge"): diff --git a/tests/api/routes/compute/test_qemu_nodes.py b/tests/api/routes/compute/test_qemu_nodes.py index 9cc14bf8..f0d3a44d 100644 --- a/tests/api/routes/compute/test_qemu_nodes.py +++ b/tests/api/routes/compute/test_qemu_nodes.py @@ -16,6 +16,7 @@ # along with this program. If not, see . import pytest +import pytest_asyncio import os import stat import shutil @@ -69,7 +70,7 @@ def base_params(tmpdir, fake_qemu_bin) -> dict: return {"name": "QEMU-TEST-1", "qemu_path": fake_qemu_bin} -@pytest.fixture +@pytest_asyncio.fixture async def qemu_vm(app: FastAPI, compute_client: AsyncClient, compute_project: Project, base_params: dict) -> None: response = await compute_client.post( diff --git a/tests/api/routes/compute/test_virtualbox_nodes.py b/tests/api/routes/compute/test_virtualbox_nodes.py index 30ffe139..5a88b6d7 100644 --- a/tests/api/routes/compute/test_virtualbox_nodes.py +++ b/tests/api/routes/compute/test_virtualbox_nodes.py @@ -16,6 +16,7 @@ # along with this program. If not, see . import pytest +import pytest_asyncio from fastapi import FastAPI, status from httpx import AsyncClient @@ -27,7 +28,7 @@ from gns3server.compute.project import Project pytestmark = pytest.mark.asyncio -@pytest.fixture(scope="function") +@pytest_asyncio.fixture(scope="function") async def vm(app: FastAPI, compute_client: AsyncClient, compute_project: Project) -> None: vboxmanage_path = "/fake/VboxManage" diff --git a/tests/api/routes/compute/test_vmware_nodes.py b/tests/api/routes/compute/test_vmware_nodes.py index 7ac81ef4..088b4db2 100644 --- a/tests/api/routes/compute/test_vmware_nodes.py +++ b/tests/api/routes/compute/test_vmware_nodes.py @@ -16,6 +16,7 @@ # along with this program. If not, see . import pytest +import pytest_asyncio from fastapi import FastAPI, status from httpx import AsyncClient @@ -27,7 +28,7 @@ from gns3server.compute.project import Project pytestmark = pytest.mark.asyncio -@pytest.fixture(scope="function") +@pytest_asyncio.fixture(scope="function") async def vm(app: FastAPI, compute_client: AsyncClient, compute_project: Project, vmx_path: str) -> dict: params = { diff --git a/tests/api/routes/compute/test_vpcs_nodes.py b/tests/api/routes/compute/test_vpcs_nodes.py index e49a84bb..f0b69366 100644 --- a/tests/api/routes/compute/test_vpcs_nodes.py +++ b/tests/api/routes/compute/test_vpcs_nodes.py @@ -16,6 +16,7 @@ # along with this program. If not, see . import pytest +import pytest_asyncio from fastapi import FastAPI, status from httpx import AsyncClient @@ -27,7 +28,7 @@ from gns3server.compute.project import Project pytestmark = pytest.mark.asyncio -@pytest.fixture +@pytest_asyncio.fixture async def vm(app: FastAPI, compute_client: AsyncClient, compute_project: Project) -> None: params = {"name": "PC TEST 1"} diff --git a/tests/api/routes/controller/test_groups.py b/tests/api/routes/controller/test_groups.py index 4e0700bb..e8d6e791 100644 --- a/tests/api/routes/controller/test_groups.py +++ b/tests/api/routes/controller/test_groups.py @@ -16,6 +16,7 @@ # along with this program. If not, see . import pytest +import pytest_asyncio from fastapi import FastAPI, status from httpx import AsyncClient @@ -171,7 +172,7 @@ class TestGroupMembersRoutes: assert len(members) == 0 -@pytest.fixture +@pytest_asyncio.fixture async def test_role(db_session: AsyncSession) -> Role: new_role = schemas.RoleCreate( diff --git a/tests/api/routes/controller/test_links.py b/tests/api/routes/controller/test_links.py index bab91d88..139fb3ff 100644 --- a/tests/api/routes/controller/test_links.py +++ b/tests/api/routes/controller/test_links.py @@ -16,6 +16,7 @@ # along with this program. If not, see . import pytest +import pytest_asyncio from typing import Tuple from fastapi import FastAPI, status @@ -34,7 +35,7 @@ from gns3server.controller.udp_link import UDPLink pytestmark = pytest.mark.asyncio -@pytest.fixture +@pytest_asyncio.fixture async def nodes(compute: Compute, project: Project) -> Tuple[Node, Node]: response = MagicMock() diff --git a/tests/api/routes/controller/test_permissions.py b/tests/api/routes/controller/test_permissions.py index 5553648d..d35583f1 100644 --- a/tests/api/routes/controller/test_permissions.py +++ b/tests/api/routes/controller/test_permissions.py @@ -16,6 +16,7 @@ # along with this program. If not, see . import pytest +import pytest_asyncio import uuid from fastapi import FastAPI, status @@ -31,7 +32,7 @@ pytestmark = pytest.mark.asyncio class TestPermissionRoutes: - @pytest.fixture() + @pytest_asyncio.fixture async def project(self, app: FastAPI, client: AsyncClient, controller: Controller) -> Project: project_uuid = str(uuid.uuid4()) diff --git a/tests/api/routes/controller/test_projects.py b/tests/api/routes/controller/test_projects.py index e347707a..e94cc8fc 100644 --- a/tests/api/routes/controller/test_projects.py +++ b/tests/api/routes/controller/test_projects.py @@ -19,26 +19,28 @@ import uuid import os import json import pytest +import pytest_asyncio from fastapi import FastAPI, status from httpx import AsyncClient from unittest.mock import patch, MagicMock -from tests.utils import asyncio_patch +from tests.utils import asyncio_patch, AsyncioMagicMock import gns3server.utils.zipfile_zstd as zipfile_zstd from gns3server.controller import Controller from gns3server.controller.project import Project +from gns3server.controller.compute import Compute pytestmark = pytest.mark.asyncio -@pytest.fixture +@pytest_asyncio.fixture async def project(app: FastAPI, client: AsyncClient, controller: Controller) -> Project: - u = str(uuid.uuid4()) - params = {"name": "test", "project_id": u} + project_id = str(uuid.uuid4()) + params = {"name": "test", "project_id": project_id} await client.post(app.url_path_for("create_project"), json=params) - return controller.get_project(u) + return controller.get_project(project_id) async def test_create_project_with_path(app: FastAPI, client: AsyncClient, controller: Controller, config) -> None: @@ -472,3 +474,47 @@ async def test_duplicate(app: FastAPI, client: AsyncClient, project: Project) -> response = await client.post(app.url_path_for("duplicate_project", project_id=project.id), json={"name": "hello"}) assert response.status_code == status.HTTP_201_CREATED assert response.json()["name"] == "hello" + + +async def test_lock_unlock(app: FastAPI, client: AsyncClient, project: Project, compute: Compute) -> None: + + # add a drawing and node to the project + params = { + "svg": '', + "x": 10, + "y": 20, + "z": 0 + } + + response = await client.post(app.url_path_for("create_drawing", project_id=project.id), json=params) + assert response.status_code == status.HTTP_201_CREATED + + response = MagicMock() + response.json = {"console": 2048} + compute.post = AsyncioMagicMock(return_value=response) + + response = await client.post(app.url_path_for("create_node", project_id=project.id), json={ + "name": "test", + "node_type": "vpcs", + "compute_id": "example.com", + "properties": { + "startup_script": "echo test" + } + }) + assert response.status_code == status.HTTP_201_CREATED + + response = await client.post(app.url_path_for("lock_project", project_id=project.id)) + assert response.status_code == status.HTTP_204_NO_CONTENT + + for drawing in project.drawings.values(): + assert drawing.locked is True + for node in project.nodes.values(): + assert node.locked is True + + response = await client.post(app.url_path_for("unlock_project", project_id=project.id)) + assert response.status_code == status.HTTP_204_NO_CONTENT + + for drawing in project.drawings.values(): + assert drawing.locked is False + for node in project.nodes.values(): + assert node.locked is False diff --git a/tests/api/routes/controller/test_roles.py b/tests/api/routes/controller/test_roles.py index 0ffe0b1a..600ca89d 100644 --- a/tests/api/routes/controller/test_roles.py +++ b/tests/api/routes/controller/test_roles.py @@ -16,6 +16,7 @@ # along with this program. If not, see . import pytest +import pytest_asyncio from fastapi import FastAPI, status from httpx import AsyncClient @@ -105,7 +106,7 @@ class TestRolesRoutes: assert response.status_code == status.HTTP_403_FORBIDDEN -@pytest.fixture +@pytest_asyncio.fixture async def test_permission(db_session: AsyncSession) -> Permission: new_permission = schemas.PermissionCreate( diff --git a/tests/api/routes/controller/test_snapshots.py b/tests/api/routes/controller/test_snapshots.py index 7b7749e5..3058cdad 100644 --- a/tests/api/routes/controller/test_snapshots.py +++ b/tests/api/routes/controller/test_snapshots.py @@ -18,6 +18,7 @@ import os import uuid import pytest +import pytest_asyncio from fastapi import FastAPI, status from httpx import AsyncClient @@ -29,7 +30,7 @@ from gns3server.controller.snapshot import Snapshot pytestmark = pytest.mark.asyncio -@pytest.fixture +@pytest_asyncio.fixture async def project(app: FastAPI, client: AsyncClient, controller: Controller) -> Project: u = str(uuid.uuid4()) @@ -39,7 +40,7 @@ async def project(app: FastAPI, client: AsyncClient, controller: Controller) -> return project -@pytest.fixture +@pytest_asyncio.fixture async def snapshot(project: Project): snapshot = await project.snapshot("test") diff --git a/tests/api/routes/controller/test_users.py b/tests/api/routes/controller/test_users.py index 042c2b32..971961ad 100644 --- a/tests/api/routes/controller/test_users.py +++ b/tests/api/routes/controller/test_users.py @@ -16,6 +16,7 @@ # along with this program. If not, see . import pytest +import pytest_asyncio from typing import Optional from fastapi import FastAPI, HTTPException, status @@ -438,7 +439,8 @@ class TestSuperAdmin: # assert response.status_code == status.HTTP_200_OK # assert len(response.json()) == 1 -@pytest.fixture + +@pytest_asyncio.fixture async def test_permission(db_session: AsyncSession) -> Permission: new_permission = schemas.PermissionCreate( diff --git a/tests/compute/builtin/nodes/test_cloud.py b/tests/compute/builtin/nodes/test_cloud.py index a45718fe..7a482260 100644 --- a/tests/compute/builtin/nodes/test_cloud.py +++ b/tests/compute/builtin/nodes/test_cloud.py @@ -17,6 +17,7 @@ import uuid import pytest +import pytest_asyncio from unittest.mock import MagicMock, patch, call from gns3server.compute.builtin.nodes.cloud import Cloud @@ -30,8 +31,7 @@ def nio(): return NIOUDP(4242, "127.0.0.1", 4343) -@pytest.fixture -@pytest.mark.asyncio +@pytest_asyncio.fixture async def manager(): m = MagicMock() diff --git a/tests/compute/docker/test_docker.py b/tests/compute/docker/test_docker.py index c118d03e..5155d4eb 100644 --- a/tests/compute/docker/test_docker.py +++ b/tests/compute/docker/test_docker.py @@ -16,6 +16,7 @@ # along with this program. If not, see . import pytest +import pytest_asyncio from unittest.mock import MagicMock, patch from tests.utils import asyncio_patch, AsyncioMagicMock @@ -23,8 +24,7 @@ from gns3server.compute.docker import Docker, DOCKER_PREFERRED_API_VERSION, DOCK from gns3server.compute.docker.docker_error import DockerError, DockerHttp404Error -@pytest.fixture -@pytest.mark.asyncio +@pytest_asyncio.fixture async def vm(): vm = Docker() diff --git a/tests/compute/docker/test_docker_vm.py b/tests/compute/docker/test_docker_vm.py index 7088a643..e6e9ee9d 100644 --- a/tests/compute/docker/test_docker_vm.py +++ b/tests/compute/docker/test_docker_vm.py @@ -18,8 +18,8 @@ import aiohttp import asyncio import pytest +import pytest_asyncio import uuid -import sys import os from tests.utils import asyncio_patch, AsyncioMagicMock @@ -33,8 +33,7 @@ from gns3server.utils.get_resource import get_resource from unittest.mock import patch, MagicMock, call -@pytest.fixture() -@pytest.mark.asyncio +@pytest_asyncio.fixture async def manager(port_manager): m = Docker.instance() @@ -42,8 +41,7 @@ async def manager(port_manager): return m -@pytest.fixture(scope="function") -@pytest.mark.asyncio +@pytest_asyncio.fixture(scope="function") async def vm(compute_project, manager): vm = DockerVM("test", str(uuid.uuid4()), compute_project, manager, "ubuntu:latest", aux_type="none") diff --git a/tests/compute/dynamips/test_dynamips_manager.py b/tests/compute/dynamips/test_dynamips_manager.py index 5665839f..94fd03e2 100644 --- a/tests/compute/dynamips/test_dynamips_manager.py +++ b/tests/compute/dynamips/test_dynamips_manager.py @@ -17,8 +17,8 @@ import pytest +import pytest_asyncio import tempfile -import sys import uuid import os @@ -28,8 +28,7 @@ from unittest.mock import patch from tests.utils import asyncio_patch, AsyncioMagicMock -@pytest.fixture -@pytest.mark.asyncio +@pytest_asyncio.fixture async def manager(port_manager): m = Dynamips.instance() diff --git a/tests/compute/dynamips/test_dynamips_router.py b/tests/compute/dynamips/test_dynamips_router.py index 2dbcf881..5ececc90 100644 --- a/tests/compute/dynamips/test_dynamips_router.py +++ b/tests/compute/dynamips/test_dynamips_router.py @@ -18,7 +18,7 @@ import os import uuid import pytest -import asyncio +import pytest_asyncio from gns3server.compute.dynamips.nodes.router import Router from gns3server.compute.dynamips.dynamips_error import DynamipsError @@ -26,8 +26,7 @@ from gns3server.compute.dynamips import Dynamips from gns3server.config import Config -@pytest.fixture -@pytest.mark.asyncio +@pytest_asyncio.fixture async def manager(port_manager): m = Dynamips.instance() diff --git a/tests/compute/iou/test_iou_vm.py b/tests/compute/iou/test_iou_vm.py index afd6fb78..76764ff5 100644 --- a/tests/compute/iou/test_iou_vm.py +++ b/tests/compute/iou/test_iou_vm.py @@ -16,11 +16,11 @@ # along with this program. If not, see . import pytest +import pytest_asyncio import asyncio import os import stat import socket -import sys import uuid import shutil @@ -32,8 +32,7 @@ from gns3server.compute.iou.iou_error import IOUError from gns3server.compute.iou import IOU -@pytest.fixture -@pytest.mark.asyncio +@pytest_asyncio.fixture async def manager(port_manager): m = IOU.instance() @@ -41,8 +40,7 @@ async def manager(port_manager): return m -@pytest.fixture(scope="function") -@pytest.mark.asyncio +@pytest_asyncio.fixture(scope="function") async def vm(compute_project, manager, config, tmpdir, fake_iou_bin, iourc_file): vm = IOUVM("test", str(uuid.uuid4()), compute_project, manager, application_id=1) diff --git a/tests/compute/qemu/test_qemu_vm.py b/tests/compute/qemu/test_qemu_vm.py index c2b824ea..d5edc874 100644 --- a/tests/compute/qemu/test_qemu_vm.py +++ b/tests/compute/qemu/test_qemu_vm.py @@ -16,6 +16,7 @@ # along with this program. If not, see . import pytest +import pytest_asyncio import asyncio import os import stat @@ -32,8 +33,7 @@ from gns3server.utils import force_unix_path, macaddress_to_int, int_to_macaddre from gns3server.compute.notification_manager import NotificationManager -@pytest.fixture -@pytest.mark.asyncio +@pytest_asyncio.fixture async def manager(port_manager): m = Qemu.instance() @@ -63,8 +63,7 @@ def fake_qemu_binary(monkeypatch, tmpdir): return bin_path -@pytest.fixture(scope="function") -@pytest.mark.asyncio +@pytest_asyncio.fixture(scope="function") async def vm(compute_project, manager, fake_qemu_binary, fake_qemu_img_binary): manager.port_manager.console_host = "127.0.0.1" diff --git a/tests/compute/test_base_node.py b/tests/compute/test_base_node.py index ea368672..58c06ff5 100644 --- a/tests/compute/test_base_node.py +++ b/tests/compute/test_base_node.py @@ -18,7 +18,7 @@ from collections import OrderedDict import pytest -import asyncio +import pytest_asyncio from tests.utils import asyncio_patch, AsyncioMagicMock @@ -29,8 +29,7 @@ from gns3server.compute.vpcs import VPCS from gns3server.compute.nios.nio_udp import NIOUDP -@pytest.fixture(scope="function") -@pytest.mark.asyncio +@pytest_asyncio.fixture(scope="function") async def manager(port_manager): m = VPCS.instance() diff --git a/tests/compute/test_manager.py b/tests/compute/test_manager.py index a676b42a..e92a82ee 100644 --- a/tests/compute/test_manager.py +++ b/tests/compute/test_manager.py @@ -18,6 +18,7 @@ import uuid import os import pytest +import pytest_asyncio from unittest.mock import patch, MagicMock from tests.utils import asyncio_patch @@ -28,8 +29,7 @@ from gns3server.compute.error import NodeError, ImageMissingError from gns3server.utils import force_unix_path -@pytest.fixture(scope="function") -@pytest.mark.asyncio +@pytest_asyncio.fixture(scope="function") async def vpcs(port_manager): VPCS._instance = None @@ -38,8 +38,7 @@ async def vpcs(port_manager): return vpcs -@pytest.fixture(scope="function") -@pytest.mark.asyncio +@pytest_asyncio.fixture(scope="function") async def qemu(port_manager): Qemu._instance = None diff --git a/tests/compute/test_project.py b/tests/compute/test_project.py index 6a8729c1..50f96792 100644 --- a/tests/compute/test_project.py +++ b/tests/compute/test_project.py @@ -19,6 +19,7 @@ import os import uuid import pytest +import pytest_asyncio from uuid import uuid4 from unittest.mock import patch @@ -29,8 +30,7 @@ from gns3server.compute.compute_error import ComputeError, ComputeForbiddenError from gns3server.compute.vpcs import VPCS, VPCSVM -@pytest.fixture(scope="function") -@pytest.mark.asyncio +@pytest_asyncio.fixture(scope="function") async def manager(port_manager): m = VPCS.instance() @@ -38,8 +38,7 @@ async def manager(port_manager): return m -@pytest.fixture(scope="function") -@pytest.mark.asyncio +@pytest_asyncio.fixture(scope="function") async def node(compute_project, manager): node = manager.create_node("test", compute_project.id, "00010203-0405-0607-0809-0a0b0c0d0e0f") diff --git a/tests/compute/virtualbox/test_virtualbox_manager.py b/tests/compute/virtualbox/test_virtualbox_manager.py index 2203c051..54d7e9f1 100644 --- a/tests/compute/virtualbox/test_virtualbox_manager.py +++ b/tests/compute/virtualbox/test_virtualbox_manager.py @@ -17,6 +17,7 @@ import pytest +import pytest_asyncio import tempfile import os import stat @@ -28,7 +29,7 @@ from gns3server.compute.virtualbox.virtualbox_error import VirtualBoxError from tests.utils import asyncio_patch -@pytest.fixture +@pytest_asyncio.fixture async def manager(port_manager): m = VirtualBox.instance() diff --git a/tests/compute/virtualbox/test_virtualbox_vm.py b/tests/compute/virtualbox/test_virtualbox_vm.py index a69660db..5303834e 100644 --- a/tests/compute/virtualbox/test_virtualbox_vm.py +++ b/tests/compute/virtualbox/test_virtualbox_vm.py @@ -17,6 +17,7 @@ import os import pytest +import pytest_asyncio from tests.utils import asyncio_patch, AsyncioMagicMock from gns3server.compute.virtualbox.virtualbox_vm import VirtualBoxVM @@ -24,8 +25,7 @@ from gns3server.compute.virtualbox.virtualbox_error import VirtualBoxError from gns3server.compute.virtualbox import VirtualBox -@pytest.fixture -@pytest.mark.asyncio +@pytest_asyncio.fixture async def manager(port_manager): m = VirtualBox.instance() @@ -33,8 +33,7 @@ async def manager(port_manager): return m -@pytest.fixture(scope="function") -@pytest.mark.asyncio +@pytest_asyncio.fixture(scope="function") async def vm(compute_project, manager): return VirtualBoxVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", compute_project, manager, "test", False) diff --git a/tests/compute/vmware/test_vmware_manager.py b/tests/compute/vmware/test_vmware_manager.py index 16e2ba61..7f2c2e0b 100644 --- a/tests/compute/vmware/test_vmware_manager.py +++ b/tests/compute/vmware/test_vmware_manager.py @@ -16,13 +16,12 @@ # along with this program. If not, see . -import pytest +import pytest_asyncio from gns3server.compute.vmware import VMware -@pytest.fixture -@pytest.mark.asyncio +@pytest_asyncio.fixture async def manager(port_manager): m = VMware.instance() diff --git a/tests/compute/vmware/test_vmware_vm.py b/tests/compute/vmware/test_vmware_vm.py index 6b797c7b..631f07e1 100644 --- a/tests/compute/vmware/test_vmware_vm.py +++ b/tests/compute/vmware/test_vmware_vm.py @@ -16,13 +16,13 @@ # along with this program. If not, see . import pytest +import pytest_asyncio from gns3server.compute.vmware.vmware_vm import VMwareVM from gns3server.compute.vmware import VMware -@pytest.fixture -@pytest.mark.asyncio +@pytest_asyncio.fixture async def manager(port_manager): m = VMware.instance() @@ -30,8 +30,7 @@ async def manager(port_manager): return m -@pytest.fixture(scope="function") -@pytest.mark.asyncio +@pytest_asyncio.fixture(scope="function") async def vm(compute_project, manager, tmpdir): fake_vmx = str(tmpdir / "test.vmx") diff --git a/tests/compute/vpcs/test_vpcs_vm.py b/tests/compute/vpcs/test_vpcs_vm.py index a99c4e15..e85604f2 100644 --- a/tests/compute/vpcs/test_vpcs_vm.py +++ b/tests/compute/vpcs/test_vpcs_vm.py @@ -16,9 +16,9 @@ # along with this program. If not, see . import pytest +import pytest_asyncio import asyncio import os -import sys from tests.utils import asyncio_patch, AsyncioMagicMock from gns3server.utils import parse_version @@ -30,8 +30,7 @@ from gns3server.compute.vpcs import VPCS from gns3server.compute.notification_manager import NotificationManager -@pytest.fixture -@pytest.mark.asyncio +@pytest_asyncio.fixture async def manager(port_manager): m = VPCS.instance() @@ -39,8 +38,7 @@ async def manager(port_manager): return m -@pytest.fixture(scope="function") -@pytest.mark.asyncio +@pytest_asyncio.fixture(scope="function") async def vm(compute_project, manager, tmpdir, ubridge_path): vm = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", compute_project, manager) diff --git a/tests/conftest.py b/tests/conftest.py index 81715666..579c4f78 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,5 +1,6 @@ import pytest import asyncio +import pytest_asyncio import tempfile import shutil import sys @@ -43,14 +44,14 @@ def event_loop(request): loop.close() -@pytest.fixture(scope="class") +@pytest_asyncio.fixture(scope="class") async def app() -> FastAPI: from gns3server.api.server import app as gns3app yield gns3app -@pytest.fixture(scope="class") +@pytest_asyncio.fixture(scope="class") async def db_engine(): db_url = os.getenv("GNS3_TEST_DATABASE_URI", "sqlite+aiosqlite:///:memory:") # "sqlite:///./sql_test_app.db" @@ -59,7 +60,7 @@ async def db_engine(): #await engine.sync_engine.dispose() -@pytest.fixture(scope="class") +@pytest_asyncio.fixture(scope="class") async def db_session(db_engine): # recreate database tables for each class @@ -80,7 +81,7 @@ async def db_session(db_engine): await session.close() -@pytest.fixture +@pytest_asyncio.fixture async def base_client(app: FastAPI, db_session: AsyncSession) -> AsyncClient: async def _get_test_db(): @@ -99,7 +100,7 @@ async def base_client(app: FastAPI, db_session: AsyncSession) -> AsyncClient: yield async_client -@pytest.fixture +@pytest_asyncio.fixture async def test_user(db_session: AsyncSession) -> User: new_user = schemas.UserCreate( @@ -119,7 +120,7 @@ async def test_user(db_session: AsyncSession) -> User: return user -@pytest.fixture +@pytest_asyncio.fixture async def test_compute(db_session: AsyncSession) -> Compute: new_compute = schemas.ComputeCreate( @@ -154,7 +155,7 @@ def authorized_client(base_client: AsyncClient, test_user: User) -> AsyncClient: return base_client -@pytest.fixture +@pytest_asyncio.fixture async def client(base_client: AsyncClient) -> AsyncClient: # The super admin is automatically created when the users table is created @@ -167,7 +168,7 @@ async def client(base_client: AsyncClient) -> AsyncClient: return base_client -@pytest.fixture +@pytest_asyncio.fixture async def compute_client(base_client: AsyncClient) -> AsyncClient: # default compute username is 'admin' @@ -206,8 +207,7 @@ def compute(controller): return compute -@pytest.fixture -@pytest.mark.asyncio +@pytest_asyncio.fixture async def project(tmpdir, controller): return await controller.add_project(name="Test") diff --git a/tests/controller/gns3vm/test_virtualbox_gns3_vm.py b/tests/controller/gns3vm/test_virtualbox_gns3_vm.py index 5e5ece62..0a9be84f 100644 --- a/tests/controller/gns3vm/test_virtualbox_gns3_vm.py +++ b/tests/controller/gns3vm/test_virtualbox_gns3_vm.py @@ -16,6 +16,7 @@ # along with this program. If not, see . import pytest +import pytest_asyncio from tests.utils import asyncio_patch from gns3server.utils.asyncio import wait_run_in_executor @@ -23,8 +24,7 @@ from gns3server.utils.asyncio import wait_run_in_executor from gns3server.controller.gns3vm.virtualbox_gns3_vm import VirtualBoxGNS3VM -@pytest.fixture -@pytest.mark.asyncio +@pytest_asyncio.fixture async def gns3vm(controller): vm = VirtualBoxGNS3VM(controller) diff --git a/tests/controller/gns3vm/test_vmware_gns3_vm.py b/tests/controller/gns3vm/test_vmware_gns3_vm.py index 78c8e95a..d0f661c1 100644 --- a/tests/controller/gns3vm/test_vmware_gns3_vm.py +++ b/tests/controller/gns3vm/test_vmware_gns3_vm.py @@ -16,12 +16,12 @@ # along with this program. If not, see . import pytest +import pytest_asyncio from gns3server.controller.gns3vm.vmware_gns3_vm import VMwareGNS3VM -@pytest.fixture -@pytest.mark.asyncio +@pytest_asyncio.fixture async def gns3vm(controller): vm = VMwareGNS3VM(controller) diff --git a/tests/controller/test_export_project.py b/tests/controller/test_export_project.py index e1e0f1a7..507e30dd 100644 --- a/tests/controller/test_export_project.py +++ b/tests/controller/test_export_project.py @@ -19,6 +19,7 @@ import os import json import pytest +import pytest_asyncio import zipfile from pathlib import Path @@ -32,8 +33,7 @@ from gns3server.utils.asyncio import aiozipstream from gns3server.controller.controller_error import ControllerError -@pytest.fixture -@pytest.mark.asyncio +@pytest_asyncio.fixture async def project(controller): p = Project(controller=controller, name="test") @@ -41,8 +41,7 @@ async def project(controller): return p -@pytest.fixture -@pytest.mark.asyncio +@pytest_asyncio.fixture async def node(controller, project): compute = MagicMock() diff --git a/tests/controller/test_link.py b/tests/controller/test_link.py index 9771de44..1448585e 100644 --- a/tests/controller/test_link.py +++ b/tests/controller/test_link.py @@ -16,6 +16,7 @@ # along with this program. If not, see . import pytest +import pytest_asyncio from unittest.mock import MagicMock from gns3server.controller.link import Link @@ -26,8 +27,7 @@ from gns3server.controller.controller_error import ControllerError from tests.utils import AsyncioBytesIO, AsyncioMagicMock -@pytest.fixture -@pytest.mark.asyncio +@pytest_asyncio.fixture async def link(project, compute): node1 = Node(project, compute, "node1", node_type="qemu") diff --git a/tests/controller/test_node_port_name.py b/tests/controller/test_node_port_name.py index 0e254f9a..193f82ae 100644 --- a/tests/controller/test_node_port_name.py +++ b/tests/controller/test_node_port_name.py @@ -30,6 +30,7 @@ def compute(): s.id = "http://test.com:42" return s + @pytest.fixture def node(compute, project): node = Node(project, compute, "demo", diff --git a/tests/controller/test_notification.py b/tests/controller/test_notification.py index 17be9d79..9204acea 100644 --- a/tests/controller/test_notification.py +++ b/tests/controller/test_notification.py @@ -16,13 +16,13 @@ # along with this program. If not, see . import pytest +import pytest_asyncio from unittest.mock import MagicMock from tests.utils import AsyncioMagicMock -@pytest.fixture -@pytest.mark.asyncio +@pytest_asyncio.fixture async def node(project): compute = MagicMock() diff --git a/tests/controller/test_project.py b/tests/controller/test_project.py index f217ae4b..2469b669 100644 --- a/tests/controller/test_project.py +++ b/tests/controller/test_project.py @@ -17,9 +17,9 @@ # along with this program. If not, see . import os -import sys import uuid import pytest +import pytest_asyncio from unittest.mock import MagicMock from tests.utils import AsyncioMagicMock, asyncio_patch from unittest.mock import patch @@ -32,8 +32,7 @@ from gns3server.controller.controller_error import ControllerError, ControllerNo from gns3server.config import Config -@pytest.fixture -@pytest.mark.asyncio +@pytest_asyncio.fixture async def node(controller, project): compute = MagicMock()