netbox-config-diff 2.3.0__tar.gz → 2.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {netbox-config-diff-2.3.0/netbox_config_diff.egg-info → netbox_config_diff-2.4.0}/PKG-INFO +2 -1
- netbox_config_diff-2.4.0/docs/media/screenshots/compliance-patch.png +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/__init__.py +1 -1
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/api/serializers.py +1 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/compliance/base.py +4 -1
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/compliance/utils.py +17 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/configurator/base.py +4 -1
- netbox_config_diff-2.4.0/netbox_config_diff/migrations/0009_configcompliance_patch.py +16 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/models/data_models.py +2 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/models/models.py +3 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/templates/netbox_config_diff/configcompliance/config.html +2 -1
- netbox_config_diff-2.4.0/netbox_config_diff/templates/netbox_config_diff/configcompliance/missing_extra.html +14 -0
- netbox_config_diff-2.4.0/netbox_config_diff/templates/netbox_config_diff/configcompliance/patch.html +11 -0
- netbox_config_diff-2.4.0/netbox_config_diff/templates/netbox_config_diff/inc/commands_card.html +16 -0
- netbox_config_diff-2.4.0/netbox_config_diff/views/base.py +52 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/views/compliance.py +29 -40
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0/netbox_config_diff.egg-info}/PKG-INFO +2 -1
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff.egg-info/SOURCES.txt +4 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff.egg-info/requires.txt +1 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/requirements/base.txt +1 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/tests/test_compliance.py +1 -0
- netbox-config-diff-2.3.0/netbox_config_diff/templates/netbox_config_diff/configcompliance/missing_extra.html +0 -42
- netbox-config-diff-2.3.0/netbox_config_diff/views/base.py +0 -13
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/LICENSE +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/MANIFEST.in +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/README.md +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/development/configuration.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/compliance-diff.png +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/compliance-error.png +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/compliance-list.png +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/compliance-missing-extra.png +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/compliance-ok.png +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/config-temp-substitute.png +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/cr-approve-button.png +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/cr-approved.png +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/cr-collecting-diff-button.png +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/cr-completed.png +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/cr-created.png +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/cr-diffs-tab.png +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/cr-job-log.png +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/cr-schedule-button.png +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/cr-scheduled.png +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/cr-unapprove-button.png +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/cr-unschedule-button.png +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/navbar.png +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/platformsetting.png +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/render-temp-substitute.png +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/script-list.png +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/script.png +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/substitute.png +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/api/__init__.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/api/urls.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/api/views.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/choices.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/compliance/__init__.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/compliance/secrets.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/configurator/__init__.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/configurator/exceptions.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/configurator/factory.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/configurator/platforms.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/configurator/utils.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/constants.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/filtersets.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/forms.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/graphql.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/jobs.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/migrations/0001_initial.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/migrations/0002_add_script.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/migrations/0003_configcompliance_actual_config_and_more.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/migrations/0004_update_script.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/migrations/0005_configcompliance_extra_missing.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/migrations/0006_substitute.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/migrations/0007_configurationrequest.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/migrations/0008_alter_configcompliance_device.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/migrations/__init__.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/models/__init__.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/models/base.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/navigation.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/scripts/config_diff.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/search.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/static/netbox_config_diff/diff2html-ui.min.js +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/static/netbox_config_diff/diff2html.dark.min.css +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/static/netbox_config_diff/diff2html.min.css +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/tables.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/templates/netbox_config_diff/configcompliance/data.html +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/templates/netbox_config_diff/configcompliance.html +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/templates/netbox_config_diff/configurationrequest/base.html +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/templates/netbox_config_diff/configurationrequest/diffs.html +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/templates/netbox_config_diff/configurationrequest.html +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/templates/netbox_config_diff/inc/diff.html +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/templates/netbox_config_diff/inc/job_log.html +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/templates/netbox_config_diff/platformsetting.html +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/templates/netbox_config_diff/substitute.html +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/urls.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/views/__init__.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/views/configuration.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff.egg-info/dependency_links.txt +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff.egg-info/top_level.txt +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/pyproject.toml +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/requirements/dev.txt +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/requirements/test.txt +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/setup.cfg +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/tests/conftest.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/tests/factories.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/tests/test_compliance_utils.py +0 -0
- {netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/tests/test_urls.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: netbox-config-diff
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4.0
|
|
4
4
|
Summary: Push rendered device configurations from NetBox to devices and apply them.
|
|
5
5
|
Author: Artem Kotik
|
|
6
6
|
Author-email: miaow2@yandex.ru
|
|
@@ -218,6 +218,7 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
|
218
218
|
Requires-Python: >=3.10
|
|
219
219
|
Description-Content-Type: text/markdown
|
|
220
220
|
License-File: LICENSE
|
|
221
|
+
Requires-Dist: hier-config==2.2.3
|
|
221
222
|
Requires-Dist: netutils==1.5.0
|
|
222
223
|
Requires-Dist: scrapli[asyncssh]==2023.07.30
|
|
223
224
|
Requires-Dist: scrapli-cfg==2023.07.30
|
|
Binary file
|
|
@@ -18,7 +18,7 @@ from utilities.utils import render_jinja2
|
|
|
18
18
|
from netbox_config_diff.models import ConplianceDeviceDataClass
|
|
19
19
|
|
|
20
20
|
from .secrets import SecretsMixin
|
|
21
|
-
from .utils import PLATFORM_MAPPING, CustomChoiceVar, exclude_lines, get_unified_diff
|
|
21
|
+
from .utils import PLATFORM_MAPPING, CustomChoiceVar, exclude_lines, get_remediation_commands, get_unified_diff
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
class ConfigDiffBase(SecretsMixin):
|
|
@@ -204,3 +204,6 @@ class ConfigDiffBase(SecretsMixin):
|
|
|
204
204
|
device.extra = diff_network_config(
|
|
205
205
|
cleaned_config, device.rendered_config, PLATFORM_MAPPING[device.platform]
|
|
206
206
|
)
|
|
207
|
+
device.patch = get_remediation_commands(
|
|
208
|
+
device.name, device.platform, cleaned_config, device.rendered_config
|
|
209
|
+
)
|
{netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/compliance/utils.py
RENAMED
|
@@ -3,6 +3,7 @@ from difflib import unified_diff
|
|
|
3
3
|
|
|
4
4
|
from django.forms import ChoiceField
|
|
5
5
|
from extras.scripts import ScriptVariable
|
|
6
|
+
from hier_config import Host
|
|
6
7
|
|
|
7
8
|
PLATFORM_MAPPING = {
|
|
8
9
|
"arista_eos": "arista_eos",
|
|
@@ -19,6 +20,15 @@ PLATFORM_MAPPING = {
|
|
|
19
20
|
"ruckus_fastiron": "ruckus_fastiron",
|
|
20
21
|
}
|
|
21
22
|
|
|
23
|
+
REMEDIATION_MAPPING = {
|
|
24
|
+
"arista_eos": "eos",
|
|
25
|
+
"cisco_iosxe": "ios",
|
|
26
|
+
"cisco_iosxr": "iosxr",
|
|
27
|
+
"cisco_nxos": "nxos",
|
|
28
|
+
"juniper_junos": "junos",
|
|
29
|
+
"vyos_vyos": "vyos",
|
|
30
|
+
}
|
|
31
|
+
|
|
22
32
|
|
|
23
33
|
class CustomChoiceVar(ScriptVariable):
|
|
24
34
|
form_field = ChoiceField
|
|
@@ -43,3 +53,10 @@ def exclude_lines(text: str, regexs: list) -> str:
|
|
|
43
53
|
for item in regexs:
|
|
44
54
|
text = re.sub(item, "", text, flags=re.I | re.M)
|
|
45
55
|
return text.strip()
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def get_remediation_commands(name: str, platform: str, actual_config: str, rendered_config: str) -> str:
|
|
59
|
+
host = Host(hostname=name, os=REMEDIATION_MAPPING.get(platform, "ios"))
|
|
60
|
+
host.load_running_config(config_text=actual_config)
|
|
61
|
+
host.load_generated_config(config_text=rendered_config)
|
|
62
|
+
return host.remediation_config_filtered_text(include_tags={}, exclude_tags={})
|
{netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/configurator/base.py
RENAMED
|
@@ -14,7 +14,7 @@ from scrapli_cfg.response import ScrapliCfgResponse
|
|
|
14
14
|
from utilities.utils import NetBoxFakeRequest
|
|
15
15
|
|
|
16
16
|
from netbox_config_diff.compliance.secrets import SecretsMixin
|
|
17
|
-
from netbox_config_diff.compliance.utils import PLATFORM_MAPPING, get_unified_diff
|
|
17
|
+
from netbox_config_diff.compliance.utils import PLATFORM_MAPPING, get_remediation_commands, get_unified_diff
|
|
18
18
|
from netbox_config_diff.configurator.exceptions import DeviceConfigurationError, DeviceValidationError
|
|
19
19
|
from netbox_config_diff.configurator.utils import CustomLogger
|
|
20
20
|
from netbox_config_diff.constants import ACCEPTABLE_DRIVERS
|
|
@@ -137,6 +137,9 @@ class Configurator(SecretsMixin):
|
|
|
137
137
|
device.extra = diff_network_config(
|
|
138
138
|
device.actual_config, device.rendered_config, PLATFORM_MAPPING[device.platform]
|
|
139
139
|
)
|
|
140
|
+
device.patch = get_remediation_commands(
|
|
141
|
+
device.name, device.platform, device.actual_config, device.rendered_config
|
|
142
|
+
)
|
|
140
143
|
self.logger.log_info(f"Got diff from {device.name}")
|
|
141
144
|
except Exception:
|
|
142
145
|
error = traceback.format_exc()
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from django.db import migrations, models
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Migration(migrations.Migration):
|
|
5
|
+
|
|
6
|
+
dependencies = [
|
|
7
|
+
("netbox_config_diff", "0008_alter_configcompliance_device"),
|
|
8
|
+
]
|
|
9
|
+
|
|
10
|
+
operations = [
|
|
11
|
+
migrations.AddField(
|
|
12
|
+
model_name="configcompliance",
|
|
13
|
+
name="patch",
|
|
14
|
+
field=models.TextField(blank=True),
|
|
15
|
+
),
|
|
16
|
+
]
|
{netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/models/data_models.py
RENAMED
|
@@ -23,6 +23,7 @@ class BaseDeviceDataClass:
|
|
|
23
23
|
diff: str = ""
|
|
24
24
|
missing: str | None = None
|
|
25
25
|
extra: str | None = None
|
|
26
|
+
patch: str | None = None
|
|
26
27
|
error: str = ""
|
|
27
28
|
config_error: str | None = None
|
|
28
29
|
auth_strict_key: bool = False
|
|
@@ -99,6 +100,7 @@ class BaseDeviceDataClass:
|
|
|
99
100
|
"actual_config": self.actual_config or "",
|
|
100
101
|
"missing": self.missing or "",
|
|
101
102
|
"extra": self.extra or "",
|
|
103
|
+
"patch": self.patch or "",
|
|
102
104
|
}
|
|
103
105
|
|
|
104
106
|
def send_to_db(self) -> None:
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
<div class="card">
|
|
9
9
|
<div class="card-header">
|
|
10
10
|
<div class="float-end">
|
|
11
|
+
{% copy_content config_field %}
|
|
11
12
|
<a href="?export=True" class="btn btn-sm btn-primary" role="button">
|
|
12
13
|
<i class="mdi mdi-download" aria-hidden="true"></i> Download
|
|
13
14
|
</a>
|
|
@@ -15,7 +16,7 @@
|
|
|
15
16
|
<h5>{{ header }}</h5>
|
|
16
17
|
</div>
|
|
17
18
|
{% if config %}
|
|
18
|
-
<pre class="card-body">{{ config }}</pre>
|
|
19
|
+
<pre class="card-body" id="{{ config_field }}">{{ config }}</pre>
|
|
19
20
|
{% else %}
|
|
20
21
|
<div class="card-body text-muted">No configuration</div>
|
|
21
22
|
{% endif %}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{% extends "netbox_config_diff/configcompliance.html" %}
|
|
2
|
+
|
|
3
|
+
{% block title %}{{ object }} - Missing/Extra{% endblock %}
|
|
4
|
+
|
|
5
|
+
{% block content %}
|
|
6
|
+
<div class="row">
|
|
7
|
+
<div class="col col-md-6">
|
|
8
|
+
{% include 'netbox_config_diff/inc/commands_card.html' with data=object.missing header='Missing' pre_id='missing' %}
|
|
9
|
+
</div>
|
|
10
|
+
<div class="col col-md-6">
|
|
11
|
+
{% include 'netbox_config_diff/inc/commands_card.html' with data=object.extra header='Extra' pre_id='extra' %}
|
|
12
|
+
</div>
|
|
13
|
+
</div>
|
|
14
|
+
{% endblock %}
|
netbox_config_diff-2.4.0/netbox_config_diff/templates/netbox_config_diff/configcompliance/patch.html
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{% extends "netbox_config_diff/configcompliance.html" %}
|
|
2
|
+
|
|
3
|
+
{% block title %}{{ object }} - Patch commands{% endblock %}
|
|
4
|
+
|
|
5
|
+
{% block content %}
|
|
6
|
+
<div class="row">
|
|
7
|
+
<div class="col col-md-6">
|
|
8
|
+
{% include 'netbox_config_diff/inc/commands_card.html' with data=object.patch header='Patch commands' pre_id='patch' %}
|
|
9
|
+
</div>
|
|
10
|
+
</div>
|
|
11
|
+
{% endblock %}
|
netbox_config_diff-2.4.0/netbox_config_diff/templates/netbox_config_diff/inc/commands_card.html
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<div class="card">
|
|
2
|
+
<div class="card-header">
|
|
3
|
+
<div class="float-end">
|
|
4
|
+
{% copy_content pre_id %}
|
|
5
|
+
<a href="?export_{{ pre_id }}=True" class="btn btn-sm btn-primary" role="button">
|
|
6
|
+
<i class="mdi mdi-download" aria-hidden="true"></i> Download
|
|
7
|
+
</a>
|
|
8
|
+
</div>
|
|
9
|
+
<h5>{{ header }}</h5>
|
|
10
|
+
</div>
|
|
11
|
+
{% if data %}
|
|
12
|
+
<pre class="card-body" id="{{ pre_id }}">{{ data }}</pre>
|
|
13
|
+
{% else %}
|
|
14
|
+
<div class="card-body text-muted">No commands</div>
|
|
15
|
+
{% endif %}
|
|
16
|
+
</div>
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
from django.http import HttpResponse
|
|
2
|
+
from django.shortcuts import render
|
|
3
|
+
from django.urls import reverse
|
|
4
|
+
from netbox.views.generic import ObjectDeleteView, ObjectEditView, ObjectView
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class BaseObjectDeleteView(ObjectDeleteView):
|
|
8
|
+
def get_return_url(self, request, obj=None):
|
|
9
|
+
return reverse(f"plugins:netbox_config_diff:{self.queryset.model._meta.model_name}_list")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class BaseObjectEditView(ObjectEditView):
|
|
13
|
+
@property
|
|
14
|
+
def default_return_url(self) -> str:
|
|
15
|
+
return f"plugins:netbox_config_diff:{self.queryset.model._meta.model_name}_list"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class BaseExportView(ObjectView):
|
|
19
|
+
def export_parts(self, name, lines, suffix):
|
|
20
|
+
response = HttpResponse(lines, content_type="text")
|
|
21
|
+
filename = f"{name}_{suffix}.txt"
|
|
22
|
+
response["Content-Disposition"] = f'attachment; filename="{filename}"'
|
|
23
|
+
return response
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class BaseConfigComplianceConfigView(BaseExportView):
|
|
27
|
+
config_field = None
|
|
28
|
+
template_header = None
|
|
29
|
+
|
|
30
|
+
def get(self, request, **kwargs):
|
|
31
|
+
instance = self.get_object(**kwargs)
|
|
32
|
+
context = self.get_extra_context(request, instance)
|
|
33
|
+
|
|
34
|
+
if request.GET.get("export"):
|
|
35
|
+
return self.export_parts(instance.device.name, context["config"], self.config_field)
|
|
36
|
+
|
|
37
|
+
return render(
|
|
38
|
+
request,
|
|
39
|
+
self.get_template_name(),
|
|
40
|
+
{
|
|
41
|
+
"object": instance,
|
|
42
|
+
"tab": self.tab,
|
|
43
|
+
**context,
|
|
44
|
+
},
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
def get_extra_context(self, request, instance):
|
|
48
|
+
return {
|
|
49
|
+
"header": self.template_header,
|
|
50
|
+
"config": getattr(instance, self.config_field),
|
|
51
|
+
"config_field": self.config_field,
|
|
52
|
+
}
|
{netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/views/compliance.py
RENAMED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
from dcim.models import Device
|
|
2
|
-
from django.http import HttpResponse
|
|
3
2
|
from django.shortcuts import redirect, render
|
|
4
3
|
from django.utils.translation import gettext as _
|
|
5
4
|
from netbox.views import generic
|
|
@@ -15,38 +14,7 @@ from netbox_config_diff.forms import (
|
|
|
15
14
|
from netbox_config_diff.models import ConfigCompliance, PlatformSetting
|
|
16
15
|
from netbox_config_diff.tables import ConfigComplianceTable, PlatformSettingTable
|
|
17
16
|
|
|
18
|
-
from .base import BaseObjectDeleteView, BaseObjectEditView
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
class BaseConfigComplianceConfigView(generic.ObjectView):
|
|
22
|
-
config_field = None
|
|
23
|
-
template_header = None
|
|
24
|
-
|
|
25
|
-
def get(self, request, **kwargs):
|
|
26
|
-
instance = self.get_object(**kwargs)
|
|
27
|
-
context = self.get_extra_context(request, instance)
|
|
28
|
-
|
|
29
|
-
if request.GET.get("export"):
|
|
30
|
-
response = HttpResponse(context["config"], content_type="text")
|
|
31
|
-
filename = f"{instance.device.name}_{self.config_field}.txt"
|
|
32
|
-
response["Content-Disposition"] = f'attachment; filename="{filename}"'
|
|
33
|
-
return response
|
|
34
|
-
|
|
35
|
-
return render(
|
|
36
|
-
request,
|
|
37
|
-
self.get_template_name(),
|
|
38
|
-
{
|
|
39
|
-
"object": instance,
|
|
40
|
-
"tab": self.tab,
|
|
41
|
-
**context,
|
|
42
|
-
},
|
|
43
|
-
)
|
|
44
|
-
|
|
45
|
-
def get_extra_context(self, request, instance):
|
|
46
|
-
return {
|
|
47
|
-
"header": self.template_header,
|
|
48
|
-
"config": getattr(instance, self.config_field),
|
|
49
|
-
}
|
|
17
|
+
from .base import BaseConfigComplianceConfigView, BaseExportView, BaseObjectDeleteView, BaseObjectEditView
|
|
50
18
|
|
|
51
19
|
|
|
52
20
|
@register_model_view(ConfigCompliance)
|
|
@@ -87,7 +55,7 @@ class ConfigComplianceActualConfigView(BaseConfigComplianceConfigView):
|
|
|
87
55
|
|
|
88
56
|
|
|
89
57
|
@register_model_view(ConfigCompliance, "missing-extra")
|
|
90
|
-
class ConfigComplianceMissingExtraConfigView(
|
|
58
|
+
class ConfigComplianceMissingExtraConfigView(BaseExportView):
|
|
91
59
|
queryset = ConfigCompliance.objects.all()
|
|
92
60
|
template_name = "netbox_config_diff/configcompliance/missing_extra.html"
|
|
93
61
|
tab = ViewTab(
|
|
@@ -95,12 +63,6 @@ class ConfigComplianceMissingExtraConfigView(generic.ObjectView):
|
|
|
95
63
|
weight=520,
|
|
96
64
|
)
|
|
97
65
|
|
|
98
|
-
def export_parts(self, name, lines, suffix):
|
|
99
|
-
response = HttpResponse(lines, content_type="text")
|
|
100
|
-
filename = f"{name}_{suffix}.txt"
|
|
101
|
-
response["Content-Disposition"] = f'attachment; filename="{filename}"'
|
|
102
|
-
return response
|
|
103
|
-
|
|
104
66
|
def get(self, request, **kwargs):
|
|
105
67
|
instance = self.get_object(**kwargs)
|
|
106
68
|
context = self.get_extra_context(request, instance)
|
|
@@ -122,6 +84,33 @@ class ConfigComplianceMissingExtraConfigView(generic.ObjectView):
|
|
|
122
84
|
)
|
|
123
85
|
|
|
124
86
|
|
|
87
|
+
@register_model_view(ConfigCompliance, "patch")
|
|
88
|
+
class ConfigCompliancePatchView(BaseExportView):
|
|
89
|
+
queryset = ConfigCompliance.objects.all()
|
|
90
|
+
template_name = "netbox_config_diff/configcompliance/patch.html"
|
|
91
|
+
tab = ViewTab(
|
|
92
|
+
label=_("Patch"),
|
|
93
|
+
weight=515,
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
def get(self, request, **kwargs):
|
|
97
|
+
instance = self.get_object(**kwargs)
|
|
98
|
+
context = self.get_extra_context(request, instance)
|
|
99
|
+
|
|
100
|
+
if request.GET.get("export_patch"):
|
|
101
|
+
return self.export_parts(instance.device.name, instance.patch, "patch")
|
|
102
|
+
|
|
103
|
+
return render(
|
|
104
|
+
request,
|
|
105
|
+
self.get_template_name(),
|
|
106
|
+
{
|
|
107
|
+
"object": instance,
|
|
108
|
+
"tab": self.tab,
|
|
109
|
+
**context,
|
|
110
|
+
},
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
|
|
125
114
|
@register_model_view(Device, "config_compliance", "config-compliance")
|
|
126
115
|
class ConfigComplianceDeviceView(generic.ObjectView):
|
|
127
116
|
queryset = Device.objects.all()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: netbox-config-diff
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4.0
|
|
4
4
|
Summary: Push rendered device configurations from NetBox to devices and apply them.
|
|
5
5
|
Author: Artem Kotik
|
|
6
6
|
Author-email: miaow2@yandex.ru
|
|
@@ -218,6 +218,7 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
|
218
218
|
Requires-Python: >=3.10
|
|
219
219
|
Description-Content-Type: text/markdown
|
|
220
220
|
License-File: LICENSE
|
|
221
|
+
Requires-Dist: hier-config==2.2.3
|
|
221
222
|
Requires-Dist: netutils==1.5.0
|
|
222
223
|
Requires-Dist: scrapli[asyncssh]==2023.07.30
|
|
223
224
|
Requires-Dist: scrapli-cfg==2023.07.30
|
{netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff.egg-info/SOURCES.txt
RENAMED
|
@@ -8,6 +8,7 @@ docs/media/screenshots/compliance-error.png
|
|
|
8
8
|
docs/media/screenshots/compliance-list.png
|
|
9
9
|
docs/media/screenshots/compliance-missing-extra.png
|
|
10
10
|
docs/media/screenshots/compliance-ok.png
|
|
11
|
+
docs/media/screenshots/compliance-patch.png
|
|
11
12
|
docs/media/screenshots/config-temp-substitute.png
|
|
12
13
|
docs/media/screenshots/cr-approve-button.png
|
|
13
14
|
docs/media/screenshots/cr-approved.png
|
|
@@ -64,6 +65,7 @@ netbox_config_diff/migrations/0005_configcompliance_extra_missing.py
|
|
|
64
65
|
netbox_config_diff/migrations/0006_substitute.py
|
|
65
66
|
netbox_config_diff/migrations/0007_configurationrequest.py
|
|
66
67
|
netbox_config_diff/migrations/0008_alter_configcompliance_device.py
|
|
68
|
+
netbox_config_diff/migrations/0009_configcompliance_patch.py
|
|
67
69
|
netbox_config_diff/migrations/__init__.py
|
|
68
70
|
netbox_config_diff/models/__init__.py
|
|
69
71
|
netbox_config_diff/models/base.py
|
|
@@ -80,8 +82,10 @@ netbox_config_diff/templates/netbox_config_diff/substitute.html
|
|
|
80
82
|
netbox_config_diff/templates/netbox_config_diff/configcompliance/config.html
|
|
81
83
|
netbox_config_diff/templates/netbox_config_diff/configcompliance/data.html
|
|
82
84
|
netbox_config_diff/templates/netbox_config_diff/configcompliance/missing_extra.html
|
|
85
|
+
netbox_config_diff/templates/netbox_config_diff/configcompliance/patch.html
|
|
83
86
|
netbox_config_diff/templates/netbox_config_diff/configurationrequest/base.html
|
|
84
87
|
netbox_config_diff/templates/netbox_config_diff/configurationrequest/diffs.html
|
|
88
|
+
netbox_config_diff/templates/netbox_config_diff/inc/commands_card.html
|
|
85
89
|
netbox_config_diff/templates/netbox_config_diff/inc/diff.html
|
|
86
90
|
netbox_config_diff/templates/netbox_config_diff/inc/job_log.html
|
|
87
91
|
netbox_config_diff/views/__init__.py
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
{% extends "netbox_config_diff/configcompliance.html" %}
|
|
2
|
-
|
|
3
|
-
{% block title %}{{ object }} - Missing/Extra{% endblock %}
|
|
4
|
-
|
|
5
|
-
{% block content %}
|
|
6
|
-
<div class="row">
|
|
7
|
-
<div class="col col-md-6">
|
|
8
|
-
<div class="card">
|
|
9
|
-
<div class="card-header">
|
|
10
|
-
<div class="float-end">
|
|
11
|
-
<a href="?export_missing=True" class="btn btn-sm btn-primary" role="button">
|
|
12
|
-
<i class="mdi mdi-download" aria-hidden="true"></i> Download
|
|
13
|
-
</a>
|
|
14
|
-
</div>
|
|
15
|
-
<h5>Missing</h5>
|
|
16
|
-
</div>
|
|
17
|
-
{% if object.missing %}
|
|
18
|
-
<pre class="card-body">{{ object.missing }}</pre>
|
|
19
|
-
{% else %}
|
|
20
|
-
<div class="card-body text-muted">No lines</div>
|
|
21
|
-
{% endif %}
|
|
22
|
-
</div>
|
|
23
|
-
</div>
|
|
24
|
-
<div class="col col-md-6">
|
|
25
|
-
<div class="card">
|
|
26
|
-
<div class="card-header">
|
|
27
|
-
<div class="float-end">
|
|
28
|
-
<a href="?export_extra=True" class="btn btn-sm btn-primary" role="button">
|
|
29
|
-
<i class="mdi mdi-download" aria-hidden="true"></i> Download
|
|
30
|
-
</a>
|
|
31
|
-
</div>
|
|
32
|
-
<h5>Extra</h5>
|
|
33
|
-
</div>
|
|
34
|
-
{% if object.extra %}
|
|
35
|
-
<pre class="card-body">{{ object.extra }}</pre>
|
|
36
|
-
{% else %}
|
|
37
|
-
<div class="card-body text-muted">No lines</div>
|
|
38
|
-
{% endif %}
|
|
39
|
-
</div>
|
|
40
|
-
</div>
|
|
41
|
-
</div>
|
|
42
|
-
{% endblock %}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
from django.urls import reverse
|
|
2
|
-
from netbox.views.generic import ObjectDeleteView, ObjectEditView
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
class BaseObjectDeleteView(ObjectDeleteView):
|
|
6
|
-
def get_return_url(self, request, obj=None):
|
|
7
|
-
return reverse(f"plugins:netbox_config_diff:{self.queryset.model._meta.model_name}_list")
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class BaseObjectEditView(ObjectEditView):
|
|
11
|
-
@property
|
|
12
|
-
def default_return_url(self) -> str:
|
|
13
|
-
return f"plugins:netbox_config_diff:{self.queryset.model._meta.model_name}_list"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/compliance-diff.png
RENAMED
|
File without changes
|
{netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/compliance-error.png
RENAMED
|
File without changes
|
{netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/compliance-list.png
RENAMED
|
File without changes
|
|
File without changes
|
{netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/compliance-ok.png
RENAMED
|
File without changes
|
|
File without changes
|
{netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/cr-approve-button.png
RENAMED
|
File without changes
|
{netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/cr-approved.png
RENAMED
|
File without changes
|
|
File without changes
|
{netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/cr-completed.png
RENAMED
|
File without changes
|
|
File without changes
|
{netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/cr-diffs-tab.png
RENAMED
|
File without changes
|
|
File without changes
|
{netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/cr-schedule-button.png
RENAMED
|
File without changes
|
{netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/cr-scheduled.png
RENAMED
|
File without changes
|
{netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/cr-unapprove-button.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/platformsetting.png
RENAMED
|
File without changes
|
|
File without changes
|
{netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/docs/media/screenshots/script-list.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/compliance/__init__.py
RENAMED
|
File without changes
|
{netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/compliance/secrets.py
RENAMED
|
File without changes
|
{netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/configurator/__init__.py
RENAMED
|
File without changes
|
{netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/configurator/exceptions.py
RENAMED
|
File without changes
|
{netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/configurator/factory.py
RENAMED
|
File without changes
|
{netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/configurator/platforms.py
RENAMED
|
File without changes
|
{netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/configurator/utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/migrations/0001_initial.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/migrations/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/scripts/config_diff.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff/views/configuration.py
RENAMED
|
File without changes
|
|
File without changes
|
{netbox-config-diff-2.3.0 → netbox_config_diff-2.4.0}/netbox_config_diff.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|