ipfabric_netbox 4.2.0b5__py3-none-any.whl → 4.2.0b6__py3-none-any.whl

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.
@@ -6,7 +6,7 @@ class NetboxIPFabricConfig(PluginConfig):
6
6
  name = "ipfabric_netbox"
7
7
  verbose_name = "NetBox IP Fabric SoT Plugin"
8
8
  description = "Sync IP Fabric into NetBox"
9
- version = "4.2.0b5"
9
+ version = "4.2.0b6"
10
10
  base_url = "ipfabric"
11
11
  min_version = "4.2.4"
12
12
 
ipfabric_netbox/forms.py CHANGED
@@ -493,6 +493,12 @@ class IPFabricSyncForm(NetBoxModelForm):
493
493
  ),
494
494
  )
495
495
 
496
+ update_custom_fields = forms.BooleanField(
497
+ required=False,
498
+ label=_("Custom Fields Updating"),
499
+ help_text=_("Update object custom fields where applicable."),
500
+ )
501
+
496
502
  scheduled = forms.DateTimeField(
497
503
  required=False,
498
504
  widget=DateTimePicker(),
@@ -519,6 +525,7 @@ class IPFabricSyncForm(NetBoxModelForm):
519
525
  "source",
520
526
  "snapshot_data",
521
527
  "auto_merge",
528
+ "update_custom_fields",
522
529
  "sites",
523
530
  "type",
524
531
  "tags",
@@ -550,7 +557,9 @@ class IPFabricSyncForm(NetBoxModelForm):
550
557
  fieldsets.append(
551
558
  FieldSet("scheduled", "interval", name=_("Ingestion Execution Parameters"))
552
559
  )
553
- fieldsets.append(FieldSet("auto_merge", name=_("Extras")))
560
+ fieldsets.append(
561
+ FieldSet("auto_merge", "update_custom_fields", name=_("Extras"))
562
+ )
554
563
  fieldsets.append(FieldSet("tags", name=_("Tags")))
555
564
 
556
565
  return fieldsets
@@ -0,0 +1,17 @@
1
+ # Generated by Django 5.2.5 on 2025-08-22 12:32
2
+ from django.db import migrations
3
+ from django.db import models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+ dependencies = [
8
+ ("ipfabric_netbox", "0016_tags_and_changelog_for_snapshots"),
9
+ ]
10
+
11
+ operations = [
12
+ migrations.AddField(
13
+ model_name="ipfabricsync",
14
+ name="update_custom_fields",
15
+ field=models.BooleanField(default=True),
16
+ ),
17
+ ]
ipfabric_netbox/models.py CHANGED
@@ -611,6 +611,7 @@ class IPFabricSync(IPFabricClient, JobsMixin, TagsMixin, ChangeLoggedModel):
611
611
  )
612
612
  parameters = models.JSONField(blank=True, null=True)
613
613
  auto_merge = models.BooleanField(default=False)
614
+ update_custom_fields = models.BooleanField(default=True)
614
615
  last_synced = models.DateTimeField(blank=True, null=True, editable=False)
615
616
  scheduled = models.DateTimeField(null=True, blank=True)
616
617
  interval = models.PositiveIntegerField(
@@ -8,6 +8,7 @@ from django.test import TestCase
8
8
  from django.utils import timezone
9
9
 
10
10
  from ipfabric_netbox.choices import IPFabricSnapshotStatusModelChoices
11
+ from ipfabric_netbox.models import IPFabricIngestion
11
12
  from ipfabric_netbox.models import IPFabricSnapshot
12
13
  from ipfabric_netbox.models import IPFabricSource
13
14
  from ipfabric_netbox.models import IPFabricSync
@@ -121,6 +122,7 @@ class IPFabricTransformMapModelTestCase(TestCase):
121
122
  type="dcim",
122
123
  status="new",
123
124
  snapshot_data=snapshot,
125
+ update_custom_fields=True,
124
126
  parameters={
125
127
  "vrf": False,
126
128
  "site": True,
@@ -138,6 +140,8 @@ class IPFabricTransformMapModelTestCase(TestCase):
138
140
  },
139
141
  )
140
142
 
143
+ ingestion = IPFabricIngestion.objects.create(sync=sync)
144
+
141
145
  runner = IPFabricSyncRunner(
142
146
  settings={
143
147
  "site": True,
@@ -152,7 +156,11 @@ class IPFabricTransformMapModelTestCase(TestCase):
152
156
  "snapshot_id": "12dd8c61-129c-431a-b98b-4c9211571f89",
153
157
  },
154
158
  sync=sync,
159
+ ingestion=ingestion,
155
160
  )
161
+ # Need to monkeypatch since we are not in active Branch (different schema)
162
+ # Using default schema "default" here since we are in "test_netbox" DB
163
+ runner.get_db_connection_name = lambda: "default"
156
164
 
157
165
  site_data = {
158
166
  "siteName": "MPLS",
@@ -166,7 +174,9 @@ class IPFabricTransformMapModelTestCase(TestCase):
166
174
  "networksCount": 6,
167
175
  }
168
176
 
169
- self.site = runner.get_model_or_update("dcim", "site", site_data)
177
+ self.site = runner.sync_item(
178
+ item=site_data, app_label="dcim", model="site", cf=sync.update_custom_fields
179
+ )
170
180
 
171
181
  device_data = {
172
182
  "id": "961251111",
@@ -204,14 +214,36 @@ class IPFabricTransformMapModelTestCase(TestCase):
204
214
  "slug": None,
205
215
  }
206
216
 
207
- self.mf_obj = runner.get_model_or_update("dcim", "manufacturer", device_data)
208
- self.dt_obj = runner.get_model_or_update("dcim", "devicetype", device_data)
209
-
210
- self.platform = runner.get_model_or_update("dcim", "platform", device_data)
211
-
212
- self.role = runner.get_model_or_update("dcim", "devicerole", device_data)
213
-
214
- self.device_object = runner.get_model_or_update("dcim", "device", device_data)
217
+ self.mf_obj = runner.sync_item(
218
+ item=device_data,
219
+ app_label="dcim",
220
+ model="manufacturer",
221
+ cf=sync.update_custom_fields,
222
+ )
223
+ self.dt_obj = runner.sync_item(
224
+ item=device_data,
225
+ app_label="dcim",
226
+ model="devicetype",
227
+ cf=sync.update_custom_fields,
228
+ )
229
+ self.platform = runner.sync_item(
230
+ item=device_data,
231
+ app_label="dcim",
232
+ model="platform",
233
+ cf=sync.update_custom_fields,
234
+ )
235
+ self.role = runner.sync_item(
236
+ item=device_data,
237
+ app_label="dcim",
238
+ model="devicerole",
239
+ cf=sync.update_custom_fields,
240
+ )
241
+ self.device_object = runner.sync_item(
242
+ item=device_data,
243
+ app_label="dcim",
244
+ model="device",
245
+ cf=sync.update_custom_fields,
246
+ )
215
247
 
216
248
  def test_transform_map(self):
217
249
  site_transform_map = IPFabricTransformMap.objects.get(name="Site Transform Map")
@@ -383,5 +415,10 @@ class IPFabricTransformMapModelTestCase(TestCase):
383
415
  )
384
416
  transform_field.template = "{{ object.hostname }} - test"
385
417
  transform_field.save()
386
- device_object = runner.get_model_or_update("dcim", "device", device_data)
418
+ device_object = runner.sync_item(
419
+ item=device_data,
420
+ app_label="dcim",
421
+ model="device",
422
+ cf=sync.update_custom_fields,
423
+ )
387
424
  self.assertEqual(device_object.name, "L21PE152 - test")
@@ -589,6 +589,35 @@ class IPFabricSyncRunner(object):
589
589
 
590
590
  return instance
591
591
 
592
+ def sync_item(
593
+ self,
594
+ item,
595
+ app_label: str,
596
+ model: str,
597
+ cf: bool = False,
598
+ ingestion: "IPFabricIngestion" = None,
599
+ ) -> ModelTypeVar | None:
600
+ """Sync a single item to NetBox."""
601
+ synced_object = self.sync_model(
602
+ app_label=app_label,
603
+ model=model,
604
+ data=item,
605
+ sync=self.settings.get(model),
606
+ )
607
+ if synced_object is None:
608
+ return None
609
+
610
+ if cf:
611
+ synced_object.snapshot()
612
+ synced_object.custom_field_data[
613
+ "ipfabric_source"
614
+ ] = self.sync.snapshot_data.source.pk
615
+ if ingestion:
616
+ synced_object.custom_field_data["ipfabric_ingestion"] = ingestion.pk
617
+ synced_object.save()
618
+
619
+ return synced_object
620
+
592
621
  def sync_items(
593
622
  self,
594
623
  items,
@@ -605,23 +634,7 @@ class IPFabricSyncRunner(object):
605
634
  return
606
635
 
607
636
  for item in items:
608
- synced_object = self.sync_model(
609
- app_label=app_label,
610
- model=model,
611
- data=item,
612
- sync=self.settings.get(model),
613
- )
614
- if synced_object is None:
615
- continue
616
-
617
- if cf:
618
- synced_object.snapshot()
619
- synced_object.custom_field_data[
620
- "ipfabric_source"
621
- ] = self.sync.snapshot_data.source.pk
622
- if ingestion:
623
- synced_object.custom_field_data["ipfabric_ingestion"] = ingestion.pk
624
- synced_object.save()
637
+ self.sync_item(item, app_label, model, cf, ingestion)
625
638
 
626
639
  @handle_errors
627
640
  def sync_devices(
@@ -684,11 +697,14 @@ class IPFabricSyncRunner(object):
684
697
 
685
698
  if device_object and self.settings.get("device"):
686
699
  device_object.snapshot()
687
- device_object.custom_field_data[
688
- "ipfabric_source"
689
- ] = self.sync.snapshot_data.source.pk
690
- if ingestion:
691
- device_object.custom_field_data["ipfabric_ingestion"] = ingestion.pk
700
+ if self.sync.update_custom_fields:
701
+ device_object.custom_field_data[
702
+ "ipfabric_source"
703
+ ] = self.sync.snapshot_data.source.pk
704
+ if ingestion:
705
+ device_object.custom_field_data[
706
+ "ipfabric_ingestion"
707
+ ] = ingestion.pk
692
708
  device_object.save()
693
709
 
694
710
  self.logger.increment_statistics(model="device")
@@ -829,7 +845,11 @@ class IPFabricSyncRunner(object):
829
845
  ) = self.collect_data()
830
846
 
831
847
  self.sync_items(
832
- app_label="dcim", model="site", items=sites, cf=True, ingestion=ingestion
848
+ app_label="dcim",
849
+ model="site",
850
+ items=sites,
851
+ cf=self.sync.update_custom_fields,
852
+ ingestion=ingestion,
833
853
  )
834
854
  self.sync_devices(
835
855
  ingestion,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: ipfabric_netbox
3
- Version: 4.2.0b5
3
+ Version: 4.2.0b6
4
4
  Summary: NetBox plugin to sync IP Fabric data into NetBox
5
5
  License: MIT
6
6
  Keywords: netbox,ipfabric,plugin,sync
@@ -1,4 +1,4 @@
1
- ipfabric_netbox/__init__.py,sha256=OFgZPAmWWR0o_36-A9EqYoMQpPdN9rgXRP8PVW7VAPA,674
1
+ ipfabric_netbox/__init__.py,sha256=E5BKH5-wfz4YUPlNookiC6kVSmlN7ZR5mc7rN9YeHCY,674
2
2
  ipfabric_netbox/api/__init__.py,sha256=XRclTGWVR0ZhAAwgYul5Wm_loug5_hUjEumbLQEwKYM,47
3
3
  ipfabric_netbox/api/serializers.py,sha256=RV1tmkbRF_Est3x1w_bfk63qwgEQc97Bm4mk89tv2FU,6502
4
4
  ipfabric_netbox/api/urls.py,sha256=1fXXVTxNY5E64Nfz6b7zXD9bZI3FcefuxAWKMe0w_QU,1240
@@ -7,7 +7,7 @@ ipfabric_netbox/choices.py,sha256=tQ5RHwmuArQ7dCLcE3A_Bnw2ctGHgw67z--AawyyPPg,52
7
7
  ipfabric_netbox/data/transform_map.json,sha256=4PsucgMHcLW3SPoKEptQCd0gA5tCF4hjrR4bGQFCWy8,21744
8
8
  ipfabric_netbox/exceptions.py,sha256=DT4dpbakvqoROtBR_F0LzvQCMNWpGhufFcUbZTx0OLY,2655
9
9
  ipfabric_netbox/filtersets.py,sha256=FrlHkLWf_mNMTaT_Zm2wl1wYkHXMX7hXxMLYAkC6_Gg,7922
10
- ipfabric_netbox/forms.py,sha256=07p_vngzsnHG0aev83JqBhb8fSBts0w-MTKu4BuoNLw,44494
10
+ ipfabric_netbox/forms.py,sha256=PLAoSJGqwHWPVO5F8Sf2iJv-L5xjYzv-wseiasaxdlg,44767
11
11
  ipfabric_netbox/graphql/__init__.py,sha256=-a5w_VY7pc-RVt8MvThkTzeAqCC3xCan4Ue6iMefmjI,754
12
12
  ipfabric_netbox/graphql/enums.py,sha256=4jtB2gKsmPXu9is5jd38hUbfrt1V5Wm1Ff-2JCDI3EU,1518
13
13
  ipfabric_netbox/graphql/filters.py,sha256=NGIxHIQhmya-aEsgzQgkRjwMxV1jaGOPxLzRzlrJPPg,12587
@@ -31,8 +31,9 @@ ipfabric_netbox/migrations/0013_switch_to_branching_plugin.py,sha256=JfdTNerjuFy
31
31
  ipfabric_netbox/migrations/0014_ipfabrictransformmapgroup_ipfabrictransformmap_group.py,sha256=RCfgKyqQhTkfSPhf0IukI3fjeAEBUs5pKWIpsLxgzp0,2272
32
32
  ipfabric_netbox/migrations/0015_ipfabricingestionissue.py,sha256=AjAkyboa4BSXsN53BqzO1k_U6QHu4rlA2IhzhubocJw,1732
33
33
  ipfabric_netbox/migrations/0016_tags_and_changelog_for_snapshots.py,sha256=XqftTQ4GFnoCoGSHPa2WL_bjSVCGxdP2MFXCUa6LN1k,929
34
+ ipfabric_netbox/migrations/0017_ipfabricsync_update_custom_fields.py,sha256=IVbAL2WdigYT40sXN0A8K3HweJ_O4QqyzjB06TbkG5E,447
34
35
  ipfabric_netbox/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
- ipfabric_netbox/models.py,sha256=qvpeoufUHznDe8M4Zf-VDtqQlFPOFYtl3EFAKjRrclI,36107
36
+ ipfabric_netbox/models.py,sha256=U9_ooh8juhtXwwcj0ay_6KZ-FlBt2SYrR7YCScAYa9k,36168
36
37
  ipfabric_netbox/navigation.py,sha256=2dEJ_wKHb52Tl0FOV1TH3JbxRe8YZ56ewrTsBFGKpCg,2210
37
38
  ipfabric_netbox/signals.py,sha256=cGa5PVD2i24pGXiVNfbu6ruIDqPVdwKQHTSWe9Ura84,1838
38
39
  ipfabric_netbox/tables.py,sha256=pHKv6Bosjnc-7aApak3nLhzxqBiA30olPdaMO8F1PQg,8262
@@ -70,14 +71,14 @@ ipfabric_netbox/templatetags/ipfabric_netbox_helpers.py,sha256=STw4pAd2qG7hgf-O6
70
71
  ipfabric_netbox/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
71
72
  ipfabric_netbox/tests/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
72
73
  ipfabric_netbox/tests/api/test_api.py,sha256=DVMnhtleWJdpmVHafqCh9fgN6PZhWMEBXBL_rfm3ly8,30615
73
- ipfabric_netbox/tests/test_models.py,sha256=4SGMX0LZ_fThkc-F1AMZIQbpmJvQNVFnS6QYZpIZkNA,14998
74
+ ipfabric_netbox/tests/test_models.py,sha256=rPwdVs127vU78yOcmlC44f7dZw12oLVzTSJf1nH0jus,16068
74
75
  ipfabric_netbox/urls.py,sha256=ok66LP09rYi01qJmwdGGlBzV9wrGWVwVAIngPcreJxg,5449
75
76
  ipfabric_netbox/utilities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
76
- ipfabric_netbox/utilities/ipfutils.py,sha256=4W6fYuguvVdhNlWok-dTUhI0M4CK7hrBiMcLAtPuKIQ,31411
77
+ ipfabric_netbox/utilities/ipfutils.py,sha256=wFmL5oriuF-is1ZlrIcLmoeYUY5ih-CA9weRQrx5AiA,31885
77
78
  ipfabric_netbox/utilities/logging.py,sha256=GYknjocMN6LQ2873_az3y0RKm29TCXaWviUIIneH-x0,3445
78
79
  ipfabric_netbox/utilities/nbutils.py,sha256=kFBEiJOGvr_49hJWCS2duXojx2-A9kVk0Xp_vj0ohfs,2641
79
80
  ipfabric_netbox/utilities/transform_map.py,sha256=QotbGc2TksINJrb62STgAigpC5Nsgi5umYHu_0rZd8k,2204
80
81
  ipfabric_netbox/views.py,sha256=nGWO-PlTyKviBzGEdmE3C_1I-xFjZMldqOWGx12wdbg,36855
81
- ipfabric_netbox-4.2.0b5.dist-info/METADATA,sha256=A8aUgRhs6Z7yZtjdw8l83gbxistnKYeqTrIXkiejA-E,4638
82
- ipfabric_netbox-4.2.0b5.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
83
- ipfabric_netbox-4.2.0b5.dist-info/RECORD,,
82
+ ipfabric_netbox-4.2.0b6.dist-info/METADATA,sha256=UKZI463uPse64h8bR0yCQQvkYUbqTuWwZlDMtG5fpFY,4638
83
+ ipfabric_netbox-4.2.0b6.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
84
+ ipfabric_netbox-4.2.0b6.dist-info/RECORD,,