From 5fdbc0f9f5d7298f2a27384fb6b1483ad123a55c Mon Sep 17 00:00:00 2001 From: Brian Tiemann Date: Thu, 23 Oct 2025 20:19:16 -0400 Subject: [PATCH 1/8] Clone all GraphQL objects to V1 versions --- netbox/circuits/graphql/filter_mixins_v1.py | 19 + netbox/circuits/graphql/filters_v1.py | 228 ++++ netbox/circuits/graphql/schema_v1.py | 42 + netbox/circuits/graphql/types_v1.py | 189 +++ netbox/core/graphql/filter_mixins_v1.py | 36 + netbox/core/graphql/filters_v1.py | 89 ++ netbox/core/graphql/mixins_v1.py | 35 + netbox/core/graphql/schema_v1.py | 15 + netbox/core/graphql/types_v1.py | 56 + netbox/dcim/graphql/filter_mixins_v1.py | 155 +++ netbox/dcim/graphql/filters_v1.py | 1020 +++++++++++++++++ netbox/dcim/graphql/gfk_mixins_v1.py | 137 +++ netbox/dcim/graphql/mixins_v1.py | 43 + netbox/dcim/graphql/schema_v1.py | 138 +++ netbox/dcim/graphql/types_v1.py | 906 +++++++++++++++ netbox/extras/graphql/filter_mixins_v1.py | 52 + netbox/extras/graphql/filters_v1.py | 357 ++++++ netbox/extras/graphql/mixins_v1.py | 62 + netbox/extras/graphql/schema_v1.py | 60 + netbox/extras/graphql/types_v1.py | 239 ++++ netbox/ipam/graphql/filter_mixins_v1.py | 25 + netbox/ipam/graphql/filters_v1.py | 392 +++++++ netbox/ipam/graphql/mixins_v1.py | 18 + netbox/ipam/graphql/schema_v1.py | 63 + netbox/ipam/graphql/types_v1.py | 360 ++++++ netbox/netbox/graphql/filter_mixins_v1.py | 104 ++ netbox/netbox/graphql/schema.py | 30 +- netbox/netbox/graphql/types_v1.py | 100 ++ netbox/tenancy/graphql/filter_mixins_v1.py | 38 + netbox/tenancy/graphql/filters_v1.py | 210 ++++ netbox/tenancy/graphql/mixins_v1.py | 12 + netbox/tenancy/graphql/schema_v1.py | 27 + netbox/tenancy/graphql/types_v1.py | 147 +++ netbox/users/graphql/filters_v1.py | 34 + netbox/users/graphql/schema_v1.py | 15 + netbox/users/graphql/types_v1.py | 34 + .../graphql/filter_mixins_v1.py | 28 + netbox/virtualization/graphql/filters_v1.py | 170 +++ netbox/virtualization/graphql/schema_v1.py | 27 + netbox/virtualization/graphql/types_v1.py | 146 +++ netbox/vpn/graphql/filters_v1.py | 192 ++++ netbox/vpn/graphql/schema_v1.py | 39 + netbox/vpn/graphql/types_v1.py | 157 +++ netbox/wireless/graphql/filter_mixins_v1.py | 26 + netbox/wireless/graphql/filters_v1.py | 72 ++ netbox/wireless/graphql/schema_v1.py | 18 + netbox/wireless/graphql/types_v1.py | 71 ++ 47 files changed, 6423 insertions(+), 10 deletions(-) create mode 100644 netbox/circuits/graphql/filter_mixins_v1.py create mode 100644 netbox/circuits/graphql/filters_v1.py create mode 100644 netbox/circuits/graphql/schema_v1.py create mode 100644 netbox/circuits/graphql/types_v1.py create mode 100644 netbox/core/graphql/filter_mixins_v1.py create mode 100644 netbox/core/graphql/filters_v1.py create mode 100644 netbox/core/graphql/mixins_v1.py create mode 100644 netbox/core/graphql/schema_v1.py create mode 100644 netbox/core/graphql/types_v1.py create mode 100644 netbox/dcim/graphql/filter_mixins_v1.py create mode 100644 netbox/dcim/graphql/filters_v1.py create mode 100644 netbox/dcim/graphql/gfk_mixins_v1.py create mode 100644 netbox/dcim/graphql/mixins_v1.py create mode 100644 netbox/dcim/graphql/schema_v1.py create mode 100644 netbox/dcim/graphql/types_v1.py create mode 100644 netbox/extras/graphql/filter_mixins_v1.py create mode 100644 netbox/extras/graphql/filters_v1.py create mode 100644 netbox/extras/graphql/mixins_v1.py create mode 100644 netbox/extras/graphql/schema_v1.py create mode 100644 netbox/extras/graphql/types_v1.py create mode 100644 netbox/ipam/graphql/filter_mixins_v1.py create mode 100644 netbox/ipam/graphql/filters_v1.py create mode 100644 netbox/ipam/graphql/mixins_v1.py create mode 100644 netbox/ipam/graphql/schema_v1.py create mode 100644 netbox/ipam/graphql/types_v1.py create mode 100644 netbox/netbox/graphql/filter_mixins_v1.py create mode 100644 netbox/netbox/graphql/types_v1.py create mode 100644 netbox/tenancy/graphql/filter_mixins_v1.py create mode 100644 netbox/tenancy/graphql/filters_v1.py create mode 100644 netbox/tenancy/graphql/mixins_v1.py create mode 100644 netbox/tenancy/graphql/schema_v1.py create mode 100644 netbox/tenancy/graphql/types_v1.py create mode 100644 netbox/users/graphql/filters_v1.py create mode 100644 netbox/users/graphql/schema_v1.py create mode 100644 netbox/users/graphql/types_v1.py create mode 100644 netbox/virtualization/graphql/filter_mixins_v1.py create mode 100644 netbox/virtualization/graphql/filters_v1.py create mode 100644 netbox/virtualization/graphql/schema_v1.py create mode 100644 netbox/virtualization/graphql/types_v1.py create mode 100644 netbox/vpn/graphql/filters_v1.py create mode 100644 netbox/vpn/graphql/schema_v1.py create mode 100644 netbox/vpn/graphql/types_v1.py create mode 100644 netbox/wireless/graphql/filter_mixins_v1.py create mode 100644 netbox/wireless/graphql/filters_v1.py create mode 100644 netbox/wireless/graphql/schema_v1.py create mode 100644 netbox/wireless/graphql/types_v1.py diff --git a/netbox/circuits/graphql/filter_mixins_v1.py b/netbox/circuits/graphql/filter_mixins_v1.py new file mode 100644 index 0000000000..15ebce2d42 --- /dev/null +++ b/netbox/circuits/graphql/filter_mixins_v1.py @@ -0,0 +1,19 @@ +from dataclasses import dataclass +from typing import Annotated, TYPE_CHECKING + +import strawberry +import strawberry_django + +from netbox.graphql.filter_mixins_v1 import OrganizationalModelFilterMixinV1 + +if TYPE_CHECKING: + from netbox.graphql.enums import ColorEnum + +__all__ = ( + 'BaseCircuitTypeFilterMixinV1', +) + + +@dataclass +class BaseCircuitTypeFilterMixinV1(OrganizationalModelFilterMixinV1): + color: Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')] | None = strawberry_django.filter_field() diff --git a/netbox/circuits/graphql/filters_v1.py b/netbox/circuits/graphql/filters_v1.py new file mode 100644 index 0000000000..caf4b7c627 --- /dev/null +++ b/netbox/circuits/graphql/filters_v1.py @@ -0,0 +1,228 @@ +from datetime import date +from typing import Annotated, TYPE_CHECKING + +import strawberry +import strawberry_django +from strawberry.scalars import ID +from strawberry_django import FilterLookup, DateFilterLookup + +from circuits import models +from core.graphql.filter_mixins_v1 import BaseObjectTypeFilterMixinV1, ChangeLogFilterMixinV1 +from dcim.graphql.filter_mixins_v1 import CabledObjectModelFilterMixinV1 +from extras.graphql.filter_mixins_v1 import CustomFieldsFilterMixinV1, TagsFilterMixinV1 +from netbox.graphql.filter_mixins_v1 import ( + DistanceFilterMixinV1, + ImageAttachmentFilterMixinV1, + OrganizationalModelFilterMixinV1, + PrimaryModelFilterMixinV1, +) +from tenancy.graphql.filter_mixins_v1 import ContactFilterMixinV1, TenancyFilterMixinV1 +from .filter_mixins_v1 import BaseCircuitTypeFilterMixinV1 + +if TYPE_CHECKING: + from core.graphql.filters_v1 import ContentTypeFilterV1 + from dcim.graphql.filters_v1 import ( + InterfaceFilterV1, LocationFilterV1, RegionFilterV1, SiteFilterV1, SiteGroupFilterV1 + ) + from ipam.graphql.filters_v1 import ASNFilterV1 + from netbox.graphql.filter_lookups import IntegerLookup + from .enums import * + +__all__ = ( + 'CircuitFilterV1', + 'CircuitGroupAssignmentFilterV1', + 'CircuitGroupFilterV1', + 'CircuitTerminationFilterV1', + 'CircuitTypeFilterV1', + 'ProviderFilterV1', + 'ProviderAccountFilterV1', + 'ProviderNetworkFilterV1', + 'VirtualCircuitFilterV1', + 'VirtualCircuitTerminationFilterV1', + 'VirtualCircuitTypeFilterV1', +) + + +@strawberry_django.filter_type(models.CircuitTermination, lookups=True) +class CircuitTerminationFilterV1( + BaseObjectTypeFilterMixinV1, + CustomFieldsFilterMixinV1, + TagsFilterMixinV1, + ChangeLogFilterMixinV1, + CabledObjectModelFilterMixinV1, +): + circuit: Annotated['CircuitFilterV1', strawberry.lazy('circuits.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + term_side: Annotated['CircuitTerminationSideEnum', strawberry.lazy('circuits.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + termination_type: Annotated['ContentTypeFilterV1', strawberry.lazy('core.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + termination_id: ID | None = strawberry_django.filter_field() + port_speed: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + upstream_speed: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + xconnect_id: FilterLookup[str] | None = strawberry_django.filter_field() + pp_info: FilterLookup[str] | None = strawberry_django.filter_field() + description: FilterLookup[str] | None = strawberry_django.filter_field() + + # Cached relations + _provider_network: Annotated['ProviderNetworkFilterV1', strawberry.lazy('circuits.graphql.filters_v1')] | None = ( + strawberry_django.filter_field(name='provider_network') + ) + _location: Annotated['LocationFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field(name='location') + ) + _region: Annotated['RegionFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field(name='region') + ) + _site_group: Annotated['SiteGroupFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field(name='site_group') + ) + _site: Annotated['SiteFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field(name='site') + ) + + +@strawberry_django.filter_type(models.Circuit, lookups=True) +class CircuitFilterV1( + ContactFilterMixinV1, + ImageAttachmentFilterMixinV1, + DistanceFilterMixinV1, + TenancyFilterMixinV1, + PrimaryModelFilterMixinV1 +): + cid: FilterLookup[str] | None = strawberry_django.filter_field() + provider: Annotated['ProviderFilterV1', strawberry.lazy('circuits.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + provider_id: ID | None = strawberry_django.filter_field() + provider_account: Annotated['ProviderAccountFilterV1', strawberry.lazy('circuits.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + provider_account_id: ID | None = strawberry_django.filter_field() + type: Annotated['CircuitTypeFilterV1', strawberry.lazy('circuits.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + type_id: ID | None = strawberry_django.filter_field() + status: Annotated['CircuitStatusEnum', strawberry.lazy('circuits.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + install_date: DateFilterLookup[date] | None = strawberry_django.filter_field() + termination_date: DateFilterLookup[date] | None = strawberry_django.filter_field() + commit_rate: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + terminations: Annotated['CircuitTerminationFilterV1', strawberry.lazy('circuits.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.CircuitType, lookups=True) +class CircuitTypeFilterV1(BaseCircuitTypeFilterMixinV1): + pass + + +@strawberry_django.filter_type(models.CircuitGroup, lookups=True) +class CircuitGroupFilterV1(TenancyFilterMixinV1, OrganizationalModelFilterMixinV1): + pass + + +@strawberry_django.filter_type(models.CircuitGroupAssignment, lookups=True) +class CircuitGroupAssignmentFilterV1( + BaseObjectTypeFilterMixinV1, CustomFieldsFilterMixinV1, TagsFilterMixinV1, ChangeLogFilterMixinV1 +): + member_type: Annotated['ContentTypeFilterV1', strawberry.lazy('core.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + member_id: ID | None = strawberry_django.filter_field() + group: Annotated['CircuitGroupFilterV1', strawberry.lazy('circuits.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + group_id: ID | None = strawberry_django.filter_field() + priority: Annotated['CircuitPriorityEnum', strawberry.lazy('circuits.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.Provider, lookups=True) +class ProviderFilterV1(ContactFilterMixinV1, PrimaryModelFilterMixinV1): + name: FilterLookup[str] | None = strawberry_django.filter_field() + slug: FilterLookup[str] | None = strawberry_django.filter_field() + asns: Annotated['ASNFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = strawberry_django.filter_field() + circuits: Annotated['CircuitFilterV1', strawberry.lazy('circuits.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.ProviderAccount, lookups=True) +class ProviderAccountFilterV1(ContactFilterMixinV1, PrimaryModelFilterMixinV1): + provider: Annotated['ProviderFilterV1', strawberry.lazy('circuits.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + provider_id: ID | None = strawberry_django.filter_field() + account: FilterLookup[str] | None = strawberry_django.filter_field() + name: FilterLookup[str] | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.ProviderNetwork, lookups=True) +class ProviderNetworkFilterV1(PrimaryModelFilterMixinV1): + name: FilterLookup[str] | None = strawberry_django.filter_field() + provider: Annotated['ProviderFilterV1', strawberry.lazy('circuits.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + provider_id: ID | None = strawberry_django.filter_field() + service_id: FilterLookup[str] | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.VirtualCircuitType, lookups=True) +class VirtualCircuitTypeFilterV1(BaseCircuitTypeFilterMixinV1): + pass + + +@strawberry_django.filter_type(models.VirtualCircuit, lookups=True) +class VirtualCircuitFilterV1(TenancyFilterMixinV1, PrimaryModelFilterMixinV1): + cid: FilterLookup[str] | None = strawberry_django.filter_field() + provider_network: Annotated['ProviderNetworkFilterV1', strawberry.lazy('circuits.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + provider_network_id: ID | None = strawberry_django.filter_field() + provider_account: Annotated['ProviderAccountFilterV1', strawberry.lazy('circuits.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + provider_account_id: ID | None = strawberry_django.filter_field() + type: Annotated['VirtualCircuitTypeFilterV1', strawberry.lazy('circuits.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + type_id: ID | None = strawberry_django.filter_field() + status: Annotated['CircuitStatusEnum', strawberry.lazy('circuits.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + group_assignments: Annotated[ + 'CircuitGroupAssignmentFilterV1', strawberry.lazy('circuits.graphql.filters_v1') + ] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.VirtualCircuitTermination, lookups=True) +class VirtualCircuitTerminationFilterV1( + BaseObjectTypeFilterMixinV1, CustomFieldsFilterMixinV1, TagsFilterMixinV1, ChangeLogFilterMixinV1 +): + virtual_circuit: Annotated['VirtualCircuitFilterV1', strawberry.lazy('circuits.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + virtual_circuit_id: ID | None = strawberry_django.filter_field() + role: Annotated['VirtualCircuitTerminationRoleEnum', strawberry.lazy('circuits.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + interface: Annotated['InterfaceFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + interface_id: ID | None = strawberry_django.filter_field() + description: FilterLookup[str] | None = strawberry_django.filter_field() diff --git a/netbox/circuits/graphql/schema_v1.py b/netbox/circuits/graphql/schema_v1.py new file mode 100644 index 0000000000..1134978f97 --- /dev/null +++ b/netbox/circuits/graphql/schema_v1.py @@ -0,0 +1,42 @@ +from typing import List + +import strawberry +import strawberry_django + +from .types_v1 import * + + +@strawberry.type(name="Query") +class CircuitsQueryV1: + circuit: CircuitTypeV1 = strawberry_django.field() + circuit_list: List[CircuitTypeV1] = strawberry_django.field() + + circuit_termination: CircuitTerminationTypeV1 = strawberry_django.field() + circuit_termination_list: List[CircuitTerminationTypeV1] = strawberry_django.field() + + circuit_type: CircuitTypeTypeV1 = strawberry_django.field() + circuit_type_list: List[CircuitTypeTypeV1] = strawberry_django.field() + + circuit_group: CircuitGroupTypeV1 = strawberry_django.field() + circuit_group_list: List[CircuitGroupTypeV1] = strawberry_django.field() + + circuit_group_assignment: CircuitGroupAssignmentTypeV1 = strawberry_django.field() + circuit_group_assignment_list: List[CircuitGroupAssignmentTypeV1] = strawberry_django.field() + + provider: ProviderTypeV1 = strawberry_django.field() + provider_list: List[ProviderTypeV1] = strawberry_django.field() + + provider_account: ProviderAccountTypeV1 = strawberry_django.field() + provider_account_list: List[ProviderAccountTypeV1] = strawberry_django.field() + + provider_network: ProviderNetworkTypeV1 = strawberry_django.field() + provider_network_list: List[ProviderNetworkTypeV1] = strawberry_django.field() + + virtual_circuit: VirtualCircuitTypeV1 = strawberry_django.field() + virtual_circuit_list: List[VirtualCircuitTypeV1] = strawberry_django.field() + + virtual_circuit_termination: VirtualCircuitTerminationTypeV1 = strawberry_django.field() + virtual_circuit_termination_list: List[VirtualCircuitTerminationTypeV1] = strawberry_django.field() + + virtual_circuit_type: VirtualCircuitTypeTypeV1 = strawberry_django.field() + virtual_circuit_type_list: List[VirtualCircuitTypeTypeV1] = strawberry_django.field() diff --git a/netbox/circuits/graphql/types_v1.py b/netbox/circuits/graphql/types_v1.py new file mode 100644 index 0000000000..3e7669df6d --- /dev/null +++ b/netbox/circuits/graphql/types_v1.py @@ -0,0 +1,189 @@ +from typing import Annotated, List, TYPE_CHECKING, Union + +import strawberry +import strawberry_django + +from circuits import models +from dcim.graphql.mixins_v1 import CabledObjectMixinV1 +from extras.graphql.mixins_v1 import ContactsMixinV1, CustomFieldsMixinV1, TagsMixinV1 +from netbox.graphql.types_v1 import BaseObjectTypeV1, NetBoxObjectTypeV1, ObjectTypeV1, OrganizationalObjectTypeV1 +from tenancy.graphql.types_v1 import TenantTypeV1 +from .filters_v1 import * + +if TYPE_CHECKING: + from dcim.graphql.types_v1 import InterfaceTypeV1, LocationTypeV1, RegionTypeV1, SiteGroupTypeV1, SiteTypeV1 + from ipam.graphql.types_v1 import ASNTypeV1 + +__all__ = ( + 'CircuitGroupAssignmentTypeV1', + 'CircuitGroupTypeV1', + 'CircuitTerminationTypeV1', + 'CircuitTypeV1', + 'CircuitTypeTypeV1', + 'ProviderTypeV1', + 'ProviderAccountTypeV1', + 'ProviderNetworkTypeV1', + 'VirtualCircuitTerminationTypeV1', + 'VirtualCircuitTypeV1', + 'VirtualCircuitTypeTypeV1', +) + + +@strawberry_django.type( + models.Provider, + fields='__all__', + filters=ProviderFilterV1, + pagination=True +) +class ProviderTypeV1(NetBoxObjectTypeV1, ContactsMixinV1): + + networks: List[Annotated["ProviderNetworkTypeV1", strawberry.lazy('circuits.graphql.types_v1')]] + circuits: List[Annotated["CircuitTypeV1", strawberry.lazy('circuits.graphql.types_v1')]] + asns: List[Annotated["ASNTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] + accounts: List[Annotated["ProviderAccountTypeV1", strawberry.lazy('circuits.graphql.types_v1')]] + + +@strawberry_django.type( + models.ProviderAccount, + fields='__all__', + filters=ProviderAccountFilterV1, + pagination=True +) +class ProviderAccountTypeV1(ContactsMixinV1, NetBoxObjectTypeV1): + provider: Annotated["ProviderTypeV1", strawberry.lazy('circuits.graphql.types_v1')] + + circuits: List[Annotated["CircuitTypeV1", strawberry.lazy('circuits.graphql.types_v1')]] + + +@strawberry_django.type( + models.ProviderNetwork, + fields='__all__', + filters=ProviderNetworkFilterV1, + pagination=True +) +class ProviderNetworkTypeV1(NetBoxObjectTypeV1): + provider: Annotated["ProviderTypeV1", strawberry.lazy('circuits.graphql.types_v1')] + + circuit_terminations: List[Annotated["CircuitTerminationTypeV1", strawberry.lazy('circuits.graphql.types_v1')]] + + +@strawberry_django.type( + models.CircuitTermination, + exclude=['termination_type', 'termination_id', '_location', '_region', '_site', '_site_group', '_provider_network'], + filters=CircuitTerminationFilterV1, + pagination=True +) +class CircuitTerminationTypeV1(CustomFieldsMixinV1, TagsMixinV1, CabledObjectMixinV1, ObjectTypeV1): + circuit: Annotated["CircuitTypeV1", strawberry.lazy('circuits.graphql.types_v1')] + + @strawberry_django.field + def termination(self) -> Annotated[Union[ + Annotated["LocationTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["RegionTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["SiteGroupTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["SiteTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["ProviderNetworkTypeV1", strawberry.lazy('circuits.graphql.types_v1')], + ], strawberry.union("CircuitTerminationTerminationTypeV1")] | None: + return self.termination + + +@strawberry_django.type( + models.CircuitType, + fields='__all__', + filters=CircuitTypeFilterV1, + pagination=True +) +class CircuitTypeTypeV1(OrganizationalObjectTypeV1): + color: str + + circuits: List[Annotated["CircuitTypeV1", strawberry.lazy('circuits.graphql.types_v1')]] + + +@strawberry_django.type( + models.Circuit, + fields='__all__', + filters=CircuitFilterV1, + pagination=True +) +class CircuitTypeV1(NetBoxObjectTypeV1, ContactsMixinV1): + provider: ProviderTypeV1 + provider_account: ProviderAccountTypeV1 | None + termination_a: CircuitTerminationTypeV1 | None + termination_z: CircuitTerminationTypeV1 | None + type: CircuitTypeTypeV1 + tenant: TenantTypeV1 | None + + terminations: List[CircuitTerminationTypeV1] + + +@strawberry_django.type( + models.CircuitGroup, + fields='__all__', + filters=CircuitGroupFilterV1, + pagination=True +) +class CircuitGroupTypeV1(OrganizationalObjectTypeV1): + tenant: TenantTypeV1 | None + + +@strawberry_django.type( + models.CircuitGroupAssignment, + exclude=['member_type', 'member_id'], + filters=CircuitGroupAssignmentFilterV1, + pagination=True +) +class CircuitGroupAssignmentTypeV1(TagsMixinV1, BaseObjectTypeV1): + group: Annotated["CircuitGroupTypeV1", strawberry.lazy('circuits.graphql.types_v1')] + + @strawberry_django.field + def member(self) -> Annotated[Union[ + Annotated["CircuitTypeV1", strawberry.lazy('circuits.graphql.types_v1')], + Annotated["VirtualCircuitTypeV1", strawberry.lazy('circuits.graphql.types_v1')], + ], strawberry.union("CircuitGroupAssignmentMemberTypeV1")] | None: + return self.member + + +@strawberry_django.type( + models.VirtualCircuitType, + fields='__all__', + filters=VirtualCircuitTypeFilterV1, + pagination=True +) +class VirtualCircuitTypeTypeV1(OrganizationalObjectTypeV1): + color: str + + virtual_circuits: List[Annotated["VirtualCircuitTypeV1", strawberry.lazy('circuits.graphql.types_v1')]] + + +@strawberry_django.type( + models.VirtualCircuitTermination, + fields='__all__', + filters=VirtualCircuitTerminationFilterV1, + pagination=True +) +class VirtualCircuitTerminationTypeV1(CustomFieldsMixinV1, TagsMixinV1, ObjectTypeV1): + virtual_circuit: Annotated[ + "VirtualCircuitTypeV1", + strawberry.lazy('circuits.graphql.types_v1') + ] = strawberry_django.field(select_related=["virtual_circuit"]) + interface: Annotated[ + "InterfaceTypeV1", + strawberry.lazy('dcim.graphql.types_v1') + ] = strawberry_django.field(select_related=["interface"]) + + +@strawberry_django.type( + models.VirtualCircuit, + fields='__all__', + filters=VirtualCircuitFilterV1, + pagination=True +) +class VirtualCircuitTypeV1(NetBoxObjectTypeV1): + provider_network: ProviderNetworkTypeV1 = strawberry_django.field(select_related=["provider_network"]) + provider_account: ProviderAccountTypeV1 | None + type: Annotated["VirtualCircuitTypeTypeV1", strawberry.lazy('circuits.graphql.types_v1')] = strawberry_django.field( + select_related=["type"] + ) + tenant: TenantTypeV1 | None + + terminations: List[VirtualCircuitTerminationTypeV1] diff --git a/netbox/core/graphql/filter_mixins_v1.py b/netbox/core/graphql/filter_mixins_v1.py new file mode 100644 index 0000000000..58c39705f8 --- /dev/null +++ b/netbox/core/graphql/filter_mixins_v1.py @@ -0,0 +1,36 @@ +from dataclasses import dataclass +from datetime import datetime +from typing import Annotated, TYPE_CHECKING + +import strawberry +import strawberry_django +from strawberry import ID +from strawberry_django import DatetimeFilterLookup + +if TYPE_CHECKING: + from .filters_v1 import * + +__all__ = ( + 'BaseFilterMixinV1', + 'BaseObjectTypeFilterMixinV1', + 'ChangeLogFilterMixinV1', +) + + +# @strawberry.input +class BaseFilterMixinV1: ... + + +@dataclass +class BaseObjectTypeFilterMixinV1(BaseFilterMixinV1): + id: ID | None = strawberry.UNSET + + +@dataclass +class ChangeLogFilterMixinV1(BaseFilterMixinV1): + id: ID | None = strawberry.UNSET + changelog: Annotated['ObjectChangeFilterV1', strawberry.lazy('core.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + created: DatetimeFilterLookup[datetime] | None = strawberry_django.filter_field() + last_updated: DatetimeFilterLookup[datetime] | None = strawberry_django.filter_field() diff --git a/netbox/core/graphql/filters_v1.py b/netbox/core/graphql/filters_v1.py new file mode 100644 index 0000000000..c75de0c75c --- /dev/null +++ b/netbox/core/graphql/filters_v1.py @@ -0,0 +1,89 @@ +from datetime import datetime +from typing import Annotated, TYPE_CHECKING + +import strawberry +import strawberry_django +from django.contrib.contenttypes.models import ContentType as DjangoContentType +from strawberry.scalars import ID +from strawberry_django import DatetimeFilterLookup, FilterLookup + +from core import models +from core.graphql.filter_mixins_v1 import BaseFilterMixinV1 +from netbox.graphql.filter_mixins import PrimaryModelFilterMixin + +if TYPE_CHECKING: + from netbox.graphql.filter_lookups import IntegerLookup, JSONFilter + from users.graphql.filters import UserFilter + +__all__ = ( + 'DataFileFilterV1', + 'DataSourceFilterV1', + 'ObjectChangeFilterV1', + 'ContentTypeFilterV1', +) + + +@strawberry_django.filter_type(models.DataFile, lookups=True) +class DataFileFilterV1(BaseFilterMixinV1): + id: ID | None = strawberry_django.filter_field() + created: DatetimeFilterLookup[datetime] | None = strawberry_django.filter_field() + last_updated: DatetimeFilterLookup[datetime] | None = strawberry_django.filter_field() + source: Annotated['DataSourceFilterV1', strawberry.lazy('core.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + source_id: ID | None = strawberry_django.filter_field() + path: FilterLookup[str] | None = strawberry_django.filter_field() + size: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + hash: FilterLookup[str] | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.DataSource, lookups=True) +class DataSourceFilterV1(PrimaryModelFilterMixin): + name: FilterLookup[str] | None = strawberry_django.filter_field() + type: FilterLookup[str] | None = strawberry_django.filter_field() + source_url: FilterLookup[str] | None = strawberry_django.filter_field() + status: FilterLookup[str] | None = strawberry_django.filter_field() + enabled: FilterLookup[bool] | None = strawberry_django.filter_field() + ignore_rules: FilterLookup[str] | None = strawberry_django.filter_field() + parameters: Annotated['JSONFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + last_synced: DatetimeFilterLookup[datetime] | None = strawberry_django.filter_field() + datafiles: Annotated['DataFileFilterV1', strawberry.lazy('core.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.ObjectChange, lookups=True) +class ObjectChangeFilterV1(BaseFilterMixinV1): + id: ID | None = strawberry_django.filter_field() + time: DatetimeFilterLookup[datetime] | None = strawberry_django.filter_field() + user: Annotated['UserFilter', strawberry.lazy('users.graphql.filters')] | None = strawberry_django.filter_field() + user_name: FilterLookup[str] | None = strawberry_django.filter_field() + request_id: FilterLookup[str] | None = strawberry_django.filter_field() + action: FilterLookup[str] | None = strawberry_django.filter_field() + changed_object_type: Annotated['ContentTypeFilterV1', strawberry.lazy('core.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + changed_object_type_id: ID | None = strawberry_django.filter_field() + changed_object_id: ID | None = strawberry_django.filter_field() + related_object_type: Annotated['ContentTypeFilterV1', strawberry.lazy('core.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + related_object_id: ID | None = strawberry_django.filter_field() + object_repr: FilterLookup[str] | None = strawberry_django.filter_field() + prechange_data: Annotated['JSONFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + postchange_data: Annotated['JSONFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(DjangoContentType, lookups=True) +class ContentTypeFilterV1(BaseFilterMixinV1): + id: ID | None = strawberry_django.filter_field() + app_label: FilterLookup[str] | None = strawberry_django.filter_field() + model: FilterLookup[str] | None = strawberry_django.filter_field() diff --git a/netbox/core/graphql/mixins_v1.py b/netbox/core/graphql/mixins_v1.py new file mode 100644 index 0000000000..722068cdd4 --- /dev/null +++ b/netbox/core/graphql/mixins_v1.py @@ -0,0 +1,35 @@ +from typing import Annotated, List, TYPE_CHECKING + +import strawberry +import strawberry_django +from django.contrib.contenttypes.models import ContentType +from strawberry.types import Info + +from core.models import ObjectChange + +if TYPE_CHECKING: + from core.graphql.types_v1 import DataFileTypeV1, DataSourceTypeV1, ObjectChangeTypeV1 + +__all__ = ( + 'ChangelogMixinV1', + 'SyncedDataMixinV1', +) + + +@strawberry.type +class ChangelogMixinV1: + + @strawberry_django.field + def changelog(self, info: Info) -> List[Annotated['ObjectChangeTypeV1', strawberry.lazy('.types_v1')]]: # noqa: F821 + content_type = ContentType.objects.get_for_model(self) + object_changes = ObjectChange.objects.filter( + changed_object_type=content_type, + changed_object_id=self.pk + ) + return object_changes.restrict(info.context.request.user, 'view') + + +@strawberry.type +class SyncedDataMixinV1: + data_source: Annotated['DataSourceTypeV1', strawberry.lazy('core.graphql.types_v1')] | None + data_file: Annotated['DataFileTypeV1', strawberry.lazy('core.graphql.types_v1')] | None diff --git a/netbox/core/graphql/schema_v1.py b/netbox/core/graphql/schema_v1.py new file mode 100644 index 0000000000..b94d14a706 --- /dev/null +++ b/netbox/core/graphql/schema_v1.py @@ -0,0 +1,15 @@ +from typing import List + +import strawberry +import strawberry_django + +from .types_v1 import * + + +@strawberry.type(name="Query") +class CoreQueryV1: + data_file: DataFileTypeV1 = strawberry_django.field() + data_file_list: List[DataFileTypeV1] = strawberry_django.field() + + data_source: DataSourceTypeV1 = strawberry_django.field() + data_source_list: List[DataSourceTypeV1] = strawberry_django.field() diff --git a/netbox/core/graphql/types_v1.py b/netbox/core/graphql/types_v1.py new file mode 100644 index 0000000000..67effeae4c --- /dev/null +++ b/netbox/core/graphql/types_v1.py @@ -0,0 +1,56 @@ +from typing import Annotated, List + +import strawberry +import strawberry_django +from django.contrib.contenttypes.models import ContentType as DjangoContentType + +from core import models +from netbox.graphql.types_v1 import BaseObjectTypeV1, NetBoxObjectTypeV1 +from .filters_v1 import * + +__all__ = ( + 'ContentTypeV1', + 'DataFileTypeV1', + 'DataSourceTypeV1', + 'ObjectChangeTypeV1', +) + + +@strawberry_django.type( + models.DataFile, + exclude=['data',], + filters=DataFileFilterV1, + pagination=True +) +class DataFileTypeV1(BaseObjectTypeV1): + source: Annotated["DataSourceTypeV1", strawberry.lazy('core.graphql.types_v1')] + + +@strawberry_django.type( + models.DataSource, + fields='__all__', + filters=DataSourceFilterV1, + pagination=True +) +class DataSourceTypeV1(NetBoxObjectTypeV1): + + datafiles: List[Annotated["DataFileTypeV1", strawberry.lazy('core.graphql.types_v1')]] + + +@strawberry_django.type( + models.ObjectChange, + fields='__all__', + filters=ObjectChangeFilterV1, + pagination=True +) +class ObjectChangeTypeV1(BaseObjectTypeV1): + pass + + +@strawberry_django.type( + DjangoContentType, + fields='__all__', + pagination=True +) +class ContentTypeV1: + pass diff --git a/netbox/dcim/graphql/filter_mixins_v1.py b/netbox/dcim/graphql/filter_mixins_v1.py new file mode 100644 index 0000000000..55f3294975 --- /dev/null +++ b/netbox/dcim/graphql/filter_mixins_v1.py @@ -0,0 +1,155 @@ +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 core.graphql.filter_mixins_v1 import BaseFilterMixinV1, ChangeLogFilterMixinV1 +from core.graphql.filters_v1 import ContentTypeFilterV1 +from netbox.graphql.filter_mixins_v1 import NetBoxModelFilterMixinV1, PrimaryModelFilterMixinV1, WeightFilterMixinV1 +from .enums import * + +if TYPE_CHECKING: + from netbox.graphql.filter_lookups import IntegerLookup + from extras.graphql.filters_v1 import ConfigTemplateFilterV1 + from ipam.graphql.filters_v1 import VLANFilterV1, VLANTranslationPolicyFilterV1 + from .filters_v1 import * + +__all__ = ( + 'CabledObjectModelFilterMixinV1', + 'ComponentModelFilterMixinV1', + 'ComponentTemplateFilterMixinV1', + 'InterfaceBaseFilterMixinV1', + 'ModularComponentModelFilterMixinV1', + 'ModularComponentTemplateFilterMixinV1', + 'RackBaseFilterMixinV1', + 'RenderConfigFilterMixinV1', + 'ScopedFilterMixinV1', +) + + +@dataclass +class ScopedFilterMixinV1(BaseFilterMixinV1): + scope_type: Annotated['ContentTypeFilterV1', strawberry.lazy('core.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + scope_id: ID | None = strawberry_django.filter_field() + + +@dataclass +class ComponentModelFilterMixinV1(NetBoxModelFilterMixinV1): + device: Annotated['DeviceFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + device_id: ID | None = strawberry_django.filter_field() + name: FilterLookup[str] | None = strawberry_django.filter_field() + label: FilterLookup[str] | None = strawberry_django.filter_field() + description: FilterLookup[str] | None = strawberry_django.filter_field() + + +@dataclass +class ModularComponentModelFilterMixinV1(ComponentModelFilterMixinV1): + module: Annotated['ModuleFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + module_id: ID | None = strawberry_django.filter_field() + inventory_items: Annotated['InventoryItemFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + + +@dataclass +class CabledObjectModelFilterMixinV1(BaseFilterMixinV1): + cable: Annotated['CableFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + cable_id: ID | None = strawberry_django.filter_field() + cable_end: CableEndEnum | None = strawberry_django.filter_field() + mark_connected: FilterLookup[bool] | None = strawberry_django.filter_field() + + +@dataclass +class ComponentTemplateFilterMixinV1(ChangeLogFilterMixinV1): + device_type: Annotated['DeviceTypeFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + device_type_id: ID | None = strawberry_django.filter_field() + name: FilterLookup[str] | None = strawberry_django.filter_field() + label: FilterLookup[str] | None = strawberry_django.filter_field() + description: FilterLookup[str] | None = strawberry_django.filter_field() + + +@dataclass +class ModularComponentTemplateFilterMixinV1(ComponentTemplateFilterMixinV1): + module_type: Annotated['ModuleTypeFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + + +@dataclass +class RenderConfigFilterMixinV1(BaseFilterMixinV1): + config_template: Annotated['ConfigTemplateFilterV1', strawberry.lazy('extras.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + config_template_id: ID | None = strawberry_django.filter_field() + + +@dataclass +class InterfaceBaseFilterMixinV1(BaseFilterMixinV1): + enabled: FilterLookup[bool] | None = strawberry_django.filter_field() + mtu: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + mode: InterfaceModeEnum | None = strawberry_django.filter_field() + bridge: Annotated['InterfaceFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + bridge_id: ID | None = strawberry_django.filter_field() + untagged_vlan: Annotated['VLANFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + tagged_vlans: Annotated['VLANFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + qinq_svlan: Annotated['VLANFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + vlan_translation_policy: Annotated[ + 'VLANTranslationPolicyFilterV1', strawberry.lazy('ipam.graphql.filters_v1') + ] | None = strawberry_django.filter_field() + primary_mac_address: Annotated['MACAddressFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + primary_mac_address_id: ID | None = strawberry_django.filter_field() + + +@dataclass +class RackBaseFilterMixinV1(WeightFilterMixinV1, PrimaryModelFilterMixinV1): + width: Annotated['RackWidthEnum', strawberry.lazy('dcim.graphql.enums')] | None = strawberry_django.filter_field() + u_height: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + starting_unit: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + desc_units: FilterLookup[bool] | None = strawberry_django.filter_field() + outer_width: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + outer_height: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + outer_depth: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + outer_unit: Annotated['RackDimensionUnitEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + mounting_depth: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + max_weight: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) diff --git a/netbox/dcim/graphql/filters_v1.py b/netbox/dcim/graphql/filters_v1.py new file mode 100644 index 0000000000..be87c36186 --- /dev/null +++ b/netbox/dcim/graphql/filters_v1.py @@ -0,0 +1,1020 @@ +from typing import Annotated, TYPE_CHECKING + +from django.db.models import Q +import strawberry +import strawberry_django +from strawberry.scalars import ID +from strawberry_django import FilterLookup + +from core.graphql.filter_mixins_v1 import ChangeLogFilterMixinV1 +from dcim import models +from dcim.constants import * +from dcim.graphql.enums import InterfaceKindEnum +from extras.graphql.filter_mixins_v1 import ConfigContextFilterMixinV1 +from netbox.graphql.filter_mixins_v1 import ( + PrimaryModelFilterMixinV1, + OrganizationalModelFilterMixinV1, + NestedGroupModelFilterMixinV1, + ImageAttachmentFilterMixinV1, + WeightFilterMixinV1, +) +from tenancy.graphql.filter_mixins_v1 import TenancyFilterMixinV1, ContactFilterMixinV1 +from .filter_mixins_v1 import ( + CabledObjectModelFilterMixinV1, + ComponentModelFilterMixinV1, + ComponentTemplateFilterMixinV1, + InterfaceBaseFilterMixinV1, + ModularComponentModelFilterMixinV1, + ModularComponentTemplateFilterMixinV1, + RackBaseFilterMixinV1, + RenderConfigFilterMixinV1, +) + +if TYPE_CHECKING: + from core.graphql.filters_v1 import ContentTypeFilterV1 + from extras.graphql.filters_v1 import ConfigTemplateFilterV1, ImageAttachmentFilterV1 + from ipam.graphql.filters_v1 import ( + ASNFilterV1, FHRPGroupAssignmentFilterV1, IPAddressFilterV1, PrefixFilterV1, VLANGroupFilterV1, VRFFilterV1, + ) + from netbox.graphql.enums import ColorEnum + from netbox.graphql.filter_lookups import FloatLookup, IntegerArrayLookup, IntegerLookup, TreeNodeFilter + from users.graphql.filters_v1 import UserFilterV1 + from virtualization.graphql.filters_v1 import ClusterFilterV1 + from vpn.graphql.filters_v1 import L2VPNFilterV1, TunnelTerminationFilterV1 + from wireless.graphql.enums import WirelessChannelEnum, WirelessRoleEnum + from wireless.graphql.filters_v1 import WirelessLANFilterV1, WirelessLinkFilterV1 + from .enums import * + +__all__ = ( + 'CableFilterV1', + 'CableTerminationFilterV1', + 'ConsolePortFilterV1', + 'ConsolePortTemplateFilterV1', + 'ConsoleServerPortFilterV1', + 'ConsoleServerPortTemplateFilterV1', + 'DeviceFilterV1', + 'DeviceBayFilterV1', + 'DeviceBayTemplateFilterV1', + 'DeviceRoleFilterV1', + 'DeviceTypeFilterV1', + 'FrontPortFilterV1', + 'FrontPortTemplateFilterV1', + 'InterfaceFilterV1', + 'InterfaceTemplateFilterV1', + 'InventoryItemFilterV1', + 'InventoryItemRoleFilterV1', + 'InventoryItemTemplateFilterV1', + 'LocationFilterV1', + 'MACAddressFilterV1', + 'ManufacturerFilterV1', + 'ModuleFilterV1', + 'ModuleBayFilterV1', + 'ModuleBayTemplateFilterV1', + 'ModuleTypeFilterV1', + 'ModuleTypeProfileFilterV1', + 'PlatformFilterV1', + 'PowerFeedFilterV1', + 'PowerOutletFilterV1', + 'PowerOutletTemplateFilterV1', + 'PowerPanelFilterV1', + 'PowerPortFilterV1', + 'PowerPortTemplateFilterV1', + 'RackFilterV1', + 'RackReservationFilterV1', + 'RackRoleFilterV1', + 'RackTypeFilterV1', + 'RearPortFilterV1', + 'RearPortTemplateFilterV1', + 'RegionFilterV1', + 'SiteFilterV1', + 'SiteGroupFilterV1', + 'VirtualChassisFilterV1', + 'VirtualDeviceContextFilterV1', +) + + +@strawberry_django.filter_type(models.Cable, lookups=True) +class CableFilterV1(PrimaryModelFilterMixinV1, TenancyFilterMixinV1): + type: Annotated['CableTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = strawberry_django.filter_field() + status: Annotated['LinkStatusEnum', strawberry.lazy('dcim.graphql.enums')] | None = strawberry_django.filter_field() + label: FilterLookup[str] | None = strawberry_django.filter_field() + color: Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')] | None = strawberry_django.filter_field() + length: Annotated['FloatLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + length_unit: Annotated['CableLengthUnitEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + terminations: Annotated['CableTerminationFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.CableTermination, lookups=True) +class CableTerminationFilterV1(ChangeLogFilterMixinV1): + cable: Annotated['CableFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + cable_id: ID | None = strawberry_django.filter_field() + cable_end: Annotated['CableEndEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + termination_type: Annotated['CableTerminationFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + termination_id: ID | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.ConsolePort, lookups=True) +class ConsolePortFilterV1(ModularComponentModelFilterMixinV1, CabledObjectModelFilterMixinV1): + type: Annotated['ConsolePortTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + speed: Annotated['ConsolePortSpeedEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.ConsolePortTemplate, lookups=True) +class ConsolePortTemplateFilterV1(ModularComponentTemplateFilterMixinV1): + type: Annotated['ConsolePortTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.ConsoleServerPort, lookups=True) +class ConsoleServerPortFilterV1(ModularComponentModelFilterMixinV1, CabledObjectModelFilterMixinV1): + type: Annotated['ConsolePortTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + speed: Annotated['ConsolePortSpeedEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.ConsoleServerPortTemplate, lookups=True) +class ConsoleServerPortTemplateFilterV1(ModularComponentTemplateFilterMixinV1): + type: Annotated['ConsolePortTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.Device, lookups=True) +class DeviceFilterV1( + ContactFilterMixinV1, + TenancyFilterMixinV1, + ImageAttachmentFilterMixinV1, + RenderConfigFilterMixinV1, + ConfigContextFilterMixinV1, + PrimaryModelFilterMixinV1, +): + device_type: Annotated['DeviceTypeFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + device_type_id: ID | None = strawberry_django.filter_field() + role: Annotated['DeviceRoleFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + role_id: ID | None = strawberry_django.filter_field() + platform: Annotated['PlatformFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + name: FilterLookup[str] | None = strawberry_django.filter_field() + serial: FilterLookup[str] | None = strawberry_django.filter_field() + asset_tag: FilterLookup[str] | None = strawberry_django.filter_field() + site: Annotated['SiteFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + site_id: ID | None = strawberry_django.filter_field() + location: Annotated['LocationFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + location_id: Annotated['TreeNodeFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + rack: Annotated['RackFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + rack_id: ID | None = strawberry_django.filter_field() + position: Annotated['FloatLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + face: Annotated['DeviceFaceEnum', strawberry.lazy('dcim.graphql.enums')] | None = strawberry_django.filter_field() + status: Annotated['DeviceStatusEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + airflow: Annotated['DeviceAirflowEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + primary_ip4: Annotated['IPAddressFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + primary_ip4_id: ID | None = strawberry_django.filter_field() + primary_ip6: Annotated['IPAddressFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + primary_ip6_id: ID | None = strawberry_django.filter_field() + oob_ip: Annotated['IPAddressFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + oob_ip_id: ID | None = strawberry_django.filter_field() + cluster: Annotated['ClusterFilterV1', strawberry.lazy('virtualization.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + cluster_id: ID | None = strawberry_django.filter_field() + virtual_chassis: Annotated['VirtualChassisFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + virtual_chassis_id: ID | None = strawberry_django.filter_field() + vc_position: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + vc_priority: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + latitude: Annotated['FloatLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + longitude: Annotated['FloatLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + console_ports: Annotated['ConsolePortFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + console_server_ports: Annotated['ConsoleServerPortFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + power_outlets: Annotated['PowerOutletFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + power_ports: Annotated['PowerPortFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + interfaces: Annotated['InterfaceFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + front_ports: Annotated['FrontPortFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + rear_ports: Annotated['RearPortFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + device_bays: Annotated['DeviceBayFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + module_bays: Annotated['ModuleBayFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + modules: Annotated['ModuleFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + console_port_count: FilterLookup[int] | None = strawberry_django.filter_field() + console_server_port_count: FilterLookup[int] | None = strawberry_django.filter_field() + power_port_count: FilterLookup[int] | None = strawberry_django.filter_field() + power_outlet_count: FilterLookup[int] | None = strawberry_django.filter_field() + interface_count: FilterLookup[int] | None = strawberry_django.filter_field() + front_port_count: FilterLookup[int] | None = strawberry_django.filter_field() + rear_port_count: FilterLookup[int] | None = strawberry_django.filter_field() + device_bay_count: FilterLookup[int] | None = strawberry_django.filter_field() + module_bay_count: FilterLookup[int] | None = strawberry_django.filter_field() + inventory_item_count: FilterLookup[int] | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.DeviceBay, lookups=True) +class DeviceBayFilterV1(ComponentModelFilterMixinV1): + installed_device: Annotated['DeviceFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + installed_device_id: ID | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.DeviceBayTemplate, lookups=True) +class DeviceBayTemplateFilterV1(ComponentTemplateFilterMixinV1): + pass + + +@strawberry_django.filter_type(models.InventoryItemTemplate, lookups=True) +class InventoryItemTemplateFilterV1(ComponentTemplateFilterMixinV1): + parent: Annotated['InventoryItemTemplateFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + component_type: Annotated['ContentTypeFilterV1', strawberry.lazy('core.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + component_id: ID | None = strawberry_django.filter_field() + role: Annotated['InventoryItemRoleFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + role_id: ID | None = strawberry_django.filter_field() + manufacturer: Annotated['ManufacturerFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + manufacturer_id: ID | None = strawberry_django.filter_field() + part_id: FilterLookup[str] | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.DeviceRole, lookups=True) +class DeviceRoleFilterV1(OrganizationalModelFilterMixinV1, RenderConfigFilterMixinV1): + color: Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')] | None = strawberry_django.filter_field() + vm_role: FilterLookup[bool] | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.DeviceType, lookups=True) +class DeviceTypeFilterV1(ImageAttachmentFilterMixinV1, PrimaryModelFilterMixinV1, WeightFilterMixinV1): + manufacturer: Annotated['ManufacturerFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + manufacturer_id: ID | None = strawberry_django.filter_field() + model: FilterLookup[str] | None = strawberry_django.filter_field() + slug: FilterLookup[str] | None = strawberry_django.filter_field() + default_platform: Annotated['PlatformFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + default_platform_id: ID | None = strawberry_django.filter_field() + part_number: FilterLookup[str] | None = strawberry_django.filter_field() + u_height: Annotated['FloatLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + exclude_from_utilization: FilterLookup[bool] | None = strawberry_django.filter_field() + is_full_depth: FilterLookup[bool] | None = strawberry_django.filter_field() + subdevice_role: Annotated['SubdeviceRoleEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + airflow: Annotated['DeviceAirflowEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + front_image: Annotated['ImageAttachmentFilterV1', strawberry.lazy('extras.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + rear_image: Annotated['ImageAttachmentFilterV1', strawberry.lazy('extras.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + console_port_templates: ( + Annotated['ConsolePortTemplateFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None + ) = strawberry_django.filter_field() + console_server_port_templates: ( + Annotated['ConsoleServerPortTemplateFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None + ) = strawberry_django.filter_field() + power_port_templates: ( + Annotated['PowerPortTemplateFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None + ) = strawberry_django.filter_field() + power_outlet_templates: ( + Annotated['PowerOutletTemplateFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None + ) = strawberry_django.filter_field() + interface_templates: ( + Annotated['InterfaceTemplateFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None + ) = strawberry_django.filter_field() + front_port_templates: ( + Annotated['FrontPortTemplateFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None + ) = strawberry_django.filter_field() + rear_port_templates: ( + Annotated['RearPortTemplateFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None + ) = strawberry_django.filter_field() + device_bay_templates: ( + Annotated['DeviceBayTemplateFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None + ) = strawberry_django.filter_field() + module_bay_templates: ( + Annotated['ModuleBayTemplateFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None + ) = strawberry_django.filter_field() + inventory_item_templates: ( + Annotated['InventoryItemTemplateFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None + ) = strawberry_django.filter_field() + console_port_template_count: FilterLookup[int] | None = strawberry_django.filter_field() + console_server_port_template_count: FilterLookup[int] | None = strawberry_django.filter_field() + power_port_template_count: FilterLookup[int] | None = strawberry_django.filter_field() + power_outlet_template_count: FilterLookup[int] | None = strawberry_django.filter_field() + interface_template_count: FilterLookup[int] | None = strawberry_django.filter_field() + front_port_template_count: FilterLookup[int] | None = strawberry_django.filter_field() + rear_port_template_count: FilterLookup[int] | None = strawberry_django.filter_field() + device_bay_template_count: FilterLookup[int] | None = strawberry_django.filter_field() + module_bay_template_count: FilterLookup[int] | None = strawberry_django.filter_field() + inventory_item_template_count: FilterLookup[int] | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.FrontPort, lookups=True) +class FrontPortFilterV1(ModularComponentModelFilterMixinV1, CabledObjectModelFilterMixinV1): + type: Annotated['PortTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = strawberry_django.filter_field() + color: Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')] | None = strawberry_django.filter_field() + rear_port: Annotated['RearPortFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + rear_port_id: ID | None = strawberry_django.filter_field() + rear_port_position: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.FrontPortTemplate, lookups=True) +class FrontPortTemplateFilterV1(ModularComponentTemplateFilterMixinV1): + type: Annotated['PortTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = strawberry_django.filter_field() + color: Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')] | None = strawberry_django.filter_field() + rear_port: Annotated['RearPortTemplateFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + rear_port_id: ID | None = strawberry_django.filter_field() + rear_port_position: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.MACAddress, lookups=True) +class MACAddressFilterV1(PrimaryModelFilterMixinV1): + mac_address: FilterLookup[str] | None = strawberry_django.filter_field() + assigned_object_type: Annotated['ContentTypeFilterV1', strawberry.lazy('core.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + assigned_object_id: ID | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.Interface, lookups=True) +class InterfaceFilterV1(ModularComponentModelFilterMixinV1, InterfaceBaseFilterMixinV1, CabledObjectModelFilterMixinV1): + vcdcs: Annotated['VirtualDeviceContextFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + lag: Annotated['InterfaceFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + lag_id: ID | None = strawberry_django.filter_field() + type: Annotated['InterfaceTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + mgmt_only: FilterLookup[bool] | None = strawberry_django.filter_field() + speed: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + duplex: Annotated['InterfaceDuplexEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + wwn: FilterLookup[str] | None = strawberry_django.filter_field() + parent: Annotated['InterfaceFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + parent_id: ID | None = strawberry_django.filter_field() + rf_role: Annotated['WirelessRoleEnum', strawberry.lazy('wireless.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + rf_channel: Annotated['WirelessChannelEnum', strawberry.lazy('wireless.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + rf_channel_frequency: Annotated['FloatLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + rf_channel_width: Annotated['FloatLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + tx_power: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + poe_mode: Annotated['InterfacePoEModeEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + poe_type: Annotated['InterfacePoETypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + wireless_link: Annotated['WirelessLinkFilterV1', strawberry.lazy('wireless.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + wireless_link_id: ID | None = strawberry_django.filter_field() + wireless_lans: Annotated['WirelessLANFilterV1', strawberry.lazy('wireless.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + vrf: Annotated['VRFFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = strawberry_django.filter_field() + vrf_id: ID | None = strawberry_django.filter_field() + ip_addresses: Annotated['IPAddressFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + mac_addresses: Annotated['MACAddressFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + fhrp_group_assignments: Annotated[ + 'FHRPGroupAssignmentFilterV1', strawberry.lazy('ipam.graphql.filters_v1') + ] | None = ( + strawberry_django.filter_field() + ) + tunnel_terminations: Annotated['TunnelTerminationFilterV1', strawberry.lazy('vpn.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + l2vpn_terminations: Annotated['L2VPNFilterV1', strawberry.lazy('vpn.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + + @strawberry_django.filter_field + def connected(self, queryset, value: bool, prefix: str): + if value is True: + return queryset, Q(**{f"{prefix}_path__is_active": True}) + else: + return queryset, Q(**{f"{prefix}_path__isnull": True}) | Q(**{f"{prefix}_path__is_active": False}) + + @strawberry_django.filter_field + def kind( + self, + queryset, + value: Annotated['InterfaceKindEnum', strawberry.lazy('dcim.graphql.enums')], + prefix: str + ): + if value == InterfaceKindEnum.KIND_PHYSICAL: + return queryset, ~Q(**{f"{prefix}type__in": NONCONNECTABLE_IFACE_TYPES}) + elif value == InterfaceKindEnum.KIND_VIRTUAL: + return queryset, Q(**{f"{prefix}type__in": VIRTUAL_IFACE_TYPES}) + elif value == InterfaceKindEnum.KIND_WIRELESS: + return queryset, Q(**{f"{prefix}type__in": WIRELESS_IFACE_TYPES}) + + +@strawberry_django.filter_type(models.InterfaceTemplate, lookups=True) +class InterfaceTemplateFilterV1(ModularComponentTemplateFilterMixinV1): + type: Annotated['InterfaceTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + enabled: FilterLookup[bool] | None = strawberry_django.filter_field() + mgmt_only: FilterLookup[bool] | None = strawberry_django.filter_field() + bridge: Annotated['InterfaceTemplateFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + bridge_id: ID | None = strawberry_django.filter_field() + poe_mode: Annotated['InterfacePoEModeEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + poe_type: Annotated['InterfacePoETypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + rf_role: Annotated['WirelessRoleEnum', strawberry.lazy('wireless.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.InventoryItem, lookups=True) +class InventoryItemFilterV1(ComponentModelFilterMixinV1): + parent: Annotated['InventoryItemFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + parent_id: ID | None = strawberry_django.filter_field() + component_type: Annotated['ContentTypeFilterV1', strawberry.lazy('core.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + component_id: ID | None = strawberry_django.filter_field() + status: Annotated['InventoryItemStatusEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + role: Annotated['InventoryItemRoleFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + role_id: ID | None = strawberry_django.filter_field() + manufacturer: Annotated['ManufacturerFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + manufacturer_id: ID | None = strawberry_django.filter_field() + part_id: FilterLookup[str] | None = strawberry_django.filter_field() + serial: FilterLookup[str] | None = strawberry_django.filter_field() + asset_tag: FilterLookup[str] | None = strawberry_django.filter_field() + discovered: FilterLookup[bool] | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.InventoryItemRole, lookups=True) +class InventoryItemRoleFilterV1(OrganizationalModelFilterMixinV1): + color: Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')] | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.Location, lookups=True) +class LocationFilterV1( + ContactFilterMixinV1, ImageAttachmentFilterMixinV1, TenancyFilterMixinV1, NestedGroupModelFilterMixinV1 +): + site: Annotated['SiteFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + site_id: ID | None = strawberry_django.filter_field() + status: Annotated['LocationStatusEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + facility: FilterLookup[str] | None = strawberry_django.filter_field() + prefixes: Annotated['PrefixFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + vlan_groups: Annotated['VLANGroupFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.Manufacturer, lookups=True) +class ManufacturerFilterV1(ContactFilterMixinV1, OrganizationalModelFilterMixinV1): + pass + + +@strawberry_django.filter_type(models.Module, lookups=True) +class ModuleFilterV1(PrimaryModelFilterMixinV1, ConfigContextFilterMixinV1): + device: Annotated['DeviceFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + device_id: ID | None = strawberry_django.filter_field() + module_bay: Annotated['ModuleBayFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + module_bay_id: ID | None = strawberry_django.filter_field() + module_type: Annotated['ModuleTypeFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + module_type_id: ID | None = strawberry_django.filter_field() + status: Annotated['ModuleStatusEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + serial: FilterLookup[str] | None = strawberry_django.filter_field() + asset_tag: FilterLookup[str] | None = strawberry_django.filter_field() + console_ports: Annotated['ConsolePortFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + console_server_ports: Annotated['ConsoleServerPortFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + power_outlets: Annotated['PowerOutletFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + power_ports: Annotated['PowerPortFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + interfaces: Annotated['InterfaceFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + front_ports: Annotated['FrontPortFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + rear_ports: Annotated['RearPortFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + device_bays: Annotated['DeviceBayFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + module_bays: Annotated['ModuleBayFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + modules: Annotated['ModuleFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.ModuleBay, lookups=True) +class ModuleBayFilterV1(ModularComponentModelFilterMixinV1): + parent: Annotated['ModuleBayFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + parent_id: ID | None = strawberry_django.filter_field() + position: FilterLookup[str] | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.ModuleBayTemplate, lookups=True) +class ModuleBayTemplateFilterV1(ModularComponentTemplateFilterMixinV1): + position: FilterLookup[str] | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.ModuleTypeProfile, lookups=True) +class ModuleTypeProfileFilterV1(PrimaryModelFilterMixinV1): + name: FilterLookup[str] | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.ModuleType, lookups=True) +class ModuleTypeFilterV1(ImageAttachmentFilterMixinV1, PrimaryModelFilterMixinV1, WeightFilterMixinV1): + manufacturer: Annotated['ManufacturerFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + manufacturer_id: ID | None = strawberry_django.filter_field() + profile: Annotated['ModuleTypeProfileFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + profile_id: ID | None = strawberry_django.filter_field() + model: FilterLookup[str] | None = strawberry_django.filter_field() + part_number: FilterLookup[str] | None = strawberry_django.filter_field() + airflow: Annotated['ModuleAirflowEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + console_port_templates: ( + Annotated['ConsolePortTemplateFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None + ) = strawberry_django.filter_field() + console_server_port_templates: ( + Annotated['ConsoleServerPortTemplateFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None + ) = strawberry_django.filter_field() + power_port_templates: ( + Annotated['PowerPortTemplateFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None + ) = strawberry_django.filter_field() + power_outlet_templates: ( + Annotated['PowerOutletTemplateFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None + ) = strawberry_django.filter_field() + interface_templates: ( + Annotated['InterfaceTemplateFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None + ) = strawberry_django.filter_field() + front_port_templates: ( + Annotated['FrontPortTemplateFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None + ) = strawberry_django.filter_field() + rear_port_templates: ( + Annotated['RearPortTemplateFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None + ) = strawberry_django.filter_field() + device_bay_templates: ( + Annotated['DeviceBayTemplateFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None + ) = strawberry_django.filter_field() + module_bay_templates: ( + Annotated['ModuleBayTemplateFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None + ) = strawberry_django.filter_field() + inventory_item_templates: ( + Annotated['InventoryItemTemplateFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None + ) = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.Platform, lookups=True) +class PlatformFilterV1(OrganizationalModelFilterMixinV1): + manufacturer: Annotated['ManufacturerFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + manufacturer_id: ID | None = strawberry_django.filter_field() + config_template: Annotated['ConfigTemplateFilterV1', strawberry.lazy('extras.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + config_template_id: ID | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.PowerFeed, lookups=True) +class PowerFeedFilterV1(CabledObjectModelFilterMixinV1, TenancyFilterMixinV1, PrimaryModelFilterMixinV1): + power_panel: Annotated['PowerPanelFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + power_panel_id: ID | None = strawberry_django.filter_field() + rack: Annotated['RackFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + rack_id: ID | None = strawberry_django.filter_field() + name: FilterLookup[str] | None = strawberry_django.filter_field() + status: Annotated['PowerFeedStatusEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + type: Annotated['PowerFeedTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + supply: Annotated['PowerFeedSupplyEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + phase: Annotated['PowerFeedPhaseEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + voltage: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + amperage: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + max_utilization: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + available_power: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.PowerOutlet, lookups=True) +class PowerOutletFilterV1(ModularComponentModelFilterMixinV1, CabledObjectModelFilterMixinV1): + type: Annotated['PowerOutletTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + power_port: Annotated['PowerPortFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + power_port_id: ID | None = strawberry_django.filter_field() + feed_leg: Annotated['PowerOutletFeedLegEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + color: Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')] | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.PowerOutletTemplate, lookups=True) +class PowerOutletTemplateFilterV1(ModularComponentModelFilterMixinV1): + type: Annotated['PowerOutletTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + power_port: Annotated['PowerPortTemplateFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + power_port_id: ID | None = strawberry_django.filter_field() + feed_leg: Annotated['PowerOutletFeedLegEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.PowerPanel, lookups=True) +class PowerPanelFilterV1(ContactFilterMixinV1, ImageAttachmentFilterMixinV1, PrimaryModelFilterMixinV1): + site: Annotated['SiteFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + site_id: ID | None = strawberry_django.filter_field() + location: Annotated['LocationFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + location_id: Annotated['TreeNodeFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + name: FilterLookup[str] | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.PowerPort, lookups=True) +class PowerPortFilterV1(ModularComponentModelFilterMixinV1, CabledObjectModelFilterMixinV1): + type: Annotated['PowerPortTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + maximum_draw: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + allocated_draw: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.PowerPortTemplate, lookups=True) +class PowerPortTemplateFilterV1(ModularComponentTemplateFilterMixinV1): + type: Annotated['PowerPortTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + maximum_draw: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + allocated_draw: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.RackType, lookups=True) +class RackTypeFilterV1(RackBaseFilterMixinV1): + form_factor: Annotated['RackFormFactorEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + manufacturer: Annotated['ManufacturerFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + manufacturer_id: ID | None = strawberry_django.filter_field() + model: FilterLookup[str] | None = strawberry_django.filter_field() + slug: FilterLookup[str] | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.Rack, lookups=True) +class RackFilterV1(ContactFilterMixinV1, ImageAttachmentFilterMixinV1, TenancyFilterMixinV1, RackBaseFilterMixinV1): + form_factor: Annotated['RackFormFactorEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + rack_type: Annotated['RackTypeFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + rack_type_id: ID | None = strawberry_django.filter_field() + name: FilterLookup[str] | None = strawberry_django.filter_field() + facility_id: FilterLookup[str] | None = strawberry_django.filter_field() + site: Annotated['SiteFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + site_id: ID | None = strawberry_django.filter_field() + location: Annotated['LocationFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + location_id: Annotated['TreeNodeFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + status: Annotated['RackStatusEnum', strawberry.lazy('dcim.graphql.enums')] | None = strawberry_django.filter_field() + role: Annotated['RackRoleFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + role_id: ID | None = strawberry_django.filter_field() + serial: FilterLookup[str] | None = strawberry_django.filter_field() + asset_tag: FilterLookup[str] | None = strawberry_django.filter_field() + airflow: Annotated['RackAirflowEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + vlan_groups: Annotated['VLANGroupFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.RackReservation, lookups=True) +class RackReservationFilterV1(TenancyFilterMixinV1, PrimaryModelFilterMixinV1): + rack: Annotated['RackFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + rack_id: ID | None = strawberry_django.filter_field() + units: Annotated['IntegerArrayLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + user: Annotated['UserFilterV1', strawberry.lazy('users.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + user_id: ID | None = strawberry_django.filter_field() + description: FilterLookup[str] | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.RackRole, lookups=True) +class RackRoleFilterV1(OrganizationalModelFilterMixinV1): + color: Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')] | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.RearPort, lookups=True) +class RearPortFilterV1(ModularComponentModelFilterMixinV1, CabledObjectModelFilterMixinV1): + type: Annotated['PortTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = strawberry_django.filter_field() + color: Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')] | None = strawberry_django.filter_field() + positions: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.RearPortTemplate, lookups=True) +class RearPortTemplateFilterV1(ModularComponentTemplateFilterMixinV1): + type: Annotated['PortTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = strawberry_django.filter_field() + color: Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')] | None = strawberry_django.filter_field() + positions: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.Region, lookups=True) +class RegionFilterV1(ContactFilterMixinV1, NestedGroupModelFilterMixinV1): + prefixes: Annotated['PrefixFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + vlan_groups: Annotated['VLANGroupFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.Site, lookups=True) +class SiteFilterV1(ContactFilterMixinV1, ImageAttachmentFilterMixinV1, TenancyFilterMixinV1, PrimaryModelFilterMixinV1): + name: FilterLookup[str] | None = strawberry_django.filter_field() + slug: FilterLookup[str] | None = strawberry_django.filter_field() + status: Annotated['SiteStatusEnum', strawberry.lazy('dcim.graphql.enums')] | None = strawberry_django.filter_field() + region: Annotated['RegionFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + region_id: Annotated['TreeNodeFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + group: Annotated['SiteGroupFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + group_id: Annotated['TreeNodeFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + facility: FilterLookup[str] | None = strawberry_django.filter_field() + asns: Annotated['ASNFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = strawberry_django.filter_field() + time_zone: FilterLookup[str] | None = strawberry_django.filter_field() + physical_address: FilterLookup[str] | None = strawberry_django.filter_field() + shipping_address: FilterLookup[str] | None = strawberry_django.filter_field() + latitude: Annotated['FloatLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + longitude: Annotated['FloatLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + prefixes: Annotated['PrefixFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + vlan_groups: Annotated['VLANGroupFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.SiteGroup, lookups=True) +class SiteGroupFilterV1(ContactFilterMixinV1, NestedGroupModelFilterMixinV1): + prefixes: Annotated['PrefixFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + vlan_groups: Annotated['VLANGroupFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.VirtualChassis, lookups=True) +class VirtualChassisFilterV1(PrimaryModelFilterMixinV1): + master: Annotated['DeviceFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + master_id: ID | None = strawberry_django.filter_field() + name: FilterLookup[str] | None = strawberry_django.filter_field() + domain: FilterLookup[str] | None = strawberry_django.filter_field() + members: ( + Annotated['DeviceFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None + ) = strawberry_django.filter_field() + member_count: FilterLookup[int] | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.VirtualDeviceContext, lookups=True) +class VirtualDeviceContextFilterV1(TenancyFilterMixinV1, PrimaryModelFilterMixinV1): + device: Annotated['DeviceFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + device_id: ID | None = strawberry_django.filter_field() + name: FilterLookup[str] | None = strawberry_django.filter_field() + status: Annotated['VirtualDeviceContextStatusEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + identifier: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + primary_ip4: Annotated['IPAddressFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + primary_ip4_id: ID | None = strawberry_django.filter_field() + primary_ip6: Annotated['IPAddressFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + primary_ip6_id: ID | None = strawberry_django.filter_field() + comments: FilterLookup[str] | None = strawberry_django.filter_field() + interfaces: ( + Annotated['InterfaceFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None + ) = strawberry_django.filter_field() diff --git a/netbox/dcim/graphql/gfk_mixins_v1.py b/netbox/dcim/graphql/gfk_mixins_v1.py new file mode 100644 index 0000000000..378b3a916c --- /dev/null +++ b/netbox/dcim/graphql/gfk_mixins_v1.py @@ -0,0 +1,137 @@ +from strawberry.types import Info + +from circuits.graphql.types_v1 import CircuitTerminationTypeV1, ProviderNetworkTypeV1 +from circuits.models import CircuitTermination, ProviderNetwork +from dcim.graphql.types_v1 import ( + ConsolePortTemplateTypeV1, + ConsolePortTypeV1, + ConsoleServerPortTemplateTypeV1, + ConsoleServerPortTypeV1, + FrontPortTemplateTypeV1, + FrontPortTypeV1, + InterfaceTemplateTypeV1, + InterfaceTypeV1, + PowerFeedTypeV1, + PowerOutletTemplateTypeV1, + PowerOutletTypeV1, + PowerPortTemplateTypeV1, + PowerPortTypeV1, + RearPortTemplateTypeV1, + RearPortTypeV1, +) +from dcim.models import ( + ConsolePort, + ConsolePortTemplate, + ConsoleServerPort, + ConsoleServerPortTemplate, + FrontPort, + FrontPortTemplate, + Interface, + InterfaceTemplate, + PowerFeed, + PowerOutlet, + PowerOutletTemplate, + PowerPort, + PowerPortTemplate, + RearPort, + RearPortTemplate, +) + + +class InventoryItemTemplateComponentTypeV1: + class Meta: + types = ( + ConsolePortTemplateTypeV1, + ConsoleServerPortTemplateTypeV1, + FrontPortTemplateTypeV1, + InterfaceTemplateTypeV1, + PowerOutletTemplateTypeV1, + PowerPortTemplateTypeV1, + RearPortTemplateTypeV1, + ) + + @classmethod + def resolve_type(cls, instance, info: Info): + if type(instance) is ConsolePortTemplate: + return ConsolePortTemplateTypeV1 + if type(instance) is ConsoleServerPortTemplate: + return ConsoleServerPortTemplateTypeV1 + if type(instance) is FrontPortTemplate: + return FrontPortTemplateTypeV1 + if type(instance) is InterfaceTemplate: + return InterfaceTemplateTypeV1 + if type(instance) is PowerOutletTemplate: + return PowerOutletTemplateTypeV1 + if type(instance) is PowerPortTemplate: + return PowerPortTemplateTypeV1 + if type(instance) is RearPortTemplate: + return RearPortTemplateTypeV1 + + +class InventoryItemComponentTypeV1: + class Meta: + types = ( + ConsolePortTypeV1, + ConsoleServerPortTypeV1, + FrontPortTypeV1, + InterfaceTypeV1, + PowerOutletTypeV1, + PowerPortTypeV1, + RearPortTypeV1, + ) + + @classmethod + def resolve_type(cls, instance, info: Info): + if type(instance) is ConsolePort: + return ConsolePortTypeV1 + if type(instance) is ConsoleServerPort: + return ConsoleServerPortTypeV1 + if type(instance) is FrontPort: + return FrontPortTypeV1 + if type(instance) is Interface: + return InterfaceTypeV1 + if type(instance) is PowerOutlet: + return PowerOutletTypeV1 + if type(instance) is PowerPort: + return PowerPortTypeV1 + if type(instance) is RearPort: + return RearPortTypeV1 + + +class ConnectedEndpointTypeV1: + class Meta: + types = ( + CircuitTerminationTypeV1, + ConsolePortTypeV1, + ConsoleServerPortTypeV1, + FrontPortTypeV1, + InterfaceTypeV1, + PowerFeedTypeV1, + PowerOutletTypeV1, + PowerPortTypeV1, + ProviderNetworkTypeV1, + RearPortTypeV1, + ) + + @classmethod + def resolve_type(cls, instance, info: Info): + if type(instance) is CircuitTermination: + return CircuitTerminationTypeV1 + if type(instance) is ConsolePort: + return ConsolePortTypeV1 + if type(instance) is ConsoleServerPort: + return ConsoleServerPortTypeV1 + if type(instance) is FrontPort: + return FrontPortTypeV1 + if type(instance) is Interface: + return InterfaceTypeV1 + if type(instance) is PowerFeed: + return PowerFeedTypeV1 + if type(instance) is PowerOutlet: + return PowerOutletTypeV1 + if type(instance) is PowerPort: + return PowerPortTypeV1 + if type(instance) is ProviderNetwork: + return ProviderNetworkTypeV1 + if type(instance) is RearPort: + return RearPortTypeV1 diff --git a/netbox/dcim/graphql/mixins_v1.py b/netbox/dcim/graphql/mixins_v1.py new file mode 100644 index 0000000000..694283e3cc --- /dev/null +++ b/netbox/dcim/graphql/mixins_v1.py @@ -0,0 +1,43 @@ +from typing import Annotated, List, Union + +import strawberry + +__all__ = ( + 'CabledObjectMixinV1', + 'PathEndpointMixinV1', +) + + +@strawberry.type +class CabledObjectMixinV1: + cable: Annotated["CableTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None # noqa: F821 + + link_peers: List[Annotated[Union[ + Annotated["CircuitTerminationTypeV1", strawberry.lazy('circuits.graphql.types_v1')], # noqa: F821 + Annotated["ConsolePortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], # noqa: F821 + Annotated["ConsoleServerPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], # noqa: F821 + Annotated["FrontPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], # noqa: F821 + Annotated["InterfaceTypeV1", strawberry.lazy('dcim.graphql.types_v1')], # noqa: F821 + Annotated["PowerFeedTypeV1", strawberry.lazy('dcim.graphql.types_v1')], # noqa: F821 + Annotated["PowerOutletTypeV1", strawberry.lazy('dcim.graphql.types_v1')], # noqa: F821 + Annotated["PowerPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], # noqa: F821 + Annotated["RearPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], # noqa: F821 + ], strawberry.union("LinkPeerType")]] + + +@strawberry.type +class PathEndpointMixinV1: + + connected_endpoints: List[Annotated[Union[ + Annotated["CircuitTerminationTypeV1", strawberry.lazy('circuits.graphql.types_v1')], # noqa: F821 + Annotated["VirtualCircuitTerminationTypeV1", strawberry.lazy('circuits.graphql.types_v1')], # noqa: F821 + Annotated["ConsolePortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], # noqa: F821 + Annotated["ConsoleServerPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], # noqa: F821 + Annotated["FrontPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], # noqa: F821 + Annotated["InterfaceTypeV1", strawberry.lazy('dcim.graphql.types_v1')], # noqa: F821 + Annotated["PowerFeedTypeV1", strawberry.lazy('dcim.graphql.types_v1')], # noqa: F821 + Annotated["PowerOutletTypeV1", strawberry.lazy('dcim.graphql.types_v1')], # noqa: F821 + Annotated["PowerPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], # noqa: F821 + Annotated["ProviderNetworkTypeV1", strawberry.lazy('circuits.graphql.types_v1')], # noqa: F821 + Annotated["RearPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], # noqa: F821 + ], strawberry.union("ConnectedEndpointTypeV1")]] diff --git a/netbox/dcim/graphql/schema_v1.py b/netbox/dcim/graphql/schema_v1.py new file mode 100644 index 0000000000..29d2f09ba9 --- /dev/null +++ b/netbox/dcim/graphql/schema_v1.py @@ -0,0 +1,138 @@ +from typing import List + +import strawberry +import strawberry_django + +from .types_v1 import * + + +@strawberry.type(name="Query") +class DCIMQueryV1: + cable: CableTypeV1 = strawberry_django.field() + cable_list: List[CableTypeV1] = strawberry_django.field() + + console_port: ConsolePortTypeV1 = strawberry_django.field() + console_port_list: List[ConsolePortTypeV1] = strawberry_django.field() + + console_port_template: ConsolePortTemplateTypeV1 = strawberry_django.field() + console_port_template_list: List[ConsolePortTemplateTypeV1] = strawberry_django.field() + + console_server_port: ConsoleServerPortTypeV1 = strawberry_django.field() + console_server_port_list: List[ConsoleServerPortTypeV1] = strawberry_django.field() + + console_server_port_template: ConsoleServerPortTemplateTypeV1 = strawberry_django.field() + console_server_port_template_list: List[ConsoleServerPortTemplateTypeV1] = strawberry_django.field() + + device: DeviceTypeV1 = strawberry_django.field() + device_list: List[DeviceTypeV1] = strawberry_django.field() + + device_bay: DeviceBayTypeV1 = strawberry_django.field() + device_bay_list: List[DeviceBayTypeV1] = strawberry_django.field() + + device_bay_template: DeviceBayTemplateTypeV1 = strawberry_django.field() + device_bay_template_list: List[DeviceBayTemplateTypeV1] = strawberry_django.field() + + device_role: DeviceRoleTypeV1 = strawberry_django.field() + device_role_list: List[DeviceRoleTypeV1] = strawberry_django.field() + + device_type: DeviceTypeTypeV1 = strawberry_django.field() + device_type_list: List[DeviceTypeTypeV1] = strawberry_django.field() + + front_port: FrontPortTypeV1 = strawberry_django.field() + front_port_list: List[FrontPortTypeV1] = strawberry_django.field() + + front_port_template: FrontPortTemplateTypeV1 = strawberry_django.field() + front_port_template_list: List[FrontPortTemplateTypeV1] = strawberry_django.field() + + mac_address: MACAddressTypeV1 = strawberry_django.field() + mac_address_list: List[MACAddressTypeV1] = strawberry_django.field() + + interface: InterfaceTypeV1 = strawberry_django.field() + interface_list: List[InterfaceTypeV1] = strawberry_django.field() + + interface_template: InterfaceTemplateTypeV1 = strawberry_django.field() + interface_template_list: List[InterfaceTemplateTypeV1] = strawberry_django.field() + + inventory_item: InventoryItemTypeV1 = strawberry_django.field() + inventory_item_list: List[InventoryItemTypeV1] = strawberry_django.field() + + inventory_item_role: InventoryItemRoleTypeV1 = strawberry_django.field() + inventory_item_role_list: List[InventoryItemRoleTypeV1] = strawberry_django.field() + + inventory_item_template: InventoryItemTemplateTypeV1 = strawberry_django.field() + inventory_item_template_list: List[InventoryItemTemplateTypeV1] = strawberry_django.field() + + location: LocationTypeV1 = strawberry_django.field() + location_list: List[LocationTypeV1] = strawberry_django.field() + + manufacturer: ManufacturerTypeV1 = strawberry_django.field() + manufacturer_list: List[ManufacturerTypeV1] = strawberry_django.field() + + module: ModuleTypeV1 = strawberry_django.field() + module_list: List[ModuleTypeV1] = strawberry_django.field() + + module_bay: ModuleBayTypeV1 = strawberry_django.field() + module_bay_list: List[ModuleBayTypeV1] = strawberry_django.field() + + module_bay_template: ModuleBayTemplateTypeV1 = strawberry_django.field() + module_bay_template_list: List[ModuleBayTemplateTypeV1] = strawberry_django.field() + + module_type_profile: ModuleTypeProfileTypeV1 = strawberry_django.field() + module_type_profile_list: List[ModuleTypeProfileTypeV1] = strawberry_django.field() + + module_type: ModuleTypeTypeV1 = strawberry_django.field() + module_type_list: List[ModuleTypeTypeV1] = strawberry_django.field() + + platform: PlatformTypeV1 = strawberry_django.field() + platform_list: List[PlatformTypeV1] = strawberry_django.field() + + power_feed: PowerFeedTypeV1 = strawberry_django.field() + power_feed_list: List[PowerFeedTypeV1] = strawberry_django.field() + + power_outlet: PowerOutletTypeV1 = strawberry_django.field() + power_outlet_list: List[PowerOutletTypeV1] = strawberry_django.field() + + power_outlet_template: PowerOutletTemplateTypeV1 = strawberry_django.field() + power_outlet_template_list: List[PowerOutletTemplateTypeV1] = strawberry_django.field() + + power_panel: PowerPanelTypeV1 = strawberry_django.field() + power_panel_list: List[PowerPanelTypeV1] = strawberry_django.field() + + power_port: PowerPortTypeV1 = strawberry_django.field() + power_port_list: List[PowerPortTypeV1] = strawberry_django.field() + + power_port_template: PowerPortTemplateTypeV1 = strawberry_django.field() + power_port_template_list: List[PowerPortTemplateTypeV1] = strawberry_django.field() + + rack_type: RackTypeTypeV1 = strawberry_django.field() + rack_type_list: List[RackTypeTypeV1] = strawberry_django.field() + + rack: RackTypeV1 = strawberry_django.field() + rack_list: List[RackTypeV1] = strawberry_django.field() + + rack_reservation: RackReservationTypeV1 = strawberry_django.field() + rack_reservation_list: List[RackReservationTypeV1] = strawberry_django.field() + + rack_role: RackRoleTypeV1 = strawberry_django.field() + rack_role_list: List[RackRoleTypeV1] = strawberry_django.field() + + rear_port: RearPortTypeV1 = strawberry_django.field() + rear_port_list: List[RearPortTypeV1] = strawberry_django.field() + + rear_port_template: RearPortTemplateTypeV1 = strawberry_django.field() + rear_port_template_list: List[RearPortTemplateTypeV1] = strawberry_django.field() + + region: RegionTypeV1 = strawberry_django.field() + region_list: List[RegionTypeV1] = strawberry_django.field() + + site: SiteTypeV1 = strawberry_django.field() + site_list: List[SiteTypeV1] = strawberry_django.field() + + site_group: SiteGroupTypeV1 = strawberry_django.field() + site_group_list: List[SiteGroupTypeV1] = strawberry_django.field() + + virtual_chassis: VirtualChassisTypeV1 = strawberry_django.field() + virtual_chassis_list: List[VirtualChassisTypeV1] = strawberry_django.field() + + virtual_device_context: VirtualDeviceContextTypeV1 = strawberry_django.field() + virtual_device_context_list: List[VirtualDeviceContextTypeV1] = strawberry_django.field() diff --git a/netbox/dcim/graphql/types_v1.py b/netbox/dcim/graphql/types_v1.py new file mode 100644 index 0000000000..c7f069ecbd --- /dev/null +++ b/netbox/dcim/graphql/types_v1.py @@ -0,0 +1,906 @@ +from typing import Annotated, List, TYPE_CHECKING, Union + +import strawberry +import strawberry_django + +from core.graphql.mixins_v1 import ChangelogMixinV1 +from dcim import models +from extras.graphql.mixins_v1 import ( + ConfigContextMixinV1, + ContactsMixinV1, + CustomFieldsMixinV1, + ImageAttachmentsMixinV1, + TagsMixinV1, +) +from ipam.graphql.mixins_v1 import IPAddressesMixinV1, VLANGroupsMixinV1 +from netbox.graphql.scalars import BigInt +from netbox.graphql.types_v1 import BaseObjectTypeV1, NetBoxObjectTypeV1, OrganizationalObjectTypeV1 +from .filters_v1 import * +from .mixins_v1 import CabledObjectMixinV1, PathEndpointMixinV1 + +if TYPE_CHECKING: + from circuits.graphql.types_v1 import CircuitTerminationTypeV1 + from extras.graphql.types_v1 import ConfigTemplateTypeV1 + from ipam.graphql.types_v1 import ( + ASNTypeV1, + IPAddressTypeV1, + PrefixTypeV1, + ServiceTypeV1, + VLANTranslationPolicyTypeV1, + VLANTypeV1, + VRFTypeV1, + ) + from tenancy.graphql.types_v1 import TenantTypeV1 + from users.graphql.types_v1 import UserTypeV1 + from virtualization.graphql.types_v1 import ClusterTypeV1, VMInterfaceTypeV1, VirtualMachineTypeV1 + from vpn.graphql.types_v1 import L2VPNTerminationTypeV1 + from wireless.graphql.types_v1 import WirelessLANTypeV1, WirelessLinkTypeV1 + +__all__ = ( + 'CableTypeV1', + 'ComponentTypeV1', + 'ConsolePortTypeV1', + 'ConsolePortTemplateTypeV1', + 'ConsoleServerPortTypeV1', + 'ConsoleServerPortTemplateTypeV1', + 'DeviceTypeV1', + 'DeviceBayTypeV1', + 'DeviceBayTemplateTypeV1', + 'DeviceRoleTypeV1', + 'DeviceTypeTypeV1', + 'FrontPortTypeV1', + 'FrontPortTemplateTypeV1', + 'InterfaceTypeV1', + 'InterfaceTemplateTypeV1', + 'InventoryItemTypeV1', + 'InventoryItemRoleTypeV1', + 'InventoryItemTemplateTypeV1', + 'LocationTypeV1', + 'MACAddressTypeV1', + 'ManufacturerTypeV1', + 'ModularComponentTypeV1', + 'ModuleTypeV1', + 'ModuleBayTypeV1', + 'ModuleBayTemplateTypeV1', + 'ModuleTypeProfileTypeV1', + 'ModuleTypeTypeV1', + 'PlatformTypeV1', + 'PowerFeedTypeV1', + 'PowerOutletTypeV1', + 'PowerOutletTemplateTypeV1', + 'PowerPanelTypeV1', + 'PowerPortTypeV1', + 'PowerPortTemplateTypeV1', + 'RackTypeV1', + 'RackReservationTypeV1', + 'RackRoleTypeV1', + 'RackTypeTypeV1', + 'RearPortTypeV1', + 'RearPortTemplateTypeV1', + 'RegionTypeV1', + 'SiteTypeV1', + 'SiteGroupTypeV1', + 'VirtualChassisTypeV1', + 'VirtualDeviceContextTypeV1', +) + + +# +# Base types +# + + +@strawberry.type +class ComponentTypeV1( + ChangelogMixinV1, + CustomFieldsMixinV1, + TagsMixinV1, + BaseObjectTypeV1 +): + """ + Base type for device/VM components + """ + device: Annotated["DeviceTypeV1", strawberry.lazy('dcim.graphql.types_v1')] + + +@strawberry.type +class ModularComponentTypeV1(ComponentTypeV1): + module: Annotated["ModuleTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + + +@strawberry.type +class ComponentTemplateTypeV1( + ChangelogMixinV1, + BaseObjectTypeV1 +): + """ + Base type for device/VM components + """ + device_type: Annotated["DeviceTypeTypeV1", strawberry.lazy('dcim.graphql.types_v1')] + + +@strawberry.type +class ModularComponentTemplateTypeV1(ComponentTemplateTypeV1): + """ + Base type for ComponentTemplateModel which supports optional assignment to a ModuleType. + """ + device_type: Annotated["DeviceTypeTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + module_type: Annotated["ModuleTypeTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + +# +# Model types +# + + +@strawberry_django.type( + models.CableTermination, + exclude=['termination_type', 'termination_id', '_device', '_rack', '_location', '_site'], + filters=CableTerminationFilterV1, + pagination=True +) +class CableTerminationTypeV1(NetBoxObjectTypeV1): + cable: Annotated["CableTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + termination: Annotated[Union[ + Annotated["CircuitTerminationTypeV1", strawberry.lazy('circuits.graphql.types_v1')], + Annotated["ConsolePortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["ConsoleServerPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["FrontPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["InterfaceTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["PowerFeedTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["PowerOutletTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["PowerPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["RearPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + ], strawberry.union("CableTerminationTerminationTypeV1")] | None + + +@strawberry_django.type( + models.Cable, + fields='__all__', + filters=CableFilterV1, + pagination=True +) +class CableTypeV1(NetBoxObjectTypeV1): + color: str + tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None + + terminations: List[CableTerminationTypeV1] + + a_terminations: List[Annotated[Union[ + Annotated["CircuitTerminationTypeV1", strawberry.lazy('circuits.graphql.types_v1')], + Annotated["ConsolePortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["ConsoleServerPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["FrontPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["InterfaceTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["PowerFeedTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["PowerOutletTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["PowerPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["RearPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + ], strawberry.union("CableTerminationTerminationTypeV1")]] + + b_terminations: List[Annotated[Union[ + Annotated["CircuitTerminationTypeV1", strawberry.lazy('circuits.graphql.types_v1')], + Annotated["ConsolePortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["ConsoleServerPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["FrontPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["InterfaceTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["PowerFeedTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["PowerOutletTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["PowerPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["RearPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + ], strawberry.union("CableTerminationTerminationTypeV1")]] + + +@strawberry_django.type( + models.ConsolePort, + exclude=['_path'], + filters=ConsolePortFilterV1, + pagination=True +) +class ConsolePortTypeV1(ModularComponentTypeV1, CabledObjectMixinV1, PathEndpointMixinV1): + pass + + +@strawberry_django.type( + models.ConsolePortTemplate, + fields='__all__', + filters=ConsolePortTemplateFilterV1, + pagination=True +) +class ConsolePortTemplateTypeV1(ModularComponentTemplateTypeV1): + pass + + +@strawberry_django.type( + models.ConsoleServerPort, + exclude=['_path'], + filters=ConsoleServerPortFilterV1, + pagination=True +) +class ConsoleServerPortTypeV1(ModularComponentTypeV1, CabledObjectMixinV1, PathEndpointMixinV1): + pass + + +@strawberry_django.type( + models.ConsoleServerPortTemplate, + fields='__all__', + filters=ConsoleServerPortTemplateFilterV1, + pagination=True +) +class ConsoleServerPortTemplateTypeV1(ModularComponentTemplateTypeV1): + pass + + +@strawberry_django.type( + models.Device, + fields='__all__', + filters=DeviceFilterV1, + pagination=True +) +class DeviceTypeV1(ConfigContextMixinV1, ImageAttachmentsMixinV1, ContactsMixinV1, NetBoxObjectTypeV1): + console_port_count: BigInt + console_server_port_count: BigInt + power_port_count: BigInt + power_outlet_count: BigInt + interface_count: BigInt + front_port_count: BigInt + rear_port_count: BigInt + device_bay_count: BigInt + module_bay_count: BigInt + inventory_item_count: BigInt + config_template: Annotated["ConfigTemplateTypeV1", strawberry.lazy('extras.graphql.types_v1')] | None + device_type: Annotated["DeviceTypeTypeV1", strawberry.lazy('dcim.graphql.types_v1')] + role: Annotated["DeviceRoleTypeV1", strawberry.lazy('dcim.graphql.types_v1')] + tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None + platform: Annotated["PlatformTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + site: Annotated["SiteTypeV1", strawberry.lazy('dcim.graphql.types_v1')] + location: Annotated["LocationTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + rack: Annotated["RackTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + primary_ip4: Annotated["IPAddressTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None + primary_ip6: Annotated["IPAddressTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None + oob_ip: Annotated["IPAddressTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None + cluster: Annotated["ClusterTypeV1", strawberry.lazy('virtualization.graphql.types_v1')] | None + virtual_chassis: Annotated["VirtualChassisTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + + virtual_machines: List[Annotated["VirtualMachineTypeV1", strawberry.lazy('virtualization.graphql.types_v1')]] + modules: List[Annotated["ModuleTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + interfaces: List[Annotated["InterfaceTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + rearports: List[Annotated["RearPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + consoleports: List[Annotated["ConsolePortTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + powerports: List[Annotated["PowerPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + cabletermination_set: List[Annotated["CableTerminationTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + consoleserverports: List[Annotated["ConsoleServerPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + poweroutlets: List[Annotated["PowerOutletTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + frontports: List[Annotated["FrontPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + devicebays: List[Annotated["DeviceBayTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + modulebays: List[Annotated["ModuleBayTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + services: List[Annotated["ServiceTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] + inventoryitems: List[Annotated["InventoryItemTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + vdcs: List[Annotated["VirtualDeviceContextTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + + @strawberry_django.field + def vc_master_for(self) -> Annotated["VirtualChassisTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None: + return self.vc_master_for if hasattr(self, 'vc_master_for') else None + + @strawberry_django.field + def parent_bay(self) -> Annotated["DeviceBayTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None: + return self.parent_bay if hasattr(self, 'parent_bay') else None + + +@strawberry_django.type( + models.DeviceBay, + fields='__all__', + filters=DeviceBayFilterV1, + pagination=True +) +class DeviceBayTypeV1(ComponentTypeV1): + installed_device: Annotated["DeviceTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + + +@strawberry_django.type( + models.DeviceBayTemplate, + fields='__all__', + filters=DeviceBayTemplateFilterV1, + pagination=True +) +class DeviceBayTemplateTypeV1(ComponentTemplateTypeV1): + pass + + +@strawberry_django.type( + models.InventoryItemTemplate, + exclude=['component_type', 'component_id', 'parent'], + filters=InventoryItemTemplateFilterV1, + pagination=True +) +class InventoryItemTemplateTypeV1(ComponentTemplateTypeV1): + role: Annotated["InventoryItemRoleTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + manufacturer: Annotated["ManufacturerTypeV1", strawberry.lazy('dcim.graphql.types_v1')] + + @strawberry_django.field + def parent(self) -> Annotated["InventoryItemTemplateTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None: + return self.parent + + child_items: List[Annotated["InventoryItemTemplateTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + + component: Annotated[Union[ + Annotated["ConsolePortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["ConsoleServerPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["FrontPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["InterfaceTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["PowerOutletTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["PowerPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["RearPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + ], strawberry.union("InventoryItemTemplateComponentTypeV1")] | None + + +@strawberry_django.type( + models.DeviceRole, + fields='__all__', + filters=DeviceRoleFilterV1, + pagination=True +) +class DeviceRoleTypeV1(OrganizationalObjectTypeV1): + parent: Annotated['DeviceRoleTypeV1', strawberry.lazy('dcim.graphql.types_v1')] | None + children: List[Annotated['DeviceRoleTypeV1', strawberry.lazy('dcim.graphql.types_v1')]] + color: str + config_template: Annotated["ConfigTemplateTypeV1", strawberry.lazy('extras.graphql.types_v1')] | None + + virtual_machines: List[Annotated["VirtualMachineTypeV1", strawberry.lazy('virtualization.graphql.types_v1')]] + devices: List[Annotated["DeviceTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + + +@strawberry_django.type( + models.DeviceType, + fields='__all__', + filters=DeviceTypeFilterV1, + pagination=True +) +class DeviceTypeTypeV1(NetBoxObjectTypeV1): + console_port_template_count: BigInt + console_server_port_template_count: BigInt + power_port_template_count: BigInt + power_outlet_template_count: BigInt + interface_template_count: BigInt + front_port_template_count: BigInt + rear_port_template_count: BigInt + device_bay_template_count: BigInt + module_bay_template_count: BigInt + inventory_item_template_count: BigInt + front_image: strawberry_django.fields.types.DjangoImageType | None + rear_image: strawberry_django.fields.types.DjangoImageType | None + manufacturer: Annotated["ManufacturerTypeV1", strawberry.lazy('dcim.graphql.types_v1')] + default_platform: Annotated["PlatformTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + + frontporttemplates: List[Annotated["FrontPortTemplateTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + modulebaytemplates: List[Annotated["ModuleBayTemplateTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + instances: List[Annotated["DeviceTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + poweroutlettemplates: List[Annotated["PowerOutletTemplateTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + powerporttemplates: List[Annotated["PowerPortTemplateTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + inventoryitemtemplates: List[Annotated["InventoryItemTemplateTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + rearporttemplates: List[Annotated["RearPortTemplateTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + consoleserverporttemplates: List[ + Annotated["ConsoleServerPortTemplateTypeV1", strawberry.lazy('dcim.graphql.types_v1')] + ] + interfacetemplates: List[Annotated["InterfaceTemplateTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + devicebaytemplates: List[Annotated["DeviceBayTemplateTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + consoleporttemplates: List[Annotated["ConsolePortTemplateTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + + +@strawberry_django.type( + models.FrontPort, + fields='__all__', + filters=FrontPortFilterV1, + pagination=True +) +class FrontPortTypeV1(ModularComponentTypeV1, CabledObjectMixinV1): + color: str + rear_port: Annotated["RearPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')] + + +@strawberry_django.type( + models.FrontPortTemplate, + fields='__all__', + filters=FrontPortTemplateFilterV1, + pagination=True +) +class FrontPortTemplateTypeV1(ModularComponentTemplateTypeV1): + color: str + rear_port: Annotated["RearPortTemplateTypeV1", strawberry.lazy('dcim.graphql.types_v1')] + + +@strawberry_django.type( + models.MACAddress, + exclude=['assigned_object_type', 'assigned_object_id'], + filters=MACAddressFilterV1, + pagination=True +) +class MACAddressTypeV1(NetBoxObjectTypeV1): + mac_address: str + + @strawberry_django.field + def assigned_object(self) -> Annotated[Union[ + Annotated["InterfaceTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["VMInterfaceTypeV1", strawberry.lazy('virtualization.graphql.types_v1')], + ], strawberry.union("MACAddressAssignmentTypeV1")] | None: + return self.assigned_object + + +@strawberry_django.type( + models.Interface, + exclude=['_path'], + filters=InterfaceFilterV1, + pagination=True +) +class InterfaceTypeV1(IPAddressesMixinV1, ModularComponentTypeV1, CabledObjectMixinV1, PathEndpointMixinV1): + _name: str + wwn: str | None + parent: Annotated["InterfaceTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + bridge: Annotated["InterfaceTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + lag: Annotated["InterfaceTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + wireless_link: Annotated["WirelessLinkTypeV1", strawberry.lazy('wireless.graphql.types_v1')] | None + untagged_vlan: Annotated["VLANTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None + vrf: Annotated["VRFTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None + primary_mac_address: Annotated["MACAddressTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + qinq_svlan: Annotated["VLANTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None + vlan_translation_policy: Annotated["VLANTranslationPolicyTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None + l2vpn_termination: Annotated["L2VPNTerminationTypeV1", strawberry.lazy('vpn.graphql.types_v1')] | None + + vdcs: List[Annotated["VirtualDeviceContextTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + tagged_vlans: List[Annotated["VLANTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] + bridge_interfaces: List[Annotated["InterfaceTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + wireless_lans: List[Annotated["WirelessLANTypeV1", strawberry.lazy('wireless.graphql.types_v1')]] + member_interfaces: List[Annotated["InterfaceTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + child_interfaces: List[Annotated["InterfaceTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + mac_addresses: List[Annotated["MACAddressTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + + +@strawberry_django.type( + models.InterfaceTemplate, + fields='__all__', + filters=InterfaceTemplateFilterV1, + pagination=True +) +class InterfaceTemplateTypeV1(ModularComponentTemplateTypeV1): + _name: str + bridge: Annotated["InterfaceTemplateTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + + bridge_interfaces: List[Annotated["InterfaceTemplateTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + + +@strawberry_django.type( + models.InventoryItem, + exclude=['component_type', 'component_id', 'parent'], + filters=InventoryItemFilterV1, + pagination=True +) +class InventoryItemTypeV1(ComponentTypeV1): + role: Annotated["InventoryItemRoleTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + manufacturer: Annotated["ManufacturerTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + + child_items: List[Annotated["InventoryItemTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + + @strawberry_django.field + def parent(self) -> Annotated["InventoryItemTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None: + return self.parent + + component: Annotated[Union[ + Annotated["ConsolePortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["ConsoleServerPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["FrontPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["InterfaceTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["PowerOutletTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["PowerPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["RearPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + ], strawberry.union("InventoryItemComponentTypeV1")] | None + + +@strawberry_django.type( + models.InventoryItemRole, + fields='__all__', + filters=InventoryItemRoleFilterV1, + pagination=True +) +class InventoryItemRoleTypeV1(OrganizationalObjectTypeV1): + color: str + + inventory_items: List[Annotated["InventoryItemTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + inventory_item_templates: List[Annotated["InventoryItemTemplateTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + + +@strawberry_django.type( + models.Location, + # fields='__all__', + exclude=['parent'], # bug - temp + filters=LocationFilterV1, + pagination=True +) +class LocationTypeV1(VLANGroupsMixinV1, ImageAttachmentsMixinV1, ContactsMixinV1, OrganizationalObjectTypeV1): + site: Annotated["SiteTypeV1", strawberry.lazy('dcim.graphql.types_v1')] + tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None + parent: Annotated["LocationTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + + powerpanel_set: List[Annotated["PowerPanelTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + cabletermination_set: List[Annotated["CableTerminationTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + racks: List[Annotated["RackTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + devices: List[Annotated["DeviceTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + children: List[Annotated["LocationTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + + @strawberry_django.field + def clusters(self) -> List[Annotated["ClusterTypeV1", strawberry.lazy('virtualization.graphql.types_v1')]]: + return self.cluster_set.all() + + @strawberry_django.field + def circuit_terminations(self) -> List[ + Annotated["CircuitTerminationTypeV1", strawberry.lazy('circuits.graphql.types_v1')] + ]: + return self.circuit_terminations.all() + + +@strawberry_django.type( + models.Manufacturer, + fields='__all__', + filters=ManufacturerFilterV1, + pagination=True +) +class ManufacturerTypeV1(OrganizationalObjectTypeV1, ContactsMixinV1): + + platforms: List[Annotated["PlatformTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + device_types: List[Annotated["DeviceTypeTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + inventory_item_templates: List[Annotated["InventoryItemTemplateTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + inventory_items: List[Annotated["InventoryItemTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + module_types: List[Annotated["ModuleTypeTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + + +@strawberry_django.type( + models.Module, + fields='__all__', + filters=ModuleFilterV1, + pagination=True +) +class ModuleTypeV1(NetBoxObjectTypeV1): + device: Annotated["DeviceTypeV1", strawberry.lazy('dcim.graphql.types_v1')] + module_bay: Annotated["ModuleBayTypeV1", strawberry.lazy('dcim.graphql.types_v1')] + module_type: Annotated["ModuleTypeTypeV1", strawberry.lazy('dcim.graphql.types_v1')] + + interfaces: List[Annotated["InterfaceTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + powerports: List[Annotated["PowerPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + consoleserverports: List[Annotated["ConsoleServerPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + consoleports: List[Annotated["ConsolePortTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + poweroutlets: List[Annotated["PowerOutletTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + rearports: List[Annotated["RearPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + frontports: List[Annotated["FrontPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + + +@strawberry_django.type( + models.ModuleBay, + # fields='__all__', + exclude=['parent'], + filters=ModuleBayFilterV1, + pagination=True +) +class ModuleBayTypeV1(ModularComponentTypeV1): + + installed_module: Annotated["ModuleTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + children: List[Annotated["ModuleBayTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + + @strawberry_django.field + def parent(self) -> Annotated["ModuleBayTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None: + return self.parent + + +@strawberry_django.type( + models.ModuleBayTemplate, + fields='__all__', + filters=ModuleBayTemplateFilterV1, + pagination=True +) +class ModuleBayTemplateTypeV1(ModularComponentTemplateTypeV1): + pass + + +@strawberry_django.type( + models.ModuleTypeProfile, + fields='__all__', + filters=ModuleTypeProfileFilterV1, + pagination=True +) +class ModuleTypeProfileTypeV1(NetBoxObjectTypeV1): + module_types: List[Annotated["ModuleTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + + +@strawberry_django.type( + models.ModuleType, + fields='__all__', + filters=ModuleTypeFilterV1, + pagination=True +) +class ModuleTypeTypeV1(NetBoxObjectTypeV1): + profile: Annotated["ModuleTypeProfileTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + manufacturer: Annotated["ManufacturerTypeV1", strawberry.lazy('dcim.graphql.types_v1')] + + frontporttemplates: List[Annotated["FrontPortTemplateTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + consoleserverporttemplates: List[ + Annotated["ConsoleServerPortTemplateTypeV1", strawberry.lazy('dcim.graphql.types_v1')] + ] + interfacetemplates: List[Annotated["InterfaceTemplateTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + powerporttemplates: List[Annotated["PowerPortTemplateTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + poweroutlettemplates: List[Annotated["PowerOutletTemplateTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + rearporttemplates: List[Annotated["RearPortTemplateTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + instances: List[Annotated["ModuleTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + consoleporttemplates: List[Annotated["ConsolePortTemplateTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + + +@strawberry_django.type( + models.Platform, + fields='__all__', + filters=PlatformFilterV1, + pagination=True +) +class PlatformTypeV1(OrganizationalObjectTypeV1): + parent: Annotated['PlatformTypeV1', strawberry.lazy('dcim.graphql.types_v1')] | None + children: List[Annotated['PlatformTypeV1', strawberry.lazy('dcim.graphql.types_v1')]] + manufacturer: Annotated["ManufacturerTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + config_template: Annotated["ConfigTemplateTypeV1", strawberry.lazy('extras.graphql.types_v1')] | None + + virtual_machines: List[Annotated["VirtualMachineTypeV1", strawberry.lazy('virtualization.graphql.types_v1')]] + devices: List[Annotated["DeviceTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + + +@strawberry_django.type( + models.PowerFeed, + exclude=['_path'], + filters=PowerFeedFilterV1, + pagination=True +) +class PowerFeedTypeV1(NetBoxObjectTypeV1, CabledObjectMixinV1, PathEndpointMixinV1): + power_panel: Annotated["PowerPanelTypeV1", strawberry.lazy('dcim.graphql.types_v1')] + rack: Annotated["RackTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None + + +@strawberry_django.type( + models.PowerOutlet, + exclude=['_path'], + filters=PowerOutletFilterV1, + pagination=True +) +class PowerOutletTypeV1(ModularComponentTypeV1, CabledObjectMixinV1, PathEndpointMixinV1): + power_port: Annotated["PowerPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + color: str + + +@strawberry_django.type( + models.PowerOutletTemplate, + fields='__all__', + filters=PowerOutletTemplateFilterV1, + pagination=True +) +class PowerOutletTemplateTypeV1(ModularComponentTemplateTypeV1): + power_port: Annotated["PowerPortTemplateTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + + +@strawberry_django.type( + models.PowerPanel, + fields='__all__', + filters=PowerPanelFilterV1, + pagination=True +) +class PowerPanelTypeV1(NetBoxObjectTypeV1, ContactsMixinV1): + site: Annotated["SiteTypeV1", strawberry.lazy('dcim.graphql.types_v1')] + location: Annotated["LocationTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + + powerfeeds: List[Annotated["PowerFeedTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + + +@strawberry_django.type( + models.PowerPort, + exclude=['_path'], + filters=PowerPortFilterV1, + pagination=True +) +class PowerPortTypeV1(ModularComponentTypeV1, CabledObjectMixinV1, PathEndpointMixinV1): + + poweroutlets: List[Annotated["PowerOutletTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + + +@strawberry_django.type( + models.PowerPortTemplate, + fields='__all__', + filters=PowerPortTemplateFilterV1, + pagination=True +) +class PowerPortTemplateTypeV1(ModularComponentTemplateTypeV1): + poweroutlet_templates: List[Annotated["PowerOutletTemplateTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + + +@strawberry_django.type( + models.RackType, + fields='__all__', + filters=RackTypeFilterV1, + pagination=True +) +class RackTypeTypeV1(NetBoxObjectTypeV1): + manufacturer: Annotated["ManufacturerTypeV1", strawberry.lazy('dcim.graphql.types_v1')] + + +@strawberry_django.type( + models.Rack, + fields='__all__', + filters=RackFilterV1, + pagination=True +) +class RackTypeV1(VLANGroupsMixinV1, ImageAttachmentsMixinV1, ContactsMixinV1, NetBoxObjectTypeV1): + site: Annotated["SiteTypeV1", strawberry.lazy('dcim.graphql.types_v1')] + location: Annotated["LocationTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None + role: Annotated["RackRoleTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + + rack_type: Annotated["RackTypeTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + reservations: List[Annotated["RackReservationTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + devices: List[Annotated["DeviceTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + powerfeeds: List[Annotated["PowerFeedTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + cabletermination_set: List[Annotated["CableTerminationTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + + +@strawberry_django.type( + models.RackReservation, + fields='__all__', + filters=RackReservationFilterV1, + pagination=True +) +class RackReservationTypeV1(NetBoxObjectTypeV1): + units: List[int] + rack: Annotated["RackTypeV1", strawberry.lazy('dcim.graphql.types_v1')] + tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None + user: Annotated["UserTypeV1", strawberry.lazy('users.graphql.types_v1')] + + +@strawberry_django.type( + models.RackRole, + fields='__all__', + filters=RackRoleFilterV1, + pagination=True +) +class RackRoleTypeV1(OrganizationalObjectTypeV1): + color: str + + racks: List[Annotated["RackTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + + +@strawberry_django.type( + models.RearPort, + fields='__all__', + filters=RearPortFilterV1, + pagination=True +) +class RearPortTypeV1(ModularComponentTypeV1, CabledObjectMixinV1): + color: str + + frontports: List[Annotated["FrontPortTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + + +@strawberry_django.type( + models.RearPortTemplate, + fields='__all__', + filters=RearPortTemplateFilterV1, + pagination=True +) +class RearPortTemplateTypeV1(ModularComponentTemplateTypeV1): + color: str + + frontport_templates: List[Annotated["FrontPortTemplateTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + + +@strawberry_django.type( + models.Region, + exclude=['parent'], + filters=RegionFilterV1, + pagination=True +) +class RegionTypeV1(VLANGroupsMixinV1, ContactsMixinV1, OrganizationalObjectTypeV1): + + sites: List[Annotated["SiteTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + children: List[Annotated["RegionTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + + @strawberry_django.field + def parent(self) -> Annotated["RegionTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None: + return self.parent + + @strawberry_django.field + def clusters(self) -> List[Annotated["ClusterTypeV1", strawberry.lazy('virtualization.graphql.types_v1')]]: + return self.cluster_set.all() + + @strawberry_django.field + def circuit_terminations(self) -> List[ + Annotated["CircuitTerminationTypeV1", strawberry.lazy('circuits.graphql.types_v1')] + ]: + return self.circuit_terminations.all() + + +@strawberry_django.type( + models.Site, + fields='__all__', + filters=SiteFilterV1, + pagination=True +) +class SiteTypeV1(VLANGroupsMixinV1, ImageAttachmentsMixinV1, ContactsMixinV1, NetBoxObjectTypeV1): + time_zone: str | None + region: Annotated["RegionTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + group: Annotated["SiteGroupTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None + + prefixes: List[Annotated["PrefixTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] + virtual_machines: List[Annotated["VirtualMachineTypeV1", strawberry.lazy('virtualization.graphql.types_v1')]] + racks: List[Annotated["RackTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + cabletermination_set: List[Annotated["CableTerminationTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + powerpanel_set: List[Annotated["PowerPanelTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + devices: List[Annotated["DeviceTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + locations: List[Annotated["LocationTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + asns: List[Annotated["ASNTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] + circuit_terminations: List[Annotated["CircuitTerminationTypeV1", strawberry.lazy('circuits.graphql.types_v1')]] + clusters: List[Annotated["ClusterTypeV1", strawberry.lazy('virtualization.graphql.types_v1')]] + vlans: List[Annotated["VLANTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] + + @strawberry_django.field + def clusters(self) -> List[Annotated["ClusterTypeV1", strawberry.lazy('virtualization.graphql.types_v1')]]: + return self.cluster_set.all() + + @strawberry_django.field + def circuit_terminations(self) -> List[ + Annotated["CircuitTerminationTypeV1", strawberry.lazy('circuits.graphql.types_v1')] + ]: + return self.circuit_terminations.all() + + +@strawberry_django.type( + models.SiteGroup, + exclude=['parent'], # bug - temp + filters=SiteGroupFilterV1, + pagination=True +) +class SiteGroupTypeV1(VLANGroupsMixinV1, ContactsMixinV1, OrganizationalObjectTypeV1): + + sites: List[Annotated["SiteTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + children: List[Annotated["SiteGroupTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + + @strawberry_django.field + def parent(self) -> Annotated["SiteGroupTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None: + return self.parent + + @strawberry_django.field + def clusters(self) -> List[Annotated["ClusterTypeV1", strawberry.lazy('virtualization.graphql.types_v1')]]: + return self.cluster_set.all() + + @strawberry_django.field + def circuit_terminations(self) -> List[ + Annotated["CircuitTerminationTypeV1", strawberry.lazy('circuits.graphql.types_v1')] + ]: + return self.circuit_terminations.all() + + +@strawberry_django.type( + models.VirtualChassis, + fields='__all__', + filters=VirtualChassisFilterV1, + pagination=True +) +class VirtualChassisTypeV1(NetBoxObjectTypeV1): + member_count: BigInt + master: Annotated["DeviceTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + + members: List[Annotated["DeviceTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + + +@strawberry_django.type( + models.VirtualDeviceContext, + fields='__all__', + filters=VirtualDeviceContextFilterV1, + pagination=True +) +class VirtualDeviceContextTypeV1(NetBoxObjectTypeV1): + device: Annotated["DeviceTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + primary_ip4: Annotated["IPAddressTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None + primary_ip6: Annotated["IPAddressTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None + tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None + + interfaces: List[Annotated["InterfaceTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] diff --git a/netbox/extras/graphql/filter_mixins_v1.py b/netbox/extras/graphql/filter_mixins_v1.py new file mode 100644 index 0000000000..48611cc835 --- /dev/null +++ b/netbox/extras/graphql/filter_mixins_v1.py @@ -0,0 +1,52 @@ +from dataclasses import dataclass +from typing import Annotated, TYPE_CHECKING + +import strawberry +import strawberry_django +from strawberry_django import FilterLookup + +from core.graphql.filter_mixins_v1 import BaseFilterMixinV1 + +if TYPE_CHECKING: + from netbox.graphql.filter_lookups import JSONFilter + from .filters_v1 import * + +__all__ = ( + 'CustomFieldsFilterMixinV1', + 'JournalEntriesFilterMixinV1', + 'TagsFilterMixinV1', + 'ConfigContextFilterMixinV1', + 'TagBaseFilterMixinV1', +) + + +@dataclass +class CustomFieldsFilterMixinV1(BaseFilterMixinV1): + custom_field_data: Annotated['JSONFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + + +@dataclass +class JournalEntriesFilterMixinV1(BaseFilterMixinV1): + journal_entries: Annotated['JournalEntryFilterV1', strawberry.lazy('extras.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + + +@dataclass +class TagsFilterMixinV1(BaseFilterMixinV1): + tags: Annotated['TagFilter', strawberry.lazy('extras.graphql.filters')] | None = strawberry_django.filter_field() + + +@dataclass +class ConfigContextFilterMixinV1(BaseFilterMixinV1): + local_context_data: Annotated['JSONFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + + +@dataclass +class TagBaseFilterMixinV1(BaseFilterMixinV1): + name: FilterLookup[str] | None = strawberry_django.filter_field() + slug: FilterLookup[str] | None = strawberry_django.filter_field() diff --git a/netbox/extras/graphql/filters_v1.py b/netbox/extras/graphql/filters_v1.py new file mode 100644 index 0000000000..b903fee343 --- /dev/null +++ b/netbox/extras/graphql/filters_v1.py @@ -0,0 +1,357 @@ +from typing import Annotated, TYPE_CHECKING + +import strawberry +import strawberry_django +from strawberry.scalars import ID +from strawberry_django import FilterLookup + +from core.graphql.filter_mixins_v1 import BaseObjectTypeFilterMixinV1, ChangeLogFilterMixinV1 +from extras import models +from extras.graphql.filter_mixins_v1 import TagBaseFilterMixinV1, CustomFieldsFilterMixinV1, TagsFilterMixinV1 +from netbox.graphql.filter_mixins_v1 import PrimaryModelFilterMixinV1, SyncedDataFilterMixinV1 + +if TYPE_CHECKING: + from core.graphql.filters_v1 import ContentTypeFilterV1 + from dcim.graphql.filters_v1 import ( + DeviceRoleFilterV1, + DeviceTypeFilterV1, + LocationFilterV1, + PlatformFilterV1, + RegionFilterV1, + SiteFilterV1, + SiteGroupFilterV1, + ) + from tenancy.graphql.filters_v1 import TenantFilterV1, TenantGroupFilterV1 + from netbox.graphql.enums import ColorEnum + from netbox.graphql.filter_lookups import FloatLookup, IntegerLookup, JSONFilter, StringArrayLookup, TreeNodeFilter + from virtualization.graphql.filters_v1 import ClusterFilterV1, ClusterGroupFilterV1, ClusterTypeFilterV1 + from .enums import * + +__all__ = ( + 'ConfigContextFilterV1', + 'ConfigContextProfileFilterV1', + 'ConfigTemplateFilterV1', + 'CustomFieldFilterV1', + 'CustomFieldChoiceSetFilterV1', + 'CustomLinkFilterV1', + 'EventRuleFilterV1', + 'ExportTemplateFilterV1', + 'ImageAttachmentFilterV1', + 'JournalEntryFilterV1', + 'NotificationGroupFilterV1', + 'SavedFilterFilterV1', + 'TableConfigFilterV1', + 'TagFilterV1', + 'WebhookFilterV1', +) + + +@strawberry_django.filter_type(models.ConfigContext, lookups=True) +class ConfigContextFilterV1(BaseObjectTypeFilterMixinV1, SyncedDataFilterMixinV1, ChangeLogFilterMixinV1): + name: FilterLookup[str] | None = strawberry_django.filter_field() + weight: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + description: FilterLookup[str] | None = strawberry_django.filter_field() + is_active: FilterLookup[bool] | None = strawberry_django.filter_field() + regions: Annotated['RegionFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + region_id: Annotated['TreeNodeFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + site_groups: Annotated['SiteGroupFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + site_group_id: Annotated['TreeNodeFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + sites: Annotated['SiteFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + locations: Annotated['LocationFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + device_types: Annotated['DeviceTypeFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + roles: Annotated['DeviceRoleFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + platforms: Annotated['PlatformFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + cluster_types: Annotated['ClusterTypeFilterV1', strawberry.lazy('virtualization.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + cluster_groups: Annotated['ClusterGroupFilterV1', strawberry.lazy('virtualization.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + clusters: Annotated['ClusterFilterV1', strawberry.lazy('virtualization.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + tenant_groups: Annotated['TenantGroupFilterV1', strawberry.lazy('tenancy.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + tenant_group_id: Annotated['TreeNodeFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + tenants: Annotated['TenantFilterV1', strawberry.lazy('tenancy.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + tags: Annotated['TagFilterV1', strawberry.lazy('extras.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + data: Annotated['JSONFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.ConfigContextProfile, lookups=True) +class ConfigContextProfileFilterV1(SyncedDataFilterMixinV1, PrimaryModelFilterMixinV1): + name: FilterLookup[str] = strawberry_django.filter_field() + description: FilterLookup[str] = strawberry_django.filter_field() + tags: Annotated['TagFilterV1', strawberry.lazy('extras.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.ConfigTemplate, lookups=True) +class ConfigTemplateFilterV1(BaseObjectTypeFilterMixinV1, SyncedDataFilterMixinV1, ChangeLogFilterMixinV1): + name: FilterLookup[str] | None = strawberry_django.filter_field() + description: FilterLookup[str] | None = strawberry_django.filter_field() + template_code: FilterLookup[str] | None = strawberry_django.filter_field() + environment_params: Annotated['JSONFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + mime_type: FilterLookup[str] | None = strawberry_django.filter_field() + file_name: FilterLookup[str] | None = strawberry_django.filter_field() + file_extension: FilterLookup[str] | None = strawberry_django.filter_field() + as_attachment: FilterLookup[bool] | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.CustomField, lookups=True) +class CustomFieldFilterV1(BaseObjectTypeFilterMixinV1, ChangeLogFilterMixinV1): + type: Annotated['CustomFieldTypeEnum', strawberry.lazy('extras.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + object_types: Annotated['ContentTypeFilterV1', strawberry.lazy('core.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + related_object_type: Annotated['ContentTypeFilterV1', strawberry.lazy('core.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + name: FilterLookup[str] | None = strawberry_django.filter_field() + label: FilterLookup[str] | None = strawberry_django.filter_field() + group_name: FilterLookup[str] | None = strawberry_django.filter_field() + description: FilterLookup[str] | None = strawberry_django.filter_field() + required: FilterLookup[bool] | None = strawberry_django.filter_field() + unique: FilterLookup[bool] | None = strawberry_django.filter_field() + search_weight: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + filter_logic: Annotated['CustomFieldFilterLogicEnum', strawberry.lazy('extras.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + default: Annotated['JSONFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + related_object_filter: Annotated['JSONFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + weight: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + validation_minimum: Annotated['FloatLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + validation_maximum: Annotated['FloatLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + validation_regex: FilterLookup[str] | None = strawberry_django.filter_field() + choice_set: Annotated['CustomFieldChoiceSetFilterV1', strawberry.lazy('extras.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + choice_set_id: ID | None = strawberry_django.filter_field() + ui_visible: Annotated['CustomFieldUIVisibleEnum', strawberry.lazy('extras.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + ui_editable: Annotated['CustomFieldUIEditableEnum', strawberry.lazy('extras.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + is_cloneable: FilterLookup[bool] | None = strawberry_django.filter_field() + comments: FilterLookup[str] | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.CustomFieldChoiceSet, lookups=True) +class CustomFieldChoiceSetFilterV1(BaseObjectTypeFilterMixinV1, ChangeLogFilterMixinV1): + name: FilterLookup[str] | None = strawberry_django.filter_field() + description: FilterLookup[str] | None = strawberry_django.filter_field() + base_choices: Annotated['CustomFieldChoiceSetBaseEnum', strawberry.lazy('extras.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + extra_choices: Annotated['StringArrayLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + order_alphabetically: FilterLookup[bool] | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.CustomLink, lookups=True) +class CustomLinkFilterV1(BaseObjectTypeFilterMixinV1, ChangeLogFilterMixinV1): + name: FilterLookup[str] | None = strawberry_django.filter_field() + enabled: FilterLookup[bool] | None = strawberry_django.filter_field() + link_text: FilterLookup[str] | None = strawberry_django.filter_field() + link_url: FilterLookup[str] | None = strawberry_django.filter_field() + weight: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + group_name: FilterLookup[str] | None = strawberry_django.filter_field() + button_class: Annotated['CustomLinkButtonClassEnum', strawberry.lazy('extras.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + new_window: FilterLookup[bool] | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.ExportTemplate, lookups=True) +class ExportTemplateFilterV1(BaseObjectTypeFilterMixinV1, SyncedDataFilterMixinV1, ChangeLogFilterMixinV1): + name: FilterLookup[str] | None = strawberry_django.filter_field() + description: FilterLookup[str] | None = strawberry_django.filter_field() + template_code: FilterLookup[str] | None = strawberry_django.filter_field() + environment_params: Annotated['JSONFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + mime_type: FilterLookup[str] | None = strawberry_django.filter_field() + file_name: FilterLookup[str] | None = strawberry_django.filter_field() + file_extension: FilterLookup[str] | None = strawberry_django.filter_field() + as_attachment: FilterLookup[bool] | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.ImageAttachment, lookups=True) +class ImageAttachmentFilterV1(BaseObjectTypeFilterMixinV1, ChangeLogFilterMixinV1): + object_type: Annotated['ContentTypeFilterV1', strawberry.lazy('core.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + object_id: ID | None = strawberry_django.filter_field() + image_height: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + image_width: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + name: FilterLookup[str] | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.JournalEntry, lookups=True) +class JournalEntryFilterV1( + BaseObjectTypeFilterMixinV1, CustomFieldsFilterMixinV1, TagsFilterMixinV1, ChangeLogFilterMixinV1 +): + assigned_object_type: Annotated['ContentTypeFilterV1', strawberry.lazy('core.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + assigned_object_type_id: ID | None = strawberry_django.filter_field() + assigned_object_id: ID | None = strawberry_django.filter_field() + created_by: Annotated['UserFilterV1', strawberry.lazy('users.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + kind: Annotated['JournalEntryKindEnum', strawberry.lazy('extras.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + comments: FilterLookup[str] | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.NotificationGroup, lookups=True) +class NotificationGroupFilterV1(BaseObjectTypeFilterMixinV1, ChangeLogFilterMixinV1): + name: FilterLookup[str] | None = strawberry_django.filter_field() + description: FilterLookup[str] | None = strawberry_django.filter_field() + groups: Annotated['GroupFilterV1', strawberry.lazy('users.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + users: Annotated['UserFilterV1', strawberry.lazy('users.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.SavedFilter, lookups=True) +class SavedFilterFilterV1(BaseObjectTypeFilterMixinV1, ChangeLogFilterMixinV1): + name: FilterLookup[str] | None = strawberry_django.filter_field() + slug: FilterLookup[str] | None = strawberry_django.filter_field() + description: FilterLookup[str] | None = strawberry_django.filter_field() + user: Annotated['UserFilterV1', strawberry.lazy('users.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + user_id: ID | None = strawberry_django.filter_field() + weight: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + enabled: FilterLookup[bool] | None = strawberry_django.filter_field() + shared: FilterLookup[bool] | None = strawberry_django.filter_field() + parameters: Annotated['JSONFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.TableConfig, lookups=True) +class TableConfigFilterV1(BaseObjectTypeFilterMixinV1, ChangeLogFilterMixinV1): + name: FilterLookup[str] | None = strawberry_django.filter_field() + description: FilterLookup[str] | None = strawberry_django.filter_field() + user: Annotated['UserFilterV1', strawberry.lazy('users.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + user_id: ID | None = strawberry_django.filter_field() + weight: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + enabled: FilterLookup[bool] | None = strawberry_django.filter_field() + shared: FilterLookup[bool] | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.Tag, lookups=True) +class TagFilterV1(BaseObjectTypeFilterMixinV1, ChangeLogFilterMixinV1, TagBaseFilterMixinV1): + color: Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')] | None = strawberry_django.filter_field() + description: FilterLookup[str] | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.Webhook, lookups=True) +class WebhookFilterV1( + BaseObjectTypeFilterMixinV1, CustomFieldsFilterMixinV1, TagsFilterMixinV1, ChangeLogFilterMixinV1 +): + name: FilterLookup[str] | None = strawberry_django.filter_field() + description: FilterLookup[str] | None = strawberry_django.filter_field() + payload_url: FilterLookup[str] | None = strawberry_django.filter_field() + http_method: Annotated['WebhookHttpMethodEnum', strawberry.lazy('extras.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + http_content_type: FilterLookup[str] | None = strawberry_django.filter_field() + additional_headers: FilterLookup[str] | None = strawberry_django.filter_field() + body_template: FilterLookup[str] | None = strawberry_django.filter_field() + secret: FilterLookup[str] | None = strawberry_django.filter_field() + ssl_verification: FilterLookup[bool] | None = strawberry_django.filter_field() + ca_file_path: FilterLookup[str] | None = strawberry_django.filter_field() + events: Annotated['EventRuleFilterV1', strawberry.lazy('extras.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.EventRule, lookups=True) +class EventRuleFilterV1( + BaseObjectTypeFilterMixinV1, CustomFieldsFilterMixinV1, TagsFilterMixinV1, ChangeLogFilterMixinV1 +): + name: FilterLookup[str] | None = strawberry_django.filter_field() + description: FilterLookup[str] | None = strawberry_django.filter_field() + event_types: Annotated['StringArrayLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + enabled: FilterLookup[bool] | None = strawberry_django.filter_field() + conditions: Annotated['JSONFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + action_type: Annotated['EventRuleActionEnum', strawberry.lazy('extras.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + action_object_type: FilterLookup[str] | None = strawberry_django.filter_field() + action_object_type_id: ID | None = strawberry_django.filter_field() + action_object_id: ID | None = strawberry_django.filter_field() + action_data: Annotated['JSONFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + comments: FilterLookup[str] | None = strawberry_django.filter_field() diff --git a/netbox/extras/graphql/mixins_v1.py b/netbox/extras/graphql/mixins_v1.py new file mode 100644 index 0000000000..4f56549d77 --- /dev/null +++ b/netbox/extras/graphql/mixins_v1.py @@ -0,0 +1,62 @@ +from typing import TYPE_CHECKING, Annotated, List + +import strawberry +import strawberry_django +from strawberry.types import Info + +__all__ = ( + 'ConfigContextMixinV1', + 'ContactsMixinV1', + 'CustomFieldsMixinV1', + 'ImageAttachmentsMixinV1', + 'JournalEntriesMixinV1', + 'TagsMixinV1', +) + +if TYPE_CHECKING: + from .types_v1 import ImageAttachmentTypeV1, JournalEntryTypeV1, TagTypeV1 + from tenancy.graphql.types_v1 import ContactAssignmentTypeV1 + + +@strawberry.type +class ConfigContextMixinV1: + + @strawberry_django.field + def config_context(self) -> strawberry.scalars.JSON: + return self.get_config_context() + + +@strawberry.type +class CustomFieldsMixinV1: + + @strawberry_django.field + def custom_fields(self) -> strawberry.scalars.JSON: + return self.custom_field_data + + +@strawberry.type +class ImageAttachmentsMixinV1: + + @strawberry_django.field + def image_attachments(self, info: Info) -> List[Annotated['ImageAttachmentTypeV1', strawberry.lazy('.types_v1')]]: + return self.images.restrict(info.context.request.user, 'view') + + +@strawberry.type +class JournalEntriesMixinV1: + + @strawberry_django.field + def journal_entries(self, info: Info) -> List[Annotated['JournalEntryTypeV1', strawberry.lazy('.types_v1')]]: + return self.journal_entries.all() + + +@strawberry.type +class TagsMixinV1: + + tags: List[Annotated['TagTypeV1', strawberry.lazy('.types_v1')]] + + +@strawberry.type +class ContactsMixinV1: + + contacts: List[Annotated['ContactAssignmentTypeV1', strawberry.lazy('tenancy.graphql.types_v1')]] diff --git a/netbox/extras/graphql/schema_v1.py b/netbox/extras/graphql/schema_v1.py new file mode 100644 index 0000000000..3a27571058 --- /dev/null +++ b/netbox/extras/graphql/schema_v1.py @@ -0,0 +1,60 @@ +from typing import List + +import strawberry +import strawberry_django + +from .types_v1 import * + + +@strawberry.type(name="Query") +class ExtrasQueryV1: + config_context: ConfigContextTypeV1 = strawberry_django.field() + config_context_list: List[ConfigContextTypeV1] = strawberry_django.field() + + config_context_profile: ConfigContextProfileTypeV1 = strawberry_django.field() + config_context_profile_list: List[ConfigContextProfileTypeV1] = strawberry_django.field() + + config_template: ConfigTemplateTypeV1 = strawberry_django.field() + config_template_list: List[ConfigTemplateTypeV1] = strawberry_django.field() + + custom_field: CustomFieldTypeV1 = strawberry_django.field() + custom_field_list: List[CustomFieldTypeV1] = strawberry_django.field() + + custom_field_choice_set: CustomFieldChoiceSetTypeV1 = strawberry_django.field() + custom_field_choice_set_list: List[CustomFieldChoiceSetTypeV1] = strawberry_django.field() + + custom_link: CustomLinkTypeV1 = strawberry_django.field() + custom_link_list: List[CustomLinkTypeV1] = strawberry_django.field() + + export_template: ExportTemplateTypeV1 = strawberry_django.field() + export_template_list: List[ExportTemplateTypeV1] = strawberry_django.field() + + image_attachment: ImageAttachmentTypeV1 = strawberry_django.field() + image_attachment_list: List[ImageAttachmentTypeV1] = strawberry_django.field() + + saved_filter: SavedFilterTypeV1 = strawberry_django.field() + saved_filter_list: List[SavedFilterTypeV1] = strawberry_django.field() + + table_config: TableConfigTypeV1 = strawberry_django.field() + table_config_list: List[TableConfigTypeV1] = strawberry_django.field() + + journal_entry: JournalEntryTypeV1 = strawberry_django.field() + journal_entry_list: List[JournalEntryTypeV1] = strawberry_django.field() + + notification: NotificationTypeV1 = strawberry_django.field() + notification_list: List[NotificationTypeV1] = strawberry_django.field() + + notification_group: NotificationGroupTypeV1 = strawberry_django.field() + notification_group_list: List[NotificationGroupTypeV1] = strawberry_django.field() + + subscription: SubscriptionTypeV1 = strawberry_django.field() + subscription_list: List[SubscriptionTypeV1] = strawberry_django.field() + + tag: TagTypeV1 = strawberry_django.field() + tag_list: List[TagTypeV1] = strawberry_django.field() + + webhook: WebhookTypeV1 = strawberry_django.field() + webhook_list: List[WebhookTypeV1] = strawberry_django.field() + + event_rule: EventRuleTypeV1 = strawberry_django.field() + event_rule_list: List[EventRuleTypeV1] = strawberry_django.field() diff --git a/netbox/extras/graphql/types_v1.py b/netbox/extras/graphql/types_v1.py new file mode 100644 index 0000000000..d51b57e885 --- /dev/null +++ b/netbox/extras/graphql/types_v1.py @@ -0,0 +1,239 @@ +from typing import Annotated, List, TYPE_CHECKING + +import strawberry +import strawberry_django + +from core.graphql.mixins_v1 import SyncedDataMixinV1 +from extras import models +from extras.graphql.mixins_v1 import CustomFieldsMixinV1, TagsMixinV1 +from netbox.graphql.types_v1 import ( + BaseObjectTypeV1, ContentTypeTypeV1, NetBoxObjectTypeV1, ObjectTypeV1, OrganizationalObjectTypeV1 +) +from .filters_v1 import * + +if TYPE_CHECKING: + from dcim.graphql.types_v1 import ( + DeviceRoleTypeV1, + DeviceTypeV1, + DeviceTypeTypeV1, + LocationTypeV1, + PlatformTypeV1, + RegionTypeV1, + SiteGroupTypeV1, + SiteTypeV1, + ) + from tenancy.graphql.types_v1 import TenantGroupTypeV1, TenantTypeV1 + from users.graphql.types_v1 import GroupTypeV1, UserTypeV1 + from virtualization.graphql.types_v1 import ( + ClusterGroupTypeV1, ClusterTypeV1, ClusterTypeTypeV1, VirtualMachineTypeV1 + ) + +__all__ = ( + 'ConfigContextProfileTypeV1', + 'ConfigContextTypeV1', + 'ConfigTemplateTypeV1', + 'CustomFieldChoiceSetTypeV1', + 'CustomFieldTypeV1', + 'CustomLinkTypeV1', + 'EventRuleTypeV1', + 'ExportTemplateTypeV1', + 'ImageAttachmentTypeV1', + 'JournalEntryTypeV1', + 'NotificationGroupTypeV1', + 'NotificationTypeV1', + 'SavedFilterTypeV1', + 'SubscriptionTypeV1', + 'TableConfigTypeV1', + 'TagTypeV1', + 'WebhookTypeV1', +) + + +@strawberry_django.type( + models.ConfigContextProfile, + fields='__all__', + filters=ConfigContextProfileFilterV1, + pagination=True +) +class ConfigContextProfileTypeV1(SyncedDataMixinV1, NetBoxObjectTypeV1): + pass + + +@strawberry_django.type( + models.ConfigContext, + fields='__all__', + filters=ConfigContextFilterV1, + pagination=True +) +class ConfigContextTypeV1(SyncedDataMixinV1, ObjectTypeV1): + profile: ConfigContextProfileTypeV1 | None + roles: List[Annotated["DeviceRoleTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + device_types: List[Annotated["DeviceTypeTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + tags: List[Annotated["TagTypeV1", strawberry.lazy('extras.graphql.types_v1')]] + platforms: List[Annotated["PlatformTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + regions: List[Annotated["RegionTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + cluster_groups: List[Annotated["ClusterGroupTypeV1", strawberry.lazy('virtualization.graphql.types_v1')]] + tenant_groups: List[Annotated["TenantGroupTypeV1", strawberry.lazy('tenancy.graphql.types_v1')]] + cluster_types: List[Annotated["ClusterTypeTypeV1", strawberry.lazy('virtualization.graphql.types_v1')]] + clusters: List[Annotated["ClusterTypeV1", strawberry.lazy('virtualization.graphql.types_v1')]] + locations: List[Annotated["LocationTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + sites: List[Annotated["SiteTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + tenants: List[Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')]] + site_groups: List[Annotated["SiteGroupTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + + +@strawberry_django.type( + models.ConfigTemplate, + fields='__all__', + filters=ConfigTemplateFilterV1, + pagination=True +) +class ConfigTemplateTypeV1(SyncedDataMixinV1, TagsMixinV1, ObjectTypeV1): + virtualmachines: List[Annotated["VirtualMachineTypeV1", strawberry.lazy('virtualization.graphql.types_v1')]] + devices: List[Annotated["DeviceTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + platforms: List[Annotated["PlatformTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + device_roles: List[Annotated["DeviceRoleTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + + +@strawberry_django.type( + models.CustomField, + fields='__all__', + filters=CustomFieldFilterV1, + pagination=True +) +class CustomFieldTypeV1(ObjectTypeV1): + related_object_type: Annotated["ContentTypeTypeV1", strawberry.lazy('netbox.graphql.types_v1')] | None + choice_set: Annotated["CustomFieldChoiceSetTypeV1", strawberry.lazy('extras.graphql.types_v1')] | None + + +@strawberry_django.type( + models.CustomFieldChoiceSet, + exclude=['extra_choices'], + filters=CustomFieldChoiceSetFilterV1, + pagination=True +) +class CustomFieldChoiceSetTypeV1(ObjectTypeV1): + + choices_for: List[Annotated["CustomFieldTypeV1", strawberry.lazy('extras.graphql.types_v1')]] + extra_choices: List[List[str]] | None + + +@strawberry_django.type( + models.CustomLink, + fields='__all__', + filters=CustomLinkFilterV1, + pagination=True +) +class CustomLinkTypeV1(ObjectTypeV1): + pass + + +@strawberry_django.type( + models.ExportTemplate, + fields='__all__', + filters=ExportTemplateFilterV1, + pagination=True +) +class ExportTemplateTypeV1(SyncedDataMixinV1, ObjectTypeV1): + pass + + +@strawberry_django.type( + models.ImageAttachment, + fields='__all__', + filters=ImageAttachmentFilterV1, + pagination=True +) +class ImageAttachmentTypeV1(BaseObjectTypeV1): + object_type: Annotated["ContentTypeTypeV1", strawberry.lazy('netbox.graphql.types_v1')] | None + + +@strawberry_django.type( + models.JournalEntry, + fields='__all__', + filters=JournalEntryFilterV1, + pagination=True +) +class JournalEntryTypeV1(CustomFieldsMixinV1, TagsMixinV1, ObjectTypeV1): + assigned_object_type: Annotated["ContentTypeTypeV1", strawberry.lazy('netbox.graphql.types_v1')] | None + created_by: Annotated["UserTypeV1", strawberry.lazy('users.graphql.types_v1')] | None + + +@strawberry_django.type( + models.Notification, + # filters=NotificationFilter + pagination=True +) +class NotificationTypeV1(ObjectTypeV1): + user: Annotated["UserTypeV1", strawberry.lazy('users.graphql.types_v1')] | None + + +@strawberry_django.type( + models.NotificationGroup, + filters=NotificationGroupFilterV1, + pagination=True +) +class NotificationGroupTypeV1(ObjectTypeV1): + users: List[Annotated["UserTypeV1", strawberry.lazy('users.graphql.types_v1')]] + groups: List[Annotated["GroupTypeV1", strawberry.lazy('users.graphql.types_v1')]] + + +@strawberry_django.type( + models.SavedFilter, + exclude=['content_types',], + filters=SavedFilterFilterV1, + pagination=True +) +class SavedFilterTypeV1(ObjectTypeV1): + user: Annotated["UserTypeV1", strawberry.lazy('users.graphql.types_v1')] | None + + +@strawberry_django.type( + models.Subscription, + # filters=NotificationFilter + pagination=True +) +class SubscriptionTypeV1(ObjectTypeV1): + user: Annotated["UserTypeV1", strawberry.lazy('users.graphql.types_v1')] | None + + +@strawberry_django.type( + models.TableConfig, + fields='__all__', + filters=TableConfigFilterV1, + pagination=True +) +class TableConfigTypeV1(ObjectTypeV1): + user: Annotated["UserTypeV1", strawberry.lazy('users.graphql.types_v1')] | None + + +@strawberry_django.type( + models.Tag, + exclude=['extras_taggeditem_items', ], + filters=TagFilterV1, + pagination=True +) +class TagTypeV1(ObjectTypeV1): + color: str + + object_types: List[ContentTypeTypeV1] + + +@strawberry_django.type( + models.Webhook, + exclude=['content_types',], + filters=WebhookFilterV1, + pagination=True +) +class WebhookTypeV1(OrganizationalObjectTypeV1): + pass + + +@strawberry_django.type( + models.EventRule, + exclude=['content_types',], + filters=EventRuleFilterV1, + pagination=True +) +class EventRuleTypeV1(OrganizationalObjectTypeV1): + action_object_type: Annotated["ContentTypeTypeV1", strawberry.lazy('netbox.graphql.types_v1')] | None diff --git a/netbox/ipam/graphql/filter_mixins_v1.py b/netbox/ipam/graphql/filter_mixins_v1.py new file mode 100644 index 0000000000..0ba314d5b3 --- /dev/null +++ b/netbox/ipam/graphql/filter_mixins_v1.py @@ -0,0 +1,25 @@ +from dataclasses import dataclass +from typing import Annotated, TYPE_CHECKING + +import strawberry +import strawberry_django + +from core.graphql.filter_mixins_v1 import BaseFilterMixinV1 + +if TYPE_CHECKING: + from netbox.graphql.filter_lookups import IntegerLookup + from .enums import * + +__all__ = ( + 'ServiceBaseFilterMixinV1', +) + + +@dataclass +class ServiceBaseFilterMixinV1(BaseFilterMixinV1): + protocol: Annotated['ServiceProtocolEnum', strawberry.lazy('ipam.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + ports: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) diff --git a/netbox/ipam/graphql/filters_v1.py b/netbox/ipam/graphql/filters_v1.py new file mode 100644 index 0000000000..7e2171e768 --- /dev/null +++ b/netbox/ipam/graphql/filters_v1.py @@ -0,0 +1,392 @@ +from datetime import date +from typing import Annotated, TYPE_CHECKING + +import netaddr +import strawberry +import strawberry_django +from django.db.models import Q +from netaddr.core import AddrFormatError +from strawberry.scalars import ID +from strawberry_django import FilterLookup, DateFilterLookup + +from core.graphql.filter_mixins_v1 import BaseObjectTypeFilterMixinV1, ChangeLogFilterMixinV1 +from dcim.graphql.filter_mixins_v1 import ScopedFilterMixinV1 +from dcim.models import Device +from ipam import models +from ipam.graphql.filter_mixins_v1 import ServiceBaseFilterMixinV1 +from netbox.graphql.filter_mixins_v1 import ( + NetBoxModelFilterMixinV1, OrganizationalModelFilterMixinV1, PrimaryModelFilterMixinV1 +) +from tenancy.graphql.filter_mixins_v1 import ContactFilterMixinV1, TenancyFilterMixinV1 +from virtualization.models import VMInterface + +if TYPE_CHECKING: + from netbox.graphql.filter_lookups import IntegerLookup, IntegerRangeArrayLookup + from circuits.graphql.filters_v1 import ProviderFilterV1 + from core.graphql.filters_v1 import ContentTypeFilterV1 + from dcim.graphql.filters_v1 import SiteFilterV1 + from vpn.graphql.filters_v1 import L2VPNFilterV1 + from .enums import * + +__all__ = ( + 'ASNFilterV1', + 'ASNRangeFilterV1', + 'AggregateFilterV1', + 'FHRPGroupFilterV1', + 'FHRPGroupAssignmentFilterV1', + 'IPAddressFilterV1', + 'IPRangeFilterV1', + 'PrefixFilterV1', + 'RIRFilterV1', + 'RoleFilterV1', + 'RouteTargetFilterV1', + 'ServiceFilterV1', + 'ServiceTemplateFilterV1', + 'VLANFilterV1', + 'VLANGroupFilterV1', + 'VLANTranslationPolicyFilterV1', + 'VLANTranslationRuleFilterV1', + 'VRFFilterV1', +) + + +@strawberry_django.filter_type(models.ASN, lookups=True) +class ASNFilterV1(TenancyFilterMixinV1, PrimaryModelFilterMixinV1): + rir: Annotated['RIRFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = strawberry_django.filter_field() + rir_id: ID | None = strawberry_django.filter_field() + asn: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + sites: ( + Annotated['SiteFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None + ) = strawberry_django.filter_field() + providers: ( + Annotated['ProviderFilterV1', strawberry.lazy('circuits.graphql.filters_v1')] | None + ) = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.ASNRange, lookups=True) +class ASNRangeFilterV1(TenancyFilterMixinV1, OrganizationalModelFilterMixinV1): + name: FilterLookup[str] | None = strawberry_django.filter_field() + slug: FilterLookup[str] | None = strawberry_django.filter_field() + rir: Annotated['RIRFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = strawberry_django.filter_field() + rir_id: ID | None = strawberry_django.filter_field() + start: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + end: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.Aggregate, lookups=True) +class AggregateFilterV1(ContactFilterMixinV1, TenancyFilterMixinV1, PrimaryModelFilterMixinV1): + prefix: Annotated['PrefixFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + prefix_id: ID | None = strawberry_django.filter_field() + rir: Annotated['RIRFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = strawberry_django.filter_field() + rir_id: ID | None = strawberry_django.filter_field() + date_added: DateFilterLookup[date] | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.FHRPGroup, lookups=True) +class FHRPGroupFilterV1(PrimaryModelFilterMixinV1): + group_id: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + name: FilterLookup[str] | None = strawberry_django.filter_field() + protocol: Annotated['FHRPGroupProtocolEnum', strawberry.lazy('ipam.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + auth_type: Annotated['FHRPGroupAuthTypeEnum', strawberry.lazy('ipam.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + auth_key: FilterLookup[str] | None = strawberry_django.filter_field() + ip_addresses: Annotated['IPAddressFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.FHRPGroupAssignment, lookups=True) +class FHRPGroupAssignmentFilterV1(BaseObjectTypeFilterMixinV1, ChangeLogFilterMixinV1): + interface_type: Annotated['ContentTypeFilterV1', strawberry.lazy('core.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + interface_id: FilterLookup[str] | None = strawberry_django.filter_field() + group: Annotated['FHRPGroupFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + group_id: ID | None = strawberry_django.filter_field() + priority: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + + @strawberry_django.filter_field() + def device_id(self, queryset, value: list[str], prefix) -> Q: + return self.filter_device('id', value) + + @strawberry_django.filter_field() + def device(self, value: list[str], prefix) -> Q: + return self.filter_device('name', value) + + @strawberry_django.filter_field() + def virtual_machine_id(self, value: list[str], prefix) -> Q: + return Q(interface_id__in=VMInterface.objects.filter(virtual_machine_id__in=value)) + + @strawberry_django.filter_field() + def virtual_machine(self, value: list[str], prefix) -> Q: + return Q(interface_id__in=VMInterface.objects.filter(virtual_machine__name__in=value)) + + def filter_device(self, field, value) -> Q: + """Helper to standardize logic for device and device_id filters""" + devices = Device.objects.filter(**{f'{field}__in': value}) + interface_ids = [] + for device in devices: + interface_ids.extend(device.vc_interfaces().values_list('id', flat=True)) + return Q(interface_id__in=interface_ids) + + +@strawberry_django.filter_type(models.IPAddress, lookups=True) +class IPAddressFilterV1(ContactFilterMixinV1, TenancyFilterMixinV1, PrimaryModelFilterMixinV1): + address: FilterLookup[str] | None = strawberry_django.filter_field() + vrf: Annotated['VRFFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = strawberry_django.filter_field() + vrf_id: ID | None = strawberry_django.filter_field() + status: Annotated['IPAddressStatusEnum', strawberry.lazy('ipam.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + role: Annotated['IPAddressRoleEnum', strawberry.lazy('ipam.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + assigned_object_type: Annotated['ContentTypeFilterV1', strawberry.lazy('core.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + assigned_object_id: ID | None = strawberry_django.filter_field() + nat_inside: Annotated['IPAddressFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + nat_inside_id: ID | None = strawberry_django.filter_field() + nat_outside: Annotated['IPAddressFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + nat_outside_id: ID | None = strawberry_django.filter_field() + dns_name: FilterLookup[str] | None = strawberry_django.filter_field() + + @strawberry_django.filter_field() + def assigned(self, value: bool, prefix) -> Q: + return Q(assigned_object_id__isnull=(not value)) + + @strawberry_django.filter_field() + def parent(self, value: list[str], prefix) -> Q: + if not value: + return Q() + q = Q() + for subnet in value: + try: + query = str(netaddr.IPNetwork(subnet.strip()).cidr) + q |= Q(address__net_host_contained=query) + except (AddrFormatError, ValueError): + return Q() + return q + + @strawberry_django.filter_field() + def family( + self, + value: Annotated['IPAddressFamilyEnum', strawberry.lazy('ipam.graphql.enums')], + prefix, + ) -> Q: + return Q(**{f"{prefix}address__family": value.value}) + + +@strawberry_django.filter_type(models.IPRange, lookups=True) +class IPRangeFilterV1(ContactFilterMixinV1, TenancyFilterMixinV1, PrimaryModelFilterMixinV1): + start_address: FilterLookup[str] | None = strawberry_django.filter_field() + end_address: FilterLookup[str] | None = strawberry_django.filter_field() + size: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + vrf: Annotated['VRFFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = strawberry_django.filter_field() + vrf_id: ID | None = strawberry_django.filter_field() + status: Annotated['IPRangeStatusEnum', strawberry.lazy('ipam.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + role: Annotated['RoleFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + mark_utilized: FilterLookup[bool] | None = strawberry_django.filter_field() + + @strawberry_django.filter_field() + def parent(self, value: list[str], prefix) -> Q: + if not value: + return Q() + q = Q() + for subnet in value: + try: + query = str(netaddr.IPNetwork(subnet.strip()).cidr) + q |= Q(start_address__net_host_contained=query, end_address__net_host_contained=query) + except (AddrFormatError, ValueError): + return Q() + return q + + @strawberry_django.filter_field() + def contains(self, value: list[str], prefix) -> Q: + if not value: + return Q() + q = Q() + for subnet in value: + net = netaddr.IPNetwork(subnet.strip()) + q |= Q( + start_address__host__inet__lte=str(netaddr.IPAddress(net.first)), + end_address__host__inet__gte=str(netaddr.IPAddress(net.last)), + ) + return q + + +@strawberry_django.filter_type(models.Prefix, lookups=True) +class PrefixFilterV1(ContactFilterMixinV1, ScopedFilterMixinV1, TenancyFilterMixinV1, PrimaryModelFilterMixinV1): + prefix: FilterLookup[str] | None = strawberry_django.filter_field() + vrf: Annotated['VRFFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = strawberry_django.filter_field() + vrf_id: ID | None = strawberry_django.filter_field() + vlan: Annotated['VLANFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + vlan_id: ID | None = strawberry_django.filter_field() + status: Annotated['PrefixStatusEnum', strawberry.lazy('ipam.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + role: Annotated['RoleFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + role_id: ID | None = strawberry_django.filter_field() + is_pool: FilterLookup[bool] | None = strawberry_django.filter_field() + mark_utilized: FilterLookup[bool] | None = strawberry_django.filter_field() + + @strawberry_django.filter_field() + def contains(self, value: list[str], prefix) -> Q: + if not value: + return Q() + q = Q() + for subnet in value: + query = str(netaddr.IPNetwork(subnet.strip()).cidr) + q |= Q(prefix__net_contains=query) + return q + + +@strawberry_django.filter_type(models.RIR, lookups=True) +class RIRFilterV1(OrganizationalModelFilterMixinV1): + is_private: FilterLookup[bool] | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.Role, lookups=True) +class RoleFilterV1(OrganizationalModelFilterMixinV1): + weight: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.RouteTarget, lookups=True) +class RouteTargetFilterV1(TenancyFilterMixinV1, PrimaryModelFilterMixinV1): + name: FilterLookup[str] | None = strawberry_django.filter_field() + importing_vrfs: Annotated['VRFFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + exporting_vrfs: Annotated['VRFFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + importing_l2vpns: Annotated['L2VPNFilterV1', strawberry.lazy('vpn.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + exporting_l2vpns: Annotated['L2VPNFilterV1', strawberry.lazy('vpn.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.Service, lookups=True) +class ServiceFilterV1(ContactFilterMixinV1, ServiceBaseFilterMixinV1, PrimaryModelFilterMixinV1): + name: FilterLookup[str] | None = strawberry_django.filter_field() + ip_addresses: Annotated['IPAddressFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + parent_object_type: Annotated['ContentTypeFilterV1', strawberry.lazy('core.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + parent_object_id: ID | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.ServiceTemplate, lookups=True) +class ServiceTemplateFilterV1(ServiceBaseFilterMixinV1, PrimaryModelFilterMixinV1): + name: FilterLookup[str] | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.VLAN, lookups=True) +class VLANFilterV1(TenancyFilterMixinV1, PrimaryModelFilterMixinV1): + site: Annotated['SiteFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + site_id: ID | None = strawberry_django.filter_field() + group: Annotated['VLANGroupFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + group_id: ID | None = strawberry_django.filter_field() + vid: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + name: FilterLookup[str] | None = strawberry_django.filter_field() + status: Annotated['VLANStatusEnum', strawberry.lazy('ipam.graphql.enums')] | None = strawberry_django.filter_field() + role: Annotated['RoleFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + role_id: ID | None = strawberry_django.filter_field() + qinq_svlan: Annotated['VLANFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + qinq_svlan_id: ID | None = strawberry_django.filter_field() + qinq_cvlans: Annotated['VLANFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + qinq_role: Annotated['VLANQinQRoleEnum', strawberry.lazy('ipam.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + l2vpn_terminations: Annotated['L2VPNFilterV1', strawberry.lazy('vpn.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.VLANGroup, lookups=True) +class VLANGroupFilterV1(ScopedFilterMixinV1, OrganizationalModelFilterMixinV1): + vid_ranges: Annotated['IntegerRangeArrayLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.VLANTranslationPolicy, lookups=True) +class VLANTranslationPolicyFilterV1(PrimaryModelFilterMixinV1): + name: FilterLookup[str] | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.VLANTranslationRule, lookups=True) +class VLANTranslationRuleFilterV1(NetBoxModelFilterMixinV1): + policy: Annotated['VLANTranslationPolicyFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + policy_id: ID | None = strawberry_django.filter_field() + description: FilterLookup[str] | None = strawberry_django.filter_field() + local_vid: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + remote_vid: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.VRF, lookups=True) +class VRFFilterV1(TenancyFilterMixinV1, PrimaryModelFilterMixinV1): + name: FilterLookup[str] | None = strawberry_django.filter_field() + rd: FilterLookup[str] | None = strawberry_django.filter_field() + enforce_unique: FilterLookup[bool] | None = strawberry_django.filter_field() + import_targets: Annotated['RouteTargetFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + export_targets: Annotated['RouteTargetFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) diff --git a/netbox/ipam/graphql/mixins_v1.py b/netbox/ipam/graphql/mixins_v1.py new file mode 100644 index 0000000000..6d3e31197e --- /dev/null +++ b/netbox/ipam/graphql/mixins_v1.py @@ -0,0 +1,18 @@ +from typing import Annotated, List + +import strawberry + +__all__ = ( + 'IPAddressesMixinV1', + 'VLANGroupsMixinV1', +) + + +@strawberry.type +class IPAddressesMixinV1: + ip_addresses: List[Annotated["IPAddressTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] # noqa: F821 + + +@strawberry.type +class VLANGroupsMixinV1: + vlan_groups: List[Annotated["VLANGroupTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] # noqa: F821 diff --git a/netbox/ipam/graphql/schema_v1.py b/netbox/ipam/graphql/schema_v1.py new file mode 100644 index 0000000000..3bc7fdd978 --- /dev/null +++ b/netbox/ipam/graphql/schema_v1.py @@ -0,0 +1,63 @@ +from typing import List + +import strawberry +import strawberry_django + +from .types_v1 import * + + +@strawberry.type(name="Query") +class IPAMQueryV1: + asn: ASNTypeV1 = strawberry_django.field() + asn_list: List[ASNTypeV1] = strawberry_django.field() + + asn_range: ASNRangeTypeV1 = strawberry_django.field() + asn_range_list: List[ASNRangeTypeV1] = strawberry_django.field() + + aggregate: AggregateTypeV1 = strawberry_django.field() + aggregate_list: List[AggregateTypeV1] = strawberry_django.field() + + ip_address: IPAddressTypeV1 = strawberry_django.field() + ip_address_list: List[IPAddressTypeV1] = strawberry_django.field() + + ip_range: IPRangeTypeV1 = strawberry_django.field() + ip_range_list: List[IPRangeTypeV1] = strawberry_django.field() + + prefix: PrefixTypeV1 = strawberry_django.field() + prefix_list: List[PrefixTypeV1] = strawberry_django.field() + + rir: RIRTypeV1 = strawberry_django.field() + rir_list: List[RIRTypeV1] = strawberry_django.field() + + role: RoleTypeV1 = strawberry_django.field() + role_list: List[RoleTypeV1] = strawberry_django.field() + + route_target: RouteTargetTypeV1 = strawberry_django.field() + route_target_list: List[RouteTargetTypeV1] = strawberry_django.field() + + service: ServiceTypeV1 = strawberry_django.field() + service_list: List[ServiceTypeV1] = strawberry_django.field() + + service_template: ServiceTemplateTypeV1 = strawberry_django.field() + service_template_list: List[ServiceTemplateTypeV1] = strawberry_django.field() + + fhrp_group: FHRPGroupTypeV1 = strawberry_django.field() + fhrp_group_list: List[FHRPGroupTypeV1] = strawberry_django.field() + + fhrp_group_assignment: FHRPGroupAssignmentTypeV1 = strawberry_django.field() + fhrp_group_assignment_list: List[FHRPGroupAssignmentTypeV1] = strawberry_django.field() + + vlan: VLANTypeV1 = strawberry_django.field() + vlan_list: List[VLANTypeV1] = strawberry_django.field() + + vlan_group: VLANGroupTypeV1 = strawberry_django.field() + vlan_group_list: List[VLANGroupTypeV1] = strawberry_django.field() + + vlan_translation_policy: VLANTranslationPolicyTypeV1 = strawberry_django.field() + vlan_translation_policy_list: List[VLANTranslationPolicyTypeV1] = strawberry_django.field() + + vlan_translation_rule: VLANTranslationRuleTypeV1 = strawberry_django.field() + vlan_translation_rule_list: List[VLANTranslationRuleTypeV1] = strawberry_django.field() + + vrf: VRFTypeV1 = strawberry_django.field() + vrf_list: List[VRFTypeV1] = strawberry_django.field() diff --git a/netbox/ipam/graphql/types_v1.py b/netbox/ipam/graphql/types_v1.py new file mode 100644 index 0000000000..7b5d2c6522 --- /dev/null +++ b/netbox/ipam/graphql/types_v1.py @@ -0,0 +1,360 @@ +from typing import Annotated, List, TYPE_CHECKING, Union + +import strawberry +import strawberry_django + +from circuits.graphql.types_v1 import ProviderTypeV1 +from dcim.graphql.types_v1 import SiteTypeV1 +from extras.graphql.mixins_v1 import ContactsMixinV1 +from ipam import models +from netbox.graphql.scalars import BigInt +from netbox.graphql.types_v1 import BaseObjectTypeV1, NetBoxObjectTypeV1, OrganizationalObjectTypeV1 +from .filters_v1 import * +from .mixins_v1 import IPAddressesMixinV1 + +if TYPE_CHECKING: + from dcim.graphql.types_v1 import ( + DeviceTypeV1, + InterfaceTypeV1, + LocationTypeV1, + RackTypeV1, + RegionTypeV1, + SiteGroupTypeV1, + SiteTypeV1, + ) + from tenancy.graphql.types_v1 import TenantTypeV1 + from virtualization.graphql.types_v1 import ( + ClusterGroupTypeV1, ClusterTypeV1, VMInterfaceTypeV1, VirtualMachineTypeV1 + ) + from vpn.graphql.types_v1 import L2VPNTypeV1, TunnelTerminationTypeV1 + from wireless.graphql.types_v1 import WirelessLANTypeV1 + +__all__ = ( + 'ASNTypeV1', + 'ASNRangeTypeV1', + 'AggregateTypeV1', + 'FHRPGroupTypeV1', + 'FHRPGroupAssignmentTypeV1', + 'IPAddressTypeV1', + 'IPRangeTypeV1', + 'PrefixTypeV1', + 'RIRTypeV1', + 'RoleTypeV1', + 'RouteTargetTypeV1', + 'ServiceTypeV1', + 'ServiceTemplateTypeV1', + 'VLANTypeV1', + 'VLANGroupTypeV1', + 'VLANTranslationPolicyTypeV1', + 'VLANTranslationRuleTypeV1', + 'VRFTypeV1', +) + + +@strawberry.type +class IPAddressFamilyTypeV1: + value: int + label: str + + +@strawberry.type +class BaseIPAddressFamilyTypeV1: + """ + Base type for models that need to expose their IPAddress family type. + """ + + @strawberry.field + def family(self) -> IPAddressFamilyTypeV1: + # Note that self, is an instance of models.IPAddress + # thus resolves to the address family value. + return IPAddressFamilyTypeV1(value=self.family, label=f'IPv{self.family}') + + +@strawberry_django.type( + models.ASN, + fields='__all__', + filters=ASNFilterV1, + pagination=True +) +class ASNTypeV1(NetBoxObjectTypeV1, ContactsMixinV1): + asn: BigInt + rir: Annotated["RIRTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None + tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None + + sites: List[SiteTypeV1] + providers: List[ProviderTypeV1] + + +@strawberry_django.type( + models.ASNRange, + fields='__all__', + filters=ASNRangeFilterV1, + pagination=True +) +class ASNRangeTypeV1(NetBoxObjectTypeV1): + start: BigInt + end: BigInt + rir: Annotated["RIRTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None + tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None + + +@strawberry_django.type( + models.Aggregate, + fields='__all__', + filters=AggregateFilterV1, + pagination=True +) +class AggregateTypeV1(NetBoxObjectTypeV1, ContactsMixinV1, BaseIPAddressFamilyTypeV1): + prefix: str + rir: Annotated["RIRTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None + tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None + + +@strawberry_django.type( + models.FHRPGroup, + fields='__all__', + filters=FHRPGroupFilterV1, + pagination=True +) +class FHRPGroupTypeV1(NetBoxObjectTypeV1, IPAddressesMixinV1): + + fhrpgroupassignment_set: List[Annotated["FHRPGroupAssignmentTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] + + +@strawberry_django.type( + models.FHRPGroupAssignment, + exclude=['interface_type', 'interface_id'], + filters=FHRPGroupAssignmentFilterV1, + pagination=True +) +class FHRPGroupAssignmentTypeV1(BaseObjectTypeV1): + group: Annotated["FHRPGroupTypeV1", strawberry.lazy('ipam.graphql.types_v1')] + + @strawberry_django.field + def interface(self) -> Annotated[Union[ + Annotated["InterfaceTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["VMInterfaceTypeV1", strawberry.lazy('virtualization.graphql.types_v1')], + ], strawberry.union("FHRPGroupInterfaceTypeV1")]: + return self.interface + + +@strawberry_django.type( + models.IPAddress, + exclude=['assigned_object_type', 'assigned_object_id', 'address'], + filters=IPAddressFilterV1, + pagination=True +) +class IPAddressTypeV1(NetBoxObjectTypeV1, ContactsMixinV1, BaseIPAddressFamilyTypeV1): + address: str + vrf: Annotated["VRFTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None + tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None + nat_inside: Annotated["IPAddressTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None + + nat_outside: List[Annotated["IPAddressTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] + tunnel_terminations: List[Annotated["TunnelTerminationTypeV1", strawberry.lazy('vpn.graphql.types_v1')]] + services: List[Annotated["ServiceTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] + + @strawberry_django.field + def assigned_object(self) -> Annotated[Union[ + Annotated["InterfaceTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["FHRPGroupTypeV1", strawberry.lazy('ipam.graphql.types_v1')], + Annotated["VMInterfaceTypeV1", strawberry.lazy('virtualization.graphql.types_v1')], + ], strawberry.union("IPAddressAssignmentTypeV1")] | None: + return self.assigned_object + + +@strawberry_django.type( + models.IPRange, + fields='__all__', + filters=IPRangeFilterV1, + pagination=True +) +class IPRangeTypeV1(NetBoxObjectTypeV1, ContactsMixinV1): + start_address: str + end_address: str + vrf: Annotated["VRFTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None + tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None + role: Annotated["RoleTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None + + +@strawberry_django.type( + models.Prefix, + exclude=['scope_type', 'scope_id', '_location', '_region', '_site', '_site_group'], + filters=PrefixFilterV1, + pagination=True +) +class PrefixTypeV1(NetBoxObjectTypeV1, ContactsMixinV1, BaseIPAddressFamilyTypeV1): + prefix: str + vrf: Annotated["VRFTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None + tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None + vlan: Annotated["VLANTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None + role: Annotated["RoleTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None + + @strawberry_django.field + def scope(self) -> Annotated[Union[ + Annotated["LocationTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["RegionTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["SiteGroupTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["SiteTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + ], strawberry.union("PrefixScopeTypeV1")] | None: + return self.scope + + +@strawberry_django.type( + models.RIR, + fields='__all__', + filters=RIRFilterV1, + pagination=True +) +class RIRTypeV1(OrganizationalObjectTypeV1): + + asn_ranges: List[Annotated["ASNRangeTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] + asns: List[Annotated["ASNTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] + aggregates: List[Annotated["AggregateTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] + + +@strawberry_django.type( + models.Role, + fields='__all__', + filters=RoleFilterV1, + pagination=True +) +class RoleTypeV1(OrganizationalObjectTypeV1): + + prefixes: List[Annotated["PrefixTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] + ip_ranges: List[Annotated["IPRangeTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] + vlans: List[Annotated["VLANTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] + + +@strawberry_django.type( + models.RouteTarget, + fields='__all__', + filters=RouteTargetFilterV1, + pagination=True +) +class RouteTargetTypeV1(NetBoxObjectTypeV1): + tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None + + importing_l2vpns: List[Annotated["L2VPNTypeV1", strawberry.lazy('vpn.graphql.types_v1')]] + exporting_l2vpns: List[Annotated["L2VPNTypeV1", strawberry.lazy('vpn.graphql.types_v1')]] + importing_vrfs: List[Annotated["VRFTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] + exporting_vrfs: List[Annotated["VRFTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] + + +@strawberry_django.type( + models.Service, + exclude=('parent_object_type', 'parent_object_id'), + filters=ServiceFilterV1, + pagination=True +) +class ServiceTypeV1(NetBoxObjectTypeV1, ContactsMixinV1): + ports: List[int] + ipaddresses: List[Annotated["IPAddressTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] + + @strawberry_django.field + def parent(self) -> Annotated[Union[ + Annotated["DeviceTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["VirtualMachineTypeV1", strawberry.lazy('virtualization.graphql.types_v1')], + Annotated["FHRPGroupTypeV1", strawberry.lazy('ipam.graphql.types_v1')], + ], strawberry.union("ServiceParentTypeV1")] | None: + return self.parent + + +@strawberry_django.type( + models.ServiceTemplate, + fields='__all__', + filters=ServiceTemplateFilterV1, + pagination=True +) +class ServiceTemplateTypeV1(NetBoxObjectTypeV1): + ports: List[int] + + +@strawberry_django.type( + models.VLAN, + exclude=['qinq_svlan'], + filters=VLANFilterV1, + pagination=True +) +class VLANTypeV1(NetBoxObjectTypeV1): + site: Annotated["SiteTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None + group: Annotated["VLANGroupTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None + tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None + role: Annotated["RoleTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None + + interfaces_as_untagged: List[Annotated["InterfaceTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + vminterfaces_as_untagged: List[Annotated["VMInterfaceTypeV1", strawberry.lazy('virtualization.graphql.types_v1')]] + wirelesslan_set: List[Annotated["WirelessLANTypeV1", strawberry.lazy('wireless.graphql.types_v1')]] + prefixes: List[Annotated["PrefixTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] + interfaces_as_tagged: List[Annotated["InterfaceTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + vminterfaces_as_tagged: List[Annotated["VMInterfaceTypeV1", strawberry.lazy('virtualization.graphql.types_v1')]] + + @strawberry_django.field + def qinq_svlan(self) -> Annotated["VLANTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None: + return self.qinq_svlan + + +@strawberry_django.type( + models.VLANGroup, + exclude=['scope_type', 'scope_id'], + filters=VLANGroupFilterV1, + pagination=True +) +class VLANGroupTypeV1(OrganizationalObjectTypeV1): + + vlans: List[VLANTypeV1] + vid_ranges: List[str] + tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None + + @strawberry_django.field + def scope(self) -> Annotated[Union[ + Annotated["ClusterTypeV1", strawberry.lazy('virtualization.graphql.types_v1')], + Annotated["ClusterGroupTypeV1", strawberry.lazy('virtualization.graphql.types_v1')], + Annotated["LocationTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["RackTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["RegionTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["SiteTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["SiteGroupTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + ], strawberry.union("VLANGroupScopeTypeV1")] | None: + return self.scope + + +@strawberry_django.type( + models.VLANTranslationPolicy, + fields='__all__', + filters=VLANTranslationPolicyFilterV1, + pagination=True +) +class VLANTranslationPolicyTypeV1(NetBoxObjectTypeV1): + rules: List[Annotated["VLANTranslationRuleTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] + + +@strawberry_django.type( + models.VLANTranslationRule, + fields='__all__', + filters=VLANTranslationRuleFilterV1, + pagination=True +) +class VLANTranslationRuleTypeV1(NetBoxObjectTypeV1): + policy: Annotated[ + "VLANTranslationPolicyTypeV1", + strawberry.lazy('ipam.graphql.types_v1') + ] = strawberry_django.field(select_related=["policy"]) + + +@strawberry_django.type( + models.VRF, + fields='__all__', + filters=VRFFilterV1, + pagination=True +) +class VRFTypeV1(NetBoxObjectTypeV1): + tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None + + interfaces: List[Annotated["InterfaceTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + ip_addresses: List[Annotated["IPAddressTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] + vminterfaces: List[Annotated["VMInterfaceTypeV1", strawberry.lazy('virtualization.graphql.types_v1')]] + ip_ranges: List[Annotated["IPRangeTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] + export_targets: List[Annotated["RouteTargetTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] + import_targets: List[Annotated["RouteTargetTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] + prefixes: List[Annotated["PrefixTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] diff --git a/netbox/netbox/graphql/filter_mixins_v1.py b/netbox/netbox/graphql/filter_mixins_v1.py new file mode 100644 index 0000000000..2d34ff12da --- /dev/null +++ b/netbox/netbox/graphql/filter_mixins_v1.py @@ -0,0 +1,104 @@ +from dataclasses import dataclass +from datetime import datetime +from typing import TypeVar, TYPE_CHECKING, Annotated + +import strawberry +import strawberry_django +from strawberry import ID +from strawberry_django import FilterLookup, DatetimeFilterLookup + +from core.graphql.filter_mixins_v1 import BaseFilterMixinV1, BaseObjectTypeFilterMixinV1, ChangeLogFilterMixinV1 +from extras.graphql.filter_mixins_v1 import CustomFieldsFilterMixinV1, JournalEntriesFilterMixinV1, TagsFilterMixinV1 + +__all__ = ( + 'DistanceFilterMixinV1', + 'ImageAttachmentFilterMixinV1', + 'NestedGroupModelFilterMixinV1', + 'NetBoxModelFilterMixinV1', + 'OrganizationalModelFilterMixinV1', + 'PrimaryModelFilterMixinV1', + 'SyncedDataFilterMixinV1', + 'WeightFilterMixinV1', +) + +T = TypeVar('T') + + +if TYPE_CHECKING: + from .enums import * + from core.graphql.filters_v1 import * + from extras.graphql.filters_v1 import * + + +class NetBoxModelFilterMixinV1( + ChangeLogFilterMixinV1, + CustomFieldsFilterMixinV1, + JournalEntriesFilterMixinV1, + TagsFilterMixinV1, + BaseObjectTypeFilterMixinV1, +): + pass + + +@dataclass +class NestedGroupModelFilterMixinV1(NetBoxModelFilterMixinV1): + name: FilterLookup[str] | None = strawberry_django.filter_field() + slug: FilterLookup[str] | None = strawberry_django.filter_field() + description: FilterLookup[str] | None = strawberry_django.filter_field() + parent_id: ID | None = strawberry_django.filter_field() + + +@dataclass +class OrganizationalModelFilterMixinV1( + ChangeLogFilterMixinV1, + CustomFieldsFilterMixinV1, + TagsFilterMixinV1, + BaseObjectTypeFilterMixinV1, +): + name: FilterLookup[str] | None = strawberry_django.filter_field() + slug: FilterLookup[str] | None = strawberry_django.filter_field() + description: FilterLookup[str] | None = strawberry_django.filter_field() + + +@dataclass +class PrimaryModelFilterMixinV1(NetBoxModelFilterMixinV1): + description: FilterLookup[str] | None = strawberry_django.filter_field() + comments: FilterLookup[str] | None = strawberry_django.filter_field() + + +@dataclass +class ImageAttachmentFilterMixinV1(BaseFilterMixinV1): + images: Annotated['ImageAttachmentFilterV1', strawberry.lazy('extras.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + + +@dataclass +class WeightFilterMixinV1(BaseFilterMixinV1): + weight: FilterLookup[float] | None = strawberry_django.filter_field() + weight_unit: Annotated['WeightUnitEnum', strawberry.lazy('netbox.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + + +@dataclass +class SyncedDataFilterMixinV1(BaseFilterMixinV1): + data_source: Annotated['DataSourceFilterV1', strawberry.lazy('core.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + data_source_id: FilterLookup[int] | None = strawberry_django.filter_field() + data_file: Annotated['DataFileFilterV1', strawberry.lazy('core.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + data_file_id: FilterLookup[int] | None = strawberry_django.filter_field() + data_path: FilterLookup[str] | None = strawberry_django.filter_field() + auto_sync_enabled: FilterLookup[bool] | None = strawberry_django.filter_field() + data_synced: DatetimeFilterLookup[datetime] | None = strawberry_django.filter_field() + + +@dataclass +class DistanceFilterMixinV1(BaseFilterMixinV1): + distance: FilterLookup[float] | None = strawberry_django.filter_field() + distance_unit: Annotated['DistanceUnitEnum', strawberry.lazy('netbox.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) diff --git a/netbox/netbox/graphql/schema.py b/netbox/netbox/graphql/schema.py index 70a6ec7bfa..54fe61712f 100644 --- a/netbox/netbox/graphql/schema.py +++ b/netbox/netbox/graphql/schema.py @@ -4,16 +4,26 @@ from strawberry.extensions import MaxAliasesLimiter from strawberry.schema.config import StrawberryConfig +from circuits.graphql.schema_v1 import CircuitsQueryV1 from circuits.graphql.schema import CircuitsQuery +from core.graphql.schema_v1 import CoreQueryV1 from core.graphql.schema import CoreQuery +from dcim.graphql.schema_v1 import DCIMQueryV1 from dcim.graphql.schema import DCIMQuery +from extras.graphql.schema_v1 import ExtrasQueryV1 from extras.graphql.schema import ExtrasQuery +from ipam.graphql.schema_v1 import IPAMQueryV1 from ipam.graphql.schema import IPAMQuery from netbox.registry import registry +from tenancy.graphql.schema_v1 import TenancyQueryV1 from tenancy.graphql.schema import TenancyQuery +from users.graphql.schema_v1 import UsersQueryV1 from users.graphql.schema import UsersQuery +from virtualization.graphql.schema_v1 import VirtualizationQueryV1 from virtualization.graphql.schema import VirtualizationQuery +from vpn.graphql.schema_v1 import VPNQueryV1 from vpn.graphql.schema import VPNQuery +from wireless.graphql.schema_v1 import WirelessQueryV1 from wireless.graphql.schema import WirelessQuery __all__ = ( @@ -27,16 +37,16 @@ @strawberry.type class QueryV1( - UsersQuery, - CircuitsQuery, - CoreQuery, - DCIMQuery, - ExtrasQuery, - IPAMQuery, - TenancyQuery, - VirtualizationQuery, - VPNQuery, - WirelessQuery, + UsersQueryV1, + CircuitsQueryV1, + CoreQueryV1, + DCIMQueryV1, + ExtrasQueryV1, + IPAMQueryV1, + TenancyQueryV1, + VirtualizationQueryV1, + VPNQueryV1, + WirelessQueryV1, *registry['plugins']['graphql_schemas'], # Append plugin schemas ): """Query class for GraphQL API v1""" diff --git a/netbox/netbox/graphql/types_v1.py b/netbox/netbox/graphql/types_v1.py new file mode 100644 index 0000000000..c6b3ad2ecf --- /dev/null +++ b/netbox/netbox/graphql/types_v1.py @@ -0,0 +1,100 @@ +import strawberry +import strawberry_django +from strawberry.types import Info +from django.contrib.contenttypes.models import ContentType + +from core.graphql.mixins import ChangelogMixin +from core.models import ObjectType as ObjectType_ +from extras.graphql.mixins import CustomFieldsMixin, JournalEntriesMixin, TagsMixin + +__all__ = ( + 'BaseObjectTypeV1', + 'ContentTypeTypeV1', + 'ObjectTypeV1', + 'OrganizationalObjectTypeV1', + 'NetBoxObjectTypeV1', +) + + +# +# Base types +# + +@strawberry.type +class BaseObjectTypeV1: + """ + Base GraphQL object type for all NetBox objects. Restricts the model queryset to enforce object permissions. + """ + + @classmethod + def get_queryset(cls, queryset, info: Info, **kwargs): + # Enforce object permissions on the queryset + if hasattr(queryset, 'restrict'): + return queryset.restrict(info.context.request.user, 'view') + else: + return queryset + + @strawberry_django.field + def display(self) -> str: + return str(self) + + @strawberry_django.field + def class_type(self) -> str: + return self.__class__.__name__ + + +class ObjectTypeV1( + ChangelogMixin, + BaseObjectTypeV1 +): + """ + Base GraphQL object type for unclassified models which support change logging + """ + pass + + +class OrganizationalObjectTypeV1( + ChangelogMixin, + CustomFieldsMixin, + TagsMixin, + BaseObjectTypeV1 +): + """ + Base type for organizational models + """ + pass + + +class NetBoxObjectTypeV1( + ChangelogMixin, + CustomFieldsMixin, + JournalEntriesMixin, + TagsMixin, + BaseObjectTypeV1 +): + """ + GraphQL type for most NetBox models. Includes support for custom fields, change logging, journaling, and tags. + """ + pass + + +# +# Miscellaneous types +# + +@strawberry_django.type( + ContentType, + fields=['id', 'app_label', 'model'], + pagination=True +) +class ContentTypeTypeV1: + pass + + +@strawberry_django.type( + ObjectType_, + fields=['id', 'app_label', 'model'], + pagination=True +) +class ObjectTypeTypeV1: + pass diff --git a/netbox/tenancy/graphql/filter_mixins_v1.py b/netbox/tenancy/graphql/filter_mixins_v1.py new file mode 100644 index 0000000000..c5ffd914f8 --- /dev/null +++ b/netbox/tenancy/graphql/filter_mixins_v1.py @@ -0,0 +1,38 @@ +from dataclasses import dataclass +from typing import Annotated, TYPE_CHECKING + +import strawberry +import strawberry_django +from strawberry import ID + +from core.graphql.filter_mixins_v1 import BaseFilterMixinV1 + +if TYPE_CHECKING: + from netbox.graphql.filter_lookups import TreeNodeFilter + from .filters_v1 import ContactAssignmentFilterV1, TenantFilterV1, TenantGroupFilterV1 + +__all__ = ( + 'ContactFilterMixinV1', + 'TenancyFilterMixinV1', +) + + +@dataclass +class ContactFilterMixinV1(BaseFilterMixinV1): + contacts: Annotated['ContactAssignmentFilterV1', strawberry.lazy('tenancy.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + + +@dataclass +class TenancyFilterMixinV1(BaseFilterMixinV1): + tenant: Annotated['TenantFilterV1', strawberry.lazy('tenancy.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + tenant_id: ID | None = strawberry_django.filter_field() + tenant_group: Annotated['TenantGroupFilterV1', strawberry.lazy('tenancy.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + tenant_group_id: Annotated['TreeNodeFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) diff --git a/netbox/tenancy/graphql/filters_v1.py b/netbox/tenancy/graphql/filters_v1.py new file mode 100644 index 0000000000..fb101858bc --- /dev/null +++ b/netbox/tenancy/graphql/filters_v1.py @@ -0,0 +1,210 @@ +from typing import Annotated, TYPE_CHECKING + +import strawberry +import strawberry_django +from strawberry.scalars import ID +from strawberry_django import FilterLookup + +from core.graphql.filter_mixins_v1 import ChangeLogFilterMixinV1 +from extras.graphql.filter_mixins_v1 import CustomFieldsFilterMixinV1, TagsFilterMixinV1 +from netbox.graphql.filter_mixins_v1 import ( + NestedGroupModelFilterMixinV1, + OrganizationalModelFilterMixinV1, + PrimaryModelFilterMixinV1, +) +from tenancy import models +from .filter_mixins_v1 import ContactFilterMixinV1 + +if TYPE_CHECKING: + from core.graphql.filters_v1 import ContentTypeFilterV1 + from circuits.graphql.filters_v1 import CircuitFilterV1, CircuitGroupFilterV1, VirtualCircuitFilterV1 + from dcim.graphql.filters_v1 import ( + CableFilterV1, + DeviceFilterV1, + LocationFilterV1, + PowerFeedFilterV1, + RackFilterV1, + RackReservationFilterV1, + SiteFilterV1, + VirtualDeviceContextFilterV1, + ) + from ipam.graphql.filters_v1 import ( + AggregateFilterV1, + ASNFilterV1, + ASNRangeFilterV1, + IPAddressFilterV1, + IPRangeFilterV1, + PrefixFilterV1, + RouteTargetFilterV1, + VLANFilterV1, + VLANGroupFilterV1, + VRFFilterV1, + ) + from netbox.graphql.filter_lookups import TreeNodeFilter + from wireless.graphql.filters_v1 import WirelessLANFilterV1, WirelessLinkFilterV1 + from virtualization.graphql.filters_v1 import ClusterFilterV1, VirtualMachineFilterV1 + from vpn.graphql.filters_v1 import L2VPNFilterV1, TunnelFilterV1 + from .enums import * + +__all__ = ( + 'TenantFilterV1', + 'TenantGroupFilterV1', + 'ContactFilterV1', + 'ContactRoleFilterV1', + 'ContactGroupFilterV1', + 'ContactAssignmentFilterV1', +) + + +@strawberry_django.filter_type(models.Tenant, lookups=True) +class TenantFilterV1(PrimaryModelFilterMixinV1, ContactFilterMixinV1): + name: FilterLookup[str] | None = strawberry_django.filter_field() + slug: FilterLookup[str] | None = strawberry_django.filter_field() + group: Annotated['TenantGroupFilterV1', strawberry.lazy('tenancy.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + group_id: Annotated['TreeNodeFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + + # Reverse relations + aggregates: Annotated['AggregateFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + asns: Annotated['ASNFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = strawberry_django.filter_field() + asn_ranges: Annotated['ASNRangeFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + cables: Annotated['CableFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + circuit_groups: Annotated['CircuitGroupFilterV1', strawberry.lazy('circuits.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + circuits: Annotated['CircuitFilterV1', strawberry.lazy('circuits.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + clusters: Annotated['ClusterFilterV1', strawberry.lazy('virtualization.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + devices: Annotated['DeviceFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + ip_addresses: Annotated['IPAddressFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + ip_ranges: Annotated['IPRangeFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + l2vpns: Annotated['L2VPNFilterV1', strawberry.lazy('vpn.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + locations: Annotated['LocationFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + power_feeds: Annotated['PowerFeedFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + prefixes: Annotated['PrefixFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + racks: Annotated['RackFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + rackreservations: Annotated['RackReservationFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + route_targets: Annotated['RouteTargetFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + sites: Annotated['SiteFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + tunnels: Annotated['TunnelFilterV1', strawberry.lazy('vpn.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + vdcs: Annotated['VirtualDeviceContextFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + virtual_machines: Annotated[ + 'VirtualMachineFilterV1', strawberry.lazy('virtualization.graphql.filters_v1') + ] | None = ( + strawberry_django.filter_field() + ) + vlan_groups: Annotated['VLANGroupFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + vlans: Annotated['VLANFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + virtual_circuits: Annotated['VirtualCircuitFilterV1', strawberry.lazy('circuits.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + vrfs: Annotated['VRFFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = strawberry_django.filter_field() + wireless_lans: Annotated['WirelessLANFilterV1', strawberry.lazy('wireless.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + wireless_links: Annotated['WirelessLinkFilterV1', strawberry.lazy('wireless.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.TenantGroup, lookups=True) +class TenantGroupFilterV1(OrganizationalModelFilterMixinV1): + parent: Annotated['TenantGroupFilterV1', strawberry.lazy('tenancy.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + parent_id: ID | None = strawberry.UNSET + tenants: Annotated['TenantFilterV1', strawberry.lazy('tenancy.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + children: Annotated['TenantGroupFilterV1', strawberry.lazy('tenancy.graphql.filters_v1'), True] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.Contact, lookups=True) +class ContactFilterV1(PrimaryModelFilterMixinV1): + name: FilterLookup[str] | None = strawberry_django.filter_field() + title: FilterLookup[str] | None = strawberry_django.filter_field() + phone: FilterLookup[str] | None = strawberry_django.filter_field() + email: FilterLookup[str] | None = strawberry_django.filter_field() + address: FilterLookup[str] | None = strawberry_django.filter_field() + link: FilterLookup[str] | None = strawberry_django.filter_field() + groups: Annotated['ContactGroupFilterV1', strawberry.lazy('tenancy.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + assignments: Annotated['ContactAssignmentFilterV1', strawberry.lazy('tenancy.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.ContactRole, lookups=True) +class ContactRoleFilterV1(OrganizationalModelFilterMixinV1): + pass + + +@strawberry_django.filter_type(models.ContactGroup, lookups=True) +class ContactGroupFilterV1(NestedGroupModelFilterMixinV1): + parent: Annotated['ContactGroupFilterV1', strawberry.lazy('tenancy.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.ContactAssignment, lookups=True) +class ContactAssignmentFilterV1(CustomFieldsFilterMixinV1, TagsFilterMixinV1, ChangeLogFilterMixinV1): + object_type: Annotated['ContentTypeFilterV1', strawberry.lazy('core.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + object_id: ID | None = strawberry_django.filter_field() + contact: Annotated['ContactFilterV1', strawberry.lazy('tenancy.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + contact_id: ID | None = strawberry_django.filter_field() + role: Annotated['ContactRoleFilterV1', strawberry.lazy('tenancy.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + role_id: ID | None = strawberry_django.filter_field() + priority: Annotated['ContactPriorityEnum', strawberry.lazy('tenancy.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) diff --git a/netbox/tenancy/graphql/mixins_v1.py b/netbox/tenancy/graphql/mixins_v1.py new file mode 100644 index 0000000000..a6c31b68a0 --- /dev/null +++ b/netbox/tenancy/graphql/mixins_v1.py @@ -0,0 +1,12 @@ +from typing import Annotated, List + +import strawberry + +__all__ = ( + 'ContactAssignmentsMixinV1', +) + + +@strawberry.type +class ContactAssignmentsMixinV1: + assignments: List[Annotated["ContactAssignmentTypeV1", strawberry.lazy('tenancy.graphql.types_v1')]] # noqa: F821 diff --git a/netbox/tenancy/graphql/schema_v1.py b/netbox/tenancy/graphql/schema_v1.py new file mode 100644 index 0000000000..135f1573f6 --- /dev/null +++ b/netbox/tenancy/graphql/schema_v1.py @@ -0,0 +1,27 @@ +from typing import List + +import strawberry +import strawberry_django + +from .types_v1 import * + + +@strawberry.type(name="Query") +class TenancyQueryV1: + tenant: TenantTypeV1 = strawberry_django.field() + tenant_list: List[TenantTypeV1] = strawberry_django.field() + + tenant_group: TenantGroupTypeV1 = strawberry_django.field() + tenant_group_list: List[TenantGroupTypeV1] = strawberry_django.field() + + contact: ContactTypeV1 = strawberry_django.field() + contact_list: List[ContactTypeV1] = strawberry_django.field() + + contact_role: ContactRoleTypeV1 = strawberry_django.field() + contact_role_list: List[ContactRoleTypeV1] = strawberry_django.field() + + contact_group: ContactGroupTypeV1 = strawberry_django.field() + contact_group_list: List[ContactGroupTypeV1] = strawberry_django.field() + + contact_assignment: ContactAssignmentTypeV1 = strawberry_django.field() + contact_assignment_list: List[ContactAssignmentTypeV1] = strawberry_django.field() diff --git a/netbox/tenancy/graphql/types_v1.py b/netbox/tenancy/graphql/types_v1.py new file mode 100644 index 0000000000..cc4b774bc0 --- /dev/null +++ b/netbox/tenancy/graphql/types_v1.py @@ -0,0 +1,147 @@ +from typing import Annotated, List, TYPE_CHECKING + +import strawberry +import strawberry_django + +from extras.graphql.mixins_v1 import CustomFieldsMixinV1, TagsMixinV1, ContactsMixinV1 +from netbox.graphql.types_v1 import BaseObjectTypeV1, OrganizationalObjectTypeV1, NetBoxObjectTypeV1 +from tenancy import models +from .filters_v1 import * +from .mixins_v1 import ContactAssignmentsMixinV1 + +if TYPE_CHECKING: + from circuits.graphql.types_v1 import CircuitTypeV1 + from dcim.graphql.types_v1 import ( + CableTypeV1, + DeviceTypeV1, + LocationTypeV1, + PowerFeedTypeV1, + RackTypeV1, + RackReservationTypeV1, + SiteTypeV1, + VirtualDeviceContextTypeV1, + ) + from ipam.graphql.types_v1 import ( + AggregateTypeV1, + ASNTypeV1, + ASNRangeTypeV1, + IPAddressTypeV1, + IPRangeTypeV1, + PrefixTypeV1, + RouteTargetTypeV1, + VLANTypeV1, + VRFTypeV1, + ) + from netbox.graphql.types_v1 import ContentTypeTypeV1 + from wireless.graphql.types_v1 import WirelessLANTypeV1, WirelessLinkTypeV1 + from virtualization.graphql.types_v1 import ClusterTypeV1, VirtualMachineTypeV1 + from vpn.graphql.types_v1 import L2VPNTypeV1, TunnelTypeV1 + +__all__ = ( + 'ContactAssignmentTypeV1', + 'ContactGroupTypeV1', + 'ContactRoleTypeV1', + 'ContactTypeV1', + 'TenantTypeV1', + 'TenantGroupTypeV1', +) + + +# +# Tenants +# + +@strawberry_django.type( + models.Tenant, + fields='__all__', + filters=TenantFilterV1, + pagination=True +) +class TenantTypeV1(ContactsMixinV1, NetBoxObjectTypeV1): + group: Annotated['TenantGroupTypeV1', strawberry.lazy('tenancy.graphql.types_v1')] | None + asns: List[Annotated['ASNTypeV1', strawberry.lazy('ipam.graphql.types_v1')]] + circuits: List[Annotated['CircuitTypeV1', strawberry.lazy('circuits.graphql.types_v1')]] + sites: List[Annotated['SiteTypeV1', strawberry.lazy('dcim.graphql.types_v1')]] + vlans: List[Annotated['VLANTypeV1', strawberry.lazy('ipam.graphql.types_v1')]] + wireless_lans: List[Annotated['WirelessLANTypeV1', strawberry.lazy('wireless.graphql.types_v1')]] + route_targets: List[Annotated['RouteTargetTypeV1', strawberry.lazy('ipam.graphql.types_v1')]] + locations: List[Annotated['LocationTypeV1', strawberry.lazy('dcim.graphql.types_v1')]] + ip_ranges: List[Annotated['IPRangeTypeV1', strawberry.lazy('ipam.graphql.types_v1')]] + rackreservations: List[Annotated['RackReservationTypeV1', strawberry.lazy('dcim.graphql.types_v1')]] + racks: List[Annotated['RackTypeV1', strawberry.lazy('dcim.graphql.types_v1')]] + vdcs: List[Annotated['VirtualDeviceContextTypeV1', strawberry.lazy('dcim.graphql.types_v1')]] + prefixes: List[Annotated['PrefixTypeV1', strawberry.lazy('ipam.graphql.types_v1')]] + cables: List[Annotated['CableTypeV1', strawberry.lazy('dcim.graphql.types_v1')]] + virtual_machines: List[Annotated['VirtualMachineTypeV1', strawberry.lazy('virtualization.graphql.types_v1')]] + vrfs: List[Annotated['VRFTypeV1', strawberry.lazy('ipam.graphql.types_v1')]] + asn_ranges: List[Annotated['ASNRangeTypeV1', strawberry.lazy('ipam.graphql.types_v1')]] + wireless_links: List[Annotated['WirelessLinkTypeV1', strawberry.lazy('wireless.graphql.types_v1')]] + aggregates: List[Annotated['AggregateTypeV1', strawberry.lazy('ipam.graphql.types_v1')]] + power_feeds: List[Annotated['PowerFeedTypeV1', strawberry.lazy('dcim.graphql.types_v1')]] + devices: List[Annotated['DeviceTypeV1', strawberry.lazy('dcim.graphql.types_v1')]] + tunnels: List[Annotated['TunnelTypeV1', strawberry.lazy('vpn.graphql.types_v1')]] + ip_addresses: List[Annotated['IPAddressTypeV1', strawberry.lazy('ipam.graphql.types_v1')]] + clusters: List[Annotated['ClusterTypeV1', strawberry.lazy('virtualization.graphql.types_v1')]] + l2vpns: List[Annotated['L2VPNTypeV1', strawberry.lazy('vpn.graphql.types_v1')]] + + +@strawberry_django.type( + models.TenantGroup, + fields='__all__', + filters=TenantGroupFilterV1, + pagination=True +) +class TenantGroupTypeV1(OrganizationalObjectTypeV1): + parent: Annotated['TenantGroupTypeV1', strawberry.lazy('tenancy.graphql.types_v1')] | None + + tenants: List[TenantTypeV1] + children: List[Annotated['TenantGroupTypeV1', strawberry.lazy('tenancy.graphql.types_v1')]] + + +# +# Contacts +# + +@strawberry_django.type( + models.Contact, + fields='__all__', + filters=ContactFilterV1, + pagination=True +) +class ContactTypeV1(ContactAssignmentsMixinV1, NetBoxObjectTypeV1): + groups: List[Annotated['ContactGroupTypeV1', strawberry.lazy('tenancy.graphql.types_v1')]] + + +@strawberry_django.type( + models.ContactRole, + fields='__all__', + filters=ContactRoleFilterV1, + pagination=True +) +class ContactRoleTypeV1(ContactAssignmentsMixinV1, OrganizationalObjectTypeV1): + pass + + +@strawberry_django.type( + models.ContactGroup, + fields='__all__', + filters=ContactGroupFilterV1, + pagination=True +) +class ContactGroupTypeV1(OrganizationalObjectTypeV1): + parent: Annotated['ContactGroupTypeV1', strawberry.lazy('tenancy.graphql.types_v1')] | None + + contacts: List[ContactTypeV1] + children: List[Annotated['ContactGroupTypeV1', strawberry.lazy('tenancy.graphql.types_v1')]] + + +@strawberry_django.type( + models.ContactAssignment, + fields='__all__', + filters=ContactAssignmentFilterV1, + pagination=True +) +class ContactAssignmentTypeV1(CustomFieldsMixinV1, TagsMixinV1, BaseObjectTypeV1): + object_type: Annotated['ContentTypeTypeV1', strawberry.lazy('netbox.graphql.types_v1')] | None + contact: Annotated['ContactTypeV1', strawberry.lazy('tenancy.graphql.types_v1')] | None + role: Annotated['ContactRoleTypeV1', strawberry.lazy('tenancy.graphql.types_v1')] | None diff --git a/netbox/users/graphql/filters_v1.py b/netbox/users/graphql/filters_v1.py new file mode 100644 index 0000000000..1b08ed6fc9 --- /dev/null +++ b/netbox/users/graphql/filters_v1.py @@ -0,0 +1,34 @@ +from datetime import datetime +from typing import Annotated + +import strawberry +import strawberry_django +from strawberry_django import DatetimeFilterLookup, FilterLookup + +from core.graphql.filter_mixins_v1 import BaseObjectTypeFilterMixinV1 +from users import models + +__all__ = ( + 'GroupFilterV1', + 'UserFilterV1', +) + + +@strawberry_django.filter_type(models.Group, lookups=True) +class GroupFilterV1(BaseObjectTypeFilterMixinV1): + name: FilterLookup[str] | None = strawberry_django.filter_field() + description: FilterLookup[str] | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.User, lookups=True) +class UserFilterV1(BaseObjectTypeFilterMixinV1): + username: FilterLookup[str] | None = strawberry_django.filter_field() + first_name: FilterLookup[str] | None = strawberry_django.filter_field() + last_name: FilterLookup[str] | None = strawberry_django.filter_field() + email: FilterLookup[str] | None = strawberry_django.filter_field() + is_superuser: FilterLookup[bool] | None = strawberry_django.filter_field() + is_active: FilterLookup[bool] | None = strawberry_django.filter_field() + date_joined: DatetimeFilterLookup[datetime] | None = strawberry_django.filter_field() + last_login: DatetimeFilterLookup[datetime] | None = strawberry_django.filter_field() + groups: Annotated['GroupFilterV1', strawberry.lazy('users.graphql.filters_v1')] | None = ( + strawberry_django.filter_field()) diff --git a/netbox/users/graphql/schema_v1.py b/netbox/users/graphql/schema_v1.py new file mode 100644 index 0000000000..69c3b9d57a --- /dev/null +++ b/netbox/users/graphql/schema_v1.py @@ -0,0 +1,15 @@ +from typing import List + +import strawberry +import strawberry_django + +from .types_v1 import * + + +@strawberry.type(name="Query") +class UsersQueryV1: + group: GroupTypeV1 = strawberry_django.field() + group_list: List[GroupTypeV1] = strawberry_django.field() + + user: UserTypeV1 = strawberry_django.field() + user_list: List[UserTypeV1] = strawberry_django.field() diff --git a/netbox/users/graphql/types_v1.py b/netbox/users/graphql/types_v1.py new file mode 100644 index 0000000000..3b48431d08 --- /dev/null +++ b/netbox/users/graphql/types_v1.py @@ -0,0 +1,34 @@ +from typing import List + +import strawberry_django + +from netbox.graphql.types_v1 import BaseObjectTypeV1 +from users.models import Group, User +from .filters_v1 import * + +__all__ = ( + 'GroupTypeV1', + 'UserTypeV1', +) + + +@strawberry_django.type( + Group, + fields=['id', 'name'], + filters=GroupFilterV1, + pagination=True +) +class GroupTypeV1(BaseObjectTypeV1): + pass + + +@strawberry_django.type( + User, + fields=[ + 'id', 'username', 'first_name', 'last_name', 'email', 'is_active', 'date_joined', 'groups', + ], + filters=UserFilterV1, + pagination=True +) +class UserTypeV1(BaseObjectTypeV1): + groups: List[GroupTypeV1] diff --git a/netbox/virtualization/graphql/filter_mixins_v1.py b/netbox/virtualization/graphql/filter_mixins_v1.py new file mode 100644 index 0000000000..7de4192c8c --- /dev/null +++ b/netbox/virtualization/graphql/filter_mixins_v1.py @@ -0,0 +1,28 @@ +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_v1 import NetBoxModelFilterMixinV1 + +if TYPE_CHECKING: + from .filters_v1 import VirtualMachineFilterV1 + +__all__ = ( + 'VMComponentFilterMixinV1', +) + + +@dataclass +class VMComponentFilterMixinV1(NetBoxModelFilterMixinV1): + virtual_machine: Annotated[ + 'VirtualMachineFilterV1', strawberry.lazy('virtualization.graphql.filters_v1') + ] | 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() diff --git a/netbox/virtualization/graphql/filters_v1.py b/netbox/virtualization/graphql/filters_v1.py new file mode 100644 index 0000000000..d1ba0cff4e --- /dev/null +++ b/netbox/virtualization/graphql/filters_v1.py @@ -0,0 +1,170 @@ +from typing import Annotated, TYPE_CHECKING + +import strawberry +import strawberry_django +from strawberry.scalars import ID +from strawberry_django import FilterLookup + +from dcim.graphql.filter_mixins_v1 import InterfaceBaseFilterMixinV1, RenderConfigFilterMixinV1, ScopedFilterMixinV1 +from extras.graphql.filter_mixins_v1 import ConfigContextFilterMixinV1 +from netbox.graphql.filter_mixins_v1 import ( + ImageAttachmentFilterMixinV1, + OrganizationalModelFilterMixinV1, + PrimaryModelFilterMixinV1, +) +from tenancy.graphql.filter_mixins_v1 import ContactFilterMixinV1, TenancyFilterMixinV1 +from virtualization import models +from virtualization.graphql.filter_mixins_v1 import VMComponentFilterMixinV1 + +if TYPE_CHECKING: + from .enums import * + from netbox.graphql.filter_lookups import FloatLookup, IntegerLookup + from dcim.graphql.filters_v1 import ( + DeviceFilterV1, DeviceRoleFilterV1, MACAddressFilterV1, PlatformFilterV1, SiteFilterV1 + ) + from ipam.graphql.filters_v1 import ( + FHRPGroupAssignmentFilterV1, + IPAddressFilterV1, + ServiceFilterV1, + VLANGroupFilterV1, + VRFFilterV1, + ) + from vpn.graphql.filters_v1 import L2VPNFilterV1, TunnelTerminationFilterV1 + +__all__ = ( + 'ClusterFilterV1', + 'ClusterGroupFilterV1', + 'ClusterTypeFilterV1', + 'VirtualMachineFilterV1', + 'VMInterfaceFilterV1', + 'VirtualDiskFilterV1', +) + + +@strawberry_django.filter_type(models.Cluster, lookups=True) +class ClusterFilterV1(ContactFilterMixinV1, ScopedFilterMixinV1, TenancyFilterMixinV1, PrimaryModelFilterMixinV1): + name: FilterLookup[str] | None = strawberry_django.filter_field() + type: Annotated['ClusterTypeFilterV1', strawberry.lazy('virtualization.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + type_id: ID | None = strawberry_django.filter_field() + group: Annotated['ClusterGroupFilterV1', strawberry.lazy('virtualization.graphql.filters_v1')] | 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['VLANGroupFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.ClusterGroup, lookups=True) +class ClusterGroupFilterV1(ContactFilterMixinV1, OrganizationalModelFilterMixinV1): + vlan_groups: Annotated['VLANGroupFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.ClusterType, lookups=True) +class ClusterTypeFilterV1(OrganizationalModelFilterMixinV1): + pass + + +@strawberry_django.filter_type(models.VirtualMachine, lookups=True) +class VirtualMachineFilterV1( + ContactFilterMixinV1, + ImageAttachmentFilterMixinV1, + RenderConfigFilterMixinV1, + ConfigContextFilterMixinV1, + TenancyFilterMixinV1, + PrimaryModelFilterMixinV1, +): + name: FilterLookup[str] | None = strawberry_django.filter_field() + site: Annotated['SiteFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + site_id: ID | None = strawberry_django.filter_field() + cluster: Annotated['ClusterFilterV1', strawberry.lazy('virtualization.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + cluster_id: ID | None = strawberry_django.filter_field() + device: Annotated['DeviceFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + device_id: ID | None = strawberry_django.filter_field() + platform: Annotated['PlatformFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | 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['DeviceRoleFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + role_id: ID | None = strawberry_django.filter_field() + primary_ip4: Annotated['IPAddressFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + primary_ip4_id: ID | None = strawberry_django.filter_field() + primary_ip6: Annotated['IPAddressFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | 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['VMInterfaceFilterV1', strawberry.lazy('virtualization.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + services: Annotated['ServiceFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + virtual_disks: Annotated['VirtualDiskFilterV1', strawberry.lazy('virtualization.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.VMInterface, lookups=True) +class VMInterfaceFilterV1(VMComponentFilterMixinV1, InterfaceBaseFilterMixinV1): + ip_addresses: Annotated['IPAddressFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + vrf: Annotated['VRFFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = strawberry_django.filter_field() + vrf_id: ID | None = strawberry_django.filter_field() + parent: Annotated['VMInterfaceFilterV1', strawberry.lazy('virtualization.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + parent_id: ID | None = strawberry_django.filter_field() + fhrp_group_assignments: Annotated[ + 'FHRPGroupAssignmentFilterV1', strawberry.lazy('ipam.graphql.filters_v1') + ] | None = ( + strawberry_django.filter_field() + ) + tunnel_terminations: Annotated['TunnelTerminationFilterV1', strawberry.lazy('vpn.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + l2vpn_terminations: Annotated['L2VPNFilterV1', strawberry.lazy('vpn.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + mac_addresses: Annotated['MACAddressFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.VirtualDisk, lookups=True) +class VirtualDiskFilterV1(VMComponentFilterMixinV1): + size: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) diff --git a/netbox/virtualization/graphql/schema_v1.py b/netbox/virtualization/graphql/schema_v1.py new file mode 100644 index 0000000000..85994411fb --- /dev/null +++ b/netbox/virtualization/graphql/schema_v1.py @@ -0,0 +1,27 @@ +from typing import List + +import strawberry +import strawberry_django + +from .types_v1 import * + + +@strawberry.type(name="Query") +class VirtualizationQueryV1: + cluster: ClusterTypeV1 = strawberry_django.field() + cluster_list: List[ClusterTypeV1] = strawberry_django.field() + + cluster_group: ClusterGroupTypeV1 = strawberry_django.field() + cluster_group_list: List[ClusterGroupTypeV1] = strawberry_django.field() + + cluster_type: ClusterTypeTypeV1 = strawberry_django.field() + cluster_type_list: List[ClusterTypeTypeV1] = strawberry_django.field() + + virtual_machine: VirtualMachineTypeV1 = strawberry_django.field() + virtual_machine_list: List[VirtualMachineTypeV1] = strawberry_django.field() + + vm_interface: VMInterfaceTypeV1 = strawberry_django.field() + vm_interface_list: List[VMInterfaceTypeV1] = strawberry_django.field() + + virtual_disk: VirtualDiskTypeV1 = strawberry_django.field() + virtual_disk_list: List[VirtualDiskTypeV1] = strawberry_django.field() diff --git a/netbox/virtualization/graphql/types_v1.py b/netbox/virtualization/graphql/types_v1.py new file mode 100644 index 0000000000..079fa7b29a --- /dev/null +++ b/netbox/virtualization/graphql/types_v1.py @@ -0,0 +1,146 @@ +from typing import Annotated, List, TYPE_CHECKING, Union + +import strawberry +import strawberry_django + +from extras.graphql.mixins_v1 import ConfigContextMixinV1, ContactsMixinV1 +from ipam.graphql.mixins_v1 import IPAddressesMixinV1, VLANGroupsMixinV1 +from netbox.graphql.scalars import BigInt +from netbox.graphql.types_v1 import OrganizationalObjectTypeV1, NetBoxObjectTypeV1 +from virtualization import models +from .filters_v1 import * + +if TYPE_CHECKING: + from dcim.graphql.types_v1 import ( + DeviceRoleTypeV1, + DeviceTypeV1, + LocationTypeV1, + MACAddressTypeV1, + PlatformTypeV1, + RegionTypeV1, + SiteGroupTypeV1, + SiteTypeV1, + ) + from extras.graphql.types_v1 import ConfigTemplateTypeV1 + from ipam.graphql.types_v1 import IPAddressTypeV1, ServiceTypeV1, VLANTranslationPolicyTypeV1, VLANTypeV1, VRFTypeV1 + from tenancy.graphql.types_v1 import TenantTypeV1 + +__all__ = ( + 'ClusterTypeV1', + 'ClusterGroupTypeV1', + 'ClusterTypeTypeV1', + 'VirtualDiskTypeV1', + 'VirtualMachineTypeV1', + 'VMInterfaceTypeV1', +) + + +@strawberry.type +class ComponentTypeV1(NetBoxObjectTypeV1): + """ + Base type for device/VM components + """ + virtual_machine: Annotated["VirtualMachineTypeV1", strawberry.lazy('virtualization.graphql.types_v1')] + + +@strawberry_django.type( + models.Cluster, + exclude=['scope_type', 'scope_id', '_location', '_region', '_site', '_site_group'], + filters=ClusterFilterV1, + pagination=True +) +class ClusterTypeV1(ContactsMixinV1, VLANGroupsMixinV1, NetBoxObjectTypeV1): + type: Annotated["ClusterTypeTypeV1", strawberry.lazy('virtualization.graphql.types_v1')] | None + group: Annotated["ClusterGroupTypeV1", strawberry.lazy('virtualization.graphql.types_v1')] | None + tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None + virtual_machines: List[Annotated["VirtualMachineTypeV1", strawberry.lazy('virtualization.graphql.types_v1')]] + devices: List[Annotated["DeviceTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + + @strawberry_django.field + def scope(self) -> Annotated[Union[ + Annotated["LocationTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["RegionTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["SiteGroupTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["SiteTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + ], strawberry.union("ClusterScopeTypeV1")] | None: + return self.scope + + +@strawberry_django.type( + models.ClusterGroup, + fields='__all__', + filters=ClusterGroupFilterV1, + pagination=True +) +class ClusterGroupTypeV1(ContactsMixinV1, VLANGroupsMixinV1, OrganizationalObjectTypeV1): + + clusters: List[Annotated["ClusterTypeV1", strawberry.lazy('virtualization.graphql.types_v1')]] + + +@strawberry_django.type( + models.ClusterType, + fields='__all__', + filters=ClusterTypeFilterV1, + pagination=True +) +class ClusterTypeTypeV1(OrganizationalObjectTypeV1): + + clusters: List[ClusterTypeV1] + + +@strawberry_django.type( + models.VirtualMachine, + fields='__all__', + filters=VirtualMachineFilterV1, + pagination=True +) +class VirtualMachineTypeV1(ConfigContextMixinV1, ContactsMixinV1, NetBoxObjectTypeV1): + interface_count: BigInt + virtual_disk_count: BigInt + interface_count: BigInt + config_template: Annotated["ConfigTemplateTypeV1", strawberry.lazy('extras.graphql.types_v1')] | None + site: Annotated["SiteTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + cluster: Annotated["ClusterTypeV1", strawberry.lazy('virtualization.graphql.types_v1')] | None + device: Annotated["DeviceTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None + platform: Annotated["PlatformTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + role: Annotated["DeviceRoleTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + primary_ip4: Annotated["IPAddressTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None + primary_ip6: Annotated["IPAddressTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None + + interfaces: List[Annotated["VMInterfaceTypeV1", strawberry.lazy('virtualization.graphql.types_v1')]] + services: List[Annotated["ServiceTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] + virtualdisks: List[Annotated["VirtualDiskTypeV1", strawberry.lazy('virtualization.graphql.types_v1')]] + + +@strawberry_django.type( + models.VMInterface, + fields='__all__', + filters=VMInterfaceFilterV1, + pagination=True +) +class VMInterfaceTypeV1(IPAddressesMixinV1, ComponentTypeV1): + _name: str + mac_address: str | None + parent: Annotated["VMInterfaceTypeV1", strawberry.lazy('virtualization.graphql.types_v1')] | None + bridge: Annotated["VMInterfaceTypeV1", strawberry.lazy('virtualization.graphql.types_v1')] | None + untagged_vlan: Annotated["VLANTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None + vrf: Annotated["VRFTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None + primary_mac_address: Annotated["MACAddressTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + qinq_svlan: Annotated["VLANTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None + vlan_translation_policy: Annotated["VLANTranslationPolicyTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None + + tagged_vlans: List[Annotated["VLANTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] + bridge_interfaces: List[Annotated["VMInterfaceTypeV1", strawberry.lazy('virtualization.graphql.types_v1')]] + child_interfaces: List[Annotated["VMInterfaceTypeV1", strawberry.lazy('virtualization.graphql.types_v1')]] + mac_addresses: List[Annotated["MACAddressTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + + +@strawberry_django.type( + models.VirtualDisk, + fields='__all__', + filters=VirtualDiskFilterV1, + pagination=True +) +class VirtualDiskTypeV1(ComponentTypeV1): + pass diff --git a/netbox/vpn/graphql/filters_v1.py b/netbox/vpn/graphql/filters_v1.py new file mode 100644 index 0000000000..9b70b9a9ee --- /dev/null +++ b/netbox/vpn/graphql/filters_v1.py @@ -0,0 +1,192 @@ +from typing import Annotated, TYPE_CHECKING + +import strawberry +import strawberry_django +from strawberry.scalars import ID +from strawberry_django import FilterLookup + +from core.graphql.filter_mixins_v1 import BaseObjectTypeFilterMixinV1, ChangeLogFilterMixinV1 +from extras.graphql.filter_mixins_v1 import CustomFieldsFilterMixinV1, TagsFilterMixinV1 +from netbox.graphql.filter_mixins_v1 import ( + NetBoxModelFilterMixinV1, OrganizationalModelFilterMixinV1, PrimaryModelFilterMixinV1 +) +from tenancy.graphql.filter_mixins_v1 import ContactFilterMixinV1, TenancyFilterMixinV1 +from vpn import models + +if TYPE_CHECKING: + from core.graphql.filters_v1 import ContentTypeFilterV1 + from ipam.graphql.filters_v1 import IPAddressFilterV1, RouteTargetFilterV1 + from netbox.graphql.filter_lookups import IntegerLookup + from .enums import * + +__all__ = ( + 'TunnelGroupFilterV1', + 'TunnelTerminationFilterV1', + 'TunnelFilterV1', + 'IKEProposalFilterV1', + 'IKEPolicyFilterV1', + 'IPSecProposalFilterV1', + 'IPSecPolicyFilterV1', + 'IPSecProfileFilterV1', + 'L2VPNFilterV1', + 'L2VPNTerminationFilterV1', +) + + +@strawberry_django.filter_type(models.TunnelGroup, lookups=True) +class TunnelGroupFilterV1(OrganizationalModelFilterMixinV1): + pass + + +@strawberry_django.filter_type(models.TunnelTermination, lookups=True) +class TunnelTerminationFilterV1( + BaseObjectTypeFilterMixinV1, CustomFieldsFilterMixinV1, TagsFilterMixinV1, ChangeLogFilterMixinV1 +): + tunnel: Annotated['TunnelFilterV1', strawberry.lazy('vpn.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + tunnel_id: ID | None = strawberry_django.filter_field() + role: Annotated['TunnelTerminationRoleEnum', strawberry.lazy('vpn.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + termination_type: Annotated['TunnelTerminationTypeEnum', strawberry.lazy('vpn.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + termination_type_id: ID | None = strawberry_django.filter_field() + termination_id: ID | None = strawberry_django.filter_field() + outside_ip: Annotated['IPAddressFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + outside_ip_id: ID | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.Tunnel, lookups=True) +class TunnelFilterV1(TenancyFilterMixinV1, PrimaryModelFilterMixinV1): + name: FilterLookup[str] | None = strawberry_django.filter_field() + status: Annotated['TunnelStatusEnum', strawberry.lazy('vpn.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + group: Annotated['TunnelGroupFilterV1', strawberry.lazy('vpn.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + group_id: ID | None = strawberry_django.filter_field() + encapsulation: Annotated['TunnelEncapsulationEnum', strawberry.lazy('vpn.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + ipsec_profile: Annotated['IPSecProfileFilterV1', strawberry.lazy('vpn.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + tunnel_id: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + terminations: Annotated['TunnelTerminationFilterV1', strawberry.lazy('vpn.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.IKEProposal, lookups=True) +class IKEProposalFilterV1(PrimaryModelFilterMixinV1): + name: FilterLookup[str] | None = strawberry_django.filter_field() + authentication_method: Annotated['AuthenticationMethodEnum', strawberry.lazy('vpn.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + encryption_algorithm: Annotated['EncryptionAlgorithmEnum', strawberry.lazy('vpn.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + authentication_algorithm: Annotated['AuthenticationAlgorithmEnum', strawberry.lazy('vpn.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + group: Annotated['DHGroupEnum', strawberry.lazy('vpn.graphql.enums')] | None = strawberry_django.filter_field() + sa_lifetime: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + ike_policies: Annotated['IKEPolicyFilterV1', strawberry.lazy('vpn.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.IKEPolicy, lookups=True) +class IKEPolicyFilterV1(PrimaryModelFilterMixinV1): + name: FilterLookup[str] | None = strawberry_django.filter_field() + version: Annotated['IKEVersionEnum', strawberry.lazy('vpn.graphql.enums')] | None = strawberry_django.filter_field() + mode: Annotated['IKEModeEnum', strawberry.lazy('vpn.graphql.enums')] | None = strawberry_django.filter_field() + proposals: Annotated['IKEProposalFilterV1', strawberry.lazy('vpn.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + preshared_key: FilterLookup[str] | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.IPSecProposal, lookups=True) +class IPSecProposalFilterV1(PrimaryModelFilterMixinV1): + name: FilterLookup[str] | None = strawberry_django.filter_field() + encryption_algorithm: Annotated['EncryptionAlgorithmEnum', strawberry.lazy('vpn.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + authentication_algorithm: Annotated['AuthenticationAlgorithmEnum', strawberry.lazy('vpn.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + sa_lifetime_seconds: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + sa_lifetime_data: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + ipsec_policies: Annotated['IPSecPolicyFilterV1', strawberry.lazy('vpn.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.IPSecPolicy, lookups=True) +class IPSecPolicyFilterV1(PrimaryModelFilterMixinV1): + name: FilterLookup[str] | None = strawberry_django.filter_field() + proposals: Annotated['IPSecProposalFilterV1', strawberry.lazy('vpn.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + pfs_group: Annotated['DHGroupEnum', strawberry.lazy('vpn.graphql.enums')] | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.IPSecProfile, lookups=True) +class IPSecProfileFilterV1(PrimaryModelFilterMixinV1): + name: FilterLookup[str] | None = strawberry_django.filter_field() + mode: Annotated['IPSecModeEnum', strawberry.lazy('vpn.graphql.enums')] | None = strawberry_django.filter_field() + ike_policy: Annotated['IKEPolicyFilterV1', strawberry.lazy('vpn.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + ike_policy_id: ID | None = strawberry_django.filter_field() + ipsec_policy: Annotated['IPSecPolicyFilterV1', strawberry.lazy('vpn.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + ipsec_policy_id: ID | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.L2VPN, lookups=True) +class L2VPNFilterV1(ContactFilterMixinV1, TenancyFilterMixinV1, PrimaryModelFilterMixinV1): + name: FilterLookup[str] | None = strawberry_django.filter_field() + slug: FilterLookup[str] | None = strawberry_django.filter_field() + type: Annotated['L2VPNTypeEnum', strawberry.lazy('vpn.graphql.enums')] | None = strawberry_django.filter_field() + identifier: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) + import_targets: Annotated['RouteTargetFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + export_targets: Annotated['RouteTargetFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + terminations: Annotated['L2VPNTerminationFilterV1', strawberry.lazy('vpn.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.L2VPNTermination, lookups=True) +class L2VPNTerminationFilterV1(NetBoxModelFilterMixinV1): + l2vpn: Annotated['L2VPNFilterV1', strawberry.lazy('vpn.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + l2vpn_id: ID | None = strawberry_django.filter_field() + assigned_object_type: Annotated['ContentTypeFilterV1', strawberry.lazy('core.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + assigned_object_id: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + strawberry_django.filter_field() + ) diff --git a/netbox/vpn/graphql/schema_v1.py b/netbox/vpn/graphql/schema_v1.py new file mode 100644 index 0000000000..7ed22333ce --- /dev/null +++ b/netbox/vpn/graphql/schema_v1.py @@ -0,0 +1,39 @@ +from typing import List + +import strawberry +import strawberry_django + +from .types_v1 import * + + +@strawberry.type(name="Query") +class VPNQueryV1: + ike_policy: IKEPolicyTypeV1 = strawberry_django.field() + ike_policy_list: List[IKEPolicyTypeV1] = strawberry_django.field() + + ike_proposal: IKEProposalTypeV1 = strawberry_django.field() + ike_proposal_list: List[IKEProposalTypeV1] = strawberry_django.field() + + ipsec_policy: IPSecPolicyTypeV1 = strawberry_django.field() + ipsec_policy_list: List[IPSecPolicyTypeV1] = strawberry_django.field() + + ipsec_profile: IPSecProfileTypeV1 = strawberry_django.field() + ipsec_profile_list: List[IPSecProfileTypeV1] = strawberry_django.field() + + ipsec_proposal: IPSecProposalTypeV1 = strawberry_django.field() + ipsec_proposal_list: List[IPSecProposalTypeV1] = strawberry_django.field() + + l2vpn: L2VPNTypeV1 = strawberry_django.field() + l2vpn_list: List[L2VPNTypeV1] = strawberry_django.field() + + l2vpn_termination: L2VPNTerminationTypeV1 = strawberry_django.field() + l2vpn_termination_list: List[L2VPNTerminationTypeV1] = strawberry_django.field() + + tunnel: TunnelTypeV1 = strawberry_django.field() + tunnel_list: List[TunnelTypeV1] = strawberry_django.field() + + tunnel_group: TunnelGroupTypeV1 = strawberry_django.field() + tunnel_group_list: List[TunnelGroupTypeV1] = strawberry_django.field() + + tunnel_termination: TunnelTerminationTypeV1 = strawberry_django.field() + tunnel_termination_list: List[TunnelTerminationTypeV1] = strawberry_django.field() diff --git a/netbox/vpn/graphql/types_v1.py b/netbox/vpn/graphql/types_v1.py new file mode 100644 index 0000000000..7812f88bbf --- /dev/null +++ b/netbox/vpn/graphql/types_v1.py @@ -0,0 +1,157 @@ +from typing import Annotated, List, TYPE_CHECKING, Union + +import strawberry +import strawberry_django + +from extras.graphql.mixins_v1 import ContactsMixinV1, CustomFieldsMixinV1, TagsMixinV1 +from netbox.graphql.types_v1 import ObjectTypeV1, OrganizationalObjectTypeV1, NetBoxObjectTypeV1 +from vpn import models +from .filters_v1 import * + +if TYPE_CHECKING: + from dcim.graphql.types_v1 import InterfaceTypeV1 + from ipam.graphql.types_v1 import IPAddressTypeV1, RouteTargetTypeV1, VLANTypeV1 + from netbox.graphql.types_v1 import ContentTypeTypeV1 + from tenancy.graphql.types_v1 import TenantTypeV1 + from virtualization.graphql.types_v1 import VMInterfaceTypeV1 + +__all__ = ( + 'IKEPolicyTypeV1', + 'IKEProposalTypeV1', + 'IPSecPolicyTypeV1', + 'IPSecProfileTypeV1', + 'IPSecProposalTypeV1', + 'L2VPNTypeV1', + 'L2VPNTerminationTypeV1', + 'TunnelGroupTypeV1', + 'TunnelTerminationTypeV1', + 'TunnelTypeV1', +) + + +@strawberry_django.type( + models.TunnelGroup, + fields='__all__', + filters=TunnelGroupFilterV1, + pagination=True +) +class TunnelGroupTypeV1(ContactsMixinV1, OrganizationalObjectTypeV1): + + tunnels: List[Annotated["TunnelTypeV1", strawberry.lazy('vpn.graphql.types_v1')]] + + +@strawberry_django.type( + models.TunnelTermination, + fields='__all__', + filters=TunnelTerminationFilterV1, + pagination=True +) +class TunnelTerminationTypeV1(CustomFieldsMixinV1, TagsMixinV1, ObjectTypeV1): + tunnel: Annotated["TunnelTypeV1", strawberry.lazy('vpn.graphql.types_v1')] + termination_type: Annotated["ContentTypeTypeV1", strawberry.lazy('netbox.graphql.types_v1')] | None + outside_ip: Annotated["IPAddressTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None + + +@strawberry_django.type( + models.Tunnel, + fields='__all__', + filters=TunnelFilterV1, + pagination=True +) +class TunnelTypeV1(ContactsMixinV1, NetBoxObjectTypeV1): + group: Annotated["TunnelGroupTypeV1", strawberry.lazy('vpn.graphql.types_v1')] | None + ipsec_profile: Annotated["IPSecProfileTypeV1", strawberry.lazy('vpn.graphql.types_v1')] | None + tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None + + terminations: List[Annotated["TunnelTerminationTypeV1", strawberry.lazy('vpn.graphql.types_v1')]] + + +@strawberry_django.type( + models.IKEProposal, + fields='__all__', + filters=IKEProposalFilterV1, + pagination=True +) +class IKEProposalTypeV1(OrganizationalObjectTypeV1): + + ike_policies: List[Annotated["IKEPolicyTypeV1", strawberry.lazy('vpn.graphql.types_v1')]] + + +@strawberry_django.type( + models.IKEPolicy, + fields='__all__', + filters=IKEPolicyFilterV1, + pagination=True +) +class IKEPolicyTypeV1(OrganizationalObjectTypeV1): + + proposals: List[Annotated["IKEProposalTypeV1", strawberry.lazy('vpn.graphql.types_v1')]] + ipsec_profiles: List[Annotated["IPSecProfileTypeV1", strawberry.lazy('vpn.graphql.types_v1')]] + + +@strawberry_django.type( + models.IPSecProposal, + fields='__all__', + filters=IPSecProposalFilterV1, + pagination=True +) +class IPSecProposalTypeV1(OrganizationalObjectTypeV1): + + ipsec_policies: List[Annotated["IPSecPolicyTypeV1", strawberry.lazy('vpn.graphql.types_v1')]] + + +@strawberry_django.type( + models.IPSecPolicy, + fields='__all__', + filters=IPSecPolicyFilterV1, + pagination=True +) +class IPSecPolicyTypeV1(OrganizationalObjectTypeV1): + + proposals: List[Annotated["IPSecProposalTypeV1", strawberry.lazy('vpn.graphql.types_v1')]] + ipsec_profiles: List[Annotated["IPSecProfileTypeV1", strawberry.lazy('vpn.graphql.types_v1')]] + + +@strawberry_django.type( + models.IPSecProfile, + fields='__all__', + filters=IPSecProfileFilterV1, + pagination=True +) +class IPSecProfileTypeV1(OrganizationalObjectTypeV1): + ike_policy: Annotated["IKEPolicyTypeV1", strawberry.lazy('vpn.graphql.types_v1')] + ipsec_policy: Annotated["IPSecPolicyTypeV1", strawberry.lazy('vpn.graphql.types_v1')] + + tunnels: List[Annotated["TunnelTypeV1", strawberry.lazy('vpn.graphql.types_v1')]] + + +@strawberry_django.type( + models.L2VPN, + fields='__all__', + filters=L2VPNFilterV1, + pagination=True +) +class L2VPNTypeV1(ContactsMixinV1, NetBoxObjectTypeV1): + tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None + + export_targets: List[Annotated["RouteTargetTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] + terminations: List[Annotated["L2VPNTerminationTypeV1", strawberry.lazy('vpn.graphql.types_v1')]] + import_targets: List[Annotated["RouteTargetTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] + + +@strawberry_django.type( + models.L2VPNTermination, + exclude=['assigned_object_type', 'assigned_object_id'], + filters=L2VPNTerminationFilterV1, + pagination=True +) +class L2VPNTerminationTypeV1(NetBoxObjectTypeV1): + l2vpn: Annotated["L2VPNTypeV1", strawberry.lazy('vpn.graphql.types_v1')] + + @strawberry_django.field + def assigned_object(self) -> Annotated[Union[ + Annotated["InterfaceTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["VLANTypeV1", strawberry.lazy('ipam.graphql.types_v1')], + Annotated["VMInterfaceTypeV1", strawberry.lazy('virtualization.graphql.types_v1')], + ], strawberry.union("L2VPNAssignmentTypeV1")]: + return self.assigned_object diff --git a/netbox/wireless/graphql/filter_mixins_v1.py b/netbox/wireless/graphql/filter_mixins_v1.py new file mode 100644 index 0000000000..2e32f2cde2 --- /dev/null +++ b/netbox/wireless/graphql/filter_mixins_v1.py @@ -0,0 +1,26 @@ +from dataclasses import dataclass +from typing import Annotated, TYPE_CHECKING + +import strawberry +import strawberry_django +from strawberry_django import FilterLookup + +from core.graphql.filter_mixins_v1 import BaseFilterMixinV1 + +if TYPE_CHECKING: + from .enums import * + +__all__ = ( + 'WirelessAuthenticationBaseFilterMixinV1', +) + + +@dataclass +class WirelessAuthenticationBaseFilterMixinV1(BaseFilterMixinV1): + auth_type: Annotated['WirelessAuthTypeEnum', strawberry.lazy('wireless.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + auth_cipher: Annotated['WirelessAuthCipherEnum', strawberry.lazy('wireless.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + auth_psk: FilterLookup[str] | None = strawberry_django.filter_field() diff --git a/netbox/wireless/graphql/filters_v1.py b/netbox/wireless/graphql/filters_v1.py new file mode 100644 index 0000000000..166679843d --- /dev/null +++ b/netbox/wireless/graphql/filters_v1.py @@ -0,0 +1,72 @@ +from typing import Annotated, TYPE_CHECKING + +import strawberry +import strawberry_django +from strawberry.scalars import ID +from strawberry_django import FilterLookup + +from dcim.graphql.filter_mixins_v1 import ScopedFilterMixinV1 +from netbox.graphql.filter_mixins_v1 import ( + DistanceFilterMixinV1, PrimaryModelFilterMixinV1, NestedGroupModelFilterMixinV1 +) +from tenancy.graphql.filter_mixins_v1 import TenancyFilterMixinV1 +from wireless import models +from .filter_mixins_v1 import WirelessAuthenticationBaseFilterMixinV1 + +if TYPE_CHECKING: + from dcim.graphql.filters_v1 import InterfaceFilterV1 + from ipam.graphql.filters_v1 import VLANFilterV1 + from .enums import * + +__all__ = ( + 'WirelessLANGroupFilterV1', + 'WirelessLANFilterV1', + 'WirelessLinkFilterV1', +) + + +@strawberry_django.filter_type(models.WirelessLANGroup, lookups=True) +class WirelessLANGroupFilterV1(NestedGroupModelFilterMixinV1): + pass + + +@strawberry_django.filter_type(models.WirelessLAN, lookups=True) +class WirelessLANFilterV1( + WirelessAuthenticationBaseFilterMixinV1, + ScopedFilterMixinV1, + TenancyFilterMixinV1, + PrimaryModelFilterMixinV1 +): + ssid: FilterLookup[str] | None = strawberry_django.filter_field() + status: Annotated['WirelessLANStatusEnum', strawberry.lazy('wireless.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) + group: Annotated['WirelessLANGroupFilterV1', strawberry.lazy('wireless.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + group_id: ID | None = strawberry_django.filter_field() + vlan: Annotated['VLANFilterV1', strawberry.lazy('ipam.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + vlan_id: ID | None = strawberry_django.filter_field() + + +@strawberry_django.filter_type(models.WirelessLink, lookups=True) +class WirelessLinkFilterV1( + WirelessAuthenticationBaseFilterMixinV1, + DistanceFilterMixinV1, + TenancyFilterMixinV1, + PrimaryModelFilterMixinV1 +): + interface_a: Annotated['InterfaceFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + interface_a_id: ID | None = strawberry_django.filter_field() + interface_b: Annotated['InterfaceFilterV1', strawberry.lazy('dcim.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + interface_b_id: ID | None = strawberry_django.filter_field() + ssid: FilterLookup[str] | None = strawberry_django.filter_field() + status: Annotated['WirelessLANStatusEnum', strawberry.lazy('wireless.graphql.enums')] | None = ( + strawberry_django.filter_field() + ) diff --git a/netbox/wireless/graphql/schema_v1.py b/netbox/wireless/graphql/schema_v1.py new file mode 100644 index 0000000000..fafe28c082 --- /dev/null +++ b/netbox/wireless/graphql/schema_v1.py @@ -0,0 +1,18 @@ +from typing import List + +import strawberry +import strawberry_django + +from .types_v1 import * + + +@strawberry.type(name="Query") +class WirelessQueryV1: + wireless_lan: WirelessLANTypeV1 = strawberry_django.field() + wireless_lan_list: List[WirelessLANTypeV1] = strawberry_django.field() + + wireless_lan_group: WirelessLANGroupTypeV1 = strawberry_django.field() + wireless_lan_group_list: List[WirelessLANGroupTypeV1] = strawberry_django.field() + + wireless_link: WirelessLinkTypeV1 = strawberry_django.field() + wireless_link_list: List[WirelessLinkTypeV1] = strawberry_django.field() diff --git a/netbox/wireless/graphql/types_v1.py b/netbox/wireless/graphql/types_v1.py new file mode 100644 index 0000000000..b774f8f28c --- /dev/null +++ b/netbox/wireless/graphql/types_v1.py @@ -0,0 +1,71 @@ +from typing import Annotated, List, TYPE_CHECKING, Union + +import strawberry +import strawberry_django + +from netbox.graphql.types_v1 import OrganizationalObjectTypeV1, NetBoxObjectTypeV1 +from wireless import models +from .filters_v1 import * + +if TYPE_CHECKING: + from dcim.graphql.types_v1 import ( + DeviceTypeV1, InterfaceTypeV1, LocationTypeV1, RegionTypeV1, SiteGroupTypeV1, SiteTypeV1 + ) + from ipam.graphql.types_v1 import VLANTypeV1 + from tenancy.graphql.types_v1 import TenantTypeV1 + +__all__ = ( + 'WirelessLANTypeV1', + 'WirelessLANGroupTypeV1', + 'WirelessLinkTypeV1', +) + + +@strawberry_django.type( + models.WirelessLANGroup, + fields='__all__', + filters=WirelessLANGroupFilterV1, + pagination=True +) +class WirelessLANGroupTypeV1(OrganizationalObjectTypeV1): + parent: Annotated["WirelessLANGroupTypeV1", strawberry.lazy('wireless.graphql.types_v1')] | None + + wireless_lans: List[Annotated["WirelessLANTypeV1", strawberry.lazy('wireless.graphql.types_v1')]] + children: List[Annotated["WirelessLANGroupTypeV1", strawberry.lazy('wireless.graphql.types_v1')]] + + +@strawberry_django.type( + models.WirelessLAN, + exclude=['scope_type', 'scope_id', '_location', '_region', '_site', '_site_group'], + filters=WirelessLANFilterV1, + pagination=True +) +class WirelessLANTypeV1(NetBoxObjectTypeV1): + group: Annotated["WirelessLANGroupTypeV1", strawberry.lazy('wireless.graphql.types_v1')] | None + vlan: Annotated["VLANTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None + tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None + + interfaces: List[Annotated["InterfaceTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] + + @strawberry_django.field + def scope(self) -> Annotated[Union[ + Annotated["LocationTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["RegionTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["SiteGroupTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + Annotated["SiteTypeV1", strawberry.lazy('dcim.graphql.types_v1')], + ], strawberry.union("WirelessLANScopeTypeV1")] | None: + return self.scope + + +@strawberry_django.type( + models.WirelessLink, + fields='__all__', + filters=WirelessLinkFilterV1, + pagination=True +) +class WirelessLinkTypeV1(NetBoxObjectTypeV1): + interface_a: Annotated["InterfaceTypeV1", strawberry.lazy('dcim.graphql.types_v1')] + interface_b: Annotated["InterfaceTypeV1", strawberry.lazy('dcim.graphql.types_v1')] + tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None + _interface_a_device: Annotated["DeviceTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + _interface_b_device: Annotated["DeviceTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None From a4084884d3a20aa983fb7e606460c76c4055ebd0 Mon Sep 17 00:00:00 2001 From: Brian Tiemann Date: Fri, 24 Oct 2025 14:33:34 -0400 Subject: [PATCH 2/8] Convert all id fields and enum fields to FilterLookups (with in_list and exact support) --- netbox/circuits/graphql/filters.py | 14 ++- netbox/core/graphql/filter_mixins.py | 6 +- netbox/dcim/graphql/filters.py | 152 ++++++++++++++--------- netbox/extras/graphql/filters.py | 30 +++-- netbox/ipam/graphql/filters.py | 20 +-- netbox/tenancy/graphql/filters.py | 2 +- netbox/virtualization/graphql/filters.py | 6 +- netbox/vpn/graphql/filters.py | 54 +++++--- netbox/wireless/graphql/filters.py | 4 +- 9 files changed, 183 insertions(+), 105 deletions(-) diff --git a/netbox/circuits/graphql/filters.py b/netbox/circuits/graphql/filters.py index d6ef2976d1..545e76cb8f 100644 --- a/netbox/circuits/graphql/filters.py +++ b/netbox/circuits/graphql/filters.py @@ -52,7 +52,9 @@ class CircuitTerminationFilter( circuit: Annotated['CircuitFilter', strawberry.lazy('circuits.graphql.filters')] | None = ( strawberry_django.filter_field() ) - term_side: Annotated['CircuitTerminationSideEnum', strawberry.lazy('circuits.graphql.enums')] | None = ( + term_side: ( + FilterLookup[Annotated['CircuitTerminationSideEnum', strawberry.lazy('circuits.graphql.enums')]] | None + ) = ( strawberry_django.filter_field() ) termination_type: Annotated['ContentTypeFilter', strawberry.lazy('core.graphql.filters')] | None = ( @@ -108,7 +110,7 @@ class CircuitFilter( strawberry_django.filter_field() ) type_id: ID | None = strawberry_django.filter_field() - status: Annotated['CircuitStatusEnum', strawberry.lazy('circuits.graphql.enums')] | None = ( + status: FilterLookup[Annotated['CircuitStatusEnum', strawberry.lazy('circuits.graphql.enums')]] | None = ( strawberry_django.filter_field() ) install_date: DateFilterLookup[date] | None = strawberry_django.filter_field() @@ -143,7 +145,7 @@ class CircuitGroupAssignmentFilter( strawberry_django.filter_field() ) group_id: ID | None = strawberry_django.filter_field() - priority: Annotated['CircuitPriorityEnum', strawberry.lazy('circuits.graphql.enums')] | None = ( + priority: FilterLookup[Annotated['CircuitPriorityEnum', strawberry.lazy('circuits.graphql.enums')]] | None = ( strawberry_django.filter_field() ) @@ -198,7 +200,7 @@ class VirtualCircuitFilter(TenancyFilterMixin, PrimaryModelFilterMixin): strawberry_django.filter_field() ) type_id: ID | None = strawberry_django.filter_field() - status: Annotated['CircuitStatusEnum', strawberry.lazy('circuits.graphql.enums')] | None = ( + status: FilterLookup[Annotated['CircuitStatusEnum', strawberry.lazy('circuits.graphql.enums')]] | None = ( strawberry_django.filter_field() ) group_assignments: Annotated['CircuitGroupAssignmentFilter', strawberry.lazy('circuits.graphql.filters')] | None = ( @@ -214,7 +216,9 @@ class VirtualCircuitTerminationFilter( strawberry_django.filter_field() ) virtual_circuit_id: ID | None = strawberry_django.filter_field() - role: Annotated['VirtualCircuitTerminationRoleEnum', strawberry.lazy('circuits.graphql.enums')] | None = ( + role: ( + FilterLookup[Annotated['VirtualCircuitTerminationRoleEnum', strawberry.lazy('circuits.graphql.enums')]] | None + ) = ( strawberry_django.filter_field() ) interface: Annotated['InterfaceFilter', strawberry.lazy('dcim.graphql.filters')] | None = ( diff --git a/netbox/core/graphql/filter_mixins.py b/netbox/core/graphql/filter_mixins.py index 670ec2ebb3..27d950d73a 100644 --- a/netbox/core/graphql/filter_mixins.py +++ b/netbox/core/graphql/filter_mixins.py @@ -5,7 +5,7 @@ import strawberry import strawberry_django from strawberry import ID -from strawberry_django import DatetimeFilterLookup +from strawberry_django import FilterLookup, DatetimeFilterLookup if TYPE_CHECKING: from .filters import * @@ -23,12 +23,12 @@ class BaseFilterMixin: ... @dataclass class BaseObjectTypeFilterMixin(BaseFilterMixin): - id: ID | None = strawberry.UNSET + id: FilterLookup[ID] | None = strawberry_django.filter_field() @dataclass class ChangeLogFilterMixin(BaseFilterMixin): - id: ID | None = strawberry.UNSET + id: FilterLookup[ID] | None = strawberry_django.filter_field() changelog: Annotated['ObjectChangeFilter', strawberry.lazy('core.graphql.filters')] | None = ( strawberry_django.filter_field() ) diff --git a/netbox/dcim/graphql/filters.py b/netbox/dcim/graphql/filters.py index af2922e136..c2f4d9749f 100644 --- a/netbox/dcim/graphql/filters.py +++ b/netbox/dcim/graphql/filters.py @@ -95,14 +95,20 @@ @strawberry_django.filter_type(models.Cable, lookups=True) class CableFilter(PrimaryModelFilterMixin, TenancyFilterMixin): - type: Annotated['CableTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = strawberry_django.filter_field() - status: Annotated['LinkStatusEnum', strawberry.lazy('dcim.graphql.enums')] | None = strawberry_django.filter_field() + type: FilterLookup[Annotated['CableTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + strawberry_django.filter_field() + ) + status: FilterLookup[Annotated['LinkStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + strawberry_django.filter_field() + ) label: FilterLookup[str] | None = strawberry_django.filter_field() - color: Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')] | None = strawberry_django.filter_field() + color: FilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = ( + strawberry_django.filter_field() + ) length: Annotated['FloatLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) - length_unit: Annotated['CableLengthUnitEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + length_unit: FilterLookup[Annotated['CableLengthUnitEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) terminations: Annotated['CableTerminationFilter', strawberry.lazy('dcim.graphql.filters')] | None = ( @@ -114,7 +120,7 @@ class CableFilter(PrimaryModelFilterMixin, TenancyFilterMixin): class CableTerminationFilter(ChangeLogFilterMixin): cable: Annotated['CableFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field() cable_id: ID | None = strawberry_django.filter_field() - cable_end: Annotated['CableEndEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + cable_end: FilterLookup[Annotated['CableEndEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) termination_type: Annotated['CableTerminationFilter', strawberry.lazy('dcim.graphql.filters')] | None = ( @@ -125,34 +131,34 @@ class CableTerminationFilter(ChangeLogFilterMixin): @strawberry_django.filter_type(models.ConsolePort, lookups=True) class ConsolePortFilter(ModularComponentModelFilterMixin, CabledObjectModelFilterMixin): - type: Annotated['ConsolePortTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + type: FilterLookup[Annotated['ConsolePortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - speed: Annotated['ConsolePortSpeedEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + speed: FilterLookup[Annotated['ConsolePortSpeedEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) @strawberry_django.filter_type(models.ConsolePortTemplate, lookups=True) class ConsolePortTemplateFilter(ModularComponentTemplateFilterMixin): - type: Annotated['ConsolePortTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + type: FilterLookup[Annotated['ConsolePortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) @strawberry_django.filter_type(models.ConsoleServerPort, lookups=True) class ConsoleServerPortFilter(ModularComponentModelFilterMixin, CabledObjectModelFilterMixin): - type: Annotated['ConsolePortTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + type: FilterLookup[Annotated['ConsolePortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - speed: Annotated['ConsolePortSpeedEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + speed: FilterLookup[Annotated['ConsolePortSpeedEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) @strawberry_django.filter_type(models.ConsoleServerPortTemplate, lookups=True) class ConsoleServerPortTemplateFilter(ModularComponentTemplateFilterMixin): - type: Annotated['ConsolePortTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + type: FilterLookup[Annotated['ConsolePortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) @@ -193,11 +199,13 @@ class DeviceFilter( position: Annotated['FloatLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) - face: Annotated['DeviceFaceEnum', strawberry.lazy('dcim.graphql.enums')] | None = strawberry_django.filter_field() - status: Annotated['DeviceStatusEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + face: FilterLookup[Annotated['DeviceFaceEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + strawberry_django.filter_field() + ) + status: FilterLookup[Annotated['DeviceStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - airflow: Annotated['DeviceAirflowEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + airflow: FilterLookup[Annotated['DeviceAirflowEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) primary_ip4: Annotated['IPAddressFilter', strawberry.lazy('ipam.graphql.filters')] | None = ( @@ -309,7 +317,9 @@ class InventoryItemTemplateFilter(ComponentTemplateFilterMixin): @strawberry_django.filter_type(models.DeviceRole, lookups=True) class DeviceRoleFilter(OrganizationalModelFilterMixin, RenderConfigFilterMixin): - color: Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')] | None = strawberry_django.filter_field() + color: FilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = ( + strawberry_django.filter_field() + ) vm_role: FilterLookup[bool] | None = strawberry_django.filter_field() @@ -331,10 +341,10 @@ class DeviceTypeFilter(ImageAttachmentFilterMixin, PrimaryModelFilterMixin, Weig ) exclude_from_utilization: FilterLookup[bool] | None = strawberry_django.filter_field() is_full_depth: FilterLookup[bool] | None = strawberry_django.filter_field() - subdevice_role: Annotated['SubdeviceRoleEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + subdevice_role: FilterLookup[Annotated['SubdeviceRoleEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - airflow: Annotated['DeviceAirflowEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + airflow: FilterLookup[Annotated['DeviceAirflowEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) front_image: Annotated['ImageAttachmentFilter', strawberry.lazy('extras.graphql.filters')] | None = ( @@ -387,8 +397,12 @@ class DeviceTypeFilter(ImageAttachmentFilterMixin, PrimaryModelFilterMixin, Weig @strawberry_django.filter_type(models.FrontPort, lookups=True) class FrontPortFilter(ModularComponentModelFilterMixin, CabledObjectModelFilterMixin): - type: Annotated['PortTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = strawberry_django.filter_field() - color: Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')] | None = strawberry_django.filter_field() + type: FilterLookup[Annotated['PortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + strawberry_django.filter_field() + ) + color: FilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = ( + strawberry_django.filter_field() + ) rear_port: Annotated['RearPortFilter', strawberry.lazy('dcim.graphql.filters')] | None = ( strawberry_django.filter_field() ) @@ -400,8 +414,12 @@ class FrontPortFilter(ModularComponentModelFilterMixin, CabledObjectModelFilterM @strawberry_django.filter_type(models.FrontPortTemplate, lookups=True) class FrontPortTemplateFilter(ModularComponentTemplateFilterMixin): - type: Annotated['PortTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = strawberry_django.filter_field() - color: Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')] | None = strawberry_django.filter_field() + type: FilterLookup[Annotated['PortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + strawberry_django.filter_field() + ) + color: FilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = ( + strawberry_django.filter_field() + ) rear_port: Annotated['RearPortTemplateFilter', strawberry.lazy('dcim.graphql.filters')] | None = ( strawberry_django.filter_field() ) @@ -427,14 +445,14 @@ class InterfaceFilter(ModularComponentModelFilterMixin, InterfaceBaseFilterMixin ) lag: Annotated['InterfaceFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field() lag_id: ID | None = strawberry_django.filter_field() - type: Annotated['InterfaceTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + type: FilterLookup[Annotated['InterfaceTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) mgmt_only: FilterLookup[bool] | None = strawberry_django.filter_field() speed: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) - duplex: Annotated['InterfaceDuplexEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + duplex: FilterLookup[Annotated['InterfaceDuplexEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) wwn: FilterLookup[str] | None = strawberry_django.filter_field() @@ -442,10 +460,10 @@ class InterfaceFilter(ModularComponentModelFilterMixin, InterfaceBaseFilterMixin strawberry_django.filter_field() ) parent_id: ID | None = strawberry_django.filter_field() - rf_role: Annotated['WirelessRoleEnum', strawberry.lazy('wireless.graphql.enums')] | None = ( + rf_role: FilterLookup[Annotated['WirelessRoleEnum', strawberry.lazy('wireless.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - rf_channel: Annotated['WirelessChannelEnum', strawberry.lazy('wireless.graphql.enums')] | None = ( + rf_channel: FilterLookup[Annotated['WirelessChannelEnum', strawberry.lazy('wireless.graphql.enums')]] | None = ( strawberry_django.filter_field() ) rf_channel_frequency: Annotated['FloatLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( @@ -457,10 +475,10 @@ class InterfaceFilter(ModularComponentModelFilterMixin, InterfaceBaseFilterMixin tx_power: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) - poe_mode: Annotated['InterfacePoEModeEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + poe_mode: FilterLookup[Annotated['InterfacePoEModeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - poe_type: Annotated['InterfacePoETypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + poe_type: FilterLookup[Annotated['InterfacePoETypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) wireless_link: Annotated['WirelessLinkFilter', strawberry.lazy('wireless.graphql.filters')] | None = ( @@ -512,7 +530,7 @@ def kind( @strawberry_django.filter_type(models.InterfaceTemplate, lookups=True) class InterfaceTemplateFilter(ModularComponentTemplateFilterMixin): - type: Annotated['InterfaceTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + type: FilterLookup[Annotated['InterfaceTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) enabled: FilterLookup[bool] | None = strawberry_django.filter_field() @@ -521,13 +539,13 @@ class InterfaceTemplateFilter(ModularComponentTemplateFilterMixin): strawberry_django.filter_field() ) bridge_id: ID | None = strawberry_django.filter_field() - poe_mode: Annotated['InterfacePoEModeEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + poe_mode: FilterLookup[Annotated['InterfacePoEModeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - poe_type: Annotated['InterfacePoETypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + poe_type: FilterLookup[Annotated['InterfacePoETypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - rf_role: Annotated['WirelessRoleEnum', strawberry.lazy('wireless.graphql.enums')] | None = ( + rf_role: FilterLookup[Annotated['WirelessRoleEnum', strawberry.lazy('wireless.graphql.enums')]] | None = ( strawberry_django.filter_field() ) @@ -542,7 +560,7 @@ class InventoryItemFilter(ComponentModelFilterMixin): strawberry_django.filter_field() ) component_id: ID | None = strawberry_django.filter_field() - status: Annotated['InventoryItemStatusEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + status: FilterLookup[Annotated['InventoryItemStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) role: Annotated['InventoryItemRoleFilter', strawberry.lazy('dcim.graphql.filters')] | None = ( @@ -561,14 +579,16 @@ class InventoryItemFilter(ComponentModelFilterMixin): @strawberry_django.filter_type(models.InventoryItemRole, lookups=True) class InventoryItemRoleFilter(OrganizationalModelFilterMixin): - color: Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')] | None = strawberry_django.filter_field() + color: FilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = ( + strawberry_django.filter_field() + ) @strawberry_django.filter_type(models.Location, lookups=True) class LocationFilter(ContactFilterMixin, ImageAttachmentFilterMixin, TenancyFilterMixin, NestedGroupModelFilterMixin): site: Annotated['SiteFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field() site_id: ID | None = strawberry_django.filter_field() - status: Annotated['LocationStatusEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + status: FilterLookup[Annotated['LocationStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) facility: FilterLookup[str] | None = strawberry_django.filter_field() @@ -597,7 +617,7 @@ class ModuleFilter(PrimaryModelFilterMixin, ConfigContextFilterMixin): strawberry_django.filter_field() ) module_type_id: ID | None = strawberry_django.filter_field() - status: Annotated['ModuleStatusEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + status: FilterLookup[Annotated['ModuleStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) serial: FilterLookup[str] | None = strawberry_django.filter_field() @@ -665,7 +685,7 @@ class ModuleTypeFilter(ImageAttachmentFilterMixin, PrimaryModelFilterMixin, Weig profile_id: ID | None = strawberry_django.filter_field() model: FilterLookup[str] | None = strawberry_django.filter_field() part_number: FilterLookup[str] | None = strawberry_django.filter_field() - airflow: Annotated['ModuleAirflowEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + airflow: FilterLookup[Annotated['ModuleAirflowEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) console_port_templates: ( @@ -721,16 +741,16 @@ class PowerFeedFilter(CabledObjectModelFilterMixin, TenancyFilterMixin, PrimaryM rack: Annotated['RackFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field() rack_id: ID | None = strawberry_django.filter_field() name: FilterLookup[str] | None = strawberry_django.filter_field() - status: Annotated['PowerFeedStatusEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + status: FilterLookup[Annotated['PowerFeedStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - type: Annotated['PowerFeedTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + type: FilterLookup[Annotated['PowerFeedTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - supply: Annotated['PowerFeedSupplyEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + supply: FilterLookup[Annotated['PowerFeedSupplyEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - phase: Annotated['PowerFeedPhaseEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + phase: FilterLookup[Annotated['PowerFeedPhaseEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) voltage: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( @@ -749,29 +769,31 @@ class PowerFeedFilter(CabledObjectModelFilterMixin, TenancyFilterMixin, PrimaryM @strawberry_django.filter_type(models.PowerOutlet, lookups=True) class PowerOutletFilter(ModularComponentModelFilterMixin, CabledObjectModelFilterMixin): - type: Annotated['PowerOutletTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + type: FilterLookup[Annotated['PowerOutletTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) power_port: Annotated['PowerPortFilter', strawberry.lazy('dcim.graphql.filters')] | None = ( strawberry_django.filter_field() ) power_port_id: ID | None = strawberry_django.filter_field() - feed_leg: Annotated['PowerOutletFeedLegEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + feed_leg: FilterLookup[Annotated['PowerOutletFeedLegEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + strawberry_django.filter_field() + ) + color: FilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - color: Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')] | None = strawberry_django.filter_field() @strawberry_django.filter_type(models.PowerOutletTemplate, lookups=True) class PowerOutletTemplateFilter(ModularComponentModelFilterMixin): - type: Annotated['PowerOutletTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + type: FilterLookup[Annotated['PowerOutletTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) power_port: Annotated['PowerPortTemplateFilter', strawberry.lazy('dcim.graphql.filters')] | None = ( strawberry_django.filter_field() ) power_port_id: ID | None = strawberry_django.filter_field() - feed_leg: Annotated['PowerOutletFeedLegEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + feed_leg: FilterLookup[Annotated['PowerOutletFeedLegEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) @@ -791,7 +813,7 @@ class PowerPanelFilter(ContactFilterMixin, ImageAttachmentFilterMixin, PrimaryMo @strawberry_django.filter_type(models.PowerPort, lookups=True) class PowerPortFilter(ModularComponentModelFilterMixin, CabledObjectModelFilterMixin): - type: Annotated['PowerPortTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + type: FilterLookup[Annotated['PowerPortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) maximum_draw: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( @@ -804,7 +826,7 @@ class PowerPortFilter(ModularComponentModelFilterMixin, CabledObjectModelFilterM @strawberry_django.filter_type(models.PowerPortTemplate, lookups=True) class PowerPortTemplateFilter(ModularComponentTemplateFilterMixin): - type: Annotated['PowerPortTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + type: FilterLookup[Annotated['PowerPortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) maximum_draw: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( @@ -817,7 +839,7 @@ class PowerPortTemplateFilter(ModularComponentTemplateFilterMixin): @strawberry_django.filter_type(models.RackType, lookups=True) class RackTypeFilter(RackBaseFilterMixin): - form_factor: Annotated['RackFormFactorEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + form_factor: FilterLookup[Annotated['RackFormFactorEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) manufacturer: Annotated['ManufacturerFilter', strawberry.lazy('dcim.graphql.filters')] | None = ( @@ -830,7 +852,7 @@ class RackTypeFilter(RackBaseFilterMixin): @strawberry_django.filter_type(models.Rack, lookups=True) class RackFilter(ContactFilterMixin, ImageAttachmentFilterMixin, TenancyFilterMixin, RackBaseFilterMixin): - form_factor: Annotated['RackFormFactorEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + form_factor: FilterLookup[Annotated['RackFormFactorEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) rack_type: Annotated['RackTypeFilter', strawberry.lazy('dcim.graphql.filters')] | None = ( @@ -847,12 +869,14 @@ class RackFilter(ContactFilterMixin, ImageAttachmentFilterMixin, TenancyFilterMi location_id: Annotated['TreeNodeFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) - status: Annotated['RackStatusEnum', strawberry.lazy('dcim.graphql.enums')] | None = strawberry_django.filter_field() + status: FilterLookup[Annotated['RackStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + strawberry_django.filter_field() + ) role: Annotated['RackRoleFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field() role_id: ID | None = strawberry_django.filter_field() serial: FilterLookup[str] | None = strawberry_django.filter_field() asset_tag: FilterLookup[str] | None = strawberry_django.filter_field() - airflow: Annotated['RackAirflowEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + airflow: FilterLookup[Annotated['RackAirflowEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) vlan_groups: Annotated['VLANGroupFilter', strawberry.lazy('ipam.graphql.filters')] | None = ( @@ -874,13 +898,19 @@ class RackReservationFilter(TenancyFilterMixin, PrimaryModelFilterMixin): @strawberry_django.filter_type(models.RackRole, lookups=True) class RackRoleFilter(OrganizationalModelFilterMixin): - color: Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')] | None = strawberry_django.filter_field() + color: FilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = ( + strawberry_django.filter_field() + ) @strawberry_django.filter_type(models.RearPort, lookups=True) class RearPortFilter(ModularComponentModelFilterMixin, CabledObjectModelFilterMixin): - type: Annotated['PortTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = strawberry_django.filter_field() - color: Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')] | None = strawberry_django.filter_field() + type: FilterLookup[Annotated['PortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + strawberry_django.filter_field() + ) + color: FilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = ( + strawberry_django.filter_field() + ) positions: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) @@ -888,8 +918,12 @@ class RearPortFilter(ModularComponentModelFilterMixin, CabledObjectModelFilterMi @strawberry_django.filter_type(models.RearPortTemplate, lookups=True) class RearPortTemplateFilter(ModularComponentTemplateFilterMixin): - type: Annotated['PortTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = strawberry_django.filter_field() - color: Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')] | None = strawberry_django.filter_field() + type: FilterLookup[Annotated['PortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + strawberry_django.filter_field() + ) + color: FilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = ( + strawberry_django.filter_field() + ) positions: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) @@ -909,7 +943,9 @@ class RegionFilter(ContactFilterMixin, NestedGroupModelFilterMixin): class SiteFilter(ContactFilterMixin, ImageAttachmentFilterMixin, TenancyFilterMixin, PrimaryModelFilterMixin): name: FilterLookup[str] | None = strawberry_django.filter_field() slug: FilterLookup[str] | None = strawberry_django.filter_field() - status: Annotated['SiteStatusEnum', strawberry.lazy('dcim.graphql.enums')] | None = strawberry_django.filter_field() + status: FilterLookup[Annotated['SiteStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + strawberry_django.filter_field() + ) region: Annotated['RegionFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field() region_id: Annotated['TreeNodeFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() @@ -966,7 +1002,7 @@ class VirtualDeviceContextFilter(TenancyFilterMixin, PrimaryModelFilterMixin): device: Annotated['DeviceFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field() device_id: ID | None = strawberry_django.filter_field() name: FilterLookup[str] | None = strawberry_django.filter_field() - status: Annotated['VirtualDeviceContextStatusEnum', strawberry.lazy('dcim.graphql.enums')] | None = ( + status: FilterLookup[Annotated['VirtualDeviceContextStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) identifier: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( diff --git a/netbox/extras/graphql/filters.py b/netbox/extras/graphql/filters.py index 13221982c9..75aaac955a 100644 --- a/netbox/extras/graphql/filters.py +++ b/netbox/extras/graphql/filters.py @@ -121,7 +121,7 @@ class ConfigTemplateFilter(BaseObjectTypeFilterMixin, SyncedDataFilterMixin, Cha @strawberry_django.filter_type(models.CustomField, lookups=True) class CustomFieldFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin): - type: Annotated['CustomFieldTypeEnum', strawberry.lazy('extras.graphql.enums')] | None = ( + type: FilterLookup[Annotated['CustomFieldTypeEnum', strawberry.lazy('extras.graphql.enums')]] | None = ( strawberry_django.filter_field() ) object_types: Annotated['ContentTypeFilter', strawberry.lazy('core.graphql.filters')] | None = ( @@ -139,7 +139,9 @@ class CustomFieldFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin): search_weight: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) - filter_logic: Annotated['CustomFieldFilterLogicEnum', strawberry.lazy('extras.graphql.enums')] | None = ( + filter_logic: ( + FilterLookup[Annotated['CustomFieldFilterLogicEnum', strawberry.lazy('extras.graphql.enums')]] | None + ) = ( strawberry_django.filter_field() ) default: Annotated['JSONFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( @@ -162,10 +164,12 @@ class CustomFieldFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin): strawberry_django.filter_field() ) choice_set_id: ID | None = strawberry_django.filter_field() - ui_visible: Annotated['CustomFieldUIVisibleEnum', strawberry.lazy('extras.graphql.enums')] | None = ( + ui_visible: FilterLookup[Annotated['CustomFieldUIVisibleEnum', strawberry.lazy('extras.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - ui_editable: Annotated['CustomFieldUIEditableEnum', strawberry.lazy('extras.graphql.enums')] | None = ( + ui_editable: ( + FilterLookup[Annotated['CustomFieldUIEditableEnum', strawberry.lazy('extras.graphql.enums')]] | None + ) = ( strawberry_django.filter_field() ) is_cloneable: FilterLookup[bool] | None = strawberry_django.filter_field() @@ -176,7 +180,9 @@ class CustomFieldFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin): class CustomFieldChoiceSetFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin): name: FilterLookup[str] | None = strawberry_django.filter_field() description: FilterLookup[str] | None = strawberry_django.filter_field() - base_choices: Annotated['CustomFieldChoiceSetBaseEnum', strawberry.lazy('extras.graphql.enums')] | None = ( + base_choices: ( + FilterLookup[Annotated['CustomFieldChoiceSetBaseEnum', strawberry.lazy('extras.graphql.enums')]] | None + ) = ( strawberry_django.filter_field() ) extra_choices: Annotated['StringArrayLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( @@ -195,7 +201,9 @@ class CustomLinkFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin): strawberry_django.filter_field() ) group_name: FilterLookup[str] | None = strawberry_django.filter_field() - button_class: Annotated['CustomLinkButtonClassEnum', strawberry.lazy('extras.graphql.enums')] | None = ( + button_class: ( + FilterLookup[Annotated['CustomLinkButtonClassEnum', strawberry.lazy('extras.graphql.enums')]] | None + ) = ( strawberry_django.filter_field() ) new_window: FilterLookup[bool] | None = strawberry_django.filter_field() @@ -240,7 +248,7 @@ class JournalEntryFilter(BaseObjectTypeFilterMixin, CustomFieldsFilterMixin, Tag created_by: Annotated['UserFilter', strawberry.lazy('users.graphql.filters')] | None = ( strawberry_django.filter_field() ) - kind: Annotated['JournalEntryKindEnum', strawberry.lazy('extras.graphql.enums')] | None = ( + kind: FilterLookup[Annotated['JournalEntryKindEnum', strawberry.lazy('extras.graphql.enums')]] | None = ( strawberry_django.filter_field() ) comments: FilterLookup[str] | None = strawberry_django.filter_field() @@ -286,7 +294,9 @@ class TableConfigFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin): @strawberry_django.filter_type(models.Tag, lookups=True) class TagFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin, TagBaseFilterMixin): - color: Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')] | None = strawberry_django.filter_field() + color: FilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = ( + strawberry_django.filter_field() + ) description: FilterLookup[str] | None = strawberry_django.filter_field() @@ -295,7 +305,7 @@ class WebhookFilter(BaseObjectTypeFilterMixin, CustomFieldsFilterMixin, TagsFilt name: FilterLookup[str] | None = strawberry_django.filter_field() description: FilterLookup[str] | None = strawberry_django.filter_field() payload_url: FilterLookup[str] | None = strawberry_django.filter_field() - http_method: Annotated['WebhookHttpMethodEnum', strawberry.lazy('extras.graphql.enums')] | None = ( + http_method: FilterLookup[Annotated['WebhookHttpMethodEnum', strawberry.lazy('extras.graphql.enums')]] | None = ( strawberry_django.filter_field() ) http_content_type: FilterLookup[str] | None = strawberry_django.filter_field() @@ -320,7 +330,7 @@ class EventRuleFilter(BaseObjectTypeFilterMixin, CustomFieldsFilterMixin, TagsFi conditions: Annotated['JSONFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) - action_type: Annotated['EventRuleActionEnum', strawberry.lazy('extras.graphql.enums')] | None = ( + action_type: FilterLookup[Annotated['EventRuleActionEnum', strawberry.lazy('extras.graphql.enums')]] | None = ( strawberry_django.filter_field() ) action_object_type: FilterLookup[str] | None = strawberry_django.filter_field() diff --git a/netbox/ipam/graphql/filters.py b/netbox/ipam/graphql/filters.py index 4b2431aa2d..30ab8612e0 100644 --- a/netbox/ipam/graphql/filters.py +++ b/netbox/ipam/graphql/filters.py @@ -92,10 +92,10 @@ class FHRPGroupFilter(PrimaryModelFilterMixin): strawberry_django.filter_field() ) name: FilterLookup[str] | None = strawberry_django.filter_field() - protocol: Annotated['FHRPGroupProtocolEnum', strawberry.lazy('ipam.graphql.enums')] | None = ( + protocol: FilterLookup[Annotated['FHRPGroupProtocolEnum', strawberry.lazy('ipam.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - auth_type: Annotated['FHRPGroupAuthTypeEnum', strawberry.lazy('ipam.graphql.enums')] | None = ( + auth_type: FilterLookup[Annotated['FHRPGroupAuthTypeEnum', strawberry.lazy('ipam.graphql.enums')]] | None = ( strawberry_django.filter_field() ) auth_key: FilterLookup[str] | None = strawberry_django.filter_field() @@ -148,10 +148,10 @@ class IPAddressFilter(ContactFilterMixin, TenancyFilterMixin, PrimaryModelFilter address: FilterLookup[str] | 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() - status: Annotated['IPAddressStatusEnum', strawberry.lazy('ipam.graphql.enums')] | None = ( + status: FilterLookup[Annotated['IPAddressStatusEnum', strawberry.lazy('ipam.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - role: Annotated['IPAddressRoleEnum', strawberry.lazy('ipam.graphql.enums')] | None = ( + role: FilterLookup[Annotated['IPAddressRoleEnum', strawberry.lazy('ipam.graphql.enums')]] | None = ( strawberry_django.filter_field() ) assigned_object_type: Annotated['ContentTypeFilter', strawberry.lazy('core.graphql.filters')] | None = ( @@ -188,7 +188,7 @@ def parent(self, value: list[str], prefix) -> Q: @strawberry_django.filter_field() def family( self, - value: Annotated['IPAddressFamilyEnum', strawberry.lazy('ipam.graphql.enums')], + value: FilterLookup[Annotated['IPAddressFamilyEnum', strawberry.lazy('ipam.graphql.enums')]], prefix, ) -> Q: return Q(**{f"{prefix}address__family": value.value}) @@ -203,7 +203,7 @@ class IPRangeFilter(ContactFilterMixin, TenancyFilterMixin, PrimaryModelFilterMi ) vrf: Annotated['VRFFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field() vrf_id: ID | None = strawberry_django.filter_field() - status: Annotated['IPRangeStatusEnum', strawberry.lazy('ipam.graphql.enums')] | None = ( + status: FilterLookup[Annotated['IPRangeStatusEnum', strawberry.lazy('ipam.graphql.enums')]] | None = ( strawberry_django.filter_field() ) role: Annotated['RoleFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field() @@ -243,7 +243,7 @@ class PrefixFilter(ContactFilterMixin, ScopedFilterMixin, TenancyFilterMixin, Pr vrf_id: ID | None = strawberry_django.filter_field() vlan: Annotated['VLANFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field() vlan_id: ID | None = strawberry_django.filter_field() - status: Annotated['PrefixStatusEnum', strawberry.lazy('ipam.graphql.enums')] | None = ( + status: FilterLookup[Annotated['PrefixStatusEnum', strawberry.lazy('ipam.graphql.enums')]] | None = ( strawberry_django.filter_field() ) role: Annotated['RoleFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field() @@ -320,7 +320,9 @@ class VLANFilter(TenancyFilterMixin, PrimaryModelFilterMixin): strawberry_django.filter_field() ) name: FilterLookup[str] | None = strawberry_django.filter_field() - status: Annotated['VLANStatusEnum', strawberry.lazy('ipam.graphql.enums')] | None = strawberry_django.filter_field() + status: FilterLookup[Annotated['VLANStatusEnum', strawberry.lazy('ipam.graphql.enums')]] | None = ( + strawberry_django.filter_field() + ) role: Annotated['RoleFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field() role_id: ID | None = strawberry_django.filter_field() qinq_svlan: Annotated['VLANFilter', strawberry.lazy('ipam.graphql.filters')] | None = ( @@ -330,7 +332,7 @@ class VLANFilter(TenancyFilterMixin, PrimaryModelFilterMixin): qinq_cvlans: Annotated['VLANFilter', strawberry.lazy('ipam.graphql.filters')] | None = ( strawberry_django.filter_field() ) - qinq_role: Annotated['VLANQinQRoleEnum', strawberry.lazy('ipam.graphql.enums')] | None = ( + qinq_role: FilterLookup[Annotated['VLANQinQRoleEnum', strawberry.lazy('ipam.graphql.enums')]] | None = ( strawberry_django.filter_field() ) l2vpn_terminations: Annotated['L2VPNFilter', strawberry.lazy('vpn.graphql.filters')] | None = ( diff --git a/netbox/tenancy/graphql/filters.py b/netbox/tenancy/graphql/filters.py index fb37359ef6..08682c4428 100644 --- a/netbox/tenancy/graphql/filters.py +++ b/netbox/tenancy/graphql/filters.py @@ -191,6 +191,6 @@ class ContactAssignmentFilter(CustomFieldsFilterMixin, TagsFilterMixin, ChangeLo strawberry_django.filter_field() ) role_id: ID | None = strawberry_django.filter_field() - priority: Annotated['ContactPriorityEnum', strawberry.lazy('tenancy.graphql.enums')] | None = ( + priority: FilterLookup[Annotated['ContactPriorityEnum', strawberry.lazy('tenancy.graphql.enums')]] | None = ( strawberry_django.filter_field() ) diff --git a/netbox/virtualization/graphql/filters.py b/netbox/virtualization/graphql/filters.py index a10ade5a21..7ee8d90534 100644 --- a/netbox/virtualization/graphql/filters.py +++ b/netbox/virtualization/graphql/filters.py @@ -50,7 +50,7 @@ class ClusterFilter(ContactFilterMixin, ScopedFilterMixin, TenancyFilterMixin, P strawberry_django.filter_field() ) group_id: ID | None = strawberry_django.filter_field() - status: Annotated['ClusterStatusEnum', strawberry.lazy('virtualization.graphql.enums')] | None = ( + status: FilterLookup[Annotated['ClusterStatusEnum', strawberry.lazy('virtualization.graphql.enums')]] | None = ( strawberry_django.filter_field() ) vlan_groups: Annotated['VLANGroupFilter', strawberry.lazy('ipam.graphql.filters')] | None = ( @@ -92,7 +92,9 @@ class VirtualMachineFilter( strawberry_django.filter_field() ) platform_id: ID | None = strawberry_django.filter_field() - status: Annotated['VirtualMachineStatusEnum', strawberry.lazy('virtualization.graphql.enums')] | None = ( + status: ( + FilterLookup[Annotated['VirtualMachineStatusEnum', strawberry.lazy('virtualization.graphql.enums')]] | None + ) = ( strawberry_django.filter_field() ) role: Annotated['DeviceRoleFilter', strawberry.lazy('dcim.graphql.filters')] | None = ( diff --git a/netbox/vpn/graphql/filters.py b/netbox/vpn/graphql/filters.py index 21adcd1001..d7bd423eff 100644 --- a/netbox/vpn/graphql/filters.py +++ b/netbox/vpn/graphql/filters.py @@ -42,10 +42,12 @@ class TunnelTerminationFilter( ): tunnel: Annotated['TunnelFilter', strawberry.lazy('vpn.graphql.filters')] | None = strawberry_django.filter_field() tunnel_id: ID | None = strawberry_django.filter_field() - role: Annotated['TunnelTerminationRoleEnum', strawberry.lazy('vpn.graphql.enums')] | None = ( + role: FilterLookup[Annotated['TunnelTerminationRoleEnum', strawberry.lazy('vpn.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - termination_type: Annotated['TunnelTerminationTypeEnum', strawberry.lazy('vpn.graphql.enums')] | None = ( + termination_type: ( + FilterLookup[Annotated['TunnelTerminationTypeEnum', strawberry.lazy('vpn.graphql.enums')]] | None + ) = ( strawberry_django.filter_field() ) termination_type_id: ID | None = strawberry_django.filter_field() @@ -59,14 +61,14 @@ class TunnelTerminationFilter( @strawberry_django.filter_type(models.Tunnel, lookups=True) class TunnelFilter(TenancyFilterMixin, PrimaryModelFilterMixin): name: FilterLookup[str] | None = strawberry_django.filter_field() - status: Annotated['TunnelStatusEnum', strawberry.lazy('vpn.graphql.enums')] | None = ( + status: FilterLookup[Annotated['TunnelStatusEnum', strawberry.lazy('vpn.graphql.enums')]] | None = ( strawberry_django.filter_field() ) group: Annotated['TunnelGroupFilter', strawberry.lazy('vpn.graphql.filters')] | None = ( strawberry_django.filter_field() ) group_id: ID | None = strawberry_django.filter_field() - encapsulation: Annotated['TunnelEncapsulationEnum', strawberry.lazy('vpn.graphql.enums')] | None = ( + encapsulation: FilterLookup[Annotated['TunnelEncapsulationEnum', strawberry.lazy('vpn.graphql.enums')]] | None = ( strawberry_django.filter_field() ) ipsec_profile: Annotated['IPSecProfileFilter', strawberry.lazy('vpn.graphql.filters')] | None = ( @@ -83,16 +85,24 @@ class TunnelFilter(TenancyFilterMixin, PrimaryModelFilterMixin): @strawberry_django.filter_type(models.IKEProposal, lookups=True) class IKEProposalFilter(PrimaryModelFilterMixin): name: FilterLookup[str] | None = strawberry_django.filter_field() - authentication_method: Annotated['AuthenticationMethodEnum', strawberry.lazy('vpn.graphql.enums')] | None = ( + authentication_method: ( + FilterLookup[Annotated['AuthenticationMethodEnum', strawberry.lazy('vpn.graphql.enums')]] | None + ) = ( strawberry_django.filter_field() ) - encryption_algorithm: Annotated['EncryptionAlgorithmEnum', strawberry.lazy('vpn.graphql.enums')] | None = ( + encryption_algorithm: ( + FilterLookup[Annotated['EncryptionAlgorithmEnum', strawberry.lazy('vpn.graphql.enums')]] | None + ) = ( strawberry_django.filter_field() ) - authentication_algorithm: Annotated['AuthenticationAlgorithmEnum', strawberry.lazy('vpn.graphql.enums')] | None = ( + authentication_algorithm: ( + FilterLookup[Annotated['AuthenticationAlgorithmEnum', strawberry.lazy('vpn.graphql.enums')]] | None + ) = ( + strawberry_django.filter_field() + ) + group: FilterLookup[Annotated['DHGroupEnum', strawberry.lazy('vpn.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - group: Annotated['DHGroupEnum', strawberry.lazy('vpn.graphql.enums')] | None = strawberry_django.filter_field() sa_lifetime: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) @@ -104,8 +114,12 @@ class IKEProposalFilter(PrimaryModelFilterMixin): @strawberry_django.filter_type(models.IKEPolicy, lookups=True) class IKEPolicyFilter(PrimaryModelFilterMixin): name: FilterLookup[str] | None = strawberry_django.filter_field() - version: Annotated['IKEVersionEnum', strawberry.lazy('vpn.graphql.enums')] | None = strawberry_django.filter_field() - mode: Annotated['IKEModeEnum', strawberry.lazy('vpn.graphql.enums')] | None = strawberry_django.filter_field() + version: FilterLookup[Annotated['IKEVersionEnum', strawberry.lazy('vpn.graphql.enums')]] | None = ( + strawberry_django.filter_field() + ) + mode: FilterLookup[Annotated['IKEModeEnum', strawberry.lazy('vpn.graphql.enums')]] | None = ( + strawberry_django.filter_field() + ) proposals: Annotated['IKEProposalFilter', strawberry.lazy('vpn.graphql.filters')] | None = ( strawberry_django.filter_field() ) @@ -115,10 +129,14 @@ class IKEPolicyFilter(PrimaryModelFilterMixin): @strawberry_django.filter_type(models.IPSecProposal, lookups=True) class IPSecProposalFilter(PrimaryModelFilterMixin): name: FilterLookup[str] | None = strawberry_django.filter_field() - encryption_algorithm: Annotated['EncryptionAlgorithmEnum', strawberry.lazy('vpn.graphql.enums')] | None = ( + encryption_algorithm: ( + FilterLookup[Annotated['EncryptionAlgorithmEnum', strawberry.lazy('vpn.graphql.enums')]] | None + ) = ( strawberry_django.filter_field() ) - authentication_algorithm: Annotated['AuthenticationAlgorithmEnum', strawberry.lazy('vpn.graphql.enums')] | None = ( + authentication_algorithm: FilterLookup[ + Annotated['AuthenticationAlgorithmEnum', strawberry.lazy('vpn.graphql.enums')] + ] | None = ( strawberry_django.filter_field() ) sa_lifetime_seconds: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( @@ -138,13 +156,17 @@ class IPSecPolicyFilter(PrimaryModelFilterMixin): proposals: Annotated['IPSecProposalFilter', strawberry.lazy('vpn.graphql.filters')] | None = ( strawberry_django.filter_field() ) - pfs_group: Annotated['DHGroupEnum', strawberry.lazy('vpn.graphql.enums')] | None = strawberry_django.filter_field() + pfs_group: FilterLookup[Annotated['DHGroupEnum', strawberry.lazy('vpn.graphql.enums')]] | None = ( + strawberry_django.filter_field() + ) @strawberry_django.filter_type(models.IPSecProfile, lookups=True) class IPSecProfileFilter(PrimaryModelFilterMixin): name: FilterLookup[str] | None = strawberry_django.filter_field() - mode: Annotated['IPSecModeEnum', strawberry.lazy('vpn.graphql.enums')] | None = strawberry_django.filter_field() + mode: FilterLookup[Annotated['IPSecModeEnum', strawberry.lazy('vpn.graphql.enums')]] | None = ( + strawberry_django.filter_field() + ) ike_policy: Annotated['IKEPolicyFilter', strawberry.lazy('vpn.graphql.filters')] | None = ( strawberry_django.filter_field() ) @@ -159,7 +181,9 @@ class IPSecProfileFilter(PrimaryModelFilterMixin): class L2VPNFilter(ContactFilterMixin, TenancyFilterMixin, PrimaryModelFilterMixin): name: FilterLookup[str] | None = strawberry_django.filter_field() slug: FilterLookup[str] | None = strawberry_django.filter_field() - type: Annotated['L2VPNTypeEnum', strawberry.lazy('vpn.graphql.enums')] | None = strawberry_django.filter_field() + type: FilterLookup[Annotated['L2VPNTypeEnum', strawberry.lazy('vpn.graphql.enums')]] | None = ( + strawberry_django.filter_field() + ) identifier: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) diff --git a/netbox/wireless/graphql/filters.py b/netbox/wireless/graphql/filters.py index 5bd22afaba..bcf10a7b46 100644 --- a/netbox/wireless/graphql/filters.py +++ b/netbox/wireless/graphql/filters.py @@ -36,7 +36,7 @@ class WirelessLANFilter( PrimaryModelFilterMixin ): ssid: FilterLookup[str] | None = strawberry_django.filter_field() - status: Annotated['WirelessLANStatusEnum', strawberry.lazy('wireless.graphql.enums')] | None = ( + status: FilterLookup[Annotated['WirelessLANStatusEnum', strawberry.lazy('wireless.graphql.enums')]] | None = ( strawberry_django.filter_field() ) group: Annotated['WirelessLANGroupFilter', strawberry.lazy('wireless.graphql.filters')] | None = ( @@ -63,6 +63,6 @@ class WirelessLinkFilter( ) interface_b_id: ID | None = strawberry_django.filter_field() ssid: FilterLookup[str] | None = strawberry_django.filter_field() - status: Annotated['WirelessLANStatusEnum', strawberry.lazy('wireless.graphql.enums')] | None = ( + status: FilterLookup[Annotated['WirelessLANStatusEnum', strawberry.lazy('wireless.graphql.enums')]] | None = ( strawberry_django.filter_field() ) From 5a3eb1053fd35ad59ee99cc9e2094cbd928a982a Mon Sep 17 00:00:00 2001 From: Brian Tiemann Date: Fri, 24 Oct 2025 17:47:34 -0400 Subject: [PATCH 3/8] Change usages of FilterLookup to BaseFilterLookup --- netbox/circuits/graphql/filters.py | 14 +-- netbox/dcim/graphql/filters.py | 120 ++++++++++++----------- netbox/extras/graphql/filters.py | 26 ++--- netbox/ipam/graphql/filters.py | 20 ++-- netbox/tenancy/graphql/filters.py | 4 +- netbox/virtualization/graphql/filters.py | 6 +- netbox/vpn/graphql/filters.py | 40 ++++---- netbox/wireless/graphql/filters.py | 6 +- 8 files changed, 124 insertions(+), 112 deletions(-) diff --git a/netbox/circuits/graphql/filters.py b/netbox/circuits/graphql/filters.py index 545e76cb8f..25cb8092df 100644 --- a/netbox/circuits/graphql/filters.py +++ b/netbox/circuits/graphql/filters.py @@ -4,7 +4,7 @@ import strawberry import strawberry_django from strawberry.scalars import ID -from strawberry_django import FilterLookup, DateFilterLookup +from strawberry_django import BaseFilterLookup, FilterLookup, DateFilterLookup from circuits import models from core.graphql.filter_mixins import BaseObjectTypeFilterMixin, ChangeLogFilterMixin @@ -53,7 +53,7 @@ class CircuitTerminationFilter( strawberry_django.filter_field() ) term_side: ( - FilterLookup[Annotated['CircuitTerminationSideEnum', strawberry.lazy('circuits.graphql.enums')]] | None + BaseFilterLookup[Annotated['CircuitTerminationSideEnum', strawberry.lazy('circuits.graphql.enums')]] | None ) = ( strawberry_django.filter_field() ) @@ -110,7 +110,7 @@ class CircuitFilter( strawberry_django.filter_field() ) type_id: ID | None = strawberry_django.filter_field() - status: FilterLookup[Annotated['CircuitStatusEnum', strawberry.lazy('circuits.graphql.enums')]] | None = ( + status: BaseFilterLookup[Annotated['CircuitStatusEnum', strawberry.lazy('circuits.graphql.enums')]] | None = ( strawberry_django.filter_field() ) install_date: DateFilterLookup[date] | None = strawberry_django.filter_field() @@ -145,7 +145,7 @@ class CircuitGroupAssignmentFilter( strawberry_django.filter_field() ) group_id: ID | None = strawberry_django.filter_field() - priority: FilterLookup[Annotated['CircuitPriorityEnum', strawberry.lazy('circuits.graphql.enums')]] | None = ( + priority: BaseFilterLookup[Annotated['CircuitPriorityEnum', strawberry.lazy('circuits.graphql.enums')]] | None = ( strawberry_django.filter_field() ) @@ -200,7 +200,7 @@ class VirtualCircuitFilter(TenancyFilterMixin, PrimaryModelFilterMixin): strawberry_django.filter_field() ) type_id: ID | None = strawberry_django.filter_field() - status: FilterLookup[Annotated['CircuitStatusEnum', strawberry.lazy('circuits.graphql.enums')]] | None = ( + status: BaseFilterLookup[Annotated['CircuitStatusEnum', strawberry.lazy('circuits.graphql.enums')]] | None = ( strawberry_django.filter_field() ) group_assignments: Annotated['CircuitGroupAssignmentFilter', strawberry.lazy('circuits.graphql.filters')] | None = ( @@ -217,7 +217,9 @@ class VirtualCircuitTerminationFilter( ) virtual_circuit_id: ID | None = strawberry_django.filter_field() role: ( - FilterLookup[Annotated['VirtualCircuitTerminationRoleEnum', strawberry.lazy('circuits.graphql.enums')]] | None + BaseFilterLookup[ + Annotated['VirtualCircuitTerminationRoleEnum', strawberry.lazy('circuits.graphql.enums')] + ] | None ) = ( strawberry_django.filter_field() ) diff --git a/netbox/dcim/graphql/filters.py b/netbox/dcim/graphql/filters.py index c2f4d9749f..ef38782535 100644 --- a/netbox/dcim/graphql/filters.py +++ b/netbox/dcim/graphql/filters.py @@ -4,7 +4,7 @@ import strawberry import strawberry_django from strawberry.scalars import ID -from strawberry_django import FilterLookup +from strawberry_django import BaseFilterLookup, FilterLookup from core.graphql.filter_mixins import ChangeLogFilterMixin from dcim import models @@ -95,20 +95,20 @@ @strawberry_django.filter_type(models.Cable, lookups=True) class CableFilter(PrimaryModelFilterMixin, TenancyFilterMixin): - type: FilterLookup[Annotated['CableTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + type: BaseFilterLookup[Annotated['CableTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - status: FilterLookup[Annotated['LinkStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + status: BaseFilterLookup[Annotated['LinkStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) label: FilterLookup[str] | None = strawberry_django.filter_field() - color: FilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = ( + color: BaseFilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = ( strawberry_django.filter_field() ) length: Annotated['FloatLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) - length_unit: FilterLookup[Annotated['CableLengthUnitEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + length_unit: BaseFilterLookup[Annotated['CableLengthUnitEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) terminations: Annotated['CableTerminationFilter', strawberry.lazy('dcim.graphql.filters')] | None = ( @@ -120,7 +120,7 @@ class CableFilter(PrimaryModelFilterMixin, TenancyFilterMixin): class CableTerminationFilter(ChangeLogFilterMixin): cable: Annotated['CableFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field() cable_id: ID | None = strawberry_django.filter_field() - cable_end: FilterLookup[Annotated['CableEndEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + cable_end: BaseFilterLookup[Annotated['CableEndEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) termination_type: Annotated['CableTerminationFilter', strawberry.lazy('dcim.graphql.filters')] | None = ( @@ -131,34 +131,34 @@ class CableTerminationFilter(ChangeLogFilterMixin): @strawberry_django.filter_type(models.ConsolePort, lookups=True) class ConsolePortFilter(ModularComponentModelFilterMixin, CabledObjectModelFilterMixin): - type: FilterLookup[Annotated['ConsolePortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + type: BaseFilterLookup[Annotated['ConsolePortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - speed: FilterLookup[Annotated['ConsolePortSpeedEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + speed: BaseFilterLookup[Annotated['ConsolePortSpeedEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) @strawberry_django.filter_type(models.ConsolePortTemplate, lookups=True) class ConsolePortTemplateFilter(ModularComponentTemplateFilterMixin): - type: FilterLookup[Annotated['ConsolePortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + type: BaseFilterLookup[Annotated['ConsolePortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) @strawberry_django.filter_type(models.ConsoleServerPort, lookups=True) class ConsoleServerPortFilter(ModularComponentModelFilterMixin, CabledObjectModelFilterMixin): - type: FilterLookup[Annotated['ConsolePortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + type: BaseFilterLookup[Annotated['ConsolePortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - speed: FilterLookup[Annotated['ConsolePortSpeedEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + speed: BaseFilterLookup[Annotated['ConsolePortSpeedEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) @strawberry_django.filter_type(models.ConsoleServerPortTemplate, lookups=True) class ConsoleServerPortTemplateFilter(ModularComponentTemplateFilterMixin): - type: FilterLookup[Annotated['ConsolePortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + type: BaseFilterLookup[Annotated['ConsolePortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) @@ -199,13 +199,13 @@ class DeviceFilter( position: Annotated['FloatLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) - face: FilterLookup[Annotated['DeviceFaceEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + face: BaseFilterLookup[Annotated['DeviceFaceEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - status: FilterLookup[Annotated['DeviceStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + status: BaseFilterLookup[Annotated['DeviceStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - airflow: FilterLookup[Annotated['DeviceAirflowEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + airflow: BaseFilterLookup[Annotated['DeviceAirflowEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) primary_ip4: Annotated['IPAddressFilter', strawberry.lazy('ipam.graphql.filters')] | None = ( @@ -317,7 +317,7 @@ class InventoryItemTemplateFilter(ComponentTemplateFilterMixin): @strawberry_django.filter_type(models.DeviceRole, lookups=True) class DeviceRoleFilter(OrganizationalModelFilterMixin, RenderConfigFilterMixin): - color: FilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = ( + color: BaseFilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = ( strawberry_django.filter_field() ) vm_role: FilterLookup[bool] | None = strawberry_django.filter_field() @@ -341,10 +341,10 @@ class DeviceTypeFilter(ImageAttachmentFilterMixin, PrimaryModelFilterMixin, Weig ) exclude_from_utilization: FilterLookup[bool] | None = strawberry_django.filter_field() is_full_depth: FilterLookup[bool] | None = strawberry_django.filter_field() - subdevice_role: FilterLookup[Annotated['SubdeviceRoleEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + subdevice_role: BaseFilterLookup[Annotated['SubdeviceRoleEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - airflow: FilterLookup[Annotated['DeviceAirflowEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + airflow: BaseFilterLookup[Annotated['DeviceAirflowEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) front_image: Annotated['ImageAttachmentFilter', strawberry.lazy('extras.graphql.filters')] | None = ( @@ -397,10 +397,10 @@ class DeviceTypeFilter(ImageAttachmentFilterMixin, PrimaryModelFilterMixin, Weig @strawberry_django.filter_type(models.FrontPort, lookups=True) class FrontPortFilter(ModularComponentModelFilterMixin, CabledObjectModelFilterMixin): - type: FilterLookup[Annotated['PortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + type: BaseFilterLookup[Annotated['PortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - color: FilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = ( + color: BaseFilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = ( strawberry_django.filter_field() ) rear_port: Annotated['RearPortFilter', strawberry.lazy('dcim.graphql.filters')] | None = ( @@ -414,10 +414,10 @@ class FrontPortFilter(ModularComponentModelFilterMixin, CabledObjectModelFilterM @strawberry_django.filter_type(models.FrontPortTemplate, lookups=True) class FrontPortTemplateFilter(ModularComponentTemplateFilterMixin): - type: FilterLookup[Annotated['PortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + type: BaseFilterLookup[Annotated['PortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - color: FilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = ( + color: BaseFilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = ( strawberry_django.filter_field() ) rear_port: Annotated['RearPortTemplateFilter', strawberry.lazy('dcim.graphql.filters')] | None = ( @@ -445,14 +445,14 @@ class InterfaceFilter(ModularComponentModelFilterMixin, InterfaceBaseFilterMixin ) lag: Annotated['InterfaceFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field() lag_id: ID | None = strawberry_django.filter_field() - type: FilterLookup[Annotated['InterfaceTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + type: BaseFilterLookup[Annotated['InterfaceTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) mgmt_only: FilterLookup[bool] | None = strawberry_django.filter_field() speed: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) - duplex: FilterLookup[Annotated['InterfaceDuplexEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + duplex: BaseFilterLookup[Annotated['InterfaceDuplexEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) wwn: FilterLookup[str] | None = strawberry_django.filter_field() @@ -460,10 +460,10 @@ class InterfaceFilter(ModularComponentModelFilterMixin, InterfaceBaseFilterMixin strawberry_django.filter_field() ) parent_id: ID | None = strawberry_django.filter_field() - rf_role: FilterLookup[Annotated['WirelessRoleEnum', strawberry.lazy('wireless.graphql.enums')]] | None = ( + rf_role: BaseFilterLookup[Annotated['WirelessRoleEnum', strawberry.lazy('wireless.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - rf_channel: FilterLookup[Annotated['WirelessChannelEnum', strawberry.lazy('wireless.graphql.enums')]] | None = ( + rf_channel: BaseFilterLookup[Annotated['WirelessChannelEnum', strawberry.lazy('wireless.graphql.enums')]] | None = ( strawberry_django.filter_field() ) rf_channel_frequency: Annotated['FloatLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( @@ -475,10 +475,10 @@ class InterfaceFilter(ModularComponentModelFilterMixin, InterfaceBaseFilterMixin tx_power: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) - poe_mode: FilterLookup[Annotated['InterfacePoEModeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + poe_mode: BaseFilterLookup[Annotated['InterfacePoEModeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - poe_type: FilterLookup[Annotated['InterfacePoETypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + poe_type: BaseFilterLookup[Annotated['InterfacePoETypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) wireless_link: Annotated['WirelessLinkFilter', strawberry.lazy('wireless.graphql.filters')] | None = ( @@ -530,7 +530,7 @@ def kind( @strawberry_django.filter_type(models.InterfaceTemplate, lookups=True) class InterfaceTemplateFilter(ModularComponentTemplateFilterMixin): - type: FilterLookup[Annotated['InterfaceTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + type: BaseFilterLookup[Annotated['InterfaceTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) enabled: FilterLookup[bool] | None = strawberry_django.filter_field() @@ -539,13 +539,13 @@ class InterfaceTemplateFilter(ModularComponentTemplateFilterMixin): strawberry_django.filter_field() ) bridge_id: ID | None = strawberry_django.filter_field() - poe_mode: FilterLookup[Annotated['InterfacePoEModeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + poe_mode: BaseFilterLookup[Annotated['InterfacePoEModeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - poe_type: FilterLookup[Annotated['InterfacePoETypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + poe_type: BaseFilterLookup[Annotated['InterfacePoETypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - rf_role: FilterLookup[Annotated['WirelessRoleEnum', strawberry.lazy('wireless.graphql.enums')]] | None = ( + rf_role: BaseFilterLookup[Annotated['WirelessRoleEnum', strawberry.lazy('wireless.graphql.enums')]] | None = ( strawberry_django.filter_field() ) @@ -560,7 +560,7 @@ class InventoryItemFilter(ComponentModelFilterMixin): strawberry_django.filter_field() ) component_id: ID | None = strawberry_django.filter_field() - status: FilterLookup[Annotated['InventoryItemStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + status: BaseFilterLookup[Annotated['InventoryItemStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) role: Annotated['InventoryItemRoleFilter', strawberry.lazy('dcim.graphql.filters')] | None = ( @@ -579,7 +579,7 @@ class InventoryItemFilter(ComponentModelFilterMixin): @strawberry_django.filter_type(models.InventoryItemRole, lookups=True) class InventoryItemRoleFilter(OrganizationalModelFilterMixin): - color: FilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = ( + color: BaseFilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = ( strawberry_django.filter_field() ) @@ -588,7 +588,7 @@ class InventoryItemRoleFilter(OrganizationalModelFilterMixin): class LocationFilter(ContactFilterMixin, ImageAttachmentFilterMixin, TenancyFilterMixin, NestedGroupModelFilterMixin): site: Annotated['SiteFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field() site_id: ID | None = strawberry_django.filter_field() - status: FilterLookup[Annotated['LocationStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + status: BaseFilterLookup[Annotated['LocationStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) facility: FilterLookup[str] | None = strawberry_django.filter_field() @@ -617,7 +617,7 @@ class ModuleFilter(PrimaryModelFilterMixin, ConfigContextFilterMixin): strawberry_django.filter_field() ) module_type_id: ID | None = strawberry_django.filter_field() - status: FilterLookup[Annotated['ModuleStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + status: BaseFilterLookup[Annotated['ModuleStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) serial: FilterLookup[str] | None = strawberry_django.filter_field() @@ -685,7 +685,7 @@ class ModuleTypeFilter(ImageAttachmentFilterMixin, PrimaryModelFilterMixin, Weig profile_id: ID | None = strawberry_django.filter_field() model: FilterLookup[str] | None = strawberry_django.filter_field() part_number: FilterLookup[str] | None = strawberry_django.filter_field() - airflow: FilterLookup[Annotated['ModuleAirflowEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + airflow: BaseFilterLookup[Annotated['ModuleAirflowEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) console_port_templates: ( @@ -741,16 +741,16 @@ class PowerFeedFilter(CabledObjectModelFilterMixin, TenancyFilterMixin, PrimaryM rack: Annotated['RackFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field() rack_id: ID | None = strawberry_django.filter_field() name: FilterLookup[str] | None = strawberry_django.filter_field() - status: FilterLookup[Annotated['PowerFeedStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + status: BaseFilterLookup[Annotated['PowerFeedStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - type: FilterLookup[Annotated['PowerFeedTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + type: BaseFilterLookup[Annotated['PowerFeedTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - supply: FilterLookup[Annotated['PowerFeedSupplyEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + supply: BaseFilterLookup[Annotated['PowerFeedSupplyEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - phase: FilterLookup[Annotated['PowerFeedPhaseEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + phase: BaseFilterLookup[Annotated['PowerFeedPhaseEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) voltage: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( @@ -769,31 +769,31 @@ class PowerFeedFilter(CabledObjectModelFilterMixin, TenancyFilterMixin, PrimaryM @strawberry_django.filter_type(models.PowerOutlet, lookups=True) class PowerOutletFilter(ModularComponentModelFilterMixin, CabledObjectModelFilterMixin): - type: FilterLookup[Annotated['PowerOutletTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + type: BaseFilterLookup[Annotated['PowerOutletTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) power_port: Annotated['PowerPortFilter', strawberry.lazy('dcim.graphql.filters')] | None = ( strawberry_django.filter_field() ) power_port_id: ID | None = strawberry_django.filter_field() - feed_leg: FilterLookup[Annotated['PowerOutletFeedLegEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + feed_leg: BaseFilterLookup[Annotated['PowerOutletFeedLegEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - color: FilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = ( + color: BaseFilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = ( strawberry_django.filter_field() ) @strawberry_django.filter_type(models.PowerOutletTemplate, lookups=True) class PowerOutletTemplateFilter(ModularComponentModelFilterMixin): - type: FilterLookup[Annotated['PowerOutletTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + type: BaseFilterLookup[Annotated['PowerOutletTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) power_port: Annotated['PowerPortTemplateFilter', strawberry.lazy('dcim.graphql.filters')] | None = ( strawberry_django.filter_field() ) power_port_id: ID | None = strawberry_django.filter_field() - feed_leg: FilterLookup[Annotated['PowerOutletFeedLegEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + feed_leg: BaseFilterLookup[Annotated['PowerOutletFeedLegEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) @@ -813,7 +813,7 @@ class PowerPanelFilter(ContactFilterMixin, ImageAttachmentFilterMixin, PrimaryMo @strawberry_django.filter_type(models.PowerPort, lookups=True) class PowerPortFilter(ModularComponentModelFilterMixin, CabledObjectModelFilterMixin): - type: FilterLookup[Annotated['PowerPortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + type: BaseFilterLookup[Annotated['PowerPortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) maximum_draw: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( @@ -826,7 +826,7 @@ class PowerPortFilter(ModularComponentModelFilterMixin, CabledObjectModelFilterM @strawberry_django.filter_type(models.PowerPortTemplate, lookups=True) class PowerPortTemplateFilter(ModularComponentTemplateFilterMixin): - type: FilterLookup[Annotated['PowerPortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + type: BaseFilterLookup[Annotated['PowerPortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) maximum_draw: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( @@ -839,7 +839,7 @@ class PowerPortTemplateFilter(ModularComponentTemplateFilterMixin): @strawberry_django.filter_type(models.RackType, lookups=True) class RackTypeFilter(RackBaseFilterMixin): - form_factor: FilterLookup[Annotated['RackFormFactorEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + form_factor: BaseFilterLookup[Annotated['RackFormFactorEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) manufacturer: Annotated['ManufacturerFilter', strawberry.lazy('dcim.graphql.filters')] | None = ( @@ -852,7 +852,7 @@ class RackTypeFilter(RackBaseFilterMixin): @strawberry_django.filter_type(models.Rack, lookups=True) class RackFilter(ContactFilterMixin, ImageAttachmentFilterMixin, TenancyFilterMixin, RackBaseFilterMixin): - form_factor: FilterLookup[Annotated['RackFormFactorEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + form_factor: BaseFilterLookup[Annotated['RackFormFactorEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) rack_type: Annotated['RackTypeFilter', strawberry.lazy('dcim.graphql.filters')] | None = ( @@ -869,14 +869,14 @@ class RackFilter(ContactFilterMixin, ImageAttachmentFilterMixin, TenancyFilterMi location_id: Annotated['TreeNodeFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) - status: FilterLookup[Annotated['RackStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + status: BaseFilterLookup[Annotated['RackStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) role: Annotated['RackRoleFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field() role_id: ID | None = strawberry_django.filter_field() serial: FilterLookup[str] | None = strawberry_django.filter_field() asset_tag: FilterLookup[str] | None = strawberry_django.filter_field() - airflow: FilterLookup[Annotated['RackAirflowEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + airflow: BaseFilterLookup[Annotated['RackAirflowEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) vlan_groups: Annotated['VLANGroupFilter', strawberry.lazy('ipam.graphql.filters')] | None = ( @@ -898,17 +898,17 @@ class RackReservationFilter(TenancyFilterMixin, PrimaryModelFilterMixin): @strawberry_django.filter_type(models.RackRole, lookups=True) class RackRoleFilter(OrganizationalModelFilterMixin): - color: FilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = ( + color: BaseFilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = ( strawberry_django.filter_field() ) @strawberry_django.filter_type(models.RearPort, lookups=True) class RearPortFilter(ModularComponentModelFilterMixin, CabledObjectModelFilterMixin): - type: FilterLookup[Annotated['PortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + type: BaseFilterLookup[Annotated['PortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - color: FilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = ( + color: BaseFilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = ( strawberry_django.filter_field() ) positions: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( @@ -918,10 +918,10 @@ class RearPortFilter(ModularComponentModelFilterMixin, CabledObjectModelFilterMi @strawberry_django.filter_type(models.RearPortTemplate, lookups=True) class RearPortTemplateFilter(ModularComponentTemplateFilterMixin): - type: FilterLookup[Annotated['PortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + type: BaseFilterLookup[Annotated['PortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - color: FilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = ( + color: BaseFilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = ( strawberry_django.filter_field() ) positions: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( @@ -943,7 +943,7 @@ class RegionFilter(ContactFilterMixin, NestedGroupModelFilterMixin): class SiteFilter(ContactFilterMixin, ImageAttachmentFilterMixin, TenancyFilterMixin, PrimaryModelFilterMixin): name: FilterLookup[str] | None = strawberry_django.filter_field() slug: FilterLookup[str] | None = strawberry_django.filter_field() - status: FilterLookup[Annotated['SiteStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + status: BaseFilterLookup[Annotated['SiteStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) region: Annotated['RegionFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field() @@ -1002,7 +1002,9 @@ class VirtualDeviceContextFilter(TenancyFilterMixin, PrimaryModelFilterMixin): device: Annotated['DeviceFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field() device_id: ID | None = strawberry_django.filter_field() name: FilterLookup[str] | None = strawberry_django.filter_field() - status: FilterLookup[Annotated['VirtualDeviceContextStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( + status: ( + BaseFilterLookup[Annotated['VirtualDeviceContextStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None + ) = ( strawberry_django.filter_field() ) identifier: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( diff --git a/netbox/extras/graphql/filters.py b/netbox/extras/graphql/filters.py index 75aaac955a..724c534212 100644 --- a/netbox/extras/graphql/filters.py +++ b/netbox/extras/graphql/filters.py @@ -3,7 +3,7 @@ import strawberry import strawberry_django from strawberry.scalars import ID -from strawberry_django import FilterLookup +from strawberry_django import BaseFilterLookup, FilterLookup from core.graphql.filter_mixins import BaseObjectTypeFilterMixin, ChangeLogFilterMixin from extras import models @@ -121,7 +121,7 @@ class ConfigTemplateFilter(BaseObjectTypeFilterMixin, SyncedDataFilterMixin, Cha @strawberry_django.filter_type(models.CustomField, lookups=True) class CustomFieldFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin): - type: FilterLookup[Annotated['CustomFieldTypeEnum', strawberry.lazy('extras.graphql.enums')]] | None = ( + type: BaseFilterLookup[Annotated['CustomFieldTypeEnum', strawberry.lazy('extras.graphql.enums')]] | None = ( strawberry_django.filter_field() ) object_types: Annotated['ContentTypeFilter', strawberry.lazy('core.graphql.filters')] | None = ( @@ -140,7 +140,7 @@ class CustomFieldFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin): strawberry_django.filter_field() ) filter_logic: ( - FilterLookup[Annotated['CustomFieldFilterLogicEnum', strawberry.lazy('extras.graphql.enums')]] | None + BaseFilterLookup[Annotated['CustomFieldFilterLogicEnum', strawberry.lazy('extras.graphql.enums')]] | None ) = ( strawberry_django.filter_field() ) @@ -164,11 +164,13 @@ class CustomFieldFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin): strawberry_django.filter_field() ) choice_set_id: ID | None = strawberry_django.filter_field() - ui_visible: FilterLookup[Annotated['CustomFieldUIVisibleEnum', strawberry.lazy('extras.graphql.enums')]] | None = ( + ui_visible: ( + BaseFilterLookup[Annotated['CustomFieldUIVisibleEnum', strawberry.lazy('extras.graphql.enums')]] | None + ) = ( strawberry_django.filter_field() ) ui_editable: ( - FilterLookup[Annotated['CustomFieldUIEditableEnum', strawberry.lazy('extras.graphql.enums')]] | None + BaseFilterLookup[Annotated['CustomFieldUIEditableEnum', strawberry.lazy('extras.graphql.enums')]] | None ) = ( strawberry_django.filter_field() ) @@ -181,7 +183,7 @@ class CustomFieldChoiceSetFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin name: FilterLookup[str] | None = strawberry_django.filter_field() description: FilterLookup[str] | None = strawberry_django.filter_field() base_choices: ( - FilterLookup[Annotated['CustomFieldChoiceSetBaseEnum', strawberry.lazy('extras.graphql.enums')]] | None + BaseFilterLookup[Annotated['CustomFieldChoiceSetBaseEnum', strawberry.lazy('extras.graphql.enums')]] | None ) = ( strawberry_django.filter_field() ) @@ -202,7 +204,7 @@ class CustomLinkFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin): ) group_name: FilterLookup[str] | None = strawberry_django.filter_field() button_class: ( - FilterLookup[Annotated['CustomLinkButtonClassEnum', strawberry.lazy('extras.graphql.enums')]] | None + BaseFilterLookup[Annotated['CustomLinkButtonClassEnum', strawberry.lazy('extras.graphql.enums')]] | None ) = ( strawberry_django.filter_field() ) @@ -248,7 +250,7 @@ class JournalEntryFilter(BaseObjectTypeFilterMixin, CustomFieldsFilterMixin, Tag created_by: Annotated['UserFilter', strawberry.lazy('users.graphql.filters')] | None = ( strawberry_django.filter_field() ) - kind: FilterLookup[Annotated['JournalEntryKindEnum', strawberry.lazy('extras.graphql.enums')]] | None = ( + kind: BaseFilterLookup[Annotated['JournalEntryKindEnum', strawberry.lazy('extras.graphql.enums')]] | None = ( strawberry_django.filter_field() ) comments: FilterLookup[str] | None = strawberry_django.filter_field() @@ -294,7 +296,7 @@ class TableConfigFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin): @strawberry_django.filter_type(models.Tag, lookups=True) class TagFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin, TagBaseFilterMixin): - color: FilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = ( + color: BaseFilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = ( strawberry_django.filter_field() ) description: FilterLookup[str] | None = strawberry_django.filter_field() @@ -305,7 +307,9 @@ class WebhookFilter(BaseObjectTypeFilterMixin, CustomFieldsFilterMixin, TagsFilt name: FilterLookup[str] | None = strawberry_django.filter_field() description: FilterLookup[str] | None = strawberry_django.filter_field() payload_url: FilterLookup[str] | None = strawberry_django.filter_field() - http_method: FilterLookup[Annotated['WebhookHttpMethodEnum', strawberry.lazy('extras.graphql.enums')]] | None = ( + http_method: ( + BaseFilterLookup[Annotated['WebhookHttpMethodEnum', strawberry.lazy('extras.graphql.enums')]] | None + ) = ( strawberry_django.filter_field() ) http_content_type: FilterLookup[str] | None = strawberry_django.filter_field() @@ -330,7 +334,7 @@ class EventRuleFilter(BaseObjectTypeFilterMixin, CustomFieldsFilterMixin, TagsFi conditions: Annotated['JSONFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) - action_type: FilterLookup[Annotated['EventRuleActionEnum', strawberry.lazy('extras.graphql.enums')]] | None = ( + action_type: BaseFilterLookup[Annotated['EventRuleActionEnum', strawberry.lazy('extras.graphql.enums')]] | None = ( strawberry_django.filter_field() ) action_object_type: FilterLookup[str] | None = strawberry_django.filter_field() diff --git a/netbox/ipam/graphql/filters.py b/netbox/ipam/graphql/filters.py index 30ab8612e0..1183a106a4 100644 --- a/netbox/ipam/graphql/filters.py +++ b/netbox/ipam/graphql/filters.py @@ -7,7 +7,7 @@ from django.db.models import Q from netaddr.core import AddrFormatError from strawberry.scalars import ID -from strawberry_django import FilterLookup, DateFilterLookup +from strawberry_django import BaseFilterLookup, FilterLookup, DateFilterLookup from core.graphql.filter_mixins import BaseObjectTypeFilterMixin, ChangeLogFilterMixin from dcim.graphql.filter_mixins import ScopedFilterMixin @@ -92,10 +92,10 @@ class FHRPGroupFilter(PrimaryModelFilterMixin): strawberry_django.filter_field() ) name: FilterLookup[str] | None = strawberry_django.filter_field() - protocol: FilterLookup[Annotated['FHRPGroupProtocolEnum', strawberry.lazy('ipam.graphql.enums')]] | None = ( + protocol: BaseFilterLookup[Annotated['FHRPGroupProtocolEnum', strawberry.lazy('ipam.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - auth_type: FilterLookup[Annotated['FHRPGroupAuthTypeEnum', strawberry.lazy('ipam.graphql.enums')]] | None = ( + auth_type: BaseFilterLookup[Annotated['FHRPGroupAuthTypeEnum', strawberry.lazy('ipam.graphql.enums')]] | None = ( strawberry_django.filter_field() ) auth_key: FilterLookup[str] | None = strawberry_django.filter_field() @@ -148,10 +148,10 @@ class IPAddressFilter(ContactFilterMixin, TenancyFilterMixin, PrimaryModelFilter address: FilterLookup[str] | 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() - status: FilterLookup[Annotated['IPAddressStatusEnum', strawberry.lazy('ipam.graphql.enums')]] | None = ( + status: BaseFilterLookup[Annotated['IPAddressStatusEnum', strawberry.lazy('ipam.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - role: FilterLookup[Annotated['IPAddressRoleEnum', strawberry.lazy('ipam.graphql.enums')]] | None = ( + role: BaseFilterLookup[Annotated['IPAddressRoleEnum', strawberry.lazy('ipam.graphql.enums')]] | None = ( strawberry_django.filter_field() ) assigned_object_type: Annotated['ContentTypeFilter', strawberry.lazy('core.graphql.filters')] | None = ( @@ -188,7 +188,7 @@ def parent(self, value: list[str], prefix) -> Q: @strawberry_django.filter_field() def family( self, - value: FilterLookup[Annotated['IPAddressFamilyEnum', strawberry.lazy('ipam.graphql.enums')]], + value: Annotated['IPAddressFamilyEnum', strawberry.lazy('ipam.graphql.enums')], prefix, ) -> Q: return Q(**{f"{prefix}address__family": value.value}) @@ -203,7 +203,7 @@ class IPRangeFilter(ContactFilterMixin, TenancyFilterMixin, PrimaryModelFilterMi ) vrf: Annotated['VRFFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field() vrf_id: ID | None = strawberry_django.filter_field() - status: FilterLookup[Annotated['IPRangeStatusEnum', strawberry.lazy('ipam.graphql.enums')]] | None = ( + status: BaseFilterLookup[Annotated['IPRangeStatusEnum', strawberry.lazy('ipam.graphql.enums')]] | None = ( strawberry_django.filter_field() ) role: Annotated['RoleFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field() @@ -243,7 +243,7 @@ class PrefixFilter(ContactFilterMixin, ScopedFilterMixin, TenancyFilterMixin, Pr vrf_id: ID | None = strawberry_django.filter_field() vlan: Annotated['VLANFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field() vlan_id: ID | None = strawberry_django.filter_field() - status: FilterLookup[Annotated['PrefixStatusEnum', strawberry.lazy('ipam.graphql.enums')]] | None = ( + status: BaseFilterLookup[Annotated['PrefixStatusEnum', strawberry.lazy('ipam.graphql.enums')]] | None = ( strawberry_django.filter_field() ) role: Annotated['RoleFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field() @@ -320,7 +320,7 @@ class VLANFilter(TenancyFilterMixin, PrimaryModelFilterMixin): strawberry_django.filter_field() ) name: FilterLookup[str] | None = strawberry_django.filter_field() - status: FilterLookup[Annotated['VLANStatusEnum', strawberry.lazy('ipam.graphql.enums')]] | None = ( + status: BaseFilterLookup[Annotated['VLANStatusEnum', strawberry.lazy('ipam.graphql.enums')]] | None = ( strawberry_django.filter_field() ) role: Annotated['RoleFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field() @@ -332,7 +332,7 @@ class VLANFilter(TenancyFilterMixin, PrimaryModelFilterMixin): qinq_cvlans: Annotated['VLANFilter', strawberry.lazy('ipam.graphql.filters')] | None = ( strawberry_django.filter_field() ) - qinq_role: FilterLookup[Annotated['VLANQinQRoleEnum', strawberry.lazy('ipam.graphql.enums')]] | None = ( + qinq_role: BaseFilterLookup[Annotated['VLANQinQRoleEnum', strawberry.lazy('ipam.graphql.enums')]] | None = ( strawberry_django.filter_field() ) l2vpn_terminations: Annotated['L2VPNFilter', strawberry.lazy('vpn.graphql.filters')] | None = ( diff --git a/netbox/tenancy/graphql/filters.py b/netbox/tenancy/graphql/filters.py index 08682c4428..dbdbfd7503 100644 --- a/netbox/tenancy/graphql/filters.py +++ b/netbox/tenancy/graphql/filters.py @@ -3,7 +3,7 @@ import strawberry import strawberry_django from strawberry.scalars import ID -from strawberry_django import FilterLookup +from strawberry_django import BaseFilterLookup, FilterLookup from core.graphql.filter_mixins import ChangeLogFilterMixin from extras.graphql.filter_mixins import CustomFieldsFilterMixin, TagsFilterMixin @@ -191,6 +191,6 @@ class ContactAssignmentFilter(CustomFieldsFilterMixin, TagsFilterMixin, ChangeLo strawberry_django.filter_field() ) role_id: ID | None = strawberry_django.filter_field() - priority: FilterLookup[Annotated['ContactPriorityEnum', strawberry.lazy('tenancy.graphql.enums')]] | None = ( + priority: BaseFilterLookup[Annotated['ContactPriorityEnum', strawberry.lazy('tenancy.graphql.enums')]] | None = ( strawberry_django.filter_field() ) diff --git a/netbox/virtualization/graphql/filters.py b/netbox/virtualization/graphql/filters.py index 7ee8d90534..5b29e362a1 100644 --- a/netbox/virtualization/graphql/filters.py +++ b/netbox/virtualization/graphql/filters.py @@ -3,7 +3,7 @@ import strawberry import strawberry_django from strawberry.scalars import ID -from strawberry_django import FilterLookup +from strawberry_django import BaseFilterLookup, FilterLookup from dcim.graphql.filter_mixins import InterfaceBaseFilterMixin, RenderConfigFilterMixin, ScopedFilterMixin from extras.graphql.filter_mixins import ConfigContextFilterMixin @@ -50,7 +50,7 @@ class ClusterFilter(ContactFilterMixin, ScopedFilterMixin, TenancyFilterMixin, P strawberry_django.filter_field() ) group_id: ID | None = strawberry_django.filter_field() - status: FilterLookup[Annotated['ClusterStatusEnum', strawberry.lazy('virtualization.graphql.enums')]] | None = ( + status: BaseFilterLookup[Annotated['ClusterStatusEnum', strawberry.lazy('virtualization.graphql.enums')]] | None = ( strawberry_django.filter_field() ) vlan_groups: Annotated['VLANGroupFilter', strawberry.lazy('ipam.graphql.filters')] | None = ( @@ -93,7 +93,7 @@ class VirtualMachineFilter( ) platform_id: ID | None = strawberry_django.filter_field() status: ( - FilterLookup[Annotated['VirtualMachineStatusEnum', strawberry.lazy('virtualization.graphql.enums')]] | None + BaseFilterLookup[Annotated['VirtualMachineStatusEnum', strawberry.lazy('virtualization.graphql.enums')]] | None ) = ( strawberry_django.filter_field() ) diff --git a/netbox/vpn/graphql/filters.py b/netbox/vpn/graphql/filters.py index d7bd423eff..7955550c9a 100644 --- a/netbox/vpn/graphql/filters.py +++ b/netbox/vpn/graphql/filters.py @@ -3,7 +3,7 @@ import strawberry import strawberry_django from strawberry.scalars import ID -from strawberry_django import FilterLookup +from strawberry_django import BaseFilterLookup, FilterLookup from core.graphql.filter_mixins import BaseObjectTypeFilterMixin, ChangeLogFilterMixin from extras.graphql.filter_mixins import CustomFieldsFilterMixin, TagsFilterMixin @@ -42,11 +42,11 @@ class TunnelTerminationFilter( ): tunnel: Annotated['TunnelFilter', strawberry.lazy('vpn.graphql.filters')] | None = strawberry_django.filter_field() tunnel_id: ID | None = strawberry_django.filter_field() - role: FilterLookup[Annotated['TunnelTerminationRoleEnum', strawberry.lazy('vpn.graphql.enums')]] | None = ( + role: BaseFilterLookup[Annotated['TunnelTerminationRoleEnum', strawberry.lazy('vpn.graphql.enums')]] | None = ( strawberry_django.filter_field() ) termination_type: ( - FilterLookup[Annotated['TunnelTerminationTypeEnum', strawberry.lazy('vpn.graphql.enums')]] | None + BaseFilterLookup[Annotated['TunnelTerminationTypeEnum', strawberry.lazy('vpn.graphql.enums')]] | None ) = ( strawberry_django.filter_field() ) @@ -61,14 +61,16 @@ class TunnelTerminationFilter( @strawberry_django.filter_type(models.Tunnel, lookups=True) class TunnelFilter(TenancyFilterMixin, PrimaryModelFilterMixin): name: FilterLookup[str] | None = strawberry_django.filter_field() - status: FilterLookup[Annotated['TunnelStatusEnum', strawberry.lazy('vpn.graphql.enums')]] | None = ( + status: BaseFilterLookup[Annotated['TunnelStatusEnum', strawberry.lazy('vpn.graphql.enums')]] | None = ( strawberry_django.filter_field() ) group: Annotated['TunnelGroupFilter', strawberry.lazy('vpn.graphql.filters')] | None = ( strawberry_django.filter_field() ) group_id: ID | None = strawberry_django.filter_field() - encapsulation: FilterLookup[Annotated['TunnelEncapsulationEnum', strawberry.lazy('vpn.graphql.enums')]] | None = ( + encapsulation: ( + BaseFilterLookup[Annotated['TunnelEncapsulationEnum', strawberry.lazy('vpn.graphql.enums')]] | None + ) = ( strawberry_django.filter_field() ) ipsec_profile: Annotated['IPSecProfileFilter', strawberry.lazy('vpn.graphql.filters')] | None = ( @@ -86,21 +88,21 @@ class TunnelFilter(TenancyFilterMixin, PrimaryModelFilterMixin): class IKEProposalFilter(PrimaryModelFilterMixin): name: FilterLookup[str] | None = strawberry_django.filter_field() authentication_method: ( - FilterLookup[Annotated['AuthenticationMethodEnum', strawberry.lazy('vpn.graphql.enums')]] | None + BaseFilterLookup[Annotated['AuthenticationMethodEnum', strawberry.lazy('vpn.graphql.enums')]] | None ) = ( strawberry_django.filter_field() ) encryption_algorithm: ( - FilterLookup[Annotated['EncryptionAlgorithmEnum', strawberry.lazy('vpn.graphql.enums')]] | None + BaseFilterLookup[Annotated['EncryptionAlgorithmEnum', strawberry.lazy('vpn.graphql.enums')]] | None ) = ( strawberry_django.filter_field() ) authentication_algorithm: ( - FilterLookup[Annotated['AuthenticationAlgorithmEnum', strawberry.lazy('vpn.graphql.enums')]] | None + BaseFilterLookup[Annotated['AuthenticationAlgorithmEnum', strawberry.lazy('vpn.graphql.enums')]] | None ) = ( strawberry_django.filter_field() ) - group: FilterLookup[Annotated['DHGroupEnum', strawberry.lazy('vpn.graphql.enums')]] | None = ( + group: BaseFilterLookup[Annotated['DHGroupEnum', strawberry.lazy('vpn.graphql.enums')]] | None = ( strawberry_django.filter_field() ) sa_lifetime: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( @@ -114,10 +116,10 @@ class IKEProposalFilter(PrimaryModelFilterMixin): @strawberry_django.filter_type(models.IKEPolicy, lookups=True) class IKEPolicyFilter(PrimaryModelFilterMixin): name: FilterLookup[str] | None = strawberry_django.filter_field() - version: FilterLookup[Annotated['IKEVersionEnum', strawberry.lazy('vpn.graphql.enums')]] | None = ( + version: BaseFilterLookup[Annotated['IKEVersionEnum', strawberry.lazy('vpn.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - mode: FilterLookup[Annotated['IKEModeEnum', strawberry.lazy('vpn.graphql.enums')]] | None = ( + mode: BaseFilterLookup[Annotated['IKEModeEnum', strawberry.lazy('vpn.graphql.enums')]] | None = ( strawberry_django.filter_field() ) proposals: Annotated['IKEProposalFilter', strawberry.lazy('vpn.graphql.filters')] | None = ( @@ -130,13 +132,15 @@ class IKEPolicyFilter(PrimaryModelFilterMixin): class IPSecProposalFilter(PrimaryModelFilterMixin): name: FilterLookup[str] | None = strawberry_django.filter_field() encryption_algorithm: ( - FilterLookup[Annotated['EncryptionAlgorithmEnum', strawberry.lazy('vpn.graphql.enums')]] | None + BaseFilterLookup[Annotated['EncryptionAlgorithmEnum', strawberry.lazy('vpn.graphql.enums')]] | None ) = ( strawberry_django.filter_field() ) - authentication_algorithm: FilterLookup[ - Annotated['AuthenticationAlgorithmEnum', strawberry.lazy('vpn.graphql.enums')] - ] | None = ( + authentication_algorithm: ( + BaseFilterLookup[ + BaseFilterLookup[Annotated['AuthenticationAlgorithmEnum', strawberry.lazy('vpn.graphql.enums')]] + ] | None + ) = ( strawberry_django.filter_field() ) sa_lifetime_seconds: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( @@ -156,7 +160,7 @@ class IPSecPolicyFilter(PrimaryModelFilterMixin): proposals: Annotated['IPSecProposalFilter', strawberry.lazy('vpn.graphql.filters')] | None = ( strawberry_django.filter_field() ) - pfs_group: FilterLookup[Annotated['DHGroupEnum', strawberry.lazy('vpn.graphql.enums')]] | None = ( + pfs_group: BaseFilterLookup[Annotated['DHGroupEnum', strawberry.lazy('vpn.graphql.enums')]] | None = ( strawberry_django.filter_field() ) @@ -164,7 +168,7 @@ class IPSecPolicyFilter(PrimaryModelFilterMixin): @strawberry_django.filter_type(models.IPSecProfile, lookups=True) class IPSecProfileFilter(PrimaryModelFilterMixin): name: FilterLookup[str] | None = strawberry_django.filter_field() - mode: FilterLookup[Annotated['IPSecModeEnum', strawberry.lazy('vpn.graphql.enums')]] | None = ( + mode: BaseFilterLookup[Annotated['IPSecModeEnum', strawberry.lazy('vpn.graphql.enums')]] | None = ( strawberry_django.filter_field() ) ike_policy: Annotated['IKEPolicyFilter', strawberry.lazy('vpn.graphql.filters')] | None = ( @@ -181,7 +185,7 @@ class IPSecProfileFilter(PrimaryModelFilterMixin): class L2VPNFilter(ContactFilterMixin, TenancyFilterMixin, PrimaryModelFilterMixin): name: FilterLookup[str] | None = strawberry_django.filter_field() slug: FilterLookup[str] | None = strawberry_django.filter_field() - type: FilterLookup[Annotated['L2VPNTypeEnum', strawberry.lazy('vpn.graphql.enums')]] | None = ( + type: BaseFilterLookup[Annotated['L2VPNTypeEnum', strawberry.lazy('vpn.graphql.enums')]] | None = ( strawberry_django.filter_field() ) identifier: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( diff --git a/netbox/wireless/graphql/filters.py b/netbox/wireless/graphql/filters.py index bcf10a7b46..342e078ed3 100644 --- a/netbox/wireless/graphql/filters.py +++ b/netbox/wireless/graphql/filters.py @@ -3,7 +3,7 @@ import strawberry import strawberry_django from strawberry.scalars import ID -from strawberry_django import FilterLookup +from strawberry_django import BaseFilterLookup, FilterLookup from dcim.graphql.filter_mixins import ScopedFilterMixin from netbox.graphql.filter_mixins import DistanceFilterMixin, PrimaryModelFilterMixin, NestedGroupModelFilterMixin @@ -36,7 +36,7 @@ class WirelessLANFilter( PrimaryModelFilterMixin ): ssid: FilterLookup[str] | None = strawberry_django.filter_field() - status: FilterLookup[Annotated['WirelessLANStatusEnum', strawberry.lazy('wireless.graphql.enums')]] | None = ( + status: BaseFilterLookup[Annotated['WirelessLANStatusEnum', strawberry.lazy('wireless.graphql.enums')]] | None = ( strawberry_django.filter_field() ) group: Annotated['WirelessLANGroupFilter', strawberry.lazy('wireless.graphql.filters')] | None = ( @@ -63,6 +63,6 @@ class WirelessLinkFilter( ) interface_b_id: ID | None = strawberry_django.filter_field() ssid: FilterLookup[str] | None = strawberry_django.filter_field() - status: FilterLookup[Annotated['WirelessLANStatusEnum', strawberry.lazy('wireless.graphql.enums')]] | None = ( + status: BaseFilterLookup[Annotated['WirelessLANStatusEnum', strawberry.lazy('wireless.graphql.enums')]] | None = ( strawberry_django.filter_field() ) From 2f6494cd936999f326341fe116df4f13a36e31e9 Mon Sep 17 00:00:00 2001 From: Brian Tiemann Date: Fri, 24 Oct 2025 18:34:07 -0400 Subject: [PATCH 4/8] Merge feature --- netbox/dcim/graphql/types_v1.py | 1 + 1 file changed, 1 insertion(+) diff --git a/netbox/dcim/graphql/types_v1.py b/netbox/dcim/graphql/types_v1.py index c7f069ecbd..53f89087a2 100644 --- a/netbox/dcim/graphql/types_v1.py +++ b/netbox/dcim/graphql/types_v1.py @@ -677,6 +677,7 @@ class PowerOutletTypeV1(ModularComponentTypeV1, CabledObjectMixinV1, PathEndpoin ) class PowerOutletTemplateTypeV1(ModularComponentTemplateTypeV1): power_port: Annotated["PowerPortTemplateTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + color: str @strawberry_django.type( From b8fea8c8df125dd19f960637130b463ea07a7f7d Mon Sep 17 00:00:00 2001 From: Brian Tiemann Date: Fri, 24 Oct 2025 18:36:31 -0400 Subject: [PATCH 5/8] Merge feature --- netbox/dcim/graphql/types_v1.py | 1 + 1 file changed, 1 insertion(+) diff --git a/netbox/dcim/graphql/types_v1.py b/netbox/dcim/graphql/types_v1.py index c7f069ecbd..53f89087a2 100644 --- a/netbox/dcim/graphql/types_v1.py +++ b/netbox/dcim/graphql/types_v1.py @@ -677,6 +677,7 @@ class PowerOutletTypeV1(ModularComponentTypeV1, CabledObjectMixinV1, PathEndpoin ) class PowerOutletTemplateTypeV1(ModularComponentTemplateTypeV1): power_port: Annotated["PowerPortTemplateTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None + color: str @strawberry_django.type( From 1d6d154919eb1c6c1551e7a48b4dc09c17830317 Mon Sep 17 00:00:00 2001 From: Brian Tiemann Date: Fri, 24 Oct 2025 20:55:47 -0400 Subject: [PATCH 6/8] Set GRAPHQL_DEFAULT_VERSION = 2 in testing environment --- netbox/netbox/configuration_testing.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/netbox/netbox/configuration_testing.py b/netbox/netbox/configuration_testing.py index 3e552e9441..69ced660da 100644 --- a/netbox/netbox/configuration_testing.py +++ b/netbox/netbox/configuration_testing.py @@ -51,3 +51,5 @@ 'version': 1, 'disable_existing_loggers': True } + +GRAPHQL_DEFAULT_VERSION = 2 From b62f735f6063334b8ebf4d1ff12daf808244fca3 Mon Sep 17 00:00:00 2001 From: Brian Tiemann Date: Fri, 24 Oct 2025 21:18:51 -0400 Subject: [PATCH 7/8] Integrate Owner and JournalEntries fields --- netbox/netbox/configuration_testing.py | 3 ++- netbox/netbox/graphql/types_v1.py | 35 +++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/netbox/netbox/configuration_testing.py b/netbox/netbox/configuration_testing.py index 69ced660da..6256af00ac 100644 --- a/netbox/netbox/configuration_testing.py +++ b/netbox/netbox/configuration_testing.py @@ -52,4 +52,5 @@ 'disable_existing_loggers': True } -GRAPHQL_DEFAULT_VERSION = 2 +# TODO: Switch to 2 +GRAPHQL_DEFAULT_VERSION = 1 diff --git a/netbox/netbox/graphql/types_v1.py b/netbox/netbox/graphql/types_v1.py index c6b3ad2ecf..66a3ac9051 100644 --- a/netbox/netbox/graphql/types_v1.py +++ b/netbox/netbox/graphql/types_v1.py @@ -6,13 +6,16 @@ from core.graphql.mixins import ChangelogMixin from core.models import ObjectType as ObjectType_ from extras.graphql.mixins import CustomFieldsMixin, JournalEntriesMixin, TagsMixin +from users.graphql.mixins import OwnerMixin __all__ = ( 'BaseObjectTypeV1', 'ContentTypeTypeV1', + 'NestedGroupObjectTypeV1', + 'NetBoxObjectTypeV1', 'ObjectTypeV1', 'OrganizationalObjectTypeV1', - 'NetBoxObjectTypeV1', + 'PrimaryObjectTypeV1', ) @@ -53,10 +56,26 @@ class ObjectTypeV1( pass +class PrimaryObjectTypeV1( + ChangelogMixin, + CustomFieldsMixin, + JournalEntriesMixin, + TagsMixin, + OwnerMixin, + BaseObjectTypeV1 +): + """ + Base GraphQL type for models which inherit from PrimaryModel. + """ + pass + + class OrganizationalObjectTypeV1( ChangelogMixin, CustomFieldsMixin, + JournalEntriesMixin, TagsMixin, + OwnerMixin, BaseObjectTypeV1 ): """ @@ -65,6 +84,20 @@ class OrganizationalObjectTypeV1( pass +class NestedGroupObjectTypeV1( + ChangelogMixin, + CustomFieldsMixin, + JournalEntriesMixin, + TagsMixin, + OwnerMixin, + BaseObjectTypeV1 +): + """ + Base GraphQL type for models which inherit from NestedGroupModel. + """ + pass + + class NetBoxObjectTypeV1( ChangelogMixin, CustomFieldsMixin, From a00b4cd03caa5912a549e15dc48c137fc55b1b54 Mon Sep 17 00:00:00 2001 From: Brian Tiemann Date: Fri, 24 Oct 2025 23:11:35 -0400 Subject: [PATCH 8/8] Incorporate Owner fields/types into V1 classes --- netbox/circuits/graphql/types_v1.py | 14 ++++--- netbox/core/graphql/types_v1.py | 5 +-- netbox/dcim/graphql/types_v1.py | 44 ++++++++++------------ netbox/extras/graphql/types_v1.py | 21 ++++++----- netbox/ipam/graphql/types_v1.py | 31 +++++++-------- netbox/netbox/graphql/types_v1.py | 46 +++++++++++------------ netbox/tenancy/graphql/types_v1.py | 8 ++-- netbox/users/graphql/filters_v1.py | 23 ++++++++++++ netbox/users/graphql/mixins_v1.py | 15 ++++++++ netbox/users/graphql/schema_v1.py | 6 +++ netbox/users/graphql/types_v1.py | 24 +++++++++++- netbox/virtualization/graphql/types_v1.py | 9 +++-- netbox/vpn/graphql/types_v1.py | 11 +++--- netbox/wireless/graphql/types_v1.py | 8 ++-- 14 files changed, 166 insertions(+), 99 deletions(-) create mode 100644 netbox/users/graphql/mixins_v1.py diff --git a/netbox/circuits/graphql/types_v1.py b/netbox/circuits/graphql/types_v1.py index 3e7669df6d..c9f9234dc9 100644 --- a/netbox/circuits/graphql/types_v1.py +++ b/netbox/circuits/graphql/types_v1.py @@ -6,7 +6,9 @@ from circuits import models from dcim.graphql.mixins_v1 import CabledObjectMixinV1 from extras.graphql.mixins_v1 import ContactsMixinV1, CustomFieldsMixinV1, TagsMixinV1 -from netbox.graphql.types_v1 import BaseObjectTypeV1, NetBoxObjectTypeV1, ObjectTypeV1, OrganizationalObjectTypeV1 +from netbox.graphql.types_v1 import ( + BaseObjectTypeV1, ObjectTypeV1, OrganizationalObjectTypeV1, PrimaryObjectTypeV1 +) from tenancy.graphql.types_v1 import TenantTypeV1 from .filters_v1 import * @@ -35,7 +37,7 @@ filters=ProviderFilterV1, pagination=True ) -class ProviderTypeV1(NetBoxObjectTypeV1, ContactsMixinV1): +class ProviderTypeV1(ContactsMixinV1, PrimaryObjectTypeV1): networks: List[Annotated["ProviderNetworkTypeV1", strawberry.lazy('circuits.graphql.types_v1')]] circuits: List[Annotated["CircuitTypeV1", strawberry.lazy('circuits.graphql.types_v1')]] @@ -49,7 +51,7 @@ class ProviderTypeV1(NetBoxObjectTypeV1, ContactsMixinV1): filters=ProviderAccountFilterV1, pagination=True ) -class ProviderAccountTypeV1(ContactsMixinV1, NetBoxObjectTypeV1): +class ProviderAccountTypeV1(ContactsMixinV1, PrimaryObjectTypeV1): provider: Annotated["ProviderTypeV1", strawberry.lazy('circuits.graphql.types_v1')] circuits: List[Annotated["CircuitTypeV1", strawberry.lazy('circuits.graphql.types_v1')]] @@ -61,7 +63,7 @@ class ProviderAccountTypeV1(ContactsMixinV1, NetBoxObjectTypeV1): filters=ProviderNetworkFilterV1, pagination=True ) -class ProviderNetworkTypeV1(NetBoxObjectTypeV1): +class ProviderNetworkTypeV1(PrimaryObjectTypeV1): provider: Annotated["ProviderTypeV1", strawberry.lazy('circuits.graphql.types_v1')] circuit_terminations: List[Annotated["CircuitTerminationTypeV1", strawberry.lazy('circuits.graphql.types_v1')]] @@ -105,7 +107,7 @@ class CircuitTypeTypeV1(OrganizationalObjectTypeV1): filters=CircuitFilterV1, pagination=True ) -class CircuitTypeV1(NetBoxObjectTypeV1, ContactsMixinV1): +class CircuitTypeV1(PrimaryObjectTypeV1, ContactsMixinV1): provider: ProviderTypeV1 provider_account: ProviderAccountTypeV1 | None termination_a: CircuitTerminationTypeV1 | None @@ -178,7 +180,7 @@ class VirtualCircuitTerminationTypeV1(CustomFieldsMixinV1, TagsMixinV1, ObjectTy filters=VirtualCircuitFilterV1, pagination=True ) -class VirtualCircuitTypeV1(NetBoxObjectTypeV1): +class VirtualCircuitTypeV1(PrimaryObjectTypeV1): provider_network: ProviderNetworkTypeV1 = strawberry_django.field(select_related=["provider_network"]) provider_account: ProviderAccountTypeV1 | None type: Annotated["VirtualCircuitTypeTypeV1", strawberry.lazy('circuits.graphql.types_v1')] = strawberry_django.field( diff --git a/netbox/core/graphql/types_v1.py b/netbox/core/graphql/types_v1.py index 67effeae4c..7dc8c0e3b0 100644 --- a/netbox/core/graphql/types_v1.py +++ b/netbox/core/graphql/types_v1.py @@ -5,7 +5,7 @@ from django.contrib.contenttypes.models import ContentType as DjangoContentType from core import models -from netbox.graphql.types_v1 import BaseObjectTypeV1, NetBoxObjectTypeV1 +from netbox.graphql.types_v1 import BaseObjectTypeV1, PrimaryObjectTypeV1 from .filters_v1 import * __all__ = ( @@ -32,8 +32,7 @@ class DataFileTypeV1(BaseObjectTypeV1): filters=DataSourceFilterV1, pagination=True ) -class DataSourceTypeV1(NetBoxObjectTypeV1): - +class DataSourceTypeV1(PrimaryObjectTypeV1): datafiles: List[Annotated["DataFileTypeV1", strawberry.lazy('core.graphql.types_v1')]] diff --git a/netbox/dcim/graphql/types_v1.py b/netbox/dcim/graphql/types_v1.py index 53f89087a2..ab0ba5f076 100644 --- a/netbox/dcim/graphql/types_v1.py +++ b/netbox/dcim/graphql/types_v1.py @@ -8,13 +8,14 @@ from extras.graphql.mixins_v1 import ( ConfigContextMixinV1, ContactsMixinV1, - CustomFieldsMixinV1, ImageAttachmentsMixinV1, - TagsMixinV1, ) from ipam.graphql.mixins_v1 import IPAddressesMixinV1, VLANGroupsMixinV1 from netbox.graphql.scalars import BigInt -from netbox.graphql.types_v1 import BaseObjectTypeV1, NetBoxObjectTypeV1, OrganizationalObjectTypeV1 +from netbox.graphql.types_v1 import ( + BaseObjectTypeV1, NetBoxObjectTypeV1, OrganizationalObjectTypeV1, PrimaryObjectTypeV1 +) +from users.graphql.mixins_v1 import OwnerMixinV1 from .filters_v1 import * from .mixins_v1 import CabledObjectMixinV1, PathEndpointMixinV1 @@ -91,12 +92,7 @@ @strawberry.type -class ComponentTypeV1( - ChangelogMixinV1, - CustomFieldsMixinV1, - TagsMixinV1, - BaseObjectTypeV1 -): +class ComponentTypeV1(OwnerMixinV1, NetBoxObjectTypeV1): """ Base type for device/VM components """ @@ -159,7 +155,7 @@ class CableTerminationTypeV1(NetBoxObjectTypeV1): filters=CableFilterV1, pagination=True ) -class CableTypeV1(NetBoxObjectTypeV1): +class CableTypeV1(PrimaryObjectTypeV1): color: str tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None @@ -236,7 +232,7 @@ class ConsoleServerPortTemplateTypeV1(ModularComponentTemplateTypeV1): filters=DeviceFilterV1, pagination=True ) -class DeviceTypeV1(ConfigContextMixinV1, ImageAttachmentsMixinV1, ContactsMixinV1, NetBoxObjectTypeV1): +class DeviceTypeV1(ConfigContextMixinV1, ImageAttachmentsMixinV1, ContactsMixinV1, PrimaryObjectTypeV1): console_port_count: BigInt console_server_port_count: BigInt power_port_count: BigInt @@ -355,7 +351,7 @@ class DeviceRoleTypeV1(OrganizationalObjectTypeV1): filters=DeviceTypeFilterV1, pagination=True ) -class DeviceTypeTypeV1(NetBoxObjectTypeV1): +class DeviceTypeTypeV1(PrimaryObjectTypeV1): console_port_template_count: BigInt console_server_port_template_count: BigInt power_port_template_count: BigInt @@ -414,7 +410,7 @@ class FrontPortTemplateTypeV1(ModularComponentTemplateTypeV1): filters=MACAddressFilterV1, pagination=True ) -class MACAddressTypeV1(NetBoxObjectTypeV1): +class MACAddressTypeV1(PrimaryObjectTypeV1): mac_address: str @strawberry_django.field @@ -557,7 +553,7 @@ class ManufacturerTypeV1(OrganizationalObjectTypeV1, ContactsMixinV1): filters=ModuleFilterV1, pagination=True ) -class ModuleTypeV1(NetBoxObjectTypeV1): +class ModuleTypeV1(PrimaryObjectTypeV1): device: Annotated["DeviceTypeV1", strawberry.lazy('dcim.graphql.types_v1')] module_bay: Annotated["ModuleBayTypeV1", strawberry.lazy('dcim.graphql.types_v1')] module_type: Annotated["ModuleTypeTypeV1", strawberry.lazy('dcim.graphql.types_v1')] @@ -604,7 +600,7 @@ class ModuleBayTemplateTypeV1(ModularComponentTemplateTypeV1): filters=ModuleTypeProfileFilterV1, pagination=True ) -class ModuleTypeProfileTypeV1(NetBoxObjectTypeV1): +class ModuleTypeProfileTypeV1(PrimaryObjectTypeV1): module_types: List[Annotated["ModuleTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] @@ -614,7 +610,7 @@ class ModuleTypeProfileTypeV1(NetBoxObjectTypeV1): filters=ModuleTypeFilterV1, pagination=True ) -class ModuleTypeTypeV1(NetBoxObjectTypeV1): +class ModuleTypeTypeV1(PrimaryObjectTypeV1): profile: Annotated["ModuleTypeProfileTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None manufacturer: Annotated["ManufacturerTypeV1", strawberry.lazy('dcim.graphql.types_v1')] @@ -652,7 +648,7 @@ class PlatformTypeV1(OrganizationalObjectTypeV1): filters=PowerFeedFilterV1, pagination=True ) -class PowerFeedTypeV1(NetBoxObjectTypeV1, CabledObjectMixinV1, PathEndpointMixinV1): +class PowerFeedTypeV1(CabledObjectMixinV1, PathEndpointMixinV1, PrimaryObjectTypeV1): power_panel: Annotated["PowerPanelTypeV1", strawberry.lazy('dcim.graphql.types_v1')] rack: Annotated["RackTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None @@ -686,7 +682,7 @@ class PowerOutletTemplateTypeV1(ModularComponentTemplateTypeV1): filters=PowerPanelFilterV1, pagination=True ) -class PowerPanelTypeV1(NetBoxObjectTypeV1, ContactsMixinV1): +class PowerPanelTypeV1(ContactsMixinV1, PrimaryObjectTypeV1): site: Annotated["SiteTypeV1", strawberry.lazy('dcim.graphql.types_v1')] location: Annotated["LocationTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None @@ -720,7 +716,7 @@ class PowerPortTemplateTypeV1(ModularComponentTemplateTypeV1): filters=RackTypeFilterV1, pagination=True ) -class RackTypeTypeV1(NetBoxObjectTypeV1): +class RackTypeTypeV1(PrimaryObjectTypeV1): manufacturer: Annotated["ManufacturerTypeV1", strawberry.lazy('dcim.graphql.types_v1')] @@ -730,7 +726,7 @@ class RackTypeTypeV1(NetBoxObjectTypeV1): filters=RackFilterV1, pagination=True ) -class RackTypeV1(VLANGroupsMixinV1, ImageAttachmentsMixinV1, ContactsMixinV1, NetBoxObjectTypeV1): +class RackTypeV1(VLANGroupsMixinV1, ImageAttachmentsMixinV1, ContactsMixinV1, PrimaryObjectTypeV1): site: Annotated["SiteTypeV1", strawberry.lazy('dcim.graphql.types_v1')] location: Annotated["LocationTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None @@ -749,7 +745,7 @@ class RackTypeV1(VLANGroupsMixinV1, ImageAttachmentsMixinV1, ContactsMixinV1, Ne filters=RackReservationFilterV1, pagination=True ) -class RackReservationTypeV1(NetBoxObjectTypeV1): +class RackReservationTypeV1(PrimaryObjectTypeV1): units: List[int] rack: Annotated["RackTypeV1", strawberry.lazy('dcim.graphql.types_v1')] tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None @@ -824,7 +820,7 @@ def circuit_terminations(self) -> List[ filters=SiteFilterV1, pagination=True ) -class SiteTypeV1(VLANGroupsMixinV1, ImageAttachmentsMixinV1, ContactsMixinV1, NetBoxObjectTypeV1): +class SiteTypeV1(VLANGroupsMixinV1, ImageAttachmentsMixinV1, ContactsMixinV1, PrimaryObjectTypeV1): time_zone: str | None region: Annotated["RegionTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None group: Annotated["SiteGroupTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None @@ -885,7 +881,7 @@ def circuit_terminations(self) -> List[ filters=VirtualChassisFilterV1, pagination=True ) -class VirtualChassisTypeV1(NetBoxObjectTypeV1): +class VirtualChassisTypeV1(PrimaryObjectTypeV1): member_count: BigInt master: Annotated["DeviceTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None @@ -898,7 +894,7 @@ class VirtualChassisTypeV1(NetBoxObjectTypeV1): filters=VirtualDeviceContextFilterV1, pagination=True ) -class VirtualDeviceContextTypeV1(NetBoxObjectTypeV1): +class VirtualDeviceContextTypeV1(PrimaryObjectTypeV1): device: Annotated["DeviceTypeV1", strawberry.lazy('dcim.graphql.types_v1')] | None primary_ip4: Annotated["IPAddressTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None primary_ip6: Annotated["IPAddressTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None diff --git a/netbox/extras/graphql/types_v1.py b/netbox/extras/graphql/types_v1.py index d51b57e885..1693fe1da4 100644 --- a/netbox/extras/graphql/types_v1.py +++ b/netbox/extras/graphql/types_v1.py @@ -7,8 +7,9 @@ from extras import models from extras.graphql.mixins_v1 import CustomFieldsMixinV1, TagsMixinV1 from netbox.graphql.types_v1 import ( - BaseObjectTypeV1, ContentTypeTypeV1, NetBoxObjectTypeV1, ObjectTypeV1, OrganizationalObjectTypeV1 + BaseObjectTypeV1, ContentTypeTypeV1, ObjectTypeV1, OrganizationalObjectTypeV1, PrimaryObjectTypeV1 ) +from users.graphql.mixins_v1 import OwnerMixinV1 from .filters_v1 import * if TYPE_CHECKING: @@ -55,7 +56,7 @@ filters=ConfigContextProfileFilterV1, pagination=True ) -class ConfigContextProfileTypeV1(SyncedDataMixinV1, NetBoxObjectTypeV1): +class ConfigContextProfileTypeV1(SyncedDataMixinV1, PrimaryObjectTypeV1): pass @@ -65,7 +66,7 @@ class ConfigContextProfileTypeV1(SyncedDataMixinV1, NetBoxObjectTypeV1): filters=ConfigContextFilterV1, pagination=True ) -class ConfigContextTypeV1(SyncedDataMixinV1, ObjectTypeV1): +class ConfigContextTypeV1(SyncedDataMixinV1, OwnerMixinV1, ObjectTypeV1): profile: ConfigContextProfileTypeV1 | None roles: List[Annotated["DeviceRoleTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] device_types: List[Annotated["DeviceTypeTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] @@ -88,7 +89,7 @@ class ConfigContextTypeV1(SyncedDataMixinV1, ObjectTypeV1): filters=ConfigTemplateFilterV1, pagination=True ) -class ConfigTemplateTypeV1(SyncedDataMixinV1, TagsMixinV1, ObjectTypeV1): +class ConfigTemplateTypeV1(SyncedDataMixinV1, OwnerMixinV1, TagsMixinV1, ObjectTypeV1): virtualmachines: List[Annotated["VirtualMachineTypeV1", strawberry.lazy('virtualization.graphql.types_v1')]] devices: List[Annotated["DeviceTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] platforms: List[Annotated["PlatformTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] @@ -101,7 +102,7 @@ class ConfigTemplateTypeV1(SyncedDataMixinV1, TagsMixinV1, ObjectTypeV1): filters=CustomFieldFilterV1, pagination=True ) -class CustomFieldTypeV1(ObjectTypeV1): +class CustomFieldTypeV1(OwnerMixinV1, ObjectTypeV1): related_object_type: Annotated["ContentTypeTypeV1", strawberry.lazy('netbox.graphql.types_v1')] | None choice_set: Annotated["CustomFieldChoiceSetTypeV1", strawberry.lazy('extras.graphql.types_v1')] | None @@ -112,7 +113,7 @@ class CustomFieldTypeV1(ObjectTypeV1): filters=CustomFieldChoiceSetFilterV1, pagination=True ) -class CustomFieldChoiceSetTypeV1(ObjectTypeV1): +class CustomFieldChoiceSetTypeV1(OwnerMixinV1, ObjectTypeV1): choices_for: List[Annotated["CustomFieldTypeV1", strawberry.lazy('extras.graphql.types_v1')]] extra_choices: List[List[str]] | None @@ -124,7 +125,7 @@ class CustomFieldChoiceSetTypeV1(ObjectTypeV1): filters=CustomLinkFilterV1, pagination=True ) -class CustomLinkTypeV1(ObjectTypeV1): +class CustomLinkTypeV1(OwnerMixinV1, ObjectTypeV1): pass @@ -134,7 +135,7 @@ class CustomLinkTypeV1(ObjectTypeV1): filters=ExportTemplateFilterV1, pagination=True ) -class ExportTemplateTypeV1(SyncedDataMixinV1, ObjectTypeV1): +class ExportTemplateTypeV1(SyncedDataMixinV1, OwnerMixinV1, ObjectTypeV1): pass @@ -184,7 +185,7 @@ class NotificationGroupTypeV1(ObjectTypeV1): filters=SavedFilterFilterV1, pagination=True ) -class SavedFilterTypeV1(ObjectTypeV1): +class SavedFilterTypeV1(OwnerMixinV1, ObjectTypeV1): user: Annotated["UserTypeV1", strawberry.lazy('users.graphql.types_v1')] | None @@ -213,7 +214,7 @@ class TableConfigTypeV1(ObjectTypeV1): filters=TagFilterV1, pagination=True ) -class TagTypeV1(ObjectTypeV1): +class TagTypeV1(OwnerMixinV1, ObjectTypeV1): color: str object_types: List[ContentTypeTypeV1] diff --git a/netbox/ipam/graphql/types_v1.py b/netbox/ipam/graphql/types_v1.py index 7b5d2c6522..091a2f2150 100644 --- a/netbox/ipam/graphql/types_v1.py +++ b/netbox/ipam/graphql/types_v1.py @@ -8,7 +8,9 @@ from extras.graphql.mixins_v1 import ContactsMixinV1 from ipam import models from netbox.graphql.scalars import BigInt -from netbox.graphql.types_v1 import BaseObjectTypeV1, NetBoxObjectTypeV1, OrganizationalObjectTypeV1 +from netbox.graphql.types_v1 import ( + BaseObjectTypeV1, NetBoxObjectTypeV1, OrganizationalObjectTypeV1, PrimaryObjectTypeV1 +) from .filters_v1 import * from .mixins_v1 import IPAddressesMixinV1 @@ -76,7 +78,7 @@ def family(self) -> IPAddressFamilyTypeV1: filters=ASNFilterV1, pagination=True ) -class ASNTypeV1(NetBoxObjectTypeV1, ContactsMixinV1): +class ASNTypeV1(ContactsMixinV1, PrimaryObjectTypeV1): asn: BigInt rir: Annotated["RIRTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None @@ -91,7 +93,7 @@ class ASNTypeV1(NetBoxObjectTypeV1, ContactsMixinV1): filters=ASNRangeFilterV1, pagination=True ) -class ASNRangeTypeV1(NetBoxObjectTypeV1): +class ASNRangeTypeV1(OrganizationalObjectTypeV1): start: BigInt end: BigInt rir: Annotated["RIRTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None @@ -104,7 +106,7 @@ class ASNRangeTypeV1(NetBoxObjectTypeV1): filters=AggregateFilterV1, pagination=True ) -class AggregateTypeV1(NetBoxObjectTypeV1, ContactsMixinV1, BaseIPAddressFamilyTypeV1): +class AggregateTypeV1(ContactsMixinV1, BaseIPAddressFamilyTypeV1, PrimaryObjectTypeV1): prefix: str rir: Annotated["RIRTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None @@ -116,8 +118,7 @@ class AggregateTypeV1(NetBoxObjectTypeV1, ContactsMixinV1, BaseIPAddressFamilyTy filters=FHRPGroupFilterV1, pagination=True ) -class FHRPGroupTypeV1(NetBoxObjectTypeV1, IPAddressesMixinV1): - +class FHRPGroupTypeV1(IPAddressesMixinV1, PrimaryObjectTypeV1): fhrpgroupassignment_set: List[Annotated["FHRPGroupAssignmentTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] @@ -144,7 +145,7 @@ def interface(self) -> Annotated[Union[ filters=IPAddressFilterV1, pagination=True ) -class IPAddressTypeV1(NetBoxObjectTypeV1, ContactsMixinV1, BaseIPAddressFamilyTypeV1): +class IPAddressTypeV1(ContactsMixinV1, BaseIPAddressFamilyTypeV1, PrimaryObjectTypeV1): address: str vrf: Annotated["VRFTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None @@ -169,7 +170,7 @@ def assigned_object(self) -> Annotated[Union[ filters=IPRangeFilterV1, pagination=True ) -class IPRangeTypeV1(NetBoxObjectTypeV1, ContactsMixinV1): +class IPRangeTypeV1(ContactsMixinV1, PrimaryObjectTypeV1): start_address: str end_address: str vrf: Annotated["VRFTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None @@ -183,7 +184,7 @@ class IPRangeTypeV1(NetBoxObjectTypeV1, ContactsMixinV1): filters=PrefixFilterV1, pagination=True ) -class PrefixTypeV1(NetBoxObjectTypeV1, ContactsMixinV1, BaseIPAddressFamilyTypeV1): +class PrefixTypeV1(ContactsMixinV1, BaseIPAddressFamilyTypeV1, PrimaryObjectTypeV1): prefix: str vrf: Annotated["VRFTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None @@ -232,7 +233,7 @@ class RoleTypeV1(OrganizationalObjectTypeV1): filters=RouteTargetFilterV1, pagination=True ) -class RouteTargetTypeV1(NetBoxObjectTypeV1): +class RouteTargetTypeV1(PrimaryObjectTypeV1): tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None importing_l2vpns: List[Annotated["L2VPNTypeV1", strawberry.lazy('vpn.graphql.types_v1')]] @@ -247,7 +248,7 @@ class RouteTargetTypeV1(NetBoxObjectTypeV1): filters=ServiceFilterV1, pagination=True ) -class ServiceTypeV1(NetBoxObjectTypeV1, ContactsMixinV1): +class ServiceTypeV1(ContactsMixinV1, PrimaryObjectTypeV1): ports: List[int] ipaddresses: List[Annotated["IPAddressTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] @@ -266,7 +267,7 @@ def parent(self) -> Annotated[Union[ filters=ServiceTemplateFilterV1, pagination=True ) -class ServiceTemplateTypeV1(NetBoxObjectTypeV1): +class ServiceTemplateTypeV1(PrimaryObjectTypeV1): ports: List[int] @@ -276,7 +277,7 @@ class ServiceTemplateTypeV1(NetBoxObjectTypeV1): filters=VLANFilterV1, pagination=True ) -class VLANTypeV1(NetBoxObjectTypeV1): +class VLANTypeV1(PrimaryObjectTypeV1): site: Annotated["SiteTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None group: Annotated["VLANGroupTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None @@ -325,7 +326,7 @@ def scope(self) -> Annotated[Union[ filters=VLANTranslationPolicyFilterV1, pagination=True ) -class VLANTranslationPolicyTypeV1(NetBoxObjectTypeV1): +class VLANTranslationPolicyTypeV1(PrimaryObjectTypeV1): rules: List[Annotated["VLANTranslationRuleTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] @@ -348,7 +349,7 @@ class VLANTranslationRuleTypeV1(NetBoxObjectTypeV1): filters=VRFFilterV1, pagination=True ) -class VRFTypeV1(NetBoxObjectTypeV1): +class VRFTypeV1(PrimaryObjectTypeV1): tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None interfaces: List[Annotated["InterfaceTypeV1", strawberry.lazy('dcim.graphql.types_v1')]] diff --git a/netbox/netbox/graphql/types_v1.py b/netbox/netbox/graphql/types_v1.py index 66a3ac9051..5fc776d8d8 100644 --- a/netbox/netbox/graphql/types_v1.py +++ b/netbox/netbox/graphql/types_v1.py @@ -3,10 +3,10 @@ from strawberry.types import Info from django.contrib.contenttypes.models import ContentType -from core.graphql.mixins import ChangelogMixin +from core.graphql.mixins_v1 import ChangelogMixinV1 from core.models import ObjectType as ObjectType_ -from extras.graphql.mixins import CustomFieldsMixin, JournalEntriesMixin, TagsMixin -from users.graphql.mixins import OwnerMixin +from extras.graphql.mixins_v1 import CustomFieldsMixinV1, JournalEntriesMixinV1, TagsMixinV1 +from users.graphql.mixins_v1 import OwnerMixinV1 __all__ = ( 'BaseObjectTypeV1', @@ -47,7 +47,7 @@ def class_type(self) -> str: class ObjectTypeV1( - ChangelogMixin, + ChangelogMixinV1, BaseObjectTypeV1 ): """ @@ -57,11 +57,11 @@ class ObjectTypeV1( class PrimaryObjectTypeV1( - ChangelogMixin, - CustomFieldsMixin, - JournalEntriesMixin, - TagsMixin, - OwnerMixin, + ChangelogMixinV1, + CustomFieldsMixinV1, + JournalEntriesMixinV1, + TagsMixinV1, + OwnerMixinV1, BaseObjectTypeV1 ): """ @@ -71,11 +71,11 @@ class PrimaryObjectTypeV1( class OrganizationalObjectTypeV1( - ChangelogMixin, - CustomFieldsMixin, - JournalEntriesMixin, - TagsMixin, - OwnerMixin, + ChangelogMixinV1, + CustomFieldsMixinV1, + JournalEntriesMixinV1, + TagsMixinV1, + OwnerMixinV1, BaseObjectTypeV1 ): """ @@ -85,11 +85,11 @@ class OrganizationalObjectTypeV1( class NestedGroupObjectTypeV1( - ChangelogMixin, - CustomFieldsMixin, - JournalEntriesMixin, - TagsMixin, - OwnerMixin, + ChangelogMixinV1, + CustomFieldsMixinV1, + JournalEntriesMixinV1, + TagsMixinV1, + OwnerMixinV1, BaseObjectTypeV1 ): """ @@ -99,10 +99,10 @@ class NestedGroupObjectTypeV1( class NetBoxObjectTypeV1( - ChangelogMixin, - CustomFieldsMixin, - JournalEntriesMixin, - TagsMixin, + ChangelogMixinV1, + CustomFieldsMixinV1, + JournalEntriesMixinV1, + TagsMixinV1, BaseObjectTypeV1 ): """ diff --git a/netbox/tenancy/graphql/types_v1.py b/netbox/tenancy/graphql/types_v1.py index cc4b774bc0..82e7d7610d 100644 --- a/netbox/tenancy/graphql/types_v1.py +++ b/netbox/tenancy/graphql/types_v1.py @@ -4,7 +4,9 @@ import strawberry_django from extras.graphql.mixins_v1 import CustomFieldsMixinV1, TagsMixinV1, ContactsMixinV1 -from netbox.graphql.types_v1 import BaseObjectTypeV1, OrganizationalObjectTypeV1, NetBoxObjectTypeV1 +from netbox.graphql.types_v1 import ( + BaseObjectTypeV1, OrganizationalObjectTypeV1, PrimaryObjectTypeV1 +) from tenancy import models from .filters_v1 import * from .mixins_v1 import ContactAssignmentsMixinV1 @@ -57,7 +59,7 @@ filters=TenantFilterV1, pagination=True ) -class TenantTypeV1(ContactsMixinV1, NetBoxObjectTypeV1): +class TenantTypeV1(ContactsMixinV1, PrimaryObjectTypeV1): group: Annotated['TenantGroupTypeV1', strawberry.lazy('tenancy.graphql.types_v1')] | None asns: List[Annotated['ASNTypeV1', strawberry.lazy('ipam.graphql.types_v1')]] circuits: List[Annotated['CircuitTypeV1', strawberry.lazy('circuits.graphql.types_v1')]] @@ -108,7 +110,7 @@ class TenantGroupTypeV1(OrganizationalObjectTypeV1): filters=ContactFilterV1, pagination=True ) -class ContactTypeV1(ContactAssignmentsMixinV1, NetBoxObjectTypeV1): +class ContactTypeV1(ContactAssignmentsMixinV1, PrimaryObjectTypeV1): groups: List[Annotated['ContactGroupTypeV1', strawberry.lazy('tenancy.graphql.types_v1')]] diff --git a/netbox/users/graphql/filters_v1.py b/netbox/users/graphql/filters_v1.py index 1b08ed6fc9..951c666ae5 100644 --- a/netbox/users/graphql/filters_v1.py +++ b/netbox/users/graphql/filters_v1.py @@ -10,6 +10,8 @@ __all__ = ( 'GroupFilterV1', + 'OwnerFilterV1', + 'OwnerGroupFilterV1', 'UserFilterV1', ) @@ -32,3 +34,24 @@ class UserFilterV1(BaseObjectTypeFilterMixinV1): last_login: DatetimeFilterLookup[datetime] | None = strawberry_django.filter_field() groups: Annotated['GroupFilterV1', strawberry.lazy('users.graphql.filters_v1')] | None = ( strawberry_django.filter_field()) + + +@strawberry_django.filter_type(models.Owner, lookups=True) +class OwnerFilterV1(BaseObjectTypeFilterMixinV1): + name: FilterLookup[str] | None = strawberry_django.filter_field() + description: FilterLookup[str] | None = strawberry_django.filter_field() + group: Annotated['OwnerGroupFilterV1', strawberry.lazy('users.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + user_groups: Annotated['GroupFilterV1', strawberry.lazy('users.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + users: Annotated['UserFilterV1', strawberry.lazy('users.graphql.filters_v1')] | None = ( + strawberry_django.filter_field() + ) + + +@strawberry_django.filter_type(models.OwnerGroup, lookups=True) +class OwnerGroupFilterV1(BaseObjectTypeFilterMixinV1): + name: FilterLookup[str] | None = strawberry_django.filter_field() + description: FilterLookup[str] | None = strawberry_django.filter_field() diff --git a/netbox/users/graphql/mixins_v1.py b/netbox/users/graphql/mixins_v1.py new file mode 100644 index 0000000000..b2fb22e6df --- /dev/null +++ b/netbox/users/graphql/mixins_v1.py @@ -0,0 +1,15 @@ +from typing import Annotated, TYPE_CHECKING + +import strawberry + +if TYPE_CHECKING: + from users.graphql.types_v1 import OwnerTypeV1 + +__all__ = ( + 'OwnerMixinV1', +) + + +@strawberry.type +class OwnerMixinV1: + owner: Annotated['OwnerTypeV1', strawberry.lazy('users.graphql.types_v1')] | None diff --git a/netbox/users/graphql/schema_v1.py b/netbox/users/graphql/schema_v1.py index 69c3b9d57a..b5389f35e0 100644 --- a/netbox/users/graphql/schema_v1.py +++ b/netbox/users/graphql/schema_v1.py @@ -13,3 +13,9 @@ class UsersQueryV1: user: UserTypeV1 = strawberry_django.field() user_list: List[UserTypeV1] = strawberry_django.field() + + owner_group: OwnerGroupTypeV1 = strawberry_django.field() + owner_group_list: List[OwnerGroupTypeV1] = strawberry_django.field() + + owner: OwnerTypeV1 = strawberry_django.field() + owner_list: List[OwnerTypeV1] = strawberry_django.field() diff --git a/netbox/users/graphql/types_v1.py b/netbox/users/graphql/types_v1.py index 3b48431d08..16b0aecde9 100644 --- a/netbox/users/graphql/types_v1.py +++ b/netbox/users/graphql/types_v1.py @@ -3,11 +3,13 @@ import strawberry_django from netbox.graphql.types_v1 import BaseObjectTypeV1 -from users.models import Group, User +from users.models import Group, Owner, OwnerGroup, User from .filters_v1 import * __all__ = ( 'GroupTypeV1', + 'OwnerGroupTypeV1', + 'OwnerTypeV1', 'UserTypeV1', ) @@ -32,3 +34,23 @@ class GroupTypeV1(BaseObjectTypeV1): ) class UserTypeV1(BaseObjectTypeV1): groups: List[GroupTypeV1] + + +@strawberry_django.type( + OwnerGroup, + fields=['id', 'name', 'description'], + filters=OwnerGroupFilterV1, + pagination=True +) +class OwnerGroupTypeV1(BaseObjectTypeV1): + pass + + +@strawberry_django.type( + Owner, + fields=['id', 'group', 'name', 'description', 'user_groups', 'users'], + filters=OwnerFilterV1, + pagination=True +) +class OwnerTypeV1(BaseObjectTypeV1): + group: OwnerGroupTypeV1 | None diff --git a/netbox/virtualization/graphql/types_v1.py b/netbox/virtualization/graphql/types_v1.py index 079fa7b29a..ba6add3cb1 100644 --- a/netbox/virtualization/graphql/types_v1.py +++ b/netbox/virtualization/graphql/types_v1.py @@ -6,7 +6,8 @@ from extras.graphql.mixins_v1 import ConfigContextMixinV1, ContactsMixinV1 from ipam.graphql.mixins_v1 import IPAddressesMixinV1, VLANGroupsMixinV1 from netbox.graphql.scalars import BigInt -from netbox.graphql.types_v1 import OrganizationalObjectTypeV1, NetBoxObjectTypeV1 +from netbox.graphql.types_v1 import OrganizationalObjectTypeV1, NetBoxObjectTypeV1, PrimaryObjectTypeV1 +from users.graphql.mixins_v1 import OwnerMixinV1 from virtualization import models from .filters_v1 import * @@ -36,7 +37,7 @@ @strawberry.type -class ComponentTypeV1(NetBoxObjectTypeV1): +class ComponentTypeV1(OwnerMixinV1, NetBoxObjectTypeV1): """ Base type for device/VM components """ @@ -49,7 +50,7 @@ class ComponentTypeV1(NetBoxObjectTypeV1): filters=ClusterFilterV1, pagination=True ) -class ClusterTypeV1(ContactsMixinV1, VLANGroupsMixinV1, NetBoxObjectTypeV1): +class ClusterTypeV1(ContactsMixinV1, VLANGroupsMixinV1, PrimaryObjectTypeV1): type: Annotated["ClusterTypeTypeV1", strawberry.lazy('virtualization.graphql.types_v1')] | None group: Annotated["ClusterGroupTypeV1", strawberry.lazy('virtualization.graphql.types_v1')] | None tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None @@ -94,7 +95,7 @@ class ClusterTypeTypeV1(OrganizationalObjectTypeV1): filters=VirtualMachineFilterV1, pagination=True ) -class VirtualMachineTypeV1(ConfigContextMixinV1, ContactsMixinV1, NetBoxObjectTypeV1): +class VirtualMachineTypeV1(ConfigContextMixinV1, ContactsMixinV1, PrimaryObjectTypeV1): interface_count: BigInt virtual_disk_count: BigInt interface_count: BigInt diff --git a/netbox/vpn/graphql/types_v1.py b/netbox/vpn/graphql/types_v1.py index 7812f88bbf..6872cf6e2e 100644 --- a/netbox/vpn/graphql/types_v1.py +++ b/netbox/vpn/graphql/types_v1.py @@ -4,7 +4,7 @@ import strawberry_django from extras.graphql.mixins_v1 import ContactsMixinV1, CustomFieldsMixinV1, TagsMixinV1 -from netbox.graphql.types_v1 import ObjectTypeV1, OrganizationalObjectTypeV1, NetBoxObjectTypeV1 +from netbox.graphql.types_v1 import ObjectTypeV1, OrganizationalObjectTypeV1, NetBoxObjectTypeV1, PrimaryObjectTypeV1 from vpn import models from .filters_v1 import * @@ -58,7 +58,7 @@ class TunnelTerminationTypeV1(CustomFieldsMixinV1, TagsMixinV1, ObjectTypeV1): filters=TunnelFilterV1, pagination=True ) -class TunnelTypeV1(ContactsMixinV1, NetBoxObjectTypeV1): +class TunnelTypeV1(ContactsMixinV1, PrimaryObjectTypeV1): group: Annotated["TunnelGroupTypeV1", strawberry.lazy('vpn.graphql.types_v1')] | None ipsec_profile: Annotated["IPSecProfileTypeV1", strawberry.lazy('vpn.graphql.types_v1')] | None tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None @@ -72,8 +72,7 @@ class TunnelTypeV1(ContactsMixinV1, NetBoxObjectTypeV1): filters=IKEProposalFilterV1, pagination=True ) -class IKEProposalTypeV1(OrganizationalObjectTypeV1): - +class IKEProposalTypeV1(PrimaryObjectTypeV1): ike_policies: List[Annotated["IKEPolicyTypeV1", strawberry.lazy('vpn.graphql.types_v1')]] @@ -95,7 +94,7 @@ class IKEPolicyTypeV1(OrganizationalObjectTypeV1): filters=IPSecProposalFilterV1, pagination=True ) -class IPSecProposalTypeV1(OrganizationalObjectTypeV1): +class IPSecProposalTypeV1(PrimaryObjectTypeV1): ipsec_policies: List[Annotated["IPSecPolicyTypeV1", strawberry.lazy('vpn.graphql.types_v1')]] @@ -131,7 +130,7 @@ class IPSecProfileTypeV1(OrganizationalObjectTypeV1): filters=L2VPNFilterV1, pagination=True ) -class L2VPNTypeV1(ContactsMixinV1, NetBoxObjectTypeV1): +class L2VPNTypeV1(ContactsMixinV1, PrimaryObjectTypeV1): tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None export_targets: List[Annotated["RouteTargetTypeV1", strawberry.lazy('ipam.graphql.types_v1')]] diff --git a/netbox/wireless/graphql/types_v1.py b/netbox/wireless/graphql/types_v1.py index b774f8f28c..2c0fbe12ff 100644 --- a/netbox/wireless/graphql/types_v1.py +++ b/netbox/wireless/graphql/types_v1.py @@ -3,7 +3,7 @@ import strawberry import strawberry_django -from netbox.graphql.types_v1 import OrganizationalObjectTypeV1, NetBoxObjectTypeV1 +from netbox.graphql.types_v1 import PrimaryObjectTypeV1, NestedGroupObjectTypeV1 from wireless import models from .filters_v1 import * @@ -27,7 +27,7 @@ filters=WirelessLANGroupFilterV1, pagination=True ) -class WirelessLANGroupTypeV1(OrganizationalObjectTypeV1): +class WirelessLANGroupTypeV1(NestedGroupObjectTypeV1): parent: Annotated["WirelessLANGroupTypeV1", strawberry.lazy('wireless.graphql.types_v1')] | None wireless_lans: List[Annotated["WirelessLANTypeV1", strawberry.lazy('wireless.graphql.types_v1')]] @@ -40,7 +40,7 @@ class WirelessLANGroupTypeV1(OrganizationalObjectTypeV1): filters=WirelessLANFilterV1, pagination=True ) -class WirelessLANTypeV1(NetBoxObjectTypeV1): +class WirelessLANTypeV1(PrimaryObjectTypeV1): group: Annotated["WirelessLANGroupTypeV1", strawberry.lazy('wireless.graphql.types_v1')] | None vlan: Annotated["VLANTypeV1", strawberry.lazy('ipam.graphql.types_v1')] | None tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None @@ -63,7 +63,7 @@ def scope(self) -> Annotated[Union[ filters=WirelessLinkFilterV1, pagination=True ) -class WirelessLinkTypeV1(NetBoxObjectTypeV1): +class WirelessLinkTypeV1(PrimaryObjectTypeV1): interface_a: Annotated["InterfaceTypeV1", strawberry.lazy('dcim.graphql.types_v1')] interface_b: Annotated["InterfaceTypeV1", strawberry.lazy('dcim.graphql.types_v1')] tenant: Annotated["TenantTypeV1", strawberry.lazy('tenancy.graphql.types_v1')] | None