diff --git a/docs/general.rst b/docs/general.rst index 916d5399..23bf7c80 100644 --- a/docs/general.rst +++ b/docs/general.rst @@ -265,9 +265,9 @@ The available notification are: * link.created * link.updated * link.deleted - * item.created - * item.updated - * item.deleted + * shape.created + * shape.updated + * shape.deleted * log.error * log.warning * log.info diff --git a/docs/glossary.rst b/docs/glossary.rst index ec00ed2e..35529d13 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -6,10 +6,10 @@ Node A Virtual Machine (Dynamips, IOU, Qemu, VPCS...), a cloud, a builtin device (switch, hub...) -Item +Shape ----- -Item are visual element not used by the network emulation. Like +Shape are visual element not used by the network emulation. Like text, images, rectangle... They are pure SVG elements. Adapter diff --git a/gns3server/controller/project.py b/gns3server/controller/project.py index a9809af0..388a0418 100644 --- a/gns3server/controller/project.py +++ b/gns3server/controller/project.py @@ -24,7 +24,7 @@ import shutil from uuid import UUID, uuid4 from .node import Node -from .item import Item +from .shape import Shape from .topology import project_to_topology, load_topology from .udp_link import UDPLink from ..config import Config @@ -77,7 +77,7 @@ class Project: self._allocated_node_names = set() self._nodes = {} self._links = {} - self._items = {} + self._shapes = {} # Create the project on demand on the compute node self._project_created_on_compute = set() @@ -266,42 +266,42 @@ class Project: return self._nodes @property - def items(self): + def shapes(self): """ - :returns: Dictionary of the items + :returns: Dictionary of the shapes """ - return self._items + return self._shapes @asyncio.coroutine - def add_item(self, item_id=None, **kwargs): + def add_shape(self, shape_id=None, **kwargs): """ - Create an item or return an existing item + Create an shape or return an existing shape - :param kwargs: See the documentation of item + :param kwargs: See the documentation of shape """ - if item_id not in self._items: - item = Item(self, item_id=item_id, **kwargs) - self._items[item.id] = item - self.controller.notification.emit("item.created", item.__json__()) + if shape_id not in self._shapes: + shape = Shape(self, shape_id=shape_id, **kwargs) + self._shapes[shape.id] = shape + self.controller.notification.emit("shape.created", shape.__json__()) self.dump() - return item - return self._items[item_id] + return shape + return self._shapes[shape_id] - def get_item(self, item_id): + def get_shape(self, shape_id): """ - Return the Item or raise a 404 if the item is unknown + Return the Shape or raise a 404 if the shape is unknown """ try: - return self._items[item_id] + return self._shapes[shape_id] except KeyError: - raise aiohttp.web.HTTPNotFound(text="Item ID {} doesn't exist".format(item_id)) + raise aiohttp.web.HTTPNotFound(text="Shape ID {} doesn't exist".format(shape_id)) @asyncio.coroutine - def delete_item(self, item_id): - item = self.get_item(item_id) - del self._items[item.id] + def delete_shape(self, shape_id): + shape = self.get_shape(shape_id) + del self._shapes[shape.id] self.dump() - self.controller.notification.emit("item.deleted", item.__json__()) + self.controller.notification.emit("shape.deleted", shape.__json__()) @asyncio.coroutine def add_link(self, link_id=None): @@ -397,8 +397,8 @@ class Project: node = self.get_node(node_link["node_id"]) yield from link.add_node(node, node_link["adapter_number"], node_link["port_number"]) - for item_data in topology.get("items", []): - item = yield from self.add_item(**item_data) + for shape_data in topology.get("shapes", []): + shape = yield from self.add_shape(**shape_data) self._status = "opened" def dump(self): diff --git a/gns3server/controller/item.py b/gns3server/controller/shape.py similarity index 84% rename from gns3server/controller/item.py rename to gns3server/controller/shape.py index 4dc50e5c..26cb49c0 100644 --- a/gns3server/controller/item.py +++ b/gns3server/controller/shape.py @@ -19,18 +19,18 @@ import asyncio import uuid -class Item: +class Shape: """ - Item are visual element not used by the network emulation. Like + Shape are visual element not used by the network emulation. Like text, images, rectangle... They are pure SVG elements. """ - def __init__(self, project, item_id=None, svg=None, x=0, y=0, z=0): + def __init__(self, project, shape_id=None, svg=None, x=0, y=0, z=0): self.svg = "" self._project = project - if item_id is None: + if shape_id is None: self._id = str(uuid.uuid4()) else: - self._id = item_id + self._id = shape_id self._x = x self._y = y self._z = z @@ -83,7 +83,7 @@ class Item: for prop in kwargs: if getattr(self, prop) != kwargs[prop]: setattr(self, prop, kwargs[prop]) - self._project.controller.notification.emit("item.updated", self.__json__()) + self._project.controller.notification.emit("shape.updated", self.__json__()) self._project.dump() def __json__(self, topology_dump=False): @@ -92,20 +92,20 @@ class Item: """ if topology_dump: return { - "item_id": self._id, + "shape_id": self._id, "x": self._x, "y": self._y, "z": self._z, } return { "project_id": self._project.id, - "item_id": self._id, + "shape_id": self._id, "x": self._x, "y": self._y, "z": self._z, } def __repr__(self): - return "".format(self._id) + return "".format(self._id) diff --git a/gns3server/controller/topology.py b/gns3server/controller/topology.py index 74525a74..42e7d880 100644 --- a/gns3server/controller/topology.py +++ b/gns3server/controller/topology.py @@ -34,7 +34,7 @@ def project_to_topology(project): "nodes": [], "links": [], "computes": [], - "items": [] + "shapes": [] }, "type": "topology", "revision": GNS3_FILE_FORMAT_REVISION, @@ -47,8 +47,8 @@ def project_to_topology(project): data["topology"]["nodes"].append(node.__json__(topology_dump=True)) for link in project.links.values(): data["topology"]["links"].append(link.__json__(topology_dump=True)) - for item in project.items.values(): - data["topology"]["items"].append(item.__json__(topology_dump=True)) + for shape in project.shapes.values(): + data["topology"]["shapes"].append(shape.__json__(topology_dump=True)) for compute in computes: if hasattr(compute, "__json__"): data["topology"]["computes"].append(compute.__json__(topology_dump=True)) diff --git a/gns3server/handlers/api/controller/__init__.py b/gns3server/handlers/api/controller/__init__.py index 768e7583..3bc15ced 100644 --- a/gns3server/handlers/api/controller/__init__.py +++ b/gns3server/handlers/api/controller/__init__.py @@ -20,4 +20,4 @@ from .project_handler import ProjectHandler from .node_handler import NodeHandler from .link_handler import LinkHandler from .server_handler import ServerHandler -from .item_handler import ItemHandler +from .shape_handler import ShapeHandler diff --git a/gns3server/handlers/api/controller/item_handler.py b/gns3server/handlers/api/controller/shape_handler.py similarity index 62% rename from gns3server/handlers/api/controller/item_handler.py rename to gns3server/handlers/api/controller/shape_handler.py index 815ea8a0..19bfa19d 100644 --- a/gns3server/handlers/api/controller/item_handler.py +++ b/gns3server/handlers/api/controller/shape_handler.py @@ -20,88 +20,88 @@ import aiohttp from gns3server.web.route import Route from gns3server.controller import Controller -from gns3server.schemas.item import ( - ITEM_OBJECT_SCHEMA, +from gns3server.schemas.shape import ( + SHAPE_OBJECT_SCHEMA, ) -class ItemHandler: +class ShapeHandler: """ - API entry point for Item + API entry point for Shape """ @Route.get( - r"/projects/{project_id}/items", + r"/projects/{project_id}/shapes", parameters={ "project_id": "Project UUID" }, status_codes={ - 200: "List of items returned", + 200: "List of shapes returned", }, - description="List items of a project") - def list_items(request, response): + description="List shapes of a project") + def list_shapes(request, response): controller = Controller.instance() project = controller.get_project(request.match_info["project_id"]) - response.json([v for v in project.items.values()]) + response.json([v for v in project.shapes.values()]) @Route.post( - r"/projects/{project_id}/items", + r"/projects/{project_id}/shapes", parameters={ "project_id": "Project UUID" }, status_codes={ - 201: "Item created", + 201: "Shape created", 400: "Invalid request" }, - description="Create a new item instance", - input=ITEM_OBJECT_SCHEMA, - output=ITEM_OBJECT_SCHEMA) + description="Create a new shape instance", + input=SHAPE_OBJECT_SCHEMA, + output=SHAPE_OBJECT_SCHEMA) def create(request, response): controller = Controller.instance() project = controller.get_project(request.match_info["project_id"]) - item = yield from project.add_item(**request.json) + shape = yield from project.add_shape(**request.json) response.set_status(201) - response.json(item) + response.json(shape) @Route.put( - r"/projects/{project_id}/items/{item_id}", + r"/projects/{project_id}/shapes/{shape_id}", parameters={ "project_id": "Project UUID", - "item_id": "Item UUID" + "shape_id": "Shape UUID" }, status_codes={ - 201: "Item updated", + 201: "Shape updated", 400: "Invalid request" }, - description="Create a new item instance", - input=ITEM_OBJECT_SCHEMA, - output=ITEM_OBJECT_SCHEMA) + description="Create a new shape instance", + input=SHAPE_OBJECT_SCHEMA, + output=SHAPE_OBJECT_SCHEMA) def update(request, response): controller = Controller.instance() project = controller.get_project(request.match_info["project_id"]) - item = project.get_item(request.match_info["item_id"]) - yield from item.update(**request.json) + shape = project.get_shape(request.match_info["shape_id"]) + yield from shape.update(**request.json) response.set_status(201) - response.json(item) + response.json(shape) @Route.delete( - r"/projects/{project_id}/items/{item_id}", + r"/projects/{project_id}/shapes/{shape_id}", parameters={ "project_id": "Project UUID", - "item_id": "Item UUID" + "shape_id": "Shape UUID" }, status_codes={ - 204: "Item deleted", + 204: "Shape deleted", 400: "Invalid request" }, - description="Delete a item instance") + description="Delete a shape instance") def delete(request, response): controller = Controller.instance() project = controller.get_project(request.match_info["project_id"]) - yield from project.delete_item(request.match_info["item_id"]) + yield from project.delete_shape(request.match_info["shape_id"]) response.set_status(204) diff --git a/gns3server/schemas/item.py b/gns3server/schemas/shape.py similarity index 90% rename from gns3server/schemas/item.py rename to gns3server/schemas/shape.py index 5e22b2d4..ae955343 100644 --- a/gns3server/schemas/item.py +++ b/gns3server/schemas/shape.py @@ -16,13 +16,13 @@ # along with this program. If not, see . -ITEM_OBJECT_SCHEMA = { +SHAPE_OBJECT_SCHEMA = { "$schema": "http://json-schema.org/draft-04/schema#", - "description": "An item object", + "description": "An shape object", "type": "object", "properties": { - "item_id": { - "description": "Link UUID", + "shape_id": { + "description": "Shape UUID", "type": "string", "minLength": 36, "maxLength": 36, @@ -48,7 +48,7 @@ ITEM_OBJECT_SCHEMA = { "type": "integer" }, "svg": { - "description": "SVG content of the item", + "description": "SVG content of the shape", "type": "string", "pattern": "^<.+>$" } diff --git a/tests/controller/test_project.py b/tests/controller/test_project.py index cc094291..9ba87647 100644 --- a/tests/controller/test_project.py +++ b/tests/controller/test_project.py @@ -213,30 +213,30 @@ def test_deleteLink(async_run, project, controller): assert len(project._links) == 0 -def test_addItem(async_run, project, controller): +def test_addShape(async_run, project, controller): controller.notification.emit = MagicMock() - item = async_run(project.add_item(None, svg="")) - assert len(project._items) == 1 - controller.notification.emit.assert_any_call("item.created", item.__json__()) + shape = async_run(project.add_shape(None, svg="")) + assert len(project._shapes) == 1 + controller.notification.emit.assert_any_call("shape.created", shape.__json__()) -def test_getItem(async_run, project): - item = async_run(project.add_item(None)) - assert project.get_item(item.id) == item +def test_getShape(async_run, project): + shape = async_run(project.add_shape(None)) + assert project.get_shape(shape.id) == shape with pytest.raises(aiohttp.web_exceptions.HTTPNotFound): - project.get_item("test") + project.get_shape("test") -def test_deleteItem(async_run, project, controller): - assert len(project._items) == 0 - item = async_run(project.add_item()) - assert len(project._items) == 1 +def test_deleteShape(async_run, project, controller): + assert len(project._shapes) == 0 + shape = async_run(project.add_shape()) + assert len(project._shapes) == 1 controller._notification = MagicMock() - async_run(project.delete_item(item.id)) - controller.notification.emit.assert_any_call("item.deleted", item.__json__()) - assert len(project._items) == 0 + async_run(project.delete_shape(shape.id)) + controller.notification.emit.assert_any_call("shape.deleted", shape.__json__()) + assert len(project._shapes) == 0 def test_delete(async_run, project, controller): diff --git a/tests/controller/test_item.py b/tests/controller/test_shape.py similarity index 71% rename from tests/controller/test_item.py rename to tests/controller/test_shape.py index 6202da24..7e10ec80 100644 --- a/tests/controller/test_item.py +++ b/tests/controller/test_shape.py @@ -22,7 +22,7 @@ import uuid from tests.utils import AsyncioMagicMock -from gns3server.controller.item import Item +from gns3server.controller.shape import Shape from gns3server.controller.project import Project @@ -32,43 +32,43 @@ def project(controller, async_run): @pytest.fixture -def item(project): - return Item(project, None, svg="") +def shape(project): + return Shape(project, None, svg="") def test_init_without_uuid(project): - item = Item(project, None, svg="") - assert item.id is not None + shape = Shape(project, None, svg="") + assert shape.id is not None def test_init_with_uuid(project): id = str(uuid.uuid4()) - item = Item(project, id, svg="") - assert item.id == id + shape = Shape(project, id, svg="") + assert shape.id == id def test_json(project): - i = Item(project, None, svg="") + i = Shape(project, None, svg="") assert i.__json__() == { - "item_id": i.id, + "shape_id": i.id, "project_id": project.id, "x": i.x, "y": i.y, "z": i.z } assert i.__json__(topology_dump=True) == { - "item_id": i.id, + "shape_id": i.id, "x": i.x, "y": i.y, "z": i.z } -def test_update(item, project, async_run, controller): +def test_update(shape, project, async_run, controller): controller._notification = AsyncioMagicMock() project.dump = MagicMock() - async_run(item.update(x=42)) - assert item.x == 42 - controller._notification.emit.assert_called_with("item.updated", item.__json__()) + async_run(shape.update(x=42)) + assert shape.x == 42 + controller._notification.emit.assert_called_with("shape.updated", shape.__json__()) assert project.dump.called diff --git a/tests/controller/test_topology.py b/tests/controller/test_topology.py index 886cdfdc..431f058a 100644 --- a/tests/controller/test_topology.py +++ b/tests/controller/test_topology.py @@ -38,7 +38,7 @@ def test_project_to_topology_empty(tmpdir): "nodes": [], "links": [], "computes": [], - "items": [] + "shapes": [] }, "type": "topology", "version": __version__ @@ -58,14 +58,14 @@ def test_basic_topology(tmpdir, async_run, controller): async_run(link.add_node(node1, 0, 0)) async_run(link.add_node(node2, 0, 0)) - item = async_run(project.add_item(svg="")) + shape = async_run(project.add_shape(svg="")) topo = project_to_topology(project) assert len(topo["topology"]["nodes"]) == 2 assert node1.__json__(topology_dump=True) in topo["topology"]["nodes"] assert topo["topology"]["links"][0] == link.__json__(topology_dump=True) assert topo["topology"]["computes"][0] == compute.__json__(topology_dump=True) - assert topo["topology"]["items"][0] == item.__json__(topology_dump=True) + assert topo["topology"]["shapes"][0] == shape.__json__(topology_dump=True) def test_load_topology(tmpdir): @@ -77,7 +77,7 @@ def test_load_topology(tmpdir): "nodes": [], "links": [], "computes": [], - "items": [] + "shapes": [] }, "type": "topology", "version": __version__} diff --git a/tests/handlers/api/controller/test_item.py b/tests/handlers/api/controller/test_shape.py similarity index 65% rename from tests/handlers/api/controller/test_item.py rename to tests/handlers/api/controller/test_shape.py index 8b728cf8..4aee6dcd 100644 --- a/tests/handlers/api/controller/test_item.py +++ b/tests/handlers/api/controller/test_shape.py @@ -30,7 +30,7 @@ from tests.utils import asyncio_patch from gns3server.handlers.api.controller.project_handler import ProjectHandler from gns3server.controller import Controller -from gns3server.controller.item import Item +from gns3server.controller.shape import Shape @@ -39,49 +39,49 @@ def project(http_controller, async_run): return async_run(Controller.instance().add_project()) -def test_create_item(http_controller, tmpdir, project, async_run): +def test_create_shape(http_controller, tmpdir, project, async_run): - response = http_controller.post("/projects/{}/items".format(project.id), { + response = http_controller.post("/projects/{}/shapes".format(project.id), { "svg": '', "x": 10, "y": 20, "z": 0 }, example=True) assert response.status == 201 - assert response.json["item_id"] is not None + assert response.json["shape_id"] is not None -def test_update_item(http_controller, tmpdir, project, async_run): +def test_update_shape(http_controller, tmpdir, project, async_run): - response = http_controller.post("/projects/{}/items".format(project.id), { + response = http_controller.post("/projects/{}/shapes".format(project.id), { "svg": '', "x": 10, "y": 20, "z": 0 },) - response = http_controller.put("/projects/{}/items/{}".format(project.id, response.json["item_id"]), { + response = http_controller.put("/projects/{}/shapes/{}".format(project.id, response.json["shape_id"]), { "x": 42, }, example=True) assert response.status == 201 assert response.json["x"] == 42 -def test_list_item(http_controller, tmpdir, project, async_run): - response = http_controller.post("/projects/{}/items".format(project.id), { +def test_list_shape(http_controller, tmpdir, project, async_run): + response = http_controller.post("/projects/{}/shapes".format(project.id), { "svg": '', "x": 10, "y": 20, "z": 0 }, example=False) - response = http_controller.get("/projects/{}/items".format(project.id), example=True) + response = http_controller.get("/projects/{}/shapes".format(project.id), example=True) assert response.status == 200 assert len(response.json) == 1 -def test_delete_item(http_controller, tmpdir, project, async_run): +def test_delete_shape(http_controller, tmpdir, project, async_run): - item = Item(project) - project._items = {item.id: item} - response = http_controller.delete("/projects/{}/items/{}".format(project.id, item.id), example=True) + shape = Shape(project) + project._shapes = {shape.id: shape} + response = http_controller.delete("/projects/{}/shapes/{}".format(project.id, shape.id), example=True) assert response.status == 204 - assert item.id not in project._items + assert shape.id not in project._shapes