ipfabric_netbox 4.3.1b1__py3-none-any.whl → 4.3.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.
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/serializers.py +4 -2
- ipfabric_netbox/choices.py +36 -0
- ipfabric_netbox/filtersets.py +6 -2
- ipfabric_netbox/forms.py +7 -4
- ipfabric_netbox/graphql/enums.py +10 -3
- ipfabric_netbox/graphql/filters.py +4 -3
- ipfabric_netbox/jobs.py +6 -5
- ipfabric_netbox/models.py +27 -26
- ipfabric_netbox/tests/api/test_api.py +6 -5
- ipfabric_netbox/tests/test_forms.py +16 -15
- ipfabric_netbox/tests/test_views.py +24 -23
- ipfabric_netbox/utilities/ipfutils.py +2 -2
- {ipfabric_netbox-4.3.1b1.dist-info → ipfabric_netbox-4.3.1b2.dist-info}/METADATA +1 -1
- {ipfabric_netbox-4.3.1b1.dist-info → ipfabric_netbox-4.3.1b2.dist-info}/RECORD +16 -16
- {ipfabric_netbox-4.3.1b1.dist-info → ipfabric_netbox-4.3.1b2.dist-info}/WHEEL +0 -0
ipfabric_netbox/__init__.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
from core.choices import DataSourceStatusChoices
|
|
2
1
|
from django.contrib.contenttypes.models import ContentType
|
|
3
2
|
from netbox.api.fields import ChoiceField
|
|
4
3
|
from netbox.api.fields import ContentTypeField
|
|
@@ -7,6 +6,8 @@ from netbox.api.serializers import NestedGroupModelSerializer
|
|
|
7
6
|
from netbox_branching.api.serializers import BranchSerializer
|
|
8
7
|
from rest_framework import serializers
|
|
9
8
|
|
|
9
|
+
from ipfabric_netbox.choices import IPFabricSourceStatusChoices
|
|
10
|
+
from ipfabric_netbox.choices import IPFabricSyncStatusChoices
|
|
10
11
|
from ipfabric_netbox.models import IPFabricIngestion
|
|
11
12
|
from ipfabric_netbox.models import IPFabricIngestionIssue
|
|
12
13
|
from ipfabric_netbox.models import IPFabricRelationshipField
|
|
@@ -114,7 +115,7 @@ class IPFabricRelationshipFieldSerializer(NestedGroupModelSerializer):
|
|
|
114
115
|
|
|
115
116
|
|
|
116
117
|
class IPFabricSourceSerializer(NestedGroupModelSerializer):
|
|
117
|
-
status = ChoiceField(choices=
|
|
118
|
+
status = ChoiceField(choices=IPFabricSourceStatusChoices, read_only=True)
|
|
118
119
|
url = serializers.URLField()
|
|
119
120
|
|
|
120
121
|
class Meta:
|
|
@@ -175,6 +176,7 @@ class IPFabricSnapshotSerializer(NestedGroupModelSerializer):
|
|
|
175
176
|
|
|
176
177
|
|
|
177
178
|
class IPFabricSyncSerializer(NestedGroupModelSerializer):
|
|
179
|
+
status = ChoiceField(choices=IPFabricSyncStatusChoices, read_only=True)
|
|
178
180
|
snapshot_data = IPFabricSnapshotSerializer(nested=True)
|
|
179
181
|
parameters = serializers.JSONField()
|
|
180
182
|
|
ipfabric_netbox/choices.py
CHANGED
|
@@ -229,3 +229,39 @@ class IPFabricRawDataTypeChoices(ChoiceSet):
|
|
|
229
229
|
(IPADDRESS, "IP Address", "gray"),
|
|
230
230
|
(SITE, "Site", "gray"),
|
|
231
231
|
)
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
class IPFabricSourceStatusChoices(ChoiceSet):
|
|
235
|
+
NEW = "new"
|
|
236
|
+
QUEUED = "queued"
|
|
237
|
+
SYNCING = "syncing"
|
|
238
|
+
COMPLETED = "completed"
|
|
239
|
+
FAILED = "failed"
|
|
240
|
+
|
|
241
|
+
CHOICES = (
|
|
242
|
+
(NEW, _("New"), "blue"),
|
|
243
|
+
(QUEUED, _("Queued"), "orange"),
|
|
244
|
+
(SYNCING, _("Syncing"), "cyan"),
|
|
245
|
+
(COMPLETED, _("Completed"), "green"),
|
|
246
|
+
(FAILED, _("Failed"), "red"),
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
class IPFabricSyncStatusChoices(ChoiceSet):
|
|
251
|
+
NEW = "new"
|
|
252
|
+
QUEUED = "queued"
|
|
253
|
+
SYNCING = "syncing"
|
|
254
|
+
READY_TO_MERGE = "ready_to_merge"
|
|
255
|
+
MERGING = "merging"
|
|
256
|
+
COMPLETED = "completed"
|
|
257
|
+
FAILED = "failed"
|
|
258
|
+
|
|
259
|
+
CHOICES = (
|
|
260
|
+
(NEW, _("New"), "blue"),
|
|
261
|
+
(QUEUED, _("Queued"), "orange"),
|
|
262
|
+
(SYNCING, _("Syncing"), "cyan"),
|
|
263
|
+
(READY_TO_MERGE, _("Ready to merge"), "purple"),
|
|
264
|
+
(MERGING, _("Merging"), "cyan"),
|
|
265
|
+
(COMPLETED, _("Completed"), "green"),
|
|
266
|
+
(FAILED, _("Failed"), "red"),
|
|
267
|
+
)
|
ipfabric_netbox/filtersets.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import django_filters
|
|
2
|
-
from core.choices import DataSourceStatusChoices
|
|
3
2
|
from core.choices import ObjectChangeActionChoices
|
|
4
3
|
from django.db.models import Q
|
|
5
4
|
from django.utils.translation import gettext as _
|
|
@@ -8,6 +7,8 @@ from netbox.filtersets import ChangeLoggedModelFilterSet
|
|
|
8
7
|
from netbox.filtersets import NetBoxModelFilterSet
|
|
9
8
|
from netbox_branching.models import ChangeDiff
|
|
10
9
|
|
|
10
|
+
from .choices import IPFabricSourceStatusChoices
|
|
11
|
+
from .choices import IPFabricSyncStatusChoices
|
|
11
12
|
from .models import IPFabricData
|
|
12
13
|
from .models import IPFabricIngestion
|
|
13
14
|
from .models import IPFabricIngestionIssue
|
|
@@ -110,7 +111,7 @@ class IPFabricSnapshotFilterSet(ChangeLoggedModelFilterSet):
|
|
|
110
111
|
|
|
111
112
|
class IPFabricSourceFilterSet(NetBoxModelFilterSet):
|
|
112
113
|
status = django_filters.MultipleChoiceFilter(
|
|
113
|
-
choices=
|
|
114
|
+
choices=IPFabricSourceStatusChoices, null_value=None
|
|
114
115
|
)
|
|
115
116
|
|
|
116
117
|
class Meta:
|
|
@@ -235,6 +236,9 @@ class IPFabricSyncFilterSet(ChangeLoggedModelFilterSet):
|
|
|
235
236
|
to_field_name="name",
|
|
236
237
|
label=_("Snapshot (name)"),
|
|
237
238
|
)
|
|
239
|
+
status = django_filters.MultipleChoiceFilter(
|
|
240
|
+
choices=IPFabricSyncStatusChoices, null_value=None
|
|
241
|
+
)
|
|
238
242
|
|
|
239
243
|
class Meta:
|
|
240
244
|
model = IPFabricSync
|
ipfabric_netbox/forms.py
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import copy
|
|
2
2
|
|
|
3
|
-
from core.choices import DataSourceStatusChoices
|
|
4
3
|
from core.choices import JobIntervalChoices
|
|
5
4
|
from django import forms
|
|
6
5
|
from django.contrib.contenttypes.models import ContentType
|
|
@@ -31,7 +30,9 @@ from utilities.forms.widgets import HTMXSelect
|
|
|
31
30
|
from utilities.forms.widgets import NumberWithOptions
|
|
32
31
|
|
|
33
32
|
from .choices import IPFabricSnapshotStatusModelChoices
|
|
33
|
+
from .choices import IPFabricSourceStatusChoices
|
|
34
34
|
from .choices import IPFabricSourceTypeChoices
|
|
35
|
+
from .choices import IPFabricSyncStatusChoices
|
|
35
36
|
from .choices import IPFabricTransformMapSourceModelChoices
|
|
36
37
|
from .choices import required_transform_map_contenttypes
|
|
37
38
|
from .choices import transform_field_source_columns
|
|
@@ -383,7 +384,9 @@ class IPFabricSourceFilterForm(NetBoxModelFilterSetForm):
|
|
|
383
384
|
FieldSet("q", "filter_id"),
|
|
384
385
|
FieldSet("status", name=_("Source")),
|
|
385
386
|
)
|
|
386
|
-
status = forms.MultipleChoiceField(
|
|
387
|
+
status = forms.MultipleChoiceField(
|
|
388
|
+
choices=IPFabricSourceStatusChoices, required=False
|
|
389
|
+
)
|
|
387
390
|
|
|
388
391
|
|
|
389
392
|
class IPFabricIngestionFilterForm(SavedFiltersMixin, FilterForm):
|
|
@@ -481,7 +484,7 @@ class IPFabricSourceForm(NetBoxModelForm):
|
|
|
481
484
|
parameters["timeout"] = self.cleaned_data[name]
|
|
482
485
|
|
|
483
486
|
self.instance.parameters = parameters
|
|
484
|
-
self.instance.status =
|
|
487
|
+
self.instance.status = IPFabricSourceStatusChoices.NEW
|
|
485
488
|
|
|
486
489
|
instance = super().save(*args, **kwargs)
|
|
487
490
|
|
|
@@ -801,7 +804,7 @@ class IPFabricSyncForm(NetBoxModelForm):
|
|
|
801
804
|
group.pk for group in self.cleaned_data["groups"]
|
|
802
805
|
]
|
|
803
806
|
self.instance.parameters = parameters
|
|
804
|
-
self.instance.status =
|
|
807
|
+
self.instance.status = IPFabricSyncStatusChoices.NEW
|
|
805
808
|
return super().save(*args, **kwargs)
|
|
806
809
|
|
|
807
810
|
|
ipfabric_netbox/graphql/enums.py
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import strawberry
|
|
2
|
-
from core.choices import DataSourceStatusChoices
|
|
3
2
|
from core.choices import JobStatusChoices
|
|
4
3
|
from netbox_branching.choices import BranchStatusChoices
|
|
5
4
|
|
|
6
5
|
from ipfabric_netbox.choices import IPFabricRawDataTypeChoices
|
|
7
6
|
from ipfabric_netbox.choices import IPFabricSnapshotStatusModelChoices
|
|
7
|
+
from ipfabric_netbox.choices import IPFabricSourceStatusChoices
|
|
8
8
|
from ipfabric_netbox.choices import IPFabricSourceTypeChoices
|
|
9
|
+
from ipfabric_netbox.choices import IPFabricSyncStatusChoices
|
|
9
10
|
from ipfabric_netbox.choices import IPFabricTransformMapSourceModelChoices
|
|
10
11
|
|
|
11
12
|
__all__ = (
|
|
12
|
-
"
|
|
13
|
+
"IPFabricSourceStatusEnum",
|
|
14
|
+
"IPFabricSyncStatusEnum",
|
|
13
15
|
"IPFabricTransformMapSourceModelEnum",
|
|
14
16
|
"IPFabricSourceTypeEnum",
|
|
15
17
|
"IPFabricSnapshotStatusModelEnum",
|
|
@@ -18,7 +20,12 @@ __all__ = (
|
|
|
18
20
|
"JobStatusEnum",
|
|
19
21
|
)
|
|
20
22
|
|
|
21
|
-
|
|
23
|
+
IPFabricSourceStatusEnum = strawberry.enum(
|
|
24
|
+
IPFabricSourceStatusChoices.as_enum(prefix="type")
|
|
25
|
+
)
|
|
26
|
+
IPFabricSyncStatusEnum = strawberry.enum(
|
|
27
|
+
IPFabricSyncStatusChoices.as_enum(prefix="type")
|
|
28
|
+
)
|
|
22
29
|
IPFabricTransformMapSourceModelEnum = strawberry.enum(
|
|
23
30
|
IPFabricTransformMapSourceModelChoices.as_enum(prefix="type")
|
|
24
31
|
)
|
|
@@ -21,10 +21,11 @@ from users.graphql.filters import UserFilter
|
|
|
21
21
|
|
|
22
22
|
from ipfabric_netbox import models
|
|
23
23
|
from ipfabric_netbox.graphql.enums import BranchStatusEnum
|
|
24
|
-
from ipfabric_netbox.graphql.enums import DataSourceStatusEnum
|
|
25
24
|
from ipfabric_netbox.graphql.enums import IPFabricRawDataTypeEnum
|
|
26
25
|
from ipfabric_netbox.graphql.enums import IPFabricSnapshotStatusModelEnum
|
|
26
|
+
from ipfabric_netbox.graphql.enums import IPFabricSourceStatusEnum
|
|
27
27
|
from ipfabric_netbox.graphql.enums import IPFabricSourceTypeEnum
|
|
28
|
+
from ipfabric_netbox.graphql.enums import IPFabricSyncStatusEnum
|
|
28
29
|
from ipfabric_netbox.graphql.enums import IPFabricTransformMapSourceModelEnum
|
|
29
30
|
from ipfabric_netbox.graphql.enums import JobStatusEnum
|
|
30
31
|
|
|
@@ -127,7 +128,7 @@ class IPFabricSourceFilter(PrimaryModelFilterMixin):
|
|
|
127
128
|
url: FilterLookup[str] | None = strawberry_django.filter_field()
|
|
128
129
|
status: (
|
|
129
130
|
Annotated[
|
|
130
|
-
"
|
|
131
|
+
"IPFabricSourceStatusEnum", strawberry.lazy("ipfabric_netbox.graphql.enums")
|
|
131
132
|
]
|
|
132
133
|
| None
|
|
133
134
|
) = strawberry_django.filter_field()
|
|
@@ -179,7 +180,7 @@ class IPFabricSyncFilter(TagsFilterMixin, ChangeLogFilterMixin, BaseFilterMixin)
|
|
|
179
180
|
) = strawberry_django.filter_field()
|
|
180
181
|
status: (
|
|
181
182
|
Annotated[
|
|
182
|
-
"
|
|
183
|
+
"IPFabricSyncStatusEnum", strawberry.lazy("ipfabric_netbox.graphql.enums")
|
|
183
184
|
]
|
|
184
185
|
| None
|
|
185
186
|
) = strawberry_django.filter_field()
|
ipfabric_netbox/jobs.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from datetime import timedelta
|
|
3
3
|
|
|
4
|
-
from core.choices import DataSourceStatusChoices
|
|
5
4
|
from core.choices import JobStatusChoices
|
|
6
5
|
from core.exceptions import SyncError
|
|
7
6
|
from netbox.context_managers import event_tracking
|
|
@@ -9,6 +8,8 @@ from rq.timeouts import JobTimeoutException
|
|
|
9
8
|
from utilities.datetime import local_now
|
|
10
9
|
from utilities.request import NetBoxFakeRequest
|
|
11
10
|
|
|
11
|
+
from .choices import IPFabricSourceStatusChoices
|
|
12
|
+
from .choices import IPFabricSyncStatusChoices
|
|
12
13
|
from .models import IPFabricIngestion
|
|
13
14
|
from .models import IPFabricSource
|
|
14
15
|
from .models import IPFabricSync
|
|
@@ -26,7 +27,7 @@ def sync_ipfabricsource(job, *args, **kwargs):
|
|
|
26
27
|
except Exception as e:
|
|
27
28
|
job.terminate(status=JobStatusChoices.STATUS_ERRORED)
|
|
28
29
|
IPFabricSource.objects.filter(pk=ipfsource.pk).update(
|
|
29
|
-
status=
|
|
30
|
+
status=IPFabricSourceStatusChoices.FAILED
|
|
30
31
|
)
|
|
31
32
|
if type(e) in (SyncError, JobTimeoutException):
|
|
32
33
|
logging.error(e)
|
|
@@ -44,7 +45,7 @@ def sync_ipfabric(job, *args, **kwargs):
|
|
|
44
45
|
except Exception as e:
|
|
45
46
|
job.terminate(status=JobStatusChoices.STATUS_ERRORED)
|
|
46
47
|
IPFabricSync.objects.filter(pk=sync.pk).update(
|
|
47
|
-
status=
|
|
48
|
+
status=IPFabricSyncStatusChoices.FAILED
|
|
48
49
|
)
|
|
49
50
|
if type(e) in (SyncError, JobTimeoutException):
|
|
50
51
|
logging.error(e)
|
|
@@ -90,7 +91,7 @@ def sync_ipfabric(job, *args, **kwargs):
|
|
|
90
91
|
|
|
91
92
|
with event_tracking(request):
|
|
92
93
|
sync.scheduled = new_scheduled_time
|
|
93
|
-
sync.status =
|
|
94
|
+
sync.status = IPFabricSyncStatusChoices.QUEUED
|
|
94
95
|
sync.full_clean()
|
|
95
96
|
sync.save()
|
|
96
97
|
logger.info(
|
|
@@ -126,7 +127,7 @@ def merge_ipfabric_ingestion(job, remove_branch=False, *args, **kwargs):
|
|
|
126
127
|
print(e)
|
|
127
128
|
job.terminate(status=JobStatusChoices.STATUS_ERRORED)
|
|
128
129
|
IPFabricSync.objects.filter(pk=ingestion.sync.pk).update(
|
|
129
|
-
status=
|
|
130
|
+
status=IPFabricSyncStatusChoices.FAILED
|
|
130
131
|
)
|
|
131
132
|
if type(e) in (SyncError, JobTimeoutException):
|
|
132
133
|
logging.error(e)
|
ipfabric_netbox/models.py
CHANGED
|
@@ -7,7 +7,6 @@ from copy import deepcopy
|
|
|
7
7
|
from uuid import uuid4
|
|
8
8
|
|
|
9
9
|
import httpx
|
|
10
|
-
from core.choices import DataSourceStatusChoices
|
|
11
10
|
from core.choices import JobStatusChoices
|
|
12
11
|
from core.exceptions import SyncError
|
|
13
12
|
from core.models import Job
|
|
@@ -46,7 +45,9 @@ from utilities.request import NetBoxFakeRequest
|
|
|
46
45
|
|
|
47
46
|
from .choices import IPFabricRawDataTypeChoices
|
|
48
47
|
from .choices import IPFabricSnapshotStatusModelChoices
|
|
48
|
+
from .choices import IPFabricSourceStatusChoices
|
|
49
49
|
from .choices import IPFabricSourceTypeChoices
|
|
50
|
+
from .choices import IPFabricSyncStatusChoices
|
|
50
51
|
from .choices import IPFabricTransformMapSourceModelChoices
|
|
51
52
|
from .choices import required_transform_map_contenttypes
|
|
52
53
|
from .signals import clear_other_primary_ip
|
|
@@ -418,7 +419,7 @@ class IPFabricClient:
|
|
|
418
419
|
self.handle_sync_failure("Error", e)
|
|
419
420
|
|
|
420
421
|
def handle_sync_failure(self, failure_type, exception, message=None):
|
|
421
|
-
self.status =
|
|
422
|
+
self.status = IPFabricSyncStatusChoices.FAILED
|
|
422
423
|
|
|
423
424
|
if message:
|
|
424
425
|
self.logger.log_failure(
|
|
@@ -439,8 +440,8 @@ class IPFabricSource(IPFabricClient, JobsMixin, PrimaryModel):
|
|
|
439
440
|
url = models.CharField(max_length=200, verbose_name=_("URL"))
|
|
440
441
|
status = models.CharField(
|
|
441
442
|
max_length=50,
|
|
442
|
-
choices=
|
|
443
|
-
default=
|
|
443
|
+
choices=IPFabricSourceStatusChoices,
|
|
444
|
+
default=IPFabricSourceStatusChoices.NEW,
|
|
444
445
|
editable=False,
|
|
445
446
|
)
|
|
446
447
|
parameters = models.JSONField(blank=True, null=True)
|
|
@@ -460,8 +461,8 @@ class IPFabricSource(IPFabricClient, JobsMixin, PrimaryModel):
|
|
|
460
461
|
@property
|
|
461
462
|
def ready_for_sync(self):
|
|
462
463
|
return self.status not in (
|
|
463
|
-
|
|
464
|
-
|
|
464
|
+
IPFabricSourceStatusChoices.QUEUED,
|
|
465
|
+
IPFabricSourceStatusChoices.SYNCING,
|
|
465
466
|
)
|
|
466
467
|
|
|
467
468
|
@property
|
|
@@ -476,7 +477,7 @@ class IPFabricSource(IPFabricClient, JobsMixin, PrimaryModel):
|
|
|
476
477
|
|
|
477
478
|
def enqueue_sync_job(self, request):
|
|
478
479
|
# Set the status to "syncing"
|
|
479
|
-
self.status =
|
|
480
|
+
self.status = IPFabricSourceStatusChoices.QUEUED
|
|
480
481
|
IPFabricSource.objects.filter(pk=self.pk).update(status=self.status)
|
|
481
482
|
|
|
482
483
|
# Enqueue a sync job
|
|
@@ -489,7 +490,7 @@ class IPFabricSource(IPFabricClient, JobsMixin, PrimaryModel):
|
|
|
489
490
|
|
|
490
491
|
def sync(self, job):
|
|
491
492
|
self.logger = SyncLogging(job=job.pk)
|
|
492
|
-
if self.status ==
|
|
493
|
+
if self.status == IPFabricSourceStatusChoices.SYNCING:
|
|
493
494
|
self.logger.log_failure(
|
|
494
495
|
"Cannot initiate sync; syncing already in progress.", obj=self
|
|
495
496
|
)
|
|
@@ -497,7 +498,7 @@ class IPFabricSource(IPFabricClient, JobsMixin, PrimaryModel):
|
|
|
497
498
|
|
|
498
499
|
pre_sync.send(sender=self.__class__, instance=self)
|
|
499
500
|
|
|
500
|
-
self.status =
|
|
501
|
+
self.status = IPFabricSourceStatusChoices.SYNCING
|
|
501
502
|
IPFabricSource.objects.filter(pk=self.pk).update(status=self.status)
|
|
502
503
|
|
|
503
504
|
# Begin Sync
|
|
@@ -542,7 +543,7 @@ class IPFabricSource(IPFabricClient, JobsMixin, PrimaryModel):
|
|
|
542
543
|
f"Created/Updated Snapshot {snapshot.name} ({snapshot.snapshot_id})",
|
|
543
544
|
obj=snapshot, # noqa E225
|
|
544
545
|
)
|
|
545
|
-
self.status =
|
|
546
|
+
self.status = IPFabricSourceStatusChoices.COMPLETED
|
|
546
547
|
self.logger.log_success(f"Completed syncing snapshots from {self.name}")
|
|
547
548
|
logger.debug(f"Completed syncing snapshots from {self.url}")
|
|
548
549
|
except Exception as e:
|
|
@@ -621,8 +622,8 @@ class IPFabricSync(IPFabricClient, JobsMixin, TagsMixin, ChangeLoggedModel):
|
|
|
621
622
|
)
|
|
622
623
|
status = models.CharField(
|
|
623
624
|
max_length=50,
|
|
624
|
-
choices=
|
|
625
|
-
default=
|
|
625
|
+
choices=IPFabricSyncStatusChoices,
|
|
626
|
+
default=IPFabricSyncStatusChoices.NEW,
|
|
626
627
|
editable=False,
|
|
627
628
|
)
|
|
628
629
|
parameters = models.JSONField(blank=True, null=True)
|
|
@@ -668,7 +669,7 @@ class IPFabricSync(IPFabricClient, JobsMixin, TagsMixin, ChangeLoggedModel):
|
|
|
668
669
|
return reverse("plugins:ipfabric_netbox:ipfabricsync", args=[self.pk])
|
|
669
670
|
|
|
670
671
|
def get_status_color(self):
|
|
671
|
-
return
|
|
672
|
+
return IPFabricSyncStatusChoices.colors.get(self.status)
|
|
672
673
|
|
|
673
674
|
def save(self, *args, **kwargs):
|
|
674
675
|
super().save(*args, **kwargs)
|
|
@@ -677,7 +678,7 @@ class IPFabricSync(IPFabricClient, JobsMixin, TagsMixin, ChangeLoggedModel):
|
|
|
677
678
|
|
|
678
679
|
@property
|
|
679
680
|
def ready_for_sync(self):
|
|
680
|
-
if self.status not in (
|
|
681
|
+
if self.status not in (IPFabricSyncStatusChoices.SYNCING,):
|
|
681
682
|
if self.snapshot_data.source.type == "remote":
|
|
682
683
|
if self.snapshot_data.ipf_data.count() > 0:
|
|
683
684
|
return True
|
|
@@ -723,7 +724,7 @@ class IPFabricSync(IPFabricClient, JobsMixin, TagsMixin, ChangeLoggedModel):
|
|
|
723
724
|
|
|
724
725
|
def enqueue_sync_job(self, adhoc=False, user=None) -> Job | None:
|
|
725
726
|
def set_syncing_status():
|
|
726
|
-
self.status =
|
|
727
|
+
self.status = IPFabricSyncStatusChoices.QUEUED
|
|
727
728
|
IPFabricSync.objects.filter(pk=self.pk).update(status=self.status)
|
|
728
729
|
|
|
729
730
|
def sync_snapshots():
|
|
@@ -794,12 +795,12 @@ class IPFabricSync(IPFabricClient, JobsMixin, TagsMixin, ChangeLoggedModel):
|
|
|
794
795
|
f"Combination of these transform map groups failed validation. Missing maps: {missing}."
|
|
795
796
|
)
|
|
796
797
|
|
|
797
|
-
if self.status ==
|
|
798
|
+
if self.status == IPFabricSyncStatusChoices.SYNCING:
|
|
798
799
|
raise SyncError("Cannot initiate sync; ingestion already in progress.")
|
|
799
800
|
|
|
800
801
|
pre_sync.send(sender=self.__class__, instance=self)
|
|
801
802
|
|
|
802
|
-
self.status =
|
|
803
|
+
self.status = IPFabricSyncStatusChoices.SYNCING
|
|
803
804
|
IPFabricSync.objects.filter(pk=self.pk).update(status=self.status)
|
|
804
805
|
|
|
805
806
|
# Begin Sync
|
|
@@ -875,11 +876,11 @@ class IPFabricSync(IPFabricClient, JobsMixin, TagsMixin, ChangeLoggedModel):
|
|
|
875
876
|
current_request.set(token.old_value)
|
|
876
877
|
active_branch.set(current_branch)
|
|
877
878
|
|
|
878
|
-
if self.status !=
|
|
879
|
-
self.status =
|
|
879
|
+
if self.status != IPFabricSyncStatusChoices.FAILED:
|
|
880
|
+
self.status = IPFabricSyncStatusChoices.READY_TO_MERGE
|
|
880
881
|
|
|
881
882
|
except Exception as e:
|
|
882
|
-
self.status =
|
|
883
|
+
self.status = IPFabricSyncStatusChoices.FAILED
|
|
883
884
|
self.logger.log_failure(f"Ingestion Failed: `{e}`", obj=ingestion)
|
|
884
885
|
self.logger.log_failure(
|
|
885
886
|
f"Stack Trace: `{traceback.format_exc()}`", obj=ingestion
|
|
@@ -893,7 +894,7 @@ class IPFabricSync(IPFabricClient, JobsMixin, TagsMixin, ChangeLoggedModel):
|
|
|
893
894
|
|
|
894
895
|
self.last_synced = timezone.now()
|
|
895
896
|
|
|
896
|
-
if self.auto_merge and self.status ==
|
|
897
|
+
if self.auto_merge and self.status == IPFabricSyncStatusChoices.READY_TO_MERGE:
|
|
897
898
|
self.logger.log_info("Auto Merging Ingestion", obj=ingestion)
|
|
898
899
|
logger.info("Auto Merging Ingestion")
|
|
899
900
|
try:
|
|
@@ -947,7 +948,7 @@ class IPFabricIngestion(JobsMixin, models.Model):
|
|
|
947
948
|
|
|
948
949
|
def enqueue_merge_job(self, user, remove_branch=False):
|
|
949
950
|
# Set the status to "queued"
|
|
950
|
-
self.status =
|
|
951
|
+
self.status = IPFabricSyncStatusChoices.QUEUED
|
|
951
952
|
IPFabricSync.objects.filter(ipfabricingestion=self.pk).update(
|
|
952
953
|
status=self.status
|
|
953
954
|
)
|
|
@@ -988,12 +989,12 @@ class IPFabricIngestion(JobsMixin, models.Model):
|
|
|
988
989
|
|
|
989
990
|
def sync_merge(self):
|
|
990
991
|
ipfabricsync = self.sync
|
|
991
|
-
if ipfabricsync.status ==
|
|
992
|
+
if ipfabricsync.status == IPFabricSyncStatusChoices.MERGING:
|
|
992
993
|
raise SyncError("Cannot initiate merge; merge already in progress.")
|
|
993
994
|
|
|
994
995
|
pre_sync.send(sender=self.__class__, instance=self)
|
|
995
996
|
|
|
996
|
-
ipfabricsync.status =
|
|
997
|
+
ipfabricsync.status = IPFabricSyncStatusChoices.MERGING
|
|
997
998
|
IPFabricSync.objects.filter(ipfabricingestion=self.pk).update(
|
|
998
999
|
status=self.sync.status
|
|
999
1000
|
)
|
|
@@ -1010,9 +1011,9 @@ class IPFabricIngestion(JobsMixin, models.Model):
|
|
|
1010
1011
|
assign_virtualchassis_master, sender=VirtualChassis
|
|
1011
1012
|
)
|
|
1012
1013
|
signals.pre_save.disconnect(clear_other_primary_ip, sender=Device)
|
|
1013
|
-
ipfabricsync.status =
|
|
1014
|
+
ipfabricsync.status = IPFabricSyncStatusChoices.COMPLETED
|
|
1014
1015
|
except Exception as e:
|
|
1015
|
-
ipfabricsync.status =
|
|
1016
|
+
ipfabricsync.status = IPFabricSyncStatusChoices.FAILED
|
|
1016
1017
|
logger.debug(f"Merging {self.name} Failed: `{e}`")
|
|
1017
1018
|
|
|
1018
1019
|
logger.debug(f"Completed merge {self.name}")
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
from core.choices import DataSourceStatusChoices
|
|
2
1
|
from django.contrib.contenttypes.models import ContentType
|
|
3
2
|
from django.utils import timezone
|
|
4
3
|
from rest_framework import status
|
|
5
4
|
from utilities.testing import APIViewTestCases
|
|
6
5
|
|
|
6
|
+
from ipfabric_netbox.choices import IPFabricSourceStatusChoices
|
|
7
|
+
from ipfabric_netbox.choices import IPFabricSyncStatusChoices
|
|
7
8
|
from ipfabric_netbox.models import IPFabricData
|
|
8
9
|
from ipfabric_netbox.models import IPFabricIngestion
|
|
9
10
|
from ipfabric_netbox.models import IPFabricIngestionIssue
|
|
@@ -397,7 +398,7 @@ class IPFabricSourceTest(APIViewTestCases.APIViewTestCase):
|
|
|
397
398
|
# Get the first source from setUpTestData
|
|
398
399
|
source = IPFabricSource.objects.first()
|
|
399
400
|
# Set status to make ready_for_sync return True
|
|
400
|
-
source.status =
|
|
401
|
+
source.status = IPFabricSourceStatusChoices.COMPLETED
|
|
401
402
|
source.save()
|
|
402
403
|
|
|
403
404
|
with self.settings(CELERY_TASK_ALWAYS_EAGER=True):
|
|
@@ -437,7 +438,7 @@ class IPFabricSourceTest(APIViewTestCases.APIViewTestCase):
|
|
|
437
438
|
|
|
438
439
|
source = IPFabricSource.objects.first()
|
|
439
440
|
# Set status to make ready_for_sync return False
|
|
440
|
-
source.status =
|
|
441
|
+
source.status = IPFabricSourceStatusChoices.SYNCING
|
|
441
442
|
source.save()
|
|
442
443
|
|
|
443
444
|
url = f"{BASE}/source/{source.pk}/sync/"
|
|
@@ -707,7 +708,7 @@ class IPFabricSyncTest(APIViewTestCases.APIViewTestCase):
|
|
|
707
708
|
# Get the first sync from setUpTestData
|
|
708
709
|
sync = IPFabricSync.objects.first()
|
|
709
710
|
# Set status and ensure snapshot has data to make ready_for_sync return True
|
|
710
|
-
sync.status =
|
|
711
|
+
sync.status = IPFabricSyncStatusChoices.COMPLETED
|
|
711
712
|
sync.save()
|
|
712
713
|
|
|
713
714
|
# Ensure the snapshot has data
|
|
@@ -753,7 +754,7 @@ class IPFabricSyncTest(APIViewTestCases.APIViewTestCase):
|
|
|
753
754
|
|
|
754
755
|
sync = IPFabricSync.objects.first()
|
|
755
756
|
# Set status to make ready_for_sync return False
|
|
756
|
-
sync.status =
|
|
757
|
+
sync.status = IPFabricSyncStatusChoices.SYNCING
|
|
757
758
|
sync.save()
|
|
758
759
|
|
|
759
760
|
url = f"{BASE}/sync/{sync.pk}/sync/"
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
from datetime import timedelta
|
|
2
2
|
from unittest.mock import patch
|
|
3
3
|
|
|
4
|
-
from core.choices import DataSourceStatusChoices
|
|
5
4
|
from dcim.models import Device
|
|
6
5
|
from dcim.models import Site
|
|
7
6
|
from django.contrib.contenttypes.models import ContentType
|
|
@@ -9,7 +8,9 @@ from django.test import TestCase
|
|
|
9
8
|
from utilities.datetime import local_now
|
|
10
9
|
|
|
11
10
|
from ipfabric_netbox.choices import IPFabricSnapshotStatusModelChoices
|
|
11
|
+
from ipfabric_netbox.choices import IPFabricSourceStatusChoices
|
|
12
12
|
from ipfabric_netbox.choices import IPFabricSourceTypeChoices
|
|
13
|
+
from ipfabric_netbox.choices import IPFabricSyncStatusChoices
|
|
13
14
|
from ipfabric_netbox.forms import IPFabricIngestionFilterForm
|
|
14
15
|
from ipfabric_netbox.forms import IPFabricIngestionMergeForm
|
|
15
16
|
from ipfabric_netbox.forms import IPFabricRelationshipFieldForm
|
|
@@ -38,7 +39,7 @@ class IPFabricSourceFormTestCase(TestCase):
|
|
|
38
39
|
name="Test IP Fabric Source",
|
|
39
40
|
type=IPFabricSourceTypeChoices.LOCAL,
|
|
40
41
|
url="https://test.ipfabric.local",
|
|
41
|
-
status=
|
|
42
|
+
status=IPFabricSourceStatusChoices.NEW,
|
|
42
43
|
parameters={"auth": "test_token", "verify": True, "timeout": 30},
|
|
43
44
|
)
|
|
44
45
|
|
|
@@ -134,7 +135,7 @@ class IPFabricSourceFormTestCase(TestCase):
|
|
|
134
135
|
)
|
|
135
136
|
self.assertTrue(form.is_valid(), form.errors)
|
|
136
137
|
instance = form.save()
|
|
137
|
-
self.assertEqual(instance.status,
|
|
138
|
+
self.assertEqual(instance.status, IPFabricSourceStatusChoices.NEW)
|
|
138
139
|
|
|
139
140
|
def test_form_initializes_existing_parameters(self):
|
|
140
141
|
# Test that form properly initializes with existing instance parameters
|
|
@@ -339,7 +340,7 @@ class IPFabricRelationshipFieldFormTestCase(TestCase):
|
|
|
339
340
|
name="Test Source",
|
|
340
341
|
type=IPFabricSourceTypeChoices.LOCAL,
|
|
341
342
|
url="https://test.ipfabric.local",
|
|
342
|
-
status=
|
|
343
|
+
status=IPFabricSourceStatusChoices.NEW,
|
|
343
344
|
)
|
|
344
345
|
|
|
345
346
|
cls.transform_map_group = IPFabricTransformMapGroup.objects.create(
|
|
@@ -453,7 +454,7 @@ class IPFabricTransformFieldFormTestCase(TestCase):
|
|
|
453
454
|
name="Test Source",
|
|
454
455
|
type=IPFabricSourceTypeChoices.LOCAL,
|
|
455
456
|
url="https://test.ipfabric.local",
|
|
456
|
-
status=
|
|
457
|
+
status=IPFabricSourceStatusChoices.NEW,
|
|
457
458
|
)
|
|
458
459
|
|
|
459
460
|
cls.transform_map_group = IPFabricTransformMapGroup.objects.create(
|
|
@@ -671,7 +672,7 @@ class IPFabricSnapshotFilterFormTestCase(TestCase):
|
|
|
671
672
|
name="Test Source",
|
|
672
673
|
type=IPFabricSourceTypeChoices.LOCAL,
|
|
673
674
|
url="https://test.ipfabric.local",
|
|
674
|
-
status=
|
|
675
|
+
status=IPFabricSourceStatusChoices.NEW,
|
|
675
676
|
)
|
|
676
677
|
|
|
677
678
|
def test_all_fields_are_optional(self):
|
|
@@ -699,8 +700,8 @@ class IPFabricSourceFilterFormTestCase(TestCase):
|
|
|
699
700
|
form = IPFabricSourceFilterForm(
|
|
700
701
|
data={
|
|
701
702
|
"status": [
|
|
702
|
-
|
|
703
|
-
|
|
703
|
+
IPFabricSourceStatusChoices.NEW,
|
|
704
|
+
IPFabricSourceStatusChoices.COMPLETED,
|
|
704
705
|
]
|
|
705
706
|
}
|
|
706
707
|
)
|
|
@@ -714,7 +715,7 @@ class IPFabricIngestionFilterFormTestCase(TestCase):
|
|
|
714
715
|
name="Test Source",
|
|
715
716
|
type=IPFabricSourceTypeChoices.LOCAL,
|
|
716
717
|
url="https://test.ipfabric.local",
|
|
717
|
-
status=
|
|
718
|
+
status=IPFabricSourceStatusChoices.NEW,
|
|
718
719
|
)
|
|
719
720
|
|
|
720
721
|
cls.snapshot = IPFabricSnapshot.objects.create(
|
|
@@ -762,7 +763,7 @@ class IPFabricSyncFormTestCase(TestCase):
|
|
|
762
763
|
name="Test Source",
|
|
763
764
|
type=IPFabricSourceTypeChoices.LOCAL,
|
|
764
765
|
url="https://test.ipfabric.local",
|
|
765
|
-
status=
|
|
766
|
+
status=IPFabricSourceStatusChoices.NEW,
|
|
766
767
|
)
|
|
767
768
|
|
|
768
769
|
cls.snapshot = IPFabricSnapshot.objects.create(
|
|
@@ -1017,7 +1018,7 @@ class IPFabricSyncFormTestCase(TestCase):
|
|
|
1017
1018
|
name="Different Source",
|
|
1018
1019
|
type=IPFabricSourceTypeChoices.LOCAL,
|
|
1019
1020
|
url="https://different.ipfabric.local",
|
|
1020
|
-
status=
|
|
1021
|
+
status=IPFabricSourceStatusChoices.NEW,
|
|
1021
1022
|
)
|
|
1022
1023
|
|
|
1023
1024
|
# Try to use self.snapshot (which belongs to self.source) with different_source
|
|
@@ -1179,7 +1180,7 @@ class IPFabricSyncFormTestCase(TestCase):
|
|
|
1179
1180
|
self.assertEqual(sync_instance.name, "Test Sync Save")
|
|
1180
1181
|
self.assertEqual(sync_instance.snapshot_data.source, self.source)
|
|
1181
1182
|
self.assertEqual(sync_instance.snapshot_data, self.snapshot)
|
|
1182
|
-
self.assertEqual(sync_instance.status,
|
|
1183
|
+
self.assertEqual(sync_instance.status, IPFabricSyncStatusChoices.NEW)
|
|
1183
1184
|
self.assertTrue(sync_instance.auto_merge)
|
|
1184
1185
|
self.assertTrue(sync_instance.update_custom_fields)
|
|
1185
1186
|
|
|
@@ -1364,11 +1365,11 @@ class IPFabricSyncFormTestCase(TestCase):
|
|
|
1364
1365
|
sync_instance = form.save()
|
|
1365
1366
|
|
|
1366
1367
|
# Status should always be NEW after save
|
|
1367
|
-
self.assertEqual(sync_instance.status,
|
|
1368
|
+
self.assertEqual(sync_instance.status, IPFabricSyncStatusChoices.NEW)
|
|
1368
1369
|
|
|
1369
1370
|
# Verify in database as well
|
|
1370
1371
|
saved_instance = IPFabricSync.objects.get(pk=sync_instance.pk)
|
|
1371
|
-
self.assertEqual(saved_instance.status,
|
|
1372
|
+
self.assertEqual(saved_instance.status, IPFabricSyncStatusChoices.NEW)
|
|
1372
1373
|
|
|
1373
1374
|
def test_fieldsets_for_local_source_type(self):
|
|
1374
1375
|
"""Test that fieldsets returns correct structure for local source type"""
|
|
@@ -1413,7 +1414,7 @@ class IPFabricSyncFormTestCase(TestCase):
|
|
|
1413
1414
|
name="Test Remote Source",
|
|
1414
1415
|
type=IPFabricSourceTypeChoices.REMOTE,
|
|
1415
1416
|
url="https://remote.ipfabric.local",
|
|
1416
|
-
status=
|
|
1417
|
+
status=IPFabricSourceStatusChoices.NEW,
|
|
1417
1418
|
)
|
|
1418
1419
|
|
|
1419
1420
|
remote_snapshot = IPFabricSnapshot.objects.create(
|
|
@@ -3,7 +3,6 @@ from datetime import timedelta
|
|
|
3
3
|
from unittest.mock import patch
|
|
4
4
|
from uuid import uuid4
|
|
5
5
|
|
|
6
|
-
from core.choices import DataSourceStatusChoices
|
|
7
6
|
from core.choices import JobStatusChoices
|
|
8
7
|
from core.models import Job
|
|
9
8
|
from dcim.models import Device
|
|
@@ -24,7 +23,9 @@ from utilities.testing import ModelTestCase
|
|
|
24
23
|
from utilities.testing import ViewTestCases
|
|
25
24
|
|
|
26
25
|
from ipfabric_netbox.choices import IPFabricSnapshotStatusModelChoices
|
|
26
|
+
from ipfabric_netbox.choices import IPFabricSourceStatusChoices
|
|
27
27
|
from ipfabric_netbox.choices import IPFabricSourceTypeChoices
|
|
28
|
+
from ipfabric_netbox.choices import IPFabricSyncStatusChoices
|
|
28
29
|
from ipfabric_netbox.forms import dcim_parameters
|
|
29
30
|
from ipfabric_netbox.forms import ipam_parameters
|
|
30
31
|
from ipfabric_netbox.forms import tableChoices
|
|
@@ -79,7 +80,7 @@ class IPFabricSourceTestCase(
|
|
|
79
80
|
name="IP Fabric Source 1",
|
|
80
81
|
type=IPFabricSourceTypeChoices.LOCAL,
|
|
81
82
|
url="https://ipfabric1.example.com",
|
|
82
|
-
status=
|
|
83
|
+
status=IPFabricSourceStatusChoices.NEW,
|
|
83
84
|
parameters={"auth": "token1", "verify": True, "timeout": 30},
|
|
84
85
|
last_synced=timezone.now(),
|
|
85
86
|
),
|
|
@@ -87,7 +88,7 @@ class IPFabricSourceTestCase(
|
|
|
87
88
|
name="IP Fabric Source 2",
|
|
88
89
|
type=IPFabricSourceTypeChoices.LOCAL,
|
|
89
90
|
url="https://ipfabric2.example.com",
|
|
90
|
-
status=
|
|
91
|
+
status=IPFabricSourceStatusChoices.COMPLETED,
|
|
91
92
|
parameters={"auth": "token2", "verify": False, "timeout": 60},
|
|
92
93
|
last_synced=timezone.now(),
|
|
93
94
|
),
|
|
@@ -95,7 +96,7 @@ class IPFabricSourceTestCase(
|
|
|
95
96
|
name="IP Fabric Source 3",
|
|
96
97
|
type=IPFabricSourceTypeChoices.LOCAL,
|
|
97
98
|
url="https://ipfabric3.example.com",
|
|
98
|
-
status=
|
|
99
|
+
status=IPFabricSourceStatusChoices.FAILED,
|
|
99
100
|
parameters={"auth": "token3", "verify": True, "timeout": 45},
|
|
100
101
|
),
|
|
101
102
|
)
|
|
@@ -390,13 +391,13 @@ class IPFabricSnapshotTestCase(
|
|
|
390
391
|
name="Test Source 1",
|
|
391
392
|
type=IPFabricSourceTypeChoices.LOCAL,
|
|
392
393
|
url="https://ipfabric1.example.com",
|
|
393
|
-
status=
|
|
394
|
+
status=IPFabricSourceStatusChoices.NEW,
|
|
394
395
|
)
|
|
395
396
|
source2 = IPFabricSource.objects.create(
|
|
396
397
|
name="Test Source 2",
|
|
397
398
|
type=IPFabricSourceTypeChoices.REMOTE,
|
|
398
399
|
url="https://ipfabric2.example.com",
|
|
399
|
-
status=
|
|
400
|
+
status=IPFabricSourceStatusChoices.COMPLETED,
|
|
400
401
|
)
|
|
401
402
|
|
|
402
403
|
# Create three IPFabricSnapshot instances for testing
|
|
@@ -511,7 +512,7 @@ class IPFabricDataTestCase(
|
|
|
511
512
|
name="Test Source",
|
|
512
513
|
type=IPFabricSourceTypeChoices.LOCAL,
|
|
513
514
|
url="https://ipfabric.example.com",
|
|
514
|
-
status=
|
|
515
|
+
status=IPFabricSourceStatusChoices.NEW,
|
|
515
516
|
)
|
|
516
517
|
|
|
517
518
|
snapshot = IPFabricSnapshot.objects.create(
|
|
@@ -628,7 +629,7 @@ class IPFabricSyncTestCase(
|
|
|
628
629
|
name="Test Source",
|
|
629
630
|
type=IPFabricSourceTypeChoices.LOCAL,
|
|
630
631
|
url="https://ipfabric.example.com",
|
|
631
|
-
status=
|
|
632
|
+
status=IPFabricSourceStatusChoices.NEW,
|
|
632
633
|
)
|
|
633
634
|
|
|
634
635
|
snapshot1 = IPFabricSnapshot.objects.create(
|
|
@@ -654,7 +655,7 @@ class IPFabricSyncTestCase(
|
|
|
654
655
|
IPFabricSync(
|
|
655
656
|
name="Sync Job 1",
|
|
656
657
|
snapshot_data=snapshot1,
|
|
657
|
-
status=
|
|
658
|
+
status=IPFabricSyncStatusChoices.NEW,
|
|
658
659
|
parameters=get_parameters(),
|
|
659
660
|
last_synced=timezone.now(),
|
|
660
661
|
scheduled=timezone.now() + timedelta(hours=6),
|
|
@@ -663,14 +664,14 @@ class IPFabricSyncTestCase(
|
|
|
663
664
|
IPFabricSync(
|
|
664
665
|
name="Sync Job 2",
|
|
665
666
|
snapshot_data=snapshot1,
|
|
666
|
-
status=
|
|
667
|
+
status=IPFabricSyncStatusChoices.COMPLETED,
|
|
667
668
|
parameters=get_parameters(),
|
|
668
669
|
last_synced=timezone.now(),
|
|
669
670
|
),
|
|
670
671
|
IPFabricSync(
|
|
671
672
|
name="Sync Job 3",
|
|
672
673
|
snapshot_data=snapshot2,
|
|
673
|
-
status=
|
|
674
|
+
status=IPFabricSyncStatusChoices.FAILED,
|
|
674
675
|
parameters=get_parameters(),
|
|
675
676
|
),
|
|
676
677
|
)
|
|
@@ -701,16 +702,16 @@ class IPFabricSyncTestCase(
|
|
|
701
702
|
|
|
702
703
|
cls.csv_data = (
|
|
703
704
|
"name,snapshot_data,status,parameters",
|
|
704
|
-
f'Sync CSV 1,{snapshot1.pk},{
|
|
705
|
-
f'Sync CSV 2,{snapshot1.pk},{
|
|
706
|
-
f'Sync CSV 3,{snapshot2.pk},{
|
|
705
|
+
f'Sync CSV 1,{snapshot1.pk},{IPFabricSyncStatusChoices.NEW},"{{\\"auto_merge\\": true}}"', # noqa: E231
|
|
706
|
+
f'Sync CSV 2,{snapshot1.pk},{IPFabricSyncStatusChoices.COMPLETED},"{{\\"auto_merge\\": false}}"', # noqa: E231
|
|
707
|
+
f'Sync CSV 3,{snapshot2.pk},{IPFabricSyncStatusChoices.NEW},"{{\\"auto_merge\\": true}}"', # noqa: E231
|
|
707
708
|
)
|
|
708
709
|
|
|
709
710
|
cls.csv_update_data = (
|
|
710
711
|
"id,name,status",
|
|
711
|
-
f"{cls.syncs[0].pk},Updated Sync 1,{
|
|
712
|
-
f"{cls.syncs[1].pk},Updated Sync 2,{
|
|
713
|
-
f"{cls.syncs[2].pk},Updated Sync 3,{
|
|
712
|
+
f"{cls.syncs[0].pk},Updated Sync 1,{IPFabricSyncStatusChoices.COMPLETED}", # noqa: E231
|
|
713
|
+
f"{cls.syncs[1].pk},Updated Sync 2,{IPFabricSyncStatusChoices.FAILED}", # noqa: E231
|
|
714
|
+
f"{cls.syncs[2].pk},Updated Sync 3,{IPFabricSyncStatusChoices.COMPLETED}", # noqa: E231
|
|
714
715
|
)
|
|
715
716
|
|
|
716
717
|
cls.bulk_edit_data = {
|
|
@@ -1503,7 +1504,7 @@ class IPFabricIngestionTestCase(
|
|
|
1503
1504
|
name="Test Source",
|
|
1504
1505
|
type=IPFabricSourceTypeChoices.LOCAL,
|
|
1505
1506
|
url="https://ipfabric.example.com",
|
|
1506
|
-
status=
|
|
1507
|
+
status=IPFabricSourceStatusChoices.NEW,
|
|
1507
1508
|
)
|
|
1508
1509
|
|
|
1509
1510
|
snapshot = IPFabricSnapshot.objects.create(
|
|
@@ -1519,7 +1520,7 @@ class IPFabricIngestionTestCase(
|
|
|
1519
1520
|
sync1 = IPFabricSync.objects.create(
|
|
1520
1521
|
name="Test Sync 1",
|
|
1521
1522
|
snapshot_data=snapshot,
|
|
1522
|
-
status=
|
|
1523
|
+
status=IPFabricSyncStatusChoices.NEW,
|
|
1523
1524
|
parameters={"batch_size": 100},
|
|
1524
1525
|
last_synced=timezone.now(),
|
|
1525
1526
|
)
|
|
@@ -1527,7 +1528,7 @@ class IPFabricIngestionTestCase(
|
|
|
1527
1528
|
sync2 = IPFabricSync.objects.create(
|
|
1528
1529
|
name="Test Sync 2",
|
|
1529
1530
|
snapshot_data=snapshot,
|
|
1530
|
-
status=
|
|
1531
|
+
status=IPFabricSyncStatusChoices.COMPLETED,
|
|
1531
1532
|
parameters={"batch_size": 200},
|
|
1532
1533
|
last_synced=timezone.now(),
|
|
1533
1534
|
)
|
|
@@ -1535,7 +1536,7 @@ class IPFabricIngestionTestCase(
|
|
|
1535
1536
|
sync3 = IPFabricSync.objects.create(
|
|
1536
1537
|
name="Test Sync 3",
|
|
1537
1538
|
snapshot_data=snapshot,
|
|
1538
|
-
status=
|
|
1539
|
+
status=IPFabricSyncStatusChoices.FAILED,
|
|
1539
1540
|
parameters={"batch_size": 50},
|
|
1540
1541
|
)
|
|
1541
1542
|
|
|
@@ -1596,7 +1597,7 @@ class IPFabricIngestionTestCase(
|
|
|
1596
1597
|
|
|
1597
1598
|
cls.form_data = {
|
|
1598
1599
|
"snapshot": snapshot.pk,
|
|
1599
|
-
"status":
|
|
1600
|
+
"status": IPFabricSyncStatusChoices.NEW,
|
|
1600
1601
|
"parameters": '{"batch_size": 150}',
|
|
1601
1602
|
}
|
|
1602
1603
|
|
|
@@ -1914,7 +1915,7 @@ class IPFabricTableViewTestCase(PluginPathMixin, ModelTestCase):
|
|
|
1914
1915
|
name="IP Fabric Source 1",
|
|
1915
1916
|
type=IPFabricSourceTypeChoices.LOCAL,
|
|
1916
1917
|
url="https://ipfabric1.example.com",
|
|
1917
|
-
status=
|
|
1918
|
+
status=IPFabricSourceStatusChoices.NEW,
|
|
1918
1919
|
parameters={"auth": "token1", "verify": True, "timeout": 30},
|
|
1919
1920
|
last_synced=timezone.now(),
|
|
1920
1921
|
)
|
|
@@ -5,7 +5,6 @@ from typing import Callable
|
|
|
5
5
|
from typing import TYPE_CHECKING
|
|
6
6
|
from typing import TypeVar
|
|
7
7
|
|
|
8
|
-
from core.choices import DataSourceStatusChoices
|
|
9
8
|
from core.exceptions import SyncError
|
|
10
9
|
from dcim.models import Device
|
|
11
10
|
from dcim.models import Interface
|
|
@@ -22,6 +21,7 @@ from netbox.config import get_config
|
|
|
22
21
|
from netutils.utils import jinja2_convenience_function
|
|
23
22
|
|
|
24
23
|
from ..choices import IPFabricSourceTypeChoices
|
|
24
|
+
from ..choices import IPFabricSyncStatusChoices
|
|
25
25
|
from ..exceptions import create_or_get_sync_issue
|
|
26
26
|
from ..exceptions import IPAddressDuplicateError
|
|
27
27
|
from ..exceptions import SearchError
|
|
@@ -185,7 +185,7 @@ class IPFabricSyncRunner(object):
|
|
|
185
185
|
obj=self.sync,
|
|
186
186
|
)
|
|
187
187
|
# Make sure the whole sync is failed when we encounter error
|
|
188
|
-
self.sync.status =
|
|
188
|
+
self.sync.status = IPFabricSyncStatusChoices.FAILED
|
|
189
189
|
return None
|
|
190
190
|
|
|
191
191
|
return wrapper
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
ipfabric_netbox/__init__.py,sha256=
|
|
1
|
+
ipfabric_netbox/__init__.py,sha256=HcmpvN2Z1p1Rm0fFyHjsl-TotcxDAFjLhiSa6E-GcOs,674
|
|
2
2
|
ipfabric_netbox/api/__init__.py,sha256=XRclTGWVR0ZhAAwgYul5Wm_loug5_hUjEumbLQEwKYM,47
|
|
3
|
-
ipfabric_netbox/api/serializers.py,sha256=
|
|
3
|
+
ipfabric_netbox/api/serializers.py,sha256=92Cwhnqsm1l1oZfdHH5aJI1VFX0eO5JS4BsdXE6Ur18,6738
|
|
4
4
|
ipfabric_netbox/api/urls.py,sha256=1fXXVTxNY5E64Nfz6b7zXD9bZI3FcefuxAWKMe0w_QU,1240
|
|
5
5
|
ipfabric_netbox/api/views.py,sha256=qOBTIzPtOBY75tTjirsTBbiRXrQQid478Tp15-WKbmQ,6859
|
|
6
|
-
ipfabric_netbox/choices.py,sha256=
|
|
6
|
+
ipfabric_netbox/choices.py,sha256=Cky13o9awZBAc5L7ufaGIX5tXu54IUu-9kCx001Ysag,5957
|
|
7
7
|
ipfabric_netbox/data/transform_map.json,sha256=4PsucgMHcLW3SPoKEptQCd0gA5tCF4hjrR4bGQFCWy8,21744
|
|
8
8
|
ipfabric_netbox/exceptions.py,sha256=DT4dpbakvqoROtBR_F0LzvQCMNWpGhufFcUbZTx0OLY,2655
|
|
9
|
-
ipfabric_netbox/filtersets.py,sha256=
|
|
10
|
-
ipfabric_netbox/forms.py,sha256=
|
|
9
|
+
ipfabric_netbox/filtersets.py,sha256=4I_ogO0Wqexf4e4gy_CirdGmA6vSCybyCadFcjI2LM8,8011
|
|
10
|
+
ipfabric_netbox/forms.py,sha256=dNqV1p8biMYrUiBnt1jpoSqci_suicEyY_o0gm4L0YY,50003
|
|
11
11
|
ipfabric_netbox/graphql/__init__.py,sha256=-a5w_VY7pc-RVt8MvThkTzeAqCC3xCan4Ue6iMefmjI,754
|
|
12
|
-
ipfabric_netbox/graphql/enums.py,sha256=
|
|
13
|
-
ipfabric_netbox/graphql/filters.py,sha256=
|
|
12
|
+
ipfabric_netbox/graphql/enums.py,sha256=sZ2neNkM4HUA4ODvio9aFcI8tIJoc2xKuy9_c5b40Q8,1565
|
|
13
|
+
ipfabric_netbox/graphql/filters.py,sha256=QYYE_5wE57cpRzhXJzU8IEpDDnPb97NUd9Zbf0OZfNA,13066
|
|
14
14
|
ipfabric_netbox/graphql/schema.py,sha256=5UVHA1hHRvho5eLuuS-HLXTVTbxpUUx68ovG03gumGE,3209
|
|
15
15
|
ipfabric_netbox/graphql/types.py,sha256=8RxdxiA-WnoaWSzh-tUJCuZBYGmd6QjfJiJcLirRMKY,5961
|
|
16
|
-
ipfabric_netbox/jobs.py,sha256=
|
|
16
|
+
ipfabric_netbox/jobs.py,sha256=4wM-IdE7ngiRYkL_U87y6gBhc_G5tDsZPw9GL2b2jog,4638
|
|
17
17
|
ipfabric_netbox/migrations/0001_initial.py,sha256=VphxkWL6QzWq2tcrdXlog718xQtiEGizKwS830z_fOs,13824
|
|
18
18
|
ipfabric_netbox/migrations/0001_initial_squashed_0013_switch_to_branching_plugin.py,sha256=OvofuA8ImeJmjrbtCrZPcRxAUWx2Ww4DUXLBZYsy6qE,21381
|
|
19
19
|
ipfabric_netbox/migrations/0002_ipfabricsnapshot_status.py,sha256=xQpouHjOutyj6riN2B592njzSvz_icpkUbo5W7nWLYw,431
|
|
@@ -36,7 +36,7 @@ ipfabric_netbox/migrations/0018_remove_type_field.py,sha256=ffxW6IS3BLCbvM5M9DbD
|
|
|
36
36
|
ipfabric_netbox/migrations/0019_alter_ipfabrictransformmap_options_and_more.py,sha256=ieDVedt9KpJBicAiC3kdZXzHeos12N0L9EdRXKmIVgY,501
|
|
37
37
|
ipfabric_netbox/migrations/0020_clean_scheduled_jobs.py,sha256=zjCVKnCWTKYYkpVRwHjqRIRR2j6ALSKXYMfraRjNu7Y,2652
|
|
38
38
|
ipfabric_netbox/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
39
|
-
ipfabric_netbox/models.py,sha256=
|
|
39
|
+
ipfabric_netbox/models.py,sha256=mN0J1WfbY4zZvn3iaUj_mZppLfgaJErLZRjNGmxuyvE,38345
|
|
40
40
|
ipfabric_netbox/navigation.py,sha256=2dEJ_wKHb52Tl0FOV1TH3JbxRe8YZ56ewrTsBFGKpCg,2210
|
|
41
41
|
ipfabric_netbox/signals.py,sha256=cGa5PVD2i24pGXiVNfbu6ruIDqPVdwKQHTSWe9Ura84,1838
|
|
42
42
|
ipfabric_netbox/tables.py,sha256=BpPmL6-KClX16Ol_PIADyOx9NtDR9oauXH5iO4GeSoI,9008
|
|
@@ -72,17 +72,17 @@ ipfabric_netbox/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NM
|
|
|
72
72
|
ipfabric_netbox/templatetags/ipfabric_netbox_helpers.py,sha256=STw4pAd2qG7hgf-O6UNTwsO5VqEa_gxf5wLv50BWL4Q,417
|
|
73
73
|
ipfabric_netbox/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
74
74
|
ipfabric_netbox/tests/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
75
|
-
ipfabric_netbox/tests/api/test_api.py,sha256=
|
|
76
|
-
ipfabric_netbox/tests/test_forms.py,sha256=
|
|
75
|
+
ipfabric_netbox/tests/api/test_api.py,sha256=rnpGj3_cuh-QGQgOoARWuvtipDNCjcICn_Qbv2kUMQA,35304
|
|
76
|
+
ipfabric_netbox/tests/test_forms.py,sha256=ZZezIMjf5UiFGzpIlfIdnmXK5Urk8SdapF5c2MMOYoA,61693
|
|
77
77
|
ipfabric_netbox/tests/test_models.py,sha256=FFrIT5xxv_yvujKpxGjRJPNPBDF2Pqi8zbY0vxuJeQs,16043
|
|
78
|
-
ipfabric_netbox/tests/test_views.py,sha256=
|
|
78
|
+
ipfabric_netbox/tests/test_views.py,sha256=KKHKA4ejTEwdy6Ce5StJxjxWVWbQ54Y1puyPeBRw1vM,87923
|
|
79
79
|
ipfabric_netbox/urls.py,sha256=qF2BzZEDnPRd3opFaRfiMdaarYKFfv69iMaAbU2rsBU,2702
|
|
80
80
|
ipfabric_netbox/utilities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
81
|
-
ipfabric_netbox/utilities/ipfutils.py,sha256=
|
|
81
|
+
ipfabric_netbox/utilities/ipfutils.py,sha256=I5okghNJV8M82eWACz1-px46AChcSWsoOu5_DpEXojo,31886
|
|
82
82
|
ipfabric_netbox/utilities/logging.py,sha256=GYknjocMN6LQ2873_az3y0RKm29TCXaWviUIIneH-x0,3445
|
|
83
83
|
ipfabric_netbox/utilities/nbutils.py,sha256=kFBEiJOGvr_49hJWCS2duXojx2-A9kVk0Xp_vj0ohfs,2641
|
|
84
84
|
ipfabric_netbox/utilities/transform_map.py,sha256=GpM_7Mm6FE0qV2qbyj4YfDn0l-JkeeEHQOZkNVSSHk4,2391
|
|
85
85
|
ipfabric_netbox/views.py,sha256=JcXvoLo8JQ0PUyvUwi1tZQgrxw9okKBlocsIUKoGAbo,44758
|
|
86
|
-
ipfabric_netbox-4.3.
|
|
87
|
-
ipfabric_netbox-4.3.
|
|
88
|
-
ipfabric_netbox-4.3.
|
|
86
|
+
ipfabric_netbox-4.3.1b2.dist-info/METADATA,sha256=6Bqriy8Ls-ErFbDdQMCnUxhZRCjLVN92fneBGhI5b7A,4754
|
|
87
|
+
ipfabric_netbox-4.3.1b2.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
88
|
+
ipfabric_netbox-4.3.1b2.dist-info/RECORD,,
|
|
File without changes
|