From 9404c00411abc811201ef976668a8a82d943cc37 Mon Sep 17 00:00:00 2001 From: grossmj Date: Sun, 18 Apr 2021 15:40:38 +0930 Subject: [PATCH] Complete type annotations for API endpoints. --- .../api/routes/compute/atm_switch_nodes.py | 58 +++++++++----- gns3server/api/routes/compute/capabilities.py | 2 +- gns3server/api/routes/compute/cloud_nodes.py | 69 +++++++++++------ gns3server/api/routes/compute/compute.py | 14 ++-- gns3server/api/routes/compute/docker_nodes.py | 63 ++++++++++------ .../api/routes/compute/dynamips_nodes.py | 59 +++++++++------ .../api/routes/compute/ethernet_hub_nodes.py | 60 ++++++++++----- .../routes/compute/ethernet_switch_nodes.py | 66 ++++++++++------ .../compute/frame_relay_switch_nodes.py | 69 +++++++++++------ gns3server/api/routes/compute/images.py | 12 +-- gns3server/api/routes/compute/iou_nodes.py | 48 +++++++----- gns3server/api/routes/compute/nat_nodes.py | 69 +++++++++++------ .../api/routes/compute/notifications.py | 2 +- gns3server/api/routes/compute/projects.py | 23 +++--- gns3server/api/routes/compute/qemu_nodes.py | 75 ++++++++++++------- .../api/routes/compute/virtualbox_nodes.py | 75 ++++++++++++------- gns3server/api/routes/compute/vmware_nodes.py | 68 +++++++++++------ gns3server/api/routes/compute/vpcs_nodes.py | 73 ++++++++++++------ .../api/routes/controller/appliances.py | 4 +- gns3server/api/routes/controller/computes.py | 12 +-- .../api/routes/controller/controller.py | 13 ++-- gns3server/api/routes/controller/drawings.py | 10 +-- gns3server/api/routes/controller/gns3vm.py | 9 ++- gns3server/api/routes/controller/links.py | 22 +++--- gns3server/api/routes/controller/nodes.py | 52 ++++++------- .../api/routes/controller/notifications.py | 4 +- gns3server/api/routes/controller/projects.py | 45 ++++++----- gns3server/api/routes/controller/snapshots.py | 13 ++-- gns3server/api/routes/controller/symbols.py | 11 +-- gns3server/api/routes/controller/templates.py | 10 +-- gns3server/compute/base_manager.py | 14 ++-- gns3server/db/repositories/users.py | 4 +- gns3server/schemas/controller/computes.py | 8 +- gns3server/schemas/controller/links.py | 2 +- gns3server/schemas/controller/users.py | 6 +- 35 files changed, 730 insertions(+), 414 deletions(-) diff --git a/gns3server/api/routes/compute/atm_switch_nodes.py b/gns3server/api/routes/compute/atm_switch_nodes.py index 6a84ab27..44dbc57a 100644 --- a/gns3server/api/routes/compute/atm_switch_nodes.py +++ b/gns3server/api/routes/compute/atm_switch_nodes.py @@ -20,7 +20,7 @@ API routes for ATM switch nodes. import os -from fastapi import APIRouter, Depends, Body, status +from fastapi import APIRouter, Depends, Body, Path, status from fastapi.encoders import jsonable_encoder from fastapi.responses import StreamingResponse from uuid import UUID @@ -34,7 +34,7 @@ responses = {404: {"model": schemas.ErrorMessage, "description": "Could not find router = APIRouter(responses=responses) -async def dep_node(project_id: UUID, node_id: UUID): +async def dep_node(project_id: UUID, node_id: UUID) -> ATMSwitch: """ Dependency to retrieve a node. """ @@ -50,7 +50,7 @@ async def dep_node(project_id: UUID, node_id: UUID): status_code=status.HTTP_201_CREATED, responses={409: {"model": schemas.ErrorMessage, "description": "Could not create ATM switch node"}}, ) -async def create_atm_switch(project_id: UUID, node_data: schemas.ATMSwitchCreate): +async def create_atm_switch(project_id: UUID, node_data: schemas.ATMSwitchCreate) -> schemas.ATMSwitch: """ Create a new ATM switch node. """ @@ -59,7 +59,7 @@ async def create_atm_switch(project_id: UUID, node_data: schemas.ATMSwitchCreate dynamips_manager = Dynamips.instance() node_data = jsonable_encoder(node_data, exclude_unset=True) node = await dynamips_manager.create_node( - node_data.pop("name"), + node_data.get("name"), str(project_id), node_data.get("node_id"), node_type="atm_switch", @@ -69,7 +69,7 @@ async def create_atm_switch(project_id: UUID, node_data: schemas.ATMSwitchCreate @router.get("/{node_id}", response_model=schemas.ATMSwitch) -def get_atm_switch(node: ATMSwitch = Depends(dep_node)): +def get_atm_switch(node: ATMSwitch = Depends(dep_node)) -> schemas.ATMSwitch: """ Return an ATM switch node. """ @@ -78,7 +78,10 @@ def get_atm_switch(node: ATMSwitch = Depends(dep_node)): @router.post("/{node_id}/duplicate", response_model=schemas.ATMSwitch, status_code=status.HTTP_201_CREATED) -async def duplicate_atm_switch(destination_node_id: UUID = Body(..., embed=True), node: ATMSwitch = Depends(dep_node)): +async def duplicate_atm_switch( + destination_node_id: UUID = Body(..., embed=True), + node: ATMSwitch = Depends(dep_node) +) -> schemas.ATMSwitch: """ Duplicate an ATM switch node. """ @@ -88,7 +91,10 @@ async def duplicate_atm_switch(destination_node_id: UUID = Body(..., embed=True) @router.put("/{node_id}", response_model=schemas.ATMSwitch) -async def update_atm_switch(node_data: schemas.ATMSwitchUpdate, node: ATMSwitch = Depends(dep_node)): +async def update_atm_switch( + node_data: schemas.ATMSwitchUpdate, + node: ATMSwitch = Depends(dep_node) +) -> schemas.ATMSwitch: """ Update an ATM switch node. """ @@ -103,7 +109,7 @@ async def update_atm_switch(node_data: schemas.ATMSwitchUpdate, node: ATMSwitch @router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT) -async def delete_atm_switch_node(node: ATMSwitch = Depends(dep_node)): +async def delete_atm_switch_node(node: ATMSwitch = Depends(dep_node)) -> None: """ Delete an ATM switch node. """ @@ -122,7 +128,7 @@ def start_atm_switch(node: ATMSwitch = Depends(dep_node)): @router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT) -def stop_atm_switch(node: ATMSwitch = Depends(dep_node)): +def stop_atm_switch(node: ATMSwitch = Depends(dep_node)) -> None: """ Stop an ATM switch node. This endpoint results in no action since ATM switch nodes are always on. @@ -132,7 +138,7 @@ def stop_atm_switch(node: ATMSwitch = Depends(dep_node)): @router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT) -def suspend_atm_switch(node: ATMSwitch = Depends(dep_node)): +def suspend_atm_switch(node: ATMSwitch = Depends(dep_node)) -> None: """ Suspend an ATM switch node. This endpoint results in no action since ATM switch nodes are always on. @@ -147,8 +153,12 @@ def suspend_atm_switch(node: ATMSwitch = Depends(dep_node)): response_model=schemas.UDPNIO, ) async def create_nio( - adapter_number: int, port_number: int, nio_data: schemas.UDPNIO, node: ATMSwitch = Depends(dep_node) -): + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + nio_data: schemas.UDPNIO, + node: ATMSwitch = Depends(dep_node) +) -> schemas.UDPNIO: """ Add a NIO (Network Input/Output) to the node. The adapter number on the switch is always 0. @@ -160,7 +170,7 @@ async def create_nio( @router.delete("/{node_id}/adapters/{adapter_number}/ports/{port_number}/nio", status_code=status.HTTP_204_NO_CONTENT) -async def delete_nio(adapter_number: int, port_number: int, node: ATMSwitch = Depends(dep_node)): +async def delete_nio(adapter_number: int, port_number: int, node: ATMSwitch = Depends(dep_node)) -> None: """ Remove a NIO (Network Input/Output) from the node. The adapter number on the switch is always 0. @@ -172,8 +182,12 @@ async def delete_nio(adapter_number: int, port_number: int, node: ATMSwitch = De @router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start") async def start_capture( - adapter_number: int, port_number: int, node_capture_data: schemas.NodeCapture, node: ATMSwitch = Depends(dep_node) -): + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + node_capture_data: schemas.NodeCapture, + node: ATMSwitch = Depends(dep_node) +) -> dict: """ Start a packet capture on the node. The adapter number on the switch is always 0. @@ -188,7 +202,12 @@ async def start_capture( "/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stop_capture", status_code=status.HTTP_204_NO_CONTENT, ) -async def stop_capture(adapter_number: int, port_number: int, node: ATMSwitch = Depends(dep_node)): +async def stop_capture( + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + node: ATMSwitch = Depends(dep_node) +) -> None: """ Stop a packet capture on the node. The adapter number on the switch is always 0. @@ -198,7 +217,12 @@ async def stop_capture(adapter_number: int, port_number: int, node: ATMSwitch = @router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream") -async def stream_pcap_file(adapter_number: int, port_number: int, node: ATMSwitch = Depends(dep_node)): +async def stream_pcap_file( + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + node: ATMSwitch = Depends(dep_node) +) -> StreamingResponse: """ Stream the pcap capture file. The adapter number on the switch is always 0. diff --git a/gns3server/api/routes/compute/capabilities.py b/gns3server/api/routes/compute/capabilities.py index 0931aa5c..8e865348 100644 --- a/gns3server/api/routes/compute/capabilities.py +++ b/gns3server/api/routes/compute/capabilities.py @@ -32,7 +32,7 @@ router = APIRouter() @router.get("/capabilities", response_model=schemas.Capabilities) -def get_capabilities(): +def get_capabilities() -> dict: node_types = [] for module in MODULES: diff --git a/gns3server/api/routes/compute/cloud_nodes.py b/gns3server/api/routes/compute/cloud_nodes.py index 34bda678..65ad686f 100644 --- a/gns3server/api/routes/compute/cloud_nodes.py +++ b/gns3server/api/routes/compute/cloud_nodes.py @@ -20,7 +20,7 @@ API routes for cloud nodes. import os -from fastapi import APIRouter, Depends, status +from fastapi import APIRouter, Depends, Path, status from fastapi.encoders import jsonable_encoder from fastapi.responses import StreamingResponse from typing import Union @@ -35,7 +35,7 @@ responses = {404: {"model": schemas.ErrorMessage, "description": "Could not find router = APIRouter(responses=responses) -def dep_node(project_id: UUID, node_id: UUID): +def dep_node(project_id: UUID, node_id: UUID) -> Cloud: """ Dependency to retrieve a node. """ @@ -51,7 +51,7 @@ def dep_node(project_id: UUID, node_id: UUID): status_code=status.HTTP_201_CREATED, responses={409: {"model": schemas.ErrorMessage, "description": "Could not create cloud node"}}, ) -async def create_cloud(project_id: UUID, node_data: schemas.CloudCreate): +async def create_cloud(project_id: UUID, node_data: schemas.CloudCreate) -> schemas.Cloud: """ Create a new cloud node. """ @@ -76,7 +76,7 @@ async def create_cloud(project_id: UUID, node_data: schemas.CloudCreate): @router.get("/{node_id}", response_model=schemas.Cloud) -def get_cloud(node: Cloud = Depends(dep_node)): +def get_cloud(node: Cloud = Depends(dep_node)) -> schemas.Cloud: """ Return a cloud node. """ @@ -85,7 +85,7 @@ def get_cloud(node: Cloud = Depends(dep_node)): @router.put("/{node_id}", response_model=schemas.Cloud) -def update_cloud(node_data: schemas.CloudUpdate, node: Cloud = Depends(dep_node)): +def update_cloud(node_data: schemas.CloudUpdate, node: Cloud = Depends(dep_node)) -> schemas.Cloud: """ Update a cloud node. """ @@ -99,7 +99,7 @@ def update_cloud(node_data: schemas.CloudUpdate, node: Cloud = Depends(dep_node) @router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT) -async def delete_cloud(node: Cloud = Depends(dep_node)): +async def delete_cloud(node: Cloud = Depends(dep_node)) -> None: """ Delete a cloud node. """ @@ -108,7 +108,7 @@ async def delete_cloud(node: Cloud = Depends(dep_node)): @router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT) -async def start_cloud(node: Cloud = Depends(dep_node)): +async def start_cloud(node: Cloud = Depends(dep_node)) -> None: """ Start a cloud node. """ @@ -117,7 +117,7 @@ async def start_cloud(node: Cloud = Depends(dep_node)): @router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT) -async def stop_cloud(node: Cloud = Depends(dep_node)): +async def stop_cloud(node: Cloud = Depends(dep_node)) -> None: """ Stop a cloud node. This endpoint results in no action since cloud nodes cannot be stopped. @@ -127,7 +127,7 @@ async def stop_cloud(node: Cloud = Depends(dep_node)): @router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT) -async def suspend_cloud(node: Cloud = Depends(dep_node)): +async def suspend_cloud(node: Cloud = Depends(dep_node)) -> None: """ Suspend a cloud node. This endpoint results in no action since cloud nodes cannot be suspended. @@ -142,11 +142,12 @@ async def suspend_cloud(node: Cloud = Depends(dep_node)): response_model=Union[schemas.EthernetNIO, schemas.TAPNIO, schemas.UDPNIO], ) async def create_cloud_nio( - adapter_number: int, - port_number: int, - nio_data: Union[schemas.EthernetNIO, schemas.TAPNIO, schemas.UDPNIO], - node: Cloud = Depends(dep_node), -): + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + nio_data: Union[schemas.EthernetNIO, schemas.TAPNIO, schemas.UDPNIO], + node: Cloud = Depends(dep_node), +) -> Union[schemas.EthernetNIO, schemas.TAPNIO, schemas.UDPNIO]: """ Add a NIO (Network Input/Output) to the node. The adapter number on the cloud is always 0. @@ -163,11 +164,12 @@ async def create_cloud_nio( response_model=Union[schemas.EthernetNIO, schemas.TAPNIO, schemas.UDPNIO], ) async def update_cloud_nio( - adapter_number: int, - port_number: int, - nio_data: Union[schemas.EthernetNIO, schemas.TAPNIO, schemas.UDPNIO], - node: Cloud = Depends(dep_node), -): + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + nio_data: Union[schemas.EthernetNIO, schemas.TAPNIO, schemas.UDPNIO], + node: Cloud = Depends(dep_node), +) -> Union[schemas.EthernetNIO, schemas.TAPNIO, schemas.UDPNIO]: """ Update a NIO (Network Input/Output) to the node. The adapter number on the cloud is always 0. @@ -181,7 +183,12 @@ async def update_cloud_nio( @router.delete("/{node_id}/adapters/{adapter_number}/ports/{port_number}/nio", status_code=status.HTTP_204_NO_CONTENT) -async def delete_cloud_nio(adapter_number: int, port_number: int, node: Cloud = Depends(dep_node)): +async def delete_cloud_nio( + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + node: Cloud = Depends(dep_node) +) -> None: """ Remove a NIO (Network Input/Output) from the node. The adapter number on the cloud is always 0. @@ -192,8 +199,12 @@ async def delete_cloud_nio(adapter_number: int, port_number: int, node: Cloud = @router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start") async def start_cloud_capture( - adapter_number: int, port_number: int, node_capture_data: schemas.NodeCapture, node: Cloud = Depends(dep_node) -): + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + node_capture_data: schemas.NodeCapture, + node: Cloud = Depends(dep_node) +) -> dict: """ Start a packet capture on the node. The adapter number on the cloud is always 0. @@ -207,7 +218,12 @@ async def start_cloud_capture( @router.post( "/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stop", status_code=status.HTTP_204_NO_CONTENT ) -async def stop_cloud_capture(adapter_number: int, port_number: int, node: Cloud = Depends(dep_node)): +async def stop_cloud_capture( + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + node: Cloud = Depends(dep_node) +) -> None: """ Stop a packet capture on the node. The adapter number on the cloud is always 0. @@ -217,7 +233,12 @@ async def stop_cloud_capture(adapter_number: int, port_number: int, node: Cloud @router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/pcap") -async def stream_pcap_file(adapter_number: int, port_number: int, node: Cloud = Depends(dep_node)): +async def stream_pcap_file( + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + node: Cloud = Depends(dep_node) +) -> StreamingResponse: """ Stream the pcap capture file. The adapter number on the cloud is always 0. diff --git a/gns3server/api/routes/compute/compute.py b/gns3server/api/routes/compute/compute.py index 2ae6ec2f..d97ab3f2 100644 --- a/gns3server/api/routes/compute/compute.py +++ b/gns3server/api/routes/compute/compute.py @@ -123,13 +123,15 @@ def compute_statistics() -> dict: @router.get("/qemu/binaries") -async def get_qemu_binaries(archs: Optional[List[str]] = Body(None, embed=True)): +async def get_qemu_binaries( + archs: Optional[List[str]] = Body(None, embed=True) +) -> List[str]: return await Qemu.binary_list(archs) @router.get("/qemu/img-binaries") -async def get_image_binaries(): +async def get_image_binaries() -> List[str]: return await Qemu.img_binary_list() @@ -148,7 +150,7 @@ async def get_qemu_capabilities() -> dict: status_code=status.HTTP_204_NO_CONTENT, responses={403: {"model": schemas.ErrorMessage, "description": "Forbidden to create Qemu image"}}, ) -async def create_qemu_image(image_data: schemas.QemuImageCreate): +async def create_qemu_image(image_data: schemas.QemuImageCreate) -> None: """ Create a Qemu image. """ @@ -167,7 +169,7 @@ async def create_qemu_image(image_data: schemas.QemuImageCreate): status_code=status.HTTP_204_NO_CONTENT, responses={403: {"model": schemas.ErrorMessage, "description": "Forbidden to update Qemu image"}}, ) -async def update_qemu_image(image_data: schemas.QemuImageUpdate): +async def update_qemu_image(image_data: schemas.QemuImageUpdate) -> None: """ Update a Qemu image. """ @@ -181,13 +183,13 @@ async def update_qemu_image(image_data: schemas.QemuImageUpdate): @router.get("/virtualbox/vms", response_model=List[dict]) -async def get_virtualbox_vms(): +async def get_virtualbox_vms() -> List[dict]: vbox_manager = VirtualBox.instance() return await vbox_manager.list_vms() @router.get("/vmware/vms", response_model=List[dict]) -async def get_vms(): +async def get_vms() -> List[dict]: vmware_manager = VMware.instance() return await vmware_manager.list_vms() diff --git a/gns3server/api/routes/compute/docker_nodes.py b/gns3server/api/routes/compute/docker_nodes.py index 0f90e267..042f2312 100644 --- a/gns3server/api/routes/compute/docker_nodes.py +++ b/gns3server/api/routes/compute/docker_nodes.py @@ -34,7 +34,7 @@ responses = {404: {"model": schemas.ErrorMessage, "description": "Could not find router = APIRouter(responses=responses) -def dep_node(project_id: UUID, node_id: UUID): +def dep_node(project_id: UUID, node_id: UUID) -> DockerVM: """ Dependency to retrieve a node. """ @@ -50,7 +50,7 @@ def dep_node(project_id: UUID, node_id: UUID): status_code=status.HTTP_201_CREATED, responses={409: {"model": schemas.ErrorMessage, "description": "Could not create Docker node"}}, ) -async def create_docker_node(project_id: UUID, node_data: schemas.DockerCreate): +async def create_docker_node(project_id: UUID, node_data: schemas.DockerCreate) -> schemas.Docker: """ Create a new Docker node. """ @@ -86,7 +86,7 @@ async def create_docker_node(project_id: UUID, node_data: schemas.DockerCreate): @router.get("/{node_id}", response_model=schemas.Docker) -def get_docker_node(node: DockerVM = Depends(dep_node)): +def get_docker_node(node: DockerVM = Depends(dep_node)) -> schemas.Docker: """ Return a Docker node. """ @@ -95,7 +95,7 @@ def get_docker_node(node: DockerVM = Depends(dep_node)): @router.put("/{node_id}", response_model=schemas.Docker) -async def update_docker_node(node_data: schemas.DockerUpdate, node: DockerVM = Depends(dep_node)): +async def update_docker_node(node_data: schemas.DockerUpdate, node: DockerVM = Depends(dep_node)) -> schemas.Docker: """ Update a Docker node. """ @@ -132,7 +132,7 @@ async def update_docker_node(node_data: schemas.DockerUpdate, node: DockerVM = D @router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT) -async def start_docker_node(node: DockerVM = Depends(dep_node)): +async def start_docker_node(node: DockerVM = Depends(dep_node)) -> None: """ Start a Docker node. """ @@ -141,7 +141,7 @@ async def start_docker_node(node: DockerVM = Depends(dep_node)): @router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT) -async def stop_docker_node(node: DockerVM = Depends(dep_node)): +async def stop_docker_node(node: DockerVM = Depends(dep_node)) -> None: """ Stop a Docker node. """ @@ -150,7 +150,7 @@ async def stop_docker_node(node: DockerVM = Depends(dep_node)): @router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT) -async def suspend_docker_node(node: DockerVM = Depends(dep_node)): +async def suspend_docker_node(node: DockerVM = Depends(dep_node)) -> None: """ Suspend a Docker node. """ @@ -159,7 +159,7 @@ async def suspend_docker_node(node: DockerVM = Depends(dep_node)): @router.post("/{node_id}/reload", status_code=status.HTTP_204_NO_CONTENT) -async def reload_docker_node(node: DockerVM = Depends(dep_node)): +async def reload_docker_node(node: DockerVM = Depends(dep_node)) -> None: """ Reload a Docker node. """ @@ -168,7 +168,7 @@ async def reload_docker_node(node: DockerVM = Depends(dep_node)): @router.post("/{node_id}/pause", status_code=status.HTTP_204_NO_CONTENT) -async def pause_docker_node(node: DockerVM = Depends(dep_node)): +async def pause_docker_node(node: DockerVM = Depends(dep_node)) -> None: """ Pause a Docker node. """ @@ -177,7 +177,7 @@ async def pause_docker_node(node: DockerVM = Depends(dep_node)): @router.post("/{node_id}/unpause", status_code=status.HTTP_204_NO_CONTENT) -async def unpause_docker_node(node: DockerVM = Depends(dep_node)): +async def unpause_docker_node(node: DockerVM = Depends(dep_node)) -> None: """ Unpause a Docker node. """ @@ -186,7 +186,7 @@ async def unpause_docker_node(node: DockerVM = Depends(dep_node)): @router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT) -async def delete_docker_node(node: DockerVM = Depends(dep_node)): +async def delete_docker_node(node: DockerVM = Depends(dep_node)) -> None: """ Delete a Docker node. """ @@ -195,7 +195,10 @@ async def delete_docker_node(node: DockerVM = Depends(dep_node)): @router.post("/{node_id}/duplicate", response_model=schemas.Docker, status_code=status.HTTP_201_CREATED) -async def duplicate_docker_node(destination_node_id: UUID = Body(..., embed=True), node: DockerVM = Depends(dep_node)): +async def duplicate_docker_node( + destination_node_id: UUID = Body(..., embed=True), + node: DockerVM = Depends(dep_node) +) -> schemas.Docker: """ Duplicate a Docker node. """ @@ -211,7 +214,7 @@ async def duplicate_docker_node(destination_node_id: UUID = Body(..., embed=True ) async def create_docker_node_nio( adapter_number: int, port_number: int, nio_data: schemas.UDPNIO, node: DockerVM = Depends(dep_node) -): +) -> schemas.UDPNIO: """ Add a NIO (Network Input/Output) to the node. The port number on the Docker node is always 0. @@ -229,7 +232,7 @@ async def create_docker_node_nio( ) async def update_docker_node_nio( adapter_number: int, port_number: int, nio_data: schemas.UDPNIO, node: DockerVM = Depends(dep_node) -): +) -> schemas.UDPNIO: """ Update a NIO (Network Input/Output) on the node. The port number on the Docker node is always 0. @@ -243,7 +246,11 @@ async def update_docker_node_nio( @router.delete("/{node_id}/adapters/{adapter_number}/ports/{port_number}/nio", status_code=status.HTTP_204_NO_CONTENT) -async def delete_docker_node_nio(adapter_number: int, port_number: int, node: DockerVM = Depends(dep_node)): +async def delete_docker_node_nio( + adapter_number: int, + port_number: int, + node: DockerVM = Depends(dep_node) +) -> None: """ Delete a NIO (Network Input/Output) from the node. The port number on the Docker node is always 0. @@ -254,8 +261,11 @@ async def delete_docker_node_nio(adapter_number: int, port_number: int, node: Do @router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start") async def start_docker_node_capture( - adapter_number: int, port_number: int, node_capture_data: schemas.NodeCapture, node: DockerVM = Depends(dep_node) -): + adapter_number: int, + port_number: int, + node_capture_data: schemas.NodeCapture, + node: DockerVM = Depends(dep_node) +) -> dict: """ Start a packet capture on the node. The port number on the Docker node is always 0. @@ -267,9 +277,14 @@ async def start_docker_node_capture( @router.post( - "/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stop", status_code=status.HTTP_204_NO_CONTENT + "/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stop", + status_code=status.HTTP_204_NO_CONTENT ) -async def stop_docker_node_capture(adapter_number: int, port_number: int, node: DockerVM = Depends(dep_node)): +async def stop_docker_node_capture( + adapter_number: int, + port_number: int, + node: DockerVM = Depends(dep_node) +) -> None: """ Stop a packet capture on the node. The port number on the Docker node is always 0. @@ -279,7 +294,11 @@ async def stop_docker_node_capture(adapter_number: int, port_number: int, node: @router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream") -async def stream_pcap_file(adapter_number: int, port_number: int, node: DockerVM = Depends(dep_node)): +async def stream_pcap_file( + adapter_number: int, + port_number: int, + node: DockerVM = Depends(dep_node) +) -> StreamingResponse: """ Stream the pcap capture file. The port number on the Docker node is always 0. @@ -291,7 +310,7 @@ async def stream_pcap_file(adapter_number: int, port_number: int, node: DockerVM @router.websocket("/{node_id}/console/ws") -async def console_ws(websocket: WebSocket, node: DockerVM = Depends(dep_node)): +async def console_ws(websocket: WebSocket, node: DockerVM = Depends(dep_node)) -> None: """ Console WebSocket. """ @@ -300,6 +319,6 @@ async def console_ws(websocket: WebSocket, node: DockerVM = Depends(dep_node)): @router.post("/{node_id}/console/reset", status_code=status.HTTP_204_NO_CONTENT) -async def reset_console(node: DockerVM = Depends(dep_node)): +async def reset_console(node: DockerVM = Depends(dep_node)) -> None: await node.reset_console() diff --git a/gns3server/api/routes/compute/dynamips_nodes.py b/gns3server/api/routes/compute/dynamips_nodes.py index bff59c6c..81317fd6 100644 --- a/gns3server/api/routes/compute/dynamips_nodes.py +++ b/gns3server/api/routes/compute/dynamips_nodes.py @@ -40,7 +40,7 @@ router = APIRouter(responses=responses) DEFAULT_CHASSIS = {"c1700": "1720", "c2600": "2610", "c3600": "3640"} -def dep_node(project_id: UUID, node_id: UUID): +def dep_node(project_id: UUID, node_id: UUID) -> Router: """ Dependency to retrieve a node. """ @@ -56,7 +56,7 @@ def dep_node(project_id: UUID, node_id: UUID): status_code=status.HTTP_201_CREATED, responses={409: {"model": schemas.ErrorMessage, "description": "Could not create Dynamips node"}}, ) -async def create_router(project_id: UUID, node_data: schemas.DynamipsCreate): +async def create_router(project_id: UUID, node_data: schemas.DynamipsCreate) -> schemas.Dynamips: """ Create a new Dynamips router. """ @@ -85,7 +85,7 @@ async def create_router(project_id: UUID, node_data: schemas.DynamipsCreate): @router.get("/{node_id}", response_model=schemas.Dynamips) -def get_router(node: Router = Depends(dep_node)): +def get_router(node: Router = Depends(dep_node)) -> schemas.Dynamips: """ Return Dynamips router. """ @@ -94,7 +94,7 @@ def get_router(node: Router = Depends(dep_node)): @router.put("/{node_id}", response_model=schemas.Dynamips) -async def update_router(node_data: schemas.DynamipsUpdate, node: Router = Depends(dep_node)): +async def update_router(node_data: schemas.DynamipsUpdate, node: Router = Depends(dep_node)) -> schemas.Dynamips: """ Update a Dynamips router. """ @@ -105,7 +105,7 @@ async def update_router(node_data: schemas.DynamipsUpdate, node: Router = Depend @router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT) -async def delete_router(node: Router = Depends(dep_node)): +async def delete_router(node: Router = Depends(dep_node)) -> None: """ Delete a Dynamips router. """ @@ -114,7 +114,7 @@ async def delete_router(node: Router = Depends(dep_node)): @router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT) -async def start_router(node: Router = Depends(dep_node)): +async def start_router(node: Router = Depends(dep_node)) -> None: """ Start a Dynamips router. """ @@ -127,7 +127,7 @@ async def start_router(node: Router = Depends(dep_node)): @router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT) -async def stop_router(node: Router = Depends(dep_node)): +async def stop_router(node: Router = Depends(dep_node)) -> None: """ Stop a Dynamips router. """ @@ -136,13 +136,13 @@ async def stop_router(node: Router = Depends(dep_node)): @router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT) -async def suspend_router(node: Router = Depends(dep_node)): +async def suspend_router(node: Router = Depends(dep_node)) -> None: await node.suspend() @router.post("/{node_id}/resume", status_code=status.HTTP_204_NO_CONTENT) -async def resume_router(node: Router = Depends(dep_node)): +async def resume_router(node: Router = Depends(dep_node)) -> None: """ Resume a suspended Dynamips router. """ @@ -151,7 +151,7 @@ async def resume_router(node: Router = Depends(dep_node)): @router.post("/{node_id}/reload", status_code=status.HTTP_204_NO_CONTENT) -async def reload_router(node: Router = Depends(dep_node)): +async def reload_router(node: Router = Depends(dep_node)) -> None: """ Reload a suspended Dynamips router. """ @@ -164,7 +164,12 @@ async def reload_router(node: Router = Depends(dep_node)): status_code=status.HTTP_201_CREATED, response_model=schemas.UDPNIO, ) -async def create_nio(adapter_number: int, port_number: int, nio_data: schemas.UDPNIO, node: Router = Depends(dep_node)): +async def create_nio( + adapter_number: int, + port_number: int, + nio_data: schemas.UDPNIO, + node: Router = Depends(dep_node) +) -> schemas.UDPNIO: """ Add a NIO (Network Input/Output) to the node. """ @@ -179,7 +184,12 @@ async def create_nio(adapter_number: int, port_number: int, nio_data: schemas.UD status_code=status.HTTP_201_CREATED, response_model=schemas.UDPNIO, ) -async def update_nio(adapter_number: int, port_number: int, nio_data: schemas.UDPNIO, node: Router = Depends(dep_node)): +async def update_nio( + adapter_number: int, + port_number: int, + nio_data: schemas.UDPNIO, + node: Router = Depends(dep_node) +) -> schemas.UDPNIO: """ Update a NIO (Network Input/Output) on the node. """ @@ -192,7 +202,7 @@ async def update_nio(adapter_number: int, port_number: int, nio_data: schemas.UD @router.delete("/{node_id}/adapters/{adapter_number}/ports/{port_number}/nio", status_code=status.HTTP_204_NO_CONTENT) -async def delete_nio(adapter_number: int, port_number: int, node: Router = Depends(dep_node)): +async def delete_nio(adapter_number: int, port_number: int, node: Router = Depends(dep_node)) -> None: """ Delete a NIO (Network Input/Output) from the node. """ @@ -203,8 +213,11 @@ async def delete_nio(adapter_number: int, port_number: int, node: Router = Depen @router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start") async def start_capture( - adapter_number: int, port_number: int, node_capture_data: schemas.NodeCapture, node: Router = Depends(dep_node) -): + adapter_number: int, + port_number: int, + node_capture_data: schemas.NodeCapture, + node: Router = Depends(dep_node) +) -> dict: """ Start a packet capture on the node. """ @@ -227,7 +240,7 @@ async def start_capture( @router.post( "/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stop", status_code=status.HTTP_204_NO_CONTENT ) -async def stop_capture(adapter_number: int, port_number: int, node: Router = Depends(dep_node)): +async def stop_capture(adapter_number: int, port_number: int, node: Router = Depends(dep_node)) -> None: """ Stop a packet capture on the node. """ @@ -236,7 +249,11 @@ async def stop_capture(adapter_number: int, port_number: int, node: Router = Dep @router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream") -async def stream_pcap_file(adapter_number: int, port_number: int, node: Router = Depends(dep_node)): +async def stream_pcap_file( + adapter_number: int, + port_number: int, + node: Router = Depends(dep_node) +) -> StreamingResponse: """ Stream the pcap capture file. """ @@ -266,8 +283,8 @@ async def get_auto_idlepc(node: Router = Depends(dep_node)) -> dict: return {"idlepc": idlepc} -@router.post("/{node_id}/duplicate", status_code=status.HTTP_201_CREATED) -async def duplicate_router(destination_node_id: UUID, node: Router = Depends(dep_node)): +@router.post("/{node_id}/duplicate", response_model=schemas.Dynamips, status_code=status.HTTP_201_CREATED) +async def duplicate_router(destination_node_id: UUID, node: Router = Depends(dep_node)) -> schemas.Dynamips: """ Duplicate a router. """ @@ -277,7 +294,7 @@ async def duplicate_router(destination_node_id: UUID, node: Router = Depends(dep @router.websocket("/{node_id}/console/ws") -async def console_ws(websocket: WebSocket, node: Router = Depends(dep_node)): +async def console_ws(websocket: WebSocket, node: Router = Depends(dep_node)) -> None: """ Console WebSocket. """ @@ -286,6 +303,6 @@ async def console_ws(websocket: WebSocket, node: Router = Depends(dep_node)): @router.post("/{node_id}/console/reset", status_code=status.HTTP_204_NO_CONTENT) -async def reset_console(node: Router = Depends(dep_node)): +async def reset_console(node: Router = Depends(dep_node)) -> None: await node.reset_console() diff --git a/gns3server/api/routes/compute/ethernet_hub_nodes.py b/gns3server/api/routes/compute/ethernet_hub_nodes.py index c14dce63..783cd397 100644 --- a/gns3server/api/routes/compute/ethernet_hub_nodes.py +++ b/gns3server/api/routes/compute/ethernet_hub_nodes.py @@ -20,7 +20,7 @@ API routes for Ethernet hub nodes. import os -from fastapi import APIRouter, Depends, Body, status +from fastapi import APIRouter, Depends, Body, Path, status from fastapi.encoders import jsonable_encoder from fastapi.responses import StreamingResponse from uuid import UUID @@ -34,7 +34,7 @@ responses = {404: {"model": schemas.ErrorMessage, "description": "Could not find router = APIRouter(responses=responses) -def dep_node(project_id: UUID, node_id: UUID): +def dep_node(project_id: UUID, node_id: UUID) -> EthernetHub: """ Dependency to retrieve a node. """ @@ -50,7 +50,7 @@ def dep_node(project_id: UUID, node_id: UUID): status_code=status.HTTP_201_CREATED, responses={409: {"model": schemas.ErrorMessage, "description": "Could not create Ethernet hub node"}}, ) -async def create_ethernet_hub(project_id: UUID, node_data: schemas.EthernetHubCreate): +async def create_ethernet_hub(project_id: UUID, node_data: schemas.EthernetHubCreate) -> schemas.EthernetHub: """ Create a new Ethernet hub. """ @@ -69,7 +69,7 @@ async def create_ethernet_hub(project_id: UUID, node_data: schemas.EthernetHubCr @router.get("/{node_id}", response_model=schemas.EthernetHub) -def get_ethernet_hub(node: EthernetHub = Depends(dep_node)): +def get_ethernet_hub(node: EthernetHub = Depends(dep_node)) -> schemas.EthernetHub: """ Return an Ethernet hub. """ @@ -80,7 +80,7 @@ def get_ethernet_hub(node: EthernetHub = Depends(dep_node)): @router.post("/{node_id}/duplicate", response_model=schemas.EthernetHub, status_code=status.HTTP_201_CREATED) async def duplicate_ethernet_hub( destination_node_id: UUID = Body(..., embed=True), node: EthernetHub = Depends(dep_node) -): +) -> schemas.EthernetHub: """ Duplicate an Ethernet hub. """ @@ -90,7 +90,10 @@ async def duplicate_ethernet_hub( @router.put("/{node_id}", response_model=schemas.EthernetHub) -async def update_ethernet_hub(node_data: schemas.EthernetHubUpdate, node: EthernetHub = Depends(dep_node)): +async def update_ethernet_hub( + node_data: schemas.EthernetHubUpdate, + node: EthernetHub = Depends(dep_node) +) -> schemas.EthernetHub: """ Update an Ethernet hub. """ @@ -105,7 +108,7 @@ async def update_ethernet_hub(node_data: schemas.EthernetHubUpdate, node: Ethern @router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT) -async def delete_ethernet_hub(node: EthernetHub = Depends(dep_node)): +async def delete_ethernet_hub(node: EthernetHub = Depends(dep_node)) -> None: """ Delete an Ethernet hub. """ @@ -114,7 +117,7 @@ async def delete_ethernet_hub(node: EthernetHub = Depends(dep_node)): @router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT) -def start_ethernet_hub(node: EthernetHub = Depends(dep_node)): +def start_ethernet_hub(node: EthernetHub = Depends(dep_node)) -> None: """ Start an Ethernet hub. This endpoint results in no action since Ethernet hub nodes are always on. @@ -124,7 +127,7 @@ def start_ethernet_hub(node: EthernetHub = Depends(dep_node)): @router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT) -def stop_ethernet_hub(node: EthernetHub = Depends(dep_node)): +def stop_ethernet_hub(node: EthernetHub = Depends(dep_node)) -> None: """ Stop an Ethernet hub. This endpoint results in no action since Ethernet hub nodes are always on. @@ -134,7 +137,7 @@ def stop_ethernet_hub(node: EthernetHub = Depends(dep_node)): @router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT) -def suspend_ethernet_hub(node: EthernetHub = Depends(dep_node)): +def suspend_ethernet_hub(node: EthernetHub = Depends(dep_node)) -> None: """ Suspend an Ethernet hub. This endpoint results in no action since Ethernet hub nodes are always on. @@ -149,8 +152,12 @@ def suspend_ethernet_hub(node: EthernetHub = Depends(dep_node)): response_model=schemas.UDPNIO, ) async def create_nio( - adapter_number: int, port_number: int, nio_data: schemas.UDPNIO, node: EthernetHub = Depends(dep_node) -): + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + nio_data: schemas.UDPNIO, + node: EthernetHub = Depends(dep_node) +) -> schemas.UDPNIO: """ Add a NIO (Network Input/Output) to the node. The adapter number on the hub is always 0. @@ -162,7 +169,12 @@ async def create_nio( @router.delete("/{node_id}/adapters/{adapter_number}/ports/{port_number}/nio", status_code=status.HTTP_204_NO_CONTENT) -async def delete_nio(adapter_number: int, port_number: int, node: EthernetHub = Depends(dep_node)): +async def delete_nio( + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + node: EthernetHub = Depends(dep_node) +) -> None: """ Delete a NIO (Network Input/Output) from the node. The adapter number on the hub is always 0. @@ -174,8 +186,12 @@ async def delete_nio(adapter_number: int, port_number: int, node: EthernetHub = @router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start") async def start_capture( - adapter_number: int, port_number: int, node_capture_data: schemas.NodeCapture, node: EthernetHub = Depends(dep_node) -): + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + node_capture_data: schemas.NodeCapture, + node: EthernetHub = Depends(dep_node) +) -> dict: """ Start a packet capture on the node. The adapter number on the hub is always 0. @@ -189,7 +205,12 @@ async def start_capture( @router.post( "/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stop", status_code=status.HTTP_204_NO_CONTENT ) -async def stop_capture(adapter_number: int, port_number: int, node: EthernetHub = Depends(dep_node)): +async def stop_capture( + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + node: EthernetHub = Depends(dep_node) +) -> None: """ Stop a packet capture on the node. The adapter number on the hub is always 0. @@ -199,7 +220,12 @@ async def stop_capture(adapter_number: int, port_number: int, node: EthernetHub @router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream") -async def stream_pcap_file(adapter_number: int, port_number: int, node: EthernetHub = Depends(dep_node)): +async def stream_pcap_file( + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + node: EthernetHub = Depends(dep_node) +) -> StreamingResponse: """ Stream the pcap capture file. The adapter number on the hub is always 0. diff --git a/gns3server/api/routes/compute/ethernet_switch_nodes.py b/gns3server/api/routes/compute/ethernet_switch_nodes.py index 51628dfb..3375dd19 100644 --- a/gns3server/api/routes/compute/ethernet_switch_nodes.py +++ b/gns3server/api/routes/compute/ethernet_switch_nodes.py @@ -20,7 +20,7 @@ API routes for Ethernet switch nodes. import os -from fastapi import APIRouter, Depends, Body, status +from fastapi import APIRouter, Depends, Body, Path, status from fastapi.encoders import jsonable_encoder from fastapi.responses import StreamingResponse from uuid import UUID @@ -34,7 +34,7 @@ responses = {404: {"model": schemas.ErrorMessage, "description": "Could not find router = APIRouter(responses=responses) -def dep_node(project_id: UUID, node_id: UUID): +def dep_node(project_id: UUID, node_id: UUID) -> EthernetSwitch: """ Dependency to retrieve a node. """ @@ -50,7 +50,7 @@ def dep_node(project_id: UUID, node_id: UUID): status_code=status.HTTP_201_CREATED, responses={409: {"model": schemas.ErrorMessage, "description": "Could not create Ethernet switch node"}}, ) -async def create_ethernet_switch(project_id: UUID, node_data: schemas.EthernetSwitchCreate): +async def create_ethernet_switch(project_id: UUID, node_data: schemas.EthernetSwitchCreate) -> schemas.EthernetSwitch: """ Create a new Ethernet switch. """ @@ -72,15 +72,16 @@ async def create_ethernet_switch(project_id: UUID, node_data: schemas.EthernetSw @router.get("/{node_id}", response_model=schemas.EthernetSwitch) -def get_ethernet_switch(node: EthernetSwitch = Depends(dep_node)): +def get_ethernet_switch(node: EthernetSwitch = Depends(dep_node)) -> schemas.EthernetSwitch: return node.asdict() @router.post("/{node_id}/duplicate", response_model=schemas.EthernetSwitch, status_code=status.HTTP_201_CREATED) async def duplicate_ethernet_switch( - destination_node_id: UUID = Body(..., embed=True), node: EthernetSwitch = Depends(dep_node) -): + destination_node_id: UUID = Body(..., embed=True), + node: EthernetSwitch = Depends(dep_node) +) -> schemas.EthernetSwitch: """ Duplicate an Ethernet switch. """ @@ -90,7 +91,10 @@ async def duplicate_ethernet_switch( @router.put("/{node_id}", response_model=schemas.EthernetSwitch) -async def update_ethernet_switch(node_data: schemas.EthernetSwitchUpdate, node: EthernetSwitch = Depends(dep_node)): +async def update_ethernet_switch( + node_data: schemas.EthernetSwitchUpdate, + node: EthernetSwitch = Depends(dep_node) +) -> schemas.EthernetSwitch: """ Update an Ethernet switch. """ @@ -108,7 +112,7 @@ async def update_ethernet_switch(node_data: schemas.EthernetSwitchUpdate, node: @router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT) -async def delete_ethernet_switch(node: EthernetSwitch = Depends(dep_node)): +async def delete_ethernet_switch(node: EthernetSwitch = Depends(dep_node)) -> None: """ Delete an Ethernet switch. """ @@ -117,7 +121,7 @@ async def delete_ethernet_switch(node: EthernetSwitch = Depends(dep_node)): @router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT) -def start_ethernet_switch(node: EthernetSwitch = Depends(dep_node)): +def start_ethernet_switch(node: EthernetSwitch = Depends(dep_node)) -> None: """ Start an Ethernet switch. This endpoint results in no action since Ethernet switch nodes are always on. @@ -127,7 +131,7 @@ def start_ethernet_switch(node: EthernetSwitch = Depends(dep_node)): @router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT) -def stop_ethernet_switch(node: EthernetSwitch = Depends(dep_node)): +def stop_ethernet_switch(node: EthernetSwitch = Depends(dep_node)) -> None: """ Stop an Ethernet switch. This endpoint results in no action since Ethernet switch nodes are always on. @@ -137,7 +141,7 @@ def stop_ethernet_switch(node: EthernetSwitch = Depends(dep_node)): @router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT) -def suspend_ethernet_switch(node: EthernetSwitch = Depends(dep_node)): +def suspend_ethernet_switch(node: EthernetSwitch = Depends(dep_node)) -> None: """ Suspend an Ethernet switch. This endpoint results in no action since Ethernet switch nodes are always on. @@ -152,8 +156,12 @@ def suspend_ethernet_switch(node: EthernetSwitch = Depends(dep_node)): response_model=schemas.UDPNIO, ) async def create_nio( - adapter_number: int, port_number: int, nio_data: schemas.UDPNIO, node: EthernetSwitch = Depends(dep_node) -): + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + nio_data: schemas.UDPNIO, + node: EthernetSwitch = Depends(dep_node) +) -> schemas.UDPNIO: nio = await Dynamips.instance().create_nio(node, jsonable_encoder(nio_data, exclude_unset=True)) await node.add_nio(nio, port_number) @@ -161,7 +169,12 @@ async def create_nio( @router.delete("/{node_id}/adapters/{adapter_number}/ports/{port_number}/nio", status_code=status.HTTP_204_NO_CONTENT) -async def delete_nio(adapter_number: int, port_number: int, node: EthernetSwitch = Depends(dep_node)): +async def delete_nio( + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + node: EthernetSwitch = Depends(dep_node) +) -> None: """ Delete a NIO (Network Input/Output) from the node. The adapter number on the switch is always 0. @@ -173,11 +186,12 @@ async def delete_nio(adapter_number: int, port_number: int, node: EthernetSwitch @router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start") async def start_capture( - adapter_number: int, - port_number: int, - node_capture_data: schemas.NodeCapture, - node: EthernetSwitch = Depends(dep_node), -): + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + node_capture_data: schemas.NodeCapture, + node: EthernetSwitch = Depends(dep_node), +) -> dict: """ Start a packet capture on the node. The adapter number on the switch is always 0. @@ -191,7 +205,12 @@ async def start_capture( @router.post( "/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stop", status_code=status.HTTP_204_NO_CONTENT ) -async def stop_capture(adapter_number: int, port_number: int, node: EthernetSwitch = Depends(dep_node)): +async def stop_capture( + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + node: EthernetSwitch = Depends(dep_node) +) -> None: """ Stop a packet capture on the node. The adapter number on the switch is always 0. @@ -201,7 +220,12 @@ async def stop_capture(adapter_number: int, port_number: int, node: EthernetSwit @router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream") -async def stream_pcap_file(adapter_number: int, port_number: int, node: EthernetSwitch = Depends(dep_node)): +async def stream_pcap_file( + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + node: EthernetSwitch = Depends(dep_node) +) -> StreamingResponse: """ Stream the pcap capture file. The adapter number on the switch is always 0. diff --git a/gns3server/api/routes/compute/frame_relay_switch_nodes.py b/gns3server/api/routes/compute/frame_relay_switch_nodes.py index 7b9f5ecb..d0ea5537 100644 --- a/gns3server/api/routes/compute/frame_relay_switch_nodes.py +++ b/gns3server/api/routes/compute/frame_relay_switch_nodes.py @@ -20,7 +20,7 @@ API routes for Frame Relay switch nodes. import os -from fastapi import APIRouter, Depends, Body, status +from fastapi import APIRouter, Depends, Body, Path, status from fastapi.encoders import jsonable_encoder from fastapi.responses import StreamingResponse from uuid import UUID @@ -34,7 +34,7 @@ responses = {404: {"model": schemas.ErrorMessage, "description": "Could not find router = APIRouter(responses=responses) -def dep_node(project_id: UUID, node_id: UUID): +def dep_node(project_id: UUID, node_id: UUID) -> FrameRelaySwitch: """ Dependency to retrieve a node. """ @@ -50,7 +50,10 @@ def dep_node(project_id: UUID, node_id: UUID): status_code=status.HTTP_201_CREATED, responses={409: {"model": schemas.ErrorMessage, "description": "Could not create Frame Relay switch node"}}, ) -async def create_frame_relay_switch(project_id: UUID, node_data: schemas.FrameRelaySwitchCreate): +async def create_frame_relay_switch( + project_id: UUID, + node_data: schemas.FrameRelaySwitchCreate +) -> schemas.FrameRelaySwitch: """ Create a new Frame Relay switch node. """ @@ -69,7 +72,7 @@ async def create_frame_relay_switch(project_id: UUID, node_data: schemas.FrameRe @router.get("/{node_id}", response_model=schemas.FrameRelaySwitch) -def get_frame_relay_switch(node: FrameRelaySwitch = Depends(dep_node)): +def get_frame_relay_switch(node: FrameRelaySwitch = Depends(dep_node)) -> schemas.FrameRelaySwitch: """ Return a Frame Relay switch node. """ @@ -79,8 +82,9 @@ def get_frame_relay_switch(node: FrameRelaySwitch = Depends(dep_node)): @router.post("/{node_id}/duplicate", response_model=schemas.FrameRelaySwitch, status_code=status.HTTP_201_CREATED) async def duplicate_frame_relay_switch( - destination_node_id: UUID = Body(..., embed=True), node: FrameRelaySwitch = Depends(dep_node) -): + destination_node_id: UUID = Body(..., embed=True), + node: FrameRelaySwitch = Depends(dep_node) +) -> schemas.FrameRelaySwitch: """ Duplicate a Frame Relay switch node. """ @@ -91,8 +95,9 @@ async def duplicate_frame_relay_switch( @router.put("/{node_id}", response_model=schemas.FrameRelaySwitch) async def update_frame_relay_switch( - node_data: schemas.FrameRelaySwitchUpdate, node: FrameRelaySwitch = Depends(dep_node) -): + node_data: schemas.FrameRelaySwitchUpdate, + node: FrameRelaySwitch = Depends(dep_node) +) -> schemas.FrameRelaySwitch: """ Update an Frame Relay switch node. """ @@ -107,7 +112,7 @@ async def update_frame_relay_switch( @router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT) -async def delete_frame_relay_switch(node: FrameRelaySwitch = Depends(dep_node)): +async def delete_frame_relay_switch(node: FrameRelaySwitch = Depends(dep_node)) -> None: """ Delete a Frame Relay switch node. """ @@ -116,7 +121,7 @@ async def delete_frame_relay_switch(node: FrameRelaySwitch = Depends(dep_node)): @router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT) -def start_frame_relay_switch(node: FrameRelaySwitch = Depends(dep_node)): +def start_frame_relay_switch(node: FrameRelaySwitch = Depends(dep_node)) -> None: """ Start a Frame Relay switch node. This endpoint results in no action since Frame Relay switch nodes are always on. @@ -126,7 +131,7 @@ def start_frame_relay_switch(node: FrameRelaySwitch = Depends(dep_node)): @router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT) -def stop_frame_relay_switch(node: FrameRelaySwitch = Depends(dep_node)): +def stop_frame_relay_switch(node: FrameRelaySwitch = Depends(dep_node)) -> None: """ Stop a Frame Relay switch node. This endpoint results in no action since Frame Relay switch nodes are always on. @@ -136,7 +141,7 @@ def stop_frame_relay_switch(node: FrameRelaySwitch = Depends(dep_node)): @router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT) -def suspend_frame_relay_switch(node: FrameRelaySwitch = Depends(dep_node)): +def suspend_frame_relay_switch(node: FrameRelaySwitch = Depends(dep_node)) -> None: """ Suspend a Frame Relay switch node. This endpoint results in no action since Frame Relay switch nodes are always on. @@ -151,8 +156,12 @@ def suspend_frame_relay_switch(node: FrameRelaySwitch = Depends(dep_node)): response_model=schemas.UDPNIO, ) async def create_nio( - adapter_number: int, port_number: int, nio_data: schemas.UDPNIO, node: FrameRelaySwitch = Depends(dep_node) -): + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + nio_data: schemas.UDPNIO, + node: FrameRelaySwitch = Depends(dep_node) +) -> schemas.UDPNIO: """ Add a NIO (Network Input/Output) to the node. The adapter number on the switch is always 0. @@ -164,7 +173,12 @@ async def create_nio( @router.delete("/{node_id}/adapters/{adapter_number}/ports/{port_number}/nio", status_code=status.HTTP_204_NO_CONTENT) -async def delete_nio(adapter_number: int, port_number: int, node: FrameRelaySwitch = Depends(dep_node)): +async def delete_nio( + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + node: FrameRelaySwitch = Depends(dep_node) +) -> None: """ Remove a NIO (Network Input/Output) from the node. The adapter number on the switch is always 0. @@ -176,11 +190,12 @@ async def delete_nio(adapter_number: int, port_number: int, node: FrameRelaySwit @router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start") async def start_capture( - adapter_number: int, - port_number: int, - node_capture_data: schemas.NodeCapture, - node: FrameRelaySwitch = Depends(dep_node), -): + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + node_capture_data: schemas.NodeCapture, + node: FrameRelaySwitch = Depends(dep_node), +) -> dict: """ Start a packet capture on the node. The adapter number on the switch is always 0. @@ -194,7 +209,12 @@ async def start_capture( @router.post( "/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stop", status_code=status.HTTP_204_NO_CONTENT ) -async def stop_capture(adapter_number: int, port_number: int, node: FrameRelaySwitch = Depends(dep_node)): +async def stop_capture( + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + node: FrameRelaySwitch = Depends(dep_node) +) -> None: """ Stop a packet capture on the node. The adapter number on the switch is always 0. @@ -204,7 +224,12 @@ async def stop_capture(adapter_number: int, port_number: int, node: FrameRelaySw @router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream") -async def stream_pcap_file(adapter_number: int, port_number: int, node: FrameRelaySwitch = Depends(dep_node)): +async def stream_pcap_file( + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + node: FrameRelaySwitch = Depends(dep_node) +) -> StreamingResponse: """ Stream the pcap capture file. The adapter number on the hub is always 0. diff --git a/gns3server/api/routes/compute/images.py b/gns3server/api/routes/compute/images.py index 6f5fe522..b5103aaf 100644 --- a/gns3server/api/routes/compute/images.py +++ b/gns3server/api/routes/compute/images.py @@ -54,7 +54,7 @@ async def get_dynamips_images() -> List[str]: @router.post("/dynamips/images/{filename:path}", status_code=status.HTTP_204_NO_CONTENT) -async def upload_dynamips_image(filename: str, request: Request): +async def upload_dynamips_image(filename: str, request: Request) -> None: """ Upload a Dynamips IOS image. """ @@ -64,7 +64,7 @@ async def upload_dynamips_image(filename: str, request: Request): @router.get("/dynamips/images/{filename:path}") -async def download_dynamips_image(filename: str): +async def download_dynamips_image(filename: str) -> FileResponse: """ Download a Dynamips IOS image. """ @@ -93,7 +93,7 @@ async def get_iou_images() -> List[str]: @router.post("/iou/images/{filename:path}", status_code=status.HTTP_204_NO_CONTENT) -async def upload_iou_image(filename: str, request: Request): +async def upload_iou_image(filename: str, request: Request) -> None: """ Upload an IOU image. """ @@ -103,7 +103,7 @@ async def upload_iou_image(filename: str, request: Request): @router.get("/iou/images/{filename:path}") -async def download_iou_image(filename: str): +async def download_iou_image(filename: str) -> FileResponse: """ Download an IOU image. """ @@ -129,14 +129,14 @@ async def get_qemu_images() -> List[str]: @router.post("/qemu/images/{filename:path}", status_code=status.HTTP_204_NO_CONTENT) -async def upload_qemu_image(filename: str, request: Request): +async def upload_qemu_image(filename: str, request: Request) -> None: qemu_manager = Qemu.instance() await qemu_manager.write_image(urllib.parse.unquote(filename), request.stream()) @router.get("/qemu/images/{filename:path}") -async def download_qemu_image(filename: str): +async def download_qemu_image(filename: str) -> FileResponse: qemu_manager = Qemu.instance() filename = urllib.parse.unquote(filename) diff --git a/gns3server/api/routes/compute/iou_nodes.py b/gns3server/api/routes/compute/iou_nodes.py index 32e19fcf..1234c10d 100644 --- a/gns3server/api/routes/compute/iou_nodes.py +++ b/gns3server/api/routes/compute/iou_nodes.py @@ -35,7 +35,7 @@ responses = {404: {"model": schemas.ErrorMessage, "description": "Could not find router = APIRouter(responses=responses) -def dep_node(project_id: UUID, node_id: UUID): +def dep_node(project_id: UUID, node_id: UUID) -> IOUVM: """ Dependency to retrieve a node. """ @@ -51,7 +51,7 @@ def dep_node(project_id: UUID, node_id: UUID): status_code=status.HTTP_201_CREATED, responses={409: {"model": schemas.ErrorMessage, "description": "Could not create IOU node"}}, ) -async def create_iou_node(project_id: UUID, node_data: schemas.IOUCreate): +async def create_iou_node(project_id: UUID, node_data: schemas.IOUCreate) -> schemas.IOU: """ Create a new IOU node. """ @@ -83,7 +83,7 @@ async def create_iou_node(project_id: UUID, node_data: schemas.IOUCreate): @router.get("/{node_id}", response_model=schemas.IOU) -def get_iou_node(node: IOUVM = Depends(dep_node)): +def get_iou_node(node: IOUVM = Depends(dep_node)) -> schemas.IOU: """ Return an IOU node. """ @@ -92,7 +92,7 @@ def get_iou_node(node: IOUVM = Depends(dep_node)): @router.put("/{node_id}", response_model=schemas.IOU) -async def update_iou_node(node_data: schemas.IOUUpdate, node: IOUVM = Depends(dep_node)): +async def update_iou_node(node_data: schemas.IOUUpdate, node: IOUVM = Depends(dep_node)) -> schemas.IOU: """ Update an IOU node. """ @@ -113,7 +113,7 @@ async def update_iou_node(node_data: schemas.IOUUpdate, node: IOUVM = Depends(de @router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT) -async def delete_iou_node(node: IOUVM = Depends(dep_node)): +async def delete_iou_node(node: IOUVM = Depends(dep_node)) -> None: """ Delete an IOU node. """ @@ -122,7 +122,10 @@ async def delete_iou_node(node: IOUVM = Depends(dep_node)): @router.post("/{node_id}/duplicate", response_model=schemas.IOU, status_code=status.HTTP_201_CREATED) -async def duplicate_iou_node(destination_node_id: UUID = Body(..., embed=True), node: IOUVM = Depends(dep_node)): +async def duplicate_iou_node( + destination_node_id: UUID = Body(..., embed=True), + node: IOUVM = Depends(dep_node) +) -> schemas.IOU: """ Duplicate an IOU node. """ @@ -132,7 +135,7 @@ async def duplicate_iou_node(destination_node_id: UUID = Body(..., embed=True), @router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT) -async def start_iou_node(start_data: schemas.IOUStart, node: IOUVM = Depends(dep_node)): +async def start_iou_node(start_data: schemas.IOUStart, node: IOUVM = Depends(dep_node)) -> None: """ Start an IOU node. """ @@ -147,7 +150,7 @@ async def start_iou_node(start_data: schemas.IOUStart, node: IOUVM = Depends(dep @router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT) -async def stop_iou_node(node: IOUVM = Depends(dep_node)): +async def stop_iou_node(node: IOUVM = Depends(dep_node)) -> None: """ Stop an IOU node. """ @@ -156,7 +159,7 @@ async def stop_iou_node(node: IOUVM = Depends(dep_node)): @router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT) -def suspend_iou_node(node: IOUVM = Depends(dep_node)): +def suspend_iou_node(node: IOUVM = Depends(dep_node)) -> None: """ Suspend an IOU node. Does nothing since IOU doesn't support being suspended. @@ -166,7 +169,7 @@ def suspend_iou_node(node: IOUVM = Depends(dep_node)): @router.post("/{node_id}/reload", status_code=status.HTTP_204_NO_CONTENT) -async def reload_iou_node(node: IOUVM = Depends(dep_node)): +async def reload_iou_node(node: IOUVM = Depends(dep_node)) -> None: """ Reload an IOU node. """ @@ -184,7 +187,7 @@ async def create_iou_node_nio( port_number: int, nio_data: Union[schemas.EthernetNIO, schemas.TAPNIO, schemas.UDPNIO], node: IOUVM = Depends(dep_node), -): +) -> Union[schemas.EthernetNIO, schemas.TAPNIO, schemas.UDPNIO]: """ Add a NIO (Network Input/Output) to the node. """ @@ -204,7 +207,7 @@ async def update_iou_node_nio( port_number: int, nio_data: Union[schemas.EthernetNIO, schemas.TAPNIO, schemas.UDPNIO], node: IOUVM = Depends(dep_node), -): +) -> Union[schemas.EthernetNIO, schemas.TAPNIO, schemas.UDPNIO]: """ Update a NIO (Network Input/Output) on the node. """ @@ -217,7 +220,7 @@ async def update_iou_node_nio( @router.delete("/{node_id}/adapters/{adapter_number}/ports/{port_number}/nio", status_code=status.HTTP_204_NO_CONTENT) -async def delete_iou_node_nio(adapter_number: int, port_number: int, node: IOUVM = Depends(dep_node)): +async def delete_iou_node_nio(adapter_number: int, port_number: int, node: IOUVM = Depends(dep_node)) -> None: """ Delete a NIO (Network Input/Output) from the node. """ @@ -227,8 +230,11 @@ async def delete_iou_node_nio(adapter_number: int, port_number: int, node: IOUVM @router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start") async def start_iou_node_capture( - adapter_number: int, port_number: int, node_capture_data: schemas.NodeCapture, node: IOUVM = Depends(dep_node) -): + adapter_number: int, + port_number: int, + node_capture_data: schemas.NodeCapture, + node: IOUVM = Depends(dep_node) +) -> dict: """ Start a packet capture on the node. """ @@ -241,7 +247,7 @@ async def start_iou_node_capture( @router.post( "/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stop", status_code=status.HTTP_204_NO_CONTENT ) -async def stop_iou_node_capture(adapter_number: int, port_number: int, node: IOUVM = Depends(dep_node)): +async def stop_iou_node_capture(adapter_number: int, port_number: int, node: IOUVM = Depends(dep_node)) -> None: """ Stop a packet capture on the node. """ @@ -250,7 +256,11 @@ async def stop_iou_node_capture(adapter_number: int, port_number: int, node: IOU @router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream") -async def stream_pcap_file(adapter_number: int, port_number: int, node: IOUVM = Depends(dep_node)): +async def stream_pcap_file( + adapter_number: int, + port_number: int, + node: IOUVM = Depends(dep_node) +) -> StreamingResponse: """ Stream the pcap capture file. """ @@ -261,7 +271,7 @@ async def stream_pcap_file(adapter_number: int, port_number: int, node: IOUVM = @router.websocket("/{node_id}/console/ws") -async def console_ws(websocket: WebSocket, node: IOUVM = Depends(dep_node)): +async def console_ws(websocket: WebSocket, node: IOUVM = Depends(dep_node)) -> None: """ Console WebSocket. """ @@ -270,6 +280,6 @@ async def console_ws(websocket: WebSocket, node: IOUVM = Depends(dep_node)): @router.post("/{node_id}/console/reset", status_code=status.HTTP_204_NO_CONTENT) -async def reset_console(node: IOUVM = Depends(dep_node)): +async def reset_console(node: IOUVM = Depends(dep_node)) -> None: await node.reset_console() diff --git a/gns3server/api/routes/compute/nat_nodes.py b/gns3server/api/routes/compute/nat_nodes.py index f4f92f6a..c15f9225 100644 --- a/gns3server/api/routes/compute/nat_nodes.py +++ b/gns3server/api/routes/compute/nat_nodes.py @@ -20,7 +20,7 @@ API routes for NAT nodes. import os -from fastapi import APIRouter, Depends, status +from fastapi import APIRouter, Depends, Path, status from fastapi.encoders import jsonable_encoder from fastapi.responses import StreamingResponse from typing import Union @@ -35,7 +35,7 @@ responses = {404: {"model": schemas.ErrorMessage, "description": "Could not find router = APIRouter(responses=responses) -def dep_node(project_id: UUID, node_id: UUID): +def dep_node(project_id: UUID, node_id: UUID) -> Nat: """ Dependency to retrieve a node. """ @@ -51,7 +51,7 @@ def dep_node(project_id: UUID, node_id: UUID): status_code=status.HTTP_201_CREATED, responses={409: {"model": schemas.ErrorMessage, "description": "Could not create NAT node"}}, ) -async def create_nat_node(project_id: UUID, node_data: schemas.NATCreate): +async def create_nat_node(project_id: UUID, node_data: schemas.NATCreate) -> schemas.NAT: """ Create a new NAT node. """ @@ -71,7 +71,7 @@ async def create_nat_node(project_id: UUID, node_data: schemas.NATCreate): @router.get("/{node_id}", response_model=schemas.NAT) -def get_nat_node(node: Nat = Depends(dep_node)): +def get_nat_node(node: Nat = Depends(dep_node)) -> schemas.NAT: """ Return a NAT node. """ @@ -80,7 +80,7 @@ def get_nat_node(node: Nat = Depends(dep_node)): @router.put("/{node_id}", response_model=schemas.NAT) -def update_nat_node(node_data: schemas.NATUpdate, node: Nat = Depends(dep_node)): +def update_nat_node(node_data: schemas.NATUpdate, node: Nat = Depends(dep_node)) -> schemas.NAT: """ Update a NAT node. """ @@ -94,7 +94,7 @@ def update_nat_node(node_data: schemas.NATUpdate, node: Nat = Depends(dep_node)) @router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT) -async def delete_nat_node(node: Nat = Depends(dep_node)): +async def delete_nat_node(node: Nat = Depends(dep_node)) -> None: """ Delete a cloud node. """ @@ -103,7 +103,7 @@ async def delete_nat_node(node: Nat = Depends(dep_node)): @router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT) -async def start_nat_node(node: Nat = Depends(dep_node)): +async def start_nat_node(node: Nat = Depends(dep_node)) -> None: """ Start a NAT node. """ @@ -112,7 +112,7 @@ async def start_nat_node(node: Nat = Depends(dep_node)): @router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT) -async def stop_nat_node(node: Nat = Depends(dep_node)): +async def stop_nat_node(node: Nat = Depends(dep_node)) -> None: """ Stop a NAT node. This endpoint results in no action since cloud nodes cannot be stopped. @@ -122,7 +122,7 @@ async def stop_nat_node(node: Nat = Depends(dep_node)): @router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT) -async def suspend_nat_node(node: Nat = Depends(dep_node)): +async def suspend_nat_node(node: Nat = Depends(dep_node)) -> None: """ Suspend a NAT node. This endpoint results in no action since NAT nodes cannot be suspended. @@ -137,11 +137,12 @@ async def suspend_nat_node(node: Nat = Depends(dep_node)): response_model=Union[schemas.EthernetNIO, schemas.TAPNIO, schemas.UDPNIO], ) async def create_nat_node_nio( - adapter_number: int, - port_number: int, - nio_data: Union[schemas.EthernetNIO, schemas.TAPNIO, schemas.UDPNIO], - node: Nat = Depends(dep_node), -): + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + nio_data: Union[schemas.EthernetNIO, schemas.TAPNIO, schemas.UDPNIO], + node: Nat = Depends(dep_node), +) -> Union[schemas.EthernetNIO, schemas.TAPNIO, schemas.UDPNIO]: """ Add a NIO (Network Input/Output) to the node. The adapter number on the cloud is always 0. @@ -158,11 +159,12 @@ async def create_nat_node_nio( response_model=Union[schemas.EthernetNIO, schemas.TAPNIO, schemas.UDPNIO], ) async def update_nat_node_nio( - adapter_number: int, - port_number: int, - nio_data: Union[schemas.EthernetNIO, schemas.TAPNIO, schemas.UDPNIO], - node: Nat = Depends(dep_node), -): + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + nio_data: Union[schemas.EthernetNIO, schemas.TAPNIO, schemas.UDPNIO], + node: Nat = Depends(dep_node), +) -> Union[schemas.EthernetNIO, schemas.TAPNIO, schemas.UDPNIO]: """ Update a NIO (Network Input/Output) to the node. The adapter number on the cloud is always 0. @@ -176,7 +178,12 @@ async def update_nat_node_nio( @router.delete("/{node_id}/adapters/{adapter_number}/ports/{port_number}/nio", status_code=status.HTTP_204_NO_CONTENT) -async def delete_nat_node_nio(adapter_number: int, port_number: int, node: Nat = Depends(dep_node)): +async def delete_nat_node_nio( + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + node: Nat = Depends(dep_node) +) -> None: """ Remove a NIO (Network Input/Output) from the node. The adapter number on the cloud is always 0. @@ -187,8 +194,12 @@ async def delete_nat_node_nio(adapter_number: int, port_number: int, node: Nat = @router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start") async def start_nat_node_capture( - adapter_number: int, port_number: int, node_capture_data: schemas.NodeCapture, node: Nat = Depends(dep_node) -): + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + node_capture_data: schemas.NodeCapture, + node: Nat = Depends(dep_node) +) -> dict: """ Start a packet capture on the node. The adapter number on the cloud is always 0. @@ -202,7 +213,12 @@ async def start_nat_node_capture( @router.post( "/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stop", status_code=status.HTTP_204_NO_CONTENT ) -async def stop_nat_node_capture(adapter_number: int, port_number: int, node: Nat = Depends(dep_node)): +async def stop_nat_node_capture( + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + node: Nat = Depends(dep_node) +): """ Stop a packet capture on the node. The adapter number on the cloud is always 0. @@ -212,7 +228,12 @@ async def stop_nat_node_capture(adapter_number: int, port_number: int, node: Nat @router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream") -async def stream_pcap_file(adapter_number: int, port_number: int, node: Nat = Depends(dep_node)): +async def stream_pcap_file( + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + node: Nat = Depends(dep_node) +) -> StreamingResponse: """ Stream the pcap capture file. The adapter number on the cloud is always 0. diff --git a/gns3server/api/routes/compute/notifications.py b/gns3server/api/routes/compute/notifications.py index 830488e5..99d9ed31 100644 --- a/gns3server/api/routes/compute/notifications.py +++ b/gns3server/api/routes/compute/notifications.py @@ -31,7 +31,7 @@ router = APIRouter() @router.websocket("/notifications/ws") -async def notification_ws(websocket: WebSocket): +async def notification_ws(websocket: WebSocket) -> None: """ Receive project notifications about the project from WebSocket. """ diff --git a/gns3server/api/routes/compute/projects.py b/gns3server/api/routes/compute/projects.py index fd446db9..8d9fe3b8 100644 --- a/gns3server/api/routes/compute/projects.py +++ b/gns3server/api/routes/compute/projects.py @@ -41,7 +41,7 @@ router = APIRouter() _notifications_listening = {} -def dep_project(project_id: UUID): +def dep_project(project_id: UUID) -> Project: """ Dependency to retrieve a project. """ @@ -52,7 +52,7 @@ def dep_project(project_id: UUID): @router.get("/projects", response_model=List[schemas.Project]) -def get_compute_projects(): +def get_compute_projects() -> List[schemas.Project]: """ Get all projects opened on the compute. """ @@ -62,7 +62,7 @@ def get_compute_projects(): @router.post("/projects", status_code=status.HTTP_201_CREATED, response_model=schemas.Project) -def create_compute_project(project_data: schemas.ProjectCreate): +def create_compute_project(project_data: schemas.ProjectCreate) -> schemas.Project: """ Create a new project on the compute. """ @@ -79,7 +79,10 @@ def create_compute_project(project_data: schemas.ProjectCreate): @router.put("/projects/{project_id}", response_model=schemas.Project) -async def update_compute_project(project_data: schemas.ProjectUpdate, project: Project = Depends(dep_project)): +async def update_compute_project( + project_data: schemas.ProjectUpdate, + project: Project = Depends(dep_project) +) -> schemas.Project: """ Update project on the compute. """ @@ -89,7 +92,7 @@ async def update_compute_project(project_data: schemas.ProjectUpdate, project: P @router.get("/projects/{project_id}", response_model=schemas.Project) -def get_compute_project(project: Project = Depends(dep_project)): +def get_compute_project(project: Project = Depends(dep_project)) -> schemas.Project: """ Return a project from the compute. """ @@ -98,7 +101,7 @@ def get_compute_project(project: Project = Depends(dep_project)): @router.post("/projects/{project_id}/close", status_code=status.HTTP_204_NO_CONTENT) -async def close_compute_project(project: Project = Depends(dep_project)): +async def close_compute_project(project: Project = Depends(dep_project)) -> None: """ Close a project on the compute. """ @@ -116,7 +119,7 @@ async def close_compute_project(project: Project = Depends(dep_project)): @router.delete("/projects/{project_id}", status_code=status.HTTP_204_NO_CONTENT) -async def delete_compute_project(project: Project = Depends(dep_project)): +async def delete_compute_project(project: Project = Depends(dep_project)) -> None: """ Delete project from the compute. """ @@ -180,7 +183,7 @@ async def delete_compute_project(project: Project = Depends(dep_project)): @router.get("/projects/{project_id}/files", response_model=List[schemas.ProjectFile]) -async def get_compute_project_files(project: Project = Depends(dep_project)): +async def get_compute_project_files(project: Project = Depends(dep_project)) -> List[schemas.ProjectFile]: """ Return files belonging to a project. """ @@ -189,7 +192,7 @@ async def get_compute_project_files(project: Project = Depends(dep_project)): @router.get("/projects/{project_id}/files/{file_path:path}") -async def get_compute_project_file(file_path: str, project: Project = Depends(dep_project)): +async def get_compute_project_file(file_path: str, project: Project = Depends(dep_project)) -> FileResponse: """ Get a file from a project. """ @@ -208,7 +211,7 @@ async def get_compute_project_file(file_path: str, project: Project = Depends(de @router.post("/projects/{project_id}/files/{file_path:path}", status_code=status.HTTP_204_NO_CONTENT) -async def write_compute_project_file(file_path: str, request: Request, project: Project = Depends(dep_project)): +async def write_compute_project_file(file_path: str, request: Request, project: Project = Depends(dep_project)) -> None: path = os.path.normpath(file_path) diff --git a/gns3server/api/routes/compute/qemu_nodes.py b/gns3server/api/routes/compute/qemu_nodes.py index 97645af6..16a86091 100644 --- a/gns3server/api/routes/compute/qemu_nodes.py +++ b/gns3server/api/routes/compute/qemu_nodes.py @@ -19,9 +19,8 @@ API routes for Qemu nodes. """ import os -import sys -from fastapi import APIRouter, WebSocket, Depends, Body, status +from fastapi import APIRouter, WebSocket, Depends, Body, Path, status from fastapi.encoders import jsonable_encoder from fastapi.responses import StreamingResponse from uuid import UUID @@ -36,7 +35,7 @@ responses = {404: {"model": schemas.ErrorMessage, "description": "Could not find router = APIRouter(responses=responses) -def dep_node(project_id: UUID, node_id: UUID): +def dep_node(project_id: UUID, node_id: UUID) -> QemuVM: """ Dependency to retrieve a node. """ @@ -52,7 +51,7 @@ def dep_node(project_id: UUID, node_id: UUID): status_code=status.HTTP_201_CREATED, responses={409: {"model": schemas.ErrorMessage, "description": "Could not create Qemu node"}}, ) -async def create_qemu_node(project_id: UUID, node_data: schemas.QemuCreate): +async def create_qemu_node(project_id: UUID, node_data: schemas.QemuCreate) -> schemas.Qemu: """ Create a new Qemu node. """ @@ -80,7 +79,7 @@ async def create_qemu_node(project_id: UUID, node_data: schemas.QemuCreate): @router.get("/{node_id}", response_model=schemas.Qemu) -def get_qemu_node(node: QemuVM = Depends(dep_node)): +def get_qemu_node(node: QemuVM = Depends(dep_node)) -> schemas.Qemu: """ Return a Qemu node. """ @@ -89,7 +88,7 @@ def get_qemu_node(node: QemuVM = Depends(dep_node)): @router.put("/{node_id}", response_model=schemas.Qemu) -async def update_qemu_node(node_data: schemas.QemuUpdate, node: QemuVM = Depends(dep_node)): +async def update_qemu_node(node_data: schemas.QemuUpdate, node: QemuVM = Depends(dep_node)) -> schemas.Qemu: """ Update a Qemu node. """ @@ -105,7 +104,7 @@ async def update_qemu_node(node_data: schemas.QemuUpdate, node: QemuVM = Depends @router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT) -async def delete_qemu_node(node: QemuVM = Depends(dep_node)): +async def delete_qemu_node(node: QemuVM = Depends(dep_node)) -> None: """ Delete a Qemu node. """ @@ -114,7 +113,10 @@ async def delete_qemu_node(node: QemuVM = Depends(dep_node)): @router.post("/{node_id}/duplicate", response_model=schemas.Qemu, status_code=status.HTTP_201_CREATED) -async def duplicate_qemu_node(destination_node_id: UUID = Body(..., embed=True), node: QemuVM = Depends(dep_node)): +async def duplicate_qemu_node( + destination_node_id: UUID = Body(..., embed=True), + node: QemuVM = Depends(dep_node) +) -> schemas.Qemu: """ Duplicate a Qemu node. """ @@ -124,13 +126,13 @@ async def duplicate_qemu_node(destination_node_id: UUID = Body(..., embed=True), @router.post("/{node_id}/resize_disk", status_code=status.HTTP_204_NO_CONTENT) -async def resize_qemu_node_disk(node_data: schemas.QemuDiskResize, node: QemuVM = Depends(dep_node)): +async def resize_qemu_node_disk(node_data: schemas.QemuDiskResize, node: QemuVM = Depends(dep_node)) -> None: await node.resize_disk(node_data.drive_name, node_data.extend) @router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT) -async def start_qemu_node(node: QemuVM = Depends(dep_node)): +async def start_qemu_node(node: QemuVM = Depends(dep_node)) -> None: """ Start a Qemu node. """ @@ -146,7 +148,7 @@ async def start_qemu_node(node: QemuVM = Depends(dep_node)): @router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT) -async def stop_qemu_node(node: QemuVM = Depends(dep_node)): +async def stop_qemu_node(node: QemuVM = Depends(dep_node)) -> None: """ Stop a Qemu node. """ @@ -155,7 +157,7 @@ async def stop_qemu_node(node: QemuVM = Depends(dep_node)): @router.post("/{node_id}/reload", status_code=status.HTTP_204_NO_CONTENT) -async def reload_qemu_node(node: QemuVM = Depends(dep_node)): +async def reload_qemu_node(node: QemuVM = Depends(dep_node)) -> None: """ Reload a Qemu node. """ @@ -164,7 +166,7 @@ async def reload_qemu_node(node: QemuVM = Depends(dep_node)): @router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT) -async def suspend_qemu_node(node: QemuVM = Depends(dep_node)): +async def suspend_qemu_node(node: QemuVM = Depends(dep_node)) -> None: """ Suspend a Qemu node. """ @@ -173,7 +175,7 @@ async def suspend_qemu_node(node: QemuVM = Depends(dep_node)): @router.post("/{node_id}/resume", status_code=status.HTTP_204_NO_CONTENT) -async def resume_qemu_node(node: QemuVM = Depends(dep_node)): +async def resume_qemu_node(node: QemuVM = Depends(dep_node)) -> None: """ Resume a Qemu node. """ @@ -187,8 +189,12 @@ async def resume_qemu_node(node: QemuVM = Depends(dep_node)): response_model=schemas.UDPNIO, ) async def create_qemu_node_nio( - adapter_number: int, port_number: int, nio_data: schemas.UDPNIO, node: QemuVM = Depends(dep_node) -): + *, + adapter_number: int, + port_number: int = Path(..., ge=0, le=0), + nio_data: schemas.UDPNIO, + node: QemuVM = Depends(dep_node) +) -> schemas.UDPNIO: """ Add a NIO (Network Input/Output) to the node. The port number on the Qemu node is always 0. @@ -205,8 +211,12 @@ async def create_qemu_node_nio( response_model=schemas.UDPNIO, ) async def update_qemu_node_nio( - adapter_number: int, port_number: int, nio_data: schemas.UDPNIO, node: QemuVM = Depends(dep_node) -): + *, + adapter_number: int, + port_number: int = Path(..., ge=0, le=0), + nio_data: schemas.UDPNIO, + node: QemuVM = Depends(dep_node) +) -> schemas.UDPNIO: """ Update a NIO (Network Input/Output) on the node. The port number on the Qemu node is always 0. @@ -222,7 +232,11 @@ async def update_qemu_node_nio( @router.delete("/{node_id}/adapters/{adapter_number}/ports/{port_number}/nio", status_code=status.HTTP_204_NO_CONTENT) -async def delete_qemu_node_nio(adapter_number: int, port_number: int, node: QemuVM = Depends(dep_node)): +async def delete_qemu_node_nio( + adapter_number: int, + port_number: int = Path(..., ge=0, le=0), + node: QemuVM = Depends(dep_node) +) -> None: """ Delete a NIO (Network Input/Output) from the node. The port number on the Qemu node is always 0. @@ -233,8 +247,12 @@ async def delete_qemu_node_nio(adapter_number: int, port_number: int, node: Qemu @router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start") async def start_qemu_node_capture( - adapter_number: int, port_number: int, node_capture_data: schemas.NodeCapture, node: QemuVM = Depends(dep_node) -): + *, + adapter_number: int, + port_number: int = Path(..., ge=0, le=0), + node_capture_data: schemas.NodeCapture, + node: QemuVM = Depends(dep_node) +) -> dict: """ Start a packet capture on the node. The port number on the Qemu node is always 0. @@ -248,7 +266,11 @@ async def start_qemu_node_capture( @router.post( "/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stop", status_code=status.HTTP_204_NO_CONTENT ) -async def stop_qemu_node_capture(adapter_number: int, port_number: int, node: QemuVM = Depends(dep_node)): +async def stop_qemu_node_capture( + adapter_number: int, + port_number: int = Path(..., ge=0, le=0), + node: QemuVM = Depends(dep_node) +) -> None: """ Stop a packet capture on the node. The port number on the Qemu node is always 0. @@ -258,7 +280,10 @@ async def stop_qemu_node_capture(adapter_number: int, port_number: int, node: Qe @router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream") -async def stream_pcap_file(adapter_number: int, port_number: int, node: QemuVM = Depends(dep_node)): +async def stream_pcap_file( + adapter_number: int, + port_number: int = Path(..., ge=0, le=0), + node: QemuVM = Depends(dep_node)) -> StreamingResponse: """ Stream the pcap capture file. The port number on the Qemu node is always 0. @@ -270,7 +295,7 @@ async def stream_pcap_file(adapter_number: int, port_number: int, node: QemuVM = @router.websocket("/{node_id}/console/ws") -async def console_ws(websocket: WebSocket, node: QemuVM = Depends(dep_node)): +async def console_ws(websocket: WebSocket, node: QemuVM = Depends(dep_node)) -> None: """ Console WebSocket. """ @@ -279,6 +304,6 @@ async def console_ws(websocket: WebSocket, node: QemuVM = Depends(dep_node)): @router.post("/{node_id}/console/reset", status_code=status.HTTP_204_NO_CONTENT) -async def reset_console(node: QemuVM = Depends(dep_node)): +async def reset_console(node: QemuVM = Depends(dep_node)) -> None: await node.reset_console() diff --git a/gns3server/api/routes/compute/virtualbox_nodes.py b/gns3server/api/routes/compute/virtualbox_nodes.py index bb23563c..93b548a0 100644 --- a/gns3server/api/routes/compute/virtualbox_nodes.py +++ b/gns3server/api/routes/compute/virtualbox_nodes.py @@ -20,7 +20,7 @@ API routes for VirtualBox nodes. import os -from fastapi import APIRouter, WebSocket, Depends, status +from fastapi import APIRouter, WebSocket, Depends, Path, status from fastapi.encoders import jsonable_encoder from fastapi.responses import StreamingResponse from uuid import UUID @@ -28,7 +28,6 @@ from uuid import UUID from gns3server import schemas from gns3server.compute.virtualbox import VirtualBox from gns3server.compute.virtualbox.virtualbox_error import VirtualBoxError -from gns3server.compute.project_manager import ProjectManager from gns3server.compute.virtualbox.virtualbox_vm import VirtualBoxVM responses = {404: {"model": schemas.ErrorMessage, "description": "Could not find project or VirtualBox node"}} @@ -36,7 +35,7 @@ responses = {404: {"model": schemas.ErrorMessage, "description": "Could not find router = APIRouter(responses=responses) -def dep_node(project_id: UUID, node_id: UUID): +def dep_node(project_id: UUID, node_id: UUID) -> VirtualBoxVM: """ Dependency to retrieve a node. """ @@ -52,7 +51,7 @@ def dep_node(project_id: UUID, node_id: UUID): status_code=status.HTTP_201_CREATED, responses={409: {"model": schemas.ErrorMessage, "description": "Could not create VirtualBox node"}}, ) -async def create_virtualbox_node(project_id: UUID, node_data: schemas.VirtualBoxCreate): +async def create_virtualbox_node(project_id: UUID, node_data: schemas.VirtualBoxCreate) -> schemas.VirtualBox: """ Create a new VirtualBox node. """ @@ -84,7 +83,7 @@ async def create_virtualbox_node(project_id: UUID, node_data: schemas.VirtualBox @router.get("/{node_id}", response_model=schemas.VirtualBox) -def get_virtualbox_node(node: VirtualBoxVM = Depends(dep_node)): +def get_virtualbox_node(node: VirtualBoxVM = Depends(dep_node)) -> schemas.VirtualBox: """ Return a VirtualBox node. """ @@ -93,7 +92,10 @@ def get_virtualbox_node(node: VirtualBoxVM = Depends(dep_node)): @router.put("/{node_id}", response_model=schemas.VirtualBox) -async def update_virtualbox_node(node_data: schemas.VirtualBoxUpdate, node: VirtualBoxVM = Depends(dep_node)): +async def update_virtualbox_node( + node_data: schemas.VirtualBoxUpdate, + node: VirtualBoxVM = Depends(dep_node) +) -> schemas.VirtualBox: """ Update a VirtualBox node. """ @@ -135,7 +137,7 @@ async def update_virtualbox_node(node_data: schemas.VirtualBoxUpdate, node: Virt @router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT) -async def delete_virtualbox_node(node: VirtualBoxVM = Depends(dep_node)): +async def delete_virtualbox_node(node: VirtualBoxVM = Depends(dep_node)) -> None: """ Delete a VirtualBox node. """ @@ -144,7 +146,7 @@ async def delete_virtualbox_node(node: VirtualBoxVM = Depends(dep_node)): @router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT) -async def start_virtualbox_node(node: VirtualBoxVM = Depends(dep_node)): +async def start_virtualbox_node(node: VirtualBoxVM = Depends(dep_node)) -> None: """ Start a VirtualBox node. """ @@ -153,7 +155,7 @@ async def start_virtualbox_node(node: VirtualBoxVM = Depends(dep_node)): @router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT) -async def stop_virtualbox_node(node: VirtualBoxVM = Depends(dep_node)): +async def stop_virtualbox_node(node: VirtualBoxVM = Depends(dep_node)) -> None: """ Stop a VirtualBox node. """ @@ -162,7 +164,7 @@ async def stop_virtualbox_node(node: VirtualBoxVM = Depends(dep_node)): @router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT) -async def suspend_virtualbox_node(node: VirtualBoxVM = Depends(dep_node)): +async def suspend_virtualbox_node(node: VirtualBoxVM = Depends(dep_node)) -> None: """ Suspend a VirtualBox node. """ @@ -171,7 +173,7 @@ async def suspend_virtualbox_node(node: VirtualBoxVM = Depends(dep_node)): @router.post("/{node_id}/resume", status_code=status.HTTP_204_NO_CONTENT) -async def resume_virtualbox_node(node: VirtualBoxVM = Depends(dep_node)): +async def resume_virtualbox_node(node: VirtualBoxVM = Depends(dep_node)) -> None: """ Resume a VirtualBox node. """ @@ -180,7 +182,7 @@ async def resume_virtualbox_node(node: VirtualBoxVM = Depends(dep_node)): @router.post("/{node_id}/reload", status_code=status.HTTP_204_NO_CONTENT) -async def reload_virtualbox_node(node: VirtualBoxVM = Depends(dep_node)): +async def reload_virtualbox_node(node: VirtualBoxVM = Depends(dep_node)) -> None: """ Reload a VirtualBox node. """ @@ -194,8 +196,12 @@ async def reload_virtualbox_node(node: VirtualBoxVM = Depends(dep_node)): response_model=schemas.UDPNIO, ) async def create_virtualbox_node_nio( - adapter_number: int, port_number: int, nio_data: schemas.UDPNIO, node: VirtualBoxVM = Depends(dep_node) -): + *, + adapter_number: int, + port_number: int = Path(..., ge=0, le=0), + nio_data: schemas.UDPNIO, + node: VirtualBoxVM = Depends(dep_node) +) -> schemas.UDPNIO: """ Add a NIO (Network Input/Output) to the node. The port number on the VirtualBox node is always 0. @@ -212,8 +218,12 @@ async def create_virtualbox_node_nio( response_model=schemas.UDPNIO, ) async def update_virtualbox_node_nio( - adapter_number: int, port_number: int, nio_data: schemas.UDPNIO, node: VirtualBoxVM = Depends(dep_node) -): + *, + adapter_number: int, + port_number: int = Path(..., ge=0, le=0), + nio_data: schemas.UDPNIO, + node: VirtualBoxVM = Depends(dep_node) +) -> schemas.UDPNIO: """ Update a NIO (Network Input/Output) on the node. The port number on the VirtualBox node is always 0. @@ -229,7 +239,11 @@ async def update_virtualbox_node_nio( @router.delete("/{node_id}/adapters/{adapter_number}/ports/{port_number}/nio", status_code=status.HTTP_204_NO_CONTENT) -async def delete_virtualbox_node_nio(adapter_number: int, port_number: int, node: VirtualBoxVM = Depends(dep_node)): +async def delete_virtualbox_node_nio( + adapter_number: int, + port_number: int = Path(..., ge=0, le=0), + node: VirtualBoxVM = Depends(dep_node) +) -> None: """ Delete a NIO (Network Input/Output) from the node. The port number on the VirtualBox node is always 0. @@ -240,11 +254,12 @@ async def delete_virtualbox_node_nio(adapter_number: int, port_number: int, node @router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start") async def start_virtualbox_node_capture( - adapter_number: int, - port_number: int, - node_capture_data: schemas.NodeCapture, - node: VirtualBoxVM = Depends(dep_node), -): + *, + adapter_number: int, + port_number: int = Path(..., ge=0, le=0), + node_capture_data: schemas.NodeCapture, + node: VirtualBoxVM = Depends(dep_node), +) -> dict: """ Start a packet capture on the node. The port number on the VirtualBox node is always 0. @@ -258,7 +273,11 @@ async def start_virtualbox_node_capture( @router.post( "/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stop", status_code=status.HTTP_204_NO_CONTENT ) -async def stop_virtualbox_node_capture(adapter_number: int, port_number: int, node: VirtualBoxVM = Depends(dep_node)): +async def stop_virtualbox_node_capture( + adapter_number: int, + port_number: int = Path(..., ge=0, le=0), + node: VirtualBoxVM = Depends(dep_node) +) -> None: """ Stop a packet capture on the node. The port number on the VirtualBox node is always 0. @@ -268,7 +287,11 @@ async def stop_virtualbox_node_capture(adapter_number: int, port_number: int, no @router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream") -async def stream_pcap_file(adapter_number: int, port_number: int, node: VirtualBoxVM = Depends(dep_node)): +async def stream_pcap_file( + adapter_number: int, + port_number: int = Path(..., ge=0, le=0), + node: VirtualBoxVM = Depends(dep_node) +) -> StreamingResponse: """ Stream the pcap capture file. The port number on the VirtualBox node is always 0. @@ -280,7 +303,7 @@ async def stream_pcap_file(adapter_number: int, port_number: int, node: VirtualB @router.websocket("/{node_id}/console/ws") -async def console_ws(websocket: WebSocket, node: VirtualBoxVM = Depends(dep_node)): +async def console_ws(websocket: WebSocket, node: VirtualBoxVM = Depends(dep_node)) -> None: """ Console WebSocket. """ @@ -289,6 +312,6 @@ async def console_ws(websocket: WebSocket, node: VirtualBoxVM = Depends(dep_node @router.post("/{node_id}/console/reset", status_code=status.HTTP_204_NO_CONTENT) -async def reset_console(node: VirtualBoxVM = Depends(dep_node)): +async def reset_console(node: VirtualBoxVM = Depends(dep_node)) -> None: await node.reset_console() diff --git a/gns3server/api/routes/compute/vmware_nodes.py b/gns3server/api/routes/compute/vmware_nodes.py index 05ef6929..976b749e 100644 --- a/gns3server/api/routes/compute/vmware_nodes.py +++ b/gns3server/api/routes/compute/vmware_nodes.py @@ -20,7 +20,7 @@ API routes for VMware nodes. import os -from fastapi import APIRouter, WebSocket, Depends, status +from fastapi import APIRouter, WebSocket, Depends, Path, status from fastapi.encoders import jsonable_encoder from fastapi.responses import StreamingResponse from uuid import UUID @@ -35,7 +35,7 @@ responses = {404: {"model": schemas.ErrorMessage, "description": "Could not find router = APIRouter(responses=responses) -def dep_node(project_id: UUID, node_id: UUID): +def dep_node(project_id: UUID, node_id: UUID) -> VMwareVM: """ Dependency to retrieve a node. """ @@ -51,7 +51,7 @@ def dep_node(project_id: UUID, node_id: UUID): status_code=status.HTTP_201_CREATED, responses={409: {"model": schemas.ErrorMessage, "description": "Could not create VMware node"}}, ) -async def create_vmware_node(project_id: UUID, node_data: schemas.VMwareCreate): +async def create_vmware_node(project_id: UUID, node_data: schemas.VMwareCreate) -> schemas.VMware: """ Create a new VMware node. """ @@ -77,7 +77,7 @@ async def create_vmware_node(project_id: UUID, node_data: schemas.VMwareCreate): @router.get("/{node_id}", response_model=schemas.VMware) -def get_vmware_node(node: VMwareVM = Depends(dep_node)): +def get_vmware_node(node: VMwareVM = Depends(dep_node)) -> schemas.VMware: """ Return a VMware node. """ @@ -86,7 +86,7 @@ def get_vmware_node(node: VMwareVM = Depends(dep_node)): @router.put("/{node_id}", response_model=schemas.VMware) -def update_vmware_node(node_data: schemas.VMwareUpdate, node: VMwareVM = Depends(dep_node)): +def update_vmware_node(node_data: schemas.VMwareUpdate, node: VMwareVM = Depends(dep_node)) -> schemas.VMware: """ Update a VMware node. """ @@ -103,7 +103,7 @@ def update_vmware_node(node_data: schemas.VMwareUpdate, node: VMwareVM = Depends @router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT) -async def delete_vmware_node(node: VMwareVM = Depends(dep_node)): +async def delete_vmware_node(node: VMwareVM = Depends(dep_node)) -> None: """ Delete a VMware node. """ @@ -112,7 +112,7 @@ async def delete_vmware_node(node: VMwareVM = Depends(dep_node)): @router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT) -async def start_vmware_node(node: VMwareVM = Depends(dep_node)): +async def start_vmware_node(node: VMwareVM = Depends(dep_node)) -> None: """ Start a VMware node. """ @@ -121,7 +121,7 @@ async def start_vmware_node(node: VMwareVM = Depends(dep_node)): @router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT) -async def stop_vmware_node(node: VMwareVM = Depends(dep_node)): +async def stop_vmware_node(node: VMwareVM = Depends(dep_node)) -> None: """ Stop a VMware node. """ @@ -130,7 +130,7 @@ async def stop_vmware_node(node: VMwareVM = Depends(dep_node)): @router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT) -async def suspend_vmware_node(node: VMwareVM = Depends(dep_node)): +async def suspend_vmware_node(node: VMwareVM = Depends(dep_node)) -> None: """ Suspend a VMware node. """ @@ -139,7 +139,7 @@ async def suspend_vmware_node(node: VMwareVM = Depends(dep_node)): @router.post("/{node_id}/resume", status_code=status.HTTP_204_NO_CONTENT) -async def resume_vmware_node(node: VMwareVM = Depends(dep_node)): +async def resume_vmware_node(node: VMwareVM = Depends(dep_node)) -> None: """ Resume a VMware node. """ @@ -148,7 +148,7 @@ async def resume_vmware_node(node: VMwareVM = Depends(dep_node)): @router.post("/{node_id}/reload", status_code=status.HTTP_204_NO_CONTENT) -async def reload_vmware_node(node: VMwareVM = Depends(dep_node)): +async def reload_vmware_node(node: VMwareVM = Depends(dep_node)) -> None: """ Reload a VMware node. """ @@ -162,8 +162,12 @@ async def reload_vmware_node(node: VMwareVM = Depends(dep_node)): response_model=schemas.UDPNIO, ) async def create_vmware_node_nio( - adapter_number: int, port_number: int, nio_data: schemas.UDPNIO, node: VMwareVM = Depends(dep_node) -): + *, + adapter_number: int, + port_number: int = Path(..., ge=0, le=0), + nio_data: schemas.UDPNIO, + node: VMwareVM = Depends(dep_node) +) -> schemas.UDPNIO: """ Add a NIO (Network Input/Output) to the node. The port number on the VMware node is always 0. @@ -180,8 +184,12 @@ async def create_vmware_node_nio( response_model=schemas.UDPNIO, ) async def update_vmware_node_nio( - adapter_number: int, port_number: int, nio_data: schemas.UDPNIO, node: VMwareVM = Depends(dep_node) -): + *, + adapter_number: int, + port_number: int = Path(..., ge=0, le=0), + nio_data: schemas.UDPNIO, + node: VMwareVM = Depends(dep_node) +) -> schemas.UDPNIO: """ Update a NIO (Network Input/Output) on the node. The port number on the VMware node is always 0. @@ -195,7 +203,11 @@ async def update_vmware_node_nio( @router.delete("/{node_id}/adapters/{adapter_number}/ports/{port_number}/nio", status_code=status.HTTP_204_NO_CONTENT) -async def delete_vmware_node_nio(adapter_number: int, port_number: int, node: VMwareVM = Depends(dep_node)): +async def delete_vmware_node_nio( + adapter_number: int, + port_number: int = Path(..., ge=0, le=0), + node: VMwareVM = Depends(dep_node) +) -> None: """ Delete a NIO (Network Input/Output) from the node. The port number on the VMware node is always 0. @@ -206,8 +218,12 @@ async def delete_vmware_node_nio(adapter_number: int, port_number: int, node: VM @router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start") async def start_vmware_node_capture( - adapter_number: int, port_number: int, node_capture_data: schemas.NodeCapture, node: VMwareVM = Depends(dep_node) -): + *, + adapter_number: int, + port_number: int = Path(..., ge=0, le=0), + node_capture_data: schemas.NodeCapture, + node: VMwareVM = Depends(dep_node) +) -> dict: """ Start a packet capture on the node. The port number on the VMware node is always 0. @@ -221,7 +237,11 @@ async def start_vmware_node_capture( @router.post( "/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stop", status_code=status.HTTP_204_NO_CONTENT ) -async def stop_vmware_node_capture(adapter_number: int, port_number: int, node: VMwareVM = Depends(dep_node)): +async def stop_vmware_node_capture( + adapter_number: int, + port_number: int = Path(..., ge=0, le=0), + node: VMwareVM = Depends(dep_node) +) -> None: """ Stop a packet capture on the node. The port number on the VMware node is always 0. @@ -231,7 +251,11 @@ async def stop_vmware_node_capture(adapter_number: int, port_number: int, node: @router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream") -async def stream_pcap_file(adapter_number: int, port_number: int, node: VMwareVM = Depends(dep_node)): +async def stream_pcap_file( + adapter_number: int, + port_number: int = Path(..., ge=0, le=0), + node: VMwareVM = Depends(dep_node) +) -> StreamingResponse: """ Stream the pcap capture file. The port number on the VMware node is always 0. @@ -256,7 +280,7 @@ def allocate_vmnet(node: VMwareVM = Depends(dep_node)) -> dict: @router.websocket("/{node_id}/console/ws") -async def console_ws(websocket: WebSocket, node: VMwareVM = Depends(dep_node)): +async def console_ws(websocket: WebSocket, node: VMwareVM = Depends(dep_node)) -> None: """ Console WebSocket. """ @@ -265,6 +289,6 @@ async def console_ws(websocket: WebSocket, node: VMwareVM = Depends(dep_node)): @router.post("/{node_id}/console/reset", status_code=status.HTTP_204_NO_CONTENT) -async def reset_console(node: VMwareVM = Depends(dep_node)): +async def reset_console(node: VMwareVM = Depends(dep_node)) -> None: await node.reset_console() diff --git a/gns3server/api/routes/compute/vpcs_nodes.py b/gns3server/api/routes/compute/vpcs_nodes.py index a34d99d5..7d9ffab9 100644 --- a/gns3server/api/routes/compute/vpcs_nodes.py +++ b/gns3server/api/routes/compute/vpcs_nodes.py @@ -20,7 +20,7 @@ API routes for VPCS nodes. import os -from fastapi import APIRouter, WebSocket, Depends, Body, status +from fastapi import APIRouter, WebSocket, Depends, Body, Path, status from fastapi.encoders import jsonable_encoder from fastapi.responses import StreamingResponse from uuid import UUID @@ -34,7 +34,7 @@ responses = {404: {"model": schemas.ErrorMessage, "description": "Could not find router = APIRouter(responses=responses) -def dep_node(project_id: UUID, node_id: UUID): +def dep_node(project_id: UUID, node_id: UUID) -> VPCSVM: """ Dependency to retrieve a node. """ @@ -50,7 +50,7 @@ def dep_node(project_id: UUID, node_id: UUID): status_code=status.HTTP_201_CREATED, responses={409: {"model": schemas.ErrorMessage, "description": "Could not create VMware node"}}, ) -async def create_vpcs_node(project_id: UUID, node_data: schemas.VPCSCreate): +async def create_vpcs_node(project_id: UUID, node_data: schemas.VPCSCreate) -> schemas.VPCS: """ Create a new VPCS node. """ @@ -70,7 +70,7 @@ async def create_vpcs_node(project_id: UUID, node_data: schemas.VPCSCreate): @router.get("/{node_id}", response_model=schemas.VPCS) -def get_vpcs_node(node: VPCSVM = Depends(dep_node)): +def get_vpcs_node(node: VPCSVM = Depends(dep_node)) -> schemas.VPCS: """ Return a VPCS node. """ @@ -79,7 +79,7 @@ def get_vpcs_node(node: VPCSVM = Depends(dep_node)): @router.put("/{node_id}", response_model=schemas.VPCS) -def update_vpcs_node(node_data: schemas.VPCSUpdate, node: VPCSVM = Depends(dep_node)): +def update_vpcs_node(node_data: schemas.VPCSUpdate, node: VPCSVM = Depends(dep_node)) -> schemas.VPCS: """ Update a VPCS node. """ @@ -93,7 +93,7 @@ def update_vpcs_node(node_data: schemas.VPCSUpdate, node: VPCSVM = Depends(dep_n @router.delete("/{node_id}", status_code=status.HTTP_204_NO_CONTENT) -async def delete_vpcs_node(node: VPCSVM = Depends(dep_node)): +async def delete_vpcs_node(node: VPCSVM = Depends(dep_node)) -> None: """ Delete a VPCS node. """ @@ -102,7 +102,9 @@ async def delete_vpcs_node(node: VPCSVM = Depends(dep_node)): @router.post("/{node_id}/duplicate", response_model=schemas.VPCS, status_code=status.HTTP_201_CREATED) -async def duplicate_vpcs_node(destination_node_id: UUID = Body(..., embed=True), node: VPCSVM = Depends(dep_node)): +async def duplicate_vpcs_node( + destination_node_id: UUID = Body(..., embed=True), + node: VPCSVM = Depends(dep_node)) -> None: """ Duplicate a VPCS node. """ @@ -112,7 +114,7 @@ async def duplicate_vpcs_node(destination_node_id: UUID = Body(..., embed=True), @router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT) -async def start_vpcs_node(node: VPCSVM = Depends(dep_node)): +async def start_vpcs_node(node: VPCSVM = Depends(dep_node)) -> None: """ Start a VPCS node. """ @@ -121,7 +123,7 @@ async def start_vpcs_node(node: VPCSVM = Depends(dep_node)): @router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT) -async def stop_vpcs_node(node: VPCSVM = Depends(dep_node)): +async def stop_vpcs_node(node: VPCSVM = Depends(dep_node)) -> None: """ Stop a VPCS node. """ @@ -130,7 +132,7 @@ async def stop_vpcs_node(node: VPCSVM = Depends(dep_node)): @router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT) -async def suspend_vpcs_node(node: VPCSVM = Depends(dep_node)): +async def suspend_vpcs_node(node: VPCSVM = Depends(dep_node)) -> None: """ Suspend a VPCS node. Does nothing, suspend is not supported by VPCS. @@ -140,7 +142,7 @@ async def suspend_vpcs_node(node: VPCSVM = Depends(dep_node)): @router.post("/{node_id}/reload", status_code=status.HTTP_204_NO_CONTENT) -async def reload_vpcs_node(node: VPCSVM = Depends(dep_node)): +async def reload_vpcs_node(node: VPCSVM = Depends(dep_node)) -> None: """ Reload a VPCS node. """ @@ -154,8 +156,12 @@ async def reload_vpcs_node(node: VPCSVM = Depends(dep_node)): response_model=schemas.UDPNIO, ) async def create_vpcs_node_nio( - adapter_number: int, port_number: int, nio_data: schemas.UDPNIO, node: VPCSVM = Depends(dep_node) -): + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + nio_data: schemas.UDPNIO, + node: VPCSVM = Depends(dep_node) +) -> schemas.UDPNIO: """ Add a NIO (Network Input/Output) to the node. The adapter number on the VPCS node is always 0. @@ -172,8 +178,12 @@ async def create_vpcs_node_nio( response_model=schemas.UDPNIO, ) async def update_vpcs_node_nio( - adapter_number: int, port_number: int, nio_data: schemas.UDPNIO, node: VPCSVM = Depends(dep_node) -): + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + nio_data: schemas.UDPNIO, + node: VPCSVM = Depends(dep_node) +) -> schemas.UDPNIO: """ Update a NIO (Network Input/Output) on the node. The adapter number on the VPCS node is always 0. @@ -187,7 +197,12 @@ async def update_vpcs_node_nio( @router.delete("/{node_id}/adapters/{adapter_number}/ports/{port_number}/nio", status_code=status.HTTP_204_NO_CONTENT) -async def delete_vpcs_node_nio(adapter_number: int, port_number: int, node: VPCSVM = Depends(dep_node)): +async def delete_vpcs_node_nio( + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + node: VPCSVM = Depends(dep_node) +) -> None: """ Delete a NIO (Network Input/Output) from the node. The adapter number on the VPCS node is always 0. @@ -198,8 +213,12 @@ async def delete_vpcs_node_nio(adapter_number: int, port_number: int, node: VPCS @router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start") async def start_vpcs_node_capture( - adapter_number: int, port_number: int, node_capture_data: schemas.NodeCapture, node: VPCSVM = Depends(dep_node) -): + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + node_capture_data: schemas.NodeCapture, + node: VPCSVM = Depends(dep_node) +) -> dict: """ Start a packet capture on the node. The adapter number on the VPCS node is always 0. @@ -213,7 +232,12 @@ async def start_vpcs_node_capture( @router.post( "/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stop", status_code=status.HTTP_204_NO_CONTENT ) -async def stop_vpcs_node_capture(adapter_number: int, port_number: int, node: VPCSVM = Depends(dep_node)): +async def stop_vpcs_node_capture( + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + node: VPCSVM = Depends(dep_node) +) -> None: """ Stop a packet capture on the node. The adapter number on the VPCS node is always 0. @@ -223,13 +247,18 @@ async def stop_vpcs_node_capture(adapter_number: int, port_number: int, node: VP @router.post("/{node_id}/console/reset", status_code=status.HTTP_204_NO_CONTENT) -async def reset_console(node: VPCSVM = Depends(dep_node)): +async def reset_console(node: VPCSVM = Depends(dep_node)) -> None: await node.reset_console() @router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream") -async def stream_pcap_file(adapter_number: int, port_number: int, node: VPCSVM = Depends(dep_node)): +async def stream_pcap_file( + *, + adapter_number: int = Path(..., ge=0, le=0), + port_number: int, + node: VPCSVM = Depends(dep_node) +) -> StreamingResponse: """ Stream the pcap capture file. The adapter number on the VPCS node is always 0. @@ -241,7 +270,7 @@ async def stream_pcap_file(adapter_number: int, port_number: int, node: VPCSVM = @router.websocket("/{node_id}/console/ws") -async def console_ws(websocket: WebSocket, node: VPCSVM = Depends(dep_node)): +async def console_ws(websocket: WebSocket, node: VPCSVM = Depends(dep_node)) -> None: """ Console WebSocket. """ diff --git a/gns3server/api/routes/controller/appliances.py b/gns3server/api/routes/controller/appliances.py index 8876c83b..0a2dfc7e 100644 --- a/gns3server/api/routes/controller/appliances.py +++ b/gns3server/api/routes/controller/appliances.py @@ -19,13 +19,13 @@ API routes for appliances. """ from fastapi import APIRouter -from typing import Optional +from typing import Optional, List router = APIRouter() @router.get("") -async def get_appliances(update: Optional[bool] = None, symbol_theme: Optional[str] = "Classic"): +async def get_appliances(update: Optional[bool] = None, symbol_theme: Optional[str] = "Classic") -> List[dict]: """ Return all appliances known by the controller. """ diff --git a/gns3server/api/routes/controller/computes.py b/gns3server/api/routes/controller/computes.py index ff0c13e3..2cc8727c 100644 --- a/gns3server/api/routes/controller/computes.py +++ b/gns3server/api/routes/controller/computes.py @@ -93,7 +93,7 @@ async def update_compute( @router.delete("/{compute_id}", status_code=status.HTTP_204_NO_CONTENT) async def delete_compute( compute_id: Union[str, UUID], computes_repo: ComputesRepository = Depends(get_repository(ComputesRepository)) -): +) -> None: """ Delete a compute from the controller. """ @@ -102,7 +102,7 @@ async def delete_compute( @router.get("/{compute_id}/{emulator}/images") -async def get_images(compute_id: Union[str, UUID], emulator: str): +async def get_images(compute_id: Union[str, UUID], emulator: str) -> List[str]: """ Return the list of images available on a compute for a given emulator type. """ @@ -113,7 +113,7 @@ async def get_images(compute_id: Union[str, UUID], emulator: str): @router.get("/{compute_id}/{emulator}/{endpoint_path:path}") -async def forward_get(compute_id: Union[str, UUID], emulator: str, endpoint_path: str): +async def forward_get(compute_id: Union[str, UUID], emulator: str, endpoint_path: str) -> dict: """ Forward a GET request to a compute. Read the full compute API documentation for available routes. @@ -125,7 +125,7 @@ async def forward_get(compute_id: Union[str, UUID], emulator: str, endpoint_path @router.post("/{compute_id}/{emulator}/{endpoint_path:path}") -async def forward_post(compute_id: Union[str, UUID], emulator: str, endpoint_path: str, compute_data: dict): +async def forward_post(compute_id: Union[str, UUID], emulator: str, endpoint_path: str, compute_data: dict) -> dict: """ Forward a POST request to a compute. Read the full compute API documentation for available routes. @@ -136,7 +136,7 @@ async def forward_post(compute_id: Union[str, UUID], emulator: str, endpoint_pat @router.put("/{compute_id}/{emulator}/{endpoint_path:path}") -async def forward_put(compute_id: Union[str, UUID], emulator: str, endpoint_path: str, compute_data: dict): +async def forward_put(compute_id: Union[str, UUID], emulator: str, endpoint_path: str, compute_data: dict) -> dict: """ Forward a PUT request to a compute. Read the full compute API documentation for available routes. @@ -147,7 +147,7 @@ async def forward_put(compute_id: Union[str, UUID], emulator: str, endpoint_path @router.post("/{compute_id}/auto_idlepc") -async def autoidlepc(compute_id: Union[str, UUID], auto_idle_pc: schemas.AutoIdlePC): +async def autoidlepc(compute_id: Union[str, UUID], auto_idle_pc: schemas.AutoIdlePC) -> str: """ Find a suitable Idle-PC value for a given IOS image. This may take a few minutes. """ diff --git a/gns3server/api/routes/controller/controller.py b/gns3server/api/routes/controller/controller.py index 8dfa2998..d26e5137 100644 --- a/gns3server/api/routes/controller/controller.py +++ b/gns3server/api/routes/controller/controller.py @@ -20,6 +20,7 @@ import os from fastapi import APIRouter, status from fastapi.encoders import jsonable_encoder +from typing import List from gns3server.config import Config from gns3server.controller import Controller @@ -40,7 +41,7 @@ router = APIRouter() status_code=status.HTTP_204_NO_CONTENT, responses={403: {"model": schemas.ErrorMessage, "description": "Server shutdown not allowed"}}, ) -async def shutdown(): +async def shutdown() -> None: """ Shutdown the local server """ @@ -71,7 +72,7 @@ async def shutdown(): @router.get("/version", response_model=schemas.Version) -def get_version(): +def get_version() -> dict: """ Return the server version number. """ @@ -86,7 +87,7 @@ def get_version(): response_model_exclude_defaults=True, responses={409: {"model": schemas.ErrorMessage, "description": "Invalid version"}}, ) -def check_version(version: schemas.Version): +def check_version(version: schemas.Version) -> dict: """ Check if version is the same as the server. @@ -102,7 +103,7 @@ def check_version(version: schemas.Version): @router.get("/iou_license", response_model=schemas.IOULicense) -def get_iou_license(): +def get_iou_license() -> schemas.IOULicense: """ Return the IOU license settings """ @@ -111,7 +112,7 @@ def get_iou_license(): @router.put("/iou_license", status_code=status.HTTP_201_CREATED, response_model=schemas.IOULicense) -async def update_iou_license(iou_license: schemas.IOULicense): +async def update_iou_license(iou_license: schemas.IOULicense) -> schemas.IOULicense: """ Update the IOU license settings. """ @@ -124,7 +125,7 @@ async def update_iou_license(iou_license: schemas.IOULicense): @router.get("/statistics") -async def statistics(): +async def statistics() -> List[dict]: """ Return server statistics. """ diff --git a/gns3server/api/routes/controller/drawings.py b/gns3server/api/routes/controller/drawings.py index b3804947..bce40ca7 100644 --- a/gns3server/api/routes/controller/drawings.py +++ b/gns3server/api/routes/controller/drawings.py @@ -32,7 +32,7 @@ router = APIRouter(responses=responses) @router.get("", response_model=List[schemas.Drawing], response_model_exclude_unset=True) -async def get_drawings(project_id: UUID): +async def get_drawings(project_id: UUID) -> List[schemas.Drawing]: """ Return the list of all drawings for a given project. """ @@ -42,7 +42,7 @@ async def get_drawings(project_id: UUID): @router.post("", status_code=status.HTTP_201_CREATED, response_model=schemas.Drawing) -async def create_drawing(project_id: UUID, drawing_data: schemas.Drawing): +async def create_drawing(project_id: UUID, drawing_data: schemas.Drawing) -> schemas.Drawing: """ Create a new drawing. """ @@ -53,7 +53,7 @@ async def create_drawing(project_id: UUID, drawing_data: schemas.Drawing): @router.get("/{drawing_id}", response_model=schemas.Drawing, response_model_exclude_unset=True) -async def get_drawing(project_id: UUID, drawing_id: UUID): +async def get_drawing(project_id: UUID, drawing_id: UUID) -> schemas.Drawing: """ Return a drawing. """ @@ -64,7 +64,7 @@ async def get_drawing(project_id: UUID, drawing_id: UUID): @router.put("/{drawing_id}", response_model=schemas.Drawing, response_model_exclude_unset=True) -async def update_drawing(project_id: UUID, drawing_id: UUID, drawing_data: schemas.Drawing): +async def update_drawing(project_id: UUID, drawing_id: UUID, drawing_data: schemas.Drawing) -> schemas.Drawing: """ Update a drawing. """ @@ -76,7 +76,7 @@ async def update_drawing(project_id: UUID, drawing_id: UUID, drawing_data: schem @router.delete("/{drawing_id}", status_code=status.HTTP_204_NO_CONTENT) -async def delete_drawing(project_id: UUID, drawing_id: UUID): +async def delete_drawing(project_id: UUID, drawing_id: UUID) -> None: """ Delete a drawing. """ diff --git a/gns3server/api/routes/controller/gns3vm.py b/gns3server/api/routes/controller/gns3vm.py index 80329dfe..d019189b 100644 --- a/gns3server/api/routes/controller/gns3vm.py +++ b/gns3server/api/routes/controller/gns3vm.py @@ -21,6 +21,7 @@ API routes for managing the GNS3 VM. from fastapi import APIRouter from fastapi.encoders import jsonable_encoder +from typing import List from gns3server.controller import Controller from gns3server import schemas @@ -29,7 +30,7 @@ router = APIRouter() @router.get("/engines") -async def get_engines(): +async def get_engines() -> List[dict]: """ Return the list of supported engines for the GNS3VM. """ @@ -39,7 +40,7 @@ async def get_engines(): @router.get("/engines/{engine}/vms") -async def get_vms(engine: str): +async def get_vms(engine: str) -> List[dict]: """ Return all the available VMs for a specific virtualization engine. """ @@ -49,7 +50,7 @@ async def get_vms(engine: str): @router.get("", response_model=schemas.GNS3VM) -async def get_gns3vm_settings(): +async def get_gns3vm_settings() -> schemas.GNS3VM: """ Return the GNS3 VM settings. """ @@ -58,7 +59,7 @@ async def get_gns3vm_settings(): @router.put("", response_model=schemas.GNS3VM, response_model_exclude_unset=True) -async def update_gns3vm_settings(gns3vm_data: schemas.GNS3VM): +async def update_gns3vm_settings(gns3vm_data: schemas.GNS3VM) -> schemas.GNS3VM: """ Update the GNS3 VM settings. """ diff --git a/gns3server/api/routes/controller/links.py b/gns3server/api/routes/controller/links.py index 0cab04a6..31ecff6e 100644 --- a/gns3server/api/routes/controller/links.py +++ b/gns3server/api/routes/controller/links.py @@ -42,7 +42,7 @@ responses = {404: {"model": schemas.ErrorMessage, "description": "Could not find router = APIRouter(responses=responses) -async def dep_link(project_id: UUID, link_id: UUID): +async def dep_link(project_id: UUID, link_id: UUID) -> Link: """ Dependency to retrieve a link. """ @@ -53,7 +53,7 @@ async def dep_link(project_id: UUID, link_id: UUID): @router.get("", response_model=List[schemas.Link], response_model_exclude_unset=True) -async def get_links(project_id: UUID): +async def get_links(project_id: UUID) -> List[schemas.Link]: """ Return all links for a given project. """ @@ -71,7 +71,7 @@ async def get_links(project_id: UUID): 409: {"model": schemas.ErrorMessage, "description": "Could not create link"}, }, ) -async def create_link(project_id: UUID, link_data: schemas.LinkCreate): +async def create_link(project_id: UUID, link_data: schemas.LinkCreate) -> schemas.Link: """ Create a new link. """ @@ -98,7 +98,7 @@ async def create_link(project_id: UUID, link_data: schemas.LinkCreate): @router.get("/{link_id}/available_filters") -async def get_filters(link: Link = Depends(dep_link)): +async def get_filters(link: Link = Depends(dep_link)) -> List[dict]: """ Return all filters available for a given link. """ @@ -107,7 +107,7 @@ async def get_filters(link: Link = Depends(dep_link)): @router.get("/{link_id}", response_model=schemas.Link, response_model_exclude_unset=True) -async def get_link(link: Link = Depends(dep_link)): +async def get_link(link: Link = Depends(dep_link)) -> schemas.Link: """ Return a link. """ @@ -116,7 +116,7 @@ async def get_link(link: Link = Depends(dep_link)): @router.put("/{link_id}", response_model=schemas.Link, response_model_exclude_unset=True) -async def update_link(link_data: schemas.LinkUpdate, link: Link = Depends(dep_link)): +async def update_link(link_data: schemas.LinkUpdate, link: Link = Depends(dep_link)) -> schemas.Link: """ Update a link. """ @@ -132,7 +132,7 @@ async def update_link(link_data: schemas.LinkUpdate, link: Link = Depends(dep_li @router.delete("/{link_id}", status_code=status.HTTP_204_NO_CONTENT) -async def delete_link(project_id: UUID, link: Link = Depends(dep_link)): +async def delete_link(project_id: UUID, link: Link = Depends(dep_link)) -> None: """ Delete a link. """ @@ -142,7 +142,7 @@ async def delete_link(project_id: UUID, link: Link = Depends(dep_link)): @router.post("/{link_id}/reset", response_model=schemas.Link) -async def reset_link(link: Link = Depends(dep_link)): +async def reset_link(link: Link = Depends(dep_link)) -> schemas.Link: """ Reset a link. """ @@ -152,7 +152,7 @@ async def reset_link(link: Link = Depends(dep_link)): @router.post("/{link_id}/capture/start", status_code=status.HTTP_201_CREATED, response_model=schemas.Link) -async def start_capture(capture_data: dict, link: Link = Depends(dep_link)): +async def start_capture(capture_data: dict, link: Link = Depends(dep_link)) -> schemas.Link: """ Start packet capture on the link. """ @@ -165,7 +165,7 @@ async def start_capture(capture_data: dict, link: Link = Depends(dep_link)): @router.post("/{link_id}/capture/stop", status_code=status.HTTP_204_NO_CONTENT) -async def stop_capture(link: Link = Depends(dep_link)): +async def stop_capture(link: Link = Depends(dep_link)) -> None: """ Stop packet capture on the link. """ @@ -174,7 +174,7 @@ async def stop_capture(link: Link = Depends(dep_link)): @router.get("/{link_id}/capture/stream") -async def stream_pcap(request: Request, link: Link = Depends(dep_link)): +async def stream_pcap(request: Request, link: Link = Depends(dep_link)) -> StreamingResponse: """ Stream the PCAP capture file from compute. """ diff --git a/gns3server/api/routes/controller/nodes.py b/gns3server/api/routes/controller/nodes.py index 58d0e114..899e9a31 100644 --- a/gns3server/api/routes/controller/nodes.py +++ b/gns3server/api/routes/controller/nodes.py @@ -81,7 +81,7 @@ responses = {404: {"model": schemas.ErrorMessage, "description": "Could not find router = APIRouter(route_class=NodeConcurrency, responses=responses) -async def dep_project(project_id: UUID): +async def dep_project(project_id: UUID) -> Project: """ Dependency to retrieve a project. """ @@ -90,7 +90,7 @@ async def dep_project(project_id: UUID): return project -async def dep_node(node_id: UUID, project: Project = Depends(dep_project)): +async def dep_node(node_id: UUID, project: Project = Depends(dep_project)) -> None: """ Dependency to retrieve a node. """ @@ -108,7 +108,7 @@ async def dep_node(node_id: UUID, project: Project = Depends(dep_project)): 409: {"model": schemas.ErrorMessage, "description": "Could not create node"}, }, ) -async def create_node(node_data: schemas.NodeCreate, project: Project = Depends(dep_project)): +async def create_node(node_data: schemas.NodeCreate, project: Project = Depends(dep_project)) -> schemas.Node: """ Create a new node. """ @@ -121,7 +121,7 @@ async def create_node(node_data: schemas.NodeCreate, project: Project = Depends( @router.get("", response_model=List[schemas.Node], response_model_exclude_unset=True) -async def get_nodes(project: Project = Depends(dep_project)): +async def get_nodes(project: Project = Depends(dep_project)) -> List[schemas.Node]: """ Return all nodes belonging to a given project. """ @@ -130,7 +130,7 @@ async def get_nodes(project: Project = Depends(dep_project)): @router.post("/start", status_code=status.HTTP_204_NO_CONTENT) -async def start_all_nodes(project: Project = Depends(dep_project)): +async def start_all_nodes(project: Project = Depends(dep_project)) -> None: """ Start all nodes belonging to a given project. """ @@ -139,7 +139,7 @@ async def start_all_nodes(project: Project = Depends(dep_project)): @router.post("/stop", status_code=status.HTTP_204_NO_CONTENT) -async def stop_all_nodes(project: Project = Depends(dep_project)): +async def stop_all_nodes(project: Project = Depends(dep_project)) -> None: """ Stop all nodes belonging to a given project. """ @@ -148,7 +148,7 @@ async def stop_all_nodes(project: Project = Depends(dep_project)): @router.post("/suspend", status_code=status.HTTP_204_NO_CONTENT) -async def suspend_all_nodes(project: Project = Depends(dep_project)): +async def suspend_all_nodes(project: Project = Depends(dep_project)) -> None: """ Suspend all nodes belonging to a given project. """ @@ -157,7 +157,7 @@ async def suspend_all_nodes(project: Project = Depends(dep_project)): @router.post("/reload", status_code=status.HTTP_204_NO_CONTENT) -async def reload_all_nodes(project: Project = Depends(dep_project)): +async def reload_all_nodes(project: Project = Depends(dep_project)) -> None: """ Reload all nodes belonging to a given project. """ @@ -167,7 +167,7 @@ async def reload_all_nodes(project: Project = Depends(dep_project)): @router.get("/{node_id}", response_model=schemas.Node) -def get_node(node: Node = Depends(dep_node)): +def get_node(node: Node = Depends(dep_node)) -> schemas.Node: """ Return a node from a given project. """ @@ -176,7 +176,7 @@ def get_node(node: Node = Depends(dep_node)): @router.put("/{node_id}", response_model=schemas.Node, response_model_exclude_unset=True) -async def update_node(node_data: schemas.NodeUpdate, node: Node = Depends(dep_node)): +async def update_node(node_data: schemas.NodeUpdate, node: Node = Depends(dep_node)) -> schemas.Node: """ Update a node. """ @@ -197,7 +197,7 @@ async def update_node(node_data: schemas.NodeUpdate, node: Node = Depends(dep_no status_code=status.HTTP_204_NO_CONTENT, responses={**responses, 409: {"model": schemas.ErrorMessage, "description": "Cannot delete node"}}, ) -async def delete_node(node_id: UUID, project: Project = Depends(dep_project)): +async def delete_node(node_id: UUID, project: Project = Depends(dep_project)) -> None: """ Delete a node from a project. """ @@ -206,7 +206,7 @@ async def delete_node(node_id: UUID, project: Project = Depends(dep_project)): @router.post("/{node_id}/duplicate", response_model=schemas.Node, status_code=status.HTTP_201_CREATED) -async def duplicate_node(duplicate_data: schemas.NodeDuplicate, node: Node = Depends(dep_node)): +async def duplicate_node(duplicate_data: schemas.NodeDuplicate, node: Node = Depends(dep_node)) -> schemas.Node: """ Duplicate a node. """ @@ -216,7 +216,7 @@ async def duplicate_node(duplicate_data: schemas.NodeDuplicate, node: Node = Dep @router.post("/{node_id}/start", status_code=status.HTTP_204_NO_CONTENT) -async def start_node(start_data: dict, node: Node = Depends(dep_node)): +async def start_node(start_data: dict, node: Node = Depends(dep_node)) -> None: """ Start a node. """ @@ -225,7 +225,7 @@ async def start_node(start_data: dict, node: Node = Depends(dep_node)): @router.post("/{node_id}/stop", status_code=status.HTTP_204_NO_CONTENT) -async def stop_node(node: Node = Depends(dep_node)): +async def stop_node(node: Node = Depends(dep_node)) -> None: """ Stop a node. """ @@ -234,7 +234,7 @@ async def stop_node(node: Node = Depends(dep_node)): @router.post("/{node_id}/suspend", status_code=status.HTTP_204_NO_CONTENT) -async def suspend_node(node: Node = Depends(dep_node)): +async def suspend_node(node: Node = Depends(dep_node)) -> None: """ Suspend a node. """ @@ -243,7 +243,7 @@ async def suspend_node(node: Node = Depends(dep_node)): @router.post("/{node_id}/reload", status_code=status.HTTP_204_NO_CONTENT) -async def reload_node(node: Node = Depends(dep_node)): +async def reload_node(node: Node = Depends(dep_node)) -> None: """ Reload a node. """ @@ -252,7 +252,7 @@ async def reload_node(node: Node = Depends(dep_node)): @router.get("/{node_id}/links", response_model=List[schemas.Link], response_model_exclude_unset=True) -async def get_node_links(node: Node = Depends(dep_node)): +async def get_node_links(node: Node = Depends(dep_node)) -> List[schemas.Link]: """ Return all the links connected to a node. """ @@ -264,7 +264,7 @@ async def get_node_links(node: Node = Depends(dep_node)): @router.get("/{node_id}/dynamips/auto_idlepc") -async def auto_idlepc(node: Node = Depends(dep_node)): +async def auto_idlepc(node: Node = Depends(dep_node)) -> str: """ Compute an Idle-PC value for a Dynamips node """ @@ -273,7 +273,7 @@ async def auto_idlepc(node: Node = Depends(dep_node)): @router.get("/{node_id}/dynamips/idlepc_proposals") -async def idlepc_proposals(node: Node = Depends(dep_node)): +async def idlepc_proposals(node: Node = Depends(dep_node)) -> List[str]: """ Compute a list of potential idle-pc values for a Dynamips node """ @@ -281,8 +281,8 @@ async def idlepc_proposals(node: Node = Depends(dep_node)): return await node.dynamips_idlepc_proposals() -@router.post("/{node_id}/resize_disk", status_code=status.HTTP_201_CREATED) -async def resize_disk(resize_data: dict, node: Node = Depends(dep_node)): +@router.post("/{node_id}/resize_disk", status_code=status.HTTP_204_NO_CONTENT) +async def resize_disk(resize_data: dict, node: Node = Depends(dep_node)) -> None: """ Resize a disk image. """ @@ -290,7 +290,7 @@ async def resize_disk(resize_data: dict, node: Node = Depends(dep_node)): @router.get("/{node_id}/files/{file_path:path}") -async def get_file(file_path: str, node: Node = Depends(dep_node)): +async def get_file(file_path: str, node: Node = Depends(dep_node)) -> Response: """ Return a file in the node directory """ @@ -309,7 +309,7 @@ async def get_file(file_path: str, node: Node = Depends(dep_node)): @router.post("/{node_id}/files/{file_path:path}", status_code=status.HTTP_201_CREATED) -async def post_file(file_path: str, request: Request, node: Node = Depends(dep_node)): +async def post_file(file_path: str, request: Request, node: Node = Depends(dep_node)) -> dict: """ Write a file in the node directory. """ @@ -329,7 +329,7 @@ async def post_file(file_path: str, request: Request, node: Node = Depends(dep_n @router.websocket("/{node_id}/console/ws") -async def ws_console(websocket: WebSocket, node: Node = Depends(dep_node)): +async def ws_console(websocket: WebSocket, node: Node = Depends(dep_node)) -> None: """ WebSocket console. """ @@ -377,7 +377,7 @@ async def ws_console(websocket: WebSocket, node: Node = Depends(dep_node)): @router.post("/console/reset", status_code=status.HTTP_204_NO_CONTENT) -async def reset_console_all_nodes(project: Project = Depends(dep_project)): +async def reset_console_all_nodes(project: Project = Depends(dep_project)) -> None: """ Reset console for all nodes belonging to the project. """ @@ -386,6 +386,6 @@ async def reset_console_all_nodes(project: Project = Depends(dep_project)): @router.post("/{node_id}/console/reset", status_code=status.HTTP_204_NO_CONTENT) -async def console_reset(node: Node = Depends(dep_node)): +async def console_reset(node: Node = Depends(dep_node)) -> None: await node.post("/console/reset") # , request.json) diff --git a/gns3server/api/routes/controller/notifications.py b/gns3server/api/routes/controller/notifications.py index bb64fbb9..3634a7d4 100644 --- a/gns3server/api/routes/controller/notifications.py +++ b/gns3server/api/routes/controller/notifications.py @@ -32,7 +32,7 @@ router = APIRouter() @router.get("") -async def http_notification(): +async def http_notification() -> StreamingResponse: """ Receive controller notifications about the controller from HTTP stream. """ @@ -47,7 +47,7 @@ async def http_notification(): @router.websocket("/ws") -async def notification_ws(websocket: WebSocket): +async def notification_ws(websocket: WebSocket) -> None: """ Receive project notifications about the controller from WebSocket. """ diff --git a/gns3server/api/routes/controller/projects.py b/gns3server/api/routes/controller/projects.py index 7b5775a2..c8936f5f 100644 --- a/gns3server/api/routes/controller/projects.py +++ b/gns3server/api/routes/controller/projects.py @@ -51,7 +51,7 @@ responses = {404: {"model": schemas.ErrorMessage, "description": "Could not find router = APIRouter(responses=responses) -def dep_project(project_id: UUID): +def dep_project(project_id: UUID) -> Project: """ Dependency to retrieve a project. """ @@ -64,7 +64,7 @@ CHUNK_SIZE = 1024 * 8 # 8KB @router.get("", response_model=List[schemas.Project], response_model_exclude_unset=True) -def get_projects(): +def get_projects() -> List[schemas.Project]: """ Return all projects. """ @@ -80,7 +80,7 @@ def get_projects(): response_model_exclude_unset=True, responses={409: {"model": schemas.ErrorMessage, "description": "Could not create project"}}, ) -async def create_project(project_data: schemas.ProjectCreate): +async def create_project(project_data: schemas.ProjectCreate) -> schemas.Project: """ Create a new project. """ @@ -91,7 +91,7 @@ async def create_project(project_data: schemas.ProjectCreate): @router.get("/{project_id}", response_model=schemas.Project) -def get_project(project: Project = Depends(dep_project)): +def get_project(project: Project = Depends(dep_project)) -> schemas.Project: """ Return a project. """ @@ -100,7 +100,10 @@ def get_project(project: Project = Depends(dep_project)): @router.put("/{project_id}", response_model=schemas.Project, response_model_exclude_unset=True) -async def update_project(project_data: schemas.ProjectUpdate, project: Project = Depends(dep_project)): +async def update_project( + project_data: schemas.ProjectUpdate, + project: Project = Depends(dep_project) +) -> schemas.Project: """ Update a project. """ @@ -110,7 +113,7 @@ async def update_project(project_data: schemas.ProjectUpdate, project: Project = @router.delete("/{project_id}", status_code=status.HTTP_204_NO_CONTENT) -async def delete_project(project: Project = Depends(dep_project)): +async def delete_project(project: Project = Depends(dep_project)) -> None: """ Delete a project. """ @@ -121,7 +124,7 @@ async def delete_project(project: Project = Depends(dep_project)): @router.get("/{project_id}/stats") -def get_project_stats(project: Project = Depends(dep_project)): +def get_project_stats(project: Project = Depends(dep_project)) -> dict: """ Return a project statistics. """ @@ -134,7 +137,7 @@ def get_project_stats(project: Project = Depends(dep_project)): status_code=status.HTTP_204_NO_CONTENT, responses={**responses, 409: {"model": schemas.ErrorMessage, "description": "Could not close project"}}, ) -async def close_project(project: Project = Depends(dep_project)): +async def close_project(project: Project = Depends(dep_project)) -> None: """ Close a project. """ @@ -148,7 +151,7 @@ async def close_project(project: Project = Depends(dep_project)): response_model=schemas.Project, responses={**responses, 409: {"model": schemas.ErrorMessage, "description": "Could not open project"}}, ) -async def open_project(project: Project = Depends(dep_project)): +async def open_project(project: Project = Depends(dep_project)) -> schemas.Project: """ Open a project. """ @@ -163,7 +166,7 @@ async def open_project(project: Project = Depends(dep_project)): response_model=schemas.Project, responses={**responses, 409: {"model": schemas.ErrorMessage, "description": "Could not load project"}}, ) -async def load_project(path: str = Body(..., embed=True)): +async def load_project(path: str = Body(..., embed=True)) -> schemas.Project: """ Load a project (local server only). """ @@ -180,7 +183,7 @@ async def load_project(path: str = Body(..., embed=True)): @router.get("/{project_id}/notifications") -async def notification(project_id: UUID): +async def notification(project_id: UUID) -> StreamingResponse: """ Receive project notifications about the controller from HTTP stream. """ @@ -211,7 +214,7 @@ async def notification(project_id: UUID): @router.websocket("/{project_id}/notifications/ws") -async def notification_ws(project_id: UUID, websocket: WebSocket): +async def notification_ws(project_id: UUID, websocket: WebSocket) -> None: """ Receive project notifications about the controller from WebSocket. """ @@ -248,7 +251,7 @@ async def export_project( include_images: bool = False, reset_mac_addresses: bool = False, compression: str = "zip", -): +) -> StreamingResponse: """ Export a project as a portable archive. """ @@ -294,7 +297,12 @@ async def export_project( @router.post("/{project_id}/import", status_code=status.HTTP_201_CREATED, response_model=schemas.Project) -async def import_project(project_id: UUID, request: Request, path: Optional[Path] = None, name: Optional[str] = None): +async def import_project( + project_id: UUID, + request: Request, + path: Optional[Path] = None, + name: Optional[str] = None +) -> schemas.Project: """ Import a project from a portable archive. """ @@ -332,7 +340,10 @@ async def import_project(project_id: UUID, request: Request, path: Optional[Path response_model=schemas.Project, responses={**responses, 409: {"model": schemas.ErrorMessage, "description": "Could not duplicate project"}}, ) -async def duplicate_project(project_data: schemas.ProjectDuplicate, project: Project = Depends(dep_project)): +async def duplicate_project( + project_data: schemas.ProjectDuplicate, + project: Project = Depends(dep_project) +) -> schemas.Project: """ Duplicate a project. """ @@ -352,7 +363,7 @@ async def duplicate_project(project_data: schemas.ProjectDuplicate, project: Pro @router.get("/{project_id}/files/{file_path:path}") -async def get_file(file_path: str, project: Project = Depends(dep_project)): +async def get_file(file_path: str, project: Project = Depends(dep_project)) -> FileResponse: """ Return a file from a project. """ @@ -371,7 +382,7 @@ async def get_file(file_path: str, project: Project = Depends(dep_project)): @router.post("/{project_id}/files/{file_path:path}", status_code=status.HTTP_204_NO_CONTENT) -async def write_file(file_path: str, request: Request, project: Project = Depends(dep_project)): +async def write_file(file_path: str, request: Request, project: Project = Depends(dep_project)) -> None: """ Write a file from a project. """ diff --git a/gns3server/api/routes/controller/snapshots.py b/gns3server/api/routes/controller/snapshots.py index 5cf2f067..d410e88a 100644 --- a/gns3server/api/routes/controller/snapshots.py +++ b/gns3server/api/routes/controller/snapshots.py @@ -36,7 +36,7 @@ responses = {404: {"model": schemas.ErrorMessage, "description": "Could not find router = APIRouter(responses=responses) -def dep_project(project_id: UUID): +def dep_project(project_id: UUID) -> Project: """ Dependency to retrieve a project. """ @@ -46,7 +46,10 @@ def dep_project(project_id: UUID): @router.post("", status_code=status.HTTP_201_CREATED, response_model=schemas.Snapshot) -async def create_snapshot(snapshot_data: schemas.SnapshotCreate, project: Project = Depends(dep_project)): +async def create_snapshot( + snapshot_data: schemas.SnapshotCreate, + project: Project = Depends(dep_project) +) -> schemas.Snapshot: """ Create a new snapshot of a project. """ @@ -56,7 +59,7 @@ async def create_snapshot(snapshot_data: schemas.SnapshotCreate, project: Projec @router.get("", response_model=List[schemas.Snapshot], response_model_exclude_unset=True) -def get_snapshots(project: Project = Depends(dep_project)): +def get_snapshots(project: Project = Depends(dep_project)) -> List[schemas.Snapshot]: """ Return all snapshots belonging to a given project. """ @@ -66,7 +69,7 @@ def get_snapshots(project: Project = Depends(dep_project)): @router.delete("/{snapshot_id}", status_code=status.HTTP_204_NO_CONTENT) -async def delete_snapshot(snapshot_id: UUID, project: Project = Depends(dep_project)): +async def delete_snapshot(snapshot_id: UUID, project: Project = Depends(dep_project)) -> None: """ Delete a snapshot. """ @@ -75,7 +78,7 @@ async def delete_snapshot(snapshot_id: UUID, project: Project = Depends(dep_proj @router.post("/{snapshot_id}/restore", status_code=status.HTTP_201_CREATED, response_model=schemas.Project) -async def restore_snapshot(snapshot_id: UUID, project: Project = Depends(dep_project)): +async def restore_snapshot(snapshot_id: UUID, project: Project = Depends(dep_project)) -> schemas.Project: """ Restore a snapshot. """ diff --git a/gns3server/api/routes/controller/symbols.py b/gns3server/api/routes/controller/symbols.py index c4c1b392..127f2c14 100644 --- a/gns3server/api/routes/controller/symbols.py +++ b/gns3server/api/routes/controller/symbols.py @@ -23,6 +23,7 @@ import os from fastapi import APIRouter, Request, status from fastapi.responses import FileResponse +from typing import List from gns3server.controller import Controller from gns3server import schemas @@ -37,7 +38,7 @@ router = APIRouter() @router.get("") -def get_symbols(): +def get_symbols() -> List[str]: controller = Controller.instance() return controller.symbols.list() @@ -46,7 +47,7 @@ def get_symbols(): @router.get( "/{symbol_id:path}/raw", responses={404: {"model": schemas.ErrorMessage, "description": "Could not find symbol"}} ) -async def get_symbol(symbol_id: str): +async def get_symbol(symbol_id: str) -> FileResponse: """ Download a symbol file. """ @@ -63,7 +64,7 @@ async def get_symbol(symbol_id: str): "/{symbol_id:path}/dimensions", responses={404: {"model": schemas.ErrorMessage, "description": "Could not find symbol"}}, ) -async def get_symbol_dimensions(symbol_id: str): +async def get_symbol_dimensions(symbol_id: str) -> dict: """ Get a symbol dimensions. """ @@ -78,7 +79,7 @@ async def get_symbol_dimensions(symbol_id: str): @router.post("/{symbol_id:path}/raw", status_code=status.HTTP_204_NO_CONTENT) -async def upload_symbol(symbol_id: str, request: Request): +async def upload_symbol(symbol_id: str, request: Request) -> None: """ Upload a symbol file. """ @@ -97,7 +98,7 @@ async def upload_symbol(symbol_id: str, request: Request): @router.get("/default_symbols") -def get_default_symbols(): +def get_default_symbols() -> dict: """ Return all default symbols. """ diff --git a/gns3server/api/routes/controller/templates.py b/gns3server/api/routes/controller/templates.py index 0b1f50b2..bb2c5ae9 100644 --- a/gns3server/api/routes/controller/templates.py +++ b/gns3server/api/routes/controller/templates.py @@ -44,7 +44,7 @@ router = APIRouter(responses=responses) async def create_template( template_create: schemas.TemplateCreate, templates_repo: TemplatesRepository = Depends(get_repository(TemplatesRepository)), -) -> dict: +) -> schemas.Template: """ Create a new template. """ @@ -58,7 +58,7 @@ async def get_template( request: Request, response: Response, templates_repo: TemplatesRepository = Depends(get_repository(TemplatesRepository)), -) -> dict: +) -> schemas.Template: """ Return a template. """ @@ -79,7 +79,7 @@ async def update_template( template_id: UUID, template_update: schemas.TemplateUpdate, templates_repo: TemplatesRepository = Depends(get_repository(TemplatesRepository)), -) -> dict: +) -> schemas.Template: """ Update a template. """ @@ -104,7 +104,7 @@ async def delete_template( @router.get("/templates", response_model=List[schemas.Template], response_model_exclude_unset=True) async def get_templates( templates_repo: TemplatesRepository = Depends(get_repository(TemplatesRepository)), -) -> List[dict]: +) -> List[schemas.Template]: """ Return all templates. """ @@ -115,7 +115,7 @@ async def get_templates( @router.post("/templates/{template_id}/duplicate", response_model=schemas.Template, status_code=status.HTTP_201_CREATED) async def duplicate_template( template_id: UUID, templates_repo: TemplatesRepository = Depends(get_repository(TemplatesRepository)) -) -> dict: +) -> schemas.Template: """ Duplicate a template. """ diff --git a/gns3server/compute/base_manager.py b/gns3server/compute/base_manager.py index b578706c..57c7e252 100644 --- a/gns3server/compute/base_manager.py +++ b/gns3server/compute/base_manager.py @@ -20,25 +20,25 @@ import struct import stat import asyncio import aiofiles - import socket import shutil import re - import logging -from gns3server.utils.asyncio import cancellable_wait_run_in_executor -from gns3server.compute.compute_error import ComputeError, ComputeForbiddenError, ComputeNotFoundError - log = logging.getLogger(__name__) -from uuid import UUID, uuid4 +from gns3server.utils.asyncio import cancellable_wait_run_in_executor +from gns3server.compute.compute_error import ComputeError, ComputeForbiddenError, ComputeNotFoundError from gns3server.utils.interfaces import is_interface_up + +from uuid import UUID, uuid4 +from typing import Type from ..config import Config from ..utils.asyncio import wait_run_in_executor from ..utils import force_unix_path from .project_manager import ProjectManager from .port_manager import PortManager +from .base_node import BaseNode from .nios.nio_udp import NIOUDP from .nios.nio_tap import NIOTAP @@ -150,7 +150,7 @@ class BaseManager: BaseManager._instance = None log.debug(f"Module {self.module_name} unloaded") - def get_node(self, node_id, project_id=None): + def get_node(self, node_id, project_id=None) -> Type[BaseNode]: """ Returns a Node instance. diff --git a/gns3server/db/repositories/users.py b/gns3server/db/repositories/users.py index 2a5ce4aa..4b531588 100644 --- a/gns3server/db/repositories/users.py +++ b/gns3server/db/repositories/users.py @@ -59,7 +59,7 @@ class UsersRepository(BaseRepository): async def create_user(self, user: schemas.UserCreate) -> models.User: - hashed_password = self._auth_service.hash_password(user.password) + hashed_password = self._auth_service.hash_password(user.password.get_secret_value()) db_user = models.User( username=user.username, email=user.email, full_name=user.full_name, hashed_password=hashed_password ) @@ -73,7 +73,7 @@ class UsersRepository(BaseRepository): update_values = user_update.dict(exclude_unset=True) password = update_values.pop("password", None) if password: - update_values["hashed_password"] = self._auth_service.hash_password(password=password) + update_values["hashed_password"] = self._auth_service.hash_password(password=password.get_secret_value()) query = update(models.User).where(models.User.user_id == user_id).values(update_values) diff --git a/gns3server/schemas/controller/computes.py b/gns3server/schemas/controller/computes.py index 46972810..f84bb527 100644 --- a/gns3server/schemas/controller/computes.py +++ b/gns3server/schemas/controller/computes.py @@ -54,7 +54,13 @@ class ComputeCreate(ComputeBase): class Config: schema_extra = { - "example": {"name": "My compute", "host": "127.0.0.1", "port": 3080, "user": "user", "password": "password"} + "example": { + "name": "My compute", + "host": "127.0.0.1", + "port": 3080, + "user": "user", + "password": "password" + } } @validator("name", always=True) diff --git a/gns3server/schemas/controller/links.py b/gns3server/schemas/controller/links.py index fbbf50a1..6a375cb9 100644 --- a/gns3server/schemas/controller/links.py +++ b/gns3server/schemas/controller/links.py @@ -30,7 +30,7 @@ class LinkNode(BaseModel): node_id: UUID adapter_number: int port_number: int - label: Optional[Label] + label: Optional[Label] = None class LinkType(str, Enum): diff --git a/gns3server/schemas/controller/users.py b/gns3server/schemas/controller/users.py index 445e1d7b..1073311c 100644 --- a/gns3server/schemas/controller/users.py +++ b/gns3server/schemas/controller/users.py @@ -15,7 +15,7 @@ # along with this program. If not, see . from typing import Optional -from pydantic import EmailStr, BaseModel, Field +from pydantic import EmailStr, BaseModel, Field, SecretStr from uuid import UUID from .base import DateTimeModelMixin @@ -37,7 +37,7 @@ class UserCreate(UserBase): """ username: str = Field(..., min_length=3, regex="[a-zA-Z0-9_-]+$") - password: str = Field(..., min_length=7, max_length=100) + password: SecretStr = Field(..., min_length=7, max_length=100) class UserUpdate(UserBase): @@ -45,7 +45,7 @@ class UserUpdate(UserBase): Properties to update an user. """ - password: Optional[str] = Field(None, min_length=7, max_length=100) + password: Optional[SecretStr] = Field(None, min_length=7, max_length=100) class User(DateTimeModelMixin, UserBase):