From 88edcde8d6c190cc7278798f99a386d3efc9f022 Mon Sep 17 00:00:00 2001 From: wkoot <3715211+wkoot@users.noreply.github.com> Date: Wed, 19 Apr 2023 10:14:32 +0200 Subject: [PATCH] Unify api serializers (#16) --- .env | 2 +- .github/workflows/docker-image.yml | 23 ++++- .gitignore | 2 + MANIFEST.in | 5 +- ci/Dockerfile-CI | 4 + ci/configuration/extra.py | 7 ++ ci/configuration/ldap/extra.py | 28 ------ ci/configuration/ldap/ldap_config.py | 90 ------------------- ...ose.override.yml => docker-compose.ci.yml} | 4 + ci/docker-compose.yml | 2 - ci/reports/.gitkeep | 0 ci/requirements_ci.txt | 2 + netbox_slm/__init__.py | 9 +- netbox_slm/api/serializers.py | 10 +-- netbox_slm/api/urls.py | 2 +- netbox_slm/api/views.py | 6 +- netbox_slm/filtersets.py | 8 +- netbox_slm/forms.py | 11 +-- netbox_slm/models.py | 4 +- netbox_slm/navigation.py | 1 - netbox_slm/tables.py | 4 +- netbox_slm/tests/test_models.py | 36 ++++++++ netbox_slm/tests/test_smoke.py | 16 ---- netbox_slm/urls.py | 2 +- netbox_slm/views.py | 8 +- setup.cfg | 14 ++- setup.py | 4 +- sonar-project.properties | 13 +++ start-netbox.sh | 2 +- 29 files changed, 127 insertions(+), 192 deletions(-) delete mode 100644 ci/configuration/ldap/extra.py delete mode 100644 ci/configuration/ldap/ldap_config.py rename ci/{docker-compose.override.yml => docker-compose.ci.yml} (76%) create mode 100644 ci/reports/.gitkeep create mode 100644 ci/requirements_ci.txt create mode 100644 netbox_slm/tests/test_models.py delete mode 100644 netbox_slm/tests/test_smoke.py create mode 100644 sonar-project.properties diff --git a/.env b/.env index 6f67894..56a3cc3 100644 --- a/.env +++ b/.env @@ -1,3 +1,3 @@ COMPOSE_PATH_SEPARATOR=: -COMPOSE_FILE=ci/docker-compose.yml:ci/docker-compose.override.yml +COMPOSE_FILE=ci/docker-compose.yml:ci/docker-compose.ci.yml COMPOSE_PROJECT_NAME=netbox-docker diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index c215f3d..74bb16d 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -1,6 +1,11 @@ name: Docker Image CI -on: [push, pull_request] +on: + push: + branches: + - master + pull_request: + types: [opened, synchronize, reopened] jobs: build: @@ -15,5 +20,17 @@ jobs: # clearcache is provided by Django extras, which is not loaded if netbox-slm cannot be loaded run: docker compose run netbox sh -c "/opt/netbox/venv/bin/python manage.py clearcache" - - name: Run Django tests for netbox_slm - run: docker compose run netbox sh -c "/opt/netbox/venv/bin/python manage.py test netbox_slm" + - name: Run Django tests with coverage for netbox_slm + run: | + chmod go+w ci/reports + docker compose run netbox sh -c " \ + /opt/netbox/venv/bin/coverage run --source='netbox_slm' manage.py test netbox_slm && \ + /opt/netbox/venv/bin/coverage report --fail-under=0 && \ + /opt/netbox/venv/bin/coverage xml -o /ci/reports/coverage.xml" + + - name: Sonarcloud scan + if: env.SONAR_TOKEN != null + uses: sonarsource/sonarcloud-github-action@master + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/.gitignore b/.gitignore index bdab604..a5534c1 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,6 @@ **/.vscode **/dist **/netbox_slm.egg-info +ci/docker-compose.override.yml +ci/reports out/production diff --git a/MANIFEST.in b/MANIFEST.in index 813087f..fd64489 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,3 +1,4 @@ include ../LICENSE -include ../README.rst -recursive-include netbox_slm/templates * \ No newline at end of file +include ../README.md +include ../SECURITY.md +recursive-include netbox_slm/templates * diff --git a/ci/Dockerfile-CI b/ci/Dockerfile-CI index 6ca4687..822fc40 100644 --- a/ci/Dockerfile-CI +++ b/ci/Dockerfile-CI @@ -1,3 +1,7 @@ FROM netboxcommunity/netbox:v3.4.7 +RUN mkdir /ci && chmod go+w /ci +COPY ../ci/requirements_ci.txt /ci/ +RUN pip install -r /ci/requirements_ci.txt + COPY ../netbox_slm /opt/netbox/netbox/netbox_slm diff --git a/ci/configuration/extra.py b/ci/configuration/extra.py index 740aeb3..c721991 100644 --- a/ci/configuration/extra.py +++ b/ci/configuration/extra.py @@ -2,3 +2,10 @@ PLUGINS = ['netbox_slm'] DEBUG = True SECRET_KEY = 'dummy' DEVELOPER = True +PLUGINS_CONFIG = { + 'netbox_slm': dict( + TEST_RUNNER='xmlrunner.extra.djangotestrunner.XMLTestRunner', + TEST_OUTPUT_DIR='/ci/reports/', + TEST_OUTPUT_FILE_NAME='junit.xml', + ) +} diff --git a/ci/configuration/ldap/extra.py b/ci/configuration/ldap/extra.py deleted file mode 100644 index 4505197..0000000 --- a/ci/configuration/ldap/extra.py +++ /dev/null @@ -1,28 +0,0 @@ -#### -## This file contains extra configuration options that can't be configured -## directly through environment variables. -## All vairables set here overwrite any existing found in ldap_config.py -#### - -# # This Python script inherits all the imports from ldap_config.py -# from django_auth_ldap.config import LDAPGroupQuery # Imported since not in ldap_config.py - -# # Sets a base requirement of membetship to netbox-user-ro, netbox-user-rw, or netbox-user-admin. -# AUTH_LDAP_REQUIRE_GROUP = ( -# LDAPGroupQuery("cn=netbox-user-ro,ou=groups,dc=example,dc=com") -# | LDAPGroupQuery("cn=netbox-user-rw,ou=groups,dc=example,dc=com") -# | LDAPGroupQuery("cn=netbox-user-admin,ou=groups,dc=example,dc=com") -# ) - -# # Sets LDAP Flag groups variables with example. -# AUTH_LDAP_USER_FLAGS_BY_GROUP = { -# "is_staff": ( -# LDAPGroupQuery("cn=netbox-user-ro,ou=groups,dc=example,dc=com") -# | LDAPGroupQuery("cn=netbox-user-rw,ou=groups,dc=example,dc=com") -# | LDAPGroupQuery("cn=netbox-user-admin,ou=groups,dc=example,dc=com") -# ), -# "is_superuser": "cn=netbox-user-admin,ou=groups,dc=example,dc=com", -# } - -# # Sets LDAP Mirror groups variables with example groups -# AUTH_LDAP_MIRROR_GROUPS = ["netbox-user-ro", "netbox-user-rw", "netbox-user-admin"] diff --git a/ci/configuration/ldap/ldap_config.py b/ci/configuration/ldap/ldap_config.py deleted file mode 100644 index 3071b45..0000000 --- a/ci/configuration/ldap/ldap_config.py +++ /dev/null @@ -1,90 +0,0 @@ -from importlib import import_module -from os import environ - -import ldap -from django_auth_ldap.config import LDAPSearch - - -# Read secret from file -def _read_secret(secret_name, default=None): - try: - f = open('/run/secrets/' + secret_name, 'r', encoding='utf-8') - except EnvironmentError: - return default - else: - with f: - return f.readline().strip() - -# Import and return the group type based on string name -def _import_group_type(group_type_name): - mod = import_module('django_auth_ldap.config') - try: - return getattr(mod, group_type_name)() - except: - return None - -# Server URI -AUTH_LDAP_SERVER_URI = environ.get('AUTH_LDAP_SERVER_URI', '') - -# The following may be needed if you are binding to Active Directory. -AUTH_LDAP_CONNECTION_OPTIONS = { - ldap.OPT_REFERRALS: 0 -} - -# Set the DN and password for the NetBox service account. -AUTH_LDAP_BIND_DN = environ.get('AUTH_LDAP_BIND_DN', '') -AUTH_LDAP_BIND_PASSWORD = _read_secret('auth_ldap_bind_password', environ.get('AUTH_LDAP_BIND_PASSWORD', '')) - -# Set a string template that describes any user’s distinguished name based on the username. -AUTH_LDAP_USER_DN_TEMPLATE = environ.get('AUTH_LDAP_USER_DN_TEMPLATE', None) - -# Enable STARTTLS for ldap authentication. -AUTH_LDAP_START_TLS = environ.get('AUTH_LDAP_START_TLS', 'False').lower() == 'true' - -# Include this setting if you want to ignore certificate errors. This might be needed to accept a self-signed cert. -# Note that this is a NetBox-specific setting which sets: -# ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER) -LDAP_IGNORE_CERT_ERRORS = environ.get('LDAP_IGNORE_CERT_ERRORS', 'False').lower() == 'true' - -AUTH_LDAP_USER_SEARCH_BASEDN = environ.get('AUTH_LDAP_USER_SEARCH_BASEDN', '') -AUTH_LDAP_USER_SEARCH_ATTR = environ.get('AUTH_LDAP_USER_SEARCH_ATTR', 'sAMAccountName') -AUTH_LDAP_USER_SEARCH = LDAPSearch( - AUTH_LDAP_USER_SEARCH_BASEDN, - ldap.SCOPE_SUBTREE, - "(" + AUTH_LDAP_USER_SEARCH_ATTR + "=%(user)s)" -) - -# This search ought to return all groups to which the user belongs. django_auth_ldap uses this to determine group -# heirarchy. -AUTH_LDAP_GROUP_SEARCH_BASEDN = environ.get('AUTH_LDAP_GROUP_SEARCH_BASEDN', '') -AUTH_LDAP_GROUP_SEARCH_CLASS = environ.get('AUTH_LDAP_GROUP_SEARCH_CLASS', 'group') -AUTH_LDAP_GROUP_SEARCH = LDAPSearch(AUTH_LDAP_GROUP_SEARCH_BASEDN, ldap.SCOPE_SUBTREE, - "(objectClass=" + AUTH_LDAP_GROUP_SEARCH_CLASS + ")") -AUTH_LDAP_GROUP_TYPE = _import_group_type(environ.get('AUTH_LDAP_GROUP_TYPE', 'GroupOfNamesType')) - -# Define a group required to login. -AUTH_LDAP_REQUIRE_GROUP = environ.get('AUTH_LDAP_REQUIRE_GROUP_DN') - -# Define special user types using groups. Exercise great caution when assigning superuser status. -AUTH_LDAP_USER_FLAGS_BY_GROUP = {} - -if AUTH_LDAP_REQUIRE_GROUP is not None: - AUTH_LDAP_USER_FLAGS_BY_GROUP = { - "is_active": environ.get('AUTH_LDAP_REQUIRE_GROUP_DN', ''), - "is_staff": environ.get('AUTH_LDAP_IS_ADMIN_DN', ''), - "is_superuser": environ.get('AUTH_LDAP_IS_SUPERUSER_DN', '') - } - -# For more granular permissions, we can map LDAP groups to Django groups. -AUTH_LDAP_FIND_GROUP_PERMS = environ.get('AUTH_LDAP_FIND_GROUP_PERMS', 'True').lower() == 'true' -AUTH_LDAP_MIRROR_GROUPS = environ.get('AUTH_LDAP_MIRROR_GROUPS', '').lower() == 'true' - -# Cache groups for one hour to reduce LDAP traffic -AUTH_LDAP_CACHE_TIMEOUT = int(environ.get('AUTH_LDAP_CACHE_TIMEOUT', 3600)) - -# Populate the Django user from the LDAP directory. -AUTH_LDAP_USER_ATTR_MAP = { - "first_name": environ.get('AUTH_LDAP_ATTR_FIRSTNAME', 'givenName'), - "last_name": environ.get('AUTH_LDAP_ATTR_LASTNAME', 'sn'), - "email": environ.get('AUTH_LDAP_ATTR_MAIL', 'mail') -} diff --git a/ci/docker-compose.override.yml b/ci/docker-compose.ci.yml similarity index 76% rename from ci/docker-compose.override.yml rename to ci/docker-compose.ci.yml index 5838746..0939273 100644 --- a/ci/docker-compose.override.yml +++ b/ci/docker-compose.ci.yml @@ -7,6 +7,10 @@ services: context: .. dockerfile: ci/Dockerfile-CI image: netbox:slm + environment: + - COVERAGE_FILE=/ci/.coverage + volumes: + - ./reports:/ci/reports netbox-worker: image: netbox:slm netbox-housekeeping: diff --git a/ci/docker-compose.yml b/ci/docker-compose.yml index e862fae..1b5997d 100644 --- a/ci/docker-compose.yml +++ b/ci/docker-compose.yml @@ -11,8 +11,6 @@ services: user: 'unit:root' volumes: - ./configuration:/etc/netbox/config:z,ro -# - ./reports:/etc/netbox/reports:z,ro -# - ./scripts:/etc/netbox/scripts:z,ro - netbox-media-files:/opt/netbox/netbox/media:z netbox-worker: <<: *netbox diff --git a/ci/reports/.gitkeep b/ci/reports/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/ci/requirements_ci.txt b/ci/requirements_ci.txt new file mode 100644 index 0000000..eca0d7a --- /dev/null +++ b/ci/requirements_ci.txt @@ -0,0 +1,2 @@ +coverage==7.2.2 +unittest-xml-reporting==3.2.0 diff --git a/netbox_slm/__init__.py b/netbox_slm/__init__.py index 67a513c..82f0b04 100644 --- a/netbox_slm/__init__.py +++ b/netbox_slm/__init__.py @@ -4,14 +4,15 @@ from extras.plugins import PluginConfig class SLMConfig(PluginConfig): name = 'netbox_slm' verbose_name = 'Software Lifecycle Management' - description = 'Software Lifecycle Management' - version = '1.2' - author = 'Hedde van der Heide' - author_email = 'hedde.vanderheide@ictu.nl' + description = 'Software Lifecycle Management Netbox Plugin.' + version = '1.3' + author = 'ICTU' + author_email = 'open-source-projects@ictu.nl' base_url = 'slm' required_settings = [] default_settings = { 'version_info': False } + config = SLMConfig diff --git a/netbox_slm/api/serializers.py b/netbox_slm/api/serializers.py index 520663a..c0fe19e 100644 --- a/netbox_slm/api/serializers.py +++ b/netbox_slm/api/serializers.py @@ -1,9 +1,7 @@ from rest_framework import serializers from netbox.api.serializers import NetBoxModelSerializer -from netbox_slm.models import ( - SoftwareProduct, SoftwareProductVersion, SoftwareProductInstallation, -) +from netbox_slm.models import SoftwareProduct, SoftwareProductVersion, SoftwareProductInstallation class SoftwareProductSerializer(NetBoxModelSerializer): @@ -19,7 +17,7 @@ class SoftwareProductSerializer(NetBoxModelSerializer): ] def get_display(self, obj): - return f"{obj.manufacturer.name} - {obj.name}" + return f"{obj.manufacturer} - {obj}" class SoftwareProductVersionSerializer(NetBoxModelSerializer): @@ -35,7 +33,7 @@ class SoftwareProductVersionSerializer(NetBoxModelSerializer): ] def get_display(self, obj): - return obj.name + return f"{obj}" class SoftwareProductInstallationSerializer(NetBoxModelSerializer): @@ -52,4 +50,4 @@ class SoftwareProductInstallationSerializer(NetBoxModelSerializer): ] def get_display(self, obj): - return obj + return f"{obj}" diff --git a/netbox_slm/api/urls.py b/netbox_slm/api/urls.py index 421eb61..aaa1d43 100644 --- a/netbox_slm/api/urls.py +++ b/netbox_slm/api/urls.py @@ -12,4 +12,4 @@ router.APIRootView = NetboxSLMRootView router.register("softwareproducts", SoftwareProductViewSet) router.register("softwareproductversions", SoftwareProductVersionViewSet) router.register("softwareproductinstallations", SoftwareProductInstallationViewSet) -urlpatterns = router.urls \ No newline at end of file +urlpatterns = router.urls diff --git a/netbox_slm/api/views.py b/netbox_slm/api/views.py index 021c22a..88b13b6 100644 --- a/netbox_slm/api/views.py +++ b/netbox_slm/api/views.py @@ -1,15 +1,13 @@ -from netbox.api.viewsets import NetBoxModelViewSet from rest_framework.routers import APIRootView +from netbox.api.viewsets import NetBoxModelViewSet from netbox_slm.api.serializers import ( SoftwareProductSerializer, SoftwareProductVersionSerializer, SoftwareProductInstallationSerializer, ) from netbox_slm.filtersets import ( SoftwareProductFilterSet, SoftwareProductVersionFilterSet, SoftwareProductInstallationFilterSet, ) -from netbox_slm.models import ( - SoftwareProduct, SoftwareProductVersion, SoftwareProductInstallation, -) +from netbox_slm.models import SoftwareProduct, SoftwareProductVersion, SoftwareProductInstallation class NetboxSLMRootView(APIRootView): diff --git a/netbox_slm/filtersets.py b/netbox_slm/filtersets.py index 93bace7..99778a8 100644 --- a/netbox_slm/filtersets.py +++ b/netbox_slm/filtersets.py @@ -1,11 +1,12 @@ from django.db.models import Q from netbox.filtersets import NetBoxModelFilterSet -from netbox_slm.models import * +from netbox_slm.models import SoftwareProduct, SoftwareProductVersion, SoftwareProductInstallation class SoftwareProductFilterSet(NetBoxModelFilterSet): """Filter capabilities for SoftwareProduct instances.""" + class Meta: model = SoftwareProduct fields = tuple() @@ -14,13 +15,13 @@ class SoftwareProductFilterSet(NetBoxModelFilterSet): """Perform the filtered search.""" if not value.strip(): return queryset - qs_filter = Q(name__icontains=value) | \ - Q(manufacturer__name__icontains=value) + qs_filter = Q(name__icontains=value) | Q(manufacturer__name__icontains=value) return queryset.filter(qs_filter) class SoftwareProductVersionFilterSet(NetBoxModelFilterSet): """Filter capabilities for SoftwareProductVersion instances.""" + class Meta: model = SoftwareProductVersion fields = ( @@ -39,6 +40,7 @@ class SoftwareProductVersionFilterSet(NetBoxModelFilterSet): class SoftwareProductInstallationFilterSet(NetBoxModelFilterSet): """Filter capabilities for SoftwareProductInstallation instances.""" + class Meta: model = SoftwareProductInstallation fields = tuple() diff --git a/netbox_slm/forms.py b/netbox_slm/forms.py index e7cea70..e03f4c3 100644 --- a/netbox_slm/forms.py +++ b/netbox_slm/forms.py @@ -3,16 +3,9 @@ from django.urls import reverse_lazy from django.utils.translation import gettext as _ from dcim.models import Manufacturer, Device -from netbox.forms import ( - NetBoxModelForm, - NetBoxModelCSVForm, - NetBoxModelBulkEditForm, - NetBoxModelFilterSetForm, -) +from netbox.forms import NetBoxModelForm, NetBoxModelCSVForm, NetBoxModelBulkEditForm, NetBoxModelFilterSetForm from netbox_slm.models import SoftwareProduct, SoftwareProductVersion, SoftwareProductInstallation -from utilities.forms import ( - DynamicModelChoiceField, APISelect, TagFilterField, ChoiceField -) +from utilities.forms import DynamicModelChoiceField, APISelect, TagFilterField from virtualization.models import VirtualMachine diff --git a/netbox_slm/models.py b/netbox_slm/models.py index bf6545f..d2beac9 100644 --- a/netbox_slm/models.py +++ b/netbox_slm/models.py @@ -9,7 +9,7 @@ from utilities.querysets import RestrictedQuerySet class SoftwareProduct(NetBoxModel): name = models.CharField(max_length=128) description = models.CharField(max_length=255, null=True, blank=True) - + manufacturer = models.ForeignKey( to='dcim.Manufacturer', on_delete=models.PROTECT, @@ -89,4 +89,4 @@ class SoftwareProductInstallation(NetBoxModel): return self.device or self.virtualmachine def render_type(self): - return f"{'device' if self.device else 'virtualmachine'}" + return 'device' if self.device else 'virtualmachine' diff --git a/netbox_slm/navigation.py b/netbox_slm/navigation.py index 71c25de..d34579b 100644 --- a/netbox_slm/navigation.py +++ b/netbox_slm/navigation.py @@ -1,7 +1,6 @@ from extras.plugins import PluginMenuButton, PluginMenuItem from utilities.choices import ButtonColorChoices - menu_items = ( PluginMenuItem( link='plugins:netbox_slm:softwareproduct_list', diff --git a/netbox_slm/tables.py b/netbox_slm/tables.py index 3accc26..bec0967 100644 --- a/netbox_slm/tables.py +++ b/netbox_slm/tables.py @@ -1,9 +1,9 @@ import django_tables2 as tables - from django.db.models import Count from django_tables2.utils import Accessor + +from netbox.tables import NetBoxTable, ToggleColumn, columns from netbox_slm.models import SoftwareProduct, SoftwareProductVersion, SoftwareProductInstallation -from netbox.tables import NetBoxTable, ChoiceFieldColumn, ToggleColumn, columns class SoftwareProductTable(NetBoxTable): diff --git a/netbox_slm/tests/test_models.py b/netbox_slm/tests/test_models.py new file mode 100644 index 0000000..25062a1 --- /dev/null +++ b/netbox_slm/tests/test_models.py @@ -0,0 +1,36 @@ +from django.test import TestCase + +from netbox_slm.models import SoftwareProduct, SoftwareProductVersion, SoftwareProductInstallation + + +class ModelTestCase(TestCase): + def setUp(self): + self.p_name = "test product" + self.v_name = "test version" + + self.software_product = SoftwareProduct.objects.create(name=self.p_name) + self.software_product_version = SoftwareProductVersion.objects.create( + name=self.v_name, software_product=self.software_product + ) + self.software_product_installation = SoftwareProductInstallation.objects.create( + software_product=self.software_product, version=self.software_product_version + ) + + def test_model_name(self): + self.assertEqual(self.p_name, str(self.software_product)) + self.assertEqual(self.v_name, str(self.software_product_version)) + self.assertTrue(str(self.software_product_installation).isnumeric()) # should be PK + + def test_absolute_url(self): + self.assertEqual("/plugins/slm/software-products/1/", self.software_product.get_absolute_url()) + self.assertEqual("/plugins/slm/versions/1/", self.software_product_version.get_absolute_url()) + self.assertEqual("/plugins/slm/installations/1/", self.software_product_installation.get_absolute_url()) + + def test_get_installation_count(self): + installation_ss = '1' + self.assertEqual(installation_ss.format(self.p_name), self.software_product.get_installation_count()) + self.assertEqual(installation_ss.format(self.v_name), self.software_product_version.get_installation_count()) + + def test_product_installation_methods(self): + self.assertEqual("virtualmachine", self.software_product_installation.render_type()) + self.assertIsNone(self.software_product_installation.get_platform()) diff --git a/netbox_slm/tests/test_smoke.py b/netbox_slm/tests/test_smoke.py deleted file mode 100644 index 0a08181..0000000 --- a/netbox_slm/tests/test_smoke.py +++ /dev/null @@ -1,16 +0,0 @@ -from django.test import TestCase - -from netbox_slm.models import SoftwareProduct, SoftwareProductVersion, SoftwareProductInstallation - - -class ModelTestCase(TestCase): - def test_smoke(self): - software_product = SoftwareProduct.objects.create(name="test product") - software_product_version = SoftwareProductVersion.objects.create( - name="test version", software_product=software_product - ) - software_product_installation = SoftwareProductInstallation.objects.create( - software_product=software_product, version=software_product_version - ) - - self.assertEqual('virtualmachine', software_product_installation.render_type()) diff --git a/netbox_slm/urls.py b/netbox_slm/urls.py index 7e3e2d9..d951389 100644 --- a/netbox_slm/urls.py +++ b/netbox_slm/urls.py @@ -1,6 +1,6 @@ from django.urls import path -from netbox.views.generic import ObjectChangeLogView +from netbox.views.generic import ObjectChangeLogView from netbox_slm import views from netbox_slm.models import SoftwareProduct, SoftwareProductVersion, SoftwareProductInstallation diff --git a/netbox_slm/views.py b/netbox_slm/views.py index 898e540..e549a57 100644 --- a/netbox_slm/views.py +++ b/netbox_slm/views.py @@ -1,10 +1,6 @@ from netbox.views import generic -from netbox_slm import filtersets -from netbox_slm import forms -from netbox_slm import tables -from netbox_slm.models import ( - SoftwareProduct, SoftwareProductVersion, SoftwareProductInstallation -) +from netbox_slm import filtersets, forms, tables +from netbox_slm.models import SoftwareProduct, SoftwareProductVersion, SoftwareProductInstallation class SoftwareProductListView(generic.ObjectListView): diff --git a/setup.cfg b/setup.cfg index 36e87d0..33ccb12 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,11 +1,9 @@ [metadata] name = netbox-slm -version = 1.2 +version = 1.3 description = Software Lifecycle Management Netbox Plugin. -# long_description = file: README.rst -# long_description_content_type='text/x-rst' -author = Hedde van der Heide -author_email = hedde.vanderheide@ictu.nl +author = ICTU +author_email = open-source-projects@ictu.nl license = Apache 2.0 classifiers = Environment :: Web Environment @@ -16,13 +14,13 @@ classifiers = Programming Language :: Python Programming Language :: Python :: 3 Programming Language :: Python :: 3 :: Only - Programming Language :: Python :: 3.7 - Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 + Programming Language :: Python :: 3.10 + Programming Language :: Python :: 3.11 Topic :: Internet :: WWW/HTTP Topic :: Internet :: WWW/HTTP :: Dynamic Content [options] include_package_data = true packages = find: -python_requires = >=3.7 +python_requires = >=3.9 diff --git a/setup.py b/setup.py index 02997c3..6068493 100644 --- a/setup.py +++ b/setup.py @@ -1,3 +1,3 @@ -from setuptools import setup, Extension +from setuptools import setup -setup() \ No newline at end of file +setup() diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 0000000..fe9e86d --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,13 @@ +# Project metadata +sonar.organization=ictu +sonar.projectKey=ICTU_netbox_slm +sonar.projectName=netbox-slm +sonar.projectVersion=1.3 + +# Path is relative to the sonar-project.properties file +sonar.sources=netbox_slm +sonar.python.version=3.9 + +# Unit tests +sonar.python.xunit.reportPath=ci/reports/junit.xml +sonar.python.coverage.reportPaths=ci/reports/coverage.xml diff --git a/start-netbox.sh b/start-netbox.sh index 96758e3..749e0f9 100755 --- a/start-netbox.sh +++ b/start-netbox.sh @@ -1,7 +1,7 @@ git clone -b release https://github.com/netbox-community/netbox-docker.git cd netbox-docker tee docker-compose.override.yml <