Closes #7598: Enable custom field filtering for GraphQL (#18701)

This commit is contained in:
Jeremy Stretch
2025-03-07 13:49:06 -05:00
committed by GitHub
parent bbf4eea76c
commit c35f5f829a
47 changed files with 3041 additions and 681 deletions

View File

@@ -0,0 +1,11 @@
import strawberry
from virtualization.choices import *
__all__ = (
'ClusterStatusEnum',
'VirtualMachineStatusEnum',
)
ClusterStatusEnum = strawberry.enum(ClusterStatusChoices.as_enum())
VirtualMachineStatusEnum = strawberry.enum(VirtualMachineStatusChoices.as_enum())

View File

@@ -0,0 +1,26 @@
from dataclasses import dataclass
from typing import Annotated, TYPE_CHECKING
import strawberry
import strawberry_django
from strawberry import ID
from strawberry_django import FilterLookup
from netbox.graphql.filter_mixins import NetBoxModelFilterMixin
if TYPE_CHECKING:
from .filters import VirtualMachineFilter
__all__ = (
'VMComponentFilterMixin',
)
@dataclass
class VMComponentFilterMixin(NetBoxModelFilterMixin):
virtual_manchine: Annotated['VirtualMachineFilter', strawberry.lazy('virtualization.graphql.filters')] | None = (
strawberry_django.filter_field()
)
virtual_machine_id: ID | None = strawberry_django.filter_field()
name: FilterLookup[str] | None = strawberry_django.filter_field()
description: FilterLookup[str] | None = strawberry_django.filter_field()

View File

@@ -1,7 +1,33 @@
import strawberry_django
from typing import Annotated, TYPE_CHECKING
from netbox.graphql.filter_mixins import autotype_decorator, BaseFilterMixin
from virtualization import filtersets, models
import strawberry
import strawberry_django
from strawberry.scalars import ID
from strawberry_django import FilterLookup
from dcim.graphql.filter_mixins import InterfaceBaseFilterMixin, RenderConfigFilterMixin, ScopedFilterMixin
from extras.graphql.filter_mixins import ConfigContextFilterMixin
from netbox.graphql.filter_mixins import (
ImageAttachmentFilterMixin,
OrganizationalModelFilterMixin,
PrimaryModelFilterMixin,
)
from tenancy.graphql.filter_mixins import ContactFilterMixin, TenancyFilterMixin
from virtualization import models
from virtualization.graphql.filter_mixins import VMComponentFilterMixin
if TYPE_CHECKING:
from .enums import *
from netbox.graphql.filter_lookups import FloatLookup, IntegerLookup
from dcim.graphql.filters import DeviceFilter, DeviceRoleFilter, MACAddressFilter, PlatformFilter, SiteFilter
from ipam.graphql.filters import (
FHRPGroupAssignmentFilter,
IPAddressFilter,
ServiceFilter,
VLANGroupFilter,
VRFFilter,
)
from vpn.graphql.filters import L2VPNFilter, TunnelTerminationFilter
__all__ = (
'ClusterFilter',
@@ -14,36 +40,119 @@ __all__ = (
@strawberry_django.filter(models.Cluster, lookups=True)
@autotype_decorator(filtersets.ClusterFilterSet)
class ClusterFilter(BaseFilterMixin):
pass
class ClusterFilter(ContactFilterMixin, ScopedFilterMixin, TenancyFilterMixin, PrimaryModelFilterMixin):
name: FilterLookup[str] | None = strawberry_django.filter_field()
type: Annotated['ClusterTypeFilter', strawberry.lazy('virtualization.graphql.filters')] | None = (
strawberry_django.filter_field()
)
type_id: ID | None = strawberry_django.filter_field()
group: Annotated['ClusterGroupFilter', strawberry.lazy('virtualization.graphql.filters')] | None = (
strawberry_django.filter_field()
)
group_id: ID | None = strawberry_django.filter_field()
status: Annotated['ClusterStatusEnum', strawberry.lazy('virtualization.graphql.enums')] | None = (
strawberry_django.filter_field()
)
vlan_groups: Annotated['VLANGroupFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.ClusterGroup, lookups=True)
@autotype_decorator(filtersets.ClusterGroupFilterSet)
class ClusterGroupFilter(BaseFilterMixin):
pass
class ClusterGroupFilter(ContactFilterMixin, OrganizationalModelFilterMixin):
vlan_groups: Annotated['VLANGroupFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.ClusterType, lookups=True)
@autotype_decorator(filtersets.ClusterTypeFilterSet)
class ClusterTypeFilter(BaseFilterMixin):
class ClusterTypeFilter(OrganizationalModelFilterMixin):
pass
@strawberry_django.filter(models.VirtualMachine, lookups=True)
@autotype_decorator(filtersets.VirtualMachineFilterSet)
class VirtualMachineFilter(BaseFilterMixin):
pass
class VirtualMachineFilter(
ContactFilterMixin,
ImageAttachmentFilterMixin,
RenderConfigFilterMixin,
ConfigContextFilterMixin,
TenancyFilterMixin,
PrimaryModelFilterMixin,
):
name: FilterLookup[str] | None = strawberry_django.filter_field()
site: Annotated['SiteFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field()
site_id: ID | None = strawberry_django.filter_field()
cluster: Annotated['ClusterFilter', strawberry.lazy('virtualization.graphql.filters')] | None = (
strawberry_django.filter_field()
)
cluster_id: ID | None = strawberry_django.filter_field()
device: Annotated['DeviceFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field()
device_id: ID | None = strawberry_django.filter_field()
platform: Annotated['PlatformFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
platform_id: ID | None = strawberry_django.filter_field()
status: Annotated['VirtualMachineStatusEnum', strawberry.lazy('virtualization.graphql.enums')] | None = (
strawberry_django.filter_field()
)
role: Annotated['DeviceRoleFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
role_id: ID | None = strawberry_django.filter_field()
primary_ip4: Annotated['IPAddressFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
primary_ip4_id: ID | None = strawberry_django.filter_field()
primary_ip6: Annotated['IPAddressFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
primary_ip6_id: ID | None = strawberry_django.filter_field()
vcpus: Annotated['FloatLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
memory: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
disk: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
serial: FilterLookup[str] | None = strawberry_django.filter_field()
interface_count: FilterLookup[int] | None = strawberry_django.filter_field()
virtual_disk_count: FilterLookup[int] | None = strawberry_django.filter_field()
interfaces: Annotated['VMInterfaceFilter', strawberry.lazy('virtualization.graphql.filters')] | None = (
strawberry_django.filter_field()
)
services: Annotated['ServiceFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
virtual_disks: Annotated['VirtualDiskFilter', strawberry.lazy('virtualization.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.VMInterface, lookups=True)
@autotype_decorator(filtersets.VMInterfaceFilterSet)
class VMInterfaceFilter(BaseFilterMixin):
pass
class VMInterfaceFilter(VMComponentFilterMixin, InterfaceBaseFilterMixin):
ip_addresses: Annotated['IPAddressFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
vrf: Annotated['VRFFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field()
vrf_id: ID | None = strawberry_django.filter_field()
fhrp_group_assignments: Annotated['FHRPGroupAssignmentFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
tunnel_terminations: Annotated['TunnelTerminationFilter', strawberry.lazy('vpn.graphql.filters')] | None = (
strawberry_django.filter_field()
)
l2vpn_terminations: Annotated['L2VPNFilter', strawberry.lazy('vpn.graphql.filters')] | None = (
strawberry_django.filter_field()
)
mac_addresses: Annotated['MACAddressFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.VirtualDisk, lookups=True)
@autotype_decorator(filtersets.VirtualDiskFilterSet)
class VirtualDiskFilter(BaseFilterMixin):
pass
class VirtualDiskFilter(VMComponentFilterMixin):
size: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)

View File

@@ -1,4 +1,4 @@
from typing import Annotated, List, Union
from typing import Annotated, List, TYPE_CHECKING, Union
import strawberry
import strawberry_django
@@ -10,6 +10,21 @@ from netbox.graphql.types import OrganizationalObjectType, NetBoxObjectType
from virtualization import models
from .filters import *
if TYPE_CHECKING:
from dcim.graphql.types import (
DeviceRoleType,
DeviceType,
LocationType,
MACAddressType,
PlatformType,
RegionType,
SiteGroupType,
SiteType,
)
from extras.graphql.types import ConfigTemplateType
from ipam.graphql.types import IPAddressType, ServiceType, VLANTranslationPolicyType, VLANType, VRFType
from tenancy.graphql.types import TenantType
__all__ = (
'ClusterType',
'ClusterGroupType',
@@ -30,7 +45,7 @@ class ComponentType(NetBoxObjectType):
@strawberry_django.type(
models.Cluster,
exclude=('scope_type', 'scope_id', '_location', '_region', '_site', '_site_group'),
exclude=['scope_type', 'scope_id', '_location', '_region', '_site', '_site_group'],
filters=ClusterFilter
)
class ClusterType(VLANGroupsMixin, NetBoxObjectType):