ipfabric_netbox 4.2.1__py3-none-any.whl → 4.2.1b2__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.
ipfabric_netbox/forms.py CHANGED
@@ -46,22 +46,6 @@ exclude_fields = [
46
46
  "status",
47
47
  ]
48
48
 
49
-
50
- class IPFSiteChoiceField(forms.MultipleChoiceField):
51
- def valid_value(self, value):
52
- """Check to see if the provided value is a valid choice."""
53
- text_value = str(value)
54
- for k, v in self.choices:
55
- if isinstance(v, (list, tuple)):
56
- for k2, v2 in v:
57
- if value == k2 or text_value == str(k2):
58
- return True
59
- else:
60
- if value == k or text_value == str(k):
61
- return True
62
- return False
63
-
64
-
65
49
  dcim_parameters = {
66
50
  "site": forms.BooleanField(required=False, label=_("Sites"), initial=True),
67
51
  "manufacturer": forms.BooleanField(
@@ -78,43 +62,45 @@ dcim_parameters = {
78
62
  "virtualchassis": forms.BooleanField(
79
63
  required=False, label=_("Virtual Chassis"), initial=True
80
64
  ),
81
- "interface": forms.BooleanField(required=False, label=_("Interfaces")),
82
- "macaddress": forms.BooleanField(required=False, label=_("MAC Addresses")),
83
- "inventoryitem": forms.BooleanField(required=False, label=_("Part Numbers")),
65
+ "interface": forms.BooleanField(
66
+ required=False, label=_("Interfaces"), initial=False
67
+ ),
68
+ "macaddress": forms.BooleanField(
69
+ required=False, label=_("MAC Addresses"), initial=False
70
+ ),
71
+ "inventoryitem": forms.BooleanField(
72
+ required=False, label=_("Part Numbers"), initial=False
73
+ ),
84
74
  }
85
75
  ipam_parameters = {
86
- "vlan": forms.BooleanField(required=False, label=_("VLANs")),
87
- "vrf": forms.BooleanField(required=False, label=_("VRFs")),
88
- "prefix": forms.BooleanField(required=False, label=_("Prefixes")),
89
- "ipaddress": forms.BooleanField(required=False, label=_("IP Addresses")),
76
+ "vlan": forms.BooleanField(required=False, label=_("VLANs"), initial=False),
77
+ "vrf": forms.BooleanField(required=False, label=_("VRFs"), initial=False),
78
+ "prefix": forms.BooleanField(required=False, label=_("Prefixes"), initial=False),
79
+ "ipaddress": forms.BooleanField(
80
+ required=False, label=_("IP Addresses"), initial=False
81
+ ),
90
82
  }
91
83
  sync_parameters = {"dcim": dcim_parameters, "ipam": ipam_parameters}
92
84
 
93
85
 
94
- def source_column_choices(model):
86
+ def source_column_choices(model: str) -> list[tuple[str, str]]:
95
87
  columns = transform_field_source_columns.get(model, None)
96
88
  if columns:
97
89
  choices = [(f, f) for f in transform_field_source_columns.get(model)]
98
90
  else:
99
- choices = []
91
+ # This should never happen, but better be safe than sorry
92
+ choices = [] # pragma: no cover
100
93
  return choices
101
94
 
102
95
 
103
- def add_all_sites(choices):
104
- """
105
- Add a blank choice to the beginning of a choices list.
106
- """
107
- return ((None, "All Sites"),) + tuple(choices)
108
-
109
-
110
- def str_to_list(str):
111
- if not isinstance(str, list):
112
- return [str]
96
+ def str_to_list(_str: str | list) -> list[str]:
97
+ if not isinstance(_str, list):
98
+ return [_str]
113
99
  else:
114
- return str
100
+ return _str
115
101
 
116
102
 
117
- def list_to_choices(choices):
103
+ def list_to_choices(choices: list[str]) -> tuple[tuple[str, str], ...]:
118
104
  new_choices = ()
119
105
  for choice in choices:
120
106
  new_choices = new_choices + ((choice, choice),)
@@ -176,7 +162,7 @@ class IPFabricRelationshipFieldForm(NetBoxModelForm):
176
162
  )
177
163
  self.fields["target_field"].widget.initial = self.instance.target_field
178
164
  else:
179
- if kwargs["initial"].get("transform_map", None):
165
+ if kwargs.get("initial", {}).get("transform_map", None):
180
166
  transform_map_id = kwargs["initial"]["transform_map"]
181
167
  transform_map = IPFabricTransformMap.objects.get(
182
168
  pk=transform_map_id
@@ -258,7 +244,7 @@ class IPFabricTransformFieldForm(NetBoxModelForm):
258
244
  source_column_choices(source_fields)
259
245
  )
260
246
  else:
261
- if kwargs["initial"].get("transform_map", None):
247
+ if kwargs.get("initial", {}).get("transform_map", None):
262
248
  transform_map_id = kwargs["initial"]["transform_map"]
263
249
  transform_map = IPFabricTransformMap.objects.get(
264
250
  pk=transform_map_id
@@ -375,22 +361,22 @@ class IPFabricSourceForm(NetBoxModelForm):
375
361
  "type": HTMXSelect(),
376
362
  }
377
363
 
378
- @property
379
- def fieldsets(self):
380
- fieldsets = [
381
- FieldSet("name", "type", "url", name=_("Source")),
382
- FieldSet("timeout", name=_("Parameters")),
383
- ]
384
-
385
- if self.source_type == "local":
386
- fieldsets[1] = FieldSet("auth", "verify", "timeout", name=_("Parameters"))
387
-
388
- return fieldsets
389
-
390
364
  def __init__(self, *args, **kwargs):
391
365
  super().__init__(*args, **kwargs)
392
366
  self.source_type = get_field_value(self, "type")
393
367
 
368
+ # Set fieldsets dynamically based on source_type
369
+ if self.source_type == "local":
370
+ self.fieldsets = [
371
+ FieldSet("name", "type", "url", name=_("Source")),
372
+ FieldSet("auth", "verify", "timeout", name=_("Parameters")),
373
+ ]
374
+ else:
375
+ self.fieldsets = [
376
+ FieldSet("name", "type", "url", name=_("Source")),
377
+ FieldSet("timeout", name=_("Parameters")),
378
+ ]
379
+
394
380
  self.fields["timeout"] = forms.IntegerField(
395
381
  required=False,
396
382
  label=_("Timeout"),
@@ -451,6 +437,9 @@ class OrderedModelMultipleChoiceField(forms.ModelMultipleChoiceField):
451
437
 
452
438
  def clean(self, value):
453
439
  qs = super().clean(value)
440
+ # Handle None or empty values
441
+ if not value:
442
+ return qs
454
443
  clauses = " ".join(
455
444
  ["WHEN id=%s THEN %s" % (pk, i) for i, pk in enumerate(value)]
456
445
  )
@@ -488,11 +477,18 @@ class IPFabricSyncForm(NetBoxModelForm):
488
477
  sites = forms.MultipleChoiceField(
489
478
  required=False,
490
479
  label=_("Sites"),
480
+ help_text=_("Defaults to all sites if none selected."),
491
481
  widget=APISelectMultiple(
492
482
  api_url="/api/plugins/ipfabric/snapshot/{{snapshot_data}}/sites/",
493
483
  ),
494
484
  )
495
485
 
486
+ update_custom_fields = forms.BooleanField(
487
+ required=False,
488
+ label=_("Custom Fields Updating"),
489
+ help_text=_("Update object custom fields where applicable."),
490
+ )
491
+
496
492
  scheduled = forms.DateTimeField(
497
493
  required=False,
498
494
  widget=DateTimePicker(),
@@ -519,41 +515,13 @@ class IPFabricSyncForm(NetBoxModelForm):
519
515
  "source",
520
516
  "snapshot_data",
521
517
  "auto_merge",
518
+ "update_custom_fields",
522
519
  "sites",
523
- "type",
524
520
  "tags",
525
521
  "scheduled",
526
522
  "interval",
527
523
  )
528
- widgets = {
529
- "source": HTMXSelect(),
530
- "type": HTMXSelect(),
531
- }
532
-
533
- @property
534
- def fieldsets(self):
535
- fieldsets = [
536
- FieldSet("name", "source", "groups", name=_("IP Fabric Source")),
537
- ]
538
- if self.source_type == "local":
539
- fieldsets.append(
540
- FieldSet("snapshot_data", "sites", name=_("Snapshot Information")),
541
- )
542
- else:
543
- fieldsets.append(
544
- FieldSet("snapshot_data", name=_("Snapshot Information")),
545
- )
546
- fieldsets.append(FieldSet("type", name=_("Ingestion Type")))
547
- if self.backend_fields:
548
- for k, v in self.backend_fields.items():
549
- fieldsets.append(FieldSet(*v, name=f"{k.upper()} Parameters"))
550
- fieldsets.append(
551
- FieldSet("scheduled", "interval", name=_("Ingestion Execution Parameters"))
552
- )
553
- fieldsets.append(FieldSet("auto_merge", name=_("Extras")))
554
- fieldsets.append(FieldSet("tags", name=_("Tags")))
555
-
556
- return fieldsets
524
+ widgets = {"source": HTMXSelect()}
557
525
 
558
526
  def __init__(self, *args, **kwargs):
559
527
  super().__init__(*args, **kwargs)
@@ -585,20 +553,13 @@ class IPFabricSyncForm(NetBoxModelForm):
585
553
  self.initial["sites"] = self.instance.parameters.get("sites", [])
586
554
  self.initial["groups"] = self.instance.parameters.get("groups", [])
587
555
 
588
- backend_type = get_field_value(self, "type")
589
- backend = {}
590
- if backend_type == "all":
591
- backend = sync_parameters
592
- else:
593
- backend[backend_type] = sync_parameters.get(backend_type)
594
-
595
556
  now = local_now().strftime("%Y-%m-%d %H:%M:%S")
596
557
  self.fields["scheduled"].help_text += f" (current time: <strong>{now}</strong>)"
597
558
 
598
559
  # Add backend-specific form fields
599
560
  self.backend_fields = {}
600
561
 
601
- for k, v in backend.items():
562
+ for k, v in sync_parameters.items():
602
563
  self.backend_fields[k] = []
603
564
  for name, form_field in v.items():
604
565
  field_name = f"ipf_{name}"
@@ -607,17 +568,52 @@ class IPFabricSyncForm(NetBoxModelForm):
607
568
  if self.instance and self.instance.parameters:
608
569
  self.fields[field_name].initial = self.instance.parameters.get(name)
609
570
 
571
+ # Set fieldsets dynamically based and backend_fields
572
+ fieldsets = [
573
+ FieldSet("name", "source", "groups", name=_("IP Fabric Source")),
574
+ ]
575
+ if self.source_type == "local":
576
+ fieldsets.append(
577
+ FieldSet("snapshot_data", "sites", name=_("Snapshot Information")),
578
+ )
579
+ else:
580
+ fieldsets.append(
581
+ FieldSet("snapshot_data", name=_("Snapshot Information")),
582
+ )
583
+ for k, v in self.backend_fields.items():
584
+ fieldsets.append(FieldSet(*v, name=f"{k.upper()} Parameters"))
585
+ fieldsets.append(
586
+ FieldSet("scheduled", "interval", name=_("Ingestion Execution Parameters"))
587
+ )
588
+ fieldsets.append(
589
+ FieldSet("auto_merge", "update_custom_fields", name=_("Extras"))
590
+ )
591
+ fieldsets.append(FieldSet("tags", name=_("Tags")))
592
+
593
+ self.fieldsets = fieldsets
594
+
610
595
  def clean(self):
611
596
  super().clean()
612
- snapshot = self.cleaned_data["snapshot_data"]
613
597
 
614
598
  sites = self.data.get("sites")
615
- choices = list_to_choices(str_to_list(sites))
616
- self.fields["sites"].choices = choices
617
-
618
- if sites:
619
- if not any(y in x for x in snapshot.sites for y in sites):
620
- raise ValidationError({"sites": f"{sites} not part of the snapshot."})
599
+ self.fields["sites"].choices = list_to_choices(str_to_list(sites))
600
+ if sites and "snapshot_data" in self.cleaned_data:
601
+ snapshot = self.cleaned_data["snapshot_data"]
602
+ # Check if all sites are valid - fail if any site is not found in snapshot.sites
603
+ if not all(
604
+ any(site in snapshot_site for snapshot_site in snapshot.sites)
605
+ for site in sites
606
+ ):
607
+ invalid_sites = [
608
+ site
609
+ for site in sites
610
+ if not any(
611
+ site in snapshot_site for snapshot_site in snapshot.sites
612
+ )
613
+ ]
614
+ raise ValidationError(
615
+ {"sites": f"Sites {invalid_sites} not part of the snapshot."}
616
+ )
621
617
 
622
618
  scheduled_time = self.cleaned_data.get("scheduled")
623
619
  if scheduled_time and scheduled_time < local_now():
@@ -665,50 +661,6 @@ class IPFabricSyncForm(NetBoxModelForm):
665
661
  return object
666
662
 
667
663
 
668
- # class SyncForm(forms.Form):
669
- # def __init__(self, *args, **kwargs):
670
- # self.snapshots = kwargs.pop("snapshot_choices", None)
671
- # self.sites = kwargs.pop("site_choices", None)
672
- # super(SyncForm, self).__init__(*args, **kwargs)
673
- # if self.snapshots:
674
- # snapshot_choices = [
675
- # (snapshot_id, snapshot_name)
676
- # for snapshot_name, snapshot_id in self.snapshots.values()
677
- # ]
678
- # self.fields["snapshot"] = forms.ChoiceField(
679
- # label="Snapshot",
680
- # required=True,
681
- # choices=snapshot_choices,
682
- # help_text="IPFabric snapshot to sync from. Defaults to $last",
683
- # widget=forms.Select(
684
- # attrs={
685
- # "hx-get": reverse("plugins:ipfabric_netbox:ipfabricsync_add"),
686
- # "hx-trigger": "change",
687
- # "hx-target": "#modules",
688
- # "class": "form-control",
689
- # }
690
- # ),
691
- # )
692
- # if self.sites:
693
- # site_choices = [(site, site) for site in self.sites]
694
- # self.fields["site"] = forms.ChoiceField(
695
- # label="Site",
696
- # required=False,
697
- # choices=add_blank_choice(site_choices),
698
- # help_text="Sites available within snapshot",
699
- # widget=forms.Select(attrs={"class": "form-control"}),
700
- # )
701
- # else:
702
- # self.fields["site"] = forms.ChoiceField(
703
- # label="Site",
704
- # required=False,
705
- # choices=add_blank_choice([]),
706
- # help_text="Sites available within snapshot",
707
- # widget=forms.Select(
708
- # attrs={"class": "form-control", "disabled": "disabled"}
709
- # ),
710
- # )
711
-
712
664
  tableChoices = [
713
665
  ("eol_details", "Inventory - EOL_DETAILS"),
714
666
  ("fans", "Inventory - FANS"),
@@ -0,0 +1,23 @@
1
+ from .schema import IPFabricDataQuery
2
+ from .schema import IPFabricIngestionIssueQuery
3
+ from .schema import IPFabricIngestionQuery
4
+ from .schema import IPFabricRelationshipFieldQuery
5
+ from .schema import IPFabricSnapshotQuery
6
+ from .schema import IPFabricSourceQuery
7
+ from .schema import IPFabricSyncQuery
8
+ from .schema import IPFabricTransformFieldQuery
9
+ from .schema import IPFabricTransformMapGroupQuery
10
+ from .schema import IPFabricTransformMapQuery
11
+
12
+ schema = [
13
+ IPFabricTransformMapGroupQuery,
14
+ IPFabricTransformMapQuery,
15
+ IPFabricTransformFieldQuery,
16
+ IPFabricRelationshipFieldQuery,
17
+ IPFabricSourceQuery,
18
+ IPFabricSnapshotQuery,
19
+ IPFabricSyncQuery,
20
+ IPFabricIngestionQuery,
21
+ IPFabricIngestionIssueQuery,
22
+ IPFabricDataQuery,
23
+ ]
@@ -0,0 +1,35 @@
1
+ import strawberry
2
+ from core.choices import DataSourceStatusChoices
3
+ from core.choices import JobStatusChoices
4
+ from netbox_branching.choices import BranchStatusChoices
5
+
6
+ from ipfabric_netbox.choices import IPFabricRawDataTypeChoices
7
+ from ipfabric_netbox.choices import IPFabricSnapshotStatusModelChoices
8
+ from ipfabric_netbox.choices import IPFabricSourceTypeChoices
9
+ from ipfabric_netbox.choices import IPFabricTransformMapSourceModelChoices
10
+
11
+ __all__ = (
12
+ "DataSourceStatusEnum",
13
+ "IPFabricTransformMapSourceModelEnum",
14
+ "IPFabricSourceTypeEnum",
15
+ "IPFabricSnapshotStatusModelEnum",
16
+ "IPFabricRawDataTypeEnum",
17
+ "BranchStatusEnum",
18
+ "JobStatusEnum",
19
+ )
20
+
21
+ DataSourceStatusEnum = strawberry.enum(DataSourceStatusChoices.as_enum(prefix="type"))
22
+ IPFabricTransformMapSourceModelEnum = strawberry.enum(
23
+ IPFabricTransformMapSourceModelChoices.as_enum(prefix="type")
24
+ )
25
+ IPFabricSourceTypeEnum = strawberry.enum(
26
+ IPFabricSourceTypeChoices.as_enum(prefix="type")
27
+ )
28
+ IPFabricSnapshotStatusModelEnum = strawberry.enum(
29
+ IPFabricSnapshotStatusModelChoices.as_enum(prefix="type")
30
+ )
31
+ IPFabricRawDataTypeEnum = strawberry.enum(
32
+ IPFabricRawDataTypeChoices.as_enum(prefix="type")
33
+ )
34
+ BranchStatusEnum = strawberry.enum(BranchStatusChoices.as_enum(prefix="type"))
35
+ JobStatusEnum = strawberry.enum(JobStatusChoices.as_enum(prefix="type"))