diff --git a/plugins/module_utils/network/vyos/config/vrf/vrf.py b/plugins/module_utils/network/vyos/config/vrf/vrf.py index 58366034..2adf5bf4 100644 --- a/plugins/module_utils/network/vyos/config/vrf/vrf.py +++ b/plugins/module_utils/network/vyos/config/vrf/vrf.py @@ -1,239 +1,242 @@ # # -*- coding: utf-8 -*- # Copyright 2021 Red Hat # GNU General Public License v3.0+ # (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # from __future__ import absolute_import, division, print_function __metaclass__ = type """ The vyos_vrf config file. It is in this file where the current configuration (as dict) is compared to the provided configuration (as dict) and the command set necessary to bring the current configuration to its desired end-state is created. """ from copy import deepcopy from ansible.module_utils.six import iteritems from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module import ( ResourceModule, ) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.facts import Facts from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.rm_templates.vrf import ( VrfTemplate, ) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.utils.utils import combine from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.utils.version import ( LooseVersion, ) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import get_os_version # from ansible.plugins.filter.core import combine class Vrf(ResourceModule): """ The vyos_vrf config class """ def __init__(self, module): super(Vrf, self).__init__( empty_fact_val={}, facts_module=Facts(module), module=module, resource="vrf", tmplt=VrfTemplate(), ) self.parsers = [ "bind_to_all", ] def _validate_template(self): version = get_os_version(self._module) if LooseVersion(version) >= LooseVersion("1.4"): self._tmplt = VrfTemplate() else: self._module.fail_json(msg="VRF is not supported in this version of VyOS") def parse(self): """override parse to check template""" self._validate_template() return super().parse() def get_parser(self, name): """get_parsers""" self._validate_template() return super().get_parser(name) def execute_module(self): """Execute the module :rtype: A dictionary :returns: The result from module execution """ if self.state not in ["parsed", "gathered"]: self.generate_commands() self.run_commands() return self.result def generate_commands(self): """Generate configuration commands to send based on want, have and desired state. """ wantd = {} haved = {} wantd = deepcopy(self.want) haved = deepcopy(self.have) # self._module.fail_json(msg="WanT: " + str(self.want) + "**** H: " + str(self.have)) # if state is merged, merge want onto have and then compare if self.state in ["merged", "replaced"]: # wantd = dict_merge(wantd, haved) # wantd = haved | combine(wantd, recursive=True) wantd = combine(haved, wantd, recursive=True) # self._module.fail_json(msg="Want: " + str(wantd) + "**** H: " + str(haved)) # if state is deleted, delete and empty out wantd if self.state == "deleted": w = deepcopy(wantd) + if w == {}: + self.commands.append("delete vrf") + return for k, want in iteritems(w): if not (k in haved and haved[k]): del wantd[k] else: if isinstance(want, list): for entry in want: wname = entry.get("name") haved["instances"] = [ i for i in haved.get("instances", []) if i.get("name") != wname ] self.commands.append("delete vrf name {}".format(wname)) else: self.commands.append("delete vrf {}".format(k.replace("_", "-"))) del wantd[k] if self.state == "overridden": w = deepcopy(wantd) h = deepcopy(haved) for k, want in iteritems(w): if k in haved and haved[k] != want: if isinstance(want, list): for entry in want: wname = entry.get("name") hdict = next( (inst for inst in haved["instances"] if inst["name"] == wname), None, ) if entry != hdict: haved["instances"] = [ i for i in haved.get("instances", []) if i.get("name") != wname ] self.commands.append("delete vrf name {}".format(wname)) self.commands.append("commit") for k, want in iteritems(wantd): if isinstance(want, list): self._compare_instances(want=want, have=haved.pop(k, {})) self.compare( parsers=self.parsers, want={k: want}, have={k: haved.pop(k, {})}, ) # self._module.fail_json(msg=self.commands) def _compare_instances(self, want, have): """Compare the instances of the VRF""" parsers = [ "table_id", "vni", "description", "disable_vrf", ] # self._module.fail_json(msg="want: " + str(want) + "**** have: " + str(have)) for entry in want: h = {} wname = entry.get("name") # h = next((vrf for vrf in have if vrf["name"] == wname), {}) h = { k: v for vrf in have if vrf.get("name") == wname for k, v in vrf.items() if k != "address_family" } self.compare(parsers=parsers, want=entry, have=h) if "address_family" in entry: wafi = {"name": wname, "address_family": entry.get("address_family", [])} # hdict = next((item for item in have if item["name"] == wname), None) hdict = next((d for d in have if d.get("name") == wname), None) hafi = { "name": (hdict or {"name": wname})["name"], "address_family": hdict.get("address_family", []) if hdict else [], } # self._module.fail_json(msg="wafi: " + str(wafi) + "**** hafi: " + str(hafi)) self._compare_addr_family(wafi, hafi) def _compare_addr_family(self, want, have): """Compare the address families of the VRF""" afi_parsers = [ # "address_family", "disable_forwarding", "disable_nht", ] # self._module.fail_json(msg="wAfi: " + str(want) + "**** hAfi: " + str(have)) wafi = self.afi_to_list(want) hafi = self.afi_to_list(have) lookup = {(d["name"], d["afi"]): d for d in hafi} pairs = [(d1, lookup.get((d1["name"], d1["afi"]), {})) for d1 in wafi] for wafd, hafd in pairs: # self._module.fail_json(msg="wAfd: " + str(wafd) + "**** hAfd: " + str(hafd)) if "route_maps" in wafd: self._compare_route_maps(wafd, hafd) self.compare(parsers=afi_parsers, want=wafd, have=hafd) # self.compare(parsers=afi_parsers, want=wafi, have=hafi) def afi_to_list(self, data): """Convert address family dict to list""" return [ {"name": data["name"], **{**af, "afi": "ip" if af["afi"] == "ipv4" else af["afi"]}} for af in data["address_family"] ] def _compare_route_maps(self, wafd, hafd): want_rms = wafd.get("route_maps", []) have_rms = hafd.get("route_maps", []) for want in want_rms: match = next( ( h for h in have_rms if h["rm_name"] == want["rm_name"] and h["protocol"] == want["protocol"] ), {}, ) base = {"name": wafd["name"], "afi": wafd["afi"]} self.compare( parsers="route_maps", want={**base, "route_maps": want}, have={**base, "route_maps": match}, ) diff --git a/tests/unit/modules/network/vyos/test_vyos_vrf.py b/tests/unit/modules/network/vyos/test_vyos_vrf.py index 3b498e57..9c931377 100644 --- a/tests/unit/modules/network/vyos/test_vyos_vrf.py +++ b/tests/unit/modules/network/vyos/test_vyos_vrf.py @@ -1,732 +1,503 @@ # (c) 2021 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 . # 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_vrf from ansible_collections.vyos.vyos.tests.unit.modules.utils import set_module_args from .vyos_module import TestVyosModule, load_fixture class TestVyosVrfModule(TestVyosModule): module = vyos_vrf def setUp(self): super(TestVyosVrfModule, 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_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.vrf.vrf.VrfFacts.get_config", ) 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.vrf.vrf.get_os_version", ) self.get_os_version = self.mock_get_os_version.start() self.get_os_version.return_value = "1.5" + self.maxDiff = None def tearDown(self): super(TestVyosVrfModule, self).tearDown() self.mock_get_resource_connection_config.stop() self.mock_get_resource_connection_facts.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_vrf_config.cfg" def load_from_file(*args, **kwargs): output = load_fixture(filename) return output self.execute_show_command.side_effect = load_from_file def test_vrf_merged_idempotent(self): - # set_module_args( - # dict( - # config=dict( - # allow_clients=["10.1.1.0/24", "10.1.2.0/24"], - # listen_addresses=["10.2.3.1", "10.4.3.1"], - # servers=[ - # dict(server="server1"), - # dict(server="server3", options=["noselect", "dynamic"]), - # dict(server="time1.vyos.net"), - # dict(server="time2.vyos.net"), - # dict(server="time3.vyos.net"), - # ], - # ), - # state="merged", - # ), - # ) set_module_args( dict( config=dict( bind_to_all=True, instances=[ dict( name="vrf-blue", description="blue-vrf", disable=False, table_id=100, vni=1000, ), dict( name="vrf-red", description="red-vrf", disable=True, table_id=101, vni=1001, address_family=[ dict( afi="ipv4", disable_forwarding=True, route_maps=[ dict(rm_name="rm1", protocol="kernel"), dict(rm_name="rm1", protocol="rip"), ], ), dict( afi="ipv6", nht_no_resolve_via_default=False, ), ], ), ], ), state="merged", ), ) self.execute_module(changed=False, commands=[]) def test_vrf_merged(self): set_module_args( dict( config=dict( bind_to_all=True, instances=[ dict( name="vrf-green", description="green-vrf", table_id=110, vni=1010, ), ], ), state="merged", ), ) commands = [ "set vrf name vrf-green table 110", "set vrf name vrf-green vni 1010", "set vrf name vrf-green description green-vrf", ] self.execute_module(changed=True, commands=commands) + def test_vrf_replaced(self): + set_module_args( + dict( + config=dict( + bind_to_all=True, + instances=[ + dict( + name="vrf-blue", + description="blue-vrf-replaced", + disable=True, + table_id=100, + vni=1000, + ), + dict( + name="vrf-red", + description="red-vrf", + disable=True, + table_id=101, + vni=1001, + address_family=[ + dict( + afi="ipv4", + disable_forwarding=False, + route_maps=[ + dict(rm_name="rm1", protocol="kernel"), + dict(rm_name="rm1", protocol="rip"), + ], + ), + dict( + afi="ipv6", + nht_no_resolve_via_default=True, + ), + ], + ), + ], + ), + state="replaced", + ), + ) + commands = [ + "set vrf name vrf-blue description blue-vrf-replaced", + "set vrf name vrf-blue disable", + "delete vrf name vrf-red ip disable-forwarding", + "set vrf name vrf-red ipv6 nht no-resolve-via-default", + ] + self.execute_module(changed=True, commands=commands) -# def test_ntp_replaced(self): -# set_module_args( -# dict( -# config=dict( -# allow_clients=["10.3.4.0/24", "10.4.5.0/24"], -# listen_addresses=["10.3.3.1", "10.4.4.1"], -# servers=[ -# dict(server="server4", options=["noselect", "prefer"]), -# dict( -# server="server6", -# options=[ -# "noselect", -# "dynamic", -# "prefer", -# "preempt", -# ], -# ), -# dict(server="time1.vyos.net"), -# dict(server="time2.vyos.net"), -# dict(server="time3.vyos.net"), -# ], -# ), -# state="replaced", -# ), -# ) -# commands = [ -# "delete system ntp allow-clients address 10.1.1.0/24", -# "delete system ntp allow-clients address 10.1.2.0/24", -# "delete system ntp listen-address 10.2.3.1", -# "delete system ntp listen-address 10.4.3.1", -# "delete system ntp server server1", -# "delete system ntp server server3", -# "set system ntp allow-clients address 10.3.4.0/24", -# "set system ntp allow-clients address 10.4.5.0/24", -# "set system ntp listen-address 10.3.3.1", -# "set system ntp listen-address 10.4.4.1", -# "set system ntp server server4 noselect", -# "set system ntp server server4 prefer", -# "set system ntp server server6 noselect", -# "set system ntp server server6 dynamic", -# "set system ntp server server6 prefer", -# "set system ntp server server6 preempt", -# ] -# self.execute_module(changed=True, commands=commands) - -# def test_ntp_replaced_idempotent(self): -# set_module_args( -# dict( -# config=dict( -# allow_clients=["10.1.1.0/24", "10.1.2.0/24"], -# listen_addresses=["10.2.3.1", "10.4.3.1"], -# servers=[ -# dict(server="server1"), -# dict(server="server3", options=["noselect", "dynamic"]), -# dict(server="time1.vyos.net"), -# dict(server="time2.vyos.net"), -# dict(server="time3.vyos.net"), -# ], -# ), -# state="replaced", -# ), -# ) -# self.execute_module(changed=False, commands=[]) - -# def test_ntp_overridden(self): -# set_module_args( -# dict( -# config=dict( -# allow_clients=["10.9.9.0/24"], -# listen_addresses=["10.9.9.1"], -# servers=[ -# dict(server="server9"), -# dict(server="server6", options=["noselect", "dynamic"]), -# dict(server="time1.vyos.net"), -# dict(server="time2.vyos.net"), -# dict(server="time3.vyos.net"), -# ], -# ), -# state="overridden", -# ), -# ) -# commands = [ -# "delete system ntp allow-clients address 10.1.1.0/24", -# "delete system ntp allow-clients address 10.1.2.0/24", -# "delete system ntp listen-address 10.2.3.1", -# "delete system ntp listen-address 10.4.3.1", -# "delete system ntp server server1", -# "delete system ntp server server3", -# "set system ntp allow-clients address 10.9.9.0/24", -# "set system ntp listen-address 10.9.9.1", -# "set system ntp server server9", -# "set system ntp server server6 noselect", -# "set system ntp server server6 dynamic", -# ] -# self.execute_module(changed=True, commands=commands) - -# def test_ntp_overridden_idempotent(self): -# set_module_args( -# dict( -# config=dict( -# allow_clients=["10.1.1.0/24", "10.1.2.0/24"], -# listen_addresses=["10.2.3.1", "10.4.3.1"], -# servers=[ -# dict(server="server1"), -# dict(server="server3", options=["noselect", "dynamic"]), -# dict(server="time1.vyos.net"), -# dict(server="time2.vyos.net"), -# dict(server="time3.vyos.net"), -# ], -# ), -# state="overridden", -# ), -# ) -# self.execute_module(changed=False, commands=[]) - -# def test_ntp_rendered(self): -# set_module_args( -# dict( -# config=dict( -# allow_clients=["10.7.7.0/24", "10.8.8.0/24"], -# listen_addresses=["10.7.9.1"], -# servers=[ -# dict(server="server79"), -# dict(server="server46", options=["noselect", "dynamic"]), -# dict(server="time1.vyos.net"), -# dict(server="time2.vyos.net"), -# dict(server="time3.vyos.net"), -# ], -# ), -# state="rendered", -# ), -# ) -# rendered_commands = [ -# "set system ntp allow-clients address 10.7.7.0/24", -# "set system ntp allow-clients address 10.8.8.0/24", -# "set system ntp listen-address 10.7.9.1", -# "set system ntp server server79", -# "set system ntp server server46 noselect", -# "set system ntp server server46 dynamic", -# "set system ntp server time1.vyos.net", -# "set system ntp server time2.vyos.net", -# "set system ntp server time3.vyos.net", -# ] -# result = self.execute_module(changed=False) -# self.assertEqual( -# sorted(result["rendered"]), -# sorted(rendered_commands), -# result["rendered"], -# ) - -# def test_ntp_parsed(self): -# commands = ( -# "set system ntp allow-clients address 10.7.7.0/24", -# "set system ntp allow-clients address 10.6.7.0/24", -# "set system ntp listen-address 10.7.9.1", -# "set system ntp listen-address 10.7.7.1", -# "set system ntp server check", -# "set system ntp server server46 noselect", -# "set system ntp server server46 prefer", -# "set system ntp server time1.vyos.net", -# "set system ntp server time2.vyos.net", -# "set system ntp server time3.vyos.net", -# ) -# parsed_str = "\n".join(commands) -# set_module_args(dict(running_config=parsed_str, state="parsed")) -# result = self.execute_module(changed=False) -# parsed_list = { -# "allow_clients": ["10.6.7.0/24", "10.7.7.0/24"], -# "listen_addresses": ["10.7.7.1", "10.7.9.1"], -# "servers": [ -# {"server": "check"}, -# {"server": "server46", "options": ["noselect", "prefer"]}, -# {"server": "time1.vyos.net"}, -# {"server": "time2.vyos.net"}, -# {"server": "time3.vyos.net"}, -# ], -# } -# self.assertEqual(parsed_list, result["parsed"]) - -# def test_ntp_gathered(self): -# set_module_args(dict(state="gathered")) -# result = self.execute_module(changed=False) -# gathered_list = { -# "allow_clients": ["10.1.1.0/24", "10.1.2.0/24"], -# "listen_addresses": ["10.2.3.1", "10.4.3.1"], -# "servers": [ -# {"server": "server1"}, -# {"server": "server3", "options": ["dynamic", "noselect"]}, -# {"server": "time1.vyos.net"}, -# {"server": "time2.vyos.net"}, -# {"server": "time3.vyos.net"}, -# ], -# } - -# self.assertEqual(gathered_list, result["gathered"]) - -# def test_ntp_deleted(self): -# # Delete the subsections that we include (listen_addresses and servers) -# set_module_args( -# dict( -# config=dict( -# allow_clients=["10.1.1.0/24"], -# listen_addresses=["10.2.3.1"], -# servers=[ -# dict(server="server1"), -# dict(server="server3", options=["noselect"]), -# dict(server="time1.vyos.net"), -# dict(server="time2.vyos.net"), -# dict(server="time3.vyos.net"), -# ], -# ), -# state="deleted", -# ), -# ) -# commands = [ -# "delete system ntp allow-clients", # 10.1.1.0/24", -# "delete system ntp listen-address", # 10.2.3.1", -# "delete system ntp server server1", -# "delete system ntp server server3", -# "delete system ntp server time1.vyos.net", -# "delete system ntp server time2.vyos.net", -# "delete system ntp server time3.vyos.net", -# "delete system ntp", -# ] -# self.execute_module(changed=True, commands=commands) - -# def test_ntp__all_deleted(self): -# set_module_args( -# dict( -# config=dict(), -# state="deleted", -# ), -# ) -# commands = [ -# "delete system ntp allow-clients", -# "delete system ntp listen-address", -# "delete system ntp server server1", -# "delete system ntp server server3", -# "delete system ntp server time1.vyos.net", -# "delete system ntp server time2.vyos.net", -# "delete system ntp server time3.vyos.net", -# "delete system ntp", -# ] -# self.execute_module(changed=True, commands=commands) - - -# class TestVyosNTPModule14(TestVyosModule): -# module = vyos_ntp_global - -# def setUp(self): -# super(TestVyosNTPModule14, 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_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.ntp_global.ntp_global.Ntp_globalFacts.get_config", -# ) - -# 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.ntp_global.ntp_global.get_os_version", -# ) -# self.get_os_version = self.mock_get_os_version.start() -# self.get_os_version.return_value = "1.4" - -# def tearDown(self): -# super(TestVyosNTPModule14, self).tearDown() -# self.mock_get_resource_connection_config.stop() -# self.mock_get_resource_connection_facts.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_ntp_config_v14.cfg" - -# def load_from_file(*args, **kwargs): -# output = load_fixture(filename) -# return output - -# self.execute_show_command.side_effect = load_from_file - -# def test_ntp_merged_idempotent(self): -# set_module_args( -# dict( -# config=dict( -# allow_clients=["10.1.1.0/24", "10.1.2.0/24"], -# listen_addresses=["10.2.3.1", "10.4.3.1"], -# servers=[ -# dict(server="server1"), -# dict(server="server3", options=["noselect", "pool"]), -# dict(server="time1.vyos.net"), -# dict(server="time2.vyos.net"), -# dict(server="time3.vyos.net"), -# ], -# ), -# state="merged", -# ), -# ) -# self.execute_module(changed=False, commands=[]) - -# def test_ntp_merged(self): -# set_module_args( -# dict( -# config=dict( -# allow_clients=["10.2.2.0/24", "10.3.3.0/24"], -# listen_addresses=["10.3.4.1", "10.4.5.1"], -# servers=[ -# dict(server="server4", options=["pool", "prefer"]), -# dict( -# server="server5", -# options=[ -# "noselect", -# "pool", -# "nts", -# "prefer", -# ], -# ), -# ], -# ), -# state="merged", -# ), -# ) - -# commands = [ -# "set service ntp allow-client address 10.2.2.0/24", -# "set service ntp allow-client address 10.3.3.0/24", -# "set service ntp listen-address 10.3.4.1", -# "set service ntp listen-address 10.4.5.1", -# "set service ntp server server4 pool", -# "set service ntp server server4 prefer", -# "set service ntp server server5 pool", -# "set service ntp server server5 noselect", -# "set service ntp server server5 nts", -# "set service ntp server server5 prefer", -# ] - -# self.execute_module(changed=True, commands=commands) - -# def test_ntp_replaced(self): -# set_module_args( -# dict( -# config=dict( -# allow_clients=["10.3.4.0/24", "10.4.5.0/24"], -# listen_addresses=["10.3.3.1", "10.4.4.1"], -# servers=[ -# dict(server="server4", options=["noselect", "prefer"]), -# dict( -# server="server6", -# options=[ -# "noselect", -# "pool", -# "prefer", -# "nts", -# ], -# ), -# dict(server="time1.vyos.net"), -# dict(server="time2.vyos.net"), -# dict(server="time3.vyos.net"), -# ], -# ), -# state="replaced", -# ), -# ) -# commands = [ -# "delete service ntp allow-client address 10.1.1.0/24", -# "delete service ntp allow-client address 10.1.2.0/24", -# "delete service ntp listen-address 10.2.3.1", -# "delete service ntp listen-address 10.4.3.1", -# "delete service ntp server server1", -# "delete service ntp server server3", -# "set service ntp allow-client address 10.3.4.0/24", -# "set service ntp allow-client address 10.4.5.0/24", -# "set service ntp listen-address 10.3.3.1", -# "set service ntp listen-address 10.4.4.1", -# "set service ntp server server4 noselect", -# "set service ntp server server4 prefer", -# "set service ntp server server6 noselect", -# "set service ntp server server6 pool", -# "set service ntp server server6 prefer", -# "set service ntp server server6 nts", -# ] -# self.execute_module(changed=True, commands=commands) - -# def test_ntp_replaced_idempotent(self): -# set_module_args( -# dict( -# config=dict( -# allow_clients=["10.1.1.0/24", "10.1.2.0/24"], -# listen_addresses=["10.2.3.1", "10.4.3.1"], -# servers=[ -# dict(server="server1"), -# dict(server="server3", options=["noselect", "pool"]), -# dict(server="time1.vyos.net"), -# dict(server="time2.vyos.net"), -# dict(server="time3.vyos.net"), -# ], -# ), -# state="replaced", -# ), -# ) -# self.execute_module(changed=False, commands=[]) - -# def test_ntp_overridden(self): -# set_module_args( -# dict( -# config=dict( -# allow_clients=["10.9.9.0/24"], -# listen_addresses=["10.9.9.1"], -# servers=[ -# dict(server="server9"), -# dict(server="server6", options=["noselect", "pool"]), -# dict(server="time1.vyos.net"), -# dict(server="time2.vyos.net"), -# dict(server="time3.vyos.net"), -# ], -# ), -# state="overridden", -# ), -# ) -# commands = [ -# "delete service ntp allow-client address 10.1.1.0/24", -# "delete service ntp allow-client address 10.1.2.0/24", -# "delete service ntp listen-address 10.2.3.1", -# "delete service ntp listen-address 10.4.3.1", -# "delete service ntp server server1", -# "delete service ntp server server3", -# "set service ntp allow-client address 10.9.9.0/24", -# "set service ntp listen-address 10.9.9.1", -# "set service ntp server server9", -# "set service ntp server server6 noselect", -# "set service ntp server server6 pool", -# ] -# self.execute_module(changed=True, commands=commands) - -# def test_ntp_overridden_idempotent(self): -# set_module_args( -# dict( -# config=dict( -# allow_clients=["10.1.1.0/24", "10.1.2.0/24"], -# listen_addresses=["10.2.3.1", "10.4.3.1"], -# servers=[ -# dict(server="server1"), -# dict(server="server3", options=["noselect", "pool"]), -# dict(server="time1.vyos.net"), -# dict(server="time2.vyos.net"), -# dict(server="time3.vyos.net"), -# ], -# ), -# state="overridden", -# ), -# ) -# self.execute_module(changed=False, commands=[]) - -# def test_ntp_rendered(self): -# set_module_args( -# dict( -# config=dict( -# allow_clients=["10.7.7.0/24", "10.8.8.0/24"], -# listen_addresses=["10.7.9.1"], -# servers=[ -# dict(server="server79"), -# dict(server="server46", options=["noselect", "pool"]), -# dict(server="time1.vyos.net"), -# dict(server="time2.vyos.net"), -# dict(server="time3.vyos.net"), -# ], -# ), -# state="rendered", -# ), -# ) -# rendered_commands = [ -# "set service ntp allow-client address 10.7.7.0/24", -# "set service ntp allow-client address 10.8.8.0/24", -# "set service ntp listen-address 10.7.9.1", -# "set service ntp server server79", -# "set service ntp server server46 noselect", -# "set service ntp server server46 pool", -# "set service ntp server time1.vyos.net", -# "set service ntp server time2.vyos.net", -# "set service ntp server time3.vyos.net", -# ] -# result = self.execute_module(changed=False) -# self.assertEqual( -# sorted(result["rendered"]), -# sorted(rendered_commands), -# result["rendered"], -# ) + def test_vrf_replaced_idempotent(self): + set_module_args( + dict( + config=dict( + bind_to_all=True, + instances=[ + dict( + name="vrf-blue", + description="blue-vrf", + disable=False, + table_id=100, + vni=1000, + ), + dict( + name="vrf-red", + description="red-vrf", + disable=True, + table_id=101, + vni=1001, + address_family=[ + dict( + afi="ipv4", + disable_forwarding=True, + route_maps=[ + dict(rm_name="rm1", protocol="kernel"), + dict(rm_name="rm1", protocol="rip"), + ], + ), + dict( + afi="ipv6", + nht_no_resolve_via_default=False, + ), + ], + ), + ], + ), + state="replaced", + ), + ) + self.execute_module(changed=False, commands=[]) -# def test_ntp_parsed(self): -# commands = ( -# "set service ntp allow-client address 10.7.7.0/24", -# "set service ntp allow-client address 10.6.7.0/24", -# "set service ntp listen-address 10.7.9.1", -# "set service ntp listen-address 10.7.7.1", -# "set service ntp server check", -# "set service ntp server server46 noselect", -# "set service ntp server server46 prefer", -# "set service ntp server time1.vyos.net", -# "set service ntp server time2.vyos.net", -# "set service ntp server time3.vyos.net", -# ) -# parsed_str = "\n".join(commands) -# set_module_args(dict(running_config=parsed_str, state="parsed")) -# result = self.execute_module(changed=False) -# parsed_list = { -# "allow_clients": ["10.6.7.0/24", "10.7.7.0/24"], -# "listen_addresses": ["10.7.7.1", "10.7.9.1"], -# "servers": [ -# {"server": "check"}, -# {"server": "server46", "options": ["noselect", "prefer"]}, -# {"server": "time1.vyos.net"}, -# {"server": "time2.vyos.net"}, -# {"server": "time3.vyos.net"}, -# ], -# } -# self.assertEqual(parsed_list, result["parsed"]) + def test_vrf_overridden(self): + set_module_args( + dict( + config=dict( + instances=[ + dict( + name="vrf-blue", + description="blue-vrf", + disable=True, + table_id=103, + vni=1002, + ), + ], + ), + state="overridden", + ), + ) + commands = [ + "delete vrf name vrf-blue", + "commit", + "set vrf name vrf-blue table 103", + "set vrf name vrf-blue vni 1002", + "set vrf name vrf-blue description blue-vrf", + "set vrf name vrf-blue disable", + "delete vrf bind-to-all", + ] + self.execute_module(changed=True, commands=commands) -# def test_ntp_gathered(self): -# set_module_args(dict(state="gathered")) -# result = self.execute_module(changed=False) -# gathered_list = { -# "allow_clients": ["10.1.1.0/24", "10.1.2.0/24"], -# "listen_addresses": ["10.2.3.1", "10.4.3.1"], -# "servers": [ -# {"server": "server1"}, -# {"server": "server3", "options": ["noselect", "pool"]}, -# {"server": "time1.vyos.net"}, -# {"server": "time2.vyos.net"}, -# {"server": "time3.vyos.net"}, -# ], -# } + # def test_vrf_overridden_idempotent(self): + # set_module_args( + # dict( + # config=dict( + # bind_to_all=True, + # instances=[ + # dict( + # name="vrf-blue", + # description="blue-vrf", + # disable=False, + # table_id=100, + # vni=1000, + # ), + # dict( + # name="vrf-red", + # description="red-vrf", + # disable=True, + # table_id=101, + # vni=1001, + # address_family=[ + # dict( + # afi="ipv4", + # disable_forwarding=True, + # route_maps=[ + # dict(rm_name="rm1", protocol="kernel"), + # dict(rm_name="rm1", protocol="rip"), + # ], + # ), + # dict( + # afi="ipv6", + # nht_no_resolve_via_default=False, + # ), + # ], + # ), + # ], + # ), + # state="overridden", + # ), + # ) + # self.execute_module(changed=False, commands=[]) + + def test_vrf_rendered(self): + set_module_args( + dict( + config=dict( + bind_to_all=True, + instances=[ + dict( + name="vrf-green", + description="green-vrf", + disabled=True, + table_id=105, + vni=1000, + ), + dict( + name="vrf-amber", + description="amber-vrf", + disable=False, + table_id=111, + vni=1001, + address_family=[ + dict( + afi="ipv4", + disable_forwarding=True, + route_maps=[ + dict(rm_name="rm1", protocol="kernel"), + dict(rm_name="rm1", protocol="ospf"), + ], + ), + dict( + afi="ipv6", + nht_no_resolve_via_default=False, + ), + ], + ), + ], + ), + state="rendered", + ), + ) + rendered_commands = [ + "set vrf bind-to-all", + "set vrf name vrf-green table 105", + "set vrf name vrf-green vni 1000", + "set vrf name vrf-green description green-vrf", + "set vrf name vrf-green disable", + "set vrf name vrf-amber table 111", + "set vrf name vrf-amber vni 1001", + "set vrf name vrf-amber description amber-vrf", + "set vrf name vrf-amber ip protocol kernel route-map rm1", + "set vrf name vrf-amber ip protocol ospf route-map rm1", + "set vrf name vrf-amber ip disable-forwarding", + ] + result = self.execute_module(changed=False) + self.assertEqual( + sorted(result["rendered"]), + sorted(rendered_commands), + result["rendered"], + ) -# self.assertEqual(gathered_list, result["gathered"]) + def test_vrf_parsed(self): + commands = ( + "set vrf bind-to-all", + "set vrf name vrf1 description 'red'", + "set vrf name vrf1 disable", + "set vrf name vrf1 table 101", + "set vrf name vrf1 vni 501", + "set vrf name vrf2 description 'green'", + "set vrf name vrf2 disable", + "set vrf name vrf2 table 102", + "set vrf name vrf2 vni 102", + "set vrf name vrf1 ip disable-forwarding", + "set vrf name vrf1 ip nht no-resolve-via-default", + "set vrf name vrf-red ip protocol kernel route-map 'rm1'", + "set vrf name vrf-red ip protocol ospf route-map 'rm1'", + "set vrf name vrf-red ipv6 nht no-resolve-via-default", + ) + parsed_str = "\n".join(commands) + set_module_args(dict(running_config=parsed_str, state="parsed")) + result = self.execute_module(changed=False) + parsed_list = { + "bind_to_all": True, + "instances": [ + { + "address_family": [ + { + "afi": "ipv4", + "disable_forwarding": True, + "nht_no_resolve_via_default": True, + }, + ], + "description": "red", + "disable": True, + "name": "vrf1", + }, + { + "description": "green", + "disable": True, + "name": "vrf2", + }, + { + "address_family": [ + { + "afi": "ipv4", + "disable_forwarding": False, + "nht_no_resolve_via_default": False, + "route_maps": [ + { + "protocol": "kernel", + "rm_name": "rm1", + }, + { + "protocol": "ospf", + "rm_name": "rm1", + }, + ], + }, + { + "afi": "ipv6", + "disable_forwarding": False, + "nht_no_resolve_via_default": True, + }, + ], + "disable": False, + "name": "vrf-red", + }, + ], + } + self.assertEqual(parsed_list, result["parsed"]) + + def test_vrf_gathered(self): + set_module_args(dict(state="gathered")) + result = self.execute_module(changed=False) + gathered_list = { + "bind_to_all": True, + "instances": [ + { + "description": "blue-vrf", + "disable": False, + "name": "vrf-blue", + "table_id": 100, + "vni": 1000, + }, + { + "address_family": [ + { + "afi": "ipv4", + "disable_forwarding": True, + "nht_no_resolve_via_default": False, + "route_maps": [ + { + "protocol": "kernel", + "rm_name": "rm1", + }, + { + "protocol": "rip", + "rm_name": "rm1", + }, + ], + }, + ], + "description": "red-vrf", + "disable": True, + "name": "vrf-red", + "table_id": 101, + "vni": 1001, + }, + ], + } + self.assertEqual(gathered_list, result["gathered"]) + + def test_vrf_deleted(self): + # Delete the instances and global setting bind_to_all + set_module_args( + dict( + config=dict( + bind_to_all=False, + instances=[ + dict( + name="vrf-blue", + ), + ], + ), + state="deleted", + ), + ) + commands = [ + "delete vrf bind-to-all", + "delete vrf name vrf-blue", + ] + self.execute_module(changed=True, commands=commands) -# def test_ntp_deleted(self): -# set_module_args( -# dict( -# config=dict( -# allow_clients=["10.1.1.0/24"], -# listen_addresses=["10.2.3.1"], -# servers=[ -# dict(server="server1"), -# dict(server="server3", options=["noselect"]), -# dict(server="time1.vyos.net"), -# dict(server="time2.vyos.net"), -# dict(server="time3.vyos.net"), -# ], -# ), -# state="deleted", -# ), -# ) -# commands = [ -# "delete service ntp allow-client", -# "delete service ntp listen-address", -# "delete service ntp server server1", -# "delete service ntp server server3", -# "delete service ntp server time1.vyos.net", -# "delete service ntp server time2.vyos.net", -# "delete service ntp server time3.vyos.net", -# "delete service ntp", -# ] -# self.execute_module(changed=True, commands=commands) + # def test_vrf__all_deleted(self): + # set_module_args( + # dict( + # config=dict({}), + # state="deleted", + # ), + # ) + # commands = [ + # "delete vrf", + # ] + # self.execute_module(changed=True, commands=commands)