diff --git a/lib/ansible/modules/notification/campfire.py b/lib/ansible/modules/notification/campfire.py index cf64381ddc1..9cc845e0600 100644 --- a/lib/ansible/modules/notification/campfire.py +++ b/lib/ansible/modules/notification/campfire.py @@ -72,7 +72,14 @@ EXAMPLES = ''' msg: Task completed ... with feeling. ''' -import cgi +try: + from html import escape as html_escape +except ImportError: + # Python-3.2 or later + import cgi + + def html_escape(text, quote=True): + return cgi.escape(text, quote) from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.urls import fetch_url @@ -126,14 +133,14 @@ def main(): # Send some audible notification if requested if notify: - response, info = fetch_url(module, target_url, data=NSTR % cgi.escape(notify), headers=headers) + response, info = fetch_url(module, target_url, data=NSTR % html_escape(notify), headers=headers) if info['status'] not in [200, 201]: module.fail_json(msg="unable to send msg: '%s', campfire api" " returned error code: '%s'" % (notify, info['status'])) # Send the message - response, info = fetch_url(module, target_url, data=MSTR % cgi.escape(msg), headers=headers) + response, info = fetch_url(module, target_url, data=MSTR % html_escape(msg), headers=headers) if info['status'] not in [200, 201]: module.fail_json(msg="unable to send msg: '%s', campfire api" " returned error code: '%s'" % diff --git a/test/units/modules/notification/test_campfire.py b/test/units/modules/notification/test_campfire.py new file mode 100644 index 00000000000..33f53e957ee --- /dev/null +++ b/test/units/modules/notification/test_campfire.py @@ -0,0 +1,93 @@ + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import pytest +from units.compat.mock import patch +from ansible.modules.notification import campfire +from units.modules.utils import AnsibleExitJson, AnsibleFailJson, ModuleTestCase, set_module_args + + +class TestCampfireModule(ModuleTestCase): + + def setUp(self): + super(TestCampfireModule, self).setUp() + self.module = campfire + + def tearDown(self): + super(TestCampfireModule, self).tearDown() + + @pytest.fixture + def fetch_url_mock(self, mocker): + return mocker.patch('ansible.module_utils.notification.campfire.fetch_url') + + def test_without_required_parameters(self): + """Failure must occurs when all parameters are missing""" + with self.assertRaises(AnsibleFailJson): + set_module_args({}) + self.module.main() + + def test_successful_message(self): + """Test failure message""" + set_module_args({ + 'subscription': 'test', + 'token': 'abc', + 'room': 'test', + 'msg': 'test' + }) + + with patch.object(campfire, "fetch_url") as fetch_url_mock: + fetch_url_mock.return_value = (None, {"status": 200}) + with self.assertRaises(AnsibleExitJson): + self.module.main() + + assert fetch_url_mock.call_count == 1 + url = fetch_url_mock.call_args[0][1] + data = fetch_url_mock.call_args[1]['data'] + + assert url == 'https://test.campfirenow.com/room/test/speak.xml' + assert data == 'test' + + def test_successful_message_with_notify(self): + """Test failure message""" + set_module_args({ + 'subscription': 'test', + 'token': 'abc', + 'room': 'test', + 'msg': 'test', + 'notify': 'bell' + }) + + with patch.object(campfire, "fetch_url") as fetch_url_mock: + fetch_url_mock.return_value = (None, {"status": 200}) + with self.assertRaises(AnsibleExitJson): + self.module.main() + + assert fetch_url_mock.call_count == 2 + notify_call = fetch_url_mock.mock_calls[0] + url = notify_call[1][1] + data = notify_call[2]['data'] + + assert url == 'https://test.campfirenow.com/room/test/speak.xml' + assert data == 'SoundMessagebell' + + message_call = fetch_url_mock.mock_calls[1] + url = message_call[1][1] + data = message_call[2]['data'] + + assert url == 'https://test.campfirenow.com/room/test/speak.xml' + assert data == 'test' + + def test_failure_message(self): + """Test failure message""" + set_module_args({ + 'subscription': 'test', + 'token': 'abc', + 'room': 'test', + 'msg': 'test' + }) + + with patch.object(campfire, "fetch_url") as fetch_url_mock: + fetch_url_mock.return_value = (None, {"status": 403}) + with self.assertRaises(AnsibleFailJson): + self.module.main()