mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-08-27 12:30:13 +03:00
fix: propagate 405 when suspending a node without suspend support
Suspending a single VPCS/IOU node returned a fake 204: the controller route swallowed the compute 405 that the node types honestly raise, so callers saw success while the node stayed started. Surface the 405 instead. The best-effort swallow on suspend_all is kept (and now covered by a test) since mixed projects legitimately contain always-running node types.
This commit is contained in:
parent
97e7a79117
commit
c9bc635996
@ -372,14 +372,13 @@ async def suspend_node(node: Node = Depends(dep_node)) -> None:
|
||||
"""
|
||||
Suspend a node.
|
||||
|
||||
Node types without suspend support return a 405 error instead of a
|
||||
silent no-op, so the caller cannot mistake it for a suspended node.
|
||||
|
||||
Required privilege: Node.PowerMgmt
|
||||
"""
|
||||
|
||||
try:
|
||||
await node.suspend()
|
||||
except HTTPException as e:
|
||||
if not e.status_code == status.HTTP_405_METHOD_NOT_ALLOWED:
|
||||
raise
|
||||
|
||||
|
||||
@router.post(
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from fastapi import FastAPI, status
|
||||
from fastapi import FastAPI, HTTPException, status
|
||||
from httpx import AsyncClient
|
||||
|
||||
from unittest.mock import MagicMock
|
||||
@ -300,6 +300,40 @@ class TestNodeRoutes:
|
||||
response = await client.post(app.url_path_for("suspend_node", project_id=project.id, node_id=node.id))
|
||||
assert response.status_code == status.HTTP_204_NO_CONTENT
|
||||
|
||||
async def test_suspend_node_unsupported(
|
||||
self,
|
||||
app: FastAPI,
|
||||
client: AsyncClient,
|
||||
project: Project,
|
||||
compute: Compute,
|
||||
node: Node
|
||||
) -> None:
|
||||
|
||||
# node types without suspend support (e.g. VPCS, IOU) must surface the
|
||||
# compute 405 instead of reporting a fake success
|
||||
compute.post = AsyncioMagicMock(
|
||||
side_effect=HTTPException(status_code=status.HTTP_405_METHOD_NOT_ALLOWED, detail="Suspend is not supported")
|
||||
)
|
||||
response = await client.post(app.url_path_for("suspend_node", project_id=project.id, node_id=node.id))
|
||||
assert response.status_code == status.HTTP_405_METHOD_NOT_ALLOWED
|
||||
|
||||
async def test_suspend_all_nodes_tolerates_unsupported(
|
||||
self,
|
||||
app: FastAPI,
|
||||
client: AsyncClient,
|
||||
project: Project,
|
||||
compute: Compute,
|
||||
node: Node
|
||||
) -> None:
|
||||
|
||||
# suspending all nodes of a mixed project stays best-effort: nodes
|
||||
# without suspend support are skipped without failing the request
|
||||
compute.post = AsyncioMagicMock(
|
||||
side_effect=HTTPException(status_code=status.HTTP_405_METHOD_NOT_ALLOWED, detail="Suspend is not supported")
|
||||
)
|
||||
response = await client.post(app.url_path_for("suspend_all_nodes", project_id=project.id))
|
||||
assert response.status_code == status.HTTP_204_NO_CONTENT
|
||||
|
||||
|
||||
async def test_reload_node(
|
||||
self,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user