Skip to content

Commit

Permalink
refactor: 🚧 Replace custom Notes by Nautobot ones (#324)
Browse files Browse the repository at this point in the history
* refactor: 🚧 Replace custom Notes by Nautobot ones

* add change doc

* Split migrations into two files

* fix migration reference name

* fix: add NoteModelFormMixin, clean view, and format with ruff

* recover instance check for view

* merge fixes

* rename maintenance path

* fix for 2.0.0

* ruff

* adjust migrations

* Apply suggestions from code review

Co-authored-by: Glenn Matthews <glenn.matthews@networktocode.com>

* recover test checks and clean view

---------

Co-authored-by: Glenn Matthews <glenn.matthews@networktocode.com>
  • Loading branch information
chadell and glennmatthews authored Oct 15, 2024
1 parent a68d46c commit a560946
Show file tree
Hide file tree
Showing 17 changed files with 144 additions and 447 deletions.
1 change: 1 addition & 0 deletions changes/324.housekeeping
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Replace custom Note model by the Nautobot one
11 changes: 0 additions & 11 deletions nautobot_circuit_maintenance/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from nautobot_circuit_maintenance.models import (
CircuitImpact,
CircuitMaintenance,
Note,
NotificationSource,
ParsedNotification,
RawNotification,
Expand Down Expand Up @@ -42,16 +41,6 @@ class Meta:
fields = "__all__"


class NoteSerializer(NautobotModelSerializer):
"""Serializer for API."""

class Meta:
"""Meta class for MaintenanceNoteSerializer."""

model = Note
fields = "__all__"


class NotificationSourceSerializer(NautobotModelSerializer):
"""Serializer for NotificationSource records."""

Expand Down
1 change: 0 additions & 1 deletion nautobot_circuit_maintenance/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

router = routers.DefaultRouter()
router.register("circuit-maintenances", views.MaintenanceTaskView)
router.register("notes", views.MaintenanceNoteTaskView)
router.register("circuit-impacts", views.MaintenanceCircuitImpactTaskView)
router.register("notification-sources", views.NotificationSourceTaskView)
router.register("parsed-notifications", views.ParsedNotificationTaskView)
Expand Down
9 changes: 0 additions & 9 deletions nautobot_circuit_maintenance/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
from nautobot_circuit_maintenance.models import (
CircuitImpact,
CircuitMaintenance,
Note,
NotificationSource,
ParsedNotification,
RawNotification,
Expand All @@ -17,7 +16,6 @@
from .serializers import (
CircuitImpactSerializer,
CircuitMaintenanceSerializer,
NoteSerializer,
NotificationSourceSerializer,
ParsedNotificationSerializer,
RawNotificationSerializer,
Expand All @@ -32,13 +30,6 @@ class MaintenanceTaskView(CustomFieldModelViewSet):
filterset_class = filters.CircuitMaintenanceFilterSet


class MaintenanceNoteTaskView(CustomFieldModelViewSet):
"""API view for Circuit Note CRUD operations."""

queryset = Note.objects.prefetch_related()
serializer_class = NoteSerializer


class MaintenanceCircuitImpactTaskView(CustomFieldModelViewSet):
"""API view for Circuit Impact CRUD operations."""

Expand Down
12 changes: 0 additions & 12 deletions nautobot_circuit_maintenance/choices.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,3 @@ class CircuitImpactChoices(ChoiceSet):
(DEGRADED, "DEGRADED"),
(OUTAGE, "OUTAGE"),
)


class NoteLevelChoices(ChoiceSet):
"""Valid values for Circuit Maintenance Note level."""

INFO = "INFO"
WARNING = "WARNING"

CHOICES = (
(INFO, "INFO"),
(WARNING, "WARNING"),
)
26 changes: 1 addition & 25 deletions nautobot_circuit_maintenance/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from nautobot.core.filters import NaturalKeyOrPKMultipleChoiceFilter
from nautobot.extras.filters import NautobotFilterSet

from .models import CircuitImpact, CircuitMaintenance, Note, NotificationSource, ParsedNotification, RawNotification
from .models import CircuitImpact, CircuitMaintenance, NotificationSource, ParsedNotification, RawNotification

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -74,30 +74,6 @@ class Meta:
fields = "__all__"


class NoteFilterSet(NautobotFilterSet):
"""Filter capabilities for Note instances."""

maintenance = NaturalKeyOrPKMultipleChoiceFilter(
field_name="maintenance",
queryset=CircuitMaintenance.objects.all(),
to_field_name="name",
label="CircuitMaintenance",
)

class Meta:
"""Meta class attributes for NoteFilterSet."""

model = Note
fields = "__all__"

def search(self, queryset, name, value): # pylint: disable=unused-argument
"""Perform the filtered search."""
if not value.strip():
return queryset
qs_filter = Q(title__icontains=value)
return queryset.filter(qs_filter)


class RawNotificationFilterSet(NautobotFilterSet):
"""Filter capabilities for Raw Notification instances."""

Expand Down
42 changes: 2 additions & 40 deletions nautobot_circuit_maintenance/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
CustomFieldModelBulkEditFormMixin,
CustomFieldModelFilterFormMixin,
CustomFieldModelFormMixin,
NoteModelFormMixin,
RelationshipModelFormMixin,
)
from nautobot.circuits.models import Circuit, Provider
Expand All @@ -27,7 +28,6 @@
from .models import (
CircuitImpact,
CircuitMaintenance,
Note,
NotificationSource,
RawNotification,
)
Expand Down Expand Up @@ -73,7 +73,7 @@ class CircuitImpactFilterForm(BootstrapMixin, CustomFieldModelFilterFormMixin):
impact = forms.CharField(max_length=50)


class CircuitMaintenanceForm(BootstrapMixin, CustomFieldModelFormMixin, RelationshipModelFormMixin):
class CircuitMaintenanceForm(BootstrapMixin, CustomFieldModelFormMixin, RelationshipModelFormMixin, NoteModelFormMixin):
"""Filter Form for CircuitMaintenance instances."""

class Meta: # noqa: D106 "Missing docstring in public nested class"
Expand Down Expand Up @@ -119,44 +119,6 @@ class Meta: # noqa: D106 "Missing docstring in public nested class"
nullable_fields = ["status", "ack", "description"]


class NoteForm(BootstrapMixin, CustomFieldModelFormMixin, RelationshipModelFormMixin):
"""Form for creating new maintenance note."""

class Meta: # noqa: D106 "Missing docstring in public nested class"
"""Metaclass attributes for NoteForm."""

model = Note
fields = ["maintenance", "title", "comment", "level"]
widgets = {"maintenance": forms.HiddenInput()}


class NoteBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModelBulkEditFormMixin):
"""Form for bulk editing Notes."""

pk = forms.ModelMultipleChoiceField(queryset=Note.objects.all(), widget=forms.MultipleHiddenInput)
title = forms.CharField(max_length=200)
level = forms.CharField(max_length=50, required=False)
comment = forms.CharField(max_length=200)

class Meta: # noqa: D106 "Missing docstring in public nested class"
nullable_fields = ["level"]


class NoteFilterForm(BootstrapMixin, CustomFieldModelFilterFormMixin):
"""Filter Form for creating new maintenance note."""

model = Note
q = forms.CharField(required=False, label="Search")
maintenance = DynamicModelMultipleChoiceField(
queryset=CircuitMaintenance.objects.all(),
to_field_name="pk",
required=False,
)
title = forms.CharField(max_length=200)
level = forms.CharField(max_length=50, required=False)
comment = forms.CharField(max_length=200)


class RawNotificationFilterSetForm(BootstrapMixin, CustomFieldModelFilterFormMixin):
"""Form for filtering Raw Notification instances."""

Expand Down
18 changes: 8 additions & 10 deletions nautobot_circuit_maintenance/handle_notifications/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,21 @@
from circuit_maintenance_parser import Maintenance, NotificationData, ProviderError, init_provider
from dateutil import parser
from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ObjectDoesNotExist
from django.db import transaction
from nautobot.circuits.models import Circuit, Provider
from nautobot.extras.jobs import DryRunVar, Job
from nautobot.extras.models import Note

from nautobot_circuit_maintenance.choices import CircuitMaintenanceStatusChoices
from nautobot_circuit_maintenance.enum import MessageProcessingStatus
from nautobot_circuit_maintenance.models import (
MAX_MAINTENANCE_NAME_LENGTH,
MAX_NOTE_TITLE_LENGTH,
MAX_NOTIFICATION_SENDER_LENGTH,
MAX_NOTIFICATION_SUBJECT_LENGTH,
CircuitImpact,
CircuitMaintenance,
Note,
NotificationSource,
ParsedNotification,
RawNotification,
Expand Down Expand Up @@ -71,13 +71,12 @@ def create_circuit_maintenance(
)
else:
note_entry, created = Note.objects.get_or_create(
maintenance=circuit_maintenance_entry,
title=f"Nonexistent circuit ID {circuit.circuit_id}"[:MAX_NOTE_TITLE_LENGTH],
comment=(
assigned_object_id=circuit_maintenance_entry.id,
assigned_object_type=ContentType.objects.get_for_model(CircuitMaintenance),
note=(
f"Circuit ID {circuit.circuit_id} referenced was not found in the database, so omitted from the "
"maintenance."
),
level="WARNING",
)
if created:
job.logger.warning(
Expand Down Expand Up @@ -146,13 +145,12 @@ def update_circuit_maintenance(
)
else:
note_entry, created = Note.objects.get_or_create(
maintenance=circuit_maintenance_entry,
title=f"Nonexistent circuit ID {circuit.circuit_id}"[:MAX_NOTE_TITLE_LENGTH],
comment=(
assigned_object_id=circuit_maintenance_entry.id,
assigned_object_type=ContentType.objects.get_for_model(CircuitMaintenance),
note=(
f"Circuit ID {circuit.circuit_id} referenced was not found in the database, so omitted from the "
"maintenance."
),
level="WARNING",
)
if created:
job.logger.warning(
Expand Down
41 changes: 41 additions & 0 deletions nautobot_circuit_maintenance/migrations/0014_migrate_notes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Generated by Django 4.2.16 on 2024-09-13 08:49

from django.db import migrations


def move_data_to_new_model(apps, schema_editor):
CircuitMaintenance = apps.get_model("nautobot_circuit_maintenance", "CircuitMaintenance")
ContentType = apps.get_model("contenttypes", "ContentType")
OldModel = apps.get_model("nautobot_circuit_maintenance", "Note")
NewModel = apps.get_model("extras", "Note")

for old_obj in OldModel.objects.all():
NewModel.objects.create(
note=f"### {old_obj.title}\n\n{old_obj.comment}",
assigned_object_type=ContentType.objects.get_for_model(CircuitMaintenance),
assigned_object_id=old_obj.maintenance.id,
user_name="migration",
)


def reverse_move_data(apps, schema_editor):
OldModel = apps.get_model("nautobot_circuit_maintenance", "Note")
NewModel = apps.get_model("extras", "Note")

for new_obj in NewModel.objects.all():
OldModel.objects.create(
title=new_obj.note[:20], # truncate to 20
content=new_obj.note,
maintenance=new_obj.assigned_object,
)


class Migration(migrations.Migration):
dependencies = [
("nautobot_circuit_maintenance", "0013_rename_site_search_job"),
("extras", "0043_note"),
]

operations = [
migrations.RunPython(move_data_to_new_model, reverse_move_data),
]
15 changes: 15 additions & 0 deletions nautobot_circuit_maintenance/migrations/0015_delete_note.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Generated by Django 4.2.16 on 2024-09-13 08:49

from django.db import migrations


class Migration(migrations.Migration):
dependencies = [
("nautobot_circuit_maintenance", "0014_migrate_notes"),
]

operations = [
migrations.DeleteModel(
name="Note",
),
]
37 changes: 1 addition & 36 deletions nautobot_circuit_maintenance/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from nautobot.core.models.generics import OrganizationalModel, PrimaryModel
from nautobot.extras.utils import extras_features

from .choices import CircuitImpactChoices, CircuitMaintenanceStatusChoices, NoteLevelChoices
from .choices import CircuitImpactChoices, CircuitMaintenanceStatusChoices

logger = logging.getLogger(__name__)

Expand All @@ -24,7 +24,6 @@
MAX_NOTIFICATION_SENDER_LENGTH = 200
MAX_NOTIFICATION_SUBJECT_LENGTH = 200
MAX_NOTIFICATION_TOTAL_LENGTH = 16384
MAX_NOTE_TITLE_LENGTH = 200


@extras_features(
Expand Down Expand Up @@ -119,40 +118,6 @@ def get_absolute_url(self, api=False):
return reverse("plugins:nautobot_circuit_maintenance:circuitimpact", args=[self.pk])


@extras_features(
"custom_fields",
"custom_links",
"custom_validators",
"export_templates",
"relationships",
"webhooks",
)
class Note(OrganizationalModel):
"""Model for maintenance notes."""

maintenance = models.ForeignKey(CircuitMaintenance, on_delete=models.CASCADE, default=None)
title = models.CharField(max_length=MAX_NOTE_TITLE_LENGTH)
level = models.CharField(
default=NoteLevelChoices.INFO,
max_length=50,
choices=NoteLevelChoices,
)
comment = models.TextField()

class Meta: # noqa: D106 "Missing docstring in public nested class"
ordering = ["last_updated"]
unique_together = ["maintenance", "title"]

def __str__(self):
"""String value for HTML rendering."""
# str(self) is used in change logging, and ObjectChange.object_repr field is limited to 200 characters.
return f"{self.title}"[:200]

def get_absolute_url(self, api=False):
"""Returns reverse loop up URL."""
return reverse("plugins:nautobot_circuit_maintenance:note", args=[self.pk])


@extras_features(
"custom_fields",
"custom_links",
Expand Down
16 changes: 1 addition & 15 deletions nautobot_circuit_maintenance/tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import django_tables2 as tables
from nautobot.core.tables import BaseTable, ToggleColumn

from .models import CircuitImpact, CircuitMaintenance, Note, NotificationSource, RawNotification
from .models import CircuitImpact, CircuitMaintenance, NotificationSource, RawNotification


class CircuitMaintenanceTable(BaseTable):
Expand Down Expand Up @@ -70,20 +70,6 @@ class Meta(BaseTable.Meta):
fields = ("pk", "maintenance", "circuit", "impact") # pylint:disable=nb-use-fields-all


class NoteTable(BaseTable):
"""Table to display Note model."""

pk = ToggleColumn()
maintenance = tables.Column(linkify=True)
title = tables.Column(linkify=True)

class Meta(BaseTable.Meta):
"""Meta for class NoteTable."""

model = Note
fields = ("pk", "maintenance", "title", "level", "comment", "last_updated") # pylint:disable=nb-use-fields-all


class NotificationSourceTable(BaseTable):
"""Table to display Circuit Impact model."""

Expand Down
Loading

0 comments on commit a560946

Please sign in to comment.