mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-08-27 20:40:13 +03:00
Use lists for tags instead of dicts
This commit is contained in:
parent
66f32cecf2
commit
bdcb6445c7
@ -137,7 +137,7 @@ async def create_node(node_data: schemas.NodeCreate, project: Project = Depends(
|
||||
)
|
||||
def get_nodes(
|
||||
project: Project = Depends(dep_project),
|
||||
tags: Optional[List[str]] = Query(None, description="Filter by tags (e.g., tags=vendor:cisco&tags=model:7200)")
|
||||
tags: Optional[List[str]] = Query(None, description="Filter by tags (e.g. tags=vendor:cisco&tags=model:7200)")
|
||||
) -> List[schemas.Node]:
|
||||
"""
|
||||
Return all nodes belonging to a given project.
|
||||
@ -145,7 +145,7 @@ def get_nodes(
|
||||
Required privilege: Node.Audit
|
||||
|
||||
Query Parameters:
|
||||
- tags: Filter by tags in format "key:value". Multiple tags are ANDed together.
|
||||
- tags: Filter by tags. Multiple tags are ANDed together.
|
||||
Example: ?tags=vendor:cisco&tags=model:7200
|
||||
"""
|
||||
|
||||
@ -155,29 +155,19 @@ def get_nodes(
|
||||
else:
|
||||
nodes = [v.asdict() for v in project.nodes.values()]
|
||||
|
||||
# Filter by tags if provided
|
||||
# Filter by tags if provided (all filter tags have to match the node tags)
|
||||
if tags:
|
||||
filtered_nodes = []
|
||||
for node in nodes:
|
||||
node_dict = node.asdict() if hasattr(node, 'asdict') else node
|
||||
node_tags = node_dict.get("tags") or {}
|
||||
# Check if all tag filters match
|
||||
node_tags = node.get("tags") or []
|
||||
match = True
|
||||
for tag_filter in tags:
|
||||
if ":" in tag_filter:
|
||||
key, value = tag_filter.split(":", 1)
|
||||
if node_tags.get(key) != value:
|
||||
match = False
|
||||
break
|
||||
else:
|
||||
# Check if key exists
|
||||
if tag_filter not in node_tags:
|
||||
match = False
|
||||
break
|
||||
if tag_filter not in node_tags:
|
||||
match = False
|
||||
break
|
||||
if match:
|
||||
filtered_nodes.append(node)
|
||||
nodes = filtered_nodes
|
||||
|
||||
return filtered_nodes
|
||||
return nodes
|
||||
|
||||
|
||||
|
||||
@ -170,7 +170,7 @@ async def get_templates(
|
||||
templates_repo: TemplatesRepository = Depends(get_repository(TemplatesRepository)),
|
||||
current_user: schemas.User = Depends(get_current_active_user),
|
||||
rbac_repo: RbacRepository = Depends(get_repository(RbacRepository)),
|
||||
tags: Optional[List[str]] = Query(None, description="Filter by tags (e.g., tags=vendor:cisco&tags=model:7200)")
|
||||
tags: Optional[List[str]] = Query(None, description="Filter by tags (e.g. tags=vendor:cisco&tags=model:7200)")
|
||||
) -> List[schemas.Template]:
|
||||
"""
|
||||
Return all templates.
|
||||
@ -178,30 +178,22 @@ async def get_templates(
|
||||
Required privilege: Template.Audit
|
||||
|
||||
Query Parameters:
|
||||
- tags: Filter by tags in format "key:value". Multiple tags are ANDed together.
|
||||
- tags: Filter by tags. Multiple tags are ANDed together.
|
||||
Example: ?tags=vendor:cisco&tags=model:7200
|
||||
"""
|
||||
|
||||
templates = await TemplatesService(templates_repo).get_templates()
|
||||
|
||||
# Filter by tags if provided
|
||||
# Filter by tags if provided (all filter tags have to match the node tags)
|
||||
if tags:
|
||||
filtered_templates = []
|
||||
for template in templates:
|
||||
template_tags = template.get("tags") or {}
|
||||
# Check if all tag filters match
|
||||
template_tags = template.get("tags") or []
|
||||
match = True
|
||||
for tag_filter in tags:
|
||||
if ":" in tag_filter:
|
||||
key, value = tag_filter.split(":", 1)
|
||||
if template_tags.get(key) != value:
|
||||
match = False
|
||||
break
|
||||
else:
|
||||
# Check if key exists
|
||||
if tag_filter not in template_tags:
|
||||
match = False
|
||||
break
|
||||
if tag_filter not in template_tags:
|
||||
match = False
|
||||
break
|
||||
if match:
|
||||
filtered_templates.append(template)
|
||||
templates = filtered_templates
|
||||
|
||||
@ -97,7 +97,7 @@ class Node:
|
||||
self._y = 0
|
||||
self._z = 1 # default z value is 1
|
||||
self._locked = False
|
||||
self._tags = {}
|
||||
self._tags = []
|
||||
self._ports = None
|
||||
self._symbol = None
|
||||
self._custom_adapters = []
|
||||
@ -225,10 +225,7 @@ class Node:
|
||||
|
||||
@tags.setter
|
||||
def tags(self, val):
|
||||
if isinstance(val, dict):
|
||||
self._tags = val
|
||||
else:
|
||||
self._tags = {}
|
||||
self._tags = val
|
||||
|
||||
def _base_config_file_content(self, path):
|
||||
if not os.path.isabs(path):
|
||||
|
||||
@ -36,7 +36,7 @@ class Template(BaseTable):
|
||||
builtin = Column(Boolean, default=False)
|
||||
usage = Column(String)
|
||||
template_type = Column(String)
|
||||
tags = Column(JSON, default='{}')
|
||||
tags = Column(JSON)
|
||||
compute_id = Column(String)
|
||||
images = relationship("Image", secondary=image_template_map, back_populates="templates")
|
||||
|
||||
|
||||
@ -14,8 +14,8 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from pydantic import BaseModel, Field, model_validator
|
||||
from typing import List, Optional, Union, Any, Dict
|
||||
from pydantic import BaseModel, Field
|
||||
from typing import List, Optional, Union
|
||||
from enum import Enum
|
||||
from uuid import UUID, uuid4
|
||||
|
||||
@ -128,14 +128,14 @@ class NodeBase(BaseModel):
|
||||
z: Optional[int] = 1
|
||||
locked: Optional[bool] = Field(False, description="Whether the element locked or not")
|
||||
port_name_format: Optional[str] = Field(
|
||||
None, descript_port_name_formation="Formatting for port name {0} will be replace by port number"
|
||||
None, description="Formatting for port name {0} will be replace by port number"
|
||||
)
|
||||
port_segment_size: Optional[int] = Field(None, description="Size of the port segment")
|
||||
first_port_name: Optional[str] = Field(None, description="Name of the first port")
|
||||
custom_adapters: Optional[List[CustomAdapter]] = None
|
||||
tags: Optional[Dict[str, str]] = Field(
|
||||
default_factory=dict,
|
||||
description="User-defined metadata tags inherited from template or custom"
|
||||
tags: Optional[List[str]] = Field(
|
||||
default_factory=list,
|
||||
description="User-defined metadata tags (e.g. 'vendor:cisco' or 'model:7200')"
|
||||
)
|
||||
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from pydantic import ConfigDict, BaseModel, Field
|
||||
from typing import Optional, Union, Dict
|
||||
from typing import Optional, List
|
||||
from enum import Enum
|
||||
from uuid import UUID
|
||||
|
||||
@ -48,9 +48,9 @@ class TemplateBase(BaseModel):
|
||||
template_type: Optional[NodeType] = None
|
||||
compute_id: Optional[str] = None
|
||||
usage: Optional[str] = ""
|
||||
tags: Optional[Dict[str, str]] = Field(
|
||||
default_factory=dict,
|
||||
description="User-defined metadata tags as key-value pairs (e.g., {'vendor': 'cisco', 'model': '7200', 'netmiko_device_type': 'cisco_ios'})"
|
||||
tags: Optional[List[str]] = Field(
|
||||
default_factory=list,
|
||||
description="User-defined metadata tags (e.g. 'vendor:cisco' or 'model:7200')"
|
||||
)
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user