feat: automate patchpanel mappings and cable tenancy

This commit is contained in:
2026-08-06 15:09:08 +02:00
parent e1153cfce4
commit 0c4a737d41
9 changed files with 405 additions and 20 deletions
+68 -1
View File
@@ -5,7 +5,13 @@ from django import forms
from django.test import SimpleTestCase
from tenancy.models import TenantGroup
from netbox_utilities.tenant_autofill import apply_tenant_autofill, infer_tenant_id, tenant_id_from_object
from netbox_utilities.tenant_autofill import (
apply_cable_instance_tenant,
apply_tenant_autofill,
infer_tenant_id,
tenant_id_from_cable_terminations,
tenant_id_from_object,
)
from netbox_utilities.tenant_scope import ActiveTenantScope, active_tenant_scope
@@ -17,6 +23,11 @@ class FakeMeta:
return [SimpleNamespace(name=name) for name in self.field_names]
class FakeCableMeta(FakeMeta):
app_label = "dcim"
model_name = "cable"
class FakeObject:
def __init__(self, *, tenant_id=None, **relations):
self.tenant_id = tenant_id
@@ -25,6 +36,14 @@ class FakeObject:
setattr(self, name, value)
class FakeCable(FakeObject):
def __init__(self, *, tenant_id=None, a_terminations=None, b_terminations=None):
super().__init__(tenant_id=tenant_id)
self._meta = FakeCableMeta("tenant")
self.a_terminations = a_terminations or []
self.b_terminations = b_terminations or []
class FakeQuerySet:
def __init__(self, model):
self.model = model
@@ -50,6 +69,54 @@ class TenantAutofillTest(SimpleTestCase):
finally:
active_tenant_scope.reset(token)
def test_finds_common_cable_tenant_from_both_ends(self):
terminations = [FakeObject(device=FakeObject(tenant_id=42)), FakeObject(device=FakeObject(tenant_id=42))]
self.assertEqual(tenant_id_from_cable_terminations(terminations), 42)
def test_does_not_guess_when_cable_ends_have_different_tenants(self):
terminations = [FakeObject(device=FakeObject(tenant_id=42)), FakeObject(device=FakeObject(tenant_id=43))]
self.assertIsNone(tenant_id_from_cable_terminations(terminations))
def test_assigns_common_tenant_to_cable_instance(self):
cable = FakeCable(
a_terminations=[FakeObject(device=FakeObject(tenant_id=42))],
b_terminations=[FakeObject(device=FakeObject(tenant_id=42))],
)
self.assertEqual(apply_cable_instance_tenant(cable), 42)
self.assertEqual(cable.tenant_id, 42)
def test_prefers_cable_terminations_over_global_scope(self):
form = SimpleNamespace(
fields={"tenant": forms.IntegerField()},
initial={},
instance=FakeCable(a_terminations=[FakeObject(device=FakeObject(tenant_id=42))]),
is_bound=False,
)
token = active_tenant_scope.set(ActiveTenantScope("tenant", 17, frozenset({17})))
try:
self.assertEqual(infer_tenant_id(form), 42)
finally:
active_tenant_scope.reset(token)
def test_conflicting_cable_ends_do_not_fall_back_to_global_scope(self):
form = SimpleNamespace(
fields={"tenant": forms.IntegerField()},
initial={},
instance=FakeCable(
a_terminations=[FakeObject(device=FakeObject(tenant_id=42))],
b_terminations=[FakeObject(device=FakeObject(tenant_id=43))],
),
is_bound=False,
)
token = active_tenant_scope.set(ActiveTenantScope("tenant", 17, frozenset({17})))
try:
self.assertIsNone(infer_tenant_id(form))
finally:
active_tenant_scope.reset(token)
@patch("netbox_utilities.tenant_autofill._infer_group_id", return_value=None)
@patch("netbox_utilities.tenant_autofill.infer_tenant_id", return_value=23)
def test_prefills_and_marks_tenant_field(self, _infer_tenant_id, _infer_group_id):