NetBox 3.5 Support (#148)

* NetBox 3.5 updates
This commit is contained in:
Ryan Merolle 2023-06-23 14:41:42 -04:00 committed by GitHub
parent fa38ef4df2
commit 108fbb6751
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 133 additions and 143 deletions

View File

@ -1,8 +1,8 @@
ARG NETBOX_VARIANT=v3.4
ARG NETBOX_VARIANT=v3.5
FROM netboxcommunity/netbox:${NETBOX_VARIANT}
ARG NETBOX_INITIALIZERS_VARIANT=3.4.*
ARG NETBOX_INITIALIZERS_VARIANT=3.5.*
ARG DEBIAN_FRONTEND=noninteractive

View File

@ -7,7 +7,7 @@ from os.path import abspath, dirname, join
# Read secret from file
def _read_secret(secret_name, default=None):
try:
f = open("/run/secrets/" + secret_name, encoding="utf-8")
f = open(f"/run/secrets/{secret_name}", encoding="utf-8")
except OSError:
return default
else:
@ -74,8 +74,7 @@ REDIS = {
environ.get("REDIS_CACHE_PASSWORD", environ.get("REDIS_PASSWORD", "")),
),
"DATABASE": int(environ.get("REDIS_CACHE_DATABASE", 1)),
"SSL": environ.get("REDIS_CACHE_SSL", environ.get("REDIS_SSL", "False")).lower()
== "true",
"SSL": environ.get("REDIS_CACHE_SSL", environ.get("REDIS_SSL", "False")).lower() == "true",
"INSECURE_SKIP_TLS_VERIFY": environ.get(
"REDIS_CACHE_INSECURE_SKIP_TLS_VERIFY",
environ.get("REDIS_INSECURE_SKIP_TLS_VERIFY", "False"),
@ -252,9 +251,7 @@ REMOTE_AUTH_BACKEND = environ.get(
"netbox.authentication.RemoteUserBackend",
)
REMOTE_AUTH_HEADER = environ.get("REMOTE_AUTH_HEADER", "HTTP_REMOTE_USER")
REMOTE_AUTH_AUTO_CREATE_USER = (
environ.get("REMOTE_AUTH_AUTO_CREATE_USER", "True").lower() == "true"
)
REMOTE_AUTH_AUTO_CREATE_USER = environ.get("REMOTE_AUTH_AUTO_CREATE_USER", "True").lower() == "true"
REMOTE_AUTH_DEFAULT_GROUPS = list(
filter(None, environ.get("REMOTE_AUTH_DEFAULT_GROUPS", "").split(" ")),
)

View File

@ -78,23 +78,31 @@
"extensions": [
"DavidAnson.vscode-markdownlint",
"GitHub.codespaces",
"GitHub.copilot",
"GitHub.copilot-labs",
"GitHub.vscode-pull-request-github",
"Gruntfuggly.todo-tree",
"Tyriar.sort-lines",
"aaron-bond.better-comments",
"batisteo.vscode-django",
"charliermarsh.ruff",
"codezombiech.gitignore",
"esbenp.prettier-vscode",
"exiasr.hadolint",
"formulahendry.auto-rename-tag",
"mintlify.document",
"ms-python.isort",
"ms-python.pylint",
"ms-python.python",
"ms-python.vscode-pylance",
"ms-vscode.makefile-tools",
"mutantdino.resourcemonitor",
"oderwat.indent-rainbow",
"paulomenezes.duplicated-code",
"redhat.vscode-yaml",
"searKing.preview-vscode",
"sourcery.sourcery"
"sourcery.sourcery",
"wholroyd.jinja",
"yzhang.markdown-all-in-one"
]
}
},

View File

@ -15,7 +15,7 @@ REDIS_DATABASE=0
REDIS_HOST=redis
REDIS_INSECURE_SKIP_TLS_VERIFY=false
REDIS_PASSWORD=H733Kdjndks81
SECRET_KEY=r8OwDznj!!dciP9ghmRfdu1Ysxm0AiPeDCQhKE+N_rClfWNj
SECRET_KEY=r8OwDznj!!dciP9ghmRfdu1Ysxm0AiPeDCQhKE+N_rClfWNjaa
SUPERUSER_API_TOKEN=0123456789abcdef0123456789abcdef01234567
SUPERUSER_EMAIL=admin@example.com
SUPERUSER_NAME=admin

View File

@ -10,6 +10,7 @@ pycodestyle
pydocstyle
pylint
pylint-django
ruff
sourcery-analytics
wily
yapf
sourcery-analytics

View File

@ -1,3 +1,3 @@
[flake8]
max-line-length = 160
max-line-length = 140
extend-ignore = E203

View File

@ -23,14 +23,14 @@ body:
attributes:
label: NetBox access-list plugin version
description: What version of the NetBox access-list plugin are you currently running?
placeholder: v1.2.0
placeholder: v1.3.0
validations:
required: true
- type: input
attributes:
label: NetBox version
description: What version of NetBox are you currently running?
placeholder: v3.4.3
placeholder: v3.5.4
validations:
required: true
- type: textarea

View File

@ -15,7 +15,7 @@ body:
attributes:
label: NetBox version
description: What version of NetBox are you currently running?
placeholder: v3.4.3
placeholder: v3.5.4
validations:
required: true
- type: dropdown

View File

@ -1,8 +0,0 @@
[settings]
profile = black
; vertical hanging indent mode also used in black configuration
multi_line_output = 3
; necessary because black expect the trailing comma
include_trailing_comma = true

View File

@ -1,4 +1,4 @@
{
"threshold": 10,
"ignore": ["**/tests/**"]
"ignore": ["**/migrations/**", "**/tests/**"]
}

View File

@ -21,13 +21,13 @@ repos:
- "--profile=black"
exclude: ^.devcontainer/
- repo: https://github.com/psf/black
rev: 23.1.0
rev: 23.3.0
hooks:
- id: black
language_version: python3
exclude: ^.devcontainer/
- repo: https://github.com/asottile/add-trailing-comma
rev: v2.4.0
rev: v2.5.1
hooks:
- id: add-trailing-comma
args:
@ -38,13 +38,13 @@ repos:
- id: flake8
exclude: ^.devcontainer/
- repo: https://github.com/asottile/pyupgrade
rev: v3.3.1
rev: v3.7.0
hooks:
- id: pyupgrade
args:
- "--py39-plus"
- repo: https://github.com/adrienverge/yamllint
rev: v1.29.0
rev: v1.32.0
hooks:
- id: yamllint
- repo: https://github.com/econchick/interrogate
@ -59,9 +59,13 @@ repos:
# - id: htmlhint
# args: [--config, .htmlhintrc]
- repo: https://github.com/igorshubovych/markdownlint-cli
rev: v0.33.0
rev: v0.35.0
hooks:
- id: markdownlint
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.0.272
hooks:
- id: ruff
#- repo: local
# hooks:
# - id: wily

View File

@ -1,9 +1,9 @@
ARG NETBOX_VARIANT=v3.4
ARG NETBOX_VARIANT=v3.5
FROM netboxcommunity/netbox:${NETBOX_VARIANT}
RUN mkdir -pv /plugins/netbox-acls
COPY . /plugins/netbox-acls
RUN /opt/netbox/venv/bin/python3 /plugins/netbox-acls/setup.py develop
RUN cp -rf /plugins/netbox-acls/netbox_acls/ /opt/netbox/venv/lib/python3.10/site-packages/netbox_acls
RUN /opt/netbox/venv/bin/python3 /plugins/netbox-acls/setup.py develop && \
cp -rf /plugins/netbox-acls/netbox_acls/ /opt/netbox/venv/lib/python3.10/site-packages/netbox_acls

View File

@ -41,6 +41,7 @@ Each Plugin Version listed below has been tested with its corresponding NetBox V
| 3.2 | 1.0.1 |
| 3.3 | 1.1.0 |
| 3.4 | 1.2.2 |
| 3.5 | 1.3.0 |
## Installing

View File

@ -14,7 +14,7 @@ from os.path import abspath, dirname
# Read secret from file
def _read_secret(secret_name, default=None):
try:
f = open("/run/secrets/" + secret_name, encoding="utf-8")
f = open(f"/run/secrets/{secret_name}", encoding="utf-8")
except OSError:
return default
else:
@ -81,8 +81,7 @@ REDIS = {
environ.get("REDIS_CACHE_PASSWORD", environ.get("REDIS_PASSWORD", "")),
),
"DATABASE": int(environ.get("REDIS_CACHE_DATABASE", 1)),
"SSL": environ.get("REDIS_CACHE_SSL", environ.get("REDIS_SSL", "False")).lower()
== "true",
"SSL": environ.get("REDIS_CACHE_SSL", environ.get("REDIS_SSL", "False")).lower() == "true",
"INSECURE_SKIP_TLS_VERIFY": environ.get(
"REDIS_CACHE_INSECURE_SKIP_TLS_VERIFY",
environ.get("REDIS_INSECURE_SKIP_TLS_VERIFY", "False"),

2
env/netbox.env vendored
View File

@ -14,7 +14,7 @@ REDIS_DATABASE=0
REDIS_HOST=redis
REDIS_INSECURE_SKIP_TLS_VERIFY=false
REDIS_PASSWORD=H733Kdjndks81
SECRET_KEY=r8OwDznj!!dciP9ghmRfdu1Ysxm0AiPeDCQhKE+N_rClfWNj
SECRET_KEY=r8OwDznj!!dciP9ghmRfdu1Ysxm0AiPeDCQhKE+N_rClfWNjaa
SUPERUSER_API_TOKEN=0123456789abcdef0123456789abcdef01234567
SUPERUSER_EMAIL=admin@example.com
SUPERUSER_NAME=admin

View File

@ -17,8 +17,8 @@ class NetBoxACLsConfig(PluginConfig):
version = __version__
description = "Manage simple ACLs in NetBox"
base_url = "access-lists"
min_version = "3.4.0"
max_version = "3.4.99"
min_version = "3.5.0"
max_version = "3.5.99"
config = NetBoxACLsConfig

View File

@ -4,8 +4,7 @@ while Django itself handles the database abstraction.
"""
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ObjectDoesNotExist
from drf_yasg.utils import swagger_serializer_method
from drf_spectacular.utils import extend_schema_field
from ipam.api.serializers import NestedPrefixSerializer
from netbox.api.fields import ContentTypeField
from netbox.api.serializers import NetBoxModelSerializer
@ -32,13 +31,9 @@ __all__ = [
# Sets a standard error message for ACL rules with an action of remark, but no remark set.
error_message_no_remark = "Action is set to remark, you MUST add a remark."
# Sets a standard error message for ACL rules with an action of remark, but no source_prefix is set.
error_message_action_remark_source_prefix_set = (
"Action is set to remark, Source Prefix CANNOT be set."
)
error_message_action_remark_source_prefix_set = "Action is set to remark, Source Prefix CANNOT be set."
# Sets a standard error message for ACL rules with an action not set to remark, but no remark is set.
error_message_remark_without_action_remark = (
"CANNOT set remark unless action is set to remark."
)
error_message_remark_without_action_remark = "CANNOT set remark unless action is set to remark."
# Sets a standard error message for ACL rules no associated to an ACL of the same type.
error_message_acl_type = "Provided parent Access List is not of right type."
@ -81,7 +76,7 @@ class AccessListSerializer(NetBoxModelSerializer):
"rule_count",
)
@swagger_serializer_method(serializer_or_field=serializers.DictField)
@extend_schema_field(serializers.DictField())
def get_assigned_object(self, obj):
serializer = get_serializer_for_model(
obj.assigned_object,
@ -99,11 +94,7 @@ class AccessListSerializer(NetBoxModelSerializer):
error_message = {}
# Check if Access List has no existing rules before change the Access List's type.
if (
self.instance
and self.instance.type != data.get("type")
and self.instance.rule_count > 0
):
if self.instance and self.instance.type != data.get("type") and self.instance.rule_count > 0:
error_message["type"] = [
"This ACL has ACL rules associated, CANNOT change ACL type.",
]
@ -149,7 +140,7 @@ class ACLInterfaceAssignmentSerializer(NetBoxModelSerializer):
"last_updated",
)
@swagger_serializer_method(serializer_or_field=serializers.DictField)
@extend_schema_field(serializers.DictField())
def get_assigned_object(self, obj):
serializer = get_serializer_for_model(
obj.assigned_object,
@ -168,24 +159,14 @@ class ACLInterfaceAssignmentSerializer(NetBoxModelSerializer):
acl_host = data["access_list"].assigned_object
if data["assigned_object_type"].model == "interface":
interface_host = (
data["assigned_object_type"]
.get_object_for_this_type(id=data["assigned_object_id"])
.device
)
interface_host = data["assigned_object_type"].get_object_for_this_type(id=data["assigned_object_id"]).device
elif data["assigned_object_type"].model == "vminterface":
interface_host = (
data["assigned_object_type"]
.get_object_for_this_type(id=data["assigned_object_id"])
.virtual_machine
)
interface_host = data["assigned_object_type"].get_object_for_this_type(id=data["assigned_object_id"]).virtual_machine
else:
interface_host = None
# Check that the associated interface's parent host has the selected ACL defined.
if acl_host != interface_host:
error_acl_not_assigned_to_host = (
"Access List not present on the selected interface's host."
)
error_acl_not_assigned_to_host = "Access List not present on the selected interface's host."
error_message["access_list"] = [error_acl_not_assigned_to_host]
error_message["assigned_object_id"] = [error_acl_not_assigned_to_host]

View File

@ -10,6 +10,5 @@ ACL_HOST_ASSIGNMENT_MODELS = Q(
)
ACL_INTERFACE_ASSIGNMENT_MODELS = Q(
Q(app_label="dcim", model="interface")
| Q(app_label="virtualization", model="vminterface"),
Q(app_label="dcim", model="interface") | Q(app_label="virtualization", model="vminterface"),
)

View File

@ -7,11 +7,11 @@ Draft for a possible BulkEditForm, but may not be worth wile.
# from django.core.exceptions import ValidationError
# from django.utils.safestring import mark_safe
# from netbox.forms import NetBoxModelBulkEditForm
# from utilities.forms import (
# from utilities.forms.utils import add_blank_choice
# from utilities.forms.fields import (
# ChoiceField,
# DynamicModelChoiceField,
# StaticSelect,
# add_blank_choice,
# )
# from virtualization.models import VirtualMachine

View File

@ -6,13 +6,13 @@ from dcim.models import Device, Interface, Region, Site, SiteGroup, VirtualChass
from django import forms
from ipam.models import Prefix
from netbox.forms import NetBoxModelFilterSetForm
from utilities.forms import (
from utilities.forms.fields import (
ChoiceField,
DynamicModelChoiceField,
DynamicModelMultipleChoiceField,
TagFilterField,
add_blank_choice,
)
from utilities.forms.utils import add_blank_choice
from virtualization.models import VirtualMachine, VMInterface
from ..choices import (

View File

@ -8,7 +8,7 @@ from django.contrib.contenttypes.models import ContentType
from django.utils.safestring import mark_safe
from ipam.models import Prefix
from netbox.forms import NetBoxModelForm
from utilities.forms import CommentField, DynamicModelChoiceField
from utilities.forms.fields import CommentField, DynamicModelChoiceField
from virtualization.models import (
Cluster,
ClusterGroup,
@ -39,20 +39,14 @@ help_text_acl_rule_logic = mark_safe(
# Sets a standard help_text value to be used by the various classes for acl action
help_text_acl_action = "Action the rule will take (remark, deny, or allow)."
# Sets a standard help_text value to be used by the various classes for acl index
help_text_acl_rule_index = (
"Determines the order of the rule in the ACL processing. AKA Sequence Number."
)
help_text_acl_rule_index = "Determines the order of the rule in the ACL processing. AKA Sequence Number."
# Sets a standard error message for ACL rules with an action of remark, but no remark set.
error_message_no_remark = "Action is set to remark, you MUST add a remark."
# Sets a standard error message for ACL rules with an action of remark, but no source_prefix is set.
error_message_action_remark_source_prefix_set = (
"Action is set to remark, Source Prefix CANNOT be set."
)
error_message_action_remark_source_prefix_set = "Action is set to remark, Source Prefix CANNOT be set."
# Sets a standard error message for ACL rules with an action not set to remark, but no remark is set.
error_message_remark_without_action_remark = (
"CANNOT set remark unless action is set to remark."
)
error_message_remark_without_action_remark = "CANNOT set remark unless action is set to remark."
class AccessListForm(NetBoxModelForm):
@ -149,7 +143,6 @@ class AccessListForm(NetBoxModelForm):
}
def __init__(self, *args, **kwargs):
# Initialize helper selectors
instance = kwargs.get("instance")
initial = kwargs.get("initial", {}).copy()
@ -168,9 +161,7 @@ class AccessListForm(NetBoxModelForm):
if instance.assigned_object.cluster:
initial["cluster"] = instance.assigned_object.cluster
if instance.assigned_object.cluster.group:
initial[
"cluster_group"
] = instance.assigned_object.cluster.group
initial["cluster_group"] = instance.assigned_object.cluster.group
if instance.assigned_object.cluster.type:
initial["cluster_type"] = instance.assigned_object.cluster.type
@ -199,13 +190,9 @@ class AccessListForm(NetBoxModelForm):
virtual_machine = cleaned_data.get("virtual_machine")
# Check if more than one host type selected.
if (
(device and virtual_chassis)
or (device and virtual_machine)
or (virtual_chassis and virtual_machine)
):
if (device and virtual_chassis) or (device and virtual_machine) or (virtual_chassis and virtual_machine):
raise forms.ValidationError(
"Access Lists must be assigned to one host (either a device, virtual chassis or virtual machine) at a time.",
"Access Lists must be assigned to one host at a time. Either a device, virtual chassis or virtual machine."
)
# Check if no hosts selected.
if not device and not virtual_chassis and not virtual_machine:
@ -230,24 +217,16 @@ class AccessListForm(NetBoxModelForm):
).exists()
# Check if duplicate entry.
if (
"name" in self.changed_data or host_type in self.changed_data
) and existing_acls:
error_same_acl_name = (
"An ACL with this name is already associated to this host."
)
if ("name" in self.changed_data or host_type in self.changed_data) and existing_acls:
error_same_acl_name = "An ACL with this name is already associated to this host."
error_message |= {
host_type: [error_same_acl_name],
"name": [error_same_acl_name],
}
if self.instance.pk:
# Check if Access List has no existing rules before change the Access List's type.
if (
acl_type == ACLTypeChoices.TYPE_EXTENDED
and self.instance.aclstandardrules.exists()
) or (
acl_type == ACLTypeChoices.TYPE_STANDARD
and self.instance.aclextendedrules.exists()
if self.instance.pk and (
(acl_type == ACLTypeChoices.TYPE_EXTENDED and self.instance.aclstandardrules.exists())
or (acl_type == ACLTypeChoices.TYPE_STANDARD and self.instance.aclextendedrules.exists())
):
error_message["type"] = [
"This ACL has ACL rules associated, CANNOT change ACL type.",
@ -261,9 +240,7 @@ class AccessListForm(NetBoxModelForm):
def save(self, *args, **kwargs):
# Set assigned object
self.instance.assigned_object = (
self.cleaned_data.get("device")
or self.cleaned_data.get("virtual_chassis")
or self.cleaned_data.get("virtual_machine")
self.cleaned_data.get("device") or self.cleaned_data.get("virtual_chassis") or self.cleaned_data.get("virtual_machine")
)
return super().save(*args, **kwargs)
@ -324,7 +301,6 @@ class ACLInterfaceAssignmentForm(NetBoxModelForm):
comments = CommentField()
def __init__(self, *args, **kwargs):
# Initialize helper selectors
instance = kwargs.get("instance")
initial = kwargs.get("initial", {}).copy()
@ -376,15 +352,15 @@ class ACLInterfaceAssignmentForm(NetBoxModelForm):
# Check if both interface and vminterface are set.
if interface and vminterface:
error_too_many_interfaces = "Access Lists must be assigned to one type of interface at a time (VM interface or physical interface)"
error_too_many_interfaces = (
"Access Lists must be assigned to one type of interface at a time (VM interface or physical interface)"
)
error_message |= {
"interface": [error_too_many_interfaces],
"vminterface": [error_too_many_interfaces],
}
elif not (interface or vminterface):
error_no_interface = (
"An Access List assignment but specify an Interface or VM Interface."
)
error_no_interface = "An Access List assignment but specify an Interface or VM Interface."
error_message |= {
"interface": [error_no_interface],
"vminterface": [error_no_interface],
@ -410,9 +386,7 @@ class ACLInterfaceAssignmentForm(NetBoxModelForm):
# Check that an interface's parent device/virtual_machine is assigned to the Access List.
if access_list_host != host:
error_acl_not_assigned_to_host = (
"Access List not present on selected host."
)
error_acl_not_assigned_to_host = "Access List not present on selected host."
error_message |= {
"access_list": [error_acl_not_assigned_to_host],
assigned_object_type: [error_acl_not_assigned_to_host],
@ -437,9 +411,7 @@ class ACLInterfaceAssignmentForm(NetBoxModelForm):
assigned_object_type=assigned_object_type_id,
direction=direction,
).exists():
error_interface_already_assigned = (
"Interfaces can only have 1 Access List assigned in each direction."
)
error_interface_already_assigned = "Interfaces can only have 1 Access List assigned in each direction."
error_message |= {
"direction": [error_interface_already_assigned],
assigned_object_type: [error_interface_already_assigned],

View File

@ -3,6 +3,7 @@ from netbox.graphql.fields import ObjectField, ObjectListField
from .types import *
class Query(ObjectType):
"""
Defines the queries available to this plugin via the graphql api.

View File

@ -72,4 +72,3 @@ class ACLStandardRuleType(NetBoxObjectType):
model = models.ACLStandardRule
fields = "__all__"
filterset_class = filtersets.ACLStandardRuleFilterSet

View File

@ -282,7 +282,9 @@ class Migration(migrations.Migration):
},
),
# migrations.AddConstraint(
# model_name='accesslist',
# constraint=models.UniqueConstraint(fields=('assigned_object_type', 'assigned_object_id'), name='accesslist_assigned_object'),
# model_name="accesslist",
# constraint=models.UniqueConstraint(
# fields=("assigned_object_type", "assigned_object_id"), name="accesslist_assigned_object"
# ),
# ),
]

View File

@ -6,7 +6,6 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("contenttypes", "0002_remove_content_type_name"),
("netbox_acls", "0001_initial"),

View File

@ -5,7 +5,6 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("netbox_acls", "0002_alter_accesslist_options_and_more"),
]

View File

@ -1,4 +1,4 @@
from dcim.models import Device, DeviceRole, DeviceType, Interface, Manufacturer, Site
from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Site
from django.contrib.contenttypes.models import ContentType
from django.urls import reverse
from rest_framework import status

View File

@ -47,7 +47,11 @@ urlpatterns = (
views.ACLInterfaceAssignmentEditView.as_view(),
name="aclinterfaceassignment_add",
),
# path('interface-assignments/edit/', views.ACLInterfaceAssignmentBulkEditView.as_view(), name='aclinterfaceassignment_bulk_edit'),
# path(
# "interface-assignments/edit/",
# views.ACLInterfaceAssignmentBulkEditView.as_view(),
# name="aclinterfaceassignment_bulk_edit"
# ),
path(
"interface-assignments/delete/",
views.ACLInterfaceAssignmentBulkDeleteView.as_view(),

View File

@ -1 +1 @@
__version__ = "1.2.2"
__version__ = "1.3.0"

View File

@ -50,7 +50,8 @@ class AccessListView(generic.ObjectView):
def get_extra_context(self, request, instance):
"""
Depending on the Access List type, the list view will return the required ACL Rule using the previous defined tables in tables.py.
Depending on the Access List type, the list view will return
the required ACL Rule using the previous defined tables in tables.py.
"""
if instance.type == choices.ACLTypeChoices.TYPE_EXTENDED:
@ -227,8 +228,7 @@ class ACLInterfaceAssignmentEditView(generic.ObjectEditView):
"""
return {
"access_list": request.GET.get("access_list")
or request.POST.get("access_list"),
"access_list": request.GET.get("access_list") or request.POST.get("access_list"),
"direction": request.GET.get("direction") or request.POST.get("direction"),
}
@ -360,8 +360,7 @@ class ACLStandardRuleEditView(generic.ObjectEditView):
"""
return {
"access_list": request.GET.get("access_list")
or request.POST.get("access_list"),
"access_list": request.GET.get("access_list") or request.POST.get("access_list"),
}
@ -443,8 +442,7 @@ class ACLExtendedRuleEditView(generic.ObjectEditView):
"""
return {
"access_list": request.GET.get("access_list")
or request.POST.get("access_list"),
"access_list": request.GET.get("access_list") or request.POST.get("access_list"),
}

23
pyproject.toml Normal file
View File

@ -0,0 +1,23 @@
[tool.black]
line-length = 140
[tool.isort]
profile = "black"
include_trailing_comma = true
multi_line_output = 3
[tool.pylint]
max-line-length = 140
[tool.pyright]
include = ["netbox_secrets"]
exclude = [
"**/node_modules",
"**/__pycache__",
]
reportMissingImports = true
reportMissingTypeStubs = false
[tool.ruff]
line-length = 140

View File

@ -9,7 +9,7 @@ from setuptools import find_packages, setup
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()
long_description = fh.read().replace("(docs/img/", "(https://raw.githubusercontent.com/ryanmerolle/netbox-acls/release/docs/img/")
def read(relative_path):
@ -43,7 +43,18 @@ setup(
include_package_data=True,
zip_safe=False,
classifiers=[
"Framework :: Django",
"Development Status :: 5 - Production/Stable",
"Natural Language :: English",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Intended Audience :: System Administrators",
"Intended Audience :: Telecommunications Industry",
"Framework :: Django",
"Topic :: System :: Networking",
"Topic :: Internet",
],
)