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

Version 2.6.0 #75

Merged
merged 26 commits into from
Jul 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
b1032be
Change URLs in Usage to docs
miaow2 Nov 14, 2023
d70debc
Update project description
miaow2 Dec 12, 2023
04476cd
Add video presentation
miaow2 Dec 12, 2023
f83d730
Closes #50: Add template field to ConfigDiffScript (#51)
miaow2 Jan 27, 2024
63dd590
Closes #47: Move plugin to separete menu item in navbar (#52)
miaow2 Jan 28, 2024
5dd31cf
Closes #53: Add netbox-rq to installation process docs
miaow2 Jan 31, 2024
79c3ec3
Changelog for 2.2.0 version
miaow2 Feb 6, 2024
a757ac7
Handle junipers templates with set commands (#58)
miaow2 Apr 9, 2024
cd091be
Reverse columns in diff (#59)
miaow2 Apr 9, 2024
bbf8293
Add python 3.12 and Netbox 3.7.5 in CI
miaow2 Apr 10, 2024
afaafd5
Closes #56: Add python 3.12 and Netbox 3.7.5 in CI
miaow2 Apr 10, 2024
834e88e
Add warning about using set commands in Juniper
miaow2 Apr 11, 2024
1ca2303
Version 2.3.0
miaow2 Apr 11, 2024
21704dd
Merge branch 'main' into develop
miaow2 Apr 11, 2024
7d52fa3
Closes #63: Add patch commands for configuration
miaow2 May 12, 2024
63fc61b
Merge branch 'main' into develop
miaow2 May 12, 2024
487dbfa
Version 2.4.0
miaow2 May 12, 2024
d3672ec
Closes #67: Add option default_desired_privilege_level (#68)
cknost Jun 22, 2024
5dee473
Add docs for desired privilege level variables
miaow2 Jun 22, 2024
0980a05
Closes #69: Fix logger in SecretsMixin (#71)
miaow2 Jun 22, 2024
b52db25
Closes #70: Add escapejs filter to diff template (#72)
miaow2 Jun 30, 2024
d5a6d99
Version 2.5.0
miaow2 Jun 30, 2024
2234cc7
Merge branch 'main' into develop
miaow2 Jun 30, 2024
a0240d9
Closes #62: Add support for NetBox 4.0 (#74)
miaow2 Jul 14, 2024
5c3c92d
Update changelog
miaow2 Jul 14, 2024
3439c25
Merge branch 'main' into develop
miaow2 Jul 14, 2024
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
4 changes: 2 additions & 2 deletions .github/workflows/commit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ jobs:
- name: Run ruff format
run: ruff format .
- name: Run ruff
run: ruff .
run: ruff check .

test:
runs-on: ubuntu-latest
strategy:
max-parallel: 10
matrix:
netbox_version: ["v3.5.9", "v3.6.9", "v3.7.8"]
netbox_version: ["v3.6.9", "v3.7.8", "v4.0.7"]
steps:
- name: Checkout
uses: actions/checkout@v3
Expand Down
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[![NetBox version](https://img.shields.io/badge/NetBox-3.5|3.6-blue.svg)](https://github.com/netbox-community/netbox)
[![NetBox version](https://img.shields.io/badge/NetBox-3.6|3.7|4.0-blue.svg)](https://github.com/netbox-community/netbox)
[![Supported Versions](https://img.shields.io/pypi/pyversions/netbox-config-diff.svg)](https://pypi.org/project/netbox-config-diff/)
[![PyPI version](https://badge.fury.io/py/netbox-config-diff.svg)](https://badge.fury.io/py/netbox-config-diff)
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
Expand Down Expand Up @@ -42,9 +42,10 @@ This is possible thanks to the scrapli_cfg. Read [Scrapli](https://github.com/sc

## Compatibility

| NetBox Version | Plugin Version |
|----------------|----------------|
| 3.5, 3.6, 3.7 | =>0.1.0 |
| NetBox Version | Plugin Version |
|----------------|------------------|
| 3.5 | =>0.1.0, <=2.5.0 |
| 3.6, 3.7, 4.0 | =>0.1.0 |

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

## Video

My presention about plugin at October NetBox community call (19.10.2023).
My presention about plugin at October NetBox community call (19.10.2023, plugin version 2.0.0).

[![October NetBox community call](https://img.youtube.com/vi/B4uhtYh278o/0.jpg)](https://youtu.be/B4uhtYh278o?t=425)
<!--usage-end-->
Expand Down
2 changes: 1 addition & 1 deletion development/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ ENV PYTHONDONTWRITEBYTECODE 1
ARG NETBOX_VERSION

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

# Install NetBox
Expand Down
6 changes: 6 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
# Changelog


## 2.6.0 (2024-07-14)

* [#62](https://github.com/miaow2/netbox-config-diff/issues/62) Add support for NetBox 4.0

This release drops support for NetBox 3.5.

## 2.5.0 (2024-06-30)

* [#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))
Expand Down
12 changes: 9 additions & 3 deletions netbox_config_diff/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
from extras.plugins import PluginConfig
from netbox.settings import VERSION

if VERSION.startswith("3."):
from extras.plugins import PluginConfig
else:
from netbox.plugins import PluginConfig


__author__ = "Artem Kotik"
__email__ = "[email protected]"
__version__ = "2.5.0"
__version__ = "2.6.0"


class ConfigDiffConfig(PluginConfig):
Expand All @@ -14,7 +20,7 @@ class ConfigDiffConfig(PluginConfig):
version = __version__
base_url = "config-diff"
required_settings = ["USERNAME", "PASSWORD"]
min_version = "3.5.0"
min_version = "3.6.0"
default_settings = {
"USER_SECRET_ROLE": "Username",
"PASSWORD_SECRET_ROLE": "Password",
Expand Down
8 changes: 7 additions & 1 deletion netbox_config_diff/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,22 @@
from dcim.models import Device
from netbox.api.fields import ChoiceField, SerializedPKRelatedField
from netbox.api.serializers import NetBoxModelSerializer
from netbox.settings import VERSION
from rest_framework import serializers
from rest_framework.serializers import ValidationError
from users.api.nested_serializers import NestedUserSerializer
from utilities.utils import local_now

from netbox_config_diff.choices import ConfigComplianceStatusChoices, ConfigurationRequestStatusChoices
from netbox_config_diff.constants import ACCEPTABLE_DRIVERS
from netbox_config_diff.models import ConfigCompliance, ConfigurationRequest, PlatformSetting, Substitute

if VERSION.startswith("3."):
from utilities.utils import local_now
else:
from utilities.datetime import local_now


# TODO: after droping support for NetBox 3.x, delete nested serializers and add brief_fields
class ConfigComplianceSerializer(NetBoxModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name="plugins-api:netbox_config_diff-api:configcompliance-detail")
device = NestedDeviceSerializer()
Expand Down
7 changes: 6 additions & 1 deletion netbox_config_diff/compliance/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,20 @@
from django.db.models import Q
from extras.scripts import MultiObjectVar, ObjectVar, TextVar
from jinja2.exceptions import TemplateError
from netbox.settings import VERSION
from netutils.config.compliance import diff_network_config
from utilities.exceptions import AbortScript
from utilities.utils import render_jinja2

from netbox_config_diff.models import ConplianceDeviceDataClass

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

if VERSION.startswith("3."):
from utilities.utils import render_jinja2
else:
from utilities.jinja2 import render_jinja2


class ConfigDiffBase(SecretsMixin):
site = ObjectVar(
Expand Down
7 changes: 6 additions & 1 deletion netbox_config_diff/compliance/secrets.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@
from typing import TYPE_CHECKING

from dcim.models import Device
from extras.plugins import get_installed_plugins, get_plugin_config
from netbox.settings import VERSION

if TYPE_CHECKING:
from netbox_secrets.models import Secret

if VERSION.startswith("3."):
from extras.plugins import get_installed_plugins, get_plugin_config
else:
from netbox.plugins import get_installed_plugins, get_plugin_config


class SecretsMixin:
username: str
Expand Down
7 changes: 6 additions & 1 deletion netbox_config_diff/configurator/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
from asgiref.sync import sync_to_async
from dcim.models import Device
from jinja2.exceptions import TemplateError
from netbox.settings import VERSION
from netutils.config.compliance import diff_network_config
from scrapli import AsyncScrapli
from scrapli_cfg.platform.base.async_platform import AsyncScrapliCfgPlatform
from scrapli_cfg.response import ScrapliCfgResponse
from utilities.utils import NetBoxFakeRequest

from netbox_config_diff.compliance.secrets import SecretsMixin
from netbox_config_diff.compliance.utils import PLATFORM_MAPPING, get_remediation_commands, get_unified_diff
Expand All @@ -22,6 +22,11 @@

from .factory import AsyncScrapliCfg

if VERSION.startswith("3."):
from utilities.utils import NetBoxFakeRequest
else:
from utilities.request import NetBoxFakeRequest


class Configurator(SecretsMixin):
def __init__(self, devices: Iterable[Device], request: NetBoxFakeRequest) -> None:
Expand Down
23 changes: 23 additions & 0 deletions netbox_config_diff/forms/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from .general import (
ConfigComplianceFilterForm,
ConfigurationRequestFilterForm,
ConfigurationRequestForm,
ConfigurationRequestScheduleForm,
PlatformSettingBulkEditForm,
PlatformSettingFilterForm,
PlatformSettingForm,
SubstituteFilterForm,
SubstituteForm,
)

__all__ = [
"ConfigComplianceFilterForm",
"ConfigurationRequestFilterForm",
"ConfigurationRequestForm",
"ConfigurationRequestScheduleForm",
"PlatformSettingBulkEditForm",
"PlatformSettingFilterForm",
"PlatformSettingForm",
"SubstituteFilterForm",
"SubstituteForm",
]
12 changes: 12 additions & 0 deletions netbox_config_diff/forms/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from django.forms import ModelForm
from netbox.settings import VERSION

if VERSION.startswith("3."):
from utilities.forms.mixins import BootstrapMixin

class CustomForm(BootstrapMixin, ModelForm):
pass
else:

class CustomForm(ModelForm):
pass
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,25 @@
from django import forms
from django.contrib.auth import get_user_model
from netbox.forms import NetBoxModelBulkEditForm, NetBoxModelFilterSetForm, NetBoxModelForm
from netbox.settings import VERSION
from utilities.forms.fields import (
DynamicModelChoiceField,
DynamicModelMultipleChoiceField,
TagFilterField,
)
from utilities.forms.mixins import BootstrapMixin
from utilities.forms.widgets import DateTimePicker
from utilities.utils import local_now

from netbox_config_diff.choices import ConfigComplianceStatusChoices, ConfigurationRequestStatusChoices
from netbox_config_diff.constants import ACCEPTABLE_DRIVERS
from netbox_config_diff.models import ConfigCompliance, ConfigurationRequest, PlatformSetting, Substitute

from .base import CustomForm

if VERSION.startswith("3."):
from utilities.utils import local_now
else:
from utilities.datetime import local_now


class ConfigComplianceFilterForm(NetBoxModelFilterSetForm):
model = ConfigCompliance
Expand Down Expand Up @@ -157,7 +163,7 @@ class ConfigurationRequestFilterForm(NetBoxModelFilterSetForm):
tag = TagFilterField(model)


class ConfigurationRequestScheduleForm(BootstrapMixin, forms.ModelForm):
class ConfigurationRequestScheduleForm(CustomForm):
scheduled = forms.DateTimeField(
widget=DateTimePicker(),
label="Schedule at",
Expand Down
6 changes: 6 additions & 0 deletions netbox_config_diff/graphql/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from netbox.settings import VERSION

if VERSION.startswith("3."):
from .old.schema import schema # noqa
else:
from .new.schema import schema # noqa
Empty file.
34 changes: 34 additions & 0 deletions netbox_config_diff/graphql/new/filters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import strawberry_django
from netbox.graphql.filter_mixins import BaseFilterMixin, autotype_decorator

from netbox_config_diff.filtersets import (
ConfigComplianceFilterSet,
ConfigurationRequestFilterSet,
PlatformSettingFilterSet,
SubstituteFilterSet,
)
from netbox_config_diff.models import ConfigCompliance, ConfigurationRequest, PlatformSetting, Substitute


@strawberry_django.filter(ConfigCompliance, lookups=True)
@autotype_decorator(ConfigComplianceFilterSet)
class ConfigComplianceFilter(BaseFilterMixin):
pass


@strawberry_django.filter(ConfigurationRequest, lookups=True)
@autotype_decorator(ConfigurationRequestFilterSet)
class ConfigurationRequestFilter(BaseFilterMixin):
pass


@strawberry_django.filter(PlatformSetting, lookups=True)
@autotype_decorator(PlatformSettingFilterSet)
class PlatformSettingFilter(BaseFilterMixin):
pass


@strawberry_django.filter(Substitute, lookups=True)
@autotype_decorator(SubstituteFilterSet)
class SubstituteFilter(BaseFilterMixin):
pass
36 changes: 36 additions & 0 deletions netbox_config_diff/graphql/new/schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import strawberry
import strawberry_django

from netbox_config_diff.models import ConfigCompliance, ConfigurationRequest, PlatformSetting, Substitute

from .types import ConfigComplianceType, ConfigurationRequestType, PlatformSettingType, SubstituteType


@strawberry.type
class NetBoxConfigDiffQuery:
@strawberry.field
def config_compliance(self, id: int) -> ConfigComplianceType:
return ConfigCompliance.objects.get(pk=id)

config_compliance_list: list[ConfigComplianceType] = strawberry_django.field()

@strawberry.field
def configuration_request(self, id: int) -> ConfigurationRequestType:
return ConfigurationRequest.objects.get(pk=id)

configuration_request_list: list[ConfigurationRequestType] = strawberry_django.field()

@strawberry.field
def platform_setting(self, id: int) -> PlatformSettingType:
return PlatformSetting.objects.get(pk=id)

platform_setting_list: list[PlatformSettingType] = strawberry_django.field()

@strawberry.field
def substitute(self, id: int) -> SubstituteType:
return Substitute.objects.get(pk=id)

substitute_list: list[SubstituteType] = strawberry_django.field()


schema = [NetBoxConfigDiffQuery]
55 changes: 55 additions & 0 deletions netbox_config_diff/graphql/new/types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from typing import Annotated

import strawberry
import strawberry_django
from dcim.graphql.types import DeviceType, PlatformType
from netbox.graphql.types import NetBoxObjectType, ObjectType
from users.graphql.types import UserType

from netbox_config_diff.models import ConfigCompliance, ConfigurationRequest, PlatformSetting, Substitute

from .filters import ConfigComplianceFilter, ConfigurationRequestFilter, PlatformSettingFilter, SubstituteFilter


@strawberry_django.type(ConfigCompliance, fields="__all__", filters=ConfigComplianceFilter)
class ConfigComplianceType(ObjectType):
device: Annotated["DeviceType", strawberry.lazy("dcim.graphql.types")]
status: str
diff: str
error: str
actual_config: str
rendered_config: str
missing: str
extra: str
patch: str


@strawberry_django.type(ConfigurationRequest, fields="__all__", filters=ConfigurationRequestFilter)
class ConfigurationRequestType(NetBoxObjectType):
created_by: Annotated["UserType", strawberry.lazy("users.graphql.types")] | None
approved_by: Annotated["UserType", strawberry.lazy("users.graphql.types")] | None
scheduled_by: Annotated["UserType", strawberry.lazy("users.graphql.types")] | None
status: str
devices: list[Annotated["DeviceType", strawberry.lazy("dcim.graphql.types")]]
description: str
comments: str
scheduled: str
started: str
completed: str


@strawberry_django.type(PlatformSetting, fields="__all__", filters=PlatformSettingFilter)
class PlatformSettingType(NetBoxObjectType):
platform: Annotated["PlatformType", strawberry.lazy("dcim.graphql.types")]
description: str
driver: str
command: str
exclude_regex: str


@strawberry_django.type(Substitute, fields="__all__", filters=SubstituteFilter)
class SubstituteType(NetBoxObjectType):
platform_setting: Annotated["PlatformSettingType", strawberry.lazy("netbox_config_diff.graphql.new.types")]
name: str
description: str
regexp: str
Empty file.
File renamed without changes.
Loading
Loading