adding tests to agent alert actions and a bunch of fixes

This commit is contained in:
sadnub
2021-02-21 14:03:01 -05:00
parent 6925510f44
commit d4ce23eced
5 changed files with 257 additions and 62 deletions

View File

@@ -6,7 +6,7 @@ from itertools import cycle
from django.conf import settings
from django.utils import timezone as djangotime
from model_bakery.recipe import Recipe, foreign_key
from model_bakery.recipe import Recipe, foreign_key, seq
def generate_agent_id(hostname):
@@ -30,8 +30,7 @@ agent = Recipe(
hostname="DESKTOP-TEST123",
version="1.3.0",
monitoring_type=cycle(["workstation", "server"]),
salt_id=generate_agent_id("DESKTOP-TEST123"),
agent_id="71AHC-AA813-HH1BC-AAHH5-00013|DESKTOP-TEST123",
agent_id=seq("asdkj3h4234-1234hg3h4g34-234jjh34|DESKTOP-TEST123"),
)
server_agent = agent.extend(

View File

@@ -724,34 +724,32 @@ class Agent(BaseAuditModel):
# called when agent is back online
if checkin:
if Alert.objects.filter(agent=self, resolved=False).exists():
# resolve alert if exists
alert = Alert.objects.get(agent=self, resolved=False)
alert.resolve()
# check if a resolved notification should be emailed
if (
not alert.resolved_email_sent
and alert_template
alert_template
and alert_template.agent_email_on_resolved
or self.overdue_email_alert
and not alert.resolved_email_sent
):
agent_recovery_email_task.delay(pk=alert.pk)
# check if a resolved notification should be texted
if (
not alert.resolved_sms_sent
and alert_template
alert_template
and alert_template.agent_text_on_resolved
or self.overdue_text_alert
and not alert.resolved_sms_sent
):
agent_recovery_sms_task.delay(pk=alert.pk)
# check if any scripts should be run
if (
not alert.resolved_action_run
and alert_template
and alert_template.resolved_action
and (alert_template
and alert_template.resolved_action)
):
r = self.run_script(
scriptpk=alert_template.resolved_action.pk,
@@ -809,37 +807,35 @@ class Agent(BaseAuditModel):
# create dashboard alert if enabled
if (
alert_template
and alert_template.agent_always_alert
or self.overdue_dashboard_alert
self.overdue_dashboard_alert
or (alert_template
and alert_template.agent_always_alert)
):
alert.hidden = False
alert.save()
# send email alert if enabled
if (
not alert.email_sent
and alert_template
and alert_template.agent_always_email
or self.overdue_email_alert
self.overdue_email_alert
or (alert_template
and alert_template.agent_always_email)
):
agent_outage_email_task.delay(
pk=alert.pk,
alert_interval=alert_template.check_periodic_alert_days
alert_interval=alert_template.agent_periodic_alert_days
if alert_template
else None,
)
# send text message if enabled
if (
not alert.sms_sent
and alert_template
and alert_template.agent_always_text
or self.overdue_text_alert
self.overdue_text_alert
or (alert_template
and alert_template.agent_always_text)
):
agent_outage_sms_task.delay(
pk=alert.pk,
alert_interval=alert_template.check_periodic_alert_days
alert_interval=alert_template.agent_periodic_alert_days
if alert_template
else None,
)

View File

@@ -1,7 +1,8 @@
from datetime import datetime, timedelta
from unittest.mock import patch
from django.utils import timezone as djangotime
from model_bakery import baker, seq
from django.conf import settings
from core.models import CoreSettings
from tacticalrmm.test import TacticalTestCase
@@ -346,7 +347,15 @@ class TestAlertsViews(TacticalTestCase):
class TestAlertTasks(TacticalTestCase):
def setUp(self):
self.authenticate()
self.setup_coresettings()
core = CoreSettings.objects.first()
core.twilio_account_sid = "test"
core.twilio_auth_token = "test"
core.text_recipients = ["+12314567890"]
core.email_recipients = ["test@example.com"]
core.twilio_number = "+12314567890"
core.save()
def test_unsnooze_alert_task(self):
from alerts.tasks import unsnooze_alerts
@@ -484,27 +493,222 @@ class TestAlertTasks(TacticalTestCase):
self.assertEquals(workstation.get_alert_template().pk, alert_templates[1].pk)
self.assertEquals(server.get_alert_template().pk, alert_templates[2].pk)
def test_handle_agent_offline_alerts(self):
from agents.tasks import agent_outages_task
@patch("agents.tasks.sleep")
@patch("smtplib.SMTP")
@patch("core.models.TwClient")
@patch("agents.tasks.agent_outage_sms_task.delay")
@patch("agents.tasks.agent_outage_email_task.delay")
@patch("agents.tasks.agent_recovery_email_task.delay")
@patch("agents.tasks.agent_recovery_sms_task.delay")
def test_handle_agent_offline_alerts(
self, recovery_sms, recovery_email, outage_email, outage_sms, TwClient, SMTP, sleep
):
from agents.tasks import (
agent_outages_task,
agent_outage_sms_task,
agent_outage_email_task,
agent_recovery_sms_task,
agent_recovery_email_task,
)
from alerts.models import Alert
agent = baker.make_recipe("agents.overdue_agent")
# setup sms and email mock objects
TwClient.messages.create.return_value.sid = "SomeRandomText"
SMTP.return_value = True
agent_dashboard_alert = baker.make_recipe("agents.overdue_agent")
# call outages task and no alert should be created
agent_outages_task()
self.assertFalse(Alert.objects.filter(agent=agent).exists())
self.assertEquals(Alert.objects.count(), 0)
# set overdue_dashboard_alert and alert should be created
agent.overdue_dashboard_alert = True
agent.save()
agent_dashboard_alert.overdue_dashboard_alert = True
agent_dashboard_alert.save()
# create other agents with various alert settings
alert_template_always_alert = baker.make(
"alerts.AlertTemplate", is_active=True, agent_always_alert=True
)
alert_template_always_text = baker.make(
"alerts.AlertTemplate", is_active=True, agent_always_text=True, agent_periodic_alert_days=5
)
alert_template_always_email = baker.make(
"alerts.AlertTemplate", is_active=True, agent_always_email=True, agent_periodic_alert_days=5
)
alert_template_blank = baker.make("alerts.AlertTemplate", is_active=True)
agent_template_email = baker.make_recipe("agents.overdue_agent")
agent_template_dashboard = baker.make_recipe("agents.overdue_agent")
agent_template_text = baker.make_recipe("agents.overdue_agent")
agent_template_blank = baker.make_recipe("agents.overdue_agent")
# assign alert templates to agent's clients
agent_template_email.client.alert_template = alert_template_always_email
agent_template_email.client.save()
agent_template_dashboard.client.alert_template = alert_template_always_alert
agent_template_dashboard.client.save()
agent_template_text.client.alert_template = alert_template_always_text
agent_template_text.client.save()
agent_template_blank.client.alert_template = alert_template_blank
agent_template_blank.client.save()
agent_text_alert = baker.make_recipe(
"agents.overdue_agent", overdue_text_alert=True
)
agent_email_alert = baker.make_recipe(
"agents.overdue_agent", overdue_email_alert=True
)
agent_outages_task()
# should have created 6 alerts
self.assertEquals(Alert.objects.count(), 6)
# other specific agents should have created alerts
self.assertEquals(Alert.objects.filter(agent=agent_dashboard_alert).count(), 1)
self.assertEquals(Alert.objects.filter(agent=agent_text_alert).count(), 1)
self.assertEquals(Alert.objects.filter(agent=agent_email_alert).count(), 1)
self.assertEquals(Alert.objects.filter(agent=agent_template_email).count(), 1)
self.assertEquals(
Alert.objects.filter(agent=agent_template_dashboard).count(), 1
)
self.assertEquals(Alert.objects.filter(agent=agent_template_text).count(), 1)
self.assertEquals(Alert.objects.filter(agent=agent_template_blank).count(), 0)
# check if email and text tasks were called
self.assertEquals(outage_email.call_count, 2)
self.assertEquals(outage_sms.call_count, 2)
outage_sms.assert_any_call(
pk=Alert.objects.get(agent=agent_text_alert).pk, alert_interval=None
)
outage_sms.assert_any_call(
pk=Alert.objects.get(agent=agent_template_text).pk, alert_interval=5
)
outage_email.assert_any_call(
pk=Alert.objects.get(agent=agent_email_alert).pk, alert_interval=None
)
outage_email.assert_any_call(
pk=Alert.objects.get(agent=agent_template_email).pk, alert_interval=5
)
# call the email/sms outage tasks synchronously
agent_outage_sms_task(
pk=Alert.objects.get(agent=agent_text_alert).pk, alert_interval=None
)
agent_outage_email_task(
pk=Alert.objects.get(agent=agent_email_alert).pk, alert_interval=None
)
agent_outage_sms_task(
pk=Alert.objects.get(agent=agent_template_text).pk, alert_interval=5
)
agent_outage_email_task(
pk=Alert.objects.get(agent=agent_template_email).pk, alert_interval=5
)
# check if email/text sent was set
self.assertTrue(Alert.objects.get(agent=agent_text_alert).sms_sent)
self.assertFalse(Alert.objects.get(agent=agent_text_alert).email_sent)
self.assertTrue(Alert.objects.get(agent=agent_email_alert).email_sent)
self.assertFalse(Alert.objects.get(agent=agent_email_alert).sms_sent)
self.assertTrue(Alert.objects.get(agent=agent_template_text).sms_sent)
self.assertTrue(Alert.objects.get(agent=agent_template_email).email_sent)
self.assertFalse(Alert.objects.get(agent=agent_dashboard_alert).email_sent)
self.assertFalse(Alert.objects.get(agent=agent_dashboard_alert).sms_sent)
SMTP.reset_mock()
TwClient.reset_mock()
# calling agent outage task again shouldn't create duplicate alerts and won't send alerts
agent_outages_task()
self.assertEquals(Alert.objects.count(), 6)
SMTP.assert_not_called()
TwClient.assert_not_called()
# test periodic notification
# change email/text sent to sometime in the past
alert_text = Alert.objects.get(agent=agent_template_text)
alert_text.sms_sent = djangotime.now() - djangotime.timedelta(days=20)
alert_text.save()
alert_email = Alert.objects.get(agent=agent_template_email)
alert_email.email_sent = djangotime.now() - djangotime.timedelta(days=20)
alert_email.save()
agent_outages_task()
self.assertTrue(Alert.objects.filter(agent=agent).exists())
print(outage_sms.call_count)
print(outage_email.call_count)
outage_sms.assert_any_call(
pk=Alert.objects.get(agent=agent_template_text).pk, alert_interval=5
)
outage_email.assert_any_call(
pk=Alert.objects.get(agent=agent_template_email).pk, alert_interval=5
)
agent_outage_sms_task(
pk=Alert.objects.get(agent=agent_template_text).pk, alert_interval=5
)
agent_outage_email_task(
pk=Alert.objects.get(agent=agent_template_email).pk, alert_interval=5
)
self.assertEquals(SMTP.call_count, 1)
self.assertEquals(TwClient.call_count, 1)
# test resolved alerts
# alter the alert template to email and test on resolved
alert_template_always_email.agent_email_on_resolved = True
alert_template_always_email.save()
alert_template_always_text.agent_text_on_resolved = True
alert_template_always_text.save()
# have the two agents checkin
url = "/api/v3/checkin/"
agent_template_text.version = settings.LATEST_AGENT_VER
agent_template_text.save()
agent_template_email.version = settings.LATEST_AGENT_VER
agent_template_email.save()
data = {
"agent_id": agent_template_text.agent_id,
"version": settings.LATEST_AGENT_VER
}
resp = self.client.patch(url, data, format="json")
self.assertEqual(resp.status_code, 200)
data = {
"agent_id": agent_template_email.agent_id,
"version": settings.LATEST_AGENT_VER
}
resp = self.client.patch(url, data, format="json")
self.assertEqual(resp.status_code, 200)
recovery_sms.assert_called_with(
pk=Alert.objects.get(agent=agent_template_text).pk
)
recovery_email.assert_any_call(
pk=Alert.objects.get(agent=agent_template_email).pk
)
agent_recovery_sms_task(pk=Alert.objects.get(agent=agent_template_text).pk)
agent_recovery_email_task(pk=Alert.objects.get(agent=agent_template_email).pk)
self.assertTrue(Alert.objects.get(agent=agent_template_text).resolved_sms_sent)
self.assertTrue(Alert.objects.get(agent=agent_template_email).resolved_email_sent)
def test_handle_check_alerts(self):
pass
def test_handle_task_alerts(self):
pass
def test_override_email_settings(self):
pass

View File

@@ -249,27 +249,25 @@ class AutomatedTask(BaseAuditModel):
# check if resolved email should be send
if (
not alert.resolved_email_sent
and self.email_alert
or alert_template
and alert_template.task_email_on_resolved
(alert_template
and alert_template.task_email_on_resolved)
and not alert.resolved_email_sent
):
handle_resolved_task_email_alert.delay(pk=alert.pk)
# check if resolved text should be sent
if (
not alert.resolved_sms_sent
and self.text_alert
or alert_template
and alert_template.task_text_on_resolved
(alert_template
and alert_template.task_text_on_resolved)
and not alert.resolved_sms_sent
):
handle_resolved_task_sms_alert.delay(pk=alert.pk)
# check if resolved script should be run
if (
alert_template
and alert_template.resolved_action
and not alert.resolved_action_run
not alert.resolved_action_run
and (alert_template
and alert_template.resolved_action)
):
r = self.agent.run_script(
@@ -328,38 +326,37 @@ class AutomatedTask(BaseAuditModel):
# create alert in dashboard if enabled
if (
self.dashboard_alert
or alert_template
and alert_template.task_always_alert
or (alert_template
and self.alert_severity in alert_template.task_dashboard_alert_severity
and alert_template.task_always_alert)
):
alert.hidden = False
alert.save()
# send email if enabled
if (
not alert.email_sent
and self.email_alert
or alert_template
self.email_alert
or (alert_template
and self.alert_severity in alert_template.task_email_alert_severity
and alert_template.check_always_email
and alert_template.task_always_email)
):
handle_task_email_alert.delay(
pk=alert.pk,
alert_template=alert_template.check_periodic_alert_days
alert_template=alert_template.task_periodic_alert_days
if alert_template
else None,
)
# send text if enabled
if (
not alert.sms_sent
and self.text_alert
or alert_template
self.text_alert
or (alert_template
and self.alert_severity in alert_template.task_text_alert_severity
and alert_template.check_always_text
and alert_template.task_always_text)
):
handle_task_sms_alert.delay(
pk=alert.pk,
alert_template=alert_template.check_periodic_alert_days
alert_template=alert_template.task_periodic_alert_days
if alert_template
else None,
)

View File

@@ -360,9 +360,9 @@ class Check(BaseAuditModel):
# create alert in dashboard if enabled
if (
self.dashboard_alert
or alert_template
or (alert_template
and self.alert_severity in alert_template.check_dashboard_alert_severity
and alert_template.check_always_alert
and alert_template.check_always_alert)
):
alert.hidden = False
alert.save()
@@ -384,11 +384,10 @@ class Check(BaseAuditModel):
# send text if enabled
if (
not alert.sms_sent
and self.text_alert
or alert_template
self.text_alert
or (alert_template
and self.alert_severity in alert_template.check_text_alert_severity
and alert_template.check_always_text
and alert_template.check_always_text)
):
handle_check_sms_alert_task.delay(
pk=alert.pk,