Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Netbox 4.0 Compatibility #199

Merged
merged 7 commits into from
Jun 7, 2024
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 Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
ARG NETBOX_VARIANT=v3.7
ARG NETBOX_VARIANT=v4.0

FROM netboxcommunity/netbox:${NETBOX_VARIANT}

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Each Plugin Version listed below has been tested with its corresponding NetBox V

| NetBox Version | Plugin Version |
|:--------------:|:--------------:|
| >= 4.0.2 | 1.6.0 |
| 3.7 | 1.5.0 |
| 3.6 | 1.4.0 |
| 3.5 | 1.3.0 |
Expand Down
1 change: 1 addition & 0 deletions netbox_acls/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* @ryanmerolle @abhi1693 @cruse1977 @natm
6 changes: 3 additions & 3 deletions netbox_acls/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Define the NetBox Plugin
"""

from extras.plugins import PluginConfig
from netbox.plugins import PluginConfig

from .version import __version__

Expand All @@ -17,8 +17,8 @@ class NetBoxACLsConfig(PluginConfig):
version = __version__
description = "Manage simple ACLs in NetBox"
base_url = "access-lists"
min_version = "3.7.0"
max_version = "3.7.99"
min_version = "4.0.2"
max_version = "4.0.99"


config = NetBoxACLsConfig
7 changes: 5 additions & 2 deletions netbox_acls/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ class Meta:
"last_updated",
"rule_count",
)
brief_fields = ("id", "url", "name", "display")

@extend_schema_field(serializers.DictField())
def get_assigned_object(self, obj):
Expand Down Expand Up @@ -139,6 +140,7 @@ class Meta:
"created",
"last_updated",
)
brief_fields = ("id", "url", "access_list")

@extend_schema_field(serializers.DictField())
def get_assigned_object(self, obj):
Expand Down Expand Up @@ -212,6 +214,7 @@ class Meta:
"last_updated",
"source_prefix",
)
brief_fields = ("id", "url", "display")

def validate(self, data):
"""
Expand Down Expand Up @@ -284,7 +287,7 @@ class Meta:
"protocol",
"remark",
)

brief_fields = ("id", "url", "display")
def validate(self, data):
"""
Validate the ACLExtendedRule django model's inputs before allowing it to update the instance:
Expand Down Expand Up @@ -328,7 +331,7 @@ def validate(self, data):
if data.get("protocol"):
error_message["protocol"] = [
"Action is set to remark, Protocol CANNOT be set.",
]
]

if error_message:
raise serializers.ValidationError(error_message)
Expand Down
7 changes: 7 additions & 0 deletions netbox_acls/graphql/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,9 @@
from .schema import *
from .types import *

schema = [
schema.NetBoxACLSAccessListQuery,
schema.NetBoxACLSStandardRuleQuery,
schema.NetBoxACLSACLExtendedRuleQuery
]

30 changes: 30 additions & 0 deletions netbox_acls/graphql/filters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import strawberry_django
from .. import filtersets, models
from netbox.graphql.filter_mixins import autotype_decorator, BaseFilterMixin

__all__ = (
'AccessListFilter',
'ACLInterfaceAssignmentFilter',
'ACLExtendedRuleFilter',
'ACLStandardRuleFilter',
)

@strawberry_django.filter(models.AccessList, lookups=True)
@autotype_decorator(filtersets.AccessListFilterSet)
class AccessListFilter(BaseFilterMixin):
pass

@strawberry_django.filter(models.ACLStandardRule, lookups=True)
@autotype_decorator(filtersets.ACLStandardRuleFilterSet)
class ACLStandardRuleFilter(BaseFilterMixin):
pass

@strawberry_django.filter(models.ACLExtendedRule, lookups=True)
@autotype_decorator(filtersets.ACLExtendedRuleFilterSet)
class ACLExtendedRuleFilter(BaseFilterMixin):
pass

@strawberry_django.filter(models.ACLInterfaceAssignment, lookups=True)
@autotype_decorator(filtersets.ACLInterfaceAssignmentFilterSet)
class ACLInterfaceAssignmentFilter(BaseFilterMixin):
pass
34 changes: 22 additions & 12 deletions netbox_acls/graphql/schema.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,32 @@
from graphene import ObjectType
from netbox.graphql.fields import ObjectField, ObjectListField

import strawberry
import strawberry_django
from .types import *
from ..models import *


class Query(ObjectType):
@strawberry.type
class NetBoxACLSAccessListQuery:
"""
Defines the queries available to this plugin via the graphql api.
"""
@strawberry.field
def access_list(self, id: int) -> AccessListType:
return AccessList.objects.get(pk=id)
access_list_list: list[AccessListType] = strawberry_django.field()

@strawberry.type
class NetBoxACLSACLExtendedRuleQuery:
@strawberry.field
def acl_extended_rule(self, id: int) -> ACLExtendedRuleType:
return ACLExtendedRule.objects.get(pk=id)
acl_extended_rule_list: list[ACLExtendedRuleType] = strawberry_django.field()

access_list = ObjectField(AccessListType)
access_list_list = ObjectListField(AccessListType)

acl_extended_rule = ObjectField(ACLExtendedRuleType)
acl_extended_rule_list = ObjectListField(ACLExtendedRuleType)

acl_standard_rule = ObjectField(ACLStandardRuleType)
acl_standard_rule_list = ObjectListField(ACLStandardRuleType)
@strawberry.type
class NetBoxACLSStandardRuleQuery:
@strawberry.field
def acl_standard_rule(self, id: int) -> ACLStandardRuleType:
return ACLStandardRule.objects.get(pk=id)
acl_standard_rule_list: list[ACLStandardRuleType] = strawberry_django.field()


schema = Query
99 changes: 69 additions & 30 deletions netbox_acls/graphql/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,73 +2,112 @@
Define the object types and queries availble via the graphql api.
"""

from netbox.graphql.types import NetBoxObjectType
import strawberry
import strawberry_django

from .. import filtersets, models

__all__ = (
"AccessListType",
"ACLInterfaceAssignmentType",
"ACLExtendedRuleType",
"ACLStandardRuleType",
)
from typing import Annotated, List, Union
from .filters import *
from .. import models
from netbox.graphql.types import OrganizationalObjectType

@strawberry_django.type(
models.AccessList,
fields='__all__',
filters=AccessListFilter,
exclude=('assigned_object_type', 'assigned_object_id')
)

class AccessListType(NetBoxObjectType):
class AccessListType(OrganizationalObjectType):
"""
Defines the object type for the django model AccessList.
"""
assigned_object_type: Annotated["ContentTypeType", strawberry.lazy("netbox.graphql.types")]
assigned_object: Annotated[Union[
Annotated["DeviceType", strawberry.lazy('dcim.graphql.types')],
Annotated["VirtualMachineType", strawberry.lazy('virtualization.graphql.types')],
], strawberry.union("ACLAssignmentType")]


class Meta:
"""
Associates the filterset, fields, and model for the django model AccessList.
"""

model = models.AccessList
fields = "__all__"
filterset_class = filtersets.AccessListFilterSet


class ACLInterfaceAssignmentType(NetBoxObjectType):
@strawberry_django.field
def accesslists(self) -> List[Annotated["AccessList", strawberry.lazy('accesslists.graphql.types')]]:
return self.accesslists.all()

@strawberry_django.type(
models.ACLInterfaceAssignment,
fields='__all__',
exclude=('assigned_object_type', 'assigned_object_id'),
filters=ACLInterfaceAssignmentFilter
)
class ACLInterfaceAssignmentType(OrganizationalObjectType):
"""
Defines the object type for the django model AccessList.
"""
access_list: Annotated["AccessListType", strawberry.lazy("netbox_acls.graphql.types")]
assigned_object_type: Annotated["ContentTypeType", strawberry.lazy("netbox.graphql.types")]
assigned_object: Annotated[Union[
Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')],
Annotated["VMInterfaceType", strawberry.lazy('virtualization.graphql.types')],
], strawberry.union("ACLInterfaceAssignmentType")]




class Meta:
"""
Associates the filterset, fields, and model for the django model ACLInterfaceAssignment.
"""
@strawberry_django.field
def aclinterfaceassignments(self) -> List[Annotated["ACLInterfaceAssignment", strawberry.lazy('aclinterfaceassignments.graphql.types')]]:
return self.aclinterfaceassignments.all()

@strawberry_django.type(
models.ACLExtendedRule,
fields='__all__',
filters=ACLExtendedRuleFilter
)

model = models.ACLInterfaceAssignment
fields = "__all__"
filterset_class = filtersets.ACLInterfaceAssignmentFilterSet


class ACLExtendedRuleType(NetBoxObjectType):
class ACLExtendedRuleType(OrganizationalObjectType):
"""
Defines the object type for the django model ACLExtendedRule.
"""
source_ports: List[int]
destination_ports: List[int]
access_list: Annotated["AccessListType", strawberry.lazy("netbox_acls.graphql.types")]
destination_prefix: Annotated["PrefixType", strawberry.lazy("ipam.graphql.types")]
source_prefix: Annotated["PrefixType", strawberry.lazy("ipam.graphql.types")]

class Meta:
"""
Associates the filterset, fields, and model for the django model ACLExtendedRule.
"""
@strawberry_django.field
def aclextendedrules(self) -> List[Annotated["ACLExtendedRule", strawberry.lazy('aclextendedrule.graphql.types')]]:
return self.aclextendedrules.all()

model = models.ACLExtendedRule
fields = "__all__"
filterset_class = filtersets.ACLExtendedRuleFilterSet

@strawberry_django.type(
models.ACLStandardRule,
fields='__all__',
filters=ACLStandardRuleFilter
)

class ACLStandardRuleType(NetBoxObjectType):
class ACLStandardRuleType(OrganizationalObjectType):
"""
Defines the object type for the django model ACLStandardRule.
"""
access_list: Annotated["AccessListType", strawberry.lazy("netbox_acls.graphql.types")]
source_prefix: Annotated["PrefixType", strawberry.lazy("ipam.graphql.types")]

class Meta:
"""
Associates the filterset, fields, and model for the django model ACLStandardRule.
Associates the filterset, fields, and model for the django model ACLExtendedRule.
"""
@strawberry_django.field
def aclstandardrules(self) -> List[Annotated["ACLStandardRule", strawberry.lazy('aclstandardrule.graphql.types')]]:
return self.aclstandardrules.all()

model = models.ACLStandardRule
fields = "__all__"
filterset_class = filtersets.ACLStandardRuleFilterSet
8 changes: 2 additions & 6 deletions netbox_acls/navigation.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
"""

from django.conf import settings
from extras.plugins import PluginMenu, PluginMenuButton, PluginMenuItem
from utilities.choices import ButtonColorChoices
from netbox.plugins import PluginMenu, PluginMenuButton, PluginMenuItem


plugin_settings = settings.PLUGINS_CONFIG["netbox_acls"]

Expand All @@ -21,7 +21,6 @@
link="plugins:netbox_acls:accesslist_add",
title="Add",
icon_class="mdi mdi-plus-thick",
color=ButtonColorChoices.GREEN,
permissions=["netbox_acls.add_accesslist"],
),
),
Expand All @@ -35,7 +34,6 @@
link="plugins:netbox_acls:aclstandardrule_add",
title="Add",
icon_class="mdi mdi-plus-thick",
color=ButtonColorChoices.GREEN,
permissions=["netbox_acls.add_aclstandardrule"],
),
),
Expand All @@ -49,7 +47,6 @@
link="plugins:netbox_acls:aclextendedrule_add",
title="Add",
icon_class="mdi mdi-plus-thick",
color=ButtonColorChoices.GREEN,
permissions=["netbox_acls.add_aclextendedrule"],
),
),
Expand All @@ -63,7 +60,6 @@
link="plugins:netbox_acls:aclinterfaceassignment_add",
title="Add",
icon_class="mdi mdi-plus-thick",
color=ButtonColorChoices.GREEN,
permissions=["netbox_acls.add_aclinterfaceassignment"],
),
),
Expand Down
2 changes: 1 addition & 1 deletion netbox_acls/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def setUpTestData(cls):
name="Device 1",
site=site,
device_type=devicetype,
device_role=devicerole,
role=devicerole,
)

access_lists = (
Expand Down
2 changes: 1 addition & 1 deletion netbox_acls/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "1.5.0"
__version__ = "1.6.0"
8 changes: 4 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
script_dir = os.path.abspath(os.path.dirname(__file__))

with open(os.path.join(script_dir, "README.md"), encoding="utf-8") as fh:
long_description = fh.read().replace("(docs/img/", "(https://raw.githubusercontent.com/ryanmerolle/netbox-acls/release/docs/img/")
long_description = fh.read().replace("(docs/img/", "(https://raw.githubusercontent.com/netbox-community/netbox-acls/release/docs/img/")


def read(relative_path):
Expand Down Expand Up @@ -37,7 +37,7 @@ def get_version(relative_path):
description="A NetBox plugin for Access List management",
long_description=long_description,
long_description_content_type="text/markdown",
url="https://github.com/ryanmerolle/netbox-acls",
url="https://github.com/netbox-community/netbox-acls",
license="Apache 2.0",
install_requires=[],
python_requires=">=3.10",
Expand All @@ -61,7 +61,7 @@ def get_version(relative_path):
"Topic :: Internet",
],
project_urls={
"Issues": "https://github.com/ryanmerolle/netbox-acls/issues",
"Source": "https://github.com/ryanmerolle/netbox-acls",
"Issues": "https://github.com/netbox-community/netbox-acls/issues",
"Source": "https://github.com/netbox-community/netbox-acls",
},
)