Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
PYTHON_VER?=3.10
NETBOX_VER?=v4.0.2
NETBOX_VER?=v4.3.2

NAME=netbox-bgp

Expand Down
2 changes: 1 addition & 1 deletion develop/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
ARG python_ver=3.12
FROM python:${python_ver}

ARG netbox_ver=v4.3.1
ARG netbox_ver=v4.3.2
ENV PYTHONUNBUFFERED 1

RUN mkdir -p /opt
Expand Down
52 changes: 52 additions & 0 deletions netbox_bgp/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,53 @@
PrefixListRule,
CommunityList,
CommunityListRule,
ASPathList,
ASPathListRule
)

from netbox_bgp.choices import CommunityStatusChoices, SessionStatusChoices


class ASPathListSerializer(NetBoxModelSerializer):
url = HyperlinkedIdentityField(view_name="plugins-api:netbox_bgp-api:aspathlist-detail")

class Meta:
model = ASPathList
fields = [
"id",
"url",
"name",
"display",
"description",
"tags",
"custom_fields",
"comments",
]
brief_fields = ("id", "url", "display", "name", "description")


class ASPathListRuleSerializer(NetBoxModelSerializer):
aspath_list = ASPathListSerializer(nested=True)

class Meta:
model = ASPathListRule
fields = [
"id",
"description",
"tags",
"custom_fields",
"display",
"aspath_list",
"created",
"last_updated",
"index",
"action",
"pattern",
"comments",
]
brief_fields = ("id", "display", "description")


class RoutingPolicySerializer(NetBoxModelSerializer):
url = HyperlinkedIdentityField(view_name="plugins-api:netbox_bgp-api:routingpolicy-detail")

Expand Down Expand Up @@ -286,6 +328,14 @@ class RoutingPolicyRuleSerializer(NetBoxModelSerializer):
allow_null=True,
many=True,
)
match_aspath_list = SerializedPKRelatedField(
queryset=ASPathList.objects.all(),
serializer=ASPathListSerializer,
nested=True,
required=False,
allow_null=True,
many=True,
)

class Meta:
model = RoutingPolicyRule
Expand All @@ -298,6 +348,7 @@ class Meta:
"routing_policy",
"match_community",
"match_community_list",
"match_aspath_list",
"match_custom",
"set_actions",
"match_ipv6_address",
Expand Down Expand Up @@ -335,3 +386,4 @@ class Meta:
"comments",
)
brief_fields = ("id", "display", "description")

5 changes: 4 additions & 1 deletion netbox_bgp/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
from .views import (
BGPSessionViewSet, RoutingPolicyViewSet, BGPPeerGroupViewSet, CommunityViewSet,
PrefixListViewSet, PrefixListRuleViewSet, RoutingPolicyRuleViewSet,
CommunityListViewSet, CommunityListRuleViewSet, RootView
CommunityListViewSet, CommunityListRuleViewSet, RootView,
ASPathListViewSet, ASPathListRuleViewSet
)


Expand All @@ -20,5 +21,7 @@
router.register('prefix-list-rule', PrefixListRuleViewSet)
router.register('community-list', CommunityListViewSet)
router.register('community-list-rule', CommunityListRuleViewSet)
router.register('aspath-list', ASPathListViewSet)
router.register('aspath-list-rule', ASPathListRuleViewSet)

urlpatterns = router.urls
21 changes: 18 additions & 3 deletions netbox_bgp/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,20 @@
from .serializers import (
BGPSessionSerializer, RoutingPolicySerializer, BGPPeerGroupSerializer,
CommunitySerializer, PrefixListSerializer, PrefixListRuleSerializer,
RoutingPolicyRuleSerializer, CommunityListSerializer, CommunityListRuleSerializer
RoutingPolicyRuleSerializer, CommunityListSerializer, CommunityListRuleSerializer,
ASPathListSerializer, ASPathListRuleSerializer
)
from netbox_bgp.models import (
BGPSession, RoutingPolicy, BGPPeerGroup,
Community, PrefixList, PrefixListRule,
RoutingPolicyRule, CommunityList, CommunityListRule
RoutingPolicyRule, CommunityList, CommunityListRule,
ASPathList, ASPathListRule
)
from netbox_bgp.filtersets import (
BGPSessionFilterSet, RoutingPolicyFilterSet, BGPPeerGroupFilterSet,
CommunityFilterSet, PrefixListFilterSet, PrefixListRuleFilterSet,
RoutingPolicyRuleFilterSet, CommunityListFilterSet, CommunityListRuleFilterSet
RoutingPolicyRuleFilterSet, CommunityListFilterSet, CommunityListRuleFilterSet,
ASPathListFilterSet, ASPathListRuleFilterSet
)

class RootView(APIRootView):
Expand Down Expand Up @@ -74,3 +77,15 @@ class PrefixListRuleViewSet(NetBoxModelViewSet):
queryset = PrefixListRule.objects.all()
serializer_class = PrefixListRuleSerializer
filterset_class = PrefixListRuleFilterSet


class ASPathListViewSet(NetBoxModelViewSet):
queryset = ASPathList.objects.all()
serializer_class = ASPathListSerializer
filterset_class = ASPathListFilterSet


class ASPathListRuleViewSet(NetBoxModelViewSet):
queryset = ASPathListRule.objects.all()
serializer_class = ASPathListRuleSerializer
filterset_class = ASPathListRuleFilterSet
38 changes: 37 additions & 1 deletion netbox_bgp/filtersets.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,48 @@
from .models import (
Community, BGPSession, RoutingPolicy, RoutingPolicyRule,
BGPPeerGroup, PrefixList, PrefixListRule, CommunityList,
CommunityListRule
CommunityListRule, ASPathList, ASPathListRule
)
from ipam.models import IPAddress, ASN
from dcim.models import Device, Site
from virtualization.models import VirtualMachine


class ASPathListFilterSet(NetBoxModelFilterSet):

class Meta:
model = ASPathList
fields = ['id', 'name', 'description']

def search(self, queryset, name, value):
"""Perform the filtered search."""
if not value.strip():
return queryset
qs_filter = (
Q(name__icontains=value)
| Q(description__icontains=value)
)
return queryset.filter(qs_filter)


class ASPathListRuleFilterSet(NetBoxModelFilterSet):

class Meta:
model = ASPathListRule
fields = ['id', 'action', 'aspath_list', 'aspath_list_id']

def search(self, queryset, name, value):
"""Perform the filtered search."""
if not value.strip():
return queryset
qs_filter = (
Q(action__icontains=value)
| Q(aspath_list__icontains=value)
| Q(aspath_list_id__icontains=value)
)
return queryset.filter(qs_filter)


class CommunityFilterSet(NetBoxModelFilterSet, TenancyFilterSet):

class Meta:
Expand Down
61 changes: 61 additions & 0 deletions netbox_bgp/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
PrefixListRule,
CommunityList,
CommunityListRule,
ASPathList,
ASPathListRule,
)

from .choices import (
Expand All @@ -50,6 +52,59 @@

from virtualization.models import VirtualMachine

class ASPathListFilterForm(NetBoxModelFilterSetForm):
model = ASPathList
q = forms.CharField(required=False, label="Search")

tag = TagFilterField(model)

class ASPathListRuleFilterForm(NetBoxModelFilterSetForm):
model = ASPathListRule
q = forms.CharField(required=False, label="Search")
aspath_list = DynamicModelChoiceField(queryset=ASPathList.objects.all(), required=False)
tag = TagFilterField(model)


class ASPathListForm(NetBoxModelForm):

comments = CommentField()

class Meta:
model = ASPathList
fields = ["name", "description", "tags", "comments"]


class ASPathListBulkEditForm(NetBoxModelBulkEditForm):
description = forms.CharField(max_length=200, required=False)

model = ASPathList
nullable_fields = [
"description",
]


class ASPathListImportForm(NetBoxModelImportForm):

class Meta:
model = ASPathList
fields = ["name", "description", "tags"]


class ASPathListRuleImportForm(NetBoxModelImportForm):

class Meta:
model = ASPathListRule
fields = ["aspath_list", "index", "action", "pattern", "description", "tags", "comments"]


class ASPathListRuleForm(NetBoxModelForm):
comments = CommentField()

class Meta:
model = ASPathListRule
fields = ["aspath_list", "index", "action", "pattern", "description", "tags", "comments"]


class CommunityForm(NetBoxModelForm):
status = forms.ChoiceField(
required=False,
Expand Down Expand Up @@ -647,6 +702,11 @@ class RoutingPolicyRuleForm(NetBoxModelForm):
}
)

match_aspath_list = DynamicModelMultipleChoiceField(
queryset=ASPathList.objects.all(),
required=False,
)

match_custom = forms.JSONField(
label="Custom Match",
help_text='Any custom match statements, e.g., {"ip nexthop": "1.1.1.1"}',
Expand Down Expand Up @@ -674,6 +734,7 @@ class Meta:
"match_community_list",
"match_ip_address",
"match_ipv6_address",
"match_aspath_list",
"match_custom",
"set_actions",
"description",
Expand Down
8 changes: 4 additions & 4 deletions netbox_bgp/graphql/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
"NetBoxBGPIPAddressFamilyEnum",
)

NetBoxBGPCommunityStatusEnum = strawberry.enum(CommunityStatusChoices.as_enum())
NetBoxBGPSessionStatusEnum = strawberry.enum(SessionStatusChoices.as_enum())
NetBoxBGPActionEnum = strawberry.enum(ActionChoices.as_enum())
NetBoxBGPIPAddressFamilyEnum = strawberry.enum(IPAddressFamilyChoices.as_enum())
NetBoxBGPCommunityStatusEnum = strawberry.enum(CommunityStatusChoices.as_enum(), name="NetBoxBGPCommunityStatusEnum" )
NetBoxBGPSessionStatusEnum = strawberry.enum(SessionStatusChoices.as_enum(), name="NetBoxBGPSessionStatusEnum")
NetBoxBGPActionEnum = strawberry.enum(ActionChoices.as_enum(), name="NetBoxBGPActionEnum")
NetBoxBGPIPAddressFamilyEnum = strawberry.enum(IPAddressFamilyChoices.as_enum(), name="NetBoxBGPIPAddressFamilyEnum")

36 changes: 35 additions & 1 deletion netbox_bgp/graphql/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from netbox.graphql.filter_mixins import NetBoxModelFilterMixin
from tenancy.graphql.filter_mixins import TenancyFilterMixin
from ipam.graphql.filters import IPAddressFilter, ASNFilter
from dcim.graphql.filter import DeviceFilter
from dcim.graphql.filters import DeviceFilter

from netbox_bgp.models import (
Community,
Expand All @@ -19,6 +19,8 @@
PrefixListRule,
CommunityList,
CommunityListRule,
ASPathList,
ASPathListRule
)

from netbox_bgp.filtersets import (
Expand All @@ -31,6 +33,8 @@
PrefixListRuleFilterSet,
CommunityListFilterSet,
CommunityListRuleFilterSet,
ASPathListFilterSet,
ASPathListRuleFilterSet
)

from netbox_bgp.graphql.enums import (
Expand All @@ -51,8 +55,31 @@
"NetBoxBGPPrefixListRuleFilter",
"NetBoxBGPCommunityListFilter",
"NetBoxBGPCommunityListRuleFilter",
"NetBoxBGPASPathListFilter",
"NetBoxBGPASPathListRuleFilter"
)

@strawberry_django.filter_type(ASPathList, lookups=True)
class NetBoxBGPASPathListFilter(NetBoxModelFilterMixin):
name: FilterLookup[str] | None = strawberry_django.filter_field()
description: FilterLookup[str] | None = strawberry_django.filter_field()

@strawberry_django.filter_type(ASPathListRule, lookups=True)
class NetBoxBGPASPathListRuleFilter(NetBoxModelFilterMixin):
value: FilterLookup[str] | None = strawberry_django.filter_field()
aspath_list: (
Annotated[
"NetBoxBGPASPathListFilter", strawberry.lazy("netbox_bgp.graphql.filters")
]
| None
) = strawberry_django.filter_field()
aspath_list_id: ID | None = strawberry_django.filter_field()
action: (
Annotated[
"NetBoxBGPActionEnum", strawberry.lazy("netbox_bgp.graphql.enums")
]
| None
) = strawberry_django.filter_field()

@strawberry_django.filter_type(Community, lookups=True)
class NetBoxBGPCommunityFilter(TenancyFilterMixin, NetBoxModelFilterMixin):
Expand Down Expand Up @@ -152,6 +179,13 @@ class NetBoxBGPRoutingPolicyRuleFilter(NetBoxModelFilterMixin):
]
| None
) = strawberry_django.filter_field()
aspath_list: (
Annotated[
"NetBoxBGPASPathListFilter", strawberry.lazy("netbox_bgp.graphql.filters")
]
| None
) = strawberry_django.filter_field()
aspath_list_id: ID | None = strawberry_django.filter_field()


@strawberry_django.filter_type(PrefixList, lookups=True)
Expand Down
Loading