diff --git a/netbox_diode_plugin/api/differ.py b/netbox_diode_plugin/api/differ.py index ca18faf..63ad865 100644 --- a/netbox_diode_plugin/api/differ.py +++ b/netbox_diode_plugin/api/differ.py @@ -6,11 +6,11 @@ import datetime import logging +import netaddr from django.contrib.contenttypes.models import ContentType from django.core.exceptions import ValidationError -from utilities.data import shallow_compare_dict from django.db.backends.postgresql.psycopg_any import NumericRange -import netaddr +from utilities.data import shallow_compare_dict from .common import Change, ChangeSet, ChangeSetException, ChangeSetResult, ChangeType, error_from_validation_error from .plugin_utils import get_primary_value, legal_fields diff --git a/netbox_diode_plugin/api/matcher.py b/netbox_diode_plugin/api/matcher.py index c033a26..c0ee706 100644 --- a/netbox_diode_plugin/api/matcher.py +++ b/netbox_diode_plugin/api/matcher.py @@ -8,6 +8,7 @@ from functools import cache, lru_cache from typing import Type +import netaddr from core.models import ObjectType as NetBoxType from django.conf import settings from django.contrib.contenttypes.fields import ContentType @@ -17,7 +18,6 @@ from django.db.models.fields import SlugField from django.db.models.lookups import Exact from django.db.models.query_utils import Q -import netaddr from extras.models.customfields import CustomField from .common import AutoSlug, UnresolvedReference diff --git a/netbox_diode_plugin/api/transformer.py b/netbox_diode_plugin/api/transformer.py index 830e5a7..f95ec52 100644 --- a/netbox_diode_plugin/api/transformer.py +++ b/netbox_diode_plugin/api/transformer.py @@ -364,6 +364,10 @@ def _resolve_existing_references(entities: list[dict]) -> list[dict]: data = copy.deepcopy(data) _update_resolved_refs(data, new_refs) + if data.get('_is_post_create'): + resolved.append(data) + continue + existing = find_existing_object(data, object_type) if existing is not None: logger.debug(f"existing {data} -> {existing}") diff --git a/netbox_diode_plugin/tests/test_api_diff_and_apply.py b/netbox_diode_plugin/tests/test_api_diff_and_apply.py index fdd3386..9a58989 100644 --- a/netbox_diode_plugin/tests/test_api_diff_and_apply.py +++ b/netbox_diode_plugin/tests/test_api_diff_and_apply.py @@ -2,24 +2,24 @@ # Copyright 2024 NetBox Labs Inc """Diode NetBox Plugin - Tests.""" +import copy import datetime import decimal import logging from uuid import uuid4 - +import netaddr +from circuits.models import Circuit from core.models import ObjectType from dcim.models import Device, Interface, Site -from ipam.models import VLANGroup -from circuits.models import Circuit from django.contrib.auth import get_user_model from extras.models import CustomField from extras.models.customfields import CustomFieldTypeChoices -from ipam.models import IPAddress -import netaddr +from ipam.models import IPAddress, VLANGroup from rest_framework import status from users.models import Token from utilities.testing import APITestCase +from virtualization.models import VMInterface logger = logging.getLogger(__name__) @@ -822,7 +822,78 @@ def test_generate_diff_update_ip_address(self): self.assertEqual(ip2.vrf, None) self.assertEqual(ip2.status, "deprecated") + def test_generate_diff_and_apply_complex_vminterface(self): + """Test generate diff and apply and update a complex vm interface.""" + payload = { + "timestamp": 1, + "object_type": "virtualization.vminterface", + "entity": { + "vm_interface": { + "virtual_machine": { + "name": "Virtual Machine 15e00bdf-4294-41df-a450-ffcfec6c7f2b", + "status": "active", + "site": { + "name": "Site 10" + }, + "cluster": { + "name": "Cluster 10", + "type": { + "name": "Cluster type 10" + }, + "group": { + "name": "Cluster group 10" + }, + "status": "active", + "scope_site": { + "name": "Site 10" + } + }, + "role": { + "name": "Role 10" + }, + "platform": { + "name": "Platform 10", + "manufacturer": { + "name": "Manufacturer 10" + } + }, + "vcpus": 1.0, + "memory": "4096", + "disk": "100", + "description": "Virtual Machine A description", + "comments": "Lorem ipsum dolor sit amet", + "tags": [ + { + "name": "tag 1" + } + ] + }, + "name": "Interface 47e8a593-8b74-4e94-9a8e-c02113f0bf88", + "enabled": False, + "mtu": "1500", + "primary_mac_address": { + "mac_address": "00:00:00:00:00:00" + }, + "description": "Interface A description", + "tags": [ + { + "name": "tag 1" + } + ] + } + } + } + _ = self.diff_and_apply(payload) + payload2 = copy.deepcopy(payload) + payload2['entity']['vm_interface']["mtu"] = "2000" + payload2['entity']['vm_interface']["primary_mac_address"] = { + "mac_address": "00:00:00:00:00:01" + } + _ = self.diff_and_apply(payload2) + vm_interface = VMInterface.objects.get(name="Interface 47e8a593-8b74-4e94-9a8e-c02113f0bf88") + self.assertEqual(vm_interface.mtu, 2000) + self.assertEqual(vm_interface.primary_mac_address.mac_address, "00:00:00:00:00:01") def diff_and_apply(self, payload): """Diff and apply the payload."""