Closes #7598: GraphQL Filter Redesign

This commit is contained in:
Jeremy Sanders 2025-01-07 13:58:43 -06:00
parent b913661297
commit 999cae939e
34 changed files with 4490 additions and 623 deletions

View File

@ -0,0 +1,86 @@
from enum import Enum
import strawberry
__all__ = [
'CircuitStatusEnum',
'CircuitCommitRateEnum',
'CircuitTerminationSideEnum',
'CircuitTerminationPortSpeedEnum',
'CircuitPriorityEnum',
'VirtualCircuitTerminationRoleEnum',
]
#
# Circuits
#
@strawberry.enum
class CircuitStatusEnum(Enum):
STATUS_DEPROVISIONING = 'deprovisioning'
STATUS_ACTIVE = 'active'
STATUS_PLANNED = 'planned'
STATUS_PROVISIONING = 'provisioning'
STATUS_OFFLINE = 'offline'
STATUS_DECOMMISSIONED = 'decommissioned'
@strawberry.enum
class CircuitCommitRateEnum(Enum):
TEN_MBPS = 10000
HUNDRED_MBPS = 100000
ONE_GBPS = 1000000
TEN_GBPS = 10000000
TWENTY_FIVE_GBPS = 25000000
FORTY_GBPS = 40000000
HUNDRED_GBPS = 100000000
TWO_HUNDRED_GBPS = 200000000
FOUR_HUNDRED_GBPS = 400000000
T1 = 1544
E1 = 2048
#
# CircuitTerminations
#
@strawberry.enum
class CircuitTerminationSideEnum(Enum):
SIDE_A = 'A'
SIDE_Z = 'Z'
@strawberry.enum
class CircuitTerminationPortSpeedEnum(Enum):
TEN_MBPS = 10000
HUNDRED_MBPS = 100000
ONE_GBPS = 1000000
TEN_GBPS = 10000000
TWENTY_FIVE_GBPS = 25000000
FORTY_GBPS = 40000000
HUNDRED_GBPS = 100000000
TWO_HUNDRED_GBPS = 200000000
FOUR_HUNDRED_GBPS = 400000000
T1 = 1544
E1 = 2048
@strawberry.enum
class CircuitPriorityEnum(Enum):
PRIORITY_PRIMARY = 'primary'
PRIORITY_SECONDARY = 'secondary'
PRIORITY_TERTIARY = 'tertiary'
PRIORITY_INACTIVE = 'inactive'
#
# Virtual circuits
#
@strawberry.enum
class VirtualCircuitTerminationRoleEnum(Enum):
ROLE_PEER = 'peer'
ROLE_HUB = 'hub'
ROLE_SPOKE = 'spoke'

View File

@ -0,0 +1,17 @@
from dataclasses import dataclass
from typing import Annotated, TYPE_CHECKING
import strawberry
import strawberry_django
from netbox.graphql.filter_mixins import OrganizationalModelFilterMixin
if TYPE_CHECKING:
from .filters import *
from core.graphql.filter_lookups import *
from netbox.graphql.enums import *
__all__ = ['BaseCircuitTypeFilterMixin']
@dataclass
class BaseCircuitTypeFilterMixin(OrganizationalModelFilterMixin):
color: Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')] | None = strawberry_django.filter_field()

View File

@ -1,7 +1,33 @@
from datetime import date
from typing import Annotated, TYPE_CHECKING
import strawberry
from strawberry.scalars import ID
import strawberry_django
from strawberry_django import FilterLookup, DateFilterLookup
from extras.graphql.filter_mixins import *
from netbox.graphql.filter_mixins import *
from core.graphql.filter_mixins import *
from tenancy.graphql.filter_mixins import *
from dcim.graphql.filter_mixins import *
from .filter_mixins import *
from circuits import filtersets, models
from netbox.graphql.filter_mixins import autotype_decorator, BaseFilterMixin
from circuits import models
if TYPE_CHECKING:
from .enums import *
from netbox.graphql.enums import *
from wireless.graphql.enums import *
from core.graphql.filter_lookups import *
from core.graphql.filters import *
from extras.graphql.filters import *
from circuits.graphql.filters import *
from dcim.graphql.filters import *
from ipam.graphql.filters import *
from tenancy.graphql.filters import *
from wireless.graphql.filters import *
from users.graphql.filters import *
from virtualization.graphql.filters import *
from vpn.graphql.filters import *
__all__ = (
'CircuitFilter',
@ -19,66 +45,165 @@ __all__ = (
@strawberry_django.filter(models.CircuitTermination, lookups=True)
@autotype_decorator(filtersets.CircuitTerminationFilterSet)
class CircuitTerminationFilter(BaseFilterMixin):
pass
class CircuitTerminationFilter(
BaseObjectTypeFilterMixin,
CustomFieldsFilterMixin,
TagsFilterMixin,
ChangeLogFilterMixin,
CabledObjectModelFilterMixin,
):
circuit: Annotated['CircuitFilter', strawberry.lazy('circuits.graphql.filters')] | None = (
strawberry_django.filter_field()
)
term_side: Annotated['CircuitTerminationSideEnum', strawberry.lazy('circuits.graphql.enums')] | None = (
strawberry_django.filter_field()
)
termination_type: Annotated['ContentTypeFilter', strawberry.lazy('core.graphql.filters')] | None = (
strawberry_django.filter_field()
)
termination_id: ID | None = strawberry_django.filter_field()
port_speed: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
upstream_speed: Annotated['IntegerLookup', strawberry.lazy('core.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()
@strawberry_django.filter(models.Circuit, lookups=True)
@autotype_decorator(filtersets.CircuitFilterSet)
class CircuitFilter(BaseFilterMixin):
pass
class CircuitFilter(ContactFilterMixin, ImageAttachmentFilterMixin, DistanceFilterMixin, PrimaryModelFilterMixin):
cid: FilterLookup[str] | None = strawberry_django.filter_field()
provider: Annotated['ProviderFilter', strawberry.lazy('circuits.graphql.filters')] | None = (
strawberry_django.filter_field()
)
provider_id: ID | None = strawberry_django.filter_field()
provider_account: Annotated['ProviderAccountFilter', strawberry.lazy('circuits.graphql.filters')] | None = (
strawberry_django.filter_field()
)
provider_account_id: ID | None = strawberry_django.filter_field()
type: Annotated['CircuitTypeFilter', strawberry.lazy('circuits.graphql.filters')] | 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()
)
tenant: Annotated['TenantFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
tenant_id: ID | 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('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.CircuitType, lookups=True)
@autotype_decorator(filtersets.CircuitTypeFilterSet)
class CircuitTypeFilter(BaseFilterMixin):
class CircuitTypeFilter(BaseCircuitTypeFilterMixin):
pass
@strawberry_django.filter(models.CircuitGroup, lookups=True)
@autotype_decorator(filtersets.CircuitGroupFilterSet)
class CircuitGroupFilter(BaseFilterMixin):
pass
class CircuitGroupFilter(OrganizationalModelFilterMixin):
tenant: Annotated['TenantFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
tenant_id: ID | None = strawberry_django.filter_field()
@strawberry_django.filter(models.CircuitGroupAssignment, lookups=True)
@autotype_decorator(filtersets.CircuitGroupAssignmentFilterSet)
class CircuitGroupAssignmentFilter(BaseFilterMixin):
pass
class CircuitGroupAssignmentFilter(
BaseObjectTypeFilterMixin, CustomFieldsFilterMixin, TagsFilterMixin, ChangeLogFilterMixin
):
member_type: Annotated['ContentTypeFilter', strawberry.lazy('core.graphql.filters')] | None = (
strawberry_django.filter_field()
)
member_type_id: ID | None = strawberry_django.filter_field()
group: Annotated['CircuitGroupFilter', strawberry.lazy('circuits.graphql.filters')] | 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(models.Provider, lookups=True)
@autotype_decorator(filtersets.ProviderFilterSet)
class ProviderFilter(BaseFilterMixin):
pass
class ProviderFilter(ContactFilterMixin, PrimaryModelFilterMixin):
name: FilterLookup[str] | None = strawberry_django.filter_field()
slug: FilterLookup[str] | None = strawberry_django.filter_field()
asns: Annotated['ASNFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field()
@strawberry_django.filter(models.ProviderAccount, lookups=True)
@autotype_decorator(filtersets.ProviderAccountFilterSet)
class ProviderAccountFilter(BaseFilterMixin):
pass
class ProviderAccountFilter(ContactFilterMixin, PrimaryModelFilterMixin):
provider: Annotated['ProviderFilter', strawberry.lazy('circuits.graphql.filters')] | 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(models.ProviderNetwork, lookups=True)
@autotype_decorator(filtersets.ProviderNetworkFilterSet)
class ProviderNetworkFilter(BaseFilterMixin):
pass
class ProviderNetworkFilter(PrimaryModelFilterMixin):
name: FilterLookup[str] | None = strawberry_django.filter_field()
provider: Annotated['ProviderFilter', strawberry.lazy('circuits.graphql.filters')] | 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(models.VirtualCircuitType, lookups=True)
@autotype_decorator(filtersets.VirtualCircuitTypeFilterSet)
class VirtualCircuitTypeFilter(BaseFilterMixin):
class VirtualCircuitTypeFilter(BaseCircuitTypeFilterMixin):
pass
@strawberry_django.filter(models.VirtualCircuit, lookups=True)
@autotype_decorator(filtersets.VirtualCircuitFilterSet)
class VirtualCircuitFilter(BaseFilterMixin):
pass
class VirtualCircuitFilter(PrimaryModelFilterMixin):
cid: FilterLookup[str] | None = strawberry_django.filter_field()
provider_network: Annotated['ProviderNetworkFilter', strawberry.lazy('circuits.graphql.filters')] | None = (
strawberry_django.filter_field()
)
provider_network_id: ID | None = strawberry_django.filter_field()
provider_account: Annotated['ProviderAccountFilter', strawberry.lazy('circuits.graphql.filters')] | None = (
strawberry_django.filter_field()
)
provider_account_id: ID | None = strawberry_django.filter_field()
type: Annotated['VirtualCircuitTypeFilter', strawberry.lazy('circuits.graphql.filters')] | 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()
)
tenant: Annotated['TenantFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
tenant_id: ID | None = strawberry_django.filter_field()
group_assignments: Annotated['CircuitGroupAssignmentFilter', strawberry.lazy('circuits.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.VirtualCircuitTermination, lookups=True)
@autotype_decorator(filtersets.VirtualCircuitTerminationFilterSet)
class VirtualCircuitTerminationFilter(BaseFilterMixin):
pass
class VirtualCircuitTerminationFilter(
BaseObjectTypeFilterMixin, CustomFieldsFilterMixin, TagsFilterMixin, ChangeLogFilterMixin
):
virtual_circuit: Annotated['VirtualCircuitFilter', strawberry.lazy('circuits.graphql.filters')] | 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['InterfaceFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
interface_id: ID | None = strawberry_django.filter_field()
description: FilterLookup[str] | None = strawberry_django.filter_field()

View File

@ -0,0 +1,218 @@
from enum import Enum
from typing import TypeVar, Tuple, Generic
from django.db.models import Q, QuerySet
from django.core.exceptions import FieldDoesNotExist
from django.db.models.fields.related import ForeignKey, ManyToManyField, ManyToManyRel, ManyToOneRel
import strawberry
from strawberry import ID
from strawberry.types import Info
import strawberry_django
from strawberry_django import (
process_filters,
FilterLookup,
RangeLookup,
ComparisonFilterLookup,
DateFilterLookup,
DatetimeFilterLookup,
TimeFilterLookup,
)
__all__ = [
'JSONFilter',
'TreeNodeFilter',
'IntegerLookup',
'FloatLookup',
'ArrayLookup',
'IntegerArrayLookup',
'FloatArrayLookup',
'StringArrayLookup',
]
T = TypeVar('T')
SKIP_MSG = 'Filter will be skipped on `null` value'
@strawberry.input(one_of=True, description='Lookup for JSON field. Only one of the lookup fields can be set.')
class JSONLookup:
string_lookup: FilterLookup[str] | None = strawberry_django.filter_field()
int_range_lookup: RangeLookup[int] | None = strawberry_django.filter_field()
int_comparison_lookup: ComparisonFilterLookup[int] | None = strawberry_django.filter_field()
float_range_lookup: RangeLookup[float] | None = strawberry_django.filter_field()
float_comparison_lookup: ComparisonFilterLookup[float] | None = strawberry_django.filter_field()
date_lookup: DateFilterLookup[str] | None = strawberry_django.filter_field()
datetime_lookup: DatetimeFilterLookup[str] | None = strawberry_django.filter_field()
time_lookup: TimeFilterLookup[str] | None = strawberry_django.filter_field()
boolean_lookup: FilterLookup[bool] | None = strawberry_django.filter_field()
def get_filter(self):
for field in self.__strawberry_definition__.fields:
value = getattr(self, field.name, None)
if value is not strawberry.UNSET:
return value
return None
@strawberry.input(one_of=True, description='Lookup for Integer fields. Only one of the lookup fields can be set.')
class IntegerLookup:
filter_lookup: FilterLookup[int] | None = strawberry_django.filter_field()
range_lookup: RangeLookup[int] | None = strawberry_django.filter_field()
comparison_lookup: ComparisonFilterLookup[int] | None = strawberry_django.filter_field()
def get_filter(self):
for field in self.__strawberry_definition__.fields:
value = getattr(self, field.name, None)
if value is not strawberry.UNSET:
return value
return None
@strawberry_django.filter_field
def filter(self, info: Info, queryset: QuerySet, prefix: str = '') -> Tuple[QuerySet, Q]:
filters = self.get_filter()
if not filters:
return queryset, Q()
return process_filters(filters=filters, queryset=queryset, info=info, prefix=prefix)
@strawberry.input(one_of=True, description='Lookup for Float fields. Only one of the lookup fields can be set.')
class FloatLookup:
filter_lookup: FilterLookup[float] | None = strawberry_django.filter_field()
range_lookup: RangeLookup[float] | None = strawberry_django.filter_field()
comparison_lookup: ComparisonFilterLookup[float] | None = strawberry_django.filter_field()
def get_filter(self):
for field in self.__strawberry_definition__.fields:
value = getattr(self, field.name, None)
if value is not strawberry.UNSET:
return value
return None
@strawberry_django.filter_field
def filter(self, info: Info, queryset: QuerySet, prefix: str = '') -> Tuple[QuerySet, Q]:
filters = self.get_filter()
if not filters:
return queryset, Q()
return process_filters(filters=filters, queryset=queryset, info=info, prefix=prefix)
@strawberry.input
class JSONFilter:
"""
Class for JSON field lookups with paths
"""
path: str
lookup: JSONLookup
@strawberry_django.filter_field
def filter(self, info: Info, queryset: QuerySet, prefix: str = '') -> Tuple[QuerySet, Q]:
filters = self.lookup.get_filter()
if not filters:
return queryset, Q()
json_path = f'{prefix}{self.path}__'
return process_filters(filters=filters, queryset=queryset, info=info, prefix=json_path)
@strawberry.enum
class TreeNodeMatch(Enum):
EXACT = 'exact' # Just the node itself
DESCENDANTS = 'descendants' # Node and all descendants
SELF_AND_DESCENDANTS = 'self_and_descendants' # Node and all descendants
CHILDREN = 'children' # Just immediate children
SIBLINGS = 'siblings' # Nodes with same parent
ANCESTORS = 'ancestors' # All parent nodes
PARENT = 'parent' # Just immediate parent
@strawberry.input
class TreeNodeFilter:
id: ID
match_type: TreeNodeMatch
@strawberry_django.filter_field
def filter(self, info: Info, queryset: QuerySet, prefix: str = '') -> Tuple[QuerySet, Q]:
model_field_name = prefix.removesuffix('__').removesuffix('_id')
model_field = None
try:
model_field = queryset.model._meta.get_field(model_field_name)
except FieldDoesNotExist:
try:
model_field = queryset.model._meta.get_field(f'{model_field_name}s')
except FieldDoesNotExist:
return queryset, Q(pk__in=[])
if hasattr(model_field, 'related_model'):
related_model = model_field.related_model
else:
return queryset, Q(pk__in=[])
# Generate base Q filter for the related model without prefix
q_filter = generate_tree_node_q_filter(related_model, self)
# Handle different relationship types
if isinstance(model_field, (ManyToManyField, ManyToManyRel)):
return queryset, Q(**{f'{model_field_name}__in': related_model.objects.filter(q_filter)})
elif isinstance(model_field, ForeignKey):
return queryset, Q(**{f'{model_field_name}__{k}': v for k, v in q_filter.children})
elif isinstance(model_field, ManyToOneRel):
return queryset, Q(**{f'{model_field_name}__in': related_model.objects.filter(q_filter)})
else:
return queryset, Q(**{f'{model_field_name}__{k}': v for k, v in q_filter.children})
def generate_tree_node_q_filter(model_class, filter_value: TreeNodeFilter) -> Q:
"""
Generate appropriate Q filter for MPTT tree filtering based on match type
"""
try:
node = model_class.objects.get(id=filter_value.id)
except model_class.DoesNotExist:
return Q(pk__in=[])
if filter_value.match_type == TreeNodeMatch.EXACT:
return Q(id=filter_value.id)
elif filter_value.match_type == TreeNodeMatch.DESCENDANTS:
return Q(tree_id=node.tree_id, lft__gt=node.lft, rght__lt=node.rght)
elif filter_value.match_type == TreeNodeMatch.SELF_AND_DESCENDANTS:
return Q(tree_id=node.tree_id, lft__gte=node.lft, rght__lte=node.rght)
elif filter_value.match_type == TreeNodeMatch.CHILDREN:
return Q(tree_id=node.tree_id, level=node.level + 1, lft__gt=node.lft, rght__lt=node.rght)
elif filter_value.match_type == TreeNodeMatch.SIBLINGS:
return Q(tree_id=node.tree_id, level=node.level, parent=node.parent) & ~Q(id=node.id)
elif filter_value.match_type == TreeNodeMatch.ANCESTORS:
return Q(tree_id=node.tree_id, lft__lt=node.lft, rght__gt=node.rght)
elif filter_value.match_type == TreeNodeMatch.PARENT:
return Q(id=node.parent_id) if node.parent_id else Q(pk__in=[])
return Q()
@strawberry.input(one_of=True, description='Lookup for Array fields. Only one of the lookup fields can be set.')
class ArrayLookup(Generic[T]):
"""
Class for Array field lookups
"""
contains: list[T] | None = strawberry_django.filter_field(description='Contains the value')
contained_by: list[T] | None = strawberry_django.filter_field(description='Contained by the value')
overlap: list[T] | None = strawberry_django.filter_field(description='Overlaps with the value')
length: int | None = strawberry_django.filter_field(description='Length of the array')
@strawberry.input(one_of=True, description='Lookup for Array fields. Only one of the lookup fields can be set.')
class IntegerArrayLookup(ArrayLookup[int]):
pass
@strawberry.input(one_of=True, description='Lookup for Array fields. Only one of the lookup fields can be set.')
class FloatArrayLookup(ArrayLookup[float]):
pass
@strawberry.input(one_of=True, description='Lookup for Array fields. Only one of the lookup fields can be set.')
class StringArrayLookup(ArrayLookup[str]):
pass

View File

@ -0,0 +1,31 @@
from dataclasses import dataclass
from datetime import datetime
from typing import Annotated, TYPE_CHECKING
import strawberry
from strawberry import ID
import strawberry_django
from strawberry_django import DatetimeFilterLookup
if TYPE_CHECKING:
from .filters import *
__all__ = ['BaseFilterMixin', 'BaseObjectTypeFilterMixin', 'ChangeLogFilterMixin']
# @strawberry.input
class BaseFilterMixin: ...
@dataclass
class BaseObjectTypeFilterMixin(BaseFilterMixin):
id: ID | None = strawberry.UNSET
@dataclass
class ChangeLogFilterMixin(BaseFilterMixin):
changelog: Annotated['ObjectChangeFilter', strawberry.lazy('core.graphql.filters')] | None = (
strawberry_django.filter_field()
)
created: DatetimeFilterLookup[datetime] | None = strawberry_django.filter_field()
last_updated: DatetimeFilterLookup[datetime] | None = strawberry_django.filter_field()

View File

@ -1,28 +1,93 @@
from datetime import datetime
from typing import Annotated, TYPE_CHECKING
import strawberry
from strawberry.scalars import ID
import strawberry_django
from strawberry_django import (
DatetimeFilterLookup,
FilterLookup,
)
from django.contrib.contenttypes.models import ContentType as DjangoContentType
from core.graphql.filter_mixins import BaseFilterMixin
from core.graphql.filter_lookups import JSONFilter
from netbox.graphql.filter_mixins import (
PrimaryModelFilterMixin,
)
from core import models
if TYPE_CHECKING:
from core.graphql.filter_lookups import *
from users.graphql.filters import *
from core import filtersets, models
from netbox.graphql.filter_mixins import autotype_decorator, BaseFilterMixin
__all__ = (
'DataFileFilter',
'DataSourceFilter',
'ObjectChangeFilter',
'ContentTypeFilter',
)
@strawberry_django.filter(models.DataFile, lookups=True)
@autotype_decorator(filtersets.DataFileFilterSet)
class DataFileFilter(BaseFilterMixin):
pass
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['DataSourceFilter', strawberry.lazy('core.graphql.filters')] | 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('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
hash: FilterLookup[str] | None = strawberry_django.filter_field()
@strawberry_django.filter(models.DataSource, lookups=True)
@autotype_decorator(filtersets.DataSourceFilterSet)
class DataSourceFilter(BaseFilterMixin):
pass
class DataSourceFilter(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('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
last_synced: DatetimeFilterLookup[datetime] | None = strawberry_django.filter_field()
datafiles: Annotated['DataFileFilter', strawberry.lazy('core.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.ObjectChange, lookups=True)
@autotype_decorator(filtersets.ObjectChangeFilterSet)
class ObjectChangeFilter(BaseFilterMixin):
pass
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['ContentTypeFilter', strawberry.lazy('core.graphql.filters')] | 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_id: ID | 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('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
postchange_data: Annotated['JSONFilter', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(DjangoContentType, lookups=True)
class ContentTypeFilter(BaseFilterMixin):
id: ID | None = strawberry_django.filter_field()
app_label: FilterLookup[str] | None = strawberry_django.filter_field()
model: FilterLookup[str] | None = strawberry_django.filter_field()

View File

@ -1,4 +1,4 @@
from typing import Annotated, List
from typing import Annotated, List, TYPE_CHECKING
import strawberry
import strawberry_django
@ -6,6 +6,9 @@ from django.contrib.contenttypes.models import ContentType
from core.models import ObjectChange
if TYPE_CHECKING:
from netbox.core.graphql.types import ObjectChangeType
__all__ = (
'ChangelogMixin',
)

View File

@ -2,7 +2,7 @@ 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 import BaseObjectType, NetBoxObjectType
from .filters import *
@ -11,6 +11,7 @@ __all__ = (
'DataFileType',
'DataSourceType',
'ObjectChangeType',
'ContentType',
)
@ -40,3 +41,8 @@ class DataSourceType(NetBoxObjectType):
)
class ObjectChangeType(BaseObjectType):
pass
@strawberry_django.type(DjangoContentType, fields='__all__')
class ContentType:
pass

View File

@ -0,0 +1,857 @@
from enum import Enum
import strawberry
#
# Sites
#
@strawberry.enum
class SiteStatusEnum(Enum):
STATUS_PLANNED = 'planned'
STATUS_STAGING = 'staging'
STATUS_ACTIVE = 'active'
STATUS_DECOMMISSIONING = 'decommissioning'
STATUS_RETIRED = 'retired'
#
# Locations
#
@strawberry.enum
class LocationStatusEnum(Enum):
STATUS_PLANNED = 'planned'
STATUS_STAGING = 'staging'
STATUS_ACTIVE = 'active'
STATUS_DECOMMISSIONING = 'decommissioning'
STATUS_RETIRED = 'retired'
#
# Racks
#
@strawberry.enum
class RackFormFactorEnum(Enum):
TYPE_2POST = '2-post-frame'
TYPE_4POST = '4-post-frame'
TYPE_CABINET = '4-post-cabinet'
TYPE_WALLFRAME = 'wall-frame'
TYPE_WALLFRAME_VERTICAL = 'wall-frame-vertical'
TYPE_WALLCABINET = 'wall-cabinet'
TYPE_WALLCABINET_VERTICAL = 'wall-cabinet-vertical'
@strawberry.enum
class RackWidthEnum(Enum):
WIDTH_10IN = 10
WIDTH_19IN = 19
WIDTH_21IN = 21
WIDTH_23IN = 23
@strawberry.enum
class RackStatusEnum(Enum):
STATUS_RESERVED = 'reserved'
STATUS_AVAILABLE = 'available'
STATUS_PLANNED = 'planned'
STATUS_ACTIVE = 'active'
STATUS_DEPRECATED = 'deprecated'
@strawberry.enum
class RackDimensionUnitEnum(Enum):
UNIT_MILLIMETER = 'mm'
UNIT_INCH = 'in'
@strawberry.enum
class RackElevationDetailRenderEnum(Enum):
RENDER_JSON = 'json'
RENDER_SVG = 'svg'
@strawberry.enum
class RackAirflowEnum(Enum):
FRONT_TO_REAR = 'front-to-rear'
REAR_TO_FRONT = 'rear-to-front'
#
# DeviceTypes
#
@strawberry.enum
class SubdeviceRoleEnum(Enum):
ROLE_PARENT = 'parent'
ROLE_CHILD = 'child'
#
# Devices
#
@strawberry.enum
class DeviceFaceEnum(Enum):
FACE_FRONT = 'front'
FACE_REAR = 'rear'
@strawberry.enum
class DeviceStatusEnum(Enum):
STATUS_OFFLINE = 'offline'
STATUS_ACTIVE = 'active'
STATUS_PLANNED = 'planned'
STATUS_STAGED = 'staged'
STATUS_FAILED = 'failed'
STATUS_INVENTORY = 'inventory'
STATUS_DECOMMISSIONING = 'decommissioning'
@strawberry.enum
class DeviceAirflowEnum(Enum):
AIRFLOW_FRONT_TO_REAR = 'front-to-rear'
AIRFLOW_REAR_TO_FRONT = 'rear-to-front'
AIRFLOW_LEFT_TO_RIGHT = 'left-to-right'
AIRFLOW_RIGHT_TO_LEFT = 'right-to-left'
AIRFLOW_SIDE_TO_REAR = 'side-to-rear'
AIRFLOW_REAR_TO_SIDE = 'rear-to-side'
AIRFLOW_BOTTOM_TO_TOP = 'bottom-to-top'
AIRFLOW_TOP_TO_BOTTOM = 'top-to-bottom'
AIRFLOW_PASSIVE = 'passive'
AIRFLOW_MIXED = 'mixed'
#
# Modules
#
@strawberry.enum
class ModuleStatusEnum(Enum):
key = 'Module.status'
STATUS_OFFLINE = 'offline'
STATUS_ACTIVE = 'active'
STATUS_PLANNED = 'planned'
STATUS_STAGED = 'staged'
STATUS_FAILED = 'failed'
STATUS_DECOMMISSIONING = 'decommissioning'
@strawberry.enum
class ModuleAirflowEnum(Enum):
FRONT_TO_REAR = 'front-to-rear'
REAR_TO_FRONT = 'rear-to-front'
LEFT_TO_RIGHT = 'left-to-right'
RIGHT_TO_LEFT = 'right-to-left'
SIDE_TO_REAR = 'side-to-rear'
PASSIVE = 'passive'
#
# ConsolePorts
#
@strawberry.enum
class ConsolePortTypeEnum(Enum):
TYPE_DE9 = 'de-9'
TYPE_DB25 = 'db-25'
TYPE_RJ11 = 'rj-11'
TYPE_RJ12 = 'rj-12'
TYPE_RJ45 = 'rj-45'
TYPE_MINI_DIN_8 = 'mini-din-8'
TYPE_USB_A = 'usb-a'
TYPE_USB_B = 'usb-b'
TYPE_USB_C = 'usb-c'
TYPE_USB_MINI_A = 'usb-mini-a'
TYPE_USB_MINI_B = 'usb-mini-b'
TYPE_USB_MICRO_A = 'usb-micro-a'
TYPE_USB_MICRO_B = 'usb-micro-b'
TYPE_USB_MICRO_AB = 'usb-micro-ab'
TYPE_OTHER = 'other'
@strawberry.enum
class ConsolePortSpeedEnum(Enum):
SPEED_1200 = 1200
SPEED_2400 = 2400
SPEED_4800 = 4800
SPEED_9600 = 9600
SPEED_19200 = 19200
SPEED_38400 = 38400
SPEED_57600 = 57600
SPEED_115200 = 115200
#
# PowerPorts
#
@strawberry.enum
class PowerPortTypeEnum(Enum):
# IEC 60320
TYPE_IEC_C6 = 'iec-60320-c6'
TYPE_IEC_C8 = 'iec-60320-c8'
TYPE_IEC_C14 = 'iec-60320-c14'
TYPE_IEC_C16 = 'iec-60320-c16'
TYPE_IEC_C20 = 'iec-60320-c20'
TYPE_IEC_C22 = 'iec-60320-c22'
# IEC 60309
TYPE_IEC_PNE4H = 'iec-60309-p-n-e-4h'
TYPE_IEC_PNE6H = 'iec-60309-p-n-e-6h'
TYPE_IEC_PNE9H = 'iec-60309-p-n-e-9h'
TYPE_IEC_2PE4H = 'iec-60309-2p-e-4h'
TYPE_IEC_2PE6H = 'iec-60309-2p-e-6h'
TYPE_IEC_2PE9H = 'iec-60309-2p-e-9h'
TYPE_IEC_3PE4H = 'iec-60309-3p-e-4h'
TYPE_IEC_3PE6H = 'iec-60309-3p-e-6h'
TYPE_IEC_3PE9H = 'iec-60309-3p-e-9h'
TYPE_IEC_3PNE4H = 'iec-60309-3p-n-e-4h'
TYPE_IEC_3PNE6H = 'iec-60309-3p-n-e-6h'
TYPE_IEC_3PNE9H = 'iec-60309-3p-n-e-9h'
# IEC 60906-1
TYPE_IEC_60906_1 = 'iec-60906-1'
TYPE_NBR_14136_10A = 'nbr-14136-10a'
TYPE_NBR_14136_20A = 'nbr-14136-20a'
# NEMA non-locking
TYPE_NEMA_115P = 'nema-1-15p'
TYPE_NEMA_515P = 'nema-5-15p'
TYPE_NEMA_520P = 'nema-5-20p'
TYPE_NEMA_530P = 'nema-5-30p'
TYPE_NEMA_550P = 'nema-5-50p'
TYPE_NEMA_615P = 'nema-6-15p'
TYPE_NEMA_620P = 'nema-6-20p'
TYPE_NEMA_630P = 'nema-6-30p'
TYPE_NEMA_650P = 'nema-6-50p'
TYPE_NEMA_1030P = 'nema-10-30p'
TYPE_NEMA_1050P = 'nema-10-50p'
TYPE_NEMA_1420P = 'nema-14-20p'
TYPE_NEMA_1430P = 'nema-14-30p'
TYPE_NEMA_1450P = 'nema-14-50p'
TYPE_NEMA_1460P = 'nema-14-60p'
TYPE_NEMA_1515P = 'nema-15-15p'
TYPE_NEMA_1520P = 'nema-15-20p'
TYPE_NEMA_1530P = 'nema-15-30p'
TYPE_NEMA_1550P = 'nema-15-50p'
TYPE_NEMA_1560P = 'nema-15-60p'
# NEMA locking
TYPE_NEMA_L115P = 'nema-l1-15p'
TYPE_NEMA_L515P = 'nema-l5-15p'
TYPE_NEMA_L520P = 'nema-l5-20p'
TYPE_NEMA_L530P = 'nema-l5-30p'
TYPE_NEMA_L550P = 'nema-l5-50p'
TYPE_NEMA_L615P = 'nema-l6-15p'
TYPE_NEMA_L620P = 'nema-l6-20p'
TYPE_NEMA_L630P = 'nema-l6-30p'
TYPE_NEMA_L650P = 'nema-l6-50p'
TYPE_NEMA_L1030P = 'nema-l10-30p'
TYPE_NEMA_L1420P = 'nema-l14-20p'
TYPE_NEMA_L1430P = 'nema-l14-30p'
TYPE_NEMA_L1450P = 'nema-l14-50p'
TYPE_NEMA_L1460P = 'nema-l14-60p'
TYPE_NEMA_L1520P = 'nema-l15-20p'
TYPE_NEMA_L1530P = 'nema-l15-30p'
TYPE_NEMA_L1550P = 'nema-l15-50p'
TYPE_NEMA_L1560P = 'nema-l15-60p'
TYPE_NEMA_L2120P = 'nema-l21-20p'
TYPE_NEMA_L2130P = 'nema-l21-30p'
TYPE_NEMA_L2220P = 'nema-l22-20p'
TYPE_NEMA_L2230P = 'nema-l22-30p'
# California style
TYPE_CS6361C = 'cs6361c'
TYPE_CS6365C = 'cs6365c'
TYPE_CS8165C = 'cs8165c'
TYPE_CS8265C = 'cs8265c'
TYPE_CS8365C = 'cs8365c'
TYPE_CS8465C = 'cs8465c'
# ITA/international
TYPE_ITA_C = 'ita-c'
TYPE_ITA_E = 'ita-e'
TYPE_ITA_F = 'ita-f'
TYPE_ITA_EF = 'ita-ef'
TYPE_ITA_G = 'ita-g'
TYPE_ITA_H = 'ita-h'
TYPE_ITA_I = 'ita-i'
TYPE_ITA_J = 'ita-j'
TYPE_ITA_K = 'ita-k'
TYPE_ITA_L = 'ita-l'
TYPE_ITA_M = 'ita-m'
TYPE_ITA_N = 'ita-n'
TYPE_ITA_O = 'ita-o'
# USB
TYPE_USB_A = 'usb-a'
TYPE_USB_B = 'usb-b'
TYPE_USB_C = 'usb-c'
TYPE_USB_MINI_A = 'usb-mini-a'
TYPE_USB_MINI_B = 'usb-mini-b'
TYPE_USB_MICRO_A = 'usb-micro-a'
TYPE_USB_MICRO_B = 'usb-micro-b'
TYPE_USB_MICRO_AB = 'usb-micro-ab'
TYPE_USB_3_B = 'usb-3-b'
TYPE_USB_3_MICROB = 'usb-3-micro-b'
# Molex
TYPE_MOLEX_MICRO_FIT_1X2 = 'molex-micro-fit-1x2'
TYPE_MOLEX_MICRO_FIT_2X2 = 'molex-micro-fit-2x2'
TYPE_MOLEX_MICRO_FIT_2X4 = 'molex-micro-fit-2x4'
# Direct current (DC)
TYPE_DC = 'dc-terminal'
# Proprietary
TYPE_SAF_D_GRID = 'saf-d-grid'
TYPE_NEUTRIK_POWERCON_20A = 'neutrik-powercon-20'
TYPE_NEUTRIK_POWERCON_32A = 'neutrik-powercon-32'
TYPE_NEUTRIK_POWERCON_TRUE1 = 'neutrik-powercon-true1'
TYPE_NEUTRIK_POWERCON_TRUE1_TOP = 'neutrik-powercon-true1-top'
TYPE_UBIQUITI_SMARTPOWER = 'ubiquiti-smartpower'
# Other
TYPE_HARDWIRED = 'hardwired'
TYPE_OTHER = 'other'
#
# PowerOutlets
#
@strawberry.enum
class PowerOutletTypeEnum(Enum):
# IEC 60320
TYPE_IEC_C5 = 'iec-60320-c5'
TYPE_IEC_C7 = 'iec-60320-c7'
TYPE_IEC_C13 = 'iec-60320-c13'
TYPE_IEC_C15 = 'iec-60320-c15'
TYPE_IEC_C19 = 'iec-60320-c19'
TYPE_IEC_C21 = 'iec-60320-c21'
# IEC 60309
TYPE_IEC_PNE4H = 'iec-60309-p-n-e-4h'
TYPE_IEC_PNE6H = 'iec-60309-p-n-e-6h'
TYPE_IEC_PNE9H = 'iec-60309-p-n-e-9h'
TYPE_IEC_2PE4H = 'iec-60309-2p-e-4h'
TYPE_IEC_2PE6H = 'iec-60309-2p-e-6h'
TYPE_IEC_2PE9H = 'iec-60309-2p-e-9h'
TYPE_IEC_3PE4H = 'iec-60309-3p-e-4h'
TYPE_IEC_3PE6H = 'iec-60309-3p-e-6h'
TYPE_IEC_3PE9H = 'iec-60309-3p-e-9h'
TYPE_IEC_3PNE4H = 'iec-60309-3p-n-e-4h'
TYPE_IEC_3PNE6H = 'iec-60309-3p-n-e-6h'
TYPE_IEC_3PNE9H = 'iec-60309-3p-n-e-9h'
# IEC 60906-1
TYPE_IEC_60906_1 = 'iec-60906-1'
TYPE_NBR_14136_10A = 'nbr-14136-10a'
TYPE_NBR_14136_20A = 'nbr-14136-20a'
# NEMA non-locking
TYPE_NEMA_115R = 'nema-1-15r'
TYPE_NEMA_515R = 'nema-5-15r'
TYPE_NEMA_520R = 'nema-5-20r'
TYPE_NEMA_530R = 'nema-5-30r'
TYPE_NEMA_550R = 'nema-5-50r'
TYPE_NEMA_615R = 'nema-6-15r'
TYPE_NEMA_620R = 'nema-6-20r'
TYPE_NEMA_630R = 'nema-6-30r'
TYPE_NEMA_650R = 'nema-6-50r'
TYPE_NEMA_1030R = 'nema-10-30r'
TYPE_NEMA_1050R = 'nema-10-50r'
TYPE_NEMA_1420R = 'nema-14-20r'
TYPE_NEMA_1430R = 'nema-14-30r'
TYPE_NEMA_1450R = 'nema-14-50r'
TYPE_NEMA_1460R = 'nema-14-60r'
TYPE_NEMA_1515R = 'nema-15-15r'
TYPE_NEMA_1520R = 'nema-15-20r'
TYPE_NEMA_1530R = 'nema-15-30r'
TYPE_NEMA_1550R = 'nema-15-50r'
TYPE_NEMA_1560R = 'nema-15-60r'
# NEMA locking
TYPE_NEMA_L115R = 'nema-l1-15r'
TYPE_NEMA_L515R = 'nema-l5-15r'
TYPE_NEMA_L520R = 'nema-l5-20r'
TYPE_NEMA_L530R = 'nema-l5-30r'
TYPE_NEMA_L550R = 'nema-l5-50r'
TYPE_NEMA_L615R = 'nema-l6-15r'
TYPE_NEMA_L620R = 'nema-l6-20r'
TYPE_NEMA_L630R = 'nema-l6-30r'
TYPE_NEMA_L650R = 'nema-l6-50r'
TYPE_NEMA_L1030R = 'nema-l10-30r'
TYPE_NEMA_L1420R = 'nema-l14-20r'
TYPE_NEMA_L1430R = 'nema-l14-30r'
TYPE_NEMA_L1450R = 'nema-l14-50r'
TYPE_NEMA_L1460R = 'nema-l14-60r'
TYPE_NEMA_L1520R = 'nema-l15-20r'
TYPE_NEMA_L1530R = 'nema-l15-30r'
TYPE_NEMA_L1550R = 'nema-l15-50r'
TYPE_NEMA_L1560R = 'nema-l15-60r'
TYPE_NEMA_L2120R = 'nema-l21-20r'
TYPE_NEMA_L2130R = 'nema-l21-30r'
TYPE_NEMA_L2220R = 'nema-l22-20r'
TYPE_NEMA_L2230R = 'nema-l22-30r'
# California style
TYPE_CS6360C = 'CS6360C'
TYPE_CS6364C = 'CS6364C'
TYPE_CS8164C = 'CS8164C'
TYPE_CS8264C = 'CS8264C'
TYPE_CS8364C = 'CS8364C'
TYPE_CS8464C = 'CS8464C'
# ITA/international
TYPE_ITA_E = 'ita-e'
TYPE_ITA_F = 'ita-f'
TYPE_ITA_G = 'ita-g'
TYPE_ITA_H = 'ita-h'
TYPE_ITA_I = 'ita-i'
TYPE_ITA_J = 'ita-j'
TYPE_ITA_K = 'ita-k'
TYPE_ITA_L = 'ita-l'
TYPE_ITA_M = 'ita-m'
TYPE_ITA_N = 'ita-n'
TYPE_ITA_O = 'ita-o'
TYPE_ITA_MULTISTANDARD = 'ita-multistandard'
# USB
TYPE_USB_A = 'usb-a'
TYPE_USB_MICROB = 'usb-micro-b'
TYPE_USB_C = 'usb-c'
# Molex
TYPE_MOLEX_MICRO_FIT_1X2 = 'molex-micro-fit-1x2'
TYPE_MOLEX_MICRO_FIT_2X2 = 'molex-micro-fit-2x2'
TYPE_MOLEX_MICRO_FIT_2X4 = 'molex-micro-fit-2x4'
# Direct current (DC)
TYPE_DC = 'dc-terminal'
# Proprietary
TYPE_EATON_C39 = 'eaton-c39'
TYPE_HDOT_CX = 'hdot-cx'
TYPE_SAF_D_GRID = 'saf-d-grid'
TYPE_NEUTRIK_POWERCON_20A = 'neutrik-powercon-20a'
TYPE_NEUTRIK_POWERCON_32A = 'neutrik-powercon-32a'
TYPE_NEUTRIK_POWERCON_TRUE1 = 'neutrik-powercon-true1'
TYPE_NEUTRIK_POWERCON_TRUE1_TOP = 'neutrik-powercon-true1-top'
TYPE_UBIQUITI_SMARTPOWER = 'ubiquiti-smartpower'
# Other
TYPE_HARDWIRED = 'hardwired'
TYPE_OTHER = 'other'
@strawberry.enum
class PowerOutletFeedLegEnum(Enum):
FEED_LEG_A = 'A'
FEED_LEG_B = 'B'
FEED_LEG_C = 'C'
#
# Interfaces
#
@strawberry.enum
class InterfaceKindEnum(Enum):
KIND_PHYSICAL = 'physical'
KIND_VIRTUAL = 'virtual'
KIND_WIRELESS = 'wireless'
@strawberry.enum
class InterfaceTypeEnum(Enum):
# Virtual
TYPE_VIRTUAL = 'virtual'
TYPE_BRIDGE = 'bridge'
TYPE_LAG = 'lag'
# Ethernet
TYPE_100ME_FX = '100base-fx'
TYPE_100ME_LFX = '100base-lfx'
TYPE_100ME_FIXED = '100base-tx'
TYPE_100ME_T1 = '100base-t1'
TYPE_100ME_SFP = '100base-x-sfp'
TYPE_1GE_FIXED = '1000base-t'
TYPE_1GE_LX_FIXED = '1000base-lx'
TYPE_1GE_TX_FIXED = '1000base-tx'
TYPE_1GE_GBIC = '1000base-x-gbic'
TYPE_1GE_SFP = '1000base-x-sfp'
TYPE_2GE_FIXED = '2.5gbase-t'
TYPE_5GE_FIXED = '5gbase-t'
TYPE_10GE_FIXED = '10gbase-t'
TYPE_10GE_CX4 = '10gbase-cx4'
TYPE_10GE_SFP_PLUS = '10gbase-x-sfpp'
TYPE_10GE_XFP = '10gbase-x-xfp'
TYPE_10GE_XENPAK = '10gbase-x-xenpak'
TYPE_10GE_X2 = '10gbase-x-x2'
TYPE_25GE_SFP28 = '25gbase-x-sfp28'
TYPE_50GE_SFP56 = '50gbase-x-sfp56'
TYPE_40GE_QSFP_PLUS = '40gbase-x-qsfpp'
TYPE_50GE_QSFP28 = '50gbase-x-sfp28'
TYPE_100GE_CFP = '100gbase-x-cfp'
TYPE_100GE_CFP2 = '100gbase-x-cfp2'
TYPE_100GE_CFP4 = '100gbase-x-cfp4'
TYPE_100GE_CXP = '100gbase-x-cxp'
TYPE_100GE_CPAK = '100gbase-x-cpak'
TYPE_100GE_DSFP = '100gbase-x-dsfp'
TYPE_100GE_SFP_DD = '100gbase-x-sfpdd'
TYPE_100GE_QSFP28 = '100gbase-x-qsfp28'
TYPE_100GE_QSFP_DD = '100gbase-x-qsfpdd'
TYPE_200GE_CFP2 = '200gbase-x-cfp2'
TYPE_200GE_QSFP56 = '200gbase-x-qsfp56'
TYPE_200GE_QSFP_DD = '200gbase-x-qsfpdd'
TYPE_400GE_CFP2 = '400gbase-x-cfp2'
TYPE_400GE_QSFP112 = '400gbase-x-qsfp112'
TYPE_400GE_QSFP_DD = '400gbase-x-qsfpdd'
TYPE_400GE_OSFP = '400gbase-x-osfp'
TYPE_400GE_OSFP_RHS = '400gbase-x-osfp-rhs'
TYPE_400GE_CDFP = '400gbase-x-cdfp'
TYPE_400GE_CFP8 = '400gbase-x-cfp8'
TYPE_800GE_QSFP_DD = '800gbase-x-qsfpdd'
TYPE_800GE_OSFP = '800gbase-x-osfp'
# Ethernet Backplane
TYPE_1GE_KX = '1000base-kx'
TYPE_2GE_KX = '2.5gbase-kx'
TYPE_5GE_KR = '5gbase-kr'
TYPE_10GE_KR = '10gbase-kr'
TYPE_10GE_KX4 = '10gbase-kx4'
TYPE_25GE_KR = '25gbase-kr'
TYPE_40GE_KR4 = '40gbase-kr4'
TYPE_50GE_KR = '50gbase-kr'
TYPE_100GE_KP4 = '100gbase-kp4'
TYPE_100GE_KR2 = '100gbase-kr2'
TYPE_100GE_KR4 = '100gbase-kr4'
# Wireless
TYPE_80211A = 'ieee802.11a'
TYPE_80211G = 'ieee802.11g'
TYPE_80211N = 'ieee802.11n'
TYPE_80211AC = 'ieee802.11ac'
TYPE_80211AD = 'ieee802.11ad'
TYPE_80211AX = 'ieee802.11ax'
TYPE_80211AY = 'ieee802.11ay'
TYPE_80211BE = 'ieee802.11be'
TYPE_802151 = 'ieee802.15.1'
TYPE_802154 = 'ieee802.15.4'
TYPE_OTHER_WIRELESS = 'other-wireless'
# Cellular
TYPE_GSM = 'gsm'
TYPE_CDMA = 'cdma'
TYPE_LTE = 'lte'
TYPE_4G = '4g'
TYPE_5G = '5g'
# SONET
TYPE_SONET_OC3 = 'sonet-oc3'
TYPE_SONET_OC12 = 'sonet-oc12'
TYPE_SONET_OC48 = 'sonet-oc48'
TYPE_SONET_OC192 = 'sonet-oc192'
TYPE_SONET_OC768 = 'sonet-oc768'
TYPE_SONET_OC1920 = 'sonet-oc1920'
TYPE_SONET_OC3840 = 'sonet-oc3840'
# Fibrechannel
TYPE_1GFC_SFP = '1gfc-sfp'
TYPE_2GFC_SFP = '2gfc-sfp'
TYPE_4GFC_SFP = '4gfc-sfp'
TYPE_8GFC_SFP_PLUS = '8gfc-sfpp'
TYPE_16GFC_SFP_PLUS = '16gfc-sfpp'
TYPE_32GFC_SFP28 = '32gfc-sfp28'
TYPE_32GFC_SFP_PLUS = '32gfc-sfpp'
TYPE_64GFC_QSFP_PLUS = '64gfc-qsfpp'
TYPE_64GFC_SFP_DD = '64gfc-sfpdd'
TYPE_64GFC_SFP_PLUS = '64gfc-sfpp'
TYPE_128GFC_QSFP28 = '128gfc-qsfp28'
# InfiniBand
TYPE_INFINIBAND_SDR = 'infiniband-sdr'
TYPE_INFINIBAND_DDR = 'infiniband-ddr'
TYPE_INFINIBAND_QDR = 'infiniband-qdr'
TYPE_INFINIBAND_FDR10 = 'infiniband-fdr10'
TYPE_INFINIBAND_FDR = 'infiniband-fdr'
TYPE_INFINIBAND_EDR = 'infiniband-edr'
TYPE_INFINIBAND_HDR = 'infiniband-hdr'
TYPE_INFINIBAND_NDR = 'infiniband-ndr'
TYPE_INFINIBAND_XDR = 'infiniband-xdr'
# Serial
TYPE_T1 = 't1'
TYPE_E1 = 'e1'
TYPE_T3 = 't3'
TYPE_E3 = 'e3'
# ATM/DSL
TYPE_XDSL = 'xdsl'
# Coaxial
TYPE_DOCSIS = 'docsis'
# PON
TYPE_BPON = 'bpon'
TYPE_EPON = 'epon'
TYPE_10G_EPON = '10g-epon'
TYPE_GPON = 'gpon'
TYPE_XG_PON = 'xg-pon'
TYPE_XGS_PON = 'xgs-pon'
TYPE_NG_PON2 = 'ng-pon2'
TYPE_25G_PON = '25g-pon'
TYPE_50G_PON = '50g-pon'
# Stacking
TYPE_STACKWISE = 'cisco-stackwise'
TYPE_STACKWISE_PLUS = 'cisco-stackwise-plus'
TYPE_FLEXSTACK = 'cisco-flexstack'
TYPE_FLEXSTACK_PLUS = 'cisco-flexstack-plus'
TYPE_STACKWISE80 = 'cisco-stackwise-80'
TYPE_STACKWISE160 = 'cisco-stackwise-160'
TYPE_STACKWISE320 = 'cisco-stackwise-320'
TYPE_STACKWISE480 = 'cisco-stackwise-480'
TYPE_STACKWISE1T = 'cisco-stackwise-1t'
TYPE_JUNIPER_VCP = 'juniper-vcp'
TYPE_SUMMITSTACK = 'extreme-summitstack'
TYPE_SUMMITSTACK128 = 'extreme-summitstack-128'
TYPE_SUMMITSTACK256 = 'extreme-summitstack-256'
TYPE_SUMMITSTACK512 = 'extreme-summitstack-512'
# Other
TYPE_OTHER = 'other'
@strawberry.enum
class InterfaceSpeedEnum(Enum):
SPEED_10MBPS = 10000
SPEED_100MBPS = 100000
SPEED_1GBPS = 1000000
SPEED_10GBPS = 10000000
SPEED_25GBPS = 25000000
SPEED_40GBPS = 40000000
SPEED_100GBPS = 100000000
SPEED_200GBPS = 200000000
SPEED_400GBPS = 400000000
@strawberry.enum
class InterfaceDuplexEnum(Enum):
DUPLEX_HALF = 'half'
DUPLEX_FULL = 'full'
DUPLEX_AUTO = 'auto'
@strawberry.enum
class InterfaceModeEnum(Enum):
MODE_ACCESS = 'access'
MODE_TAGGED = 'tagged'
MODE_TAGGED_ALL = 'tagged-all'
MODE_Q_IN_Q = 'q-in-q'
@strawberry.enum
class InterfacePoEModeEnum(Enum):
MODE_PD = 'pd'
MODE_PSE = 'pse'
@strawberry.enum
class InterfacePoETypeEnum(Enum):
TYPE_1_8023AF = 'type1-ieee802.3af'
TYPE_2_8023AT = 'type2-ieee802.3at'
TYPE_3_8023BT = 'type3-ieee802.3bt'
TYPE_4_8023BT = 'type4-ieee802.3bt'
PASSIVE_24V_2PAIR = 'passive-24v-2pair'
PASSIVE_24V_4PAIR = 'passive-24v-4pair'
PASSIVE_48V_2PAIR = 'passive-48v-2pair'
PASSIVE_48V_4PAIR = 'passive-48v-4pair'
#
# FrontPorts/RearPorts
#
@strawberry.enum
class PortTypeEnum(Enum):
TYPE_8P8C = '8p8c'
TYPE_8P6C = '8p6c'
TYPE_8P4C = '8p4c'
TYPE_8P2C = '8p2c'
TYPE_6P6C = '6p6c'
TYPE_6P4C = '6p4c'
TYPE_6P2C = '6p2c'
TYPE_4P4C = '4p4c'
TYPE_4P2C = '4p2c'
TYPE_GG45 = 'gg45'
TYPE_TERA4P = 'tera-4p'
TYPE_TERA2P = 'tera-2p'
TYPE_TERA1P = 'tera-1p'
TYPE_110_PUNCH = '110-punch'
TYPE_BNC = 'bnc'
TYPE_F = 'f'
TYPE_N = 'n'
TYPE_MRJ21 = 'mrj21'
TYPE_ST = 'st'
TYPE_SC = 'sc'
TYPE_SC_PC = 'sc-pc'
TYPE_SC_UPC = 'sc-upc'
TYPE_SC_APC = 'sc-apc'
TYPE_FC = 'fc'
TYPE_LC = 'lc'
TYPE_LC_PC = 'lc-pc'
TYPE_LC_UPC = 'lc-upc'
TYPE_LC_APC = 'lc-apc'
TYPE_MTRJ = 'mtrj'
TYPE_MPO = 'mpo'
TYPE_LSH = 'lsh'
TYPE_LSH_PC = 'lsh-pc'
TYPE_LSH_UPC = 'lsh-upc'
TYPE_LSH_APC = 'lsh-apc'
TYPE_LX5 = 'lx5'
TYPE_LX5_PC = 'lx5-pc'
TYPE_LX5_UPC = 'lx5-upc'
TYPE_LX5_APC = 'lx5-apc'
TYPE_SPLICE = 'splice'
TYPE_CS = 'cs'
TYPE_SN = 'sn'
TYPE_SMA_905 = 'sma-905'
TYPE_SMA_906 = 'sma-906'
TYPE_URM_P2 = 'urm-p2'
TYPE_URM_P4 = 'urm-p4'
TYPE_URM_P8 = 'urm-p8'
TYPE_USB_A = 'usb-a'
TYPE_USB_B = 'usb-b'
TYPE_USB_C = 'usb-c'
TYPE_USB_MINI_A = 'usb-mini-a'
TYPE_USB_MINI_B = 'usb-mini-b'
TYPE_USB_MICRO_A = 'usb-micro-a'
TYPE_USB_MICRO_B = 'usb-micro-b'
TYPE_USB_MICRO_AB = 'usb-micro-ab'
TYPE_OTHER = 'other'
#
# Cables/links
#
@strawberry.enum
class CableTypeEnum(Enum):
TYPE_CAT3 = 'cat3'
TYPE_CAT5 = 'cat5'
TYPE_CAT5E = 'cat5e'
TYPE_CAT6 = 'cat6'
TYPE_CAT6A = 'cat6a'
TYPE_CAT7 = 'cat7'
TYPE_CAT7A = 'cat7a'
TYPE_CAT8 = 'cat8'
TYPE_DAC_ACTIVE = 'dac-active'
TYPE_DAC_PASSIVE = 'dac-passive'
TYPE_MRJ21_TRUNK = 'mrj21-trunk'
TYPE_COAXIAL = 'coaxial'
TYPE_MMF = 'mmf'
TYPE_MMF_OM1 = 'mmf-om1'
TYPE_MMF_OM2 = 'mmf-om2'
TYPE_MMF_OM3 = 'mmf-om3'
TYPE_MMF_OM4 = 'mmf-om4'
TYPE_MMF_OM5 = 'mmf-om5'
TYPE_SMF = 'smf'
TYPE_SMF_OS1 = 'smf-os1'
TYPE_SMF_OS2 = 'smf-os2'
TYPE_AOC = 'aoc'
TYPE_POWER = 'power'
TYPE_USB = 'usb'
@strawberry.enum
class LinkStatusEnum(Enum):
STATUS_CONNECTED = 'connected'
STATUS_PLANNED = 'planned'
STATUS_DECOMMISSIONING = 'decommissioning'
@strawberry.enum
class CableLengthUnitEnum(Enum):
# Metric
UNIT_KILOMETER = 'km'
UNIT_METER = 'm'
UNIT_CENTIMETER = 'cm'
# Imperial
UNIT_MILE = 'mi'
UNIT_FOOT = 'ft'
UNIT_INCH = 'in'
#
# CableTerminations
#
@strawberry.enum
class CableEndEnum(Enum):
SIDE_A = 'A'
SIDE_B = 'B'
#
# PowerFeeds
#
@strawberry.enum
class PowerFeedStatusEnum(Enum):
key = 'PowerFeed.status'
STATUS_OFFLINE = 'offline'
STATUS_ACTIVE = 'active'
STATUS_PLANNED = 'planned'
STATUS_FAILED = 'failed'
@strawberry.enum
class PowerFeedTypeEnum(Enum):
TYPE_PRIMARY = 'primary'
TYPE_REDUNDANT = 'redundant'
@strawberry.enum
class PowerFeedSupplyEnum(Enum):
SUPPLY_AC = 'ac'
SUPPLY_DC = 'dc'
@strawberry.enum
class PowerFeedPhaseEnum(Enum):
PHASE_SINGLE = 'single-phase'
PHASE_3PHASE = 'three-phase'
#
# VDC
#
@strawberry.enum
class VirtualDeviceContextStatusEnum(Enum):
key = 'VirtualDeviceContext.status'
STATUS_ACTIVE = 'active'
STATUS_PLANNED = 'planned'
STATUS_OFFLINE = 'offline'
#
# InventoryItem
#
@strawberry.enum
class InventoryItemStatusEnum(Enum):
key = 'InventoryItem.status'
STATUS_OFFLINE = 'offline'
STATUS_ACTIVE = 'active'
STATUS_PLANNED = 'planned'
STATUS_STAGED = 'staged'
STATUS_FAILED = 'failed'
STATUS_DECOMMISSIONING = 'decommissioning'

View File

@ -0,0 +1,138 @@
from dataclasses import dataclass
from typing import Annotated, TYPE_CHECKING
import strawberry
from strawberry import ID
import strawberry_django
from strawberry_django import FilterLookup
from core.graphql.filter_mixins import *
from netbox.graphql.filter_mixins import *
from .enums import *
if TYPE_CHECKING:
from .filters import *
from core.graphql.filter_lookups import *
from extras.graphql.filters import *
from ipam.graphql.filters import *
__all__ = [
'ComponentModelFilterMixin',
'ModularComponentModelFilterMixin',
'CabledObjectModelFilterMixin',
'ComponentTemplateFilterMixin',
'ModularComponentTemplateFilterMixin',
'RenderConfigFilterMixin',
'InterfaceBaseFilterMixin',
'RackBaseFilterMixin',
]
@dataclass
class ComponentModelFilterMixin(NetBoxModelFilterMixin):
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()
lable: FilterLookup[str] | None = strawberry_django.filter_field()
description: FilterLookup[str] | None = strawberry_django.filter_field()
@dataclass
class ModularComponentModelFilterMixin(ComponentModelFilterMixin):
module: Annotated['ModuleFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field()
module_id: ID | None = strawberry_django.filter_field()
inventory_items: Annotated['InventoryItemFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@dataclass
class CabledObjectModelFilterMixin(BaseFilterMixin):
cable: Annotated['CableFilter', strawberry.lazy('dcim.graphql.filters')] | 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 ComponentTemplateFilterMixin(ChangeLogFilterMixin):
device_type: Annotated['DeviceTypeFilter', strawberry.lazy('dcim.graphql.filters')] | 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 ModularComponentTemplateFilterMixin(ComponentTemplateFilterMixin):
module_type: Annotated['ModuleTypeFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@dataclass
class RenderConfigFilterMixin(BaseFilterMixin):
config_template: Annotated['ConfigTemplateFilter', strawberry.lazy('extras.graphql.filters')] | None = (
strawberry_django.filter_field()
)
config_template_id: ID | None = strawberry_django.filter_field()
@dataclass
class InterfaceBaseFilterMixin(BaseFilterMixin):
enabled: FilterLookup[bool] | None = strawberry_django.filter_field()
mtu: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
mode: InterfaceModeEnum | None = strawberry_django.filter_field()
parent: Annotated['InterfaceFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
parent_id: ID | None = strawberry_django.filter_field()
bridge: Annotated['InterfaceFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
bridge_id: ID | None = strawberry_django.filter_field()
untagged_vlan: Annotated['VLANFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
tagged_vlans: Annotated['VLANFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
qinq_svlan: Annotated['VLANFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
vlan_tranlation_policy: Annotated['VLANTranslationPolicyFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
primary_mac_address: Annotated['MACAddressFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
primary_mac_address_id: ID | None = strawberry_django.filter_field()
@dataclass
class RackBaseFilterMixin(WeightFilterMixin, PrimaryModelFilterMixin):
width: Annotated['RackWidthEnum', strawberry.lazy('dcim.graphql.enums')] | None = strawberry_django.filter_field()
u_height: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
starting_unit: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
desc_units: FilterLookup[bool] | None = strawberry_django.filter_field()
outer_width: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
outer_depth: Annotated['IntegerLookup', strawberry.lazy('core.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('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
max_weight: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)

View File

@ -1,7 +1,41 @@
from typing import Annotated, TYPE_CHECKING
import strawberry
from strawberry.scalars import ID
import strawberry_django
from strawberry_django import (
FilterLookup,
)
from extras.graphql.filter_mixins import (
ConfigContextFilterMixin,
)
from netbox.graphql.filter_mixins import (
PrimaryModelFilterMixin,
OrganizationalModelFilterMixin,
NestedGroupModelFilterMixin,
ImageAttachmentFilterMixin,
WeightFilterMixin,
)
from .filter_mixins import *
from dcim import models
from core.graphql.filter_mixins import *
from tenancy.graphql.filter_mixins import TenancyFilterMixin, ContactFilterMixin
if TYPE_CHECKING:
from .enums import *
from netbox.graphql.enums import *
from wireless.graphql.enums import *
from core.graphql.filter_lookups import *
from core.graphql.filters import *
from extras.graphql.filters import *
from circuits.graphql.filters import *
from dcim.graphql.filters import *
from ipam.graphql.filters import *
from tenancy.graphql.filters import *
from wireless.graphql.filters import *
from users.graphql.filters import *
from virtualization.graphql.filters import *
from vpn.graphql.filters import *
from dcim import filtersets, models
from netbox.graphql.filter_mixins import autotype_decorator, BaseFilterMixin
__all__ = (
'CableFilter',
@ -51,258 +85,766 @@ __all__ = (
@strawberry_django.filter(models.Cable, lookups=True)
@autotype_decorator(filtersets.CableFilterSet)
class CableFilter(BaseFilterMixin):
pass
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()
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('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
length_unit: Annotated['CableLengthUnitEnum', strawberry.lazy('dcim.graphql.enums')] | None = (
strawberry_django.filter_field()
)
terminations: Annotated['CableTerminationFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.CableTermination, lookups=True)
@autotype_decorator(filtersets.CableTerminationFilterSet)
class CableTerminationFilter(BaseFilterMixin):
pass
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 = (
strawberry_django.filter_field()
)
termination_type: Annotated['CableTerminationFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
termination_id: ID | None = strawberry_django.filter_field()
@strawberry_django.filter(models.ConsolePort, lookups=True)
@autotype_decorator(filtersets.ConsolePortFilterSet)
class ConsolePortFilter(BaseFilterMixin):
pass
class ConsolePortFilter(ModularComponentModelFilterMixin, CabledObjectModelFilterMixin):
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(models.ConsolePortTemplate, lookups=True)
@autotype_decorator(filtersets.ConsolePortTemplateFilterSet)
class ConsolePortTemplateFilter(BaseFilterMixin):
pass
class ConsolePortTemplateFilter(ModularComponentTemplateFilterMixin):
type: Annotated['ConsolePortTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.ConsoleServerPort, lookups=True)
@autotype_decorator(filtersets.ConsoleServerPortFilterSet)
class ConsoleServerPortFilter(BaseFilterMixin):
pass
class ConsoleServerPortFilter(ModularComponentModelFilterMixin, CabledObjectModelFilterMixin):
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(models.ConsoleServerPortTemplate, lookups=True)
@autotype_decorator(filtersets.ConsoleServerPortTemplateFilterSet)
class ConsoleServerPortTemplateFilter(BaseFilterMixin):
pass
class ConsoleServerPortTemplateFilter(ModularComponentTemplateFilterMixin):
type: Annotated['ConsolePortTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.Device, lookups=True)
@autotype_decorator(filtersets.DeviceFilterSet)
class DeviceFilter(BaseFilterMixin):
pass
class DeviceFilter(
ContactFilterMixin,
TenancyFilterMixin,
ImageAttachmentFilterMixin,
RenderConfigFilterMixin,
ConfigContextFilterMixin,
PrimaryModelFilterMixin,
):
device_type: Annotated['DeviceTypeFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
device_type_id: ID | None = strawberry_django.filter_field()
role: Annotated['DeviceRoleFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
role_id: ID | None = strawberry_django.filter_field()
platform: Annotated['PlatformFilter', strawberry.lazy('dcim.graphql.filters')] | 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['SiteFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field()
site_id: ID | None = strawberry_django.filter_field()
location: Annotated['LocationFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
location_id: Annotated['TreeNodeFilter', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
rack: Annotated['RackFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field()
rack_id: ID | None = strawberry_django.filter_field()
position: Annotated['FloatLookup', strawberry.lazy('core.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['IPAddressFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
primary_ip4_id: ID | None = strawberry_django.filter_field()
primary_ip6: Annotated['IPAddressFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
primary_ip6_id: ID | None = strawberry_django.filter_field()
oob_ip: Annotated['IPAddressFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
oob_ip_id: ID | None = strawberry_django.filter_field()
cluster: Annotated['ClusterFilter', strawberry.lazy('virtualization.graphql.filters')] | None = (
strawberry_django.filter_field()
)
cluster_id: ID | None = strawberry_django.filter_field()
virtual_chassis: Annotated['VirtualChassisFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
virtual_chassis_id: ID | None = strawberry_django.filter_field()
vc_position: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
vc_priority: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
latitude: Annotated['FloatLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
longitude: Annotated['FloatLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
interfaces: Annotated['InterfaceFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
consoleports: Annotated['ConsolePortFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
consoleserverports: Annotated['ConsoleServerPortFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
poweroutlets: Annotated['PowerOutletFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
powerports: Annotated['PowerPortFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
devicebays: Annotated['DeviceBayFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
frontports: Annotated['FrontPortFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
rearports: Annotated['RearPortFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
modulebays: Annotated['ModuleBayFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
modules: Annotated['ModuleFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.DeviceBay, lookups=True)
@autotype_decorator(filtersets.DeviceBayFilterSet)
class DeviceBayFilter(BaseFilterMixin):
pass
class DeviceBayFilter(ComponentModelFilterMixin):
installed_device: Annotated['DeviceFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
installed_device_id: ID | None = strawberry_django.filter_field()
@strawberry_django.filter(models.DeviceBayTemplate, lookups=True)
@autotype_decorator(filtersets.DeviceBayTemplateFilterSet)
class DeviceBayTemplateFilter(BaseFilterMixin):
class DeviceBayTemplateFilter(ComponentTemplateFilterMixin):
pass
@strawberry_django.filter(models.InventoryItemTemplate, lookups=True)
@autotype_decorator(filtersets.InventoryItemTemplateFilterSet)
class InventoryItemTemplateFilter(BaseFilterMixin):
pass
class InventoryItemTemplateFilter(ComponentTemplateFilterMixin):
parent: Annotated['InventoryItemTemplateFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
component_type: Annotated['ContentTypeFilter', strawberry.lazy('core.graphql.filters')] | None = (
strawberry_django.filter_field()
)
component_id: ID | None = strawberry_django.filter_field()
role: Annotated['InventoryItemRoleFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
role_id: ID | None = strawberry_django.filter_field()
manufacturer: Annotated['ManufacturerFilter', strawberry.lazy('dcim.graphql.filters')] | 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(models.DeviceRole, lookups=True)
@autotype_decorator(filtersets.DeviceRoleFilterSet)
class DeviceRoleFilter(BaseFilterMixin):
pass
class DeviceRoleFilter(OrganizationalModelFilterMixin, RenderConfigFilterMixin):
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(models.DeviceType, lookups=True)
@autotype_decorator(filtersets.DeviceTypeFilterSet)
class DeviceTypeFilter(BaseFilterMixin):
pass
class DeviceTypeFilter(ImageAttachmentFilterMixin, PrimaryModelFilterMixin, WeightFilterMixin):
manufacturer: Annotated['ManufacturerFilter', strawberry.lazy('dcim.graphql.filters')] | 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['PlatformFilter', strawberry.lazy('dcim.graphql.filters')] | 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('core.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['ImageAttachmentFilter', strawberry.lazy('extras.graphql.filters')] | None = (
strawberry_django.filter_field()
)
rear_image: Annotated['ImageAttachmentFilter', strawberry.lazy('extras.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.FrontPort, lookups=True)
@autotype_decorator(filtersets.FrontPortFilterSet)
class FrontPortFilter(BaseFilterMixin):
pass
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()
rear_port: Annotated['RearPortFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
rear_port_id: ID | None = strawberry_django.filter_field()
rear_port_position: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.FrontPortTemplate, lookups=True)
@autotype_decorator(filtersets.FrontPortTemplateFilterSet)
class FrontPortTemplateFilter(BaseFilterMixin):
pass
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()
rear_port: Annotated['RearPortTemplateFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
rear_port_id: ID | None = strawberry_django.filter_field()
rear_port_position: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.MACAddress, lookups=True)
@autotype_decorator(filtersets.MACAddressFilterSet)
class MACAddressFilter(BaseFilterMixin):
pass
class MACAddressFilter(PrimaryModelFilterMixin):
mac_address: FilterLookup[str] | None = strawberry_django.filter_field()
assigned_object_type: Annotated['ContentTypeFilter', strawberry.lazy('core.graphql.filters')] | None = (
strawberry_django.filter_field()
)
assigned_object_id: ID | None = strawberry_django.filter_field()
@strawberry_django.filter(models.Interface, lookups=True)
@autotype_decorator(filtersets.InterfaceFilterSet)
class InterfaceFilter(BaseFilterMixin):
pass
class InterfaceFilter(ModularComponentModelFilterMixin, InterfaceBaseFilterMixin, CabledObjectModelFilterMixin):
vcdcs: Annotated['VirtualDeviceContextFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
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 = (
strawberry_django.filter_field()
)
mgmt_only: FilterLookup[bool] | None = strawberry_django.filter_field()
speed: Annotated['IntegerLookup', strawberry.lazy('core.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()
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('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
rf_channel_width: Annotated['FloatLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
tx_power: Annotated['IntegerLookup', strawberry.lazy('core.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['WirelessLinkFilter', strawberry.lazy('wireless.graphql.filters')] | None = (
strawberry_django.filter_field()
)
wireless_link_id: ID | None = strawberry_django.filter_field()
wireless_lans: Annotated['WirelessLANFilter', strawberry.lazy('wireless.graphql.filters')] | None = (
strawberry_django.filter_field()
)
vrf: Annotated['VRFFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field()
vrf_id: ID | None = strawberry_django.filter_field()
ip_addresses: Annotated['IPAddressFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
mac_addresses: Annotated['MACAddressFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
fhrp_group_assignments: Annotated['FHRPGroupAssignmentFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
tunnel_terminations: Annotated['TunnelTerminationFilter', strawberry.lazy('vpn.graphql.filters')] | None = (
strawberry_django.filter_field()
)
l2vpn_terminations: Annotated['L2VPNFilter', strawberry.lazy('vpn.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.InterfaceTemplate, lookups=True)
@autotype_decorator(filtersets.InterfaceTemplateFilterSet)
class InterfaceTemplateFilter(BaseFilterMixin):
pass
class InterfaceTemplateFilter(ModularComponentTemplateFilterMixin):
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['InterfaceTemplateFilter', strawberry.lazy('dcim.graphql.filters')] | 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(models.InventoryItem, lookups=True)
@autotype_decorator(filtersets.InventoryItemFilterSet)
class InventoryItemFilter(BaseFilterMixin):
pass
class InventoryItemFilter(ComponentModelFilterMixin):
parent: Annotated['InventoryItemFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
parent_id: ID | None = strawberry_django.filter_field()
component_type: Annotated['ContentTypeFilter', strawberry.lazy('core.graphql.filters')] | 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['InventoryItemRoleFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
role_id: ID | None = strawberry_django.filter_field()
manufacturer: Annotated['ManufacturerFilter', strawberry.lazy('dcim.graphql.filters')] | 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(models.InventoryItemRole, lookups=True)
@autotype_decorator(filtersets.InventoryItemRoleFilterSet)
class InventoryItemRoleFilter(BaseFilterMixin):
pass
class InventoryItemRoleFilter(OrganizationalModelFilterMixin):
color: Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')] | None = strawberry_django.filter_field()
@strawberry_django.filter(models.Location, lookups=True)
@autotype_decorator(filtersets.LocationFilterSet)
class LocationFilter(BaseFilterMixin):
pass
class LocationFilter(ContactFilterMixin, ImageAttachmentFilterMixin, 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 = (
strawberry_django.filter_field()
)
tenant: Annotated['TenantFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
tenant_id: ID | None = strawberry_django.filter_field()
facility: FilterLookup[str] | None = strawberry_django.filter_field()
prefixes: Annotated['PrefixFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
vlan_groups: Annotated['VLANGroupFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.Manufacturer, lookups=True)
@autotype_decorator(filtersets.ManufacturerFilterSet)
class ManufacturerFilter(BaseFilterMixin):
class ManufacturerFilter(ContactFilterMixin, OrganizationalModelFilterMixin):
pass
@strawberry_django.filter(models.Module, lookups=True)
@autotype_decorator(filtersets.ModuleFilterSet)
class ModuleFilter(BaseFilterMixin):
pass
class ModuleFilter(PrimaryModelFilterMixin, ConfigContextFilterMixin):
device: Annotated['DeviceFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field()
device_id: ID | None = strawberry_django.filter_field()
module_bay: Annotated['ModuleBayFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
module_bay_id: ID | None = strawberry_django.filter_field()
module_type: Annotated['ModuleTypeFilter', strawberry.lazy('dcim.graphql.filters')] | 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()
@strawberry_django.filter(models.ModuleBay, lookups=True)
@autotype_decorator(filtersets.ModuleBayFilterSet)
class ModuleBayFilter(BaseFilterMixin):
pass
class ModuleBayFilter(ModularComponentModelFilterMixin):
parent: Annotated['ModuleBayFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
parent_id: ID | None = strawberry_django.filter_field()
position: FilterLookup[str] | None = strawberry_django.filter_field()
@strawberry_django.filter(models.ModuleBayTemplate, lookups=True)
@autotype_decorator(filtersets.ModuleBayTemplateFilterSet)
class ModuleBayTemplateFilter(BaseFilterMixin):
pass
class ModuleBayTemplateFilter(ModularComponentTemplateFilterMixin):
position: FilterLookup[str] | None = strawberry_django.filter_field()
@strawberry_django.filter(models.ModuleType, lookups=True)
@autotype_decorator(filtersets.ModuleTypeFilterSet)
class ModuleTypeFilter(BaseFilterMixin):
pass
class ModuleTypeFilter(ImageAttachmentFilterMixin, PrimaryModelFilterMixin, WeightFilterMixin):
manufacturer: Annotated['ManufacturerFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
manufacturer_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()
)
@strawberry_django.filter(models.Platform, lookups=True)
@autotype_decorator(filtersets.PlatformFilterSet)
class PlatformFilter(BaseFilterMixin):
pass
class PlatformFilter(OrganizationalModelFilterMixin):
manufacturer: Annotated['ManufacturerFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
manufacturer_id: ID | None = strawberry_django.filter_field()
config_template: Annotated['ConfigTemplateFilter', strawberry.lazy('extras.graphql.filters')] | None = (
strawberry_django.filter_field()
)
config_template_id: ID | None = strawberry_django.filter_field()
@strawberry_django.filter(models.PowerFeed, lookups=True)
@autotype_decorator(filtersets.PowerFeedFilterSet)
class PowerFeedFilter(BaseFilterMixin):
pass
class PowerFeedFilter(PrimaryModelFilterMixin, CabledObjectModelFilterMixin):
power_panel: Annotated['PowerPanelFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
power_panel_id: ID | None = strawberry_django.filter_field()
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 = (
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('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
amperage: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
max_utilization: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
available_power: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
tenant: Annotated['TenantFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
tenant_id: ID | None = strawberry_django.filter_field()
@strawberry_django.filter(models.PowerOutlet, lookups=True)
@autotype_decorator(filtersets.PowerOutletFilterSet)
class PowerOutletFilter(BaseFilterMixin):
pass
class PowerOutletFilter(ModularComponentModelFilterMixin, CabledObjectModelFilterMixin):
type: 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 = (
strawberry_django.filter_field()
)
color: Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')] | None = strawberry_django.filter_field()
@strawberry_django.filter(models.PowerOutletTemplate, lookups=True)
@autotype_decorator(filtersets.PowerOutletTemplateFilterSet)
class PowerOutletTemplateFilter(BaseFilterMixin):
pass
class PowerOutletTemplateFilter(ModularComponentModelFilterMixin):
type: 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 = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.PowerPanel, lookups=True)
@autotype_decorator(filtersets.PowerPanelFilterSet)
class PowerPanelFilter(BaseFilterMixin):
pass
class PowerPanelFilter(ContactFilterMixin, ImageAttachmentFilterMixin, PrimaryModelFilterMixin):
site: Annotated['SiteFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field()
site_id: ID | None = strawberry_django.filter_field()
location: Annotated['LocationFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
location_id: Annotated['TreeNodeFilter', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
name: FilterLookup[str] | None = strawberry_django.filter_field()
@strawberry_django.filter(models.PowerPort, lookups=True)
@autotype_decorator(filtersets.PowerPortFilterSet)
class PowerPortFilter(BaseFilterMixin):
pass
class PowerPortFilter(ModularComponentModelFilterMixin, CabledObjectModelFilterMixin):
type: Annotated['PowerPortTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = (
strawberry_django.filter_field()
)
maximum_draw: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
allocated_draw: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.PowerPortTemplate, lookups=True)
@autotype_decorator(filtersets.PowerPortTemplateFilterSet)
class PowerPortTemplateFilter(BaseFilterMixin):
pass
class PowerPortTemplateFilter(ModularComponentTemplateFilterMixin):
type: Annotated['PowerPortTypeEnum', strawberry.lazy('dcim.graphql.enums')] | None = (
strawberry_django.filter_field()
)
maximum_draw: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
allocated_draw: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.RackType, lookups=True)
@autotype_decorator(filtersets.RackTypeFilterSet)
class RackTypeFilter(BaseFilterMixin):
pass
class RackTypeFilter(RackBaseFilterMixin):
form_factor: Annotated['RackFormFactorEnum', strawberry.lazy('dcim.graphql.enums')] | None = (
strawberry_django.filter_field()
)
manufacturer: Annotated['ManufacturerFilter', strawberry.lazy('dcim.graphql.filters')] | 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(models.Rack, lookups=True)
@autotype_decorator(filtersets.RackFilterSet)
class RackFilter(BaseFilterMixin):
pass
class RackFilter(ContactFilterMixin, ImageAttachmentFilterMixin, RackBaseFilterMixin):
form_factor: Annotated['RackFormFactorEnum', strawberry.lazy('dcim.graphql.enums')] | None = (
strawberry_django.filter_field()
)
rack_type: Annotated['RackTypeFilter', strawberry.lazy('dcim.graphql.filters')] | 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['SiteFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field()
site_id: ID | None = strawberry_django.filter_field()
location: Annotated['LocationFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
location_id: Annotated['TreeNodeFilter', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
tenant: Annotated['TenantFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
tenant_id: ID | None = strawberry_django.filter_field()
status: 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 = (
strawberry_django.filter_field()
)
vlan_groups: Annotated['VLANGroupFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.RackReservation, lookups=True)
@autotype_decorator(filtersets.RackReservationFilterSet)
class RackReservationFilter(BaseFilterMixin):
pass
class RackReservationFilter(PrimaryModelFilterMixin):
rack: Annotated['RackFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field()
rack_id: ID | None = strawberry_django.filter_field()
units: Annotated['IntegerArrayLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
tenant: Annotated['TenantFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
tenant_id: ID | None = strawberry_django.filter_field()
user: Annotated['UserFilter', strawberry.lazy('users.graphql.filters')] | None = strawberry_django.filter_field()
user_id: ID | None = strawberry_django.filter_field()
description: FilterLookup[str] | None = strawberry_django.filter_field()
@strawberry_django.filter(models.RackRole, lookups=True)
@autotype_decorator(filtersets.RackRoleFilterSet)
class RackRoleFilter(BaseFilterMixin):
pass
class RackRoleFilter(OrganizationalModelFilterMixin):
color: Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')] | None = strawberry_django.filter_field()
@strawberry_django.filter(models.RearPort, lookups=True)
@autotype_decorator(filtersets.RearPortFilterSet)
class RearPortFilter(BaseFilterMixin):
pass
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()
positions: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.RearPortTemplate, lookups=True)
@autotype_decorator(filtersets.RearPortTemplateFilterSet)
class RearPortTemplateFilter(BaseFilterMixin):
pass
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()
positions: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.Region, lookups=True)
@autotype_decorator(filtersets.RegionFilterSet)
class RegionFilter(BaseFilterMixin):
pass
class RegionFilter(ContactFilterMixin, NestedGroupModelFilterMixin):
prefixes: Annotated['PrefixFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
vlan_groups: Annotated['VLANGroupFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.Site, lookups=True)
@autotype_decorator(filtersets.SiteFilterSet)
class SiteFilter(BaseFilterMixin):
pass
class SiteFilter(ContactFilterMixin, ImageAttachmentFilterMixin, 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()
region: Annotated['RegionFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field()
region_id: Annotated['TreeNodeFilter', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
group: Annotated['SiteGroupFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
group_id: Annotated['TreeNodeFilter', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
tenant: Annotated['TenantFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
tenant_id: ID | None = strawberry_django.filter_field()
facility: FilterLookup[str] | None = strawberry_django.filter_field()
asns: Annotated['ASNFilter', strawberry.lazy('ipam.graphql.filters')] | 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('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
longitude: Annotated['FloatLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
prefixes: Annotated['PrefixFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
vlan_groups: Annotated['VLANGroupFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.SiteGroup, lookups=True)
@autotype_decorator(filtersets.SiteGroupFilterSet)
class SiteGroupFilter(BaseFilterMixin):
pass
class SiteGroupFilter(ContactFilterMixin, NestedGroupModelFilterMixin):
prefixes: Annotated['PrefixFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
vlan_groups: Annotated['VLANGroupFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.VirtualChassis, lookups=True)
@autotype_decorator(filtersets.VirtualChassisFilterSet)
class VirtualChassisFilter(BaseFilterMixin):
pass
class VirtualChassisFilter(PrimaryModelFilterMixin):
master: Annotated['DeviceFilter', strawberry.lazy('dcim.graphql.filters')] | 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()
@strawberry_django.filter(models.VirtualDeviceContext, lookups=True)
@autotype_decorator(filtersets.VirtualDeviceContextFilterSet)
class VirtualDeviceContextFilter(BaseFilterMixin):
pass
class VirtualDeviceContextFilter(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 = (
strawberry_django.filter_field()
)
identifier: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
primary_ip4: Annotated['IPAddressFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
primary_ip4_id: ID | None = strawberry_django.filter_field()
primary_ip6: Annotated['IPAddressFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
primary_ip6_id: ID | None = strawberry_django.filter_field()
tenant: Annotated['TenantFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
tenant_id: ID | None = strawberry_django.filter_field()
comments: FilterLookup[str] | None = strawberry_django.filter_field()

View File

@ -0,0 +1,190 @@
from enum import Enum
import strawberry
__all__ = [
'CustomFieldTypeEnum',
'CustomFieldFilterLogicEnum',
'CustomFieldUIVisibleEnum',
'CustomFieldUIEditableEnum',
'CustomFieldChoiceSetBaseEnum',
'CustomLinkButtonClassEnum',
'BookmarkOrderingEnum',
'JournalEntryKindEnum',
'LogLevelEnum',
'DurationEnum',
'WebhookHttpMethodEnum',
'ChangeActionEnum',
'DashboardWidgetColorEnum',
'EventRuleActionEnum',
]
#
# CustomFields
#
@strawberry.enum
class CustomFieldTypeEnum(Enum):
TYPE_TEXT = 'text'
TYPE_LONGTEXT = 'longtext'
TYPE_INTEGER = 'integer'
TYPE_DECIMAL = 'decimal'
TYPE_BOOLEAN = 'boolean'
TYPE_DATE = 'date'
TYPE_DATETIME = 'datetime'
TYPE_URL = 'url'
TYPE_JSON = 'json'
TYPE_SELECT = 'select'
TYPE_MULTISELECT = 'multiselect'
TYPE_OBJECT = 'object'
TYPE_MULTIOBJECT = 'multiobject'
@strawberry.enum
class CustomFieldFilterLogicEnum(Enum):
FILTER_DISABLED = 'disabled'
FILTER_LOOSE = 'loose'
FILTER_EXACT = 'exact'
@strawberry.enum
class CustomFieldUIVisibleEnum(Enum):
ALWAYS = 'always'
IF_SET = 'if-set'
HIDDEN = 'hidden'
@strawberry.enum
class CustomFieldUIEditableEnum(Enum):
YES = 'yes'
NO = 'no'
HIDDEN = 'hidden'
@strawberry.enum
class CustomFieldChoiceSetBaseEnum(Enum):
IATA = 'IATA'
ISO_3166 = 'ISO_3166'
UN_LOCODE = 'UN_LOCODE'
#
# CustomLinks
#
@strawberry.enum
class CustomLinkButtonClassEnum(Enum):
LINK = 'ghost-dark'
#
# Bookmarks
#
@strawberry.enum
class BookmarkOrderingEnum(Enum):
ORDERING_NEWEST = '-created'
ORDERING_OLDEST = 'created'
ORDERING_ALPHABETICAL_AZ = 'name'
ORDERING_ALPHABETICAL_ZA = '-name'
#
# Journal entries
#
@strawberry.enum
class JournalEntryKindEnum(Enum):
key = 'JournalEntry.kind'
KIND_INFO = 'info'
KIND_SUCCESS = 'success'
KIND_WARNING = 'warning'
KIND_DANGER = 'danger'
#
# Reports and Scripts
#
@strawberry.enum
class LogLevelEnum(Enum):
LOG_DEBUG = 'debug'
LOG_DEFAULT = 'default'
LOG_INFO = 'info'
LOG_SUCCESS = 'success'
LOG_WARNING = 'warning'
LOG_FAILURE = 'failure'
@strawberry.enum
class DurationEnum(Enum):
HOURLY = 60
TWELVE_HOURS = 720
DAILY = 1440
WEEKLY = 10080
THIRTY_DAYS = 43200
#
# Webhooks
#
@strawberry.enum
class WebhookHttpMethodEnum(Enum):
METHOD_GET = 'GET'
METHOD_POST = 'POST'
METHOD_PUT = 'PUT'
METHOD_PATCH = 'PATCH'
METHOD_DELETE = 'DELETE'
#
# Staging
#
@strawberry.enum
class ChangeActionEnum(Enum):
ACTION_CREATE = 'create'
ACTION_UPDATE = 'update'
ACTION_DELETE = 'delete'
#
# Dashboard widgets
#
@strawberry.enum
class DashboardWidgetColorEnum(Enum):
BLUE = 'blue'
INDIGO = 'indigo'
PURPLE = 'purple'
PINK = 'pink'
RED = 'red'
ORANGE = 'orange'
YELLOW = 'yellow'
GREEN = 'green'
TEAL = 'teal'
CYAN = 'cyan'
GRAY = 'gray'
BLACK = 'black'
WHITE = 'white'
#
# Event Rules
#
@strawberry.enum
class EventRuleActionEnum(Enum):
WEBHOOK = 'webhook'
SCRIPT = 'script'
NOTIFICATION = 'notification'

View File

@ -0,0 +1,53 @@
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 import BaseFilterMixin
if TYPE_CHECKING:
from core.graphql.filter_lookups import *
from .filters import *
__all__ = [
'CustomFieldsFilterMixin',
'JournalEntriesFilterMixin',
'TagsFilterMixin',
'ConfigContextFilterMixin',
'TagBaseFilterMixin',
]
@dataclass
class CustomFieldsFilterMixin(BaseFilterMixin):
custom_field_data: Annotated['JSONFilter', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
@dataclass
class JournalEntriesFilterMixin(BaseFilterMixin):
journal_entries: Annotated['JournalEntryFilter', strawberry.lazy('extras.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@dataclass
class TagsFilterMixin(BaseFilterMixin):
tags: Annotated['TagFilter', strawberry.lazy('extras.graphql.filters')] | None = strawberry_django.filter_field()
@dataclass
class ConfigContextFilterMixin(BaseFilterMixin):
local_config_context: Annotated['ConfigContextFilter', strawberry.lazy('extras.graphql.filters')] | None = (
strawberry_django.filter_field()
)
config_context: Annotated['ConfigContextFilter', strawberry.lazy('extras.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@dataclass
class TagBaseFilterMixin(BaseFilterMixin):
name: FilterLookup[str] | None = strawberry_django.filter_field()
slug: FilterLookup[str] | None = strawberry_django.filter_field()

View File

@ -1,7 +1,33 @@
from typing import Annotated, TYPE_CHECKING
import strawberry
from strawberry.scalars import ID
import strawberry_django
from strawberry_django import (
FilterLookup,
)
from netbox.graphql.filter_mixins import (
BaseObjectTypeFilterMixin,
ChangeLogFilterMixin,
SyncedDataFilterMixin,
)
from extras import models
from extras.graphql.filter_mixins import TagBaseFilterMixin, CustomFieldsFilterMixin, TagsFilterMixin
if TYPE_CHECKING:
from .enums import *
from netbox.graphql.enums import *
from wireless.graphql.enums import *
from core.graphql.filter_lookups import *
from extras.graphql.filters import *
from circuits.graphql.filters import *
from dcim.graphql.filters import *
from ipam.graphql.filters import *
from tenancy.graphql.filters import *
from wireless.graphql.filters import *
from users.graphql.filters import *
from virtualization.graphql.filters import *
from vpn.graphql.filters import *
from extras import filtersets, models
from netbox.graphql.filter_mixins import autotype_decorator, BaseFilterMixin
__all__ = (
'ConfigContextFilter',
@ -21,78 +47,253 @@ __all__ = (
@strawberry_django.filter(models.ConfigContext, lookups=True)
@autotype_decorator(filtersets.ConfigContextFilterSet)
class ConfigContextFilter(BaseFilterMixin):
pass
class ConfigContextFilter(BaseObjectTypeFilterMixin, SyncedDataFilterMixin, ChangeLogFilterMixin):
name: FilterLookup[str] = strawberry_django.filter_field()
weight: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
description: FilterLookup[str] = strawberry_django.filter_field()
is_active: FilterLookup[bool] = strawberry_django.filter_field()
regions: Annotated['RegionFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
region_id: Annotated['TreeNodeFilter', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
site_groups: Annotated['SiteGroupFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
site_group_id: Annotated['TreeNodeFilter', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
sites: Annotated['SiteFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field()
locations: Annotated['LocationFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
device_types: Annotated['DeviceTypeFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
roles: Annotated['DeviceRoleFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
platforms: Annotated['PlatformFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
cluster_types: Annotated['ClusterTypeFilter', strawberry.lazy('virtualization.graphql.filters')] | None = (
strawberry_django.filter_field()
)
cluster_groups: Annotated['ClusterGroupFilter', strawberry.lazy('virtualization.graphql.filters')] | None = (
strawberry_django.filter_field()
)
clusters: Annotated['ClusterFilter', strawberry.lazy('virtualization.graphql.filters')] | None = (
strawberry_django.filter_field()
)
tenant_groups: Annotated['TenantGroupFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
tenant_group_id: Annotated['TreeNodeFilter', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
tenants: Annotated['TenantFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
tags: Annotated['TagFilter', strawberry.lazy('extras.graphql.filters')] | None = strawberry_django.filter_field()
data: Annotated['JSONFilter', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.ConfigTemplate, lookups=True)
@autotype_decorator(filtersets.ConfigTemplateFilterSet)
class ConfigTemplateFilter(BaseFilterMixin):
pass
class ConfigTemplateFilter(BaseObjectTypeFilterMixin, SyncedDataFilterMixin, ChangeLogFilterMixin):
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('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.CustomField, lookups=True)
@autotype_decorator(filtersets.CustomFieldFilterSet)
class CustomFieldFilter(BaseFilterMixin):
pass
class CustomFieldFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin):
type: Annotated['CustomFieldTypeEnum', strawberry.lazy('extras.graphql.enums')] | None = (
strawberry_django.filter_field()
)
related_object_type_id: ID | 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('core.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('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
related_object_filter: Annotated['JSONFilter', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
weight: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
validation_minimum: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
validation_maximum: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
validation_regex: FilterLookup[str] | None = strawberry_django.filter_field()
choice_set: Annotated['CustomFieldChoiceSetFilter', strawberry.lazy('extras.graphql.filters')] | 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(models.CustomFieldChoiceSet, lookups=True)
@autotype_decorator(filtersets.CustomFieldChoiceSetFilterSet)
class CustomFieldChoiceSetFilter(BaseFilterMixin):
pass
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 = (
strawberry_django.filter_field()
)
extra_choices: Annotated['StringArrayLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
order_alphabetically: FilterLookup[bool] | None = strawberry_django.filter_field()
@strawberry_django.filter(models.CustomLink, lookups=True)
@autotype_decorator(filtersets.CustomLinkFilterSet)
class CustomLinkFilter(BaseFilterMixin):
pass
class CustomLinkFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin):
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('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
group_name: FilterLookup[str] | None = strawberry_django.filter_field()
button_class: FilterLookup[str] | None = strawberry_django.filter_field()
new_window: FilterLookup[bool] | None = strawberry_django.filter_field()
@strawberry_django.filter(models.ExportTemplate, lookups=True)
@autotype_decorator(filtersets.ExportTemplateFilterSet)
class ExportTemplateFilter(BaseFilterMixin):
pass
class ExportTemplateFilter(BaseObjectTypeFilterMixin, SyncedDataFilterMixin, ChangeLogFilterMixin):
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()
mime_type: 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(models.ImageAttachment, lookups=True)
@autotype_decorator(filtersets.ImageAttachmentFilterSet)
class ImageAttachmentFilter(BaseFilterMixin):
pass
class ImageAttachmentFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin):
object_id: ID | None = strawberry_django.filter_field()
image_height: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
image_width: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
name: FilterLookup[str] | None = strawberry_django.filter_field()
@strawberry_django.filter(models.JournalEntry, lookups=True)
@autotype_decorator(filtersets.JournalEntryFilterSet)
class JournalEntryFilter(BaseFilterMixin):
pass
class JournalEntryFilter(BaseObjectTypeFilterMixin, CustomFieldsFilterMixin, TagsFilterMixin, ChangeLogFilterMixin):
assigned_object_type: Annotated['ContentTypeFilter', strawberry.lazy('core.graphql.filters')] | 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['UserFilter', strawberry.lazy('users.graphql.filters')] | 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(models.NotificationGroup, lookups=True)
@autotype_decorator(filtersets.NotificationGroupFilterSet)
class NotificationGroupFilter(BaseFilterMixin):
pass
class NotificationGroupFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin):
name: FilterLookup[str] | None = strawberry_django.filter_field()
description: FilterLookup[str] | None = strawberry_django.filter_field()
groups: Annotated['GroupFilter', strawberry.lazy('users.graphql.filters')] | None = strawberry_django.filter_field()
users: Annotated['UserFilter', strawberry.lazy('users.graphql.filters')] | None = strawberry_django.filter_field()
@strawberry_django.filter(models.SavedFilter, lookups=True)
@autotype_decorator(filtersets.SavedFilterFilterSet)
class SavedFilterFilter(BaseFilterMixin):
pass
class SavedFilterFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin):
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['UserFilter', strawberry.lazy('users.graphql.filters')] | None = strawberry_django.filter_field()
user_id: ID | None = strawberry_django.filter_field()
weight: Annotated['IntegerLookup', strawberry.lazy('core.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('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.Tag, lookups=True)
@autotype_decorator(filtersets.TagFilterSet)
class TagFilter(BaseFilterMixin):
pass
class TagFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin, TagBaseFilterMixin):
color: Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')] | None = strawberry_django.filter_field()
description: FilterLookup[str] | None = strawberry_django.filter_field()
@strawberry_django.filter(models.Webhook, lookups=True)
@autotype_decorator(filtersets.WebhookFilterSet)
class WebhookFilter(BaseFilterMixin):
pass
class WebhookFilter(BaseObjectTypeFilterMixin, CustomFieldsFilterMixin, TagsFilterMixin, ChangeLogFilterMixin):
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['EventRuleFilter', strawberry.lazy('extras.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.EventRule, lookups=True)
@autotype_decorator(filtersets.EventRuleFilterSet)
class EventRuleFilter(BaseFilterMixin):
pass
class EventRuleFilter(BaseObjectTypeFilterMixin, CustomFieldsFilterMixin, TagsFilterMixin, ChangeLogFilterMixin):
name: FilterLookup[str] | None = strawberry_django.filter_field()
description: FilterLookup[str] | None = strawberry_django.filter_field()
event_types: Annotated['StringArrayLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
enabled: FilterLookup[bool] | None = strawberry_django.filter_field()
conditions: Annotated['JSONFilter', strawberry.lazy('core.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('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
comments: FilterLookup[str] | None = strawberry_django.filter_field()

View File

@ -0,0 +1,132 @@
from enum import Enum
import strawberry
__all__ = [
'IPAddressFamilyEnum',
'PrefixStatusEnum',
'IPRangeStatusEnum',
'IPAddressStatusEnum',
'IPAddressRoleEnum',
'FHRPGroupProtocolEnum',
'FHRPGroupAuthTypeEnum',
'VLANStatusEnum',
'VLANQinQRoleEnum',
'ServiceProtocolEnum',
]
@strawberry.enum
class IPAddressFamilyEnum(Enum):
FAMILY_4 = 4
FAMILY_6 = 6
#
# Prefixes
#
@strawberry.enum
class PrefixStatusEnum(Enum):
key = 'Prefix.status'
STATUS_CONTAINER = 'container'
STATUS_ACTIVE = 'active'
STATUS_RESERVED = 'reserved'
STATUS_DEPRECATED = 'deprecated'
#
# IP Ranges
#
@strawberry.enum
class IPRangeStatusEnum(Enum):
key = 'IPRange.status'
STATUS_ACTIVE = 'active'
STATUS_RESERVED = 'reserved'
STATUS_DEPRECATED = 'deprecated'
#
# IP Addresses
#
@strawberry.enum
class IPAddressStatusEnum(Enum):
key = 'IPAddress.status'
STATUS_ACTIVE = 'active'
STATUS_RESERVED = 'reserved'
STATUS_DEPRECATED = 'deprecated'
STATUS_DHCP = 'dhcp'
STATUS_SLAAC = 'slaac'
@strawberry.enum
class IPAddressRoleEnum(Enum):
ROLE_LOOPBACK = 'loopback'
ROLE_SECONDARY = 'secondary'
ROLE_ANYCAST = 'anycast'
ROLE_VIP = 'vip'
ROLE_VRRP = 'vrrp'
ROLE_HSRP = 'hsrp'
ROLE_GLBP = 'glbp'
ROLE_CARP = 'carp'
#
# FHRP
#
@strawberry.enum
class FHRPGroupProtocolEnum(Enum):
PROTOCOL_VRRP2 = 'vrrp2'
PROTOCOL_VRRP3 = 'vrrp3'
PROTOCOL_HSRP = 'hsrp'
PROTOCOL_GLBP = 'glbp'
PROTOCOL_CARP = 'carp'
PROTOCOL_CLUSTERXL = 'clusterxl'
PROTOCOL_OTHER = 'other'
@strawberry.enum
class FHRPGroupAuthTypeEnum(Enum):
AUTHENTICATION_PLAINTEXT = 'plaintext'
AUTHENTICATION_MD5 = 'md5'
#
# VLANs
#
@strawberry.enum
class VLANStatusEnum(Enum):
key = 'VLAN.status'
STATUS_ACTIVE = 'active'
STATUS_RESERVED = 'reserved'
STATUS_DEPRECATED = 'deprecated'
@strawberry.enum
class VLANQinQRoleEnum(Enum):
ROLE_SERVICE = 'svlan'
ROLE_CUSTOMER = 'cvlan'
#
# Services
#
@strawberry.enum
class ServiceProtocolEnum(Enum):
PROTOCOL_TCP = 'tcp'
PROTOCOL_UDP = 'udp'
PROTOCOL_SCTP = 'sctp'

View File

@ -0,0 +1,22 @@
from dataclasses import dataclass
from typing import Annotated, TYPE_CHECKING
import strawberry
import strawberry_django
from core.graphql.filter_mixins import *
if TYPE_CHECKING:
from .enums import *
from core.graphql.filter_lookups import *
__all__ = ['ServiceBaseFilterMixin']
@dataclass
class ServiceBaseFilterMixin(BaseFilterMixin):
protocol: Annotated['ServiceProtocolEnum', strawberry.lazy('ipam.graphql.enums')] | None = (
strawberry_django.filter_field()
)
ports: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)

View File

@ -1,7 +1,37 @@
from datetime import date
from typing import Annotated, TYPE_CHECKING
import netaddr
from netaddr.core import AddrFormatError
from django.db.models import Q
import strawberry
from strawberry.scalars import ID
import strawberry_django
from strawberry_django import (
FilterLookup,
DateFilterLookup,
)
from core.graphql.filter_mixins import *
from netbox.graphql.filter_mixins import *
from tenancy.graphql.filter_mixins import *
from ipam import filtersets, models
from netbox.graphql.filter_mixins import autotype_decorator, BaseFilterMixin
from ipam import models
from ipam.graphql.filter_mixins import *
if TYPE_CHECKING:
from .enums import *
from netbox.graphql.enums import *
from wireless.graphql.enums import *
from core.graphql.filter_lookups import *
from core.graphql.filters import *
from extras.graphql.filters import *
from circuits.graphql.filters import *
from dcim.graphql.filters import *
from ipam.graphql.filters import *
from tenancy.graphql.filters import *
from wireless.graphql.filters import *
from users.graphql.filters import *
from virtualization.graphql.filters import *
from vpn.graphql.filters import *
__all__ = (
'ASNFilter',
@ -26,108 +56,303 @@ __all__ = (
@strawberry_django.filter(models.ASN, lookups=True)
@autotype_decorator(filtersets.ASNFilterSet)
class ASNFilter(BaseFilterMixin):
pass
class ASNFilter(PrimaryModelFilterMixin):
rir: Annotated['RIRFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field()
rir_id: ID | None = strawberry_django.filter_field()
asn: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
tenant: Annotated['TenantFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
tenant_id: ID | None = strawberry_django.filter_field()
@strawberry_django.filter(models.ASNRange, lookups=True)
@autotype_decorator(filtersets.ASNRangeFilterSet)
class ASNRangeFilter(BaseFilterMixin):
pass
class ASNRangeFilter(OrganizationalModelFilterMixin):
name: FilterLookup[str] | None = strawberry_django.filter_field()
slug: FilterLookup[str] | None = strawberry_django.filter_field()
rir: Annotated['RIRFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field()
rir_id: ID | None = strawberry_django.filter_field()
start: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
end: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
tenant: Annotated['TenantFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
tenant_id: ID | None = strawberry_django.filter_field()
@strawberry_django.filter(models.Aggregate, lookups=True)
@autotype_decorator(filtersets.AggregateFilterSet)
class AggregateFilter(BaseFilterMixin):
pass
class AggregateFilter(ContactFilterMixin, PrimaryModelFilterMixin):
prefix: Annotated['PrefixFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field()
prefix_id: ID | None = strawberry_django.filter_field()
rir: Annotated['RIRFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field()
rir_id: ID | None = strawberry_django.filter_field()
tenant: Annotated['TenantFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
tenant_id: ID | None = strawberry_django.filter_field()
date_added: DateFilterLookup[date] | None = strawberry_django.filter_field()
@strawberry_django.filter(models.FHRPGroup, lookups=True)
@autotype_decorator(filtersets.FHRPGroupFilterSet)
class FHRPGroupFilter(BaseFilterMixin):
pass
class FHRPGroupFilter(PrimaryModelFilterMixin):
group_id: Annotated['IntegerLookup', strawberry.lazy('core.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['IPAddressFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.FHRPGroupAssignment, lookups=True)
@autotype_decorator(filtersets.FHRPGroupAssignmentFilterSet)
class FHRPGroupAssignmentFilter(BaseFilterMixin):
pass
class FHRPGroupAssignmentFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin):
inteface_type: Annotated['ContentTypeFilter', strawberry.lazy('core.graphql.filters')] | None = (
strawberry_django.filter_field()
)
interface_id: FilterLookup[str] | None = strawberry_django.filter_field()
group: Annotated['FHRPGroupFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
group_id: ID | None = strawberry_django.filter_field()
priority: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.IPAddress, lookups=True)
@autotype_decorator(filtersets.IPAddressFilterSet)
class IPAddressFilter(BaseFilterMixin):
pass
class IPAddressFilter(ContactFilterMixin, PrimaryModelFilterMixin):
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()
tenant: Annotated['TenantFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
tenant_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['ContentTypeFilter', strawberry.lazy('core.graphql.filters')] | None = (
strawberry_django.filter_field()
)
assigned_object_id: ID | None = strawberry_django.filter_field()
nat_inside: Annotated['IPAddressFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
nat_inside_id: ID | None = strawberry_django.filter_field()
nat_outside: Annotated['IPAddressFilter', strawberry.lazy('ipam.graphql.filters')] | 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 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(models.IPRange, lookups=True)
@autotype_decorator(filtersets.IPRangeFilterSet)
class IPRangeFilter(BaseFilterMixin):
pass
class IPRangeFilter(ContactFilterMixin, PrimaryModelFilterMixin):
start_address: FilterLookup[str] | None = strawberry_django.filter_field()
end_address: FilterLookup[str] | None = strawberry_django.filter_field()
size: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | 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()
tenant: Annotated['TenantFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
tenant_id: ID | None = strawberry_django.filter_field()
status: Annotated['IPRangeStatusEnum', strawberry.lazy('ipam.graphql.enums')] | None = (
strawberry_django.filter_field()
)
role: Annotated['IPAddressRoleEnum', strawberry.lazy('ipam.graphql.enums')] | 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(models.Prefix, lookups=True)
@autotype_decorator(filtersets.PrefixFilterSet)
class PrefixFilter(BaseFilterMixin):
pass
class PrefixFilter(ContactFilterMixin, PrimaryModelFilterMixin):
prefix: 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()
tenant: Annotated['TenantFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
tenant_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 = (
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()
is_pool: FilterLookup[bool] | None = strawberry_django.filter_field()
mark_utilized: FilterLookup[bool] | None = strawberry_django.filter_field()
scope_type: Annotated['ContentTypeFilter', strawberry.lazy('core.graphql.filters')] | None = (
strawberry_django.filter_field()
)
scope_id: ID | None = strawberry_django.filter_field()
@strawberry_django.filter(models.RIR, lookups=True)
@autotype_decorator(filtersets.RIRFilterSet)
class RIRFilter(BaseFilterMixin):
pass
class RIRFilter(OrganizationalModelFilterMixin):
is_private: FilterLookup[bool] | None = strawberry_django.filter_field()
@strawberry_django.filter(models.Role, lookups=True)
@autotype_decorator(filtersets.RoleFilterSet)
class RoleFilter(BaseFilterMixin):
pass
class RoleFilter(OrganizationalModelFilterMixin):
weight: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.RouteTarget, lookups=True)
@autotype_decorator(filtersets.RouteTargetFilterSet)
class RouteTargetFilter(BaseFilterMixin):
pass
class RouteTargetFilter(PrimaryModelFilterMixin):
name: FilterLookup[str] | None = strawberry_django.filter_field()
tenant: Annotated['TenantFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
tenant_id: ID | None = strawberry_django.filter_field()
@strawberry_django.filter(models.Service, lookups=True)
@autotype_decorator(filtersets.ServiceFilterSet)
class ServiceFilter(BaseFilterMixin):
pass
class ServiceFilter(ContactFilterMixin, ServiceBaseFilterMixin, PrimaryModelFilterMixin):
device: Annotated['DeviceFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field()
device_id: ID | None = strawberry_django.filter_field()
virtual_machine: Annotated['VirtualMachineFilter', strawberry.lazy('virtualization.graphql.filters')] | None = (
strawberry_django.filter_field()
)
virtual_machine_id: ID | None = strawberry_django.filter_field()
name: FilterLookup[str] | None = strawberry_django.filter_field()
ipaddresses: Annotated['IPAddressFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.ServiceTemplate, lookups=True)
@autotype_decorator(filtersets.ServiceTemplateFilterSet)
class ServiceTemplateFilter(BaseFilterMixin):
pass
class ServiceTemplateFilter(ServiceBaseFilterMixin, PrimaryModelFilterMixin):
name: FilterLookup[str] | None = strawberry_django.filter_field()
@strawberry_django.filter(models.VLAN, lookups=True)
@autotype_decorator(filtersets.VLANFilterSet)
class VLANFilter(BaseFilterMixin):
pass
class VLANFilter(PrimaryModelFilterMixin):
site: Annotated['SiteFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field()
site_id: ID | None = strawberry_django.filter_field()
group: Annotated['VLANGroupFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
group_id: ID | None = strawberry_django.filter_field()
vid: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
name: FilterLookup[str] | None = strawberry_django.filter_field()
tenant: Annotated['TenantFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
tenant_id: ID | None = strawberry_django.filter_field()
status: 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 = (
strawberry_django.filter_field()
)
qinq_svlan_id: ID | None = strawberry_django.filter_field()
qinq_cvlan: Annotated['VLANFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
qinq_cvlan_id: ID | None = strawberry_django.filter_field()
qinq_role: Annotated['VLANQinQRoleEnum', strawberry.lazy('ipam.graphql.enums')] | None = (
strawberry_django.filter_field()
)
l2vpn_terminations: Annotated['L2VPNFilter', strawberry.lazy('vpn.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.VLANGroup, lookups=True)
@autotype_decorator(filtersets.VLANGroupFilterSet)
class VLANGroupFilter(BaseFilterMixin):
pass
class VLANGroupFilter(OrganizationalModelFilterMixin):
scope_type: Annotated['ContentTypeFilter', strawberry.lazy('core.graphql.filters')] | None = (
strawberry_django.filter_field()
)
scope_type_id: ID | None = strawberry_django.filter_field()
scope_id: ID | None = strawberry_django.filter_field()
vid_ranges: Annotated['IntegerArrayLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.VLANTranslationPolicy, lookups=True)
@autotype_decorator(filtersets.VLANTranslationPolicyFilterSet)
class VLANTranslationPolicyFilter(BaseFilterMixin):
pass
class VLANTranslationPolicyFilter(PrimaryModelFilterMixin):
name: FilterLookup[str] | None = strawberry_django.filter_field()
@strawberry_django.filter(models.VLANTranslationRule, lookups=True)
@autotype_decorator(filtersets.VLANTranslationRuleFilterSet)
class VLANTranslationRuleFilter(BaseFilterMixin):
pass
class VLANTranslationRuleFilter(NetBoxModelFilterMixin):
policy: Annotated['VLANTranslationPolicyFilter', strawberry.lazy('ipam.graphql.filters')] | 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('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
remote_vid: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.VRF, lookups=True)
@autotype_decorator(filtersets.VRFFilterSet)
class VRFFilter(BaseFilterMixin):
pass
class VRFFilter(PrimaryModelFilterMixin):
name: FilterLookup[str] | None = strawberry_django.filter_field()
rd: FilterLookup[str] | None = strawberry_django.filter_field()
tenant: Annotated['TenantFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
tenant_id: ID | None = strawberry_django.filter_field()
enforce_unique: FilterLookup[bool] | None = strawberry_django.filter_field()
import_targets: Annotated['RouteTargetFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
export_targets: Annotated['RouteTargetFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)

View File

@ -0,0 +1,120 @@
from enum import Enum
import strawberry
__all__ = [
'ColorEnum',
'ButtonColorEnum',
'ImportMethodEnumEnum',
'ImportFormatEnum',
'DistanceUnitEnum',
'WeightUnitEnum',
]
#
# Generic color choices
#
@strawberry.enum
class ColorEnum(Enum):
COLOR_DARK_RED = 'aa1409'
COLOR_RED = 'f44336'
COLOR_PINK = 'e91e63'
COLOR_ROSE = 'ffe4e1'
COLOR_FUCHSIA = 'ff66ff'
COLOR_PURPLE = '9c27b0'
COLOR_DARK_PURPLE = '673ab7'
COLOR_INDIGO = '3f51b5'
COLOR_BLUE = '2196f3'
COLOR_LIGHT_BLUE = '03a9f4'
COLOR_CYAN = '00bcd4'
COLOR_TEAL = '009688'
COLOR_AQUA = '00ffff'
COLOR_DARK_GREEN = '2f6a31'
COLOR_GREEN = '4caf50'
COLOR_LIGHT_GREEN = '8bc34a'
COLOR_LIME = 'cddc39'
COLOR_YELLOW = 'ffeb3b'
COLOR_AMBER = 'ffc107'
COLOR_ORANGE = 'ff9800'
COLOR_DARK_ORANGE = 'ff5722'
COLOR_BROWN = '795548'
COLOR_LIGHT_GREY = 'c0c0c0'
COLOR_GREY = '9e9e9e'
COLOR_DARK_GREY = '607d8b'
COLOR_BLACK = '111111'
COLOR_WHITE = 'ffffff'
#
# Button color choices
#
@strawberry.enum
class ButtonColorEnum(Enum):
DEFAULT = 'default'
BLUE = 'blue'
INDIGO = 'indigo'
PURPLE = 'purple'
PINK = 'pink'
RED = 'red'
ORANGE = 'orange'
YELLOW = 'yellow'
GREEN = 'green'
TEAL = 'teal'
CYAN = 'cyan'
GRAY = 'gray'
GREY = 'gray' # Backward compatability for <3.2
BLACK = 'black'
WHITE = 'white'
#
# Import
#
@strawberry.enum
class ImportMethodEnumEnum(Enum):
DIRECT = 'direct'
UPLOAD = 'upload'
DATA_FILE = 'datafile'
@strawberry.enum
class ImportFormatEnum(Enum):
AUTO = 'auto'
CSV = 'csv'
JSON = 'json'
YAML = 'yaml'
# @strawberry.enum
# class CSVDelimiterEnum(Enum):
# AUTO = 'auto'
# COMMA = CSV_DELIMITERS['comma']
# SEMICOLON = CSV_DELIMITERS['semicolon']
# TAB = CSV_DELIMITERS['tab']
@strawberry.enum
class DistanceUnitEnum(Enum):
# Metric
UNIT_KILOMETER = 'km'
UNIT_METER = 'm'
# Imperial
UNIT_MILE = 'mi'
UNIT_FOOT = 'ft'
@strawberry.enum
class WeightUnitEnum(Enum):
# Metric
UNIT_KILOGRAM = 'kg'
UNIT_GRAM = 'g'
# Imperial
UNIT_POUND = 'lb'
UNIT_OUNCE = 'oz'

View File

@ -1,209 +1,114 @@
from functools import partialmethod
from typing import List
from dataclasses import dataclass
from typing import TypeVar, TYPE_CHECKING, Annotated
import django_filters
from datetime import datetime
import strawberry
from strawberry import ID
import strawberry_django
from django.core.exceptions import FieldDoesNotExist
from strawberry import auto
from strawberry_django import FilterLookup, DatetimeFilterLookup
from ipam.fields import ASNField
from netbox.graphql.scalars import BigInt
from utilities.fields import ColorField, CounterCacheField
from extras.models import *
from utilities.filters import *
from core.graphql.filter_lookups import *
from core.graphql.filter_mixins import *
from extras.graphql.filter_mixins import *
__all__ = [
'NetBoxModelFilterMixin',
'OrganizationalModelFilterMixin',
'PrimaryModelFilterMixin',
# 'autotype_decorator',
'NestedGroupModelFilterMixin',
'ImageAttachmentFilterMixin',
'WeightFilterMixin',
'SyncedDataFilterMixin',
'DistanceFilterMixin',
]
T = TypeVar('T')
def map_strawberry_type(field):
should_create_function = False
attr_type = None
# NetBox Filter types - put base classes after derived classes
if isinstance(field, ContentTypeFilter):
should_create_function = True
attr_type = str | None
elif isinstance(field, MultiValueArrayFilter):
pass
elif isinstance(field, MultiValueCharFilter):
# Note: Need to use the legacy FilterLookup from filters, not from
# strawberry_django.FilterLookup as we currently have USE_DEPRECATED_FILTERS
attr_type = strawberry_django.filters.FilterLookup[str] | None
elif isinstance(field, MultiValueDateFilter):
attr_type = auto
elif isinstance(field, MultiValueDateTimeFilter):
attr_type = auto
elif isinstance(field, MultiValueDecimalFilter):
pass
elif isinstance(field, MultiValueMACAddressFilter):
should_create_function = True
attr_type = List[str] | None
elif isinstance(field, MultiValueNumberFilter):
should_create_function = True
attr_type = List[str] | None
elif isinstance(field, MultiValueTimeFilter):
pass
elif isinstance(field, MultiValueWWNFilter):
should_create_function = True
attr_type = List[str] | None
elif isinstance(field, NullableCharFieldFilter):
pass
elif isinstance(field, NumericArrayFilter):
should_create_function = True
attr_type = int | None
elif isinstance(field, TreeNodeMultipleChoiceFilter):
should_create_function = True
attr_type = List[str] | None
# From django_filters - ordering of these matters as base classes must
# come after derived classes so the base class doesn't get matched first
# a pass for the check (no attr_type) means we don't currently handle
# or use that type
elif issubclass(type(field), django_filters.OrderingFilter):
pass
elif issubclass(type(field), django_filters.BaseRangeFilter):
pass
elif issubclass(type(field), django_filters.BaseInFilter):
pass
elif issubclass(type(field), django_filters.LookupChoiceFilter):
pass
elif issubclass(type(field), django_filters.AllValuesMultipleFilter):
pass
elif issubclass(type(field), django_filters.AllValuesFilter):
pass
elif issubclass(type(field), django_filters.TimeRangeFilter):
pass
elif issubclass(type(field), django_filters.IsoDateTimeFromToRangeFilter):
should_create_function = True
attr_type = str | None
elif issubclass(type(field), django_filters.DateTimeFromToRangeFilter):
should_create_function = True
attr_type = str | None
elif issubclass(type(field), django_filters.DateFromToRangeFilter):
should_create_function = True
attr_type = str | None
elif issubclass(type(field), django_filters.DateRangeFilter):
should_create_function = True
attr_type = str | None
elif issubclass(type(field), django_filters.RangeFilter):
pass
elif issubclass(type(field), django_filters.NumericRangeFilter):
pass
elif issubclass(type(field), django_filters.NumberFilter):
should_create_function = True
attr_type = int | None
elif issubclass(type(field), django_filters.ModelMultipleChoiceFilter):
should_create_function = True
attr_type = List[str] | None
elif issubclass(type(field), django_filters.ModelChoiceFilter):
should_create_function = True
attr_type = str | None
elif issubclass(type(field), django_filters.DurationFilter):
pass
elif issubclass(type(field), django_filters.IsoDateTimeFilter):
pass
elif issubclass(type(field), django_filters.DateTimeFilter):
attr_type = auto
elif issubclass(type(field), django_filters.TimeFilter):
attr_type = auto
elif issubclass(type(field), django_filters.DateFilter):
attr_type = auto
elif issubclass(type(field), django_filters.TypedMultipleChoiceFilter):
pass
elif issubclass(type(field), django_filters.MultipleChoiceFilter):
attr_type = str | None
elif issubclass(type(field), django_filters.TypedChoiceFilter):
pass
elif issubclass(type(field), django_filters.ChoiceFilter):
pass
elif issubclass(type(field), django_filters.BooleanFilter):
should_create_function = True
attr_type = bool | None
elif issubclass(type(field), django_filters.UUIDFilter):
should_create_function = True
attr_type = str | None
elif issubclass(type(field), django_filters.CharFilter):
# looks like only used by 'q'
should_create_function = True
attr_type = str | None
return should_create_function, attr_type
if TYPE_CHECKING:
from .enums import *
from core.graphql.filters import *
from tenancy.graphql.filters import *
from extras.graphql.filters import *
def autotype_decorator(filterset):
"""
Decorator used to auto creates a dataclass used by Strawberry based on a filterset.
Must go after the Strawberry decorator as follows:
@strawberry_django.filter(models.Example, lookups=True)
@autotype_decorator(filtersets.ExampleFilterSet)
class ExampleFilter(BaseFilterMixin):
class NetBoxModelFilterMixin(
ChangeLogFilterMixin,
CustomFieldsFilterMixin,
JournalEntriesFilterMixin,
TagsFilterMixin,
BaseObjectTypeFilterMixin,
):
pass
The Filter itself must be derived from BaseFilterMixin. For items listed in meta.fields
of the filterset, usually just a type specifier is generated, so for
`fields = [created, ]` the dataclass would be:
class ExampleFilter(BaseFilterMixin):
created: auto
For other filter fields a function needs to be created for Strawberry with the
naming convention `filter_{fieldname}` which is auto detected and called by
Strawberry, this function uses the filterset to handle the query.
"""
def create_attribute_and_function(cls, fieldname, attr_type, should_create_function):
if fieldname not in cls.__annotations__ and attr_type:
cls.__annotations__[fieldname] = attr_type
filter_name = f"filter_{fieldname}"
if should_create_function and not hasattr(cls, filter_name):
filter_by_filterset = getattr(cls, 'filter_by_filterset')
setattr(cls, filter_name, partialmethod(filter_by_filterset, key=fieldname))
def wrapper(cls):
cls.filterset = filterset
fields = filterset.get_fields()
model = filterset._meta.model
for fieldname in fields.keys():
should_create_function = False
attr_type = auto
if fieldname not in cls.__annotations__:
try:
field = model._meta.get_field(fieldname)
except FieldDoesNotExist:
continue
if isinstance(field, CounterCacheField):
should_create_function = True
attr_type = BigInt | None
elif isinstance(field, ASNField):
should_create_function = True
attr_type = List[str] | None
elif isinstance(field, ColorField):
should_create_function = True
attr_type = List[str] | None
create_attribute_and_function(cls, fieldname, attr_type, should_create_function)
declared_filters = filterset.declared_filters
for fieldname, field in declared_filters.items():
should_create_function, attr_type = map_strawberry_type(field)
if attr_type is None:
raise NotImplementedError(f"GraphQL Filter field unknown: {fieldname}: {field}")
create_attribute_and_function(cls, fieldname, attr_type, should_create_function)
return cls
return wrapper
@dataclass
class NestedGroupModelFilterMixin(NetBoxModelFilterMixin):
name: FilterLookup[str] | None = strawberry_django.filter_field()
slug: FilterLookup[str] | None = strawberry_django.filter_field()
description: FilterLookup[str] | None = strawberry_django.filter_field()
lft: IntegerLookup | None = strawberry_django.filter_field()
rght: IntegerLookup | None = strawberry_django.filter_field()
tree_id: IntegerLookup | None = strawberry_django.filter_field()
level: IntegerLookup | None = strawberry_django.filter_field()
parent_id: ID | None = strawberry_django.filter_field()
@strawberry.input
class BaseFilterMixin:
@dataclass
class OrganizationalModelFilterMixin(
ChangeLogFilterMixin,
CustomFieldsFilterMixin,
TagsFilterMixin,
BaseObjectTypeFilterMixin,
):
name: FilterLookup[str] | None = strawberry_django.filter_field()
slug: FilterLookup[str] | None = strawberry_django.filter_field()
description: FilterLookup[str] | None = strawberry_django.filter_field()
def filter_by_filterset(self, queryset, key):
filterset = self.filterset(data={key: getattr(self, key)}, queryset=queryset)
if not filterset.is_valid():
# We could raise validation error but strawberry logs it all to the
# console i.e. raise ValidationError(f"{k}: {v[0]}")
return filterset.qs.none()
return filterset.qs
@dataclass
class PrimaryModelFilterMixin(NetBoxModelFilterMixin):
description: FilterLookup[str] | None = strawberry_django.filter_field()
comments: FilterLookup[str] | None = strawberry_django.filter_field()
@dataclass
class ImageAttachmentFilterMixin(BaseFilterMixin):
images: Annotated['ImageAttachmentFilter', strawberry.lazy('extras.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@dataclass
class WeightFilterMixin(BaseFilterMixin):
weight: FilterLookup[float] | None = strawberry_django.filter_field()
weight_unit: Annotated['WeightUnitEnum', strawberry.lazy('netbox.graphql.enums')] | None = (
strawberry_django.filter_field()
)
@dataclass
class SyncedDataFilterMixin(BaseFilterMixin):
data_source: Annotated['DataSourceFilter', strawberry.lazy('core.graphql.filters')] | None = (
strawberry_django.filter_field()
)
data_source_id: FilterLookup[int] | None = strawberry_django.filter_field()
data_file: Annotated['DataFileFilter', strawberry.lazy('core.graphql.filters')] | 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 DistanceFilterMixin(BaseFilterMixin):
distance: FilterLookup[float] | None = strawberry_django.filter_field()
distance_unit: Annotated['DistanceUnitEnum', strawberry.lazy('netbox.graphql.enums')] | None = (
strawberry_django.filter_field()
)

View File

@ -38,7 +38,8 @@ schema = strawberry.Schema(
query=Query,
config=StrawberryConfig(auto_camel_case=False),
extensions=[
DjangoOptimizerExtension(prefetch_custom_queryset=True),
# DjangoOptimizerExtension(prefetch_custom_queryset=True),
DjangoOptimizerExtension(prefetch_custom_queryset=True, enable_prefetch_related_optimization=False),
MaxAliasesLimiter(max_alias_count=settings.GRAPHQL_MAX_ALIASES),
]
)

View File

@ -775,7 +775,7 @@ LOCALE_PATHS = (
STRAWBERRY_DJANGO = {
"DEFAULT_PK_FIELD_NAME": "id",
"TYPE_DESCRIPTION_FROM_MODEL_DOCSTRING": True,
"USE_DEPRECATED_FILTERS": True,
"USE_DEPRECATED_FILTERS": False,
}
#

View File

@ -99,12 +99,13 @@ class GraphQLAPITestCase(APITestCase):
# Test OR logic
query = """{
location_list( filters: {
status: \"""" + LocationStatusChoices.STATUS_PLANNED + """\",
OR: {status: \"""" + LocationStatusChoices.STATUS_STAGING + """\"}
status: STATUS_PLANNED,
OR: {status: STATUS_STAGING}
}) {
id site {id}
}
}"""
print(query)
response = self.client.post(url, data={'query': query}, format="json", **self.header)
self.assertHttpStatus(response, status.HTTP_200_OK)
data = json.loads(response.content)

View File

@ -0,0 +1,33 @@
from dataclasses import dataclass
from typing import Annotated, TYPE_CHECKING
import strawberry
from strawberry import ID
import strawberry_django
from core.graphql.filter_mixins import BaseFilterMixin
if TYPE_CHECKING:
from .filters import *
from core.graphql.filter_lookups import *
__all__ = ['TenancyFilterMixin', 'ContactFilterMixin']
@dataclass
class ContactFilterMixin(BaseFilterMixin):
contacts: Annotated['ContactFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@dataclass
class TenancyFilterMixin(BaseFilterMixin):
tenant: Annotated['TenantFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
tenant_id: ID | None = strawberry_django.filter_field()
group: Annotated['TenantGroupFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
group_id: Annotated['TreeNodeFilter', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)

View File

@ -1,7 +1,28 @@
from typing import Annotated, TYPE_CHECKING
import strawberry
from strawberry.scalars import ID
import strawberry_django
from strawberry_django import (
FilterLookup,
)
from netbox.graphql.filter_mixins import (
PrimaryModelFilterMixin,
OrganizationalModelFilterMixin,
NestedGroupModelFilterMixin,
)
from extras.graphql.filter_mixins import CustomFieldsFilterMixin, TagsFilterMixin
from core.graphql.filter_mixins import ChangeLogFilterMixin
from tenancy import models
from .filter_mixins import ContactFilterMixin
from netbox.graphql.filter_mixins import autotype_decorator, BaseFilterMixin
from tenancy import filtersets, models
if TYPE_CHECKING:
from core.graphql.filter_lookups import TreeNodeFilter
from circuits.graphql.filters import *
from dcim.graphql.filters import *
from ipam.graphql.filters import *
from wireless.graphql.filters import *
from virtualization.graphql.filters import *
from vpn.graphql.filters import *
__all__ = (
'TenantFilter',
@ -14,36 +35,127 @@ __all__ = (
@strawberry_django.filter(models.Tenant, lookups=True)
@autotype_decorator(filtersets.TenantFilterSet)
class TenantFilter(BaseFilterMixin):
pass
class TenantFilter(PrimaryModelFilterMixin, ContactFilterMixin):
name: FilterLookup[str] | None = strawberry_django.filter_field()
slug: FilterLookup[str] | None = strawberry_django.filter_field()
group: Annotated['TenantGroupFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
group_id: Annotated['TreeNodeFilter', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
asns: Annotated['ASNFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field()
circuits: Annotated['CircuitFilter', strawberry.lazy('circuits.graphql.filters')] | None = (
strawberry_django.filter_field()
)
sites: Annotated['SiteFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field()
vlans: Annotated['VLANFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field()
wireless_lans: Annotated['WirelessLANFilter', strawberry.lazy('wireless.graphql.filters')] | None = (
strawberry_django.filter_field()
)
route_targets: Annotated['RouteTargetFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
locations: Annotated['LocationFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
ip_ranges: Annotated['IPRangeFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
rackreservations: Annotated['RackReservationFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
racks: Annotated['RackFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field()
vdcs: Annotated['VirtualDeviceContextFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
prefixes: Annotated['PrefixFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
cables: Annotated['CableFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field()
virtual_machines: Annotated['VirtualMachineFilter', strawberry.lazy('virtualization.graphql.filters')] | None = (
strawberry_django.filter_field()
)
vrfs: Annotated['VRFFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field()
asn_ranges: Annotated['ASNRangeFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
wireless_links: Annotated['WirelessLinkFilter', strawberry.lazy('wireless.graphql.filters')] | None = (
strawberry_django.filter_field()
)
aggregates: Annotated['AggregateFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
power_feeds: Annotated['PowerFeedFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
devices: Annotated['DeviceFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
tunnels: Annotated['TunnelFilter', strawberry.lazy('vpn.graphql.filters')] | None = strawberry_django.filter_field()
ip_addresses: Annotated['IPAddressFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
clusters: Annotated['ClusterFilter', strawberry.lazy('virtualization.graphql.filters')] | None = (
strawberry_django.filter_field()
)
l2vpns: Annotated['L2VPNFilter', strawberry.lazy('vpn.graphql.filters')] | None = strawberry_django.filter_field()
@strawberry_django.filter(models.TenantGroup, lookups=True)
@autotype_decorator(filtersets.TenantGroupFilterSet)
class TenantGroupFilter(BaseFilterMixin):
pass
class TenantGroupFilter(OrganizationalModelFilterMixin):
parent: Annotated['TenantGroupFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
parent_id: ID | None = strawberry.UNSET
tenants: Annotated['TenantFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
children: Annotated['TenantGroupFilter', strawberry.lazy('tenancy.graphql.filters'), True] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.Contact, lookups=True)
@autotype_decorator(filtersets.ContactFilterSet)
class ContactFilter(BaseFilterMixin):
pass
class ContactFilter(PrimaryModelFilterMixin):
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()
group: Annotated['ContactGroupFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
group_id: Annotated['TreeNodeFilter', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
assignments: Annotated['ContactAssignmentFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.ContactRole, lookups=True)
@autotype_decorator(filtersets.ContactRoleFilterSet)
class ContactRoleFilter(BaseFilterMixin):
class ContactRoleFilter(OrganizationalModelFilterMixin):
pass
@strawberry_django.filter(models.ContactGroup, lookups=True)
@autotype_decorator(filtersets.ContactGroupFilterSet)
class ContactGroupFilter(BaseFilterMixin):
pass
class ContactGroupFilter(NestedGroupModelFilterMixin):
parent: Annotated['ContactGroupFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.ContactAssignment, lookups=True)
@autotype_decorator(filtersets.ContactAssignmentFilterSet)
class ContactAssignmentFilter(BaseFilterMixin):
pass
class ContactAssignmentFilter(CustomFieldsFilterMixin, TagsFilterMixin, ChangeLogFilterMixin):
object_id: ID | None = strawberry_django.filter_field()
contact: Annotated['ContactFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
contact_id: ID | None = strawberry_django.filter_field()
role: Annotated['ContactRoleFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
role_id: ID | None = strawberry_django.filter_field()
priority: FilterLookup[str] | None = strawberry_django.filter_field()

View File

@ -1,4 +1,4 @@
from typing import Annotated, List
from typing import Annotated, List, TYPE_CHECKING
import strawberry
import strawberry_django
@ -9,6 +9,14 @@ from tenancy import models
from .mixins import ContactAssignmentsMixin
from .filters import *
if TYPE_CHECKING:
from circuits.graphql.types import *
from dcim.graphql.types import *
from ipam.graphql.types import *
from wireless.graphql.types import *
from virtualization.graphql.types import *
from vpn.graphql.types import *
__all__ = (
'ContactAssignmentType',
'ContactGroupType',
@ -23,92 +31,70 @@ __all__ = (
# Tenants
#
@strawberry_django.type(
models.Tenant,
fields='__all__',
filters=TenantFilter
)
@strawberry_django.type(models.Tenant, fields='__all__', filters=TenantFilter)
class TenantType(NetBoxObjectType):
group: Annotated["TenantGroupType", strawberry.lazy('tenancy.graphql.types')] | None
asns: List[Annotated["ASNType", strawberry.lazy('ipam.graphql.types')]]
circuits: List[Annotated["CircuitType", strawberry.lazy('circuits.graphql.types')]]
sites: List[Annotated["SiteType", strawberry.lazy('dcim.graphql.types')]]
vlans: List[Annotated["VLANType", strawberry.lazy('ipam.graphql.types')]]
wireless_lans: List[Annotated["WirelessLANType", strawberry.lazy('wireless.graphql.types')]]
route_targets: List[Annotated["RouteTargetType", strawberry.lazy('ipam.graphql.types')]]
locations: List[Annotated["LocationType", strawberry.lazy('dcim.graphql.types')]]
ip_ranges: List[Annotated["IPRangeType", strawberry.lazy('ipam.graphql.types')]]
rackreservations: List[Annotated["RackReservationType", strawberry.lazy('dcim.graphql.types')]]
racks: List[Annotated["RackType", strawberry.lazy('dcim.graphql.types')]]
vdcs: List[Annotated["VirtualDeviceContextType", strawberry.lazy('dcim.graphql.types')]]
prefixes: List[Annotated["PrefixType", strawberry.lazy('ipam.graphql.types')]]
cables: List[Annotated["CableType", strawberry.lazy('dcim.graphql.types')]]
virtual_machines: List[Annotated["VirtualMachineType", strawberry.lazy('virtualization.graphql.types')]]
vrfs: List[Annotated["VRFType", strawberry.lazy('ipam.graphql.types')]]
asn_ranges: List[Annotated["ASNRangeType", strawberry.lazy('ipam.graphql.types')]]
wireless_links: List[Annotated["WirelessLinkType", strawberry.lazy('wireless.graphql.types')]]
aggregates: List[Annotated["AggregateType", strawberry.lazy('ipam.graphql.types')]]
power_feeds: List[Annotated["PowerFeedType", strawberry.lazy('dcim.graphql.types')]]
devices: List[Annotated["DeviceType", strawberry.lazy('dcim.graphql.types')]]
tunnels: List[Annotated["TunnelType", strawberry.lazy('vpn.graphql.types')]]
ip_addresses: List[Annotated["IPAddressType", strawberry.lazy('ipam.graphql.types')]]
clusters: List[Annotated["ClusterType", strawberry.lazy('virtualization.graphql.types')]]
l2vpns: List[Annotated["L2VPNType", strawberry.lazy('vpn.graphql.types')]]
group: Annotated['TenantGroupType', strawberry.lazy('tenancy.graphql.types')]
contacts: List[Annotated['ContactType', strawberry.lazy('tenancy.graphql.types')]]
asns: List[Annotated['ASNType', strawberry.lazy('ipam.graphql.types')]]
circuits: List[Annotated['CircuitType', strawberry.lazy('circuits.graphql.types')]]
sites: List[Annotated['SiteType', strawberry.lazy('dcim.graphql.types')]]
vlans: List[Annotated['VLANType', strawberry.lazy('ipam.graphql.types')]]
wireless_lans: List[Annotated['WirelessLANType', strawberry.lazy('wireless.graphql.types')]]
route_targets: List[Annotated['RouteTargetType', strawberry.lazy('ipam.graphql.types')]]
locations: List[Annotated['LocationType', strawberry.lazy('dcim.graphql.types')]]
ip_ranges: List[Annotated['IPRangeType', strawberry.lazy('ipam.graphql.types')]]
rackreservations: List[Annotated['RackReservationType', strawberry.lazy('dcim.graphql.types')]]
racks: List[Annotated['RackType', strawberry.lazy('dcim.graphql.types')]]
vdcs: List[Annotated['VirtualDeviceContextType', strawberry.lazy('dcim.graphql.types')]]
prefixes: List[Annotated['PrefixType', strawberry.lazy('ipam.graphql.types')]]
cables: List[Annotated['CableType', strawberry.lazy('dcim.graphql.types')]]
virtual_machines: List[Annotated['VirtualMachineType', strawberry.lazy('virtualization.graphql.types')]]
vrfs: List[Annotated['VRFType', strawberry.lazy('ipam.graphql.types')]]
asn_ranges: List[Annotated['ASNRangeType', strawberry.lazy('ipam.graphql.types')]]
wireless_links: List[Annotated['WirelessLinkType', strawberry.lazy('wireless.graphql.types')]]
aggregates: List[Annotated['AggregateType', strawberry.lazy('ipam.graphql.types')]]
power_feeds: List[Annotated['PowerFeedType', strawberry.lazy('dcim.graphql.types')]]
devices: List[Annotated['DeviceType', strawberry.lazy('dcim.graphql.types')]]
tunnels: List[Annotated['TunnelType', strawberry.lazy('vpn.graphql.types')]]
ip_addresses: List[Annotated['IPAddressType', strawberry.lazy('ipam.graphql.types')]]
clusters: List[Annotated['ClusterType', strawberry.lazy('virtualization.graphql.types')]]
l2vpns: List[Annotated['L2VPNType', strawberry.lazy('vpn.graphql.types')]]
@strawberry_django.type(
models.TenantGroup,
fields='__all__',
filters=TenantGroupFilter
)
@strawberry_django.type(models.TenantGroup, fields='__all__', filters=TenantGroupFilter)
class TenantGroupType(OrganizationalObjectType):
parent: Annotated["TenantGroupType", strawberry.lazy('tenancy.graphql.types')] | None
parent: Annotated['TenantGroupType', strawberry.lazy('tenancy.graphql.types')] | None
tenants: List[TenantType]
children: List[Annotated["TenantGroupType", strawberry.lazy('tenancy.graphql.types')]]
children: List[Annotated['TenantGroupType', strawberry.lazy('tenancy.graphql.types')]]
#
# Contacts
#
@strawberry_django.type(
models.Contact,
fields='__all__',
filters=ContactFilter
)
@strawberry_django.type(models.Contact, fields='__all__', filters=ContactFilter)
class ContactType(ContactAssignmentsMixin, NetBoxObjectType):
group: Annotated["ContactGroupType", strawberry.lazy('tenancy.graphql.types')] | None
group: Annotated['ContactGroupType', strawberry.lazy('tenancy.graphql.types')] | None
@strawberry_django.type(
models.ContactRole,
fields='__all__',
filters=ContactRoleFilter
)
@strawberry_django.type(models.ContactRole, fields='__all__', filters=ContactRoleFilter)
class ContactRoleType(ContactAssignmentsMixin, OrganizationalObjectType):
pass
@strawberry_django.type(
models.ContactGroup,
fields='__all__',
filters=ContactGroupFilter
)
@strawberry_django.type(models.ContactGroup, fields='__all__', filters=ContactGroupFilter)
class ContactGroupType(OrganizationalObjectType):
parent: Annotated["ContactGroupType", strawberry.lazy('tenancy.graphql.types')] | None
parent: Annotated['ContactGroupType', strawberry.lazy('tenancy.graphql.types')] | None
contacts: List[ContactType]
children: List[Annotated["ContactGroupType", strawberry.lazy('tenancy.graphql.types')]]
children: List[Annotated['ContactGroupType', strawberry.lazy('tenancy.graphql.types')]]
@strawberry_django.type(
models.ContactAssignment,
fields='__all__',
filters=ContactAssignmentFilter
)
@strawberry_django.type(models.ContactAssignment, fields='__all__', filters=ContactAssignmentFilter)
class ContactAssignmentType(CustomFieldsMixin, TagsMixin, BaseObjectType):
object_type: Annotated["ContentTypeType", strawberry.lazy('netbox.graphql.types')] | None
contact: Annotated["ContactType", strawberry.lazy('tenancy.graphql.types')] | None
role: Annotated["ContactRoleType", strawberry.lazy('tenancy.graphql.types')] | None
object_type: Annotated['ContentTypeType', strawberry.lazy('netbox.graphql.types')] | None
contact: Annotated['ContactType', strawberry.lazy('tenancy.graphql.types')] | None
role: Annotated['ContactRoleType', strawberry.lazy('tenancy.graphql.types')] | None

View File

@ -1,7 +1,31 @@
from datetime import datetime
from typing import Annotated, TYPE_CHECKING
import strawberry
import strawberry_django
from strawberry_django import (
FilterLookup,
DatetimeFilterLookup,
)
from core.graphql.filter_mixins import *
from netbox.graphql.filter_mixins import *
from tenancy.graphql.filter_mixins import *
from netbox.graphql.filter_mixins import autotype_decorator, BaseFilterMixin
from users import filtersets, models
from users import models
if TYPE_CHECKING:
from .enums import *
from netbox.graphql.enums import *
from wireless.graphql.enums import *
from core.graphql.filter_lookups import *
from extras.graphql.filters import *
from circuits.graphql.filters import *
from dcim.graphql.filters import *
from ipam.graphql.filters import *
from tenancy.graphql.filters import *
from wireless.graphql.filters import *
from users.graphql.filters import *
from virtualization.graphql.filters import *
from vpn.graphql.filters import *
__all__ = (
'GroupFilter',
@ -10,12 +34,18 @@ __all__ = (
@strawberry_django.filter(models.Group, lookups=True)
@autotype_decorator(filtersets.GroupFilterSet)
class GroupFilter(BaseFilterMixin):
pass
class GroupFilter(BaseObjectTypeFilterMixin):
name: FilterLookup[str] | None = strawberry_django.filter_field()
description: FilterLookup[str] | None = strawberry_django.filter_field()
@strawberry_django.filter(models.User, lookups=True)
@autotype_decorator(filtersets.UserFilterSet)
class UserFilter(BaseFilterMixin):
pass
class UserFilter(BaseObjectTypeFilterMixin):
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_staff: 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()
groups: Annotated['GroupFilter', strawberry.lazy('users.graphql.filters')] | None = strawberry_django.filter_field()

View File

@ -0,0 +1,33 @@
from enum import Enum
import strawberry
__all__ = ['ClusterStatusEnum', 'VirtualMachineStatusEnum']
#
# Clusters
#
@strawberry.enum
class ClusterStatusEnum(Enum):
STATUS_PLANNED = 'planned'
STATUS_STAGING = 'staging'
STATUS_ACTIVE = 'active'
STATUS_DECOMMISSIONING = 'decommissioning'
STATUS_OFFLINE = 'offline'
#
# VirtualMachines
#
@strawberry.enum
class VirtualMachineStatusEnum(Enum):
STATUS_OFFLINE = 'offline'
STATUS_ACTIVE = 'active'
STATUS_PLANNED = 'planned'
STATUS_STAGED = 'staged'
STATUS_FAILED = 'failed'
STATUS_DECOMMISSIONING = 'decommissioning'

View File

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

View File

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

161
netbox/vpn/graphql/enums.py Normal file
View File

@ -0,0 +1,161 @@
from enum import Enum
import strawberry
__all__ = [
'TunnelStatusEnum',
'TunnelEncapsulationEnum',
'TunnelTerminationTypeEnum',
'TunnelTerminationRoleEnum',
'IKEVersionEnum',
'IKEModeEnum',
'AuthenticationMethodEnum',
'IPSecModeEnum',
'EncryptionAlgorithmEnum',
'AuthenticationAlgorithmEnum',
'DHGroupEnum',
'L2VPNTypeEnum',
]
#
# Tunnels
#
@strawberry.enum
class TunnelStatusEnum(Enum):
key = 'Tunnel.status'
STATUS_PLANNED = 'planned'
STATUS_ACTIVE = 'active'
STATUS_DISABLED = 'disabled'
@strawberry.enum
class TunnelEncapsulationEnum(Enum):
ENCAP_GRE = 'gre'
ENCAP_IPSEC_TRANSPORT = 'ipsec-transport'
ENCAP_IPSEC_TUNNEL = 'ipsec-tunnel'
ENCAP_IP_IP = 'ip-ip'
ENCAP_L2TP = 'l2tp'
ENCAP_OPENVPN = 'openvpn'
ENCAP_PPTP = 'pptp'
ENCAP_WIREGUARD = 'wireguard'
@strawberry.enum
class TunnelTerminationTypeEnum(Enum):
# For TunnelCreateForm
TYPE_DEVICE = 'dcim.device'
TYPE_VIRTUALMACHINE = 'virtualization.virtualmachine'
@strawberry.enum
class TunnelTerminationRoleEnum(Enum):
ROLE_PEER = 'peer'
ROLE_HUB = 'hub'
ROLE_SPOKE = 'spoke'
#
# Crypto
#
@strawberry.enum
class IKEVersionEnum(Enum):
VERSION_1 = 1
VERSION_2 = 2
@strawberry.enum
class IKEModeEnum(Enum):
AGGRESSIVE = 'aggressive'
MAIN = 'main'
@strawberry.enum
class AuthenticationMethodEnum(Enum):
PRESHARED_KEYS = 'preshared-keys'
CERTIFICATES = 'certificates'
RSA_SIGNATURES = 'rsa-signatures'
DSA_SIGNATURES = 'dsa-signatures'
@strawberry.enum
class IPSecModeEnum(Enum):
ESP = 'esp'
AH = 'ah'
@strawberry.enum
class EncryptionAlgorithmEnum(Enum):
ENCRYPTION_AES128_CBC = 'aes-128-cbc'
ENCRYPTION_AES128_GCM = 'aes-128-gcm'
ENCRYPTION_AES192_CBC = 'aes-192-cbc'
ENCRYPTION_AES192_GCM = 'aes-192-gcm'
ENCRYPTION_AES256_CBC = 'aes-256-cbc'
ENCRYPTION_AES256_GCM = 'aes-256-gcm'
ENCRYPTION_3DES = '3des-cbc'
ENCRYPTION_DES = 'des-cbc'
@strawberry.enum
class AuthenticationAlgorithmEnum(Enum):
AUTH_HMAC_SHA1 = 'hmac-sha1'
AUTH_HMAC_SHA256 = 'hmac-sha256'
AUTH_HMAC_SHA384 = 'hmac-sha384'
AUTH_HMAC_SHA512 = 'hmac-sha512'
AUTH_HMAC_MD5 = 'hmac-md5'
@strawberry.enum
class DHGroupEnum(Enum):
# https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml#ikev2-parameters-8
GROUP_1 = 1 # 768-bit MODP
GROUP_2 = 2 # 1024-but MODP
# Groups 3-4 reserved
GROUP_5 = 5 # 1536-bit MODP
# Groups 6-13 unassigned
GROUP_14 = 14 # 2048-bit MODP
GROUP_15 = 15 # 3072-bit MODP
GROUP_16 = 16 # 4096-bit MODP
GROUP_17 = 17 # 6144-bit MODP
GROUP_18 = 18 # 8192-bit MODP
GROUP_19 = 19 # 256-bit random ECP
GROUP_20 = 20 # 384-bit random ECP
GROUP_21 = 21 # 521-bit random ECP (521 is not a typo)
GROUP_22 = 22 # 1024-bit MODP w/160-bit prime
GROUP_23 = 23 # 2048-bit MODP w/224-bit prime
GROUP_24 = 24 # 2048-bit MODP w/256-bit prime
GROUP_25 = 25 # 192-bit ECP
GROUP_26 = 26 # 224-bit ECP
GROUP_27 = 27 # brainpoolP224r1
GROUP_28 = 28 # brainpoolP256r1
GROUP_29 = 29 # brainpoolP384r1
GROUP_30 = 30 # brainpoolP512r1
GROUP_31 = 31 # Curve25519
GROUP_32 = 32 # Curve448
GROUP_33 = 33 # GOST3410_2012_256
GROUP_34 = 34 # GOST3410_2012_512
#
# L2VPN
#
@strawberry.enum
class L2VPNTypeEnum(Enum):
TYPE_VPLS = 'vpls'
TYPE_VPWS = 'vpws'
TYPE_EPL = 'epl'
TYPE_EVPL = 'evpl'
TYPE_EPLAN = 'ep-lan'
TYPE_EVPLAN = 'evp-lan'
TYPE_EPTREE = 'ep-tree'
TYPE_EVPTREE = 'evp-tree'
TYPE_VXLAN = 'vxlan'
TYPE_VXLAN_EVPN = 'vxlan-evpn'
TYPE_MPLS_EVPN = 'mpls-evpn'
TYPE_PBB_EVPN = 'pbb-evpn'
TYPE_EVPN_VPWS = 'evpn-vpws'

View File

@ -1,7 +1,34 @@
from typing import Annotated, TYPE_CHECKING
import strawberry
from strawberry.scalars import ID
import strawberry_django
from strawberry_django import (
FilterLookup,
)
from extras.graphql.filter_mixins import *
from netbox.graphql.filter_mixins import *
from core.graphql.filter_mixins import *
from tenancy.graphql.filter_mixins import *
# from .filter_mixins import *
from vpn import models
if TYPE_CHECKING:
from .enums import *
from netbox.graphql.enums import *
from wireless.graphql.enums import *
from core.graphql.filter_lookups import *
from core.graphql.filters import *
from extras.graphql.filters import *
from circuits.graphql.filters import *
from dcim.graphql.filters import *
from ipam.graphql.filters import *
from tenancy.graphql.filters import *
from wireless.graphql.filters import *
from users.graphql.filters import *
from virtualization.graphql.filters import *
from vpn.graphql.filters import *
from netbox.graphql.filter_mixins import autotype_decorator, BaseFilterMixin
from vpn import filtersets, models
__all__ = (
'TunnelGroupFilter',
@ -18,60 +45,151 @@ __all__ = (
@strawberry_django.filter(models.TunnelGroup, lookups=True)
@autotype_decorator(filtersets.TunnelGroupFilterSet)
class TunnelGroupFilter(BaseFilterMixin):
class TunnelGroupFilter(OrganizationalModelFilterMixin):
pass
@strawberry_django.filter(models.TunnelTermination, lookups=True)
@autotype_decorator(filtersets.TunnelTerminationFilterSet)
class TunnelTerminationFilter(BaseFilterMixin):
pass
class TunnelTerminationFilter(
BaseObjectTypeFilterMixin, CustomFieldsFilterMixin, TagsFilterMixin, ChangeLogFilterMixin
):
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 = (
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['IPAddressFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
outside_ip_id: ID | None = strawberry_django.filter_field()
@strawberry_django.filter(models.Tunnel, lookups=True)
@autotype_decorator(filtersets.TunnelFilterSet)
class TunnelFilter(BaseFilterMixin):
pass
class TunnelFilter(PrimaryModelFilterMixin):
name: FilterLookup[str] | None = strawberry_django.filter_field()
status: 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 = (
strawberry_django.filter_field()
)
ipsec_profile: Annotated['IPSecProfileFilter', strawberry.lazy('vpn.graphql.filters')] | None = (
strawberry_django.filter_field()
)
tenant: Annotated['TenantFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
tenant_id: ID | None = strawberry_django.filter_field()
tunnel_id: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.IKEProposal, lookups=True)
@autotype_decorator(filtersets.IKEProposalFilterSet)
class IKEProposalFilter(BaseFilterMixin):
pass
class IKEProposalFilter(PrimaryModelFilterMixin):
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('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.IKEPolicy, lookups=True)
@autotype_decorator(filtersets.IKEPolicyFilterSet)
class IKEPolicyFilter(BaseFilterMixin):
pass
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()
proposals: Annotated['IKEProposalFilter', strawberry.lazy('vpn.graphql.filters')] | None = (
strawberry_django.filter_field()
)
preshared_key: FilterLookup[str] | None = strawberry_django.filter_field()
@strawberry_django.filter(models.IPSecProposal, lookups=True)
@autotype_decorator(filtersets.IPSecProposalFilterSet)
class IPSecProposalFilter(BaseFilterMixin):
pass
class IPSecProposalFilter(PrimaryModelFilterMixin):
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('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
sa_lifetime_data: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter(models.IPSecPolicy, lookups=True)
@autotype_decorator(filtersets.IPSecPolicyFilterSet)
class IPSecPolicyFilter(BaseFilterMixin):
pass
class IPSecPolicyFilter(PrimaryModelFilterMixin):
name: FilterLookup[str] | None = strawberry_django.filter_field()
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()
@strawberry_django.filter(models.IPSecProfile, lookups=True)
@autotype_decorator(filtersets.IPSecProfileFilterSet)
class IPSecProfileFilter(BaseFilterMixin):
pass
class IPSecProfileFilter(PrimaryModelFilterMixin):
name: FilterLookup[str] | None = strawberry_django.filter_field()
mode: 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()
)
ike_policy_id: ID | None = strawberry_django.filter_field()
ipsec_policy: Annotated['IPSecPolicyFilter', strawberry.lazy('vpn.graphql.filters')] | None = (
strawberry_django.filter_field()
)
ipsec_policy_id: ID | None = strawberry_django.filter_field()
@strawberry_django.filter(models.L2VPN, lookups=True)
@autotype_decorator(filtersets.L2VPNFilterSet)
class L2VPNFilter(BaseFilterMixin):
pass
class L2VPNFilter(ContactFilterMixin, 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()
identifier: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
import_targets: Annotated['RouteTargetFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
export_targets: Annotated['RouteTargetFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
tenant: Annotated['TenantFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
tenant_id: ID | None = strawberry_django.filter_field()
@strawberry_django.filter(models.L2VPNTermination, lookups=True)
@autotype_decorator(filtersets.L2VPNTerminationFilterSet)
class L2VPNTerminationFilter(BaseFilterMixin):
pass
class L2VPNTerminationFilter(NetBoxModelFilterMixin):
l2vpn: Annotated['L2VPNFilter', strawberry.lazy('vpn.graphql.filters')] | None = strawberry_django.filter_field()
l2vpn_id: ID | None = strawberry_django.filter_field()
assigned_object_type: Annotated['ContentTypeFilter', strawberry.lazy('core.graphql.filters')] | None = (
strawberry_django.filter_field()
)
assigned_object_id: Annotated['IntegerLookup', strawberry.lazy('core.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)

View File

@ -0,0 +1,249 @@
from enum import Enum
import strawberry
__all__ = [
'WirelessRoleEnum',
'WirelessLANStatusEnum',
'WirelessChannelEnum',
'WirelessAuthTypeEnum',
'WirelessAuthCipherEnum',
]
@strawberry.enum
class WirelessRoleEnum(Enum):
ROLE_AP = 'ap'
ROLE_STATION = 'station'
@strawberry.enum
class WirelessLANStatusEnum(Enum):
key = 'WirelessLAN.status'
STATUS_ACTIVE = 'active'
STATUS_RESERVED = 'reserved'
STATUS_DISABLED = 'disabled'
STATUS_DEPRECATED = 'deprecated'
@strawberry.enum
class WirelessChannelEnum(Enum):
# 2.4 GHz
CHANNEL_24G_1 = '2.4g-1-2412-22'
CHANNEL_24G_2 = '2.4g-2-2417-22'
CHANNEL_24G_3 = '2.4g-3-2422-22'
CHANNEL_24G_4 = '2.4g-4-2427-22'
CHANNEL_24G_5 = '2.4g-5-2432-22'
CHANNEL_24G_6 = '2.4g-6-2437-22'
CHANNEL_24G_7 = '2.4g-7-2442-22'
CHANNEL_24G_8 = '2.4g-8-2447-22'
CHANNEL_24G_9 = '2.4g-9-2452-22'
CHANNEL_24G_10 = '2.4g-10-2457-22'
CHANNEL_24G_11 = '2.4g-11-2462-22'
CHANNEL_24G_12 = '2.4g-12-2467-22'
CHANNEL_24G_13 = '2.4g-13-2472-22'
# 5 GHz
CHANNEL_5G_32 = '5g-32-5160-20'
CHANNEL_5G_34 = '5g-34-5170-40'
CHANNEL_5G_36 = '5g-36-5180-20'
CHANNEL_5G_38 = '5g-38-5190-40'
CHANNEL_5G_40 = '5g-40-5200-20'
CHANNEL_5G_42 = '5g-42-5210-80'
CHANNEL_5G_44 = '5g-44-5220-20'
CHANNEL_5G_46 = '5g-46-5230-40'
CHANNEL_5G_48 = '5g-48-5240-20'
CHANNEL_5G_50 = '5g-50-5250-160'
CHANNEL_5G_52 = '5g-52-5260-20'
CHANNEL_5G_54 = '5g-54-5270-40'
CHANNEL_5G_56 = '5g-56-5280-20'
CHANNEL_5G_58 = '5g-58-5290-80'
CHANNEL_5G_60 = '5g-60-5300-20'
CHANNEL_5G_62 = '5g-62-5310-40'
CHANNEL_5G_64 = '5g-64-5320-20'
CHANNEL_5G_100 = '5g-100-5500-20'
CHANNEL_5G_102 = '5g-102-5510-40'
CHANNEL_5G_104 = '5g-104-5520-20'
CHANNEL_5G_106 = '5g-106-5530-80'
CHANNEL_5G_108 = '5g-108-5540-20'
CHANNEL_5G_110 = '5g-110-5550-40'
CHANNEL_5G_112 = '5g-112-5560-20'
CHANNEL_5G_114 = '5g-114-5570-160'
CHANNEL_5G_116 = '5g-116-5580-20'
CHANNEL_5G_118 = '5g-118-5590-40'
CHANNEL_5G_120 = '5g-120-5600-20'
CHANNEL_5G_122 = '5g-122-5610-80'
CHANNEL_5G_124 = '5g-124-5620-20'
CHANNEL_5G_126 = '5g-126-5630-40'
CHANNEL_5G_128 = '5g-128-5640-20'
CHANNEL_5G_132 = '5g-132-5660-20'
CHANNEL_5G_134 = '5g-134-5670-40'
CHANNEL_5G_136 = '5g-136-5680-20'
CHANNEL_5G_138 = '5g-138-5690-80'
CHANNEL_5G_140 = '5g-140-5700-20'
CHANNEL_5G_142 = '5g-142-5710-40'
CHANNEL_5G_144 = '5g-144-5720-20'
CHANNEL_5G_149 = '5g-149-5745-20'
CHANNEL_5G_151 = '5g-151-5755-40'
CHANNEL_5G_153 = '5g-153-5765-20'
CHANNEL_5G_155 = '5g-155-5775-80'
CHANNEL_5G_157 = '5g-157-5785-20'
CHANNEL_5G_159 = '5g-159-5795-40'
CHANNEL_5G_161 = '5g-161-5805-20'
CHANNEL_5G_163 = '5g-163-5815-160'
CHANNEL_5G_165 = '5g-165-5825-20'
CHANNEL_5G_167 = '5g-167-5835-40'
CHANNEL_5G_169 = '5g-169-5845-20'
CHANNEL_5G_171 = '5g-171-5855-80'
CHANNEL_5G_173 = '5g-173-5865-20'
CHANNEL_5G_175 = '5g-175-5875-40'
CHANNEL_5G_177 = '5g-177-5885-20'
# 6 GHz
CHANNEL_6G_1 = '6g-1-5955-20'
CHANNEL_6G_3 = '6g-3-5965-40'
CHANNEL_6G_5 = '6g-5-5975-20'
CHANNEL_6G_7 = '6g-7-5985-80'
CHANNEL_6G_9 = '6g-9-5995-20'
CHANNEL_6G_11 = '6g-11-6005-40'
CHANNEL_6G_13 = '6g-13-6015-20'
CHANNEL_6G_15 = '6g-15-6025-160'
CHANNEL_6G_17 = '6g-17-6035-20'
CHANNEL_6G_19 = '6g-19-6045-40'
CHANNEL_6G_21 = '6g-21-6055-20'
CHANNEL_6G_23 = '6g-23-6065-80'
CHANNEL_6G_25 = '6g-25-6075-20'
CHANNEL_6G_27 = '6g-27-6085-40'
CHANNEL_6G_29 = '6g-29-6095-20'
CHANNEL_6G_31 = '6g-31-6105-320'
CHANNEL_6G_33 = '6g-33-6115-20'
CHANNEL_6G_35 = '6g-35-6125-40'
CHANNEL_6G_37 = '6g-37-6135-20'
CHANNEL_6G_39 = '6g-39-6145-80'
CHANNEL_6G_41 = '6g-41-6155-20'
CHANNEL_6G_43 = '6g-43-6165-40'
CHANNEL_6G_45 = '6g-45-6175-20'
CHANNEL_6G_47 = '6g-47-6185-160'
CHANNEL_6G_49 = '6g-49-6195-20'
CHANNEL_6G_51 = '6g-51-6205-40'
CHANNEL_6G_53 = '6g-53-6215-20'
CHANNEL_6G_55 = '6g-55-6225-80'
CHANNEL_6G_57 = '6g-57-6235-20'
CHANNEL_6G_59 = '6g-59-6245-40'
CHANNEL_6G_61 = '6g-61-6255-20'
CHANNEL_6G_65 = '6g-65-6275-20'
CHANNEL_6G_67 = '6g-67-6285-40'
CHANNEL_6G_69 = '6g-69-6295-20'
CHANNEL_6G_71 = '6g-71-6305-80'
CHANNEL_6G_73 = '6g-73-6315-20'
CHANNEL_6G_75 = '6g-75-6325-40'
CHANNEL_6G_77 = '6g-77-6335-20'
CHANNEL_6G_79 = '6g-79-6345-160'
CHANNEL_6G_81 = '6g-81-6355-20'
CHANNEL_6G_83 = '6g-83-6365-40'
CHANNEL_6G_85 = '6g-85-6375-20'
CHANNEL_6G_87 = '6g-87-6385-80'
CHANNEL_6G_89 = '6g-89-6395-20'
CHANNEL_6G_91 = '6g-91-6405-40'
CHANNEL_6G_93 = '6g-93-6415-20'
CHANNEL_6G_95 = '6g-95-6425-320'
CHANNEL_6G_97 = '6g-97-6435-20'
CHANNEL_6G_99 = '6g-99-6445-40'
CHANNEL_6G_101 = '6g-101-6455-20'
CHANNEL_6G_103 = '6g-103-6465-80'
CHANNEL_6G_105 = '6g-105-6475-20'
CHANNEL_6G_107 = '6g-107-6485-40'
CHANNEL_6G_109 = '6g-109-6495-20'
CHANNEL_6G_111 = '6g-111-6505-160'
CHANNEL_6G_113 = '6g-113-6515-20'
CHANNEL_6G_115 = '6g-115-6525-40'
CHANNEL_6G_117 = '6g-117-6535-20'
CHANNEL_6G_119 = '6g-119-6545-80'
CHANNEL_6G_121 = '6g-121-6555-20'
CHANNEL_6G_123 = '6g-123-6565-40'
CHANNEL_6G_125 = '6g-125-6575-20'
CHANNEL_6G_129 = '6g-129-6595-20'
CHANNEL_6G_131 = '6g-131-6605-40'
CHANNEL_6G_133 = '6g-133-6615-20'
CHANNEL_6G_135 = '6g-135-6625-80'
CHANNEL_6G_137 = '6g-137-6635-20'
CHANNEL_6G_139 = '6g-139-6645-40'
CHANNEL_6G_141 = '6g-141-6655-20'
CHANNEL_6G_143 = '6g-143-6665-160'
CHANNEL_6G_145 = '6g-145-6675-20'
CHANNEL_6G_147 = '6g-147-6685-40'
CHANNEL_6G_149 = '6g-149-6695-20'
CHANNEL_6G_151 = '6g-151-6705-80'
CHANNEL_6G_153 = '6g-153-6715-20'
CHANNEL_6G_155 = '6g-155-6725-40'
CHANNEL_6G_157 = '6g-157-6735-20'
CHANNEL_6G_159 = '6g-159-6745-320'
CHANNEL_6G_161 = '6g-161-6755-20'
CHANNEL_6G_163 = '6g-163-6765-40'
CHANNEL_6G_165 = '6g-165-6775-20'
CHANNEL_6G_167 = '6g-167-6785-80'
CHANNEL_6G_169 = '6g-169-6795-20'
CHANNEL_6G_171 = '6g-171-6805-40'
CHANNEL_6G_173 = '6g-173-6815-20'
CHANNEL_6G_175 = '6g-175-6825-160'
CHANNEL_6G_177 = '6g-177-6835-20'
CHANNEL_6G_179 = '6g-179-6845-40'
CHANNEL_6G_181 = '6g-181-6855-20'
CHANNEL_6G_183 = '6g-183-6865-80'
CHANNEL_6G_185 = '6g-185-6875-20'
CHANNEL_6G_187 = '6g-187-6885-40'
CHANNEL_6G_189 = '6g-189-6895-20'
CHANNEL_6G_193 = '6g-193-6915-20'
CHANNEL_6G_195 = '6g-195-6925-40'
CHANNEL_6G_197 = '6g-197-6935-20'
CHANNEL_6G_199 = '6g-199-6945-80'
CHANNEL_6G_201 = '6g-201-6955-20'
CHANNEL_6G_203 = '6g-203-6965-40'
CHANNEL_6G_205 = '6g-205-6975-20'
CHANNEL_6G_207 = '6g-207-6985-160'
CHANNEL_6G_209 = '6g-209-6995-20'
CHANNEL_6G_211 = '6g-211-7005-40'
CHANNEL_6G_213 = '6g-213-7015-20'
CHANNEL_6G_215 = '6g-215-7025-80'
CHANNEL_6G_217 = '6g-217-7035-20'
CHANNEL_6G_219 = '6g-219-7045-40'
CHANNEL_6G_221 = '6g-221-7055-20'
CHANNEL_6G_225 = '6g-225-7075-20'
CHANNEL_6G_227 = '6g-227-7085-40'
CHANNEL_6G_229 = '6g-229-7095-20'
CHANNEL_6G_233 = '6g-233-7115-20'
# 60 GHz
CHANNEL_60G_1 = '60g-1-58320-2160'
CHANNEL_60G_2 = '60g-2-60480-2160'
CHANNEL_60G_3 = '60g-3-62640-2160'
CHANNEL_60G_4 = '60g-4-64800-2160'
CHANNEL_60G_5 = '60g-5-66960-2160'
CHANNEL_60G_6 = '60g-6-69120-2160'
CHANNEL_60G_9 = '60g-9-59400-4320'
CHANNEL_60G_10 = '60g-10-61560-4320'
CHANNEL_60G_11 = '60g-11-63720-4320'
CHANNEL_60G_12 = '60g-12-65880-4320'
CHANNEL_60G_13 = '60g-13-68040-4320'
CHANNEL_60G_17 = '60g-17-60480-6480'
CHANNEL_60G_18 = '60g-18-62640-6480'
CHANNEL_60G_19 = '60g-19-64800-6480'
CHANNEL_60G_20 = '60g-20-66960-6480'
CHANNEL_60G_25 = '60g-25-61560-6480'
CHANNEL_60G_26 = '60g-26-63720-6480'
CHANNEL_60G_27 = '60g-27-65880-6480'
@strawberry.enum
class WirelessAuthTypeEnum(Enum):
TYPE_OPEN = 'open'
TYPE_WEP = 'wep'
TYPE_WPA_PERSONAL = 'wpa-personal'
TYPE_WPA_ENTERPRISE = 'wpa-enterprise'
@strawberry.enum
class WirelessAuthCipherEnum(Enum):
CIPHER_AUTO = 'auto'
CIPHER_TKIP = 'tkip'
CIPHER_AES = 'aes'

View File

@ -0,0 +1,24 @@
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 import BaseFilterMixin
if TYPE_CHECKING:
from .filters import *
from .enums import *
__all__ = ['WirelessAuthenticationBaseFilterMixin']
@dataclass
class WirelessAuthenticationBaseFilterMixin(BaseFilterMixin):
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()

View File

@ -1,7 +1,32 @@
from typing import Annotated, TYPE_CHECKING
import strawberry
from strawberry.scalars import ID
import strawberry_django
from strawberry_django import (
FilterLookup,
)
from extras.graphql.filter_mixins import *
from netbox.graphql.filter_mixins import *
from core.graphql.filter_mixins import *
from tenancy.graphql.filter_mixins import *
from .filter_mixins import *
from netbox.graphql.filter_mixins import autotype_decorator, BaseFilterMixin
from wireless import filtersets, models
from wireless import models
if TYPE_CHECKING:
from .enums import *
from netbox.graphql.enums import *
from wireless.graphql.enums import *
from core.graphql.filter_lookups import *
from extras.graphql.filters import *
from circuits.graphql.filters import *
from dcim.graphql.filters import *
from ipam.graphql.filters import *
from tenancy.graphql.filters import *
from wireless.graphql.filters import *
from users.graphql.filters import *
from virtualization.graphql.filters import *
from vpn.graphql.filters import *
__all__ = (
'WirelessLANGroupFilter',
@ -11,18 +36,40 @@ __all__ = (
@strawberry_django.filter(models.WirelessLANGroup, lookups=True)
@autotype_decorator(filtersets.WirelessLANGroupFilterSet)
class WirelessLANGroupFilter(BaseFilterMixin):
class WirelessLANGroupFilter(NestedGroupModelFilterMixin):
pass
@strawberry_django.filter(models.WirelessLAN, lookups=True)
@autotype_decorator(filtersets.WirelessLANFilterSet)
class WirelessLANFilter(BaseFilterMixin):
pass
class WirelessLANFilter(WirelessAuthenticationBaseFilterMixin, PrimaryModelFilterMixin):
ssid: FilterLookup[str] | None = strawberry_django.filter_field()
group: Annotated['WirelessLANGroupFilter', strawberry.lazy('wireless.graphql.filters')] | None = (
strawberry_django.filter_field()
)
group_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()
tenant: Annotated['TenantFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
tenant_id: ID | None = strawberry_django.filter_field()
@strawberry_django.filter(models.WirelessLink, lookups=True)
@autotype_decorator(filtersets.WirelessLinkFilterSet)
class WirelessLinkFilter(BaseFilterMixin):
pass
class WirelessLinkFilter(WirelessAuthenticationBaseFilterMixin, DistanceFilterMixin, PrimaryModelFilterMixin):
interface_a: Annotated['InterfaceFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
interface_a_id: ID | None = strawberry_django.filter_field()
interface_b: Annotated['InterfaceFilter', strawberry.lazy('dcim.graphql.filters')] | 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()
)
tenant: Annotated['TenantFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
tenant_id: ID | None = strawberry_django.filter_field()