mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-11-03 14:01:15 +02:00
fix: dedupe and report automatic template creation from images
install_appliances_from_image relied on the name+version pair check in TemplatesService, so the same appliance reached through a second image (the CSR1000v case) created a second template sharing the name. The auto path now skips when any template with the same name exists, whatever the version, and returns a manifest of created and skipped candidates; POST /images/install replies 200 with that manifest instead of an empty 204, and the image_install MCP tool surfaces it.
This commit is contained in:
7 files changed
+154
-11
No files matched your search
@@ -328,10 +328,54 @@ class TestImageRoutes:
|
||||
with asyncio_patch("gns3server.api.routes.controller.images.get_builtin_disks", return_value=[]) as mock:
|
||||
response = await client.post(app.url_path_for("install_images"))
|
||||
assert mock.called
|
||||
assert response.status_code == status.HTTP_204_NO_CONTENT
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
created = response.json()["created"]
|
||||
assert len(created) == 1
|
||||
assert created[0]["name"] == "Empty VM"
|
||||
assert created[0]["version"] == "100G"
|
||||
|
||||
templates_repo = TemplatesRepository(db_session)
|
||||
templates = await templates_repo.get_templates()
|
||||
assert len(templates) == 1
|
||||
assert templates[0].name == "Empty VM"
|
||||
assert templates[0].version == "100G"
|
||||
assert templates[0].version == "100G"
|
||||
await templates_repo.delete_template(templates[0].template_id)
|
||||
|
||||
async def test_install_all_skips_existing_template_name(
|
||||
self, app: FastAPI,
|
||||
client: AsyncClient,
|
||||
db_session: AsyncSession,
|
||||
controller: Controller
|
||||
) -> None:
|
||||
# two images matching two versions of the same appliance must not
|
||||
# produce two templates with the same name
|
||||
#
|
||||
# earlier tests in this class uploaded the same filenames from different
|
||||
# (function-scoped) images directories; drop those stale rows so the
|
||||
# install route only sees this test's uploads
|
||||
images_repo = ImagesRepository(db_session)
|
||||
for image_name in ("empty30G.qcow2", "empty100G.qcow2"):
|
||||
await images_repo.delete_image(image_name)
|
||||
for image_path in ("tests/resources/empty30G.qcow2", "tests/resources/empty100G.qcow2"):
|
||||
with open(image_path, "rb") as f:
|
||||
image_data = f.read()
|
||||
response = await client.post(
|
||||
app.url_path_for("upload_image", image_path=os.path.basename(image_path)),
|
||||
content=image_data)
|
||||
assert response.status_code == status.HTTP_201_CREATED
|
||||
|
||||
controller.appliance_manager.load_appliances() # make sure appliances are loaded
|
||||
with asyncio_patch("gns3server.api.routes.controller.images.get_builtin_disks", return_value=[]):
|
||||
response = await client.post(app.url_path_for("install_images"))
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
|
||||
manifest = response.json()
|
||||
assert len(manifest["created"]) == 1
|
||||
assert manifest["created"][0]["name"] == "Empty VM"
|
||||
assert any("already exists" in skipped["reason"] for skipped in manifest["skipped"])
|
||||
|
||||
templates_repo = TemplatesRepository(db_session)
|
||||
templates = await templates_repo.get_templates()
|
||||
assert len(templates) == 1
|
||||
assert templates[0].name == "Empty VM"
|
||||
await templates_repo.delete_template(templates[0].template_id)
|
||||
Reference in new issue
Block a user