Skip to content

Commit

Permalink
feat: server archivation
Browse files Browse the repository at this point in the history
  • Loading branch information
tymees committed Oct 31, 2024
1 parent 8cd4c73 commit 5b3614e
Show file tree
Hide file tree
Showing 10 changed files with 202 additions and 333 deletions.
3 changes: 3 additions & 0 deletions humitifier-server/src/hosts/alerts.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ def puppet_agent_disabled(scan_data: dict, host: Host):
def generate_alerts(scan_data: dict, host: Host, delete_old_alerts: bool = True):
alerts = []

if host.archived:
return alerts

if not scan_data:
return host.alerts.get_or_create(
level=AlertLevel.CRITICAL,
Expand Down
18 changes: 18 additions & 0 deletions humitifier-server/src/hosts/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,20 @@ def filter(self, qs, value):
return qs


class IncludeArchivedFilter(ChoiceFilter):
def __init__(self, *args, **kwargs):
kwargs['choices'] = [
(True, "Include archived servers"),
]
kwargs['field_name'] = 'archived'
super().__init__(*args, **kwargs)

def filter(self, qs, value):
if not value:
return qs.filter(archived=False)
return qs


class FiltersForm(Form):
template_name = 'base/page_parts/filters_form_template.html'

Expand Down Expand Up @@ -140,6 +154,10 @@ class Meta:
]
)

archived = IncludeArchivedFilter(
empty_label="Exclude archived servers",
)


class AlertFilters(django_filters.FilterSet):
class Meta:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ def handle(self, *args, **options):
hosts = Host.objects.all()

for host in hosts:
generate_alerts(host.last_scan_cache, host)
host.regenerate_alerts()
19 changes: 19 additions & 0 deletions humitifier-server/src/hosts/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ class Meta:

protected = models.BooleanField(default=False)

archived = models.BooleanField(default=False)

archival_date = models.DateTimeField(null=True)

##
## Generated fields
## These fields are derived from the last scan cache, and are generated
Expand Down Expand Up @@ -101,6 +105,9 @@ def add_scan(
cache_scan: bool = True,
generate_alerts: bool = True
):
if self.archived:
return None

scan = Scan(host=self, data=scan_data)
scan.save()

Expand All @@ -116,6 +123,11 @@ def add_scan(

return scan

def regenerate_alerts(self):
from hosts import alerts

alerts.generate_alerts(self.last_scan_cache, self)

##
## Properties
##
Expand Down Expand Up @@ -151,6 +163,13 @@ def get_os_display(self):
return mark_safe("<span class='italic'>Unknown</span>")
return strip_quotes(self.os)

@property
def archived_string(self):
if self.archived:
date = self.archival_date.strftime("%Y-%m-%d %H:%M")
return f"This server was archived on {date}"
return ""

def __str__(self):
return self.fqdn

Expand Down
29 changes: 29 additions & 0 deletions humitifier-server/src/hosts/templates/hosts/archive.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{% extends 'base/base_page_template.html' %}

{% block content %}
<div class="h-full--header w-full bg px-7 py-5 ">
{% if object.archived %}
<h1 class="text-3xl font-bold">Un-archive host</h1>
<p class="mt-6">
Are you sure you want to un-archive host '<strong>{{ object.fqdn }}</strong>'?
</p>
{% else %}
<h1 class="text-3xl font-bold">Archive host</h1>
<p class="mt-6">
Are you sure you want to archive host '<strong>{{ object.fqdn }}</strong>'?
</p>
{% endif %}
<form method="post">
{% csrf_token %}
{{ form }}
<div class="flex gap-2 mt-6">
<a href="{% url 'hosts:detail' object.fqdn %}" class="btn btn-outline">
Cancel
</a>
<button type="submit" class="btn light:btn-primary dark:btn-outline">
Confirm
</button>
</div>
</form>
</div>
{% endblock %}
13 changes: 13 additions & 0 deletions humitifier-server/src/hosts/templates/hosts/detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@
<a class="btn btn-sm light:btn-primary dark:btn-outline hidden md:block" href="{% url 'hosts:download_raw' host.fqdn %}?{% param_replace %}">
Download raw data
</a>
<a class="btn btn-sm light:btn-primary dark:btn-outline hidden md:block" href="{% url 'hosts:archive' host.fqdn %}">
{% if host.archived %}
Un-archive
{% else %}
Archive
{% endif %}
</a>
</div>
</div>

Expand All @@ -46,6 +53,12 @@
{% endwith %}
{% endif %}

{% if host.archived %}
{% with alert=host.archived_string %}
{% include 'hosts/detail_parts/alerts/info.html' %}
{% endwith %}
{% endif %}

<div class="p-3 columns-1 lg:columns-2 xl:columns-2 2xl:columns-3 ultrawide:columns-4 gap-3">
<div class="break-inside-avoid mb-3">
{% include 'hosts/detail_parts/facts/host_meta.html' %}
Expand Down
5 changes: 4 additions & 1 deletion humitifier-server/src/hosts/urls.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from django.urls import path

from .views import DataSourcesView, ExportView, HostDetailView, HostsListView, \
from .views import ArchiveHostView, DataSourcesView, ExportView, HostDetailView, \
HostsListView, \
HostsRawDownloadView, ScanProfilesView, TasksView

app_name = 'hosts'
Expand All @@ -10,6 +11,8 @@
path("host/<fqdn>/", HostDetailView.as_view(), name="detail"),
path("host/<fqdn>/raw/", HostsRawDownloadView.as_view(),
name="download_raw"),
path("host/<fqdn>/archive/", ArchiveHostView.as_view(),
name="archive"),
path("export/", ExportView.as_view(), name="export"),
path("tasks/", TasksView.as_view(), name="tasks"),
path("scan-profiles/", ScanProfilesView.as_view(), name="scan_profiles"),
Expand Down
50 changes: 49 additions & 1 deletion humitifier-server/src/hosts/views.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import json

from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.http import HttpResponse
from django.forms import Form
from django.http import HttpResponse, HttpResponseRedirect
from django.urls import reverse
from django.utils import timezone
from django.views import View
from django.views.generic import TemplateView
from django.views.generic.detail import BaseDetailView, \
SingleObjectTemplateResponseMixin
from django.views.generic.edit import FormMixin

from main.views import FilteredListView

Expand Down Expand Up @@ -106,6 +112,48 @@ def get(self, request, fqdn):
return response


class ArchiveHostView(
SingleObjectTemplateResponseMixin,
FormMixin,
BaseDetailView
):
model = Host
form_class = Form
template_name = 'hosts/archive.html'
slug_field = 'fqdn'
slug_url_kwarg = 'fqdn'

def get_queryset(self):
return Host.objects.get_for_user(self.request.user)

def get_success_url(self):
return reverse('hosts:detail', kwargs={'fqdn': self.object.fqdn})

def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)

def form_valid(self, form):
success_url = self.get_success_url()

if self.object.archived:
self.object.archived = False
self.object.archival_date = None
self.object.save()
self.object.regenerate_alerts()
else:
self.object.archived = True
self.object.archival_date = timezone.now()
self.object.save()
self.object.alerts.all().delete()

return HttpResponseRedirect(success_url)


class ExportView(TemplateView):
template_name = 'main/not_implemented.html'

Expand Down
2 changes: 1 addition & 1 deletion humitifier-server/src/main/context_processors.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def layout_context(request):
"""
user = request.user

hosts = Host.objects.get_for_user(user)
hosts = Host.objects.get_for_user(user).exclude(archived=True)
all_alerts = Alert.objects.get_for_user(user)

tag_line = "HumIT CMDB"
Expand Down
Loading

0 comments on commit 5b3614e

Please sign in to comment.