ipfabric_netbox 4.3.2b8__py3-none-any.whl → 4.3.2b10__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.

Files changed (49) hide show
  1. ipfabric_netbox/__init__.py +2 -2
  2. ipfabric_netbox/api/serializers.py +112 -7
  3. ipfabric_netbox/api/urls.py +6 -0
  4. ipfabric_netbox/api/views.py +23 -0
  5. ipfabric_netbox/choices.py +72 -40
  6. ipfabric_netbox/data/endpoint.json +47 -0
  7. ipfabric_netbox/data/filters.json +51 -0
  8. ipfabric_netbox/data/transform_map.json +188 -174
  9. ipfabric_netbox/exceptions.py +7 -5
  10. ipfabric_netbox/filtersets.py +310 -41
  11. ipfabric_netbox/forms.py +324 -79
  12. ipfabric_netbox/graphql/__init__.py +6 -0
  13. ipfabric_netbox/graphql/enums.py +5 -5
  14. ipfabric_netbox/graphql/filters.py +56 -4
  15. ipfabric_netbox/graphql/schema.py +28 -0
  16. ipfabric_netbox/graphql/types.py +61 -1
  17. ipfabric_netbox/jobs.py +18 -1
  18. ipfabric_netbox/migrations/0022_prepare_for_filters.py +182 -0
  19. ipfabric_netbox/migrations/0023_populate_filters_data.py +279 -0
  20. ipfabric_netbox/migrations/0024_finish_filters.py +29 -0
  21. ipfabric_netbox/models.py +384 -12
  22. ipfabric_netbox/navigation.py +98 -24
  23. ipfabric_netbox/tables.py +194 -9
  24. ipfabric_netbox/templates/ipfabric_netbox/htmx_list.html +5 -0
  25. ipfabric_netbox/templates/ipfabric_netbox/inc/combined_expressions.html +59 -0
  26. ipfabric_netbox/templates/ipfabric_netbox/inc/combined_expressions_content.html +39 -0
  27. ipfabric_netbox/templates/ipfabric_netbox/inc/endpoint_filters_with_selector.html +54 -0
  28. ipfabric_netbox/templates/ipfabric_netbox/ipfabricendpoint.html +39 -0
  29. ipfabric_netbox/templates/ipfabric_netbox/ipfabricfilter.html +51 -0
  30. ipfabric_netbox/templates/ipfabric_netbox/ipfabricfilterexpression.html +39 -0
  31. ipfabric_netbox/templates/ipfabric_netbox/ipfabricfilterexpression_edit.html +150 -0
  32. ipfabric_netbox/templates/ipfabric_netbox/ipfabricsync.html +1 -1
  33. ipfabric_netbox/templates/ipfabric_netbox/ipfabrictransformmap.html +16 -2
  34. ipfabric_netbox/templatetags/ipfabric_netbox_helpers.py +65 -0
  35. ipfabric_netbox/tests/api/test_api.py +333 -13
  36. ipfabric_netbox/tests/test_filtersets.py +2592 -0
  37. ipfabric_netbox/tests/test_forms.py +1256 -74
  38. ipfabric_netbox/tests/test_models.py +242 -34
  39. ipfabric_netbox/tests/test_views.py +2030 -25
  40. ipfabric_netbox/urls.py +35 -0
  41. ipfabric_netbox/utilities/endpoint.py +30 -0
  42. ipfabric_netbox/utilities/filters.py +88 -0
  43. ipfabric_netbox/utilities/ipfutils.py +254 -316
  44. ipfabric_netbox/utilities/logging.py +7 -7
  45. ipfabric_netbox/utilities/transform_map.py +126 -0
  46. ipfabric_netbox/views.py +719 -5
  47. {ipfabric_netbox-4.3.2b8.dist-info → ipfabric_netbox-4.3.2b10.dist-info}/METADATA +3 -2
  48. {ipfabric_netbox-4.3.2b8.dist-info → ipfabric_netbox-4.3.2b10.dist-info}/RECORD +49 -33
  49. {ipfabric_netbox-4.3.2b8.dist-info → ipfabric_netbox-4.3.2b10.dist-info}/WHEEL +1 -1
@@ -1,5 +1,7 @@
1
1
  import django_filters
2
2
  from core.choices import ObjectChangeActionChoices
3
+ from django.contrib.contenttypes.models import ContentType
4
+ from django.db.models import JSONField
3
5
  from django.db.models import Q
4
6
  from django.utils.translation import gettext as _
5
7
  from netbox.filtersets import BaseFilterSet
@@ -10,6 +12,9 @@ from netbox_branching.models import ChangeDiff
10
12
  from .choices import IPFabricSourceStatusChoices
11
13
  from .choices import IPFabricSyncStatusChoices
12
14
  from .models import IPFabricData
15
+ from .models import IPFabricEndpoint
16
+ from .models import IPFabricFilter
17
+ from .models import IPFabricFilterExpression
13
18
  from .models import IPFabricIngestion
14
19
  from .models import IPFabricIngestionIssue
15
20
  from .models import IPFabricRelationshipField
@@ -80,7 +85,8 @@ class IPFabricDataFilterSet(BaseFilterSet):
80
85
  def search(self, queryset, name, value):
81
86
  if not value.strip():
82
87
  return queryset
83
- return queryset.filter(Q(snapshot_data__icontains=value))
88
+ # Search by snapshot name since snapshot_data is a ForeignKey
89
+ return queryset.filter(Q(snapshot_data__name__icontains=value))
84
90
 
85
91
 
86
92
  class IPFabricSnapshotFilterSet(ChangeLoggedModelFilterSet):
@@ -128,16 +134,76 @@ class IPFabricSourceFilterSet(NetBoxModelFilterSet):
128
134
  )
129
135
 
130
136
 
137
+ class IPFabricSyncFilterSet(ChangeLoggedModelFilterSet):
138
+ q = django_filters.CharFilter(method="search")
139
+ name = django_filters.CharFilter()
140
+ snapshot_data_id = django_filters.ModelMultipleChoiceFilter(
141
+ queryset=IPFabricSnapshot.objects.all(),
142
+ label=_("Snapshot (ID)"),
143
+ )
144
+ snapshot_data = django_filters.ModelMultipleChoiceFilter(
145
+ field_name="snapshot_data__name",
146
+ queryset=IPFabricSnapshot.objects.all(),
147
+ to_field_name="name",
148
+ label=_("Snapshot (name)"),
149
+ )
150
+ status = django_filters.MultipleChoiceFilter(
151
+ choices=IPFabricSyncStatusChoices, null_value=None
152
+ )
153
+
154
+ ipfabric_filter_id = django_filters.ModelMultipleChoiceFilter(
155
+ queryset=IPFabricFilter.objects.all(),
156
+ field_name="filters",
157
+ label=_("IP Fabric Filter (ID)"),
158
+ )
159
+ ipfabric_filter = django_filters.CharFilter(
160
+ field_name="filters__name",
161
+ lookup_expr="iexact",
162
+ label=_("IP Fabric Filter (name)"),
163
+ distinct=True,
164
+ )
165
+ ipfabric_filters = django_filters.ModelMultipleChoiceFilter(
166
+ queryset=IPFabricFilter.objects.all(),
167
+ field_name="filters",
168
+ label=_("IP Fabric Filters"),
169
+ )
170
+
171
+ class Meta:
172
+ model = IPFabricSync
173
+ fields = (
174
+ "id",
175
+ "name",
176
+ "snapshot_data",
177
+ "snapshot_data_id",
178
+ "status",
179
+ "auto_merge",
180
+ "last_synced",
181
+ "scheduled",
182
+ "interval",
183
+ "ipfabric_filter_id",
184
+ "ipfabric_filter",
185
+ "ipfabric_filters",
186
+ )
187
+
188
+ def search(self, queryset, name, value):
189
+ if not value.strip():
190
+ return queryset
191
+ return queryset.filter(
192
+ Q(name__icontains=value) | Q(snapshot_data__name__icontains=value)
193
+ )
194
+
195
+
131
196
  class IPFabricIngestionFilterSet(BaseFilterSet):
132
197
  q = django_filters.CharFilter(method="search")
133
198
  sync_id = django_filters.ModelMultipleChoiceFilter(
199
+ field_name="sync",
134
200
  queryset=IPFabricSync.objects.all(),
135
201
  label=_("Sync (ID)"),
136
202
  )
137
203
  sync = django_filters.ModelMultipleChoiceFilter(
138
204
  field_name="sync__name",
139
205
  queryset=IPFabricSync.objects.all(),
140
- to_field_name="branch__name",
206
+ to_field_name="name",
141
207
  label=_("Sync (name)"),
142
208
  )
143
209
 
@@ -153,6 +219,186 @@ class IPFabricIngestionFilterSet(BaseFilterSet):
153
219
  )
154
220
 
155
221
 
222
+ class IPFabricFilterFilterSet(NetBoxModelFilterSet):
223
+ q = django_filters.CharFilter(method="search")
224
+
225
+ sync_id = django_filters.ModelMultipleChoiceFilter(
226
+ queryset=IPFabricSync.objects.all(),
227
+ field_name="syncs",
228
+ label=_("Syncs (ID)"),
229
+ )
230
+ sync = django_filters.CharFilter(
231
+ field_name="syncs__name",
232
+ lookup_expr="iexact",
233
+ label=_("Sync (name)"),
234
+ distinct=True,
235
+ )
236
+ syncs = django_filters.ModelMultipleChoiceFilter(
237
+ queryset=IPFabricSync.objects.all(),
238
+ field_name="syncs",
239
+ label=_("Syncs (ID)"),
240
+ )
241
+
242
+ endpoint_id = django_filters.ModelMultipleChoiceFilter(
243
+ queryset=IPFabricEndpoint.objects.all(),
244
+ field_name="endpoints",
245
+ label=_("Endpoints (ID)"),
246
+ )
247
+ endpoint = django_filters.CharFilter(
248
+ field_name="endpoints__name",
249
+ lookup_expr="iexact",
250
+ label=_("Endpoint (Name)"),
251
+ distinct=True,
252
+ )
253
+ endpoint_path = django_filters.CharFilter(
254
+ field_name="endpoints__endpoint",
255
+ lookup_expr="iexact",
256
+ label=_("Endpoint (Path)"),
257
+ distinct=True,
258
+ )
259
+ endpoints = django_filters.ModelMultipleChoiceFilter(
260
+ queryset=IPFabricEndpoint.objects.all(),
261
+ field_name="endpoints",
262
+ label=_("Endpoints (ID)"),
263
+ )
264
+
265
+ expression_id = django_filters.ModelMultipleChoiceFilter(
266
+ queryset=IPFabricFilterExpression.objects.all(),
267
+ field_name="expressions",
268
+ label=_("Expression (ID)"),
269
+ )
270
+ expression = django_filters.CharFilter(
271
+ field_name="expressions__name",
272
+ lookup_expr="iexact",
273
+ label=_("Expression (name)"),
274
+ distinct=True,
275
+ )
276
+ expressions = django_filters.ModelMultipleChoiceFilter(
277
+ queryset=IPFabricFilterExpression.objects.all(),
278
+ field_name="expressions",
279
+ label=_("Expressions (ID)"),
280
+ )
281
+
282
+ class Meta:
283
+ model = IPFabricFilter
284
+ fields = (
285
+ "id",
286
+ "name",
287
+ "description",
288
+ "endpoint_id",
289
+ "endpoint",
290
+ "endpoint_path",
291
+ "endpoints",
292
+ "filter_type",
293
+ "sync_id",
294
+ "sync",
295
+ "syncs",
296
+ "expression_id",
297
+ "expression",
298
+ "expressions",
299
+ )
300
+
301
+ def search(self, queryset, name, value):
302
+ if not value.strip():
303
+ return queryset
304
+ return queryset.filter(
305
+ Q(name__icontains=value) | Q(description__icontains=value)
306
+ )
307
+
308
+
309
+ class IPFabricFilterExpressionFilterSet(NetBoxModelFilterSet):
310
+ q = django_filters.CharFilter(method="search")
311
+
312
+ ipfabric_filter_id = django_filters.ModelMultipleChoiceFilter(
313
+ queryset=IPFabricFilter.objects.all(),
314
+ field_name="filters",
315
+ label=_("Filter (ID)"),
316
+ )
317
+ ipfabric_filter = django_filters.CharFilter(
318
+ field_name="filters__name",
319
+ lookup_expr="iexact",
320
+ label=_("Filters (name)"),
321
+ distinct=True,
322
+ )
323
+ ipfabric_filters = django_filters.ModelMultipleChoiceFilter(
324
+ queryset=IPFabricFilter.objects.all(),
325
+ field_name="filters",
326
+ label=_("Filters (ID)"),
327
+ )
328
+
329
+ class Meta:
330
+ model = IPFabricFilterExpression
331
+ fields = (
332
+ "id",
333
+ "name",
334
+ "description",
335
+ "expression",
336
+ "ipfabric_filter_id",
337
+ "ipfabric_filter",
338
+ "ipfabric_filters",
339
+ )
340
+ filter_overrides = {
341
+ JSONField: {
342
+ "filter_class": django_filters.CharFilter,
343
+ "extra": lambda f: {"lookup_expr": "icontains"},
344
+ },
345
+ }
346
+
347
+ def search(self, queryset, name, value):
348
+ if not value.strip():
349
+ return queryset
350
+ return queryset.filter(
351
+ Q(name__icontains=value) | Q(description__icontains=value)
352
+ )
353
+
354
+
355
+ class IPFabricEndpointFilterSet(NetBoxModelFilterSet):
356
+ q = django_filters.CharFilter(method="search")
357
+
358
+ endpoint = django_filters.CharFilter(
359
+ field_name="endpoint",
360
+ lookup_expr="iexact",
361
+ label=_("Endpoint (Path)"),
362
+ )
363
+ ipfabric_filter_id = django_filters.ModelMultipleChoiceFilter(
364
+ queryset=IPFabricFilter.objects.all(),
365
+ field_name="filters",
366
+ label=_("IP Fabric Filter (ID)"),
367
+ )
368
+ ipfabric_filter = django_filters.CharFilter(
369
+ field_name="filters__name",
370
+ lookup_expr="iexact",
371
+ label=_("IP Fabric Filter (name)"),
372
+ distinct=True,
373
+ )
374
+ ipfabric_filters = django_filters.ModelMultipleChoiceFilter(
375
+ queryset=IPFabricFilter.objects.all(),
376
+ field_name="filters",
377
+ label=_("IP Fabric Filters"),
378
+ )
379
+
380
+ class Meta:
381
+ model = IPFabricEndpoint
382
+ fields = (
383
+ "id",
384
+ "name",
385
+ "description",
386
+ "endpoint",
387
+ "ipfabric_filter_id",
388
+ "ipfabric_filter",
389
+ "ipfabric_filters",
390
+ )
391
+
392
+ def search(self, queryset, name, value):
393
+ if not value.strip().rstrip("/"):
394
+ return queryset
395
+ return queryset.filter(
396
+ Q(name__icontains=value)
397
+ | Q(endpoint__icontains=value)
398
+ | Q(description__icontains=value)
399
+ )
400
+
401
+
156
402
  class IPFabricTransformMapGroupFilterSet(NetBoxModelFilterSet):
157
403
  q = django_filters.CharFilter(method="search")
158
404
 
@@ -177,10 +423,31 @@ class IPFabricTransformMapFilterSet(NetBoxModelFilterSet):
177
423
  group = django_filters.ModelMultipleChoiceFilter(
178
424
  queryset=IPFabricTransformMapGroup.objects.all(), label=_("Transform Map Group")
179
425
  )
426
+ source_endpoint = django_filters.ModelChoiceFilter(
427
+ queryset=IPFabricEndpoint.objects.all(), label=_("Source Endpoint")
428
+ )
429
+ source_endpoint_id = django_filters.ModelMultipleChoiceFilter(
430
+ queryset=IPFabricEndpoint.objects.all(),
431
+ field_name="source_endpoint",
432
+ label=_("Source Endpoint (ID)"),
433
+ )
434
+ source_endpoints = django_filters.ModelMultipleChoiceFilter(
435
+ queryset=IPFabricEndpoint.objects.all(),
436
+ field_name="source_endpoint",
437
+ label=_("Source Endpoints"),
438
+ )
180
439
 
181
440
  class Meta:
182
441
  model = IPFabricTransformMap
183
- fields = ("id", "name", "group", "source_model", "target_model")
442
+ fields = (
443
+ "id",
444
+ "name",
445
+ "group",
446
+ "source_endpoint",
447
+ "source_endpoint_id",
448
+ "source_endpoints",
449
+ "target_model",
450
+ )
184
451
 
185
452
  def search(self, queryset, name, value):
186
453
  if not value.strip():
@@ -194,12 +461,32 @@ class IPFabricTransformFieldFilterSet(BaseFilterSet):
194
461
  transform_map = django_filters.ModelMultipleChoiceFilter(
195
462
  queryset=IPFabricTransformMap.objects.all(), label=_("Transform Map")
196
463
  )
464
+ transform_map_id = django_filters.ModelMultipleChoiceFilter(
465
+ queryset=IPFabricTransformMap.objects.all(),
466
+ field_name="transform_map",
467
+ label=_("Transform Map (ID)"),
468
+ )
469
+ source_field = django_filters.CharFilter(
470
+ field_name="source_field",
471
+ lookup_expr="exact",
472
+ label=_("Source Field"),
473
+ )
474
+ target_field = django_filters.CharFilter(
475
+ field_name="target_field",
476
+ lookup_expr="exact",
477
+ label=_("Target Field"),
478
+ )
479
+ coalesce = django_filters.BooleanFilter(
480
+ field_name="coalesce",
481
+ label=_("Coalesce"),
482
+ )
197
483
 
198
484
  class Meta:
199
485
  model = IPFabricTransformField
200
486
  fields = (
201
487
  "id",
202
488
  "transform_map",
489
+ "transform_map_id",
203
490
  "source_field",
204
491
  "target_field",
205
492
  "coalesce",
@@ -211,52 +498,34 @@ class IPFabricRelationshipFieldFilterSet(BaseFilterSet):
211
498
  transform_map = django_filters.ModelMultipleChoiceFilter(
212
499
  queryset=IPFabricTransformMap.objects.all(), label=_("Transform Map")
213
500
  )
501
+ transform_map_id = django_filters.ModelMultipleChoiceFilter(
502
+ queryset=IPFabricTransformMap.objects.all(),
503
+ field_name="transform_map",
504
+ label=_("Transform Map (ID)"),
505
+ )
506
+ source_model = django_filters.ModelChoiceFilter(
507
+ queryset=ContentType.objects.all(),
508
+ field_name="source_model",
509
+ label=_("Source Model"),
510
+ )
511
+ target_field = django_filters.CharFilter(
512
+ field_name="target_field",
513
+ lookup_expr="exact",
514
+ label=_("Target Field"),
515
+ )
516
+ coalesce = django_filters.BooleanFilter(
517
+ field_name="coalesce",
518
+ label=_("Coalesce"),
519
+ )
214
520
 
215
521
  class Meta:
216
522
  model = IPFabricRelationshipField
217
523
  fields = (
218
524
  "id",
219
525
  "transform_map",
526
+ "transform_map_id",
220
527
  "source_model",
221
528
  "target_field",
222
529
  "coalesce",
223
530
  "template",
224
531
  )
225
-
226
-
227
- class IPFabricSyncFilterSet(ChangeLoggedModelFilterSet):
228
- q = django_filters.CharFilter(method="search")
229
- snapshot_data_id = django_filters.ModelMultipleChoiceFilter(
230
- queryset=IPFabricSnapshot.objects.all(),
231
- label=_("Snapshot (ID)"),
232
- )
233
- snapshot_data = django_filters.ModelMultipleChoiceFilter(
234
- field_name="snapshot_data__name",
235
- queryset=IPFabricSnapshot.objects.all(),
236
- to_field_name="name",
237
- label=_("Snapshot (name)"),
238
- )
239
- status = django_filters.MultipleChoiceFilter(
240
- choices=IPFabricSyncStatusChoices, null_value=None
241
- )
242
-
243
- class Meta:
244
- model = IPFabricSync
245
- fields = (
246
- "id",
247
- "name",
248
- "snapshot_data",
249
- "snapshot_data_id",
250
- "status",
251
- "auto_merge",
252
- "last_synced",
253
- "scheduled",
254
- "interval",
255
- )
256
-
257
- def search(self, queryset, name, value):
258
- if not value.strip():
259
- return queryset
260
- return queryset.filter(
261
- Q(name__icontains=value) | Q(snapshot_data__name__icontains=value)
262
- )