Skip to content

Commit

Permalink
Version 2.8.0
Browse files Browse the repository at this point in the history
  • Loading branch information
miaow2 authored Nov 10, 2024
1 parent 9d6bc9d commit 6e4615c
Show file tree
Hide file tree
Showing 8 changed files with 56 additions and 13 deletions.
12 changes: 12 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
# Changelog


## 2.8.0 (2024-11-10)

* [#76](https://github.com/miaow2/netbox-config-diff/issues/76) Add in NetBox 4.0 and higher some statistics for diff
* [#81](https://github.com/miaow2/netbox-config-diff/issues/81) Fix error in rendering config with several substitutes
* [#84](https://github.com/miaow2/netbox-config-diff/issues/84) Strip multiple empty lines in configs

## 2.7.0 (2024-09-29)

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

This release drops support for NetBox 3.6.

## 2.6.0 (2024-07-14)

* [#62](https://github.com/miaow2/netbox-config-diff/issues/62) Add support for NetBox 4.0
Expand Down
3 changes: 3 additions & 0 deletions docs/colliecting-diffs.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ If you have configs in NetBox DataSource, you can define it, the script instead
!!! note
Only synced DataSources are acceptable

!!! note
Diff replaces sequences of 3 or more empty lines with one empty line

If in your DataSource config names are different from the hostnames of the devices, you can specify config name with Jinja2 template in `Name template` field.
Reference device with `{{ object }}` variable.

Expand Down
2 changes: 1 addition & 1 deletion netbox_config_diff/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

__author__ = "Artem Kotik"
__email__ = "[email protected]"
__version__ = "2.7.0"
__version__ = "2.8.0"


class ConfigDiffConfig(PluginConfig):
Expand Down
17 changes: 15 additions & 2 deletions netbox_config_diff/compliance/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ def __init__(self, choices, *args, **kwargs):

def get_unified_diff(rendered_config: str, actual_config: str, device: str) -> str:
diff = unified_diff(
actual_config.splitlines(),
rendered_config.strip().splitlines(),
re.sub("\n{3,}", "\n", actual_config).splitlines(),
re.sub("\n{3,}", "\n", rendered_config).strip().splitlines(),
fromfiledate=device,
tofiledate=device,
lineterm="",
Expand All @@ -60,3 +60,16 @@ def get_remediation_commands(name: str, platform: str, actual_config: str, rende
host.load_running_config(config_text=actual_config)
host.load_generated_config(config_text=rendered_config)
return host.remediation_config_filtered_text(include_tags={}, exclude_tags={})


def get_diff_statistics(diff: str) -> tuple[int, int]:
lines_added = 0
lines_deleted = 0

for line in diff.splitlines():
if line.startswith("+") and not line.startswith("+++"):
lines_added += 1
elif line.startswith("-") and not line.startswith("---"):
lines_deleted += 1

return lines_added, lines_deleted
15 changes: 9 additions & 6 deletions netbox_config_diff/configurator/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,15 @@ async def _collect_one_diff(self, device: ConfiguratorDeviceDataClass) -> None:

device.diff = get_unified_diff(device.rendered_config, device.actual_config, device.name)
self.logger.add_diff(device.name, diff=device.diff)
device.missing = diff_network_config(
device.rendered_config, device.actual_config, PLATFORM_MAPPING[device.platform]
)
device.extra = diff_network_config(
device.actual_config, device.rendered_config, PLATFORM_MAPPING[device.platform]
)
try:
device.missing = diff_network_config(
device.rendered_config, device.actual_config, PLATFORM_MAPPING[device.platform]
)
device.extra = diff_network_config(
device.actual_config, device.rendered_config, PLATFORM_MAPPING[device.platform]
)
except Exception as e:
self.logger.log_warning(f"Unable to get missing/extra commands for {device.name}: {e}")
device.patch = get_remediation_commands(
device.name, device.platform, device.actual_config, device.rendered_config
)
Expand Down
6 changes: 3 additions & 3 deletions netbox_config_diff/configurator/platforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,15 @@ def _render_substituted_config(

replace_sections = [(name, re.search(pattern=pattern, string=source_config)) for name, pattern in substitutes]

rendered_config = ""
rendered_config = config_template
for name, replace_section in replace_sections:
if not replace_section:
msg = f"substitution pattern {name} was unable to find a match in the target config" " source"
msg = f"substitution pattern {name} was unable to find a match in the target configsource"
self.logger.critical(msg)
raise TemplateError(msg)

replace_group = replace_section.group()
rendered_config = config_template.replace(f"{{{{ {name} }}}}", replace_group)
rendered_config = rendered_config.replace(f"{{{{ {name} }}}}", replace_group)

# remove any totally empty lines (from bad regex, or just device spitting out lines w/
# nothing on it
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,14 @@ <h5 class="card-header">Error</h5>
<div class="row mb-3">
<div class="col col-md-12">
<div class="card">
<h5 class="card-header">Diff</h5>
<h2 class="card-header">Diff
{% if version|first != "3" and statistics %}
<div class="card-actions">
<span style="color: #1a7f37;">{{ statistics.0 }}</span> line(s) missing,
<span style="color: #d1242f;">{{ statistics.1 }}</span> extra line(s)
</div>
{% endif %}
</h2>
<div class="card-body" id="diffElement"></div>
</div>
</div>
Expand Down
5 changes: 5 additions & 0 deletions netbox_config_diff/views/compliance.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from netbox.views import generic
from utilities.views import ViewTab, register_model_view

from netbox_config_diff.compliance.utils import get_diff_statistics
from netbox_config_diff.filtersets import ConfigComplianceFilterSet, PlatformSettingFilterSet
from netbox_config_diff.forms import (
ConfigComplianceFilterForm,
Expand All @@ -25,10 +26,14 @@ class ConfigComplianceView(generic.ObjectView):
template_name = "netbox_config_diff/configcompliance/data.html"

def get_extra_context(self, request, instance):
statistics = None
if instance.diff:
statistics = get_diff_statistics(instance.diff)
return {
"instance": instance,
"base_template": self.base_template,
"version": VERSION,
"statistics": statistics,
}


Expand Down

0 comments on commit 6e4615c

Please sign in to comment.