diff --git a/tests/inventory/test_compliance_checks_views.py b/tests/inventory/test_compliance_checks_views.py index 69d3fe8896..e8d355a468 100644 --- a/tests/inventory/test_compliance_checks_views.py +++ b/tests/inventory/test_compliance_checks_views.py @@ -515,7 +515,7 @@ def test_machine_no_compliance_checks(self): response = self.client.get(self.machine.get_absolute_url()) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, "inventory/machine_detail.html") - self.assertContains(response, "Compliance checks (0)") + self.assertContains(response, "

Compliance checks

") def test_machine_no_tags_no_compliance_checks_in_scope(self): self._login( @@ -528,7 +528,7 @@ def test_machine_no_tags_no_compliance_checks_in_scope(self): response = self.client.get(self.machine.get_absolute_url()) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, "inventory/machine_detail.html") - self.assertContains(response, "Compliance checks (0)") + self.assertContains(response, "

Compliance checks

") def test_machine_with_tag_no_compliance_checks_in_scope(self): self._login( @@ -543,7 +543,7 @@ def test_machine_with_tag_no_compliance_checks_in_scope(self): response = self.client.get(self.machine.get_absolute_url()) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, "inventory/machine_detail.html") - self.assertContains(response, "Compliance checks (0)") + self.assertContains(response, "

Compliance checks

") def test_machine_source_mismatch_no_compliance_checks_in_scope(self): self._login( @@ -555,7 +555,7 @@ def test_machine_source_mismatch_no_compliance_checks_in_scope(self): response = self.client.get(self.machine.get_absolute_url()) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, "inventory/machine_detail.html") - self.assertContains(response, "Compliance checks (0)") + self.assertContains(response, "

Compliance checks

") def test_machine_source_match_platform_missmatch_no_compliance_checks_in_scope(self): self._login( @@ -567,7 +567,7 @@ def test_machine_source_match_platform_missmatch_no_compliance_checks_in_scope(s response = self.client.get(self.machine.get_absolute_url()) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, "inventory/machine_detail.html") - self.assertContains(response, "Compliance checks (0)") + self.assertContains(response, "

Compliance checks

") def test_machine_source_match_one_compliance_checks_in_scope(self): self._login( @@ -579,7 +579,8 @@ def test_machine_source_match_one_compliance_checks_in_scope(self): response = self.client.get(self.machine.get_absolute_url()) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, "inventory/machine_detail.html") - self.assertContains(response, "Compliance check (1)") + self.assertContains(response, "

Compliance check

") + self.assertContains(response, "0/1 OK, 1 Pending") self.assertContains(response, cc.compliance_check.name) cc_redirect_link = reverse("compliance_checks:redirect", args=(cc.compliance_check.pk,)) compliance_check_statuses = response.context["compliance_check_statuses"] @@ -600,7 +601,8 @@ def test_machine_no_tags_compliance_checks_one_in_scope_one_out_of_scope_pending response = self.client.get(self.machine.get_absolute_url()) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, "inventory/machine_detail.html") - self.assertContains(response, "Compliance check (1)") + self.assertContains(response, "

Compliance check

") + self.assertContains(response, "0/1 OK, 1 Pending") self.assertContains(response, cc_without_tag.compliance_check.name) self.assertNotContains(response, cc_with_tags.compliance_check.name) cc_redirect_link = reverse("compliance_checks:redirect", args=(cc_without_tag.compliance_check.pk,)) @@ -623,7 +625,8 @@ def test_machine_no_tags_compliance_checks_one_in_scope_one_out_of_scope_pending response = self.client.get(self.machine.get_absolute_url()) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, "inventory/machine_detail.html") - self.assertContains(response, "Compliance check (1)") + self.assertContains(response, "

Compliance check

") + self.assertContains(response, "0/1 OK, 1 Pending") self.assertContains(response, cc_without_tag.compliance_check.name) self.assertNotContains(response, cc_with_tags.compliance_check.name) cc_redirect_link = reverse("compliance_checks:redirect", args=(cc_without_tag.compliance_check.pk,)) @@ -646,7 +649,7 @@ def test_machine_no_tags_compliance_checks_one_in_scope_one_out_of_scope_no_sect response = self.client.get(self.machine.get_absolute_url()) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, "inventory/machine_detail.html") - self.assertNotContains(response, "Compliance check (1)") + self.assertNotContains(response, "

Compliance check

") self.assertNotContains(response, cc_without_tag.compliance_check.name) cc_redirect_link = reverse("compliance_checks:redirect", args=(cc_without_tag.compliance_check.pk,)) self.assertNotContains(response, cc_redirect_link) @@ -673,7 +676,8 @@ def test_machine_tags_once_compliance_check_in_scope_ok_with_link(self): response = self.client.get(self.machine.get_absolute_url()) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, "inventory/machine_detail.html") - self.assertContains(response, "Compliance check (1)") + self.assertContains(response, "

Compliance check

") + self.assertContains(response, "1/1 OK") self.assertContains(response, cc.compliance_check.name) cc_redirect_link = reverse("compliance_checks:redirect", args=(cc.compliance_check.pk,)) self.assertContains(response, cc_redirect_link) @@ -714,7 +718,8 @@ def test_machine_tags_once_compliance_check_in_scope_two_different_statuses_ok_w response = self.client.get(self.machine.get_absolute_url()) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, "inventory/machine_detail.html") - self.assertContains(response, "Compliance check (1)") + self.assertContains(response, "

Compliance check

") + self.assertContains(response, "1/1 OK") self.assertContains(response, cc.compliance_check.name) cc_redirect_link = reverse("compliance_checks:redirect", args=(cc.compliance_check.pk,)) self.assertContains(response, cc_redirect_link) diff --git a/zentral/contrib/inventory/templates/inventory/machine_detail.html b/zentral/contrib/inventory/templates/inventory/machine_detail.html index 9716439f95..bdc95789e3 100644 --- a/zentral/contrib/inventory/templates/inventory/machine_detail.html +++ b/zentral/contrib/inventory/templates/inventory/machine_detail.html @@ -463,7 +463,12 @@

Extra facts

{% if perms.compliance_checks.view_machinestatus %} -

Compliance check{{ compliance_check_statuses|length|pluralize }} ({{ compliance_check_statuses|length }})

+

Compliance check{{ compliance_check_total|pluralize }}

+ {% if compliance_check_total %} +

+ {{ compliance_check_ok }}/{{ compliance_check_total }} OK{% if compliance_check_failed %}, {{ compliance_check_failed }} Failed{% endif %}{% if compliance_check_pending %}, {{ compliance_check_pending }} Pending{% endif %}{% if compliance_check_unknown %}, {{ compliance_check_unknown }} Unknown{% endif %} +

+ {% endif %} {% if compliance_check_statuses %} diff --git a/zentral/contrib/inventory/views.py b/zentral/contrib/inventory/views.py index 32a2f4d2ff..a6eb045617 100644 --- a/zentral/contrib/inventory/views.py +++ b/zentral/contrib/inventory/views.py @@ -16,6 +16,7 @@ from zentral.conf import settings from zentral.core.compliance_checks import compliance_check_class_from_model from zentral.core.compliance_checks.forms import ComplianceCheckForm +from zentral.core.compliance_checks.models import Status from zentral.core.incidents.models import MachineIncident from zentral.core.stores.conf import frontend_store, stores from zentral.core.stores.views import EventsView, FetchEventsView, EventsStoreRedirectView @@ -535,6 +536,7 @@ def ms_sort_key(t): # compliance checks compliance_check_statuses = [] + cc_total = cc_ok = cc_pending = cc_unknown = cc_failed = 0 if self.request.user.has_perm("compliance_checks.view_machinestatus"): for cc_model, cc_pk, cc_name, status, status_time in machine.compliance_check_statuses(): cc_url = None @@ -542,7 +544,21 @@ def ms_sort_key(t): if self.request.user.has_perms(cc_cls.required_view_permissions): cc_url = reverse("compliance_checks:redirect", args=(cc_pk,)) compliance_check_statuses.append((cc_url, cc_name, status, status_time)) + cc_total += 1 + if status == Status.OK: + cc_ok += 1 + elif status == Status.PENDING: + cc_pending += 1 + elif status == Status.UNKNOWN: + cc_unknown += 1 + elif status == Status.FAILED: + cc_failed += 1 context["compliance_check_statuses"] = compliance_check_statuses + context["compliance_check_total"] = cc_total + context["compliance_check_ok"] = cc_ok + context["compliance_check_failed"] = cc_failed + context["compliance_check_pending"] = cc_pending + context["compliance_check_unknown"] = cc_unknown # event links context['show_events_link'] = frontend_store.machine_events