Skip to content

Commit f5acb73

Browse files
authored
Merge pull request #18 from miaow2/develop
Added missing and extra config lines
2 parents 8202108 + 1c63642 commit f5acb73

File tree

17 files changed

+207
-17
lines changed

17 files changed

+207
-17
lines changed

.github/workflows/mkdocs.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,7 @@ jobs:
1616
- uses: actions/setup-python@v4
1717
with:
1818
python-version: "3.10"
19-
- run: python -m pip install -r requirements/docs.txt
19+
- run: |
20+
python -m pip install --upgrade pip
21+
python -m pip install -r requirements/docs.txt
2022
- run: mkdocs gh-deploy --force

.github/workflows/publish.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
- name: Setup publish env
1616
run: |
1717
python -m pip install --upgrade pip
18-
python -m pip install setuptools wheel build twine
18+
python -m pip install -r requirements/publish.txt
1919
- name: Build
2020
run: python -m build
2121
- name: Check

.pre-commit-config.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
repos:
2+
- repo: https://github.com/pre-commit/pre-commit-hooks
3+
rev: v2.3.0
4+
hooks:
5+
- id: check-yaml
6+
- id: end-of-file-fixer
7+
- id: trailing-whitespace
8+
- repo: https://github.com/psf/black
9+
rev: 23.1.0
10+
hooks:
11+
- id: black
12+
args: [--check, --diff, --color, .]
13+
- repo: https://github.com/astral-sh/ruff-pre-commit
14+
rev: v0.0.280
15+
hooks:
16+
- id: ruff
17+
args: [netbox_config_diff]

README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
[![NetBox version](https://img.shields.io/badge/NetBox-3.5-blue.svg)](https://github.com/netbox-community/netbox)
2+
[![Supported Versions](https://img.shields.io/pypi/pyversions/netbox-config-diff.svg)](https://pypi.org/project/netbox-config-diff/)
3+
[![PyPI version](https://badge.fury.io/py/netbox-config-diff.svg)](https://badge.fury.io/py/netbox-config-diff)
4+
[![Code Style](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black)
5+
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
6+
[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
7+
[![CI](https://github.com/miaow2/netbox-config-diff/actions/workflows/commit.yaml/badge.svg?branch=develop)](https://github.com/miaow2/netbox-config-diff/actions)
8+
19
# NetBox Config Diff Plugin
210

311
NetBox plugin for Config Diff.
@@ -14,7 +22,7 @@ Read about [DataSources](https://demo.netbox.dev/static/docs/models/core/datasou
1422
Device configuration renders natively in NetBox. This [feature](https://demo.netbox.dev/static/docs/features/configuration-rendering/) was introduced in 3.5 version.
1523
NetBox Labs [blog](https://demo.netbox.dev/static/docs/features/configuration-rendering/) post about it.
1624

17-
Plugin supports a wide list of vendors (Cisco, Juniper, Huawei, MicroTik etc.) with the help of Scrapli. Read [Scrapli](https://github.com/carlmontanari/scrapli/tree/main/scrapli/driver/core) and [scrapli-community](https://github.com/scrapli/scrapli_community/tree/main/scrapli_community) documentations to find full list of vendors.
25+
Plugin supports a wide list of vendors (Cisco, Juniper, Huawei, MicroTik etc.) with the help of Scrapli. Read [Scrapli](https://carlmontanari.github.io/scrapli/user_guide/project_details/#supported-platforms) and [scrapli-community](https://scrapli.github.io/scrapli_community/user_guide/project_details/#supported-platforms) documentations to find full list of vendors.
1826
<!--about-end-->
1927

2028
## Compatibility
26.5 KB
Loading

docs/usage.md

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ Under `Plugins` navbar menu you can find plugin
55

66
![Screenshot of navbar](media/screenshots/navbar.png)
77

8-
Add PlatformSetting objects for your platforms in NetBox.
8+
## PlatformSetting
9+
10+
Add PlatformSetting objects for your platforms in NetBox. This model contains info about how to connect and what to collect from device.
911

1012
Define:
1113

@@ -19,6 +21,8 @@ You can test regexp on the site https://regex101.com/.
1921

2022
![Screenshot of PlatformSetting](media/screenshots/platformsetting.png)
2123

24+
## Script
25+
2226
Plugin adds a custom script `ConfigDiffScript` that runs all logic about diff calculations and connections to devices.
2327
You can find scripts list in navbar `Customization -> Scripts`.
2428

@@ -43,12 +47,33 @@ If you have configs in NetBox DataSource, you can define it, the script instead
4347
4448
![Screenshot of the script](media/screenshots/script.png)
4549

50+
## Results
51+
4652
After script is done you can find results in `Config Compliances` menu. Each device has its own result.
4753

4854
![Screenshot of the compliance list](media/screenshots/compliance-list.png)
4955

5056
Also result is storing rendered and actual configurations from devices.
5157

58+
With the help of [netutils](https://github.com/networktocode/netutils) library plugin stores missing and extra config lines.
59+
60+
![Screenshot of the missing/extra lines](media/screenshots/compliance-missing-extra.png)
61+
62+
Supported platforms for missing/extra lines:
63+
64+
* Arista EOS (arista_eos)
65+
* Aruba AOSCX (aruba_aoscx)
66+
* Cisco AireOS (cisco_aireos)
67+
* Cisco ASA (cisco_asa)
68+
* Cisco IOS-XE (cisco_iosxe)
69+
* Cisco IOS-XR (cisco_iosxr)
70+
* Cisco NX-OS (cisco_nxos)
71+
* Juniper JunOS (juniper_junos)
72+
* Mikrotik RouterOS (mikrotik_routeros)
73+
* Nokia SROS (nokia_sros)
74+
* PaloAlto PanOS (paloalto_panos)
75+
* Ruckus FastIron (ruckus_fastiron)
76+
5277
Compliance finished with error
5378

5479
![Screenshot of the compliance error](media/screenshots/compliance-error.png)
@@ -59,4 +84,4 @@ Render diff between configurations
5984

6085
No diff
6186

62-
![Screenshot of the compliance ok](media/screenshots/compliance-ok.png)
87+
![Screenshot of the compliance ok](media/screenshots/compliance-ok.png)

netbox_config_diff/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class ConfigDiffConfig(PluginConfig):
1010
verbose_name = "NetBox Config Diff Plugin"
1111
description = "Find diff between the intended device configuration and actual."
1212
author = __author__
13-
email = __email__
13+
author_email = __email__
1414
version = __version__
1515
base_url = "config-diff"
1616
required_settings = ["USERNAME", "PASSWORD"]

netbox_config_diff/api/serializers.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ class Meta:
2424
"diff",
2525
"rendered_config",
2626
"actual_config",
27+
"missing",
28+
"extra",
2729
"created",
2830
"last_updated",
2931
)

netbox_config_diff/compliance/base.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@
99
from django.core.exceptions import ObjectDoesNotExist
1010
from django.db.models import Q
1111
from extras.plugins import get_plugin_config
12-
from extras.querysets import ConfigContextQuerySet
1312
from extras.scripts import MultiObjectVar, ObjectVar
1413
from jinja2.exceptions import TemplateError
14+
from netutils.config.compliance import diff_network_config
1515
from utilities.exceptions import AbortScript
1616

1717
from netbox_config_diff.models import ConfigCompliance
1818

1919
from .models import DeviceDataClass
20-
from .utils import exclude_lines, get_unified_diff
20+
from .utils import PLATFORM_MAPPING, exclude_lines, get_unified_diff
2121

2222

2323
class ConfigDiffBase:
@@ -52,7 +52,7 @@ def run_script(self, data: dict) -> None:
5252
self.get_diff(devices)
5353
self.update_in_db(devices)
5454

55-
def validate_data(self, data: dict) -> Iterable[ConfigContextQuerySet]:
55+
def validate_data(self, data: dict) -> Iterable[Device]:
5656
if not data["site"] and not data["devices"]:
5757
raise AbortScript("Define site or devices")
5858
if data.get("data_source") and data["data_source"].status != DataSourceStatusChoices.COMPLETED:
@@ -101,7 +101,7 @@ def log_results(self, device: DeviceDataClass) -> None:
101101
else:
102102
self.log_success(f"{device.name} no diff")
103103

104-
def get_devices_with_rendered_configs(self, devices: Iterable[ConfigContextQuerySet]) -> Iterator[DeviceDataClass]:
104+
def get_devices_with_rendered_configs(self, devices: Iterable[Device]) -> Iterator[DeviceDataClass]:
105105
username = get_plugin_config("netbox_config_diff", "USERNAME")
106106
password = get_plugin_config("netbox_config_diff", "PASSWORD")
107107
for device in devices:
@@ -151,6 +151,12 @@ def get_diff(self, devices: list[DeviceDataClass]) -> None:
151151
for device in devices:
152152
if device.error is not None:
153153
continue
154-
device.diff = get_unified_diff(
155-
device.rendered_config, exclude_lines(device.actual_config, device.exclude_regex), device.name
156-
)
154+
cleaned_config = exclude_lines(device.actual_config, device.exclude_regex)
155+
device.diff = get_unified_diff(device.rendered_config, cleaned_config, device.name)
156+
if device.platform in PLATFORM_MAPPING:
157+
device.missing = diff_network_config(
158+
device.rendered_config, cleaned_config, PLATFORM_MAPPING[device.platform]
159+
)
160+
device.extra = diff_network_config(
161+
cleaned_config, device.rendered_config, PLATFORM_MAPPING[device.platform]
162+
)

netbox_config_diff/compliance/models.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ class DeviceDataClass:
1919
rendered_config: str | None = None
2020
actual_config: str | None = None
2121
diff: str | None = None
22+
missing: str | None = None
23+
extra: str | None = None
2224
error: str | None = None
2325
auth_strict_key: bool = False
2426
transport: str = "asyncssh"
@@ -51,6 +53,8 @@ def to_db(self):
5153
"error": self.error or "",
5254
"rendered_config": self.rendered_config or "",
5355
"actual_config": self.actual_config or "",
56+
"missing": self.missing or "",
57+
"extra": self.extra or "",
5458
}
5559

5660
async def get_actual_config(self):

0 commit comments

Comments
 (0)