[tempestmail] Custom email for different matchers

Define a set of custom tags for each filter block to be added to
the email subject. A separate email will be sent to each email
address that matches the criteria.

Change-Id: I6be404c8b25eeefc1f9574c8a26a5b320d62d2c6
Closes-Bug: #1730409
This commit is contained in:
Rafael Folco 2017-12-21 11:21:07 -02:00 committed by Emilien Macchi
parent f31bedca94
commit 18a3287dac
3 changed files with 85 additions and 23 deletions

View File

@ -96,6 +96,26 @@ gate-tripleo-ci-centos-7-ovb-ha-oooq or
gate-tripleo-ci-centos-7-ovb-containers-oooq has a test failure that matches
the regex.
```yaml
...
emails:
- mail: fail1@example.com
regex: '.*foo.*'
topics: foo1
- mail: fail1@example.com
regex: '.*bar.*'
topics: bar1
- mail: fail2@example.com
regex: '.*bar.*'
topics: bar2,extra
...
```
if a jobs contains tests matching both 'foo' and 'bar', then:
* fail1@ will receive an email '[foo1]...' and an email '[bar1]...'
* fail2@ will receive an email '[bar2][extra]...'
So, the order is:
1. If there's no jobs list the user will receive all the emails.

View File

@ -108,7 +108,7 @@ class Mail(object):
def filter_emails(self, job, data):
has_errors = False
addresses = []
bookaddr = {}
for error in [data.get(x, []) for x in ('new', 'failed', 'errors')]:
if error:
@ -123,24 +123,33 @@ class Mail(object):
m.get('jobs') or not
m.get('jobs')]
# Now we filter for regex if doesn't exists
addresses = [m.get('mail') for m in emails if not m.get('regex')]
# And finally, if regex exists
# Add all addresses except those that regex don't match
for email in emails:
for r in email.get('regex'):
if len(filter(r.search, data.get('new'))):
addresses.append(email.get('mail'))
break
add = True
if email.get('regex'):
for r in email.get('regex'):
if len(filter(r.search, data.get('new'))):
break
add = False
if add:
topics = ''
if email.get('topics'):
# Parse topics and format it between brackets
t = email.get('topics').split(',')
topics = ''.join('[{}]'.format(s) for s in t)
# Add the address to the bookaddr dict
# {'[foo][bar]' : ['john@redhat.com', 'mary@redhat.com']}
bookaddr.setdefault(topics, []).append(email.get('mail'))
else:
self.log.debug('No failures send email to everybody')
addresses = [m.get('mail') for m in self.config.emails
if not m.get('fail_only')]
# Single group with empty topic is added to the bookaddr
bookaddr.setdefault('', []).append(addresses)
data['has_errors'] = has_errors
return addresses
return bookaddr
def _send_mail_local(self, addresses, message, subject, output):
msg = MIMEText(message, 'html')
@ -167,14 +176,16 @@ class Mail(object):
requests.post(self.config.api_server, data=data)
def send_mail(self, job, data, output):
addresses = self.filter_emails(job, data)
bookaddr = self.filter_emails(job, data)
message = self.render_template(data)
subject = 'Job {} results'.format(job)
if self.config.use_api_server:
self._send_mail_api(addresses, message, subject)
else:
self._send_mail_local(addresses, message, subject, output)
# Send a separate email to the addresses grouped by topics
for topics, addresses in bookaddr.items():
subject = '{} Job {} results'.format(topics, job).lstrip()
if self.config.use_api_server:
self._send_mail_api(addresses, message, subject)
else:
self._send_mail_local(addresses, message, subject, output)
class TempestMailCmd(object):
@ -367,6 +378,7 @@ class TempestMailCmd(object):
'mail': e.get('mail'),
'jobs': e.get('jobs', []),
'regex': regex,
'topics': e.get('topics'),
'fail_only': e.get('fail_only', False)})
for t in config.get('known_failures', []):
known_failures.append({'test': t.get('test'),

View File

@ -2,6 +2,7 @@ import datetime
import mock
import tempfile
import unittest
import re
from tempestmail import Config
from tempestmail import Mail
@ -29,9 +30,9 @@ class MailTest(unittest.TestCase):
config.require_auth = True
config.emails = [
{'mail': 'email1@example.com', 'name': 'name 1',
'jobs': [], 'regex': []},
'jobs': [], 'regex': [], 'topics': ''},
{'mail': 'email2@example.com', 'name': 'name 2',
'jobs': [], 'regex': []}
'jobs': [], 'regex': [], 'topics': ''}
]
config.template = 'template.html'
return config
@ -87,16 +88,45 @@ class MailTest(unittest.TestCase):
self.assertEquals(self.data.get('has_errors'), None)
addresses = mail.filter_emails(
'periodic-tripleo-ci-centos-7-ovb-ha-tempest', self.data)
self.assertEquals(['email1@example.com', 'email2@example.com'],
self.assertEquals({'' : ['email1@example.com', 'email2@example.com']},
addresses)
mail.config.emails[0]['jobs'].append('another-job')
addresses = mail.filter_emails(
'periodic-tripleo-ci-centos-7-ovb-ha-tempest', self.data)
self.assertEquals(['email2@example.com'], addresses)
self.assertEquals({'' : ['email2@example.com']}, addresses)
self.assertEquals(self.data['has_errors'], True)
mail.config.emails[0]['jobs'] = []
mail.config.emails[0]['regex'].append('tempest.some.regex')
self.assertEquals(['email2@example.com'], addresses)
mail.config.emails[0]['regex'].append(re.compile(
'tempest.some.regex'))
self.assertEquals({'' : ['email2@example.com']}, addresses)
def test_filter_emails_topics(self):
mail = Mail(self.config)
addresses = mail.filter_emails(
'periodic-tripleo-ci-centos-7-ovb-ha-tempest', self.data)
self.assertEquals({'' : ['email1@example.com',
'email2@example.com']},
addresses)
mail.config.emails[0]['jobs'].append(
'periodic-tripleo-ci-centos-7-ovb-ha-tempest')
mail.config.emails[0]['regex'].append(re.compile(
'upload_too_many_objects'))
mail.config.emails[0]['topics'] = 'many_objects'
mail.config.emails[1]['regex'].append(re.compile(
'upload_valid_object'))
mail.config.emails[1]['topics'] = 'valid_object'
new = {'mail': 'email2@example.com', 'name': 'name 2',
'jobs': ['periodic-tripleo-ci-centos-7-ovb-ha-tempest'],
'regex': [re.compile('upload_valid_object')],
'topics': 'valid_object,object_storage'}
mail.config.emails.append(new)
addresses = mail.filter_emails(
'periodic-tripleo-ci-centos-7-ovb-ha-tempest', self.data)
bookaddr = {'[many_objects]' : ['email1@example.com'],
'[valid_object]' : ['email2@example.com'],
'[valid_object][object_storage]' : ['email2@example.com']
}
self.assertEquals(bookaddr, addresses)
@mock.patch('tempestmail.Mail._send_mail_api')
@mock.patch('tempestmail.Mail._send_mail_local')