diff --git a/changelogs/fragments/11935-slack-add_hex_color_values.yaml b/changelogs/fragments/11935-slack-add_hex_color_values.yaml new file mode 100644 index 0000000000..859c818148 --- /dev/null +++ b/changelogs/fragments/11935-slack-add_hex_color_values.yaml @@ -0,0 +1,2 @@ +minor_changes: + - Add support for hex color values in Slack module. diff --git a/lib/ansible/modules/notification/slack.py b/lib/ansible/modules/notification/slack.py index 7bf4026540..bc69c3b35a 100644 --- a/lib/ansible/modules/notification/slack.py +++ b/lib/ansible/modules/notification/slack.py @@ -92,13 +92,10 @@ options: color: version_added: "2.0" description: - - Allow text to use default colors - use the default of 'normal' to not send a custom color bar at the start of the message + - Allow text to use default colors - use the default of 'normal' to not send a custom color bar at the start of the message. + - Allowed values for color can be one of 'normal', 'good', 'warning', 'danger', any valid 3 digit or 6 digit hex color value. + - Specifying value in hex is supported from version 2.8. default: 'normal' - choices: - - 'normal' - - 'good' - - 'warning' - - 'danger' attachments: description: - Define a list of attachments. This list mirrors the Slack JSON API. @@ -132,6 +129,14 @@ EXAMPLES = """ username: '' icon_url: '' +- name: insert a color bar in front of the message with valid hex color value + slack: + token: thetoken/generatedby/slack + msg: 'This message uses color in hex value' + color: '#00aacc' + username: '' + icon_url: '' + - name: Use the attachments API slack: token: thetoken/generatedby/slack @@ -158,6 +163,7 @@ EXAMPLES = """ msg: This message has <brackets> & ampersands in plain text. """ +import re from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.urls import fetch_url @@ -173,6 +179,12 @@ escape_table = { } +def is_valid_hex_color(color_choice): + if re.match(r'^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$', color_choice): + return True + return False + + def escape_quotes(text): '''Backslash any quotes within text.''' return "".join(escape_table.get(c, c) for c in text) @@ -265,7 +277,7 @@ def main(): link_names=dict(type='int', default=1, choices=[0, 1]), parse=dict(type='str', default=None, choices=['none', 'full']), validate_certs=dict(default='yes', type='bool'), - color=dict(type='str', default='normal', choices=['normal', 'good', 'warning', 'danger']), + color=dict(type='str', default='normal'), attachments=dict(type='list', required=False, default=None) ) ) @@ -283,6 +295,11 @@ def main(): color = module.params['color'] attachments = module.params['attachments'] + color_choices = ['normal', 'good', 'warning', 'danger'] + if color not in color_choices and not is_valid_hex_color(color): + module.fail_json(msg="Color value specified should be either one of %r " + "or any valid hex value with length 3 or 6." % color_choices) + payload = build_payload_for_slack(module, text, channel, thread_id, username, icon_url, icon_emoji, link_names, parse, color, attachments) do_notify_slack(module, domain, token, payload) diff --git a/test/units/modules/notification/test_slack.py b/test/units/modules/notification/test_slack.py index 5b325cbeb5..dc2e3eea02 100644 --- a/test/units/modules/notification/test_slack.py +++ b/test/units/modules/notification/test_slack.py @@ -3,7 +3,6 @@ import pytest from units.compat.mock import patch from ansible.modules.notification import slack from units.modules.utils import AnsibleExitJson, AnsibleFailJson, ModuleTestCase, set_module_args -from ansible import module_utils class TestSlackModule(ModuleTestCase): @@ -83,3 +82,39 @@ class TestSlackModule(ModuleTestCase): assert call_data['text'] == "test" assert call_data['thread_ts'] == 100.00 assert fetch_url_mock.call_args[1]['url'] == "https://hooks.slack.com/services/XXXX/YYYY/ZZZZ" + + def test_message_with_invalid_color(self): + """tests sending invalid color value to module""" + set_module_args({ + 'token': 'XXXX/YYYY/ZZZZ', + 'msg': 'test', + 'color': 'aa', + }) + with self.assertRaises(AnsibleFailJson) as exec_info: + self.module.main() + + msg = "Color value specified should be either one of" \ + " ['normal', 'good', 'warning', 'danger'] or any valid" \ + " hex value with length 3 or 6." + assert exec_info.exception.args[0]['msg'] == msg + + +color_test = [ + ('#111111', True), + ('#00aabb', True), + ('#abc', True), + ('#gghhjj', False), + ('#ghj', False), + ('#a', False), + ('#aaaaaaaa', False), + ('', False), + ('aaaa', False), + ('$00aabb', False), + ('$00a', False), +] + + +@pytest.mark.parametrize("color_value, ret_status", color_test) +def test_is_valid_hex_color(color_value, ret_status): + generated_value = slack.is_valid_hex_color(color_value) + assert generated_value == ret_status