Skip to content

Commit

Permalink
Fix bug in config compliance list view. (#854)
Browse files Browse the repository at this point in the history
* fixed bug in config compliance table
  • Loading branch information
gsnider2195 authored Jan 10, 2025
1 parent cac0083 commit 0b00113
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 8 deletions.
1 change: 1 addition & 0 deletions changes/812.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed bug in config compliance list view.
2 changes: 2 additions & 0 deletions nautobot_golden_config/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,8 @@ def to_objectchange(self, action, *, related_object=None, object_data_extra=None
related_object=related_object,
)

is_dynamic_group_associable_model = False

class Meta:
"""Set unique together fields for model."""

Expand Down
20 changes: 12 additions & 8 deletions nautobot_golden_config/tables.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
"""Django Tables2 classes for golden_config app."""

import copy

from django.utils.html import format_html
from django_tables2 import Column, LinkColumn, TemplateColumn
from django_tables2.utils import A
Expand Down Expand Up @@ -157,7 +155,7 @@ class ConfigComplianceTable(BaseTable):

pk = ToggleColumn(accessor=A("device"))
device = TemplateColumn(
template_code="""<a href="{% url 'plugins:nautobot_golden_config:configcompliance_devicetab' pk=record.device %}?tab=nautobot_golden_config:1" <strong>{{ record.device__name }}</strong></a> """
template_code="""<a href="{% url 'plugins:nautobot_golden_config:configcompliance_devicetab' pk=record.device %}?tab=nautobot_golden_config:1"><strong>{{ record.device__name }}</strong></a> """
)

def __init__(self, *args, **kwargs):
Expand All @@ -170,13 +168,19 @@ def __init__(self, *args, **kwargs):
.values_list("rule__feature__slug", flat=True)
.distinct()
)
extra_columns = [(feature, ComplianceColumn(verbose_name=feature)) for feature in features]
kwargs["extra_columns"] = extra_columns
# Nautobot's BaseTable.configurable_columns() only recognizes columns in self.base_columns,
# so override the class's base_columns to include our additional columns as configurable.
self.base_columns = copy.deepcopy(self.base_columns)
for feature, column in extra_columns:
self.base_columns[feature] = column
# Note: The correct way to modify django_tables2 columns at init is to use the extra_columns kwarg but Nautobot doesn't support that.
for feature in features:
self.base_columns[feature] = ComplianceColumn(verbose_name=feature) # pylint: disable=no-member
compliance_columns = [
column_name
for column_name, column in self.base_columns.items() # pylint: disable=no-member
if isinstance(column, ComplianceColumn)
]
removed_features = set(compliance_columns) - set(features)
for column_name in removed_features:
del self.base_columns[column_name] # pylint: disable=no-member
super().__init__(*args, **kwargs)

class Meta(BaseTable.Meta):
Expand Down
40 changes: 40 additions & 0 deletions nautobot_golden_config/tests/test_views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Unit tests for nautobot_golden_config views."""

import datetime
import re
from unittest import mock, skip

import nautobot
Expand Down Expand Up @@ -393,3 +394,42 @@ def test_alter_queryset(self):
self.assertSequenceEqual(list(device.keys()), ["device", "device__name", *features])
for feature in features:
self.assertIn(device[feature], [0, 1])

def test_table_columns(self):
"""Test the columns of the ConfigCompliance table return the expected pivoted data."""
response = self.client.get(reverse("plugins:nautobot_golden_config:configcompliance_list"))
expected_table_headers = ["Device", "TestFeature0", "TestFeature1", "TestFeature2", "TestFeature3"]
table_headers = re.findall(r'<th class="orderable"><a href=.*>(.+)</a></th>', response.content.decode())
self.assertEqual(table_headers, expected_table_headers)

# Add a new compliance feature and ensure the table headers update correctly
device2 = Device.objects.get(name="Device 2")
new_compliance_feature = create_feature_rule_json(device2, feature="NewTestFeature")
models.ConfigCompliance.objects.create(
device=device2,
rule=new_compliance_feature,
actual={"foo": {"bar-1": "baz"}},
intended={"foo": {"bar-1": "baz"}},
compliance=True,
compliance_int=1,
)

response = self.client.get(reverse("plugins:nautobot_golden_config:configcompliance_list"))
expected_table_headers = [
"Device",
"TestFeature0",
"TestFeature1",
"TestFeature2",
"TestFeature3",
"NewTestFeature",
]
table_headers = re.findall(r'<th class="orderable"><a href=.*>(.+)</a></th>', response.content.decode())
self.assertEqual(table_headers, expected_table_headers)

# Remove compliance features and ensure the table headers update correctly
models.ConfigCompliance.objects.filter(rule__feature__name__in=["TestFeature0", "TestFeature1"]).delete()

response = self.client.get(reverse("plugins:nautobot_golden_config:configcompliance_list"))
expected_table_headers = ["Device", "TestFeature2", "TestFeature3", "NewTestFeature"]
table_headers = re.findall(r'<th class="orderable"><a href=.*>(.+)</a></th>', response.content.decode())
self.assertEqual(table_headers, expected_table_headers)

0 comments on commit 0b00113

Please sign in to comment.