Merge "Add queue name to notifications"

This commit is contained in:
Jenkins 2016-02-15 20:57:32 +00:00 committed by Gerrit Code Review
commit 2f459a6bc9
3 changed files with 80 additions and 15 deletions

View File

@ -36,6 +36,10 @@ class MailtoTask(object):
for message in messages:
p = subprocess.Popen(conf.notification.smtp_command.split(' '),
stdin=subprocess.PIPE)
# NOTE(Eva-i): Unfortunately this will add 'queue_name' key to
# our original messages(dicts) which will be later consumed in
# the storage controller. It seems safe though.
message['queue_name'] = subscription['source']
msg = text.MIMEText(json.dumps(message))
msg["to"] = subscriber.path
msg["from"] = subscription['options'].get('from', '')

View File

@ -27,6 +27,10 @@ class WebhookTask(object):
def execute(self, subscription, messages, **kwargs):
try:
for msg in messages:
# NOTE(Eva-i): Unfortunately this will add 'queue_name' key to
# our original messages(dicts) which will be later consumed in
# the storage controller. It seems safe though.
msg['queue_name'] = subscription['source']
requests.post(subscription['subscriber'],
data=json.dumps(msg),
headers={'Content-Type': 'application/json'})

View File

@ -37,11 +37,28 @@ class NotifierTest(testing.TestBase):
"total_bytes": "99614720"}
}
]
# NOTE(Eva-i): NotifiedDriver adds "queue_name" key to each
# message (dictionary), so final notifications look like this
self.notifications = [{"ttl": 300,
"body": {"event": "BackupStarted",
"backup_id":
"c378813c-3f0b-11e2-ad92"},
"queue_name": "fake_queue"
},
{"body": {"event": "BackupProgress",
"current_bytes": "0",
"total_bytes": "99614720"},
"queue_name": "fake_queue"
}
]
def test_webhook(self):
subscription = [{'subscriber': 'http://trigger_me'},
{'subscriber': 'http://call_me'},
{'subscriber': 'http://ping_me'}]
subscription = [{'subscriber': 'http://trigger_me',
'source': 'fake_queue'},
{'subscriber': 'http://call_me',
'source': 'fake_queue'},
{'subscriber': 'http://ping_me',
'source': 'fake_queue'}]
ctlr = mock.MagicMock()
ctlr.list = mock.Mock(return_value=iter([subscription]))
driver = notifier.NotifierDriver(subscription_controller=ctlr)
@ -50,24 +67,33 @@ class NotifierTest(testing.TestBase):
driver.post('fake_queue', self.messages, self.client_id,
self.project)
driver.executor.shutdown()
# Let's deserialize "data" from JSON string to dict in each mock
# call, so we can do dict comparisons. JSON string comparisons
# often fail, because dict keys can be serialized in different
# order inside the string.
for call in mock_post.call_args_list:
call[1]['data'] = json.loads(call[1]['data'])
# These are not real calls. In real calls each "data" argument is
# serialized by json.dumps. But we made a substitution before,
# so it will work.
mock_post.assert_has_calls([
mock.call(subscription[0]['subscriber'],
data=json.dumps(self.messages[0]),
data=self.notifications[0],
headers=headers),
mock.call(subscription[1]['subscriber'],
data=json.dumps(self.messages[0]),
data=self.notifications[0],
headers=headers),
mock.call(subscription[2]['subscriber'],
data=json.dumps(self.messages[0]),
data=self.notifications[0],
headers=headers),
mock.call(subscription[0]['subscriber'],
data=json.dumps(self.messages[1]),
data=self.notifications[1],
headers=headers),
mock.call(subscription[1]['subscriber'],
data=json.dumps(self.messages[1]),
data=self.notifications[1],
headers=headers),
mock.call(subscription[2]['subscriber'],
data=json.dumps(self.messages[1]),
data=self.notifications[1],
headers=headers),
], any_order=True)
self.assertEqual(6, len(mock_post.mock_calls))
@ -75,9 +101,11 @@ class NotifierTest(testing.TestBase):
@mock.patch('subprocess.Popen')
def test_mailto(self, mock_popen):
subscription = [{'subscriber': 'mailto:aaa@example.com',
'source': 'fake_queue',
'options': {'subject': 'Hello',
'from': 'zaqar@example.com'}},
{'subscriber': 'mailto:bbb@example.com',
'source': 'fake_queue',
'options': {'subject': 'Hello',
'from': 'zaqar@example.com'}}]
ctlr = mock.MagicMock()
@ -87,19 +115,18 @@ class NotifierTest(testing.TestBase):
msg = ('Content-Type: text/plain; charset="us-ascii"\n'
'MIME-Version: 1.0\nContent-Transfer-Encoding: 7bit\nto:'
' %(to)s\nfrom: %(from)s\nsubject: %(subject)s\n\n%(body)s')
mail1 = msg % {'to': subscription[0]['subscriber'][7:],
'from': 'zaqar@example.com', 'subject': 'Hello',
'body': json.dumps(self.messages[0])}
'body': json.dumps(self.notifications[0])}
mail2 = msg % {'to': subscription[0]['subscriber'][7:],
'from': 'zaqar@example.com', 'subject': 'Hello',
'body': json.dumps(self.messages[1])}
'body': json.dumps(self.notifications[1])}
mail3 = msg % {'to': subscription[1]['subscriber'][7:],
'from': 'zaqar@example.com', 'subject': 'Hello',
'body': json.dumps(self.messages[0])}
'body': json.dumps(self.notifications[0])}
mail4 = msg % {'to': subscription[1]['subscriber'][7:],
'from': 'zaqar@example.com', 'subject': 'Hello',
'body': json.dumps(self.messages[1])}
'body': json.dumps(self.notifications[1])}
def _communicate(msg):
called.add(msg)
@ -112,7 +139,23 @@ class NotifierTest(testing.TestBase):
driver.executor.shutdown()
self.assertEqual(4, len(called))
self.assertEqual({mail1, mail2, mail3, mail4}, called)
# Let's deserialize "body" from JSON string to dict and then serialize
# it back to JSON, but sorted, allowing us make comparisons.
mails = {mail1, mail2, mail3, mail4}
mail_options = []
mail_bodies = []
for mail in mails:
options, body = mail.split('\n\n')
mail_options.append(options)
mail_bodies.append(json.dumps(json.loads(body), sort_keys=True))
called_options = []
called_bodies = []
for call in called:
options, body = call.split('\n\n')
called_options.append(options)
called_bodies.append(json.dumps(json.loads(body), sort_keys=True))
self.assertEqual(sorted(mail_options), sorted(called_options))
self.assertEqual(sorted(mail_bodies), sorted(called_bodies))
def test_post_no_subscriber(self):
ctlr = mock.MagicMock()
@ -123,3 +166,17 @@ class NotifierTest(testing.TestBase):
self.project)
driver.executor.shutdown()
self.assertEqual(0, mock_post.call_count)
def test_proper_notification_data(self):
subscription = [{'subscriber': 'http://trigger_me',
'source': 'fake_queue'}]
ctlr = mock.MagicMock()
ctlr.list = mock.Mock(return_value=iter([subscription]))
driver = notifier.NotifierDriver(subscription_controller=ctlr)
with mock.patch('requests.post') as mock_post:
driver.post('fake_queue', self.messages, self.client_id,
self.project)
driver.executor.shutdown()
self.assertEqual(2, mock_post.call_count)
self.assertEqual(self.notifications[1],
json.loads(mock_post.call_args[1]['data']))