ipfabric_netbox 3.1.2__py3-none-any.whl → 3.2.0__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.
@@ -212,6 +212,18 @@ class IPFabricSyncRunner(object):
212
212
  device_object.primary_ip4 = ip_address_obj
213
213
  device_object.save()
214
214
 
215
+ if self.settings.get("macaddress") and device_interface.get("mac"):
216
+ # Need to create MAC Address object before we can assign it to Interface
217
+ macaddress_data = {
218
+ "mac": device_interface.get("mac"),
219
+ "id": interface_object.id,
220
+ }
221
+ macaddress_object = self.get_model_or_update(
222
+ "dcim", "macaddress", macaddress_data, uuid=device_uuid
223
+ )
224
+ interface_object.primary_mac_address = macaddress_object
225
+ interface_object.save()
226
+
215
227
  return True
216
228
 
217
229
  def collect_data(self):
@@ -1,35 +1,57 @@
1
- from django.contrib.contenttypes.models import ContentType
1
+ import importlib.resources
2
+ import json
2
3
 
3
- from ipfabric_netbox.models import IPFabricRelationshipField
4
- from ipfabric_netbox.models import IPFabricTransformField
5
- from ipfabric_netbox.models import IPFabricTransformMap
4
+ from django.apps import apps
6
5
 
6
+ # These functions are used in the migration file to prepare the transform maps
7
+ # Because of this we have to use historical models
8
+ # see https://docs.djangoproject.com/en/5.1/topics/migrations/#historical-models
7
9
 
8
- def BuildField(data):
10
+
11
+ def build_fields(data):
12
+ ContentType = apps.get_model("contenttypes", "ContentType")
9
13
  if "target_model" in data:
10
- ct = ContentType.objects.get(
11
- app_label=data["target_model"]["app_label"],
12
- model=data["target_model"]["model"],
14
+ ct = ContentType.objects.get_for_model(
15
+ apps.get_model(
16
+ data["target_model"]["app_label"],
17
+ data["target_model"]["model"],
18
+ )
13
19
  )
14
20
  data["target_model"] = ct
15
21
  elif "source_model" in data:
16
- ct = ContentType.objects.get(
17
- app_label=data["source_model"]["app_label"],
18
- model=data["source_model"]["model"],
22
+ ct = ContentType.objects.get_for_model(
23
+ apps.get_model(
24
+ data["source_model"]["app_label"],
25
+ data["source_model"]["model"],
26
+ )
19
27
  )
20
28
  data["source_model"] = ct
21
29
  return data
22
30
 
23
31
 
24
- def BuildTransformMaps(data):
32
+ def build_transform_maps(data):
33
+ IPFabricTransformMap = apps.get_model("ipfabric_netbox", "IPFabricTransformMap")
34
+ IPFabricTransformField = apps.get_model("ipfabric_netbox", "IPFabricTransformField")
35
+ IPFabricRelationshipField = apps.get_model(
36
+ "ipfabric_netbox", "IPFabricRelationshipField"
37
+ )
25
38
  for tm in data:
26
- field_data = BuildField(tm["data"])
39
+ field_data = build_fields(tm["data"])
27
40
  tm_obj = IPFabricTransformMap.objects.create(**field_data)
28
41
  for fm in tm["field_maps"]:
29
- field_data = BuildField(fm)
42
+ field_data = build_fields(fm)
30
43
  IPFabricTransformField.objects.create(transform_map=tm_obj, **field_data)
31
44
  for rm in tm["relationship_maps"]:
32
- relationship_data = BuildField(rm)
45
+ relationship_data = build_fields(rm)
33
46
  IPFabricRelationshipField.objects.create(
34
47
  transform_map=tm_obj, **relationship_data
35
48
  )
49
+
50
+
51
+ def get_transform_map() -> dict:
52
+ for data_file in importlib.resources.files("ipfabric_netbox.data").iterdir():
53
+ if data_file.name != "transform_map.json":
54
+ continue
55
+ with open(data_file, "rb") as data_file:
56
+ return json.load(data_file)
57
+ raise FileNotFoundError("'transform_map.json' not found in installed package")
ipfabric_netbox/views.py CHANGED
@@ -1,4 +1,3 @@
1
- import requests
2
1
  from dcim.models import Device
3
2
  from dcim.models import Site
4
3
  from django.contrib import messages
@@ -60,7 +59,8 @@ from .tables import IPFabricTransformFieldTable
60
59
  from .tables import IPFabricTransformMapTable
61
60
  from .tables import StagedChangesTable
62
61
  from .utilities.ipfutils import IPFabric
63
- from .utilities.transform_map import BuildTransformMaps
62
+ from .utilities.transform_map import build_transform_maps
63
+ from .utilities.transform_map import get_transform_map
64
64
 
65
65
 
66
66
  # Transform Map Relationship Field
@@ -140,13 +140,7 @@ class IPFabricTransformMapRestoreView(generic.ObjectListView):
140
140
 
141
141
  def post(self, request):
142
142
  IPFabricTransformMap.objects.all().delete()
143
- try:
144
- data = requests.get(
145
- "https://gitlab.com/ip-fabric/integrations/ipfabric-netbox/-/raw/main/scripts/transform_map.json"
146
- ).json()
147
- except Exception as e:
148
- messages.error(request, e)
149
- BuildTransformMaps(data=data)
143
+ build_transform_maps(data=get_transform_map())
150
144
  return redirect("plugins:ipfabric_netbox:ipfabrictransformmap_list")
151
145
 
152
146
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ipfabric_netbox
3
- Version: 3.1.2
3
+ Version: 3.2.0
4
4
  Summary: NetBox plugin to sync IP Fabric data into NetBox
5
5
  Home-page: https://gitlab.com/ip-fabric/integrations/ipfabric-netbox-sync
6
6
  License: MIT
@@ -15,7 +15,19 @@ Classifier: Programming Language :: Python :: 3.10
15
15
  Classifier: Programming Language :: Python :: 3.11
16
16
  Classifier: Programming Language :: Python :: 3.12
17
17
  Classifier: Programming Language :: Python :: 3.13
18
- Requires-Dist: ipfabric (>=6.6.4)
18
+ Provides-Extra: ipfabric-6-10
19
+ Provides-Extra: ipfabric-6-6
20
+ Provides-Extra: ipfabric-6-7
21
+ Provides-Extra: ipfabric-6-8
22
+ Provides-Extra: ipfabric-6-9
23
+ Provides-Extra: ipfabric-7-0
24
+ Requires-Dist: ipfabric (>=6.10.0,<6.11.0) ; extra != "ipfabric_6_6" and extra != "ipfabric_6_7" and extra != "ipfabric_6_8" and extra != "ipfabric_6_9" and extra == "ipfabric_6_10" and extra != "ipfabric_7_0"
25
+ Requires-Dist: ipfabric (>=6.6.0,<6.7.0) ; extra == "ipfabric_6_6" and extra != "ipfabric_6_7" and extra != "ipfabric_6_8" and extra != "ipfabric_6_9" and extra != "ipfabric_6_10" and extra != "ipfabric_7_0"
26
+ Requires-Dist: ipfabric (>=6.6.4) ; extra != "ipfabric_6_6" and extra != "ipfabric_6_7" and extra != "ipfabric_6_8" and extra != "ipfabric_6_9" and extra != "ipfabric_6_10" and extra != "ipfabric_7_0"
27
+ Requires-Dist: ipfabric (>=6.7.0,<6.8.0) ; extra != "ipfabric_6_6" and extra == "ipfabric_6_7" and extra != "ipfabric_6_8" and extra != "ipfabric_6_9" and extra != "ipfabric_6_10" and extra != "ipfabric_7_0"
28
+ Requires-Dist: ipfabric (>=6.8.0,<6.9.0) ; extra != "ipfabric_6_6" and extra != "ipfabric_6_7" and extra == "ipfabric_6_8" and extra != "ipfabric_6_9" and extra != "ipfabric_6_10" and extra != "ipfabric_7_0"
29
+ Requires-Dist: ipfabric (>=6.9.0,<6.10.0) ; extra != "ipfabric_6_6" and extra != "ipfabric_6_7" and extra != "ipfabric_6_8" and extra == "ipfabric_6_9" and extra != "ipfabric_6_10" and extra != "ipfabric_7_0"
30
+ Requires-Dist: ipfabric (>=7.0.0,<7.1.0) ; extra != "ipfabric_6_6" and extra != "ipfabric_6_7" and extra != "ipfabric_6_8" and extra != "ipfabric_6_9" and extra != "ipfabric_6_10" and extra == "ipfabric_7_0"
19
31
  Requires-Dist: netutils
20
32
  Project-URL: Bug Tracker, https://gitlab.com/ip-fabric/integrations/ipfabric-netbox-sync/-/issues
21
33
  Project-URL: Repository, https://gitlab.com/ip-fabric/integrations/ipfabric-netbox-sync
@@ -51,9 +63,10 @@ The plugin uses IP Fabric collect network data utilizing the [IP Fabric Python S
51
63
  - Diff Visualization
52
64
 
53
65
  ## NetBox Compatibility
66
+ These are the minimum NetBox versions for corresponding plugin version. Following minor versions should work too, but they are not tested.
54
67
 
55
68
  | Netbox Version | Plugin Version |
56
- | -------------- | -------------- |
69
+ |----------------|----------------|
57
70
  | 3.4 | <=1.0.11 |
58
71
  | 3.5 | <=1.0.11 |
59
72
  | 3.6 | <=1.0.11 |
@@ -62,6 +75,7 @@ The plugin uses IP Fabric collect network data utilizing the [IP Fabric Python S
62
75
  | 4.0.1 | >=3.0.1 |
63
76
  | 4.1.0 | >=3.1.0 |
64
77
  | 4.1.5 | >=3.1.1 |
78
+ | 4.2.0 | >=3.2.0 |
65
79
 
66
80
  ## Screenshots
67
81
 
@@ -1,12 +1,13 @@
1
- ipfabric_netbox/__init__.py,sha256=m4Z0tjRjIxp2-rpnhOKtfKrGz-2a1oqLIYAlkdc8hk4,1492
1
+ ipfabric_netbox/__init__.py,sha256=48sc1aEKyahTfjM_KcYMhHLxFuY_VW66OX3BohC5Tgk,313
2
2
  ipfabric_netbox/api/__init__.py,sha256=DOkvDAI4BoNgdCiNxfseeExEHyOrK8weG-LvjPRyK8A,101
3
3
  ipfabric_netbox/api/nested_serializers.py,sha256=JwIlFpOHeiMB7F-sC0gx1f6qdNevS8NsXTUEHlVZeRs,2719
4
4
  ipfabric_netbox/api/serializers.py,sha256=bTR3AJ81Q8HZI3iWLPc1tndGqD0erAbAD9hKLI4DTYY,4341
5
5
  ipfabric_netbox/api/urls.py,sha256=BSQ5nqYSx0r-wnbdKGDAb5XH7BBy_0ngV_Q7vDgjMIE,948
6
6
  ipfabric_netbox/api/views.py,sha256=X02GwpDlq25_3KlxYTWyd4PnT1RCtfp7uN0zZ5Etjp8,4429
7
7
  ipfabric_netbox/choices.py,sha256=GqcnLqsFR4gnhWEwkvQbPxXYNi5SwNoIQz-J15LTMc4,4848
8
+ ipfabric_netbox/data/transform_map.json,sha256=ghZjQhnYEF-udOGwGUA830MKv8cNMNZGp8HJ1-uBBYs,20337
8
9
  ipfabric_netbox/filtersets.py,sha256=P_2VCL892pLplPnsxul27bgGgMpHaZtgn9Vg0UsWErE,3877
9
- ipfabric_netbox/forms.py,sha256=Y-ISAtlQPjP5qYozAMZxsUCmGPmq8GhV5_ppf5Tu464,43096
10
+ ipfabric_netbox/forms.py,sha256=to04ZwPX2tewEp43zzp2P57i1m5-fUizLvuk6f3hbHk,42938
10
11
  ipfabric_netbox/jobs.py,sha256=jfWWNA42KMyzc-EGit6LJIe-SNob4-4IQRfadQF_GRE,2862
11
12
  ipfabric_netbox/migrations/0001_initial.py,sha256=nka6_HJK4Q8BlmQblDntuNzVKLR484SsC6wGSbOQgI4,13813
12
13
  ipfabric_netbox/migrations/0002_ipfabricsnapshot_status.py,sha256=xQpouHjOutyj6riN2B592njzSvz_icpkUbo5W7nWLYw,431
@@ -14,11 +15,13 @@ ipfabric_netbox/migrations/0003_ipfabricsource_type_and_more.py,sha256=XUM_ZecLl
14
15
  ipfabric_netbox/migrations/0004_ipfabricsync_auto_merge.py,sha256=hlwHGKD7q3w1a1N04yIS39f6nsL_9TJCWEJlvwCdpPA,435
15
16
  ipfabric_netbox/migrations/0005_alter_ipfabricrelationshipfield_source_model_and_more.py,sha256=egiUtdu1zHElbcIIN9sUzS93dSCltVXFv0DG9IUp1HY,2802
16
17
  ipfabric_netbox/migrations/0006_alter_ipfabrictransformmap_target_model.py,sha256=6MmI-Uz9hmzj3nKqhUKdShjLnE8KNa4qthg0NVHjANc,2163
18
+ ipfabric_netbox/migrations/0007_prepare_custom_fields.py,sha256=ohnNcbQn4CMkbh3XHtvmkctThUdYhN-ywN5xerOSmdE,3898
19
+ ipfabric_netbox/migrations/0008_prepare_transform_maps.py,sha256=Jwr-P9MQQv9N-Yx_19V4q6lmZpeIkjoUW1gh4s-lDnI,1541
20
+ ipfabric_netbox/migrations/0009_transformmap_changes_for_netbox_v4_2.py,sha256=P_ZojUapQ8x2XIe3ovZO0xUnRCXyl7WYzKeDvhQVctI,9341
17
21
  ipfabric_netbox/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
- ipfabric_netbox/models.py,sha256=Io0JD9dqAS4mkkj93yJyn9pD1nMkhmJ5IVKkLpHjDxo,30562
22
+ ipfabric_netbox/models.py,sha256=e32q25kxi4ICX2ITFp9lPUfRwXw1NMui1OW_HJCUBzE,30819
19
23
  ipfabric_netbox/navigation.py,sha256=2kZs341nAB7G76qnZT6mFxsYo68IPy-bmPMkSLA-Nk0,1735
20
- ipfabric_netbox/signals.py,sha256=GM2D_8zHfe3MzyNoe6v4Tq5ibPrbqhfEKYPhxtyrYwc,2588
21
- ipfabric_netbox/tables.py,sha256=w4YaFeYoAm4Pq5nKmD0MUbH7Mv-q86waQHyY-eL-hd8,6613
24
+ ipfabric_netbox/tables.py,sha256=4cZb-_whp132B3EJglRBEkXwkYLUpWzIybkdHfAE9tM,6819
22
25
  ipfabric_netbox/template_content.py,sha256=bP2nUf5MM-GUbtQxJ8QoYVNXhrDCrkb8wZnbeqa07EA,315
23
26
  ipfabric_netbox/templates/ipfabric_netbox/inc/diff.html,sha256=xOiIrvRIBtqDD65u6xcLo2xdwDKNpAylDmzznaJRGCw,3281
24
27
  ipfabric_netbox/templates/ipfabric_netbox/inc/json.html,sha256=qPHUdaHyKM9Y7FqBEnYwcNoyp5GMFaexJFXMRf4AqZQ,569
@@ -46,14 +49,14 @@ ipfabric_netbox/templates/ipfabric_netbox/partials/sync_last_branch.html,sha256=
46
49
  ipfabric_netbox/templates/ipfabric_netbox/sync_list.html,sha256=3wfwPUIAfzzIP_pu3gL0L3wH65UX5XFLBW5BW-CZJDc,5587
47
50
  ipfabric_netbox/templates/static/ipfabric_netbox/css/rack.css,sha256=z1H-RmmsqF2pGdhn5J64TMFiccy62xZUHHlCRd8fJrQ,118
48
51
  ipfabric_netbox/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
- ipfabric_netbox/tests/test_models.py,sha256=r1TTKuzQYaBbDjw0PzSKFe7V3IRFxiYRsqToEP52XNg,45898
52
+ ipfabric_netbox/tests/test_models.py,sha256=jnu2abpuKtxUNNAJJjJxMUdRQ8dK8dTKor3j_IcMx1Q,15513
50
53
  ipfabric_netbox/urls.py,sha256=V98K_JxHaJAgDbo-DiMj-5FQIIposLMLJCPw3dtREWU,4430
51
54
  ipfabric_netbox/utilities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
- ipfabric_netbox/utilities/ipfutils.py,sha256=iupSEk5xNJOhK_-bJZNqZRc2damrcVSpM_i5zn7npJQ,21987
55
+ ipfabric_netbox/utilities/ipfutils.py,sha256=c4yRzZds1c9TsQ8t7Hpsw0kkIh6bzDec2lStSWzjyk4,22539
53
56
  ipfabric_netbox/utilities/logging.py,sha256=2OpWlqZ6Va2LEVXmIjiCvdZ8Ncx6brCvm_PzhjbMoTU,3221
54
57
  ipfabric_netbox/utilities/nbutils.py,sha256=W-aorJjeIBYB80MAHmd1gpmhaZKH7R8lwIuCCbWWjh8,3117
55
- ipfabric_netbox/utilities/transform_map.py,sha256=I24MI0kmnPm6PeSn-Bmzf5hJQNpJRRTtPLC0R7_s62A,1256
56
- ipfabric_netbox/views.py,sha256=yS8BqrVOOiODuH72JMF5lK1SVAkJ7sfSLvzVGIXy8Bk,28478
57
- ipfabric_netbox-3.1.2.dist-info/METADATA,sha256=vsrIfygCVpXTTKkBFRNZcFOeHtw2Gw51_CI3se99xPw,3573
58
- ipfabric_netbox-3.1.2.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
59
- ipfabric_netbox-3.1.2.dist-info/RECORD,,
58
+ ipfabric_netbox/utilities/transform_map.py,sha256=g0elxtwSRJvu0ZRZHyMf4Y9R4wiQ-h2o9Er8gxUQ-Bs,2108
59
+ ipfabric_netbox/views.py,sha256=K2iKh6i8kv88c7gVh6wW7d8Adcso24ZE8m6gVUiNZSw,28285
60
+ ipfabric_netbox-3.2.0.dist-info/METADATA,sha256=S5q0v54rMCBkIkEZKDaZkK1t6UDZCup5lBdHnMErAtA,5341
61
+ ipfabric_netbox-3.2.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
62
+ ipfabric_netbox-3.2.0.dist-info/RECORD,,
@@ -1,68 +0,0 @@
1
- from typing import Optional
2
-
3
- from core.models import ObjectType
4
- from dcim.models import Device
5
- from dcim.models import Site
6
- from extras.choices import CustomFieldTypeChoices
7
- from extras.choices import CustomFieldUIEditableChoices
8
- from extras.choices import CustomFieldUIVisibleChoices
9
- from extras.choices import CustomLinkButtonClassChoices
10
- from extras.models import CustomField
11
- from extras.models import CustomLink
12
-
13
- from .models import IPFabricBranch
14
- from .models import IPFabricSource
15
-
16
-
17
- def create_custom_field(
18
- field_name: str,
19
- label: str,
20
- models: list,
21
- object_type=None,
22
- cf_type: Optional[str] = "type_text",
23
- ui_visibility: Optional[str] = "VISIBILITY_READ_ONLY",
24
- ):
25
- defaults = {
26
- "label": label,
27
- "related_object_type": ObjectType.objects.get_for_model(object_type)
28
- if object_type
29
- else None,
30
- "ui_visible": getattr(CustomFieldUIVisibleChoices, "ALWAYS"),
31
- "ui_editable": getattr(CustomFieldUIEditableChoices, "NO"),
32
- }
33
-
34
- custom_field, _ = CustomField.objects.update_or_create(
35
- type=getattr(CustomFieldTypeChoices, cf_type.upper()),
36
- name=field_name,
37
- defaults=defaults,
38
- )
39
-
40
- for model in models:
41
- custom_field.object_types.add(ObjectType.objects.get_for_model(model))
42
-
43
-
44
- def ipfabric_netbox_init():
45
- create_custom_field(
46
- "ipfabric_source",
47
- "IP Fabric Source",
48
- [Device, Site],
49
- cf_type="type_object",
50
- object_type=IPFabricSource,
51
- )
52
- create_custom_field(
53
- "ipfabric_branch",
54
- "IP Fabric Last Sync",
55
- [Device, Site],
56
- cf_type="type_object",
57
- object_type=IPFabricBranch,
58
- )
59
- cl, _ = CustomLink.objects.update_or_create(
60
- defaults={
61
- "link_text": "{% if object.custom_field_data.ipfabric_source is defined %}{% set SOURCE_ID = object.custom_field_data.ipfabric_source %}{% if SOURCE_ID %}IP Fabric{% endif %}{% endif %}",
62
- "link_url": '{% if object.custom_field_data.ipfabric_source is defined %}{% set SOURCE_ID = object.custom_field_data.ipfabric_source %}{% if SOURCE_ID %}{% set BASE_URL = object.custom_fields.filter(related_object_type__model="ipfabricsource").first().related_object_type.model_class().objects.get(pk=SOURCE_ID).url %}{{ BASE_URL }}/inventory/devices?options={"filters":{"sn": ["like","{{ object.serial }}"]}}{% endif %}{%endif%}',
63
- "new_window": True,
64
- "button_class": CustomLinkButtonClassChoices.BLUE,
65
- },
66
- name="ipfabric",
67
- )
68
- cl.object_types.add(ObjectType.objects.get_for_model(Device))