Skip to content

Commit

Permalink
Add notifications when new nodes are enrolled
Browse files Browse the repository at this point in the history
  • Loading branch information
mwielgoszewski committed Aug 15, 2017
1 parent 3de5d86 commit ebcc848
Show file tree
Hide file tree
Showing 12 changed files with 106 additions and 10 deletions.
4 changes: 3 additions & 1 deletion doorman/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
DistributedQueryTask, DistributedQueryResult,
StatusLog,
)
from doorman.tasks import analyze_result
from doorman.tasks import analyze_result, notify_of_node_enrollment
from doorman.utils import process_result


Expand Down Expand Up @@ -222,6 +222,8 @@ def enroll():
request.remote_addr, node
)

notify_of_node_enrollment.delay(node.to_dict())

return jsonify(node_key=node.node_key, node_invalid=False)


Expand Down
4 changes: 4 additions & 0 deletions doorman/extensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,10 @@ def handle_log_entry(self, entry, node):
for alerter, match in to_trigger:
self.alerters[alerter].handle_alert(node, match)

def handle_enroll(self, node):
for alerter in self.alerters.values():
alerter.handle_enroll(node)


def make_celery(app, celery):
""" From http://flask.pocoo.org/docs/0.10/patterns/celery/ """
Expand Down
4 changes: 4 additions & 0 deletions doorman/plugins/alerters/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,7 @@ class AbstractAlerterPlugin(with_metaclass(ABCMeta)):
@abstractmethod
def handle_alert(self, node, match):
raise NotImplementedError()

@abstractmethod
def handle_enroll(self, node):
raise NotImplementedError()
3 changes: 3 additions & 0 deletions doorman/plugins/alerters/debug.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,6 @@ def __init__(self, config):
def handle_alert(self, node, match):
# TODO(andrew-d): better message?
current_app.logger.log(self.level, 'Triggered alert: {0!r}'.format(match))

def handle_enroll(self, node):
current_app.logger.log(self.level, 'Node enrolled: {0!r}'.format(node))
53 changes: 47 additions & 6 deletions doorman/plugins/alerters/emailer.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,29 @@ class EmailAlerter(AbstractAlerterPlugin):

def __init__(self, config):
self.recipients = config['recipients']
self.subject_template = config.get('subject_template', 'email/alert.subject.txt')
self.message_template = config.get('message_template', 'email/alert.body.txt')
self.subject_prefix = config.get('subject_prefix', '[Doorman]')
self.config = config

def handle_alert(self, node, match):
subject_template = self.config.setdefault(
'subject_template', 'email/alert.subject.txt'
)
message_template = self.config.setdefault(
'message_template', 'email/alert.body.txt'
)
subject_prefix = self.config.setdefault(
'subject_prefix', '[Doorman]'
)

subject = render_template(
self.subject_template,
prefix=self.subject_prefix,
subject_template,
prefix=subject_prefix,
match=match,
timestamp=dt.datetime.utcnow(),
node=node
)

body = render_template(
self.message_template,
message_template,
match=match,
timestamp=dt.datetime.utcnow(),
node=node
Expand All @@ -40,3 +48,36 @@ def handle_alert(self, node, match):
)

return mail.send(message)

def handle_enroll(self, node):
subject_template = self.config.setdefault(
'enroll_subject_template', 'email/enroll.subject.txt'
)
message_template = self.config.setdefault(
'enroll_message_template', 'email/enroll.body.txt'
)
subject_prefix = self.config.setdefault(
'enroll_subject_prefix', '[Doorman]'
)

subject = render_template(
subject_template,
prefix=subject_prefix,
timestamp=dt.datetime.utcnow(),
node=node
)

body = render_template(
message_template,
timestamp=dt.datetime.utcnow(),
node=node
)

message = Message(
subject.strip(),
recipients=self.recipients,
body=body,
charset='utf-8',
)

return mail.send(message)
3 changes: 3 additions & 0 deletions doorman/plugins/alerters/pagerduty.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,6 @@ def handle_alert(self, node, match):
self.logger.warn('Could not trigger PagerDuty alert!')

self.logger.debug('Response from PagerDuty: %r', resp.content)

def handle_enroll(self, node):
pass
5 changes: 4 additions & 1 deletion doorman/plugins/alerters/sentry.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,7 @@ def handle_alert(self, node, match):
'pack': pack,
'query': query,
},
)
)

def handle_enroll(self, node):
pass
6 changes: 6 additions & 0 deletions doorman/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ def learn_from_result(result, node):
return


@celery.task()
def notify_of_node_enrollment(node):
current_app.rule_manager.handle_enroll(node)
return


@celery.task()
def example_task(one, two):
print('Adding {0} and {1}'.format(one, two))
Expand Down
9 changes: 9 additions & 0 deletions doorman/templates/email/enroll.body.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
A new node was enrolled:

Host identifier: {{ node.display_name }}
Enrolled on: {{ node.enrolled_on }}
Remote IP address: {{ node.last_ip }}

Review {{ node.display_name }} at {{ url_for('manage.get_node', node_id=node.id, _external=True) }}.

---END doorman notification
1 change: 1 addition & 0 deletions doorman/templates/email/enroll.subject.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{{ prefix | trim }} New node enrolled: {{ node.display_name }}
21 changes: 19 additions & 2 deletions tests/test_alerters.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,11 @@ def setup_method(self, _method):
self.recipients = ['test@example.com']
self.config = {
'recipients': self.recipients,
'subject_prefix': '[Doorman Test] '
'subject_prefix': '[Doorman Test]',
'enroll_subject_prefix': '[Doorman Test]',
}

def test_will_email(self, node, rule, testapp):
def test_will_email_on_rule_match(self, node, rule, testapp):
from flask_mail import email_dispatched

match = RuleMatch(
Expand Down Expand Up @@ -112,6 +113,22 @@ def verify(message, app):
alerter = EmailAlerter(self.config)
alerter.handle_alert(node.to_dict(), match)

def test_will_email_on_node_enrollment(self, node, testapp):
from flask_mail import email_dispatched

expected_subject = '[Doorman Test] New node enrolled: {display_name}'.format(
display_name=node.display_name,
)

@email_dispatched.connect
def verify(message, app):
assert message.subject == expected_subject
assert self.recipients == message.recipients
assert 'A new node was enrolled:' in message.body

alerter = EmailAlerter(self.config)
alerter.handle_enroll(node.to_dict())


class TestSentryAlerter:

Expand Down
3 changes: 3 additions & 0 deletions tests/test_functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -1362,6 +1362,9 @@ def __init__(self, *args, **kwargs):
def handle_alert(self, node, match):
self.calls.append((node, match))

def handle_enroll(self, node):
self.calls.append((node, None))

dummy_alerter = DummyAlerter()

# This patches the appropriate config to create the 'dummy' alerter. This is a bit ugly :-(
Expand Down

0 comments on commit ebcc848

Please sign in to comment.