diff options
Diffstat (limited to 'plugins')
77 files changed, 5568 insertions, 1617 deletions
diff --git a/plugins/action/vrf.py b/plugins/action/vrf.py new file mode 120000 index 00000000..331a791f --- /dev/null +++ b/plugins/action/vrf.py @@ -0,0 +1 @@ +vyos.py
\ No newline at end of file diff --git a/plugins/cliconf/vyos.py b/plugins/cliconf/vyos.py index 5beffaa1..17fcdf24 100644 --- a/plugins/cliconf/vyos.py +++ b/plugins/cliconf/vyos.py @@ -122,7 +122,9 @@ class Cliconf(CliconfBase): out = self.send_command(command) return out - def edit_config(self, candidate=None, commit=True, replace=None, comment=None): + def edit_config( + self, candidate=None, commit=True, replace=None, diff=False, comment=None, confirm=None + ): resp = {} operations = self.get_device_operations() self.check_edit_config_capability(operations, candidate, commit, replace, comment) @@ -143,7 +145,7 @@ class Cliconf(CliconfBase): if diff_config: if commit: try: - self.commit(comment) + self.commit(comment, confirm) except AnsibleConnectionFailure as e: msg = "commit failed: %s" % e.message self.discard_changes() @@ -191,12 +193,19 @@ class Cliconf(CliconfBase): check_all=check_all, ) - def commit(self, comment=None): - if comment: - command = 'commit comment "{0}"'.format(comment) + def commit(self, comment=None, confirm=None): + if confirm: + if comment: + command = 'commit-confirm {0} comment "{1}"'.format(confirm, comment) + else: + command = 'commit-confirm {0}'.format(confirm) + self.send_command(command, "Proceed?", "\n") else: - command = "commit" - self.send_command(command) + if comment: + command = 'commit comment "{0}"'.format(comment) + else: + command = "commit" + self.send_command(command) def discard_changes(self): self.send_command("exit discard") @@ -234,7 +243,9 @@ class Cliconf(CliconfBase): set_format = candidate.startswith("set") or candidate.startswith("delete") candidate_obj = NetworkConfig(indent=4, contents=candidate) + if not set_format: + config = [c.line for c in candidate_obj.items] commands = list() # this filters out less specific lines @@ -248,6 +259,7 @@ class Cliconf(CliconfBase): candidate_commands = ["set %s" % cmd.replace(" {", "") for cmd in commands] else: + candidate_commands = str(candidate).strip().split("\n") if diff_match == "none": @@ -269,12 +281,14 @@ class Cliconf(CliconfBase): updates.append(line) elif item.startswith("delete"): + if not running_commands: updates.append(line) else: item = re.sub(r"delete", "set", item) + for entry in running_commands: - if entry.startswith(item) and line not in visited: + if re.match(rf"^{re.escape(item)}\b", entry) and line not in visited: updates.append(line) visited.add(line) diff --git a/plugins/module_utils/network/vyos/argspec/firewall_rules/firewall_rules.py b/plugins/module_utils/network/vyos/argspec/firewall_rules/firewall_rules.py index 6ae17585..d1cf4fe8 100644 --- a/plugins/module_utils/network/vyos/argspec/firewall_rules/firewall_rules.py +++ b/plugins/module_utils/network/vyos/argspec/firewall_rules/firewall_rules.py @@ -83,6 +83,7 @@ class Firewall_rulesArgs(object): # pylint: disable=R0903 "continue", "return", "jump", + "offload", "queue", "synproxy", ], @@ -210,6 +211,7 @@ class Firewall_rulesArgs(object): # pylint: disable=R0903 "required": True, "type": "int", }, + "offload_target": {"type": "str"}, "outbound_interface": { "options": { "group": {"type": "str"}, 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/argspec/vrf/__init__.py b/plugins/module_utils/network/vyos/argspec/vrf/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/plugins/module_utils/network/vyos/argspec/vrf/__init__.py diff --git a/plugins/module_utils/network/vyos/argspec/vrf/vrf.py b/plugins/module_utils/network/vyos/argspec/vrf/vrf.py new file mode 100644 index 00000000..e24fd537 --- /dev/null +++ b/plugins/module_utils/network/vyos/argspec/vrf/vrf.py @@ -0,0 +1,131 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 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 + +############################################# +# WARNING # +############################################# +# +# This file is auto generated by the +# cli_rm_builder. +# +# Manually editing this file is not advised. +# +# To update the argspec make the desired changes +# in the module docstring and re-run +# cli_rm_builder. +# +############################################# + +""" +The arg spec for the vyos_vrf module +""" + +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.bgp_global.bgp_global import ( + Bgp_globalArgs, +) +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.argspec.ospfv3.ospfv3 import ( + Ospfv3Args, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.static_routes.static_routes import ( + Static_routesArgs, +) + + +class VrfArgs(object): # pylint: disable=R0903 + """The arg spec for the vyos_vrf module""" + + bgp_argument_spec = Bgp_globalArgs.argument_spec["config"] + static_routes_argument_spec = Static_routesArgs.argument_spec["config"] + ospfv2_argument_spec = Ospfv2Args.argument_spec["config"] + ospfv3_argument_spec = Ospfv3Args.argument_spec["config"] + + argument_spec = { + "config": { + "type": "dict", + "options": { + "bind_to_all": {"type": "bool", "default": False}, + "instances": { + "type": "list", + "elements": "dict", + "options": { + "name": {"required": True, "type": "str"}, + "description": {"type": "str"}, + "disable": { + "aliases": ["disabled"], + "default": False, + "type": "bool", + }, + "table_id": {"type": "int"}, + "vni": {"type": "int"}, + "address_family": { + "type": "list", + "elements": "dict", + "options": { + "afi": { + "type": "str", + "choices": ["ipv4", "ipv6"], + }, + "disable_forwarding": {"type": "bool", "default": False}, + "nht_no_resolve_via_default": {"type": "bool", "default": False}, + "route_maps": { + "type": "list", + "elements": "dict", + "options": { + "rm_name": {"type": "str", "required": True}, + "protocol": { + "type": "str", + "choices": [ + "any", + "babel", + "bgp", + "eigrp", + "isis", + "ospf", + "rip", + "static", + ], + }, + }, + }, + }, + }, + "protocols": { + # "type": "list", # sanity + # "elements": "dict", + "type": "dict", + "options": { + "bgp": bgp_argument_spec, + "ospf": ospfv2_argument_spec, + "ospfv3": ospfv3_argument_spec, + "static": static_routes_argument_spec, + }, + }, + }, + }, + }, + }, + "state": { + "type": "str", + "choices": [ + "deleted", + "merged", + "replaced", + "overridden", + "gathered", + "rendered", + "parsed", + ], + "default": "merged", + }, + "running_config": {"type": "str"}, + } # pylint: disable=C0301 diff --git a/plugins/module_utils/network/vyos/config/bgp_address_family/bgp_address_family.py b/plugins/module_utils/network/vyos/config/bgp_address_family/bgp_address_family.py index 0e6bec81..2d6481c2 100644 --- a/plugins/module_utils/network/vyos/config/bgp_address_family/bgp_address_family.py +++ b/plugins/module_utils/network/vyos/config/bgp_address_family/bgp_address_family.py @@ -20,7 +20,6 @@ created. import re -from ansible.module_utils.six import iteritems from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module import ( ResourceModule, ) @@ -32,15 +31,14 @@ from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.facts from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.rm_templates.bgp_address_family import ( Bgp_address_familyTemplate, ) - from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.rm_templates.bgp_address_family_14 import ( Bgp_address_familyTemplate14, ) - +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 Bgp_address_family(ResourceModule): """ @@ -65,7 +63,7 @@ class Bgp_address_family(ResourceModule): self._tmplt = Bgp_address_familyTemplate() def parse(self): - """ override parse to check template """ + """override parse to check template""" self._validate_template() return super().parse() @@ -93,9 +91,11 @@ class Bgp_address_family(ResourceModule): wantd = {} haved = {} - if (self.want.get("as_number") == self.have.get("as_number") or - not self.have or - LooseVersion(get_os_version(self._module)) >= LooseVersion("1.4")): + if ( + self.want.get("as_number") == self.have.get("as_number") + or not self.have + or LooseVersion(get_os_version(self._module)) >= LooseVersion("1.4") + ): if self.want: wantd = {self.want["as_number"]: self.want} if self.have: @@ -113,16 +113,16 @@ class Bgp_address_family(ResourceModule): # if state is deleted, empty out wantd and set haved to wantd if self.state == "deleted": - for k, have in iteritems(haved): + for k, have in haved.items(): self._delete_af(wantd, have) wantd = {} if self.state == "overridden": - for k, have in iteritems(haved): + for k, have in haved.items(): if k not in wantd: self._compare(want={}, have=have) - for k, want in iteritems(wantd): + for k, want in wantd.items(): self._compare(want=want, have=haved.pop(k, {})) def _compare(self, want, have): @@ -149,23 +149,23 @@ class Bgp_address_family(ResourceModule): def _compare_af(self, want, have): waf = want.get("address_family", {}) haf = have.get("address_family", {}) - for name, entry in iteritems(waf): + for name, entry in waf.items(): self._compare_lists( entry, have=haf.get(name, {}), as_number=want["as_number"], afi=name, ) - for name, entry in iteritems(haf): + for name, entry in haf.items(): if name not in waf.keys() and self.state == "replaced": continue self._compare_lists({}, entry, as_number=have["as_number"], afi=name) def _delete_af(self, want, have): - for as_num, entry in iteritems(want): - for afi, af_entry in iteritems(entry.get("address_family", {})): + for as_num, entry in want.items(): + for afi, af_entry in entry.get("address_family", {}).items(): if have.get("address_family"): - for hafi, hentry in iteritems(have["address_family"]): + for hafi, hentry in have["address_family"].items(): if hafi == afi: self.commands.append( self._tmplt.render( @@ -177,9 +177,9 @@ class Bgp_address_family(ResourceModule): True, ), ) - for neigh, neigh_entry in iteritems(entry.get("neighbors", {})): + for neigh, neigh_entry in entry.get("neighbors", {}).items(): if have.get("neighbors"): - for hneigh, hnentry in iteritems(have["neighbors"]): + for hneigh, hnentry in have["neighbors"].items(): if hneigh == neigh: if not neigh_entry.get("address_family"): self.commands.append( @@ -239,9 +239,9 @@ class Bgp_address_family(ResourceModule): ] wneigh = want.get("neighbors", {}) hneigh = have.get("neighbors", {}) - for name, entry in iteritems(wneigh): - for afi, af_entry in iteritems(entry.get("address_family")): - for k, val in iteritems(af_entry): + for name, entry in wneigh.items(): + for afi, af_entry in entry.get("address_family").items(): + for k, val in af_entry.items(): w = { "as_number": want["as_number"], "neighbors": { @@ -268,7 +268,7 @@ class Bgp_address_family(ResourceModule): want=w, have=h, ) - for name, entry in iteritems(hneigh): + for name, entry in hneigh.items(): if name not in wneigh.keys(): # remove surplus config for overridden and replaced if self.state != "replaced": @@ -284,9 +284,9 @@ class Bgp_address_family(ResourceModule): ) continue - for hafi, haf_entry in iteritems(entry.get("address_family")): + for hafi, haf_entry in entry.get("address_family").items(): # remove surplus configs for given neighbor - replace and overridden - for k, val in iteritems(haf_entry): + for k, val in haf_entry.items(): h = { "as_number": have["as_number"], "neighbors": { @@ -317,7 +317,7 @@ class Bgp_address_family(ResourceModule): for attrib in ["redistribute", "networks", "aggregate_address"]: wdict = want.pop(attrib, {}) hdict = have.pop(attrib, {}) - for key, entry in iteritems(wdict): + for key, entry in wdict.items(): if entry != hdict.get(key, {}): self.compare( parsers=parsers, @@ -348,7 +348,7 @@ class Bgp_address_family(ResourceModule): + attrib, ) hdict = {} - for key, entry in iteritems(hdict): + for key, entry in hdict.items(): self.compare( parsers=parsers, want={}, @@ -358,7 +358,7 @@ class Bgp_address_family(ResourceModule): }, ) # de-duplicate child commands if parent command is present - for val in (self.commands): + for val in self.commands: for val2 in self.commands: if val != val2 and val2.startswith(val): self.commands.remove(val2) @@ -366,13 +366,11 @@ class Bgp_address_family(ResourceModule): def _compare_asn(self, want, have): if want.get("as_number") and not have.get("as_number"): self.commands.append( - "set protocols bgp " - + "system-as " - + str(want.get("as_number")), + "set protocols bgp " + "system-as " + str(want.get("as_number")), ) def _bgp_af_list_to_dict(self, entry): - for name, proc in iteritems(entry): + for name, proc in entry.items(): if "address_family" in proc: af_dict = {} for entry in proc.get("address_family"): diff --git a/plugins/module_utils/network/vyos/config/bgp_global/bgp_global.py b/plugins/module_utils/network/vyos/config/bgp_global/bgp_global.py index 91a5af12..075c8fd2 100644 --- a/plugins/module_utils/network/vyos/config/bgp_global/bgp_global.py +++ b/plugins/module_utils/network/vyos/config/bgp_global/bgp_global.py @@ -18,7 +18,6 @@ necessary to bring the current configuration to its desired end-state is created. """ -from ansible.module_utils.six import iteritems from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module import ( ResourceModule, ) @@ -118,10 +117,10 @@ class Bgp_global(ResourceModule): # if state is deleted, empty out wantd and set haved to wantd if self.state == "purged": h_del = {} - for k, v in iteritems(haved): + for k, v in haved.items(): if k in wantd or not wantd: h_del.update({k: v}) - for num, entry in iteritems(h_del): + for num, entry in h_del.items(): self.commands.append(self._tmplt.render({"as_number": num}, "router", True)) wantd = {} @@ -129,7 +128,7 @@ class Bgp_global(ResourceModule): self._compare(want={}, have=self.have) wantd = {} - for k, want in iteritems(wantd): + for k, want in wantd.items(): self._compare(want=want, have=haved.pop(k, {})) def _compare(self, want, have): @@ -144,7 +143,7 @@ class Bgp_global(ResourceModule): parsers = ["maximum_paths", "timers"] self._compare_neighbor(want, have) self._compare_bgp_params(want, have) - for name, entry in iteritems(want): + for name, entry in want.items(): if name != "as_number": self.compare( parsers=parsers, @@ -154,7 +153,7 @@ class Bgp_global(ResourceModule): name: have.pop(name, {}), }, ) - for name, entry in iteritems(have): + for name, entry in have.items(): if name != "as_number": self.compare( parsers=parsers, @@ -217,7 +216,7 @@ class Bgp_global(ResourceModule): hneigh = have.pop("neighbor", {}) self._compare_neigh_lists(wneigh, hneigh) - for name, entry in iteritems(wneigh): + for name, entry in wneigh.items(): for k, v in entry.items(): if k == "address": continue @@ -233,7 +232,7 @@ class Bgp_global(ResourceModule): }, have={"as_number": want["as_number"], "neighbor": h}, ) - for name, entry in iteritems(hneigh): + for name, entry in hneigh.items(): if name not in wneigh.keys(): if self._check_af(name): msg = "Use the _bgp_address_family module to delete the address_family under neighbor {0}, before replacing/deleting the neighbor.".format( @@ -281,7 +280,7 @@ class Bgp_global(ResourceModule): wbgp = want.pop("bgp_params", {}) hbgp = have.pop("bgp_params", {}) - for name, entry in iteritems(wbgp): + for name, entry in wbgp.items(): if name == "confederation": if entry != hbgp.pop(name, {}): self.addcmd( @@ -325,7 +324,7 @@ class Bgp_global(ResourceModule): if not wbgp and hbgp: self.commands.append("delete protocols bgp" + self._asn_mod + " parameters") hbgp = {} - for name, entry in iteritems(hbgp): + for name, entry in hbgp.items(): if name == "confederation": self.commands.append( "delete protocols bgp" + self._asn_mod + " parameters confederation", @@ -362,7 +361,7 @@ class Bgp_global(ResourceModule): ]: wdict = want.pop(attrib, {}) hdict = have.pop(attrib, {}) - for key, entry in iteritems(wdict): + for key, entry in wdict.items(): if entry != hdict.pop(key, {}): self.addcmd(entry, "neighbor.{0}".format(attrib), False) # remove remaining items in have for replaced @@ -370,7 +369,7 @@ class Bgp_global(ResourceModule): self.addcmd(entry, "neighbor.{0}".format(attrib), True) def _bgp_global_list_to_dict(self, entry): - for name, proc in iteritems(entry): + for name, proc in entry.items(): if "neighbor" in proc: neigh_dict = {} for entry in proc.get("neighbor", []): 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 e2a25e32..d4e173c1 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 @@ -17,7 +17,6 @@ __metaclass__ = type from copy import deepcopy -from ansible.module_utils.six import iteritems from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import ( ConfigBase, ) @@ -28,13 +27,16 @@ 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, + list_diff_want_only, +) +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, ) - -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): @@ -75,6 +77,13 @@ class Firewall_global(ConfigBase): warnings = list() commands = list() + try: + self._module.params["comment"] + except KeyError: + comment = [] + else: + comment = self._module.params["comment"] + if self.state in self.ACTION_STATES: existing_firewall_global_facts = self.get_firewall_global_facts() else: @@ -83,6 +92,12 @@ class Firewall_global(ConfigBase): if self.state in self.ACTION_STATES or self.state == "rendered": commands.extend(self.set_config(existing_firewall_global_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) @@ -190,7 +205,7 @@ class Firewall_global(ConfigBase): "twa_hazards_protection", ) if want: - for key, val in iteritems(want): + for key, val in want.items(): if val and key in b_set and not have: commands.append(self._form_attr_cmd(attr=key, opr=False)) elif val and key in b_set and have and key in have and have[key] != val: @@ -200,7 +215,7 @@ class Firewall_global(ConfigBase): elif not want and have: commands.append(self._compute_command(opr=False)) elif have: - for key, val in iteritems(have): + for key, val in have.items(): if val and key in b_set: commands.append(self._form_attr_cmd(attr=key, opr=False)) else: @@ -247,7 +262,7 @@ class Firewall_global(ConfigBase): "twa_hazards_protection", ) if w_fg: - for key, val in iteritems(w_fg): + for key, val in w_fg.items(): if opr and key in l_set and not (h and self._is_w_same(w_fg, h, key)): commands.append( self._form_attr_cmd(attr=key, val=self._bool_to_str(val), opr=opr), @@ -258,11 +273,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), ) @@ -285,13 +296,13 @@ class Firewall_global(ConfigBase): if h: h_ping = h.get(attr) or {} if self._is_root_del(w[attr], h_ping, attr): - for item, value in iteritems(h[attr]): + for item, value in h[attr].items(): if not opr and item in l_set: commands.append(self._form_attr_cmd(attr=item, opr=opr)) elif w[attr]: if h and attr in h.keys(): h_ping = h.get(attr) or {} - for item, value in iteritems(w[attr]): + for item, value in w[attr].items(): if ( opr and item in l_set @@ -355,7 +366,7 @@ class Firewall_global(ConfigBase): cmd = self._compute_command(key="group", attr="ipv6-" + attr, opr=opr) else: cmd = self._compute_command(key="group", attr=attr, opr=opr) - for key, val in iteritems(want): + for key, val in want.items(): if val: if opr and key in l_set and not (h and self._is_w_same(want, h, key)): if key == "name": @@ -373,9 +384,17 @@ class Firewall_global(ConfigBase): ) elif not opr and key in l_set: if key == "name" and self._is_grp_del(h, want, key): + if len(commands) > 0 and commands[-1] == cmd + " " + want["name"] + " " + self._grp_type( + attr, + ): + commands.pop() commands.append(cmd + " " + want["name"]) continue - if not (h and in_target_not_none(h, key)) and not self._is_grp_del(h, want, "name"): + 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( @@ -435,6 +454,10 @@ 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): @@ -470,10 +493,12 @@ class Firewall_global(ConfigBase): if want: for w in want: h = self.search_attrib_in_have(have, w, "connection_type") - for key, val in iteritems(w): + for key, val in w.items(): 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"], @@ -499,7 +524,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( @@ -531,23 +558,23 @@ 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 - for key, val in iteritems(w): - if val and key != "afi": + for key, val in w.items(): + if val is not None and key != "afi": if opr and key in l_set and not (h and self._is_w_same(w, h, key)): commands.append( self._form_attr_cmd( attr=key, val=self._bool_to_str(val), opr=opr, - type=afi + type=afi, ), ) elif not opr and key in l_set: @@ -557,7 +584,7 @@ class Firewall_global(ConfigBase): attr=key, val=self._bool_to_str(val), opr=opr, - type=afi + type=afi, ), ) continue @@ -567,7 +594,7 @@ class Firewall_global(ConfigBase): attr=key, val=self._bool_to_str(val), opr=opr, - type=afi + type=afi, ), ) elif key == "icmp_redirects": @@ -587,20 +614,25 @@ 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]: if h and attr in h.keys(): h_red = h.get(attr) or {} - for item, value in iteritems(w[attr]): + for item, value in w[attr].items(): 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 @@ -634,7 +666,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): @@ -651,14 +688,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 bb6055b7..3c768e32 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 @@ -17,7 +17,6 @@ __metaclass__ = type from copy import deepcopy -from ansible.module_utils.six import iteritems from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import ( ConfigBase, ) @@ -315,7 +314,7 @@ class Firewall_rules(ConfigBase): h_rs = deepcopy(remove_empties(have)) h_rules = h_rs.pop("rules", None) if w_rs: - for key, val in iteritems(w_rs): + for key, val in w_rs.items(): if opr and key in l_set and not (h_rs and self._is_w_same(w_rs, h_rs, key)): if key == "enable_default_log": if val and (not h_rs or key not in h_rs or not h_rs[key]): @@ -359,6 +358,7 @@ class Firewall_rules(ConfigBase): "disable", "description", "jump_target", + "offload_target", ) if w_rules: for w in w_rules: @@ -366,7 +366,7 @@ class Firewall_rules(ConfigBase): h = self.search_rules_in_have_rs(h_rules, w["number"]) if w != h and self.state == "replaced": h = {} - for key, val in iteritems(w): + for key, val in w.items(): if val: if opr and key in l_set and not (h and self._is_w_same(w, h, key)): if key == "disable": @@ -464,7 +464,7 @@ class Firewall_rules(ConfigBase): if w[attr]: if h and attr in h.keys(): h_state = h.get(attr) or {} - for item, val in iteritems(w[attr]): + for item, val in w[attr].items(): if ( opr and item in l_set @@ -527,7 +527,7 @@ class Firewall_rules(ConfigBase): if w[attr]: if h and attr in h.keys(): h_recent = h.get(attr) or {} - for item, val in iteritems(w[attr]): + for item, val in w[attr].items(): if ( opr and item in l_set @@ -555,7 +555,7 @@ class Firewall_rules(ConfigBase): if w[attr]: if h and attr in h.keys(): h_icmp = h.get(attr) or {} - for item, val in iteritems(w[attr]): + for item, val in w[attr].items(): if ( opr and item in l_set @@ -598,7 +598,7 @@ class Firewall_rules(ConfigBase): if w[attr]: if h and attr in h.keys(): h_if = h.get(attr) or {} - for item, val in iteritems(w[attr]): + for item, val in w[attr].items(): if opr and item in l_set and not (h_if and self._is_w_same(w[attr], h_if, item)): commands.append( cmd @@ -633,7 +633,7 @@ class Firewall_rules(ConfigBase): if w[attr]: if h and attr in h.keys(): h_time = h.get(attr) or {} - for item, val in iteritems(w[attr]): + for item, val in w[attr].items(): if ( opr and item in l_set @@ -862,7 +862,7 @@ class Firewall_rules(ConfigBase): h_group = {} if h and h.get(attr) and key in h[attr].keys(): h_group = h[attr].get(key) - for item, val in iteritems(group): + for item, val in group.items(): if val: if ( opr @@ -1167,11 +1167,12 @@ class Firewall_rules(ConfigBase): return True elif isinstance(w, list) and isinstance(rs, list): try: + def comparison(x): - if 'name' in x: - return x['name'] - if 'number' in x: - return x['number'] + if "name" in x: + return x["name"] + if "number" in x: + return x["number"] return str(x) sorted_list1 = sorted(w, key=comparison) diff --git a/plugins/module_utils/network/vyos/config/interfaces/interfaces.py b/plugins/module_utils/network/vyos/config/interfaces/interfaces.py index a9d9307c..0a55564e 100644 --- a/plugins/module_utils/network/vyos/config/interfaces/interfaces.py +++ b/plugins/module_utils/network/vyos/config/interfaces/interfaces.py @@ -16,7 +16,6 @@ __metaclass__ = type from copy import deepcopy -from ansible.module_utils.six import iteritems from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import ( ConfigBase, ) @@ -227,7 +226,7 @@ class Interfaces(ConfigBase): updates = dict_diff(have_copy, want_copy) if updates: - for key, value in iteritems(updates): + for key, value in updates.items(): commands.append( self._compute_commands(key=key, value=value, interface=want_copy["name"]), ) @@ -243,7 +242,7 @@ class Interfaces(ConfigBase): vif_updates = dict_diff(have_vif, want_vif) if vif_updates: - for key, value in iteritems(vif_updates): + for key, value in vif_updates.items(): commands.append( self._compute_commands( key=key, diff --git a/plugins/module_utils/network/vyos/config/l3_interfaces/l3_interfaces.py b/plugins/module_utils/network/vyos/config/l3_interfaces/l3_interfaces.py index 6e0c005f..a23494cd 100644 --- a/plugins/module_utils/network/vyos/config/l3_interfaces/l3_interfaces.py +++ b/plugins/module_utils/network/vyos/config/l3_interfaces/l3_interfaces.py @@ -19,7 +19,6 @@ __metaclass__ = type from copy import deepcopy -from ansible.module_utils.six import iteritems from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import ( ConfigBase, ) @@ -80,7 +79,7 @@ class L3_interfaces(ConfigBase): commands = list() if self.state in self.ACTION_STATES: - existing_l3_interfaces_facts = self.get_l3_interfaces_facts() + existing_l3_interfaces_facts = self.mutate_autoconfig(self.get_l3_interfaces_facts()) else: existing_l3_interfaces_facts = [] @@ -96,16 +95,19 @@ class L3_interfaces(ConfigBase): result["commands"] = commands if self.state in self.ACTION_STATES or self.state == "gathered": - changed_l3_interfaces_facts = self.get_l3_interfaces_facts() + changed_l3_interfaces_facts = self.mutate_autoconfig(self.get_l3_interfaces_facts()) elif self.state == "rendered": result["rendered"] = commands elif self.state == "parsed": running_config = self._module.params["running_config"] + if not running_config: self._module.fail_json( msg="value of running_config parameter must not be empty for state parsed", ) - result["parsed"] = self.get_l3_interfaces_facts(data=running_config) + result["parsed"] = self.mutate_autoconfig( + self.get_l3_interfaces_facts(data=running_config), + ) else: changed_l3_interfaces_facts = [] @@ -129,6 +131,7 @@ class L3_interfaces(ConfigBase): """ want = self._module.params["config"] have = existing_l3_interfaces_facts + resp = self.set_state(want, have) return to_list(resp) @@ -174,6 +177,7 @@ class L3_interfaces(ConfigBase): elif state == "replaced": commands.extend(self._state_replaced(item, obj_in_have)) + commands = [command.replace("auto-config", "autoconf") for command in commands] return commands def _state_replaced(self, want, have): @@ -226,7 +230,7 @@ class L3_interfaces(ConfigBase): have_vifs = have_copy.pop("vifs", []) for update in self._get_updates(want_copy, have_copy): - for key, value in iteritems(update): + for key, value in update.items(): commands.append( self._compute_commands(key=key, value=value, interface=want_copy["name"]), ) @@ -238,7 +242,7 @@ class L3_interfaces(ConfigBase): have_vif = {} for update in self._get_updates(want_vif, have_vif): - for key, value in iteritems(update): + for key, value in update.items(): commands.append( self._compute_commands( key=key, @@ -247,7 +251,6 @@ class L3_interfaces(ConfigBase): vif=want_vif["vlan_id"], ), ) - return commands def _state_deleted(self, want, have): @@ -261,51 +264,73 @@ class L3_interfaces(ConfigBase): want_copy = deepcopy(remove_empties(want)) have_copy = deepcopy(have) - want_vifs = want_copy.pop("vifs", []) - have_vifs = have_copy.pop("vifs", []) - - for update in self._get_updates(have_copy, want_copy): - for key, value in iteritems(update): + if have_copy is not None: + if all(v in (None, {}, []) for k, v in want_copy.items() if k != "name"): commands.append( self._compute_commands( - key=key, - value=value, + key=None, + value=None, interface=want_copy["name"], remove=True, ), ) - - if have_vifs: - for have_vif in have_vifs: - want_vif = search_obj_in_list(have_vif["vlan_id"], want_vifs, key="vlan_id") - if not want_vif: - want_vif = {"vlan_id": have_vif["vlan_id"]} - - for update in self._get_updates(have_vif, want_vif): - for key, value in iteritems(update): - commands.append( - self._compute_commands( - key=key, - interface=want_copy["name"], - value=value, - vif=want_vif["vlan_id"], - remove=True, - ), - ) + return commands + + want_vifs = want_copy.pop("vifs", []) + have_vifs = have_copy.pop("vifs", []) + + if have_vifs: + for have_vif in have_vifs: + want_vif = search_obj_in_list(have_vif["vlan_id"], want_vifs, key="vlan_id") + if not want_vif: + want_vif = {"vlan_id": have_vif["vlan_id"]} + + for update in self._get_updates(have_vif, want_vif): + for key, value in update.items(): + commands.append( + self._compute_commands( + key=key, + interface=want_copy["name"], + value=value, + vif=want_vif["vlan_id"], + remove=True, + ), + ) + + for update in self._get_updates(have_copy, want_copy): + for key, value in update.items(): + commands.append( + self._compute_commands( + key=key, + value=value, + interface=want_copy["name"], + remove=True, + ), + ) return commands def _compute_commands(self, interface, key, vif=None, value=None, remove=False): - intf_context = "interfaces {0} {1}".format(get_interface_type(interface), interface) + if value == "auto-config" and vif is None: + intf_context = "interfaces {0} {1} ipv6".format( + get_interface_type(interface), + interface, + ) + else: + intf_context = "interfaces {0} {1}".format(get_interface_type(interface), interface) + set_cmd = "set {0}".format(intf_context) del_cmd = "delete {0}".format(intf_context) if vif: - set_cmd = set_cmd + (" vif {0}".format(vif)) - del_cmd = del_cmd + (" vif {0}".format(vif)) + suffix = " ipv6" if value == "auto-config" else "" + set_cmd += f" vif {vif}{suffix}" + del_cmd += f" vif {vif}{suffix}" - if remove: + if remove and key and value: command = "{0} {1} '{2}'".format(del_cmd, key, value) + elif remove and not (key and value): + command = "{0}".format(del_cmd) else: command = "{0} {1} '{2}'".format(set_cmd, key, value) @@ -318,3 +343,12 @@ class L3_interfaces(ConfigBase): updates.extend(diff_list_of_dicts(want.get("ipv6", []), have.get("ipv6", []))) return updates + + def mutate_autoconfig(self, obj): + if isinstance(obj, dict): + return dict(map(lambda kv: (kv[0], self.mutate_autoconfig(kv[1])), obj.items())) + if isinstance(obj, list): + return list(map(self.mutate_autoconfig, obj)) + if isinstance(obj, str): + return obj.replace("autoconf", "auto-config") + return obj diff --git a/plugins/module_utils/network/vyos/config/lag_interfaces/lag_interfaces.py b/plugins/module_utils/network/vyos/config/lag_interfaces/lag_interfaces.py index 6890fe0c..62270503 100644 --- a/plugins/module_utils/network/vyos/config/lag_interfaces/lag_interfaces.py +++ b/plugins/module_utils/network/vyos/config/lag_interfaces/lag_interfaces.py @@ -12,7 +12,7 @@ from __future__ import absolute_import, division, print_function __metaclass__ = type -from ansible.module_utils.six import iteritems + from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import ( ConfigBase, ) @@ -245,7 +245,7 @@ class Lag_interfaces(ConfigBase): commands.extend(self._add_bond_members(want, have)) if updates: - for key, value in iteritems(updates): + for key, value in updates.items(): if value: if key == "arp_monitor": commands.extend(self._add_arp_monitor(updates, key, want, have)) diff --git a/plugins/module_utils/network/vyos/config/lldp_global/lldp_global.py b/plugins/module_utils/network/vyos/config/lldp_global/lldp_global.py index 1dfd25e4..39724f1b 100644 --- a/plugins/module_utils/network/vyos/config/lldp_global/lldp_global.py +++ b/plugins/module_utils/network/vyos/config/lldp_global/lldp_global.py @@ -12,7 +12,7 @@ from __future__ import absolute_import, division, print_function __metaclass__ = type -from ansible.module_utils.six import iteritems + from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import ( ConfigBase, ) @@ -241,7 +241,7 @@ class Lldp_global(ConfigBase): commands.extend(self._add_management_addresses(want, have)) if updates: - for key, value in iteritems(updates): + for key, value in updates.items(): if value is not None: if key == "enable": if value is False: diff --git a/plugins/module_utils/network/vyos/config/lldp_interfaces/lldp_interfaces.py b/plugins/module_utils/network/vyos/config/lldp_interfaces/lldp_interfaces.py index 2fd6a548..97fcbce5 100644 --- a/plugins/module_utils/network/vyos/config/lldp_interfaces/lldp_interfaces.py +++ b/plugins/module_utils/network/vyos/config/lldp_interfaces/lldp_interfaces.py @@ -16,7 +16,6 @@ from __future__ import absolute_import, division, print_function __metaclass__ = type -from ansible.module_utils.six import iteritems from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import ( ConfigBase, ) @@ -285,7 +284,7 @@ class Lldp_interfaces(ConfigBase): have_dict = have_location_type.get("coordinate_based") or {} location_type = "coordinate-based" updates = dict_diff(have_dict, want_dict) - for key, value in iteritems(updates): + for key, value in updates.items(): if value: commands.append(self._compute_command(set_cmd + location_type, key, str(value))) @@ -319,7 +318,7 @@ class Lldp_interfaces(ConfigBase): if is_dict_element_present(have_location_type, "coordinate_based"): have_dict = have_location_type.get("coordinate_based") or {} location_type = "coordinate-based" - for key, value in iteritems(have_dict): + for key, value in have_dict.items(): only_in_have = key_value_in_dict(key, value, want_dict) if not only_in_have: commands.append( diff --git a/plugins/module_utils/network/vyos/config/logging_global/logging_global.py b/plugins/module_utils/network/vyos/config/logging_global/logging_global.py index f94c9195..35a2624a 100644 --- a/plugins/module_utils/network/vyos/config/logging_global/logging_global.py +++ b/plugins/module_utils/network/vyos/config/logging_global/logging_global.py @@ -20,7 +20,6 @@ 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, ) @@ -92,7 +91,7 @@ class Logging_global(ResourceModule): if self.state in ["overridden", "replaced"]: if wantd != haved: wantx, havex = self.call_op(wantd, haved, "overridden") - for k, have in iteritems(havex): + for k, have in havex.items(): if k not in wantx: self._compare(want={}, have=have) @@ -102,7 +101,7 @@ class Logging_global(ResourceModule): if self.state == "merged": wantd = dict_merge(haved, wantd) - for k, want in iteritems(wantd): + for k, want in wantd.items(): self._compare(want=want, have=haved.pop(k, {})) def _compare(self, want, have): @@ -116,12 +115,12 @@ class Logging_global(ResourceModule): def operation_rep(self, params): op_val = dict() - for k, val in iteritems(params): + for k, val in params.items(): if k in ["console", "global_params"]: mod_val = deepcopy(val) op_val.update(self.flatten_facility({k: mod_val})) elif k in ["files", "hosts", "users"]: - for m, n in iteritems(val): + for m, n in val.items(): mod_n = deepcopy(n) if mod_n.get("archive"): del mod_n["archive"] @@ -160,18 +159,18 @@ class Logging_global(ResourceModule): def flatten_facility(self, param): temp_param = dict() - for element, val in iteritems(param): + for element, val in param.items(): if element in ["console", "global_params", "syslog"]: if element != "syslog" and val.get("facilities"): - for k, v in iteritems(val.get("facilities")): + for k, v in val.get("facilities").items(): temp_param[k + element] = {element: {"facilities": v}} del val["facilities"] if val: temp_param[element] = {element: val} if element in ["files", "hosts", "users"]: - for k, v in iteritems(val): + for k, v in val.items(): if v.get("facilities"): - for pk, dat in iteritems(v.get("facilities")): + for pk, dat in v.get("facilities").items(): temp_param[pk + k] = { element: { "facilities": dat, @@ -197,7 +196,7 @@ class Logging_global(ResourceModule): "hosts": "hostname", "users": "username", } - for element, val in iteritems(param): + for element, val in param.items(): if element == "facilities": # only with recursion call _tem_par = {} for par in val: diff --git a/plugins/module_utils/network/vyos/config/ntp_global/ntp_global.py b/plugins/module_utils/network/vyos/config/ntp_global/ntp_global.py index 5d294063..06ec1d6b 100644 --- a/plugins/module_utils/network/vyos/config/ntp_global/ntp_global.py +++ b/plugins/module_utils/network/vyos/config/ntp_global/ntp_global.py @@ -18,7 +18,6 @@ necessary to bring the current configuration to its desired end-state is created. """ -from ansible.module_utils.six import iteritems from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module import ( ResourceModule, ) @@ -93,16 +92,16 @@ class Ntp_global(ResourceModule): # if state is deleted, empty out wantd and set haved to wantd if self.state == "deleted": - haved = {k: v for k, v in iteritems(haved) if k in wantd or not wantd} + haved = {k: v for k, v in haved.items() if k in wantd or not wantd} wantd = {} commandlist = self._commandlist(haved) servernames = self._servernames(haved) # removing the servername and commandlist from the list after deleting it from haved # iterate through the top-level items to delete - for k, have in iteritems(haved): + for k, have in haved.items(): if k not in wantd: - for hk, hval in iteritems(have): + for hk, hval in have.items(): if hk == "allow_clients" and hk in commandlist: self.commands.append( self._tmplt.render({"": hk}, "allow_clients_delete", True), @@ -130,7 +129,7 @@ class Ntp_global(ResourceModule): commandlist = self._commandlist(haved) servernames = self._servernames(haved) - for k, have in iteritems(haved): + for k, have in haved.items(): if k not in wantd: if "server" not in have: self._compareoverride(want={}, have=have) @@ -139,7 +138,7 @@ class Ntp_global(ResourceModule): self._compareoverride(want={}, have=have) servernames.remove(have["server"]) - for k, want in iteritems(wantd): + for k, want in wantd.items(): self._compare(want=want, have=haved.pop(k, {})) def _compare(self, want, have): @@ -155,7 +154,7 @@ class Ntp_global(ResourceModule): def _compareoverride(self, want, have): # do not delete configuration with options level - for i, val in iteritems(have): + for i, val in have.items(): if i == "options": pass else: @@ -163,12 +162,12 @@ class Ntp_global(ResourceModule): def _ntp_list_to_dict(self, entry): servers_dict = {} - for k, data in iteritems(entry): + for k, data in entry.items(): if k == "servers": for value in data: if "options" in value: result = self._serveroptions_list_to_dict(value) - for res, resvalue in iteritems(result): + for res, resvalue in result.items(): servers_dict.update({res: resvalue}) else: servers_dict.update({value["server"]: value}) @@ -179,7 +178,7 @@ class Ntp_global(ResourceModule): def _serveroptions_list_to_dict(self, entry): serveroptions_dict = {} - for Opk, Op in iteritems(entry): + for Opk, Op in entry.items(): if Opk == "options": for val in Op: dict = {} @@ -190,16 +189,16 @@ class Ntp_global(ResourceModule): def _commandlist(self, haved): commandlist = [] - for k, have in iteritems(haved): - for ck, cval in iteritems(have): + for k, have in haved.items(): + for ck, cval in have.items(): if ck != "options" and ck not in commandlist: commandlist.append(ck) return commandlist def _servernames(self, haved): servernames = [] - for k, have in iteritems(haved): - for sk, sval in iteritems(have): + for k, have in haved.items(): + for sk, sval in have.items(): if sk != "options" and sval not in servernames: servernames.append(sval) return servernames diff --git a/plugins/module_utils/network/vyos/config/ospf_interfaces/ospf_interfaces.py b/plugins/module_utils/network/vyos/config/ospf_interfaces/ospf_interfaces.py index 51b47494..837a2ddf 100644 --- a/plugins/module_utils/network/vyos/config/ospf_interfaces/ospf_interfaces.py +++ b/plugins/module_utils/network/vyos/config/ospf_interfaces/ospf_interfaces.py @@ -17,7 +17,6 @@ necessary to bring the current configuration to its desired end-state is created. """ -from ansible.module_utils.six import iteritems from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module import ( ResourceModule, ) @@ -27,17 +26,16 @@ 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.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_interfaces(ResourceModule): """ @@ -77,7 +75,7 @@ class Ospf_interfaces(ResourceModule): self._tmplt = Ospf_interfacesTemplate() def parse(self): - """ override parse to check template """ + """override parse to check template""" self._validate_template() return super().parse() @@ -119,12 +117,12 @@ class Ospf_interfaces(ResourceModule): # if state is deleted, empty out wantd and set haved to wantd if self.state == "deleted": h_del = {} - for k, v in iteritems(haved): + for k, v in haved.items(): if k in wantd or not wantd: h_del.update({k: v}) haved = h_del have_int = [] - for k, have in iteritems(haved): + for k, have in haved.items(): if k in wantd: have_int.append(k) self._remove_ospf_int(have) @@ -132,7 +130,7 @@ class Ospf_interfaces(ResourceModule): if self.state == "overridden": have_int = [] - for k, have in iteritems(haved): + for k, have in haved.items(): if k not in wantd: have_int.append(k) self._remove_ospf_int(have) @@ -142,17 +140,17 @@ class Ospf_interfaces(ResourceModule): # removing the interfaces from haved that are already negated for interface in have_int: haved.pop(interface) - for k, have in iteritems(haved): + for k, have in haved.items(): if k not in wantd: self._compare(want={}, have=have) - for k, want in iteritems(wantd): + for k, want in wantd.items(): self._compare(want=want, have=haved.pop(k, {})) def _remove_ospf_int(self, entry): int_name = entry.get("name", {}) int_addr = entry.get("address_family", {}) - for k, addr in iteritems(int_addr): + for k, addr in int_addr.items(): rem_entry = {"name": int_name, "address_family": {"afi": k}} self.addcmd(rem_entry, "ip_ospf", True) @@ -169,8 +167,8 @@ class Ospf_interfaces(ResourceModule): hdict = have.get("address_family", {}) wname = want.get("name") hname = have.get("name") - for name, entry in iteritems(wdict): - for key, param in iteritems(entry): + for name, entry in wdict.items(): + for key, param in entry.items(): w_addr = {"afi": name, key: param} h_addr = {} if hdict.get(name): @@ -178,8 +176,8 @@ class Ospf_interfaces(ResourceModule): w = {"name": wname, "address_family": w_addr} h = {"name": hname, "address_family": h_addr} self.compare(parsers=self.parsers, want=w, have=h) - for name, entry in iteritems(hdict): - for key, param in iteritems(entry): + for name, entry in hdict.items(): + for key, param in entry.items(): h_addr = {"afi": name, key: param} w_addr = {} w = {"name": wname, "address_family": w_addr} @@ -187,7 +185,7 @@ class Ospf_interfaces(ResourceModule): self.compare(parsers=self.parsers, want=w, have=h) def _ospf_int_list_to_dict(self, entry): - for name, family in iteritems(entry): + for name, family in entry.items(): if "address_family" in family: addr_dict = {} for entry in family.get("address_family", []): diff --git a/plugins/module_utils/network/vyos/config/ospfv2/ospfv2.py b/plugins/module_utils/network/vyos/config/ospfv2/ospfv2.py index ababc6f1..ed973179 100644 --- a/plugins/module_utils/network/vyos/config/ospfv2/ospfv2.py +++ b/plugins/module_utils/network/vyos/config/ospfv2/ospfv2.py @@ -17,7 +17,6 @@ __metaclass__ = type from copy import deepcopy -from ansible.module_utils.six import iteritems from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import ( ConfigBase, ) @@ -33,10 +32,11 @@ 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.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 Ospfv2(ConfigBase): """ @@ -222,7 +222,7 @@ class Ospfv2(ConfigBase): w = deepcopy(remove_empties(want)) leaf = ("default_metric", "log_adjacency_changes") if w: - for key, val in iteritems(w): + for key, val in w.items(): if opr and key in leaf and not _is_w_same(w, have, key): commands.append(self._form_attr_cmd(attr=key, val=_bool_to_str(val), opr=opr)) elif not opr and key in leaf and not _in_target(have, key): @@ -290,7 +290,7 @@ class Ospfv2(ConfigBase): ), } leaf = leaf_dict[attr] - for item, value in iteritems(want[attr]): + for item, value in want[attr].items(): if opr and item in leaf and not _is_w_same(want[attr], h, item): if item == "enabled": item = "enable" @@ -336,10 +336,22 @@ 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" + 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) @@ -352,10 +364,21 @@ class Ospfv2(ConfigBase): cmd + attr.replace("_", "-") + " " + member["address"], ) elif member not in h: - if attr == "passive_interface" and member != "default" and LooseVersion(get_os_version(self._module)) >= LooseVersion("1.4"): + 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" + 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: @@ -394,7 +417,7 @@ class Ospfv2(ConfigBase): commands.append(cmd + attr.replace("_", "-")) elif w: for w_item in w: - for key, val in iteritems(w_item): + for key, val in w_item.items(): if not cmd: cmd = self._compute_command(opr=opr) h_item = self.search_obj_in_have(h, w_item, name[attr]) @@ -502,7 +525,7 @@ class Ospfv2(ConfigBase): commands.append(self._compute_command(attr=attr, opr=opr)) elif w: for w_item in w: - for key, val in iteritems(w_item): + for key, val in w_item.items(): if not cmd: cmd = self._compute_command(opr=opr) h_item = self.search_obj_in_have(h, w_item, name[attr]) @@ -599,7 +622,7 @@ class Ospfv2(ConfigBase): leaf = leaf_dict[attr] if h and key in h.keys(): h_attrib = h.get(key) or {} - for item, val in iteritems(w[key]): + for item, val in w[key].items(): if opr and item in leaf and not _is_w_same(w[key], h_attrib, item): if item in ("administrative", "always") and val: commands.append( @@ -660,7 +683,7 @@ class Ospfv2(ConfigBase): self._form_attr_cmd(key="area", attr=w_area["area_id"], opr=opr), ) else: - for key, val in iteritems(w_area): + for key, val in w_area.items(): if opr and key in l_set and not _is_w_same(w_area, h_area, key): if key == "area_id": commands.append( @@ -733,7 +756,7 @@ class Ospfv2(ConfigBase): if w_area: if h_type and key in h_type.keys(): h_area = h_type.get(key) or {} - for item, val in iteritems(w_type[key]): + for item, val in w_type[key].items(): if ( opr and item in a_type[key] diff --git a/plugins/module_utils/network/vyos/config/ospfv3/ospfv3.py b/plugins/module_utils/network/vyos/config/ospfv3/ospfv3.py index 2538a6f5..30d30571 100644 --- a/plugins/module_utils/network/vyos/config/ospfv3/ospfv3.py +++ b/plugins/module_utils/network/vyos/config/ospfv3/ospfv3.py @@ -17,7 +17,6 @@ __metaclass__ = type from copy import deepcopy -from ansible.module_utils.six import iteritems from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import ( ConfigBase, ) @@ -204,7 +203,7 @@ class Ospfv3(ConfigBase): commands = [] w = deepcopy(remove_empties(want)) if w: - for key, val in iteritems(w): + for key, val in w.items(): commands.extend(self._render_child_param(w, have, key, opr)) return commands @@ -245,7 +244,7 @@ class Ospfv3(ConfigBase): elif want[attr]: leaf_dict = {"parameters": "router_id"} leaf = leaf_dict[attr] - for item, value in iteritems(want[attr]): + for item, value in want[attr].items(): if opr and item in leaf and not _is_w_same(want[attr], h, item): commands.append(self._form_attr_cmd(key=attr, attr=item, val=value, opr=opr)) elif not opr and item in leaf and not _in_target(h, item): @@ -283,7 +282,7 @@ class Ospfv3(ConfigBase): commands.append(self._compute_command(attr=attr, opr=opr)) elif w: for w_item in w: - for key, val in iteritems(w_item): + for key, val in w_item.items(): if not cmd: cmd = self._compute_command(opr=opr) h_item = search_obj_in_list(w_item[name[attr]], h, name[attr]) @@ -376,7 +375,7 @@ class Ospfv3(ConfigBase): self._form_attr_cmd(key="area", attr=w_area["area_id"], opr=opr), ) else: - for key, val in iteritems(w_area): + for key, val in w_area.items(): if opr and key in l_set and not _is_w_same(w_area, h_area, key): if key == "area_id": commands.append( diff --git a/plugins/module_utils/network/vyos/config/prefix_lists/prefix_lists.py b/plugins/module_utils/network/vyos/config/prefix_lists/prefix_lists.py index 9da27c15..9b703399 100644 --- a/plugins/module_utils/network/vyos/config/prefix_lists/prefix_lists.py +++ b/plugins/module_utils/network/vyos/config/prefix_lists/prefix_lists.py @@ -19,7 +19,6 @@ created. """ -from ansible.module_utils.six import iteritems from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module import ( ResourceModule, ) @@ -86,23 +85,23 @@ class Prefix_lists(ResourceModule): # if state is deleted, empty out wantd and set haved to wantd if self.state == "deleted": - haved = {k: v for k, v in iteritems(haved) if k in wantd or not wantd} - for key, hvalue in iteritems(haved): + haved = {k: v for k, v in haved.items() if k in wantd or not wantd} + for key, hvalue in haved.items(): wvalue = wantd.pop(key, {}) if wvalue: wplists = wvalue.get("prefix_lists", {}) hplists = hvalue.get("prefix_lists", {}) hvalue["prefix_lists"] = { - k: v for k, v in iteritems(hplists) if k in wplists or not wplists + k: v for k, v in hplists.items() if k in wplists or not wplists } # remove superfluous config for overridden and deleted if self.state in ["overridden", "deleted"]: - for k, have in iteritems(haved): + for k, have in haved.items(): if k not in wantd: self._compare(want={}, have=have) - for k, want in iteritems(wantd): + for k, want in wantd.items(): self._compare(want=want, have=haved.pop(k, {})) def _compare(self, want, have): @@ -127,7 +126,7 @@ class Prefix_lists(ResourceModule): ) def _compare_plists(self, want, have): - for wk, wentry in iteritems(want): + for wk, wentry in want.items(): hentry = have.pop(wk, {}) # parser list for name and descriptions @@ -143,7 +142,7 @@ class Prefix_lists(ResourceModule): self._compare_rules(want=wplrules, have=hplrules) def _compare_rules(self, want, have): - for wr, wrule in iteritems(want): + for wr, wrule in want.items(): hrule = have.pop(wr, {}) # parser list for entries @@ -164,7 +163,7 @@ class Prefix_lists(ResourceModule): ) def _prefix_list_list_to_dict(self, entry): - for afi, value in iteritems(entry): + for afi, value in entry.items(): if "prefix_lists" in value: for pl in value["prefix_lists"]: pl.update({"afi": afi}) 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..dca99d1c 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 @@ -19,7 +19,6 @@ created. """ -from ansible.module_utils.six import iteritems from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module import ( ResourceModule, ) @@ -31,6 +30,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 +65,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 +78,7 @@ class Route_maps(ResourceModule): "set_src", "set_tag", "set_weight", + "set_table", "set_comm_list", "set_comm_list_delete", "set_community", @@ -89,15 +98,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() @@ -116,16 +144,16 @@ class Route_maps(ResourceModule): # if state is deleted, empty out wantd and set haved to wantd if self.state == "deleted": - haved = {k: v for k, v in iteritems(haved) if k in wantd or not wantd} + haved = {k: v for k, v in haved.items() if k in wantd or not wantd} wantd = {} # remove superfluous config for overridden and deleted if self.state in ["overridden", "deleted"]: - for k, have in iteritems(haved): + for k, have in haved.items(): if k not in wantd: self.commands.append(self._tmplt.render({"route_map": k}, "route_map", True)) - for wk, want in iteritems(wantd): + for wk, want in wantd.items(): self._compare(want=want, have=haved.pop(wk, {})) def _compare(self, want, have): @@ -139,13 +167,13 @@ class Route_maps(ResourceModule): self._compare_entries(want=w_entries, have=h_entries) def _compare_entries(self, want, have): - for wk, wentry in iteritems(want): + for wk, wentry in want.items(): hentry = have.pop(wk, {}) self.compare(parsers=self.parsers, want=wentry, have=hentry) def _route_maps_list_to_dict(self, entry): entry = {x["route_map"]: x for x in entry} - for rmap, data in iteritems(entry): + for rmap, data in entry.items(): if "entries" in data: for x in data["entries"]: x.update({"route_map": rmap}) diff --git a/plugins/module_utils/network/vyos/config/snmp_server/snmp_server.py b/plugins/module_utils/network/vyos/config/snmp_server/snmp_server.py index 9497d7fa..4bc5ddc4 100644 --- a/plugins/module_utils/network/vyos/config/snmp_server/snmp_server.py +++ b/plugins/module_utils/network/vyos/config/snmp_server/snmp_server.py @@ -20,7 +20,6 @@ created. import re -from ansible.module_utils.six import iteritems from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module import ( ResourceModule, ) @@ -107,13 +106,13 @@ class Snmp_server(ResourceModule): """ self._compare_lists(want, have) self._compare_snmp_v3(want, have) - for key, value in iteritems(want): + for key, value in want.items(): self.compare( parsers=self.parsers, want={key: value}, have={key: have.pop(key, "")}, ) - for key, entry in iteritems(have): + for key, entry in have.items(): if entry: self.compare(parsers=self.parsers, want={}, have={key: entry}) @@ -125,10 +124,10 @@ class Snmp_server(ResourceModule): for attrib in parsers: wdict = get_from_dict(want, attrib) or {} hdict = get_from_dict(have, attrib) or {} - for key, entry in iteritems(wdict): + for key, entry in wdict.items(): # self.addcmd(entry, attrib, False) if attrib == "communities": - for k, v in iteritems(entry): + for k, v in entry.items(): if k in ["clients", "networks"]: v.sort() h = {} @@ -153,9 +152,9 @@ class Snmp_server(ResourceModule): ) have.pop(attrib, {}) # remove remaining items in have for replaced - for key, entry in iteritems(hdict): + for key, entry in hdict.items(): if attrib == "communities": - for k, v in iteritems(entry): + for k, v in entry.items(): if k != "name": self.compare( parsers="communities", @@ -188,9 +187,9 @@ class Snmp_server(ResourceModule): for attrib in attribute_dict.keys(): wattrib = get_from_dict(wdict, attrib) or {} hattrib = get_from_dict(hdict, attrib) or {} - for key, entry in iteritems(wattrib): + for key, entry in wattrib.items(): self._compare_snmp_v3_auth_privacy(entry, hattrib.get(key, {}), attrib) - for k, v in iteritems(entry): + for k, v in entry.items(): if k != attribute_dict[attrib]: h = {} if hattrib.get(key): @@ -217,11 +216,11 @@ class Snmp_server(ResourceModule): have=h, ) # remove remaining items in have for replaced - for key, entry in iteritems(hattrib): + for key, entry in hattrib.items(): self._compare_snmp_v3_auth_privacy({}, entry, attrib) self.compare(parsers=parsers, want={}, have={"snmp_v3": {attrib: entry}}) hdict.pop(attrib, {}) - for key, entry in iteritems(wdict): + for key, entry in wdict.items(): # self.addcmd(entry, attrib, False) self.compare( parsers="snmp_v3.engine_id", @@ -229,7 +228,7 @@ class Snmp_server(ResourceModule): have={"snmp_v3": {key: hdict.pop(key, {})}}, ) # remove remaining items in have for replaced - for key, entry in iteritems(hdict): + for key, entry in hdict.items(): self.compare(parsers=parsers, want={}, have={"snmp_v3": {key: entry}}) def _compare_snmp_v3_auth_privacy(self, wattrib, hattrib, attrib): @@ -244,7 +243,7 @@ class Snmp_server(ResourceModule): primary_key = "user" else: primary_key = "address" - for key, entry in iteritems(wattrib): + for key, entry in wattrib.items(): if key != primary_key and key in ["authentication", "privacy"]: self.compare( parsers=parsers, @@ -265,7 +264,7 @@ class Snmp_server(ResourceModule): }, }, ) - for key, entry in iteritems(hattrib): + for key, entry in hattrib.items(): if key != primary_key and key in ["authentication", "privacy"]: self.compare( parsers=parsers, @@ -291,13 +290,13 @@ class Snmp_server(ResourceModule): "views": "view", "trap_targets": "address", } - for k, v in iteritems(param_dict): + for k, v in param_dict.items(): if k in entry: a_dict = {} for el in entry[k]: a_dict.update({el[v]: el}) entry[k] = a_dict - for k, v in iteritems(v3_param_dict): + for k, v in v3_param_dict.items(): if entry.get("snmp_v3") and k in entry.get("snmp_v3"): a_dict = {} for el in entry["snmp_v3"][k]: diff --git a/plugins/module_utils/network/vyos/config/static_routes/static_routes.py b/plugins/module_utils/network/vyos/config/static_routes/static_routes.py index 8451e7da..da8f8e3d 100644 --- a/plugins/module_utils/network/vyos/config/static_routes/static_routes.py +++ b/plugins/module_utils/network/vyos/config/static_routes/static_routes.py @@ -17,7 +17,6 @@ from __future__ import absolute_import, division, print_function __metaclass__ = type from copy import deepcopy -from ansible.module_utils.six import iteritems from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import ( ConfigBase, ) @@ -182,7 +181,7 @@ class Static_routes(ConfigBase): """ commands = [] if have: - for key, value in iteritems(want): + for key, value in want.items(): if value: if key == "next_hops": commands.extend(self._update_next_hop(want, have)) @@ -257,7 +256,7 @@ class Static_routes(ConfigBase): """ commands = [] have = {} - for key, value in iteritems(want): + for key, value in want.items(): if value: if key == "dest": commands.append(self._compute_command(dest=want["dest"])) @@ -287,7 +286,7 @@ class Static_routes(ConfigBase): updates = dict_delete(want_blackhole, have_blackhole) if updates: - for attrib, value in iteritems(updates): + for attrib, value in updates.items(): if value: if attrib == "distance": commands.append( @@ -394,7 +393,7 @@ class Static_routes(ConfigBase): have_blackhole = have_copy.get(key) or {} updates = dict_delete(have_blackhole, want_blackhole) if updates: - for attrib, value in iteritems(updates): + for attrib, value in updates.items(): if value: if attrib == "distance": commands.append( @@ -508,7 +507,7 @@ class Static_routes(ConfigBase): commands.extend(self._add_next_hop(want, have, opr=opr)) if opr and updates: - for key, value in iteritems(updates): + for key, value in updates.items(): if value: if key == "blackhole_config": commands.extend(self._add_blackhole(key, want, have)) diff --git a/plugins/module_utils/network/vyos/config/vrf/__init__.py b/plugins/module_utils/network/vyos/config/vrf/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/plugins/module_utils/network/vyos/config/vrf/__init__.py diff --git a/plugins/module_utils/network/vyos/config/vrf/vrf.py b/plugins/module_utils/network/vyos/config/vrf/vrf.py new file mode 100644 index 00000000..aa4329d9 --- /dev/null +++ b/plugins/module_utils/network/vyos/config/vrf/vrf.py @@ -0,0 +1,308 @@ +# +# -*- 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_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module import ( + ResourceModule, +) + +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.config.bgp_global.bgp_global import ( + Bgp_global, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.config.ospfv2.ospfv2 import ( + Ospfv2, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.config.ospfv3.ospfv3 import ( + Ospfv3, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.config.static_routes.static_routes import ( + Static_routes, +) +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 + + +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) + + # if state is merged, merge want onto have and then compare + if self.state in ["merged", "replaced"]: + + wantd = combine(haved, wantd, recursive=True) + + # if state is deleted, delete and empty out wantd + if self.state == "deleted": + w = deepcopy(wantd) + if w == {} and haved != {}: + self.commands = ["delete vrf"] + return + for k, want in w.items(): + 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 w.items(): + 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, + ) + wantc = self._canonicalise(entry) + havec = self._canonicalise(hdict or {}) + + if wantc != havec: + 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 wantd.items(): + 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, {})}, + ) + + def _compare_instances(self, want, have): + """Compare the instances of the VRF""" + parsers = [ + "table_id", + "vni", + "description", + "disable_vrf", + ] + + for entry in want: + h = {} + wname = entry.get("name") + 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((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._compare_addr_family(wafi, hafi) + + if "protocols" in entry: + for protocol_name in entry["protocols"]: + + w_p_dict = entry["protocols"][protocol_name] + + h_p_dict = next( + ( + v.get("protocols", {}).get(protocol_name, {}) + for v in have + if v.get("name") == wname + ), + {}, + ) + if protocol_name == "bgp": + bgp_module = Bgp_global(self._module) + bgp_module._validate_template() + bgp_module.want = w_p_dict + bgp_module.have = h_p_dict + bgp_module.generate_commands() + protocol_commands = bgp_module.commands + elif protocol_name == "ospf": + ospfv2_module = Ospfv2(self._module) + ospfv2_module._module.params["config"] = w_p_dict + ospfv2_module.state = self.state + protocol_commands = ospfv2_module.set_config(h_p_dict) + elif protocol_name == "ospfv3": + ospfv3_module = Ospfv3(self._module) + ospfv3_module._module.params["config"] = w_p_dict + ospfv3_module.state = self.state + protocol_commands = ospfv3_module.set_config(h_p_dict) + elif protocol_name == "static": + static_routes_module = Static_routes(self._module) + static_routes_module._module.params["config"] = w_p_dict + static_routes_module.state = self.state + protocol_commands = static_routes_module.set_config(h_p_dict) + else: + self._module.fail_json( + msg="The protocol {} is not supported".format(protocol_name), + ) + self.commands.extend( + [ + cmd.replace("protocols", "vrf name " + wname + " protocols", 1) + for cmd in protocol_commands + ], + ) + + def _compare_addr_family(self, want, have): + """Compare the address families of the VRF""" + afi_parsers = [ + "disable_forwarding", + "disable_nht", + ] + + 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: + if "route_maps" in wafd: + self._compare_route_maps(wafd, hafd) + self.compare(parsers=afi_parsers, want=wafd, have=hafd) + + 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}, + ) + + def _canonicalise(self, obj): + if isinstance(obj, dict): + return {k: self._canonicalise(v) for k, v in obj.items()} + + if isinstance(obj, list): + if not obj: + return obj + + if not isinstance(obj[0], dict): + return sorted(obj) + + canon = [self._canonicalise(i) for i in obj] + + def sort_key(d): + for k in ("name", "address", "afi", "area_id", "neighbor_id", "dest"): + if k in d: + return d[k] + return tuple(sorted(d.items())) + + return sorted(canon, key=sort_key) + + return obj diff --git a/plugins/module_utils/network/vyos/facts/bgp_address_family/bgp_address_family.py b/plugins/module_utils/network/vyos/facts/bgp_address_family/bgp_address_family.py index 3386bd66..31839c5d 100644 --- a/plugins/module_utils/network/vyos/facts/bgp_address_family/bgp_address_family.py +++ b/plugins/module_utils/network/vyos/facts/bgp_address_family/bgp_address_family.py @@ -28,11 +28,11 @@ from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.rm_template from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.rm_templates.bgp_address_family_14 import ( Bgp_address_familyTemplate14, ) - +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 Bgp_address_familyFacts(object): """The vyos bgp_address_family facts class""" diff --git a/plugins/module_utils/network/vyos/facts/bgp_global/bgp_global.py b/plugins/module_utils/network/vyos/facts/bgp_global/bgp_global.py index dd793681..2883cc2d 100644 --- a/plugins/module_utils/network/vyos/facts/bgp_global/bgp_global.py +++ b/plugins/module_utils/network/vyos/facts/bgp_global/bgp_global.py @@ -25,15 +25,14 @@ from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.bgp from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.rm_templates.bgp_global import ( Bgp_globalTemplate, ) - from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.rm_templates.bgp_global_14 import ( Bgp_globalTemplate14, ) - +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 Bgp_globalFacts(object): """The vyos bgp_global facts class""" diff --git a/plugins/module_utils/network/vyos/facts/facts.py b/plugins/module_utils/network/vyos/facts/facts.py index 74bbda74..24c444dd 100644 --- a/plugins/module_utils/network/vyos/facts/facts.py +++ b/plugins/module_utils/network/vyos/facts/facts.py @@ -80,6 +80,7 @@ from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.snmp_ from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.static_routes.static_routes import ( Static_routesFacts, ) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.vrf.vrf import VrfFacts FACT_LEGACY_SUBSETS = dict(default=Default, neighbors=Neighbors, config=Config) @@ -104,6 +105,7 @@ FACT_RESOURCE_SUBSETS = dict( ntp_global=Ntp_globalFacts, snmp_server=Snmp_serverFacts, hostname=HostnameFacts, + vrf=VrfFacts, ) diff --git a/plugins/module_utils/network/vyos/facts/firewall_global/firewall_global.py b/plugins/module_utils/network/vyos/facts/firewall_global/firewall_global.py index a46f8563..3a48889e 100644 --- a/plugins/module_utils/network/vyos/facts/firewall_global/firewall_global.py +++ b/plugins/module_utils/network/vyos/facts/firewall_global/firewall_global.py @@ -179,7 +179,7 @@ class Firewall_globalFacts(object): if policies: rules_lst = [] for sp in set(policies): - sp_regex = r" %s .+$" % sp + sp_regex = r"^set firewall (?:global-options )?state-policy %s .+$" % sp cfg = "\n".join(findall(sp_regex, conf, M)) obj = self.parse_policies(cfg, sp) obj["connection_type"] = sp @@ -233,7 +233,7 @@ class Firewall_globalFacts(object): if groups: rules_lst = [] for gr in set(groups): - gr_regex = r" %s .+$" % gr + gr_regex = r"^set firewall group " + type + " %s .+$" % gr cfg = "\n".join(findall(gr_regex, conf, M)) if "ipv6" in type: # fmt: off diff --git a/plugins/module_utils/network/vyos/facts/firewall_rules/firewall_rules.py b/plugins/module_utils/network/vyos/facts/firewall_rules/firewall_rules.py index a6b56345..f8f02e7a 100644 --- a/plugins/module_utils/network/vyos/facts/firewall_rules/firewall_rules.py +++ b/plugins/module_utils/network/vyos/facts/firewall_rules/firewall_rules.py @@ -61,12 +61,20 @@ class Firewall_rulesFacts(object): objs = [] # check 1.4+ first new_rules = True - v6_rules = findall(r"^set firewall ipv6 (name|forward|input|output) (?:\'*)(\S+)(?:\'*)", data, M) + v6_rules = findall( + r"^set firewall ipv6 (name|forward|input|output) (?:\'*)(\S+)(?:\'*)", + data, + M, + ) if not v6_rules: v6_rules = findall(r"^set firewall ipv6-name (?:\'*)(\S+)(?:\'*)", data, M) if v6_rules: new_rules = False - v4_rules = findall(r"^set firewall ipv4 (name|forward|input|output) (?:\'*)(\S+)(?:\'*)", data, M) + v4_rules = findall( + r"^set firewall ipv4 (name|forward|input|output) (?:\'*)(\S+)(?:\'*)", + data, + M, + ) if not v4_rules: v4_rules = findall(r"^set firewall name (?:\'*)(\S+)(?:\'*)", data, M) if v4_rules: @@ -171,12 +179,18 @@ class Firewall_rulesFacts(object): :returns: The generated config """ conf = "\n".join(filter(lambda x: x, conf)) - a_lst = ["description", "default_action", "default_jump_target", "enable_default_log", "default_log"] + a_lst = [ + "description", + "default_action", + "default_jump_target", + "enable_default_log", + "default_log", + ] config = self.parse_attr(conf, a_lst, match) if not config: config = {} - if 'default_log' in config: - config['enable_default_log'] = config.pop('default_log') + if "default_log" in config: + config["enable_default_log"] = config.pop("default_log") config["rules"] = self.parse_rules_lst(conf) return config @@ -219,6 +233,7 @@ class Firewall_rulesFacts(object): "description", "icmp", "jump_target", + "offload_target", "queue", "queue_options", ] @@ -263,8 +278,8 @@ class Firewall_rulesFacts(object): found_lengths = findall(rule_regex, conf, M) if found_lengths: lengths = [] - for l in set(found_lengths): - obj = {"length": l.strip("'")} + for pplen in set(found_lengths): + obj = {"length": pplen.strip("'")} lengths.append(obj) return lengths @@ -389,21 +404,21 @@ class Firewall_rulesFacts(object): out = search(r"^.*" + regex + " (.+)", conf, M) if out: val = out.group(1).strip("'") - if attrib == 'type-name': - config['type_name'] = val - if attrib == 'code': - config['code'] = int(val) - if attrib == 'type': + if attrib == "type-name": + config["type_name"] = val + if attrib == "code": + config["code"] = int(val) + if attrib == "type": # <1.3 could be # (type), #/# (type/code) or 'type' (type_name) # recent this is only for strings if "/" in val: # type/code - (type_no, code) = val.split(".") - config['type'] = type_no - config['code'] = code + (type_no, code) = val.split("/") + config["type"] = int(type_no) + config["code"] = int(code) elif val.isnumeric(): - config['type'] = type_no + config["type"] = int(val) else: - config['type_name'] = val + config["type_name"] = val return config def parse_icmp(self, conf, attrib=None): @@ -414,7 +429,7 @@ class Firewall_rulesFacts(object): :return: generated config dictionary. """ cfg_dict = self.parse_icmp_attr(conf, "icmp") - if (len(cfg_dict) == 0): + if len(cfg_dict) == 0: cfg_dict = self.parse_icmp_attr(conf, "icmpv6") return cfg_dict @@ -458,7 +473,7 @@ class Firewall_rulesFacts(object): if not out: if attrib == "disable": out = search(r"^.*\d+" + " (disable$)", conf, M) - if attrib == 'log': + if attrib == "log": out = search(r"^.*\d+" + " (log$)", conf, M) if out: @@ -524,6 +539,6 @@ class Firewall_rulesFacts(object): val = out.group(1).strip("'") if "/" in val: # number/unit (number, unit) = val.split("/") - config['number'] = number - config['unit'] = unit + config["number"] = number + config["unit"] = unit return config diff --git a/plugins/module_utils/network/vyos/facts/l3_interfaces/l3_interfaces.py b/plugins/module_utils/network/vyos/facts/l3_interfaces/l3_interfaces.py index 7d4d1a08..d62ea9b8 100644 --- a/plugins/module_utils/network/vyos/facts/l3_interfaces/l3_interfaces.py +++ b/plugins/module_utils/network/vyos/facts/l3_interfaces/l3_interfaces.py @@ -20,7 +20,6 @@ import re from copy import deepcopy -from ansible.module_utils.six import iteritems from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import utils from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.l3_interfaces.l3_interfaces import ( @@ -139,7 +138,7 @@ class L3_interfacesFacts(object): else: config["ipv6"].append({"address": item}) - for key, value in iteritems(config): + for key, value in config.items(): if value == []: config[key] = None diff --git a/plugins/module_utils/network/vyos/facts/logging_global/logging_global.py b/plugins/module_utils/network/vyos/facts/logging_global/logging_global.py index 8b60bef9..da80d967 100644 --- a/plugins/module_utils/network/vyos/facts/logging_global/logging_global.py +++ b/plugins/module_utils/network/vyos/facts/logging_global/logging_global.py @@ -15,7 +15,6 @@ for a given resource, parsed, and the facts tree is populated based on the configuration. """ -from ansible.module_utils.six import iteritems from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import utils from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.logging_global.logging_global import ( @@ -38,7 +37,7 @@ class Logging_globalFacts(object): def process_facts(self, objFinal): if objFinal: - for ke, vl in iteritems(objFinal): + for ke, vl in objFinal.items(): if ke == "files": _files = [] for k, v in vl.items(): 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/facts/snmp_server/snmp_server.py b/plugins/module_utils/network/vyos/facts/snmp_server/snmp_server.py index e70a15f9..d961a0ff 100644 --- a/plugins/module_utils/network/vyos/facts/snmp_server/snmp_server.py +++ b/plugins/module_utils/network/vyos/facts/snmp_server/snmp_server.py @@ -17,7 +17,6 @@ based on the configuration. import re -from ansible.module_utils.six import iteritems from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import utils from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.snmp_server.snmp_server import ( @@ -63,7 +62,7 @@ class Snmp_serverFacts(object): if objs: if "communities" in objs: for k in objs["communities"].values(): - for param, val in iteritems(k): + for param, val in k.items(): if param in ["clients", "networks"]: if None in val: val.remove(None) diff --git a/plugins/module_utils/network/vyos/facts/static_routes/static_routes.py b/plugins/module_utils/network/vyos/facts/static_routes/static_routes.py index 99b3917b..710d91fe 100644 --- a/plugins/module_utils/network/vyos/facts/static_routes/static_routes.py +++ b/plugins/module_utils/network/vyos/facts/static_routes/static_routes.py @@ -164,9 +164,9 @@ class Static_routesFacts(object): elif dis >= 1: nh_info["enabled"] = False for element in nh_list: - if element["forward_router_address"] == nh_info["forward_router_address"]: - if "interface" in nh_info.keys(): - element["interface"] = nh_info["interface"] + if element.get("forward_router_address") == nh_info.get( + "forward_router_address", + ): if "admin_distance" in nh_info.keys(): element["admin_distance"] = nh_info["admin_distance"] if "enabled" in nh_info.keys(): @@ -174,4 +174,5 @@ class Static_routesFacts(object): nh_info = None if nh_info is not None: nh_list.append(nh_info) + nh_info = {} return nh_list diff --git a/plugins/module_utils/network/vyos/facts/vrf/__init__.py b/plugins/module_utils/network/vyos/facts/vrf/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/plugins/module_utils/network/vyos/facts/vrf/__init__.py diff --git a/plugins/module_utils/network/vyos/facts/vrf/vrf.py b/plugins/module_utils/network/vyos/facts/vrf/vrf.py new file mode 100644 index 00000000..6c7b8918 --- /dev/null +++ b/plugins/module_utils/network/vyos/facts/vrf/vrf.py @@ -0,0 +1,227 @@ +# -*- 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 fact class +It is in this file the configuration is collected from the device +for a given resource, parsed, and the facts tree is populated +based on the configuration. +""" + +import re + +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import utils + +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.vrf.vrf import VrfArgs +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.bgp_global.bgp_global import ( + Bgp_globalFacts, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.ospfv2.ospfv2 import ( + Ospfv2Facts, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.ospfv3.ospfv3 import ( + Ospfv3Facts, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.static_routes.static_routes import ( + Static_routesFacts, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.rm_templates.vrf import ( + VrfTemplate, +) + + +class VrfFacts(object): + """The vyos vrf facts class""" + + def __init__(self, module, subspec="config", options="options"): + self._module = module + self.argument_spec = VrfArgs.argument_spec + + def get_config(self, connection): + return connection.get("show configuration commands | match 'set vrf'") + + def get_config_set(self, data, connection): + """To classify the configurations beased on vrf""" + config_dict = {} + for config_line in data.splitlines(): + vrf_inst = re.search(r"set vrf name (\S+).*", config_line) + vrf_bta = re.search(r"set vrf bind-to-all", config_line) + if vrf_bta: + config_dict["bind_to_all"] = config_dict.get("bind_to_all", "") + config_line + "\n" + if vrf_inst: + config_dict[vrf_inst.group(1)] = ( + config_dict.get(vrf_inst.group(1), "") + config_line + "\n" + ) + return list(config_dict.values()) + + def populate_facts(self, connection, ansible_facts, data=None): + """Populate the facts for Vrf network resource + + :param connection: the device connection + :param ansible_facts: Facts dictionary + :param data: previously collected conf + + :rtype: dictionary + :returns: facts + """ + facts = {} + objs = [] + + if not data: + data = self.get_config(connection) + + vrf_facts = {} + instances = [] + vrf_parser = VrfTemplate(lines=[], module=self._module) + resources = self.get_config_set(data, connection) + + for resource in resources: + vrf_parser = VrfTemplate( + lines=resource.split("\n"), + module=self._module, + ) + objs = vrf_parser.parse() + + if objs and "protocols" in resource: + + protocol_lines = [] + for line in resource.strip().split("\n"): + if "protocols" in line: + idx = line.index("protocols") + protocol_lines.append("set " + line[idx:]) + objs["protocols"] = self._parse_protocols("\n".join(protocol_lines)) + + if objs: + if "bind_to_all" in objs: + vrf_facts.update(objs) + if "name" in objs: + instances.append(self._normalise_instance(objs)) + + if instances: + vrf_facts.update({"instances": instances}) + + ansible_facts["ansible_network_resources"].pop("vrf_facts", None) + facts = {"vrf": []} + + params = utils.remove_empties( + vrf_parser.validate_config( + self.argument_spec, + {"config": vrf_facts}, + redact=True, + ), + ) + + if not resources: + params["config"].pop("bind_to_all", None) + + if params.get("config"): + facts["vrf"] = params["config"] + ansible_facts["ansible_network_resources"].update(facts) + return ansible_facts + + def _normalise_instance(self, instance): + n_inst = instance.copy() + af_map = {} + + for af in instance.get("address_family", []): + afi = af.get("afi") + if not afi: + continue + + if afi not in af_map: + af_map[afi] = {"afi": afi} + + for k, v in af.items(): + if k == "afi": + continue + elif k == "route_maps": + if "route_maps" not in af_map[afi]: + af_map[afi]["route_maps"] = [] + af_map[afi]["route_maps"].extend(v) + else: + af_map[afi][k] = v + + for afi_data in af_map.values(): + if "route_maps" in afi_data: + seen = [] + deduped = [] + for item in afi_data["route_maps"]: + if item not in seen: + seen.append(item) + deduped.append(item) + afi_data["route_maps"] = deduped + + n_inst["address_family"] = list(af_map.values()) + return n_inst + + def _parse_protocols(self, protocols): + """Parse protocols and return a dictionary""" + + protocol_chunks = {} + parsed_protocols = {} + + for line in protocols.split("\n"): + parts = line.split() + if len(parts) > 2 and parts[0] == "set" and parts[1] == "protocols": + protocol = parts[2] + protocol_chunks.setdefault(protocol, []).append(line) + + protocol_strings = {proto: "\n".join(lines) for proto, lines in protocol_chunks.items()} + + for protocol_name, protocol_string in protocol_strings.items(): + protocol_dict = {} + + if protocol_name == "bgp": + bgp_module = Bgp_globalFacts(self._module) + protocol_dict = bgp_module.populate_facts( + connection=self._module._connection, + ansible_facts={"ansible_network_resources": {}}, + data=protocol_string, + ) + parsed_protocols[protocol_name] = list( + protocol_dict.get("ansible_network_resources").values(), + )[0] + + elif protocol_name == "ospf": + ospf_module = Ospfv2Facts(self._module) + protocol_dict = ospf_module.populate_facts( + connection=self._module._connection, + ansible_facts={"ansible_network_resources": {}}, + data=protocol_string, + ) + parsed_protocols[protocol_name] = list( + protocol_dict.get("ansible_network_resources").values(), + )[0] + + elif protocol_name == "ospfv3": + ospfv3_module = Ospfv3Facts(self._module) + protocol_dict = ospfv3_module.populate_facts( + connection=self._module._connection, + ansible_facts={"ansible_network_resources": {}}, + data=protocol_string, + ) + parsed_protocols[protocol_name] = list( + protocol_dict.get("ansible_network_resources").values(), + )[0] + + elif protocol_name == "static": + static_routes_module = Static_routesFacts(self._module) + protocol_dict = static_routes_module.populate_facts( + connection=self._module._connection, + ansible_facts={"ansible_network_resources": {}}, + data=protocol_string, + ) + parsed_protocols[protocol_name] = list( + protocol_dict.get("ansible_network_resources").values(), + )[0] + else: + self._module.fail_json(msg="The protocol is not supported" + protocol_name) + + return parsed_protocols diff --git a/plugins/module_utils/network/vyos/rm_templates/bgp_address_family.py b/plugins/module_utils/network/vyos/rm_templates/bgp_address_family.py index f8f86cd2..fccfc9c2 100644 --- a/plugins/module_utils/network/vyos/rm_templates/bgp_address_family.py +++ b/plugins/module_utils/network/vyos/rm_templates/bgp_address_family.py @@ -293,8 +293,8 @@ class Bgp_address_familyTemplate(NetworkTemplate): \s+(?P<afi>\S+)-unicast \s+aggregate-address \s+(?P<address>\S+) - \s*(?P<as_set>as-set)* - \s*(?P<summary_only>summary-only)* + \s*(?P<as_set>as-set)? + \s*(?P<summary_only>summary-only)? $""", re.VERBOSE, ), @@ -397,8 +397,7 @@ class Bgp_address_familyTemplate(NetworkTemplate): \s+network \s+(?P<address>\S+) \s+path-limit - \s+(?P<limit>\S+) - *$""", + \s+(?P<limit>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_af_network, @@ -432,8 +431,7 @@ class Bgp_address_familyTemplate(NetworkTemplate): \s+network \s+(?P<address>\S+) \s+route-map - \s+(?P<map>\S+) - *$""", + \s+(?P<map>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_af_network, @@ -499,8 +497,7 @@ class Bgp_address_familyTemplate(NetworkTemplate): \s+redistribute \s+(?P<proto>\S+) \s+metric - \s+(?P<val>\S+) - *$""", + \s+(?P<val>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_af_redistribute, @@ -534,8 +531,7 @@ class Bgp_address_familyTemplate(NetworkTemplate): \s+redistribute \s+(?P<proto>\S+) \s+route-map - \s+(?P<map>\S+) - *$""", + \s+(?P<map>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_af_redistribute, @@ -568,8 +564,7 @@ class Bgp_address_familyTemplate(NetworkTemplate): \s+(?P<afi>\S+)-unicast \s+redistribute \s+table - \s+(?P<tab>\S+) - *$""", + \s+(?P<tab>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_af_redistribute, @@ -659,8 +654,7 @@ class Bgp_address_familyTemplate(NetworkTemplate): \s+(?P<afi>\S+)-unicast \s+allowas-in \s+number - \s+(?P<num>\S+) - *$""", + \s+(?P<num>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_af_neighbor, @@ -877,8 +871,7 @@ class Bgp_address_familyTemplate(NetworkTemplate): \s+(?P<afi>\S+)-unicast \s+capability \s+prefix-list - \s+(?P<orf>\S+) - *$""", + \s+(?P<orf>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_af_neighbor, @@ -915,8 +908,7 @@ class Bgp_address_familyTemplate(NetworkTemplate): \s+(?P<afi>\S+)-unicast \s+default-originate \s+route-map - \s+(?P<map>\S+) - *$""", + \s+(?P<map>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_af_neighbor, @@ -992,8 +984,7 @@ class Bgp_address_familyTemplate(NetworkTemplate): \s+(?P<afi>\S+)-unicast \s+prefix-list \s+(?P<action>export|import) - \s+(?P<list>\S+) - *$""", + \s+(?P<list>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_af_neighbor_prefix_list, @@ -1033,8 +1024,7 @@ class Bgp_address_familyTemplate(NetworkTemplate): \s+(?P<afi>\S+)-unicast \s+filter-list \s+(?P<action>export|import) - \s+(?P<list>\S+) - *$""", + \s+(?P<list>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_af_neighbor_filter_list, @@ -1073,8 +1063,7 @@ class Bgp_address_familyTemplate(NetworkTemplate): \s+address-family \s+(?P<afi>\S+)-unicast \s+maximum-prefix - \s+(?P<num>\S+) - *$""", + \s+(?P<num>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_af_neighbor, @@ -1176,8 +1165,7 @@ class Bgp_address_familyTemplate(NetworkTemplate): \s+address-family \s+(?P<afi>\S+)-unicast \s+peer-group - \s+(?P<name>\S+) - *$""", + \s+(?P<name>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_af_neighbor, @@ -1246,8 +1234,7 @@ class Bgp_address_familyTemplate(NetworkTemplate): \s+(?P<afi>\S+)-unicast \s+route-map \s+(?P<action>export|import) - \s+(?P<map>\S+) - *$""", + \s+(?P<map>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_af_neighbor_route_map, @@ -1389,8 +1376,7 @@ class Bgp_address_familyTemplate(NetworkTemplate): \s+address-family \s+(?P<afi>\S+)-unicast \s+unsuppress-map - \s+(?P<map>\S+) - *$""", + \s+(?P<map>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_af_neighbor, @@ -1424,8 +1410,7 @@ class Bgp_address_familyTemplate(NetworkTemplate): \s+address-family \s+(?P<afi>\S+)-unicast \s+weight - \s+(?P<num>\S+) - *$""", + \s+(?P<num>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_af_neighbor, diff --git a/plugins/module_utils/network/vyos/rm_templates/bgp_address_family_14.py b/plugins/module_utils/network/vyos/rm_templates/bgp_address_family_14.py index fd4c9de9..09cd41a7 100644 --- a/plugins/module_utils/network/vyos/rm_templates/bgp_address_family_14.py +++ b/plugins/module_utils/network/vyos/rm_templates/bgp_address_family_14.py @@ -309,8 +309,8 @@ class Bgp_address_familyTemplate14(NetworkTemplate): \s+(?P<afi>\S+)-unicast \s+aggregate-address \s+(?P<address>\S+) - \s*(?P<as_set>as-set)* - \s*(?P<summary_only>summary-only)* + \s*(?P<as_set>as-set)? + \s*(?P<summary_only>summary-only)? $""", re.VERBOSE, ), @@ -410,8 +410,7 @@ class Bgp_address_familyTemplate14(NetworkTemplate): \s+network \s+(?P<address>\S+) \s+path-limit - \s+(?P<limit>\S+) - *$""", + \s+(?P<limit>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_af_network, @@ -444,8 +443,7 @@ class Bgp_address_familyTemplate14(NetworkTemplate): \s+network \s+(?P<address>\S+) \s+route-map - \s+(?P<map>\S+) - *$""", + \s+(?P<map>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_af_network, @@ -508,8 +506,7 @@ class Bgp_address_familyTemplate14(NetworkTemplate): \s+(?P<afi>\S+)-unicast \s+redistribute \s+(?P<proto>\S+) - \s+metric\s+(?P<val>\S+) - *$""", + \s+metric\s+(?P<val>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_af_redistribute, @@ -542,8 +539,7 @@ class Bgp_address_familyTemplate14(NetworkTemplate): \s+redistribute \s+(?P<proto>\S+) \s+route-map - \s+(?P<map>\S+) - *$""", + \s+(?P<map>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_af_redistribute, @@ -575,8 +571,7 @@ class Bgp_address_familyTemplate14(NetworkTemplate): \s+(?P<afi>\S+)-unicast \s+redistribute \s+table - \s+(?P<tab>\S+) - *$""", + \s+(?P<tab>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_af_redistribute, @@ -663,8 +658,7 @@ class Bgp_address_familyTemplate14(NetworkTemplate): \s+(?P<afi>\S+)-unicast \s+allowas-in \s+number - \s+(?P<num>\S+) - *$""", + \s+(?P<num>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_af_neighbor, @@ -875,8 +869,7 @@ class Bgp_address_familyTemplate14(NetworkTemplate): \s+(?P<afi>\S+)-unicast \s+capability \s+prefix-list - \s+(?P<orf>\S+) - *$""", + \s+(?P<orf>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_af_neighbor, @@ -912,8 +905,7 @@ class Bgp_address_familyTemplate14(NetworkTemplate): \s+(?P<afi>\S+)-unicast \s+default-originate \s+route-map - \s+(?P<map>\S+) - *$""", + \s+(?P<map>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_af_neighbor, @@ -987,8 +979,7 @@ class Bgp_address_familyTemplate14(NetworkTemplate): \s+(?P<afi>\S+)-unicast \s+prefix-list \s+(?P<action>export|import) - \s+(?P<list>\S+) - *$""", + \s+(?P<list>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_af_neighbor_prefix_list, @@ -1027,8 +1018,7 @@ class Bgp_address_familyTemplate14(NetworkTemplate): \s+(?P<afi>\S+)-unicast \s+filter-list \s+(?P<action>export|import) - \s+(?P<list>\S+) - *$""", + \s+(?P<list>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_af_neighbor_filter_list, @@ -1066,8 +1056,7 @@ class Bgp_address_familyTemplate14(NetworkTemplate): \s+address-family \s+(?P<afi>\S+)-unicast \s+maximum-prefix - \s+(?P<num>\S+) - *$""", + \s+(?P<num>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_af_neighbor, @@ -1166,8 +1155,7 @@ class Bgp_address_familyTemplate14(NetworkTemplate): \s+address-family \s+(?P<afi>\S+)-unicast \s+peer-group - \s+(?P<name>\S+) - *$""", + \s+(?P<name>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_af_neighbor, @@ -1234,8 +1222,7 @@ class Bgp_address_familyTemplate14(NetworkTemplate): \s+(?P<afi>\S+)-unicast \s+route-map \s+(?P<action>export|import) - \s+(?P<map>\S+) - *$""", + \s+(?P<map>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_af_neighbor_route_map, @@ -1373,8 +1360,7 @@ class Bgp_address_familyTemplate14(NetworkTemplate): \s+address-family \s+(?P<afi>\S+)-unicast \s+unsuppress-map - \s+(?P<map>\S+) - *$""", + \s+(?P<map>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_af_neighbor, @@ -1407,8 +1393,7 @@ class Bgp_address_familyTemplate14(NetworkTemplate): \s+address-family \s+(?P<afi>\S+)-unicast \s+weight - \s+(?P<num>\S+) - *$""", + \s+(?P<num>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_af_neighbor, diff --git a/plugins/module_utils/network/vyos/rm_templates/bgp_global.py b/plugins/module_utils/network/vyos/rm_templates/bgp_global.py index 621f65ea..03f6265b 100644 --- a/plugins/module_utils/network/vyos/rm_templates/bgp_global.py +++ b/plugins/module_utils/network/vyos/rm_templates/bgp_global.py @@ -17,7 +17,6 @@ the given network resource. import re -from ansible.module_utils.six import iteritems from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.network_template import ( NetworkTemplate, ) @@ -26,7 +25,7 @@ from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.r def _tmplt_bgp_params_confederation(config_data): command = [] for list_el in config_data["bgp_params"]["confederation"]: - for k, v in iteritems(list_el): + for k, v in list_el.items(): command.append( "protocols bgp {as_number} parameters confederation ".format(**config_data) + k @@ -65,7 +64,7 @@ def _tmplt_bgp_params_default(config_data): def _tmplt_bgp_neighbor_timers(config_data): command = [] - for k, v in iteritems(config_data["neighbor"]["timers"]): + for k, v in config_data["neighbor"]["timers"].items(): command.append( "protocols bgp {as_number} neighbor ".format(**config_data) + config_data["neighbor"]["address"] @@ -80,7 +79,7 @@ def _tmplt_bgp_neighbor_timers(config_data): def _tmplt_bgp_timers(config_data): command = [] - for k, v in iteritems(config_data["timers"]): + for k, v in config_data["timers"].items(): command.append( "protocols bgp {as_number} ".format(**config_data) + "timers " + k + " " + str(v), ) @@ -238,8 +237,7 @@ class Bgp_globalTemplate(NetworkTemplate): \s+neighbor \s+(?P<address>\S+) \s+advertisement-interval - \s+(?P<interval>\S+) - *$""", + \s+(?P<interval>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp {{ as_number }} neighbor {{ neighbor.address }} advertisement-interval {{ neighbor.advertisement_interval }}", @@ -438,8 +436,7 @@ class Bgp_globalTemplate(NetworkTemplate): \s+capability \s+orf \s+prefix-list - \s+(?P<orf>\S+) - *$""", + \s+(?P<orf>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp {{ as_number }} neighbor {{ neighbor.address }} capability orf prefix-list {{ neighbor.capability.orf }}", @@ -468,8 +465,7 @@ class Bgp_globalTemplate(NetworkTemplate): \s+(?P<address>\S+) \s+default-originate \s+route-map - \s+(?P<map>\S+) - *$""", + \s+(?P<map>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp {{ as_number }} neighbor {{ neighbor.address }} default-originate route-map {{ neighbor.default_originate }}", @@ -495,8 +491,7 @@ class Bgp_globalTemplate(NetworkTemplate): \s+neighbor \s+(?P<address>\S+) \s+description - \s+(?P<desc>\S+) - *$""", + \s+(?P<desc>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp {{ as_number }} neighbor {{ neighbor.address }} description {{ neighbor.description }}", @@ -574,8 +569,7 @@ class Bgp_globalTemplate(NetworkTemplate): \s+neighbor \s+(?P<address>\S+) \s+disable-send-community - \s+(?P<comm>\S+) - *$""", + \s+(?P<comm>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp {{ as_number }} neighbor {{ neighbor.address }} disable-send-community {{ neighbor.disable_send_community }}", @@ -634,8 +628,7 @@ class Bgp_globalTemplate(NetworkTemplate): \s+neighbor \s+(?P<address>\S+) \s+ebgp-multihop - \s+(?P<hop>\S+) - *$""", + \s+(?P<hop>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp {{ as_number }} neighbor {{ neighbor.address }} ebgp-multihop {{ neighbor.ebgp_multihop }}", @@ -662,8 +655,7 @@ class Bgp_globalTemplate(NetworkTemplate): \s+(?P<address>\S+) \s+filter-list \s+(?P<action>export|import) - \s+(?P<list>\S+) - *$""", + \s+(?P<list>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_neighbor_filter_list, @@ -722,8 +714,7 @@ class Bgp_globalTemplate(NetworkTemplate): \s+neighbor \s+(?P<address>\S+) \s+maximum-prefix - \s+(?P<num>\S+) - *$""", + \s+(?P<num>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp {{ as_number }} neighbor {{ neighbor.address }} maximum-prefix {{ neighbor.maximum_prefix }}", @@ -827,8 +818,7 @@ class Bgp_globalTemplate(NetworkTemplate): \s+neighbor \s+(?P<address>\S+) \s+password - \s+(?P<pwd>\S+) - *$""", + \s+(?P<pwd>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp {{ as_number }} neighbor {{ neighbor.address }} password {{ neighbor.password }}", @@ -854,8 +844,7 @@ class Bgp_globalTemplate(NetworkTemplate): \s+neighbor \s+(?P<address>\S+) \s+peer-group - \s+(?P<name>\S+) - *$""", + \s+(?P<name>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp {{ as_number }} neighbor {{ neighbor.address }} peer-group {{ neighbor.peer_group_name }}", @@ -881,8 +870,7 @@ class Bgp_globalTemplate(NetworkTemplate): \s+neighbor \s+(?P<address>\S+) \s+port - \s+(?P<num>\S+) - *$""", + \s+(?P<num>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp {{ as_number }} neighbor {{ neighbor.address }} port {{ neighbor.port }}", @@ -909,8 +897,7 @@ class Bgp_globalTemplate(NetworkTemplate): \s+(?P<address>\S+) \s+prefix-list \s+(?P<action>export|import) - \s+(?P<list>\S+) - *$""", + \s+(?P<list>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_neighbor_prefix_list, @@ -941,8 +928,7 @@ class Bgp_globalTemplate(NetworkTemplate): \s+neighbor \s+(?P<address>\S+) \s+remote-as - \s+(?P<num>\S+) - *$""", + \s+(?P<num>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp {{ as_number }} neighbor {{ neighbor.address }} remote-as {{ neighbor.remote_as }}", @@ -995,8 +981,7 @@ class Bgp_globalTemplate(NetworkTemplate): \s+(?P<address>\S+) \s+route-map \s+(?P<action>export|import) - \s+(?P<map>\S+) - *$""", + \s+(?P<map>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_neighbor_route_map, @@ -1158,8 +1143,7 @@ class Bgp_globalTemplate(NetworkTemplate): \s+neighbor \s+(?P<address>\S+) \s+unsuppress-map - \s+(?P<map>\S+) - *$""", + \s+(?P<map>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp {{ as_number }} neighbor {{ neighbor.address }} unsuppress-map {{ neighbor.unsuppress_map }}", @@ -1185,8 +1169,7 @@ class Bgp_globalTemplate(NetworkTemplate): \s+neighbor \s+(?P<address>\S+) \s+update-source - \s+(?P<src>\S+) - *$""", + \s+(?P<src>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp {{ as_number }} neighbor {{ neighbor.address }} update-source {{ neighbor.update_source }}", @@ -1212,8 +1195,7 @@ class Bgp_globalTemplate(NetworkTemplate): \s+neighbor \s+(?P<address>\S+) \s+weight - \s+(?P<num>\S+) - *$""", + \s+(?P<num>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp {{ as_number }} neighbor {{ neighbor.address }} weight {{ neighbor.weight }}", @@ -1239,8 +1221,7 @@ class Bgp_globalTemplate(NetworkTemplate): \s+neighbor \s+(?P<address>\S+) \s+ttl-security - \s+(?P<ttl>\S+) - *$""", + \s+(?P<ttl>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp {{ as_number }} neighbor {{ neighbor.address }} ttl-security {{ neighbor.ttl_security }}", @@ -1267,8 +1248,7 @@ class Bgp_globalTemplate(NetworkTemplate): \s+(?P<address>\S+) \s+timers \s+(?P<type>connect|holdtime|keepalive) - \s+(?P<sec>\S+) - *$""", + \s+(?P<sec>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_neighbor_timers, @@ -1296,8 +1276,7 @@ class Bgp_globalTemplate(NetworkTemplate): \s+(?P<as_num>\d+) \s+timers \s+(?P<type>\S+) - \s+(?P<val>\S+) - *$""", + \s+(?P<val>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_timers, @@ -1419,8 +1398,7 @@ class Bgp_globalTemplate(NetworkTemplate): \s+(?P<as_num>\d+) \s+parameters \s+cluster-id - \s+(?P<id>\S+) - *$""", + \s+(?P<id>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp {{ as_number }} parameters cluster-id {{ bgp_params.cluster_id }}", @@ -1443,8 +1421,7 @@ class Bgp_globalTemplate(NetworkTemplate): \s+parameters \s+confederation \s+(?P<type>identifier|peers) - \s+(?P<val>\S+) - *$""", + \s+(?P<val>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_params_confederation, @@ -1472,8 +1449,7 @@ class Bgp_globalTemplate(NetworkTemplate): \s+parameters \s+dampening \s+half-life - \s+(?P<val>\S+) - *$""", + \s+(?P<val>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp {{ as_number }} parameters dampening half-life {{ bgp_params.dampening.half_life}}", @@ -1498,8 +1474,7 @@ class Bgp_globalTemplate(NetworkTemplate): \s+parameters \s+dampening \s+max-suppress-time - \s+(?P<val>\S+) - *$""", + \s+(?P<val>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp {{ as_number }} parameters dampening max-suppress-time {{ bgp_params.dampening.max_suppress_time}}", @@ -1524,8 +1499,7 @@ class Bgp_globalTemplate(NetworkTemplate): \s+parameters \s+dampening \s+re-use - \s+(?P<val>\S+) - *$""", + \s+(?P<val>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp {{ as_number }} parameters dampening re-use {{ bgp_params.dampening.re_use}}", @@ -1550,8 +1524,7 @@ class Bgp_globalTemplate(NetworkTemplate): \s+parameters \s+dampening \s+start-suppress-time - \s+(?P<val>\S+) - *$""", + \s+(?P<val>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp {{ as_number }} parameters dampening start-suppress-time {{ bgp_params.dampening.start_suppress_time}}", @@ -1575,9 +1548,8 @@ class Bgp_globalTemplate(NetworkTemplate): \s+(?P<as_num>\d+) \s+parameters \s+default - \s*(?P<no_ipv4_unicast>no-ipv4-unicast)* - \s*(?P<local_pref>local-pref\s\S+) - *$""", + \s*(?P<no_ipv4_unicast>no-ipv4-unicast)? + \s*(?P<local_pref>local-pref\s\S+)?\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_params_default, @@ -1649,8 +1621,7 @@ class Bgp_globalTemplate(NetworkTemplate): \s+distance\sprefix \s+(?P<prefix>\S+) \s+distance - \s+(?P<val>\S+) - *$""", + \s+(?P<val>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp {{ as_number }} parameters distance prefix {{ bgp_params.distance.prefix }} distance {{ bgp_params.distance.value }}", @@ -1679,8 +1650,7 @@ class Bgp_globalTemplate(NetworkTemplate): \s+parameters \s+distance\sglobal \s+(?P<type>\S+) - \s+(?P<val>\S+) - *$""", + \s+(?P<val>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_params_distance, @@ -1730,8 +1700,7 @@ class Bgp_globalTemplate(NetworkTemplate): \s+(?P<as_num>\d+) \s+parameters \s+graceful-restart\s+stalepath-time - \s+(?P<val>\S+) - *$""", + \s+(?P<val>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp {{ as_number }} parameters graceful-restart stalepath-time {{ bgp_params.graceful_restart }}", @@ -1819,8 +1788,7 @@ class Bgp_globalTemplate(NetworkTemplate): \s+(?P<as_num>\d+) \s+parameters \s+router-id - \s+(?P<id>\S+) - *$""", + \s+(?P<id>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp {{ as_number }} parameters router-id {{ bgp_params.router_id }}", diff --git a/plugins/module_utils/network/vyos/rm_templates/bgp_global_14.py b/plugins/module_utils/network/vyos/rm_templates/bgp_global_14.py index b8beb923..cbe21e3a 100644 --- a/plugins/module_utils/network/vyos/rm_templates/bgp_global_14.py +++ b/plugins/module_utils/network/vyos/rm_templates/bgp_global_14.py @@ -17,7 +17,6 @@ the given network resource. import re -from ansible.module_utils.six import iteritems from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.network_template import ( NetworkTemplate, ) @@ -26,12 +25,9 @@ from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.r def _tmplt_bgp_params_confederation(config_data): command = [] for list_el in config_data["bgp_params"]["confederation"]: - for k, v in iteritems(list_el): + for k, v in list_el.items(): command.append( - "protocols bgp parameters confederation ".format(**config_data) - + k - + " " - + str(v), + "protocols bgp parameters confederation ".format(**config_data) + k + " " + str(v), ) return command @@ -65,7 +61,7 @@ def _tmplt_bgp_params_default(config_data): def _tmplt_bgp_neighbor_timers(config_data): command = [] - for k, v in iteritems(config_data["neighbor"]["timers"]): + for k, v in config_data["neighbor"]["timers"].items(): command.append( "protocols bgp neighbor ".format(**config_data) + config_data["neighbor"]["address"] @@ -80,7 +76,7 @@ def _tmplt_bgp_neighbor_timers(config_data): def _tmplt_bgp_timers(config_data): command = [] - for k, v in iteritems(config_data["timers"]): + for k, v in config_data["timers"].items(): command.append( "protocols bgp ".format(**config_data) + "timers " + k + " " + str(v), ) @@ -238,8 +234,7 @@ class Bgp_globalTemplate14(NetworkTemplate): \s+neighbor \s+(?P<address>\S+) \s+advertisement-interval - \s+(?P<interval>\S+) - *$""", + \s+(?P<interval>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp neighbor {{ neighbor.address }} advertisement-interval {{ neighbor.advertisement_interval }}", @@ -431,8 +426,7 @@ class Bgp_globalTemplate14(NetworkTemplate): \s+capability \s+orf \s+prefix-list - \s+(?P<orf>\S+) - *$""", + \s+(?P<orf>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp neighbor {{ neighbor.address }} capability orf prefix-list {{ neighbor.capability.orf }}", @@ -460,8 +454,7 @@ class Bgp_globalTemplate14(NetworkTemplate): \s+(?P<address>\S+) \s+default-originate \s+route-map - \s+(?P<map>\S+) - *$""", + \s+(?P<map>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp neighbor {{ neighbor.address }} default-originate route-map {{ neighbor.default_originate }}", @@ -486,8 +479,7 @@ class Bgp_globalTemplate14(NetworkTemplate): \s+neighbor \s+(?P<address>\S+) \s+description - \s+(?P<desc>\S+) - *$""", + \s+(?P<desc>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp neighbor {{ neighbor.address }} description {{ neighbor.description }}", @@ -562,8 +554,7 @@ class Bgp_globalTemplate14(NetworkTemplate): \s+neighbor \s+(?P<address>\S+) \s+disable-send-community - \s+(?P<comm>\S+) - *$""", + \s+(?P<comm>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp neighbor {{ neighbor.address }} disable-send-community {{ neighbor.disable_send_community }}", @@ -620,8 +611,7 @@ class Bgp_globalTemplate14(NetworkTemplate): \s+neighbor \s+(?P<address>\S+) \s+ebgp-multihop - \s+(?P<hop>\S+) - *$""", + \s+(?P<hop>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp neighbor {{ neighbor.address }} ebgp-multihop {{ neighbor.ebgp_multihop }}", @@ -647,8 +637,7 @@ class Bgp_globalTemplate14(NetworkTemplate): \s+(?P<address>\S+) \s+filter-list \s+(?P<action>export|import) - \s+(?P<list>\S+) - *$""", + \s+(?P<list>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_neighbor_filter_list, @@ -705,8 +694,7 @@ class Bgp_globalTemplate14(NetworkTemplate): \s+neighbor \s+(?P<address>\S+) \s+maximum-prefix - \s+(?P<num>\S+) - *$""", + \s+(?P<num>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp neighbor {{ neighbor.address }} maximum-prefix {{ neighbor.maximum_prefix }}", @@ -806,8 +794,7 @@ class Bgp_globalTemplate14(NetworkTemplate): \s+neighbor \s+(?P<address>\S+) \s+password - \s+(?P<pwd>\S+) - *$""", + \s+(?P<pwd>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp neighbor {{ neighbor.address }} password {{ neighbor.password }}", @@ -832,8 +819,7 @@ class Bgp_globalTemplate14(NetworkTemplate): \s+neighbor \s+(?P<address>\S+) \s+peer-group - \s+(?P<name>\S+) - *$""", + \s+(?P<name>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp neighbor {{ neighbor.address }} peer-group {{ neighbor.peer_group_name }}", @@ -858,8 +844,7 @@ class Bgp_globalTemplate14(NetworkTemplate): \s+neighbor \s+(?P<address>\S+) \s+port - \s+(?P<num>\S+) - *$""", + \s+(?P<num>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp neighbor {{ neighbor.address }} port {{ neighbor.port }}", @@ -885,8 +870,7 @@ class Bgp_globalTemplate14(NetworkTemplate): \s+(?P<address>\S+) \s+prefix-list \s+(?P<action>export|import) - \s+(?P<list>\S+) - *$""", + \s+(?P<list>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_neighbor_prefix_list, @@ -916,8 +900,7 @@ class Bgp_globalTemplate14(NetworkTemplate): \s+neighbor \s+(?P<address>\S+) \s+remote-as - \s+(?P<num>\S+) - *$""", + \s+(?P<num>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp neighbor {{ neighbor.address }} remote-as {{ neighbor.remote_as }}", @@ -968,8 +951,7 @@ class Bgp_globalTemplate14(NetworkTemplate): \s+(?P<address>\S+) \s+route-map \s+(?P<action>export|import) - \s+(?P<map>\S+) - *$""", + \s+(?P<map>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_neighbor_route_map, @@ -1125,8 +1107,7 @@ class Bgp_globalTemplate14(NetworkTemplate): \s+neighbor \s+(?P<address>\S+) \s+unsuppress-map - \s+(?P<map>\S+) - *$""", + \s+(?P<map>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp neighbor {{ neighbor.address }} unsuppress-map {{ neighbor.unsuppress_map }}", @@ -1151,8 +1132,7 @@ class Bgp_globalTemplate14(NetworkTemplate): \s+neighbor \s+(?P<address>\S+) \s+update-source - \s+(?P<src>\S+) - *$""", + \s+(?P<src>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp neighbor {{ neighbor.address }} update-source {{ neighbor.update_source }}", @@ -1177,8 +1157,7 @@ class Bgp_globalTemplate14(NetworkTemplate): \s+neighbor \s+(?P<address>\S+) \s+weight - \s+(?P<num>\S+) - *$""", + \s+(?P<num>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp neighbor {{ neighbor.address }} weight {{ neighbor.weight }}", @@ -1203,8 +1182,7 @@ class Bgp_globalTemplate14(NetworkTemplate): \s+neighbor \s+(?P<address>\S+) \s+ttl-security - \s+(?P<ttl>\S+) - *$""", + \s+(?P<ttl>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp neighbor {{ neighbor.address }} ttl-security {{ neighbor.ttl_security }}", @@ -1230,8 +1208,7 @@ class Bgp_globalTemplate14(NetworkTemplate): \s+(?P<address>\S+) \s+timers \s+(?P<type>connect|holdtime|keepalive) - \s+(?P<sec>\S+) - *$""", + \s+(?P<sec>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_neighbor_timers, @@ -1258,8 +1235,7 @@ class Bgp_globalTemplate14(NetworkTemplate): \s+bgp \s+timers \s+(?P<type>\S+) - \s+(?P<val>\S+) - *$""", + \s+(?P<val>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_timers, @@ -1376,8 +1352,7 @@ class Bgp_globalTemplate14(NetworkTemplate): \s+bgp \s+parameters \s+cluster-id - \s+(?P<id>\S+) - *$""", + \s+(?P<id>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp parameters cluster-id {{ bgp_params.cluster_id }}", @@ -1399,8 +1374,7 @@ class Bgp_globalTemplate14(NetworkTemplate): \s+parameters \s+confederation \s+(?P<type>identifier|peers) - \s+(?P<val>\S+) - *$""", + \s+(?P<val>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_params_confederation, @@ -1427,8 +1401,7 @@ class Bgp_globalTemplate14(NetworkTemplate): \s+parameters \s+dampening \s+half-life - \s+(?P<val>\S+) - *$""", + \s+(?P<val>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp parameters dampening half-life {{ bgp_params.dampening.half_life}}", @@ -1452,8 +1425,7 @@ class Bgp_globalTemplate14(NetworkTemplate): \s+parameters \s+dampening \s+max-suppress-time - \s+(?P<val>\S+) - *$""", + \s+(?P<val>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp parameters dampening max-suppress-time {{ bgp_params.dampening.max_suppress_time}}", @@ -1477,8 +1449,7 @@ class Bgp_globalTemplate14(NetworkTemplate): \s+parameters \s+dampening \s+re-use - \s+(?P<val>\S+) - *$""", + \s+(?P<val>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp parameters dampening re-use {{ bgp_params.dampening.re_use}}", @@ -1502,8 +1473,7 @@ class Bgp_globalTemplate14(NetworkTemplate): \s+parameters \s+dampening \s+start-suppress-time - \s+(?P<val>\S+) - *$""", + \s+(?P<val>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp parameters dampening start-suppress-time {{ bgp_params.dampening.start_suppress_time}}", @@ -1526,9 +1496,8 @@ class Bgp_globalTemplate14(NetworkTemplate): \s+bgp \s+parameters \s+default - \s*(?P<no_ipv4_unicast>no-ipv4-unicast)* - \s*(?P<local_pref>local-pref\s\S+) - *$""", + \s*(?P<no_ipv4_unicast>no-ipv4-unicast)? + \s*(?P<local_pref>local-pref\s\S+)?\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_params_default, @@ -1597,8 +1566,7 @@ class Bgp_globalTemplate14(NetworkTemplate): \s+distance\sprefix \s+(?P<prefix>\S+) \s+distance - \s+(?P<val>\S+) - *$""", + \s+(?P<val>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp parameters distance prefix {{ bgp_params.distance.prefix }} distance {{ bgp_params.distance.value }}", @@ -1626,8 +1594,7 @@ class Bgp_globalTemplate14(NetworkTemplate): \s+parameters \s+distance\sglobal \s+(?P<type>\S+) - \s+(?P<val>\S+) - *$""", + \s+(?P<val>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_bgp_params_distance, @@ -1675,8 +1642,7 @@ class Bgp_globalTemplate14(NetworkTemplate): \s+bgp \s+parameters \s+graceful-restart\s+stalepath-time - \s+(?P<val>\S+) - *$""", + \s+(?P<val>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp parameters graceful-restart stalepath-time {{ bgp_params.graceful_restart }}", @@ -1760,8 +1726,7 @@ class Bgp_globalTemplate14(NetworkTemplate): \s+bgp \s+parameters \s+router-id - \s+(?P<id>\S+) - *$""", + \s+(?P<id>\S+)\s*$""", re.VERBOSE, ), "setval": "protocols bgp parameters router-id {{ bgp_params.router_id }}", 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 134effca..af04da3b 100644 --- a/plugins/module_utils/network/vyos/rm_templates/ospf_interfaces.py +++ b/plugins/module_utils/network/vyos/rm_templates/ospf_interfaces.py @@ -365,8 +365,7 @@ class Ospf_interfacesTemplate(NetworkTemplate): \s+(?P<proto>ospf|ospfv3) \s+authentication \s+plaintext-password - \s+(?P<text>\S+) - *$""", + \s+(?P<text>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_ospf_int_auth_password, @@ -399,8 +398,7 @@ class Ospf_interfacesTemplate(NetworkTemplate): \s+key-id \s+(?P<id>\d+) \s+md5-key - \s+(?P<text>\S+) - *$""", + \s+(?P<text>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_ospf_int_auth_md5, @@ -572,8 +570,7 @@ class Ospf_interfacesTemplate(NetworkTemplate): \s+(?P<afi>ip|ipv6) \s+(?P<proto>ospf|ospfv3) \s+network - \s+(?P<val>\S+) - *$""", + \s+(?P<val>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_ospf_int_network, diff --git a/plugins/module_utils/network/vyos/rm_templates/ospf_interfaces_14.py b/plugins/module_utils/network/vyos/rm_templates/ospf_interfaces_14.py index 43fae1e9..484d7c44 100644 --- a/plugins/module_utils/network/vyos/rm_templates/ospf_interfaces_14.py +++ b/plugins/module_utils/network/vyos/rm_templates/ospf_interfaces_14.py @@ -5,6 +5,7 @@ from __future__ import absolute_import, division, print_function + __metaclass__ = type """ @@ -239,8 +240,7 @@ class Ospf_interfacesTemplate14(NetworkTemplate): \s+protocols \s+(?P<proto>ospf|ospfv3) \s+interface - \s+(?P<name>\S+) - *$""", + \s+(?P<name>\S+)\s*$""", re.VERBOSE, ), "remval": _tmplt_ospf_int_delete, @@ -265,8 +265,7 @@ class Ospf_interfacesTemplate14(NetworkTemplate): \s+(?P<name>\S+) \s+authentication \s+plaintext-password - \s+(?P<text>\S+) - *$""", + \s+(?P<text>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_ospf_int_auth_password, @@ -297,8 +296,7 @@ class Ospf_interfacesTemplate14(NetworkTemplate): \s+key-id \s+(?P<id>\d+) \s+md5-key - \s+(?P<text>\S+) - *$""", + \s+(?P<text>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_ospf_int_auth_md5, @@ -458,8 +456,7 @@ class Ospf_interfacesTemplate14(NetworkTemplate): \s+interface \s+(?P<name>\S+) \s+network - \s+(?P<val>\S+) - *$""", + \s+(?P<val>\S+)\s*$""", re.VERBOSE, ), "setval": _tmplt_ospf_int_network, 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..51d0ea1c 100644 --- a/plugins/module_utils/network/vyos/rm_templates/route_maps.py +++ b/plugins/module_utils/network/vyos/rm_templates/route_maps.py @@ -33,8 +33,7 @@ class Route_mapsTemplate(NetworkTemplate): "name": "route_map", "getval": re.compile( r""" - ^set\spolicy\sroute-map\s(?P<route_map>\S+) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\s*$""", re.VERBOSE, ), "compval": "route_map", @@ -51,8 +50,7 @@ class Route_mapsTemplate(NetworkTemplate): "name": "sequence", "getval": re.compile( r""" - ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\s*$""", re.VERBOSE, ), "compval": "sequence", @@ -75,8 +73,7 @@ class Route_mapsTemplate(NetworkTemplate): "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+) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\scall\s(?P<call>\S+)\s*$""", re.VERBOSE, ), "setval": "policy route-map {{route_map}} rule {{sequence}} call {{call}}", @@ -99,8 +96,7 @@ class Route_mapsTemplate(NetworkTemplate): "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+) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sdescription\s(?P<description>\S+)\s*$""", re.VERBOSE, ), "setval": "policy route-map {{route_map}} rule {{sequence}} description {{description}}", @@ -123,8 +119,7 @@ class Route_mapsTemplate(NetworkTemplate): "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+) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\saction\s(?P<action>\S+)\s*$""", re.VERBOSE, ), "setval": "policy route-map {{route_map}} rule {{sequence}} action {{action}}", @@ -147,8 +142,7 @@ class Route_mapsTemplate(NetworkTemplate): "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+) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\scontinue\s(?P<continue>\S+)\s*$""", re.VERBOSE, ), "setval": "policy route-map {{route_map}} rule {{sequence}} continue {{continue_sequence}}", @@ -171,8 +165,7 @@ class Route_mapsTemplate(NetworkTemplate): "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) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\son-match\s(?P<next>next)\s*$""", re.VERBOSE, ), "compval": "on_match.next", @@ -198,8 +191,7 @@ class Route_mapsTemplate(NetworkTemplate): "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+) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\son-match\sgoto\s(?P<goto>\S+)\s*$""", re.VERBOSE, ), "compval": "on_match.goto", @@ -225,8 +217,7 @@ class Route_mapsTemplate(NetworkTemplate): "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+) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\saggregator\sip\s(?P<ip>\S+)\s*$""", re.VERBOSE, ), "compval": "set.aggregator.ip", @@ -254,8 +245,7 @@ class Route_mapsTemplate(NetworkTemplate): "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+) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\saggregator\sas\s(?P<as>\S+)\s*$""", re.VERBOSE, ), "compval": "set.aggregator.as", @@ -283,8 +273,7 @@ class Route_mapsTemplate(NetworkTemplate): "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-exclude\s(?P<as>\S+) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\sas-path-exclude\s(?P<as>\S+)\s*$""", re.VERBOSE, ), "compval": "set.as_path_exclude", @@ -310,12 +299,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 +326,10 @@ 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)\s*$""", re.VERBOSE, ), + "compval": "set.atomic_aggregate", "setval": "policy route-map {{route_map}} rule {{sequence}} set atomic-aggregate", "result": { "route_maps": { @@ -363,8 +352,7 @@ class Route_mapsTemplate(NetworkTemplate): "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+) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\sbgp-extcommunity-rt\s(?P<bgp>\S+)\s*$""", re.VERBOSE, ), "compval": "set.bgp_extcommunity_rt", @@ -391,13 +379,12 @@ 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+)\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 +393,8 @@ class Route_mapsTemplate(NetworkTemplate): "{{sequence}}": { "sequence": "{{sequence}}", - "set": { - "comm_list": {"comm_list": "{{comm_list}}"}, + "match": { + "community": {"community_list": "{{comm_list}}"}, }, }, }, @@ -419,8 +406,7 @@ class Route_mapsTemplate(NetworkTemplate): "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+) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\scomm-list\s(?P<delete>delete)\s*$""", re.VERBOSE, ), "compval": "set.comm_list.comm_list", @@ -447,8 +433,7 @@ class Route_mapsTemplate(NetworkTemplate): "name": "set_extcommunity_rt", "getval": re.compile( r""" - ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\sextcommunity-rt\s(?P<extcommunity_rt>\S+) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\sextcommunity-rt\s(?P<extcommunity_rt>\S+)\s*$""", re.VERBOSE, ), "compval": "set.extcommunity_rt", @@ -475,8 +460,7 @@ class Route_mapsTemplate(NetworkTemplate): "name": "set_extcommunity_soo", "getval": re.compile( r""" - ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\sextcommunity-soo\s(?P<extcommunity_soo>\S+) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\sextcommunity-soo\s(?P<extcommunity_soo>\S+)\s*$""", re.VERBOSE, ), "compval": "set.extcommunity_soo", @@ -500,11 +484,65 @@ 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+)\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)\s*$""", + 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+) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\sip-next-hop\s(?P<ip_next_hop>\S+)\s*$""", re.VERBOSE, ), "compval": "set.ip_next_hop", @@ -533,8 +571,7 @@ class Route_mapsTemplate(NetworkTemplate): 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+) - *$""", + \s(?P<value>\S+)\s*$""", re.VERBOSE, ), "compval": "set.ipv6_next_hop", @@ -564,8 +601,7 @@ class Route_mapsTemplate(NetworkTemplate): "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<large_community>\S+) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\slarge-community\s(?P<large_community>\S+)\s*$""", re.VERBOSE, ), "compval": "set.large_community", @@ -592,8 +628,7 @@ class Route_mapsTemplate(NetworkTemplate): "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+) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\slocal-preference\s(?P<local_preference>\S+)\s*$""", re.VERBOSE, ), "compval": "set.local_preference", @@ -620,8 +655,7 @@ class Route_mapsTemplate(NetworkTemplate): "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+) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\smetric\s(?P<metric>\S+)\s*$""", re.VERBOSE, ), "compval": "set.metric", @@ -648,8 +682,7 @@ class Route_mapsTemplate(NetworkTemplate): "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+) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\smetric-type\s(?P<metric_type>\S+)\s*$""", re.VERBOSE, ), "compval": "set.metric_type", @@ -676,8 +709,7 @@ class Route_mapsTemplate(NetworkTemplate): "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+) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\sorigin\s(?P<origin>\S+)\s*$""", re.VERBOSE, ), "compval": "set.origin", @@ -704,8 +736,7 @@ class Route_mapsTemplate(NetworkTemplate): "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+) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\soriginator-id\s(?P<originator_id>\S+)\s*$""", re.VERBOSE, ), "compval": "set.originator_id", @@ -732,8 +763,7 @@ class Route_mapsTemplate(NetworkTemplate): "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+) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\ssrc\s(?P<src>\S+)\s*$""", re.VERBOSE, ), "compval": "set.src", @@ -760,8 +790,7 @@ class Route_mapsTemplate(NetworkTemplate): "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+) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\stag\s(?P<tag>\S+)\s*$""", re.VERBOSE, ), "compval": "set.tag", @@ -788,8 +817,7 @@ class Route_mapsTemplate(NetworkTemplate): "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+) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\sweight\s(?P<weight>\S+)\s*$""", re.VERBOSE, ), "compval": "set.weight", @@ -813,11 +841,37 @@ 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+)\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<value>\S+) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\scommunity\s(?P<value>\S+)\s*$""", re.VERBOSE, ), "compval": "set.community.value", @@ -846,8 +900,7 @@ class Route_mapsTemplate(NetworkTemplate): "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+) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\sas-path\s(?P<as_path>\S+)\s*$""", re.VERBOSE, ), "compval": "match.as_path", @@ -874,8 +927,7 @@ class Route_mapsTemplate(NetworkTemplate): "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+) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\scommunity\scommunity-list\s(?P<community_list>\S+)\s*$""", re.VERBOSE, ), "compval": "match.community.community_list", @@ -902,8 +954,7 @@ class Route_mapsTemplate(NetworkTemplate): "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>) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\scommunity\sexact-match(?P<exact_match>)\s*$""", re.VERBOSE, ), "compval": "match.community.exact_match", @@ -930,8 +981,7 @@ class Route_mapsTemplate(NetworkTemplate): "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+) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\sextcommunity\s(?P<extcommunity>\S+)\s*$""", re.VERBOSE, ), "compval": "match.extcommunity", @@ -958,8 +1008,7 @@ class Route_mapsTemplate(NetworkTemplate): "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+) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\sinterface\s(?P<interface>\S+)\s*$""", re.VERBOSE, ), "compval": "match.interface", @@ -986,8 +1035,7 @@ class Route_mapsTemplate(NetworkTemplate): "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+) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\slarge-community\slarge-community-list\s(?P<lc>\S+)\s*$""", re.VERBOSE, ), "compval": "match.large_community_large_community_list", @@ -1014,8 +1062,7 @@ class Route_mapsTemplate(NetworkTemplate): "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+) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\smetric\s(?P<metric>\S+)\s*$""", re.VERBOSE, ), "compval": "match.metric", @@ -1042,8 +1089,7 @@ class Route_mapsTemplate(NetworkTemplate): "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+) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\sorigin\s(?P<origin>\S+)\s*$""", re.VERBOSE, ), "compval": "match.origin", @@ -1070,8 +1116,7 @@ class Route_mapsTemplate(NetworkTemplate): "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+) - *$""", + ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\speer\s(?P<peer>\S+)\s*$""", re.VERBOSE, ), "compval": "match.peer", @@ -1100,8 +1145,7 @@ class Route_mapsTemplate(NetworkTemplate): 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+) - *$""", + \s(?P<value>\S+)\s*$""", re.VERBOSE, ), "compval": "match.ip.address", @@ -1134,8 +1178,7 @@ class Route_mapsTemplate(NetworkTemplate): 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+) - *$""", + \s(?P<value>\S+)\s*$""", re.VERBOSE, ), "compval": "match.ip.next_hop", @@ -1168,8 +1211,7 @@ class Route_mapsTemplate(NetworkTemplate): 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+) - *$""", + \s(?P<value>\S+)\s*$""", re.VERBOSE, ), "compval": "match.ip.route_source", @@ -1202,8 +1244,7 @@ class Route_mapsTemplate(NetworkTemplate): 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+) - *$""", + \s(?P<value>\S+)\s*$""", re.VERBOSE, ), "compval": "match.ipv6.address", @@ -1235,8 +1276,7 @@ class Route_mapsTemplate(NetworkTemplate): "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+) - *$""", + \s(?P<value>\S+)\s*$""", re.VERBOSE, ), "compval": "match.ipv6.next_hop", @@ -1261,12 +1301,37 @@ 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+)\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+) - *$""", + \s(?P<value>\S+)\s*$""", re.VERBOSE, ), "compval": "match.rpki", 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..ea61a555 --- /dev/null +++ b/plugins/module_utils/network/vyos/rm_templates/route_maps_14.py @@ -0,0 +1,1364 @@ +# -*- 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+)\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+)\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+)\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+)\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+)\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+)\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+)\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+)\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+)\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+)\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+)\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\s(?P<delete>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+)\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+)\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+)\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+)\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+)\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+)\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+)\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+)\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+)\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+)\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+)\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+)\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+)\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+)\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+)\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+)\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+)\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+)\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+)\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+)\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+)\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+)\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+)\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+)\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+)\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+)\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+)\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+)\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+)\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/rm_templates/snmp_server.py b/plugins/module_utils/network/vyos/rm_templates/snmp_server.py index 71753083..ff1c6465 100644 --- a/plugins/module_utils/network/vyos/rm_templates/snmp_server.py +++ b/plugins/module_utils/network/vyos/rm_templates/snmp_server.py @@ -140,9 +140,9 @@ class Snmp_serverTemplate(NetworkTemplate): r""" ^set\sservice\ssnmp\scommunity \s+(?P<name>\S+) - \s*(?P<auth>authorization\srw|authorization\sro)* - \s*(client\s(?P<client>\S+))* - \s*(network\s(?P<network>\S+))* + \s*(?P<auth>authorization\srw|authorization\sro)? + \s*(client\s(?P<client>\S+))? + \s*(network\s(?P<network>\S+))? $""", re.VERBOSE, ), @@ -164,8 +164,7 @@ class Snmp_serverTemplate(NetworkTemplate): "getval": re.compile( r""" ^set\sservice\ssnmp\scontact - \s+(?P<name>\S+) - *$""", + \s+(?P<name>\S+)\s*$""", re.VERBOSE, ), "setval": "service snmp contact {{ contact }}", @@ -179,8 +178,7 @@ class Snmp_serverTemplate(NetworkTemplate): "getval": re.compile( r""" ^set\sservice\ssnmp\sdescription - \s+(?P<name>\S+) - *$""", + \s+(?P<name>\S+)\s*$""", re.VERBOSE, ), "setval": "service snmp description {{ description }}", @@ -195,8 +193,8 @@ class Snmp_serverTemplate(NetworkTemplate): r""" ^set\sservice\ssnmp\slisten-address \s+(?P<addr>\S+) - \s*(port)* - \s*(?P<port>\d+)* + \s*(port)? + \s*(?P<port>\d+)? $""", re.VERBOSE, ), @@ -232,8 +230,7 @@ class Snmp_serverTemplate(NetworkTemplate): "getval": re.compile( r""" ^set\sservice\ssnmp\ssmux-peer - \s+(?P<name>\S+) - *$""", + \s+(?P<name>\S+)\s*$""", re.VERBOSE, ), "setval": "service snmp smux-peer {{ smux_peer }}", @@ -247,8 +244,7 @@ class Snmp_serverTemplate(NetworkTemplate): "getval": re.compile( r""" ^set\sservice\ssnmp\strap-source - \s+(?P<name>\S+) - *$""", + \s+(?P<name>\S+)\s*$""", re.VERBOSE, ), "setval": "service snmp trap-source {{ trap_source }}", @@ -263,9 +259,8 @@ class Snmp_serverTemplate(NetworkTemplate): r""" ^set\sservice\ssnmp\strap-target \s+(?P<name>\S+) - \s*(?P<comm>community\s\S+)* - \s*(?P<port>port\s\d+)* - $""", + \s*(?P<comm>community\s\S+)? + \s*(?P<port>port\s\d+)? $""", re.VERBOSE, ), "setval": _tmplt_snmp_server_trap_target, @@ -283,8 +278,7 @@ class Snmp_serverTemplate(NetworkTemplate): "getval": re.compile( r""" ^set\sservice\ssnmp\sv3\sengineid - \s+(?P<name>\S+) - *$""", + \s+(?P<name>\S+)\s*$""", re.VERBOSE, ), "setval": "service snmp v3 engineid {{ snmp_v3.engine_id }}", @@ -301,9 +295,9 @@ class Snmp_serverTemplate(NetworkTemplate): r""" ^set\sservice\ssnmp\sv3\sgroup \s+(?P<name>\S+) - \s*(?P<mode>mode\s\S+)* - \s*(?P<sec>seclevel\s\S+)* - \s*(?P<view>view\s\S+)* + \s*(?P<mode>mode\s\S+)? + \s*(?P<sec>seclevel\s\S+)? + \s*(?P<view>view\s\S+)? $""", re.VERBOSE, ), @@ -329,9 +323,9 @@ class Snmp_serverTemplate(NetworkTemplate): ^set\sservice\ssnmp\sv3\strap-target \s+(?P<name>\S+) \s+auth - \s*(?P<enc>encrypted-password\s\S+)* - \s*(?P<plain>plaintext-password\s\S+)* - \s*(?P<type>type\s\S+)* + \s*(?P<enc>encrypted-password\s\S+)? + \s*(?P<plain>plaintext-password\s\S+)? + \s*(?P<type>type\s\S+)? $""", re.VERBOSE, ), @@ -358,8 +352,7 @@ class Snmp_serverTemplate(NetworkTemplate): r""" ^set\sservice\ssnmp\sv3\strap-target \s+(?P<name>\S+) - \s+(?P<port>port\s\d+)* - $""", + \s+(?P<port>port\s\d+)? $""", re.VERBOSE, ), "setval": "service snmp v3 trap-target port {{ snmp_v3.trap_targets.port }}", @@ -381,7 +374,7 @@ class Snmp_serverTemplate(NetworkTemplate): r""" ^set\sservice\ssnmp\sv3\strap-target \s+(?P<name>\S+) - \s+(?P<protocol>protocol\s\S+)* + \s+(?P<protocol>protocol\s\S+)? $""", re.VERBOSE, ), @@ -404,7 +397,7 @@ class Snmp_serverTemplate(NetworkTemplate): r""" ^set\sservice\ssnmp\sv3\strap-target \s+(?P<name>\S+) - \s+(?P<type>type\s\S+)* + \s+(?P<type>type\s\S+)? $""", re.VERBOSE, ), @@ -427,7 +420,7 @@ class Snmp_serverTemplate(NetworkTemplate): r""" ^set\sservice\ssnmp\sv3\strap-target \s+(?P<name>\S+) - \s+(?P<user>user\s\S+)* + \s+(?P<user>user\s\S+)? $""", re.VERBOSE, ), @@ -451,9 +444,9 @@ class Snmp_serverTemplate(NetworkTemplate): ^set\sservice\ssnmp\sv3\strap-target \s+(?P<name>\S+) \s+privacy - \s*(?P<enc>encrypted-password\s\S+)* - \s*(?P<plain>plaintext-password\s\S+)* - \s*(?P<type>type\s\S+)* + \s*(?P<enc>encrypted-password\s\S+)? + \s*(?P<plain>plaintext-password\s\S+)? + \s*(?P<type>type\s\S+)? $""", re.VERBOSE, ), @@ -481,9 +474,9 @@ class Snmp_serverTemplate(NetworkTemplate): ^set\sservice\ssnmp\sv3\suser \s+(?P<name>\S+) \s+auth - \s*(?P<enc>encrypted-password\s\S+)* - \s*(?P<plain>plaintext-password\s\S+)* - \s*(?P<type>type\s\S+)* + \s*(?P<enc>encrypted-password\s\S+)? + \s*(?P<plain>plaintext-password\s\S+)? + \s*(?P<type>type\s\S+)? $""", re.VERBOSE, ), @@ -511,9 +504,9 @@ class Snmp_serverTemplate(NetworkTemplate): ^set\sservice\ssnmp\sv3\suser \s+(?P<name>\S+) \s+privacy - \s*(?P<enc>encrypted-password\s\S+)* - \s*(?P<plain>plaintext-password\s\S+)* - \s*(?P<type>type\s\S+)* + \s*(?P<enc>encrypted-password\s\S+)? + \s*(?P<plain>plaintext-password\s\S+)? + \s*(?P<type>type\s\S+)? $""", re.VERBOSE, ), @@ -540,8 +533,7 @@ class Snmp_serverTemplate(NetworkTemplate): r""" ^set\sservice\ssnmp\sv3\suser \s+(?P<name>\S+) - \s+(?P<group>group\s.+)* - $""", + \s+(?P<group>group\s.+)? $""", re.VERBOSE, ), "setval": "service snmp v3 user {{ snmp_v3.users.user }} group {{ snmp_v3.users.group }}", @@ -563,7 +555,7 @@ class Snmp_serverTemplate(NetworkTemplate): r""" ^set\sservice\ssnmp\sv3\suser \s+(?P<name>\S+) - \s+(?P<mode>mode\s\S+)* + \s+(?P<mode>mode\s\S+)? $""", re.VERBOSE, ), @@ -587,8 +579,8 @@ class Snmp_serverTemplate(NetworkTemplate): ^set\sservice\ssnmp\sv3\sview \s+(?P<name>\S+) \s+(?P<oid>oid\s\S+) - \s*(?P<ex>exclude\s\S+)* - \s*(?P<mask>mask\s\S+)* + \s*(?P<ex>exclude\s\S+)? + \s*(?P<mask>mask\s\S+)? $""", re.VERBOSE, ), diff --git a/plugins/module_utils/network/vyos/rm_templates/vrf.py b/plugins/module_utils/network/vyos/rm_templates/vrf.py new file mode 100644 index 00000000..5171404e --- /dev/null +++ b/plugins/module_utils/network/vyos/rm_templates/vrf.py @@ -0,0 +1,249 @@ +# -*- 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 VRF 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 VrfTemplate(NetworkTemplate): + def __init__(self, lines=None, module=None): + prefix = {"set": "set", "remove": "delete"} + super(VrfTemplate, self).__init__(lines=lines, tmplt=self, prefix=prefix, module=module) + + # fmt: off + PARSERS = [ + { + "name": "table_id", + "getval": re.compile( + r""" + ^set + \s+vrf + \s+name + \s+(?P<name>\S+) + \s+table + \s+'(?P<tid>\S+)' + $""", + re.VERBOSE, + ), + "setval": "vrf name {{ name }} table {{ table_id }}", + "result": { + "name": "{{ name }}", + "table_id": "{{ tid }}", + }, + }, + { + "name": "bind_to_all", + "getval": re.compile( + r""" + ^set + \svrf + \s(?P<bta>bind-to-all) + $""", + re.VERBOSE, + ), + "setval": "vrf bind-to-all", + "result": { + "bind_to_all": "{{ True if bta is defined }}", + }, + }, + { + "name": "vni", + "getval": re.compile( + r""" + ^set + \s+vrf + \s+name + \s+(?P<name>\S+) + \s+vni + \s'(?P<vni>\S+)' + $""", + re.VERBOSE, + ), + "setval": "vrf name {{name}} vni {{vni}}", + "result": { + "name": "{{ name }}", + "vni": "{{ vni }}", + }, + }, + { + "name": "description", + "getval": re.compile( + r""" + ^set + \svrf + \sname + \s(?P<name>\S+) + \sdescription + \s(?P<desc>\S+) + $""", + re.VERBOSE, + ), + "setval": "vrf name {{name}} description {{description}}", + "result": { + "name": "{{ name }}", + "description": "{{ desc }}", + }, + }, + { + "name": "disable_vrf", + "getval": re.compile( + r""" + ^set + \svrf + \sname + \s(?P<name>\S+) + \s(?P<disable>disable) + $""", + re.VERBOSE, + ), + "setval": "vrf name {{name}} disable", + "compval": "disable", + "result": { + "name": "{{ name }}", + "disable": "{{ True if disable is defined }}", + }, + }, + # { + # "name": "address_family", + # "getval": re.compile( + # r""" + # ^set + # \svrf + # \sname + # \s(?P<name>\S+) + # \s(?P<af>ip|ipv6) + # $""", + # re.VERBOSE, + # ), + # "setval": "vrf name {{name}} {{ af }}", + # 'compval': "address_family", + # "result": { + # "name": "{{ name }}", + # "address_family": { + # '{{ "ipv4" if af == "ip" else "ipv6" }}': { + # "afi": '{{ "ipv4" if af == "ip" else "ipv6" }}', + # }, + # }, + # }, + # }, + # { + # "name": "address_family.disable_forwarding", + # "getval": re.compile( + # r""" + # ^set + # \svrf + # \sname + # \s(?P<name>\S+) + # \s(?P<af>ip|ipv6) + # \s(?P<df>disable-forwarding) + # $""", + # re.VERBOSE, + # ), + # "setval": "vrf name {{name}} {{ afi }} disable-forwarding", + # # "compval": "address_family.ipv6.disable_forwarding", + # "result": { + # "name": "{{ name }}", + # "address_family": { + # '{{ "ipv4" if af == "ip" else "ipv6" }}': { + # "afi": '{{ "ipv4" if af == "ip" else "ipv6" }}', + # "disable_forwarding": "{{ True if df is defined }}", + # }, + # }, + # }, + # }, + { + "name": "disable_forwarding", + "getval": re.compile( + r""" + ^set + \svrf + \sname + \s(?P<name>\S+) + \s(?P<af>ip|ipv6) + \s(?P<df>disable-forwarding) + $""", + re.VERBOSE, + ), + "setval": "vrf name {{name}} {{ afi }} disable-forwarding", + "compval": "disable_forwarding", + "result": { + "name": "{{ name }}", + 'address_family': [{ + "afi": '{{ "ipv4" if af == "ip" else "ipv6" }}', + "disable_forwarding": "{{ True if df is defined }}", + }], + }, + }, + { + "name": "disable_nht", + "getval": re.compile( + r""" + ^set + \svrf + \sname + \s(?P<name>\S+) + \s(?P<af>ip|ipv6) + \snht + \s(?P<nht>no-resolve-via-default) + $""", + re.VERBOSE, + ), + "setval": "vrf name {{name}} {{ afi }} nht no-resolve-via-default", + "compval": "nht_no_resolve_via_default", + "result": { + "name": "{{ name }}", + "address_family": [{ + "afi": '{{ "ipv4" if af == "ip" else "ipv6" }}', + "nht_no_resolve_via_default": "{{ True if nht is defined }}", + }], + }, + }, + { + "name": "route_maps", + "getval": re.compile( + r""" + ^set + \svrf + \sname + \s(?P<name>\S+) + \s(?P<af>ip|ipv6) + \sprotocol + \s(?P<proto>\S+) + \sroute-map + \s'(?P<rm>\S+)' + $""", + re.VERBOSE, + ), + "setval": "vrf name {{name}} {{ afi }} protocol {{ route_maps.protocol }} route-map {{ route_maps.rm_name }}", + "compval": "route_maps", + "remval": "vrf name {{name}} {{ afi }} protocol {{ route_maps.protocol }}", + "result": { + "name": "{{ name }}", + "address_family": [{ + "afi": '{{ "ipv4" if af == "ip" else "ipv6" }}', + "route_maps": [{ + "rm_name": "{{ rm }}", + "protocol": "{{ proto }}", + }], + }], + }, + }, + ] + # fmt: on diff --git a/plugins/module_utils/network/vyos/utils/utils.py b/plugins/module_utils/network/vyos/utils/utils.py index 4c371962..78445c02 100644 --- a/plugins/module_utils/network/vyos/utils/utils.py +++ b/plugins/module_utils/network/vyos/utils/utils.py @@ -9,7 +9,6 @@ from __future__ import absolute_import, division, print_function __metaclass__ = type from ansible.module_utils.basic import missing_required_lib -from ansible.module_utils.six import iteritems try: @@ -198,7 +197,7 @@ def key_value_in_dict(have_key, have_value, want_dict): :param want_dict: :return: """ - for key, value in iteritems(want_dict): + for key, value in want_dict.items(): if key == have_key and value == have_value: return True return False @@ -270,7 +269,7 @@ def _is_w_same(w, h, key): def _in_target(h, key): """ - This function checks whether the target exist and key present in target config. + This functi checks whether the target exist and key present in target config. :param h: target config. :param key: attribute name. :return: True/False. @@ -286,3 +285,25 @@ def in_target_not_none(h, key): :return: True/False. """ return True if h and key in h and h[key] is not None else False + + +def combine(a, b, recursive=False, list_merge="replace"): + """ + Merge two dictionaries (shallow or deep). + :param a: dict + :param b: dict + :param recursive: bool, deep merge + :param list_merge: str, only 'replace' is supported (default Ansible behavior) + """ + if not isinstance(a, dict) or not isinstance(b, dict): + raise ValueError("combine expects two dictionaries") + + result = a.copy() + + for k, v in b.items(): + if recursive and k in result and isinstance(result[k], dict) and isinstance(v, dict): + result[k] = combine(result[k], v, recursive=True, list_merge=list_merge) + else: + result[k] = v + + return result diff --git a/plugins/module_utils/network/vyos/utils/version.py b/plugins/module_utils/network/vyos/utils/version.py index cc3028c3..6d84ef1c 100644 --- a/plugins/module_utils/network/vyos/utils/version.py +++ b/plugins/module_utils/network/vyos/utils/version.py @@ -7,6 +7,8 @@ """Provide version object to compare version numbers.""" from __future__ import absolute_import, division, print_function + + __metaclass__ = type diff --git a/plugins/module_utils/network/vyos/vyos.py b/plugins/module_utils/network/vyos/vyos.py index 1430b1b1..4987d6b0 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: @@ -90,11 +96,13 @@ def run_commands(module, commands, check_rc=True): return response -def load_config(module, commands, commit=False, comment=None): +def load_config(module, commands, commit=False, comment=None, confirm=None): connection = get_connection(module) try: - response = connection.edit_config(candidate=commands, commit=commit, comment=comment) + response = connection.edit_config( + candidate=commands, commit=commit, comment=comment, confirm=confirm + ) except ConnectionError as exc: module.fail_json(msg=to_text(exc, errors="surrogate_then_replace")) diff --git a/plugins/modules/vyos_banner.py b/plugins/modules/vyos_banner.py index 6b1da84b..c6598023 100644 --- a/plugins/modules/vyos_banner.py +++ b/plugins/modules/vyos_banner.py @@ -33,7 +33,7 @@ description: VyOS. It allows playbooks to add or remote banner text from the active running configuration. version_added: 1.0.0 notes: -- Tested against VyOS 1.1.8 (helium). +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025. - This module works with connection C(ansible.netcommon.network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). options: banner: diff --git a/plugins/modules/vyos_bgp_address_family.py b/plugins/modules/vyos_bgp_address_family.py index 14c3605d..c59b43e4 100644 --- a/plugins/modules/vyos_bgp_address_family.py +++ b/plugins/modules/vyos_bgp_address_family.py @@ -19,7 +19,8 @@ version_added: 1.0.0 short_description: BGP Address Family resource module description: - This module manages BGP address family configuration of interfaces on devices running VYOS. -- Tested against VYOS 1.3, 1.4 +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025 +- The provided examples of commands are valid for VyOS 1.4+ author: Gomathi Selvi Srinivasan (@GomathiselviS) options: config: @@ -285,17 +286,18 @@ EXAMPLES = """ # After State: # vyos@vyos:~$ show configuration commands | match "set protocols bgp" -# set protocols bgp 100 address-family ipv4-unicast redistribute static metric '50' -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number '4' -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast as-override -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast default-originate route-map 'map01' -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast distribute-list export '10' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast maximum-prefix '45' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast nexthop-self -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast route-map export 'map01' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast route-map import 'map01' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast weight '50' +# set protocols bgp system-as 100 +# set protocols bgp address-family ipv4-unicast redistribute static metric '50' +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number '4' +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast as-override +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast default-originate route-map 'map01' +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast distribute-list export '10' +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast maximum-prefix '45' +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast nexthop-self +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast route-map export 'map01' +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast route-map import 'map01' +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast weight '50' # vyos@vyos:~$ # # Module Execution: @@ -363,17 +365,17 @@ EXAMPLES = """ # "before": {}, # "changed": true, # "commands": [ -# "set protocols bgp 100 address-family ipv4-unicast redistribute static metric 50", -# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number 4", -# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast as-override", -# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med", -# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast default-originate route-map map01", -# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast distribute-list export 10", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast maximum-prefix 45", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast nexthop-self", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast route-map export map01", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast route-map import map01", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast weight 50" +# "set protocols bgp address-family ipv4-unicast redistribute static metric 50", +# "set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number 4", +# "set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast as-override", +# "set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med", +# "set protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast default-originate route-map map01", +# "set protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast distribute-list export 10", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast maximum-prefix 45", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast nexthop-self", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast route-map export map01", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast route-map import map01", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast weight 50" # ], # @@ -382,17 +384,18 @@ EXAMPLES = """ # Before state: # vyos@vyos:~$ show configuration commands | match "set protocols bgp" -# set protocols bgp 100 address-family ipv4-unicast redistribute static metric '50' -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number '4' -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast as-override -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast default-originate route-map 'map01' -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast distribute-list export '10' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast maximum-prefix '45' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast nexthop-self -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast route-map export 'map01' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast route-map import 'map01' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast weight '50' +# set protocols bgp system-as 100 +# set protocols bgp address-family ipv4-unicast redistribute static metric '50' +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number '4' +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast as-override +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast default-originate route-map 'map01' +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast distribute-list export '10' +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast maximum-prefix '45' +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast nexthop-self +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast route-map export 'map01' +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast route-map import 'map01' +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast weight '50' # vyos@vyos:~$ - name: Replace provided configuration with device configuration @@ -422,15 +425,16 @@ EXAMPLES = """ # After State: # # vyos@vyos:~$ show configuration commands | match "set protocols bgp" -# set protocols bgp 100 address-family ipv4-unicast redistribute static metric '50' -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast maximum-prefix '45' -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast nexthop-self -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast allowas-in number '4' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast as-override -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast attribute-unchanged med -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast default-originate route-map 'map01' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast distribute-list export '10' +# set protocols bgp system-as 100 +# set protocols bgp address-family ipv4-unicast redistribute static metric '50' +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast maximum-prefix '45' +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast nexthop-self +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast allowas-in number '4' +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast as-override +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast attribute-unchanged med +# set protocols bgp neighbor 100.11.34.12 address-family ipv6-unicast default-originate route-map 'map01' +# set protocols bgp neighbor 100.11.34.12 address-family ipv6-unicast distribute-list export '10' # vyos@vyos:~$ # # @@ -549,39 +553,40 @@ EXAMPLES = """ # }, # "changed": true, # "commands": [ -# "delete protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast distribute-list", -# "delete protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast default-originate", -# "delete protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged", -# "delete protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast as-override", -# "delete protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in", -# "delete protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast weight", -# "delete protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast route-map", -# "delete protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast nexthop-self", -# "delete protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast maximum-prefix", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast allowas-in number 4", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast as-override", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast attribute-unchanged med", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast default-originate route-map map01", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast distribute-list export 10", -# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast maximum-prefix 45", -# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast nexthop-self" +# "delete protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast distribute-list", +# "delete protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast default-originate", +# "delete protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged", +# "delete protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast as-override", +# "delete protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in", +# "delete protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast weight", +# "delete protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast route-map", +# "delete protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast nexthop-self", +# "delete protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast maximum-prefix", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast allowas-in number 4", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast as-override", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast attribute-unchanged med", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv6-unicast default-originate route-map map01", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv6-unicast distribute-list export 10", +# "set protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast maximum-prefix 45", +# "set protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast nexthop-self" # ], # Using overridden # vyos@vyos:~$ show configuration commands | match "set protocols bgp" -# set protocols bgp 100 address-family ipv4-unicast network 35.1.1.0/24 backdoor -# set protocols bgp 100 address-family ipv4-unicast redistribute static metric '50' -# set protocols bgp 100 address-family ipv6-unicast aggregate-address 6601:1:1:1::/64 summary-only -# set protocols bgp 100 address-family ipv6-unicast network 5001:1:1:1::/64 route-map 'map01' -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast maximum-prefix '45' -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast nexthop-self -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast allowas-in number '4' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast as-override -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast attribute-unchanged med -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast default-originate route-map 'map01' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast distribute-list export '10' +# set protocols bgp system-as 100 +# set protocols bgp address-family ipv4-unicast network 35.1.1.0/24 backdoor +# set protocols bgp address-family ipv4-unicast redistribute static metric '50' +# set protocols bgp address-family ipv6-unicast aggregate-address 6601:1:1:1::/64 summary-only +# set protocols bgp address-family ipv6-unicast network 5001:1:1:1::/64 route-map 'map01' +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast maximum-prefix '45' +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast nexthop-self +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast allowas-in number '4' +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast as-override +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast attribute-unchanged med +# set protocols bgp neighbor 100.11.34.12 address-family ipv6-unicast default-originate route-map 'map01' +# set protocols bgp neighbor 100.11.34.12 address-family ipv6-unicast distribute-list export '10' # vyos@vyos:~$ - name: Override @@ -611,13 +616,14 @@ EXAMPLES = """ # After State # vyos@vyos:~$ show configuration commands | match "set protocols bgp" -# set protocols bgp 100 address-family ipv4-unicast aggregate-address 60.9.2.0/24 summary-only -# set protocols bgp 100 address-family ipv6-unicast redistribute static metric '50' -# set protocols bgp 100 neighbor 20.33.1.1/24 -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast maximum-prefix '45' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast nexthop-self -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast route-map import 'map01' +# set protocols bgp system-as 100 +# set protocols bgp address-family ipv4-unicast aggregate-address 60.9.2.0/24 summary-only +# set protocols bgp address-family ipv6-unicast redistribute static metric '50' +# set protocols bgp neighbor 20.33.1.1/24 +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast +# set protocols bgp neighbor 100.11.34.12 address-family ipv6-unicast maximum-prefix '45' +# set protocols bgp neighbor 100.11.34.12 address-family ipv6-unicast nexthop-self +# set protocols bgp neighbor 100.11.34.12 address-family ipv6-unicast route-map import 'map01' # vyos@vyos:~$ @@ -742,21 +748,21 @@ EXAMPLES = """ # }, # "changed": true, # "commands": [ -# "delete protocols bgp 100 neighbor 20.33.1.1/24 address-family", -# "delete protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast distribute-list", -# "delete protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast default-originate", -# "delete protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast attribute-unchanged", -# "delete protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast as-override", -# "delete protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast allowas-in", -# "delete protocols bgp 100 address-family ipv6 aggregate-address", -# "delete protocols bgp 100 address-family ipv6 network", -# "delete protocols bgp 100 address-family ipv4 network", -# "delete protocols bgp 100 address-family ipv4 redistribute", -# "set protocols bgp 100 address-family ipv4-unicast aggregate-address 60.9.2.0/24 summary-only", -# "set protocols bgp 100 address-family ipv6-unicast redistribute static metric 50", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast maximum-prefix 45", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast nexthop-self", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast route-map import map01" +# "delete protocols bgp neighbor 20.33.1.1/24 address-family", +# "delete protocols bgp neighbor 100.11.34.12 address-family ipv6-unicast distribute-list", +# "delete protocols bgp neighbor 100.11.34.12 address-family ipv6-unicast default-originate", +# "delete protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast attribute-unchanged", +# "delete protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast as-override", +# "delete protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast allowas-in", +# "delete protocols bgp address-family ipv6 aggregate-address", +# "delete protocols bgp address-family ipv6 network", +# "delete protocols bgp address-family ipv4 network", +# "delete protocols bgp address-family ipv4 redistribute", +# "set protocols bgp address-family ipv4-unicast aggregate-address 60.9.2.0/24 summary-only", +# "set protocols bgp address-family ipv6-unicast redistribute static metric 50", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv6-unicast maximum-prefix 45", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv6-unicast nexthop-self", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv6-unicast route-map import map01" # ], # @@ -765,22 +771,23 @@ EXAMPLES = """ # Before State: # vyos@vyos:~$ show configuration commands | match "set protocols bgp" -# set protocols bgp 100 address-family ipv4-unicast aggregate-address 60.9.2.0/24 summary-only -# set protocols bgp 100 address-family ipv4-unicast redistribute static metric '50' -# set protocols bgp 100 address-family ipv6-unicast redistribute static metric '50' -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number '4' -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast as-override -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast default-originate route-map 'map01' -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast distribute-list export '10' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast maximum-prefix '45' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast nexthop-self -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast route-map export 'map01' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast route-map import 'map01' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast weight '50' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast maximum-prefix '45' -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast nexthop-self -# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast route-map import 'map01' +# set protocols bgp system-as 100 +# set protocols bgp address-family ipv4-unicast aggregate-address 60.9.2.0/24 summary-only +# set protocols bgp address-family ipv4-unicast redistribute static metric '50' +# set protocols bgp address-family ipv6-unicast redistribute static metric '50' +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number '4' +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast as-override +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast default-originate route-map 'map01' +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast distribute-list export '10' +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast maximum-prefix '45' +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast nexthop-self +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast route-map export 'map01' +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast route-map import 'map01' +# set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast weight '50' +# set protocols bgp neighbor 100.11.34.12 address-family ipv6-unicast maximum-prefix '45' +# set protocols bgp neighbor 100.11.34.12 address-family ipv6-unicast nexthop-self +# set protocols bgp neighbor 100.11.34.12 address-family ipv6-unicast route-map import 'map01' # vyos@vyos:~$ - name: Delete @@ -800,11 +807,12 @@ EXAMPLES = """ # After State: # vyos@vyos:~$ show configuration commands | match "set protocols bgp" -# set protocols bgp 100 address-family ipv6-unicast redistribute static metric '50' -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number '4' -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast as-override -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med -# set protocols bgp 100 neighbor 100.11.34.12 +# set protocols bgp system-as 100 +# set protocols bgp address-family ipv6-unicast redistribute static metric '50' +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number '4' +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast as-override +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med +# set protocols bgp neighbor 100.11.34.12 # vyos@vyos:~$ # # @@ -927,9 +935,9 @@ EXAMPLES = """ # }, # "changed": true, # "commands": [ -# "delete protocols bgp 100 address-family ipv4-unicast", -# "delete protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast", -# "delete protocols bgp 100 neighbor 100.11.34.12 address-family" +# "delete protocols bgp address-family ipv4-unicast", +# "delete protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast", +# "delete protocols bgp neighbor 100.11.34.12 address-family" # ], # @@ -1019,15 +1027,16 @@ EXAMPLES = """ # Native config: # vyos@vyos:~$ show configuration commands | match "set protocols bgp" -# set protocols bgp 100 address-family ipv4-unicast network 35.1.1.0/24 backdoor -# set protocols bgp 100 address-family ipv4-unicast redistribute static metric '50' -# set protocols bgp 100 address-family ipv6-unicast aggregate-address 6601:1:1:1::/64 summary-only -# set protocols bgp 100 address-family ipv6-unicast network 5001:1:1:1::/64 route-map 'map01' -# set protocols bgp 100 address-family ipv6-unicast redistribute static metric '50' -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number '4' -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast as-override -# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med -# set protocols bgp 100 neighbor 100.11.34.12 +# set protocols bgp system-as 100 +# set protocols bgp address-family ipv4-unicast network 35.1.1.0/24 backdoor +# set protocols bgp address-family ipv4-unicast redistribute static metric '50' +# set protocols bgp address-family ipv6-unicast aggregate-address 6601:1:1:1::/64 summary-only +# set protocols bgp address-family ipv6-unicast network 5001:1:1:1::/64 route-map 'map01' +# set protocols bgp address-family ipv6-unicast redistribute static metric '50' +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number '4' +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast as-override +# set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med +# set protocols bgp neighbor 100.11.34.12 - name: gather configs vyos.vyos.vyos_bgp_address_family: @@ -1131,17 +1140,17 @@ EXAMPLES = """ # Module Execution: # "rendered": [ -# "set protocols bgp 100 address-family ipv4-unicast redistribute static metric 50", -# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number 4", -# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast as-override", -# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med", -# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast default-originate route-map map01", -# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast distribute-list export 10", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast maximum-prefix 45", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast nexthop-self", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast route-map export map01", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast route-map import map01", -# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast weight 50" +# "set protocols bgp address-family ipv4-unicast redistribute static metric 50", +# "set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number 4", +# "set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast as-override", +# "set protocols bgp neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med", +# "set protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast default-originate route-map map01", +# "set protocols bgp neighbor 20.33.1.1/24 address-family ipv6-unicast distribute-list export 10", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast maximum-prefix 45", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast nexthop-self", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast route-map export map01", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast route-map import map01", +# "set protocols bgp neighbor 100.11.34.12 address-family ipv4-unicast weight 50" # ] """ diff --git a/plugins/modules/vyos_bgp_global.py b/plugins/modules/vyos_bgp_global.py index 4d7db472..7e9f63b1 100644 --- a/plugins/modules/vyos_bgp_global.py +++ b/plugins/modules/vyos_bgp_global.py @@ -19,7 +19,8 @@ version_added: 1.0.0 short_description: BGP global resource module description: - This module manages BGP global configuration of interfaces on devices running VYOS. -- Tested against VYOS 1.3, 1.4 +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025 +- The provided examples of commands are valid for VyOS 1.4+ author: - Gomathi Selvi Srinivasan (@GomathiselviS) options: @@ -73,37 +74,6 @@ options: description: - Minimum interval for sending routing updates. type: int - # bfd: # <-- added in 1.3 - # description: Enable Bidirectional Forwarding Detection (BFD) support - # type: dict - # suboptions: - # check-control-plane-failure: - # description: - # - Allow to write CBIT independence in BFD outgoing packets - # and read both C-BIT value of BFD and lookup BGP peer status - # type: bool - # allowas_in: --> Moved to address-family before 1.3 - # description: - # - Number of occurrences of AS number. - # type: int - # as_override: --> Moved to address-family before 1.3 - # description: - # - AS for routes sent to this neighbor to be the local AS. - # type: bool - # attribute_unchanged: --> Moved to address-family before 1.3 - # description: - # - BGP attributes are sent unchanged. - # type: dict - # suboptions: - # as_path: - # description: as_path - # type: bool - # med: - # description: med - # type: bool - # next_hop: - # description: next_hop - # type: bool capability: description: - Advertise capabilities to this neighbor. @@ -117,13 +87,6 @@ options: description: - Advertise extended nexthop capability to this neighbor. type: bool - # orf: --> Removed before 1.3 - # description: - # - Advertise ORF capability to this neighbor. - # type: str - # choices: - # - send - # - receive default_originate: description: - Send default route to this neighbor @@ -145,70 +108,14 @@ options: - Disable sending community attributes to this neighbor. type: str choices: ['extended', 'standard'] - # distribute_list: --> Moved to address-family before 1.3 - # description: Access-list to filter route updates to/from this neighbor. - # type: list - # elements: dict - # suboptions: - # action: - # description: Access-list to filter outgoing/incoming route updates to this neighbor - # type: str - # choices: ['export', 'import'] - # acl: - # description: Access-list number. - # type: int ebgp_multihop: description: - Allow this EBGP neighbor to not be on a directly connected network. Specify - the number hops. + the number of hops. type: int - # interface: # <-- added in 1.3 - # description: interface parameters - # type: dict - # suboptions: - # peer_group: - # description: Peer group for this neighbor - # type: str - # remote_as: - # description: - # - Remote AS number - # - Or 'external' for any number except this AS number - # - or 'internal' for this AS number - # type: str - # v6only: - # description: Enable BGP with v6 link-local only - # type: dict - # suboptions: - # peer_group: - # description: Peer group for this neighbor - # type: str - # remote_as: - # description: - # - Remote AS number - # - Or 'external' for any number except this AS number - # - or 'internal' for this AS number - # filter_list: --> Moved to address-family before 1.3 - # description: As-path-list to filter route updates to/from this neighbor. - # type: list - # elements: dict - # suboptions: - # action: - # description: filter outgoing/incoming route updates - # type: str - # choices: ['export', 'import'] - # path_list: - # description: As-path-list to filter - # type: str local_as: description: local as number not to be prepended to updates from EBGP peers type: int - # maximum_prefix: --> Moved to address-family before 1.3 - # description: Maximum number of prefixes to accept from this neighbor - # nexthop-self Nexthop for routes sent to this neighbor to be the local router. - # type: int - # nexthop_self: --> Moved to address-family before 1.3 - # description: Nexthop for routes sent to this neighbor to be the local router. - # type: bool override_capability: description: Ignore capability negotiation with specified neighbor. type: bool @@ -227,61 +134,18 @@ options: port: description: Neighbor's BGP port type: int - # prefix_list: --> Moved to address-family before 1.3 - # description: Prefix-list to filter route updates to/from this neighbor. - # type: list - # elements: dict - # suboptions: - # action: - # description: filter outgoing/incoming route updates - # type: str - # choices: ['export', 'import'] - # prefix_list: - # description: Prefix-list to filter - # type: str remote_as: description: Neighbor BGP AS number type: int - # remove_private_as: --> Moved to address-family before 1.3 - # description: Remove private AS numbers from AS path in outbound route updates - # type: bool - # route_map: --> Moved to address-family before 1.3 - # description: Route-map to filter route updates to/from this neighbor. - # type: list - # elements: dict - # suboptions: - # action: - # description: filter outgoing/incoming route updates - # type: str - # choices: ['export', 'import'] - # route_map: - # description: route-map to filter - # type: str - # route_reflector_client: --> Moved to address-family before 1.3 - # description: Neighbor as a route reflector client - # type: bool - # route_server_client: --> Removed prior to 1.3 - # description: Neighbor is route server client - # type: bool shutdown: description: Administratively shut down neighbor type: bool - # soft_reconfiguration: --> Moved to address-family before 1.3 - # description: Soft reconfiguration for neighbor - # type: bool solo: # <-- added in 1.3 description: Do not send back prefixes learned from the neighbor type: bool strict_capability_match: description: Enable strict capability negotiation type: bool - # unsuppress_map: --> Moved to address-family before 1.3 - # description: Route-map to selectively unsuppress suppressed routes - # type: str - - # weight: --> Moved to address-family before 1.3 - # description: Default weight for routes from this neighbor - # type: int timers: description: Neighbor timers type: dict @@ -539,33 +403,34 @@ EXAMPLES = """ # After State # vyos@vyos:~$ show configuration commands | match "set protocols bgp" -# set protocols bgp 65536 aggregate-address 192.0.2.0/24 'summary-only' -# set protocols bgp 65536 aggregate-address 203.0.113.0/24 'as-set' -# set protocols bgp 65536 maximum-paths ebgp '20' -# set protocols bgp 65536 maximum-paths ibgp '55' -# set protocols bgp 65536 neighbor 192.0.2.25 'disable-connected-check' -# set protocols bgp 65536 neighbor 192.0.2.25 timers holdtime '30' -# set protocols bgp 65536 neighbor 192.0.2.25 timers keepalive '10' -# set protocols bgp 65536 neighbor 203.0.113.5 attribute-unchanged 'as-path' -# set protocols bgp 65536 neighbor 203.0.113.5 attribute-unchanged 'med' -# set protocols bgp 65536 neighbor 203.0.113.5 attribute-unchanged 'next-hop' -# set protocols bgp 65536 neighbor 203.0.113.5 ebgp-multihop '2' -# set protocols bgp 65536 neighbor 203.0.113.5 remote-as '101' -# set protocols bgp 65536 neighbor 203.0.113.5 update-source '192.0.2.25' -# set protocols bgp 65536 neighbor 5001::64 distribute-list export '20' -# set protocols bgp 65536 neighbor 5001::64 distribute-list import '40' -# set protocols bgp 65536 neighbor 5001::64 maximum-prefix '34' -# set protocols bgp 65536 network 192.1.13.0/24 'backdoor' -# set protocols bgp 65536 parameters bestpath as-path 'confed' -# set protocols bgp 65536 parameters bestpath 'compare-routerid' -# set protocols bgp 65536 parameters confederation identifier '66' -# set protocols bgp 65536 parameters confederation peers '20' -# set protocols bgp 65536 parameters confederation peers '55' -# set protocols bgp 65536 parameters default 'no-ipv4-unicast' -# set protocols bgp 65536 parameters router-id '192.1.2.9' -# set protocols bgp 65536 redistribute connected route-map 'map01' -# set protocols bgp 65536 redistribute kernel metric '45' -# set protocols bgp 65536 timers keepalive '35' +# set protocols bgp system-as 65536 +# set protocols bgp aggregate-address 192.0.2.0/24 'summary-only' +# set protocols bgp aggregate-address 203.0.113.0/24 'as-set' +# set protocols bgp maximum-paths ebgp '20' +# set protocols bgp maximum-paths ibgp '55' +# set protocols bgp neighbor 192.0.2.25 'disable-connected-check' +# set protocols bgp neighbor 192.0.2.25 timers holdtime '30' +# set protocols bgp neighbor 192.0.2.25 timers keepalive '10' +# set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'as-path' +# set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'med' +# set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'next-hop' +# set protocols bgp neighbor 203.0.113.5 ebgp-multihop '2' +# set protocols bgp neighbor 203.0.113.5 remote-as '101' +# set protocols bgp neighbor 203.0.113.5 update-source '192.0.2.25' +# set protocols bgp neighbor 5001::64 distribute-list export '20' +# set protocols bgp neighbor 5001::64 distribute-list import '40' +# set protocols bgp neighbor 5001::64 maximum-prefix '34' +# set protocols bgp network 192.1.13.0/24 'backdoor' +# set protocols bgp parameters bestpath as-path 'confed' +# set protocols bgp parameters bestpath 'compare-routerid' +# set protocols bgp parameters confederation identifier '66' +# set protocols bgp parameters confederation peers '20' +# set protocols bgp parameters confederation peers '55' +# set protocols bgp parameters default 'no-ipv4-unicast' +# set protocols bgp parameters router-id '192.1.2.9' +# set protocols bgp redistribute connected route-map 'map01' +# set protocols bgp redistribute kernel metric '45' +# set protocols bgp timers keepalive '35' # vyos@vyos:~$ # # # Module Execution: @@ -671,33 +536,33 @@ EXAMPLES = """ # "before": {}, # "changed": true, # "commands": [ -# "set protocols bgp 65536 neighbor 192.0.2.25 disable-connected-check", -# "set protocols bgp 65536 neighbor 192.0.2.25 timers holdtime 30", -# "set protocols bgp 65536 neighbor 192.0.2.25 timers keepalive 10", -# "set protocols bgp 65536 neighbor 203.0.113.5 attribute-unchanged as-path", -# "set protocols bgp 65536 neighbor 203.0.113.5 attribute-unchanged med", -# "set protocols bgp 65536 neighbor 203.0.113.5 attribute-unchanged next-hop", -# "set protocols bgp 65536 neighbor 203.0.113.5 ebgp-multihop 2", -# "set protocols bgp 65536 neighbor 203.0.113.5 remote-as 101", -# "set protocols bgp 65536 neighbor 203.0.113.5 update-source 192.0.2.25", -# "set protocols bgp 65536 neighbor 5001::64 maximum-prefix 34", -# "set protocols bgp 65536 neighbor 5001::64 distribute-list export 20", -# "set protocols bgp 65536 neighbor 5001::64 distribute-list import 40", -# "set protocols bgp 65536 redistribute kernel metric 45", -# "set protocols bgp 65536 redistribute connected route-map map01", -# "set protocols bgp 65536 network 192.1.13.0/24 backdoor", -# "set protocols bgp 65536 aggregate-address 203.0.113.0/24 as-set", -# "set protocols bgp 65536 aggregate-address 192.0.2.0/24 summary-only", -# "set protocols bgp 65536 parameters bestpath as-path confed", -# "set protocols bgp 65536 parameters bestpath compare-routerid", -# "set protocols bgp 65536 parameters default no-ipv4-unicast", -# "set protocols bgp 65536 parameters router-id 192.1.2.9", -# "set protocols bgp 65536 parameters confederation peers 20", -# "set protocols bgp 65536 parameters confederation peers 55", -# "set protocols bgp 65536 parameters confederation identifier 66", -# "set protocols bgp 65536 maximum-paths ebgp 20", -# "set protocols bgp 65536 maximum-paths ibgp 55", -# "set protocols bgp 65536 timers keepalive 35" +# "set protocols bgp neighbor 192.0.2.25 disable-connected-check", +# "set protocols bgp neighbor 192.0.2.25 timers holdtime 30", +# "set protocols bgp neighbor 192.0.2.25 timers keepalive 10", +# "set protocols bgp neighbor 203.0.113.5 attribute-unchanged as-path", +# "set protocols bgp neighbor 203.0.113.5 attribute-unchanged med", +# "set protocols bgp neighbor 203.0.113.5 attribute-unchanged next-hop", +# "set protocols bgp neighbor 203.0.113.5 ebgp-multihop 2", +# "set protocols bgp neighbor 203.0.113.5 remote-as 101", +# "set protocols bgp neighbor 203.0.113.5 update-source 192.0.2.25", +# "set protocols bgp neighbor 5001::64 maximum-prefix 34", +# "set protocols bgp neighbor 5001::64 distribute-list export 20", +# "set protocols bgp neighbor 5001::64 distribute-list import 40", +# "set protocols bgp redistribute kernel metric 45", +# "set protocols bgp redistribute connected route-map map01", +# "set protocols bgp network 192.1.13.0/24 backdoor", +# "set protocols bgp aggregate-address 203.0.113.0/24 as-set", +# "set protocols bgp aggregate-address 192.0.2.0/24 summary-only", +# "set protocols bgp parameters bestpath as-path confed", +# "set protocols bgp parameters bestpath compare-routerid", +# "set protocols bgp parameters default no-ipv4-unicast", +# "set protocols bgp parameters router-id 192.1.2.9", +# "set protocols bgp parameters confederation peers 20", +# "set protocols bgp parameters confederation peers 55", +# "set protocols bgp parameters confederation identifier 66", +# "set protocols bgp maximum-paths ebgp 20", +# "set protocols bgp maximum-paths ibgp 55", +# "set protocols bgp timers keepalive 35" # ], # Using replaced: @@ -706,33 +571,34 @@ EXAMPLES = """ # Before state: # vyos@vyos:~$ show configuration commands | match "set protocols bgp" -# set protocols bgp 65536 aggregate-address 192.0.2.0/24 'summary-only' -# set protocols bgp 65536 aggregate-address 203.0.113.0/24 'as-set' -# set protocols bgp 65536 maximum-paths ebgp '20' -# set protocols bgp 65536 maximum-paths ibgp '55' -# set protocols bgp 65536 neighbor 192.0.2.25 'disable-connected-check' -# set protocols bgp 65536 neighbor 192.0.2.25 timers holdtime '30' -# set protocols bgp 65536 neighbor 192.0.2.25 timers keepalive '10' -# set protocols bgp 65536 neighbor 203.0.113.5 attribute-unchanged 'as-path' -# set protocols bgp 65536 neighbor 203.0.113.5 attribute-unchanged 'med' -# set protocols bgp 65536 neighbor 203.0.113.5 attribute-unchanged 'next-hop' -# set protocols bgp 65536 neighbor 203.0.113.5 ebgp-multihop '2' -# set protocols bgp 65536 neighbor 203.0.113.5 remote-as '101' -# set protocols bgp 65536 neighbor 203.0.113.5 update-source '192.0.2.25' -# set protocols bgp 65536 neighbor 5001::64 distribute-list export '20' -# set protocols bgp 65536 neighbor 5001::64 distribute-list import '40' -# set protocols bgp 65536 neighbor 5001::64 maximum-prefix '34' -# set protocols bgp 65536 network 192.1.13.0/24 'backdoor' -# set protocols bgp 65536 parameters bestpath as-path 'confed' -# set protocols bgp 65536 parameters bestpath 'compare-routerid' -# set protocols bgp 65536 parameters confederation identifier '66' -# set protocols bgp 65536 parameters confederation peers '20' -# set protocols bgp 65536 parameters confederation peers '55' -# set protocols bgp 65536 parameters default 'no-ipv4-unicast' -# set protocols bgp 65536 parameters router-id '192.1.2.9' -# set protocols bgp 65536 redistribute connected route-map 'map01' -# set protocols bgp 65536 redistribute kernel metric '45' -# set protocols bgp 65536 timers keepalive '35' +# set protocols bgp system-as 65536 +# set protocols bgp aggregate-address 192.0.2.0/24 'summary-only' +# set protocols bgp aggregate-address 203.0.113.0/24 'as-set' +# set protocols bgp maximum-paths ebgp '20' +# set protocols bgp maximum-paths ibgp '55' +# set protocols bgp neighbor 192.0.2.25 'disable-connected-check' +# set protocols bgp neighbor 192.0.2.25 timers holdtime '30' +# set protocols bgp neighbor 192.0.2.25 timers keepalive '10' +# set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'as-path' +# set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'med' +# set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'next-hop' +# set protocols bgp neighbor 203.0.113.5 ebgp-multihop '2' +# set protocols bgp neighbor 203.0.113.5 remote-as '101' +# set protocols bgp neighbor 203.0.113.5 update-source '192.0.2.25' +# set protocols bgp neighbor 5001::64 distribute-list export '20' +# set protocols bgp neighbor 5001::64 distribute-list import '40' +# set protocols bgp neighbor 5001::64 maximum-prefix '34' +# set protocols bgp network 192.1.13.0/24 'backdoor' +# set protocols bgp parameters bestpath as-path 'confed' +# set protocols bgp parameters bestpath 'compare-routerid' +# set protocols bgp parameters confederation identifier '66' +# set protocols bgp parameters confederation peers '20' +# set protocols bgp parameters confederation peers '55' +# set protocols bgp parameters default 'no-ipv4-unicast' +# set protocols bgp parameters router-id '192.1.2.9' +# set protocols bgp redistribute connected route-map 'map01' +# set protocols bgp redistribute kernel metric '45' +# set protocols bgp timers keepalive '35' # vyos@vyos:~$ - name: Replace @@ -757,11 +623,12 @@ EXAMPLES = """ # After state: # vyos@vyos:~$ show configuration commands | match "set protocols bgp" -# set protocols bgp 65536 neighbor 192.0.2.40 advertisement-interval '72' -# set protocols bgp 65536 neighbor 192.0.2.40 capability orf prefix-list 'receive' -# set protocols bgp 65536 network 203.0.113.0/24 route-map 'map01' -# set protocols bgp 65536 parameters bestpath as-path 'confed' -# set protocols bgp 65536 redistribute static route-map 'map01' +# set protocols bgp system-as 65536 +# set protocols bgp neighbor 192.0.2.40 advertisement-interval '72' +# set protocols bgp neighbor 192.0.2.40 capability orf prefix-list 'receive' +# set protocols bgp network 203.0.113.0/24 route-map 'map01' +# set protocols bgp parameters bestpath as-path 'confed' +# set protocols bgp redistribute static route-map 'map01' # vyos@vyos:~$ # # @@ -896,26 +763,26 @@ EXAMPLES = """ # }, # "changed": true, # "commands": [ -# "delete protocols bgp 65536 timers", -# "delete protocols bgp 65536 maximum-paths ", -# "delete protocols bgp 65536 maximum-paths ", -# "delete protocols bgp 65536 parameters router-id 192.1.2.9", -# "delete protocols bgp 65536 parameters default", -# "delete protocols bgp 65536 parameters confederation", -# "delete protocols bgp 65536 parameters bestpath compare-routerid", -# "delete protocols bgp 65536 aggregate-address", -# "delete protocols bgp 65536 network 192.1.13.0/24", -# "delete protocols bgp 65536 redistribute kernel", -# "delete protocols bgp 65536 redistribute kernel", -# "delete protocols bgp 65536 redistribute connected", -# "delete protocols bgp 65536 redistribute connected", -# "delete protocols bgp 65536 neighbor 5001::64", -# "delete protocols bgp 65536 neighbor 203.0.113.5", -# "delete protocols bgp 65536 neighbor 192.0.2.25", -# "set protocols bgp 65536 neighbor 192.0.2.40 advertisement-interval 72", -# "set protocols bgp 65536 neighbor 192.0.2.40 capability orf prefix-list receive", -# "set protocols bgp 65536 redistribute static route-map map01", -# "set protocols bgp 65536 network 203.0.113.0/24 route-map map01" +# "delete protocols bgp timers", +# "delete protocols bgp maximum-paths ", +# "delete protocols bgp maximum-paths ", +# "delete protocols bgp parameters router-id 192.1.2.9", +# "delete protocols bgp parameters default", +# "delete protocols bgp parameters confederation", +# "delete protocols bgp parameters bestpath compare-routerid", +# "delete protocols bgp aggregate-address", +# "delete protocols bgp network 192.1.13.0/24", +# "delete protocols bgp redistribute kernel", +# "delete protocols bgp redistribute kernel", +# "delete protocols bgp redistribute connected", +# "delete protocols bgp redistribute connected", +# "delete protocols bgp neighbor 5001::64", +# "delete protocols bgp neighbor 203.0.113.5", +# "delete protocols bgp neighbor 192.0.2.25", +# "set protocols bgp neighbor 192.0.2.40 advertisement-interval 72", +# "set protocols bgp neighbor 192.0.2.40 capability orf prefix-list receive", +# "set protocols bgp redistribute static route-map map01", +# "set protocols bgp network 203.0.113.0/24 route-map map01" # ], # Using deleted: @@ -924,11 +791,12 @@ EXAMPLES = """ # Before state: # vyos@vyos:~$ show configuration commands | match "set protocols bgp" -# set protocols bgp 65536 neighbor 192.0.2.40 advertisement-interval '72' -# set protocols bgp 65536 neighbor 192.0.2.40 capability orf prefix-list 'receive' -# set protocols bgp 65536 network 203.0.113.0/24 route-map 'map01' -# set protocols bgp 65536 parameters bestpath as-path 'confed' -# set protocols bgp 65536 redistribute static route-map 'map01' +# set protocols bgp system-as 65536 +# set protocols bgp neighbor 192.0.2.40 advertisement-interval '72' +# set protocols bgp neighbor 192.0.2.40 capability orf prefix-list 'receive' +# set protocols bgp network 203.0.113.0/24 route-map 'map01' +# set protocols bgp parameters bestpath as-path 'confed' +# set protocols bgp redistribute static route-map 'map01' # vyos@vyos:~$ - name: Delete configuration @@ -980,10 +848,10 @@ EXAMPLES = """ # }, # "changed": true, # "commands": [ -# "delete protocols bgp 65536 neighbor 192.0.2.40", -# "delete protocols bgp 65536 redistribute", -# "delete protocols bgp 65536 network", -# "delete protocols bgp 65536 parameters" +# "delete protocols bgp neighbor 192.0.2.40", +# "delete protocols bgp redistribute", +# "delete protocols bgp network", +# "delete protocols bgp parameters" # ], # Using purged: @@ -991,33 +859,34 @@ EXAMPLES = """ # Before state: # vyos@vyos:~$ show configuration commands | match "set protocols bgp" -# set protocols bgp 65536 aggregate-address 192.0.2.0/24 'summary-only' -# set protocols bgp 65536 aggregate-address 203.0.113.0/24 'as-set' -# set protocols bgp 65536 maximum-paths ebgp '20' -# set protocols bgp 65536 maximum-paths ibgp '55' -# set protocols bgp 65536 neighbor 192.0.2.25 'disable-connected-check' -# set protocols bgp 65536 neighbor 192.0.2.25 timers holdtime '30' -# set protocols bgp 65536 neighbor 192.0.2.25 timers keepalive '10' -# set protocols bgp 65536 neighbor 203.0.113.5 attribute-unchanged 'as-path' -# set protocols bgp 65536 neighbor 203.0.113.5 attribute-unchanged 'med' -# set protocols bgp 65536 neighbor 203.0.113.5 attribute-unchanged 'next-hop' -# set protocols bgp 65536 neighbor 203.0.113.5 ebgp-multihop '2' -# set protocols bgp 65536 neighbor 203.0.113.5 remote-as '101' -# set protocols bgp 65536 neighbor 203.0.113.5 update-source '192.0.2.25' -# set protocols bgp 65536 neighbor 5001::64 distribute-list export '20' -# set protocols bgp 65536 neighbor 5001::64 distribute-list import '40' -# set protocols bgp 65536 neighbor 5001::64 maximum-prefix '34' -# set protocols bgp 65536 network 192.1.13.0/24 'backdoor' -# set protocols bgp 65536 parameters bestpath as-path 'confed' -# set protocols bgp 65536 parameters bestpath 'compare-routerid' -# set protocols bgp 65536 parameters confederation identifier '66' -# set protocols bgp 65536 parameters confederation peers '20' -# set protocols bgp 65536 parameters confederation peers '55' -# set protocols bgp 65536 parameters default 'no-ipv4-unicast' -# set protocols bgp 65536 parameters router-id '192.1.2.9' -# set protocols bgp 65536 redistribute connected route-map 'map01' -# set protocols bgp 65536 redistribute kernel metric '45' -# set protocols bgp 65536 timers keepalive '35' +# set protocols bgp system-as 65536 +# set protocols bgp aggregate-address 192.0.2.0/24 'summary-only' +# set protocols bgp aggregate-address 203.0.113.0/24 'as-set' +# set protocols bgp maximum-paths ebgp '20' +# set protocols bgp maximum-paths ibgp '55' +# set protocols bgp neighbor 192.0.2.25 'disable-connected-check' +# set protocols bgp neighbor 192.0.2.25 timers holdtime '30' +# set protocols bgp neighbor 192.0.2.25 timers keepalive '10' +# set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'as-path' +# set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'med' +# set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'next-hop' +# set protocols bgp neighbor 203.0.113.5 ebgp-multihop '2' +# set protocols bgp neighbor 203.0.113.5 remote-as '101' +# set protocols bgp neighbor 203.0.113.5 update-source '192.0.2.25' +# set protocols bgp neighbor 5001::64 distribute-list export '20' +# set protocols bgp neighbor 5001::64 distribute-list import '40' +# set protocols bgp neighbor 5001::64 maximum-prefix '34' +# set protocols bgp network 192.1.13.0/24 'backdoor' +# set protocols bgp parameters bestpath as-path 'confed' +# set protocols bgp parameters bestpath 'compare-routerid' +# set protocols bgp parameters confederation identifier '66' +# set protocols bgp parameters confederation peers '20' +# set protocols bgp parameters confederation peers '55' +# set protocols bgp parameters default 'no-ipv4-unicast' +# set protocols bgp parameters router-id '192.1.2.9' +# set protocols bgp redistribute connected route-map 'map01' +# set protocols bgp redistribute kernel metric '45' +# set protocols bgp timers keepalive '35' # vyos@vyos:~$ @@ -1143,26 +1012,27 @@ EXAMPLES = """ # Before state: # vyos@vyos:~$ show configuration commands | match "set protocols bgp" -# set protocols bgp 65536 neighbor 192.0.2.43 advertisement-interval '72' -# set protocols bgp 65536 neighbor 192.0.2.43 capability 'dynamic' -# set protocols bgp 65536 neighbor 192.0.2.43 'disable-connected-check' -# set protocols bgp 65536 neighbor 192.0.2.43 timers holdtime '30' -# set protocols bgp 65536 neighbor 192.0.2.43 timers keepalive '10' -# set protocols bgp 65536 neighbor 203.0.113.0 address-family 'ipv6-unicast' -# set protocols bgp 65536 neighbor 203.0.113.0 capability orf prefix-list 'receive' -# set protocols bgp 65536 network 203.0.113.0/24 route-map 'map01' -# set protocols bgp 65536 parameters 'always-compare-med' -# set protocols bgp 65536 parameters bestpath as-path 'confed' -# set protocols bgp 65536 parameters bestpath 'compare-routerid' -# set protocols bgp 65536 parameters dampening half-life '33' -# set protocols bgp 65536 parameters dampening max-suppress-time '20' -# set protocols bgp 65536 parameters dampening re-use '60' -# set protocols bgp 65536 parameters dampening start-suppress-time '5' -# set protocols bgp 65536 parameters default 'no-ipv4-unicast' -# set protocols bgp 65536 parameters distance global external '66' -# set protocols bgp 65536 parameters distance global internal '20' -# set protocols bgp 65536 parameters distance global local '10' -# set protocols bgp 65536 redistribute static route-map 'map01' +# set protocols bgp system-as 65536 +# set protocols bgp neighbor 192.0.2.43 advertisement-interval '72' +# set protocols bgp neighbor 192.0.2.43 capability 'dynamic' +# set protocols bgp neighbor 192.0.2.43 'disable-connected-check' +# set protocols bgp neighbor 192.0.2.43 timers holdtime '30' +# set protocols bgp neighbor 192.0.2.43 timers keepalive '10' +# set protocols bgp neighbor 203.0.113.0 address-family 'ipv6-unicast' +# set protocols bgp neighbor 203.0.113.0 capability orf prefix-list 'receive' +# set protocols bgp network 203.0.113.0/24 route-map 'map01' +# set protocols bgp parameters 'always-compare-med' +# set protocols bgp parameters bestpath as-path 'confed' +# set protocols bgp parameters bestpath 'compare-routerid' +# set protocols bgp parameters dampening half-life '33' +# set protocols bgp parameters dampening max-suppress-time '20' +# set protocols bgp parameters dampening re-use '60' +# set protocols bgp parameters dampening start-suppress-time '5' +# set protocols bgp parameters default 'no-ipv4-unicast' +# set protocols bgp parameters distance global external '66' +# set protocols bgp parameters distance global internal '20' +# set protocols bgp parameters distance global local '10' +# set protocols bgp redistribute static route-map 'map01' # vyos@vyos:~$ ^C # vyos@vyos:~$ @@ -1199,26 +1069,27 @@ EXAMPLES = """ # Before state: # vyos@vyos:~$ show configuration commands | match "set protocols bgp" -# set protocols bgp 65536 neighbor 192.0.2.43 advertisement-interval '72' -# set protocols bgp 65536 neighbor 192.0.2.43 capability 'dynamic' -# set protocols bgp 65536 neighbor 192.0.2.43 'disable-connected-check' -# set protocols bgp 65536 neighbor 192.0.2.43 timers holdtime '30' -# set protocols bgp 65536 neighbor 192.0.2.43 timers keepalive '10' -# set protocols bgp 65536 neighbor 203.0.113.0 address-family 'ipv6-unicast' -# set protocols bgp 65536 neighbor 203.0.113.0 capability orf prefix-list 'receive' -# set protocols bgp 65536 network 203.0.113.0/24 route-map 'map01' -# set protocols bgp 65536 parameters 'always-compare-med' -# set protocols bgp 65536 parameters bestpath as-path 'confed' -# set protocols bgp 65536 parameters bestpath 'compare-routerid' -# set protocols bgp 65536 parameters dampening half-life '33' -# set protocols bgp 65536 parameters dampening max-suppress-time '20' -# set protocols bgp 65536 parameters dampening re-use '60' -# set protocols bgp 65536 parameters dampening start-suppress-time '5' -# set protocols bgp 65536 parameters default 'no-ipv4-unicast' -# set protocols bgp 65536 parameters distance global external '66' -# set protocols bgp 65536 parameters distance global internal '20' -# set protocols bgp 65536 parameters distance global local '10' -# set protocols bgp 65536 redistribute static route-map 'map01' +# set protocols bgp system-as 65536 +# set protocols bgp neighbor 192.0.2.43 advertisement-interval '72' +# set protocols bgp neighbor 192.0.2.43 capability 'dynamic' +# set protocols bgp neighbor 192.0.2.43 'disable-connected-check' +# set protocols bgp neighbor 192.0.2.43 timers holdtime '30' +# set protocols bgp neighbor 192.0.2.43 timers keepalive '10' +# set protocols bgp neighbor 203.0.113.0 address-family 'ipv6-unicast' +# set protocols bgp neighbor 203.0.113.0 capability orf prefix-list 'receive' +# set protocols bgp network 203.0.113.0/24 route-map 'map01' +# set protocols bgp parameters 'always-compare-med' +# set protocols bgp parameters bestpath as-path 'confed' +# set protocols bgp parameters bestpath 'compare-routerid' +# set protocols bgp parameters dampening half-life '33' +# set protocols bgp parameters dampening max-suppress-time '20' +# set protocols bgp parameters dampening re-use '60' +# set protocols bgp parameters dampening start-suppress-time '5' +# set protocols bgp parameters default 'no-ipv4-unicast' +# set protocols bgp parameters distance global external '66' +# set protocols bgp parameters distance global internal '20' +# set protocols bgp parameters distance global local '10' +# set protocols bgp redistribute static route-map 'map01' # vyos@vyos:~$ ^C - name: gather configs @@ -1292,26 +1163,26 @@ EXAMPLES = """ # parsed.cfg -# set protocols bgp 65536 neighbor 192.0.2.43 advertisement-interval '72' -# set protocols bgp 65536 neighbor 192.0.2.43 capability 'dynamic' -# set protocols bgp 65536 neighbor 192.0.2.43 'disable-connected-check' -# set protocols bgp 65536 neighbor 192.0.2.43 timers holdtime '30' -# set protocols bgp 65536 neighbor 192.0.2.43 timers keepalive '10' -# set protocols bgp 65536 neighbor 203.0.113.0 address-family 'ipv6-unicast' -# set protocols bgp 65536 neighbor 203.0.113.0 capability orf prefix-list 'receive' -# set protocols bgp 65536 network 203.0.113.0/24 route-map 'map01' -# set protocols bgp 65536 parameters 'always-compare-med' -# set protocols bgp 65536 parameters bestpath as-path 'confed' -# set protocols bgp 65536 parameters bestpath 'compare-routerid' -# set protocols bgp 65536 parameters dampening half-life '33' -# set protocols bgp 65536 parameters dampening max-suppress-time '20' -# set protocols bgp 65536 parameters dampening re-use '60' -# set protocols bgp 65536 parameters dampening start-suppress-time '5' -# set protocols bgp 65536 parameters default 'no-ipv4-unicast' -# set protocols bgp 65536 parameters distance global external '66' -# set protocols bgp 65536 parameters distance global internal '20' -# set protocols bgp 65536 parameters distance global local '10' -# set protocols bgp 65536 redistribute static route-map 'map01' +# set protocols bgp neighbor 192.0.2.43 advertisement-interval '72' +# set protocols bgp neighbor 192.0.2.43 capability 'dynamic' +# set protocols bgp neighbor 192.0.2.43 'disable-connected-check' +# set protocols bgp neighbor 192.0.2.43 timers holdtime '30' +# set protocols bgp neighbor 192.0.2.43 timers keepalive '10' +# set protocols bgp neighbor 203.0.113.0 address-family 'ipv6-unicast' +# set protocols bgp neighbor 203.0.113.0 capability orf prefix-list 'receive' +# set protocols bgp network 203.0.113.0/24 route-map 'map01' +# set protocols bgp parameters 'always-compare-med' +# set protocols bgp parameters bestpath as-path 'confed' +# set protocols bgp parameters bestpath 'compare-routerid' +# set protocols bgp parameters dampening half-life '33' +# set protocols bgp parameters dampening max-suppress-time '20' +# set protocols bgp parameters dampening re-use '60' +# set protocols bgp parameters dampening start-suppress-time '5' +# set protocols bgp parameters default 'no-ipv4-unicast' +# set protocols bgp parameters distance global external '66' +# set protocols bgp parameters distance global internal '20' +# set protocols bgp parameters distance global local '10' +# set protocols bgp redistribute static route-map 'map01' - name: parse configs vyos.vyos.vyos_bgp_global: @@ -1430,25 +1301,25 @@ EXAMPLES = """ # Module Execution: # "rendered": [ -# "set protocols bgp 65536 neighbor 192.0.2.43 disable-connected-check", -# "set protocols bgp 65536 neighbor 192.0.2.43 advertisement-interval 72", -# "set protocols bgp 65536 neighbor 192.0.2.43 capability dynamic", -# "set protocols bgp 65536 neighbor 192.0.2.43 timers holdtime 30", -# "set protocols bgp 65536 neighbor 192.0.2.43 timers keepalive 10", -# "set protocols bgp 65536 neighbor 203.0.113.0 capability orf prefix-list receive", -# "set protocols bgp 65536 redistribute static route-map map01", -# "set protocols bgp 65536 network 203.0.113.0/24 route-map map01", -# "set protocols bgp 65536 parameters always-compare-med", -# "set protocols bgp 65536 parameters dampening half-life 33", -# "set protocols bgp 65536 parameters dampening max-suppress-time 20", -# "set protocols bgp 65536 parameters dampening re-use 60", -# "set protocols bgp 65536 parameters dampening start-suppress-time 5", -# "set protocols bgp 65536 parameters distance global internal 20", -# "set protocols bgp 65536 parameters distance global local 10", -# "set protocols bgp 65536 parameters distance global external 66", -# "set protocols bgp 65536 parameters bestpath as-path confed", -# "set protocols bgp 65536 parameters bestpath compare-routerid", -# "set protocols bgp 65536 parameters default no-ipv4-unicast" +# "set protocols bgp neighbor 192.0.2.43 disable-connected-check", +# "set protocols bgp neighbor 192.0.2.43 advertisement-interval 72", +# "set protocols bgp neighbor 192.0.2.43 capability dynamic", +# "set protocols bgp neighbor 192.0.2.43 timers holdtime 30", +# "set protocols bgp neighbor 192.0.2.43 timers keepalive 10", +# "set protocols bgp neighbor 203.0.113.0 capability orf prefix-list receive", +# "set protocols bgp redistribute static route-map map01", +# "set protocols bgp network 203.0.113.0/24 route-map map01", +# "set protocols bgp parameters always-compare-med", +# "set protocols bgp parameters dampening half-life 33", +# "set protocols bgp parameters dampening max-suppress-time 20", +# "set protocols bgp parameters dampening re-use 60", +# "set protocols bgp parameters dampening start-suppress-time 5", +# "set protocols bgp parameters distance global internal 20", +# "set protocols bgp parameters distance global local 10", +# "set protocols bgp parameters distance global external 66", +# "set protocols bgp parameters bestpath as-path confed", +# "set protocols bgp parameters bestpath compare-routerid", +# "set protocols bgp parameters default no-ipv4-unicast" # ] """ @@ -1472,17 +1343,17 @@ commands: returned: when I(state) is C(merged), C(replaced), C(overridden), C(deleted) or C(purged) type: list sample: - - set protocols bgp 65536 redistribute static route-map map01 - - set protocols bgp 65536 network 203.0.113.0/24 route-map map01 - - set protocols bgp 65536 parameters always-compare-med + - set protocols bgp redistribute static route-map map01 + - set protocols bgp network 203.0.113.0/24 route-map map01 + - set protocols bgp parameters always-compare-med rendered: description: The provided configuration in the task rendered in device-native format (offline). returned: when I(state) is C(rendered) type: list sample: - - set protocols bgp 65536 redistribute static route-map map01 - - set protocols bgp 65536 network 203.0.113.0/24 route-map map01 - - set protocols bgp 65536 parameters always-compare-med + - set protocols bgp redistribute static route-map map01 + - set protocols bgp network 203.0.113.0/24 route-map map01 + - set protocols bgp parameters always-compare-med gathered: description: Facts about the network resource gathered from the remote device as structured data. returned: when I(state) is C(gathered) diff --git a/plugins/modules/vyos_command.py b/plugins/modules/vyos_command.py index bacbe26a..766370c2 100644 --- a/plugins/modules/vyos_command.py +++ b/plugins/modules/vyos_command.py @@ -86,7 +86,7 @@ options: default: 1 type: int notes: -- Tested against VyOS 1.1.8 (helium). +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025. - Running C(show system boot-messages all) will cause the module to hang since VyOS is using a custom pager setting to display the output of that command. - If a command sent to the device requires answering a prompt, it is possible to pass diff --git a/plugins/modules/vyos_config.py b/plugins/modules/vyos_config.py index 60be02c8..666bb629 100644 --- a/plugins/modules/vyos_config.py +++ b/plugins/modules/vyos_config.py @@ -34,7 +34,7 @@ version_added: 1.0.0 extends_documentation_fragment: - vyos.vyos.vyos notes: -- Tested against VyOS 1.1.8 (helium). +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025. - This module works with connection C(ansible.netcommon.network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). - To ensure idempotency and correct diff the configuration lines in the relevant module options should be similar to how they appear if present in the running configuration on device including the indentation. @@ -76,7 +76,7 @@ options: the playbook root directory or role root directory, if playbook is part of an ansible role. If the directory does not exist, it is created. type: bool - default: no + default: false comment: description: - Allows a commit description to be specified to be included when the configuration @@ -84,6 +84,25 @@ options: is ignored. default: configured by vyos_config type: str + confirm: + description: + - The C(confirm) argument will tell vyos to revert to the previous configuration + if not explicitly confirmed after applying the new config. When set to C(automatic) + this module will automatically confirm the configuration, if the current session + remains working with the new config. When set to C(manual), this module does + not issue the confirmation itself. + type: str + default: none + choices: + - automatic + - manual + - none + confirm_timeout: + description: + - Minutes to wait for confirmation before reverting the configuration. Does + not apply when C(confirm) is set to C(none) . + type: int + default: 10 config: description: - The C(config) argument specifies the base configuration to use to compare against @@ -97,14 +116,14 @@ options: description: - The C(save) argument controls whether or not changes made to the active configuration are saved to disk. This is independent of committing the config. When set - to True, the active configuration is saved. + to C(true), the active configuration is saved. type: bool - default: no + default: false backup_options: description: - This is a dict object containing configurable options related to backup file - path. The value of this option is read only when C(backup) is set to I(yes), - if C(backup) is set to I(no) this option will be silently ignored. + path. The value of this option is read only when C(backup) is set to C(true), + if C(backup) is set to C(false) this option will be silently ignored. suboptions: filename: description: @@ -123,6 +142,20 @@ options: in C(filename) within I(backup) directory. type: path type: dict + allow_password_change: + description: + - The C(allow_password_change) argument specifies whether any configuration lines which + would change a user's password should be filtered out. By default only plaintext + password changes are allowed and any encrypted-password keys are filtered out. In + order to allow all password updates, both plaintext and encrypted, set this argument + to C(all). + type: str + default: plaintext + choices: + - all + - plaintext + - encrypted + - none """ EXAMPLES = """ @@ -142,6 +175,11 @@ EXAMPLES = """ vyos.vyos.vyos_config: src: vyos_template.j2 +- name: revert after ten minutes, if connection is lost + vyos.vyos.vyos_config: + src: vyos_template.j2 + confirm: automatic + - name: for idempotency, use full-form commands vyos.vyos.vyos_config: lines: @@ -209,9 +247,9 @@ from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import DEFAULT_COMMENT = "configured by vyos_config" -CONFIG_FILTERS = [ - re.compile(r"set system login user \S+ authentication encrypted-password"), -] +PASSWORD_NEEDLE = re.compile( + r"set system login user \S+ authentication (encrypted|plaintext)-password", +) def get_candidate(module): @@ -270,14 +308,26 @@ def diff_config(commands, config): return list(updates) -def sanitize_config(config, result): +def sanitize_config(config, result, allow): result["filtered"] = list() + + if allow == "all": + return + index_to_filter = list() - for regex in CONFIG_FILTERS: - for index, line in enumerate(list(config)): - if regex.search(line): - result["filtered"].append(line) - index_to_filter.append(index) + + for index, line in enumerate(list(config)): + found = PASSWORD_NEEDLE.search(line) + + if found is None: + continue + + if allow == found[1]: + continue + + result["filtered"].append(line) + index_to_filter.append(index) + # Delete all filtered configs for filter_index in sorted(index_to_filter, reverse=True): del config[filter_index] @@ -286,6 +336,7 @@ def sanitize_config(config, result): def run(module, result): # get the current active config from the node or passed in via # the config param + config = module.params["config"] or get_config(module) # create the candidate config object from the arguments @@ -303,16 +354,23 @@ def run(module, result): module.fail_json(msg=to_text(exc, errors="surrogate_then_replace")) commands = response.get("config_diff") - sanitize_config(commands, result) + + allow_password_change = module.params["allow_password_change"] + sanitize_config(commands, result, allow=allow_password_change) result["commands"] = commands commit = not module.check_mode comment = module.params["comment"] + confirm = None + if module.params["confirm"] == "automatic" or module.params["confirm"] == "manual": + confirm = module.params["confirm_timeout"] diff = None if commands: - diff = load_config(module, commands, commit=commit, comment=comment) + diff = load_config(module, commands, commit=commit, comment=comment, confirm=confirm) + if module.params["confirm"] == "automatic": + run_commands(module, ["configure", "confirm", "exit"]) if result.get("filtered"): result["warnings"].append( @@ -332,10 +390,16 @@ def main(): lines=dict(type="list", elements="str"), match=dict(default="line", choices=["line", "none"]), comment=dict(default=DEFAULT_COMMENT), + confirm=dict(choices=["automatic", "manual", "none"], default="none"), + confirm_timeout=dict(type="int", default=10), config=dict(), backup=dict(type="bool", default=False), backup_options=dict(type="dict", options=backup_spec), save=dict(type="bool", default=False), + allow_password_change=dict( + default="plaintext", + choices=["all", "encrypted", "plaintext", "none"], + ), ) mutually_exclusive = [("lines", "src")] @@ -360,7 +424,7 @@ def main(): diff = run_commands(module, commands=["configure", "compare saved"])[1] if diff not in { "[edit]", - "No changes between working and saved configurations.\n\n[edit]" + "No changes between working and saved configurations.\n\n[edit]", }: if not module.check_mode: run_commands(module, commands=["save"]) diff --git a/plugins/modules/vyos_facts.py b/plugins/modules/vyos_facts.py index a999bd31..abc3c707 100644 --- a/plugins/modules/vyos_facts.py +++ b/plugins/modules/vyos_facts.py @@ -28,7 +28,7 @@ author: extends_documentation_fragment: - vyos.vyos.vyos notes: -- Tested against VyOS 1.1.8 (helium). +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025. - This module works with connection C(ansible.netcommon.network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). options: gather_subset: diff --git a/plugins/modules/vyos_firewall_global.py b/plugins/modules/vyos_firewall_global.py index e952ae50..50f92e91 100644 --- a/plugins/modules/vyos_firewall_global.py +++ b/plugins/modules/vyos_firewall_global.py @@ -46,7 +46,8 @@ description: VyOS devices. version_added: '1.0.0' notes: -- Tested against VyOS 1.3.8. +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025. +- The provided examples of commands are valid for VyOS 1.4+ - This module works with connection C(ansible.netcommon.network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). author: @@ -373,7 +374,7 @@ EXAMPLES = """ # "set firewall global-options send-redirects 'enable'", # "set firewall global-options config-trap 'enable'", # "set firewall global-options state-policy established action 'accept'", -# "set firewall global-options state-policy established log 'enable'", +# "set firewall global-options state-policy established log, # "set firewall global-options state-policy established log-level 'emerg'", # "set firewall global-options state-policy invalid action 'reject'", # "set firewall global-options broadcast-ping 'enable'", @@ -1189,7 +1190,7 @@ EXAMPLES = """ # "set firewall global-options send-redirects 'enable'", # "set firewall global-options config-trap 'enable'", # "set firewall global-options state-policy established action 'accept'", -# "set firewall global-options state-policy established log 'enable'", +# "set firewall global-options state-policy established log, # "set firewall global-options state-policy invalid action 'reject'", # "set firewall global-options broadcast-ping 'enable'", # "set firewall global-options all-ping 'enable'", diff --git a/plugins/modules/vyos_firewall_rules.py b/plugins/modules/vyos_firewall_rules.py index 850299ff..7213abd5 100644 --- a/plugins/modules/vyos_firewall_rules.py +++ b/plugins/modules/vyos_firewall_rules.py @@ -47,7 +47,8 @@ author: - Rohit Thakur (@rohitthakur2590) - Gaige B. Paulsen (@gaige) notes: -- Tested against VyOS 1.3.8. +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025. +- The provided examples of commands are valid for VyOS 1.4+ - This module works with connection C(ansible.netcommon.network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). @@ -134,6 +135,7 @@ options: - continue - return - jump + - offload - queue - synproxy destination: @@ -308,6 +310,10 @@ options: - Option to log packets matching rule. type: str choices: ['disable', 'enable'] + offload_target: + description: + - Match flowtable object. + type: str outbound_interface: description: - Match outbound interface. @@ -570,14 +576,14 @@ EXAMPLES = """ # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall group address-group 'inbound' -# set firewall name Downlink default-action 'accept' -# set firewall name Downlink description 'IPv4 INBOUND rule set' -# set firewall name Downlink rule 501 action 'accept' -# set firewall name Downlink rule 501 description 'Rule 501 is configured by Ansible' -# set firewall name Downlink rule 501 ipsec 'match-ipsec' -# set firewall name Downlink rule 502 action 'reject' -# set firewall name Downlink rule 502 description 'Rule 502 is configured by Ansible' -# set firewall name Downlink rule 502 ipsec 'match-ipsec' +# set firewall ipv4 name Downlink default-action 'accept' +# set firewall ipv4 name Downlink description 'IPv4 INBOUND rule set' +# set firewall ipv4 name Downlink rule 501 action 'accept' +# set firewall ipv4 name Downlink rule 501 description 'Rule 501 is configured by Ansible' +# set firewall ipv4 name Downlink rule 501 ipsec 'match-ipsec' +# set firewall ipv4 name Downlink rule 502 action 'reject' +# set firewall ipv4 name Downlink rule 502 description 'Rule 502 is configured by Ansible' +# set firewall ipv4 name Downlink rule 502 ipsec 'match-ipsec' - name: Delete attributes of given firewall rules. vyos.vyos.vyos_firewall_rules: @@ -619,7 +625,7 @@ EXAMPLES = """ # } # ] # "commands": [ -# "delete firewall name Downlink" +# "delete firewall ipv4 name Downlink" # ] # # "after": [] @@ -635,25 +641,25 @@ EXAMPLES = """ # ------------- # # vyos@vyos:~$ show configuration commands| grep firewall -# set firewall ipv6-name UPLINK default-action 'accept' -# set firewall ipv6-name UPLINK description 'This is ipv6 specific rule-set' -# set firewall ipv6-name UPLINK rule 1 action 'accept' -# set firewall ipv6-name UPLINK rule 1 -# set firewall ipv6-name UPLINK rule 1 description 'Fwipv6-Rule 1 is configured by Ansible' -# set firewall ipv6-name UPLINK rule 1 ipsec 'match-ipsec' -# set firewall ipv6-name UPLINK rule 2 action 'accept' -# set firewall ipv6-name UPLINK rule 2 -# set firewall ipv6-name UPLINK rule 2 description 'Fwipv6-Rule 2 is configured by Ansible' -# set firewall ipv6-name UPLINK rule 2 ipsec 'match-ipsec' +# set firewall ipv6 name UPLINK default-action 'accept' +# set firewall ipv6 name UPLINK description 'This is ipv6 specific rule-set' +# set firewall ipv6 name UPLINK rule 1 action 'accept' +# set firewall ipv6 name UPLINK rule 1 +# set firewall ipv6 name UPLINK rule 1 description 'Fwipv6-Rule 1 is configured by Ansible' +# set firewall ipv6 name UPLINK rule 1 ipsec 'match-ipsec' +# set firewall ipv6 name UPLINK rule 2 action 'accept' +# set firewall ipv6 name UPLINK rule 2 +# set firewall ipv6 name UPLINK rule 2 description 'Fwipv6-Rule 2 is configured by Ansible' +# set firewall ipv6 name UPLINK rule 2 ipsec 'match-ipsec' # set firewall group address-group 'inbound' -# set firewall name Downlink default-action 'accept' -# set firewall name Downlink description 'IPv4 INBOUND rule set' -# set firewall name Downlink rule 501 action 'accept' -# set firewall name Downlink rule 501 description 'Rule 501 is configured by Ansible' -# set firewall name Downlink rule 501 ipsec 'match-ipsec' -# set firewall name Downlink rule 502 action 'reject' -# set firewall name Downlink rule 502 description 'Rule 502 is configured by Ansible' -# set firewall name Downlink rule 502 ipsec 'match-ipsec' +# set firewall ipv4 name Downlink default-action 'accept' +# set firewall ipv4 name Downlink description 'IPv4 INBOUND rule set' +# set firewall ipv4 name Downlink rule 501 action 'accept' +# set firewall ipv4 name Downlink rule 501 description 'Rule 501 is configured by Ansible' +# set firewall ipv4 name Downlink rule 501 ipsec 'match-ipsec' +# set firewall ipv4 name Downlink rule 502 action 'reject' +# set firewall ipv4 name Downlink rule 502 description 'Rule 502 is configured by Ansible' +# set firewall ipv4 name Downlink rule 502 ipsec 'match-ipsec' - name: Delete attributes of given firewall rules. vyos.vyos.vyos_firewall_rules: @@ -717,23 +723,23 @@ EXAMPLES = """ # } # ] # "commands": [ -# "delete firewall name" +# "delete firewall ipv4 name" # ] # # "after": [] # After state # ------------ # vyos@vyos:~$ show configuration commands| grep firewall -# set firewall ipv6-name UPLINK default-action 'accept' -# set firewall ipv6-name UPLINK description 'This is ipv6 specific rule-set' -# set firewall ipv6-name UPLINK rule 1 action 'accept' -# set firewall ipv6-name UPLINK rule 1 -# set firewall ipv6-name UPLINK rule 1 description 'Fwipv6-Rule 1 is configured by Ansible' -# set firewall ipv6-name UPLINK rule 1 ipsec 'match-ipsec' -# set firewall ipv6-name UPLINK rule 2 action 'accept' -# set firewall ipv6-name UPLINK rule 2 -# set firewall ipv6-name UPLINK rule 2 description 'Fwipv6-Rule 2 is configured by Ansible' -# set firewall ipv6-name UPLINK rule 2 ipsec 'match-ipsec' +# set firewall ipv6 name UPLINK default-action 'accept' +# set firewall ipv6 name UPLINK description 'This is ipv6 specific rule-set' +# set firewall ipv6 name UPLINK rule 1 action 'accept' +# set firewall ipv6 name UPLINK rule 1 +# set firewall ipv6 name UPLINK rule 1 description 'Fwipv6-Rule 1 is configured by Ansible' +# set firewall ipv6 name UPLINK rule 1 ipsec 'match-ipsec' +# set firewall ipv6 name UPLINK rule 2 action 'accept' +# set firewall ipv6 name UPLINK rule 2 +# set firewall ipv6 name UPLINK rule 2 description 'Fwipv6-Rule 2 is configured by Ansible' +# set firewall ipv6 name UPLINK rule 2 ipsec 'match-ipsec' # Using deleted to delete all the the firewall rules when provided config is empty @@ -743,14 +749,14 @@ EXAMPLES = """ # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall group address-group 'inbound' -# set firewall name Downlink default-action 'accept' -# set firewall name Downlink description 'IPv4 INBOUND rule set' -# set firewall name Downlink rule 501 action 'accept' -# set firewall name Downlink rule 501 description 'Rule 501 is configured by Ansible' -# set firewall name Downlink rule 501 ipsec 'match-ipsec' -# set firewall name Downlink rule 502 action 'reject' -# set firewall name Downlink rule 502 description 'Rule 502 is configured by Ansible' -# set firewall name Downlink rule 502 ipsec 'match-ipsec' +# set firewall ipv4 name Downlink default-action 'accept' +# set firewall ipv4 name Downlink description 'IPv4 INBOUND rule set' +# set firewall ipv4 name Downlink rule 501 action 'accept' +# set firewall ipv4 name Downlink rule 501 description 'Rule 501 is configured by Ansible' +# set firewall ipv4 name Downlink rule 501 ipsec 'match-ipsec' +# set firewall ipv4 name Downlink rule 502 action 'reject' +# set firewall ipv4 name Downlink rule 502 description 'Rule 502 is configured by Ansible' +# set firewall ipv4 name Downlink rule 502 ipsec 'match-ipsec' # - name: Delete attributes of given firewall rules. vyos.vyos.vyos_firewall_rules: @@ -788,7 +794,7 @@ EXAMPLES = """ # } # ] # "commands": [ -# "delete firewall name" +# "delete firewall ipv4 name" # ] # # "after": [] @@ -860,35 +866,33 @@ EXAMPLES = """ # before": [] # # "commands": [ -# "set firewall ipv6-name UPLINK default-action 'accept'", -# "set firewall ipv6-name UPLINK description 'This is ipv6 specific rule-set'", -# "set firewall ipv6-name UPLINK rule 1 action 'accept'", -# "set firewall ipv6-name UPLINK rule 1", -# "set firewall ipv6-name UPLINK rule 1 description 'Fwipv6-Rule 1 is configured by Ansible'", -# "set firewall ipv6-name UPLINK rule 1 ipsec 'match-ipsec'", -# "set firewall ipv6-name UPLINK rule 2 action 'accept'", -# "set firewall ipv6-name UPLINK rule 2", -# "set firewall ipv6-name UPLINK rule 2 description 'Fwipv6-Rule 2 is configured by Ansible'", -# "set firewall ipv6-name UPLINK rule 2 ipsec 'match-ipsec'", -# "set firewall name INBOUND default-action 'accept'", -# "set firewall name INBOUND description 'IPv4 INBOUND rule set'", -# "set firewall name INBOUND rule 101 action 'accept'", -# "set firewall name INBOUND rule 101", -# "set firewall name INBOUND rule 101 description 'Rule 101 is configured by Ansible'", -# "set firewall name INBOUND rule 101 ipsec 'match-ipsec'", -# "set firewall name INBOUND rule 102 action 'reject'", -# "set firewall name INBOUND rule 102", -# "set firewall name INBOUND rule 102 description 'Rule 102 is configured by Ansible'", -# "set firewall name INBOUND rule 102 ipsec 'match-ipsec'", -# "set firewall name INBOUND rule 103 description 'Rule 103 is configured by Ansible'", -# "set firewall name INBOUND rule 103 destination group address-group inbound", -# "set firewall name INBOUND rule 103", -# "set firewall name INBOUND rule 103 source address 192.0.2.0", -# "set firewall name INBOUND rule 103 state established enable", -# "set firewall name INBOUND rule 103 state related enable", -# "set firewall name INBOUND rule 103 state invalid disable", -# "set firewall name INBOUND rule 103 state new disable", -# "set firewall name INBOUND rule 103 action 'accept'" +# "set firewall ipv6 name UPLINK default-action 'accept'", +# "set firewall ipv6 name UPLINK description 'This is ipv6 specific rule-set'", +# "set firewall ipv6 name UPLINK rule 1 action 'accept'", +# "set firewall ipv6 name UPLINK rule 1", +# "set firewall ipv6 name UPLINK rule 1 description 'Fwipv6-Rule 1 is configured by Ansible'", +# "set firewall ipv6 name UPLINK rule 1 ipsec 'match-ipsec'", +# "set firewall ipv6 name UPLINK rule 2 action 'accept'", +# "set firewall ipv6 name UPLINK rule 2", +# "set firewall ipv6 name UPLINK rule 2 description 'Fwipv6-Rule 2 is configured by Ansible'", +# "set firewall ipv6 name UPLINK rule 2 ipsec 'match-ipsec'", +# "set firewall ipv4 name INBOUND default-action 'accept'", +# "set firewall ipv4 name INBOUND description 'IPv4 INBOUND rule set'", +# "set firewall ipv4 name INBOUND rule 101 action 'accept'", +# "set firewall ipv4 name INBOUND rule 101", +# "set firewall ipv4 name INBOUND rule 101 description 'Rule 101 is configured by Ansible'", +# "set firewall ipv4 name INBOUND rule 101 ipsec 'match-ipsec'", +# "set firewall ipv4 name INBOUND rule 102 action 'reject'", +# "set firewall ipv4 name INBOUND rule 102", +# "set firewall ipv4 name INBOUND rule 102 description 'Rule 102 is configured by Ansible'", +# "set firewall ipv4 name INBOUND rule 102 ipsec 'match-ipsec'", +# "set firewall ipv4 name INBOUND rule 103 description 'Rule 103 is configured by Ansible'", +# "set firewall ipv4 name INBOUND rule 103 destination group address-group inbound", +# "set firewall ipv4 name INBOUND rule 103", +# "set firewall ipv4 name INBOUND rule 103 source address 192.0.2.0", +# "set firewall ipv4 name INBOUND rule 103 state established", +# "set firewall ipv4 name INBOUND rule 103 state related", +# "set firewall ipv4 name INBOUND rule 103 action 'accept'" # ] # # "after": [ @@ -966,30 +970,28 @@ EXAMPLES = """ # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall group address-group 'inbound' -# set firewall ipv6-name UPLINK default-action 'accept' -# set firewall ipv6-name UPLINK description 'This is ipv6 specific rule-set' -# set firewall ipv6-name UPLINK rule 1 action 'accept' -# set firewall ipv6-name UPLINK rule 1 description 'Fwipv6-Rule 1 is configured by Ansible' -# set firewall ipv6-name UPLINK rule 1 ipsec 'match-ipsec' -# set firewall ipv6-name UPLINK rule 2 action 'accept' -# set firewall ipv6-name UPLINK rule 2 description 'Fwipv6-Rule 2 is configured by Ansible' -# set firewall ipv6-name UPLINK rule 2 ipsec 'match-ipsec' -# set firewall name INBOUND default-action 'accept' -# set firewall name INBOUND description 'IPv4 INBOUND rule set' -# set firewall name INBOUND rule 101 action 'accept' -# set firewall name INBOUND rule 101 description 'Rule 101 is configured by Ansible' -# set firewall name INBOUND rule 101 ipsec 'match-ipsec' -# set firewall name INBOUND rule 102 action 'reject' -# set firewall name INBOUND rule 102 description 'Rule 102 is configured by Ansible' -# set firewall name INBOUND rule 102 ipsec 'match-ipsec' -# set firewall name INBOUND rule 103 action 'accept' -# set firewall name INBOUND rule 103 description 'Rule 103 is configured by Ansible' -# set firewall name INBOUND rule 103 destination group address-group 'inbound' -# set firewall name INBOUND rule 103 source address '192.0.2.0' -# set firewall name INBOUND rule 103 state established 'enable' -# set firewall name INBOUND rule 103 state invalid 'disable' -# set firewall name INBOUND rule 103 state new 'disable' -# set firewall name INBOUND rule 103 state related 'enable' +# set firewall ipv6 name UPLINK default-action 'accept' +# set firewall ipv6 name UPLINK description 'This is ipv6 specific rule-set' +# set firewall ipv6 name UPLINK rule 1 action 'accept' +# set firewall ipv6 name UPLINK rule 1 description 'Fwipv6-Rule 1 is configured by Ansible' +# set firewall ipv6 name UPLINK rule 1 ipsec 'match-ipsec' +# set firewall ipv6 name UPLINK rule 2 action 'accept' +# set firewall ipv6 name UPLINK rule 2 description 'Fwipv6-Rule 2 is configured by Ansible' +# set firewall ipv6 name UPLINK rule 2 ipsec 'match-ipsec' +# set firewall ipv4 name INBOUND default-action 'accept' +# set firewall ipv4 name INBOUND description 'IPv4 INBOUND rule set' +# set firewall ipv4 name INBOUND rule 101 action 'accept' +# set firewall ipv4 name INBOUND rule 101 description 'Rule 101 is configured by Ansible' +# set firewall ipv4 name INBOUND rule 101 ipsec 'match-ipsec' +# set firewall ipv4 name INBOUND rule 102 action 'reject' +# set firewall ipv4 name INBOUND rule 102 description 'Rule 102 is configured by Ansible' +# set firewall ipv4 name INBOUND rule 102 ipsec 'match-ipsec' +# set firewall ipv4 name INBOUND rule 103 action 'accept' +# set firewall ipv4 name INBOUND rule 103 description 'Rule 103 is configured by Ansible' +# set firewall ipv4 name INBOUND rule 103 destination group address-group 'inbound' +# set firewall ipv4 name INBOUND rule 103 source address '192.0.2.0' +# set firewall ipv4 name INBOUND rule 103 state established +# set firewall ipv4 name INBOUND rule 103 state related # Using replaced @@ -999,30 +1001,28 @@ EXAMPLES = """ # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall group address-group 'inbound' -# set firewall ipv6-name UPLINK default-action 'accept' -# set firewall ipv6-name UPLINK description 'This is ipv6 specific rule-set' -# set firewall ipv6-name UPLINK rule 1 action 'accept' -# set firewall ipv6-name UPLINK rule 1 description 'Fwipv6-Rule 1 is configured by Ansible' -# set firewall ipv6-name UPLINK rule 1 ipsec 'match-ipsec' -# set firewall ipv6-name UPLINK rule 2 action 'accept' -# set firewall ipv6-name UPLINK rule 2 description 'Fwipv6-Rule 2 is configured by Ansible' -# set firewall ipv6-name UPLINK rule 2 ipsec 'match-ipsec' -# set firewall name INBOUND default-action 'accept' -# set firewall name INBOUND description 'IPv4 INBOUND rule set' -# set firewall name INBOUND rule 101 action 'accept' -# set firewall name INBOUND rule 101 description 'Rule 101 is configured by Ansible' -# set firewall name INBOUND rule 101 ipsec 'match-ipsec' -# set firewall name INBOUND rule 102 action 'reject' -# set firewall name INBOUND rule 102 description 'Rule 102 is configured by Ansible' -# set firewall name INBOUND rule 102 ipsec 'match-ipsec' -# set firewall name INBOUND rule 103 action 'accept' -# set firewall name INBOUND rule 103 description 'Rule 103 is configured by Ansible' -# set firewall name INBOUND rule 103 destination group address-group 'inbound' -# set firewall name INBOUND rule 103 source address '192.0.2.0' -# set firewall name INBOUND rule 103 state established 'enable' -# set firewall name INBOUND rule 103 state invalid 'disable' -# set firewall name INBOUND rule 103 state new 'disable' -# set firewall name INBOUND rule 103 state related 'enable' +# set firewall ipv6 name UPLINK default-action 'accept' +# set firewall ipv6 name UPLINK description 'This is ipv6 specific rule-set' +# set firewall ipv6 name UPLINK rule 1 action 'accept' +# set firewall ipv6 name UPLINK rule 1 description 'Fwipv6-Rule 1 is configured by Ansible' +# set firewall ipv6 name UPLINK rule 1 ipsec 'match-ipsec' +# set firewall ipv6 name UPLINK rule 2 action 'accept' +# set firewall ipv6 name UPLINK rule 2 description 'Fwipv6-Rule 2 is configured by Ansible' +# set firewall ipv6 name UPLINK rule 2 ipsec 'match-ipsec' +# set firewall ipv4 name INBOUND default-action 'accept' +# set firewall ipv4 name INBOUND description 'IPv4 INBOUND rule set' +# set firewall ipv4 name INBOUND rule 101 action 'accept' +# set firewall ipv4 name INBOUND rule 101 description 'Rule 101 is configured by Ansible' +# set firewall ipv4 name INBOUND rule 101 ipsec 'match-ipsec' +# set firewall ipv4 name INBOUND rule 102 action 'reject' +# set firewall ipv4 name INBOUND rule 102 description 'Rule 102 is configured by Ansible' +# set firewall ipv4 name INBOUND rule 102 ipsec 'match-ipsec' +# set firewall ipv4 name INBOUND rule 103 action 'accept' +# set firewall ipv4 name INBOUND rule 103 description 'Rule 103 is configured by Ansible' +# set firewall ipv4 name INBOUND rule 103 destination group address-group 'inbound' +# set firewall ipv4 name INBOUND rule 103 source address '192.0.2.0' +# set firewall ipv4 name INBOUND rule 103 state established +# set firewall ipv4 name INBOUND rule 103 state related # - name: >- Replace device configurations of listed firewall rules with provided @@ -1126,14 +1126,14 @@ EXAMPLES = """ # ] # # "commands": [ -# "delete firewall ipv6-name UPLINK rule 1", -# "delete firewall ipv6-name UPLINK rule 2", -# "delete firewall name INBOUND rule 102", -# "delete firewall name INBOUND rule 103", -# "set firewall name INBOUND rule 104 action 'reject'", -# "set firewall name INBOUND rule 104 description 'Rule 104 is configured by Ansible'", -# "set firewall name INBOUND rule 104", -# "set firewall name INBOUND rule 104 ipsec 'match-none'" +# "delete firewall ipv6 name UPLINK rule 1", +# "delete firewall ipv6 name UPLINK rule 2", +# "delete firewall ipv4 name INBOUND rule 102", +# "delete firewall ipv4 name INBOUND rule 103", +# "set firewall ipv4 name INBOUND rule 104 action 'reject'", +# "set firewall ipv4 name INBOUND rule 104 description 'Rule 104 is configured by Ansible'", +# "set firewall ipv4 name INBOUND rule 104", +# "set firewall ipv4 name INBOUND rule 104 ipsec 'match-none'" # ] # # "after": [ @@ -1178,16 +1178,16 @@ EXAMPLES = """ # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall group address-group 'inbound' -# set firewall ipv6-name UPLINK default-action 'accept' -# set firewall ipv6-name UPLINK description 'This is ipv6 specific rule-set' -# set firewall name INBOUND default-action 'accept' -# set firewall name INBOUND description 'IPv4 INBOUND rule set' -# set firewall name INBOUND rule 101 action 'accept' -# set firewall name INBOUND rule 101 description 'Rule 101 is configured by Ansible' -# set firewall name INBOUND rule 101 ipsec 'match-ipsec' -# set firewall name INBOUND rule 104 action 'reject' -# set firewall name INBOUND rule 104 description 'Rule 104 is configured by Ansible' -# set firewall name INBOUND rule 104 ipsec 'match-none' +# set firewall ipv6 name UPLINK default-action 'accept' +# set firewall ipv6 name UPLINK description 'This is ipv6 specific rule-set' +# set firewall ipv4 name INBOUND default-action 'accept' +# set firewall ipv4 name INBOUND description 'IPv4 INBOUND rule set' +# set firewall ipv4 name INBOUND rule 101 action 'accept' +# set firewall ipv4 name INBOUND rule 101 description 'Rule 101 is configured by Ansible' +# set firewall ipv4 name INBOUND rule 101 ipsec 'match-ipsec' +# set firewall ipv4 name INBOUND rule 104 action 'reject' +# set firewall ipv4 name INBOUND rule 104 description 'Rule 104 is configured by Ansible' +# set firewall ipv4 name INBOUND rule 104 ipsec 'match-none' # Using overridden @@ -1197,16 +1197,16 @@ EXAMPLES = """ # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall group address-group 'inbound' -# set firewall ipv6-name UPLINK default-action 'accept' -# set firewall ipv6-name UPLINK description 'This is ipv6 specific rule-set' -# set firewall name INBOUND default-action 'accept' -# set firewall name INBOUND description 'IPv4 INBOUND rule set' -# set firewall name INBOUND rule 101 action 'accept' -# set firewall name INBOUND rule 101 description 'Rule 101 is configured by Ansible' -# set firewall name INBOUND rule 101 ipsec 'match-ipsec' -# set firewall name INBOUND rule 104 action 'reject' -# set firewall name INBOUND rule 104 description 'Rule 104 is configured by Ansible' -# set firewall name INBOUND rule 104 ipsec 'match-none' +# set firewall ipv6 name UPLINK default-action 'accept' +# set firewall ipv6 name UPLINK description 'This is ipv6 specific rule-set' +# set firewall ipv4 name INBOUND default-action 'accept' +# set firewall ipv4 name INBOUND description 'IPv4 INBOUND rule set' +# set firewall ipv4 name INBOUND rule 101 action 'accept' +# set firewall ipv4 name INBOUND rule 101 description 'Rule 101 is configured by Ansible' +# set firewall ipv4 name INBOUND rule 101 ipsec 'match-ipsec' +# set firewall ipv4 name INBOUND rule 104 action 'reject' +# set firewall ipv4 name INBOUND rule 104 description 'Rule 104 is configured by Ansible' +# set firewall ipv4 name INBOUND rule 104 ipsec 'match-none' # - name: Overrides all device configuration with provided configuration vyos.vyos.vyos_firewall_rules: @@ -1270,18 +1270,18 @@ EXAMPLES = """ # ] # # "commands": [ -# "delete firewall ipv6-name UPLINK", -# "delete firewall name INBOUND", -# "set firewall name Downlink default-action 'accept'", -# "set firewall name Downlink description 'IPv4 INBOUND rule set'", -# "set firewall name Downlink rule 501 action 'accept'", -# "set firewall name Downlink rule 501", -# "set firewall name Downlink rule 501 description 'Rule 501 is configured by Ansible'", -# "set firewall name Downlink rule 501 ipsec 'match-ipsec'", -# "set firewall name Downlink rule 502 action 'reject'", -# "set firewall name Downlink rule 502", -# "set firewall name Downlink rule 502 description 'Rule 502 is configured by Ansible'", -# "set firewall name Downlink rule 502 ipsec 'match-ipsec'" +# "delete firewall ipv6 name UPLINK", +# "delete firewall ipv4 name INBOUND", +# "set firewall ipv4 name Downlink default-action 'accept'", +# "set firewall ipv4 name Downlink description 'IPv4 INBOUND rule set'", +# "set firewall ipv4 name Downlink rule 501 action 'accept'", +# "set firewall ipv4 name Downlink rule 501", +# "set firewall ipv4 name Downlink rule 501 description 'Rule 501 is configured by Ansible'", +# "set firewall ipv4 name Downlink rule 501 ipsec 'match-ipsec'", +# "set firewall ipv4 name Downlink rule 502 action 'reject'", +# "set firewall ipv4 name Downlink rule 502", +# "set firewall ipv4 name Downlink rule 502 description 'Rule 502 is configured by Ansible'", +# "set firewall ipv4 name Downlink rule 502 ipsec 'match-ipsec'" # # # "after": [ @@ -1317,14 +1317,14 @@ EXAMPLES = """ # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall group address-group 'inbound' -# set firewall name Downlink default-action 'accept' -# set firewall name Downlink description 'IPv4 INBOUND rule set' -# set firewall name Downlink rule 501 action 'accept' -# set firewall name Downlink rule 501 description 'Rule 501 is configured by Ansible' -# set firewall name Downlink rule 501 ipsec 'match-ipsec' -# set firewall name Downlink rule 502 action 'reject' -# set firewall name Downlink rule 502 description 'Rule 502 is configured by Ansible' -# set firewall name Downlink rule 502 ipsec 'match-ipsec' +# set firewall ipv4 name Downlink default-action 'accept' +# set firewall ipv4 name Downlink description 'IPv4 INBOUND rule set' +# set firewall ipv4 name Downlink rule 501 action 'accept' +# set firewall ipv4 name Downlink rule 501 description 'Rule 501 is configured by Ansible' +# set firewall ipv4 name Downlink rule 501 ipsec 'match-ipsec' +# set firewall ipv4 name Downlink rule 502 action 'reject' +# set firewall ipv4 name Downlink rule 502 description 'Rule 502 is configured by Ansible' +# set firewall ipv4 name Downlink rule 502 ipsec 'match-ipsec' # Using gathered @@ -1334,30 +1334,28 @@ EXAMPLES = """ # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall group address-group 'inbound' -# set firewall ipv6-name UPLINK default-action 'accept' -# set firewall ipv6-name UPLINK description 'This is ipv6 specific rule-set' -# set firewall ipv6-name UPLINK rule 1 action 'accept' -# set firewall ipv6-name UPLINK rule 1 description 'Fwipv6-Rule 1 is configured by Ansible' -# set firewall ipv6-name UPLINK rule 1 ipsec 'match-ipsec' -# set firewall ipv6-name UPLINK rule 2 action 'accept' -# set firewall ipv6-name UPLINK rule 2 description 'Fwipv6-Rule 2 is configured by Ansible' -# set firewall ipv6-name UPLINK rule 2 ipsec 'match-ipsec' -# set firewall name INBOUND default-action 'accept' -# set firewall name INBOUND description 'IPv4 INBOUND rule set' -# set firewall name INBOUND rule 101 action 'accept' -# set firewall name INBOUND rule 101 description 'Rule 101 is configured by Ansible' -# set firewall name INBOUND rule 101 ipsec 'match-ipsec' -# set firewall name INBOUND rule 102 action 'reject' -# set firewall name INBOUND rule 102 description 'Rule 102 is configured by Ansible' -# set firewall name INBOUND rule 102 ipsec 'match-ipsec' -# set firewall name INBOUND rule 103 action 'accept' -# set firewall name INBOUND rule 103 description 'Rule 103 is configured by Ansible' -# set firewall name INBOUND rule 103 destination group address-group 'inbound' -# set firewall name INBOUND rule 103 source address '192.0.2.0' -# set firewall name INBOUND rule 103 state established 'enable' -# set firewall name INBOUND rule 103 state invalid 'disable' -# set firewall name INBOUND rule 103 state new 'disable' -# set firewall name INBOUND rule 103 state related 'enable' +# set firewall ipv6 name UPLINK default-action 'accept' +# set firewall ipv6 name UPLINK description 'This is ipv6 specific rule-set' +# set firewall ipv6 name UPLINK rule 1 action 'accept' +# set firewall ipv6 name UPLINK rule 1 description 'Fwipv6-Rule 1 is configured by Ansible' +# set firewall ipv6 name UPLINK rule 1 ipsec 'match-ipsec' +# set firewall ipv6 name UPLINK rule 2 action 'accept' +# set firewall ipv6 name UPLINK rule 2 description 'Fwipv6-Rule 2 is configured by Ansible' +# set firewall ipv6 name UPLINK rule 2 ipsec 'match-ipsec' +# set firewall ipv4 name INBOUND default-action 'accept' +# set firewall ipv4 name INBOUND description 'IPv4 INBOUND rule set' +# set firewall ipv4 name INBOUND rule 101 action 'accept' +# set firewall ipv4 name INBOUND rule 101 description 'Rule 101 is configured by Ansible' +# set firewall ipv4 name INBOUND rule 101 ipsec 'match-ipsec' +# set firewall ipv4 name INBOUND rule 102 action 'reject' +# set firewall ipv4 name INBOUND rule 102 description 'Rule 102 is configured by Ansible' +# set firewall ipv4 name INBOUND rule 102 ipsec 'match-ipsec' +# set firewall ipv4 name INBOUND rule 103 action 'accept' +# set firewall ipv4 name INBOUND rule 103 description 'Rule 103 is configured by Ansible' +# set firewall ipv4 name INBOUND rule 103 destination group address-group 'inbound' +# set firewall ipv4 name INBOUND rule 103 source address '192.0.2.0' +# set firewall ipv4 name INBOUND rule 103 state established +# set firewall ipv4 name INBOUND rule 103 state related # - name: Gather listed firewall rules with provided configurations vyos.vyos.vyos_firewall_rules: @@ -1445,30 +1443,28 @@ EXAMPLES = """ # # vyos@vyos:~$ show configuration commands| grep firewall # set firewall group address-group 'inbound' -# set firewall ipv6-name UPLINK default-action 'accept' -# set firewall ipv6-name UPLINK description 'This is ipv6 specific rule-set' -# set firewall ipv6-name UPLINK rule 1 action 'accept' -# set firewall ipv6-name UPLINK rule 1 description 'Fwipv6-Rule 1 is configured by Ansible' -# set firewall ipv6-name UPLINK rule 1 ipsec 'match-ipsec' -# set firewall ipv6-name UPLINK rule 2 action 'accept' -# set firewall ipv6-name UPLINK rule 2 description 'Fwipv6-Rule 2 is configured by Ansible' -# set firewall ipv6-name UPLINK rule 2 ipsec 'match-ipsec' -# set firewall name INBOUND default-action 'accept' -# set firewall name INBOUND description 'IPv4 INBOUND rule set' -# set firewall name INBOUND rule 101 action 'accept' -# set firewall name INBOUND rule 101 description 'Rule 101 is configured by Ansible' -# set firewall name INBOUND rule 101 ipsec 'match-ipsec' -# set firewall name INBOUND rule 102 action 'reject' -# set firewall name INBOUND rule 102 description 'Rule 102 is configured by Ansible' -# set firewall name INBOUND rule 102 ipsec 'match-ipsec' -# set firewall name INBOUND rule 103 action 'accept' -# set firewall name INBOUND rule 103 description 'Rule 103 is configured by Ansible' -# set firewall name INBOUND rule 103 destination group address-group 'inbound' -# set firewall name INBOUND rule 103 source address '192.0.2.0' -# set firewall name INBOUND rule 103 state established 'enable' -# set firewall name INBOUND rule 103 state invalid 'disable' -# set firewall name INBOUND rule 103 state new 'disable' -# set firewall name INBOUND rule 103 state related 'enable' +# set firewall ipv6 name UPLINK default-action 'accept' +# set firewall ipv6 name UPLINK description 'This is ipv6 specific rule-set' +# set firewall ipv6 name UPLINK rule 1 action 'accept' +# set firewall ipv6 name UPLINK rule 1 description 'Fwipv6-Rule 1 is configured by Ansible' +# set firewall ipv6 name UPLINK rule 1 ipsec 'match-ipsec' +# set firewall ipv6 name UPLINK rule 2 action 'accept' +# set firewall ipv6 name UPLINK rule 2 description 'Fwipv6-Rule 2 is configured by Ansible' +# set firewall ipv6 name UPLINK rule 2 ipsec 'match-ipsec' +# set firewall ipv4 name INBOUND default-action 'accept' +# set firewall ipv4 name INBOUND description 'IPv4 INBOUND rule set' +# set firewall ipv4 name INBOUND rule 101 action 'accept' +# set firewall ipv4 name INBOUND rule 101 description 'Rule 101 is configured by Ansible' +# set firewall ipv4 name INBOUND rule 101 ipsec 'match-ipsec' +# set firewall ipv4 name INBOUND rule 102 action 'reject' +# set firewall ipv4 name INBOUND rule 102 description 'Rule 102 is configured by Ansible' +# set firewall ipv4 name INBOUND rule 102 ipsec 'match-ipsec' +# set firewall ipv4 name INBOUND rule 103 action 'accept' +# set firewall ipv4 name INBOUND rule 103 description 'Rule 103 is configured by Ansible' +# set firewall ipv4 name INBOUND rule 103 destination group address-group 'inbound' +# set firewall ipv4 name INBOUND rule 103 source address '192.0.2.0' +# set firewall ipv4 name INBOUND rule 103 state established +# set firewall ipv4 name INBOUND rule 103 state related # Using rendered @@ -1518,27 +1514,25 @@ EXAMPLES = """ # # # "rendered": [ -# "set firewall ipv6-name UPLINK default-action 'accept'", -# "set firewall ipv6-name UPLINK description 'This is ipv6 specific rule-set'", -# "set firewall name INBOUND default-action 'accept'", -# "set firewall name INBOUND description 'IPv4 INBOUND rule set'", -# "set firewall name INBOUND rule 101 action 'accept'", -# "set firewall name INBOUND rule 101", -# "set firewall name INBOUND rule 101 description 'Rule 101 is configured by Ansible'", -# "set firewall name INBOUND rule 101 ipsec 'match-ipsec'", -# "set firewall name INBOUND rule 102 action 'reject'", -# "set firewall name INBOUND rule 102", -# "set firewall name INBOUND rule 102 description 'Rule 102 is configured by Ansible'", -# "set firewall name INBOUND rule 102 ipsec 'match-ipsec'", -# "set firewall name INBOUND rule 103 description 'Rule 103 is configured by Ansible'", -# "set firewall name INBOUND rule 103 destination group address-group inbound", -# "set firewall name INBOUND rule 103", -# "set firewall name INBOUND rule 103 source address 192.0.2.0", -# "set firewall name INBOUND rule 103 state established enable", -# "set firewall name INBOUND rule 103 state related enable", -# "set firewall name INBOUND rule 103 state invalid disable", -# "set firewall name INBOUND rule 103 state new disable", -# "set firewall name INBOUND rule 103 action 'accept'" +# "set firewall ipv6 name UPLINK default-action 'accept'", +# "set firewall ipv6 name UPLINK description 'This is ipv6 specific rule-set'", +# "set firewall ipv4 name INBOUND default-action 'accept'", +# "set firewall ipv4 name INBOUND description 'IPv4 INBOUND rule set'", +# "set firewall ipv4 name INBOUND rule 101 action 'accept'", +# "set firewall ipv4 name INBOUND rule 101", +# "set firewall ipv4 name INBOUND rule 101 description 'Rule 101 is configured by Ansible'", +# "set firewall ipv4 name INBOUND rule 101 ipsec 'match-ipsec'", +# "set firewall ipv4 name INBOUND rule 102 action 'reject'", +# "set firewall ipv4 name INBOUND rule 102", +# "set firewall ipv4 name INBOUND rule 102 description 'Rule 102 is configured by Ansible'", +# "set firewall ipv4 name INBOUND rule 102 ipsec 'match-ipsec'", +# "set firewall ipv4 name INBOUND rule 103 description 'Rule 103 is configured by Ansible'", +# "set firewall ipv4 name INBOUND rule 103 destination group address-group inbound", +# "set firewall ipv4 name INBOUND rule 103", +# "set firewall ipv4 name INBOUND rule 103 source address 192.0.2.0", +# "set firewall ipv4 name INBOUND rule 103 state established", +# "set firewall ipv4 name INBOUND rule 103 state related", +# "set firewall ipv4 name INBOUND rule 103 action 'accept'" # ] @@ -1549,14 +1543,14 @@ EXAMPLES = """ vyos.vyos.vyos_firewall_rules: running_config: "set firewall group address-group 'inbound' - set firewall name Downlink default-action 'accept' - set firewall name Downlink description 'IPv4 INBOUND rule set' - set firewall name Downlink rule 501 action 'accept' - set firewall name Downlink rule 501 description 'Rule 501 is configured by Ansible' - set firewall name Downlink rule 501 ipsec 'match-ipsec' - set firewall name Downlink rule 502 action 'reject' - set firewall name Downlink rule 502 description 'Rule 502 is configured by Ansible' - set firewall name Downlink rule 502 ipsec 'match-ipsec'" + set firewall ipv4 name Downlink default-action 'accept' + set firewall ipv4 name Downlink description 'IPv4 INBOUND rule set' + set firewall ipv4 name Downlink rule 501 action 'accept' + set firewall ipv4 name Downlink rule 501 description 'Rule 501 is configured by Ansible' + set firewall ipv4 name Downlink rule 501 ipsec 'match-ipsec' + set firewall ipv4 name Downlink rule 502 action 'reject' + set firewall ipv4 name Downlink rule 502 description 'Rule 502 is configured by Ansible' + set firewall ipv4 name Downlink rule 502 ipsec 'match-ipsec'" state: parsed # # @@ -1612,21 +1606,21 @@ commands: returned: always type: list sample: - - "set firewall name Downlink default-action 'accept'" - - "set firewall name Downlink description 'IPv4 INBOUND rule set'" - - "set firewall name Downlink rule 501 action 'accept'" - - "set firewall name Downlink rule 502 description 'Rule 502 is configured by Ansible'" - - "set firewall name Downlink rule 502 ipsec 'match-ipsec'" + - "set firewall ipv4 name Downlink default-action 'accept'" + - "set firewall ipv4 name Downlink description 'IPv4 INBOUND rule set'" + - "set firewall ipv4 name Downlink rule 501 action 'accept'" + - "set firewall ipv4 name Downlink rule 502 description 'Rule 502 is configured by Ansible'" + - "set firewall ipv4 name Downlink rule 502 ipsec 'match-ipsec'" rendered: description: The provided configuration in the task rendered in device-native format (offline). returned: when I(state) is C(rendered) type: list sample: - - "set firewall name Downlink default-action 'accept'" - - "set firewall name Downlink description 'IPv4 INBOUND rule set'" - - "set firewall name Downlink rule 501 action 'accept'" - - "set firewall name Downlink rule 502 description 'Rule 502 is configured by Ansible'" - - "set firewall name Downlink rule 502 ipsec 'match-ipsec'" + - "set firewall ipv4 name Downlink default-action 'accept'" + - "set firewall ipv4 name Downlink description 'IPv4 INBOUND rule set'" + - "set firewall ipv4 name Downlink rule 501 action 'accept'" + - "set firewall ipv4 name Downlink rule 502 description 'Rule 502 is configured by Ansible'" + - "set firewall ipv4 name Downlink rule 502 ipsec 'match-ipsec'" gathered: description: Facts about the network resource gathered from the remote device as structured data. returned: when I(state) is C(gathered) diff --git a/plugins/modules/vyos_interfaces.py b/plugins/modules/vyos_interfaces.py index 6125b4b9..82b4fd70 100644 --- a/plugins/modules/vyos_interfaces.py +++ b/plugins/modules/vyos_interfaces.py @@ -47,7 +47,7 @@ description: - This module supports managing base attributes of Ethernet, Bonding, VXLAN, Loopback and Virtual Tunnel Interfaces. notes: -- Tested against VyOS 1.3.8 +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025 - This module works with connection C(ansible.netcommon.network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). author: diff --git a/plugins/modules/vyos_lag_interfaces.py b/plugins/modules/vyos_lag_interfaces.py index 090021ad..a90d0098 100644 --- a/plugins/modules/vyos_lag_interfaces.py +++ b/plugins/modules/vyos_lag_interfaces.py @@ -46,7 +46,7 @@ description: This module manages attributes of link aggregation groups on VyOS n author: - Rohit Thakur (@rohitthakur2590) notes: -- Tested against VyOS 1.3.8. +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025. - This module works with connection C(ansible.netcommon.network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). options: config: diff --git a/plugins/modules/vyos_lldp_global.py b/plugins/modules/vyos_lldp_global.py index 190f4513..d1ac618a 100644 --- a/plugins/modules/vyos_lldp_global.py +++ b/plugins/modules/vyos_lldp_global.py @@ -45,7 +45,7 @@ short_description: LLDP global resource module description: This module manages link layer discovery protocol (LLDP) attributes on VyOS devices. notes: -- Tested against VyOS 1.3.8 +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025 - This module works with connection C(ansible.netcommon.network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). author: - Rohit Thakur (@rohitthakur2590) diff --git a/plugins/modules/vyos_lldp_interfaces.py b/plugins/modules/vyos_lldp_interfaces.py index 0a8f892b..ce1c9643 100644 --- a/plugins/modules/vyos_lldp_interfaces.py +++ b/plugins/modules/vyos_lldp_interfaces.py @@ -44,7 +44,7 @@ version_added: '1.0.0' short_description: LLDP interfaces resource module description: This module manages attributes of lldp interfaces on VyOS network devices. notes: -- Tested against VyOS 1.3.8 +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025 - This module works with connection C(ansible.netcommon.network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). author: diff --git a/plugins/modules/vyos_logging_global.py b/plugins/modules/vyos_logging_global.py index 9479e7b2..3380b9ea 100644 --- a/plugins/modules/vyos_logging_global.py +++ b/plugins/modules/vyos_logging_global.py @@ -20,7 +20,7 @@ short_description: Logging resource module description: This module manages the logging attributes of Vyos network devices author: Sagar Paul (@KB-perByte) notes: - - Tested against vyos 1.3.8+ + - Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025 - This module works with connection C(network_cli). - The Configuration defaults of the Vyos network devices are supposed to hinder idempotent behavior of plays diff --git a/plugins/modules/vyos_ntp_global.py b/plugins/modules/vyos_ntp_global.py index cad08a68..6461a32b 100644 --- a/plugins/modules/vyos_ntp_global.py +++ b/plugins/modules/vyos_ntp_global.py @@ -22,7 +22,7 @@ description: author: - Varshitha Yataluru (@YVarshitha) notes: -- Tested against vyos 1.3.8 +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025 - This module works with connection C(network_cli). - "VyOS v.1.4+ uses chronyd, and path changes from `system` to `service`" options: diff --git a/plugins/modules/vyos_ospf_interfaces.py b/plugins/modules/vyos_ospf_interfaces.py index f86acb7a..6a065f17 100644 --- a/plugins/modules/vyos_ospf_interfaces.py +++ b/plugins/modules/vyos_ospf_interfaces.py @@ -19,6 +19,7 @@ version_added: 1.2.0 short_description: OSPF Interfaces Resource Module. description: - This module manages OSPF configuration of interfaces on devices running VYOS. +- The provided examples of commands are valid for VyOS 1.4+ author: Gomathi Selvi Srinivasan (@GomathiselviS) options: config: @@ -173,14 +174,14 @@ EXAMPLES = """ # -------------- # vyos@vyos:~$ show configuration commands | match "ospf" -# set interfaces bonding bond2 ip ospf authentication md5 key-id 10 md5-key '1111111111232345' -# set interfaces bonding bond2 ip ospf bandwidth '70' -# set interfaces bonding bond2 ip ospf transmit-delay '45' -# set interfaces bonding bond2 ipv6 ospfv3 'passive' -# set interfaces ethernet eth1 ip ospf network 'point-to-point' -# set interfaces ethernet eth1 ip ospf priority '26' -# set interfaces ethernet eth1 ip ospf transmit-delay '50' -# set interfaces ethernet eth1 ipv6 ospfv3 dead-interval '39' +# set protocols ospf interface bond2 authentication md5 key-id 10 md5-key '1111111111232345' +# set protocols ospf interface bond2 bandwidth '70' +# set protocols ospf interface bond2 transmit-delay '45' +# set protocols ospfv3 interface bond2 'passive' +# set protocols ospf interface eth1 network 'point-to-point' +# set protocols ospf interface eth1 priority '26' +# set protocols ospf interface eth1 transmit-delay '50' +# set protocols ospfv3 interface eth1 dead-interval '39' # "after": [ # " @@ -244,14 +245,14 @@ EXAMPLES = """ # ], # "changed": true, # "commands": [ -# "set interfaces ethernet eth1 ip ospf transmit-delay 50", -# "set interfaces ethernet eth1 ip ospf priority 26", -# "set interfaces ethernet eth1 ip ospf network point-to-point", -# "set interfaces ethernet eth1 ipv6 ospfv3 dead-interval 39", -# "set interfaces bonding bond2 ip ospf transmit-delay 45", -# "set interfaces bonding bond2 ip ospf bandwidth 70", -# "set interfaces bonding bond2 ip ospf authentication md5 key-id 10 md5-key 1111111111232345", -# "set interfaces bonding bond2 ipv6 ospfv3 passive" +# "set protocols ospf interface eth1 transmit-delay 50", +# "set protocols ospf interface eth1 priority 26", +# "set protocols ospf interface eth1 network point-to-point", +# "set protocols ospfv3 interface eth1 dead-interval 39", +# "set protocols ospf interface bond2 transmit-delay 45", +# "set protocols ospf interface bond2 bandwidth 70", +# "set protocols ospf interface bond2 authentication md5 key-id 10 md5-key 1111111111232345", +# "set protocols ospfv3 interface bond2 passive" # ], # Using replaced: @@ -260,14 +261,14 @@ EXAMPLES = """ # ------------ # vyos@vyos:~$ show configuration commands | match "ospf" -# set interfaces bonding bond2 ip ospf authentication md5 key-id 10 md5-key '1111111111232345' -# set interfaces bonding bond2 ip ospf bandwidth '70' -# set interfaces bonding bond2 ip ospf transmit-delay '45' -# set interfaces bonding bond2 ipv6 ospfv3 'passive' -# set interfaces ethernet eth1 ip ospf network 'point-to-point' -# set interfaces ethernet eth1 ip ospf priority '26' -# set interfaces ethernet eth1 ip ospf transmit-delay '50' -# set interfaces ethernet eth1 ipv6 ospfv3 dead-interval '39' +# set protocols ospf interface bond2 authentication md5 key-id 10 md5-key '1111111111232345' +# set protocols ospf interface bond2 bandwidth '70' +# set protocols ospf interface bond2 transmit-delay '45' +# set protocols ospfv3 interface bond2 'passive' +# set protocols ospf interface eth1 network 'point-to-point' +# set protocols ospf interface eth1 priority '26' +# set protocols ospf interface eth1 transmit-delay '50' +# set protocols ospfv3 interface eth1 dead-interval '39' - name: Replace provided configuration with device configuration vyos.vyos.vyos_ospf_interfaces: @@ -290,10 +291,10 @@ EXAMPLES = """ # ----------- # vyos@vyos:~$ show configuration commands | match "ospf" -# set interfaces bonding bond2 ip ospf transmit-delay '45' -# set interfaces bonding bond2 ipv6 ospfv3 'passive' -# set interfaces ethernet eth1 ip ospf cost '100' -# set interfaces ethernet eth1 ipv6 ospfv3 ifmtu '33' +# set protocols ospf interface bond2 transmit-delay '45' +# set protocols ospfv3 interface bond2 'passive' +# set protocols ospf interface eth1 cost '100' +# set protocols ospfv3 interface eth1 ifmtu '33' # vyos@vyos:~$ # Module Execution @@ -383,14 +384,14 @@ EXAMPLES = """ # ], # "changed": true, # "commands": [ -# "set interfaces ethernet eth1 ip ospf cost 100", -# "set interfaces ethernet eth1 ipv6 ospfv3 ifmtu 33", -# "delete interfaces ethernet eth1 ip ospf network point-to-point", -# "delete interfaces ethernet eth1 ip ospf priority 26", -# "delete interfaces ethernet eth1 ip ospf transmit-delay 50", -# "delete interfaces ethernet eth1 ipv6 ospfv3 dead-interval 39", -# "delete interfaces bonding bond2 ip ospf authentication", -# "delete interfaces bonding bond2 ip ospf bandwidth 70" +# "set protocols ospf interface eth1 cost 100", +# "set protocols ospfv3 interface eth1 ifmtu 33", +# "delete protocols ospf interface eth1 network point-to-point", +# "delete protocols ospf interface eth1 priority 26", +# "delete protocols ospf interface eth1 transmit-delay 50", +# "delete protocols ospfv3 interface eth1 dead-interval 39", +# "delete protocols ospf interface bond2 authentication", +# "delete protocols ospf interface bond2 bandwidth 70" # ], # @@ -401,16 +402,16 @@ EXAMPLES = """ # ------------ # vyos@vyos:~$ show configuration commands | match "ospf" -# set interfaces bonding bond2 ip ospf authentication md5 key-id 10 md5-key '1111111111232345' -# set interfaces bonding bond2 ip ospf bandwidth '70' -# set interfaces bonding bond2 ip ospf transmit-delay '45' -# set interfaces bonding bond2 ipv6 ospfv3 'passive' -# set interfaces ethernet eth1 ip ospf cost '100' -# set interfaces ethernet eth1 ip ospf network 'point-to-point' -# set interfaces ethernet eth1 ip ospf priority '26' -# set interfaces ethernet eth1 ip ospf transmit-delay '50' -# set interfaces ethernet eth1 ipv6 ospfv3 dead-interval '39' -# set interfaces ethernet eth1 ipv6 ospfv3 ifmtu '33' +# set protocols ospf interface bond2 authentication md5 key-id 10 md5-key '1111111111232345' +# set protocols ospf interface bond2 bandwidth '70' +# set protocols ospf interface bond2 transmit-delay '45' +# set protocols ospfv3 interface bond2 'passive' +# set protocols ospf interface eth1 cost '100' +# set protocols ospf interface eth1 network 'point-to-point' +# set protocols ospf interface eth1 priority '26' +# set protocols ospf interface eth1 transmit-delay '50' +# set protocols ospfv3 interface eth1 dead-interval '39' +# set protocols ospfv3 interface eth1 ifmtu '33' # vyos@vyos:~$ - name: Override device configuration with provided configuration @@ -429,9 +430,9 @@ EXAMPLES = """ # ----------- # 200~vyos@vyos:~$ show configuration commands | match "ospf" -# set interfaces ethernet eth0 ip ospf cost '100' -# set interfaces ethernet eth0 ipv6 ospfv3 ifmtu '33' -# set interfaces ethernet eth0 ipv6 ospfv3 'passive' +# set protocols ospf interface eth0 cost '100' +# set protocols ospfv3 interface eth0 ifmtu '33' +# set protocols ospfv3 interface eth0 'passive' # vyos@vyos:~$ # # @@ -513,13 +514,13 @@ EXAMPLES = """ # ], # "changed": true, # "commands": [ -# "delete interfaces bonding bond2 ip ospf", -# "delete interfaces bonding bond2 ipv6 ospfv3", -# "delete interfaces ethernet eth1 ip ospf", -# "delete interfaces ethernet eth1 ipv6 ospfv3", -# "set interfaces ethernet eth0 ip ospf cost 100", -# "set interfaces ethernet eth0 ipv6 ospfv3 ifmtu 33", -# "set interfaces ethernet eth0 ipv6 ospfv3 passive" +# "delete protocols ospf interface bond2", +# "delete protocols ospfv3 interface bond2", +# "delete protocols ospf interface eth1", +# "delete protocols ospfv3 interface eth1", +# "set protocols ospf interface eth0 cost 100", +# "set protocols ospfv3 interface eth0 ifmtu 33", +# "set protocols ospfv3 interface eth0 passive" # ], # @@ -530,17 +531,17 @@ EXAMPLES = """ # ------------- # vyos@vyos:~$ show configuration commands | match "ospf" -# set interfaces bonding bond2 ip ospf authentication md5 key-id 10 md5-key '1111111111232345' -# set interfaces bonding bond2 ip ospf bandwidth '70' -# set interfaces bonding bond2 ip ospf transmit-delay '45' -# set interfaces bonding bond2 ipv6 ospfv3 'passive' -# set interfaces ethernet eth0 ip ospf cost '100' -# set interfaces ethernet eth0 ipv6 ospfv3 ifmtu '33' -# set interfaces ethernet eth0 ipv6 ospfv3 'passive' -# set interfaces ethernet eth1 ip ospf network 'point-to-point' -# set interfaces ethernet eth1 ip ospf priority '26' -# set interfaces ethernet eth1 ip ospf transmit-delay '50' -# set interfaces ethernet eth1 ipv6 ospfv3 dead-interval '39' +# set protocols ospf interface bond2 authentication md5 key-id 10 md5-key '1111111111232345' +# set protocols ospf interface bond2 bandwidth '70' +# set protocols ospf interface bond2 transmit-delay '45' +# set protocols ospfv3 interface bond2 'passive' +# set protocols ospf interface eth0 cost '100' +# set protocols ospfv3 interface eth0 ifmtu '33' +# set protocols ospfv3 interface eth0 'passive' +# set protocols ospf interface eth1 network 'point-to-point' +# set protocols ospf interface eth1 priority '26' +# set protocols ospf interface eth1 transmit-delay '50' +# set protocols ospfv3 interface eth1 dead-interval '39' # vyos@vyos:~$ - name: Delete device configuration @@ -553,14 +554,14 @@ EXAMPLES = """ # ----------- # vyos@vyos:~$ show configuration commands | match "ospf" -# set interfaces bonding bond2 ip ospf authentication md5 key-id 10 md5-key '1111111111232345' -# set interfaces bonding bond2 ip ospf bandwidth '70' -# set interfaces bonding bond2 ip ospf transmit-delay '45' -# set interfaces bonding bond2 ipv6 ospfv3 'passive' -# set interfaces ethernet eth1 ip ospf network 'point-to-point' -# set interfaces ethernet eth1 ip ospf priority '26' -# set interfaces ethernet eth1 ip ospf transmit-delay '50' -# set interfaces ethernet eth1 ipv6 ospfv3 dead-interval '39' +# set protocols ospf interface bond2 authentication md5 key-id 10 md5-key '1111111111232345' +# set protocols ospf interface bond2 bandwidth '70' +# set protocols ospf interface bond2 transmit-delay '45' +# set protocols ospfv3 interface bond2 'passive' +# set protocols ospf interface eth1 network 'point-to-point' +# set protocols ospf interface eth1 priority '26' +# set protocols ospf interface eth1 transmit-delay '50' +# set protocols ospfv3 interface eth1 dead-interval '39' # vyos@vyos:~$ # # @@ -669,25 +670,25 @@ EXAMPLES = """ # ], # "changed": true, # "commands": [ -# "delete interfaces ethernet eth0 ip ospf", -# "delete interfaces ethernet eth0 ipv6 ospfv3" +# "delete protocols ospf interface eth0", +# "delete protocols ospfv3 interface eth0" # ], # # Using parsed: # parsed.cfg: -# set interfaces bonding bond2 ip ospf authentication md5 key-id 10 md5-key '1111111111232345' -# set interfaces bonding bond2 ip ospf bandwidth '70' -# set interfaces bonding bond2 ip ospf transmit-delay '45' -# set interfaces bonding bond2 ipv6 ospfv3 'passive' -# set interfaces ethernet eth0 ip ospf cost '50' -# set interfaces ethernet eth0 ip ospf priority '26' -# set interfaces ethernet eth0 ipv6 ospfv3 instance-id '33' -# set interfaces ethernet eth0 ipv6 ospfv3 'mtu-ignore' -# set interfaces ethernet eth1 ip ospf network 'point-to-point' -# set interfaces ethernet eth1 ip ospf priority '26' -# set interfaces ethernet eth1 ip ospf transmit-delay '50' -# set interfaces ethernet eth1 ipv6 ospfv3 dead-interval '39' +# set protocols ospf interface bond2 authentication md5 key-id 10 md5-key '1111111111232345' +# set protocols ospf interface bond2 bandwidth '70' +# set protocols ospf interface bond2 transmit-delay '45' +# set protocols ospfv3 interface bond2 'passive' +# set protocols ospf interface eth0 cost '50' +# set protocols ospf interface eth0 priority '26' +# set protocols ospfv3 interface eth0 instance-id '33' +# set protocols ospfv3 interface eth0 'mtu-ignore' +# set protocols ospf interface eth1 network 'point-to-point' +# set protocols ospf interface eth1 priority '26' +# set protocols ospf interface eth1 transmit-delay '50' +# set protocols ospfv3 interface eth1 dead-interval '39' # - name: parse configs @@ -782,14 +783,14 @@ EXAMPLES = """ # ---------------- # "rendered": [ -# "set interfaces ethernet eth1 ip ospf transmit-delay 50", -# "set interfaces ethernet eth1 ip ospf priority 26", -# "set interfaces ethernet eth1 ip ospf network point-to-point", -# "set interfaces ethernet eth1 ipv6 ospfv3 dead-interval 39", -# "set interfaces bonding bond2 ip ospf transmit-delay 45", -# "set interfaces bonding bond2 ip ospf bandwidth 70", -# "set interfaces bonding bond2 ip ospf authentication md5 key-id 10 md5-key 1111111111232345", -# "set interfaces bonding bond2 ipv6 ospfv3 passive" +# "set protocols ospf interface eth1 transmit-delay 50", +# "set protocols ospf interface eth1 priority 26", +# "set protocols ospf interface eth1 network point-to-point", +# "set protocols ospfv3 interface eth1 dead-interval 39", +# "set protocols ospf interface bond2 transmit-delay 45", +# "set protocols ospf interface bond2 bandwidth 70", +# "set protocols ospf interface bond2 authentication md5 key-id 10 md5-key 1111111111232345", +# "set protocols ospfv3 interface bond2 passive" # ] # @@ -799,14 +800,14 @@ EXAMPLES = """ # Native Config: # vyos@vyos:~$ show configuration commands | match "ospf" -# set interfaces bonding bond2 ip ospf authentication md5 key-id 10 md5-key '1111111111232345' -# set interfaces bonding bond2 ip ospf bandwidth '70' -# set interfaces bonding bond2 ip ospf transmit-delay '45' -# set interfaces bonding bond2 ipv6 ospfv3 'passive' -# set interfaces ethernet eth1 ip ospf network 'point-to-point' -# set interfaces ethernet eth1 ip ospf priority '26' -# set interfaces ethernet eth1 ip ospf transmit-delay '50' -# set interfaces ethernet eth1 ipv6 ospfv3 dead-interval '39' +# set protocols ospf interface bond2 authentication md5 key-id 10 md5-key '1111111111232345' +# set protocols ospf interface bond2 bandwidth '70' +# set protocols ospf interface bond2 transmit-delay '45' +# set protocols ospfv3 interface bond2 'passive' +# set protocols ospf interface eth1 network 'point-to-point' +# set protocols ospf interface eth1 priority '26' +# set protocols ospf interface eth1 transmit-delay '50' +# set protocols ospfv3 interface eth1 dead-interval '39' # vyos@vyos:~$ - name: gather configs @@ -884,17 +885,17 @@ commands: returned: when I(state) is C(merged), C(replaced), C(overridden), C(deleted) or C(purged) type: list sample: - - "set interfaces bonding bond2 ip ospf authentication md5 key-id 10 md5-key '1111111111232345'" - - "set interfaces bonding bond2 ip ospf bandwidth '70'" - - "set interfaces bonding bond2 ip ospf transmit-delay '45'" + - "set protocols ospf interface bond2 authentication md5 key-id 10 md5-key '1111111111232345'" + - "set protocols ospf interface bond2 bandwidth '70'" + - "set protocols ospf interface bond2 transmit-delay '45'" rendered: description: The provided configuration in the task rendered in device-native format (offline). returned: when I(state) is C(rendered) type: list sample: - - "set interfaces bonding bond2 ip ospf authentication md5 key-id 10 md5-key '1111111111232345'" - - "set interfaces bonding bond2 ip ospf bandwidth '70'" - - "set interfaces bonding bond2 ip ospf transmit-delay '45'" + - "set protocols ospf interface bond2 authentication md5 key-id 10 md5-key '1111111111232345'" + - "set protocols ospf interface bond2 bandwidth '70'" + - "set protocols ospf interface bond2 transmit-delay '45'" gathered: description: Facts about the network resource gathered from the remote device as structured data. returned: when I(state) is C(gathered) diff --git a/plugins/modules/vyos_ospfv2.py b/plugins/modules/vyos_ospfv2.py index a72b7fd2..000e4d39 100644 --- a/plugins/modules/vyos_ospfv2.py +++ b/plugins/modules/vyos_ospfv2.py @@ -45,7 +45,8 @@ short_description: OSPFv2 resource module description: This resource module configures and manages attributes of OSPFv2 routes on VyOS network devices. notes: -- Tested against VyOS 1.3.8 +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025 +- The provided examples of commands are valid for VyOS 1.4+ - This module works with connection C(ansible.netcommon.network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). author: @@ -456,8 +457,8 @@ EXAMPLES = """ # "set protocols ospf parameters opaque-lsa", # "set protocols ospf parameters abr-type 'cisco'", # "set protocols ospf parameters rfc1583-compatibility", -# "set protocols ospf passive-interface eth1", -# "set protocols ospf passive-interface eth2", +# "set protocols ospf interface 'eth1' passive", +# "set protocols ospf interface 'eth2' passive", # "set protocols ospf max-metric router-lsa on-shutdown 10", # "set protocols ospf max-metric router-lsa administrative", # "set protocols ospf max-metric router-lsa on-startup 10", @@ -601,8 +602,8 @@ EXAMPLES = """ # set protocols ospf parameters 'opaque-lsa' # set protocols ospf parameters 'rfc1583-compatibility' # set protocols ospf parameters router-id '192.0.1.1' -# set protocols ospf passive-interface 'eth1' -# set protocols ospf passive-interface 'eth2' +# set protocols ospf interface 'eth1' passive +# set protocols ospf interface 'eth2' passive # set protocols ospf redistribute bgp metric '10' # set protocols ospf redistribute bgp metric-type '2' @@ -864,8 +865,8 @@ EXAMPLES = """ # set protocols ospf parameters 'opaque-lsa' # set protocols ospf parameters 'rfc1583-compatibility' # set protocols ospf parameters router-id '192.0.1.1' -# set protocols ospf passive-interface 'eth1' -# set protocols ospf passive-interface 'eth2' +# set protocols ospf interface 'eth1' passive +# set protocols ospf interface 'eth2' passive # set protocols ospf redistribute bgp metric '10' # set protocols ospf redistribute bgp metric-type '2' @@ -901,8 +902,8 @@ EXAMPLES = """ # set protocols ospf parameters 'opaque-lsa' # set protocols ospf parameters 'rfc1583-compatibility' # set protocols ospf parameters router-id '192.0.1.1' -# set protocols ospf passive-interface 'eth1' -# set protocols ospf passive-interface 'eth2' +# set protocols ospf interface 'eth1' passive +# set protocols ospf interface 'eth2' passive # set protocols ospf redistribute bgp metric '10' # set protocols ospf redistribute bgp metric-type '2' # @@ -1059,7 +1060,7 @@ EXAMPLES = """ # } # # "commands": [ -# "delete protocols ospf passive-interface eth2", +# "delete protocols ospf interface 'eth2' passive", # "delete protocols ospf area 3", # "delete protocols ospf area 4 range 192.0.3.0/24 cost", # "delete protocols ospf area 4 range 192.0.3.0/24", @@ -1191,7 +1192,7 @@ EXAMPLES = """ # set protocols ospf parameters 'opaque-lsa' # set protocols ospf parameters 'rfc1583-compatibility' # set protocols ospf parameters router-id '192.0.1.1' -# set protocols ospf passive-interface 'eth1' +# set protocols ospf interface 'eth1' passive # set protocols ospf redistribute bgp metric '10' # set protocols ospf redistribute bgp metric-type '2' @@ -1279,8 +1280,8 @@ EXAMPLES = """ # "set protocols ospf parameters opaque-lsa", # "set protocols ospf parameters abr-type 'cisco'", # "set protocols ospf parameters rfc1583-compatibility", -# "set protocols ospf passive-interface eth1", -# "set protocols ospf passive-interface eth2", +# "set protocols ospf interface 'eth1' passive", +# "set protocols ospf interface 'eth2' passive", # "set protocols ospf max-metric router-lsa on-shutdown 10", # "set protocols ospf max-metric router-lsa administrative", # "set protocols ospf max-metric router-lsa on-startup 10", @@ -1335,8 +1336,8 @@ EXAMPLES = """ set protocols ospf parameters 'opaque-lsa' set protocols ospf parameters 'rfc1583-compatibility' set protocols ospf parameters router-id '192.0.1.1' - set protocols ospf passive-interface 'eth1' - set protocols ospf passive-interface 'eth2' + set protocols ospf interface 'eth1' passive + set protocols ospf interface 'eth2' passive set protocols ospf redistribute bgp metric '10' set protocols ospf redistribute bgp metric-type '2' state: parsed @@ -1472,8 +1473,8 @@ EXAMPLES = """ # set protocols ospf parameters 'opaque-lsa' # set protocols ospf parameters 'rfc1583-compatibility' # set protocols ospf parameters router-id '192.0.1.1' -# set protocols ospf passive-interface 'eth1' -# set protocols ospf passive-interface 'eth2' +# set protocols ospf interface 'eth1' passive +# set protocols ospf interface 'eth2' passive # set protocols ospf redistribute bgp metric '10' # set protocols ospf redistribute bgp metric-type '2' # @@ -1608,8 +1609,8 @@ EXAMPLES = """ # set protocols ospf parameters 'opaque-lsa' # set protocols ospf parameters 'rfc1583-compatibility' # set protocols ospf parameters router-id '192.0.1.1' -# set protocols ospf passive-interface 'eth1' -# set protocols ospf passive-interface 'eth2' +# set protocols ospf interface 'eth1' passive +# set protocols ospf interface 'eth2' passive # set protocols ospf redistribute bgp metric '10' # set protocols ospf redistribute bgp metric-type '2' @@ -1645,8 +1646,8 @@ EXAMPLES = """ # set protocols ospf parameters 'opaque-lsa' # set protocols ospf parameters 'rfc1583-compatibility' # set protocols ospf parameters router-id '192.0.1.1' -# set protocols ospf passive-interface 'eth1' -# set protocols ospf passive-interface 'eth2' +# set protocols ospf interface 'eth1' passive +# set protocols ospf interface 'eth2' passive # set protocols ospf redistribute bgp metric '10' # set protocols ospf redistribute bgp metric-type '2' # @@ -1781,7 +1782,7 @@ commands: type: list sample: - "set protocols ospf parameters router-id 192.0.1.1" - - "set protocols ospf passive-interface 'eth1'" + - "set protocols ospf interface 'eth1' passive" """ diff --git a/plugins/modules/vyos_ospfv3.py b/plugins/modules/vyos_ospfv3.py index dbe9a857..fcb9d288 100644 --- a/plugins/modules/vyos_ospfv3.py +++ b/plugins/modules/vyos_ospfv3.py @@ -46,7 +46,7 @@ description: This resource module configures and manages attributes of OSPFv3 ro author: - Rohit Thakur (@rohitthakur2590) notes: -- Tested against VyOS 1.3.8 +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025 - This module works with connection C(ansible.netcommon.network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). options: diff --git a/plugins/modules/vyos_ping.py b/plugins/modules/vyos_ping.py index 98619399..58ca3459 100644 --- a/plugins/modules/vyos_ping.py +++ b/plugins/modules/vyos_ping.py @@ -30,7 +30,7 @@ module: vyos_ping short_description: Tests reachability using ping from VyOS network devices description: - Tests reachability using ping from a VyOS device to a remote destination. -- Tested against VyOS 1.1.8 (helium) +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025 - For a general purpose network module, see the M(ansible.netcommon.net_ping) module. - For Windows targets, use the M(ansible.windows.win_ping) module instead. - For targets running Python, use the M(ansible.builtin.ping) module instead. @@ -73,7 +73,7 @@ options: - present default: present notes: -- Tested against VyOS 1.1.8 (helium). +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025. - For a general purpose network module, see the M(ansible.netcommon.net_ping) module. - For Windows targets, use the M(ansible.windows.win_ping) module instead. - For targets running Python, use the M(ansible.builtin.ping) module instead. diff --git a/plugins/modules/vyos_prefix_lists.py b/plugins/modules/vyos_prefix_lists.py index 71d52b32..f613bf38 100644 --- a/plugins/modules/vyos_prefix_lists.py +++ b/plugins/modules/vyos_prefix_lists.py @@ -21,7 +21,7 @@ description: version_added: 2.4.0 author: Priyam Sahoo (@priyamsahoo) notes: - - Tested against VyOS 1.1.8 (helium) + - Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025 - This module works with connection C(network_cli) options: config: diff --git a/plugins/modules/vyos_route_maps.py b/plugins/modules/vyos_route_maps.py index 67d327a6..dfd22af9 100644 --- a/plugins/modules/vyos_route_maps.py +++ b/plugins/modules/vyos_route_maps.py @@ -21,7 +21,7 @@ description: - This module manages route map configurations on devices running VYOS. author: Ashwini Mhatre (@amhatre) notes: -- Tested against vyos 1.3.8 +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025 - This module works with connection C(network_cli). options: config: @@ -103,6 +103,12 @@ options: extcommunity_soo: type: str description: Set Site of Origin value. ASN:nn_or_IP_address:nn VPN extended community + extcommunity_bandwidth: + type: str + description: Set Bandwidth of Origin value. 1-25600|cumulative|num-multipaths VPN extended community + extcommunity_bandwidth_non_transitive: + type: bool + description: Set the bandwidth extended community encoded as non-transitive True/False VPN extended community ip_next_hop: type: str description: IP address. @@ -146,6 +152,9 @@ options: weight: type: str description: Border Gateway Protocol (BGP) weight attribute. Example <0-4294967295> + table: + type: str + description: Set prefixes to table. Example <1-200> match: description: Route parameters to match. type: dict @@ -226,6 +235,10 @@ options: type: str description: RPKI validation value. choices: [ "notfound", "invalid", "valid" ] + protocol: + type: str + description: Source protocol to match. + choices: [ "babel","bgp","connected","isis","kernel","ospf","ospfv3","rip","ripng","static","table","vnc" ] on_match: type: dict description: Exit policy on matches. diff --git a/plugins/modules/vyos_snmp_server.py b/plugins/modules/vyos_snmp_server.py index f574919a..2d3ae88a 100644 --- a/plugins/modules/vyos_snmp_server.py +++ b/plugins/modules/vyos_snmp_server.py @@ -20,7 +20,7 @@ short_description: Manages snmp_server resource module description: This module manages the snmp server attributes of Vyos network devices author: Gomathi Selvi Srinivasan (@GomathiselviS) notes: - - Tested against vyos 1.3.8, 1.4.1 + - Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025, 1.4.1 - This module works with connection C(network_cli). - The Configuration defaults of the Vyos network devices are supposed to hinder idempotent behavior of plays diff --git a/plugins/modules/vyos_static_routes.py b/plugins/modules/vyos_static_routes.py index 0629a8bd..436fd36d 100644 --- a/plugins/modules/vyos_static_routes.py +++ b/plugins/modules/vyos_static_routes.py @@ -44,7 +44,7 @@ version_added: '1.0.0' short_description: Static routes resource module description: This module manages attributes of static routes on VyOS network devices. notes: -- Tested against VyOS 1.3.8. +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025. - This module works with connection C(ansible.netcommon.network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). author: diff --git a/plugins/modules/vyos_system.py b/plugins/modules/vyos_system.py index 96a0e9bc..4aa0e03d 100644 --- a/plugins/modules/vyos_system.py +++ b/plugins/modules/vyos_system.py @@ -16,6 +16,7 @@ # You should have received a copy of the GNU General Public License # along with Ansible. If not, see <http://www.gnu.org/licenses/>. # + from __future__ import absolute_import, division, print_function @@ -33,7 +34,7 @@ version_added: 1.0.0 extends_documentation_fragment: - vyos.vyos.vyos notes: -- Tested against VyOS 1.1.8 (helium). +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025. - This module works with connection C(ansible.netcommon.network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). options: host_name: @@ -94,21 +95,27 @@ EXAMPLES = """ - sub1.example.com - sub2.example.com """ +from re import M, findall from ansible.module_utils.basic import AnsibleModule +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_config, + get_os_version, load_config, ) -def spec_key_to_device_key(key): +def spec_key_to_device_key(key, module): device_key = key.replace("_", "-") - # domain-search is longer than just it's key + # domain-search differs in 1.3- and 1.4+ if device_key == "domain-search": - device_key += " domain" + if LooseVersion(get_os_version(module)) <= LooseVersion("1.3"): + device_key += " domain" return device_key @@ -119,19 +126,20 @@ def config_to_dict(module): config = {"domain_search": [], "name_server": []} for line in data.split("\n"): - if line.startswith("set system host-name"): - config["host_name"] = line[22:-1] - elif line.startswith("set system domain-name"): - config["domain_name"] = line[24:-1] - elif line.startswith("set system domain-search domain"): - config["domain_search"].append(line[33:-1]) - elif line.startswith("set system name-server"): - config["name_server"].append(line[24:-1]) - + config_line = findall(r"^set system\s+(\S+)(?:\s+domain)?\s+'([^']+)'", line, M) + if config_line: + if config_line[0][0] == "host-name": + config["host_name"] = config_line[0][1] + elif config_line[0][0] == "domain-name": + config["domain_name"] = config_line[0][1] + elif config_line[0][0] == "domain-search": + config["domain_search"].append(config_line[0][1]) + elif config_line[0][0] == "name-server": + config["name_server"].append(config_line[0][1]) return config -def spec_to_commands(want, have): +def spec_to_commands(want, have, module): commands = [] state = want.pop("state") @@ -140,7 +148,7 @@ def spec_to_commands(want, have): if state == "absent" and all(v is None for v in want.values()): # Clear everything for key in have: - commands.append("delete system %s" % spec_key_to_device_key(key)) + commands.append("delete system %s" % spec_key_to_device_key(key, module)) for key in want: if want[key] is None: @@ -148,7 +156,7 @@ def spec_to_commands(want, have): current = have.get(key) proposed = want[key] - device_key = spec_key_to_device_key(key) + device_key = spec_key_to_device_key(key, module) # These keys are lists which may need to be reconciled with the device if key in ["domain_search", "name_server"]: @@ -201,7 +209,7 @@ def main(): want = map_param_to_obj(module) have = config_to_dict(module) - commands = spec_to_commands(want, have) + commands = spec_to_commands(want, have, module) result["commands"] = commands if commands: diff --git a/plugins/modules/vyos_user.py b/plugins/modules/vyos_user.py index 5aebf943..0c79ce30 100644 --- a/plugins/modules/vyos_user.py +++ b/plugins/modules/vyos_user.py @@ -37,7 +37,7 @@ version_added: 1.0.0 extends_documentation_fragment: - vyos.vyos.vyos notes: -- Tested against VyOS 1.1.8 (helium). +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025. - This module works with connection C(ansible.netcommon.network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). options: aggregate: @@ -55,7 +55,7 @@ options: description: - The username to be configured on the VyOS device. This argument accepts a string value and is mutually exclusive with the C(aggregate) argument. - required: True + required: true type: str full_name: description: @@ -205,12 +205,12 @@ commands: """ import re +import shlex from copy import deepcopy from functools import partial from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.six import iteritems from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ( remove_default_spec, ) @@ -277,7 +277,8 @@ def spec_to_commands(updates, module): add( commands, want, - "authentication plaintext-password %s" % want["configured_password"], + "authentication plaintext-password %s" + % shlex.quote(want["configured_password"]), ) return commands @@ -364,6 +365,8 @@ def get_param_value(key, item, module): # if key doesn't exist in the item, get it from module.params if not item.get(key): value = module.params[key] + else: + value = item.get(key) # validate the param value (if validator func exists) validator = globals().get("validate_%s" % key) @@ -424,7 +427,7 @@ def update_objects(want, have): if item is None: updates.append((entry, {})) elif item: - for key, value in iteritems(entry): + for key, value in entry.items(): if value and value != item[key]: updates.append((entry, item)) return updates diff --git a/plugins/modules/vyos_vlan.py b/plugins/modules/vyos_vlan.py index 49cc1258..9d23cc7c 100644 --- a/plugins/modules/vyos_vlan.py +++ b/plugins/modules/vyos_vlan.py @@ -18,7 +18,7 @@ description: - This module provides declarative management of VLANs on VyOS network devices. version_added: 1.0.0 notes: -- Tested against VyOS 1.1.8 (helium). +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025. - This module works with connection C(ansible.netcommon.network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). options: name: @@ -279,15 +279,11 @@ def map_config_to_obj(module): obj = {} eth = splitted_line[0].strip("'") - if eth.startswith("eth"): + if eth.startswith("eth") and "." in eth: obj["interfaces"] = [] - if "." in eth: - interface = eth.split(".")[0] - obj["interfaces"].append(interface) - obj["vlan_id"] = eth.split(".")[-1] - else: - obj["interfaces"].append(eth) - obj["vlan_id"] = None + interface = eth.split(".")[0] + obj["interfaces"].append(interface) + obj["vlan_id"] = eth.split(".")[-1] if splitted_line[1].strip("'") != "-": obj["address"] = splitted_line[1].strip("'") diff --git a/plugins/modules/vyos_vrf.py b/plugins/modules/vyos_vrf.py new file mode 100644 index 00000000..d0d4fe88 --- /dev/null +++ b/plugins/modules/vyos_vrf.py @@ -0,0 +1,1545 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright 2024 Red Hat +# GNU General Public License v3.0+ +# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +""" +The module file for vyos_vrf +""" + +from __future__ import absolute_import, division, print_function + + +__metaclass__ = type + +DOCUMENTATION = """ +module: vyos_vrf +version_added: 1.0.0 +short_description: VRF resource module +description: +- This module manages vrf configuration on devices running Vyos +author: +- Evgeny Molotkov (@omnom62) +notes: +- Tested against vyos 1.4.2 and 1.5-stream-2025-Q1 +- This module works with connection C(network_cli). +options: + config: + description: List of vrf configuration. + type: dict + suboptions: + bind_to_all: + default: false + description: Enable binding services to all VRFs + type: bool + instances: + description: Virtual Routing and Forwarding instance + type: list + elements: dict + suboptions: + name: + description: VRF instance name + required: true + type: str + description: + description: Description + type: str + disable: + default: false + description: Administratively disable interface + type: bool + aliases: ['disabled'] + table_id: + description: Routing table associated with this instance + type: int + vni: + description: Virtual Network Identifier + type: int + address_family: + type: list + elements: dict + description: Address family configuration + suboptions: + afi: + description: Address family identifier + type: str + choices: ['ipv4', 'ipv6'] + disable_forwarding: + default: false + description: Disable forwarding for this address family + type: bool + nht_no_resolve_via_default: + default: false + description: Disable next-hop resolution via default route + type: bool + route_maps: + description: List of route maps for this address family + type: list + elements: dict + suboptions: + rm_name: + description: Route map name + type: str + required: true + protocol: + description: Protocol to which the route map applies + type: str + choices: + - any + - babel + - bgp + - eigrp + - isis + - ospf + - rip + - static + protocols: + # type: list # sanity + # elements: dict + type: dict + description: Protocol configuration + suboptions: + bgp: + type: dict + description: BGP configuration + suboptions: + as_number: + description: + - AS number. + type: int + #maximum_paths: --> moved to address-family before 1.3 + neighbor: + description: BGP neighbor + type: list + elements: dict + suboptions: + address: + description: + - BGP neighbor address (v4/v6). + type: str + advertisement_interval: + description: + - Minimum interval for sending routing updates. + type: int + capability: + description: + - Advertise capabilities to this neighbor. + type: dict + suboptions: + dynamic: + description: + - Advertise dynamic capability to this neighbor. + type: bool + extended_nexthop: + description: + - Advertise extended nexthop capability to this neighbor. + type: bool + default_originate: + description: + - Send default route to this neighbor + type: str + description: + description: + - Description of the neighbor + type: str + disable_capability_negotiation: + description: + - Disbale capability negotiation with the neighbor + type: bool + disable_connected_check: + description: + - Disable check to see if EBGP peer's address is a connected route. + type: bool + disable_send_community: + description: + - Disable sending community attributes to this neighbor. + type: str + choices: ['extended', 'standard'] + ebgp_multihop: + description: + - Allow this EBGP neighbor to not be on a directly connected network. Specify + the number hops. + type: int + local_as: + description: local as number not to be prepended to updates from EBGP peers + type: int + override_capability: + description: Ignore capability negotiation with specified neighbor. + type: bool + passive: + description: Do not initiate a session with this neighbor + type: bool + password: + description: BGP MD5 password + type: str + peer_group_name: + description: IPv4 peer group for this peer + type: str + peer_group: + description: True if all the configs under this neighbor key is for peer group template. + type: bool + port: + description: Neighbor's BGP port + type: int + remote_as: + description: Neighbor BGP AS number + type: int + shutdown: + description: Administratively shut down neighbor + type: bool + solo: # <-- added in 1.3 + description: Do not send back prefixes learned from the neighbor + type: bool + strict_capability_match: + description: Enable strict capability negotiation + type: bool + timers: + description: Neighbor timers + type: dict + suboptions: + connect: + description: BGP connect timer for this neighbor. + type: int + holdtime: + description: BGP hold timer for this neighbor + type: int + keepalive: + description: BGP keepalive interval for this neighbor + type: int + ttl_security: + description: Number of the maximum number of hops to the BGP peer + type: int + update_source: + description: Source IP of routing updates + type: str + timers: + description: BGP protocol timers + type: dict + suboptions: + keepalive: + description: Keepalive interval + type: int + holdtime: + description: Hold time interval + type: int + bgp_params: + description: BGP parameters + type: dict + suboptions: + always_compare_med: + description: Always compare MEDs from different neighbors + type: bool + bestpath: + description: Default bestpath selection mechanism + type: dict + suboptions: + as_path: + description: AS-path attribute comparison parameters + type: str + choices: ['confed', 'ignore'] + compare_routerid: + description: Compare the router-id for identical EBGP paths + type: bool + med: + description: MED attribute comparison parameters + type: str + choices: ['confed', 'missing-as-worst'] + cluster_id: + description: Route-reflector cluster-id + type: str + confederation: + description: AS confederation parameters + type: list + elements: dict + suboptions: + identifier: + description: Confederation AS identifier + type: int + peers: + description: Peer ASs in the BGP confederation + type: int + dampening: + description: Enable route-flap dampening + type: dict + suboptions: + half_life: + description: Half-life penalty in seconds + type: int + max_suppress_time: + description: Maximum duration to suppress a stable route + type: int + re_use: + description: Time to start reusing a route + type: int + start_suppress_time: + description: When to start suppressing a route + type: int + default: + description: BGP defaults + type: dict + suboptions: + local_pref: + description: Default local preference + type: int + no_ipv4_unicast: + description: | + Deactivate IPv4 unicast for a peer by default + Deprecated: Unavailable after 1.4 + type: bool + deterministic_med: + description: Compare MEDs between different peers in the same AS + type: bool + disable_network_import_check: + description: Disable IGP route check for network statements + type: bool + distance: + description: Administrative distances for BGP routes + type: list + elements: dict + suboptions: + type: + description: Type of route + type: str + choices: ['external', 'internal', 'local'] + value: + description: distance + type: int + prefix: + description: Administrative distance for a specific BGP prefix + type: int + enforce_first_as: + description: Require first AS in the path to match peer's AS + type: bool + graceful_restart: + description: Maximum time to hold onto restarting peer's stale paths + type: int + log_neighbor_changes: + description: Log neighbor up/down changes and reset reason + type: bool + no_client_to_client_reflection: + description: Disable client to client route reflection + type: bool + no_fast_external_failover: + description: Disable immediate session reset if peer's connected link goes down + type: bool + router_id: + description: BGP router-id + type: str + scan_time: + description: BGP route scanner interval + type: int + ospf: + type: dict + description: OSPFv2 configuration + suboptions: + areas: + description: OSPFv2 area. + type: list + elements: dict + suboptions: + area_id: + description: OSPFv2 area identity. + type: str + area_type: + description: Area type. + type: dict + suboptions: + normal: + description: Normal OSPFv2 area. + type: bool + nssa: + description: NSSA OSPFv2 area. + type: dict + suboptions: + set: + description: Enabling NSSA. + type: bool + default_cost: + description: Summary-default cost of NSSA area. + type: int + no_summary: + description: Do not inject inter-area routes into stub. + type: bool + translate: + description: NSSA-ABR. + type: str + choices: [always, candidate, never] + stub: + description: Stub OSPFv2 area. + type: dict + suboptions: + set: + description: Enabling stub. + type: bool + default_cost: + description: Summary-default cost of stub area. + type: int + no_summary: + description: Do not inject inter-area routes into stub. + type: bool + authentication: + description: OSPFv2 area authentication type. + type: str + choices: [plaintext-password, md5] + network: + description: OSPFv2 network. + type: list + elements: dict + suboptions: + address: + required: true + description: OSPFv2 IPv4 network address. + type: str + range: + description: Summarize routes matching prefix (border routers only). + type: list + elements: dict + suboptions: + address: + description: border router IPv4 address. + type: str + cost: + description: Metric for this range. + type: int + not_advertise: + description: Don't advertise this range. + type: bool + substitute: + description: Announce area range (IPv4 address) as another prefix. + type: str + shortcut: + description: Area's shortcut mode. + type: str + choices: [default, disable, enable] + virtual_link: + description: Virtual link address. + type: list + elements: dict + suboptions: + address: + description: virtual link address. + type: str + authentication: + description: OSPFv2 area authentication type. + type: dict + suboptions: + md5: + description: MD5 key id based authentication. + type: list + elements: dict + suboptions: + key_id: + description: MD5 key id. + type: int + md5_key: + description: MD5 key. + type: str + plaintext_password: + description: Plain text password. + type: str + dead_interval: + description: Interval after which a neighbor is declared dead. + type: int + hello_interval: + description: Interval between hello packets. + type: int + retransmit_interval: + description: Interval between retransmitting lost link state advertisements. + type: int + transmit_delay: + description: Link state transmit delay. + type: int + log_adjacency_changes: + description: Log changes in adjacency state. + type: str + choices: [detail] + max_metric: + description: OSPFv2 maximum/infinite-distance metric. + type: dict + suboptions: + router_lsa: + description: Advertise own Router-LSA with infinite distance (stub router). + type: dict + suboptions: + administrative: + description: Administratively apply, for an indefinite period. + type: bool + on_shutdown: + description: Time to advertise self as stub-router. + type: int + on_startup: + description: Time to advertise self as stub-router + type: int + auto_cost: + description: Calculate OSPFv2 interface cost according to bandwidth. + type: dict + suboptions: + reference_bandwidth: + description: Reference bandwidth cost in Mbits/sec. + type: int + default_information: + description: Control distribution of default information. + type: dict + suboptions: + originate: + description: Distribute a default route. + type: dict + suboptions: + always: + description: Always advertise default route. + type: bool + metric: + description: OSPFv2 default metric. + type: int + metric_type: + description: OSPFv2 Metric types for default routes. + type: int + route_map: + description: Route map references. + type: str + default_metric: + description: Metric of redistributed routes + type: int + distance: + description: Administrative distance. + type: dict + suboptions: + global: + description: Global OSPFv2 administrative distance. + type: int + ospf: + description: OSPFv2 administrative distance. + type: dict + suboptions: + external: + description: Distance for external routes. + type: int + inter_area: + description: Distance for inter-area routes. + type: int + intra_area: + description: Distance for intra-area routes. + type: int + mpls_te: + description: MultiProtocol Label Switching-Traffic Engineering (MPLS-TE) parameters. + type: dict + suboptions: + enabled: + description: Enable MPLS-TE functionality. + type: bool + router_address: + description: Stable IP address of the advertising router. + type: str + neighbor: + description: Neighbor IP address. + type: list + elements: dict + suboptions: + neighbor_id: + description: Identity (number/IP address) of neighbor. + type: str + poll_interval: + description: Seconds between dead neighbor polling interval. + type: int + priority: + description: Neighbor priority. + type: int + parameters: + description: OSPFv2 specific parameters. + type: dict + suboptions: + abr_type: + description: OSPFv2 ABR Type. + type: str + choices: [cisco, ibm, shortcut, standard] + opaque_lsa: + description: Enable the Opaque-LSA capability (rfc2370). + type: bool + rfc1583_compatibility: + description: Enable rfc1583 criteria for handling AS external routes. + type: bool + router_id: + description: Override the default router identifier. + type: str + passive_interface: + description: Suppress routing updates on an interface. + type: list + elements: str + passive_interface_exclude: + description: Interface to exclude when using passive-interface default. + type: list + elements: str + redistribute: + description: Redistribute information from another routing protocol. + type: list + elements: dict + suboptions: + route_type: + description: Route type to redistribute. + type: str + choices: [bgp, connected, kernel, rip, static] + metric: + description: Metric for redistribution routes. + type: int + metric_type: + description: OSPFv2 Metric types. + type: int + route_map: + description: Route map references. + type: str + route_map: + description: Filter routes installed in local route map. + type: list + elements: str + timers: + description: Adjust routing timers. + type: dict + suboptions: + refresh: + description: Adjust refresh parameters. + type: dict + suboptions: + timers: + description: refresh timer. + type: int + throttle: + description: Throttling adaptive timers. + type: dict + suboptions: + spf: + description: OSPFv2 SPF timers. + type: dict + suboptions: + delay: + description: Delay (msec) from first change received till SPF + calculation. + type: int + initial_holdtime: + description: Initial hold time(msec) between consecutive SPF calculations. + type: int + max_holdtime: + description: maximum hold time (sec). + type: int + ospfv3: + type: dict + description: OSPFv3 configuration + suboptions: + areas: + description: OSPFv3 area. + type: list + elements: dict + suboptions: + area_id: + description: OSPFv3 Area name/identity. + type: str + export_list: + description: Name of export-list. + type: str + import_list: + description: Name of import-list. + type: str + interface: + description: Enable OSPVv3 on an interface for this area. + aliases: ['interfaces'] + type: list + elements: dict + suboptions: + name: + description: Interface name. + type: str + range: + description: Summarize routes matching prefix (border routers only). + type: list + elements: dict + suboptions: + address: + description: border router IPv4 address. + type: str + advertise: + description: Advertise this range. + type: bool + not_advertise: + description: Don't advertise this range. + type: bool + parameters: + description: OSPFv3 specific parameters. + type: dict + suboptions: + router_id: + description: Override the default router identifier. + type: str + redistribute: + description: Redistribute information from another routing protocol. + type: list + elements: dict + suboptions: + route_type: + description: Route type to redistribute. + type: str + choices: + - bgp + - connected + - kernel + - ripng + - static + route_map: + description: Route map references. + type: str + static: + type: list + description: Static routes configuration + elements: dict + suboptions: + address_families: + description: A dictionary specifying the address family to which the static + route(s) belong. + type: list + elements: dict + suboptions: + afi: + description: + - Specifies the type of route. + type: str + choices: + - ipv4 + - ipv6 + required: true + routes: + description: A dictionary that specify the static route configurations. + type: list + elements: dict + suboptions: + dest: + description: + - An IPv4/v6 address in CIDR notation that specifies the destination + network for the static route. + type: str + required: true + blackhole_config: + description: + - Configured to silently discard packets. + type: dict + suboptions: + type: + description: + - This is to configure only blackhole. + type: str + distance: + description: + - Distance for the route. + type: int + next_hops: + description: + - Next hops to the specified destination. + type: list + elements: dict + suboptions: + forward_router_address: + description: + - The IP address of the next hop that can be used to reach the + destination network. + type: str + enabled: + description: + - Disable IPv4/v6 next-hop static route. + type: bool + admin_distance: + description: + - Distance value for the route. + type: int + interface: + description: + - Name of the outgoing interface. + type: str + running_config: + description: + - This option is used only with state I(parsed). + - The value of this option should be the output received from the VYOS device by + executing the command B(show configuration commands | match "set vrf"). + - The states I(replaced) and I(overridden) have identical + behaviour for this module. + - The state I(parsed) reads the configuration from C(show configuration commands | match "set vrf") option and + transforms it into Ansible structured data as per the resource module's argspec + and the value is then returned in the I(parsed) key within the result. + type: str + state: + description: + - The state the configuration should be left in. + type: str + choices: + - deleted + - merged + - overridden + - replaced + - gathered + - rendered + - parsed + default: merged +""" + +EXAMPLES = """ +# # ------------------- +# # 1. Using merged +# # ------------------- + +# # Before state: +# # ------------- +# vyos@vyos:~$ show configuration commands | match 'set vrf' +# set vrf name vrf-blue description 'blue-vrf' +# set vrf name vrf-blue disable +# set vrf name vrf-blue table '100' +# set vrf name vrf-blue vni '1000' +# vyos@vyos:~$ + +# # Task +# # ------------- + # - name: Merge provided configuration with device configuration + # vyos.vyos.vyos_vrf: + # config: + # instances: + # - name: "vrf-green" + # description: "green-vrf" + # table_id: 110 + # vni: 1010 + +# Task output: +# ------------- + # "after": { + # "bind_to_all": false, + # "instances": [ + # { + # "description": "blue-vrf", + # "disable": true, + # "name": "vrf-blue", + # "table_id": 100, + # "vni": 1000 + # }, + # { + # "description": "green-vrf", + # "disable": false, + # "name": "vrf-green", + # "table_id": 110, + # "vni": 1010 + # } + # ] + # }, + # "before": { + # "bind_to_all": false, + # "instances": [ + # { + # "description": "blue-vrf", + # "disable": true, + # "name": "vrf-blue", + # "table_id": 100, + # "vni": 1000 + # } + # ] + # }, + # "changed": true, + # "commands": [ + # "set vrf name vrf-green table 110", + # "set vrf name vrf-green vni 1010", + # "set vrf name vrf-green description green-vrf" + # ] + +# After state: +# # ------------- +# vyos@vyos:~$ show configuration commands | match 'set vrf' +# set vrf name vrf-blue description 'blue-vrf' +# set vrf name vrf-blue disable +# set vrf name vrf-blue table '100' +# set vrf name vrf-blue vni '1000' +# set vrf name vrf-green description 'green-vrf' +# set vrf name vrf-green table '110' +# set vrf name vrf-green vni '1010' +# vyos@vyos:~$ + +# # ------------------- +# # 2. Using replaced +# # ------------------- + +# # Before state: +# # ------------- + # vyos@vyos:~$ show configuration commands | match 'set vrf' + # set vrf bind-to-all + # set vrf name vrf-blue description 'blue-vrf' + # set vrf name vrf-blue table '100' + # set vrf name vrf-blue vni '1000' + # set vrf name vrf-red description 'red-vrf' + # set vrf name vrf-red disable + # set vrf name vrf-red ip disable-forwarding + # set vrf name vrf-red ip protocol rip route-map 'rm1' + # set vrf name vrf-red table '101' + # set vrf name vrf-red vni '1001' + # vyos@vyos:~$ + + +# # Task +# # ------------- + # - name: Merge provided configuration with device configuration + # vyos.vyos.vyos_vrf: + # config: + # bind_to_all: true + # instances: + # - name: "vrf-blue" + # description: "blue-vrf" + # disable: false + # table_id: 100 + # vni: 1002 + # - name: "vrf-red" + # description: "red-vrf" + # disable: false + # table_id: 101 + # vni: 1001 + # address_family: + # - afi: "ipv4" + # disable_forwarding: false + # route_maps: + # - rm_name: "rm1" + # protocol: "ospf" + # - afi: "ipv6" + # nht_no_resolve_via_default: true + # state: replaced + +# # Task output: +# # ------------- + # "after": { + # "bind_to_all": true, + # "instances": [ + # { + # "description": "blue-vrf", + # "disable": false, + # "name": "vrf-blue", + # "table_id": 100, + # "vni": 1002 + # }, + # { + # "address_family": [ + # { + # "afi": "ipv4", + # "disable_forwarding": false, + # "nht_no_resolve_via_default": false, + # "route_maps": [ + # { + # "protocol": "ospf", + # "rm_name": "rm1" + # }, + # { + # "protocol": "rip", + # "rm_name": "rm1" + # } + # ] + # }, + # { + # "afi": "ipv6", + # "disable_forwarding": false, + # "nht_no_resolve_via_default": true + # } + # ], + # "description": "red-vrf", + # "disable": false, + # "name": "vrf-red", + # "table_id": 101, + # "vni": 1001 + # } + # ] + # }, + # "before": { + # "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": "rip", + # "rm_name": "rm1" + # } + # ] + # } + # ], + # "description": "red-vrf", + # "disable": true, + # "name": "vrf-red", + # "table_id": 101, + # "vni": 1001 + # } + # ] + # }, + # "changed": true, + # "commands": [ + # "set vrf name vrf-blue vni 1002", + # "delete vrf name vrf-red disable", + # "set vrf name vrf-red ip protocol ospf route-map rm1", + # "delete vrf name vrf-red ip disable-forwarding", + # "set vrf name vrf-red ipv6 nht no-resolve-via-default" + # ] + +# After state: +# # ------------- + # vyos@vyos:~$ + # set vrf bind-to-all + # set vrf name vrf-blue description 'blue-vrf' + # set vrf name vrf-blue table '100' + # set vrf name vrf-blue vni '1002' + # set vrf name vrf-red description 'red-vrf' + # set vrf name vrf-red ip protocol ospf route-map 'rm1' + # set vrf name vrf-red ip protocol rip route-map 'rm1' + # set vrf name vrf-red ipv6 nht no-resolve-via-default + # set vrf name vrf-red table '101' + # set vrf name vrf-red vni '1001' + # vyos@vyos:~$ + + +# # ------------------- +# # 3. Using overridden +# # ------------------- + +# # Before state: +# # ------------- + # vyos@vyos:~$ show configuration commands | match 'set vrf' + # set vrf bind-to-all + # set vrf name vrf-blue description 'blue-vrf' + # set vrf name vrf-blue table '100' + # set vrf name vrf-blue vni '1000' + # set vrf name vrf-red description 'red-vrf' + # set vrf name vrf-red disable + # set vrf name vrf-red ip disable-forwarding + # set vrf name vrf-red ip protocol rip route-map 'rm1' + # set vrf name vrf-red table '101' + # set vrf name vrf-red vni '1001' + # vyos@vyos:~$ + +# Task +# ------------- + # - name: Overridden provided configuration with device configuration + # vyos.vyos.vyos_vrf: + # config: + # bind_to_all: true + # instances: + # - name: "vrf-blue" + # description: "blue-vrf" + # disable: true + # table_id: 100 + # vni: 1000 + # - name: "vrf-red" + # description: "red-vrf" + # disable: true + # table_id: 101 + # vni: 1001 + # address_family: + # - afi: "ipv4" + # disable_forwarding: false + # route_maps: + # - rm_name: "rm1" + # protocol: "rip" + # - afi: "ipv6" + # nht_no_resolve_via_default: false + # state: overridden + +# # Task output: +# # ------------- + # "after": { + # "bind_to_all": true, + # "instances": [ + # { + # "description": "blue-vrf", + # "disable": true, + # "name": "vrf-blue", + # "table_id": 100, + # "vni": 1000 + # }, + # { + # "address_family": [ + # { + # "afi": "ipv4", + # "disable_forwarding": false, + # "nht_no_resolve_via_default": false, + # "route_maps": [ + # { + # "protocol": "rip", + # "rm_name": "rm1" + # } + # ] + # } + # ], + # "description": "red-vrf", + # "disable": true, + # "name": "vrf-red", + # "table_id": 101, + # "vni": 1001 + # } + # ] + # }, + # "before": { + # "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": "rip", + # "rm_name": "rm1" + # } + # ] + # } + # ], + # "description": "red-vrf", + # "disable": true, + # "name": "vrf-red", + # "table_id": 101, + # "vni": 1001 + # } + # ] + # }, + # "changed": true, + # "commands": [ + # "delete vrf name vrf-blue", + # "commit", + # "delete vrf name vrf-red", + # "commit", + # "set vrf name vrf-blue table 100", + # "set vrf name vrf-blue vni 1000", + # "set vrf name vrf-blue description blue-vrf", + # "set vrf name vrf-blue disable", + # "set vrf name vrf-red table 101", + # "set vrf name vrf-red vni 1001", + # "set vrf name vrf-red description red-vrf", + # "set vrf name vrf-red disable", + # "set vrf name vrf-red ip protocol rip route-map rm1" + # ] + +# After state: +# # ------------- + # vyos@vyos:~$ show configuration commands | match 'set vrf' + # set vrf bind-to-all + # set vrf name vrf-blue description 'blue-vrf' + # set vrf name vrf-blue disable + # set vrf name vrf-blue table '100' + # set vrf name vrf-blue vni '1000' + # set vrf name vrf-red description 'red-vrf' + # set vrf name vrf-red disable + # set vrf name vrf-red ip protocol rip route-map 'rm1' + # set vrf name vrf-red table '101' + # set vrf name vrf-red vni '1001' + # vyos@vyos:~$ + +# 4. Using gathered +# ------------------- + +# # Before state: +# # ------------- + # vyos@vyos:~$ show configuration commands | match 'set vrf' + # set vrf bind-to-all + # set vrf name vrf-blue description 'blue-vrf' + # set vrf name vrf-blue table '100' + # set vrf name vrf-blue vni '1000' + # set vrf name vrf-red description 'red-vrf' + # set vrf name vrf-red disable + # set vrf name vrf-red ip disable-forwarding + # set vrf name vrf-red ip protocol rip route-map 'rm1' + # set vrf name vrf-red table '101' + # set vrf name vrf-red vni '1001' + # vyos@vyos:~$ + +# Task +# ------------- +# - name: Gather provided configuration with device configuration +# vyos.vyos.vyos_vrf: +# config: +# state: gathered + +# # Task output: +# # ------------- + # "gathered": { + # "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": "rip", + # "rm_name": "rm1" + # } + # ] + # } + # ], + # "description": "red-vrf", + # "disable": true, + # "name": "vrf-red", + # "table_id": 101, + # "vni": 1001 + # } + # ] + # } + +# After state: +# # ------------- + # vyos@vyos:~$ show configuration commands | match 'set vrf' + # set vrf bind-to-all + # set vrf name vrf-blue description 'blue-vrf' + # set vrf name vrf-blue table '100' + # set vrf name vrf-blue vni '1000' + # set vrf name vrf-red description 'red-vrf' + # set vrf name vrf-red disable + # set vrf name vrf-red ip disable-forwarding + # set vrf name vrf-red ip protocol rip route-map 'rm1' + # set vrf name vrf-red table '101' + # set vrf name vrf-red vni '1001' + # vyos@vyos:~$ + + +# # ------------------- +# # 5. Using deleted +# # ------------------- + +# # Before state: +# # ------------- + # vyos@vyos:~$ show configuration commands | match 'set vrf' + # set vrf bind-to-all + # set vrf name vrf-blue description 'blue-vrf' + # set vrf name vrf-blue table '100' + # set vrf name vrf-blue vni '1000' + # set vrf name vrf-red description 'red-vrf' + # set vrf name vrf-red disable + # set vrf name vrf-red ip disable-forwarding + # set vrf name vrf-red ip protocol rip route-map 'rm1' + # set vrf name vrf-red table '101' + # set vrf name vrf-red vni '1001' + # vyos@vyos:~$ + +# # Task +# # ------------- +# - name: Replace provided configuration with device configuration +# vyos.vyos.vyos_vrf: +# config: +# bind_to_all: false +# instances: +# - name: "vrf-blue" +# state: deleted + + +# # Task output: +# # ------------- + # "after": { + # "bind_to_all": false, + # "instances": [ + # { + # "address_family": [ + # { + # "afi": "ipv4", + # "disable_forwarding": true, + # "nht_no_resolve_via_default": false, + # "route_maps": [ + # { + # "protocol": "rip", + # "rm_name": "rm1" + # } + # ] + # } + # ], + # "description": "red-vrf", + # "disable": true, + # "name": "vrf-red", + # "table_id": 101, + # "vni": 1001 + # } + # ] + # }, + # "before": { + # "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": "rip", + # "rm_name": "rm1" + # } + # ] + # } + # ], + # "description": "red-vrf", + # "disable": true, + # "name": "vrf-red", + # "table_id": 101, + # "vni": 1001 + # } + # ] + # }, + # "changed": true, + # "commands": [ + # "delete vrf bind-to-all", + # "delete vrf name vrf-blue" + # ] + +# After state: +# # ------------- + # vyos@vyos:~$ show configuration commands | match 'set vrf' + # set vrf name vrf-red description 'red-vrf' + # set vrf name vrf-red disable + # set vrf name vrf-red ip disable-forwarding + # set vrf name vrf-red ip protocol rip route-map 'rm1' + # set vrf name vrf-red table '101' + # set vrf name vrf-red vni '1001' + # vyos@vyos:~$ + +# # ------------------- +# # 6. Using rendered +# # ------------------- + +# # Before state: +# # ------------- + # vyos@vyos:~$ show configuration commands | match 'set vrf' + # set vrf name vrf-red description 'red-vrf' + # set vrf name vrf-red disable + # set vrf name vrf-red ip disable-forwarding + # set vrf name vrf-red ip protocol rip route-map 'rm1' + # set vrf name vrf-red table '101' + # set vrf name vrf-red vni '1001' + # vyos@vyos:~$ + +# Task +# ------------- + # - name: Render provided configuration with device configuration + # vyos.vyos.vyos_vrf: + # config: + # bind_to_all: true + # instances: + # - name: "vrf-green" + # description: "green-vrf" + # disabled: true + # table_id: 105 + # vni: 1000 + # - name: "vrf-amber" + # description: "amber-vrf" + # disable: false + # table_id: 111 + # vni: 1001 + # address_family: + # - afi: "ipv4" + # disable_forwarding: true + # route_maps: + # - rm_name: "rm1" + # protocol: "ospf" + # - afi: "ipv6" + # nht_no_resolve_via_default: false + # state: rendered + +# # Task output: +# # ------------- + # "rendered": [ + # "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 ospf route-map rm1", + # "set vrf name vrf-amber ip disable-forwarding" + # ] + +# # ------------------- +# # 7. Using parsed +# # ------------------- + +# # vrf_parsed.cfg: +# # ------------- +# 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 'blah2' +# 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 ospf route-map 'rm1' +# set vrf name vrf-red ipv6 nht no-resolve-via-default + +# Task: +# ------------- +# - name: Parse provided configuration with device configuration +# vyos.vyos.vyos_vrf: +# running_config: "{{ lookup('file', './vrf_parsed.cfg') }}" +# state: parsed + + +# # Task output: +# # ------------- +# "parsed": { +# "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": "blah2", +# "disable": true, +# "name": "vrf2" +# }, +# { +# "address_family": [ +# { +# "afi": "ipv4", +# "disable_forwarding": false, +# "nht_no_resolve_via_default": false, +# "route_maps": [ +# { +# "protocol": "ospf", +# "rm_name": "rm1" +# } +# ] +# }, +# { +# "afi": "ipv6", +# "disable_forwarding": false, +# "nht_no_resolve_via_default": true +# } +# ], +# "disable": false, +# "name": "vrf-red" +# } +# ] +# } +""" + +RETURN = """ +before: + description: The configuration prior to the module execution. + returned: when I(state) is C(merged), C(replaced), C(overridden), C(deleted) or C(purged) + type: dict + sample: > + This output will always be in the same format as the + module argspec. +after: + description: The resulting configuration after module execution. + returned: when changed + type: dict + sample: > + This output will always be in the same format as the + module argspec. +commands: + description: The set of commands pushed to the remote device. + returned: when I(state) is C(merged), C(replaced), C(overridden), C(deleted) or C(purged) + type: list + sample: + - set system ntp server server1 dynamic + - set system ntp server server1 prefer + - set system ntp server server2 noselect + - set system ntp server server2 preempt + - set system ntp server server_add preempt +rendered: + description: The provided configuration in the task rendered in device-native format (offline). + returned: when I(state) is C(rendered) + type: list + sample: + - set system ntp server server1 dynamic + - set system ntp server server1 prefer + - set system ntp server server2 noselect + - set system ntp server server2 preempt + - set system ntp server server_add preempt +gathered: + description: Facts about the network resource gathered from the remote device as structured data. + returned: when I(state) is C(gathered) + type: list + sample: > + This output will always be in the same format as the + module argspec. +parsed: + description: The device native config provided in I(running_config) option parsed into structured data as per module argspec. + returned: when I(state) is C(parsed) + type: list + sample: > + This output will always be in the same format as the + module argspec. +""" + +from ansible.module_utils.basic import AnsibleModule + +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.vrf.vrf import VrfArgs +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.config.vrf.vrf import Vrf + + +def main(): + """ + Main entry point for module execution + + :returns: the result form module invocation + """ + module = AnsibleModule( + argument_spec=VrfArgs.argument_spec, + mutually_exclusive=[["config", "running_config"]], + required_if=[ + ["state", "merged", ["config"]], + ["state", "replaced", ["config"]], + ["state", "overridden", ["config"]], + ["state", "rendered", ["config"]], + ["state", "parsed", ["running_config"]], + ], + supports_check_mode=True, + ) + + result = Vrf(module).execute_module() + module.exit_json(**result) + + +if __name__ == "__main__": + main() |
