summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAshwini Mhatre <amhatre@redhat.com>2021-05-12 00:04:47 +0530
committerGitHub <noreply@github.com>2021-05-11 18:34:47 +0000
commit407eec39119320875ffcdede81155a9a5ed201d7 (patch)
tree49dc6845763c9fcc082129089c1eebc5cf36968c
parent6de551224ff6ada0eb7a0a45938d535302a38d7c (diff)
downloadvyos.vyos-407eec39119320875ffcdede81155a9a5ed201d7.tar.gz
vyos.vyos-407eec39119320875ffcdede81155a9a5ed201d7.zip
Vyos route maps (#156)
Vyos route maps Reviewed-by: https://github.com/apps/ansible-zuul
-rw-r--r--changelogs/fragments/vyos-route-maps.yaml3
-rw-r--r--plugins/module_utils/network/vyos/argspec/route_maps/__init__.py0
-rw-r--r--plugins/module_utils/network/vyos/argspec/route_maps/route_maps.py230
-rw-r--r--plugins/module_utils/network/vyos/config/route_maps/__init__.py0
-rw-r--r--plugins/module_utils/network/vyos/config/route_maps/route_maps.py160
-rw-r--r--plugins/module_utils/network/vyos/facts/facts.py4
-rw-r--r--plugins/module_utils/network/vyos/facts/route_maps/__init__.py0
-rw-r--r--plugins/module_utils/network/vyos/facts/route_maps/route_maps.py84
-rw-r--r--plugins/module_utils/network/vyos/rm_templates/route_maps.py1293
-rw-r--r--plugins/modules/vyos_route_maps.py953
-rw-r--r--tests/integration/targets/vyos_route_maps/defaults/main.yaml3
-rw-r--r--tests/integration/targets/vyos_route_maps/tasks/cli.yaml19
-rw-r--r--tests/integration/targets/vyos_route_maps/tasks/main.yaml4
-rw-r--r--tests/integration/targets/vyos_route_maps/tests/cli/_parsed.cfg13
-rw-r--r--tests/integration/targets/vyos_route_maps/tests/cli/_populate.yaml23
-rw-r--r--tests/integration/targets/vyos_route_maps/tests/cli/_remove_config.yaml10
-rw-r--r--tests/integration/targets/vyos_route_maps/tests/cli/deleted.yaml36
-rw-r--r--tests/integration/targets/vyos_route_maps/tests/cli/empty_config.yaml60
-rw-r--r--tests/integration/targets/vyos_route_maps/tests/cli/gathered.yaml24
-rw-r--r--tests/integration/targets/vyos_route_maps/tests/cli/merged.yaml60
-rw-r--r--tests/integration/targets/vyos_route_maps/tests/cli/overridden.yaml56
-rw-r--r--tests/integration/targets/vyos_route_maps/tests/cli/parsed.yaml16
-rw-r--r--tests/integration/targets/vyos_route_maps/tests/cli/rendered.yaml40
-rw-r--r--tests/integration/targets/vyos_route_maps/tests/cli/replaced.yaml56
-rw-r--r--tests/integration/targets/vyos_route_maps/tests/cli/rtt.yaml81
-rw-r--r--tests/integration/targets/vyos_route_maps/vars/main.yaml109
-rw-r--r--tests/sanity/ignore-2.10.txt3
-rw-r--r--tests/sanity/ignore-2.11.txt3
-rw-r--r--tests/sanity/ignore-2.12.txt3
-rw-r--r--tests/sanity/ignore-2.9.txt3
-rw-r--r--tests/unit/modules/network/vyos/fixtures/vyos_route_maps_config.cfg18
-rw-r--r--tests/unit/modules/network/vyos/test_vyos_route_maps.py589
32 files changed, 3956 insertions, 0 deletions
diff --git a/changelogs/fragments/vyos-route-maps.yaml b/changelogs/fragments/vyos-route-maps.yaml
new file mode 100644
index 0000000..6f4e07f
--- /dev/null
+++ b/changelogs/fragments/vyos-route-maps.yaml
@@ -0,0 +1,3 @@
+---
+minor_changes:
+ - Add vyos_route_maps resource module (https://github.com/ansible-collections/vyos.vyos/pull/156.).
diff --git a/plugins/module_utils/network/vyos/argspec/route_maps/__init__.py b/plugins/module_utils/network/vyos/argspec/route_maps/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/module_utils/network/vyos/argspec/route_maps/__init__.py
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
new file mode 100644
index 0000000..790f5e6
--- /dev/null
+++ b/plugins/module_utils/network/vyos/argspec/route_maps/route_maps.py
@@ -0,0 +1,230 @@
+# -*- 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
+
+#############################################
+# 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_route_maps module
+"""
+
+
+class Route_mapsArgs(object): # pylint: disable=R0903
+ """The arg spec for the vyos_route_maps module"""
+
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "config": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "route_map": {"type": "str"},
+ "entries": {
+ "aliases": ["rules"],
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "sequence": {"type": "int"},
+ "call": {"type": "str"},
+ "description": {"type": "str"},
+ "action": {
+ "type": "str",
+ "choices": ["deny", "permit"],
+ },
+ "continue_sequence": {"type": "int"},
+ "set": {
+ "type": "dict",
+ "options": {
+ "aggregator": {
+ "type": "dict",
+ "options": {
+ "ip": {"type": "str"},
+ "as": {"type": "str"},
+ },
+ },
+ "as_path_exclude": {"type": "str"},
+ "as_path_prepend": {"type": "str"},
+ "atomic_aggregate": {"type": "bool"},
+ "bgp_extcommunity_rt": {"type": "str"},
+ "comm_list": {
+ "type": "dict",
+ "options": {
+ "comm_list": {"type": "str"},
+ "delete": {"type": "bool"},
+ },
+ },
+ "community": {
+ "type": "dict",
+ "options": {"value": {"type": "str"}},
+ },
+ "extcommunity_rt": {"type": "str"},
+ "extcommunity_soo": {"type": "str"},
+ "ip_next_hop": {"type": "str"},
+ "ipv6_next_hop": {
+ "type": "dict",
+ "options": {
+ "ip_type": {
+ "type": "str",
+ "choices": ["global", "local"],
+ },
+ "value": {"type": "str"},
+ },
+ },
+ "large_community": {"type": "str"},
+ "local_preference": {"type": "str"},
+ "metric": {"type": "str"},
+ "metric_type": {
+ "type": "str",
+ "choices": ["type-1", "type-2"],
+ },
+ "origin": {
+ "type": "str",
+ "choices": ["egp", "igp", "incomplete"],
+ },
+ "originator_id": {"type": "str"},
+ "src": {"type": "str"},
+ "tag": {"type": "str"},
+ "weight": {"type": "str"},
+ },
+ },
+ "match": {
+ "type": "dict",
+ "options": {
+ "as_path": {"type": "str"},
+ "community": {
+ "type": "dict",
+ "options": {
+ "community_list": {"type": "str"},
+ "exact_match": {"type": "bool"},
+ },
+ },
+ "extcommunity": {"type": "str"},
+ "interface": {"type": "str"},
+ "ip": {
+ "type": "dict",
+ "options": {
+ "address": {
+ "type": "dict",
+ "options": {
+ "list_type": {
+ "type": "str",
+ "choices": [
+ "access-list",
+ "prefix-list",
+ ],
+ },
+ "value": {"type": "str"},
+ },
+ },
+ "next_hop": {
+ "type": "dict",
+ "options": {
+ "list_type": {
+ "type": "str",
+ "choices": [
+ "access-list",
+ "prefix-list",
+ ],
+ },
+ "value": {"type": "str"},
+ },
+ },
+ "route_source": {
+ "type": "dict",
+ "options": {
+ "list_type": {
+ "type": "str",
+ "choices": [
+ "access-list",
+ "prefix-list",
+ ],
+ },
+ "value": {"type": "str"},
+ },
+ },
+ },
+ },
+ "ipv6": {
+ "type": "dict",
+ "options": {
+ "address": {
+ "type": "dict",
+ "options": {
+ "list_type": {
+ "type": "str",
+ "choices": [
+ "access-list",
+ "prefix-list",
+ ],
+ },
+ "value": {"type": "str"},
+ },
+ },
+ "next_hop": {"type": "str"},
+ },
+ },
+ "large_community_large_community_list": {
+ "type": "str"
+ },
+ "metric": {"type": "int"},
+ "origin": {
+ "type": "str",
+ "choices": ["ebgp", "ibgp", "incomplete"],
+ },
+ "peer": {"type": "str"},
+ "rpki": {
+ "type": "str",
+ "choices": [
+ "notfound",
+ "invalid",
+ "valid",
+ ],
+ },
+ },
+ },
+ "on_match": {
+ "type": "dict",
+ "options": {
+ "next": {"type": "bool"},
+ "goto": {"type": "int"},
+ },
+ },
+ },
+ },
+ },
+ },
+ "running_config": {"type": "str"},
+ "state": {
+ "type": "str",
+ "choices": [
+ "deleted",
+ "merged",
+ "overridden",
+ "replaced",
+ "gathered",
+ "rendered",
+ "parsed",
+ ],
+ "default": "merged",
+ },
+ } # pylint: disable=C0301
diff --git a/plugins/module_utils/network/vyos/config/route_maps/__init__.py b/plugins/module_utils/network/vyos/config/route_maps/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/module_utils/network/vyos/config/route_maps/__init__.py
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
new file mode 100644
index 0000000..5e4bbea
--- /dev/null
+++ b/plugins/module_utils/network/vyos/config/route_maps/route_maps.py
@@ -0,0 +1,160 @@
+#
+# -*- 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_route_maps 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 ansible.module_utils.six import iteritems
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
+ dict_merge,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.resource_module import (
+ ResourceModule,
+)
+from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.facts import (
+ Facts,
+)
+from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.rm_templates.route_maps import (
+ Route_mapsTemplate,
+)
+
+
+class Route_maps(ResourceModule):
+ """
+ The vyos_route_maps config class
+ """
+
+ def __init__(self, module):
+ super(Route_maps, self).__init__(
+ empty_fact_val={},
+ facts_module=Facts(module),
+ module=module,
+ resource="route_maps",
+ tmplt=Route_mapsTemplate(),
+ )
+ self.parsers = [
+ "call",
+ "description",
+ "action",
+ "continue_sequence",
+ "set_aggregator_ip",
+ "set_aggregator_as",
+ "set_as_path_exclude",
+ "set_as_path_prepend",
+ "set_atomic_aggregate",
+ "set_bgp_extcommunity_rt",
+ "set_extcommunity_rt",
+ "set_extcommunity_soo",
+ "set_ip_next_hop",
+ "set_ipv6_next_hop",
+ "set_large_community",
+ "set_local_preference",
+ "set_metric",
+ "set_metric_type",
+ "set_origin",
+ "set_originator_id",
+ "set_src",
+ "set_tag",
+ "set_weight",
+ "set_comm_list",
+ "set_comm_list_delete",
+ "set_community",
+ "match_as_path",
+ "match_community_community_list",
+ "match_community_exact_match",
+ "match_extcommunity",
+ "match_interface",
+ "match_large_community_large_community_list",
+ "match_metric",
+ "match_origin",
+ "match_peer",
+ "match_ip_address",
+ "match_ip_next_hop",
+ "match_ip_route_source",
+ "on_match_goto",
+ "on_match_next",
+ "match_ipv6_address",
+ "match_ipv6_nexthop",
+ "match_rpki",
+ ]
+
+ 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 = self._route_maps_list_to_dict(self.want)
+ haved = self._route_maps_list_to_dict(self.have)
+
+ # if state is merged, merge want onto have and then compare
+ if self.state == "merged":
+ wantd = dict_merge(haved, wantd)
+
+ # 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
+ }
+ wantd = {}
+
+ # remove superfluous config for overridden and deleted
+ if self.state in ["overridden", "deleted"]:
+ for k, have in iteritems(haved):
+ if k not in wantd:
+ self.commands.append(
+ self._tmplt.render({"route_map": k}, "route_map", True)
+ )
+
+ for wk, want in iteritems(wantd):
+ self._compare(want=want, have=haved.pop(wk, {}))
+
+ def _compare(self, want, have):
+ """Leverages the base class `compare()` method and
+ populates the list of commands to be run by comparing
+ the `want` and `have` data with the `parsers` defined
+ for the Route_maps network resource.
+ """
+ w_entries = want.get("entries", {})
+ h_entries = have.get("entries", {})
+ self._compare_entries(want=w_entries, have=h_entries)
+
+ def _compare_entries(self, want, have):
+ for wk, wentry in iteritems(want):
+ 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):
+ if "entries" in data:
+ for x in data["entries"]:
+ x.update({"route_map": rmap})
+ data["entries"] = {
+ (rmap, entry.get("sequence")): entry
+ for entry in data["entries"]
+ }
+ return entry
diff --git a/plugins/module_utils/network/vyos/facts/facts.py b/plugins/module_utils/network/vyos/facts/facts.py
index 1a2d786..81518f8 100644
--- a/plugins/module_utils/network/vyos/facts/facts.py
+++ b/plugins/module_utils/network/vyos/facts/facts.py
@@ -55,6 +55,9 @@ from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.bgp_g
from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.bgp_address_family.bgp_address_family import (
Bgp_address_familyFacts,
)
+from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.route_maps.route_maps import (
+ Route_mapsFacts,
+)
from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.legacy.base import (
Default,
Neighbors,
@@ -78,6 +81,7 @@ FACT_RESOURCE_SUBSETS = dict(
ospf_interfaces=Ospf_interfacesFacts,
bgp_global=Bgp_globalFacts,
bgp_address_family=Bgp_address_familyFacts,
+ route_maps=Route_mapsFacts,
)
diff --git a/plugins/module_utils/network/vyos/facts/route_maps/__init__.py b/plugins/module_utils/network/vyos/facts/route_maps/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/module_utils/network/vyos/facts/route_maps/__init__.py
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
new file mode 100644
index 0000000..51e8f97
--- /dev/null
+++ b/plugins/module_utils/network/vyos/facts/route_maps/route_maps.py
@@ -0,0 +1,84 @@
+# -*- 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 route_maps 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.
+"""
+
+from copy import deepcopy
+
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import (
+ utils,
+)
+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.argspec.route_maps.route_maps import (
+ Route_mapsArgs,
+)
+
+
+class Route_mapsFacts(object):
+ """The vyos route_maps facts class"""
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = Route_mapsArgs.argument_spec
+ spec = deepcopy(self.argument_spec)
+ if subspec:
+ if options:
+ facts_argument_spec = spec[subspec][options]
+ else:
+ facts_argument_spec = spec[subspec]
+ else:
+ facts_argument_spec = spec
+
+ self.generated_spec = utils.generate_dict(facts_argument_spec)
+
+ def get_config(self, connection):
+ return connection.get("show configuration commands | grep route-map")
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """Populate the facts for Route_maps 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)
+
+ # parse native config using the Route_maps template
+ route_maps_parser = Route_mapsTemplate(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:
+ if item.get("entries"):
+ item["entries"] = list(item["entries"].values())
+
+ ansible_facts["ansible_network_resources"].pop("route_maps", None)
+
+ # import epdb;epdb.serve()
+ params = utils.remove_empties(
+ utils.validate_config(self.argument_spec, {"config": objs})
+ )
+
+ if params.get("config"):
+ facts["route_maps"] = params["config"]
+ ansible_facts["ansible_network_resources"].update(facts)
+
+ return ansible_facts
diff --git a/plugins/module_utils/network/vyos/rm_templates/route_maps.py b/plugins/module_utils/network/vyos/rm_templates/route_maps.py
new file mode 100644
index 0000000..3ab18b4
--- /dev/null
+++ b/plugins/module_utils/network/vyos/rm_templates/route_maps.py
@@ -0,0 +1,1293 @@
+# -*- 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.network_template import (
+ NetworkTemplate,
+)
+
+
+class Route_mapsTemplate(NetworkTemplate):
+ def __init__(self, lines=None):
+ prefix = {"set": "set", "remove": "delete"}
+ super(Route_mapsTemplate, self).__init__(
+ lines=lines, tmplt=self, prefix=prefix
+ )
+
+ # fmt: off
+ PARSERS = [
+ {
+ "name": "route_map",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "route_map",
+ "setval": "policy route-map {{route_map}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ }
+ }
+ },
+ },
+ {
+ "name": "sequence",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "sequence",
+ "setval": "policy route-map {{route_map}} rule {{sequence}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "call",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\scall\s(?P<call>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": "policy route-map {{route_map}} rule {{sequence}} call {{call}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "call": "{{call}}"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "description",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sdescription\s(?P<description>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": "policy route-map {{route_map}} rule {{sequence}} description {{description}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "description": "{{description}}"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "action",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\saction\s(?P<action>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": "policy route-map {{route_map}} rule {{sequence}} action {{action}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "action": "{{action}}"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "continue_sequence",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\scontinue\s(?P<continue>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": "policy route-map {{route_map}} rule {{sequence}} continue {{continue_sequence}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "continue_sequence": "{{continue}}"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "on_match_next",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\son-match\s(?P<next>next)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "on_match.next",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} on-match next",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "on_match": {
+ "next": "{{True if next is defined}}"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "on_match_goto",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\son-match\sgoto\s(?P<goto>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "on_match.goto",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} on-match goto {{on_match.goto}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "on_match": {
+ "goto": "{{goto}}"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "set_aggregator_ip",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\saggregator\sip\s(?P<ip>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "set.aggregator.ip",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} set aggregator ip {{set.aggregator.ip}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "set": {
+ "aggregator": {
+ "ip": "{{ip}}"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "set_aggregator_as",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\saggregator\sas\s(?P<as>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "set.aggregator.as",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} set aggregator as {{set.aggregator.as}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "set": {
+ "aggregator": {
+ "as": "{{as}}"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "set_as_path_exclude",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\sas-path-exclude\s(?P<as>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "set.as_path_exclude",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} set as-path-exclude {{set.as_path_exclude}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "set": {
+ "as_path_exclude": "{{as}}"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "set_as_path_prepend",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\sas-path-prepend\s(?P<as>\S+)
+ *$""",
+ 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\satomic-aggregate(?P<as>)
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": "policy route-map {{route_map}} rule {{sequence}} set atomic-aggregate",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "set": {
+ "atomic_aggregate": "{{True if as is defined}}"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "set_bgp_extcommunity_rt",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\sbgp-extcommunity-rt\s(?P<bgp>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "set.bgp_extcommunity_rt",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} "
+ "set bgp-extcommunity-rt {{set.bgp_extcommunity_rt}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "set": {
+ "bgp_extcommunity_rt": "{{bgp}}"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "set_comm_list",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\scomm-list\scomm-list\s(?P<comm_list>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "set.comm_list.comm_list",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} "
+ "set comm-list comm-list {{set.comm_list.comm_list}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "set": {
+ "comm_list": {"comm_list": "{{comm_list}}"}
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "set_comm_list_delete",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\scomm-list\sdelete(?P<delete>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "set.comm_list.comm_list",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} "
+ "set comm-list delete",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "set": {
+ "comm_list": {"delete": "{{True if delete is defined}}"}
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "set_extcommunity_rt",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\sextcommunity-rt\s(?P<extcommunity_rt>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "set.extcommunity_rt",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} "
+ "set extcommunity-rt {{set.extcommunity_rt}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "set": {
+ "extcommunity_rt": "{{extcommunity_rt}}"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "set_extcommunity_soo",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\sextcommunity-soo\s(?P<extcommunity_soo>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "set.extcommunity_soo",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} "
+ "set extcommunity-soo {{set.extcommunity_soo}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "set": {
+ "extcommunity_soo": "{{set.extcommunity_soo}}"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "set_ip_next_hop",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\sip-next-hop\s(?P<ip_next_hop>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "set.ip_next_hop",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} "
+ "set ip-next-hop {{set.ip_next_hop}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "set": {
+ "ip_next_hop": "{{ip_next_hop}}"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "set_ipv6_next_hop",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\sipv6-next-hop
+ \s(?P<type>global|local)
+ \s(?P<value>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "set.ipv6_next_hop",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} "
+ "set ipv6-next-hop {{set.ipv6_next_hop.ip_type}} {{set.ipv6_next_hop.value}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "set": {
+ "ipv6_next_hop": {
+ "ip_type": "{{type}}",
+ "value": "{{value}}"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "set_large_community",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\slarge-community\s(?P<large_community>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "set.large_community",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} "
+ "set large-community {{set.large_community}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "set": {
+ "large_community": "{{large_community}}"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "set_local_preference",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\slocal-preference\s(?P<local_preference>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "set.local_preference",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} "
+ "set local-preference {{set.local_preference}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "set": {
+ "local_preference": "{{local_preference}}"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "set_metric",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\smetric\s(?P<metric>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "set.metric",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} "
+ "set metric {{set.metric}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "set": {
+ "metric": "{{metric}}"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "set_metric_type",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\smetric-type\s(?P<metric_type>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "set.metric_type",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} "
+ "set metric-type {{set.metric_type}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "set": {
+ "metric_type": "{{metric_type}}"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "set_origin",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\sorigin\s(?P<origin>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "set.origin",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} "
+ "set origin {{set.origin}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "set": {
+ "origin": "{{origin}}"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "set_originator_id",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\soriginator-id\s(?P<originator_id>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "set.originator_id",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} "
+ "set originator-id {{set.originator_id}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "set": {
+ "originator_id": "{{originator_id}}"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "set_src",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\ssrc\s(?P<src>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "set.src",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} "
+ "set src {{set.src}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "set": {
+ "src": "{{src}}"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "set_tag",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\stag\s(?P<tag>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "set.tag",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} "
+ "set tag {{set.tag}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "set": {
+ "tag": "{{tag}}"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "set_weight",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\sset\sweight\s(?P<weight>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "set.weight",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} "
+ "set weight {{set.weight}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "set": {
+ "weight": "{{weight}}"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "set_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+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "set.community.value",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} "
+ "set community {{set.community.value}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "set": {
+ "community": {
+ "value": "{{value}}",
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "match_as_path",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\sas-path\s(?P<as_path>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "match.as_path",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} "
+ "match as-path {{match.as_path}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "match": {
+ "as_path": "{{as_path}}"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "match_community_community_list",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\scommunity\scommunity-list\s(?P<community_list>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "match.community.community_list",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} "
+ "match community community-list {{match.community.community_list}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "match": {
+ "community": {"community_list": "{{community_list}}"}
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "match_community_exact_match",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\scommunity\sexact-match(?P<exact_match>)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "match.community.exact_match",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} "
+ "match community exact-match",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "match": {
+ "community": {"exact_match": "{{True if exact_match is defined}}"}
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "match_extcommunity",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\sextcommunity\s(?P<extcommunity>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "match.extcommunity",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} "
+ "match extcommunity {{match.extcommunity}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "match": {
+ "extcommunity": "{{extcommunity}}"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "match_interface",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\sinterface\s(?P<interface>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "match.interface",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} "
+ "match interface {{match.interface}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "match": {
+ "interface": "{{interface}}"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "match_large_community_large_community_list",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\slarge-community\slarge-community-list\s(?P<lc>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "match.large_community_large_community_list",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} "
+ "match large-community large-community-list {{match.large_community_large_community_list}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "match": {
+ "large_community_large_community_list": "{{lc}}"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "match_metric",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\smetric\s(?P<metric>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "match.metric",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} "
+ "match metric {{match.metric}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "match": {
+ "metric": "{{metric}}"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "match_origin",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\sorigin\s(?P<origin>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "match.origin",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} "
+ "match origin {{match.origin}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "match": {
+ "origin": "{{origin}}"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "match_peer",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\speer\s(?P<peer>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "match.peer",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} "
+ "match peer {{match.peer}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}":
+ {
+ "sequence": "{{sequence}}",
+ "match": {
+ "peer": "{{peer}}"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "match_ip_address",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\sip\saddress
+ \s(?P<list_type>access-list|prefix-list)
+ \s(?P<value>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "match.ip.address",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} "
+ "match ip address {{match.ip.address.list_type}} {{match.ip.address.value}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}": {
+ "sequence": "{{sequence}}",
+ "match": {
+ "ip": {
+ "address": {
+ "list_type": "{{list_type}}",
+ "value": "{{value}}"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "match_ip_next_hop",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\sip\snexthop
+ \s(?P<list_type>access-list|prefix-list)
+ \s(?P<value>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "match.ip.next_hop",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} "
+ "match ip nexthop {{match.ip.next_hop.list_type}} {{match.ip.next_hop.value}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}": {
+ "sequence": "{{sequence}}",
+ "match": {
+ "ip": {
+ "next_hop": {
+ "list_type": "{{list_type}}",
+ "value": "{{value}}"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "match_ip_route_source",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\sip\sroute-source
+ \s(?P<list_type>access-list|prefix-list)
+ \s(?P<value>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "match.ip.route_source",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} "
+ "match ip route-source {{match.ip.route_source.list_type}} {{match.ip.route_source.value}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}": {
+ "sequence": "{{sequence}}",
+ "match": {
+ "ip": {
+ "route_source": {
+ "list_type": "{{list_type}}",
+ "value": "{{value}}"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "match_ipv6_address",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\sipv6\saddress
+ \s(?P<list_type>access-list|prefix-list)
+ \s(?P<value>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "match.ipv6.address",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} "
+ "match ipv6 address {{match.ipv6.address.list_type}} {{match.ipv6.address.value}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}": {
+ "sequence": "{{sequence}}",
+ "match": {
+ "ipv6": {
+ "address": {
+ "list_type": "{{list_type}}",
+ "value": "{{value}}"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "match_ipv6_nexthop",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\sipv6\snexthop
+ \s(?P<value>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "match.ipv6.next_hop",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} "
+ "match ipv6 nexthop {{match.ipv6.next_hop}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}": {
+ "sequence": "{{sequence}}",
+ "match": {
+ "ipv6": {
+ "next_hop": "{{value}}"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "match_rpki",
+ "getval": re.compile(
+ r"""
+ ^set\spolicy\sroute-map\s(?P<route_map>\S+)\srule\s(?P<sequence>\d+)\smatch\srpki
+ \s(?P<value>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "compval": "match.rpki",
+ "setval": "policy route-map {{route_map}} rule {{sequence}} "
+ "match rpki {{match.rpki}}",
+ "result": {
+ "route_maps": {
+ "{{ route_map }}": {
+ "route_map": '{{ route_map }}',
+ "entries": {
+ "{{sequence}}": {
+ "sequence": "{{sequence}}",
+ "match": {
+ "rpki": "{{value}}"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+
+ ]
+ # fmt: on
diff --git a/plugins/modules/vyos_route_maps.py b/plugins/modules/vyos_route_maps.py
new file mode 100644
index 0000000..bca8383
--- /dev/null
+++ b/plugins/modules/vyos_route_maps.py
@@ -0,0 +1,953 @@
+#!/usr/bin/python
+# -*- 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)
+
+"""
+The module file for vyos_route_maps
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+DOCUMENTATION = """
+module: vyos_route_maps
+version_added: 2.3.0
+short_description: Route Map Resource Module.
+description:
+- This module manages route map configurations on devices running VYOS.
+author: Ashwini Mhatre (@amhatre)
+notes:
+- Tested against vyos 1.2.
+- This module works with connection C(network_cli).
+options:
+ config:
+ description: A list of route-map configuration.
+ type: list
+ elements: dict
+ suboptions:
+ route_map:
+ description: Route map name.
+ type: str
+ entries:
+ description: Route Map rules.
+ aliases: ["rules"]
+ type: list
+ elements: dict
+ suboptions:
+ sequence:
+ type: int
+ description: Route map rule number <1-65535>.
+ call:
+ description: Route map name
+ type: str
+ description:
+ description: Description for the rule.
+ type: str
+ action:
+ description: Action for matching routes
+ type: str
+ choices: ["deny", "permit"]
+ continue_sequence:
+ description: Continue on a different entry within the route-map.
+ type: int
+ set:
+ description: Route parameters.
+ type: dict
+ suboptions:
+ aggregator:
+ type: dict
+ description: Border Gateway Protocol (BGP) aggregator attribute.
+ suboptions:
+ ip:
+ type: str
+ description: IP address.
+ as:
+ type: str
+ description: AS number of an aggregation.
+ as_path_exclude:
+ type: str
+ description: BGP AS path exclude string ex "456 64500 45001"
+ as_path_prepend:
+ type: str
+ description: Prepend string for a Border Gateway Protocol (BGP) AS-path attribute.
+ atomic_aggregate:
+ type: bool
+ description: Border Gateway Protocol (BGP) atomic aggregate attribute.
+ bgp_extcommunity_rt:
+ type: str
+ description: ExtCommunity in format AS:value
+ comm_list:
+ type: dict
+ description: Border Gateway Protocol (BGP) communities matching a community-list.
+ suboptions:
+ comm_list:
+ type: str
+ description: BGP communities with a community-list.
+ delete:
+ type: bool
+ description: Delete BGP communities matching the community-list.
+ community:
+ type: dict
+ description: Border Gateway Protocl (BGP) community attribute.
+ suboptions:
+ value:
+ type: str
+ description: Community in 4 octet AS:value format or it can be from local-AS, no-advertise,no-expert,internet,additive,none.
+ extcommunity_rt:
+ type: str
+ description: Set route target value.ASN:nn_or_IP_address:nn VPN extended community.
+ extcommunity_soo:
+ type: str
+ description: Set Site of Origin value. ASN:nn_or_IP_address:nn VPN extended community
+ ip_next_hop:
+ type: str
+ description: IP address.
+ ipv6_next_hop:
+ type: dict
+ description: Nexthop IPv6 address.
+ suboptions:
+ ip_type:
+ description: Global or Local
+ type: str
+ choices: ["global", "local"]
+ value:
+ description: ipv6 address
+ type: str
+ large_community:
+ type: str
+ description: Set BGP large community value.
+ local_preference:
+ type: str
+ description: Border Gateway Protocol (BGP) local preference attribute.Example <0-4294967295>.
+ metric:
+ type: str
+ description: Destination routing protocol metric. Example <0-4294967295>.
+ metric_type:
+ type: str
+ choices: ['type-1', 'type-2']
+ description: Open Shortest Path First (OSPF) external metric-type.
+ origin:
+ description: Set bgp origin.
+ type: str
+ choices: [ "egp", "igp", "incomplete" ]
+ originator_id:
+ type: str
+ description: Border Gateway Protocol (BGP) originator ID attribute. Orignator IP address.
+ src:
+ type: str
+ description: Source address for route. Example <x.x.x.x> IP address.
+ tag:
+ type: str
+ description: Tag value for routing protocol. Example <1-65535>
+ weight:
+ type: str
+ description: Border Gateway Protocol (BGP) weight attribute. Example <0-4294967295>
+ match:
+ description: Route parameters to match.
+ type: dict
+ suboptions:
+ as_path:
+ description: Set as-path.
+ type: str
+ community:
+ description: BGP community attribute.
+ type: dict
+ suboptions:
+ community_list:
+ description: BGP community-list to match
+ type: str
+ exact_match:
+ description: BGP community-list to match
+ type: bool
+ extcommunity:
+ description: Extended community name.
+ type: str
+ interface:
+ description: First hop interface of a route to match.
+ type: str
+ ip:
+ description: IP prefix parameters to match.
+ type: dict
+ suboptions:
+ address:
+ description: IP address of route to match.
+ type: dict
+ suboptions:
+ list_type: &list_type
+ description: type of list
+ type: str
+ choices: ['access-list', 'prefix-list']
+ value: &value
+ type: str
+ description: value of access-list and prefix list
+ next_hop:
+ description: next hop prefix list.
+ type: dict
+ suboptions:
+ list_type: *list_type
+ value: *value
+ route_source:
+ description: IP route-source to match
+ type: dict
+ suboptions:
+ list_type: *list_type
+ value: *value
+ ipv6:
+ description: IPv6 prefix parameters to match.
+ type: dict
+ suboptions:
+ address:
+ description: IPv6 address of route to match.
+ type: dict
+ suboptions:
+ list_type: *list_type
+ value: *value
+ next_hop:
+ description: next-hop ipv6 address IPv6 <h:h:h:h:h:h:h:h>.
+ type: str
+ large_community_large_community_list:
+ type: str
+ description: BGP large-community-list to match.
+ metric:
+ description: Route metric <1-65535>.
+ type: int
+ origin:
+ description: bgp origin.
+ type: str
+ choices: [ "ebgp", "ibgp", "incomplete" ]
+ peer:
+ type: str
+ description: Peer IP address <x.x.x.x>.
+ rpki:
+ type: str
+ description: RPKI validation value.
+ choices: [ "notfound", "invalid", "valid" ]
+ on_match:
+ type: dict
+ description: Exit policy on matches.
+ suboptions:
+ next:
+ type: bool
+ description: Next sequence number to goto on match.
+ goto:
+ type: int
+ description: Rule number to goto on match <1-65535>.
+ 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 | grep route-map).
+ - The state I(parsed) reads the configuration from C(show configuration commands | grep route-map) 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 = """
+# Using merged
+# Before state
+
+# vyos@vyos:~$ show configuration commands | match "set policy route-map"
+# vyos@vyos:~$
+ - name: Merge the provided configuration with the exisiting running configuration
+ register: result
+ vyos.vyos.vyos_route_maps: &id001
+ config:
+ - route_map: test1
+ entries:
+ - sequence: 1
+ description: "test"
+ action: permit
+ continue: 2
+ on_match:
+ next: True
+ - route_map: test3
+ entries:
+ - sequence: 1
+ action: permit
+ match:
+ rpki: invalid
+ metric: 1
+ peer: 192.0.2.32
+ set:
+ local_preference: 4
+ metric: 5
+ metric_type: "type-1"
+ origin: egp
+ originator_id: 192.0.2.34
+ tag: 5
+ weight: 4
+ state: merged
+# After State
+# vyos@vyos:~$ show configuration commands | match "set policy route-maps"
+# set policy route-map test1 rule 1 description test
+# set policy route-map test1 rule 1 action permit
+# set policy route-map test1 rule 1 continue 2
+# set policy route-map test1 rule 1 on-match next
+# set policy route-map test3 rule 1 action permit
+# set policy route-map test3 rule 1 set local-preference 4
+# set policy route-map test3 rule 1 set metric 5
+# set policy route-map test3 rule 1 set metric-type type-1
+# set policy route-map test3 rule 1 set origin egp
+# set policy route-map test3 rule 1 set originator-id 192.0.2.34
+# set policy route-map test3 rule 1 set tag 5
+# set policy route-map test3 rule 1 set weight 4
+# set policy route-map test3 rule 1 match metric 1
+# set policy route-map test3 rule 1 match peer 192.0.2.32
+# set policy route-map test3 rule 1 match rpki invalid
+
+# "after": [
+# {
+# "entries": [
+# {
+# "action": "permit",
+# "continue_sequence": 2,
+# "description": "test",
+# "on_match": {
+# "next": true
+# },
+# "sequence": 1
+# }
+# ],
+# "route_map": "test1"
+# },
+# {
+# "entries": [
+# {
+# "action": "permit",
+# "match": {
+# "metric": 1,
+# "peer": "192.0.2.32",
+# "rpki": "invalid"
+# },
+# "sequence": 1,
+# "set": {
+# "local_preference": "4",
+# "metric": "5",
+# "metric_type": "type-1",
+# "origin": "egp",
+# "originator_id": "192.0.2.34",
+# "tag": "5",
+# "weight": "4"
+# }
+# }
+# ],
+# "route_map": "test3"
+# }
+# ],
+# "before": {},
+# "changed": true,
+# "commands": [
+# "set policy route-map test1 rule 1 description test",
+# "set policy route-map test1 rule 1 action permit",
+# "set policy route-map test1 rule 1 continue 2",
+# "set policy route-map test1 rule 1 on-match next",
+# "set policy route-map test3 rule 1 action permit",
+# "set policy route-map test3 rule 1 set local-preference 4",
+# "set policy route-map test3 rule 1 set metric 5",
+# "set policy route-map test3 rule 1 set metric-type type-1",
+# "set policy route-map test3 rule 1 set origin egp",
+# "set policy route-map test3 rule 1 set originator-id 192.0.2.34",
+# "set policy route-map test3 rule 1 set tag 5",
+# "set policy route-map test3 rule 1 set weight 4",
+# "set policy route-map test3 rule 1 match metric 1",
+# "set policy route-map test3 rule 1 match peer 192.0.2.32",
+# "set policy route-map test3 rule 1 match rpki invalid"
+# ],
+
+# Using replaced:
+# --------------
+
+# Before state:
+# vyos@vyos:~$ show configuration commands | match "set route-map policy"
+# set policy route-map test2 rule 1 action 'permit'
+# set policy route-map test2 rule 1 description 'test'
+# set policy route-map test2 rule 1 on-match next
+# set policy route-map test2 rule 2 action 'permit'
+# set policy route-map test2 rule 2 on-match goto '4'
+# set policy route-map test3 rule 1 action 'permit'
+# set policy route-map test3 rule 1 match metric '1'
+# set policy route-map test3 rule 1 match peer '192.0.2.32'
+# set policy route-map test3 rule 1 match rpki 'invalid'
+# set policy route-map test3 rule 1 set community 'internet'
+# set policy route-map test3 rule 1 set ip-next-hop '192.0.2.33'
+# set policy route-map test3 rule 1 set local-preference '4'
+# set policy route-map test3 rule 1 set metric '5'
+# set policy route-map test3 rule 1 set metric-type 'type-1'
+# set policy route-map test3 rule 1 set origin 'egp'
+# set policy route-map test3 rule 1 set originator-id '192.0.2.34'
+# set policy route-map test3 rule 1 set tag '5'
+# set policy route-map test3 rule 1 set weight '4'
+#
+# - name: Replace the provided configuration with the exisiting running configuration
+# register: result
+# vyos.vyos.vyos_route_maps: &id001
+# config:
+# - route_map: test3
+# entries:
+# - sequence: 1
+# action: permit
+# match:
+# rpki: invalid
+# metric: 3
+# peer: 192.0.2.35
+# set:
+# local_preference: 6
+# metric: 4
+# metric_type: "type-1"
+# origin: egp
+# originator_id: 192.0.2.34
+# tag: 4
+# weight: 4
+# state: replaced
+# After state:
+
+# vyos@vyos:~$ show configuration commands | match "set policy route-map"
+# set policy route-map test3 rule 1 set local-preference 6
+# set policy route-map test3 rule 1 set metric 4
+# set policy route-map test3 rule 1 set tag 4
+# set policy route-map test3 rule 1 match metric 3
+# set policy route-map test3 rule 1 match peer 192.0.2.35
+# vyos@vyos:~$
+#
+#
+# Module Execution:
+#
+# "after": [
+# {
+# "entries": [
+# {
+# "action": "permit",
+# "description": "test",
+# "on_match": {
+# "next": true
+# },
+# "sequence": 1
+# },
+# {
+# "action": "permit",
+# "on_match": {
+# "goto": 4
+# },
+# "sequence": 2
+# }
+# ],
+# "route_map": "test2"
+# },
+# {
+# "entries": [
+# {
+# "action": "permit",
+# "match": {
+# "metric": 3,
+# "peer": "192.0.2.35",
+# "rpki": "invalid"
+# },
+# "sequence": 1,
+# "set": {
+# "local_preference": "6",
+# "metric": "4",
+# "metric_type": "type-1",
+# "origin": "egp",
+# "originator_id": "192.0.2.34",
+# "tag": "4",
+# "weight": "4"
+# }
+# }
+# ],
+# "route_map": "test3"
+# }
+# ],
+# "before": [
+# {
+# "entries": [
+# {
+# "action": "permit",
+# "description": "test",
+# "on_match": {
+# "next": true
+# },
+# "sequence": 1
+# },
+# {
+# "action": "permit",
+# "on_match": {
+# "goto": 4
+# },
+# "sequence": 2
+# }
+# ],
+# "route_map": "test2"
+# },
+# {
+# "entries": [
+# {
+# "action": "permit",
+# "match": {
+# "metric": 1,
+# "peer": "192.0.2.32",
+# "rpki": "invalid"
+# },
+# "sequence": 1,
+# "set": {
+# "community": {
+# "value": "internet"
+# },
+# "ip_next_hop": "192.0.2.33",
+# "local_preference": "4",
+# "metric": "5",
+# "metric_type": "type-1",
+# "origin": "egp",
+# "originator_id": "192.0.2.34",
+# "tag": "5",
+# "weight": "4"
+# }
+# }
+# ],
+# "route_map": "test3"
+# }
+# ],
+# "changed": true,
+# "commands": [
+# "delete policy route-map test3 rule 1 set ip-next-hop 192.0.2.33",
+# "set policy route-map test3 rule 1 set local-preference 6",
+# "set policy route-map test3 rule 1 set metric 4",
+# "set policy route-map test3 rule 1 set tag 4",
+# "delete policy route-map test3 rule 1 set community internet",
+# "set policy route-map test3 rule 1 match metric 3",
+# "set policy route-map test3 rule 1 match peer 192.0.2.35"
+# ],
+#
+# Using deleted:
+# -------------
+
+# Before state:
+# vyos@vyos:~$ show configuration commands | match "set policy route-map"
+# set policy route-map test3 rule 1 set local-preference 6
+# set policy route-map test3 rule 1 set metric 4
+# set policy route-map test3 rule 1 set tag 4
+# set policy route-map test3 rule 1 match metric 3
+# set policy route-map test3 rule 1 match peer 192.0.2.35
+# vyos@vyos:~$
+#
+# - name: Delete the provided configuration
+# register: result
+# vyos.vyos.vyos_route_maps:
+# config:
+# state: deleted
+# After state:
+
+# vyos@vyos:~$ show configuration commands | match "set policy route-map"
+# vyos@vyos:~$
+#
+#
+# Module Execution:
+#
+# "after": {},
+# "before": [
+# {
+# "entries": [
+# {
+# "action": "permit",
+# "match": {
+# "metric": 3,
+# "peer": "192.0.2.35",
+# },
+# "sequence": 1,
+# "set": {
+# "local_preference": "6",
+# "metric": "4",
+# "tag": "4",
+# }
+# }
+# ],
+# "route_map": "test3"
+# }
+# ],
+# "changed": true,
+# "commands": [
+# "delete policy route-map test3"
+# ],
+#
+# using gathered:
+# --------------
+#
+# Before state:
+# vyos@vyos:~$ show configuration commands | match "set policy route-maps"
+# set policy route-map test1 rule 1 description test
+# set policy route-map test1 rule 1 action permit
+# set policy route-map test1 rule 1 continue 2
+# set policy route-map test1 rule 1 on-match next
+# set policy route-map test3 rule 1 action permit
+# set policy route-map test3 rule 1 set local-preference 4
+# set policy route-map test3 rule 1 set metric 5
+# set policy route-map test3 rule 1 set metric-type type-1
+# set policy route-map test3 rule 1 set origin egp
+# set policy route-map test3 rule 1 set originator-id 192.0.2.34
+# set policy route-map test3 rule 1 set tag 5
+# set policy route-map test3 rule 1 set weight 4
+# set policy route-map test3 rule 1 match metric 1
+# set policy route-map test3 rule 1 match peer 192.0.2.32
+# set policy route-map test3 rule 1 match rpki invalid
+#
+# - name: gather configs
+# vyos.vyos.vyos_route_maps:
+# state: gathered
+
+# "gathered": [
+# {
+# "entries": [
+# {
+# "action": "permit",
+# "continue_sequence": 2,
+# "description": "test",
+# "on_match": {
+# "next": true
+# },
+# "sequence": 1
+# }
+# ],
+# "route_map": "test1"
+# },
+# {
+# "entries": [
+# {
+# "action": "permit",
+# "match": {
+# "metric": 1,
+# "peer": "192.0.2.32",
+# "rpki": "invalid"
+# },
+# "sequence": 1,
+# "set": {
+# "local_preference": "4",
+# "metric": "5",
+# "metric_type": "type-1",
+# "origin": "egp",
+# "originator_id": "192.0.2.34",
+# "tag": "5",
+# "weight": "4"
+# }
+# }
+# ],
+# "route_map": "test3"
+# }
+# ]
+
+# Using parsed:
+# ------------
+
+# parsed.cfg
+# set policy route-map test1 rule 1 description test
+# set policy route-map test1 rule 1 action permit
+# set policy route-map test1 rule 1 continue 2
+# set policy route-map test1 rule 1 on-match next
+# set policy route-map test3 rule 1 action permit
+# set policy route-map test3 rule 1 set local-preference 4
+# set policy route-map test3 rule 1 set metric 5
+# set policy route-map test3 rule 1 set metric-type type-1
+# set policy route-map test3 rule 1 set origin egp
+# set policy route-map test3 rule 1 set originator-id 192.0.2.34
+# set policy route-map test3 rule 1 set tag 5
+# set policy route-map test3 rule 1 set weight 4
+# set policy route-map test3 rule 1 match metric 1
+# set policy route-map test3 rule 1 match peer 192.0.2.32
+# set policy route-map test3 rule 1 match rpki invalid
+#
+# - name: parse configs
+# vyos.vyos.vyos_route_maps:
+# running_config: "{{ lookup('file', './parsed.cfg') }}"
+# state: parsed
+# tags:
+# - parsed
+#
+# Module execution:
+# "parsed": [
+# {
+# "entries": [
+# {
+# "action": "permit",
+# "continue_sequence": 2,
+# "description": "test",
+# "on_match": {
+# "next": true
+# },
+# "sequence": 1
+# }
+# ],
+# "route_map": "test1"
+# },
+# {
+# "entries": [
+# {
+# "action": "permit",
+# "match": {
+# "metric": 1,
+# "peer": "192.0.2.32",
+# "rpki": "invalid"
+# },
+# "sequence": 1,
+# "set": {
+# "local_preference": "4",
+# "metric": "5",
+# "metric_type": "type-1",
+# "origin": "egp",
+# "originator_id": "192.0.2.34",
+# "tag": "5",
+# "weight": "4"
+# }
+# }
+# ],
+# "route_map": "test3"
+# }
+# ]
+#
+#
+# Using rendered:
+# --------------
+# - name: Structure provided configuration into device specific commands
+# register: result
+# vyos.vyos.vyos_route_maps: &id001
+# config:
+# - route_map: test1
+# entries:
+# - sequence: 1
+# description: "test"
+# action: permit
+# continue_sequence: 2
+# on_match:
+# next: True
+# - route_map: test3
+# entries:
+# - sequence: 1
+# action: permit
+# match:
+# rpki: invalid
+# metric: 1
+# peer: 192.0.2.32
+# set:
+# local_preference: 4
+# metric: 5
+# metric_type: "type-1"
+# origin: egp
+# originator_id: 192.0.2.34
+# tag: 5
+# weight: 4
+# state: rendered
+# Module Execution:
+# "rendered": [
+# "set policy route-map test1 rule 1 description test",
+# "set policy route-map test1 rule 1 action permit",
+# "set policy route-map test1 rule 1 continue 2",
+# "set policy route-map test1 rule 1 on-match next",
+# "set policy route-map test3 rule 1 action permit",
+# "set policy route-map test3 rule 1 set local-preference 4",
+# "set policy route-map test3 rule 1 set metric 5",
+# "set policy route-map test3 rule 1 set metric-type type-1",
+# "set policy route-map test3 rule 1 set origin egp",
+# "set policy route-map test3 rule 1 set originator-id 192.0.2.34",
+# "set policy route-map test3 rule 1 set tag 5",
+# "set policy route-map test3 rule 1 set weight 4",
+# "set policy route-map test3 rule 1 match metric 1",
+# "set policy route-map test3 rule 1 match peer 192.0.2.32",
+# "set policy route-map test3 rule 1 match rpki invalid"
+# ]
+#
+#
+# Using overridden:
+# --------------
+# Before state:
+# vyos@vyos:~$ show configuration commands | match "set policy route-map"
+# set policy route-map test2 rule 1 action 'permit'
+# set policy route-map test2 rule 1 description 'test'
+# set policy route-map test2 rule 1 on-match next
+# set policy route-map test2 rule 2 action 'permit'
+# set policy route-map test2 rule 2 on-match goto '4'
+# set policy route-map test3 rule 1 action 'permit'
+# set policy route-map test3 rule 1 match metric '1'
+# set policy route-map test3 rule 1 match peer '192.0.2.32'
+# set policy route-map test3 rule 1 match rpki 'invalid'
+# set policy route-map test3 rule 1 set community 'internet'
+# set policy route-map test3 rule 1 set ip-next-hop '192.0.2.33'
+# set policy route-map test3 rule 1 set local-preference '4'
+# set policy route-map test3 rule 1 set metric '5'
+# set policy route-map test3 rule 1 set metric-type 'type-1'
+# set policy route-map test3 rule 1 set origin 'egp'
+# set policy route-map test3 rule 1 set originator-id '192.0.2.34'
+# set policy route-map test3 rule 1 set tag '5'
+# set policy route-map test3 rule 1 set weight '4'
+#
+# - name: Override the existing configuration with the provided running configuration
+# register: result
+# vyos.vyos.vyos_route_maps: &id001
+# config:
+# - route_map: test3
+# entries:
+# - sequence: 1
+# action: permit
+# match:
+# rpki: invalid
+# metric: 3
+# peer: 192.0.2.35
+# set:
+# local_preference: 6
+# metric: 4
+# metric_type: "type-1"
+# origin: egp
+# originator_id: 192.0.2.34
+# tag: 4
+# weight: 4
+# state: overridden
+# After state:
+
+# vyos@vyos:~$ show configuration commands | match "set policy route-map"
+# set policy route-map test3 rule 1 set metric-type 'type-1'
+# set policy route-map test3 rule 1 set origin 'egp'
+# set policy route-map test3 rule 1 set originator-id '192.0.2.34'
+# set policy route-map test3 rule 1 set weight '4'
+# set policy route-map test3 rule 1 set local-preference 6
+# set policy route-map test3 rule 1 set metric 4
+# set policy route-map test3 rule 1 set tag 4
+# set policy route-map test3 rule 1 match metric 3
+# set policy route-map test3 rule 1 match peer 192.0.2.35
+# set policy route-map test3 rule 1 match rpki 'invalid'
+
+# Module Execution:
+# "after": [
+# {
+# "entries": [
+# {
+# "action": "permit",
+# "match": {
+# "metric": 3,
+# "peer": "192.0.2.35",
+# "rpki": "invalid"
+# },
+# "sequence": 1,
+# "set": {
+# "local_preference": "6",
+# "metric": "4",
+# "metric_type": "type-1",
+# "origin": "egp",
+# "originator_id": "192.0.2.34",
+# "tag": "4",
+# "weight": "4"
+# }
+# }
+# ],
+# "route_map": "test3"
+# }
+# ],
+# "before": [
+# {
+# "entries": [
+# {
+# "action": "permit",
+# "description": "test",
+# "on_match": {
+# "next": true
+# },
+# "sequence": 1
+# },
+# {
+# "action": "permit",
+# "on_match": {
+# "goto": 4
+# },
+# "sequence": 2
+# }
+# ],
+# "route_map": "test2"
+# },
+# {
+# "entries": [
+# {
+# "action": "permit",
+# "match": {
+# "metric": 1,
+# "peer": "192.0.2.32",
+# "rpki": "invalid"
+# },
+# "sequence": 1,
+# "set": {
+# "community": {
+# "value": "internet"
+# },
+# "ip_next_hop": "192.0.2.33",
+# "local_preference": "4",
+# "metric": "5",
+# "metric_type": "type-1",
+# "origin": "egp",
+# "originator_id": "192.0.2.34",
+# "tag": "5",
+# "weight": "4"
+# }
+# }
+# ],
+# "route_map": "test3"
+# }
+# ],
+# "changed": true,
+# "commands": [
+# "delete policy route-map test2",
+# "delete policy route-map test3 rule 1 set ip-next-hop 192.0.2.33",
+# "set policy route-map test3 rule 1 set local-preference 6",
+# "set policy route-map test3 rule 1 set metric 4",
+# "set policy route-map test3 rule 1 set tag 4",
+# "delete policy route-map test3 rule 1 set community internet",
+# "set policy route-map test3 rule 1 match metric 3",
+# "set policy route-map test3 rule 1 match peer 192.0.2.35"
+# ],
+#
+
+"""
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.route_maps.route_maps import (
+ Route_mapsArgs,
+)
+from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.config.route_maps.route_maps import (
+ Route_maps,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: the result form module invocation
+ """
+ module = AnsibleModule(
+ argument_spec=Route_mapsArgs.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 = Route_maps(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tests/integration/targets/vyos_route_maps/defaults/main.yaml b/tests/integration/targets/vyos_route_maps/defaults/main.yaml
new file mode 100644
index 0000000..852a6be
--- /dev/null
+++ b/tests/integration/targets/vyos_route_maps/defaults/main.yaml
@@ -0,0 +1,3 @@
+---
+testcase: '[^_].*'
+test_items: []
diff --git a/tests/integration/targets/vyos_route_maps/tasks/cli.yaml b/tests/integration/targets/vyos_route_maps/tasks/cli.yaml
new file mode 100644
index 0000000..93eb2fe
--- /dev/null
+++ b/tests/integration/targets/vyos_route_maps/tasks/cli.yaml
@@ -0,0 +1,19 @@
+---
+- name: Collect all cli test cases
+ find:
+ paths: '{{ role_path }}/tests/cli'
+ patterns: '{{ testcase }}.yaml'
+ use_regex: true
+ register: test_cases
+ delegate_to: localhost
+
+- name: Set test_items
+ set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
+
+- name: Run test case (connection=ansible.netcommon.network_cli)
+ include: '{{ test_case_to_run }}'
+ vars:
+ ansible_connection: ansible.netcommon.network_cli
+ with_items: '{{ test_items }}'
+ loop_control:
+ loop_var: test_case_to_run
diff --git a/tests/integration/targets/vyos_route_maps/tasks/main.yaml b/tests/integration/targets/vyos_route_maps/tasks/main.yaml
new file mode 100644
index 0000000..b957d2f
--- /dev/null
+++ b/tests/integration/targets/vyos_route_maps/tasks/main.yaml
@@ -0,0 +1,4 @@
+---
+- include: cli.yaml
+ tags:
+ - network_cli
diff --git a/tests/integration/targets/vyos_route_maps/tests/cli/_parsed.cfg b/tests/integration/targets/vyos_route_maps/tests/cli/_parsed.cfg
new file mode 100644
index 0000000..a4aa4d3
--- /dev/null
+++ b/tests/integration/targets/vyos_route_maps/tests/cli/_parsed.cfg
@@ -0,0 +1,13 @@
+set policy route-map test1 rule 1 description test
+set policy route-map test1 rule 1 action permit
+set policy route-map test1 rule 1 continue 2
+set policy route-map test3 rule 1 action permit
+set policy route-map test3 rule 1 set local-preference 4
+set policy route-map test3 rule 1 set metric 5
+set policy route-map test3 rule 1 set metric-type type-1
+set policy route-map test3 rule 1 set origin egp
+set policy route-map test3 rule 1 set originator-id 192.0.2.34
+set policy route-map test3 rule 1 set tag 5
+set policy route-map test3 rule 1 set weight 4
+set policy route-map test3 rule 1 match metric 1
+set policy route-map test3 rule 1 match peer 192.0.2.32 \ No newline at end of file
diff --git a/tests/integration/targets/vyos_route_maps/tests/cli/_populate.yaml b/tests/integration/targets/vyos_route_maps/tests/cli/_populate.yaml
new file mode 100644
index 0000000..9ef975f
--- /dev/null
+++ b/tests/integration/targets/vyos_route_maps/tests/cli/_populate.yaml
@@ -0,0 +1,23 @@
+---
+- name: setup
+ vyos.vyos.vyos_config:
+ lines:
+ - set policy route-map test2 rule 1 action 'permit'
+ - set policy route-map test2 rule 1 description 'test'
+ - set policy route-map test2 rule 2 action 'permit'
+ - set policy route-map test2 rule 2 on-match goto '4'
+ - set policy route-map test3 rule 1 action 'permit'
+ - set policy route-map test3 rule 1 match metric '1'
+ - set policy route-map test3 rule 1 match peer '192.0.2.32'
+ - set policy route-map test3 rule 1 set community 'internet'
+ - set policy route-map test3 rule 1 set ip-next-hop '192.0.2.33'
+ - set policy route-map test3 rule 1 set local-preference '4'
+ - set policy route-map test3 rule 1 set metric '5'
+ - set policy route-map test3 rule 1 set metric-type 'type-1'
+ - set policy route-map test3 rule 1 set origin 'egp'
+ - set policy route-map test3 rule 1 set originator-id '192.0.2.34'
+ - set policy route-map test3 rule 1 set tag '5'
+ - set policy route-map test3 rule 1 set weight '4'
+ ignore_errors: true
+ vars:
+ ansible_connection: ansible.netcommon.network_cli
diff --git a/tests/integration/targets/vyos_route_maps/tests/cli/_remove_config.yaml b/tests/integration/targets/vyos_route_maps/tests/cli/_remove_config.yaml
new file mode 100644
index 0000000..70e9889
--- /dev/null
+++ b/tests/integration/targets/vyos_route_maps/tests/cli/_remove_config.yaml
@@ -0,0 +1,10 @@
+---
+- name: Remove pre-existing route-maps
+ vyos.vyos.vyos_config:
+ lines:
+ - delete policy route-map test1
+ - delete policy route-map test2
+ - delete policy route-map test3
+ ignore_errors: true
+ vars:
+ ansible_connection: ansible.netcommon.network_cli
diff --git a/tests/integration/targets/vyos_route_maps/tests/cli/deleted.yaml b/tests/integration/targets/vyos_route_maps/tests/cli/deleted.yaml
new file mode 100644
index 0000000..efcb88b
--- /dev/null
+++ b/tests/integration/targets/vyos_route_maps/tests/cli/deleted.yaml
@@ -0,0 +1,36 @@
+---
+- debug:
+ msg: START vyos_route_maps deleted integration tests on connection={{
+ ansible_connection }}
+
+- include_tasks: _remove_config.yaml
+
+- include_tasks: _populate.yaml
+
+- block:
+
+ - name: Delete the provided configuration
+ register: result
+ vyos.vyos.vyos_route_maps: &id001
+ config:
+ state: deleted
+
+ - assert:
+ that:
+ - result.commands|length == 2
+ - result.changed == true
+ - result.commands|symmetric_difference(deleted.commands) == []
+
+ - name: Delete the existing configuration with the provided running configuration
+ (IDEMPOTENT)
+ register: result
+ vyos.vyos.vyos_ospf_interfaces: *id001
+
+ - name: Assert that the previous task was idempotent
+ assert:
+ that:
+ - result['changed'] == false
+
+ always:
+
+ - include_tasks: _remove_config.yaml
diff --git a/tests/integration/targets/vyos_route_maps/tests/cli/empty_config.yaml b/tests/integration/targets/vyos_route_maps/tests/cli/empty_config.yaml
new file mode 100644
index 0000000..6d992b8
--- /dev/null
+++ b/tests/integration/targets/vyos_route_maps/tests/cli/empty_config.yaml
@@ -0,0 +1,60 @@
+---
+- debug:
+ msg: START vyos_route_maps empty_config integration tests on connection={{
+ ansible_connection }}
+
+- name: Merged with empty config should give appropriate error message
+ register: result
+ ignore_errors: true
+ vyos.vyos.vyos_route_maps:
+ config:
+ state: merged
+
+- assert:
+ that:
+ - result.msg == 'value of config parameter must not be empty for state merged'
+
+- name: Replaced with empty config should give appropriate error message
+ register: result
+ ignore_errors: true
+ vyos.vyos.vyos_route_maps:
+ config:
+ state: replaced
+
+- assert:
+ that:
+ - result.msg == 'value of config parameter must not be empty for state replaced'
+
+- name: Overridden with empty config should give appropriate error message
+ register: result
+ ignore_errors: true
+ vyos.vyos.vyos_route_maps:
+ config:
+ state: overridden
+
+- assert:
+ that:
+ - result.msg == 'value of config parameter must not be empty for state overridden'
+
+- name: Parsed with empty running_config should give appropriate error message
+ register: result
+ ignore_errors: true
+ vyos.vyos.vyos_route_maps:
+ running_config:
+ state: parsed
+
+- assert:
+ that:
+ - result.msg == 'value of running_config parameter must not be empty for state
+ parsed'
+
+- name: Rendered with empty config should give appropriate error message
+ register: result
+ ignore_errors: true
+ vyos.vyos.vyos_route_maps:
+ config:
+ state: rendered
+
+- assert:
+ that:
+ - result.msg == 'value of config parameter must not be empty for state rendered'
diff --git a/tests/integration/targets/vyos_route_maps/tests/cli/gathered.yaml b/tests/integration/targets/vyos_route_maps/tests/cli/gathered.yaml
new file mode 100644
index 0000000..b73fe23
--- /dev/null
+++ b/tests/integration/targets/vyos_route_maps/tests/cli/gathered.yaml
@@ -0,0 +1,24 @@
+---
+- debug:
+ msg: START vyos_route_maps gathered integration tests on connection={{
+ ansible_connection }}
+
+- include_tasks: _remove_config.yaml
+
+- include_tasks: _populate.yaml
+
+- block:
+
+ - name: Gather config from the device in structured format.
+ register: result
+ vyos.vyos.vyos_route_maps:
+ state: gathered
+
+ - become: true
+ vyos.vyos.vyos_facts:
+ gather_network_resources: route_maps
+
+ - assert:
+ that:
+ - result.changed == false
+ - result.gathered|symmetric_difference(ansible_facts['network_resources']['route_maps']) == []
diff --git a/tests/integration/targets/vyos_route_maps/tests/cli/merged.yaml b/tests/integration/targets/vyos_route_maps/tests/cli/merged.yaml
new file mode 100644
index 0000000..2b86969
--- /dev/null
+++ b/tests/integration/targets/vyos_route_maps/tests/cli/merged.yaml
@@ -0,0 +1,60 @@
+---
+- debug:
+ msg: START vyos_route_maps merged integration tests on connection={{
+ ansible_connection }}
+
+- include_tasks: _remove_config.yaml
+
+- block:
+
+ - name: Merge the provided configuration with the exisiting running configuration
+ register: result
+ vyos.vyos.vyos_route_maps: &id001
+ config:
+ - route_map: test1
+ entries:
+ - sequence: 1
+ description: "test"
+ action: permit
+ continue_sequence: 2
+ - route_map: test3
+ entries:
+ - sequence: 1
+ action: permit
+ match:
+ metric: 1
+ peer: 192.0.2.32
+ set:
+ local_preference: 4
+ metric: 5
+ metric_type: "type-1"
+ origin: egp
+ originator_id: 192.0.2.34
+ tag: 5
+ weight: 4
+ state: merged
+
+ - become: true
+ vyos.vyos.vyos_facts:
+ gather_network_resources: route_maps
+
+ - assert:
+ that:
+ - result.commands|length == 13
+ - result.changed == true
+ - result.commands|symmetric_difference(merged.commands) == []
+ - result.after|symmetric_difference(ansible_facts['network_resources']['route_maps']) == []
+
+ - name: Merge the provided configuration with the existing running configuration
+ (IDEMPOTENT)
+ register: result
+ vyos.vyos.vyos_route_maps: *id001
+
+ - name: Assert that the previous task was idempotent
+ assert:
+ that:
+ - result['changed'] == false
+
+ always:
+
+ - include_tasks: _remove_config.yaml
diff --git a/tests/integration/targets/vyos_route_maps/tests/cli/overridden.yaml b/tests/integration/targets/vyos_route_maps/tests/cli/overridden.yaml
new file mode 100644
index 0000000..f014cf1
--- /dev/null
+++ b/tests/integration/targets/vyos_route_maps/tests/cli/overridden.yaml
@@ -0,0 +1,56 @@
+---
+- debug:
+ msg: START vyos_route_maps overridden integration tests on connection={{
+ ansible_connection }}
+
+- include_tasks: _remove_config.yaml
+
+- include_tasks: _populate.yaml
+
+- block:
+
+ - name: Override the existing configuration with the provided running configuration
+ register: result
+ vyos.vyos.vyos_route_maps: &id001
+ config:
+ - route_map: test3
+ entries:
+ - sequence: 1
+ action: permit
+ match:
+ metric: 3
+ peer: 192.0.2.35
+ set:
+ local_preference: 6
+ metric: 4
+ metric_type: "type-1"
+ origin: egp
+ originator_id: 192.0.2.34
+ tag: 4
+ weight: 4
+ state: overridden
+
+ - become: true
+ vyos.vyos.vyos_facts:
+ gather_network_resources: route_maps
+
+ - assert:
+ that:
+ - result.commands|length == 8
+ - result.changed == true
+ - result.commands|symmetric_difference(overridden.commands) == []
+ - result.after|symmetric_difference(ansible_facts['network_resources']['route_maps']) == []
+
+ - name: Override the existing configuration with the provided running configuration
+ (IDEMPOTENT)
+ register: result
+ vyos.vyos.vyos_route_maps: *id001
+
+ - name: Assert that the previous task was idempotent
+ assert:
+ that:
+ - result['changed'] == false
+
+ always:
+
+ - include_tasks: _remove_config.yaml
diff --git a/tests/integration/targets/vyos_route_maps/tests/cli/parsed.yaml b/tests/integration/targets/vyos_route_maps/tests/cli/parsed.yaml
new file mode 100644
index 0000000..47cb4cc
--- /dev/null
+++ b/tests/integration/targets/vyos_route_maps/tests/cli/parsed.yaml
@@ -0,0 +1,16 @@
+---
+- debug:
+ msg: START vyos_route_maps parsed integration tests on connection={{ ansible_connection
+ }}
+
+- name: Provide the running configuration for parsing (config to be parsed)
+ become: true
+ register: result
+ vyos.vyos.vyos_route_maps:
+ running_config: "{{ lookup('file', '_parsed.cfg') }}"
+ state: parsed
+
+- assert:
+ that:
+ - result.changed == false
+ - result.parsed|symmetric_difference(merged.after) == []
diff --git a/tests/integration/targets/vyos_route_maps/tests/cli/rendered.yaml b/tests/integration/targets/vyos_route_maps/tests/cli/rendered.yaml
new file mode 100644
index 0000000..7d194d9
--- /dev/null
+++ b/tests/integration/targets/vyos_route_maps/tests/cli/rendered.yaml
@@ -0,0 +1,40 @@
+---
+- debug:
+ msg: START vyos_route_maps rendered integration tests on connection={{
+ ansible_connection }}
+
+- include_tasks: _remove_config.yaml
+
+- block:
+
+ - name: Structure provided configuration into device specific commands
+ register: result
+ vyos.vyos.vyos_route_maps: &id001
+ config:
+ - route_map: test1
+ entries:
+ - sequence: 1
+ description: "test"
+ action: permit
+ continue_sequence: 2
+ - route_map: test3
+ entries:
+ - sequence: 1
+ action: permit
+ match:
+ metric: 1
+ peer: 192.0.2.32
+ set:
+ local_preference: 4
+ metric: 5
+ metric_type: "type-1"
+ origin: egp
+ originator_id: 192.0.2.34
+ tag: 5
+ weight: 4
+ state: rendered
+
+ - assert:
+ that:
+ - result.changed == false
+ - result.rendered|symmetric_difference(merged.commands) == []
diff --git a/tests/integration/targets/vyos_route_maps/tests/cli/replaced.yaml b/tests/integration/targets/vyos_route_maps/tests/cli/replaced.yaml
new file mode 100644
index 0000000..1675ec5
--- /dev/null
+++ b/tests/integration/targets/vyos_route_maps/tests/cli/replaced.yaml
@@ -0,0 +1,56 @@
+---
+- debug:
+ msg: START vyos_route_maps replaced integration tests on connection={{
+ ansible_connection }}
+
+- include_tasks: _remove_config.yaml
+
+- include_tasks: _populate.yaml
+
+- block:
+
+ - name: Replace the provided configuration with the exisiting running configuration
+ register: result
+ vyos.vyos.vyos_route_maps: &id001
+ config:
+ - route_map: test3
+ entries:
+ - sequence: 1
+ action: permit
+ match:
+ metric: 3
+ peer: 192.0.2.35
+ set:
+ local_preference: 6
+ metric: 4
+ metric_type: "type-1"
+ origin: egp
+ originator_id: 192.0.2.34
+ tag: 4
+ weight: 4
+ state: replaced
+
+ - become: true
+ vyos.vyos.vyos_facts:
+ gather_network_resources: route_maps
+
+ - assert:
+ that:
+ - result.commands|length == 7
+ - result.changed == true
+ - result.commands|symmetric_difference(replaced.commands) == []
+ - result.after|symmetric_difference(ansible_facts['network_resources']['route_maps']) == []
+
+ - name: Replace the provided configuration with the existing running configuration
+ (IDEMPOTENT)
+ register: result
+ vyos.vyos.vyos_route_maps: *id001
+
+ - name: Assert that the previous task was idempotent
+ assert:
+ that:
+ - result['changed'] == false
+
+ always:
+
+ - include_tasks: _remove_config.yaml
diff --git a/tests/integration/targets/vyos_route_maps/tests/cli/rtt.yaml b/tests/integration/targets/vyos_route_maps/tests/cli/rtt.yaml
new file mode 100644
index 0000000..2a95f1f
--- /dev/null
+++ b/tests/integration/targets/vyos_route_maps/tests/cli/rtt.yaml
@@ -0,0 +1,81 @@
+---
+- debug:
+ msg: START vyos_route_maps merged integration tests on connection={{
+ ansible_connection }}
+
+- include_tasks: _remove_config.yaml
+
+- block:
+
+ - name: Merge the provided configuration with the exisiting running configuration
+ register: baseconfig
+ vyos.vyos.vyos_route_maps:
+ config:
+ - route_map: test1
+ entries:
+ - sequence: 1
+ description: "test"
+ action: permit
+ continue_sequence: 2
+ - route_map: test3
+ entries:
+ - sequence: 1
+ action: permit
+ match:
+ metric: 1
+ peer: 192.0.2.32
+ set:
+ local_preference: 4
+ metric: 5
+ metric_type: "type-1"
+ origin: egp
+ originator_id: 192.0.2.34
+ tag: 5
+ weight: 4
+ state: merged
+
+ - become: true
+ vyos.vyos.vyos_facts:
+ gather_network_resources: route_maps
+
+ - assert:
+ that:
+ - baseconfig.commands|length == 13
+ - baseconfig.changed == true
+ - baseconfig.commands|symmetric_difference(merged.commands) == []
+ - baseconfig.after|symmetric_difference(ansible_facts['network_resources']['route_maps']) == []
+
+ - name: Merge the existing configuration with the provided running configuration
+ register: result
+ vyos.vyos.vyos_route_maps:
+ config:
+ - route_map: test2
+ entries:
+ - sequence: 1
+ action: permit
+ match:
+ metric: 3
+ peer: 192.0.2.35
+ set:
+ local_preference: 6
+ metric: 4
+ metric_type: "type-1"
+ origin: egp
+ originator_id: 192.0.2.34
+ tag: 4
+ weight: 4
+
+ - name: Revert back to base config using facts round trip
+ become: true
+ register: revert
+ vyos.vyos.vyos_route_maps:
+ config: "{{ ansible_facts['network_resources']['route_maps'] }}"
+ state: overridden
+
+ - name: Assert that config was reverted
+ assert:
+ that: baseconfig.after == revert.after
+
+ always:
+
+ - include_tasks: _remove_config.yaml
diff --git a/tests/integration/targets/vyos_route_maps/vars/main.yaml b/tests/integration/targets/vyos_route_maps/vars/main.yaml
new file mode 100644
index 0000000..5a0d027
--- /dev/null
+++ b/tests/integration/targets/vyos_route_maps/vars/main.yaml
@@ -0,0 +1,109 @@
+---
+merged:
+ commands:
+ - set policy route-map test1 rule 1 description test
+ - set policy route-map test1 rule 1 action permit
+ - set policy route-map test1 rule 1 continue 2
+ - set policy route-map test3 rule 1 action permit
+ - set policy route-map test3 rule 1 set local-preference 4
+ - set policy route-map test3 rule 1 set metric 5
+ - set policy route-map test3 rule 1 set metric-type type-1
+ - set policy route-map test3 rule 1 set origin egp
+ - set policy route-map test3 rule 1 set originator-id 192.0.2.34
+ - set policy route-map test3 rule 1 set tag 5
+ - set policy route-map test3 rule 1 set weight 4
+ - set policy route-map test3 rule 1 match metric 1
+ - set policy route-map test3 rule 1 match peer 192.0.2.32
+
+ after:
+ - route_map: "test3"
+ entries:
+ - sequence: 1
+ action: "permit"
+ match:
+ metric: 1
+ peer: "192.0.2.32"
+ set:
+ local_preference: "4"
+ metric: "5"
+ metric_type: "type-1"
+ origin: egp
+ originator_id: "192.0.2.34"
+ tag: "5"
+ weight: "4"
+ - route_map: "test1"
+ entries:
+ - sequence: 1
+ description: "test"
+ action: "permit"
+ continue_sequence: 2
+
+replaced:
+ commands:
+ - delete policy route-map test3 rule 1 set ip-next-hop 192.0.2.33
+ - set policy route-map test3 rule 1 set local-preference 6
+ - set policy route-map test3 rule 1 set metric 4
+ - set policy route-map test3 rule 1 set tag 4
+ - delete policy route-map test3 rule 1 set community internet
+ - set policy route-map test3 rule 1 match metric 3
+ - set policy route-map test3 rule 1 match peer 192.0.2.35
+
+ after:
+ - route_map: test2
+ entries:
+ - sequence: 1
+ description: "test"
+ action: permit
+ - sequence: 1
+ action: permit
+ on_match:
+ goto: 4
+ - route_map: test3
+ entries:
+ - sequence: 1
+ action: permit
+ match:
+ metric: 3
+ peer: 192.0.2.35
+ set:
+ local_preference: 6
+ metric: 4
+ metric_type: "type-1"
+ origin: egp
+ originator_id: 192.0.2.34
+ tag: 4
+ weight: 4
+
+overridden:
+ commands:
+ - delete policy route-map test2
+ - delete policy route-map test3 rule 1 set ip-next-hop 192.0.2.33
+ - set policy route-map test3 rule 1 set local-preference 6
+ - set policy route-map test3 rule 1 set metric 4
+ - set policy route-map test3 rule 1 set tag 4
+ - delete policy route-map test3 rule 1 set community internet
+ - set policy route-map test3 rule 1 match metric 3
+ - set policy route-map test3 rule 1 match peer 192.0.2.35
+
+ after:
+ - route_map: test3
+ entries:
+ - sequence: 1
+ action: permit
+ match:
+ metric: 3
+ peer: 192.0.2.35
+ set:
+ local_preference: 6
+ metric: 4
+ metric_type: "type-1"
+ origin: egp
+ originator_id: 192.0.2.34
+ tag: 4
+ weight: 4
+
+deleted:
+ commands:
+ - delete policy route-map test2
+ - delete policy route-map test3
+ after: []
diff --git a/tests/sanity/ignore-2.10.txt b/tests/sanity/ignore-2.10.txt
index a44822b..69f4063 100644
--- a/tests/sanity/ignore-2.10.txt
+++ b/tests/sanity/ignore-2.10.txt
@@ -1,3 +1,6 @@
plugins/action/vyos.py action-plugin-docs # base class for deprecated network platform modules using `connection: local`
plugins/module_utils/network/vyos/config/ospf_interfaces/ospf_interfaces.py compile-2.6!skip
plugins/module_utils/network/vyos/config/ospf_interfaces/ospf_interfaces.py import-2.6!skip
+plugins/module_utils/network/vyos/config/route_maps/route_maps.py compile-2.6!skip
+plugins/module_utils/network/vyos/config/route_maps/route_maps.py import-2.6!skip
+plugins/modules/vyos_route_maps.py import-2.6!skip
diff --git a/tests/sanity/ignore-2.11.txt b/tests/sanity/ignore-2.11.txt
index a44822b..69f4063 100644
--- a/tests/sanity/ignore-2.11.txt
+++ b/tests/sanity/ignore-2.11.txt
@@ -1,3 +1,6 @@
plugins/action/vyos.py action-plugin-docs # base class for deprecated network platform modules using `connection: local`
plugins/module_utils/network/vyos/config/ospf_interfaces/ospf_interfaces.py compile-2.6!skip
plugins/module_utils/network/vyos/config/ospf_interfaces/ospf_interfaces.py import-2.6!skip
+plugins/module_utils/network/vyos/config/route_maps/route_maps.py compile-2.6!skip
+plugins/module_utils/network/vyos/config/route_maps/route_maps.py import-2.6!skip
+plugins/modules/vyos_route_maps.py import-2.6!skip
diff --git a/tests/sanity/ignore-2.12.txt b/tests/sanity/ignore-2.12.txt
index a44822b..69f4063 100644
--- a/tests/sanity/ignore-2.12.txt
+++ b/tests/sanity/ignore-2.12.txt
@@ -1,3 +1,6 @@
plugins/action/vyos.py action-plugin-docs # base class for deprecated network platform modules using `connection: local`
plugins/module_utils/network/vyos/config/ospf_interfaces/ospf_interfaces.py compile-2.6!skip
plugins/module_utils/network/vyos/config/ospf_interfaces/ospf_interfaces.py import-2.6!skip
+plugins/module_utils/network/vyos/config/route_maps/route_maps.py compile-2.6!skip
+plugins/module_utils/network/vyos/config/route_maps/route_maps.py import-2.6!skip
+plugins/modules/vyos_route_maps.py import-2.6!skip
diff --git a/tests/sanity/ignore-2.9.txt b/tests/sanity/ignore-2.9.txt
index 68064bb..7178a20 100644
--- a/tests/sanity/ignore-2.9.txt
+++ b/tests/sanity/ignore-2.9.txt
@@ -13,3 +13,6 @@ plugins/modules/vyos_lldp_interface.py validate-modules:invalid-documentation #
plugins/action/vyos.py action-plugin-docs # base class for deprecated network platform modules using `connection: local`
plugins/module_utils/network/vyos/config/ospf_interfaces/ospf_interfaces.py compile-2.6!skip
plugins/module_utils/network/vyos/config/ospf_interfaces/ospf_interfaces.py import-2.6!skip
+plugins/module_utils/network/vyos/config/route_maps/route_maps.py compile-2.6!skip
+plugins/module_utils/network/vyos/config/route_maps/route_maps.py import-2.6!skip
+plugins/modules/vyos_route_maps.py import-2.6!skip
diff --git a/tests/unit/modules/network/vyos/fixtures/vyos_route_maps_config.cfg b/tests/unit/modules/network/vyos/fixtures/vyos_route_maps_config.cfg
new file mode 100644
index 0000000..c7fd9ef
--- /dev/null
+++ b/tests/unit/modules/network/vyos/fixtures/vyos_route_maps_config.cfg
@@ -0,0 +1,18 @@
+set policy route-map test3 rule 1 action 'permit'
+set policy route-map test3 rule 1 match interface 'eth2'
+set policy route-map test3 rule 1 match ipv6 nexthop 'fdda:5cc1:23:4::1f'
+set policy route-map test3 rule 1 match metric '1'
+set policy route-map test3 rule 1 match peer '1.1.1.2'
+set policy route-map test3 rule 1 match rpki 'invalid'
+set policy route-map test3 rule 1 set bgp-extcommunity-rt '22:11'
+set policy route-map test3 rule 1 set community 'internet'
+set policy route-map test3 rule 1 set ipv6-next-hop global 'fdda:5cc1:23:4::1f'
+set policy route-map test3 rule 1 set ip-next-hop '10.20.10.20'
+set policy route-map test3 rule 1 set local-preference '4'
+set policy route-map test3 rule 1 set metric '5'
+set policy route-map test3 rule 1 set metric-type 'type-1'
+set policy route-map test3 rule 1 set origin 'egp'
+set policy route-map test3 rule 1 set originator-id '10.0.2.3'
+set policy route-map test3 rule 1 set src '10.0.2.15'
+set policy route-map test3 rule 1 set tag '5'
+set policy route-map test3 rule 1 set weight '4' \ No newline at end of file
diff --git a/tests/unit/modules/network/vyos/test_vyos_route_maps.py b/tests/unit/modules/network/vyos/test_vyos_route_maps.py
new file mode 100644
index 0000000..17c605e
--- /dev/null
+++ b/tests/unit/modules/network/vyos/test_vyos_route_maps.py
@@ -0,0 +1,589 @@
+# (c) 2021 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+from ansible_collections.vyos.vyos.tests.unit.compat.mock import patch
+from ansible_collections.vyos.vyos.plugins.modules import vyos_route_maps
+from ansible_collections.vyos.vyos.tests.unit.modules.utils import (
+ set_module_args,
+)
+from .vyos_module import TestVyosModule, load_fixture
+
+
+class TestVyosRouteMapsModule(TestVyosModule):
+
+ module = vyos_route_maps
+
+ def setUp(self):
+ super(TestVyosRouteMapsModule, self).setUp()
+
+ self.mock_get_resource_connection_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module_base.get_resource_connection"
+ )
+ self.get_resource_connection_config = (
+ self.mock_get_resource_connection_config.start()
+ )
+
+ self.mock_get_resource_connection_facts = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts.get_resource_connection"
+ )
+ self.get_resource_connection_facts = (
+ self.mock_get_resource_connection_facts.start()
+ )
+
+ self.mock_execute_show_command = patch(
+ "ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.route_maps.route_maps.Route_mapsFacts.get_config"
+ )
+
+ self.execute_show_command = self.mock_execute_show_command.start()
+
+ def tearDown(self):
+ super(TestVyosRouteMapsModule, self).tearDown()
+ self.mock_get_resource_connection_config.stop()
+ self.mock_get_resource_connection_facts.stop()
+ self.mock_execute_show_command.stop()
+
+ def load_fixtures(self, commands=None, transport="cli", filename=None):
+ if filename is None:
+ filename = "vyos_route_maps_config.cfg"
+
+ def load_from_file(*args, **kwargs):
+ output = load_fixture(filename)
+ return output
+
+ self.execute_show_command.side_effect = load_from_file
+
+ def test_vyos_route_maps_merged_idempotent(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ route_map="test3",
+ entries=[
+ dict(
+ sequence=1,
+ action="permit",
+ match=dict(
+ rpki="invalid",
+ interface="eth2",
+ metric=1,
+ peer="1.1.1.2",
+ ipv6=dict(next_hop="fdda:5cc1:23:4::1f"),
+ ),
+ set=dict(
+ ipv6_next_hop=dict(
+ ip_type="global",
+ value="fdda:5cc1:23:4::1f",
+ ),
+ community=dict(value="internet"),
+ bgp_extcommunity_rt="22:11",
+ ip_next_hop="10.20.10.20",
+ local_preference=4,
+ metric=5,
+ metric_type="type-1",
+ origin="egp",
+ originator_id="10.0.2.3",
+ src="10.0.2.15",
+ tag=5,
+ weight=4,
+ ),
+ )
+ ],
+ )
+ ],
+ state="merged",
+ )
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_route_maps_merged(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ route_map="test2",
+ entries=[
+ dict(
+ sequence=1,
+ action="permit",
+ match=dict(
+ rpki="invalid",
+ interface="eth2",
+ metric=1,
+ peer="1.1.1.3",
+ ipv6=dict(next_hop="fdda:5cc1:23:4::1f"),
+ ),
+ set=dict(
+ ipv6_next_hop=dict(
+ ip_type="global",
+ value="fdda:5cc1:23:4::1f",
+ ),
+ community=dict(value="internet"),
+ bgp_extcommunity_rt="22:11",
+ ip_next_hop="10.20.10.22",
+ large_community="10:20:21",
+ local_preference=4,
+ metric=5,
+ metric_type="type-2",
+ origin="egp",
+ originator_id="10.0.2.2",
+ src="10.0.2.15",
+ tag=4,
+ weight=4,
+ ),
+ )
+ ],
+ )
+ ],
+ state="merged",
+ )
+ )
+ commands = [
+ "set policy route-map test2 rule 1 action permit",
+ "set policy route-map test2 rule 1 set bgp-extcommunity-rt 22:11",
+ "set policy route-map test2 rule 1 set ip-next-hop 10.20.10.22",
+ "set policy route-map test2 rule 1 set ipv6-next-hop global fdda:5cc1:23:4::1f",
+ "set policy route-map test2 rule 1 set large-community 10:20:21",
+ "set policy route-map test2 rule 1 set local-preference 4",
+ "set policy route-map test2 rule 1 set metric 5",
+ "set policy route-map test2 rule 1 set metric-type type-2",
+ "set policy route-map test2 rule 1 set origin egp",
+ "set policy route-map test2 rule 1 set originator-id 10.0.2.2",
+ "set policy route-map test2 rule 1 set src 10.0.2.15",
+ "set policy route-map test2 rule 1 set tag 4",
+ "set policy route-map test2 rule 1 set weight 4",
+ "set policy route-map test2 rule 1 set community internet",
+ "set policy route-map test2 rule 1 match interface eth2",
+ "set policy route-map test2 rule 1 match metric 1",
+ "set policy route-map test2 rule 1 match peer 1.1.1.3",
+ "set policy route-map test2 rule 1 match ipv6 nexthop fdda:5cc1:23:4::1f",
+ "set policy route-map test2 rule 1 match rpki invalid",
+ ]
+
+ self.execute_module(changed=True, commands=commands)
+
+ def test_route_maps_replaced(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ route_map="test3",
+ entries=[
+ dict(
+ sequence=1,
+ action="permit",
+ match=dict(
+ rpki="invalid",
+ metric=1,
+ peer="1.1.1.3",
+ ipv6=dict(next_hop="fdda:5cc1:23:4::1f"),
+ ),
+ set=dict(
+ ipv6_next_hop=dict(
+ ip_type="global",
+ value="fdda:5cc1:23:4::1f",
+ ),
+ community=dict(value="internet"),
+ bgp_extcommunity_rt="22:11",
+ ip_next_hop="10.20.10.22",
+ large_community="10:20:21",
+ local_preference=4,
+ metric=5,
+ metric_type="type-2",
+ origin="egp",
+ originator_id="10.0.2.2",
+ src="10.0.2.15",
+ tag=4,
+ weight=4,
+ ),
+ )
+ ],
+ ),
+ ],
+ state="replaced",
+ )
+ )
+ commands = [
+ "delete policy route-map test3 rule 1 match interface eth2",
+ "set policy route-map test3 rule 1 set ip-next-hop 10.20.10.22",
+ "set policy route-map test3 rule 1 set large-community 10:20:21",
+ "set policy route-map test3 rule 1 set metric-type type-2",
+ "set policy route-map test3 rule 1 set originator-id 10.0.2.2",
+ "set policy route-map test3 rule 1 set tag 4",
+ "set policy route-map test3 rule 1 match peer 1.1.1.3",
+ ]
+ self.execute_module(changed=True, commands=commands)
+
+ def test_vyos_route_maps_replaced_idempotent(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ route_map="test3",
+ entries=[
+ dict(
+ sequence=1,
+ action="permit",
+ match=dict(
+ rpki="invalid",
+ interface="eth2",
+ metric=1,
+ peer="1.1.1.2",
+ ipv6=dict(next_hop="fdda:5cc1:23:4::1f"),
+ ),
+ set=dict(
+ ipv6_next_hop=dict(
+ ip_type="global",
+ value="fdda:5cc1:23:4::1f",
+ ),
+ community=dict(value="internet"),
+ bgp_extcommunity_rt="22:11",
+ ip_next_hop="10.20.10.20",
+ local_preference=4,
+ metric=5,
+ metric_type="type-1",
+ origin="egp",
+ originator_id="10.0.2.3",
+ src="10.0.2.15",
+ tag=5,
+ weight=4,
+ ),
+ )
+ ],
+ ),
+ ],
+ state="replaced",
+ )
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_route_maps_overridden(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ route_map="test2",
+ entries=[
+ dict(
+ sequence=1,
+ action="permit",
+ match=dict(rpki="invalid", peer="1.1.1.3"),
+ set=dict(
+ ipv6_next_hop=dict(
+ ip_type="global",
+ value="fdda:5cc1:23:4::1f",
+ ),
+ community=dict(value="internet"),
+ bgp_extcommunity_rt="22:11",
+ ip_next_hop="10.20.10.22",
+ large_community="10:20:21",
+ local_preference=4,
+ metric=5,
+ metric_type="type-2",
+ origin="egp",
+ originator_id="10.0.2.2",
+ src="10.0.2.15",
+ tag=4,
+ weight=4,
+ ),
+ )
+ ],
+ )
+ ],
+ state="overridden",
+ )
+ )
+ commands = [
+ "delete policy route-map test3",
+ "set policy route-map test2 rule 1 action permit",
+ "set policy route-map test2 rule 1 set bgp-extcommunity-rt 22:11",
+ "set policy route-map test2 rule 1 set ip-next-hop 10.20.10.22",
+ "set policy route-map test2 rule 1 set ipv6-next-hop global fdda:5cc1:23:4::1f",
+ "set policy route-map test2 rule 1 set large-community 10:20:21",
+ "set policy route-map test2 rule 1 set local-preference 4",
+ "set policy route-map test2 rule 1 set metric 5",
+ "set policy route-map test2 rule 1 set metric-type type-2",
+ "set policy route-map test2 rule 1 set origin egp",
+ "set policy route-map test2 rule 1 set originator-id 10.0.2.2",
+ "set policy route-map test2 rule 1 set src 10.0.2.15",
+ "set policy route-map test2 rule 1 set tag 4",
+ "set policy route-map test2 rule 1 set weight 4",
+ "set policy route-map test2 rule 1 set community internet",
+ "set policy route-map test2 rule 1 match peer 1.1.1.3",
+ "set policy route-map test2 rule 1 match rpki invalid",
+ ]
+ self.execute_module(changed=True, commands=commands)
+
+ def test_vyos_route_maps_overridden_idempotent(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ route_map="test3",
+ entries=[
+ dict(
+ sequence=1,
+ action="permit",
+ match=dict(
+ rpki="invalid",
+ interface="eth2",
+ metric=1,
+ peer="1.1.1.2",
+ ipv6=dict(next_hop="fdda:5cc1:23:4::1f"),
+ ),
+ set=dict(
+ ipv6_next_hop=dict(
+ ip_type="global",
+ value="fdda:5cc1:23:4::1f",
+ ),
+ community=dict(value="internet"),
+ bgp_extcommunity_rt="22:11",
+ ip_next_hop="10.20.10.20",
+ local_preference=4,
+ metric=5,
+ metric_type="type-1",
+ origin="egp",
+ originator_id="10.0.2.3",
+ src="10.0.2.15",
+ tag=5,
+ weight=4,
+ ),
+ )
+ ],
+ ),
+ ],
+ state="overridden",
+ )
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_vyos_route_maps_rendered(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ route_map="test3",
+ entries=[
+ dict(
+ sequence=1,
+ action="permit",
+ match=dict(
+ rpki="invalid",
+ interface="eth2",
+ metric=1,
+ peer="1.1.1.2",
+ ipv6=dict(next_hop="fdda:5cc1:23:4::1f"),
+ ),
+ set=dict(
+ ipv6_next_hop=dict(
+ ip_type="global",
+ value="fdda:5cc1:23:4::1f",
+ ),
+ community=dict(value="internet"),
+ bgp_extcommunity_rt="22:11",
+ ip_next_hop="10.20.10.20",
+ local_preference=4,
+ metric=5,
+ metric_type="type-1",
+ origin="egp",
+ originator_id="10.0.2.3",
+ src="10.0.2.15",
+ tag=5,
+ weight=4,
+ ),
+ )
+ ],
+ ),
+ dict(
+ route_map="test1",
+ entries=[
+ dict(
+ sequence=1,
+ action="permit",
+ description="test",
+ on_match=dict(next=True),
+ ),
+ dict(
+ sequence=2,
+ action="permit",
+ on_match=dict(goto=4),
+ ),
+ ],
+ ),
+ ],
+ state="rendered",
+ )
+ )
+ rendered_cmds = [
+ "set policy route-map test3 rule 1 action permit",
+ "set policy route-map test3 rule 1 set bgp-extcommunity-rt 22:11",
+ "set policy route-map test3 rule 1 set ip-next-hop 10.20.10.20",
+ "set policy route-map test3 rule 1 set ipv6-next-hop global fdda:5cc1:23:4::1f",
+ "set policy route-map test3 rule 1 set local-preference 4",
+ "set policy route-map test3 rule 1 set metric 5",
+ "set policy route-map test3 rule 1 set metric-type type-1",
+ "set policy route-map test3 rule 1 set origin egp",
+ "set policy route-map test3 rule 1 set originator-id 10.0.2.3",
+ "set policy route-map test3 rule 1 set src 10.0.2.15",
+ "set policy route-map test3 rule 1 set tag 5",
+ "set policy route-map test3 rule 1 set weight 4",
+ "set policy route-map test3 rule 1 set community internet",
+ "set policy route-map test3 rule 1 match interface eth2",
+ "set policy route-map test3 rule 1 match metric 1",
+ "set policy route-map test3 rule 1 match peer 1.1.1.2",
+ "set policy route-map test3 rule 1 match ipv6 nexthop fdda:5cc1:23:4::1f",
+ "set policy route-map test3 rule 1 match rpki invalid",
+ "set policy route-map test1 rule 1 description test",
+ "set policy route-map test1 rule 1 action permit",
+ "set policy route-map test1 rule 1 on-match next",
+ "set policy route-map test1 rule 2 action permit",
+ "set policy route-map test1 rule 2 on-match goto 4",
+ ]
+ result = self.execute_module(changed=False)
+ self.assertEqual(
+ sorted(result["rendered"]),
+ sorted(rendered_cmds),
+ result["rendered"],
+ )
+
+ def test_yos_route_maps_parsed(self):
+
+ parsed_str = (
+ "set policy route-map test3 rule 1 action 'permit'"
+ "\nset policy route-map test3 rule 1 match interface 'eth2'\nset policy route-map test3 rule 1 match ipv6 nexthop"
+ " 'fdda:5cc1:23:4::1f'\nset policy route-map test3 rule 1 match metric '1'\nset policy route-map test3 rule 1 match peer "
+ "'1.1.1.2'\nset policy route-map test3 rule 1 match rpki 'invalid'\nset policy route-map test3 rule 1 set bgp-extcommunity-rt "
+ "'22:11'\nset policy route-map test3 rule 1 set community 'internet'\nset policy route-map test3 rule 1 set ipv6-next-hop global"
+ " 'fdda:5cc1:23:4::1f'\nset policy route-map test3 rule 1 set ip-next-hop '10.20.10.20'\nset policy route-map "
+ "test3 rule 1 set local-preference '4'\nset policy route-map test3 rule 1 set metric '5'\nset policy route-map test3 "
+ "rule 1 set metric-type 'type-1'\nset policy route-map test3 rule 1 set origin 'egp'\nset policy route-map test3 rule 1 set originator-id "
+ "'10.0.2.3'\nset policy route-map test3 rule 1 set src '10.0.2.15'"
+ "\nset policy route-map test3 rule 1 set tag '5'\nset policy route-map test3 rule 1 set weight '4'"
+ )
+ set_module_args(dict(running_config=parsed_str, state="parsed"))
+ result = self.execute_module(changed=False)
+ parsed_list = [
+ {
+ "entries": [
+ {
+ "action": "permit",
+ "match": {
+ "interface": "eth2",
+ "ipv6": {"next_hop": "fdda:5cc1:23:4::1f"},
+ "metric": 1,
+ "peer": "1.1.1.2",
+ "rpki": "invalid",
+ },
+ "sequence": 1,
+ "set": {
+ "bgp_extcommunity_rt": "22:11",
+ "community": {"value": "internet"},
+ "ip_next_hop": "10.20.10.20",
+ "ipv6_next_hop": {
+ "ip_type": "global",
+ "value": "fdda:5cc1:23:4::1f",
+ },
+ "local_preference": "4",
+ "metric": "5",
+ "metric_type": "type-1",
+ "origin": "egp",
+ "originator_id": "10.0.2.3",
+ "src": "10.0.2.15",
+ "tag": "5",
+ "weight": "4",
+ },
+ }
+ ],
+ "route_map": "test3",
+ },
+ ]
+ self.assertEqual(parsed_list, result["parsed"])
+
+ def test_vyos_route_maps_gathered(self):
+ set_module_args(dict(state="gathered"))
+ result = self.execute_module(changed=False)
+ gathered_list = [
+ {
+ "entries": [
+ {
+ "action": "permit",
+ "match": {
+ "interface": "eth2",
+ "ipv6": {"next_hop": "fdda:5cc1:23:4::1f"},
+ "metric": 1,
+ "peer": "1.1.1.2",
+ "rpki": "invalid",
+ },
+ "sequence": 1,
+ "set": {
+ "bgp_extcommunity_rt": "22:11",
+ "community": {"value": "internet"},
+ "ip_next_hop": "10.20.10.20",
+ "ipv6_next_hop": {
+ "ip_type": "global",
+ "value": "fdda:5cc1:23:4::1f",
+ },
+ "local_preference": "4",
+ "metric": "5",
+ "metric_type": "type-1",
+ "origin": "egp",
+ "originator_id": "10.0.2.3",
+ "src": "10.0.2.15",
+ "tag": "5",
+ "weight": "4",
+ },
+ }
+ ],
+ "route_map": "test3",
+ },
+ ]
+ self.assertEqual(gathered_list, result["gathered"])
+
+ def test_vyos_route_maps_deleted(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ route_map="test3",
+ entries=[
+ dict(
+ sequence=1,
+ action="permit",
+ match=dict(
+ rpki="invalid",
+ interface="eth2",
+ ),
+ set=dict(
+ origin="egp",
+ originator_id="10.0.2.3",
+ src="10.0.2.15",
+ tag=5,
+ weight=4,
+ ),
+ )
+ ],
+ ),
+ ],
+ state="deleted",
+ )
+ )
+ commands = ["delete policy route-map test3"]
+ self.execute_module(changed=True, commands=commands)