Enable changed var with ufw check mode (#49948)

* Enable 'changed' var with ufw check mode

* Fix from comment of the PR + Unit Test

* Fix on ufw module after the second review

- delete rules change works in check mode
- simplify execute def & use it on every call process
- improved regexp
- rename vars defaults to current_default_values

* Add ignore error to execute() and use it in get_current_rules()

* Update after third code review (introduce change in changed status)

* Adjust tests and fix some problems (#1)

* 'active' also appears in 'inactive'.

* 'reject' is also a valid option here.

* For example for reloaded, changed will be set back to False here.

* Improve and adjust tests.

* Fix after merging integration test

* handle "disabled" on default routed

* Add /var/lib/ufw/.. rules files

* add unit test

* Fix pep8 formatting error

* Separate ipv6 and ipv4 rules process from checkmode

* fix non-ascii error on ci

* Some change after review

* Add unit test with sub network mask

* rename is_match function by is_starting

* add changelog fragment
This commit is contained in:
Jérôme BAROTIN 2019-02-11 12:05:35 +01:00 committed by John R Barker
parent 708f0b07ba
commit b99de25f32
5 changed files with 498 additions and 41 deletions

View file

@ -0,0 +1,2 @@
minor_changes:
- ufw - enable "changed" status while check mode is enabled

View file

@ -207,11 +207,37 @@ EXAMPLES = '''
'''
import re
from operator import itemgetter
from ansible.module_utils.basic import AnsibleModule
def compile_ipv4_regexp():
r = r"((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}"
r += r"(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])"
return re.compile(r)
def compile_ipv6_regexp():
"""
validation pattern provided by :
https://stackoverflow.com/questions/53497/regular-expression-that-matches-
valid-ipv6-addresses#answer-17871737
"""
r = r"(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:"
r += r"|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}"
r += r"(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4})"
r += r"{1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]"
r += r"{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]"
r += r"{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4})"
r += r"{0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]"
r += r"|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}"
r += r"[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}"
r += r"[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))"
return re.compile(r)
def main():
module = AnsibleModule(
argument_spec=dict(
@ -241,24 +267,62 @@ def main():
cmds = []
def execute(cmd):
ipv4_regexp = compile_ipv4_regexp()
ipv6_regexp = compile_ipv6_regexp()
def filter_line_that_not_start_with(pattern, content):
return ''.join([line for line in content.splitlines(True) if line.startswith(pattern)])
def filter_line_that_contains(pattern, content):
return [line for line in content.splitlines(True) if pattern in line]
def filter_line_that_not_contains(pattern, content):
return ''.join([line for line in content.splitlines(True) if not line.contains(pattern)])
def filter_line_that_match_func(match_func, content):
return ''.join([line for line in content.splitlines(True) if match_func(line) is not None])
def filter_line_that_contains_ipv4(content):
return filter_line_that_match_func(ipv4_regexp.search, content)
def filter_line_that_contains_ipv6(content):
return filter_line_that_match_func(ipv6_regexp.search, content)
def is_starting_by_ipv4(ip):
return ipv4_regexp.match(ip) is not None
def is_starting_by_ipv6(ip):
return ipv6_regexp.match(ip) is not None
def execute(cmd, ignore_error=False):
cmd = ' '.join(map(itemgetter(-1), filter(itemgetter(0), cmd)))
cmds.append(cmd)
(rc, out, err) = module.run_command(cmd)
(rc, out, err) = module.run_command(cmd, environ_update={"LANG": "C"})
if rc != 0:
module.fail_json(msg=err or out)
if rc != 0 and not ignore_error:
module.fail_json(msg=err or out, commands=cmds)
return out
def get_current_rules():
user_rules_files = ["/lib/ufw/user.rules",
"/lib/ufw/user6.rules",
"/etc/ufw/user.rules",
"/etc/ufw/user6.rules",
"/var/lib/ufw/user.rules",
"/var/lib/ufw/user6.rules"]
cmd = [[grep_bin], ["-h"], ["'^### tuple'"]]
cmd.extend([[f] for f in user_rules_files])
return execute(cmd, ignore_error=True)
def ufw_version():
"""
Returns the major and minor version of ufw installed on the system.
"""
rc, out, err = module.run_command("%s --version" % ufw_bin)
if rc != 0:
module.fail_json(
msg="Failed to get ufw version.", rc=rc, out=out, err=err
)
out = execute([[ufw_bin], ["--version"]])
lines = [x for x in out.split('\n') if x.strip() != '']
if len(lines) == 0:
@ -291,25 +355,65 @@ def main():
# Ensure ufw is available
ufw_bin = module.get_bin_path('ufw', True)
grep_bin = module.get_bin_path('grep', True)
# Save the pre state and rules in order to recognize changes
(_, pre_state, _) = module.run_command(ufw_bin + ' status verbose')
(_, pre_rules, _) = module.run_command("grep '^### tuple' /lib/ufw/user.rules /lib/ufw/user6.rules /etc/ufw/user.rules /etc/ufw/user6.rules")
pre_state = execute([[ufw_bin], ['status verbose']])
pre_rules = get_current_rules()
# Execute commands
changed = False
# Execute filter
for (command, value) in commands.items():
cmd = [[ufw_bin], [module.check_mode, '--dry-run']]
if command == 'state':
states = {'enabled': 'enable', 'disabled': 'disable',
'reloaded': 'reload', 'reset': 'reset'}
execute(cmd + [['-f'], [states[value]]])
if value in ['reloaded', 'reset']:
changed = True
if module.check_mode:
# "active" would also match "inactive", hence the space
ufw_enabled = pre_state.find(" active") != -1
if (value == 'disabled' and ufw_enabled) or (value == 'enabled' and not ufw_enabled):
changed = True
else:
execute(cmd + [['-f'], [states[value]]])
elif command == 'logging':
execute(cmd + [[command], [value]])
extract = re.search(r'Logging: (on|off) \(([a-z]+)\)', pre_state)
if extract:
current_level = extract.group(2)
current_on_off_value = extract.group(1)
if value != "off":
if value != "on" and (value != current_level or current_on_off_value == "off"):
changed = True
elif current_on_off_value != "off":
changed = True
else:
changed = True
if not module.check_mode:
execute(cmd + [[command], [value]])
elif command == 'default':
execute(cmd + [[command], [value], [params['direction']]])
if module.check_mode:
regexp = r'Default: (deny|allow|reject) \(incoming\), (deny|allow|reject) \(outgoing\), (deny|allow|reject|disabled) \(routed\)'
extract = re.search(regexp, pre_state)
if extract is not None:
current_default_values = {}
current_default_values["incoming"] = extract.group(1)
current_default_values["outgoing"] = extract.group(2)
current_default_values["routed"] = extract.group(3)
if current_default_values[params['direction']] != value:
changed = True
else:
changed = True
else:
execute(cmd + [[command], [value], [params['direction']]])
elif command == 'rule':
# Rules are constructed according to the long format
@ -336,14 +440,34 @@ def main():
if (ufw_major == 0 and ufw_minor >= 35) or ufw_major > 0:
cmd.append([params['comment'], "comment '%s'" % params['comment']])
execute(cmd)
rules_dry = execute(cmd)
if module.check_mode:
nb_skipping_line = len(filter_line_that_contains("Skipping", rules_dry))
if not (nb_skipping_line > 0 and nb_skipping_line == len(rules_dry.splitlines(True))):
rules_dry = filter_line_that_not_start_with("### tuple", rules_dry)
# ufw dry-run doesn't send all rules so have to compare ipv4 or ipv6 rules
if is_starting_by_ipv4(params['from_ip']) or is_starting_by_ipv4(params['to_ip']):
if filter_line_that_contains_ipv4(pre_rules) != filter_line_that_contains_ipv4(rules_dry):
changed = True
elif is_starting_by_ipv6(params['from_ip']) or is_starting_by_ipv6(params['to_ip']):
if filter_line_that_contains_ipv6(pre_rules) != filter_line_that_contains_ipv6(rules_dry):
changed = True
elif pre_rules != rules_dry:
changed = True
# Get the new state
(_, post_state, _) = module.run_command(ufw_bin + ' status verbose')
(_, post_rules, _) = module.run_command("grep '^### tuple' /lib/ufw/user.rules /lib/ufw/user6.rules /etc/ufw/user.rules /etc/ufw/user6.rules")
changed = (pre_state != post_state) or (pre_rules != post_rules)
return module.exit_json(changed=changed, commands=cmds, msg=post_state.rstrip())
if module.check_mode:
return module.exit_json(changed=changed, commands=cmds)
else:
post_state = execute([[ufw_bin], ['status'], ['verbose']])
if not changed:
post_rules = get_current_rules()
changed = (pre_state != post_state) or (pre_rules != post_rules)
return module.exit_json(changed=changed, commands=cmds, msg=post_state.rstrip())
if __name__ == '__main__':

View file

@ -1,5 +1,8 @@
---
# ############################################
- name: Make sure it is off
ufw:
state: disabled
- name: Enable (check mode)
ufw:
state: enabled
@ -20,7 +23,7 @@
register: enable_idem_check
- assert:
that:
# FIXME - enable_check is changed
- enable_check is changed
- enable is changed
- enable_idem is not changed
- enable_idem_check is not changed
@ -54,7 +57,7 @@
register: ipv4_allow_idem_check
- assert:
that:
# FIXME - ipv4_allow_check is changed
- ipv4_allow_check is changed
- ipv4_allow is changed
- ipv4_allow_idem is not changed
- ipv4_allow_idem_check is not changed
@ -92,7 +95,7 @@
register: delete_ipv4_allow_idem_check
- assert:
that:
# FIXME - delete_ipv4_allow_check is changed
- delete_ipv4_allow_check is changed
- delete_ipv4_allow is changed
- delete_ipv4_allow_idem is not changed
- delete_ipv4_allow_idem_check is not changed
@ -126,7 +129,7 @@
register: ipv6_allow_idem_check
- assert:
that:
# FIXME - ipv6_allow_check is changed
- ipv6_allow_check is changed
- ipv6_allow is changed
- ipv6_allow_idem is not changed
- ipv6_allow_idem_check is not changed
@ -164,7 +167,7 @@
register: delete_ipv6_allow_idem_check
- assert:
that:
# FIXME - delete_ipv6_allow_check is changed
- delete_ipv6_allow_check is changed
- delete_ipv6_allow is changed
- delete_ipv6_allow_idem is not changed
- delete_ipv6_allow_idem_check is not changed
@ -199,7 +202,7 @@
register: ipv4_allow_idem_check
- assert:
that:
# FIXME - ipv4_allow_check is changed
- ipv4_allow_check is changed
- ipv4_allow is changed
- ipv4_allow_idem is not changed
- ipv4_allow_idem_check is not changed
@ -237,7 +240,7 @@
register: delete_ipv4_allow_idem_check
- assert:
that:
# FIXME - delete_ipv4_allow_check is changed
- delete_ipv4_allow_check is changed
- delete_ipv4_allow is changed
- delete_ipv4_allow_idem is not changed
- delete_ipv4_allow_idem_check is not changed
@ -271,7 +274,7 @@
register: ipv6_allow_idem_check
- assert:
that:
# FIXME - ipv6_allow is_check changed
- ipv6_allow_check is changed
- ipv6_allow is changed
- ipv6_allow_idem is not changed
- ipv6_allow_idem_check is not changed
@ -309,7 +312,7 @@
register: delete_ipv6_allow_idem_check
- assert:
that:
# FIXME - delete_ipv6_allow_check is changed
- delete_ipv6_allow_check is changed
- delete_ipv6_allow is changed
- delete_ipv6_allow_idem is not changed
- delete_ipv6_allow_idem_check is not changed
@ -326,8 +329,8 @@
register: reload_check
- assert:
that:
- reload is not changed # NOT as expected!
- reload_check is not changed # NOT as expected!
- reload is changed
- reload_check is changed
# ############################################
- name: Disable (check mode)
@ -350,7 +353,7 @@
register: disable_idem_check
- assert:
that:
# FIXME - disable_check is changed
- disable_check is changed
- disable is changed
- disable_idem is not changed
- disable_idem_check is not changed
@ -393,7 +396,7 @@
register: reset_idem_check
- assert:
that:
- reset_check is not changed # NOT as expected!
- reset is not changed # NOT as expected!
- reset_idem is not changed
- reset_idem_check is not changed
- reset_check is changed
- reset is changed
- reset_idem is changed
- reset_idem_check is changed

View file

@ -4,6 +4,9 @@
state: enabled
# ############################################
- name: Make sure logging is off
ufw:
logging: no
- name: Logging (check mode)
ufw:
logging: yes
@ -17,6 +20,8 @@
shell: |
ufw status verbose | grep "^Logging:"
register: ufw_logging
environment:
LC_ALL: C
- name: Logging (idempotency)
ufw:
logging: yes
@ -26,13 +31,31 @@
logging: yes
check_mode: yes
register: logging_idem_check
- name: Logging (change, check mode)
ufw:
logging: full
check_mode: yes
register: logging_change_check
- name: Logging (change)
ufw:
logging: full
register: logging_change
- name: Get logging
shell: |
ufw status verbose | grep "^Logging:"
register: ufw_logging_change
environment:
LC_ALL: C
- assert:
that:
- logging_check is not changed # NOT as expected!
- logging is not changed # NOT as expected!
- logging_check is changed
- logging is changed
- "ufw_logging.stdout == 'Logging: on (low)'"
- logging_idem is not changed
- logging_idem_check is not changed
- "ufw_logging_change.stdout == 'Logging: on (full)'"
- logging_change is changed
- logging_change_check is changed
# ############################################
- name: Default (check mode)
@ -50,6 +73,8 @@
shell: |
ufw status verbose | grep "^Default:"
register: ufw_defaults
environment:
LC_ALL: C
- name: Default (idempotency)
ufw:
default: reject
@ -76,13 +101,15 @@
shell: |
ufw status verbose | grep "^Default:"
register: ufw_defaults_change
environment:
LC_ALL: C
- assert:
that:
# FIXME - default_check is changed
- default_check is changed
- default is changed
- "'reject (incoming)' in ufw_defaults.stdout"
- default_idem is not changed
- default_idem_check is not changed
# FIXME - default_change_check is changed
- default_change_check is changed
- default_change is changed
- "'allow (incoming)' in ufw_defaults_change.stdout"

View file

@ -0,0 +1,301 @@
from units.compat import unittest
from units.compat.mock import patch
from ansible.module_utils import basic
from ansible.module_utils._text import to_bytes
import ansible.modules.system.ufw as module
import json
# mock ufw messages
ufw_version_35 = """ufw 0.35\nCopyright 2008-2015 Canonical Ltd.\n"""
ufw_verbose_header = """Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), deny (routed)
New profiles: skip
To Action From
-- ------ ----"""
ufw_status_verbose_with_port_7000 = ufw_verbose_header + """
7000/tcp ALLOW IN Anywhere
7000/tcp (v6) ALLOW IN Anywhere (v6)
"""
user_rules_with_port_7000 = """### tuple ### allow tcp 7000 0.0.0.0/0 any 0.0.0.0/0 in
### tuple ### allow tcp 7000 ::/0 any ::/0 in
"""
user_rules_with_ipv6 = """### tuple ### allow udp 5353 0.0.0.0/0 any 224.0.0.251 in
### tuple ### allow udp 5353 ::/0 any ff02::fb in
"""
ufw_status_verbose_with_ipv6 = ufw_verbose_header + """
5353/udp ALLOW IN 224.0.0.251
5353/udp ALLOW IN ff02::fb
"""
ufw_status_verbose_nothing = ufw_verbose_header
skippg_adding_existing_rules = "Skipping adding existing rule\nSkipping adding existing rule (v6)\n"
grep_config_cli = "grep -h '^### tuple' /lib/ufw/user.rules /lib/ufw/user6.rules /etc/ufw/user.rules /etc/ufw/user6.rules "
grep_config_cli += "/var/lib/ufw/user.rules /var/lib/ufw/user6.rules"
dry_mode_cmd_with_port_700 = {
"ufw status verbose": ufw_status_verbose_with_port_7000,
"ufw --version": ufw_version_35,
"ufw --dry-run allow from any to any port 7000 proto tcp": skippg_adding_existing_rules,
"ufw --dry-run delete allow from any to any port 7000 proto tcp": "",
"ufw --dry-run delete allow from any to any port 7001 proto tcp": user_rules_with_port_7000,
grep_config_cli: user_rules_with_port_7000
}
# setup configuration :
# ufw reset
# ufw enable
# ufw allow proto udp to any port 5353 from 224.0.0.251
# ufw allow proto udp to any port 5353 from ff02::fb
dry_mode_cmd_with_ipv6 = {
"ufw status verbose": ufw_status_verbose_with_ipv6,
"ufw --version": ufw_version_35,
# CONTENT of the command sudo ufw --dry-run delete allow in from ff02::fb port 5353 proto udp | grep -E "^### tupple"
"ufw --dry-run delete allow from ff02::fb to any port 5353 proto udp": "### tuple ### allow udp any ::/0 5353 ff02::fb in",
grep_config_cli: user_rules_with_ipv6,
"ufw --dry-run allow from ff02::fb to any port 5353 proto udp": skippg_adding_existing_rules,
"ufw --dry-run allow from 224.0.0.252 to any port 5353 proto udp": """### tuple ### allow udp 5353 0.0.0.0/0 any 224.0.0.251 in
### tuple ### allow udp 5353 0.0.0.0/0 any 224.0.0.252 in
""",
"ufw --dry-run allow from 10.0.0.0/24 to any port 1577 proto udp": "### tuple ### allow udp 1577 0.0.0.0/0 any 10.0.0.0/24 in"
}
dry_mode_cmd_nothing = {
"ufw status verbose": ufw_status_verbose_nothing,
"ufw --version": ufw_version_35,
grep_config_cli: "",
"ufw --dry-run allow from any to :: port 23": "### tuple ### allow any 23 :: any ::/0 in"
}
def do_nothing_func_nothing(*args, **kwarg):
return 0, dry_mode_cmd_nothing[args[0]], ""
def do_nothing_func_ipv6(*args, **kwarg):
return 0, dry_mode_cmd_with_ipv6[args[0]], ""
def do_nothing_func_port_7000(*args, **kwarg):
return 0, dry_mode_cmd_with_port_700[args[0]], ""
def set_module_args(args):
args = json.dumps({'ANSIBLE_MODULE_ARGS': args})
"""prepare arguments so that they will be picked up during module creation"""
basic._ANSIBLE_ARGS = to_bytes(args)
class AnsibleExitJson(Exception):
"""Exception class to be raised by module.exit_json and caught by the test case"""
pass
class AnsibleFailJson(Exception):
"""Exception class to be raised by module.fail_json and caught by the test case"""
pass
def exit_json(*args, **kwargs):
"""function to patch over exit_json; package return data into an exception"""
if 'changed' not in kwargs:
kwargs['changed'] = False
raise AnsibleExitJson(kwargs)
def fail_json(*args, **kwargs):
"""function to patch over fail_json; package return data into an exception"""
kwargs['failed'] = True
raise AnsibleFailJson(kwargs)
def get_bin_path(self, arg, required=False):
"""Mock AnsibleModule.get_bin_path"""
return arg
class TestUFW(unittest.TestCase):
def setUp(self):
self.mock_module_helper = patch.multiple(basic.AnsibleModule,
exit_json=exit_json,
fail_json=fail_json,
get_bin_path=get_bin_path)
self.mock_module_helper.start()
self.addCleanup(self.mock_module_helper.stop)
def test_filter_line_that_contains_ipv4(self):
reg = module.compile_ipv4_regexp()
self.assertTrue(reg.search("### tuple ### allow udp 5353 ::/0 any ff02::fb in") is None)
self.assertTrue(reg.search("### tuple ### allow udp 5353 0.0.0.0/0 any 224.0.0.251 in") is not None)
self.assertTrue(reg.match("ff02::fb") is None)
self.assertTrue(reg.match("224.0.0.251") is not None)
self.assertTrue(reg.match("10.0.0.0/8") is not None)
self.assertTrue(reg.match("somethingElse") is None)
self.assertTrue(reg.match("::") is None)
self.assertTrue(reg.match("any") is None)
def test_filter_line_that_contains_ipv6(self):
reg = module.compile_ipv6_regexp()
self.assertTrue(reg.search("### tuple ### allow udp 5353 ::/0 any ff02::fb in") is not None)
self.assertTrue(reg.search("### tuple ### allow udp 5353 0.0.0.0/0 any 224.0.0.251 in") is None)
self.assertTrue(reg.search("### tuple ### allow any 23 :: any ::/0 in") is not None)
self.assertTrue(reg.match("ff02::fb") is not None)
self.assertTrue(reg.match("224.0.0.251") is None)
self.assertTrue(reg.match("::") is not None)
def test_check_mode_add_rules(self):
set_module_args({
'rule': 'allow',
'proto': 'tcp',
'port': '7000',
'_ansible_check_mode': True
})
result = self.__getResult(do_nothing_func_port_7000)
self.assertFalse(result.exception.args[0]['changed'])
def test_check_mode_delete_existing_rules(self):
set_module_args({
'rule': 'allow',
'proto': 'tcp',
'port': '7000',
'delete': 'yes',
'_ansible_check_mode': True,
})
self.assertTrue(self.__getResult(do_nothing_func_port_7000).exception.args[0]['changed'])
def test_check_mode_delete_not_existing_rules(self):
set_module_args({
'rule': 'allow',
'proto': 'tcp',
'port': '7001',
'delete': 'yes',
'_ansible_check_mode': True,
})
self.assertFalse(self.__getResult(do_nothing_func_port_7000).exception.args[0]['changed'])
def test_enable_mode(self):
set_module_args({
'state': 'enabled',
'_ansible_check_mode': True
})
self.assertFalse(self.__getResult(do_nothing_func_port_7000).exception.args[0]['changed'])
def test_disable_mode(self):
set_module_args({
'state': 'disabled',
'_ansible_check_mode': True
})
self.assertTrue(self.__getResult(do_nothing_func_port_7000).exception.args[0]['changed'])
def test_logging_off(self):
set_module_args({
'logging': 'off',
'_ansible_check_mode': True
})
self.assertTrue(self.__getResult(do_nothing_func_port_7000).exception.args[0]['changed'])
def test_logging_on(self):
set_module_args({
'logging': 'on',
'_ansible_check_mode': True
})
self.assertFalse(self.__getResult(do_nothing_func_port_7000).exception.args[0]['changed'])
def test_default_changed(self):
set_module_args({
'default': 'allow',
"direction": "incoming",
'_ansible_check_mode': True
})
self.assertTrue(self.__getResult(do_nothing_func_port_7000).exception.args[0]['changed'])
def test_default_not_changed(self):
set_module_args({
'default': 'deny',
"direction": "incoming",
'_ansible_check_mode': True
})
self.assertFalse(self.__getResult(do_nothing_func_port_7000).exception.args[0]['changed'])
def test_ipv6_remove(self):
set_module_args({
'rule': 'allow',
'proto': 'udp',
'port': '5353',
'from': 'ff02::fb',
'delete': 'yes',
'_ansible_check_mode': True,
})
self.assertTrue(self.__getResult(do_nothing_func_ipv6).exception.args[0]['changed'])
def test_ipv6_add_existing(self):
set_module_args({
'rule': 'allow',
'proto': 'udp',
'port': '5353',
'from': 'ff02::fb',
'_ansible_check_mode': True,
})
self.assertFalse(self.__getResult(do_nothing_func_ipv6).exception.args[0]['changed'])
def test_add_not_existing_ipv4_submask(self):
set_module_args({
'rule': 'allow',
'proto': 'udp',
'port': '1577',
'from': '10.0.0.0/24',
'_ansible_check_mode': True,
})
self.assertTrue(self.__getResult(do_nothing_func_ipv6).exception.args[0]['changed'])
def test_ipv4_add_with_existing_ipv6(self):
set_module_args({
'rule': 'allow',
'proto': 'udp',
'port': '5353',
'from': '224.0.0.252',
'_ansible_check_mode': True,
})
self.assertTrue(self.__getResult(do_nothing_func_ipv6).exception.args[0]['changed'])
def test_ipv6_add_from_nothing(self):
set_module_args({
'rule': 'allow',
'port': '23',
'to': '::',
'_ansible_check_mode': True,
})
result = self.__getResult(do_nothing_func_nothing).exception.args[0]
print(result)
self.assertTrue(result['changed'])
def __getResult(self, cmd_fun):
with patch.object(basic.AnsibleModule, 'run_command') as mock_run_command:
mock_run_command.side_effect = cmd_fun
with self.assertRaises(AnsibleExitJson) as result:
module.main()
return result