Skip to content

Commit 65c16f3

Browse files
authored
fix: consider object type in fingerprint all deduplication (#91)
2 parents 9616d2c + 203ef34 commit 65c16f3

File tree

2 files changed

+37
-3
lines changed

2 files changed

+37
-3
lines changed

netbox_diode_plugin/api/matcher.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,7 @@ def _get_refs(expr) -> set[str]:
735735
logger.warning(f"Unhandled expression type for _get_refs: {type(expr)}")
736736
return refs
737737

738-
def _fingerprint_all(data: dict) -> str:
738+
def _fingerprint_all(data: dict, object_type: str|None = None) -> str:
739739
"""
740740
Returns a fingerprint of the data based on all fields.
741741
@@ -745,7 +745,7 @@ def _fingerprint_all(data: dict) -> str:
745745
if data is None:
746746
return None
747747

748-
values = []
748+
values = ["object_type", object_type]
749749
for k, v in sorted(data.items()):
750750
if k.startswith("_"):
751751
continue
@@ -776,7 +776,7 @@ def fingerprints(data: dict, object_type: str) -> list[str]:
776776
fp = matcher.fingerprint(data)
777777
if fp is not None:
778778
fps.append(fp)
779-
fp = _fingerprint_all(data)
779+
fp = _fingerprint_all(data, object_type)
780780
fps.append(fp)
781781
return fps
782782

netbox_diode_plugin/tests/test_api_generate_diff.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"""Diode NetBox Plugin - Tests."""
44

55
import logging
6+
from collections import defaultdict
67
from types import SimpleNamespace
78
from unittest import mock
89
from uuid import uuid4
@@ -377,6 +378,39 @@ def test_vlangroup_error(self):
377378
}
378379
_ = self.send_request(payload)
379380

381+
def test_generate_diff_dedupe_different_object_types(self):
382+
"""Test generate diff dedupe different object types with same values."""
383+
payload = {
384+
"timestamp": 1,
385+
"object_type": "dcim.device",
386+
"entity": {
387+
"device": {
388+
"name": "Cat8000V",
389+
"role": {"name": "undefined"},
390+
"site": {"name": "undefined"},
391+
"serial": "9OBXJHNNU5V",
392+
"status": "active",
393+
"platform": {"name": "ios", "manufacturer": {"name": "undefined"}},
394+
"device_type": {"model": "C8000V", "manufacturer": {"name": "undefined"}}
395+
},
396+
},
397+
}
398+
response = self.send_request(payload)
399+
self.assertEqual(response.status_code, status.HTTP_200_OK)
400+
cs = response.json().get("change_set", {})
401+
self.assertIsNotNone(cs.get("id"))
402+
changes = cs.get("changes", [])
403+
self.assertEqual(len(changes), 6)
404+
by_object_type = defaultdict(int)
405+
for change in changes:
406+
by_object_type[change.get("object_type")] += 1
407+
408+
self.assertEqual(by_object_type["dcim.device"], 1)
409+
self.assertEqual(by_object_type["dcim.manufacturer"], 1)
410+
self.assertEqual(by_object_type["dcim.platform"], 1)
411+
self.assertEqual(by_object_type["dcim.devicetype"], 1)
412+
self.assertEqual(by_object_type["dcim.site"], 1)
413+
self.assertEqual(by_object_type["dcim.devicerole"], 1)
380414

381415
def send_request(self, payload, status_code=status.HTTP_200_OK):
382416
"""Post the payload to the url and return the response."""

0 commit comments

Comments
 (0)