diff options
Diffstat (limited to 'plugins/module_utils')
16 files changed, 1951 insertions, 144 deletions
diff --git a/plugins/module_utils/network/vyos/argspec/ospfv3/ospfv3.py b/plugins/module_utils/network/vyos/argspec/ospfv3/ospfv3.py index a59606dd..61704345 100644 --- a/plugins/module_utils/network/vyos/argspec/ospfv3/ospfv3.py +++ b/plugins/module_utils/network/vyos/argspec/ospfv3/ospfv3.py @@ -47,6 +47,12 @@ class Ospfv3Args(object): # pylint: disable=R0903 "area_id": {"type": "str"}, "export_list": {"type": "str"}, "import_list": {"type": "str"}, + "interface": { + "aliases": ["interfaces"], + "type": "list", + "elements": "dict", + "options": {"name": {"type": "str"}}, + }, "range": { "elements": "dict", "options": { diff --git a/plugins/module_utils/network/vyos/argspec/route_maps/route_maps.py b/plugins/module_utils/network/vyos/argspec/route_maps/route_maps.py index 196db0c7..5b6d404d 100644 --- a/plugins/module_utils/network/vyos/argspec/route_maps/route_maps.py +++ b/plugins/module_utils/network/vyos/argspec/route_maps/route_maps.py @@ -74,6 +74,8 @@ class Route_mapsArgs(object): # pylint: disable=R0903 }, "extcommunity_rt": {"type": "str"}, "extcommunity_soo": {"type": "str"}, + "extcommunity_bandwidth": {"type": "str"}, + "extcommunity_bandwidth_non_transitive": {"type": "bool"}, "ip_next_hop": {"type": "str"}, "ipv6_next_hop": { "type": "dict", @@ -100,6 +102,7 @@ class Route_mapsArgs(object): # pylint: disable=R0903 "src": {"type": "str"}, "tag": {"type": "str"}, "weight": {"type": "str"}, + "table": {"type": "str"}, }, }, "match": { @@ -178,6 +181,23 @@ class Route_mapsArgs(object): # pylint: disable=R0903 "next_hop": {"type": "str"}, }, }, + "protocol": { + "type": "str", + "choices": [ + "babel", + "bgp", + "connected", + "isis", + "kernel", + "ospf", + "ospfv3", + "rip", + "ripng", + "static", + "table", + "vnc", + ], + }, "large_community_large_community_list": { "type": "str", }, diff --git a/plugins/module_utils/network/vyos/config/firewall_global/firewall_global.py b/plugins/module_utils/network/vyos/config/firewall_global/firewall_global.py index 34dc0ed6..0d73d209 100644 --- a/plugins/module_utils/network/vyos/config/firewall_global/firewall_global.py +++ b/plugins/module_utils/network/vyos/config/firewall_global/firewall_global.py @@ -29,12 +29,13 @@ from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.u from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.facts import Facts from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.utils.utils import ( list_diff_want_only, + in_target_not_none, +) +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_collections.vyos.vyos.plugins.module_utils.network.vyos.utils.version import LooseVersion - class Firewall_global(ConfigBase): """ @@ -257,11 +258,7 @@ class Firewall_global(ConfigBase): self._form_attr_cmd(attr=key, key=self._bool_to_str(val), opr=opr), ) continue - if ( - key in l_set - and not self._in_target(h, key) - and not self._is_del(l_set, h) - ): + if key in l_set and not self._in_target(h, key) and not self._is_del(l_set, h): commands.append( self._form_attr_cmd(attr=key, val=self._bool_to_str(val), opr=opr), ) @@ -372,13 +369,11 @@ class Firewall_global(ConfigBase): ) elif not opr and key in l_set: if key == "name" and self._is_grp_del(h, want, key): + if commands[-1] == cmd + " " + want["name"] + " " + self._grp_type(attr): + commands.pop() commands.append(cmd + " " + want["name"]) continue - if not (h and self._in_target(h, key)) and not self._is_grp_del( - h, - want, - key, - ): + if not (h and in_target_not_none(h, key)) and not self._is_grp_del(h, want, "name"): commands.append(cmd + " " + want["name"] + " " + key) elif key == "members": commands.extend( @@ -438,6 +433,14 @@ class Firewall_global(ConfigBase): + " " + member[self._get_mem_type(type)], ) + elif not opr and not have: + commands.append( + cmd + + " " + + name + + " " + + self._grp_type(type), + ) return commands def _get_mem_type(self, group): @@ -476,7 +479,9 @@ class Firewall_global(ConfigBase): for key, val in iteritems(w): if val and key != "connection_type": if opr and key in l_set and not (h and self._is_w_same(w, h, key)): - if key == "log" and LooseVersion(get_os_version(self._module)) >= LooseVersion("1.4"): + if key == "log" and LooseVersion( + get_os_version(self._module), + ) >= LooseVersion("1.4"): commands.append( self._form_attr_cmd( key=attr + " " + w["connection_type"], @@ -502,7 +507,9 @@ class Firewall_global(ConfigBase): ), ) break # delete the whole thing and move on - if (not self._in_target(h, key) or h[key] is None) and (self._in_target(w, key) and w[key]): + if (not self._in_target(h, key) or h[key] is None) and ( + self._in_target(w, key) and w[key] + ): # delete if not being replaced and value currently exists commands.append( self._form_attr_cmd( @@ -534,11 +541,11 @@ class Firewall_global(ConfigBase): if want: for w in want: h = self.search_attrib_in_have(have, w, "afi") - if 'afi' in w: - afi = w['afi'] + if "afi" in w: + afi = w["afi"] else: - if h and 'afi' in h: - afi = h['afi'] + if h and "afi" in h: + afi = h["afi"] else: afi = None afi = None @@ -550,7 +557,7 @@ class Firewall_global(ConfigBase): attr=key, val=self._bool_to_str(val), opr=opr, - type=afi + type=afi, ), ) elif not opr and key in l_set: @@ -560,7 +567,7 @@ class Firewall_global(ConfigBase): attr=key, val=self._bool_to_str(val), opr=opr, - type=afi + type=afi, ), ) continue @@ -570,7 +577,7 @@ class Firewall_global(ConfigBase): attr=key, val=self._bool_to_str(val), opr=opr, - type=afi + type=afi, ), ) elif key == "icmp_redirects": @@ -590,11 +597,11 @@ class Firewall_global(ConfigBase): commands = [] h_red = {} l_set = ("send", "receive") - if w and 'afi' in w: - afi = w['afi'] + if w and "afi" in w: + afi = w["afi"] else: - if h and 'afi' in h: - afi = h['afi'] + if h and "afi" in h: + afi = h["afi"] else: afi = None if w[attr]: @@ -603,7 +610,12 @@ class Firewall_global(ConfigBase): for item, value in iteritems(w[attr]): if opr and item in l_set and not (h_red and self._is_w_same(w[attr], h_red, item)): commands.append( - self._form_attr_cmd(attr=item, val=self._bool_to_str(value), opr=opr, type=afi) + self._form_attr_cmd( + attr=item, + val=self._bool_to_str(value), + opr=opr, + type=afi, + ), ) elif ( not opr @@ -637,7 +649,12 @@ class Firewall_global(ConfigBase): :param type: AF type of attribute. :return: generated command. """ - command = self._compute_command(key=key, attr=self._map_attrib(attr, type=type), val=val, opr=opr) + command = self._compute_command( + key=key, + attr=self._map_attrib(attr, type=type), + val=val, + opr=opr, + ) return command def _compute_command(self, key=None, attr=None, val=None, remove=False, opr=True): @@ -654,14 +671,20 @@ class Firewall_global(ConfigBase): cmd = "delete firewall " else: cmd = "set firewall " - if attr and key != "group" and LooseVersion(get_os_version(self._module)) >= LooseVersion("1.4"): + if ( + attr + and key != "group" + and LooseVersion(get_os_version(self._module)) >= LooseVersion("1.4") + ): cmd += "global-options " if key: cmd += key.replace("_", "-") + " " if attr: cmd += attr.replace("_", "-") if val and opr: - if key == "state_policy" and LooseVersion(get_os_version(self._module)) >= LooseVersion("1.4"): + if key == "state_policy" and LooseVersion(get_os_version(self._module)) >= LooseVersion( + "1.4", + ): cmd += "" else: cmd += " '" + str(val) + "'" diff --git a/plugins/module_utils/network/vyos/config/firewall_rules/firewall_rules.py b/plugins/module_utils/network/vyos/config/firewall_rules/firewall_rules.py index 2942b191..bb6055b7 100644 --- a/plugins/module_utils/network/vyos/config/firewall_rules/firewall_rules.py +++ b/plugins/module_utils/network/vyos/config/firewall_rules/firewall_rules.py @@ -30,10 +30,13 @@ from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.facts from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.utils.utils import ( list_diff_want_only, ) - -from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import get_os_version - -from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.utils.version import LooseVersion +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, + load_config, +) class Firewall_rules(ConfigBase): @@ -78,6 +81,14 @@ class Firewall_rules(ConfigBase): result = {"changed": False} warnings = list() commands = list() + diff = None + + try: + self._module.params["comment"] + except KeyError: + comment = [] + else: + comment = self._module.params["comment"] if self.state in self.ACTION_STATES: existing_firewall_rules_facts = self.get_firewall_rules_facts() @@ -87,6 +98,12 @@ class Firewall_rules(ConfigBase): if self.state in self.ACTION_STATES or self.state == "rendered": commands.extend(self.set_config(deepcopy(existing_firewall_rules_facts))) + if commands and self._module._diff: + commit = not self._module.check_mode + diff = load_config(self._module, commands, commit=commit, comment=comment) + if diff: + result["diff"] = {"prepared": str(diff)} + if commands and self.state in self.ACTION_STATES: if not self._module.check_mode: self._connection.edit_config(commands) @@ -213,13 +230,17 @@ class Firewall_rules(ConfigBase): commands.append(self._compute_command(rs_id, remove=True)) # Blank out the only rule set that it is removed. for entry in have: - if entry['afi'] == rs_id['afi'] and rs_id['name']: + if entry["afi"] == rs_id["afi"] and rs_id["name"]: entry["rule_sets"] = [ - rule_set for rule_set in entry["rule_sets"] if rule_set.get("name") != rs_id['name'] + rule_set + for rule_set in entry["rule_sets"] + if rule_set.get("name") != rs_id["name"] ] - elif entry['afi'] == rs_id['afi'] and rs_id['filter']: + elif entry["afi"] == rs_id["afi"] and rs_id["filter"]: entry["rule_sets"] = [ - rule_set for rule_set in entry["rule_sets"] if rule_set.get("filter") != rs_id['filter'] + rule_set + for rule_set in entry["rule_sets"] + if rule_set.get("filter") != rs_id["filter"] ] commands.extend(self._state_merged(want, have)) return commands @@ -264,7 +285,7 @@ class Firewall_rules(ConfigBase): for h in have: if h["afi"] == w["afi"]: commands.append( - self._compute_command(self._rs_id(None, w["afi"]), remove=True) + self._compute_command(self._rs_id(None, w["afi"]), remove=True), ) elif have: for h in have: @@ -452,7 +473,9 @@ class Firewall_rules(ConfigBase): if LooseVersion(get_os_version(self._module)) >= LooseVersion("1.4"): commands.append(cmd + (" " + attr + " " + item)) else: - commands.append(cmd + (" " + attr + " " + item + " " + self._bool_to_str(val))) + commands.append( + cmd + (" " + attr + " " + item + " " + self._bool_to_str(val)), + ) elif not opr and item in l_set and not self._in_target(h_state, item): commands.append(cmd + (" " + attr + " " + item)) return commands @@ -555,7 +578,9 @@ class Firewall_rules(ConfigBase): else: commands.append(cmd + (" " + attr + " " + item + " " + str(val))) elif not opr and item in l_set and not self._in_target(h_icmp, item): - commands.append(cmd + (" " + attr + " " + item.replace("_", "-") + " " + str(val))) + commands.append( + cmd + (" " + attr + " " + item.replace("_", "-") + " " + str(val)), + ) return commands def _add_interface(self, attr, w, h, cmd, opr): @@ -577,11 +602,11 @@ class Firewall_rules(ConfigBase): if opr and item in l_set and not (h_if and self._is_w_same(w[attr], h_if, item)): commands.append( cmd - + (" " + attr.replace("_", "-") + " " + item.replace("_", "-") + " " + val) + + (" " + attr.replace("_", "-") + " " + item.replace("_", "-") + " " + val), ) elif not opr and item in l_set and not (h_if and self._in_target(h_if, item)): commands.append( - cmd + (" " + attr.replace("_", "-") + " " + item.replace("_", "-")) + cmd + (" " + attr.replace("_", "-") + " " + item.replace("_", "-")), ) return commands @@ -654,14 +679,14 @@ class Firewall_rules(ConfigBase): for flag in flags: invert = flag.get("invert", False) commands.append( - cmd + (" " + attr + " flags " + ("not " if invert else "") + flag["flag"]) + cmd + (" " + attr + " flags " + ("not " if invert else "") + flag["flag"]), ) elif not opr: flags = list_diff_want_only(want, have) for flag in flags: invert = flag.get("invert", False) commands.append( - cmd + (" " + attr + " flags " + ("not " if invert else "") + flag["flag"]) + cmd + (" " + attr + " flags " + ("not " if invert else "") + flag["flag"]), ) return commands @@ -969,7 +994,10 @@ class Firewall_rules(ConfigBase): if number: cmd += " rule " + str(number) if attrib: - if LooseVersion(get_os_version(self._module)) >= LooseVersion("1.4") and attrib == "enable_default_log": + if ( + LooseVersion(get_os_version(self._module)) >= LooseVersion("1.4") + and attrib == "enable_default_log" + ): cmd += " " + "default-log" else: cmd += " " + attrib.replace("_", "-") @@ -1107,15 +1135,23 @@ class Firewall_rules(ConfigBase): for item in rs: self._prune_stubs(item) elif isinstance(rs, dict): - keys_to_remove = [key for key, value in rs.items() - if ( - (key == "disable" and value is False) - or - (key == "log" and value == "disable" and - LooseVersion(get_os_version(self._module)) >= LooseVersion("1.4")) - or - (key in ["new", "invalid", "related", "established"] and value is False and - LooseVersion(get_os_version(self._module)) >= LooseVersion("1.4")))] + keys_to_remove = [ + key + for key, value in rs.items() + if ( + (key == "disable" and value is False) + or ( + key == "log" + and value == "disable" + and LooseVersion(get_os_version(self._module)) >= LooseVersion("1.4") + ) + or ( + key in ["new", "invalid", "related", "established"] + and value is False + and LooseVersion(get_os_version(self._module)) >= LooseVersion("1.4") + ) + ) + ] for key in keys_to_remove: del rs[key] for key in rs: @@ -1131,10 +1167,19 @@ class Firewall_rules(ConfigBase): return True elif isinstance(w, list) and isinstance(rs, list): try: - sorted_list1 = sorted(w, key=lambda x: str(x)) # pylint: disable=unnecessary-lambda - sorted_list2 = sorted(rs, key=lambda x: str(x)) # pylint: disable=unnecessary-lambda + def comparison(x): + if 'name' in x: + return x['name'] + if 'number' in x: + return x['number'] + return str(x) + + sorted_list1 = sorted(w, key=comparison) + sorted_list2 = sorted(rs, key=comparison) except TypeError: return False + if len(sorted_list1) != len(sorted_list2): + return False return all(self._is_same_rs(x, y) for x, y in zip(sorted_list1, sorted_list2)) else: return w == rs diff --git a/plugins/module_utils/network/vyos/config/ospfv2/ospfv2.py b/plugins/module_utils/network/vyos/config/ospfv2/ospfv2.py index a9c1de1b..ababc6f1 100644 --- a/plugins/module_utils/network/vyos/config/ospfv2/ospfv2.py +++ b/plugins/module_utils/network/vyos/config/ospfv2/ospfv2.py @@ -33,6 +33,9 @@ from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.utils.utils _is_w_same, list_diff_want_only, ) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import get_os_version + +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.utils.version import LooseVersion class Ospfv2(ConfigBase): @@ -124,7 +127,7 @@ class Ospfv2(ConfigBase): want = self._module.params["config"] have = existing_ospfv2_facts - resp = self.set_state(want, have) + resp = self.set_state(remove_empties(want), remove_empties(have)) return to_list(resp) def set_state(self, w, h): @@ -136,7 +139,6 @@ class Ospfv2(ConfigBase): :returns: the commands necessary to migrate the current configuration to the desired configuration """ - commands = [] if self.state in ("merged", "replaced", "overridden", "rendered") and not w: self._module.fail_json( @@ -270,7 +272,6 @@ class Ospfv2(ConfigBase): :param opr: True/False. :return: generated list of commands. """ - commands = [] h = {} if have: @@ -320,7 +321,6 @@ class Ospfv2(ConfigBase): :param opr: True/False. :return: generated list of commands. """ - commands = [] h = [] if want: @@ -336,6 +336,10 @@ class Ospfv2(ConfigBase): command = cmd + attr.replace("_", "-") + " " if attr == "network": command += member["address"] + elif attr == "passive_interface" and member != "default" and LooseVersion(get_os_version(self._module)) >= LooseVersion("1.4"): + command = command.replace("passive-interface", "interface") + member + " passive" + elif attr == "passive_interface_exclude" and LooseVersion(get_os_version(self._module)) >= LooseVersion("1.4"): + command = command.replace("passive-interface-exclude", "interface") + member + " passive disable" else: command += member commands.append(command) @@ -348,7 +352,12 @@ class Ospfv2(ConfigBase): cmd + attr.replace("_", "-") + " " + member["address"], ) elif member not in h: - commands.append(cmd + attr.replace("_", "-") + " " + member) + if attr == "passive_interface" and member != "default" and LooseVersion(get_os_version(self._module)) >= LooseVersion("1.4"): + commands.append(cmd + "interface" + " " + member + " passive") + elif attr == "passive_interface_exclude" and LooseVersion(get_os_version(self._module)) >= LooseVersion("1.4"): + command = command.replace("passive-interface-exclude", "interface") + member + " passive disable" + else: + commands.append(cmd + attr.replace("_", "-") + " " + member) else: commands.append(cmd + " " + attr.replace("_", "-")) return commands diff --git a/plugins/module_utils/network/vyos/config/ospfv3/ospfv3.py b/plugins/module_utils/network/vyos/config/ospfv3/ospfv3.py index 25d9a0ea..2538a6f5 100644 --- a/plugins/module_utils/network/vyos/config/ospfv3/ospfv3.py +++ b/plugins/module_utils/network/vyos/config/ospfv3/ospfv3.py @@ -33,6 +33,10 @@ from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.utils.utils _in_target, _is_w_same, ) +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 class Ospfv3(ConfigBase): @@ -264,10 +268,12 @@ class Ospfv3(ConfigBase): name = { "redistribute": "route_type", "range": "address", + "interface": "name", } leaf_dict = { "redistribute": ("route_map", "route_type"), "range": ("address", "advertise", "not_advertise"), + "interface": ("name"), } leaf = leaf_dict[attr] w = want.get(attr) or [] @@ -282,14 +288,26 @@ class Ospfv3(ConfigBase): cmd = self._compute_command(opr=opr) h_item = search_obj_in_list(w_item[name[attr]], h, name[attr]) if opr and key in leaf and not _is_w_same(w_item, h_item, key): - if key == "route_type" or ( + if key in ["route_type", "name"] or ( key == "address" and "advertise" not in w_item and "not-advertise" not in w_item ): if not val: cmd = cmd.replace("set", "delete") - commands.append(cmd + attr + " " + str(val)) + if ( + LooseVersion(get_os_version(self._module)) >= LooseVersion("1.4") + and attr == "interface" + ): + words = cmd.split() + cmd14_list = [] + for word in words: + cmd14_list.append(word) + if word == "ospfv3": + cmd14_list.append(attr + " " + str(val)) + commands.append(" ".join(cmd14_list)) + else: + commands.append(cmd + attr + " " + str(val)) elif key in leaf_dict["range"] and key != "address": commands.append( cmd + attr + " " + w_item[name[attr]] + " " + key.replace("_", "-"), @@ -306,8 +324,20 @@ class Ospfv3(ConfigBase): + str(val), ) elif not opr and key in leaf and not _in_target(h_item, key): - if key in ("route_type", "address"): - commands.append(cmd + attr + " " + str(val)) + if key in ("route_type", "address", "name"): + if ( + LooseVersion(get_os_version(self._module)) >= LooseVersion("1.4") + and attr == "interface" + ): + words = cmd.split() + cmd14_list = [] + for word in words: + cmd14_list.append(word) + if word == "ospfv3": + cmd14_list.append(attr + " " + str(val)) + commands.append(" ".join(cmd14_list)) + else: + commands.append(cmd + attr + " " + str(val)) else: commands.append(cmd + (attr + " " + w_item[name[attr]] + " " + key)) return commands @@ -373,6 +403,10 @@ class Ospfv3(ConfigBase): commands.extend( self._render_list_dict_param(key, w_area, h_area, cmd, opr), ) + elif key == "interface": + commands.extend( + self._render_list_dict_param(key, w_area, h_area, cmd, opr), + ) return commands def _form_attr_cmd(self, key=None, attr=None, val=None, opr=True): diff --git a/plugins/module_utils/network/vyos/config/route_maps/route_maps.py b/plugins/module_utils/network/vyos/config/route_maps/route_maps.py index 9b6c3e9d..9692a253 100644 --- a/plugins/module_utils/network/vyos/config/route_maps/route_maps.py +++ b/plugins/module_utils/network/vyos/config/route_maps/route_maps.py @@ -31,6 +31,13 @@ from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.facts from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.rm_templates.route_maps import ( Route_mapsTemplate, ) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.rm_templates.route_maps_14 import ( + Route_mapsTemplate14, +) +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 class Route_maps(ResourceModule): @@ -59,6 +66,8 @@ class Route_maps(ResourceModule): "set_bgp_extcommunity_rt", "set_extcommunity_rt", "set_extcommunity_soo", + "set_extcommunity_bandwidth", + "set_extcommunity_bandwidth_non_transitive", "set_ip_next_hop", "set_ipv6_next_hop", "set_large_community", @@ -70,6 +79,7 @@ class Route_maps(ResourceModule): "set_src", "set_tag", "set_weight", + "set_table", "set_comm_list", "set_comm_list_delete", "set_community", @@ -89,15 +99,34 @@ class Route_maps(ResourceModule): "on_match_next", "match_ipv6_address", "match_ipv6_nexthop", + "match_protocol", "match_rpki", ] + def _validate_template(self): + version = get_os_version(self._module) + if LooseVersion(version) >= LooseVersion("1.4"): + self._tmplt = Route_mapsTemplate14() + else: + self._tmplt = Route_mapsTemplate() + + 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 """ + self._validate_template() if self.state not in ["parsed", "gathered"]: self.generate_commands() self.run_commands() diff --git a/plugins/module_utils/network/vyos/facts/ospf_interfaces/ospf_interfaces.py b/plugins/module_utils/network/vyos/facts/ospf_interfaces/ospf_interfaces.py index 852e1da7..2160fc71 100644 --- a/plugins/module_utils/network/vyos/facts/ospf_interfaces/ospf_interfaces.py +++ b/plugins/module_utils/network/vyos/facts/ospf_interfaces/ospf_interfaces.py @@ -23,17 +23,16 @@ from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.osp Ospf_interfacesArgs, ) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.rm_templates.ospf_interfaces import ( - Ospf_interfacesTemplate + Ospf_interfacesTemplate, ) - from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.rm_templates.ospf_interfaces_14 import ( - Ospf_interfacesTemplate14 + Ospf_interfacesTemplate14, +) +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_collections.vyos.vyos.plugins.module_utils.network.vyos.utils.version import LooseVersion - class Ospf_interfacesFacts(object): """The vyos ospf_interfaces facts class""" @@ -54,7 +53,9 @@ class Ospf_interfacesFacts(object): for config_line in data.splitlines(): ospf_int = re.search(r"set protocols (?:ospf|ospfv3) interface (\S+).*", config_line) if ospf_int: - config_dict[ospf_int.group(1)] = config_dict.get(ospf_int.group(1), "") + config_line + "\n" + config_dict[ospf_int.group(1)] = ( + config_dict.get(ospf_int.group(1), "") + config_line + "\n" + ) return list(config_dict.values()) def get_config_set_1_2(self, data): @@ -63,12 +64,15 @@ class Ospf_interfacesFacts(object): config_set = [] int_string = "" for config_line in data.splitlines(): - ospf_int = re.search(r"set interfaces \S+ (\S+) .*", config_line) + ospf_int_raw = re.findall(r"^set interfaces \S+ (\S+)", config_line, re.M) + ospf_int_vif = re.findall(r"^set interfaces \S+ (\S+) vif (\d+)", config_line, re.M) + + ospf_int = ospf_int_raw + ospf_int_vif if ospf_int: - if ospf_int.group(1) not in interface_list: + if ospf_int not in interface_list: if int_string: config_set.append(int_string) - interface_list.append(ospf_int.group(1)) + interface_list.append(ospf_int) int_string = "" int_string = int_string + config_line + "\n" if int_string: @@ -115,7 +119,6 @@ class Ospf_interfacesFacts(object): if key in objs and objs[key]: objs[key] = list(objs[key].values()) ospf_interfaces_facts.append(objs) - ansible_facts["ansible_network_resources"].pop("ospf_interfaces", None) facts = {"ospf_interfaces": []} params = utils.remove_empties( @@ -123,11 +126,10 @@ class Ospf_interfacesFacts(object): self.argument_spec, {"config": ospf_interfaces_facts}, redact=True, - ) + ), ) if params.get("config"): for cfg in params["config"]: facts["ospf_interfaces"].append(utils.remove_empties(cfg)) ansible_facts["ansible_network_resources"].update(facts) - return ansible_facts diff --git a/plugins/module_utils/network/vyos/facts/ospfv2/ospfv2.py b/plugins/module_utils/network/vyos/facts/ospfv2/ospfv2.py index bdc7c9f8..d07bf13a 100644 --- a/plugins/module_utils/network/vyos/facts/ospfv2/ospfv2.py +++ b/plugins/module_utils/network/vyos/facts/ospfv2/ospfv2.py @@ -22,6 +22,10 @@ from ansible_collections.ansible.netcommon.plugins.module_utils.network.common i from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.ospfv2.ospfv2 import ( Ospfv2Args, ) +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 class Ospfv2Facts(object): @@ -99,9 +103,9 @@ class Ospfv2Facts(object): config["areas"] = self.parse_attrib_list(conf, "area", "area_id") config["parameters"] = self.parse_attrib(conf, "parameters", "parameters") config["neighbor"] = self.parse_attrib_list(conf, "neighbor", "neighbor_id") - config["passive_interface"] = self.parse_leaf_list(conf, "passive-interface") + config["passive_interface"] = self.parse_passive(conf, "passive-interface") config["redistribute"] = self.parse_attrib_list(conf, "redistribute", "route_type") - config["passive_interface_exclude"] = self.parse_leaf_list( + config["passive_interface_exclude"] = self.parse_passive( conf, "passive-interface-exclude", ) @@ -159,6 +163,29 @@ class Ospfv2Facts(object): lst.sort() return lst + def parse_passive(self, conf, attrib): + """ + This function forms the regex to fetch the listed attributes + from the configuration data + :param conf: configuration data + :param attrib: attribute name + :return: generated rule list configuration + """ + lst = [] + items = [] + if LooseVersion(get_os_version(self._module)) >= LooseVersion("1.4"): + if attrib == "passive-interface-exclude": + items = findall("^interface (?:'*)(\\S+)(?:'*) passive disable$", conf, M) + else: + items = findall("^interface (?:'*)(\\S+)(?:'*) passive$", conf, M) + + items += findall(r"^" + attrib + " (?:'*)(\\S+)(?:'*)", conf, M) + if items: + for i in set(items): + lst.append(i.strip("'")) + lst.sort() + return lst + def parse_distance(self, conf, attrib=None): """ This function triggers the parsing of 'distance' attributes @@ -389,13 +416,13 @@ class Ospfv2Facts(object): :param match: parent node/attribute name. :return: generated config dictionary. """ - config = {} for attrib in attr_list: regex = self.map_regex(attrib) if match: regex = match.replace("_", "-") + " " + regex + if conf: if self.is_bool(attrib): out = conf.find(attrib.replace("_", "-")) @@ -403,13 +430,13 @@ class Ospfv2Facts(object): if match: if attrib == "set" and conf.find(match) >= 1: config[attrib] = True - en = conf.find(match + " 'enable'") + en = conf.find(match + " enable") != -1 if out >= 1: if dis >= 1: config[attrib] = False else: config[attrib] = True - elif match and en >= 1: + elif match and en: config[attrib] = True else: out = search(r"^.*" + regex + " (.+)", conf, M) diff --git a/plugins/module_utils/network/vyos/facts/ospfv3/ospfv3.py b/plugins/module_utils/network/vyos/facts/ospfv3/ospfv3.py index 547ff793..ae67a4b6 100644 --- a/plugins/module_utils/network/vyos/facts/ospfv3/ospfv3.py +++ b/plugins/module_utils/network/vyos/facts/ospfv3/ospfv3.py @@ -22,6 +22,10 @@ from ansible_collections.ansible.netcommon.plugins.module_utils.network.common i from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.ospfv3.ospfv3 import ( Ospfv3Args, ) +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 class Ospfv3Facts(object): @@ -100,6 +104,9 @@ class Ospfv3Facts(object): for item in set(items): i_regex = r" %s .+$" % item cfg = "\n".join(findall(i_regex, conf, M)) + if LooseVersion(get_os_version(self._module)) >= LooseVersion("1.4"): + cfg14 = findall(r"(interface .+) area '%s'$" % item, conf, M) + cfg += "\n " + item + " " + " ".join(cfg14) if attrib == "area": obj = self.parse_area(cfg, item) else: @@ -121,6 +128,8 @@ class Ospfv3Facts(object): rule = self.parse_attrib(conf, "area_id", match=area_id) r_sub = {"range": self.parse_attrib_list(conf, "range", "address")} rule.update(r_sub) + r_int = {"interface": self.parse_attrib_list(conf, "interface", "name")} + rule.update(r_int) return rule def parse_attrib(self, conf, param, match=None): @@ -133,6 +142,7 @@ class Ospfv3Facts(object): "area_id": ["export_list", "import_list"], "redistribute": ["route_map"], "range": ["advertise", "not_advertise"], + "interface": ["name"], "parameters": ["router_id"], } cfg_dict = self.parse_attr(conf, param_lst[param], match) diff --git a/plugins/module_utils/network/vyos/facts/route_maps/route_maps.py b/plugins/module_utils/network/vyos/facts/route_maps/route_maps.py index 2ad54e63..cfae26e3 100644 --- a/plugins/module_utils/network/vyos/facts/route_maps/route_maps.py +++ b/plugins/module_utils/network/vyos/facts/route_maps/route_maps.py @@ -25,6 +25,13 @@ from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.rou from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.rm_templates.route_maps import ( Route_mapsTemplate, ) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.rm_templates.route_maps_14 import ( + Route_mapsTemplate14, +) +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 class Route_mapsFacts(object): @@ -59,11 +66,18 @@ class Route_mapsFacts(object): """ facts = {} objs = [] + + if LooseVersion(get_os_version(self._module)) >= LooseVersion("1.4"): + route_maps_class = Route_mapsTemplate14 + else: + route_maps_class = Route_mapsTemplate + if not data: data = self.get_config(connection) # parse native config using the Route_maps template - route_maps_parser = Route_mapsTemplate(lines=data.splitlines()) + route_maps_parser = route_maps_class(lines=data.splitlines()) + if route_maps_parser.parse().get("route_maps"): objs = list(route_maps_parser.parse().get("route_maps").values()) for item in objs: diff --git a/plugins/module_utils/network/vyos/rm_templates/ospf_interfaces.py b/plugins/module_utils/network/vyos/rm_templates/ospf_interfaces.py index 0d7eaf84..134effca 100644 --- a/plugins/module_utils/network/vyos/rm_templates/ospf_interfaces.py +++ b/plugins/module_utils/network/vyos/rm_templates/ospf_interfaces.py @@ -23,6 +23,7 @@ from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.r from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.utils.utils import ( get_interface_type, + get_interface_with_vif, ) @@ -36,21 +37,23 @@ def _get_parameters(data): def _tmplt_ospf_int_delete(config_data): int_type = get_interface_type(config_data["name"]) + name = get_interface_with_vif(config_data["name"]) params = _get_parameters(config_data["address_family"]) - command = ( - "interfaces " + int_type + " {name} ".format(**config_data) + params[1] + " " + params[0] - ) + command = "interfaces " + int_type + " " + name + " " + params[1] + " " + params[0] return command def _tmplt_ospf_int_cost(config_data): int_type = get_interface_type(config_data["name"]) + name = get_interface_with_vif(config_data["name"]) params = _get_parameters(config_data["address_family"]) command = ( "interfaces " + int_type - + " {name} ".format(**config_data) + + " " + + name + + " " + params[1] + " " + params[0] @@ -62,11 +65,14 @@ def _tmplt_ospf_int_cost(config_data): def _tmplt_ospf_int_auth_password(config_data): int_type = get_interface_type(config_data["name"]) + name = get_interface_with_vif(config_data["name"]) params = _get_parameters(config_data["address_family"]) command = ( "interfaces " + int_type - + " {name} ".format(**config_data) + + " " + + name + + " " + params[1] + " " + params[0] @@ -79,11 +85,14 @@ def _tmplt_ospf_int_auth_password(config_data): def _tmplt_ospf_int_auth_md5(config_data): int_type = get_interface_type(config_data["name"]) + name = get_interface_with_vif(config_data["name"]) params = _get_parameters(config_data["address_family"]) command = ( "interfaces " + int_type - + " {name} ".format(**config_data) + + " " + + name + + " " + params[1] + " " + params[0] @@ -98,11 +107,14 @@ def _tmplt_ospf_int_auth_md5(config_data): def _tmplt_ospf_int_auth_md5_delete(config_data): int_type = get_interface_type(config_data["name"]) + name = get_interface_with_vif(config_data["name"]) params = _get_parameters(config_data["address_family"]) command = ( "interfaces " + int_type - + " {name} ".format(**config_data) + + " " + + name + + " " + params[1] + " " + params[0] @@ -114,11 +126,14 @@ def _tmplt_ospf_int_auth_md5_delete(config_data): def _tmplt_ospf_int_bw(config_data): int_type = get_interface_type(config_data["name"]) + name = get_interface_with_vif(config_data["name"]) params = _get_parameters(config_data["address_family"]) command = ( "interfaces " + int_type - + " {name} ".format(**config_data) + + " " + + name + + " " + params[1] + " " + params[0] @@ -130,11 +145,14 @@ def _tmplt_ospf_int_bw(config_data): def _tmplt_ospf_int_hello_interval(config_data): int_type = get_interface_type(config_data["name"]) + name = get_interface_with_vif(config_data["name"]) params = _get_parameters(config_data["address_family"]) command = ( "interfaces " + int_type - + " {name} ".format(**config_data) + + " " + + name + + " " + params[1] + " " + params[0] @@ -146,11 +164,14 @@ def _tmplt_ospf_int_hello_interval(config_data): def _tmplt_ospf_int_dead_interval(config_data): int_type = get_interface_type(config_data["name"]) + name = get_interface_with_vif(config_data["name"]) params = _get_parameters(config_data["address_family"]) command = ( "interfaces " + int_type - + " {name} ".format(**config_data) + + " " + + name + + " " + params[1] + " " + params[0] @@ -162,15 +183,10 @@ def _tmplt_ospf_int_dead_interval(config_data): def _tmplt_ospf_int_mtu_ignore(config_data): int_type = get_interface_type(config_data["name"]) + name = get_interface_with_vif(config_data["name"]) params = _get_parameters(config_data["address_family"]) command = ( - "interfaces " - + int_type - + " {name} ".format(**config_data) - + params[1] - + " " - + params[0] - + " mtu-ignore" + "interfaces " + int_type + " " + name + " " + params[1] + " " + params[0] + " mtu-ignore" ) return command @@ -178,11 +194,14 @@ def _tmplt_ospf_int_mtu_ignore(config_data): def _tmplt_ospf_int_network(config_data): int_type = get_interface_type(config_data["name"]) + name = get_interface_with_vif(config_data["name"]) params = _get_parameters(config_data["address_family"]) command = ( "interfaces " + int_type - + " {name} ".format(**config_data) + + " " + + name + + " " + params[1] + " " + params[0] @@ -194,11 +213,14 @@ def _tmplt_ospf_int_network(config_data): def _tmplt_ospf_int_priority(config_data): int_type = get_interface_type(config_data["name"]) + name = get_interface_with_vif(config_data["name"]) params = _get_parameters(config_data["address_family"]) command = ( "interfaces " + int_type - + " {name} ".format(**config_data) + + " " + + name + + " " + params[1] + " " + params[0] @@ -210,11 +232,14 @@ def _tmplt_ospf_int_priority(config_data): def _tmplt_ospf_int_retransmit_interval(config_data): int_type = get_interface_type(config_data["name"]) + name = get_interface_with_vif(config_data["name"]) params = _get_parameters(config_data["address_family"]) command = ( "interfaces " + int_type - + " {name} ".format(**config_data) + + " " + + name + + " " + params[1] + " " + params[0] @@ -226,11 +251,14 @@ def _tmplt_ospf_int_retransmit_interval(config_data): def _tmplt_ospf_int_transmit_delay(config_data): int_type = get_interface_type(config_data["name"]) + name = get_interface_with_vif(config_data["name"]) params = _get_parameters(config_data["address_family"]) command = ( "interfaces " + int_type - + " {name} ".format(**config_data) + + " " + + name + + " " + params[1] + " " + params[0] @@ -242,11 +270,14 @@ def _tmplt_ospf_int_transmit_delay(config_data): def _tmplt_ospf_int_ifmtu(config_data): int_type = get_interface_type(config_data["name"]) + name = get_interface_with_vif(config_data["name"]) params = _get_parameters(config_data["address_family"]) command = ( "interfaces " + int_type - + " {name} ".format(**config_data) + + " " + + name + + " " + params[1] + " " + params[0] @@ -258,11 +289,14 @@ def _tmplt_ospf_int_ifmtu(config_data): def _tmplt_ospf_int_instance(config_data): int_type = get_interface_type(config_data["name"]) + name = get_interface_with_vif(config_data["name"]) params = _get_parameters(config_data["address_family"]) command = ( "interfaces " + int_type - + " {name} ".format(**config_data) + + " " + + name + + " " + params[1] + " " + params[0] @@ -274,16 +308,9 @@ def _tmplt_ospf_int_instance(config_data): def _tmplt_ospf_int_passive(config_data): int_type = get_interface_type(config_data["name"]) + name = get_interface_with_vif(config_data["name"]) params = _get_parameters(config_data["address_family"]) - command = ( - "interfaces " - + int_type - + " {name} ".format(**config_data) - + params[1] - + " " - + params[0] - + " passive" - ) + command = "interfaces " + int_type + " " + name + " " + params[1] + " " + params[0] + " passive" return command @@ -308,6 +335,7 @@ class Ospf_interfacesTemplate(NetworkTemplate): \s+interfaces \s+(?P<type>\S+) \s+(?P<name>\S+) + (?:\s+vif\s+(?P<vif>\d+))? \s+(?P<afi>ip|ipv6) \s+(?P<proto>ospf|ospfv3) *$""", @@ -316,7 +344,7 @@ class Ospf_interfacesTemplate(NetworkTemplate): "remval": _tmplt_ospf_int_delete, "compval": "address_family", "result": { - "name": "{{ name }}", + "name": "{{ name + '.' + vif if vif is defined else name }}", "address_family": { "{{ afi }}": { "afi": '{{ "ipv4" if afi == "ip" else "ipv6" }}', @@ -332,6 +360,7 @@ class Ospf_interfacesTemplate(NetworkTemplate): \s+interfaces \s+(?P<type>\S+) \s+(?P<name>\S+) + (?:\s+vif\s+(?P<vif>\d+))? \s+(?P<afi>ip|ipv6) \s+(?P<proto>ospf|ospfv3) \s+authentication @@ -343,7 +372,7 @@ class Ospf_interfacesTemplate(NetworkTemplate): "setval": _tmplt_ospf_int_auth_password, "compval": "address_family.authentication", "result": { - "name": "{{ name }}", + "name": "{{ name + '.' + vif if vif is defined else name }}", "address_family": { "{{ afi }}": { "afi": '{{ "ipv4" if afi == "ip" else "ipv6" }}', @@ -362,6 +391,7 @@ class Ospf_interfacesTemplate(NetworkTemplate): \s+interfaces \s+(?P<type>\S+) \s+(?P<name>\S+) + (?:\s+vif\s+(?P<vif>\d+))? \s+(?P<afi>ip|ipv6) \s+(?P<proto>ospf|ospfv3) \s+authentication @@ -377,7 +407,7 @@ class Ospf_interfacesTemplate(NetworkTemplate): "remval": _tmplt_ospf_int_auth_md5_delete, "compval": "address_family.authentication", "result": { - "name": "{{ name }}", + "name": "{{ name + '.' + vif if vif is defined else name }}", "address_family": { "{{ afi }}": { "afi": '{{ "ipv4" if afi == "ip" else "ipv6" }}', @@ -399,6 +429,7 @@ class Ospf_interfacesTemplate(NetworkTemplate): \s+interfaces \s+(?P<type>\S+) \s+(?P<name>\S+) + (?:\s+vif\s+(?P<vif>\d+))? \s+(?P<afi>ip|ipv6) \s+(?P<proto>ospf|ospfv3) \s+bandwidth @@ -409,7 +440,7 @@ class Ospf_interfacesTemplate(NetworkTemplate): "setval": _tmplt_ospf_int_bw, "compval": "address_family.bandwidth", "result": { - "name": "{{ name }}", + "name": "{{ name + '.' + vif if vif is defined else name }}", "address_family": { "{{ afi }}": { "afi": '{{ "ipv4" if afi == "ip" else "ipv6" }}', @@ -426,6 +457,7 @@ class Ospf_interfacesTemplate(NetworkTemplate): \s+interfaces \s+(?P<type>\S+) \s+(?P<name>\S+) + (?:\s+vif\s+(?P<vif>\d+))? \s+(?P<afi>ip|ipv6) \s+(?P<proto>ospf|ospfv3) \s+cost @@ -436,7 +468,7 @@ class Ospf_interfacesTemplate(NetworkTemplate): "setval": _tmplt_ospf_int_cost, "compval": "address_family.cost", "result": { - "name": "{{ name }}", + "name": "{{ name + '.' + vif if vif is defined else name }}", "address_family": { "{{ afi }}": { "afi": '{{ "ipv4" if afi == "ip" else "ipv6" }}', @@ -453,6 +485,7 @@ class Ospf_interfacesTemplate(NetworkTemplate): \s+interfaces \s+(?P<type>\S+) \s+(?P<name>\S+) + (?:\s+vif\s+(?P<vif>\d+))? \s+(?P<afi>ip|ipv6) \s+(?P<proto>ospf|ospfv3) \s+hello-interval @@ -463,7 +496,7 @@ class Ospf_interfacesTemplate(NetworkTemplate): "setval": _tmplt_ospf_int_hello_interval, "compval": "address_family.hello_interval", "result": { - "name": "{{ name }}", + "name": "{{ name + '.' + vif if vif is defined else name }}", "address_family": { "{{ afi }}": { "afi": '{{ "ipv4" if afi == "ip" else "ipv6" }}', @@ -480,6 +513,7 @@ class Ospf_interfacesTemplate(NetworkTemplate): \s+interfaces \s+(?P<type>\S+) \s+(?P<name>\S+) + (?:\s+vif\s+(?P<vif>\d+))? \s+(?P<afi>ip|ipv6) \s+(?P<proto>ospf|ospfv3) \s+dead-interval @@ -490,7 +524,7 @@ class Ospf_interfacesTemplate(NetworkTemplate): "setval": _tmplt_ospf_int_dead_interval, "compval": "address_family.dead_interval", "result": { - "name": "{{ name }}", + "name": "{{ name + '.' + vif if vif is defined else name }}", "address_family": { "{{ afi }}": { "afi": '{{ "ipv4" if afi == "ip" else "ipv6" }}', @@ -507,6 +541,7 @@ class Ospf_interfacesTemplate(NetworkTemplate): \s+interfaces \s+(?P<type>\S+) \s+(?P<name>\S+) + (?:\s+vif\s+(?P<vif>\d+))? \s+(?P<afi>ip|ipv6) \s+(?P<proto>ospf|ospfv3) \s+(?P<mtu>mtu-ignore) @@ -516,7 +551,7 @@ class Ospf_interfacesTemplate(NetworkTemplate): "setval": _tmplt_ospf_int_mtu_ignore, "compval": "address_family.mtu_ignore", "result": { - "name": "{{ name }}", + "name": "{{ name + '.' + vif if vif is defined else name }}", "address_family": { "{{ afi }}": { "afi": '{{ "ipv4" if afi == "ip" else "ipv6" }}', @@ -533,6 +568,7 @@ class Ospf_interfacesTemplate(NetworkTemplate): \s+interfaces \s+(?P<type>\S+) \s+(?P<name>\S+) + (?:\s+vif\s+(?P<vif>\d+))? \s+(?P<afi>ip|ipv6) \s+(?P<proto>ospf|ospfv3) \s+network @@ -543,7 +579,7 @@ class Ospf_interfacesTemplate(NetworkTemplate): "setval": _tmplt_ospf_int_network, "compval": "address_family.network", "result": { - "name": "{{ name }}", + "name": "{{ name + '.' + vif if vif is defined else name }}", "address_family": { "{{ afi }}": { "afi": '{{ "ipv4" if afi == "ip" else "ipv6" }}', @@ -560,6 +596,7 @@ class Ospf_interfacesTemplate(NetworkTemplate): \s+interfaces \s+(?P<type>\S+) \s+(?P<name>\S+) + (?:\s+vif\s+(?P<vif>\d+))? \s+(?P<afi>ip|ipv6) \s+(?P<proto>ospf|ospfv3) \s+priority @@ -570,7 +607,7 @@ class Ospf_interfacesTemplate(NetworkTemplate): "setval": _tmplt_ospf_int_priority, "compval": "address_family.priority", "result": { - "name": "{{ name }}", + "name": "{{ name + '.' + vif if vif is defined else name }}", "address_family": { "{{ afi }}": { "afi": '{{ "ipv4" if afi == "ip" else "ipv6" }}', @@ -587,6 +624,7 @@ class Ospf_interfacesTemplate(NetworkTemplate): \s+interfaces \s+(?P<type>\S+) \s+(?P<name>\S+) + (?:\s+vif\s+(?P<vif>\d+))? \s+(?P<afi>ip|ipv6) \s+(?P<proto>ospf|ospfv3) \s+retransmit-interval @@ -597,7 +635,7 @@ class Ospf_interfacesTemplate(NetworkTemplate): "setval": _tmplt_ospf_int_retransmit_interval, "compval": "address_family.retransmit_interval", "result": { - "name": "{{ name }}", + "name": "{{ name + '.' + vif if vif is defined else name }}", "address_family": { "{{ afi }}": { "afi": '{{ "ipv4" if afi == "ip" else "ipv6" }}', @@ -614,6 +652,7 @@ class Ospf_interfacesTemplate(NetworkTemplate): \s+interfaces \s+(?P<type>\S+) \s+(?P<name>\S+) + (?:\s+vif\s+(?P<vif>\d+))? \s+(?P<afi>ip|ipv6) \s+(?P<proto>ospf|ospfv3) \s+transmit-delay @@ -624,7 +663,7 @@ class Ospf_interfacesTemplate(NetworkTemplate): "setval": _tmplt_ospf_int_transmit_delay, "compval": "address_family.transmit_delay", "result": { - "name": "{{ name }}", + "name": "{{ name + '.' + vif if vif is defined else name }}", "address_family": { "{{ afi }}": { "afi": '{{ "ipv4" if afi == "ip" else "ipv6" }}', @@ -641,6 +680,7 @@ class Ospf_interfacesTemplate(NetworkTemplate): \s+interfaces \s+(?P<type>\S+) \s+(?P<name>\S+) + (?:\s+vif\s+(?P<vif>\d+))? \s+(?P<afi>ip|ipv6) \s+(?P<proto>ospf|ospfv3) \s+ifmtu @@ -651,7 +691,7 @@ class Ospf_interfacesTemplate(NetworkTemplate): "setval": _tmplt_ospf_int_ifmtu, "compval": "address_family.ifmtu", "result": { - "name": "{{ name }}", + "name": "{{ name + '.' + vif if vif is defined else name }}", "address_family": { "{{ afi }}": { "afi": '{{ "ipv4" if afi == "ip" else "ipv6" }}', @@ -668,6 +708,7 @@ class Ospf_interfacesTemplate(NetworkTemplate): \s+interfaces \s+(?P<type>\S+) \s+(?P<name>\S+) + (?:\s+vif\s+(?P<vif>\d+))? \s+(?P<afi>ip|ipv6) \s+(?P<proto>ospf|ospfv3) \s+instance-id @@ -678,7 +719,7 @@ class Ospf_interfacesTemplate(NetworkTemplate): "setval": _tmplt_ospf_int_instance, "compval": "address_family.instance", "result": { - "name": "{{ name }}", + "name": "{{ name + '.' + vif if vif is defined else name }}", "address_family": { "{{ afi }}": { "afi": '{{ "ipv4" if afi == "ip" else "ipv6" }}', @@ -695,6 +736,7 @@ class Ospf_interfacesTemplate(NetworkTemplate): \s+interfaces \s+(?P<type>\S+) \s+(?P<name>\S+) + (?:\s+vif\s+(?P<vif>\d+))? \s+(?P<afi>ip|ipv6) \s+(?P<proto>ospf|ospfv3) \s+(?P<pass>passive) @@ -704,7 +746,7 @@ class Ospf_interfacesTemplate(NetworkTemplate): "setval": _tmplt_ospf_int_passive, "compval": "address_family.passive", "result": { - "name": "{{ name }}", + "name": "{{ name + '.' + vif if vif is defined else name }}", "address_family": { "{{ afi }}": { "afi": '{{ "ipv4" if afi == "ip" else "ipv6" }}', @@ -721,12 +763,13 @@ class Ospf_interfacesTemplate(NetworkTemplate): \s+interfaces \s+(?P<type>\S+) \s+(?P<name>\S+) + (?:\s+vif\s+(?P<vif>\d+))? .*$""", re.VERBOSE, ), "setval": "set interface {{ type }} {{ name }}", "result": { - "name": "{{ name }}", + "name": "{{ name + '.' + vif if vif is defined else name }}", }, }, ] diff --git a/plugins/module_utils/network/vyos/rm_templates/route_maps.py b/plugins/module_utils/network/vyos/rm_templates/route_maps.py index 8f218a6b..c6b88f7b 100644 --- a/plugins/module_utils/network/vyos/rm_templates/route_maps.py +++ b/plugins/module_utils/network/vyos/rm_templates/route_maps.py @@ -310,12 +310,12 @@ class Route_mapsTemplate(NetworkTemplate): "name": "set_as_path_prepend", "getval": re.compile( r""" - ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\sas-path-prepend\s(?P<as>\S+) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\sas-path-prepend\s(?P<as>.*) + $""", re.VERBOSE, ), "compval": "set.as_path_prepend", - "setval": "policy route-map {{route_map}} rule {{sequence}} set as-path-prepend {{set.as_path_prepend}}", + "setval": "policy route-map {{route_map}} rule {{sequence}} set as-path-prepend '{{set.as_path_prepend}}'", "result": { "route_maps": { "{{ route_map }}": { @@ -337,10 +337,11 @@ class Route_mapsTemplate(NetworkTemplate): "name": "set_atomic_aggregate", "getval": re.compile( r""" - ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\satomic-aggregate(?P<as>) + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\s(?P<as>atomic-aggregate) *$""", re.VERBOSE, ), + "compval": "set.atomic_aggregate", "setval": "policy route-map {{route_map}} rule {{sequence}} set atomic-aggregate", "result": { "route_maps": { @@ -391,13 +392,13 @@ class Route_mapsTemplate(NetworkTemplate): "name": "set_comm_list", "getval": re.compile( r""" - ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\scomm-list\scomm-list\s(?P<comm_list>\S+) + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\scommunity\scommunity-list\s(?P<comm_list>\S+) *$""", re.VERBOSE, ), - "compval": "set.comm_list.comm_list", + "compval": "match.community.community_list", "setval": "policy route-map {{route_map}} rule {{sequence}} " - "set comm-list comm-list {{set.comm_list.comm_list}}", + "match community community-list {{set.comm_list.comm_list}}", "result": { "route_maps": { "{{ route_map }}": { @@ -406,8 +407,8 @@ class Route_mapsTemplate(NetworkTemplate): "{{sequence}}": { "sequence": "{{sequence}}", - "set": { - "comm_list": {"comm_list": "{{comm_list}}"}, + "match": { + "community": {"community_list": "{{comm_list}}"}, }, }, }, @@ -500,6 +501,62 @@ class Route_mapsTemplate(NetworkTemplate): }, }, { + "name": "set_extcommunity_bandwidth", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\sextcommunity\sbandwidth\s(?P<extcommunity_bw>\S+) + *$""", + re.VERBOSE, + ), + "compval": "set.extcommunity_bandwidth", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "set extcommunity bandwidth {{set.extcommunity_bandwidth}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "set": { + "extcommunity_bandwidth": "{{extcommunity_bw}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "set_extcommunity_bandwidth_non_transitive", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\sextcommunity\s(?P<extcommunity_bw_nt>bandwidth-non-transitive) + *$""", + re.VERBOSE, + ), + "compval": "set.extcommunity_bandwidth_non_transitive", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "set extcommunity bandwidth-non-transitive", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "set": { + "extcommunity_bandwidth_non_transitive": "{{True if extcommunity_bw_nt is defined}}", + }, + }, + }, + }, + }, + }, + }, + { "name": "set_ip_next_hop", "getval": re.compile( r""" @@ -813,6 +870,34 @@ class Route_mapsTemplate(NetworkTemplate): }, }, { + "name": "set_table", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\stable\s(?P<table>\S+) + *$""", + re.VERBOSE, + ), + "compval": "set.weight", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "set table {{set.table}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "set": { + "table": "{{table}}", + }, + }, + }, + }, + }, + }, + }, + { "name": "set_community", "getval": re.compile( r""" @@ -1261,6 +1346,33 @@ class Route_mapsTemplate(NetworkTemplate): }, }, { + "name": "match_protocol", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\sprotocol\s(?P<value>\S+) + *$""", + re.VERBOSE, + ), + "compval": "match.protocol", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "match protocol {{match.protocol}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": { + "sequence": "{{sequence}}", + "match": { + "protocol": "{{value}}", + }, + }, + }, + }, + }, + }, + }, + { "name": "match_rpki", "getval": re.compile( r""" diff --git a/plugins/module_utils/network/vyos/rm_templates/route_maps_14.py b/plugins/module_utils/network/vyos/rm_templates/route_maps_14.py new file mode 100644 index 00000000..6564280d --- /dev/null +++ b/plugins/module_utils/network/vyos/rm_templates/route_maps_14.py @@ -0,0 +1,1405 @@ +# -*- 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 Route_maps parser templates file. This contains +a list of parser definitions and associated functions that +facilitates both facts gathering and native command generation for +the given network resource. +""" + +import re + +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.network_template import ( + NetworkTemplate, +) + + +class Route_mapsTemplate14(NetworkTemplate): + def __init__(self, lines=None): + prefix = {"set": "set", "remove": "delete"} + super(Route_mapsTemplate14, self).__init__(lines=lines, tmplt=self, prefix=prefix) + + # fmt: off + PARSERS = [ + { + "name": "route_map", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+) + *$""", + re.VERBOSE, + ), + "compval": "route_map", + "setval": "policy route-map {{route_map}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + }, + }, + }, + }, + { + "name": "sequence", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+) + *$""", + re.VERBOSE, + ), + "compval": "sequence", + "setval": "policy route-map {{route_map}} rule {{sequence}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + }, + }, + }, + }, + }, + }, + { + "name": "call", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\scall\s(?P<call>\S+) + *$""", + re.VERBOSE, + ), + "setval": "policy route-map {{route_map}} rule {{sequence}} call {{call}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "call": "{{call}}", + }, + }, + }, + }, + }, + }, + { + "name": "description", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sdescription\s(?P<description>\S+) + *$""", + re.VERBOSE, + ), + "setval": "policy route-map {{route_map}} rule {{sequence}} description {{description}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "description": "{{description}}", + }, + }, + }, + }, + }, + }, + { + "name": "action", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\saction\s(?P<action>\S+) + *$""", + re.VERBOSE, + ), + "setval": "policy route-map {{route_map}} rule {{sequence}} action {{action}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "action": "{{action}}", + }, + }, + }, + }, + }, + }, + { + "name": "continue_sequence", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\scontinue\s(?P<continue>\S+) + *$""", + re.VERBOSE, + ), + "setval": "policy route-map {{route_map}} rule {{sequence}} continue {{continue_sequence}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "continue_sequence": "{{continue}}", + }, + }, + }, + }, + }, + }, + { + "name": "on_match_next", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\son-match\s(?P<next>next) + *$""", + re.VERBOSE, + ), + "compval": "on_match.next", + "setval": "policy route-map {{route_map}} rule {{sequence}} on-match next", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "on_match": { + "next": "{{True if next is defined}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "on_match_goto", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\son-match\sgoto\s(?P<goto>\S+) + *$""", + re.VERBOSE, + ), + "compval": "on_match.goto", + "setval": "policy route-map {{route_map}} rule {{sequence}} on-match goto {{on_match.goto}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "on_match": { + "goto": "{{goto}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "set_aggregator_ip", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\saggregator\sip\s(?P<ip>\S+) + *$""", + re.VERBOSE, + ), + "compval": "set.aggregator.ip", + "setval": "policy route-map {{route_map}} rule {{sequence}} set aggregator ip {{set.aggregator.ip}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "set": { + "aggregator": { + "ip": "{{ip}}", + }, + }, + }, + }, + }, + }, + }, + }, + { + "name": "set_aggregator_as", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\saggregator\sas\s(?P<as>\S+) + *$""", + re.VERBOSE, + ), + "compval": "set.aggregator.as", + "setval": "policy route-map {{route_map}} rule {{sequence}} set aggregator as {{set.aggregator.as}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "set": { + "aggregator": { + "as": "{{as}}", + }, + }, + }, + }, + }, + }, + }, + }, + { + "name": "set_as_path_exclude", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\sas-path\sexclude\s(?P<as>\S+) + *$""", + re.VERBOSE, + ), + "compval": "set.as_path_exclude", + "setval": "policy route-map {{route_map}} rule {{sequence}} set as-path exclude {{set.as_path_exclude}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "set": { + "as_path_exclude": "{{as}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "set_as_path_prepend", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\sas-path\sprepend\s(?P<as>.*) + $""", + re.VERBOSE, + ), + "compval": "set.as_path_prepend", + "setval": "policy route-map {{route_map}} rule {{sequence}} set as-path prepend '{{set.as_path_prepend}}'", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "set": { + "as_path_prepend": "{{as}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "set_atomic_aggregate", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\s(?P<as>atomic-aggregate) + *$""", + re.VERBOSE, + ), + "compval": "set.atomic_aggregate", + "setval": "policy route-map {{route_map}} rule {{sequence}} set atomic-aggregate", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "set": { + "atomic_aggregate": "{{True if as is defined}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "set_bgp_extcommunity_rt", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\sbgp-extcommunity-rt\s(?P<bgp>\S+) + *$""", + re.VERBOSE, + ), + "compval": "set.bgp_extcommunity_rt", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "set bgp-extcommunity-rt {{set.bgp_extcommunity_rt}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "set": { + "bgp_extcommunity_rt": "{{bgp}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "set_comm_list", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\scommunity\scommunity-list\s(?P<comm_list>\S+) + *$""", + re.VERBOSE, + ), + "compval": "match.community.community_list", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "match community community-list {{set.comm_list.comm_list}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "match": { + "community": {"community_list": "{{comm_list}}"}, + }, + }, + }, + }, + }, + }, + }, + { + "name": "set_comm_list_delete", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\scomm-list\sdelete(?P<delete>\S+) + *$""", + re.VERBOSE, + ), + "compval": "set.comm_list.comm_list", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "set comm-list delete", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "set": { + "comm_list": {"delete": "{{True if delete is defined}}"}, + }, + }, + }, + }, + }, + }, + }, + { + "name": "set_extcommunity_rt", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\sextcommunity\srt\s(?P<extcommunity_rt>\S+) + *$""", + re.VERBOSE, + ), + "compval": "set.extcommunity_rt", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "set extcommunity rt {{set.extcommunity_rt}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "set": { + "extcommunity_rt": "{{extcommunity_rt}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "set_extcommunity_soo", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\sextcommunity\ssoo\s(?P<extcommunity_soo>\S+) + *$""", + re.VERBOSE, + ), + "compval": "set.extcommunity_soo", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "set extcommunity soo {{set.extcommunity_soo}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "set": { + "extcommunity_soo": "{{extcommunity_soo}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "set_extcommunity_bandwidth", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\sextcommunity\sbandwidth\s(?P<extcommunity_bw>\S+) + *$""", + re.VERBOSE, + ), + "compval": "set.extcommunity_bandwidth", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "set extcommunity bandwidth {{set.extcommunity_bandwidth}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "set": { + "extcommunity_bandwidth": "{{extcommunity_bw}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "set_extcommunity_bandwidth_non_transitive", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\sextcommunity\s(?P<extcommunity_bw_nt>bandwidth-non-transitive) + *$""", + re.VERBOSE, + ), + "compval": "set.extcommunity_bandwidth_non_transitive", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "set extcommunity bandwidth-non-transitive", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "set": { + "extcommunity_bandwidth_non_transitive": "{{True if extcommunity_bw_nt is defined}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "set_ip_next_hop", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\sip-next-hop\s(?P<ip_next_hop>\S+) + *$""", + re.VERBOSE, + ), + "compval": "set.ip_next_hop", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "set ip-next-hop {{set.ip_next_hop}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "set": { + "ip_next_hop": "{{ip_next_hop}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "set_ipv6_next_hop", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\sipv6-next-hop + \s(?P<type>global|local) + \s(?P<value>\S+) + *$""", + re.VERBOSE, + ), + "compval": "set.ipv6_next_hop", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "set ipv6-next-hop {{set.ipv6_next_hop.ip_type}} {{set.ipv6_next_hop.value}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "set": { + "ipv6_next_hop": { + "ip_type": "{{type}}", + "value": "{{value}}", + }, + }, + }, + }, + }, + }, + }, + }, + { + "name": "set_large_community", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\slarge-community\s(?P<op>none|replace\s(?P<large_community>\S+)) + $""", + re.VERBOSE, + ), + "compval": "set.large_community", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "set large-community {{set.large_community if set.large_community == 'none' else 'replace ' + set.large_community}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "set": { + "large_community": "{{op if op == 'none' else large_community}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "set_local_preference", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\slocal-preference\s(?P<local_preference>\S+) + *$""", + re.VERBOSE, + ), + "compval": "set.local_preference", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "set local-preference {{set.local_preference}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "set": { + "local_preference": "{{local_preference}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "set_metric", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\smetric\s(?P<metric>\S+) + *$""", + re.VERBOSE, + ), + "compval": "set.metric", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "set metric {{set.metric}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "set": { + "metric": "{{metric}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "set_metric_type", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\smetric-type\s(?P<metric_type>\S+) + *$""", + re.VERBOSE, + ), + "compval": "set.metric_type", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "set metric-type {{set.metric_type}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "set": { + "metric_type": "{{metric_type}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "set_origin", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\sorigin\s(?P<origin>\S+) + *$""", + re.VERBOSE, + ), + "compval": "set.origin", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "set origin {{set.origin}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "set": { + "origin": "{{origin}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "set_originator_id", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\soriginator-id\s(?P<originator_id>\S+) + *$""", + re.VERBOSE, + ), + "compval": "set.originator_id", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "set originator-id {{set.originator_id}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "set": { + "originator_id": "{{originator_id}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "set_src", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\ssrc\s(?P<src>\S+) + *$""", + re.VERBOSE, + ), + "compval": "set.src", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "set src {{set.src}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "set": { + "src": "{{src}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "set_tag", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\stag\s(?P<tag>\S+) + *$""", + re.VERBOSE, + ), + "compval": "set.tag", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "set tag {{set.tag}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "set": { + "tag": "{{tag}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "set_weight", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\sweight\s(?P<weight>\S+) + *$""", + re.VERBOSE, + ), + "compval": "set.weight", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "set weight {{set.weight}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "set": { + "weight": "{{weight}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "set_table", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\stable\s(?P<table>\S+) + *$""", + re.VERBOSE, + ), + "compval": "set.weight", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "set table {{set.table}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "set": { + "table": "{{table}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "set_community", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\scommunity\s(?P<op>none|replace\s(?P<value>\S+)) + $""", + re.VERBOSE, + ), + "compval": "set.community.value", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "set community {{set.community.value if set.community.value == 'none' else 'replace ' + set.community.value}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "set": { + "community": { + "value": "{{op if op == 'none' else value}}", + }, + }, + }, + }, + }, + }, + }, + }, + { + "name": "match_as_path", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\sas-path\s(?P<as_path>\S+) + *$""", + re.VERBOSE, + ), + "compval": "match.as_path", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "match as-path {{match.as_path}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "match": { + "as_path": "{{as_path}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "match_community_community_list", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\scommunity\scommunity-list\s(?P<community_list>\S+) + *$""", + re.VERBOSE, + ), + "compval": "match.community.community_list", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "match community community-list {{match.community.community_list}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "match": { + "community": {"community_list": "{{community_list}}"}, + }, + }, + }, + }, + }, + }, + }, + { + "name": "match_community_exact_match", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\scommunity\sexact-match(?P<exact_match>) + *$""", + re.VERBOSE, + ), + "compval": "match.community.exact_match", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "match community exact-match", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "match": { + "community": {"exact_match": "{{True if exact_match is defined}}"}, + }, + }, + }, + }, + }, + }, + }, + { + "name": "match_extcommunity", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\sextcommunity\s(?P<extcommunity>\S+) + *$""", + re.VERBOSE, + ), + "compval": "match.extcommunity", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "match extcommunity {{match.extcommunity}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "match": { + "extcommunity": "{{extcommunity}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "match_interface", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\sinterface\s(?P<interface>\S+) + *$""", + re.VERBOSE, + ), + "compval": "match.interface", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "match interface {{match.interface}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "match": { + "interface": "{{interface}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "match_large_community_large_community_list", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\slarge-community\slarge-community-list\s(?P<lc>\S+) + *$""", + re.VERBOSE, + ), + "compval": "match.large_community_large_community_list", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "match large-community large-community-list {{match.large_community_large_community_list}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "match": { + "large_community_large_community_list": "{{lc}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "match_metric", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\smetric\s(?P<metric>\S+) + *$""", + re.VERBOSE, + ), + "compval": "match.metric", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "match metric {{match.metric}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "match": { + "metric": "{{metric}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "match_origin", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\sorigin\s(?P<origin>\S+) + *$""", + re.VERBOSE, + ), + "compval": "match.origin", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "match origin {{match.origin}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "match": { + "origin": "{{origin}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "match_peer", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\speer\s(?P<peer>\S+) + *$""", + re.VERBOSE, + ), + "compval": "match.peer", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "match peer {{match.peer}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": + { + "sequence": "{{sequence}}", + "match": { + "peer": "{{peer}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "match_ip_address", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\sip\saddress + \s(?P<list_type>access-list|prefix-list) + \s(?P<value>\S+) + *$""", + re.VERBOSE, + ), + "compval": "match.ip.address", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "match ip address {{match.ip.address.list_type}} {{match.ip.address.value}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": { + "sequence": "{{sequence}}", + "match": { + "ip": { + "address": { + "list_type": "{{list_type}}", + "value": "{{value}}", + }, + }, + }, + }, + }, + }, + }, + }, + }, + { + "name": "match_ip_next_hop", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\sip\snexthop + \s(?P<list_type>access-list|prefix-list) + \s(?P<value>\S+) + *$""", + re.VERBOSE, + ), + "compval": "match.ip.next_hop", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "match ip nexthop {{match.ip.next_hop.list_type}} {{match.ip.next_hop.value}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": { + "sequence": "{{sequence}}", + "match": { + "ip": { + "next_hop": { + "list_type": "{{list_type}}", + "value": "{{value}}", + }, + }, + }, + }, + }, + }, + }, + }, + }, + { + "name": "match_ip_route_source", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\sip\sroute-source + \s(?P<list_type>access-list|prefix-list) + \s(?P<value>\S+) + *$""", + re.VERBOSE, + ), + "compval": "match.ip.route_source", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "match ip route-source {{match.ip.route_source.list_type}} {{match.ip.route_source.value}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": { + "sequence": "{{sequence}}", + "match": { + "ip": { + "route_source": { + "list_type": "{{list_type}}", + "value": "{{value}}", + }, + }, + }, + }, + }, + }, + }, + }, + }, + { + "name": "match_ipv6_address", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\sipv6\saddress + \s(?P<list_type>access-list|prefix-list) + \s(?P<value>\S+) + *$""", + re.VERBOSE, + ), + "compval": "match.ipv6.address", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "match ipv6 address {{match.ipv6.address.list_type}} {{match.ipv6.address.value}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": { + "sequence": "{{sequence}}", + "match": { + "ipv6": { + "address": { + "list_type": "{{list_type}}", + "value": "{{value}}", + }, + }, + }, + }, + }, + }, + }, + }, + }, + { + "name": "match_ipv6_nexthop", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\sipv6\snexthop + \s(?P<value>\S+) + *$""", + re.VERBOSE, + ), + "compval": "match.ipv6.next_hop", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "match ipv6 nexthop {{match.ipv6.next_hop}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": { + "sequence": "{{sequence}}", + "match": { + "ipv6": { + "next_hop": "{{value}}", + }, + }, + }, + }, + }, + }, + }, + }, + { + "name": "match_protocol", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\sprotocol\s(?P<value>\S+) + *$""", + re.VERBOSE, + ), + "compval": "match.protocol", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "match protocol {{match.protocol}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": { + "sequence": "{{sequence}}", + "match": { + "protocol": "{{value}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "match_rpki", + "getval": re.compile( + r""" + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\srpki + \s(?P<value>\S+) + *$""", + re.VERBOSE, + ), + "compval": "match.rpki", + "setval": "policy route-map {{route_map}} rule {{sequence}} " + "match rpki {{match.rpki}}", + "result": { + "route_maps": { + "{{ route_map }}": { + "route_map": '{{ route_map }}', + "entries": { + "{{sequence}}": { + "sequence": "{{sequence}}", + "match": { + "rpki": "{{value}}", + }, + }, + }, + }, + }, + }, + }, + + ] + # fmt: on diff --git a/plugins/module_utils/network/vyos/utils/utils.py b/plugins/module_utils/network/vyos/utils/utils.py index 8722251e..4c371962 100644 --- a/plugins/module_utils/network/vyos/utils/utils.py +++ b/plugins/module_utils/network/vyos/utils/utils.py @@ -50,6 +50,18 @@ def get_interface_type(interface): return "dummy" +def get_interface_with_vif(interface): + """Gets virtual interface if any or return as is""" + vlan = None + interface_real = interface + if "." in interface: + interface_real, vlan = interface.split(".") + + if vlan is not None: + interface_real = interface_real + " vif " + vlan + return interface_real + + def dict_delete(base, comparable): """ This function generates a dict containing key, value pairs for keys @@ -264,3 +276,13 @@ def _in_target(h, key): :return: True/False. """ return True if h and key in h else False + + +def in_target_not_none(h, key): + """ + This function checks whether the target exist,key present in target config, and the value is not None. + :param h: target config. + :param key: attribute name. + :return: True/False. + """ + return True if h and key in h and h[key] is not None else False diff --git a/plugins/module_utils/network/vyos/vyos.py b/plugins/module_utils/network/vyos/vyos.py index 1430b1b1..6bd8daee 100644 --- a/plugins/module_utils/network/vyos/vyos.py +++ b/plugins/module_utils/network/vyos/vyos.py @@ -34,6 +34,7 @@ import json from ansible.module_utils._text import to_text from ansible.module_utils.connection import Connection, ConnectionError + _DEVICE_CONFIGS = {} @@ -68,8 +69,13 @@ def get_config(module, flags=None, format=None): flags = [] if flags is None else flags global _DEVICE_CONFIGS - if _DEVICE_CONFIGS != {}: - return _DEVICE_CONFIGS + # If _DEVICE_CONFIGS is non-empty and module.params["match"] is "none", + # return the cached device configurations. This avoids redundant calls + # to the connection when no specific match criteria are provided. + if _DEVICE_CONFIGS != {} and ( + module.params["match"] is not None and module.params["match"] == "none" + ): + return to_text(_DEVICE_CONFIGS) else: connection = get_connection(module) try: |