Skip to content

Commit

Permalink
Stubs
Browse files Browse the repository at this point in the history
Initial server implementation

Admin panel updates for testing

Fix filter model unique fields
  • Loading branch information
kfdm committed Mar 6, 2019
1 parent 6ac7808 commit 92601ab
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 29 deletions.
4 changes: 4 additions & 0 deletions promgen/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
class PrometheusInline(admin.TabularInline):
model = models.Prometheus

class FilterInline(admin.TabularInline):
model = models.Filter


@admin.register(models.Host)
class HostAdmin(admin.ModelAdmin):
Expand Down Expand Up @@ -53,6 +56,7 @@ class SenderAdmin(admin.ModelAdmin):
form = SenderForm
list_filter = ('sender', 'content_type')
list_select_related = ('content_type',)
inlines = [FilterInline]


@admin.register(models.Farm)
Expand Down
34 changes: 34 additions & 0 deletions promgen/migrations/0007_message_filter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Generated by Django 2.1.2 on 2019-03-06 06:20

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('promgen', '0006_exporter_options'),
]

operations = [
migrations.CreateModel(
name='Filter',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=128)),
('value', models.CharField(max_length=128)),
],
options={
'ordering': ('sender', 'name', 'value'),
},
),
migrations.AddField(
model_name='filter',
name='sender',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='promgen.Sender'),
),
migrations.AlterUniqueTogether(
name='filter',
unique_together={('sender', 'name', 'value')},
),
]
18 changes: 18 additions & 0 deletions promgen/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,24 @@ def test(self):
from promgen import tasks
tasks.send_alert(self.sender, self.value, data)

def filtered(self, alert):
logger.debug('Checking labels %s', alert['commonLabels'])
for f in self.filter_set.all():
logger.debug("Checking filter %s %s", f.name, f.value)
if alert['commonLabels'].get(f.name) == f.value:
return True
return False


class Filter(models.Model):
sender = models.ForeignKey("Sender", on_delete=models.CASCADE)
name = models.CharField(max_length=128)
value = models.CharField(max_length=128)

class Meta:
ordering = ("sender", "name", "value")
unique_together = (("sender", "name", "value"),)


class Shard(models.Model):
name = models.CharField(max_length=128, unique=True)
Expand Down
3 changes: 3 additions & 0 deletions promgen/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ def process_alert(alert_pk):
for label, obj in routable.items():
logger.debug('Processing %s %s', label, obj)
for sender in models.Sender.objects.filter(obj=obj):
if sender.filtered(data):
logger.debug("Filtered out sender %s", sender)
continue
if hasattr(sender.driver, 'splay'):
for splay in sender.driver.splay(sender.value):
senders[splay.sender].add(splay.value)
Expand Down
87 changes: 58 additions & 29 deletions promgen/tests/test_webhook.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,52 +11,81 @@
from promgen.tests import PromgenTest


TEST_SETTINGS = PromgenTest.data_yaml('examples', 'promgen.yml')
TEST_ALERT = PromgenTest.data('examples', 'alertmanager.json')
TEST_SETTINGS = PromgenTest.data_yaml("examples", "promgen.yml")
TEST_ALERT = PromgenTest.data("examples", "alertmanager.json")


class WebhookTest(PromgenTest):
@mock.patch('django.dispatch.dispatcher.Signal.send')
@mock.patch("django.dispatch.dispatcher.Signal.send")
def setUp(self, mock_signal):
self.shard = models.Shard.objects.create(name='test.shard')
self.service = models.Service.objects.create(name='test.service', shard=self.shard)
self.project = models.Project.objects.create(name='test.project', service=self.service)
self.shard = models.Shard.objects.create(name="test.shard")
self.service = models.Service.objects.create(
name="test.service", shard=self.shard
)
self.project = models.Project.objects.create(
name="test.project", service=self.service
)

self.sender = models.Sender.objects.create(
self.senderA = models.Sender.objects.create(
obj=self.project,
sender=NotificationWebhook.__module__,
value='http://project.example.com',
value="http://project.example.com",
)

self.sender = models.Sender.objects.create(
self.senderB = models.Sender.objects.create(
obj=self.service,
sender=NotificationWebhook.__module__,
value='http://service.example.com',
value="http://service.example.com",
)

@override_settings(PROMGEN=TEST_SETTINGS)
@override_settings(CELERY_TASK_ALWAYS_EAGER=True)
@mock.patch('promgen.util.post')
@override_settings(CELERY_TASK_EAGER_PROPAGATES=True)
@mock.patch("promgen.util.post")
def test_webhook(self, mock_post):
self.client.post(reverse('alert'),
data=TEST_ALERT,
content_type='application/json'
response = self.client.post(
reverse("alert"), data=TEST_ALERT, content_type="application/json"
)

self.assertEqual(models.Alert.objects.count(), 1, 'Alert should be queued')
self.assertEqual(response.status_code, 202)
self.assertEqual(models.Alert.objects.count(), 1, "Alert should be queued")
self.assertEqual(mock_post.call_count, 2, "Two alerts should be sent")

# Our sample is the same as the original, with some annotations added
_SAMPLE = PromgenTest.data_json('examples', 'alertmanager.json')
_SAMPLE['commonAnnotations']['service'] = 'http://example.com' + self.service.get_absolute_url()
_SAMPLE['commonAnnotations']['project'] = 'http://example.com' + self.project.get_absolute_url()

mock_post.assert_has_calls([
mock.call(
'http://project.example.com',
json=_SAMPLE,
),
mock.call(
'http://service.example.com',
json=_SAMPLE,
)
], any_order=True)
_SAMPLE = PromgenTest.data_json("examples", "alertmanager.json")
_SAMPLE["commonAnnotations"]["service"] = (
"http://example.com" + self.service.get_absolute_url()
)
_SAMPLE["commonAnnotations"]["project"] = (
"http://example.com" + self.project.get_absolute_url()
)

mock_post.assert_has_calls(
[
mock.call("http://project.example.com", json=_SAMPLE),
mock.call("http://service.example.com", json=_SAMPLE),
],
any_order=True,
)

@override_settings(PROMGEN=TEST_SETTINGS)
@override_settings(CELERY_TASK_ALWAYS_EAGER=True)
@override_settings(CELERY_TASK_EAGER_PROPAGATES=True)
@mock.patch("promgen.util.post")
def test_filter(self, mock_post):
# Our first sender will only allow critical messages
models.Filter.objects.create(sender=self.senderA, name="severity", value="critical")

# Our second sender allows critical and major
models.Filter.objects.create(sender=self.senderB, name="severity", value="critical")
models.Filter.objects.create(sender=self.senderB, name="severity", value="major")

self.assertEqual(models.Filter.objects.count(), 3, "Should be three filters")

response = self.client.post(
reverse("alert"), data=TEST_ALERT, content_type="application/json"
)
self.assertEqual(response.status_code, 202)

self.assertEqual(models.Alert.objects.count(), 1, "Alert should be queued")
self.assertEqual(mock_post.call_count, 1, "One notification should be skipped")

0 comments on commit 92601ab

Please sign in to comment.