From 01511f3aef3736d83ca4d6cd0ccb62eefc1f5aa8 Mon Sep 17 00:00:00 2001 From: Volobue Date: Mon, 25 May 2026 21:37:04 +0300 Subject: [PATCH] added endpoint to v3 branch --- .../controller_get_templateidbaseconfig.txt | 17 ---- .../controller_get_templatesbaseconfigs.txt | 44 --------- .../controller_put_templateidbaseconfig.txt | 17 ---- .../template/templatesbaseconfigs.rst | 38 -------- .../templatestemplateidbaseconfigfilename.rst | 90 ------------------ tests/api/routes/controller/test_templates.py | 93 ++++++++++++++++--- 6 files changed, 79 insertions(+), 220 deletions(-) delete mode 100644 docs/api/examples/controller_get_templateidbaseconfig.txt delete mode 100644 docs/api/examples/controller_get_templatesbaseconfigs.txt delete mode 100644 docs/api/examples/controller_put_templateidbaseconfig.txt delete mode 100644 docs/api/v2/controller/template/templatesbaseconfigs.rst delete mode 100644 docs/api/v2/controller/template/templatestemplateidbaseconfigfilename.rst diff --git a/docs/api/examples/controller_get_templateidbaseconfig.txt b/docs/api/examples/controller_get_templateidbaseconfig.txt deleted file mode 100644 index 9e3d9c25c..000000000 --- a/docs/api/examples/controller_get_templateidbaseconfig.txt +++ /dev/null @@ -1,17 +0,0 @@ -curl -i -X 'http://localhost:3080/v2/templates/19021f99-e36f-394d-b4a1-8aaa902ab9cc/base-config/vpcs_base_config.txt' - -GET /v2/templates/19021f99-e36f-394d-b4a1-8aaa902ab9cc/base-config/vpcs_base_config.txt HTTP/1.1 - -HTTP/1.1 200 OK -Connection: close -X-Route: /v2/templates/{template_id}/base-config/{filename} -Server: Python/3.14 GNS3/2.2.60.dev1+713dbb7f -Content-Type: application/json -Content-Length: 144 -Date: Mon, 18 May 2026 18:34:10 GMT - -{ - "content": "# test config\n\ndhcp\n", - "filename": "vpcs_base_config.txt", - "template_id": "19021f99-e36f-394d-b4a1-8aaa902ab9cc" -} \ No newline at end of file diff --git a/docs/api/examples/controller_get_templatesbaseconfigs.txt b/docs/api/examples/controller_get_templatesbaseconfigs.txt deleted file mode 100644 index 263cbfa1f..000000000 --- a/docs/api/examples/controller_get_templatesbaseconfigs.txt +++ /dev/null @@ -1,44 +0,0 @@ -curl -i -X 'http://localhost:3080/v2/templates/base-configs' - -GET /v2/templates/base-configs HTTP/1.1 - -HTTP/1.1 200 OK -Connection: close -X-Route: /v2/templates/base-configs -Server: Python/3.14 GNS3/2.2.60.dev1+713dbb7f -Content-Type: application/json -Content-Length: 576 -Date: Mon, 18 May 2026 18:28:53 GMT - -[ - { - "filename": "config1.txt" - }, - { - "filename": "config2.txt" - }, - { - "filename": "ios_base_startup-config.txt" - }, - { - "filename": "ios_etherswitch_startup-config.txt" - }, - { - "filename": "iou_l2_base_startup-config.txt" - }, - { - "filename": "iou_l3_base_startup-config.txt" - }, - { - "filename": "test_config.txt" - }, - { - "filename": "update_test.txt" - }, - { - "filename": "vpcs_base_config.txt" - }, - { - "filename": "vpcs_base_config2.txt" - } -] \ No newline at end of file diff --git a/docs/api/examples/controller_put_templateidbaseconfig.txt b/docs/api/examples/controller_put_templateidbaseconfig.txt deleted file mode 100644 index c70e315b8..000000000 --- a/docs/api/examples/controller_put_templateidbaseconfig.txt +++ /dev/null @@ -1,17 +0,0 @@ -curl -i -X 'http://localhost:3080/v2/templates/19021f99-e36f-394d-b4a1-8aaa902ab9cc/base-config/vpcs_base_config.txt' - -PUT /v2/templates/19021f99-e36f-394d-b4a1-8aaa902ab9cc/base-config/vpcs_base_config.txt HTTP/1.1 - -HTTP/1.1 200 OK -Connection: close -X-Route: /v2/templates/{template_id}/base-config/{filename} -Server: Python/3.14 GNS3/2.2.60.dev1+713dbb7f -Content-Type: application/json -Content-Length: 144 -Date: Mon, 18 May 2026 18:37:57 GMT - -{ - "content": "# test config\n\ndhcp\n", - "filename": "vpcs_base_config.txt", - "template_id": "19021f99-e36f-394d-b4a1-8aaa902ab9cc" -} \ No newline at end of file diff --git a/docs/api/v2/controller/template/templatesbaseconfigs.rst b/docs/api/v2/controller/template/templatesbaseconfigs.rst deleted file mode 100644 index dc4de3e8c..000000000 --- a/docs/api/v2/controller/template/templatesbaseconfigs.rst +++ /dev/null @@ -1,38 +0,0 @@ -GET /v2/templates/base-configs ------------------------------------------------------------------------------------------------------------------------------------------- - -.. contents:: - -GET /v2/templates/base-configs -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -List all available base configuration files - -Response status codes -********************** -- **200**: List of base configuration files returned - -Output -******* - -.. raw:: html - - - - - - - - - - - - - - -
NameTypeDescription
filenamestringName of the base configuration file
- -Sample session -*************** - -.. literalinclude:: ../../../examples/controller_get_templatesbaseconfigs.txt \ No newline at end of file diff --git a/docs/api/v2/controller/template/templatestemplateidbaseconfigfilename.rst b/docs/api/v2/controller/template/templatestemplateidbaseconfigfilename.rst deleted file mode 100644 index 98b356270..000000000 --- a/docs/api/v2/controller/template/templatestemplateidbaseconfigfilename.rst +++ /dev/null @@ -1,90 +0,0 @@ -/v2/templates/{template_id}/base-config/{filename} ------------------------------------------------------------------------------------------------------------------------------------------- - -.. contents:: - -GET /v2/templates/**{template_id}**/base-configs/**{filename}** -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -List all available base configuration files - -Response status codes -********************** -- **200**: List of base configuration files returned - -Output -******* - -.. raw:: html - - - - - - - - - - - - - - -
NameTypeDescription
filenamestringName of the base configuration file
- -Sample session -*************** - -.. literalinclude:: ../../../examples/controller_get_templateidbaseconfig.txt - - -PUT /v2/templates/**{template_id}**/base-config/**{filename}** -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Update base configuration file content - -Response status codes -********************** -- **200**: File updated -- **404**: File not found - -Input -******* - -.. raw:: html - - - - - - - - - - - -
NameMandatoryTypeDescription
contentstringNew file content
- -Output -******* - -.. raw:: html - - - - - - - - - - - - - -
NameMandatoryTypeDescription
template_idstringTemplate UUID
filenamestringBase configuration filename
contentstringUpdated file content
- -Sample session -*************** - -.. literalinclude:: ../../../examples/controller_put_templateidbaseconfig.txt \ No newline at end of file diff --git a/tests/api/routes/controller/test_templates.py b/tests/api/routes/controller/test_templates.py index 0c61b3ab0..e26c394bf 100644 --- a/tests/api/routes/controller/test_templates.py +++ b/tests/api/routes/controller/test_templates.py @@ -33,6 +33,8 @@ from gns3server.db.repositories.templates import TemplatesRepository from gns3server.controller import Controller from gns3server.controller import Config from gns3server.services.templates import BUILTIN_TEMPLATES +from gns3server.api.routes.controller.dependencies.authentication import get_current_active_user +from gns3server import schemas pytestmark = pytest.mark.asyncio @@ -241,6 +243,15 @@ class TestTemplateRoutes: async def test_get_base_config(self, app: FastAPI, client: AsyncClient): + async def mock_get_current_active_user(): + return schemas.User( + username="admin", + user_id=uuid.uuid4(), + is_superadmin=True, + is_active=True + ) + app.dependency_overrides[get_current_active_user] = mock_get_current_active_user + create_resp = await client.post(app.url_path_for("create_template"), json={ "name": "TEST", "compute_id": "local", @@ -250,7 +261,6 @@ class TestTemplateRoutes: assert create_resp.status_code == 201 template_id = create_resp.json()["template_id"] - #создаём файл перед чтением await client.put( app.url_path_for("update_base_config", template_id=template_id, filename="test.txt"), json={"content": "hello"} @@ -268,20 +278,28 @@ class TestTemplateRoutes: assert response.json()["content"] == "hello" async def test_update_base_config(self, app: FastAPI, client: AsyncClient): - template_id = str(uuid.uuid4()) - filename = "test.txt" - await client.post(app.url_path_for("create_template"), json={ - "template_id": template_id, - "name": "TEST", + async def mock_get_current_active_user(): + return schemas.User( + username="admin", + user_id=uuid.uuid4(), + is_superadmin=True, + is_active=True + ) + app.dependency_overrides[get_current_active_user] = mock_get_current_active_user + + template_name = f"TEST_UPDATE_{uuid.uuid4().hex[:8]}" + create_resp = await client.post(app.url_path_for("create_template"), json={ + "name": template_name, "compute_id": "local", "template_type": "vpcs" }) + assert create_resp.status_code == 201 + template_id = create_resp.json()["template_id"] payload = {"content": "hello world"} - response = await client.put( - app.url_path_for("update_base_config", template_id=template_id, filename=filename), + app.url_path_for("update_base_config", template_id=template_id, filename="test.txt"), json=payload ) @@ -289,18 +307,27 @@ class TestTemplateRoutes: assert response.json()["content"] == "hello world" async def test_update_base_config_missing_content(self, app: FastAPI, client: AsyncClient): - template_id = str(uuid.uuid4()) - filename = "test.txt" - await client.post(app.url_path_for("create_template"), json={ - "template_id": template_id, - "name": "TEST", + async def mock_get_current_active_user(): + return schemas.User( + username="admin", + user_id=uuid.uuid4(), + is_superadmin=True, + is_active=True + ) + app.dependency_overrides[get_current_active_user] = mock_get_current_active_user + + template_name = f"TEST_MISSING_{uuid.uuid4().hex[:8]}" + create_resp = await client.post(app.url_path_for("create_template"), json={ + "name": template_name, "compute_id": "local", "template_type": "vpcs" }) + assert create_resp.status_code == 201 + template_id = create_resp.json()["template_id"] response = await client.put( - app.url_path_for("update_base_config", template_id=template_id, filename=filename), + app.url_path_for("update_base_config", template_id=template_id, filename="test.txt"), json={} ) @@ -313,6 +340,44 @@ class TestTemplateRoutes: assert response.status_code == 404 + async def test_list_base_configs(self, app: FastAPI, client: AsyncClient): + + async def mock_get_current_active_user(): + return schemas.User( + username="admin", + user_id=uuid.uuid4(), + is_superadmin=True, + is_active=True + ) + app.dependency_overrides[get_current_active_user] = mock_get_current_active_user + + template_name = f"TEST_LIST_{uuid.uuid4().hex[:8]}" + create_resp = await client.post(app.url_path_for("create_template"), json={ + "name": template_name, + "compute_id": "local", + "template_type": "vpcs" + }) + assert create_resp.status_code == 201 + template_id = create_resp.json()["template_id"] + + await client.put( + app.url_path_for("update_base_config", template_id=template_id, filename="config1.txt"), + json={"content": "file1"} + ) + await client.put( + app.url_path_for("update_base_config", template_id=template_id, filename="config2.txt"), + json={"content": "file2"} + ) + + response = await client.get( + app.url_path_for("list_base_configs", template_id=template_id) + ) + + assert response.status_code == 200 + filenames = [item["filename"] for item in response.json()] + assert "config1.txt" in filenames + assert "config2.txt" in filenames + class TestDuplicateTemplates: