2 Commits
Author SHA1 Message Date
wkoot 72646a6287 Update PluginMenuItem permissions and remove bulk import/edit (#41)
Closes #37
2024-07-09 23:00:58 +02:00
wkoot 86215f43a6 Prepare for upgrade to NetBox v4.0.6 (#40)
Closes #38
2024-07-09 22:15:58 +02:00
25 changed files with 195 additions and 426 deletions
+5 -5
View File
@@ -16,13 +16,13 @@ jobs:
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v4 uses: actions/setup-python@v4
with: with:
python-version: "3.9" python-version: "3.11"
- name: Install tools - name: Install tools
run: pip install .[tools] run: pip install .[tools]
- name: Run ruff - name: Run ruff lint
run: ruff netbox_slm run: ruff check netbox_slm
- name: Run black - name: Run ruff format
run: black netbox_slm run: ruff format netbox_slm
+3 -3
View File
@@ -1,4 +1,4 @@
ARG PYTHON_VERSION=3.10 ARG PYTHON_VERSION=3.11
FROM python:${PYTHON_VERSION}-alpine AS compile-image FROM python:${PYTHON_VERSION}-alpine AS compile-image
WORKDIR /build WORKDIR /build
@@ -11,7 +11,7 @@ RUN pip install -U .[build]
RUN python -m build RUN python -m build
RUN pip install --no-index /build RUN pip install --no-index /build
FROM netboxcommunity/netbox:v3.7.2 FROM netboxcommunity/netbox:v4.0.6
ARG PYTHON_VERSION=3.10 ARG PYTHON_VERSION=3.11
COPY --from=compile-image /opt/netbox/venv/lib/python${PYTHON_VERSION}/site-packages/netbox_slm /opt/netbox/venv/lib/python${PYTHON_VERSION}/site-packages/netbox_slm COPY --from=compile-image /opt/netbox/venv/lib/python${PYTHON_VERSION}/site-packages/netbox_slm /opt/netbox/venv/lib/python${PYTHON_VERSION}/site-packages/netbox_slm
+1 -1
View File
@@ -1,4 +1,4 @@
FROM netboxcommunity/netbox:v3.7.2 FROM netboxcommunity/netbox:v4.0.6
RUN mkdir /ci && chmod go+w /ci RUN mkdir /ci && chmod go+w /ci
COPY ../ci/requirements_ci.txt /ci/ COPY ../ci/requirements_ci.txt /ci/
+1 -1
View File
@@ -1,4 +1,4 @@
version: '3.7' ---
services: services:
netbox: netbox:
ports: ports:
+2 -2
View File
@@ -1,7 +1,7 @@
version: '3.7' ---
services: services:
netbox: &netbox netbox: &netbox
image: netboxcommunity/netbox:${VERSION-v3.7.2} image: netboxcommunity/netbox:${VERSION-v4.0.6}
depends_on: depends_on:
- postgres - postgres
- redis - redis
+1 -1
View File
@@ -1,2 +1,2 @@
coverage==7.2.2 coverage==7.5.4
unittest-xml-reporting==3.2.0 unittest-xml-reporting==3.2.0
+2 -2
View File
@@ -1,6 +1,6 @@
from extras.plugins import PluginConfig from netbox.plugins import PluginConfig
__version__ = "1.6.0" __version__ = "1.7.0"
class SLMConfig(PluginConfig): class SLMConfig(PluginConfig):
+12 -8
View File
@@ -10,7 +10,7 @@ class SoftwareLicenseSerializer(NetBoxModelSerializer):
class Meta: class Meta:
model = SoftwareLicense model = SoftwareLicense
fields = [ fields = (
"id", "id",
"display", "display",
"url", "url",
@@ -31,7 +31,8 @@ class SoftwareLicenseSerializer(NetBoxModelSerializer):
"custom_field_data", "custom_field_data",
"created", "created",
"last_updated", "last_updated",
] )
brief_fields = ("id", "display", "url", "name", "description")
def get_display(self, obj): def get_display(self, obj):
return f"{obj}" return f"{obj}"
@@ -43,7 +44,7 @@ class SoftwareProductSerializer(NetBoxModelSerializer):
class Meta: class Meta:
model = SoftwareProduct model = SoftwareProduct
fields = [ fields = (
"id", "id",
"display", "display",
"url", "url",
@@ -55,7 +56,8 @@ class SoftwareProductSerializer(NetBoxModelSerializer):
"custom_field_data", "custom_field_data",
"created", "created",
"last_updated", "last_updated",
] )
brief_fields = ("id", "display", "url", "name", "description")
def get_display(self, obj): def get_display(self, obj):
return f"{obj.manufacturer} - {obj}" return f"{obj.manufacturer} - {obj}"
@@ -69,7 +71,7 @@ class SoftwareProductInstallationSerializer(NetBoxModelSerializer):
class Meta: class Meta:
model = SoftwareProductInstallation model = SoftwareProductInstallation
fields = [ fields = (
"id", "id",
"display", "display",
"url", "url",
@@ -83,7 +85,8 @@ class SoftwareProductInstallationSerializer(NetBoxModelSerializer):
"custom_field_data", "custom_field_data",
"created", "created",
"last_updated", "last_updated",
] )
brief_fields = ("id", "display", "url", "name")
def get_display(self, obj): def get_display(self, obj):
return f"{obj}" return f"{obj}"
@@ -95,7 +98,7 @@ class SoftwareProductVersionSerializer(NetBoxModelSerializer):
class Meta: class Meta:
model = SoftwareProductVersion model = SoftwareProductVersion
fields = [ fields = (
"id", "id",
"display", "display",
"url", "url",
@@ -113,7 +116,8 @@ class SoftwareProductVersionSerializer(NetBoxModelSerializer):
"custom_field_data", "custom_field_data",
"created", "created",
"last_updated", "last_updated",
] )
brief_fields = ("id", "display", "url", "name")
def get_display(self, obj): def get_display(self, obj):
return f"{obj}" return f"{obj}"
+4 -24
View File
@@ -1,24 +1,4 @@
from .software_license import ( from .software_license import SoftwareLicenseForm, SoftwareLicenseFilterForm
SoftwareLicenseForm, from .software_product import SoftwareProductForm, SoftwareProductFilterForm
SoftwareLicenseFilterForm, from .software_product_installation import SoftwareProductInstallationForm, SoftwareProductInstallationFilterForm
SoftwareLicenseImportForm, from .software_product_version import SoftwareProductVersionForm, SoftwareProductVersionFilterForm
SoftwareLicenseBulkEditForm,
)
from .software_product import (
SoftwareProductForm,
SoftwareProductFilterForm,
SoftwareProductImportForm,
SoftwareProductBulkEditForm,
)
from .software_product_installation import (
SoftwareProductInstallationForm,
SoftwareProductInstallationFilterForm,
SoftwareProductInstallationImportForm,
SoftwareProductInstallationBulkEditForm,
)
from .software_product_version import (
SoftwareProductVersionForm,
SoftwareProductVersionFilterForm,
SoftwareProductVersionImportForm,
SoftwareProductVersionBulkEditForm,
)
+3 -33
View File
@@ -1,9 +1,10 @@
from django.forms import DateField from django.forms import DateField
from django.urls import reverse_lazy from django.urls import reverse_lazy
from netbox.forms import NetBoxModelForm, NetBoxModelImportForm, NetBoxModelBulkEditForm, NetBoxModelFilterSetForm from netbox.forms import NetBoxModelForm, NetBoxModelFilterSetForm
from netbox_slm.models import SoftwareProduct, SoftwareProductVersion, SoftwareProductInstallation, SoftwareLicense from netbox_slm.models import SoftwareProduct, SoftwareProductVersion, SoftwareProductInstallation, SoftwareLicense
from utilities.forms.fields import CommentField, DynamicModelChoiceField, TagFilterField, LaxURLField from utilities.forms.fields import CommentField, DynamicModelChoiceField, TagFilterField, LaxURLField
from utilities.forms.rendering import FieldSet
from utilities.forms.widgets import APISelect, DatePicker from utilities.forms.widgets import APISelect, DatePicker
@@ -62,36 +63,5 @@ class SoftwareLicenseForm(NetBoxModelForm):
class SoftwareLicenseFilterForm(NetBoxModelFilterSetForm): class SoftwareLicenseFilterForm(NetBoxModelFilterSetForm):
model = SoftwareLicense model = SoftwareLicense
fieldsets = ((None, ("q", "tag")),) fieldsets = (FieldSet(None, ("q", "tag")),)
tag = TagFilterField(model) tag = TagFilterField(model)
class SoftwareLicenseImportForm(NetBoxModelImportForm):
class Meta:
model = SoftwareLicense
fields = (
"name",
"description",
"type",
"stored_location",
"stored_location_url",
"start_date",
"expiration_date",
)
class SoftwareLicenseBulkEditForm(NetBoxModelBulkEditForm):
software_product = DynamicModelChoiceField(queryset=SoftwareProduct.objects.all(), required=False)
version = DynamicModelChoiceField(queryset=SoftwareProductVersion.objects.all(), required=False)
installation = DynamicModelChoiceField(queryset=SoftwareProductInstallation.objects.all(), required=False)
model = SoftwareLicense
fieldsets = (
(
None,
(
"software_product",
"version",
"installation",
),
),
)
+3 -25
View File
@@ -1,9 +1,8 @@
from django import forms
from dcim.models import Manufacturer from dcim.models import Manufacturer
from netbox.forms import NetBoxModelForm, NetBoxModelImportForm, NetBoxModelBulkEditForm, NetBoxModelFilterSetForm from netbox.forms import NetBoxModelForm, NetBoxModelFilterSetForm
from netbox_slm.models import SoftwareProduct from netbox_slm.models import SoftwareProduct
from utilities.forms.fields import CommentField, DynamicModelChoiceField, TagFilterField from utilities.forms.fields import CommentField, DynamicModelChoiceField, TagFilterField
from utilities.forms.rendering import FieldSet
class SoftwareProductForm(NetBoxModelForm): class SoftwareProductForm(NetBoxModelForm):
@@ -29,26 +28,5 @@ class SoftwareProductForm(NetBoxModelForm):
class SoftwareProductFilterForm(NetBoxModelFilterSetForm): class SoftwareProductFilterForm(NetBoxModelFilterSetForm):
model = SoftwareProduct model = SoftwareProduct
fieldsets = ((None, ("q", "tag")),) fieldsets = (FieldSet(None, ("q", "tag")),)
tag = TagFilterField(model) tag = TagFilterField(model)
class SoftwareProductImportForm(NetBoxModelImportForm):
class Meta:
model = SoftwareProduct
fields = (
"name",
"description",
"manufacturer",
)
class SoftwareProductBulkEditForm(NetBoxModelBulkEditForm):
pk = forms.ModelMultipleChoiceField(
queryset=SoftwareProduct.objects.all(),
widget=forms.MultipleHiddenInput(),
)
class Meta:
model = SoftwareProduct
nullable_fields = []
@@ -1,10 +1,11 @@
from django import forms from django.forms import ValidationError
from django.urls import reverse_lazy from django.urls import reverse_lazy
from dcim.models import Device from dcim.models import Device
from netbox.forms import NetBoxModelForm, NetBoxModelImportForm, NetBoxModelBulkEditForm, NetBoxModelFilterSetForm from netbox.forms import NetBoxModelForm, NetBoxModelFilterSetForm
from netbox_slm.models import SoftwareProductInstallation, SoftwareProduct, SoftwareProductVersion from netbox_slm.models import SoftwareProductInstallation, SoftwareProduct, SoftwareProductVersion
from utilities.forms.fields import CommentField, DynamicModelChoiceField, TagFilterField from utilities.forms.fields import CommentField, DynamicModelChoiceField, TagFilterField
from utilities.forms.rendering import FieldSet
from utilities.forms.widgets import APISelect from utilities.forms.widgets import APISelect
from virtualization.models import VirtualMachine, Cluster from virtualization.models import VirtualMachine, Cluster
@@ -47,7 +48,7 @@ class SoftwareProductInstallationForm(NetBoxModelForm):
version = self.cleaned_data["version"] version = self.cleaned_data["version"]
software_product = self.cleaned_data["software_product"] software_product = self.cleaned_data["software_product"]
if version not in software_product.softwareproductversion_set.all(): if version not in software_product.softwareproductversion_set.all():
raise forms.ValidationError( raise ValidationError(
f"Version '{version}' doesn't exist on {software_product}, make sure you've " f"Version '{version}' doesn't exist on {software_product}, make sure you've "
f"selected a compatible version or first select the software product." f"selected a compatible version or first select the software product."
) )
@@ -56,26 +57,5 @@ class SoftwareProductInstallationForm(NetBoxModelForm):
class SoftwareProductInstallationFilterForm(NetBoxModelFilterSetForm): class SoftwareProductInstallationFilterForm(NetBoxModelFilterSetForm):
model = SoftwareProductInstallation model = SoftwareProductInstallation
fieldsets = ((None, ("q", "tag")),) fieldsets = (FieldSet(None, ("q", "tag")),)
tag = TagFilterField(model) tag = TagFilterField(model)
class SoftwareProductInstallationImportForm(NetBoxModelImportForm):
class Meta:
model = SoftwareProductInstallation
fields = tuple()
class SoftwareProductInstallationBulkEditForm(NetBoxModelBulkEditForm):
software_product = DynamicModelChoiceField(queryset=SoftwareProduct.objects.all(), required=False)
version = DynamicModelChoiceField(queryset=SoftwareProductVersion.objects.all(), required=False)
model = SoftwareProductInstallation
fieldsets = (
(
None,
(
"software_product",
"version",
),
),
)
+6 -22
View File
@@ -1,9 +1,10 @@
from django import forms from django.forms import DateField
from django.urls import reverse_lazy from django.urls import reverse_lazy
from netbox.forms import NetBoxModelForm, NetBoxModelImportForm, NetBoxModelBulkEditForm, NetBoxModelFilterSetForm from netbox.forms import NetBoxModelForm, NetBoxModelFilterSetForm
from netbox_slm.models import SoftwareProduct, SoftwareProductVersion from netbox_slm.models import SoftwareProduct, SoftwareProductVersion
from utilities.forms.fields import CommentField, DynamicModelChoiceField, TagFilterField from utilities.forms.fields import CommentField, DynamicModelChoiceField, TagFilterField
from utilities.forms.rendering import FieldSet
from utilities.forms.widgets import APISelect, DatePicker from utilities.forms.widgets import APISelect, DatePicker
@@ -12,8 +13,8 @@ class SoftwareProductVersionForm(NetBoxModelForm):
comments = CommentField() comments = CommentField()
release_date = forms.DateField(required=False, widget=DatePicker()) release_date = DateField(required=False, widget=DatePicker())
end_of_support = forms.DateField(required=False, widget=DatePicker()) end_of_support = DateField(required=False, widget=DatePicker())
software_product = DynamicModelChoiceField( software_product = DynamicModelChoiceField(
queryset=SoftwareProduct.objects.all(), queryset=SoftwareProduct.objects.all(),
@@ -39,22 +40,5 @@ class SoftwareProductVersionForm(NetBoxModelForm):
class SoftwareProductVersionFilterForm(NetBoxModelFilterSetForm): class SoftwareProductVersionFilterForm(NetBoxModelFilterSetForm):
model = SoftwareProductVersion model = SoftwareProductVersion
fieldsets = ((None, ("q", "tag")),) fieldsets = (FieldSet(None, ("q", "tag")),)
tag = TagFilterField(model) tag = TagFilterField(model)
class SoftwareProductVersionImportForm(NetBoxModelImportForm):
class Meta:
model = SoftwareProductVersion
fields = ("name",)
class SoftwareProductVersionBulkEditForm(NetBoxModelBulkEditForm):
pk = forms.ModelMultipleChoiceField(
queryset=SoftwareProduct.objects.all(),
widget=forms.MultipleHiddenInput(),
)
class Meta:
model = SoftwareProductVersion
nullable_fields = []
+5 -34
View File
@@ -1,23 +1,15 @@
from extras.plugins import PluginMenuButton, PluginMenuItem from netbox.plugins import PluginMenuButton, PluginMenuItem
from utilities.choices import ButtonColorChoices
menu_items = ( menu_items = (
PluginMenuItem( PluginMenuItem(
link="plugins:netbox_slm:softwareproduct_list", link="plugins:netbox_slm:softwareproduct_list",
link_text="Software Products", link_text="Software Products",
permissions=["netbox_slm.add_softwareproduct"],
buttons=( buttons=(
PluginMenuButton( PluginMenuButton(
"plugins:netbox_slm:softwareproduct_add", "plugins:netbox_slm:softwareproduct_add",
"Add", "Add",
"mdi mdi-plus-thick", "mdi mdi-plus-thick",
ButtonColorChoices.GREEN,
permissions=["netbox_slm.add_softwareproduct"],
),
PluginMenuButton(
"plugins:netbox_slm:softwareproduct_import",
"Import",
"mdi mdi-upload",
ButtonColorChoices.CYAN,
permissions=["netbox_slm.add_softwareproduct"], permissions=["netbox_slm.add_softwareproduct"],
), ),
), ),
@@ -25,19 +17,12 @@ menu_items = (
PluginMenuItem( PluginMenuItem(
link="plugins:netbox_slm:softwareproductversion_list", link="plugins:netbox_slm:softwareproductversion_list",
link_text="Versions", link_text="Versions",
permissions=["netbox_slm.add_softwareproductversion"],
buttons=( buttons=(
PluginMenuButton( PluginMenuButton(
"plugins:netbox_slm:softwareproductversion_add", "plugins:netbox_slm:softwareproductversion_add",
"Add", "Add",
"mdi mdi-plus-thick", "mdi mdi-plus-thick",
ButtonColorChoices.GREEN,
permissions=["netbox_slm.add_softwareproductversion"],
),
PluginMenuButton(
"plugins:netbox_slm:softwareproductversion_import",
"Import",
"mdi mdi-upload",
ButtonColorChoices.CYAN,
permissions=["netbox_slm.add_softwareproductversion"], permissions=["netbox_slm.add_softwareproductversion"],
), ),
), ),
@@ -45,19 +30,12 @@ menu_items = (
PluginMenuItem( PluginMenuItem(
link="plugins:netbox_slm:softwareproductinstallation_list", link="plugins:netbox_slm:softwareproductinstallation_list",
link_text="Installations", link_text="Installations",
permissions=["netbox_slm.add_softwareproductinstallation"],
buttons=( buttons=(
PluginMenuButton( PluginMenuButton(
"plugins:netbox_slm:softwareproductinstallation_add", "plugins:netbox_slm:softwareproductinstallation_add",
"Add", "Add",
"mdi mdi-plus-thick", "mdi mdi-plus-thick",
ButtonColorChoices.GREEN,
permissions=["netbox_slm.add_softwareproductinstallation"],
),
PluginMenuButton(
"plugins:netbox_slm:softwareproductinstallation_import",
"Import",
"mdi mdi-upload",
ButtonColorChoices.CYAN,
permissions=["netbox_slm.add_softwareproductinstallation"], permissions=["netbox_slm.add_softwareproductinstallation"],
), ),
), ),
@@ -65,19 +43,12 @@ menu_items = (
PluginMenuItem( PluginMenuItem(
link="plugins:netbox_slm:softwarelicense_list", link="plugins:netbox_slm:softwarelicense_list",
link_text="Licenses", link_text="Licenses",
permissions=["netbox_slm.add_softwarelicense"],
buttons=( buttons=(
PluginMenuButton( PluginMenuButton(
"plugins:netbox_slm:softwarelicense_add", "plugins:netbox_slm:softwarelicense_add",
"Add", "Add",
"mdi mdi-plus-thick", "mdi mdi-plus-thick",
ButtonColorChoices.GREEN,
permissions=["netbox_slm.add_softwarelicense"],
),
PluginMenuButton(
"plugins:netbox_slm:softwarelicense_import",
"Import",
"mdi mdi-upload",
ButtonColorChoices.CYAN,
permissions=["netbox_slm.add_softwarelicense"], permissions=["netbox_slm.add_softwarelicense"],
), ),
), ),
@@ -11,58 +11,56 @@
<h5 class="card-header"> <h5 class="card-header">
Software License Software License
</h5> </h5>
<div class="card-body"> <table class="table table-hover attr-table">
<table class="table table-hover attr-table"> <tr>
<tr> <th scope="row">Name</th>
<th scope="row">Name</th> <td>{{ object.name }}</td>
<td>{{ object.name }}</td> </tr>
</tr> <tr>
<tr> <th scope="row">Description</th>
<th scope="row">Description</th> <td>{{ object.description }}</td>
<td>{{ object.description }}</td> </tr>
</tr> <tr>
<tr> <th scope="row">Type</th>
<th scope="row">Type</th> <td>{{ object.type }}</td>
<td>{{ object.type }}</td> </tr>
</tr> <tr>
<tr> <th scope="row">Stored location</th>
<th scope="row">Stored location</th>
{% if object.stored_location_url %} {% if object.stored_location_url %}
<td><a href="{{ object.stored_location_url }}">{{ object.stored_location_txt }}</a></td> <td><a href="{{ object.stored_location_url }}">{{ object.stored_location_txt }}</a></td>
{% else %} {% else %}
<td>{{ object.stored_location_txt }}</td> <td>{{ object.stored_location_txt }}</td>
{% endif %} {% endif %}
</tr> </tr>
<tr> <tr>
<th scope="row">Start date</th> <th scope="row">Start date</th>
<td>{{ object.start_date }}</td> <td>{{ object.start_date }}</td>
</tr> </tr>
<tr> <tr>
<th scope="row">Expiration date</th> <th scope="row">Expiration date</th>
<td>{{ object.expiration_date }}</td> <td>{{ object.expiration_date }}</td>
</tr> </tr>
<tr> <tr>
<th scope="row">Software Product</th> <th scope="row">Software Product</th>
<td>{{ object.software_product }}</td> <td>{{ object.software_product }}</td>
</tr> </tr>
<tr> <tr>
<th scope="row">Version</th> <th scope="row">Version</th>
<td>{{ object.version }}</td> <td>{{ object.version }}</td>
</tr> </tr>
<tr> <tr>
<th scope="row">Support</th> <th scope="row">Support</th>
<td>{{ object.support }}</td> <td>{{ object.support }}</td>
</tr> </tr>
<tr> <tr>
<th scope="row">License amount</th> <th scope="row">License amount</th>
<td>{{ object.license_amount }}</td> <td>{{ object.license_amount }}</td>
</tr> </tr>
<tr> <tr>
<th scope="row">Installation</th> <th scope="row">Installation</th>
<td>{{ object.installation }}</td> <td>{{ object.installation }}</td>
</tr> </tr>
</table> </table>
</div>
</div> </div>
{% include 'inc/panels/custom_fields.html' %} {% include 'inc/panels/custom_fields.html' %}
{% include 'inc/panels/tags.html' %} {% include 'inc/panels/tags.html' %}
@@ -11,34 +11,32 @@
<h5 class="card-header"> <h5 class="card-header">
Software Product Software Product
</h5> </h5>
<div class="card-body"> <table class="table table-hover attr-table">
<table class="table table-hover attr-table"> <tr>
<tr> <th scope="row">Name</th>
<th scope="row">Name</th> <td>{{ object.name }}</td>
<td>{{ object.name }}</td> </tr>
</tr> <tr>
<tr> <th scope="row">Description</th>
<th scope="row">Description</th> <td>{{ object.description }}</td>
<td>{{ object.description }}</td> </tr>
</tr> <tr>
<tr> <th scope="row">Manufacturer</th>
<th scope="row">Manufacturer</th> <td>{{ object.manufacturer }}</td>
<td>{{ object.manufacturer }}</td> </tr>
</tr> <tr>
<tr> <th scope="row">Versions</th>
<th scope="row">Versions</th> <td>
<td> {% for version in object.softwareproduct_versions.all %}
{% for version in object.softwareproduct_versions.all %} <a href="{% url 'plugins:netbox_slm:softwareproductversion' pk=version.pk %}">
<a href="{% url 'plugins:netbox_slm:softwareproductversion' pk=version.pk %}"> <span class="badge" style="color: #ffffff; background-color: #9e9e9e">{{ version }}</span>
<span class="badge" style="color: #ffffff; background-color: #9e9e9e">{{ version }}</span> </a>
</a> {% empty %}
{% empty %} n/a
n/a {% endfor %}
{% endfor %} </td>
</td> </tr>
</tr> </table>
</table>
</div>
</div> </div>
{% include 'inc/panels/custom_fields.html' %} {% include 'inc/panels/custom_fields.html' %}
{% include 'inc/panels/tags.html' %} {% include 'inc/panels/tags.html' %}
@@ -11,34 +11,32 @@
<h5 class="card-header"> <h5 class="card-header">
Software Product Installation Software Product Installation
</h5> </h5>
<div class="card-body"> <table class="table table-hover attr-table">
<table class="table table-hover attr-table">
{% if object.device %} {% if object.device %}
<tr> <tr>
<th scope="row">Device</th> <th scope="row">Device</th>
<td>{{ object.device }}</td> <td>{{ object.device }}</td>
</tr> </tr>
{% elif object.virtualmachine %} {% elif object.virtualmachine %}
<tr> <tr>
<th scope="row">Virtualmachine</th> <th scope="row">Virtualmachine</th>
<td>{{ object.virtualmachine }}</td> <td>{{ object.virtualmachine }}</td>
</tr> </tr>
{% else %} {% else %}
<tr> <tr>
<th scope="row">Cluster</th> <th scope="row">Cluster</th>
<td>{{ object.cluster }}</td> <td>{{ object.cluster }}</td>
</tr> </tr>
{% endif %} {% endif %}
<tr> <tr>
<th scope="row">Software Product</th> <th scope="row">Software Product</th>
<td>{{ object.software_product }}</td> <td>{{ object.software_product }}</td>
</tr> </tr>
<tr> <tr>
<th scope="row">Version</th> <th scope="row">Version</th>
<td>{{ object.version }}</td> <td>{{ object.version }}</td>
</tr> </tr>
</table> </table>
</div>
</div> </div>
{% include 'inc/panels/custom_fields.html' %} {% include 'inc/panels/custom_fields.html' %}
{% include 'inc/panels/tags.html' %} {% include 'inc/panels/tags.html' %}
@@ -11,50 +11,48 @@
<h5 class="card-header"> <h5 class="card-header">
Software Product Version Software Product Version
</h5> </h5>
<div class="card-body"> <table class="table table-hover attr-table">
<table class="table table-hover attr-table"> <tr>
<tr> <th scope="row">Name</th>
<th scope="row">Name</th> <td>{{ object.name }}</td>
<td>{{ object.name }}</td> </tr>
</tr> <tr>
<tr> <th scope="row">Release date</th>
<th scope="row">Release date</th> <td>{{ object.release_date }}</td>
<td>{{ object.release_date }}</td> </tr>
</tr> <tr>
<tr> <th scope="row">Documentation url</th>
<th scope="row">Documentation url</th>
{% if object.documentation_url %} {% if object.documentation_url %}
<td><a href="{{ object.documentation_url }}">{{ object.documentation_url }}</a></td> <td><a href="{{ object.documentation_url }}">{{ object.documentation_url }}</a></td>
{% else %} {% else %}
<td>{{ object.documentation_url }}</td> <td>{{ object.documentation_url }}</td>
{% endif %} {% endif %}
</tr> </tr>
<tr> <tr>
<th scope="row">End of support</th> <th scope="row">End of support</th>
<td>{{ object.end_of_support }}</td> <td>{{ object.end_of_support }}</td>
</tr> </tr>
<tr> <tr>
<th scope="row">Filename</th> <th scope="row">Filename</th>
{% if object.file_link %} {% if object.file_link %}
<td><a href="{{ object.file_link }}">{{ object.filename }}</a></td> <td><a href="{{ object.file_link }}">{{ object.filename }}</a></td>
{% else %} {% else %}
<td>{{ object.filename }}</td> <td>{{ object.filename }}</td>
{% endif %} {% endif %}
</tr> </tr>
<tr> <tr>
<th scope="row">File checksum</th> <th scope="row">File checksum</th>
<td>{{ object.file_checksum }}</td> <td>{{ object.file_checksum }}</td>
</tr> </tr>
<tr> <tr>
<th scope="row">Release type</th> <th scope="row">Release type</th>
<td>{{ object.get_release_type_display }}</td> <td>{{ object.get_release_type_display }}</td>
</tr> </tr>
<tr> <tr>
<th scope="row">Installations</th> <th scope="row">Installations</th>
<td>{{ object.get_installation_count }}</td> <td>{{ object.get_installation_count }}</td>
</tr> </tr>
</table> </table>
</div>
</div> </div>
{% include 'inc/panels/custom_fields.html' %} {% include 'inc/panels/custom_fields.html' %}
{% include 'inc/panels/tags.html' %} {% include 'inc/panels/tags.html' %}
-18
View File
@@ -8,8 +8,6 @@ urlpatterns = [
# SoftwareProduct # SoftwareProduct
path("software-products/", views.SoftwareProductListView.as_view(), name="softwareproduct_list"), path("software-products/", views.SoftwareProductListView.as_view(), name="softwareproduct_list"),
path("software-products/add/", views.SoftwareProductEditView.as_view(), name="softwareproduct_add"), path("software-products/add/", views.SoftwareProductEditView.as_view(), name="softwareproduct_add"),
path("software-products/import/", views.SoftwareProductBulkImportView.as_view(), name="softwareproduct_import"),
path("software-products/edit/", views.SoftwareProductBulkEditView.as_view(), name="softwareproduct_bulk_edit"),
path( path(
"software-products/delete/", views.SoftwareProductBulkDeleteView.as_view(), name="softwareproduct_bulk_delete" "software-products/delete/", views.SoftwareProductBulkDeleteView.as_view(), name="softwareproduct_bulk_delete"
), ),
@@ -27,10 +25,6 @@ urlpatterns = [
# SoftwareProductVersion # SoftwareProductVersion
path("versions/", views.SoftwareProductVersionListView.as_view(), name="softwareproductversion_list"), path("versions/", views.SoftwareProductVersionListView.as_view(), name="softwareproductversion_list"),
path("versions/add/", views.SoftwareProductVersionEditView.as_view(), name="softwareproductversion_add"), path("versions/add/", views.SoftwareProductVersionEditView.as_view(), name="softwareproductversion_add"),
path(
"versions/import/", views.SoftwareProductVersionBulkImportView.as_view(), name="softwareproductversion_import"
),
path("versions/edit/", views.SoftwareProductVersionBulkEditView.as_view(), name="softwareproductversion_bulk_edit"),
path( path(
"versions/delete/", "versions/delete/",
views.SoftwareProductVersionBulkDeleteView.as_view(), views.SoftwareProductVersionBulkDeleteView.as_view(),
@@ -60,16 +54,6 @@ urlpatterns = [
views.SoftwareProductInstallationEditView.as_view(), views.SoftwareProductInstallationEditView.as_view(),
name="softwareproductinstallation_add", name="softwareproductinstallation_add",
), ),
path(
"installations/import/",
views.SoftwareProductInstallationBulkImportView.as_view(),
name="softwareproductinstallation_import",
),
path(
"installations/edit/",
views.SoftwareProductInstallationBulkEditView.as_view(),
name="softwareproductinstallation_bulk_edit",
),
path( path(
"installations/delete/", "installations/delete/",
views.SoftwareProductInstallationBulkDeleteView.as_view(), views.SoftwareProductInstallationBulkDeleteView.as_view(),
@@ -99,8 +83,6 @@ urlpatterns = [
# SoftwareLicense # SoftwareLicense
path("licenses/", views.SoftwareLicenseListView.as_view(), name="softwarelicense_list"), path("licenses/", views.SoftwareLicenseListView.as_view(), name="softwarelicense_list"),
path("licenses/add/", views.SoftwareLicenseEditView.as_view(), name="softwarelicense_add"), path("licenses/add/", views.SoftwareLicenseEditView.as_view(), name="softwarelicense_add"),
path("licenses/import/", views.SoftwareLicenseBulkImportView.as_view(), name="softwarelicense_import"),
path("licenses/edit/", views.SoftwareLicenseBulkEditView.as_view(), name="softwarelicense_bulk_edit"),
path("licenses/delete/", views.SoftwareLicenseBulkDeleteView.as_view(), name="softwarelicense_bulk_delete"), path("licenses/delete/", views.SoftwareLicenseBulkDeleteView.as_view(), name="softwarelicense_bulk_delete"),
path("licenses/<int:pk>/", views.SoftwareLicenseView.as_view(), name="softwarelicense"), path("licenses/<int:pk>/", views.SoftwareLicenseView.as_view(), name="softwarelicense"),
path("licenses/<int:pk>/delete/", views.SoftwareLicenseDeleteView.as_view(), name="softwarelicense_delete"), path("licenses/<int:pk>/delete/", views.SoftwareLicenseDeleteView.as_view(), name="softwarelicense_delete"),
-8
View File
@@ -3,8 +3,6 @@ from .software_license import (
SoftwareLicenseView, SoftwareLicenseView,
SoftwareLicenseEditView, SoftwareLicenseEditView,
SoftwareLicenseDeleteView, SoftwareLicenseDeleteView,
SoftwareLicenseBulkImportView,
SoftwareLicenseBulkEditView,
SoftwareLicenseBulkDeleteView, SoftwareLicenseBulkDeleteView,
) )
from .software_product import ( from .software_product import (
@@ -12,8 +10,6 @@ from .software_product import (
SoftwareProductView, SoftwareProductView,
SoftwareProductEditView, SoftwareProductEditView,
SoftwareProductDeleteView, SoftwareProductDeleteView,
SoftwareProductBulkImportView,
SoftwareProductBulkEditView,
SoftwareProductBulkDeleteView, SoftwareProductBulkDeleteView,
) )
from .software_product_installation import ( from .software_product_installation import (
@@ -21,8 +17,6 @@ from .software_product_installation import (
SoftwareProductInstallationView, SoftwareProductInstallationView,
SoftwareProductInstallationEditView, SoftwareProductInstallationEditView,
SoftwareProductInstallationDeleteView, SoftwareProductInstallationDeleteView,
SoftwareProductInstallationBulkImportView,
SoftwareProductInstallationBulkEditView,
SoftwareProductInstallationBulkDeleteView, SoftwareProductInstallationBulkDeleteView,
) )
from .software_product_version import ( from .software_product_version import (
@@ -30,7 +24,5 @@ from .software_product_version import (
SoftwareProductVersionView, SoftwareProductVersionView,
SoftwareProductVersionEditView, SoftwareProductVersionEditView,
SoftwareProductVersionDeleteView, SoftwareProductVersionDeleteView,
SoftwareProductVersionBulkImportView,
SoftwareProductVersionBulkEditView,
SoftwareProductVersionBulkDeleteView, SoftwareProductVersionBulkDeleteView,
) )
-13
View File
@@ -31,19 +31,6 @@ class SoftwareLicenseDeleteView(generic.ObjectDeleteView):
queryset = SoftwareLicense.objects.all() queryset = SoftwareLicense.objects.all()
class SoftwareLicenseBulkImportView(generic.BulkImportView):
queryset = SoftwareLicense.objects.all()
model_form = forms.SoftwareLicenseImportForm
table = tables.SoftwareLicenseTable
class SoftwareLicenseBulkEditView(generic.BulkEditView):
queryset = SoftwareLicense.objects.all()
filterset = filtersets.SoftwareLicenseFilterSet
table = tables.SoftwareLicenseTable
form = forms.SoftwareLicenseBulkEditForm
class SoftwareLicenseBulkDeleteView(generic.BulkDeleteView): class SoftwareLicenseBulkDeleteView(generic.BulkDeleteView):
queryset = SoftwareLicense.objects.all() queryset = SoftwareLicense.objects.all()
table = tables.SoftwareLicenseTable table = tables.SoftwareLicenseTable
-14
View File
@@ -35,20 +35,6 @@ class SoftwareProductDeleteView(generic.ObjectDeleteView):
queryset = SoftwareProduct.objects.all() queryset = SoftwareProduct.objects.all()
class SoftwareProductBulkImportView(generic.BulkImportView):
queryset = SoftwareProduct.objects.all()
model_form = forms.SoftwareProductImportForm
table = tables.SoftwareProductTable
class SoftwareProductBulkEditView(generic.BulkEditView):
queryset = SoftwareProduct.objects.all()
filterset = filtersets.SoftwareProductFilterSet
filterset_form = forms.SoftwareProductFilterForm
table = tables.SoftwareProductTable
form = forms.SoftwareProductBulkEditForm
class SoftwareProductBulkDeleteView(generic.BulkDeleteView): class SoftwareProductBulkDeleteView(generic.BulkDeleteView):
queryset = SoftwareProduct.objects.all() queryset = SoftwareProduct.objects.all()
table = tables.SoftwareProductTable table = tables.SoftwareProductTable
@@ -31,19 +31,6 @@ class SoftwareProductInstallationDeleteView(generic.ObjectDeleteView):
queryset = SoftwareProductInstallation.objects.all() queryset = SoftwareProductInstallation.objects.all()
class SoftwareProductInstallationBulkImportView(generic.BulkImportView):
queryset = SoftwareProductInstallation.objects.all()
model_form = forms.SoftwareProductInstallationImportForm
table = tables.SoftwareProductInstallationTable
class SoftwareProductInstallationBulkEditView(generic.BulkEditView):
queryset = SoftwareProductInstallation.objects.all()
filterset = filtersets.SoftwareProductInstallationFilterSet
table = tables.SoftwareProductInstallationTable
form = forms.SoftwareProductInstallationBulkEditForm
class SoftwareProductInstallationBulkDeleteView(generic.BulkDeleteView): class SoftwareProductInstallationBulkDeleteView(generic.BulkDeleteView):
queryset = SoftwareProductInstallation.objects.all() queryset = SoftwareProductInstallation.objects.all()
table = tables.SoftwareProductInstallationTable table = tables.SoftwareProductInstallationTable
@@ -35,19 +35,6 @@ class SoftwareProductVersionDeleteView(generic.ObjectDeleteView):
queryset = SoftwareProductVersion.objects.all() queryset = SoftwareProductVersion.objects.all()
class SoftwareProductVersionBulkImportView(generic.BulkImportView):
queryset = SoftwareProductVersion.objects.all()
model_form = forms.SoftwareProductVersionImportForm
table = tables.SoftwareProductVersionTable
class SoftwareProductVersionBulkEditView(generic.BulkEditView):
queryset = SoftwareProductVersion.objects.all()
filterset = filtersets.SoftwareProductVersionFilterSet
table = tables.SoftwareProductVersionTable
form = forms.SoftwareProductVersionBulkEditForm
class SoftwareProductVersionBulkDeleteView(generic.BulkDeleteView): class SoftwareProductVersionBulkDeleteView(generic.BulkDeleteView):
queryset = SoftwareProductVersion.objects.all() queryset = SoftwareProductVersion.objects.all()
table = tables.SoftwareProductVersionTable table = tables.SoftwareProductVersionTable
+11 -22
View File
@@ -7,7 +7,7 @@ name = "netbox-slm"
dynamic = ["version"] dynamic = ["version"]
description = "Software Lifecycle Management Netbox Plugin" description = "Software Lifecycle Management Netbox Plugin"
readme = "README.md" readme = "README.md"
requires-python = ">=3.9" requires-python = ">=3.11"
license = { text = "Apache-2.0" } license = { text = "Apache-2.0" }
authors = [ authors = [
{name = "ICTU", email = "open-source-projects@ictu.nl"}, {name = "ICTU", email = "open-source-projects@ictu.nl"},
@@ -21,9 +21,8 @@ classifiers = [
"Programming Language :: Python", "Programming Language :: Python",
"Programming Language :: Python :: 3", "Programming Language :: Python :: 3",
"Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP",
"Topic :: Internet :: WWW/HTTP :: Dynamic Content", "Topic :: Internet :: WWW/HTTP :: Dynamic Content",
] ]
@@ -31,13 +30,12 @@ dependencies = []
[project.optional-dependencies] [project.optional-dependencies]
build = [ build = [
"build == 1.0.3", "build == 1.2.1",
"setuptools == 68.2.0", "setuptools == 70.3.0",
"twine == 3.7.1", "twine == 5.1.1",
] ]
tools = [ tools = [
"black == 23.3.0", "ruff == 0.5.1",
"ruff == 0.0.275",
] ]
[tool.setuptools.dynamic] [tool.setuptools.dynamic]
@@ -46,24 +44,12 @@ version = {attr = "netbox_slm.__version__"}
[tool.setuptools.packages.find] [tool.setuptools.packages.find]
include = ["netbox_slm"] include = ["netbox_slm"]
[tool.black]
line-length = 120
target-version = ["py39"]
color = true
check = true
diff = true
fast = true
extend-exclude = '''
netbox_slm/migrations/.*.py
'''
[tool.ruff] [tool.ruff]
line-length = 120 line-length = 120
target-version = "py39" target-version = "py311"
format = "github"
src = ["netbox_slm"] src = ["netbox_slm"]
[tool.ruff.per-file-ignores] [tool.ruff.lint.per-file-ignores]
"__init__.py" = [ "__init__.py" = [
"D104", # https://beta.ruff.rs/docs/rules/#pydocstyle-d - don't require doc strings in __init__.py files "D104", # https://beta.ruff.rs/docs/rules/#pydocstyle-d - don't require doc strings in __init__.py files
"F401", # https://beta.ruff.rs/docs/rules/#pyflakes-f - don't complain about unused imports in __init__.py files "F401", # https://beta.ruff.rs/docs/rules/#pyflakes-f - don't complain about unused imports in __init__.py files
@@ -71,3 +57,6 @@ src = ["netbox_slm"]
"netbox_slm/migrations/*.py" = [ "netbox_slm/migrations/*.py" = [
"E501", # https://beta.ruff.rs/docs/rules/line-too-long/ - don't check on Django generated migration files "E501", # https://beta.ruff.rs/docs/rules/line-too-long/ - don't check on Django generated migration files
] ]
[tool.ruff.format]
exclude = ["netbox_slm/migrations/*.py"]