Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE] Implement sender whitelist filters #132

Merged
merged 3 commits into from
Mar 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
6 changes: 6 additions & 0 deletions promgen/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,5 +160,11 @@ class Meta:
exclude = ['content_type', 'object_id', 'owner']


class NotifierUpdate(forms.ModelForm):
class Meta:
model = models.Sender
exclude = ['value']


class HostForm(forms.Form):
hosts = forms.CharField(widget=forms.Textarea)
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')},
),
]
32 changes: 32 additions & 0 deletions promgen/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,38 @@ def test(self):
from promgen import tasks
tasks.send_alert(self.sender, self.value, data)

def filtered(self, alert):
"""
Check filters for a specific sender

If no filters are defined, then we let the message through
If filters are defined, then we check to see if at least one filter matches
If no filters match, then we assume it's filtered out
"""
logger.debug("Checking labels %s", alert["commonLabels"])
# If we have no specific whitelist, then we let everything through
if self.filter_set.count() == 0:
return False

# If we have filters defined, then we need to check to see if our
# filters match
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 False
# If none of our filters match, then we blacklist this sender
return True


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
9 changes: 9 additions & 0 deletions promgen/static/js/promgen.vue.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,15 @@ var app = new Vue({
this_.globalAlerts = alerts.data;
});

},
setTargetList: function(event, target) {
// get the list name
let dst = event.target.list.id;
// and our selected value
let src = event.target.value;
// and set the target list
let tgt = document.getElementById(target);
tgt.setAttribute('list', dst + '.' + src);
}
},
computed: {
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
24 changes: 24 additions & 0 deletions promgen/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,30 @@
<script src="{% static "/js/promgen.js" %}"></script>
<script src="{% static "/js/promgen.vue.js" %}"></script>
{% block javascript %}{% endblock %}


<datalist style="display:none" id="common.labels">
<select>
<option>severity</option>
</select>
</datalist>

<datalist style="display:none" id="common.annotations">
<select>
<option>summary</option>
<option>grafana</option>
<option>runbook</option>
</select>
</datalist>

<datalist style="display:none" id="common.labels.severity">
<select>
<option>critical</option>
<option>major</option>
<option>minor</option>
<option>debug</option>
</select>
</datalist>
</body>

</html>
23 changes: 5 additions & 18 deletions promgen/templates/promgen/notifier_block.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,12 @@
<tr>
<th>Notifier</th>
<th>Value</th>
<th>Filters</th>
{% if show_edit %}
<th>Actions</th>
{% endif %}
</tr>
{% for notifier in object.notifiers.all %}
<tr>
<td title="Added by: {{notifier.owner}}">{{ notifier.sender }}</td>
<td>{{ notifier.show_value }}</td>
{% if show_edit %}
<td>
<form method="post" action="{% url 'notifier-test' notifier.id %}" style="display: inline">
{% csrf_token %}
<button class="btn btn-danger btn-xs">{% trans "Test" %}</button>
</form>
</td>
<td>
<form method="post" action="{% url 'notifier-delete' notifier.id %}" onsubmit="return confirm('{% trans "Delete notificiation?" %}')" style="display: inline">
{% csrf_token %}
<button class="btn btn-danger btn-xs">{% trans "Delete" %}</button>
</form>
</td>
{% endif %}
</tr>
{% include 'promgen/sender_row.html' %}
{% endfor %}
</table>
23 changes: 23 additions & 0 deletions promgen/templates/promgen/sender_form.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{% extends "base.html" %}
{% load i18n %}
{% load promgen %}
{% block content %}


<div class="page-header">
<h1>{{object|klass}}: {{object.name}}</h1>
</div>

{% breadcrumb object 'Update Notifier' %}

<table class="table table-bordered table-condensed{% if collapse %} collapse" id="{{ collapse }}{% endif %}">
<tr>
<th>Notifier</th>
<th>Value</th>
<th>Filters</th>
<th>Actions</th>
</tr>
{% include 'promgen/sender_row.html' with notifier=object show_edit=1 %}
</table>

{% endblock %}
43 changes: 43 additions & 0 deletions promgen/templates/promgen/sender_row.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{% load i18n %}
<tr>
<td title="Added by: {{notifier.owner}}">{{ notifier.sender }}</td>
<td>{{ notifier.show_value }}</td>
<td>
{% for f in notifier.filter_set.all %}
<form method="post" action="{% url 'notifier-edit' notifier.id %}" onsubmit="return confirm('Delete this filter?')" style="display: inline">
{% csrf_token %}
<input name="next" type="hidden" value="{{ request.get_full_path }}" />
<input name="filter.pk" value="{{f.id}}" type="hidden" />
<button class="label label-primary" style="display: inline-block;">
{{f.name}}:{{f.value}}
<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
</button>
</form>
{% endfor %}

<button class="btn btn-primary btn-xs" data-toggle="collapse" data-target="#notifierLabel{{notifier.id}}">+</button>
<div class="collapse" id="notifierLabel{{notifier.id}}">
<form method="post" action="{% url 'notifier-edit' notifier.id %}" style="display: inline">
{% csrf_token %}
<input name="next" type="hidden" value="{{ request.get_full_path }}" />
<input name="filter.name" placeholder="name" required list="common.labels" @change="setTargetList($event, 'newLabel{{notifier.id}}')">
<input name="filter.value" placeholder="value" required id="newLabel{{notifier.id}}">
<button class="btn btn-primary btn-xs">Submit</button>
</form>
</div>
</td>
{% if show_edit %}
<td>
<a href="{% url 'notifier-edit' notifier.id %}" class="btn btn-warning btn-xs">{% trans "Edit" %}</a>
<form method="post" action="{% url 'notifier-test' notifier.id %}" style="display: inline">
{% csrf_token %}
<input name="next" type="hidden" value="{{ request.get_full_path }}" />
<button class="btn btn-info btn-xs">{% trans "Test" %}</button>
</form>
<form method="post" action="{% url 'notifier-delete' notifier.id %}" onsubmit="return confirm('{% trans "Delete notificiation?" %}')" style="display: inline">
{% csrf_token %}
<button class="btn btn-danger btn-xs">{% trans "Delete" %}</button>
</form>
</td>
{% endif %}
</tr>
66 changes: 42 additions & 24 deletions promgen/templates/promgen/status.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,46 @@ <h1>{{user.username}} ({{user.email}})</h1>
<div class="panel panel-primary">
<div class="panel-heading">Subscriptions</div>
<table class="table">
{% for notifier in subscriptions %}
<tr>
<th>&nbsp;</th>
<th>Filters</th>
<th>Actions</th>
</tr>
{% for notifier in subscriptions %}
<tr>
<td><a href="{{notifier.content_object.get_absolute_url}}">{{notifier.content_object}}</td>
<td>
{% for f in notifier.filter_set.all %}
<span class="label label-primary" style="display: inline-block;">
{{f.name}}:{{f.value}}
</span>
{% endfor %}
</td>
<td>
<a href="{% url 'notifier-edit' notifier.id %}" class="btn btn-warning btn-xs">{% trans "Edit" %}</a>
<form method="post" action="{% url 'notifier-test' notifier.id %}" style="display: inline">
{% csrf_token %}
<input name="next" type="hidden" value="{{ request.get_full_path }}" />
<button class="btn btn-info btn-xs">{% trans "Test" %}</button>
</form>
<form method="post" action="{% url 'notifier-delete' notifier.id %}" onsubmit="return confirm('{% trans "Delete notificiation?" %}')" style="display: inline">
{% csrf_token %}
<input name="next" type="hidden" value="{{ request.get_full_path }}" />
<button class="btn btn-danger btn-xs">{% trans "Delete" %}</button>
</form>
</td>
</tr>
{% empty %}
{% empty %}
<tr>
<td colspan="2">No Subscriptions <a href="{% url 'shard-list' %}" >See Services List</a></td>
<td colspan="3">No Subscriptions <a href="{% url 'shard-list' %}">See Services List</a></td>
</tr>
{% endfor %}
{% endfor %}
</table>
</div>

<div class="panel panel-primary">
<div class="panel-heading">Notifications</div>
{% include "promgen/notifier_block.html" with object=notifiers show_edit=1 %}
{% include "promgen/notifier_block.html" with object=notifiers show_edit=1 %}
<div class="panel-body">
<div class="row">
<div class="col-md-3">
Expand All @@ -50,18 +68,18 @@ <h1>{{user.username}} ({{user.email}})</h1>
{% for k, v in view.model.driver_set|dictsort:0 %}
{% if k != "promgen.notification.user" %}
<div role="tabpanel" class="tab-pane panel panel-default" id="{{ k|slugify }}">
<form action="" method="post">{% csrf_token %}
<input type="hidden" name="sender" value="{{k}}" />
<div class="panel-body">
<pre class="help-block">{{ v.help|urlize }}</pre>
</div>
<table class="table">
{{ v.form.as_table }}
</table>
<div class="panel-footer">
<button class="btn btn-primary">Register Notifier</button>
</div>
</form>
<form action="" method="post">{% csrf_token %}
<input type="hidden" name="sender" value="{{k}}" />
<div class="panel-body">
<pre class="help-block">{{ v.help|urlize }}</pre>
</div>
<table class="table">
{{ v.form.as_table }}
</table>
<div class="panel-footer">
<button class="btn btn-primary">Register Notifier</button>
</div>
</form>
</div>
{% endif %}
{% endfor %}
Expand All @@ -78,23 +96,23 @@ <h1>{{user.username}} ({{user.email}})</h1>
<td>Discovery Plugins</td>
<td>
<ul>
{% for plugin in discovery_plugins|dictsort:"name" %}
<li>{{ plugin.name }} - {{ plugin.module_name }}</li>
{% endfor %}
{% for plugin in discovery_plugins|dictsort:"name" %}
<li>{{ plugin.name }} - {{ plugin.module_name }}</li>
{% endfor %}
</td>
</tr>
<tr>
<td>Notifier Plugins</td>
<td>
<ul>
{% for notifier in notifier_plugins|dictsort:"name" %}
<li>{{ notifier.name }} - {{ notifier.module_name }}</li>
{% endfor %}
{% for notifier in notifier_plugins|dictsort:"name" %}
<li>{{ notifier.name }} - {{ notifier.module_name }}</li>
{% endfor %}
</td>
</tr>
</table>
</div>
{% endif %}
{% endif %}


{% endblock %}
4 changes: 2 additions & 2 deletions promgen/templatetags/promgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,9 @@ def rule(obj):
yield obj.get_absolute_url(), obj.name

def sender(obj):
if isinstance(obj, models.Service):
if obj.content_type.model == "service":
yield from service(obj.content_object)
if isinstance(obj, models.Project):
if obj.content_type.model == "project":
yield from project(obj.content_object)

def generator():
Expand Down
Loading