Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor ValidatedSoftwareLCM and the software helper logic. #32

Merged
merged 3 commits into from
Nov 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 6 additions & 34 deletions nautobot_device_lifecycle_mgmt/api/serializers.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
"""API serializers implementation for the Lifecycle Management plugin."""
from django.contrib.contenttypes.models import ContentType
from django.db.models import Q

from drf_yasg.utils import swagger_serializer_method
"""API serializers implementation for the LifeCycle Management plugin."""
from rest_framework import serializers

from nautobot.core.api import ContentTypeField

from nautobot.dcim.api.nested_serializers import (
NestedDeviceSerializer,
NestedDeviceTypeSerializer,
NestedPlatformSerializer,
)
from nautobot.extras.api.customfields import CustomFieldModelSerializer
from nautobot.extras.api.serializers import TaggedObjectSerializer
from nautobot.utilities.api import get_serializer_for_model

from nautobot_device_lifecycle_mgmt.models import (
HardwareLCM,
Expand Down Expand Up @@ -168,20 +161,6 @@ class ValidatedSoftwareLCMSerializer(
)
software = NestedSoftwareLCMSerializer()

assigned_to_content_type = ContentTypeField(
queryset=ContentType.objects.filter(
Q(
app_label="dcim",
model__in=(
"device",
"devicetype",
"inventoryitem",
),
)
),
)
assigned_to = serializers.SerializerMethodField(read_only=True)

class Meta:
"""Meta attributes."""

Expand All @@ -190,22 +169,15 @@ class Meta:
"id",
"url",
"software",
"assigned_to_content_type",
"assigned_to_object_id",
"assigned_to",
"devices",
"device_types",
"device_roles",
"inventory_items",
"object_tags",
"start",
"end",
"preferred",
"valid",
"custom_fields",
"tags",
]

@swagger_serializer_method(serializer_or_field=serializers.DictField)
def get_assigned_to(self, obj):
"""Serializer method for 'assigned_to' GenericForeignKey field."""
if obj.assigned_to is None:
return None
serializer = get_serializer_for_model(obj.assigned_to, prefix="Nested")
context = {"request": self.context["request"]}
return serializer(obj.assigned_to, context=context).data
108 changes: 96 additions & 12 deletions nautobot_device_lifecycle_mgmt/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
import datetime
import django_filters
from django.db.models import Q
from django.contrib.contenttypes.models import ContentType

from nautobot.dcim.models import DeviceType, Platform, Device
from nautobot.dcim.models import DeviceType, Platform, Device, DeviceRole, InventoryItem
from nautobot.extras.models import Tag
from nautobot_device_lifecycle_mgmt.models import (
HardwareLCM,
SoftwareLCM,
Expand Down Expand Up @@ -141,9 +141,67 @@ class ValidatedSoftwareLCMFilterSet(django_filters.FilterSet):
queryset=SoftwareLCM.objects.all(),
label="Software",
)
devices_id = django_filters.ModelMultipleChoiceFilter(
field_name="devices",
queryset=Device.objects.all(),
label="Devices",
)
devices = django_filters.ModelMultipleChoiceFilter(
field_name="devices__name",
queryset=Device.objects.all(),
to_field_name="name",
label="Devices (name)",
)
device_types_id = django_filters.ModelMultipleChoiceFilter(
field_name="device_types",
queryset=DeviceType.objects.all(),
label="Device Types",
)
device_types = django_filters.ModelMultipleChoiceFilter(
field_name="device_types__model",
queryset=DeviceType.objects.all(),
to_field_name="model",
label="Device Types (model)",
)
device_roles_id = django_filters.ModelMultipleChoiceFilter(
field_name="device_roles",
queryset=DeviceRole.objects.all(),
label="Device Roles",
)
device_roles = django_filters.ModelMultipleChoiceFilter(
field_name="device_roles__slug",
queryset=DeviceRole.objects.all(),
to_field_name="slug",
label="Device Roles (slug)",
)
inventory_items_id = django_filters.ModelMultipleChoiceFilter(
field_name="inventory_items",
queryset=InventoryItem.objects.all(),
label="Inventory Items",
)
inventory_items = django_filters.ModelMultipleChoiceFilter(
field_name="inventory_items__name",
queryset=InventoryItem.objects.all(),
to_field_name="name",
label="Inventory Items (name)",
)
object_tags_id = django_filters.ModelMultipleChoiceFilter(
field_name="object_tags",
queryset=Tag.objects.all(),
label="Object Tags",
)
object_tags = django_filters.ModelMultipleChoiceFilter(
field_name="object_tags__slug",
queryset=Tag.objects.all(),
to_field_name="slug",
label="Object Tags (slug)",
)
device_name = django_filters.CharFilter(method="device", label="Device Name")
device_id = django_filters.CharFilter(method="device", label="Device ID")
# expired = django_filters.BooleanFilter(method="expired_search", label="Expired")
inventory_item_id = django_filters.CharFilter(method="inventory_item", label="InventoryItem ID")
start = django_filters.DateTimeFromToRangeFilter()
end = django_filters.DateTimeFromToRangeFilter()
valid = django_filters.BooleanFilter(method="valid_search", label="Currently valid")

class Meta:
"""Meta attributes for filter."""
Expand All @@ -152,11 +210,18 @@ class Meta:

fields = [
"software",
"devices",
"device_types",
"device_roles",
"inventory_items",
"object_tags",
"device_name",
"device_id",
"inventory_item_id",
"start",
"end",
"preferred",
"valid",
]

def search(self, queryset, name, value): # pylint: disable=unused-argument, no-self-use
Expand All @@ -167,8 +232,17 @@ def search(self, queryset, name, value): # pylint: disable=unused-argument, no-
qs_filter = Q(start__icontains=value) | Q(end__icontains=value)
return queryset.filter(qs_filter)

def valid_search(self, queryset, name, value): # pylint: disable=unused-argument, no-self-use
"""Perform the valid_search search."""
today = datetime.date.today()
if value is True:
qs_filter = Q(start__lte=today, end=None) | Q(start__lte=today, end__gte=today)
else:
qs_filter = Q(start__gt=today) | Q(end__lt=today)
return queryset.filter(qs_filter)

def device(self, queryset, name, value): # pylint: disable=no-self-use
"""Search validated software list for a given device."""
"""Search for validated software for a given device."""
value = value.strip()
if not value:
return queryset
Expand All @@ -184,14 +258,24 @@ def device(self, queryset, name, value): # pylint: disable=no-self-use
return queryset.none()

device = devices.first()
valid_soft_filter = Q(
assigned_to_content_type=ContentType.objects.get(app_label="dcim", model="device"),
assigned_to_object_id=device.pk,
) | Q(
assigned_to_content_type=ContentType.objects.get(app_label="dcim", model="devicetype"),
assigned_to_object_id=device.device_type.pk,
)
return ValidatedSoftwareLCM.objects.filter(valid_soft_filter)

return ValidatedSoftwareLCM.objects.get_for_object(device)

def inventory_item(self, queryset, name, value): # pylint: disable=unused-argument, no-self-use
"""Search for validated software for a given inventory item."""
value = value.strip()
if not value:
return queryset

print(value)
inventory_items = InventoryItem.objects.filter(id=value)

if inventory_items.count() != 1:
return queryset.none()

inventory_item = inventory_items.first()

return ValidatedSoftwareLCM.objects.get_for_object(inventory_item)


class ContractLCMFilterSet(django_filters.FilterSet):
Expand Down
Loading