diff options
Diffstat (limited to 'tests/unit')
13 files changed, 1747 insertions, 31 deletions
diff --git a/tests/unit/modules/network/vyos/fixtures/vyos_firewall_global_config_v14.cfg b/tests/unit/modules/network/vyos/fixtures/vyos_firewall_global_config_v14.cfg new file mode 100644 index 0000000..7b281de --- /dev/null +++ b/tests/unit/modules/network/vyos/fixtures/vyos_firewall_global_config_v14.cfg @@ -0,0 +1,16 @@ +set firewall group address-group RND-HOSTS address 192.0.2.1 +set firewall group address-group RND-HOSTS address 192.0.2.3 +set firewall group address-group RND-HOSTS address 192.0.2.5 +set firewall group address-group RND-HOSTS description 'This group has the Management hosts address lists' +set firewall group ipv6-address-group LOCAL-v6 address ::1 +set firewall group ipv6-address-group LOCAL-v6 address fdec:2503:89d6:59b3::1 +set firewall group ipv6-address-group LOCAL-v6 description 'This group has the hosts address lists of this machine' +set firewall group network-group RND network 192.0.2.0/24 +set firewall group network-group RND description 'This group has the Management network addresses' +set firewall group ipv6-network-group UNIQUE-LOCAL-v6 network fc00::/7 +set firewall group ipv6-network-group UNIQUE-LOCAL-v6 description 'This group encompasses the ULA address space in IPv6' +set firewall group port-group SSH port 22 +set firewall group port-group SSH description 'This group has the ssh ports' +set firewall global-options all-ping enable +set firewall global-options state-policy related action 'accept' +set firewall global-options state-policy related log-level 'alert' diff --git a/tests/unit/modules/network/vyos/fixtures/vyos_firewall_rules_config.cfg b/tests/unit/modules/network/vyos/fixtures/vyos_firewall_rules_config.cfg index a3aec78..f1fdf1e 100644 --- a/tests/unit/modules/network/vyos/fixtures/vyos_firewall_rules_config.cfg +++ b/tests/unit/modules/network/vyos/fixtures/vyos_firewall_rules_config.cfg @@ -9,6 +9,7 @@ set firewall name V4-INGRESS rule 101 set firewall name V4-INGRESS rule 101 'disable' set firewall name V4-INGRESS rule 101 action 'accept' set firewall name V4-INGRESS rule 101 ipsec 'match-ipsec' +set firewall name V4-INGRESS rule 101 log 'enable' set firewall name EGRESS default-action 'reject' set firewall ipv6-name EGRESS default-action 'reject' set firewall ipv6-name EGRESS rule 20 diff --git a/tests/unit/modules/network/vyos/fixtures/vyos_firewall_rules_config_v14.cfg b/tests/unit/modules/network/vyos/fixtures/vyos_firewall_rules_config_v14.cfg new file mode 100644 index 0000000..ef596cd --- /dev/null +++ b/tests/unit/modules/network/vyos/fixtures/vyos_firewall_rules_config_v14.cfg @@ -0,0 +1,26 @@ +set firewall ipv4 name V4-INGRESS default-action 'accept' +set firewall ipv6 name V6-INGRESS default-action 'accept' +set firewall ipv4 name V4-INGRESS description 'This is IPv4 V4-INGRESS rule set' +set firewall ipv4 name V4-INGRESS default-log +set firewall ipv4 name V4-INGRESS rule 101 protocol 'icmp' +set firewall ipv4 name V4-INGRESS rule 101 description 'Rule 101 is configured by Ansible' +set firewall ipv4 name V4-INGRESS rule 101 packet-length-exclude 100 +set firewall ipv4 name V4-INGRESS rule 101 packet-length-exclude 300 +set firewall ipv4 name V4-INGRESS rule 101 log +set firewall ipv4 name V4-INGRESS rule 101 +set firewall ipv4 name V4-INGRESS rule 101 'disable' +set firewall ipv4 name V4-INGRESS rule 101 action 'accept' +set firewall ipv4 name EGRESS default-action 'reject' +set firewall ipv6 name EGRESS default-action 'reject' +set firewall ipv6 name EGRESS rule 20 +set firewall ipv6 name EGRESS rule 20 icmpv6 type-name 'echo-request' +set firewall ipv6 input filter 1 jump-target 'V6-INGRESS' +set firewall ipv6 output filter 1 jump-target 'EGRESS' +set firewall ipv4 input filter 1 jump-target 'INGRESS' +set firewall ipv4 output filter 1 jump-target 'EGRESS' +set firewall ipv4 name IF-TEST rule 10 'disable' +set firewall ipv4 name IF-TEST rule 10 action 'accept' +set firewall ipv4 name IF-TEST rule 10 inbound-interface name 'eth0' +set firewall ipv4 name IF-TEST rule 10 outbound-interface group 'the-ethers' +set firewall ipv4 name IF-TEST rule 10 icmp type-name 'echo-request' +set firewall ipv4 name IF-TEST rule 10 state 'related' diff --git a/tests/unit/modules/network/vyos/fixtures/vyos_interfaces_config.cfg b/tests/unit/modules/network/vyos/fixtures/vyos_interfaces_config.cfg index bed0b01..175a656 100644 --- a/tests/unit/modules/network/vyos/fixtures/vyos_interfaces_config.cfg +++ b/tests/unit/modules/network/vyos/fixtures/vyos_interfaces_config.cfg @@ -3,6 +3,7 @@ set interfaces ethernet eth0 hw-id '08:00:27:7c:85:05' set interfaces ethernet eth1 description 'test-interface' set interfaces ethernet eth2 hw-id '08:00:27:04:85:99' set interfaces ethernet eth3 hw-id '08:00:27:1c:82:d1' +set interfaces ethernet eth3 disable set interfaces ethernet eth3 description 'Ethernet 3' set interfaces wireguard wg02 description 'wire guard int 2' set interfaces loopback 'lo' diff --git a/tests/unit/modules/network/vyos/fixtures/vyos_ospf_interfaces_config_14.cfg b/tests/unit/modules/network/vyos/fixtures/vyos_ospf_interfaces_config_14.cfg new file mode 100644 index 0000000..d630d94 --- /dev/null +++ b/tests/unit/modules/network/vyos/fixtures/vyos_ospf_interfaces_config_14.cfg @@ -0,0 +1,4 @@ +set protocols ospfv3 interface eth0 instance-id '33' +set protocols ospfv3 interface eth0 'mtu-ignore' +set protocols ospf interface eth1 cost '100' +set protocols ospfv3 interface eth1 ifmtu '33' diff --git a/tests/unit/modules/network/vyos/test_vyos_facts.py b/tests/unit/modules/network/vyos/test_vyos_facts.py index dd3a796..7e192e3 100644 --- a/tests/unit/modules/network/vyos/test_vyos_facts.py +++ b/tests/unit/modules/network/vyos/test_vyos_facts.py @@ -54,6 +54,7 @@ class TestVyosFactsModule(TestVyosModule): "network_os_hostname": "vyos01", "network_os_model": "VMware", "network_os_version": "VyOS 1.1.7", + "network_os_major_version": "1.1", }, "network_api": "cliconf", } diff --git a/tests/unit/modules/network/vyos/test_vyos_firewall_global.py b/tests/unit/modules/network/vyos/test_vyos_firewall_global.py index 25c5632..0cc611c 100644 --- a/tests/unit/modules/network/vyos/test_vyos_firewall_global.py +++ b/tests/unit/modules/network/vyos/test_vyos_firewall_global.py @@ -58,6 +58,12 @@ class TestVyosFirewallRulesModule(TestVyosModule): "ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.firewall_global.firewall_global.Firewall_globalFacts.get_device_data", ) + self.mock_get_os_version = patch( + "ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.config.firewall_global.firewall_global.get_os_version" + ) + self.get_os_version = self.mock_get_os_version.start() + self.get_os_version.return_value = "1.2" + self.execute_show_command = self.mock_execute_show_command.start() def tearDown(self): @@ -67,6 +73,7 @@ class TestVyosFirewallRulesModule(TestVyosModule): self.mock_get_config.stop() self.mock_load_config.stop() self.mock_execute_show_command.stop() + self.mock_get_os_version.stop() def load_fixtures(self, commands=None, filename=None): def load_from_file(*args, **kwargs): @@ -89,6 +96,7 @@ class TestVyosFirewallRulesModule(TestVyosModule): connection_type="established", action="accept", log=True, + log_level="emerg", ), dict(connection_type="invalid", action="reject"), ], @@ -358,5 +366,123 @@ class TestVyosFirewallRulesModule(TestVyosModule): def test_vyos_firewall_global_set_01_deleted(self): set_module_args(dict(config=dict(), state="deleted")) - commands = ["delete firewall "] + commands = ["delete firewall"] + self.execute_module(changed=True, commands=commands) + + def test_vyos_firewall_global_set_01_replaced_version(self): + self.get_os_version.return_value = "1.4" + set_module_args( + dict( + config=dict( + validation="strict", + config_trap=True, + log_martians=True, + syn_cookies=True, + twa_hazards_protection=True, + ping=dict(all=True, broadcast=True), + state_policy=[ + dict( + connection_type="established", + action="accept", + log=True, + ), + dict(connection_type="invalid", action="reject"), + ], + route_redirects=[ + dict( + afi="ipv4", + ip_src_route=True, + icmp_redirects=dict(send=True, receive=False), + ), + dict( + afi="ipv6", + ip_src_route=True, + icmp_redirects=dict(receive=False), + ) + ], + group=dict( + address_group=[ + dict( + afi="ipv4", + name="MGMT-HOSTS", + description="This group has the Management hosts address lists", + members=[ + dict(address="192.0.1.1"), + dict(address="192.0.1.3"), + dict(address="192.0.1.5"), + ], + ), + dict( + afi="ipv6", + name="GOOGLE-DNS-v6", + members=[ + dict(address="2001:4860:4860::8888"), + dict(address="2001:4860:4860::8844"), + ], + ), + ], + network_group=[ + dict( + afi="ipv4", + name="MGMT", + description="This group has the Management network addresses", + members=[dict(address="192.0.1.0/24")], + ), + dict( + afi="ipv6", + name="DOCUMENTATION-v6", + description="IPv6 Addresses reserved for documentation per RFC 3849", + members=[ + dict(address="2001:0DB8::/32"), + dict(address="3FFF:FFFF::/32"), + ], + ), + ], + port_group=[ + dict( + name="TELNET", + description="This group has the telnet ports", + members=[dict(port="23")], + ) + ], + ), + ), + state="merged", + ) + ) + commands = [ + "set firewall group address-group MGMT-HOSTS address 192.0.1.1", + "set firewall group address-group MGMT-HOSTS address 192.0.1.3", + "set firewall group address-group MGMT-HOSTS address 192.0.1.5", + "set firewall group address-group MGMT-HOSTS description 'This group has the Management hosts address lists'", + "set firewall group address-group MGMT-HOSTS", + "set firewall group ipv6-address-group GOOGLE-DNS-v6 address 2001:4860:4860::8888", + "set firewall group ipv6-address-group GOOGLE-DNS-v6 address 2001:4860:4860::8844", + "set firewall group ipv6-address-group GOOGLE-DNS-v6", + "set firewall group network-group MGMT network 192.0.1.0/24", + "set firewall group network-group MGMT description 'This group has the Management network addresses'", + "set firewall group network-group MGMT", + "set firewall group ipv6-network-group DOCUMENTATION-v6 network 2001:0DB8::/32", + "set firewall group ipv6-network-group DOCUMENTATION-v6 network 3FFF:FFFF::/32", + "set firewall group ipv6-network-group DOCUMENTATION-v6 description 'IPv6 Addresses reserved for documentation per RFC 3849'", + "set firewall group ipv6-network-group DOCUMENTATION-v6", + "set firewall group port-group TELNET port 23", + "set firewall group port-group TELNET description 'This group has the telnet ports'", + "set firewall group port-group TELNET", + "set firewall global-options ip-src-route 'enable'", + "set firewall global-options receive-redirects 'disable'", + "set firewall global-options send-redirects 'enable'", + "set firewall global-options config-trap 'enable'", + "set firewall global-options ipv6-src-route 'enable'", + "set firewall global-options ipv6-receive-redirects 'disable'", + "set firewall global-options state-policy established action 'accept'", + "set firewall global-options state-policy established log 'enable'", + "set firewall global-options state-policy invalid action 'reject'", + "set firewall global-options broadcast-ping 'enable'", + "set firewall global-options all-ping 'enable'", + "set firewall global-options log-martians 'enable'", + "set firewall global-options twa-hazards-protection 'enable'", + "set firewall global-options syn-cookies 'enable'", + "set firewall global-options source-validation 'strict'", + ] self.execute_module(changed=True, commands=commands) diff --git a/tests/unit/modules/network/vyos/test_vyos_firewall_global14.py b/tests/unit/modules/network/vyos/test_vyos_firewall_global14.py new file mode 100644 index 0000000..c594a1f --- /dev/null +++ b/tests/unit/modules/network/vyos/test_vyos_firewall_global14.py @@ -0,0 +1,460 @@ +# (c) 2016 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +from unittest.mock import patch + +from ansible_collections.vyos.vyos.plugins.modules import vyos_firewall_global +from ansible_collections.vyos.vyos.tests.unit.modules.utils import set_module_args + +from .vyos_module import TestVyosModule, load_fixture + + +class TestVyosFirewallRulesModule14(TestVyosModule): + module = vyos_firewall_global + + def setUp(self): + super(TestVyosFirewallRulesModule14, self).setUp() + self.mock_get_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.get_config", + ) + self.get_config = self.mock_get_config.start() + + self.mock_load_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.load_config", + ) + self.load_config = self.mock_load_config.start() + + self.mock_get_resource_connection_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base.get_resource_connection", + ) + self.get_resource_connection_config = self.mock_get_resource_connection_config.start() + + self.mock_get_resource_connection_facts = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts.get_resource_connection", + ) + self.get_resource_connection_facts = self.mock_get_resource_connection_facts.start() + + self.mock_execute_show_command = patch( + "ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.firewall_global.firewall_global.Firewall_globalFacts.get_device_data", + ) + + self.mock_get_os_version = patch( + "ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.config.firewall_global.firewall_global.get_os_version" + ) + self.get_os_version = self.mock_get_os_version.start() + self.get_os_version.return_value = "1.4" + + self.execute_show_command = self.mock_execute_show_command.start() + self.maxDiff = None + + def tearDown(self): + super(TestVyosFirewallRulesModule14, self).tearDown() + self.mock_get_resource_connection_config.stop() + self.mock_get_resource_connection_facts.stop() + self.mock_get_config.stop() + self.mock_load_config.stop() + self.mock_execute_show_command.stop() + self.mock_get_os_version.stop() + + def load_fixtures(self, commands=None, filename=None): + def load_from_file(*args, **kwargs): + return load_fixture("vyos_firewall_global_config_v14.cfg") + + self.execute_show_command.side_effect = load_from_file + + def test_vyos_firewall_global_set_01_merged(self): + set_module_args( + dict( + config=dict( + validation="strict", + config_trap=True, + log_martians=True, + syn_cookies=True, + twa_hazards_protection=True, + ping=dict(all=True, broadcast=True), + state_policy=[ + dict( + connection_type="established", + action="accept", + log=True, + log_level="emerg", + ), + dict(connection_type="invalid", action="reject"), + ], + route_redirects=[ + dict( + afi="ipv4", + ip_src_route=True, + icmp_redirects=dict(send=True, receive=False), + ), + dict( + afi="ipv6", + ip_src_route=True, + icmp_redirects=dict(receive=False), + ) + ], + group=dict( + address_group=[ + dict( + afi="ipv4", + name="MGMT-HOSTS", + description="This group has the Management hosts address lists", + members=[ + dict(address="192.0.1.1"), + dict(address="192.0.1.3"), + dict(address="192.0.1.5"), + ], + ), + dict( + afi="ipv6", + name="GOOGLE-DNS-v6", + members=[ + dict(address="2001:4860:4860::8888"), + dict(address="2001:4860:4860::8844"), + ], + ), + ], + network_group=[ + dict( + afi="ipv4", + name="MGMT", + description="This group has the Management network addresses", + members=[dict(address="192.0.1.0/24")], + ), + dict( + afi="ipv6", + name="DOCUMENTATION-v6", + description="IPv6 Addresses reserved for documentation per RFC 3849", + members=[ + dict(address="2001:0DB8::/32"), + dict(address="3FFF:FFFF::/32"), + ], + ), + ], + port_group=[ + dict( + name="TELNET", + description="This group has the telnet ports", + members=[dict(port="23")], + ) + ], + ), + ), + state="merged", + ) + ) + commands = [ + "set firewall group address-group MGMT-HOSTS address 192.0.1.1", + "set firewall group address-group MGMT-HOSTS address 192.0.1.3", + "set firewall group address-group MGMT-HOSTS address 192.0.1.5", + "set firewall group address-group MGMT-HOSTS description 'This group has the Management hosts address lists'", + "set firewall group address-group MGMT-HOSTS", + "set firewall group ipv6-address-group GOOGLE-DNS-v6 address 2001:4860:4860::8888", + "set firewall group ipv6-address-group GOOGLE-DNS-v6 address 2001:4860:4860::8844", + "set firewall group ipv6-address-group GOOGLE-DNS-v6", + "set firewall group network-group MGMT network 192.0.1.0/24", + "set firewall group network-group MGMT description 'This group has the Management network addresses'", + "set firewall group network-group MGMT", + "set firewall group ipv6-network-group DOCUMENTATION-v6 network 2001:0DB8::/32", + "set firewall group ipv6-network-group DOCUMENTATION-v6 network 3FFF:FFFF::/32", + "set firewall group ipv6-network-group DOCUMENTATION-v6 description 'IPv6 Addresses reserved for documentation per RFC 3849'", + "set firewall group ipv6-network-group DOCUMENTATION-v6", + "set firewall group port-group TELNET port 23", + "set firewall group port-group TELNET description 'This group has the telnet ports'", + "set firewall group port-group TELNET", + "set firewall global-options ip-src-route 'enable'", + "set firewall global-options receive-redirects 'disable'", + "set firewall global-options send-redirects 'enable'", + "set firewall global-options config-trap 'enable'", + "set firewall global-options ipv6-src-route 'enable'", + "set firewall global-options ipv6-receive-redirects 'disable'", + "set firewall global-options state-policy established action 'accept'", + "set firewall global-options state-policy established log 'enable'", + "set firewall global-options state-policy established log-level 'emerg'", + "set firewall global-options state-policy invalid action 'reject'", + "set firewall global-options broadcast-ping 'enable'", + "set firewall global-options log-martians 'enable'", + "set firewall global-options twa-hazards-protection 'enable'", + "set firewall global-options syn-cookies 'enable'", + "set firewall global-options source-validation 'strict'", + ] + self.execute_module(changed=True, commands=commands) + + def test_vyos_firewall_global_set_01_merged_idem(self): + set_module_args( + dict( + config=dict( + group=dict( + address_group=[ + dict( + afi="ipv4", + name="RND-HOSTS", + description="This group has the Management hosts address lists", + members=[ + dict(address="192.0.2.1"), + dict(address="192.0.2.3"), + dict(address="192.0.2.5"), + ], + ), + dict( + afi="ipv6", + name="LOCAL-v6", + description="This group has the hosts address lists of this machine", + members=[ + dict(address="::1"), + dict(address="fdec:2503:89d6:59b3::1"), + ], + ), + ], + network_group=[ + dict( + afi="ipv4", + name="RND", + description="This group has the Management network addresses", + members=[dict(address="192.0.2.0/24")], + ), + dict( + afi="ipv6", + name="UNIQUE-LOCAL-v6", + description="This group encompasses the ULA address space in IPv6", + members=[dict(address="fc00::/7")], + ), + ], + port_group=[ + dict( + name="SSH", + description="This group has the ssh ports", + members=[dict(port="22")], + ), + ], + ), + ), + state="merged", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_vyos_firewall_global_set_01_replaced(self): + set_module_args( + dict( + config=dict( + state_policy=[ + dict(connection_type="invalid", action="reject"), + ], + group=dict( + address_group=[ + dict( + afi="ipv4", + name="RND-HOSTS", + description="This group has the Management hosts address lists", + members=[ + dict(address="192.0.2.1"), + dict(address="192.0.2.7"), + dict(address="192.0.2.9"), + ], + ), + dict( + afi="ipv6", + name="LOCAL-v6", + description="This group has the hosts address lists of this machine", + members=[ + dict(address="::1"), + dict(address="fdec:2503:89d6:59b3::2"), + ], + ), + ], + network_group=[ + dict( + afi="ipv4", + name="RND", + description="This group has the Management network addresses", + members=[dict(address="192.0.2.0/24")], + ), + dict( + afi="ipv6", + name="UNIQUE-LOCAL-v6", + description="This group encompasses the ULA address space in IPv6", + members=[dict(address="fc00::/7")], + ), + ], + port_group=[ + dict( + name="SSH", + description="This group has the ssh ports", + members=[dict(port="2222")], + ), + ], + ), + ), + state="replaced", + ), + ) + commands = [ + "delete firewall group address-group RND-HOSTS address 192.0.2.3", + "delete firewall group address-group RND-HOSTS address 192.0.2.5", + "delete firewall global-options all-ping", + "delete firewall global-options state-policy related", + "set firewall global-options state-policy invalid action 'reject'", + "set firewall group address-group RND-HOSTS address 192.0.2.7", + "set firewall group address-group RND-HOSTS address 192.0.2.9", + "delete firewall group ipv6-address-group LOCAL-v6 address fdec:2503:89d6:59b3::1", + "set firewall group ipv6-address-group LOCAL-v6 address fdec:2503:89d6:59b3::2", + "delete firewall group port-group SSH port 22", + "set firewall group port-group SSH port 2222", + ] + self.execute_module(changed=True, commands=commands) + + def test_vyos_firewall_global_set_01_replaced_idem(self): + set_module_args( + dict( + config=dict( + ping=dict(all=True), + state_policy=[ + dict(connection_type="related", action="accept", log_level="alert"), + ], + group=dict( + address_group=[ + dict( + afi="ipv4", + name="RND-HOSTS", + description="This group has the Management hosts address lists", + members=[ + dict(address="192.0.2.1"), + dict(address="192.0.2.3"), + dict(address="192.0.2.5"), + ], + ), + dict( + afi="ipv6", + name="LOCAL-v6", + description="This group has the hosts address lists of this machine", + members=[ + dict(address="::1"), + dict(address="fdec:2503:89d6:59b3::1"), + ], + ), + ], + network_group=[ + dict( + afi="ipv4", + name="RND", + description="This group has the Management network addresses", + members=[dict(address="192.0.2.0/24")], + ), + dict( + afi="ipv6", + name="UNIQUE-LOCAL-v6", + description="This group encompasses the ULA address space in IPv6", + members=[dict(address="fc00::/7")], + ), + ], + port_group=[ + dict( + name="SSH", + description="This group has the ssh ports", + members=[dict(port="22")], + ), + ], + ), + ), + state="replaced", + ), + ) + self.execute_module(changed=False, commands=[]) + + def test_vyos_firewall_global_set_02_replaced(self): + set_module_args( + dict( + config=dict( + state_policy=[ + dict(connection_type="invalid", action="reject"), + dict(connection_type="related", action="drop"), + ], + group=dict( + address_group=[ + dict( + afi="ipv4", + name="RND-HOSTS", + description="This group has the Management hosts address lists", + members=[ + dict(address="192.0.2.1"), + dict(address="192.0.2.7"), + dict(address="192.0.2.9"), + ], + ), + dict( + afi="ipv6", + name="LOCAL-v6", + description="This group has the hosts address lists of this machine", + members=[ + dict(address="::1"), + dict(address="fdec:2503:89d6:59b3::2"), + ], + ), + ], + network_group=[ + dict( + afi="ipv4", + name="RND", + description="This group has the Management network addresses", + members=[dict(address="192.0.2.0/24")], + ), + dict( + afi="ipv6", + name="UNIQUE-LOCAL-v6", + description="This group encompasses the ULA address space in IPv6", + members=[dict(address="fc00::/7")], + ), + ], + port_group=[ + dict( + name="SSH", + description="This group has the ssh ports", + members=[dict(port="2222")], + ), + ], + ), + ), + state="replaced", + ), + ) + commands = [ + "delete firewall group address-group RND-HOSTS address 192.0.2.3", + "delete firewall group address-group RND-HOSTS address 192.0.2.5", + "delete firewall global-options all-ping", + "set firewall global-options state-policy related action 'drop'", + "delete firewall global-options state-policy related log-level", + "set firewall global-options state-policy invalid action 'reject'", + "set firewall group address-group RND-HOSTS address 192.0.2.7", + "set firewall group address-group RND-HOSTS address 192.0.2.9", + "delete firewall group ipv6-address-group LOCAL-v6 address fdec:2503:89d6:59b3::1", + "set firewall group ipv6-address-group LOCAL-v6 address fdec:2503:89d6:59b3::2", + "delete firewall group port-group SSH port 22", + "set firewall group port-group SSH port 2222", + ] + self.execute_module(changed=True, commands=commands) + + def test_vyos_firewall_global_set_01_deleted(self): + set_module_args(dict(config=dict(), state="deleted")) + commands = ["delete firewall global-options"] + self.execute_module(changed=True, commands=commands) diff --git a/tests/unit/modules/network/vyos/test_vyos_firewall_rules.py b/tests/unit/modules/network/vyos/test_vyos_firewall_rules.py index b43b11c..c0815bf 100644 --- a/tests/unit/modules/network/vyos/test_vyos_firewall_rules.py +++ b/tests/unit/modules/network/vyos/test_vyos_firewall_rules.py @@ -63,10 +63,10 @@ class TestVyosFirewallRulesModule(TestVyosModule): self.execute_show_command = self.mock_execute_show_command.start() self.mock_get_os_version = patch( - "ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.config.firewall_rules.firewall_rules.Firewall_rules._get_os_version", + "ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.config.firewall_rules.firewall_rules.get_os_version", ) self.get_os_version = self.mock_get_os_version.start() - self.get_os_version.return_value = "Vyos 1.2" + self.get_os_version.return_value = "1.2" def tearDown(self): super(TestVyosFirewallRulesModule, self).tearDown() @@ -374,7 +374,12 @@ class TestVyosFirewallRulesModule(TestVyosModule): weekdays="!Sat,Sun", utc=True, ), - tcp=dict(flags="ALL"), + tcp=dict( + flags=[ + dict(flag="all"), + ] + ), + ), ], ), @@ -416,7 +421,7 @@ class TestVyosFirewallRulesModule(TestVyosModule): description="Rule 101 is configured by Ansible", ipsec="match-ipsec", protocol="icmp", - disabled=True, + disable=True, icmp=dict(type_name="echo-request"), ), ], @@ -566,8 +571,22 @@ class TestVyosFirewallRulesModule(TestVyosModule): weekdays="!Sat,Sun", utc=True, ), - tcp=dict(flags="ALL"), + tcp=dict( + flags=[ + dict(flag="all"), + ] + ), ), + dict( + number="102", + tcp=dict( + flags=[ + dict(flag="ack"), + dict(flag="syn"), + dict(flag="fin", invert=True), + ], + ) + ) ], ), ], @@ -586,6 +605,8 @@ class TestVyosFirewallRulesModule(TestVyosModule): "set firewall ipv6-name INBOUND rule 101 time weekdays !Sat,Sun", "set firewall ipv6-name INBOUND rule 101 time stoptime 13:30:00", "set firewall ipv6-name INBOUND rule 101 time starttime 13:20:00", + "set firewall ipv6-name INBOUND rule 102", + "set firewall ipv6-name INBOUND rule 102 tcp flags ACK,SYN,!FIN", ] self.execute_module(changed=True, commands=commands) @@ -743,14 +764,14 @@ class TestVyosFirewallRulesModule(TestVyosModule): ipsec="match-ipsec", protocol="tcp", fragment="match-frag", - disabled=False, + disable=False, ), dict( number="102", action="accept", description="Rule 102 is configured by Ansible RM", protocol="icmp", - disabled=True, + disable=True, ), ], ), @@ -787,6 +808,7 @@ class TestVyosFirewallRulesModule(TestVyosModule): "set firewall name V4-INGRESS rule 101 protocol 'tcp'", "set firewall name V4-INGRESS rule 101 description 'Rule 101 is configured by Ansible RM'", "set firewall name V4-INGRESS rule 101 action 'reject'", + "delete firewall name V4-INGRESS rule 101 log", "set firewall name V4-INGRESS rule 102 disable", "set firewall name V4-INGRESS rule 102 action 'accept'", "set firewall name V4-INGRESS rule 102 protocol 'icmp'", @@ -817,7 +839,7 @@ class TestVyosFirewallRulesModule(TestVyosModule): ipsec="match-ipsec", protocol="icmp", fragment="match-frag", - disabled=True, + disable=True, ), ], ), @@ -848,6 +870,7 @@ class TestVyosFirewallRulesModule(TestVyosModule): ) commands = [ "delete firewall name V4-INGRESS enable-default-log", + "delete firewall name V4-INGRESS rule 101 log", ] self.execute_module(changed=True, commands=commands) @@ -871,8 +894,9 @@ class TestVyosFirewallRulesModule(TestVyosModule): ipsec="match-ipsec", protocol="icmp", fragment="match-frag", - disabled=True, - ), + disable=True, + log="enable", + ) ], ), dict( @@ -926,7 +950,8 @@ class TestVyosFirewallRulesModule(TestVyosModule): ipsec="match-ipsec", protocol="icmp", fragment="match-frag", - disabled=True, + disable=True, + log="enable" ), ], ), @@ -958,8 +983,8 @@ class TestVyosFirewallRulesModule(TestVyosModule): ipsec="match-ipsec", protocol="icmp", fragment="match-frag", - disabled=True, - ), + disable=True, + ) ], ), dict( @@ -1014,7 +1039,7 @@ class TestVyosFirewallRulesModule(TestVyosModule): log="enable", protocol="tcp", fragment="match-frag", - disabled=False, + disable=False, source=dict( group=dict( address_group="IN-ADDR-GROUP", @@ -1028,7 +1053,7 @@ class TestVyosFirewallRulesModule(TestVyosModule): action="accept", description="Rule 102 is configured by Ansible RM", protocol="icmp", - disabled=True, + disable=True, ), ], ), @@ -1103,8 +1128,9 @@ class TestVyosFirewallRulesModule(TestVyosModule): ipsec="match-ipsec", protocol="icmp", fragment="match-frag", - disabled=True, - ), + disable=True, + log="enable", + ) ], ), dict( @@ -1139,7 +1165,7 @@ class TestVyosFirewallRulesModule(TestVyosModule): self.execute_module(changed=False, commands=[]) def test_vyos_firewall_v6_rule_sets_rule_merged_01_version(self): - self.get_os_version.return_value = "VyOS 1.4-rolling-202007010117" + self.get_os_version.return_value = "1.4" set_module_args( dict( config=[ @@ -1158,8 +1184,16 @@ class TestVyosFirewallRulesModule(TestVyosModule): description="Rule 101 is configured by Ansible", ipsec="match-ipsec", protocol="icmp", - disabled=True, + disable=True, icmp=dict(type_name="echo-request"), + log="enable", + ), + dict( + number="102", + action="reject", + description="Rule 102 is configured by Ansible", + protocol="ipv6-icmp", + icmp=dict(type=7), ), ], ), @@ -1170,15 +1204,503 @@ class TestVyosFirewallRulesModule(TestVyosModule): ), ) commands = [ - "set firewall ipv6-name INBOUND default-action 'accept'", - "set firewall ipv6-name INBOUND description 'This is IPv6 INBOUND rule set'", - "set firewall ipv6-name INBOUND enable-default-log", - "set firewall ipv6-name INBOUND rule 101 protocol 'icmp'", - "set firewall ipv6-name INBOUND rule 101 description 'Rule 101 is configured by Ansible'", - "set firewall ipv6-name INBOUND rule 101", - "set firewall ipv6-name INBOUND rule 101 disable", - "set firewall ipv6-name INBOUND rule 101 action 'accept'", - "set firewall ipv6-name INBOUND rule 101 ipsec 'match-ipsec'", - "set firewall ipv6-name INBOUND rule 101 icmpv6 type-name echo-request", + "set firewall ipv6 name INBOUND default-action 'accept'", + "set firewall ipv6 name INBOUND description 'This is IPv6 INBOUND rule set'", + "set firewall ipv6 name INBOUND default-log", + "set firewall ipv6 name INBOUND rule 101 protocol 'icmp'", + "set firewall ipv6 name INBOUND rule 101 description 'Rule 101 is configured by Ansible'", + "set firewall ipv6 name INBOUND rule 101", + "set firewall ipv6 name INBOUND rule 101 disable", + "set firewall ipv6 name INBOUND rule 101 action 'accept'", + "set firewall ipv6 name INBOUND rule 101 ipsec 'match-ipsec'", + "set firewall ipv6 name INBOUND rule 101 icmpv6 type-name echo-request", + "set firewall ipv6 name INBOUND rule 101 log 'enable'", + "set firewall ipv6 name INBOUND rule 102", + "set firewall ipv6 name INBOUND rule 102 action 'reject'", + "set firewall ipv6 name INBOUND rule 102 description 'Rule 102 is configured by Ansible'", + "set firewall ipv6 name INBOUND rule 102 protocol 'ipv6-icmp'", + 'set firewall ipv6 name INBOUND rule 102 icmpv6 type 7', + ] + self.execute_module(changed=True, commands=commands) + + def test_vyos_firewall_jump_rules_merged_01(self): + self.get_os_version.return_value = "1.4" + set_module_args( + dict( + config=[ + dict( + afi="ipv6", + rule_sets=[ + dict( + name="INBOUND", + description="This is IPv6 INBOUND rule set with a jump action", + default_action="accept", + enable_default_log=True, + rules=[ + dict( + number="101", + action="jump", + description="Rule 101 is configured by Ansible", + ipsec="match-ipsec", + protocol="icmp", + icmp=dict(type_name="echo-request"), + jump_target="PROTECT-RE", + packet_length_exclude=[dict(length=100), dict(length=200)] + ), + dict( + number="102", + action="reject", + description="Rule 102 is configured by Ansible", + protocol="ipv6-icmp", + icmp=dict(type=7), + ), + ], + ), + ], + ) + ], + state="merged", + ) + ) + commands = [ + "set firewall ipv6 name INBOUND default-action 'accept'", + "set firewall ipv6 name INBOUND description 'This is IPv6 INBOUND rule set with a jump action'", + "set firewall ipv6 name INBOUND default-log", + "set firewall ipv6 name INBOUND rule 101 protocol 'icmp'", + "set firewall ipv6 name INBOUND rule 101 packet-length-exclude 100", + "set firewall ipv6 name INBOUND rule 101 packet-length-exclude 200", + "set firewall ipv6 name INBOUND rule 101 description 'Rule 101 is configured by Ansible'", + "set firewall ipv6 name INBOUND rule 101", + "set firewall ipv6 name INBOUND rule 101 ipsec 'match-ipsec'", + "set firewall ipv6 name INBOUND rule 101 icmpv6 type-name echo-request", + "set firewall ipv6 name INBOUND rule 101 action 'jump'", + "set firewall ipv6 name INBOUND rule 101 jump-target 'PROTECT-RE'", + "set firewall ipv6 name INBOUND rule 102", + "set firewall ipv6 name INBOUND rule 102 action 'reject'", + "set firewall ipv6 name INBOUND rule 102 description 'Rule 102 is configured by Ansible'", + "set firewall ipv6 name INBOUND rule 102 protocol 'ipv6-icmp'", + 'set firewall ipv6 name INBOUND rule 102 icmpv6 type 7', + ] + self.execute_module(changed=True, commands=commands) + + +class TestVyosFirewallRulesModule14(TestVyosModule): + module = vyos_firewall_rules + + def setUp(self): + super(TestVyosFirewallRulesModule14, self).setUp() + self.mock_get_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.get_config" + ) + self.get_config = self.mock_get_config.start() + + self.mock_load_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.load_config" + ) + self.load_config = self.mock_load_config.start() + + self.mock_get_resource_connection_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base.get_resource_connection" + ) + self.get_resource_connection_config = self.mock_get_resource_connection_config.start() + + self.mock_get_resource_connection_facts = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts.get_resource_connection" + ) + self.get_resource_connection_facts = self.mock_get_resource_connection_facts.start() + self.mock_execute_show_command = patch( + "ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.static_routes.static_routes.Static_routesFacts.get_device_data" + ) + + self.mock_execute_show_command = patch( + "ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.firewall_rules.firewall_rules.Firewall_rulesFacts.get_device_data" + ) + self.execute_show_command = self.mock_execute_show_command.start() + + self.mock_get_os_version = patch( + "ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.config.firewall_rules.firewall_rules.get_os_version" + ) + self.get_os_version = self.mock_get_os_version.start() + self.get_os_version.return_value = "1.4" + self.maxDiff = None + + def tearDown(self): + super(TestVyosFirewallRulesModule14, self).tearDown() + self.mock_get_resource_connection_config.stop() + self.mock_get_resource_connection_facts.stop() + self.mock_get_config.stop() + self.mock_load_config.stop() + self.mock_execute_show_command.stop() + self.mock_get_os_version.stop() + + def load_fixtures(self, commands=None, filename=None): + def load_from_file(*args, **kwargs): + return load_fixture("vyos_firewall_rules_config_v14.cfg") + + self.execute_show_command.side_effect = load_from_file + + def test_vyos_firewall_packet_length_merged_01(self): + set_module_args( + dict( + config=[ + dict( + afi="ipv6", + rule_sets=[ + dict( + name="INBOUND", + description="This is IPv6 INBOUND rule set with a jump action", + default_action="accept", + enable_default_log=True, + rules=[ + dict( + number="101", + action="jump", + description="Rule 101 is configured by Ansible", + jump_target="PROTECT-RE", + packet_length_exclude=[dict(length=100), dict(length=200)], + packet_length=[dict(length=22)] + ), + ], + ), + ], + ) + ], + state="merged", + ) + ) + commands = [ + "set firewall ipv6 name INBOUND default-action 'accept'", + "set firewall ipv6 name INBOUND description 'This is IPv6 INBOUND rule set with a jump action'", + "set firewall ipv6 name INBOUND default-log", + "set firewall ipv6 name INBOUND rule 101 packet-length-exclude 100", + "set firewall ipv6 name INBOUND rule 101 packet-length-exclude 200", + "set firewall ipv6 name INBOUND rule 101 packet-length 22", + "set firewall ipv6 name INBOUND rule 101 description 'Rule 101 is configured by Ansible'", + "set firewall ipv6 name INBOUND rule 101", + "set firewall ipv6 name INBOUND rule 101 action 'jump'", + "set firewall ipv6 name INBOUND rule 101 jump-target 'PROTECT-RE'", + ] + self.maxDiff = None + self.execute_module(changed=True, commands=commands) + + def test_vyos_firewall_packet_length_replace_01(self): + set_module_args( + dict( + config=[ + dict( + afi="ipv4", + rule_sets=[ + dict( + name="V4-INGRESS", + description="This is IPv4 V4-INGRESS rule set", + default_action="accept", + enable_default_log=True, + rules=[ + dict( + number="101", + action="accept", + description="Rule 101 is configured by Ansible", + packet_length_exclude=[dict(length=100), dict(length=200)], + packet_length=[dict(length=22)] + ), + ], + ), + ], + ) + ], + state="replaced", + ) + ) + commands = [ + "delete firewall ipv4 name V4-INGRESS rule 101 protocol", + "delete firewall ipv4 name V4-INGRESS rule 101 disable", + "delete firewall ipv4 name V4-INGRESS rule 101 packet-length-exclude 300", + "set firewall ipv4 name V4-INGRESS rule 101 packet-length-exclude 200", + "set firewall ipv4 name V4-INGRESS rule 101 packet-length 22", + ] + self.maxDiff = None + self.execute_module(changed=True, commands=commands) + + def test_vyos_firewall_filter_merged_01(self): + set_module_args( + dict( + config=[ + dict( + afi="ipv6", + rule_sets=[ + dict( + filter="input", + description="This is IPv6 INBOUND rule set with a jump action", + default_action="accept", + enable_default_log=True, + rules=[ + dict( + number="101", + action="jump", + description="Rule 101 is configured by Ansible", + jump_target="PROTECT-RE", + packet_length_exclude=[dict(length=100), dict(length=200)], + packet_length=[dict(length=22)] + ), + ], + ), + ], + ) + ], + state="merged", + ) + ) + commands = [ + "set firewall ipv6 input filter default-action 'accept'", + "set firewall ipv6 input filter description 'This is IPv6 INBOUND rule set with a jump action'", + "set firewall ipv6 input filter default-log", + "set firewall ipv6 input filter rule 101 packet-length-exclude 100", + "set firewall ipv6 input filter rule 101 packet-length-exclude 200", + "set firewall ipv6 input filter rule 101 packet-length 22", + "set firewall ipv6 input filter rule 101 description 'Rule 101 is configured by Ansible'", + "set firewall ipv6 input filter rule 101", + "set firewall ipv6 input filter rule 101 action 'jump'", + "set firewall ipv6 input filter rule 101 jump-target 'PROTECT-RE'", + ] + self.maxDiff = None + self.execute_module(changed=True, commands=commands) + + def test_vyos_firewall_interface_merged_01(self): + set_module_args( + dict( + config=[ + dict( + afi="ipv6", + rule_sets=[ + dict( + name="V6-INGRESS", + description="This is IPv6 INBOUND rule set with a jump action", + default_action="accept", + rules=[ + dict( + number="101", + action="jump", + description="Rule 101 is configured by Ansible", + jump_target="PROTECT-RE", + inbound_interface=dict(name="eth0"), + outbound_interface=dict(group="eth1"), + ), + ], + ), + ], + ) + ], + state="merged", + ) + ) + commands = [ + "set firewall ipv6 name V6-INGRESS description 'This is IPv6 INBOUND rule set with a jump action'", + "set firewall ipv6 name V6-INGRESS rule 101 inbound-interface name eth0", + "set firewall ipv6 name V6-INGRESS rule 101 outbound-interface group eth1", + "set firewall ipv6 name V6-INGRESS rule 101 description 'Rule 101 is configured by Ansible'", + "set firewall ipv6 name V6-INGRESS rule 101", + "set firewall ipv6 name V6-INGRESS rule 101 action 'jump'", + "set firewall ipv6 name V6-INGRESS rule 101 jump-target 'PROTECT-RE'", + ] + self.maxDiff = None + self.execute_module(changed=True, commands=commands) + + def test_vyos_firewall_interface_replace_02(self): + set_module_args( + dict( + config=[ + dict( + afi="ipv4", + rule_sets=[ + dict( + name="IF-TEST", + description="Changed", + rules=[ + dict( + number="10", + action="accept", + description="Rule 10 is configured by Ansible", + inbound_interface=dict(name="eth1"), + ), + ], + ), + ], + ) + ], + state="replaced", + ) + ) + commands = [ + "set firewall ipv4 name IF-TEST description 'Changed'", + "set firewall ipv4 name IF-TEST rule 10 description 'Rule 10 is configured by Ansible'", + 'set firewall ipv4 name IF-TEST rule 10 inbound-interface name eth1', + "delete firewall ipv4 name IF-TEST rule 10 outbound-interface group", + "delete firewall ipv4 name IF-TEST rule 10 disable", + "delete firewall ipv4 name IF-TEST rule 10 state related", + "delete firewall ipv4 name IF-TEST rule 10 icmp type-name echo-request", + ] + self.maxDiff = None + self.execute_module(changed=True, commands=commands) + + def test_vyos_firewall_v4_rule_sets_rule_merged_02(self): + set_module_args( + dict( + config=[ + dict( + afi="ipv4", + rule_sets=[ + dict( + name="INBOUND", + rules=[ + dict( + number="101", + protocol="tcp", + source=dict( + address="192.0.2.0", + mac_address="38:00:25:19:76:0c", + port=2127, + ), + destination=dict(address="192.0.1.0", port=2124), + limit=dict( + burst=10, + rate=dict(number=20, unit="second"), + ), + recent=dict(count=10, time=20), + state=dict( + established=True, + related=True, + invalid=True, + new=True, + ), + ), + ], + ), + ], + ), + ], + state="merged", + ), + ) + commands = [ + "set firewall ipv4 name INBOUND rule 101 protocol 'tcp'", + "set firewall ipv4 name INBOUND rule 101 destination port 2124", + "set firewall ipv4 name INBOUND rule 101", + "set firewall ipv4 name INBOUND rule 101 destination address 192.0.1.0", + "set firewall ipv4 name INBOUND rule 101 source address 192.0.2.0", + "set firewall ipv4 name INBOUND rule 101 source mac-address 38:00:25:19:76:0c", + "set firewall ipv4 name INBOUND rule 101 source port 2127", + "set firewall ipv4 name INBOUND rule 101 state new", + "set firewall ipv4 name INBOUND rule 101 state invalid", + "set firewall ipv4 name INBOUND rule 101 state related", + "set firewall ipv4 name INBOUND rule 101 state established", + "set firewall ipv4 name INBOUND rule 101 limit burst 10", + "set firewall ipv4 name INBOUND rule 101 limit rate 20/second", + "set firewall ipv4 name INBOUND rule 101 recent count 10", + "set firewall ipv4 name INBOUND rule 101 recent time 20", + ] + self.execute_module(changed=True, commands=commands) + + def test_vyos_firewall_v4_rule_sets_change_state_01(self): + set_module_args( + dict( + config=[ + dict( + afi="ipv4", + rule_sets=[ + dict( + name="IF-TEST", + rules=[ + dict( + number="10", + disable=False, + action="accept", + state=dict( + established=True, + new=True, + ), + ), + ], + ), + ], + ), + ], + state="replaced", + ), + ) + commands = [ + "delete firewall ipv4 name IF-TEST rule 10 disable", + "delete firewall ipv4 name IF-TEST rule 10 inbound-interface name", + "delete firewall ipv4 name IF-TEST rule 10 icmp type-name echo-request", + "delete firewall ipv4 name IF-TEST rule 10 outbound-interface group", + "delete firewall ipv4 name IF-TEST rule 10 state related", + "set firewall ipv4 name IF-TEST rule 10 state established", + "set firewall ipv4 name IF-TEST rule 10 state new", + ] + self.execute_module(changed=True, commands=commands) + + def test_vyos_firewall_v4v6_rule_sets_del_03(self): + set_module_args(dict(config=[], state="deleted")) + commands = ["delete firewall ipv4", "delete firewall ipv6"] + self.execute_module(changed=True, commands=commands) + + def test_vyos_firewall_v6_rule_sets_rule_merged_04(self): + set_module_args( + dict( + config=[ + dict( + afi="ipv6", + rule_sets=[ + dict( + name="INBOUND", + rules=[ + dict( + number="101", + time=dict( + monthdays="2", + startdate="2020-01-24", + starttime="13:20:00", + stopdate="2020-01-28", + stoptime="13:30:00", + weekdays="!Sat,Sun", + utc=True, + ), + tcp=dict( + flags=[ + dict(flag="all"), + ] + ), + ), + dict( + number="102", + tcp=dict( + flags=[ + dict(flag="ack"), + dict(flag="syn"), + dict(flag="fin", invert=True), + ], + ) + ) + ], + ), + ], + ), + ], + state="merged", + ), + ) + commands = [ + "set firewall ipv6 name INBOUND rule 101", + "set firewall ipv6 name INBOUND rule 101 tcp flags all", + "set firewall ipv6 name INBOUND rule 101 time utc", + "set firewall ipv6 name INBOUND rule 101 time monthdays 2", + "set firewall ipv6 name INBOUND rule 101 time startdate 2020-01-24", + "set firewall ipv6 name INBOUND rule 101 time stopdate 2020-01-28", + "set firewall ipv6 name INBOUND rule 101 time weekdays !Sat,Sun", + "set firewall ipv6 name INBOUND rule 101 time stoptime 13:30:00", + "set firewall ipv6 name INBOUND rule 101 time starttime 13:20:00", + "set firewall ipv6 name INBOUND rule 102", + "set firewall ipv6 name INBOUND rule 102 tcp flags ack", + "set firewall ipv6 name INBOUND rule 102 tcp flags not fin", + "set firewall ipv6 name INBOUND rule 102 tcp flags syn", ] self.execute_module(changed=True, commands=commands) diff --git a/tests/unit/modules/network/vyos/test_vyos_interfaces.py b/tests/unit/modules/network/vyos/test_vyos_interfaces.py index affb4f8..14e49c3 100644 --- a/tests/unit/modules/network/vyos/test_vyos_interfaces.py +++ b/tests/unit/modules/network/vyos/test_vyos_interfaces.py @@ -183,5 +183,40 @@ class TestVyosFirewallInterfacesModule(TestVyosModule): "set interfaces ethernet eth4 speed 'auto'", "delete interfaces wireguard wg02 description", "delete interfaces ethernet eth3 description", + "delete interfaces ethernet eth3 disable", ] self.execute_module(changed=True, commands=commands) + + def test_vyos_interfaces_idempotent_disable(self): + set_module_args( + dict( + config=[ + dict( + name="eth3", + description="Ethernet 3", + enabled=False, + ), + ], + state="merged", + ) + ) + + commands = [] + self.execute_module(changed=False, commands=commands) + + def test_vyos_interfaces_idempotent_disable_replace(self): + set_module_args( + dict( + config=[ + dict( + name="eth3", + description="Ethernet 3", + enabled=False, + ), + ], + state="replaced", + ) + ) + + commands = [] + self.execute_module(changed=False, commands=commands) diff --git a/tests/unit/modules/network/vyos/test_vyos_logging_global.py b/tests/unit/modules/network/vyos/test_vyos_logging_global.py index 872769e..a675151 100644 --- a/tests/unit/modules/network/vyos/test_vyos_logging_global.py +++ b/tests/unit/modules/network/vyos/test_vyos_logging_global.py @@ -386,7 +386,6 @@ class TestVyosLoggingGlobalModule(TestVyosModule): playbook["state"] = "overridden" set_module_args(playbook) result = self.execute_module(changed=True) - print(result["commands"]) self.maxDiff = None self.assertEqual(sorted(result["commands"]), sorted(compare_cmds)) diff --git a/tests/unit/modules/network/vyos/test_vyos_ospf_interfaces.py b/tests/unit/modules/network/vyos/test_vyos_ospf_interfaces.py index 1d12a3c..c7d69d0 100644 --- a/tests/unit/modules/network/vyos/test_vyos_ospf_interfaces.py +++ b/tests/unit/modules/network/vyos/test_vyos_ospf_interfaces.py @@ -43,11 +43,25 @@ class TestVyosOspfInterfacesModule(TestVyosModule): "ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.ospf_interfaces.ospf_interfaces.Ospf_interfacesFacts.get_device_data", ) self.execute_show_command = self.mock_execute_show_command.start() + self.mock_get_os_version = patch( + "ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.config.ospf_interfaces.ospf_interfaces.get_os_version" + ) + self.test_version = "1.2" + self.get_os_version = self.mock_get_os_version.start() + self.get_os_version.return_value = self.test_version + self.mock_facts_get_os_version = patch( + "ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.ospf_interfaces.ospf_interfaces.get_os_version" + ) + self.get_facts_os_version = self.mock_facts_get_os_version.start() + self.get_facts_os_version.return_value = self.test_version + self.maxDiff = None def tearDown(self): super(TestVyosOspfInterfacesModule, self).tearDown() self.mock_get_resource_connection_config.stop() self.mock_execute_show_command.stop() + self.mock_get_os_version.stop() + self.mock_facts_get_os_version.stop() def load_fixtures(self, commands=None, filename=None): if filename is None: diff --git a/tests/unit/modules/network/vyos/test_vyos_ospf_interfaces14.py b/tests/unit/modules/network/vyos/test_vyos_ospf_interfaces14.py new file mode 100644 index 0000000..ef27860 --- /dev/null +++ b/tests/unit/modules/network/vyos/test_vyos_ospf_interfaces14.py @@ -0,0 +1,511 @@ +# Spawned from test_vyos_ospf_interfaces (c) 2016 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +from unittest.mock import patch + +from ansible_collections.vyos.vyos.plugins.modules import vyos_ospf_interfaces +from ansible_collections.vyos.vyos.tests.unit.modules.utils import set_module_args + +from .vyos_module import TestVyosModule, load_fixture + + +class TestVyosOspfInterfacesModule14(TestVyosModule): + module = vyos_ospf_interfaces + + def setUp(self): + super(TestVyosOspfInterfacesModule14, self).setUp() + self.mock_get_resource_connection_config = patch( + "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module_base.get_resource_connection" + ) + self.get_resource_connection_config = self.mock_get_resource_connection_config.start() + + self.mock_execute_show_command = patch( + "ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.ospf_interfaces.ospf_interfaces.Ospf_interfacesFacts.get_device_data" + ) + self.execute_show_command = self.mock_execute_show_command.start() + self.mock_get_os_version = patch( + "ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.config.ospf_interfaces.ospf_interfaces.get_os_version" + ) + self.test_version = "1.4" + self.get_os_version = self.mock_get_os_version.start() + self.get_os_version.return_value = self.test_version + self.mock_facts_get_os_version = patch( + "ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.ospf_interfaces.ospf_interfaces.get_os_version" + ) + self.get_facts_os_version = self.mock_facts_get_os_version.start() + self.get_facts_os_version.return_value = self.test_version + self.maxDiff = None + + def tearDown(self): + super(TestVyosOspfInterfacesModule14, self).tearDown() + self.mock_get_resource_connection_config.stop() + self.mock_execute_show_command.stop() + self.mock_get_os_version.stop() + + def load_fixtures(self, commands=None, filename=None): + if filename is None: + filename = "vyos_ospf_interfaces_config_14.cfg" + + def load_from_file(*args, **kwargs): + output = load_fixture(filename) + return output + + self.execute_show_command.side_effect = load_from_file + + def sort_address_family(self, entry_list): + for entry in entry_list: + if entry.get("address_family"): + entry["address_family"].sort(key=lambda i: i.get("afi")) + + def test_vyos_ospf_interfaces_merged_new_config(self): + set_module_args( + dict( + config=[ + dict( + name="eth0", + address_family=[ + dict( + afi="ipv4", + cost=100, + authentication=dict(plaintext_password="abcdefg!"), + priority=55, + ), + dict(afi="ipv6", mtu_ignore=True, instance=20), + ], + ), + dict( + name="bond2", + address_family=[ + dict( + afi="ipv4", + transmit_delay=9, + ), + dict(afi="ipv6", passive=True), + ], + ), + ], + state="merged", + ) + ) + commands = [ + "set protocols ospf interface bond2 transmit-delay 9", + "set protocols ospfv3 interface bond2 passive", + "set protocols ospf interface eth0 cost 100", + "set protocols ospf interface eth0 priority 55", + "set protocols ospf interface eth0 authentication plaintext-password abcdefg!", + "set protocols ospfv3 interface eth0 instance-id 20", + ] + self.execute_module(changed=True, commands=commands) + + def test_vyos_ospf_interfaces_merged_idempotent(self): + set_module_args( + dict( + config=[ + dict( + name="eth0", + address_family=[ + dict(afi="ipv6", mtu_ignore=True, instance=33), + ], + ), + dict( + name="eth1", + address_family=[ + dict( + afi="ipv4", + cost=100, + ), + dict(afi="ipv6", ifmtu=33), + ], + ), + ], + ) + ) + self.execute_module(changed=False, commands=[]) + + def test_vyos_ospf_interfaces_existing_config_merged(self): + set_module_args( + dict( + config=[ + dict( + name="eth0", + address_family=[ + dict(afi="ipv6", cost=500), + ], + ), + dict( + name="eth1", + address_family=[ + dict( + afi="ipv4", + priority=100, + ), + dict(afi="ipv6", ifmtu=25), + ], + ), + ], + ) + ) + commands = [ + "set protocols ospfv3 interface eth0 cost 500", + "set protocols ospf interface eth1 priority 100", + "set protocols ospfv3 interface eth1 ifmtu 25", + ] + self.execute_module(changed=True, commands=commands) + + def test_vyos_ospf_interfaces_replaced(self): + set_module_args( + dict( + config=[ + dict( + name="eth0", + address_family=[ + dict( + afi="ipv4", + cost=100, + authentication=dict(plaintext_password="abcdefg!"), + priority=55, + ), + ], + ), + dict( + name="bond2", + address_family=[ + dict( + afi="ipv4", + transmit_delay=9, + ), + dict(afi="ipv6", passive=True), + ], + ), + ], + state="replaced", + ) + ) + commands = [ + "set protocols ospf interface bond2 transmit-delay 9", + "set protocols ospfv3 interface bond2 passive", + "set protocols ospf interface eth0 cost 100", + "set protocols ospf interface eth0 priority 55", + "set protocols ospf interface eth0 authentication plaintext-password abcdefg!", + "delete protocols ospfv3 interface eth0 instance-id 33", + "delete protocols ospfv3 interface eth0 mtu-ignore", + ] + self.execute_module(changed=True, commands=commands) + + def test_vyos_ospf_passive_interfaces_replaced(self): + set_module_args( + dict( + config=[ + dict( + name="eth0", + address_family=[ + dict( + afi="ipv4", + passive=True, + ), + ], + ), + dict( + name="eth1", + address_family=[ + dict( + afi="ipv4", + passive=True, + ), + dict( + afi="ipv6", + passive=True, + ), + ], + ), + dict( + name="bond2", + address_family=[ + dict( + afi="ipv4", + passive=True, + ), + dict(afi="ipv6", passive=True), + ], + ), + ], + state="replaced", + ) + ) + commands = [ + "delete protocols ospf interface eth1 cost 100", + "delete protocols ospfv3 interface eth0 instance-id 33", + "delete protocols ospfv3 interface eth0 mtu-ignore", + "delete protocols ospfv3 interface eth1 ifmtu 33", + "set protocols ospf interface bond2 passive", + "set protocols ospfv3 interface bond2 passive", + "set protocols ospf interface eth0 passive", + "set protocols ospf interface eth1 passive", + "set protocols ospfv3 interface eth1 passive", + ] + self.maxDiff = None + self.execute_module(changed=True, commands=commands) + + def test_vyos_ospf_interfaces_replaced_idempotent(self): + set_module_args( + dict( + config=[ + dict( + name="eth0", + address_family=[ + dict(afi="ipv6", mtu_ignore=True, instance=33), + ], + ), + dict( + name="eth1", + address_family=[ + dict( + afi="ipv4", + cost=100, + ), + dict(afi="ipv6", ifmtu=33), + ], + ), + ], + state="replaced", + ) + ) + self.execute_module(changed=False, commands=[]) + + def test_vyos_ospf_interfaces_overridden(self): + set_module_args( + dict( + config=[ + dict( + name="eth0", + address_family=[ + dict( + afi="ipv4", + cost=100, + authentication=dict(plaintext_password="abcdefg!"), + priority=55, + ), + ], + ), + dict( + name="bond2", + address_family=[ + dict( + afi="ipv4", + transmit_delay=9, + ), + dict(afi="ipv6", passive=True), + ], + ), + ], + state="overridden", + ) + ) + commands = [ + "set protocols ospf interface bond2 transmit-delay 9", + "set protocols ospfv3 interface bond2 passive", + "set protocols ospf interface eth0 cost 100", + "set protocols ospf interface eth0 priority 55", + "set protocols ospf interface eth0 authentication plaintext-password abcdefg!", + "delete protocols ospf interface eth1", + "delete protocols ospfv3 interface eth1", + "delete protocols ospfv3 interface eth0 mtu-ignore", + "delete protocols ospfv3 interface eth0 instance-id 33", + ] + self.execute_module(changed=True, commands=commands) + + def test_vyos_ospf_interfaces_overridden_idempotent(self): + set_module_args( + dict( + config=[ + dict( + name="eth0", + address_family=[ + dict(afi="ipv6", mtu_ignore=True, instance=33), + ], + ), + dict( + name="eth1", + address_family=[ + dict( + afi="ipv4", + cost=100, + ), + dict(afi="ipv6", ifmtu=33), + ], + ), + ], + state="overridden", + ) + ) + self.execute_module(changed=False, commands=[]) + + def test_vyos_ospf_interfaces_deleted(self): + set_module_args( + dict( + config=[ + dict( + name="eth0", + ), + ], + state="deleted", + ) + ) + commands = ["delete protocols ospfv3 interface eth0"] + self.execute_module(changed=True, commands=commands) + + def test_vyos_ospf_interfaces_notpresent_deleted(self): + set_module_args( + dict( + config=[ + dict( + name="eth3", + ), + ], + state="deleted", + ) + ) + self.execute_module(changed=False, commands=[]) + + def test_vyos_ospf_interfaces_rendered(self): + set_module_args( + dict( + config=[ + dict( + name="eth0", + address_family=[ + dict( + afi="ipv4", + cost=100, + authentication=dict(plaintext_password="abcdefg!"), + priority=55, + ), + dict(afi="ipv6", mtu_ignore=True, instance=20), + ], + ), + dict( + name="bond2", + address_family=[ + dict( + afi="ipv4", + transmit_delay=9, + ), + dict(afi="ipv6", passive=True), + ], + ), + ], + state="rendered", + ) + ) + commands = [ + "set protocols ospf interface eth0 cost 100", + "set protocols ospf interface eth0 authentication plaintext-password abcdefg!", + "set protocols ospf interface eth0 priority 55", + "set protocols ospfv3 interface eth0 mtu-ignore", + "set protocols ospfv3 interface eth0 instance-id 20", + "set protocols ospf interface bond2 transmit-delay 9", + "set protocols ospfv3 interface bond2 passive", + ] + result = self.execute_module(changed=False) + self.assertEqual(sorted(result["rendered"]), sorted(commands), result["rendered"]) + + def test_vyos_ospf_interfaces_parsed(self): + commands = [ + "set protocols ospf interface bond2 authentication md5 key-id 10 md5-key '1111111111232345'", + "set protocols ospf interface bond2 bandwidth '70'", + "set protocols ospf interface bond2 transmit-delay '45'", + "set protocols ospfv3 interface bond2 'passive'", + "set protocols ospf interface eth0 cost '50'", + "set protocols ospf interface eth0 priority '26'", + "set protocols ospfv3 interface eth0 instance-id '33'", + "set protocols ospfv3 interface eth0 'mtu-ignore'", + "set protocols ospf interface eth1 network 'point-to-point'", + "set protocols ospf interface eth1 priority '26'", + "set protocols ospf interface eth1 transmit-delay '50'", + "set protocols ospfv3 interface eth1 dead-interval '39'", + ] + + parsed_str = "\n".join(commands) + set_module_args(dict(running_config=parsed_str, state="parsed")) + result = self.execute_module(changed=False) + parsed_list = [ + { + "address_family": [ + { + "afi": "ipv4", + "authentication": { + "md5_key": { + "key": "1111111111232345", + "key_id": 10, + } + }, + "bandwidth": 70, + "transmit_delay": 45, + }, + {"afi": "ipv6", "passive": True}, + ], + "name": "bond2", + }, + { + "address_family": [ + {"afi": "ipv4", "cost": 50, "priority": 26}, + {"afi": "ipv6", "instance": "33", "mtu_ignore": True}, + ], + "name": "eth0", + }, + { + "address_family": [ + { + "afi": "ipv4", + "network": "point-to-point", + "priority": 26, + "transmit_delay": 50, + }, + {"afi": "ipv6", "dead_interval": 39}, + ], + "name": "eth1", + }, + ] + result_list = self.sort_address_family(result["parsed"]) + given_list = self.sort_address_family(parsed_list) + self.assertEqual(result_list, given_list) + + def test_vyos_ospf_interfaces_gathered(self): + set_module_args(dict(state="gathered")) + result = self.execute_module(changed=False, filename="vyos_ospf_interfaces_config.cfg") + gathered_list = [ + { + "address_family": [{"afi": "ipv6", "instance": "33", "mtu_ignore": True}], + "name": "eth0", + }, + { + "address_family": [ + {"afi": "ipv4", "cost": 100}, + {"afi": "ipv6", "ifmtu": 33}, + ], + "name": "eth1", + }, + ] + + result_list = self.sort_address_family(result["gathered"]) + given_list = self.sort_address_family(gathered_list) + self.assertEqual(result_list, given_list) |