From 5b0af9e3920035990d61f697ab5b89f1d23a68cc Mon Sep 17 00:00:00 2001 From: Frederico Sequeira <frederico.sequeira@ext.ec.europa.eu> Date: Fri, 15 Nov 2024 11:19:27 +0000 Subject: [PATCH 1/4] =?UTF-8?q?=E2=9C=A8=20Add=20Provider=20Credentials?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...maintenance_maintenance_window_and_more.py | 45 +++++++++++++ netbox_sys_plugin/models/__init__.py | 4 ++ .../{models.py => models/maintenance.py} | 0 netbox_sys_plugin/models/provider.py | 67 +++++++++++++++++++ netbox_sys_plugin/navigation.py | 30 ++++++--- netbox_sys_plugin/tables.py | 37 +++++++++- netbox_sys_plugin/urls.py | 1 + netbox_sys_plugin/views.py | 8 +++ 8 files changed, 181 insertions(+), 11 deletions(-) create mode 100644 netbox_sys_plugin/migrations/0002_alter_virtualmachinemaintenance_maintenance_window_and_more.py create mode 100644 netbox_sys_plugin/models/__init__.py rename netbox_sys_plugin/{models.py => models/maintenance.py} (100%) create mode 100644 netbox_sys_plugin/models/provider.py diff --git a/netbox_sys_plugin/migrations/0002_alter_virtualmachinemaintenance_maintenance_window_and_more.py b/netbox_sys_plugin/migrations/0002_alter_virtualmachinemaintenance_maintenance_window_and_more.py new file mode 100644 index 0000000..9c0f99e --- /dev/null +++ b/netbox_sys_plugin/migrations/0002_alter_virtualmachinemaintenance_maintenance_window_and_more.py @@ -0,0 +1,45 @@ +# Generated by Django 4.2.16 on 2024-11-15 09:53 + +import django.core.validators +from django.db import migrations, models +import django.db.models.deletion +import taggit.managers +import utilities.json + + +class Migration(migrations.Migration): + + dependencies = [ + ('contenttypes', '0002_remove_content_type_name'), + ('extras', '0098_webhook_custom_field_data_webhook_tags'), + ('netbox_sys_plugin', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='virtualmachinemaintenance', + name='maintenance_window', + field=models.CharField(blank=True, default=None, max_length=200, null=True, validators=[django.core.validators.RegexValidator(message='Incorrect maintenance window format', regex='(^([0-6])-[0-1]?[0-9]|2[0-3]):[0-5][0-9]$')]), + ), + migrations.CreateModel( + name='ProviderCredentials', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), + ('created', models.DateTimeField(auto_now_add=True, null=True)), + ('last_updated', models.DateTimeField(auto_now=True, null=True)), + ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder)), + ('provider_url', models.CharField(blank=True, default=None, max_length=200, null=True)), + ('provider_username', models.CharField(blank=True, default=None, max_length=200, null=True)), + ('provider_password', models.CharField(blank=True, default=None, max_length=200, null=True)), + ('assigned_object_id', models.PositiveBigIntegerField(blank=True, null=True)), + ('assigned_object_type', models.ForeignKey(blank=True, limit_choices_to=models.Q(models.Q(('app_label', 'virtualization'), ('model', 'Cluster'))), null=True, on_delete=django.db.models.deletion.PROTECT, to='contenttypes.contenttype')), + ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), + ], + options={ + 'verbose_name': 'Provider Information', + 'verbose_name_plural': 'Provider Informations', + 'ordering': ['assigned_object_id'], + 'unique_together': {('assigned_object_id',)}, + }, + ), + ] diff --git a/netbox_sys_plugin/models/__init__.py b/netbox_sys_plugin/models/__init__.py new file mode 100644 index 0000000..cef638b --- /dev/null +++ b/netbox_sys_plugin/models/__init__.py @@ -0,0 +1,4 @@ +"""Models definitions""" + +from .maintenance import VirtualMachineMaintenance +from .provider import ProviderCredentials \ No newline at end of file diff --git a/netbox_sys_plugin/models.py b/netbox_sys_plugin/models/maintenance.py similarity index 100% rename from netbox_sys_plugin/models.py rename to netbox_sys_plugin/models/maintenance.py diff --git a/netbox_sys_plugin/models/provider.py b/netbox_sys_plugin/models/provider.py new file mode 100644 index 0000000..327afbc --- /dev/null +++ b/netbox_sys_plugin/models/provider.py @@ -0,0 +1,67 @@ +"""Models definitions""" + +from django.core.validators import ( + RegexValidator, +) +from django.urls import reverse +from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation +from django.contrib.contenttypes.models import ContentType +from django.db import models +from django.db.models import Q +from virtualization.models import Cluster +from netbox.models import NetBoxModel + +CLUSTER_ASSIGNMENT_MODELS = models.Q(models.Q(app_label="virtualization", model="Cluster")) + + + +class ProviderCredentials(NetBoxModel): + """Cluster ProviderInfo definition class""" + + provider_url = models.CharField( + default=None, blank=True, null=True, + max_length=200) + + provider_username = models.CharField( + default=None, blank=True, null=True, + max_length=200) + + provider_password = models.CharField( + default=None, blank=True, null=True, + max_length=200) + + assigned_object_type = models.ForeignKey( + to=ContentType, + limit_choices_to=CLUSTER_ASSIGNMENT_MODELS, + on_delete=models.PROTECT, + null=True, + blank=True, + ) + assigned_object_id = models.PositiveBigIntegerField(null=True, blank=True) + assigned_object = GenericForeignKey( + ct_field="assigned_object_type", + fk_field="assigned_object_id", + ) + + class Meta: + """Meta class""" + unique_together = ["assigned_object_id"] + ordering = ["assigned_object_id"] + verbose_name = "Provider Information" + verbose_name_plural = "Provider Informations" + + + def __str__(self): + return f"{self.provider}" + + def get_absolute_url(self): + """override""" + return reverse("plugins:netbox_sys_plugin:providercredentials", args=[self.pk]) + +GenericRelation( + to=ProviderCredentials, + content_type_field="assigned_object_type", + object_id_field="assigned_object_id", + related_query_name="Cluster", +).contribute_to_class(Cluster, "ProviderCredentials") + diff --git a/netbox_sys_plugin/navigation.py b/netbox_sys_plugin/navigation.py index a7dd5e8..6988410 100644 --- a/netbox_sys_plugin/navigation.py +++ b/netbox_sys_plugin/navigation.py @@ -10,16 +10,16 @@ vm_maintenance_buttons = [ icon_class="mdi mdi-plus-thick", color=ButtonColorChoices.GREEN, ), - #PluginMenuButton( - # link="plugins:netbox_sys_plugin:virtualmachinemaintenance_add", - # title="Import", - # icon_class="mdi mdi-upload", - # color=ButtonColorChoices.CYAN, - # #permissions=["netbox_sys_plugin.add_macaddress"], - #), ] - +cluster_provider_credentials_buttons = [ + PluginMenuButton( + link="plugins:netbox_sys_plugin:virtualmachinemaintenance_add", + title="Add", + icon_class="mdi mdi-plus-thick", + color=ButtonColorChoices.GREEN, + ), +] vmMaintenanceItem = [ PluginMenuItem( @@ -29,9 +29,19 @@ vmMaintenanceItem = [ ), ] +clusterProviderCredentialsItem = [ + PluginMenuItem( + link="plugins:netbox_sys_plugin:providercredentials_list", + link_text="Provider Credentials", + buttons=cluster_provider_credentials_buttons, + ), +] + menu = PluginMenu( label="Sys", - groups=(("Maintenance", vmMaintenanceItem),) - , + groups=( + ("Maintenance", vmMaintenanceItem), + ("Provider", clusterProviderCredentialsItem), + ), icon_class="mdi mdi-all-inclusive-box-outline", ) diff --git a/netbox_sys_plugin/tables.py b/netbox_sys_plugin/tables.py index f3cb63b..118a627 100644 --- a/netbox_sys_plugin/tables.py +++ b/netbox_sys_plugin/tables.py @@ -2,7 +2,7 @@ import django_tables2 as tables from netbox.tables import NetBoxTable, columns -from .models import VirtualMachineMaintenance +from .models import VirtualMachineMaintenance, ProviderCredentials class VmMaintenanceTable(NetBoxTable): @@ -34,3 +34,38 @@ class VmMaintenanceTable(NetBoxTable): ) default_columns = ('id','maintenance_window','assigned_object') + + +class ProviderCredentialsTable(NetBoxTable): + """VM Maintenance Table definition class""" + + pk = columns.ToggleColumn() + id = tables.Column( + linkify=False, + ) + + assigned_object = tables.Column( + linkify=True, + orderable=False, + verbose_name="Cluster", + ) + + provider_url = tables.Column(linkify=True) + provider_username = tables.Column(linkify=True) + provider_password = tables.Column(linkify=True) + + class Meta(NetBoxTable.Meta): + """Meta class""" + model = ProviderCredentials + fields = ( + "pk", + "id", + "provider_url", + "provider_username", + "provider_password", + "assigned_object", + "created", + "last_updated", + ) + + default_columns = ('id','provider_url','provider_username','provider_password','assigned_object') diff --git a/netbox_sys_plugin/urls.py b/netbox_sys_plugin/urls.py index 8d9e94d..896246d 100644 --- a/netbox_sys_plugin/urls.py +++ b/netbox_sys_plugin/urls.py @@ -17,5 +17,6 @@ urlpatterns = ( path('vm-maintenance/<int:pk>/journal/', ObjectJournalView.as_view(), name='virtualmachinemaintenance_journal', kwargs={ 'model': models.VirtualMachineMaintenance }), + path('provider-credentials/', views.ProviderCredentialsView.as_view(), name='providercredentials_list'), ) diff --git a/netbox_sys_plugin/views.py b/netbox_sys_plugin/views.py index e4103f0..3b4baaa 100644 --- a/netbox_sys_plugin/views.py +++ b/netbox_sys_plugin/views.py @@ -29,3 +29,11 @@ class VmMaintenanceDeleteView(generic.ObjectDeleteView): """Vm maintenance delete view definition""" queryset = models.VirtualMachineMaintenance.objects.all() + +class ProviderCredentialsView(generic.ObjectListView): + """Cluster Provider Credentials list view definition""" + + queryset = models.ProviderCredentials.objects.all() + table = tables.ProviderCredentialsTable + #filterset = filtersets.VmMaintenanceFilterSet + #filterset_form = forms.VmMaintenanceFilterForm \ No newline at end of file -- GitLab From 89b3c765aba29d94c21b67caa24262198294afce Mon Sep 17 00:00:00 2001 From: Frederico Sequeira <frederico.sequeira@ext.ec.europa.eu> Date: Fri, 15 Nov 2024 14:29:40 +0000 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=8D=B1=20Updates=20Provider=20Credent?= =?UTF-8?q?ials=20objects?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- netbox_sys_plugin/api/serializers.py | 20 ++++++- netbox_sys_plugin/api/urls.py | 3 +- netbox_sys_plugin/api/views.py | 8 ++- netbox_sys_plugin/forms.py | 60 ++++++++++++++++++- netbox_sys_plugin/models/provider.py | 2 +- netbox_sys_plugin/navigation.py | 2 +- netbox_sys_plugin/template_content.py | 10 +++- .../cluster_providercredentials.html | 47 +++++++++++++++ .../providercredentials.html | 52 ++++++++++++++++ netbox_sys_plugin/urls.py | 13 +++- netbox_sys_plugin/views.py | 24 +++++++- 11 files changed, 228 insertions(+), 13 deletions(-) create mode 100644 netbox_sys_plugin/templates/netbox_sys_plugin/cluster_providercredentials.html create mode 100644 netbox_sys_plugin/templates/netbox_sys_plugin/providercredentials.html diff --git a/netbox_sys_plugin/api/serializers.py b/netbox_sys_plugin/api/serializers.py index 3ad0b68..4e7d712 100644 --- a/netbox_sys_plugin/api/serializers.py +++ b/netbox_sys_plugin/api/serializers.py @@ -1,6 +1,6 @@ from rest_framework import serializers -from virtualization.models import VirtualMachine -from .. models import VirtualMachineMaintenance +from virtualization.models import VirtualMachine, Cluster +from .. models import VirtualMachineMaintenance, ProviderCredentials from django.contrib.contenttypes.models import ContentType class VirtualMachineSerializer(serializers.ModelSerializer): @@ -8,6 +8,11 @@ class VirtualMachineSerializer(serializers.ModelSerializer): model = VirtualMachine fields = ['id', 'name'] +class ClusterSerializer(serializers.ModelSerializer): + class Meta: + model = Cluster + fields = ['id', 'name'] + class VirtualMachineMaintenanceSerializer(serializers.ModelSerializer): id = serializers.IntegerField(read_only=True) virtual_machine = VirtualMachineSerializer(source='assigned_object', read_only=True) @@ -18,3 +23,14 @@ class VirtualMachineMaintenanceSerializer(serializers.ModelSerializer): model = VirtualMachineMaintenance #fields = ['id','maintenance_window','assigned_object_type','assigned_object_id','assigned_object_type','virtual_machine'] fields = '__all__' + +class ProviderCredentialsSerializer(serializers.ModelSerializer): + id = serializers.IntegerField(read_only=True) + cluster = ClusterSerializer(source='assigned_object', read_only=True) + assigned_object_id = serializers.IntegerField(write_only=True) + assigned_object_type = serializers.CharField(write_only=True) + + class Meta: + model = ProviderCredentials + #fields = ['id','maintenance_window','assigned_object_type','assigned_object_id','assigned_object_type','virtual_machine'] + fields = '__all__' \ No newline at end of file diff --git a/netbox_sys_plugin/api/urls.py b/netbox_sys_plugin/api/urls.py index bdba566..6f3fb34 100644 --- a/netbox_sys_plugin/api/urls.py +++ b/netbox_sys_plugin/api/urls.py @@ -1,8 +1,9 @@ from rest_framework.routers import DefaultRouter -from .views import VirtualMachineMaintenanceViewSet +from .views import VirtualMachineMaintenanceViewSet, ProviderCredentialsViewSet router = DefaultRouter() router.register(r'MaintenanceWindow', VirtualMachineMaintenanceViewSet) +router.register(r'ProviderCredentials', ProviderCredentialsViewSet) app_name = "netbox_sys_plugin" diff --git a/netbox_sys_plugin/api/views.py b/netbox_sys_plugin/api/views.py index 473e143..b375333 100644 --- a/netbox_sys_plugin/api/views.py +++ b/netbox_sys_plugin/api/views.py @@ -1,8 +1,8 @@ from rest_framework import viewsets, status from rest_framework.decorators import action from rest_framework.response import Response -from .. models import VirtualMachineMaintenance -from . serializers import VirtualMachineMaintenanceSerializer +from .. models import VirtualMachineMaintenance, ProviderCredentials +from . serializers import VirtualMachineMaintenanceSerializer, ProviderCredentialsSerializer class VirtualMachineMaintenanceViewSet(viewsets.ModelViewSet): queryset = VirtualMachineMaintenance.objects.all() @@ -10,3 +10,7 @@ class VirtualMachineMaintenanceViewSet(viewsets.ModelViewSet): http_method_names = ["get", "post", "patch", "delete", "options"] +class ProviderCredentialsViewSet(viewsets.ModelViewSet): + queryset = ProviderCredentials.objects.all() + serializer_class = ProviderCredentialsSerializer + http_method_names = ["get", "post", "patch", "delete", "options"] \ No newline at end of file diff --git a/netbox_sys_plugin/forms.py b/netbox_sys_plugin/forms.py index d8dd189..0ac2861 100644 --- a/netbox_sys_plugin/forms.py +++ b/netbox_sys_plugin/forms.py @@ -1,6 +1,6 @@ """Forms definitions""" -from virtualization.models import VirtualMachine +from virtualization.models import VirtualMachine, Cluster from django.contrib.contenttypes.models import ContentType from django.utils.translation import gettext_lazy as _ from django.core.exceptions import ValidationError @@ -11,7 +11,7 @@ from netbox.forms import ( NetBoxModelFilterSetForm, ) from utilities.forms.fields import DynamicModelChoiceField -from .models import VirtualMachineMaintenance +from .models import VirtualMachineMaintenance, ProviderCredentials class VmMaitenanceForm(NetBoxModelForm): """ @@ -102,3 +102,59 @@ class VmMaintenanceFilterForm(NetBoxModelFilterSetForm): """MacAddress filter form definition class""" model = VirtualMachineMaintenance + + +class ProviderCredentialsForm(NetBoxModelForm): + """ + GUI form to add or edit a Provider Credentials. + """ + + cluster = DynamicModelChoiceField( + queryset=Cluster.objects.all(), required=False, label="Cluster" + ) + provider_url = forms.CharField( + max_length=500, min_length=1, required=False, label="Provider URL" + ) + provider_username = forms.CharField( + max_length=500, min_length=1, required=False, label="Provider Username" + ) + provider_password = forms.CharField( + max_length=500, min_length=1, required=False, label="Provider Password" + ) + + def __init__(self, *args, **kwargs): + # Initialize helper selectors + instance = kwargs.get("instance") + initial = kwargs.get("initial", {}).copy() + if instance: + if isinstance(instance.assigned_object, Cluster): + initial["cluster"] = instance.assigned_object + + kwargs["initial"] = initial + super().__init__(*args, **kwargs) + + class Meta: + """Meta class""" + model = ProviderCredentials + fields = ('provider_url', 'provider_username', 'provider_password', 'cluster') + + def clean(self): + """ + Validates form inputs before submitting: + """ + super().clean() + + if self.errors.get("mac_address"): + return + + def save(self, *args, **kwargs): + # Set assigned object + self.instance.assigned_object = ( + self.cleaned_data.get("cluster") + ) + return super().save(*args, **kwargs) + +class ProviderCredentialsFilterForm(NetBoxModelFilterSetForm): + """Provider Credentials filter form definition class""" + + model = ProviderCredentials \ No newline at end of file diff --git a/netbox_sys_plugin/models/provider.py b/netbox_sys_plugin/models/provider.py index 327afbc..2cfe425 100644 --- a/netbox_sys_plugin/models/provider.py +++ b/netbox_sys_plugin/models/provider.py @@ -52,7 +52,7 @@ class ProviderCredentials(NetBoxModel): def __str__(self): - return f"{self.provider}" + return f"{self.provider_url}" def get_absolute_url(self): """override""" diff --git a/netbox_sys_plugin/navigation.py b/netbox_sys_plugin/navigation.py index 6988410..2a39a83 100644 --- a/netbox_sys_plugin/navigation.py +++ b/netbox_sys_plugin/navigation.py @@ -14,7 +14,7 @@ vm_maintenance_buttons = [ cluster_provider_credentials_buttons = [ PluginMenuButton( - link="plugins:netbox_sys_plugin:virtualmachinemaintenance_add", + link="plugins:netbox_sys_plugin:providercredentials_add", title="Add", icon_class="mdi mdi-plus-thick", color=ButtonColorChoices.GREEN, diff --git a/netbox_sys_plugin/template_content.py b/netbox_sys_plugin/template_content.py index 7ff699e..d23d99b 100644 --- a/netbox_sys_plugin/template_content.py +++ b/netbox_sys_plugin/template_content.py @@ -11,6 +11,14 @@ class VmMaintenanceTable(PluginTemplateExtension): def left_page(self): return self.render('netbox_sys_plugin/vm_vmmaintenance_table.html', extra_context={'vmmaintenanceinfo': models.VirtualMachineMaintenance.objects.filter(VirtualMachine=self.context['object'])}) + +class ProviderCredentialsTable(PluginTemplateExtension): + """Provider Credentials object template""" + model = 'virtualization.cluster' -template_extensions = [VmMaintenanceTable] + def right_page(self): + return self.render('netbox_sys_plugin/cluster_providercredentials.html', extra_context={'providercredentialsinfo': models.ProviderCredentials.objects.filter(Cluster=self.context['object'])}) + + +template_extensions = [VmMaintenanceTable,ProviderCredentialsTable] diff --git a/netbox_sys_plugin/templates/netbox_sys_plugin/cluster_providercredentials.html b/netbox_sys_plugin/templates/netbox_sys_plugin/cluster_providercredentials.html new file mode 100644 index 0000000..28b10f1 --- /dev/null +++ b/netbox_sys_plugin/templates/netbox_sys_plugin/cluster_providercredentials.html @@ -0,0 +1,47 @@ +{% block content %} + <div class="row mb-3"> + <div class="col col-md-12"> + <div class="card"> + <h5 class="card-header">Provider Credentials</h5> + <div class="card-body"> + <table class="table table-responsive"> + <th scope="row">Provider URL</th> + <th scope="row">Provider Username</th> + <th scope="row">Provider Password</th> + {% for providercredentials in providercredentialsinfo %} + <tr> + <td> + {% if providercredentials.provider_url %} + <a href="{{ providercredentials.get_absolute_url }}">{{ providercredentials.provider_url }}</a> + {% else %} + {{ ''|placeholder }} + {% endif %} + </td> + <td> + {% if providercredentials.provider_username %} + {{ providercredentials.provider_username }} + {% else %} + {{ ''|placeholder }} + {% endif %} + </td> + <td> + {% if providercredentials.provider_password %} + {{ providercredentials.provider_password }} + {% else %} + {{ ''|placeholder }} + {% endif %} + </td> + </tr> + {% empty %} + <tr> + <td colspan="3">No maintenance window found.</td> + </tr> + {% endfor %} + </tr> + </table> + </div> + </div> + {% include 'inc/panels/custom_fields.html' %} + </div> + </div> +{% endblock content %} \ No newline at end of file diff --git a/netbox_sys_plugin/templates/netbox_sys_plugin/providercredentials.html b/netbox_sys_plugin/templates/netbox_sys_plugin/providercredentials.html new file mode 100644 index 0000000..72c879c --- /dev/null +++ b/netbox_sys_plugin/templates/netbox_sys_plugin/providercredentials.html @@ -0,0 +1,52 @@ +{% extends 'generic/object.html' %} + +{% block title%} +Provider Credentials for {{ object.assigned_object }} +{% endblock title%} + +{% block content %} +<div class="row mb-3"> + <div class="col col-md-6"> + <div class="card"> + <h5 class="card-header">Provider Credentials</h5> + <div class="card-body"> + <table class="table table-hover attr-table"> + <tr> + <th scope="row">Provider URL</th> + <td>{{ object.provider_url }}</td> + </tr> + <tr> + <th scope="row">Provider Username</th> + <td>{{ object.provider_username }}</td> + </tr> + <tr> + <th scope="row">Provider Password</th> + <td>{{ object.provider_password }}</td> + </tr> + </table> + </div> + </div> + {% include 'inc/panels/custom_fields.html' %} + {% include 'inc/panels/tags.html' %} + </div> + <div class="col col-md-6"> + <div class="card"> + <h5 class="card-header">Details</h5> + <div class="card-body"> + <table class="table table-hover attr-table"> + <tr> + <th scope="row">{{ object.assigned_object_type|cut:"virtualization | " }}</th> + <td> + {% if object.assigned_object %} + <a href="{{ object.assigned_object.get_absolute_url }}">{{ object.assigned_object }}</a> + {% else %} + {{ ''|placeholder }} + {% endif %} + </td> + </tr> + </table> + </div> + </div> + </div> +</div> +{% endblock content %} diff --git a/netbox_sys_plugin/urls.py b/netbox_sys_plugin/urls.py index 896246d..4d3e076 100644 --- a/netbox_sys_plugin/urls.py +++ b/netbox_sys_plugin/urls.py @@ -17,6 +17,17 @@ urlpatterns = ( path('vm-maintenance/<int:pk>/journal/', ObjectJournalView.as_view(), name='virtualmachinemaintenance_journal', kwargs={ 'model': models.VirtualMachineMaintenance }), - path('provider-credentials/', views.ProviderCredentialsView.as_view(), name='providercredentials_list'), + path('provider-credentials/', views.ProviderCredentialsListView.as_view(), name='providercredentials_list'), + path('provider-credentials/add/', views.ProviderCredentialsEditView.as_view(), name='providercredentials_add'), + path('provider-credentials/<int:pk>/', views.ProviderCredentialsView.as_view(), name='providercredentials'), + path('provider-credentials/<int:pk>/edit/', views.ProviderCredentialsEditView.as_view(), name='providercredentials_edit'), + path('provider-credentials/<int:pk>/delete/', views.ProviderCredentialsDeleteView.as_view(), name='providercredentials_delete'), + path('provider-credentials/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='providercredentials_changelog', kwargs={ + 'model': models.VirtualMachineMaintenance + }), + path('provider-credentials/<int:pk>/journal/', ObjectJournalView.as_view(), name='providercredentials_journal', kwargs={ + 'model': models.VirtualMachineMaintenance + }), + ) diff --git a/netbox_sys_plugin/views.py b/netbox_sys_plugin/views.py index 3b4baaa..24f7a51 100644 --- a/netbox_sys_plugin/views.py +++ b/netbox_sys_plugin/views.py @@ -30,10 +30,30 @@ class VmMaintenanceDeleteView(generic.ObjectDeleteView): queryset = models.VirtualMachineMaintenance.objects.all() -class ProviderCredentialsView(generic.ObjectListView): + +class ProviderCredentialsView(generic.ObjectView): + """ Provider Credentials view definition""" + + queryset = ( + models.ProviderCredentials.objects.all() + ) + +class ProviderCredentialsListView(generic.ObjectListView): """Cluster Provider Credentials list view definition""" queryset = models.ProviderCredentials.objects.all() table = tables.ProviderCredentialsTable #filterset = filtersets.VmMaintenanceFilterSet - #filterset_form = forms.VmMaintenanceFilterForm \ No newline at end of file + #filterset_form = forms.VmMaintenanceFilterForm + +class ProviderCredentialsDeleteView(generic.ObjectDeleteView): + """Vm maintenance delete view definition""" + + queryset = models.ProviderCredentials.objects.all() + +class ProviderCredentialsEditView(generic.ObjectEditView): + """ + Defines the edit view for the Vm maintenance django model. + """ + queryset = models.ProviderCredentials.objects.all() + form = forms.ProviderCredentialsForm \ No newline at end of file -- GitLab From 32dc7867b70d4741d952929b51a3ada3a9ccc7ce Mon Sep 17 00:00:00 2001 From: Frederico Sequeira <frederico.sequeira@ext.ec.europa.eu> Date: Fri, 15 Nov 2024 17:09:14 +0000 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=8E=A8=20Improve=20structure=20of=20c?= =?UTF-8?q?ode=20and=20add=20validations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- netbox_sys_plugin/forms/__init__.py | 4 + .../{forms.py => forms/maintenance.py} | 73 ++------------ netbox_sys_plugin/forms/provider.py | 98 +++++++++++++++++++ netbox_sys_plugin/models/maintenance.py | 2 +- netbox_sys_plugin/models/provider.py | 13 ++- netbox_sys_plugin/tables.py | 4 +- .../cluster_providercredentials.html | 8 -- .../providercredentials.html | 8 +- 8 files changed, 124 insertions(+), 86 deletions(-) create mode 100644 netbox_sys_plugin/forms/__init__.py rename netbox_sys_plugin/{forms.py => forms/maintenance.py} (58%) create mode 100644 netbox_sys_plugin/forms/provider.py diff --git a/netbox_sys_plugin/forms/__init__.py b/netbox_sys_plugin/forms/__init__.py new file mode 100644 index 0000000..0f3ba6e --- /dev/null +++ b/netbox_sys_plugin/forms/__init__.py @@ -0,0 +1,4 @@ +"""Forms definitions""" + +from .maintenance import * +from .provider import * \ No newline at end of file diff --git a/netbox_sys_plugin/forms.py b/netbox_sys_plugin/forms/maintenance.py similarity index 58% rename from netbox_sys_plugin/forms.py rename to netbox_sys_plugin/forms/maintenance.py index 0ac2861..46618c6 100644 --- a/netbox_sys_plugin/forms.py +++ b/netbox_sys_plugin/forms/maintenance.py @@ -1,6 +1,6 @@ """Forms definitions""" -from virtualization.models import VirtualMachine, Cluster +from virtualization.models import VirtualMachine from django.contrib.contenttypes.models import ContentType from django.utils.translation import gettext_lazy as _ from django.core.exceptions import ValidationError @@ -11,7 +11,7 @@ from netbox.forms import ( NetBoxModelFilterSetForm, ) from utilities.forms.fields import DynamicModelChoiceField -from .models import VirtualMachineMaintenance, ProviderCredentials +from ..models import VirtualMachineMaintenance class VmMaitenanceForm(NetBoxModelForm): """ @@ -41,19 +41,16 @@ class VmMaitenanceForm(NetBoxModelForm): current_vm_id = instance.assigned_object.id if instance.assigned_object else None else: current_vm_id = None - assigned_vms = VirtualMachineMaintenance.objects.filter( assigned_object_type=ContentType.objects.get_for_model(VirtualMachine) - #).values_list('assigned_object_id', flat=True) ).exclude(assigned_object_id=current_vm_id).values_list('assigned_object_id', flat=True) - self.fields['virtual_machine'].queryset = VirtualMachine.objects.exclude(id__in=assigned_vms) class Meta: """Meta class""" model = VirtualMachineMaintenance - fields = ( 'virtual_machine','maintenance_window') + fields = ( 'virtual_machine','maintenance_window','tags') def clean_virtual_machine(self): @@ -65,9 +62,7 @@ class VmMaitenanceForm(NetBoxModelForm): assigned_object_type=virtual_machine_ct, assigned_object_id=virtual_machine.id ).exclude(pk=self.instance.pk).exists(): - raise ValidationError( - "The virtual Machine already has a maintenance windows associates" - ) + raise ValidationError() return virtual_machine @@ -86,7 +81,7 @@ class VmMaitenanceForm(NetBoxModelForm): #Check if VM is assigned corretly if (not virtual_machine): raise ValidationError( - {"__all__": "Virtual Machine already with maintenance window"}, + {"__all__": "A Virtual Machine needs to be associated with the maintenance window"}, ) @@ -101,60 +96,4 @@ class VmMaitenanceForm(NetBoxModelForm): class VmMaintenanceFilterForm(NetBoxModelFilterSetForm): """MacAddress filter form definition class""" - model = VirtualMachineMaintenance - - -class ProviderCredentialsForm(NetBoxModelForm): - """ - GUI form to add or edit a Provider Credentials. - """ - - cluster = DynamicModelChoiceField( - queryset=Cluster.objects.all(), required=False, label="Cluster" - ) - provider_url = forms.CharField( - max_length=500, min_length=1, required=False, label="Provider URL" - ) - provider_username = forms.CharField( - max_length=500, min_length=1, required=False, label="Provider Username" - ) - provider_password = forms.CharField( - max_length=500, min_length=1, required=False, label="Provider Password" - ) - - def __init__(self, *args, **kwargs): - # Initialize helper selectors - instance = kwargs.get("instance") - initial = kwargs.get("initial", {}).copy() - if instance: - if isinstance(instance.assigned_object, Cluster): - initial["cluster"] = instance.assigned_object - - kwargs["initial"] = initial - super().__init__(*args, **kwargs) - - class Meta: - """Meta class""" - model = ProviderCredentials - fields = ('provider_url', 'provider_username', 'provider_password', 'cluster') - - def clean(self): - """ - Validates form inputs before submitting: - """ - super().clean() - - if self.errors.get("mac_address"): - return - - def save(self, *args, **kwargs): - # Set assigned object - self.instance.assigned_object = ( - self.cleaned_data.get("cluster") - ) - return super().save(*args, **kwargs) - -class ProviderCredentialsFilterForm(NetBoxModelFilterSetForm): - """Provider Credentials filter form definition class""" - - model = ProviderCredentials \ No newline at end of file + model = VirtualMachineMaintenance \ No newline at end of file diff --git a/netbox_sys_plugin/forms/provider.py b/netbox_sys_plugin/forms/provider.py new file mode 100644 index 0000000..0463217 --- /dev/null +++ b/netbox_sys_plugin/forms/provider.py @@ -0,0 +1,98 @@ +"""Forms definitions""" + +from virtualization.models import Cluster +from django.contrib.contenttypes.models import ContentType +from django.utils.translation import gettext_lazy as _ +from django.core.exceptions import ValidationError +from django import forms +from netbox.forms import ( + NetBoxModelForm, + NetBoxModelFilterSetForm, +) +from utilities.forms.fields import DynamicModelChoiceField +from ..models import ProviderCredentials + +class ProviderCredentialsForm(NetBoxModelForm): + """ + GUI form to add or edit a Provider Credentials. + """ + + cluster = DynamicModelChoiceField( + queryset=Cluster.objects.all(), required=True, label="Cluster" + ) + provider_url = forms.CharField( + max_length=200, min_length=1, required=True, label="URL" + ) + provider_username = forms.CharField( + max_length=50, min_length=1, required=True, label="Username" + ) + provider_password = forms.CharField( + max_length=20, min_length=1, required=True, label="Password" + ) + + def __init__(self, *args, **kwargs): + # Initialize helper selectors + instance = kwargs.get("instance") + initial = kwargs.get("initial", {}).copy() + if instance: + if isinstance(instance.assigned_object, Cluster): + initial["cluster"] = instance.assigned_object + kwargs["initial"] = initial + super().__init__(*args, **kwargs) + + if instance: + current_cluster_id = instance.assigned_object.id if instance.assigned_object else None + else: + current_cluster_id = None + + assigned_clusters = ProviderCredentials.objects.filter( + assigned_object_type=ContentType.objects.get_for_model(Cluster) + ).exclude(assigned_object_id=current_cluster_id).values_list('assigned_object_id', flat=True) + self.fields['cluster'].queryset = Cluster.objects.exclude(id__in=assigned_clusters) + + class Meta: + """Meta class""" + model = ProviderCredentials + fields = ('cluster','provider_url', 'provider_username', 'provider_password','tags') + + def clean_cluster(self): + + cluster = self.cleaned_data.get("cluster") + + cluster_ct = ContentType.objects.get_for_model(Cluster) + + if ProviderCredentials.objects.filter( + assigned_object_type=cluster_ct, + assigned_object_id=cluster.id + ).exclude(pk=self.instance.pk).exists(): + raise ValidationError() + return cluster + + def clean(self): + """ + Validates form inputs before submitting: + """ + super().clean() + + if self.errors.get(f"provider_url"): + return + + cluster = self.cleaned_data.get("cluster") + + #Check if cluster is assigned corretly + if (not cluster): + raise ValidationError( + {"__all__": "A Virtual Machine needs to be associated with the maintenance window"}, + ) + + def save(self, *args, **kwargs): + # Set assigned object + self.instance.assigned_object = ( + self.cleaned_data.get("cluster") + ) + return super().save(*args, **kwargs) + +class ProviderCredentialsFilterForm(NetBoxModelFilterSetForm): + """Provider Credentials filter form definition class""" + + model = ProviderCredentials \ No newline at end of file diff --git a/netbox_sys_plugin/models/maintenance.py b/netbox_sys_plugin/models/maintenance.py index e3c1bf8..53e1a81 100644 --- a/netbox_sys_plugin/models/maintenance.py +++ b/netbox_sys_plugin/models/maintenance.py @@ -51,7 +51,7 @@ class VirtualMachineMaintenance(NetBoxModel): def __str__(self): - return f"{self.maintenance_window}" + return f"For Virtual machine ID {self.assigned_object_id}" def get_absolute_url(self): """override""" diff --git a/netbox_sys_plugin/models/provider.py b/netbox_sys_plugin/models/provider.py index 2cfe425..5d52a32 100644 --- a/netbox_sys_plugin/models/provider.py +++ b/netbox_sys_plugin/models/provider.py @@ -4,6 +4,9 @@ from django.core.validators import ( RegexValidator, ) from django.urls import reverse +from django.core.validators import ( + URLValidator, +) # pylint: disable=import-error from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation from django.contrib.contenttypes.models import ContentType from django.db import models @@ -20,7 +23,9 @@ class ProviderCredentials(NetBoxModel): provider_url = models.CharField( default=None, blank=True, null=True, - max_length=200) + max_length=200, + validators=[URLValidator(schemes=["http", "https"])], + ) provider_username = models.CharField( default=None, blank=True, null=True, @@ -47,12 +52,12 @@ class ProviderCredentials(NetBoxModel): """Meta class""" unique_together = ["assigned_object_id"] ordering = ["assigned_object_id"] - verbose_name = "Provider Information" - verbose_name_plural = "Provider Informations" + verbose_name = "Provider Credential" + verbose_name_plural = "Provider Credentials" def __str__(self): - return f"{self.provider_url}" + return f"for Cluster ID {self.assigned_object_id}" def get_absolute_url(self): """override""" diff --git a/netbox_sys_plugin/tables.py b/netbox_sys_plugin/tables.py index 118a627..8c9eda6 100644 --- a/netbox_sys_plugin/tables.py +++ b/netbox_sys_plugin/tables.py @@ -51,8 +51,8 @@ class ProviderCredentialsTable(NetBoxTable): ) provider_url = tables.Column(linkify=True) - provider_username = tables.Column(linkify=True) - provider_password = tables.Column(linkify=True) + provider_username = tables.Column(linkify=False) + provider_password = tables.Column(linkify=False) class Meta(NetBoxTable.Meta): """Meta class""" diff --git a/netbox_sys_plugin/templates/netbox_sys_plugin/cluster_providercredentials.html b/netbox_sys_plugin/templates/netbox_sys_plugin/cluster_providercredentials.html index 28b10f1..ef300cc 100644 --- a/netbox_sys_plugin/templates/netbox_sys_plugin/cluster_providercredentials.html +++ b/netbox_sys_plugin/templates/netbox_sys_plugin/cluster_providercredentials.html @@ -7,7 +7,6 @@ <table class="table table-responsive"> <th scope="row">Provider URL</th> <th scope="row">Provider Username</th> - <th scope="row">Provider Password</th> {% for providercredentials in providercredentialsinfo %} <tr> <td> @@ -24,13 +23,6 @@ {{ ''|placeholder }} {% endif %} </td> - <td> - {% if providercredentials.provider_password %} - {{ providercredentials.provider_password }} - {% else %} - {{ ''|placeholder }} - {% endif %} - </td> </tr> {% empty %} <tr> diff --git a/netbox_sys_plugin/templates/netbox_sys_plugin/providercredentials.html b/netbox_sys_plugin/templates/netbox_sys_plugin/providercredentials.html index 72c879c..b86b1ec 100644 --- a/netbox_sys_plugin/templates/netbox_sys_plugin/providercredentials.html +++ b/netbox_sys_plugin/templates/netbox_sys_plugin/providercredentials.html @@ -12,15 +12,15 @@ Provider Credentials for {{ object.assigned_object }} <div class="card-body"> <table class="table table-hover attr-table"> <tr> - <th scope="row">Provider URL</th> + <th scope="row">URL</th> <td>{{ object.provider_url }}</td> </tr> <tr> - <th scope="row">Provider Username</th> + <th scope="row">Username</th> <td>{{ object.provider_username }}</td> </tr> <tr> - <th scope="row">Provider Password</th> + <th scope="row">Password</th> <td>{{ object.provider_password }}</td> </tr> </table> @@ -31,7 +31,7 @@ Provider Credentials for {{ object.assigned_object }} </div> <div class="col col-md-6"> <div class="card"> - <h5 class="card-header">Details</h5> + <h5 class="card-header">Assigned Object</h5> <div class="card-body"> <table class="table table-hover attr-table"> <tr> -- GitLab From ef5c56ad1f0428baeb74e32fd7ea70404b3eba5c Mon Sep 17 00:00:00 2001 From: Frederico Sequeira <frederico.sequeira@ext.ec.europa.eu> Date: Mon, 18 Nov 2024 15:21:46 +0000 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=8E=A8=20Add=20validations=20and=20va?= =?UTF-8?q?ult=20path=20url?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/model/netbox_sys_provider_credentials.md | 2 +- netbox_sys_plugin/filtersets.py | 31 +++++++++++++++++-- netbox_sys_plugin/forms/provider.py | 6 ++-- ...maintenance_maintenance_window_and_more.py | 12 +++---- netbox_sys_plugin/models/provider.py | 10 +++--- netbox_sys_plugin/tables.py | 26 +++++++++++----- .../cluster_providercredentials.html | 12 +++++-- .../providercredentials.html | 4 +-- netbox_sys_plugin/views.py | 4 +-- 9 files changed, 76 insertions(+), 31 deletions(-) diff --git a/docs/model/netbox_sys_provider_credentials.md b/docs/model/netbox_sys_provider_credentials.md index 11f23c6..0876ed0 100644 --- a/docs/model/netbox_sys_provider_credentials.md +++ b/docs/model/netbox_sys_provider_credentials.md @@ -9,4 +9,4 @@ | assigned_object_id | Big (8 byte) integer | cluster type unique ID | | provider_url | String | Virtual Machine type name | | provider_name | String | Virtual Machine type description | -| provider_password | String | Virtual Machine type description | \ No newline at end of file +| provider_password_vault_url | String | Virtual Machine type description | \ No newline at end of file diff --git a/netbox_sys_plugin/filtersets.py b/netbox_sys_plugin/filtersets.py index 5748c46..75a77e0 100644 --- a/netbox_sys_plugin/filtersets.py +++ b/netbox_sys_plugin/filtersets.py @@ -2,8 +2,9 @@ import django_filters from netbox.filtersets import NetBoxModelFilterSet -from virtualization.models import VirtualMachine -from .models import VirtualMachineMaintenance +from virtualization.models import VirtualMachine, Cluster +from django.db.models import Q +from .models import VirtualMachineMaintenance, ProviderCredentials class VmMaintenanceFilterSet(NetBoxModelFilterSet): @@ -24,4 +25,28 @@ class VmMaintenanceFilterSet(NetBoxModelFilterSet): # pylint: disable=W0613 def search(self, queryset, name, value): """override""" - queryset.filter(virtual_machine__icontains=value) + if not value.strip(): + return queryset + return queryset.filter(Q(maintenance_window__icontains=value)) + +class ProviderCredentialsFilterSet(NetBoxModelFilterSet): + """ProviderCredentials filterset definition class""" + + cluster = django_filters.ModelMultipleChoiceFilter( + field_name="Cluster__name", + queryset=Cluster.objects.all(), + to_field_name="name", + label="Virtual Machine (name)", + ) + + class Meta: + """Meta class""" + model = ProviderCredentials + fields = ('provider_url','provider_username','provider_password_vault_url','cluster') + + # pylint: disable=W0613 + def search(self, queryset, name, value): + """override""" + if not value.strip(): + return queryset + return queryset.filter(Q(provider_username__icontains=value)|Q(provider_url__icontains=value)|Q(provider_password_vault_url__icontains=value)) \ No newline at end of file diff --git a/netbox_sys_plugin/forms/provider.py b/netbox_sys_plugin/forms/provider.py index 0463217..1909d38 100644 --- a/netbox_sys_plugin/forms/provider.py +++ b/netbox_sys_plugin/forms/provider.py @@ -26,8 +26,8 @@ class ProviderCredentialsForm(NetBoxModelForm): provider_username = forms.CharField( max_length=50, min_length=1, required=True, label="Username" ) - provider_password = forms.CharField( - max_length=20, min_length=1, required=True, label="Password" + provider_password_vault_url = forms.CharField( + max_length=200, min_length=1, required=True, label="Password Vault URL" ) def __init__(self, *args, **kwargs): @@ -53,7 +53,7 @@ class ProviderCredentialsForm(NetBoxModelForm): class Meta: """Meta class""" model = ProviderCredentials - fields = ('cluster','provider_url', 'provider_username', 'provider_password','tags') + fields = ('cluster','provider_url', 'provider_username', 'provider_password_vault_url','tags') def clean_cluster(self): diff --git a/netbox_sys_plugin/migrations/0002_alter_virtualmachinemaintenance_maintenance_window_and_more.py b/netbox_sys_plugin/migrations/0002_alter_virtualmachinemaintenance_maintenance_window_and_more.py index 9c0f99e..64b5bde 100644 --- a/netbox_sys_plugin/migrations/0002_alter_virtualmachinemaintenance_maintenance_window_and_more.py +++ b/netbox_sys_plugin/migrations/0002_alter_virtualmachinemaintenance_maintenance_window_and_more.py @@ -1,4 +1,4 @@ -# Generated by Django 4.2.16 on 2024-11-15 09:53 +# Generated by Django 4.2.16 on 2024-11-18 15:20 import django.core.validators from django.db import migrations, models @@ -28,16 +28,16 @@ class Migration(migrations.Migration): ('created', models.DateTimeField(auto_now_add=True, null=True)), ('last_updated', models.DateTimeField(auto_now=True, null=True)), ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder)), - ('provider_url', models.CharField(blank=True, default=None, max_length=200, null=True)), - ('provider_username', models.CharField(blank=True, default=None, max_length=200, null=True)), - ('provider_password', models.CharField(blank=True, default=None, max_length=200, null=True)), + ('provider_url', models.CharField(blank=True, default=None, max_length=100, null=True, validators=[django.core.validators.URLValidator(schemes=['http', 'https'])])), + ('provider_username', models.CharField(blank=True, default=None, max_length=50, null=True)), + ('provider_password_vault_url', models.CharField(blank=True, default=None, max_length=200, null=True, validators=[django.core.validators.URLValidator(schemes=['http', 'https'])])), ('assigned_object_id', models.PositiveBigIntegerField(blank=True, null=True)), ('assigned_object_type', models.ForeignKey(blank=True, limit_choices_to=models.Q(models.Q(('app_label', 'virtualization'), ('model', 'Cluster'))), null=True, on_delete=django.db.models.deletion.PROTECT, to='contenttypes.contenttype')), ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), ], options={ - 'verbose_name': 'Provider Information', - 'verbose_name_plural': 'Provider Informations', + 'verbose_name': 'Provider Credential', + 'verbose_name_plural': 'Provider Credentials', 'ordering': ['assigned_object_id'], 'unique_together': {('assigned_object_id',)}, }, diff --git a/netbox_sys_plugin/models/provider.py b/netbox_sys_plugin/models/provider.py index 5d52a32..eb1cc24 100644 --- a/netbox_sys_plugin/models/provider.py +++ b/netbox_sys_plugin/models/provider.py @@ -23,17 +23,19 @@ class ProviderCredentials(NetBoxModel): provider_url = models.CharField( default=None, blank=True, null=True, - max_length=200, + max_length=100, validators=[URLValidator(schemes=["http", "https"])], ) provider_username = models.CharField( default=None, blank=True, null=True, - max_length=200) + max_length=50) - provider_password = models.CharField( + provider_password_vault_url = models.CharField( default=None, blank=True, null=True, - max_length=200) + max_length=200, + validators=[URLValidator(schemes=["http", "https"])], + ) assigned_object_type = models.ForeignKey( to=ContentType, diff --git a/netbox_sys_plugin/tables.py b/netbox_sys_plugin/tables.py index 8c9eda6..bea34c6 100644 --- a/netbox_sys_plugin/tables.py +++ b/netbox_sys_plugin/tables.py @@ -45,14 +45,24 @@ class ProviderCredentialsTable(NetBoxTable): ) assigned_object = tables.Column( - linkify=True, - orderable=False, - verbose_name="Cluster", + linkify=True, + orderable=False, + verbose_name="Cluster", + ) + + provider_url = tables.Column( + linkify=True, + verbose_name="URL", ) + provider_username = tables.Column( + linkify=False, + verbose_name="Username", - provider_url = tables.Column(linkify=True) - provider_username = tables.Column(linkify=False) - provider_password = tables.Column(linkify=False) + ) + provider_password_vault_url = tables.Column( + linkify=False, + verbose_name="Password Vault URL", + ) class Meta(NetBoxTable.Meta): """Meta class""" @@ -62,10 +72,10 @@ class ProviderCredentialsTable(NetBoxTable): "id", "provider_url", "provider_username", - "provider_password", + "provider_password_vault_url", "assigned_object", "created", "last_updated", ) - default_columns = ('id','provider_url','provider_username','provider_password','assigned_object') + default_columns = ('id','provider_url','provider_username','provider_password_vault_url','assigned_object') diff --git a/netbox_sys_plugin/templates/netbox_sys_plugin/cluster_providercredentials.html b/netbox_sys_plugin/templates/netbox_sys_plugin/cluster_providercredentials.html index ef300cc..82082e0 100644 --- a/netbox_sys_plugin/templates/netbox_sys_plugin/cluster_providercredentials.html +++ b/netbox_sys_plugin/templates/netbox_sys_plugin/cluster_providercredentials.html @@ -5,8 +5,9 @@ <h5 class="card-header">Provider Credentials</h5> <div class="card-body"> <table class="table table-responsive"> - <th scope="row">Provider URL</th> - <th scope="row">Provider Username</th> + <th scope="row">URL</th> + <th scope="row">Username</th> + <th scope="row">Passworl Vault URL</th> {% for providercredentials in providercredentialsinfo %} <tr> <td> @@ -23,6 +24,13 @@ {{ ''|placeholder }} {% endif %} </td> + <td> + {% if providercredentials.provider_password_vault_url %} + {{ providercredentials.provider_password_vault_url }} + {% else %} + {{ ''|placeholder }} + {% endif %} + </td> </tr> {% empty %} <tr> diff --git a/netbox_sys_plugin/templates/netbox_sys_plugin/providercredentials.html b/netbox_sys_plugin/templates/netbox_sys_plugin/providercredentials.html index b86b1ec..d18f35b 100644 --- a/netbox_sys_plugin/templates/netbox_sys_plugin/providercredentials.html +++ b/netbox_sys_plugin/templates/netbox_sys_plugin/providercredentials.html @@ -20,8 +20,8 @@ Provider Credentials for {{ object.assigned_object }} <td>{{ object.provider_username }}</td> </tr> <tr> - <th scope="row">Password</th> - <td>{{ object.provider_password }}</td> + <th scope="row">Password vault URL</th> + <td>{{ object.provider_password_vault_url }}</td> </tr> </table> </div> diff --git a/netbox_sys_plugin/views.py b/netbox_sys_plugin/views.py index 24f7a51..f80387d 100644 --- a/netbox_sys_plugin/views.py +++ b/netbox_sys_plugin/views.py @@ -43,8 +43,8 @@ class ProviderCredentialsListView(generic.ObjectListView): queryset = models.ProviderCredentials.objects.all() table = tables.ProviderCredentialsTable - #filterset = filtersets.VmMaintenanceFilterSet - #filterset_form = forms.VmMaintenanceFilterForm + filterset = filtersets.ProviderCredentialsFilterSet + filterset_form = forms.ProviderCredentialsFilterForm class ProviderCredentialsDeleteView(generic.ObjectDeleteView): """Vm maintenance delete view definition""" -- GitLab