Skip to content

Commit 295d7c8

Browse files
authored
Version 2.6.0
1 parent d5d3fe8 commit 295d7c8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+386
-165
lines changed

.github/workflows/commit.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@ jobs:
2424
- name: Run ruff format
2525
run: ruff format .
2626
- name: Run ruff
27-
run: ruff .
27+
run: ruff check .
2828

2929
test:
3030
runs-on: ubuntu-latest
3131
strategy:
3232
max-parallel: 10
3333
matrix:
34-
netbox_version: ["v3.5.9", "v3.6.9", "v3.7.8"]
34+
netbox_version: ["v3.6.9", "v3.7.8", "v4.0.7"]
3535
steps:
3636
- name: Checkout
3737
uses: actions/checkout@v3

README.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
[![NetBox version](https://img.shields.io/badge/NetBox-3.5|3.6-blue.svg)](https://github.com/netbox-community/netbox)
1+
[![NetBox version](https://img.shields.io/badge/NetBox-3.6|3.7|4.0-blue.svg)](https://github.com/netbox-community/netbox)
22
[![Supported Versions](https://img.shields.io/pypi/pyversions/netbox-config-diff.svg)](https://pypi.org/project/netbox-config-diff/)
33
[![PyPI version](https://badge.fury.io/py/netbox-config-diff.svg)](https://badge.fury.io/py/netbox-config-diff)
44
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
@@ -42,9 +42,10 @@ This is possible thanks to the scrapli_cfg. Read [Scrapli](https://github.com/sc
4242

4343
## Compatibility
4444

45-
| NetBox Version | Plugin Version |
46-
|----------------|----------------|
47-
| 3.5, 3.6, 3.7 | =>0.1.0 |
45+
| NetBox Version | Plugin Version |
46+
|----------------|------------------|
47+
| 3.5 | =>0.1.0, <=2.5.0 |
48+
| 3.6, 3.7, 4.0 | =>0.1.0 |
4849

4950
<!--install-start-->
5051
## Installing
@@ -107,7 +108,7 @@ Read this [doc](https://miaow2.github.io/netbox-config-diff/colliecting-diffs/)
107108

108109
## Video
109110

110-
My presention about plugin at October NetBox community call (19.10.2023).
111+
My presention about plugin at October NetBox community call (19.10.2023, plugin version 2.0.0).
111112

112113
[![October NetBox community call](https://img.youtube.com/vi/B4uhtYh278o/0.jpg)](https://youtu.be/B4uhtYh278o?t=425)
113114
<!--usage-end-->

development/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ ENV PYTHONDONTWRITEBYTECODE 1
66
ARG NETBOX_VERSION
77

88
RUN apt-get update \
9-
&& apt-get install -y --no-install-recommends git \
9+
&& apt-get install -y --no-install-recommends git postgresql-client libpq-dev gcc build-essential \
1010
&& pip install --upgrade pip
1111

1212
# Install NetBox

docs/changelog.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
# Changelog
22

33

4+
## 2.6.0 (2024-07-14)
5+
6+
* [#62](https://github.com/miaow2/netbox-config-diff/issues/62) Add support for NetBox 4.0
7+
8+
This release drops support for NetBox 3.5.
9+
410
## 2.5.0 (2024-06-30)
511

612
* [#67](https://github.com/miaow2/netbox-config-diff/issues/67) Add option `default_desired_privilege_level` to plugins variables (thanks to [@cknost](https://github.com/cknost))

netbox_config_diff/__init__.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
1-
from extras.plugins import PluginConfig
1+
from netbox.settings import VERSION
2+
3+
if VERSION.startswith("3."):
4+
from extras.plugins import PluginConfig
5+
else:
6+
from netbox.plugins import PluginConfig
7+
28

39
__author__ = "Artem Kotik"
410
__email__ = "miaow2@yandex.ru"
5-
__version__ = "2.5.0"
11+
__version__ = "2.6.0"
612

713

814
class ConfigDiffConfig(PluginConfig):
@@ -14,7 +20,7 @@ class ConfigDiffConfig(PluginConfig):
1420
version = __version__
1521
base_url = "config-diff"
1622
required_settings = ["USERNAME", "PASSWORD"]
17-
min_version = "3.5.0"
23+
min_version = "3.6.0"
1824
default_settings = {
1925
"USER_SECRET_ROLE": "Username",
2026
"PASSWORD_SECRET_ROLE": "Password",

netbox_config_diff/api/serializers.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,22 @@
22
from dcim.models import Device
33
from netbox.api.fields import ChoiceField, SerializedPKRelatedField
44
from netbox.api.serializers import NetBoxModelSerializer
5+
from netbox.settings import VERSION
56
from rest_framework import serializers
67
from rest_framework.serializers import ValidationError
78
from users.api.nested_serializers import NestedUserSerializer
8-
from utilities.utils import local_now
99

1010
from netbox_config_diff.choices import ConfigComplianceStatusChoices, ConfigurationRequestStatusChoices
1111
from netbox_config_diff.constants import ACCEPTABLE_DRIVERS
1212
from netbox_config_diff.models import ConfigCompliance, ConfigurationRequest, PlatformSetting, Substitute
1313

14+
if VERSION.startswith("3."):
15+
from utilities.utils import local_now
16+
else:
17+
from utilities.datetime import local_now
1418

19+
20+
# TODO: after droping support for NetBox 3.x, delete nested serializers and add brief_fields
1521
class ConfigComplianceSerializer(NetBoxModelSerializer):
1622
url = serializers.HyperlinkedIdentityField(view_name="plugins-api:netbox_config_diff-api:configcompliance-detail")
1723
device = NestedDeviceSerializer()

netbox_config_diff/compliance/base.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,20 @@
1111
from django.db.models import Q
1212
from extras.scripts import MultiObjectVar, ObjectVar, TextVar
1313
from jinja2.exceptions import TemplateError
14+
from netbox.settings import VERSION
1415
from netutils.config.compliance import diff_network_config
1516
from utilities.exceptions import AbortScript
16-
from utilities.utils import render_jinja2
1717

1818
from netbox_config_diff.models import ConplianceDeviceDataClass
1919

2020
from .secrets import SecretsMixin
2121
from .utils import PLATFORM_MAPPING, CustomChoiceVar, exclude_lines, get_remediation_commands, get_unified_diff
2222

23+
if VERSION.startswith("3."):
24+
from utilities.utils import render_jinja2
25+
else:
26+
from utilities.jinja2 import render_jinja2
27+
2328

2429
class ConfigDiffBase(SecretsMixin):
2530
site = ObjectVar(

netbox_config_diff/compliance/secrets.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,16 @@
22
from typing import TYPE_CHECKING
33

44
from dcim.models import Device
5-
from extras.plugins import get_installed_plugins, get_plugin_config
5+
from netbox.settings import VERSION
66

77
if TYPE_CHECKING:
88
from netbox_secrets.models import Secret
99

10+
if VERSION.startswith("3."):
11+
from extras.plugins import get_installed_plugins, get_plugin_config
12+
else:
13+
from netbox.plugins import get_installed_plugins, get_plugin_config
14+
1015

1116
class SecretsMixin:
1217
username: str

netbox_config_diff/configurator/base.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@
77
from asgiref.sync import sync_to_async
88
from dcim.models import Device
99
from jinja2.exceptions import TemplateError
10+
from netbox.settings import VERSION
1011
from netutils.config.compliance import diff_network_config
1112
from scrapli import AsyncScrapli
1213
from scrapli_cfg.platform.base.async_platform import AsyncScrapliCfgPlatform
1314
from scrapli_cfg.response import ScrapliCfgResponse
14-
from utilities.utils import NetBoxFakeRequest
1515

1616
from netbox_config_diff.compliance.secrets import SecretsMixin
1717
from netbox_config_diff.compliance.utils import PLATFORM_MAPPING, get_remediation_commands, get_unified_diff
@@ -22,6 +22,11 @@
2222

2323
from .factory import AsyncScrapliCfg
2424

25+
if VERSION.startswith("3."):
26+
from utilities.utils import NetBoxFakeRequest
27+
else:
28+
from utilities.request import NetBoxFakeRequest
29+
2530

2631
class Configurator(SecretsMixin):
2732
def __init__(self, devices: Iterable[Device], request: NetBoxFakeRequest) -> None:

netbox_config_diff/forms/__init__.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from .general import (
2+
ConfigComplianceFilterForm,
3+
ConfigurationRequestFilterForm,
4+
ConfigurationRequestForm,
5+
ConfigurationRequestScheduleForm,
6+
PlatformSettingBulkEditForm,
7+
PlatformSettingFilterForm,
8+
PlatformSettingForm,
9+
SubstituteFilterForm,
10+
SubstituteForm,
11+
)
12+
13+
__all__ = [
14+
"ConfigComplianceFilterForm",
15+
"ConfigurationRequestFilterForm",
16+
"ConfigurationRequestForm",
17+
"ConfigurationRequestScheduleForm",
18+
"PlatformSettingBulkEditForm",
19+
"PlatformSettingFilterForm",
20+
"PlatformSettingForm",
21+
"SubstituteFilterForm",
22+
"SubstituteForm",
23+
]

netbox_config_diff/forms/base.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from django.forms import ModelForm
2+
from netbox.settings import VERSION
3+
4+
if VERSION.startswith("3."):
5+
from utilities.forms.mixins import BootstrapMixin
6+
7+
class CustomForm(BootstrapMixin, ModelForm):
8+
pass
9+
else:
10+
11+
class CustomForm(ModelForm):
12+
pass

netbox_config_diff/forms.py renamed to netbox_config_diff/forms/general.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,25 @@
33
from django import forms
44
from django.contrib.auth import get_user_model
55
from netbox.forms import NetBoxModelBulkEditForm, NetBoxModelFilterSetForm, NetBoxModelForm
6+
from netbox.settings import VERSION
67
from utilities.forms.fields import (
78
DynamicModelChoiceField,
89
DynamicModelMultipleChoiceField,
910
TagFilterField,
1011
)
11-
from utilities.forms.mixins import BootstrapMixin
1212
from utilities.forms.widgets import DateTimePicker
13-
from utilities.utils import local_now
1413

1514
from netbox_config_diff.choices import ConfigComplianceStatusChoices, ConfigurationRequestStatusChoices
1615
from netbox_config_diff.constants import ACCEPTABLE_DRIVERS
1716
from netbox_config_diff.models import ConfigCompliance, ConfigurationRequest, PlatformSetting, Substitute
1817

18+
from .base import CustomForm
19+
20+
if VERSION.startswith("3."):
21+
from utilities.utils import local_now
22+
else:
23+
from utilities.datetime import local_now
24+
1925

2026
class ConfigComplianceFilterForm(NetBoxModelFilterSetForm):
2127
model = ConfigCompliance
@@ -157,7 +163,7 @@ class ConfigurationRequestFilterForm(NetBoxModelFilterSetForm):
157163
tag = TagFilterField(model)
158164

159165

160-
class ConfigurationRequestScheduleForm(BootstrapMixin, forms.ModelForm):
166+
class ConfigurationRequestScheduleForm(CustomForm):
161167
scheduled = forms.DateTimeField(
162168
widget=DateTimePicker(),
163169
label="Schedule at",
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from netbox.settings import VERSION
2+
3+
if VERSION.startswith("3."):
4+
from .old.schema import schema # noqa
5+
else:
6+
from .new.schema import schema # noqa

netbox_config_diff/graphql/new/__init__.py

Whitespace-only changes.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import strawberry_django
2+
from netbox.graphql.filter_mixins import BaseFilterMixin, autotype_decorator
3+
4+
from netbox_config_diff.filtersets import (
5+
ConfigComplianceFilterSet,
6+
ConfigurationRequestFilterSet,
7+
PlatformSettingFilterSet,
8+
SubstituteFilterSet,
9+
)
10+
from netbox_config_diff.models import ConfigCompliance, ConfigurationRequest, PlatformSetting, Substitute
11+
12+
13+
@strawberry_django.filter(ConfigCompliance, lookups=True)
14+
@autotype_decorator(ConfigComplianceFilterSet)
15+
class ConfigComplianceFilter(BaseFilterMixin):
16+
pass
17+
18+
19+
@strawberry_django.filter(ConfigurationRequest, lookups=True)
20+
@autotype_decorator(ConfigurationRequestFilterSet)
21+
class ConfigurationRequestFilter(BaseFilterMixin):
22+
pass
23+
24+
25+
@strawberry_django.filter(PlatformSetting, lookups=True)
26+
@autotype_decorator(PlatformSettingFilterSet)
27+
class PlatformSettingFilter(BaseFilterMixin):
28+
pass
29+
30+
31+
@strawberry_django.filter(Substitute, lookups=True)
32+
@autotype_decorator(SubstituteFilterSet)
33+
class SubstituteFilter(BaseFilterMixin):
34+
pass
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import strawberry
2+
import strawberry_django
3+
4+
from netbox_config_diff.models import ConfigCompliance, ConfigurationRequest, PlatformSetting, Substitute
5+
6+
from .types import ConfigComplianceType, ConfigurationRequestType, PlatformSettingType, SubstituteType
7+
8+
9+
@strawberry.type
10+
class NetBoxConfigDiffQuery:
11+
@strawberry.field
12+
def config_compliance(self, id: int) -> ConfigComplianceType:
13+
return ConfigCompliance.objects.get(pk=id)
14+
15+
config_compliance_list: list[ConfigComplianceType] = strawberry_django.field()
16+
17+
@strawberry.field
18+
def configuration_request(self, id: int) -> ConfigurationRequestType:
19+
return ConfigurationRequest.objects.get(pk=id)
20+
21+
configuration_request_list: list[ConfigurationRequestType] = strawberry_django.field()
22+
23+
@strawberry.field
24+
def platform_setting(self, id: int) -> PlatformSettingType:
25+
return PlatformSetting.objects.get(pk=id)
26+
27+
platform_setting_list: list[PlatformSettingType] = strawberry_django.field()
28+
29+
@strawberry.field
30+
def substitute(self, id: int) -> SubstituteType:
31+
return Substitute.objects.get(pk=id)
32+
33+
substitute_list: list[SubstituteType] = strawberry_django.field()
34+
35+
36+
schema = [NetBoxConfigDiffQuery]
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
from typing import Annotated
2+
3+
import strawberry
4+
import strawberry_django
5+
from dcim.graphql.types import DeviceType, PlatformType
6+
from netbox.graphql.types import NetBoxObjectType, ObjectType
7+
from users.graphql.types import UserType
8+
9+
from netbox_config_diff.models import ConfigCompliance, ConfigurationRequest, PlatformSetting, Substitute
10+
11+
from .filters import ConfigComplianceFilter, ConfigurationRequestFilter, PlatformSettingFilter, SubstituteFilter
12+
13+
14+
@strawberry_django.type(ConfigCompliance, fields="__all__", filters=ConfigComplianceFilter)
15+
class ConfigComplianceType(ObjectType):
16+
device: Annotated["DeviceType", strawberry.lazy("dcim.graphql.types")]
17+
status: str
18+
diff: str
19+
error: str
20+
actual_config: str
21+
rendered_config: str
22+
missing: str
23+
extra: str
24+
patch: str
25+
26+
27+
@strawberry_django.type(ConfigurationRequest, fields="__all__", filters=ConfigurationRequestFilter)
28+
class ConfigurationRequestType(NetBoxObjectType):
29+
created_by: Annotated["UserType", strawberry.lazy("users.graphql.types")] | None
30+
approved_by: Annotated["UserType", strawberry.lazy("users.graphql.types")] | None
31+
scheduled_by: Annotated["UserType", strawberry.lazy("users.graphql.types")] | None
32+
status: str
33+
devices: list[Annotated["DeviceType", strawberry.lazy("dcim.graphql.types")]]
34+
description: str
35+
comments: str
36+
scheduled: str
37+
started: str
38+
completed: str
39+
40+
41+
@strawberry_django.type(PlatformSetting, fields="__all__", filters=PlatformSettingFilter)
42+
class PlatformSettingType(NetBoxObjectType):
43+
platform: Annotated["PlatformType", strawberry.lazy("dcim.graphql.types")]
44+
description: str
45+
driver: str
46+
command: str
47+
exclude_regex: str
48+
49+
50+
@strawberry_django.type(Substitute, fields="__all__", filters=SubstituteFilter)
51+
class SubstituteType(NetBoxObjectType):
52+
platform_setting: Annotated["PlatformSettingType", strawberry.lazy("netbox_config_diff.graphql.new.types")]
53+
name: str
54+
description: str
55+
regexp: str

netbox_config_diff/graphql/old/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)