ipfabric_netbox 3.2.4__py3-none-any.whl → 3.2.4b3__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.
Potentially problematic release.
This version of ipfabric_netbox might be problematic. Click here for more details.
- ipfabric_netbox/__init__.py +1 -1
- ipfabric_netbox/api/nested_serializers.py +0 -20
- ipfabric_netbox/api/serializers.py +7 -13
- ipfabric_netbox/api/urls.py +2 -2
- ipfabric_netbox/api/views.py +5 -5
- ipfabric_netbox/data/transform_map.json +21 -35
- ipfabric_netbox/filtersets.py +15 -13
- ipfabric_netbox/forms.py +14 -42
- ipfabric_netbox/jobs.py +12 -7
- ipfabric_netbox/migrations/0001_initial.py +1 -1
- ipfabric_netbox/migrations/0001_initial_squashed_0013_switch_to_branching_plugin.py +503 -0
- ipfabric_netbox/migrations/0007_prepare_custom_fields.py +3 -3
- ipfabric_netbox/migrations/0011_update_part_number_DCIM_inventory_item_template.py +57 -0
- ipfabric_netbox/migrations/0012_remove_status_field.py +18 -0
- ipfabric_netbox/migrations/0013_switch_to_branching_plugin.py +270 -0
- ipfabric_netbox/models.py +120 -91
- ipfabric_netbox/navigation.py +1 -1
- ipfabric_netbox/signals.py +9 -2
- ipfabric_netbox/tables.py +40 -46
- ipfabric_netbox/templates/ipfabric_netbox/{ipfabricbranch.html → ipfabricingestion.html} +14 -9
- ipfabric_netbox/templates/ipfabric_netbox/ipfabricsource.html +3 -3
- ipfabric_netbox/templates/ipfabric_netbox/ipfabricsync.html +3 -3
- ipfabric_netbox/templates/ipfabric_netbox/ipfabricsync_list.html +71 -0
- ipfabric_netbox/templates/ipfabric_netbox/ipfabrictransformmap.html +0 -4
- ipfabric_netbox/templates/ipfabric_netbox/partials/ingestion_all.html +10 -0
- ipfabric_netbox/templates/ipfabric_netbox/partials/{branch_progress.html → ingestion_progress.html} +1 -1
- ipfabric_netbox/templates/ipfabric_netbox/partials/sync_last_ingestion.html +1 -0
- ipfabric_netbox/urls.py +13 -3
- ipfabric_netbox/utilities/ipfutils.py +52 -19
- ipfabric_netbox/views.py +162 -155
- {ipfabric_netbox-3.2.4.dist-info → ipfabric_netbox-3.2.4b3.dist-info}/METADATA +12 -4
- {ipfabric_netbox-3.2.4.dist-info → ipfabric_netbox-3.2.4b3.dist-info}/RECORD +34 -31
- {ipfabric_netbox-3.2.4.dist-info → ipfabric_netbox-3.2.4b3.dist-info}/WHEEL +1 -1
- ipfabric_netbox/templates/ipfabric_netbox/inc/sync_delete.html +0 -19
- ipfabric_netbox/templates/ipfabric_netbox/partials/branch_all.html +0 -10
- ipfabric_netbox/templates/ipfabric_netbox/partials/sync_last_branch.html +0 -1
- ipfabric_netbox/templates/ipfabric_netbox/sync_list.html +0 -126
- /ipfabric_netbox/templates/ipfabric_netbox/partials/{branch_status.html → ingestion_status.html} +0 -0
|
@@ -0,0 +1,503 @@
|
|
|
1
|
+
# Generated by Django 5.2.1 on 2025-05-19 15:01
|
|
2
|
+
from typing import TYPE_CHECKING
|
|
3
|
+
|
|
4
|
+
import django.core.validators
|
|
5
|
+
import django.db.migrations.operations.special
|
|
6
|
+
import django.db.models.deletion
|
|
7
|
+
import taggit.managers
|
|
8
|
+
import utilities.json
|
|
9
|
+
from django.conf import settings
|
|
10
|
+
from django.db import migrations
|
|
11
|
+
from django.db import models
|
|
12
|
+
from extras.choices import CustomFieldTypeChoices
|
|
13
|
+
from extras.choices import CustomFieldUIEditableChoices
|
|
14
|
+
from extras.choices import CustomFieldUIVisibleChoices
|
|
15
|
+
from extras.choices import CustomLinkButtonClassChoices
|
|
16
|
+
|
|
17
|
+
from ipfabric_netbox.utilities.transform_map import build_transform_maps
|
|
18
|
+
from ipfabric_netbox.utilities.transform_map import get_transform_map
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
from django.apps import apps as apps_type
|
|
22
|
+
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
|
|
23
|
+
|
|
24
|
+
# This is squashed migration since when StagedChanges were removed, NetBox Branch model
|
|
25
|
+
# was moved to netbox branching. But IPFabricBranch was extending it and I had to remove it.
|
|
26
|
+
# We need to avoid creating IPFabricBranch on NetBox >4.3.0 since Branch is not there.
|
|
27
|
+
# So instead the squash does not create it and conditionally removed the table.
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def create_custom_field(
|
|
31
|
+
apps: "apps_type",
|
|
32
|
+
field_name: str,
|
|
33
|
+
label: str,
|
|
34
|
+
target_models: list,
|
|
35
|
+
object_type=None,
|
|
36
|
+
cf_type: str | None = "type_text",
|
|
37
|
+
):
|
|
38
|
+
"""Create a single custom field and link it to required models."""
|
|
39
|
+
ObjectType = apps.get_model("core", "ObjectType")
|
|
40
|
+
|
|
41
|
+
defaults = {
|
|
42
|
+
"label": label,
|
|
43
|
+
"related_object_type": (
|
|
44
|
+
ObjectType.objects.get_for_model(object_type) if object_type else None
|
|
45
|
+
),
|
|
46
|
+
"ui_visible": getattr(CustomFieldUIVisibleChoices, "ALWAYS"),
|
|
47
|
+
"ui_editable": getattr(CustomFieldUIEditableChoices, "NO"),
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
custom_field, _ = apps.get_model("extras", "CustomField").objects.update_or_create(
|
|
51
|
+
type=getattr(CustomFieldTypeChoices, cf_type.upper()),
|
|
52
|
+
name=field_name,
|
|
53
|
+
defaults=defaults,
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
for model in target_models:
|
|
57
|
+
custom_field.object_types.add(ObjectType.objects.get_for_model(model))
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def prepare_custom_fields(apps: "apps_type", schema_editor: "BaseDatabaseSchemaEditor"):
|
|
61
|
+
"""Forward migration to prepare ipfabric_netbox custom fields and links."""
|
|
62
|
+
Device = apps.get_model("dcim", "Device")
|
|
63
|
+
Site = apps.get_model("dcim", "Site")
|
|
64
|
+
|
|
65
|
+
create_custom_field(
|
|
66
|
+
apps,
|
|
67
|
+
"ipfabric_source",
|
|
68
|
+
"IP Fabric Source",
|
|
69
|
+
[Device, Site],
|
|
70
|
+
cf_type="type_object",
|
|
71
|
+
object_type=apps.get_model("ipfabric_netbox", "IPFabricSource"),
|
|
72
|
+
)
|
|
73
|
+
create_custom_field(
|
|
74
|
+
apps,
|
|
75
|
+
"ipfabric_ingestion",
|
|
76
|
+
"IP Fabric Last Ingestion",
|
|
77
|
+
[Device, Site],
|
|
78
|
+
cf_type="type_object",
|
|
79
|
+
object_type=apps.get_model("ipfabric_netbox", "IPFabricIngestion"),
|
|
80
|
+
)
|
|
81
|
+
cl, _ = apps.get_model("extras", "CustomLink").objects.update_or_create(
|
|
82
|
+
defaults={
|
|
83
|
+
"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 %}",
|
|
84
|
+
"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%}',
|
|
85
|
+
"new_window": True,
|
|
86
|
+
"button_class": CustomLinkButtonClassChoices.BLUE,
|
|
87
|
+
},
|
|
88
|
+
name="ipfabric",
|
|
89
|
+
)
|
|
90
|
+
cl.object_types.add(
|
|
91
|
+
apps.get_model("core", "ObjectType").objects.get_for_model(Device)
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def cleanup_custom_fields(apps: "apps_type", schema_editor: "BaseDatabaseSchemaEditor"):
|
|
96
|
+
"""Reverse migration to prepare ipfabric_netbox custom fields and links."""
|
|
97
|
+
for field_name in ["ipfabric_source", "ipfabric_ingestion"]:
|
|
98
|
+
custom_field = apps.get_model("extras", "CustomField").objects.get(
|
|
99
|
+
name=field_name
|
|
100
|
+
)
|
|
101
|
+
for model in custom_field.object_types.all()[:]:
|
|
102
|
+
custom_field.object_types.remove(model)
|
|
103
|
+
custom_field.delete()
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def prepare_transform_maps(
|
|
107
|
+
apps: "apps_type", schema_editor: "BaseDatabaseSchemaEditor"
|
|
108
|
+
):
|
|
109
|
+
"""Create transform maps if they do not exist yet.
|
|
110
|
+
They used to be created during plugin.ready() so they might be present on older DBs.
|
|
111
|
+
"""
|
|
112
|
+
build_transform_maps(data=get_transform_map())
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class Migration(migrations.Migration):
|
|
116
|
+
replaces = [
|
|
117
|
+
("ipfabric_netbox", "0001_initial"),
|
|
118
|
+
("ipfabric_netbox", "0002_ipfabricsnapshot_status"),
|
|
119
|
+
("ipfabric_netbox", "0003_ipfabricsource_type_and_more"),
|
|
120
|
+
("ipfabric_netbox", "0004_ipfabricsync_auto_merge"),
|
|
121
|
+
(
|
|
122
|
+
"ipfabric_netbox",
|
|
123
|
+
"0005_alter_ipfabricrelationshipfield_source_model_and_more",
|
|
124
|
+
),
|
|
125
|
+
("ipfabric_netbox", "0006_alter_ipfabrictransformmap_target_model"),
|
|
126
|
+
("ipfabric_netbox", "0007_prepare_custom_fields"),
|
|
127
|
+
("ipfabric_netbox", "0008_prepare_transform_maps"),
|
|
128
|
+
("ipfabric_netbox", "0009_transformmap_changes_for_netbox_v4_2"),
|
|
129
|
+
("ipfabric_netbox", "0010_remove_uuid_from_get_or_create"),
|
|
130
|
+
("ipfabric_netbox", "0011_update_part_number_DCIM_inventory_item_template"),
|
|
131
|
+
("ipfabric_netbox", "0012_remove_status_field"),
|
|
132
|
+
("ipfabric_netbox", "0013_switch_to_branching_plugin"),
|
|
133
|
+
]
|
|
134
|
+
|
|
135
|
+
dependencies = [
|
|
136
|
+
("contenttypes", "0002_remove_content_type_name"),
|
|
137
|
+
("core", "0012_job_object_type_optional"),
|
|
138
|
+
("dcim", "0191_module_bay_rebuild"),
|
|
139
|
+
("extras", "0123_journalentry_kind_default"),
|
|
140
|
+
("ipam", "0070_vlangroup_vlan_id_ranges"),
|
|
141
|
+
("netbox_branching", "0003_rename_indexes"),
|
|
142
|
+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
|
143
|
+
]
|
|
144
|
+
|
|
145
|
+
operations = [
|
|
146
|
+
migrations.CreateModel(
|
|
147
|
+
name="IPFabricSource",
|
|
148
|
+
fields=[
|
|
149
|
+
(
|
|
150
|
+
"id",
|
|
151
|
+
models.BigAutoField(
|
|
152
|
+
auto_created=True, primary_key=True, serialize=False
|
|
153
|
+
),
|
|
154
|
+
),
|
|
155
|
+
("created", models.DateTimeField(auto_now_add=True, null=True)),
|
|
156
|
+
("last_updated", models.DateTimeField(auto_now=True, null=True)),
|
|
157
|
+
(
|
|
158
|
+
"custom_field_data",
|
|
159
|
+
models.JSONField(
|
|
160
|
+
blank=True,
|
|
161
|
+
default=dict,
|
|
162
|
+
encoder=utilities.json.CustomFieldJSONEncoder,
|
|
163
|
+
),
|
|
164
|
+
),
|
|
165
|
+
("description", models.CharField(blank=True, max_length=200)),
|
|
166
|
+
("comments", models.TextField(blank=True)),
|
|
167
|
+
("name", models.CharField(max_length=100, unique=True)),
|
|
168
|
+
("url", models.CharField(max_length=200)),
|
|
169
|
+
(
|
|
170
|
+
"status",
|
|
171
|
+
models.CharField(default="new", editable=False, max_length=50),
|
|
172
|
+
),
|
|
173
|
+
("parameters", models.JSONField(blank=True, null=True)),
|
|
174
|
+
("last_synced", models.DateTimeField(blank=True, null=True)),
|
|
175
|
+
(
|
|
176
|
+
"tags",
|
|
177
|
+
taggit.managers.TaggableManager(
|
|
178
|
+
through="extras.TaggedItem", to="extras.Tag"
|
|
179
|
+
),
|
|
180
|
+
),
|
|
181
|
+
("type", models.CharField(default="local", max_length=50)),
|
|
182
|
+
],
|
|
183
|
+
options={
|
|
184
|
+
"verbose_name": "IP Fabric Source",
|
|
185
|
+
"verbose_name_plural": "IP Fabric Sources",
|
|
186
|
+
"ordering": ("name",),
|
|
187
|
+
},
|
|
188
|
+
),
|
|
189
|
+
migrations.CreateModel(
|
|
190
|
+
name="IPFabricSnapshot",
|
|
191
|
+
fields=[
|
|
192
|
+
(
|
|
193
|
+
"id",
|
|
194
|
+
models.BigAutoField(
|
|
195
|
+
auto_created=True, primary_key=True, serialize=False
|
|
196
|
+
),
|
|
197
|
+
),
|
|
198
|
+
("created", models.DateTimeField(auto_now_add=True)),
|
|
199
|
+
("last_updated", models.DateTimeField(editable=False)),
|
|
200
|
+
("name", models.CharField(max_length=200)),
|
|
201
|
+
(
|
|
202
|
+
"source",
|
|
203
|
+
models.ForeignKey(
|
|
204
|
+
editable=False,
|
|
205
|
+
on_delete=django.db.models.deletion.CASCADE,
|
|
206
|
+
related_name="snapshots",
|
|
207
|
+
to="ipfabric_netbox.ipfabricsource",
|
|
208
|
+
),
|
|
209
|
+
),
|
|
210
|
+
("snapshot_id", models.CharField(max_length=100)),
|
|
211
|
+
("status", models.CharField(default="unloaded", max_length=50)),
|
|
212
|
+
("data", models.JSONField(blank=True, null=True)),
|
|
213
|
+
("date", models.DateTimeField(blank=True, editable=False, null=True)),
|
|
214
|
+
],
|
|
215
|
+
options={
|
|
216
|
+
"verbose_name": "IP Fabric Snapshot",
|
|
217
|
+
"verbose_name_plural": "IP Fabric Snapshots",
|
|
218
|
+
"ordering": ("source", "-date"),
|
|
219
|
+
},
|
|
220
|
+
),
|
|
221
|
+
migrations.CreateModel(
|
|
222
|
+
name="IPFabricTransformMap",
|
|
223
|
+
fields=[
|
|
224
|
+
(
|
|
225
|
+
"id",
|
|
226
|
+
models.BigAutoField(
|
|
227
|
+
auto_created=True, primary_key=True, serialize=False
|
|
228
|
+
),
|
|
229
|
+
),
|
|
230
|
+
("created", models.DateTimeField(auto_now_add=True, null=True)),
|
|
231
|
+
("last_updated", models.DateTimeField(auto_now=True, null=True)),
|
|
232
|
+
(
|
|
233
|
+
"custom_field_data",
|
|
234
|
+
models.JSONField(
|
|
235
|
+
blank=True,
|
|
236
|
+
default=dict,
|
|
237
|
+
encoder=utilities.json.CustomFieldJSONEncoder,
|
|
238
|
+
),
|
|
239
|
+
),
|
|
240
|
+
("name", models.CharField(max_length=100, unique=True)),
|
|
241
|
+
("source_model", models.CharField(max_length=50)),
|
|
242
|
+
(
|
|
243
|
+
"tags",
|
|
244
|
+
taggit.managers.TaggableManager(
|
|
245
|
+
through="extras.TaggedItem", to="extras.Tag"
|
|
246
|
+
),
|
|
247
|
+
),
|
|
248
|
+
(
|
|
249
|
+
"target_model",
|
|
250
|
+
models.ForeignKey(
|
|
251
|
+
limit_choices_to=models.Q(
|
|
252
|
+
models.Q(
|
|
253
|
+
models.Q(("app_label", "dcim"), ("model", "site")),
|
|
254
|
+
models.Q(
|
|
255
|
+
("app_label", "dcim"), ("model", "manufacturer")
|
|
256
|
+
),
|
|
257
|
+
models.Q(("app_label", "dcim"), ("model", "platform")),
|
|
258
|
+
models.Q(
|
|
259
|
+
("app_label", "dcim"), ("model", "devicerole")
|
|
260
|
+
),
|
|
261
|
+
models.Q(
|
|
262
|
+
("app_label", "dcim"), ("model", "devicetype")
|
|
263
|
+
),
|
|
264
|
+
models.Q(("app_label", "dcim"), ("model", "device")),
|
|
265
|
+
models.Q(
|
|
266
|
+
("app_label", "dcim"), ("model", "virtualchassis")
|
|
267
|
+
),
|
|
268
|
+
models.Q(("app_label", "dcim"), ("model", "interface")),
|
|
269
|
+
models.Q(
|
|
270
|
+
("app_label", "dcim"), ("model", "macaddress")
|
|
271
|
+
),
|
|
272
|
+
models.Q(("app_label", "ipam"), ("model", "vlan")),
|
|
273
|
+
models.Q(("app_label", "ipam"), ("model", "vrf")),
|
|
274
|
+
models.Q(("app_label", "ipam"), ("model", "prefix")),
|
|
275
|
+
models.Q(("app_label", "ipam"), ("model", "ipaddress")),
|
|
276
|
+
models.Q(
|
|
277
|
+
("app_label", "contenttypes"),
|
|
278
|
+
("model", "contenttype"),
|
|
279
|
+
),
|
|
280
|
+
models.Q(("app_label", "tenancy"), ("model", "tenant")),
|
|
281
|
+
models.Q(
|
|
282
|
+
("app_label", "dcim"), ("model", "inventoryitem")
|
|
283
|
+
),
|
|
284
|
+
_connector="OR",
|
|
285
|
+
)
|
|
286
|
+
),
|
|
287
|
+
on_delete=django.db.models.deletion.PROTECT,
|
|
288
|
+
related_name="+",
|
|
289
|
+
to="contenttypes.contenttype",
|
|
290
|
+
),
|
|
291
|
+
),
|
|
292
|
+
],
|
|
293
|
+
options={
|
|
294
|
+
"verbose_name": "IP Fabric Transform Map",
|
|
295
|
+
"verbose_name_plural": "IP Fabric Transform Maps",
|
|
296
|
+
},
|
|
297
|
+
),
|
|
298
|
+
migrations.CreateModel(
|
|
299
|
+
name="IPFabricTransformField",
|
|
300
|
+
fields=[
|
|
301
|
+
(
|
|
302
|
+
"id",
|
|
303
|
+
models.BigAutoField(
|
|
304
|
+
auto_created=True, primary_key=True, serialize=False
|
|
305
|
+
),
|
|
306
|
+
),
|
|
307
|
+
("source_field", models.CharField(max_length=100)),
|
|
308
|
+
("target_field", models.CharField(max_length=100)),
|
|
309
|
+
("coalesce", models.BooleanField(default=False)),
|
|
310
|
+
("template", models.TextField(blank=True, default="")),
|
|
311
|
+
(
|
|
312
|
+
"transform_map",
|
|
313
|
+
models.ForeignKey(
|
|
314
|
+
on_delete=django.db.models.deletion.CASCADE,
|
|
315
|
+
related_name="field_maps",
|
|
316
|
+
to="ipfabric_netbox.ipfabrictransformmap",
|
|
317
|
+
),
|
|
318
|
+
),
|
|
319
|
+
],
|
|
320
|
+
options={
|
|
321
|
+
"verbose_name": "IP Fabric Transform Field",
|
|
322
|
+
"verbose_name_plural": "IP Fabric Transform Fields",
|
|
323
|
+
"ordering": ("transform_map",),
|
|
324
|
+
},
|
|
325
|
+
),
|
|
326
|
+
migrations.CreateModel(
|
|
327
|
+
name="IPFabricSync",
|
|
328
|
+
fields=[
|
|
329
|
+
(
|
|
330
|
+
"id",
|
|
331
|
+
models.BigAutoField(
|
|
332
|
+
auto_created=True, primary_key=True, serialize=False
|
|
333
|
+
),
|
|
334
|
+
),
|
|
335
|
+
("created", models.DateTimeField(auto_now_add=True, null=True)),
|
|
336
|
+
("last_updated", models.DateTimeField(auto_now=True, null=True)),
|
|
337
|
+
("name", models.CharField(max_length=100, unique=True)),
|
|
338
|
+
("type", models.CharField(default="dcim", max_length=50)),
|
|
339
|
+
(
|
|
340
|
+
"status",
|
|
341
|
+
models.CharField(default="new", editable=False, max_length=50),
|
|
342
|
+
),
|
|
343
|
+
("parameters", models.JSONField(blank=True, null=True)),
|
|
344
|
+
(
|
|
345
|
+
"last_synced",
|
|
346
|
+
models.DateTimeField(blank=True, editable=False, null=True),
|
|
347
|
+
),
|
|
348
|
+
("scheduled", models.DateTimeField(blank=True, null=True)),
|
|
349
|
+
(
|
|
350
|
+
"interval",
|
|
351
|
+
models.PositiveIntegerField(
|
|
352
|
+
blank=True,
|
|
353
|
+
null=True,
|
|
354
|
+
validators=[django.core.validators.MinValueValidator(1)],
|
|
355
|
+
),
|
|
356
|
+
),
|
|
357
|
+
(
|
|
358
|
+
"snapshot_data",
|
|
359
|
+
models.ForeignKey(
|
|
360
|
+
on_delete=django.db.models.deletion.CASCADE,
|
|
361
|
+
related_name="snapshots",
|
|
362
|
+
to="ipfabric_netbox.ipfabricsnapshot",
|
|
363
|
+
),
|
|
364
|
+
),
|
|
365
|
+
(
|
|
366
|
+
"tags",
|
|
367
|
+
taggit.managers.TaggableManager(
|
|
368
|
+
through="extras.TaggedItem", to="extras.Tag"
|
|
369
|
+
),
|
|
370
|
+
),
|
|
371
|
+
(
|
|
372
|
+
"user",
|
|
373
|
+
models.ForeignKey(
|
|
374
|
+
blank=True,
|
|
375
|
+
null=True,
|
|
376
|
+
on_delete=django.db.models.deletion.SET_NULL,
|
|
377
|
+
related_name="+",
|
|
378
|
+
to=settings.AUTH_USER_MODEL,
|
|
379
|
+
),
|
|
380
|
+
),
|
|
381
|
+
("auto_merge", models.BooleanField(default=False)),
|
|
382
|
+
],
|
|
383
|
+
options={
|
|
384
|
+
"verbose_name": "IP Fabric Sync",
|
|
385
|
+
"ordering": ["pk"],
|
|
386
|
+
},
|
|
387
|
+
),
|
|
388
|
+
migrations.CreateModel(
|
|
389
|
+
name="IPFabricData",
|
|
390
|
+
fields=[
|
|
391
|
+
(
|
|
392
|
+
"id",
|
|
393
|
+
models.BigAutoField(
|
|
394
|
+
auto_created=True, primary_key=True, serialize=False
|
|
395
|
+
),
|
|
396
|
+
),
|
|
397
|
+
("data", models.JSONField(blank=True, null=True)),
|
|
398
|
+
("type", models.CharField(max_length=50)),
|
|
399
|
+
(
|
|
400
|
+
"snapshot_data",
|
|
401
|
+
models.ForeignKey(
|
|
402
|
+
on_delete=django.db.models.deletion.CASCADE,
|
|
403
|
+
related_name="ipf_data",
|
|
404
|
+
to="ipfabric_netbox.ipfabricsnapshot",
|
|
405
|
+
),
|
|
406
|
+
),
|
|
407
|
+
],
|
|
408
|
+
),
|
|
409
|
+
migrations.CreateModel(
|
|
410
|
+
name="IPFabricRelationshipField",
|
|
411
|
+
fields=[
|
|
412
|
+
(
|
|
413
|
+
"id",
|
|
414
|
+
models.BigAutoField(
|
|
415
|
+
auto_created=True, primary_key=True, serialize=False
|
|
416
|
+
),
|
|
417
|
+
),
|
|
418
|
+
("target_field", models.CharField(max_length=100)),
|
|
419
|
+
("coalesce", models.BooleanField(default=False)),
|
|
420
|
+
("template", models.TextField(blank=True, default="")),
|
|
421
|
+
(
|
|
422
|
+
"source_model",
|
|
423
|
+
models.ForeignKey(
|
|
424
|
+
limit_choices_to=models.Q(
|
|
425
|
+
models.Q(
|
|
426
|
+
("app_label", "dcim"),
|
|
427
|
+
("app_label", "ipam"),
|
|
428
|
+
("app_label", "tenancy"),
|
|
429
|
+
models.Q(
|
|
430
|
+
("app_label", "contenttypes"),
|
|
431
|
+
("model", "contenttype"),
|
|
432
|
+
),
|
|
433
|
+
_connector="OR",
|
|
434
|
+
)
|
|
435
|
+
),
|
|
436
|
+
on_delete=django.db.models.deletion.PROTECT,
|
|
437
|
+
related_name="ipfabric_transform_fields",
|
|
438
|
+
to="contenttypes.contenttype",
|
|
439
|
+
),
|
|
440
|
+
),
|
|
441
|
+
(
|
|
442
|
+
"transform_map",
|
|
443
|
+
models.ForeignKey(
|
|
444
|
+
on_delete=django.db.models.deletion.CASCADE,
|
|
445
|
+
related_name="relationship_maps",
|
|
446
|
+
to="ipfabric_netbox.ipfabrictransformmap",
|
|
447
|
+
),
|
|
448
|
+
),
|
|
449
|
+
],
|
|
450
|
+
options={
|
|
451
|
+
"verbose_name": "IP Fabric Relationship Field",
|
|
452
|
+
"verbose_name_plural": "IP Fabric Relationship Fields",
|
|
453
|
+
"ordering": ("transform_map",),
|
|
454
|
+
},
|
|
455
|
+
),
|
|
456
|
+
migrations.CreateModel(
|
|
457
|
+
name="IPFabricIngestion",
|
|
458
|
+
fields=[
|
|
459
|
+
(
|
|
460
|
+
"id",
|
|
461
|
+
models.BigAutoField(
|
|
462
|
+
auto_created=True, primary_key=True, serialize=False
|
|
463
|
+
),
|
|
464
|
+
),
|
|
465
|
+
(
|
|
466
|
+
"branch",
|
|
467
|
+
models.OneToOneField(
|
|
468
|
+
null=True,
|
|
469
|
+
on_delete=django.db.models.deletion.SET_NULL,
|
|
470
|
+
to="netbox_branching.branch",
|
|
471
|
+
),
|
|
472
|
+
),
|
|
473
|
+
(
|
|
474
|
+
"job",
|
|
475
|
+
models.ForeignKey(
|
|
476
|
+
null=True,
|
|
477
|
+
on_delete=django.db.models.deletion.SET_NULL,
|
|
478
|
+
to="core.job",
|
|
479
|
+
),
|
|
480
|
+
),
|
|
481
|
+
(
|
|
482
|
+
"sync",
|
|
483
|
+
models.ForeignKey(
|
|
484
|
+
on_delete=django.db.models.deletion.CASCADE,
|
|
485
|
+
to="ipfabric_netbox.ipfabricsync",
|
|
486
|
+
),
|
|
487
|
+
),
|
|
488
|
+
],
|
|
489
|
+
options={
|
|
490
|
+
"verbose_name": "IP Fabric Ingestion",
|
|
491
|
+
"verbose_name_plural": "IP Fabric Ingestion",
|
|
492
|
+
"ordering": ("pk",),
|
|
493
|
+
},
|
|
494
|
+
),
|
|
495
|
+
migrations.RunPython(
|
|
496
|
+
code=prepare_custom_fields,
|
|
497
|
+
reverse_code=cleanup_custom_fields,
|
|
498
|
+
),
|
|
499
|
+
migrations.RunPython(
|
|
500
|
+
code=prepare_transform_maps,
|
|
501
|
+
reverse_code=migrations.RunPython.noop,
|
|
502
|
+
),
|
|
503
|
+
]
|
|
@@ -25,9 +25,9 @@ def create_custom_field(
|
|
|
25
25
|
|
|
26
26
|
defaults = {
|
|
27
27
|
"label": label,
|
|
28
|
-
"related_object_type":
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
"related_object_type": (
|
|
29
|
+
ObjectType.objects.get_for_model(object_type) if object_type else None
|
|
30
|
+
),
|
|
31
31
|
"ui_visible": getattr(CustomFieldUIVisibleChoices, "ALWAYS"),
|
|
32
32
|
"ui_editable": getattr(CustomFieldUIEditableChoices, "NO"),
|
|
33
33
|
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""
|
|
2
|
+
NIM-18852.
|
|
3
|
+
Update to truncate name and description fields because they can
|
|
4
|
+
exceed DB field limits.
|
|
5
|
+
"""
|
|
6
|
+
from django.db import migrations
|
|
7
|
+
|
|
8
|
+
# Keep the original template here rather than loading it from transform_map.json
|
|
9
|
+
# so our revert won’t break if that template ever changes.
|
|
10
|
+
OLD_TEMPLATE = (
|
|
11
|
+
"{% if object.name is not none %}"
|
|
12
|
+
"{{ object.name }}"
|
|
13
|
+
"{% elif object.dscr is not none %}"
|
|
14
|
+
"{{ object.dscr}}"
|
|
15
|
+
"{% else %}Default Name{% endif %}"
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
NEW_TEMPLATE = (
|
|
19
|
+
"{% if object.name is not none %}"
|
|
20
|
+
"{{ object.name | string | truncate(64, True) }}"
|
|
21
|
+
"{% elif object.dscr is not none %}"
|
|
22
|
+
"{{ object.dscr | string | truncate(64, True) }}"
|
|
23
|
+
"{% else %}Default Name{% endif %}"
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def apply_truncate_template(apps, schema_editor):
|
|
28
|
+
"""Replace old template with truncated version on all matching transform fields."""
|
|
29
|
+
TransformField = apps.get_model("ipfabric_netbox", "IPFabricTransformField")
|
|
30
|
+
TransformField.objects.filter(
|
|
31
|
+
template=OLD_TEMPLATE,
|
|
32
|
+
source_field="name",
|
|
33
|
+
target_field="name",
|
|
34
|
+
).update(template=NEW_TEMPLATE)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def revert_truncate_template(apps, schema_editor):
|
|
38
|
+
"""Revert truncated template back to the original exact template."""
|
|
39
|
+
TransformField = apps.get_model("ipfabric_netbox", "IPFabricTransformField")
|
|
40
|
+
TransformField.objects.filter(
|
|
41
|
+
template=NEW_TEMPLATE,
|
|
42
|
+
source_field="name",
|
|
43
|
+
target_field="name",
|
|
44
|
+
).update(template=OLD_TEMPLATE)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class Migration(migrations.Migration):
|
|
48
|
+
dependencies = [
|
|
49
|
+
("ipfabric_netbox", "0010_remove_uuid_from_get_or_create"),
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
operations = [
|
|
53
|
+
migrations.RunPython(
|
|
54
|
+
apply_truncate_template,
|
|
55
|
+
revert_truncate_template,
|
|
56
|
+
),
|
|
57
|
+
]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""
|
|
2
|
+
NIM-18527.
|
|
3
|
+
Remove status field from TransformMap.
|
|
4
|
+
"""
|
|
5
|
+
from django.db import migrations
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Migration(migrations.Migration):
|
|
9
|
+
dependencies = [
|
|
10
|
+
("ipfabric_netbox", "0011_update_part_number_DCIM_inventory_item_template"),
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
operations = [
|
|
14
|
+
migrations.RemoveField(
|
|
15
|
+
model_name="ipfabrictransformmap",
|
|
16
|
+
name="status",
|
|
17
|
+
),
|
|
18
|
+
]
|