summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--changelogs/fragments/132-add-vyos-bgp-address-family.yml3
-rw-r--r--meta/runtime.yml6
-rw-r--r--plugins/module_utils/network/vyos/argspec/bgp_address_family/__init__.py0
-rw-r--r--plugins/module_utils/network/vyos/argspec/bgp_address_family/bgp_address_family.py200
-rw-r--r--plugins/module_utils/network/vyos/config/bgp_address_family/__init__.py0
-rw-r--r--plugins/module_utils/network/vyos/config/bgp_address_family/bgp_address_family.py369
-rw-r--r--plugins/module_utils/network/vyos/facts/bgp_address_family/__init__.py0
-rw-r--r--plugins/module_utils/network/vyos/facts/bgp_address_family/bgp_address_family.py101
-rw-r--r--plugins/module_utils/network/vyos/facts/facts.py4
-rw-r--r--plugins/module_utils/network/vyos/rm_templates/bgp_address_family.py1421
-rw-r--r--plugins/modules/vyos_bgp_address_family.py1192
-rw-r--r--tests/integration/targets/vyos_bgp_address_family/defaults/main.yaml3
-rw-r--r--tests/integration/targets/vyos_bgp_address_family/meta/main.yaml3
-rw-r--r--tests/integration/targets/vyos_bgp_address_family/tasks/cli.yaml19
-rw-r--r--tests/integration/targets/vyos_bgp_address_family/tasks/main.yaml4
-rw-r--r--tests/integration/targets/vyos_bgp_address_family/tests/cli/_parsed_config.cfg9
-rw-r--r--tests/integration/targets/vyos_bgp_address_family/tests/cli/_populate.yaml17
-rw-r--r--tests/integration/targets/vyos_bgp_address_family/tests/cli/_preconfig.yaml11
-rw-r--r--tests/integration/targets/vyos_bgp_address_family/tests/cli/_remove_config.yaml12
-rw-r--r--tests/integration/targets/vyos_bgp_address_family/tests/cli/deleted.yaml49
-rw-r--r--tests/integration/targets/vyos_bgp_address_family/tests/cli/empty_config.yaml60
-rw-r--r--tests/integration/targets/vyos_bgp_address_family/tests/cli/gathered.yaml24
-rw-r--r--tests/integration/targets/vyos_bgp_address_family/tests/cli/merged.yaml70
-rw-r--r--tests/integration/targets/vyos_bgp_address_family/tests/cli/overridden.yaml58
-rw-r--r--tests/integration/targets/vyos_bgp_address_family/tests/cli/parsed.yaml16
-rw-r--r--tests/integration/targets/vyos_bgp_address_family/tests/cli/rendered.yaml44
-rw-r--r--tests/integration/targets/vyos_bgp_address_family/tests/cli/replaced.yaml58
-rw-r--r--tests/integration/targets/vyos_bgp_address_family/tests/cli/rtt.yaml90
-rw-r--r--tests/integration/targets/vyos_bgp_address_family/vars/main.yaml99
-rw-r--r--tests/unit/modules/network/vyos/fixtures/vyos_bgp_address_family_config.cfg7
-rw-r--r--tests/unit/modules/network/vyos/test_vyos_bgp_address_family.py684
-rw-r--r--tox.ini2
32 files changed, 4634 insertions, 1 deletions
diff --git a/changelogs/fragments/132-add-vyos-bgp-address-family.yml b/changelogs/fragments/132-add-vyos-bgp-address-family.yml
new file mode 100644
index 0000000..9dc1894
--- /dev/null
+++ b/changelogs/fragments/132-add-vyos-bgp-address-family.yml
@@ -0,0 +1,3 @@
+---
+minor_changes:
+ - Add vyos BGP address_family resource module (https://github.com/ansible-collections/vyos.vyos/pull/132).
diff --git a/meta/runtime.yml b/meta/runtime.yml
index 1f99057..f8db7cc 100644
--- a/meta/runtime.yml
+++ b/meta/runtime.yml
@@ -10,6 +10,10 @@ plugin_routing:
redirect: vyos.vyos.vyos
bgp_global:
redirect: vyos.vyos.vyos
+ vyos_bgp_address_family:
+ redirect: vyos.vyos.vyos
+ bgp_address_family:
+ redirect: vyos.vyos.vyos
vyos_command:
redirect: vyos.vyos.vyos
command:
@@ -119,6 +123,8 @@ plugin_routing:
redirect: vyos.vyos.vyos_banner
bgp_global:
redirect: vyos.vyos.vyos_bgp_global
+ bgp_address_family:
+ redirect: vyos.vyos.vyos_bgp_address_family
command:
redirect: vyos.vyos.vyos_command
config:
diff --git a/plugins/module_utils/network/vyos/argspec/bgp_address_family/__init__.py b/plugins/module_utils/network/vyos/argspec/bgp_address_family/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/module_utils/network/vyos/argspec/bgp_address_family/__init__.py
diff --git a/plugins/module_utils/network/vyos/argspec/bgp_address_family/bgp_address_family.py b/plugins/module_utils/network/vyos/argspec/bgp_address_family/bgp_address_family.py
new file mode 100644
index 0000000..8cbbc50
--- /dev/null
+++ b/plugins/module_utils/network/vyos/argspec/bgp_address_family/bgp_address_family.py
@@ -0,0 +1,200 @@
+# -*- 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 resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+
+"""
+The arg spec for the vyos_bgp_address_family module
+"""
+
+
+class Bgp_address_familyArgs(object): # pylint: disable=R0903
+ """The arg spec for the vyos_bgp_address_family module"""
+
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "running_config": {},
+ "state": {
+ "default": "merged",
+ "type": "str",
+ "choices": [
+ "merged",
+ "replaced",
+ "deleted",
+ "gathered",
+ "parsed",
+ "rendered",
+ "purged",
+ "overridden",
+ ],
+ },
+ "config": {
+ "type": "dict",
+ "options": {
+ "neighbors": {
+ "elements": "dict",
+ "type": "list",
+ "options": {
+ "address_family": {
+ "elements": "dict",
+ "type": "list",
+ "options": {
+ "nexthop_local": {"type": "bool"},
+ "soft_reconfiguration": {"type": "bool"},
+ "unsupress_map": {"type": "str"},
+ "nexthop_self": {"type": "bool"},
+ "weight": {"type": "int"},
+ "prefix_list": {
+ "elements": "dict",
+ "type": "list",
+ "options": {
+ "action": {
+ "type": "str",
+ "choices": ["export", "import"],
+ },
+ "prefix_list": {"type": "str"},
+ },
+ },
+ "default_originate": {"type": "str"},
+ "distribute_list": {
+ "elements": "dict",
+ "type": "list",
+ "options": {
+ "action": {
+ "type": "str",
+ "choices": ["export", "import"],
+ },
+ "acl": {"type": "int"},
+ },
+ },
+ "allowas_in": {"type": "int"},
+ "filter_list": {
+ "elements": "dict",
+ "type": "list",
+ "options": {
+ "action": {
+ "type": "str",
+ "choices": ["export", "import"],
+ },
+ "path_list": {"type": "str"},
+ },
+ },
+ "route_server_client": {"type": "bool"},
+ "attribute_unchanged": {
+ "type": "dict",
+ "options": {
+ "as_path": {"type": "bool"},
+ "med": {"type": "bool"},
+ "next_hop": {"type": "bool"},
+ },
+ },
+ "peer_group": {"type": "str"},
+ "maximum_prefix": {"type": "int"},
+ "route_reflector_client": {"type": "bool"},
+ "route_map": {
+ "elements": "dict",
+ "type": "list",
+ "options": {
+ "action": {
+ "type": "str",
+ "choices": ["export", "import"],
+ },
+ "route_map": {"type": "str"},
+ },
+ },
+ "capability": {
+ "type": "dict",
+ "options": {
+ "orf": {
+ "type": "str",
+ "choices": ["send", "receive"],
+ },
+ "dynamic": {"type": "bool"},
+ },
+ },
+ "remove_private_as": {"type": "bool"},
+ "as_override": {"type": "bool"},
+ "afi": {
+ "type": "str",
+ "choices": ["ipv4", "ipv6"],
+ },
+ },
+ },
+ "neighbor_address": {"type": "str"},
+ },
+ },
+ "as_number": {"type": "int"},
+ "address_family": {
+ "elements": "dict",
+ "type": "list",
+ "options": {
+ "afi": {"type": "str", "choices": ["ipv4", "ipv6"]},
+ "redistribute": {
+ "elements": "dict",
+ "type": "list",
+ "options": {
+ "table": {"type": "str"},
+ "metric": {"type": "int"},
+ "protocol": {
+ "type": "str",
+ "choices": [
+ "connected",
+ "kernel",
+ "ospf",
+ "ospfv3",
+ "rip",
+ "ripng",
+ "static",
+ ],
+ },
+ "route_map": {"type": "str"},
+ },
+ },
+ "networks": {
+ "elements": "dict",
+ "type": "list",
+ "options": {
+ "backdoor": {"type": "bool"},
+ "prefix": {"type": "str"},
+ "path_limit": {"type": "int"},
+ "route_map": {"type": "str"},
+ },
+ },
+ "aggregate_address": {
+ "elements": "dict",
+ "type": "list",
+ "options": {
+ "summary_only": {"type": "bool"},
+ "prefix": {"type": "str"},
+ "as_set": {"type": "bool"},
+ },
+ },
+ },
+ },
+ },
+ },
+ } # pylint: disable=C0301
diff --git a/plugins/module_utils/network/vyos/config/bgp_address_family/__init__.py b/plugins/module_utils/network/vyos/config/bgp_address_family/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/module_utils/network/vyos/config/bgp_address_family/__init__.py
diff --git a/plugins/module_utils/network/vyos/config/bgp_address_family/bgp_address_family.py b/plugins/module_utils/network/vyos/config/bgp_address_family/bgp_address_family.py
new file mode 100644
index 0000000..876402f
--- /dev/null
+++ b/plugins/module_utils/network/vyos/config/bgp_address_family/bgp_address_family.py
@@ -0,0 +1,369 @@
+#
+# -*- 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_bgp_address_family 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.
+"""
+
+import re
+
+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.bgp_address_family import (
+ Bgp_address_familyTemplate,
+)
+
+
+class Bgp_address_family(ResourceModule):
+ """
+ The vyos_bgp_address_family config class
+ """
+
+ def __init__(self, module):
+ super(Bgp_address_family, self).__init__(
+ empty_fact_val={},
+ facts_module=Facts(module),
+ module=module,
+ resource="bgp_address_family",
+ tmplt=Bgp_address_familyTemplate(),
+ )
+ self.parsers = []
+
+ def execute_module(self):
+ """Execute the module
+
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ if self.state not in ["parsed", "gathered"]:
+ self.generate_commands()
+ self.run_commands()
+ return self.result
+
+ def generate_commands(self):
+ """Generate configuration commands to send based on
+ want, have and desired state.
+ """
+ wantd = {}
+ haved = {}
+
+ if (
+ self.want.get("as_number") == self.have.get("as_number")
+ or not self.have
+ ):
+ if self.want:
+ wantd = {self.want["as_number"]: self.want}
+ if self.have:
+ haved = {self.have["as_number"]: self.have}
+ else:
+ self._module.fail_json(
+ msg="Only one bgp instance is allowed per device"
+ )
+
+ # turn all lists of dicts into dicts prior to merge
+ for entry in wantd, haved:
+ self._bgp_af_list_to_dict(entry)
+
+ # 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":
+ for k, have in iteritems(haved):
+ self._delete_af(wantd, have)
+ wantd = {}
+
+ if self.state == "overridden":
+ for k, have in iteritems(haved):
+ if k not in wantd:
+ self._compare(want={}, have=have)
+
+ for k, want in iteritems(wantd):
+ self._compare(want=want, have=haved.pop(k, {}))
+
+ 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 Bgp_address_family network resource.
+ """
+ self._compare_af(want, have)
+ self._compare_neighbors(want, have)
+ # Do the negation first
+ command_set = []
+ for cmd in self.commands:
+ if cmd not in command_set:
+ if "delete" in cmd:
+ command_set.insert(0, cmd)
+ else:
+ command_set.append(cmd)
+ self.commands = command_set
+
+ def _compare_af(self, want, have):
+ waf = want.get("address_family", {})
+ haf = have.get("address_family", {})
+ for name, entry in iteritems(waf):
+ self._compare_lists(
+ entry,
+ have=haf.get(name, {}),
+ as_number=want["as_number"],
+ afi=name,
+ )
+ for name, entry in iteritems(haf):
+ if name not in waf.keys() and self.state == "replaced":
+ continue
+ self._compare_lists(
+ {}, entry, as_number=have["as_number"], afi=name
+ )
+
+ def _delete_af(self, want, have):
+ for as_num, entry in iteritems(want):
+ for afi, af_entry in iteritems(entry.get("address_family", {})):
+ if have.get("address_family"):
+ for hafi, hentry in iteritems(have["address_family"]):
+ if hafi == afi:
+ self.commands.append(
+ self._tmplt.render(
+ {
+ "as_number": as_num,
+ "address_family": {"afi": afi},
+ },
+ "address_family",
+ True,
+ )
+ )
+ for neigh, neigh_entry in iteritems(entry.get("neighbors", {})):
+ if have.get("neighbors"):
+ for hneigh, hnentry in iteritems(have["neighbors"]):
+ if hneigh == neigh:
+ if not neigh_entry.get("address_family"):
+ self.commands.append(
+ self._tmplt.render(
+ {
+ "as_number": as_num,
+ "neighbors": {
+ "neighbor_address": neigh
+ },
+ },
+ "neighbors",
+ True,
+ )
+ )
+ else:
+ for k in neigh_entry["address_family"].keys():
+ if (
+ hnentry.get("address_family")
+ and k
+ in hnentry["address_family"].keys()
+ ):
+ self.commands.append(
+ self._tmplt.render(
+ {
+ "as_number": as_num,
+ "neighbors": {
+ "neighbor_address": neigh,
+ "address_family": {
+ "afi": k
+ },
+ },
+ },
+ "neighbors.address_family",
+ True,
+ )
+ )
+
+ def _compare_neighbors(self, want, have):
+ parsers = [
+ "neighbors.allowas_in",
+ "neighbors.as_override",
+ "neighbors.attribute_unchanged.as_path",
+ "neighbors.attribute_unchanged.med",
+ "neighbors.attribute_unchanged.next_hop",
+ "neighbors.capability_dynamic",
+ "neighbors.capability_orf",
+ "neighbors.default_originate",
+ "neighbors.distribute_list",
+ "neighbors.prefix_list",
+ "neighbors.filter_list",
+ "neighbors.maximum_prefix",
+ "neighbors.nexthop_local",
+ "neighbors.nexthop_self",
+ "neighbors.peer_group",
+ "neighbors.remove_private_as",
+ "neighbors.route_map",
+ "neighbors.route_reflector_client",
+ "neighbors.route_server_client",
+ "neighbors.soft_reconfiguration",
+ "neighbors.unsuppress_map",
+ "neighbors.weight",
+ ]
+ wneigh = want.get("neighbors", {})
+ hneigh = have.get("neighbors", {})
+ for name, entry in iteritems(wneigh):
+ for afi, af_entry in iteritems(entry.get("address_family")):
+ for k, val in iteritems(af_entry):
+ w = {
+ "as_number": want["as_number"],
+ "neighbors": {
+ "neighbor_address": name,
+ "address_family": {"afi": afi, k: val},
+ },
+ }
+ h = {}
+ if hneigh.get(name):
+ if hneigh[name]["address_family"].get(afi):
+ if hneigh[name]["address_family"][afi].get(k):
+ h = {
+ "as_number": want["as_number"],
+ "neighbors": {
+ "neighbor_address": name,
+ "address_family": {
+ "afi": afi,
+ k: hneigh[name]["address_family"][
+ afi
+ ].pop(k, {}),
+ },
+ },
+ }
+ self.compare(
+ parsers=parsers,
+ want=w,
+ have=h,
+ )
+ for name, entry in iteritems(hneigh):
+ if name not in wneigh.keys():
+ # remove surplus config for overridden and replaced
+ if self.state != "replaced":
+ self.commands.append(
+ self._tmplt.render(
+ {
+ "as_number": have["as_number"],
+ "neighbors": {"neighbor_address": name},
+ },
+ "neighbors",
+ True,
+ )
+ )
+ continue
+
+ for hafi, haf_entry in iteritems(entry.get("address_family")):
+ # remove surplus configs for given neighbor - replace and overridden
+ for k, val in iteritems(haf_entry):
+ h = {
+ "as_number": have["as_number"],
+ "neighbors": {
+ "neighbor_address": name,
+ "address_family": {"afi": hafi, k: val},
+ },
+ }
+ self.compare(parsers=parsers, want={}, have=h)
+
+ def _compare_lists(self, want, have, as_number, afi):
+ parsers = [
+ "aggregate_address",
+ "network.backdoor",
+ "network.path_limit",
+ "network.route_map",
+ "redistribute.metric",
+ "redistribute.route_map",
+ "redistribute.table",
+ ]
+ for attrib in ["redistribute", "networks", "aggregate_address"]:
+ wdict = want.pop(attrib, {})
+ hdict = have.pop(attrib, {})
+ for key, entry in iteritems(wdict):
+ if entry != hdict.get(key, {}):
+ self.compare(
+ parsers=parsers,
+ want={
+ "as_number": as_number,
+ "address_family": {"afi": afi, attrib: entry},
+ },
+ have={
+ "as_number": as_number,
+ "address_family": {
+ "afi": afi,
+ attrib: hdict.pop(key, {}),
+ },
+ },
+ )
+ hdict.pop(key, {})
+ # remove remaining items in have for replaced
+ if not wdict and hdict:
+ attrib = re.sub("_", "-", attrib)
+ attrib = re.sub("networks", "network", attrib)
+ self.commands.append(
+ "delete protocols bgp "
+ + str(as_number)
+ + " "
+ + "address-family "
+ + afi
+ + " "
+ + attrib
+ )
+ hdict = {}
+ for key, entry in iteritems(hdict):
+ self.compare(
+ parsers=parsers,
+ want={},
+ have={
+ "as_number": as_number,
+ "address_family": {"afi": afi, attrib: entry},
+ },
+ )
+
+ def _bgp_af_list_to_dict(self, entry):
+ for name, proc in iteritems(entry):
+ if "address_family" in proc:
+ af_dict = {}
+ for entry in proc.get("address_family"):
+ if "networks" in entry:
+ network_dict = {}
+ for n_entry in entry.get("networks", []):
+ network_dict.update({n_entry["prefix"]: n_entry})
+ entry["networks"] = network_dict
+
+ if "aggregate_address" in entry:
+ agg_dict = {}
+ for a_entry in entry.get("aggregate_address", []):
+ agg_dict.update({a_entry["prefix"]: a_entry})
+ entry["aggregate_address"] = agg_dict
+
+ if "redistribute" in entry:
+ redis_dict = {}
+ for r_entry in entry.get("redistribute", []):
+ proto_key = r_entry.get("protocol", "table")
+ redis_dict.update({proto_key: r_entry})
+ entry["redistribute"] = redis_dict
+
+ for af in proc.get("address_family"):
+ af_dict.update({af["afi"]: af})
+ proc["address_family"] = af_dict
+
+ if "neighbors" in proc:
+ neigh_dict = {}
+ for entry in proc.get("neighbors", []):
+ neigh_dict.update({entry["neighbor_address"]: entry})
+ proc["neighbors"] = neigh_dict
+ self._bgp_af_list_to_dict(proc["neighbors"])
diff --git a/plugins/module_utils/network/vyos/facts/bgp_address_family/__init__.py b/plugins/module_utils/network/vyos/facts/bgp_address_family/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/module_utils/network/vyos/facts/bgp_address_family/__init__.py
diff --git a/plugins/module_utils/network/vyos/facts/bgp_address_family/bgp_address_family.py b/plugins/module_utils/network/vyos/facts/bgp_address_family/bgp_address_family.py
new file mode 100644
index 0000000..a7296f2
--- /dev/null
+++ b/plugins/module_utils/network/vyos/facts/bgp_address_family/bgp_address_family.py
@@ -0,0 +1,101 @@
+# -*- 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 bgp_address_family fact class
+It is in this file the configuration is collected from the device
+for a given resource, parsed, and the facts tree is populated
+based on the configuration.
+"""
+
+import re
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import (
+ utils,
+)
+from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.rm_templates.bgp_address_family import (
+ Bgp_address_familyTemplate,
+)
+from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.bgp_address_family.bgp_address_family import (
+ Bgp_address_familyArgs,
+)
+
+
+class Bgp_address_familyFacts(object):
+ """The vyos bgp_address_family facts class"""
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = Bgp_address_familyArgs.argument_spec
+
+ def get_device_data(self, connection):
+ return connection.get(
+ 'show configuration commands | match "set protocols bgp"'
+ )
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """Populate the facts for Bgp_address_family network resource
+
+ :param connection: the device connection
+ :param ansible_facts: Facts dictionary
+ :param data: previously collected conf
+
+ :rtype: dictionary
+ :returns: facts
+ """
+ facts = {}
+ objs = []
+ config_lines = []
+
+ if not data:
+ data = self.get_device_data(connection)
+
+ for resource in data.splitlines():
+ if "address-family" in resource:
+ config_lines.append(re.sub("'", "", resource))
+
+ # parse native config using the Bgp_address_family template
+ bgp_address_family_parser = Bgp_address_familyTemplate(
+ lines=config_lines
+ )
+ objs = bgp_address_family_parser.parse()
+ if objs:
+ if "address_family" in objs:
+ objs["address_family"] = list(objs["address_family"].values())
+ for af in objs["address_family"]:
+ if "networks" in af:
+ af["networks"] = sorted(
+ af["networks"], key=lambda k: k["prefix"]
+ )
+ if "aggregate_address" in af:
+ af["aggregate_address"] = sorted(
+ af["aggregate_address"], key=lambda k: k["prefix"]
+ )
+ if "neighbors" in objs:
+ objs["neighbors"] = list(objs["neighbors"].values())
+ objs["neighbors"] = sorted(
+ objs["neighbors"], key=lambda k: k["neighbor_address"]
+ )
+ for neigh in objs["neighbors"]:
+ if "address_family" in neigh:
+ neigh["address_family"] = list(
+ neigh["address_family"].values()
+ )
+
+ ansible_facts["ansible_network_resources"].pop(
+ "bgp_address_family", None
+ )
+
+ params = utils.remove_empties(
+ utils.validate_config(self.argument_spec, {"config": objs})
+ )
+
+ facts["bgp_address_family"] = params.get("config", [])
+ ansible_facts["ansible_network_resources"].update(facts)
+
+ return ansible_facts
diff --git a/plugins/module_utils/network/vyos/facts/facts.py b/plugins/module_utils/network/vyos/facts/facts.py
index 95eff2e..1a2d786 100644
--- a/plugins/module_utils/network/vyos/facts/facts.py
+++ b/plugins/module_utils/network/vyos/facts/facts.py
@@ -52,6 +52,9 @@ from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.ospf_
from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.bgp_global.bgp_global import (
Bgp_globalFacts,
)
+from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.bgp_address_family.bgp_address_family import (
+ Bgp_address_familyFacts,
+)
from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.legacy.base import (
Default,
Neighbors,
@@ -74,6 +77,7 @@ FACT_RESOURCE_SUBSETS = dict(
ospfv2=Ospfv2Facts,
ospf_interfaces=Ospf_interfacesFacts,
bgp_global=Bgp_globalFacts,
+ bgp_address_family=Bgp_address_familyFacts,
)
diff --git a/plugins/module_utils/network/vyos/rm_templates/bgp_address_family.py b/plugins/module_utils/network/vyos/rm_templates/bgp_address_family.py
new file mode 100644
index 0000000..55e2200
--- /dev/null
+++ b/plugins/module_utils/network/vyos/rm_templates/bgp_address_family.py
@@ -0,0 +1,1421 @@
+# -*- 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 Bgp_address_family 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,
+)
+
+
+def _tmplt_bgp_af_aggregate_address(config_data):
+ afi = config_data["address_family"]["afi"] + "-unicast"
+ command = "protocols bgp {as_number} address-family ".format(**config_data)
+ config_data = config_data["address_family"]
+ if config_data["aggregate_address"].get("as_set"):
+ command += afi + " aggregate-address {prefix} as-set".format(
+ **config_data["aggregate_address"]
+ )
+ if config_data["aggregate_address"].get("summary_only"):
+ command += afi + " aggregate-address {prefix} summary-only".format(
+ **config_data["aggregate_address"]
+ )
+ return command
+
+
+def _tmplt_bgp_af_redistribute_metric(config_data):
+ if config_data["address_family"]["redistribute"].get("metric"):
+ afi = config_data["address_family"]["afi"] + "-unicast"
+ command = "protocols bgp {as_number} address-family ".format(
+ **config_data
+ )
+ if config_data["address_family"]["redistribute"].get("metric"):
+ command += afi + " redistribute {protocol} metric {metric}".format(
+ **config_data["address_family"]["redistribute"]
+ )
+ return command
+
+
+def _tmplt_bgp_af_redistribute_route_map(config_data):
+ if config_data["address_family"]["redistribute"].get("route_map"):
+ afi = config_data["address_family"]["afi"] + "-unicast"
+ command = "protocols bgp {as_number} address-family ".format(
+ **config_data
+ )
+ if config_data["address_family"]["redistribute"].get("route_map"):
+ command += (
+ afi
+ + " redistribute {protocol} route-map {route_map}".format(
+ **config_data["address_family"]["redistribute"]
+ )
+ )
+ return command
+
+
+def _tmplt_bgp_af_redistribute_table(config_data):
+ if config_data["address_family"]["redistribute"].get("table"):
+ afi = config_data["address_family"]["afi"] + "-unicast"
+ command = "protocols bgp {as_number} address-family ".format(
+ **config_data
+ )
+ if config_data["address_family"]["redistribute"].get("table"):
+ command += afi + " table {table}".format(
+ **config_data["address_family"]["redistribute"]
+ )
+ return command
+
+
+def _tmplt_bgp_af_delete_redistribute(config_data):
+ afi = config_data["address_family"]["afi"] + "-unicast"
+ command = "protocols bgp {as_number} address-family ".format(**config_data)
+ config_data = config_data["address_family"]
+ command += afi + " redistribute {protocol}".format(
+ **config_data["redistribute"]
+ )
+ return command
+
+
+def _tmplt_bgp_af_neighbor_distribute_list(config_data):
+ command = []
+ afi = config_data["neighbors"]["address_family"]["afi"] + "-unicast"
+ cmd = "protocols bgp {as_number} neighbor ".format(**config_data)
+ cmd += "{neighbor_address} address-family ".format(
+ **config_data["neighbors"]
+ )
+ config_data = config_data["neighbors"]["address_family"]
+ for list_el in config_data["distribute_list"]:
+ command.append(
+ cmd
+ + afi
+ + " distribute-list "
+ + list_el["action"]
+ + " "
+ + str(list_el["acl"])
+ )
+ return command
+
+
+def _tmplt_bgp_af_neighbor_route_map(config_data):
+ command = []
+ afi = config_data["neighbors"]["address_family"]["afi"] + "-unicast"
+ cmd = "protocols bgp {as_number} neighbor ".format(**config_data)
+ cmd += "{neighbor_address} address-family ".format(
+ **config_data["neighbors"]
+ )
+ config_data = config_data["neighbors"]["address_family"]
+ for list_el in config_data["route_map"]:
+ command.append(
+ cmd
+ + afi
+ + " route-map "
+ + list_el["action"]
+ + " "
+ + str(list_el["route_map"])
+ )
+ return command
+
+
+def _tmplt_bgp_af_neighbor_prefix_list(config_data):
+ command = []
+ afi = config_data["neighbors"]["address_family"]["afi"] + "-unicast"
+ cmd = "protocols bgp {as_number} neighbor ".format(**config_data)
+ cmd += "{neighbor_address} address-family ".format(
+ **config_data["neighbors"]
+ )
+ config_data = config_data["neighbors"]["address_family"]
+ for list_el in config_data["prefix_list"]:
+ command.append(
+ cmd
+ + afi
+ + " prefix-list "
+ + list_el["action"]
+ + " "
+ + str(list_el["prefix_list"])
+ )
+ return command
+
+
+def _tmplt_bgp_af_neighbor_filter_list(config_data):
+ command = []
+ afi = config_data["neighbors"]["address_family"]["afi"] + "-unicast"
+ cmd = "protocols bgp {as_number} neighbor ".format(**config_data)
+ cmd += "{neighbor_address} address-family ".format(
+ **config_data["neighbors"]
+ )
+ config_data = config_data["neighbors"]["address_family"]
+ for list_el in config_data["filter_list"]:
+ command.append(
+ cmd
+ + afi
+ + " filter-list "
+ + list_el["action"]
+ + " "
+ + str(list_el["path_list"])
+ )
+ return command
+
+
+def _tmplt_bgp_af_neighbor_attribute(config_data):
+ command = []
+ afi = config_data["neighbors"]["address_family"]["afi"] + "-unicast"
+ cmd = "protocols bgp {as_number} neighbor ".format(**config_data)
+ cmd += "{neighbor_address} address-family ".format(
+ **config_data["neighbors"]
+ )
+ config_data = config_data["neighbors"]["address_family"]
+ for k in config_data["attribute_unchanged"].keys():
+ if config_data["attribute_unchanged"][k]:
+ k = re.sub("_", "-", k)
+ c = cmd + afi + " attribute-unchanged " + k
+ command.append(c)
+ return command
+
+
+def _tmplt_bgp_af_neighbor_delete(config_data):
+ afi = config_data["neighbors"]["address_family"]["afi"] + "-unicast"
+ command = "protocols bgp {as_number} ".format(**config_data)
+ command += (
+ "neighbor {neighbor_address} address-family ".format(
+ **config_data["neighbors"]
+ )
+ + afi
+ )
+ config_data = config_data["neighbors"]["address_family"]
+ if config_data.get("allowas_in"):
+ command += " allowas-in"
+ elif config_data.get("as_override"):
+ command += " as-override"
+ elif config_data.get("attribute_unchanged"):
+ command += " attribute-unchanged"
+ elif config_data.get("capability"):
+ command += " capability"
+ elif config_data.get("default_originate"):
+ command += " default-originate"
+ elif config_data.get("maximum_prefix"):
+ command += " maximum-prefix"
+ elif config_data.get("nexthop_local"):
+ command += " nexthop-local"
+ elif config_data.get("nexthop_self"):
+ command += " nexthop-self"
+ elif config_data.get("peer_group"):
+ command += " peer-group"
+ elif config_data.get("remote_private_as"):
+ command += " remote-private-as"
+ elif config_data.get("route_reflector_client"):
+ command += " route-reflector-client"
+ elif config_data.get("route_server_client"):
+ command += " route-server-client"
+ elif config_data.get("soft_reconfiguration"):
+ command += " soft-reconfiguration"
+ elif config_data.get("unsuppress_map"):
+ command += " unsuppress-map"
+ elif config_data.get("weight"):
+ command += " weight"
+ elif config_data.get("filter_list"):
+ command += " filter-list"
+ elif config_data.get("prefix_list"):
+ command += " prefix-list"
+ elif config_data.get("distribute_list"):
+ command += " distribute-list"
+ elif config_data.get("route_map"):
+ command += " route-map"
+ return command
+
+
+def _tmplt_bgp_af_neighbor(config_data):
+ afi = config_data["neighbors"]["address_family"]["afi"] + "-unicast"
+ command = "protocols bgp {as_number} ".format(**config_data)
+ command += (
+ "neighbor {neighbor_address} address-family ".format(
+ **config_data["neighbors"]
+ )
+ + afi
+ )
+ config_data = config_data["neighbors"]["address_family"]
+ if config_data.get("allowas_in"):
+ command += " allowas-in number {allowas_in}".format(**config_data)
+ elif config_data.get("as_override"):
+ command += " as-override"
+ elif config_data.get("capability"):
+ command += " capability "
+ if config_data["capability"].get("dynamic"):
+ command += "dynamic"
+ elif config_data["capability"].get("orf"):
+ command += " prefix-list {orf}".format(**config_data["capability"])
+ elif config_data.get("default_originate"):
+ command += " default-originate route-map {default_originate}".format(
+ **config_data
+ )
+ elif config_data.get("maximum_prefix"):
+ command += " maximum-prefix {maximum_prefix}".format(**config_data)
+ elif config_data.get("nexthop_local"):
+ command += " nexthop-local"
+ elif config_data.get("nexthop_self"):
+ command += " nexthop-self"
+ elif config_data.get("peer_group"):
+ command += " peer-group {peer_group}".format(**config_data)
+ elif config_data.get("remote_private_as"):
+ command += " remote-private-as"
+ elif config_data.get("route_reflector_client"):
+ command += " route-reflector-client"
+ elif config_data.get("route_server_client"):
+ command += " route-server-client"
+ elif config_data.get("soft_reconfiguration"):
+ command += " soft-reconfiguration inbound"
+ elif config_data.get("unsuppress_map"):
+ command += " unsuppress-map {unsuppress_map}".format(**config_data)
+ elif config_data.get("weight"):
+ command += " weight {weight}".format(**config_data)
+ return command
+
+
+class Bgp_address_familyTemplate(NetworkTemplate):
+ def __init__(self, lines=None):
+ prefix = {"set": "set", "remove": "delete"}
+ super(Bgp_address_familyTemplate, self).__init__(
+ lines=lines, tmplt=self, prefix=prefix
+ )
+
+ # fmt: off
+ PARSERS = [
+ {
+ "name": "address_family",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+(?P<as_num>\d+)
+ \s+address-family
+ \s+(?P<afi>\S+)-unicast
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": "protocols bgp {{ as_number }} address-family {{ address_family.afi }}-unicast",
+ "compval": "as_number",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ }
+ }
+ }
+ },
+ {
+ "name": "aggregate_address",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+(?P<as_num>\d+)
+ \s+address-family
+ \s+(?P<afi>\S+)-unicast
+ \s+aggregate-address
+ \s+(?P<address>\S+)
+ \s*(?P<as_set>as-set)*
+ \s*(?P<summary_only>summary-only)*
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_bgp_af_aggregate_address,
+ "remval": "protocols bgp {{ as_number }} address-family {{ address_family.afi }}-unicast aggregate-address" +
+ " {{ address_family.aggregate_address.prefix }}",
+ "compval": "address_family.aggregate_address",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "aggregate_address": [
+ {
+ "prefix": "{{ address }}",
+ "as_set": "{{ True if as_set is defined }}",
+ "summary_only": "{{ True if summary_only is defined }}"
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "name": "network.backdoor",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+(?P<as_num>\d+)
+ \s+address-family
+ \s+(?P<afi>\S+)-unicast
+ \s+network
+ \s+(?P<address>\S+)
+ \s+backdoor
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": "protocols bgp {{ as_number }} address-family {{ address_family.afi }}-unicast network {{ address_family.networks.prefix }} backdoor",
+ "remval": "protocols bgp {{ as_number }} address-family {{ address_family.afi }}-unicast network {{ address_family.networks.prefix }}",
+ "compval": "address_family.networks.backdoor",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "networks": [
+ {
+ "prefix": "{{ address }}",
+ "backdoor": "{{ True }}"
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "name": "network.path_limit",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+(?P<as_num>\d+)
+ \s+address-family
+ \s+(?P<afi>\S+)-unicast
+ \s+network
+ \s+(?P<address>\S+)
+ \s+path-limit
+ \s+(?P<limit>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": "protocols bgp {{ as_number }} address-family {{ address_family.afi }}-unicast network" +
+ "{{ address_family.networks.prefix }} path-limit {{ address_family.networks.path_limit }}",
+ "remval": "protocols bgp {{ as_number }} address-family {{ address_family.afi }}-unicast network {{ address_family.networks.address }}",
+ "compval": "address_family.networks.path_limit",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "networks": [
+ {
+ "prefix": "{{ address }}",
+ "path_limit": "{{ limit|int }}"
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "name": "network.route_map",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+(?P<as_num>\d+)
+ \s+address-family
+ \s+(?P<afi>\S+)-unicast
+ \s+network
+ \s+(?P<address>\S+)
+ \s+route-map
+ \s+(?P<map>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": "protocols bgp {{ as_number }} address-family {{ address_family.afi }}-unicast network" +
+ " {{ address_family.networks.prefix }} route-map {{ address_family.networks.route_map }}",
+ "remval": "protocols bgp {{ as_number }} address-family {{ address_family.afi }}-unicast network {{ address_family.networks.prefix }}",
+ "compval": "address_family.networks.route_map",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "networks": [
+ {
+ "prefix": "{{ address }}",
+ "route_map": "{{ map }}"
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "name": "redistribute.metric",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+(?P<as_num>\d+)
+ \s+address-family
+ \s+(?P<afi>\S+)-unicast
+ \s+redistribute
+ \s+(?P<proto>\S+)
+ \s+metric
+ \s+(?P<val>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_bgp_af_redistribute_metric,
+ "remval": _tmplt_bgp_af_delete_redistribute,
+ "compval": "address_family.redistribute.metric",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "redistribute": [
+ {
+ "protocol": "{{ proto }}",
+ "metric": "{{ val|int }}"
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "name": "redistribute.route_map",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+(?P<as_num>\d+)
+ \s+address-family
+ \s+(?P<afi>\S+)-unicast
+ \s+redistribute
+ \s+(?P<proto>\S+)
+ \s+route-map
+ \s+(?P<map>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_bgp_af_redistribute_route_map,
+ "remval": _tmplt_bgp_af_delete_redistribute,
+ "compval": "address_family.redistribute.route_map",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "redistribute": [
+ {
+ "protocol": "{{ proto }}",
+ "route_map": "{{ map }}"
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "name": "redistribute.table",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+(?P<as_num>\d+)
+ \s+address-family
+ \s+(?P<afi>\S+)-unicast
+ \s+redistribute
+ \s+table
+ \s+(?P<tab>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_bgp_af_redistribute_table,
+ "remval": _tmplt_bgp_af_delete_redistribute,
+ "compval": "address_family.redistribute.table",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "redistribute": [
+ {
+ "table": "{{ tab }}"
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "name": "neighbors",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+(?P<as_num>\d+)
+ \s+neighbor
+ \s+(?P<address>\S+)
+ \s+address-family
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": "protocols bgp {{ as_number }} neighbor {{ neighbors.neighbor_address }} address-family",
+ "compval": "neighbors",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "neighbors": {
+ "{{ address }}": {
+ "neighbor_address": "{{ address }}",
+ }
+ }
+ }
+ },
+ {
+ "name": "neighbors.address_family",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+(?P<as_num>\d+)
+ \s+neighbor
+ \s+(?P<address>\S+)
+ \s+address-family
+ \s+(?P<afi>\S+)-unicast
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": "protocols bgp {{ as_number }} neighbor {{ neighbors.neighbor_address }} address-family {{ neighbors.address_family.afi }}-unicast",
+ "compval": "neighbors",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "neighbors": {
+ "{{ address }}": {
+ "neighbor_address": "{{ address }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "neighbors.allowas_in",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+(?P<as_num>\d+)
+ \s+neighbor
+ \s+(?P<address>\S+)
+ \s+address-family
+ \s+(?P<afi>\S+)-unicast
+ \s+allowas-in
+ \s+number
+ \s+(?P<num>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_bgp_af_neighbor,
+ "remval": _tmplt_bgp_af_neighbor_delete,
+ "compval": "neighbors.address_family.allowas_in",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "neighbors": {
+ "{{ address }}": {
+ "neighbor_address": "{{ address }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "allowas_in": "{{ num }}"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "neighbors.as_override",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+(?P<as_num>\d+)
+ \s+neighbor
+ \s+(?P<address>\S+)
+ \s+address-family
+ \s+(?P<afi>\S+)-unicast
+ \s+as-override
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_bgp_af_neighbor,
+ "remval": _tmplt_bgp_af_neighbor_delete,
+ "compval": "neighbors.address_family.as_override",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "neighbors": {
+ "{{ address }}": {
+ "neighbor_address": "{{ address }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "as_override": "{{ True }}"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "neighbors.attribute_unchanged.as_path",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+(?P<as_num>\d+)
+ \s+neighbor
+ \s+(?P<address>\S+)
+ \s+address-family
+ \s+(?P<afi>\S+)-unicast
+ \s+attribute-unchanged
+ \s+(?P<val>as-path)
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_bgp_af_neighbor_attribute,
+ "remval": _tmplt_bgp_af_neighbor_delete,
+ "compval": "neighbors.address_family.attribute_unchanged.as_path",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "neighbors": {
+ "{{ address }}": {
+ "neighbor_address": "{{ address }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "attribute_unchanged": {
+ "as_path": "{{ True }}"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "neighbors.attribute_unchanged.med",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+(?P<as_num>\d+)
+ \s+neighbor
+ \s+(?P<address>\S+)
+ \s+address-family
+ \s+(?P<afi>\S+)-unicast
+ \s+attribute-unchanged
+ \s+(?P<val>med)
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_bgp_af_neighbor_attribute,
+ "remval": _tmplt_bgp_af_neighbor_delete,
+ "compval": "neighbors.address_family.attribute_unchanged.med",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "neighbors": {
+ "{{ address }}": {
+ "neighbor_address": "{{ address }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "attribute_unchanged": {
+ "med": "{{ True }}"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "neighbors.attribute_unchanged.next_hop",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+(?P<as_num>\d+)
+ \s+neighbor
+ \s+(?P<address>\S+)
+ \s+address-family
+ \s+(?P<afi>\S+)-unicast
+ \s+attribute-unchanged
+ \s+(?P<val>next-hop)
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_bgp_af_neighbor_attribute,
+ "remval": _tmplt_bgp_af_neighbor_delete,
+ "compval": "neighbors.address_family.attribute_unchanged.next_hop",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "neighbors": {
+ "{{ address }}": {
+ "neighbor_address": "{{ address }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "attribute_unchanged": {
+ "next_hop": "{{ True }}"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "neighbors.capability_dynamic",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+(?P<as_num>\d+)
+ \s+neighbor
+ \s+(?P<address>\S+)
+ \s+address-family
+ \s+(?P<afi>\S+)-unicast
+ \s+capability
+ \s+dynamic
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_bgp_af_neighbor,
+ "remval": _tmplt_bgp_af_neighbor_delete,
+ "compval": "neighbors.address_family.capability.dynamic",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "neighbors": {
+ "{{ address }}": {
+ "neighbor_address": "{{ address }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "capability": {
+ "dynamic": "{{ true }}"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "neighbors.capability_orf",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+(?P<as_num>\d+)
+ \s+neighbor
+ \s+(?P<address>\S+)
+ \s+address-family
+ \s+(?P<afi>\S+)-unicast
+ \s+capability
+ \s+prefix-list
+ \s+(?P<orf>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_bgp_af_neighbor,
+ "remval": _tmplt_bgp_af_neighbor_delete,
+ "compval": "neighbors.address_family.capability.orf",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "neighbors": {
+ "{{ address }}": {
+ "neighbor_address": "{{ address }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "capability": {
+ "orf": "{{ orf }}"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "neighbors.default_originate",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+(?P<as_num>\d+)
+ \s+neighbor
+ \s+(?P<address>\S+)
+ \s+address-family
+ \s+(?P<afi>\S+)-unicast
+ \s+default-originate
+ \s+route-map
+ \s+(?P<map>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_bgp_af_neighbor,
+ "remval": _tmplt_bgp_af_neighbor_delete,
+ "compval": "neighbors.address_family.default_originate",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "neighbors": {
+ "{{ address }}": {
+ "neighbor_address": "{{ address }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "default_originate": "{{ map }}"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "neighbors.distribute_list",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+(?P<as_num>\d+)
+ \s+neighbor
+ \s+(?P<address>\S+)
+ \s+address-family
+ \s+(?P<afi>\S+)-unicast
+ \s+distribute-list
+ \s+(?P<action>export|import)
+ \s+(?P<list>\d+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_bgp_af_neighbor_distribute_list,
+ "remval": _tmplt_bgp_af_neighbor_delete,
+ "compval": "neighbors.address_family.distribute_list",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "neighbors": {
+ "{{ address }}": {
+ "neighbor_address": "{{ address }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "distribute_list": [
+ {
+ "action": "{{ action }}",
+ "acl": "{{ list }}"
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "neighbors.prefix_list",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+(?P<as_num>\d+)
+ \s+neighbor
+ \s+(?P<address>\S+)
+ \s+address-family
+ \s+(?P<afi>\S+)-unicast
+ \s+prefix-list
+ \s+(?P<action>export|import)
+ \s+(?P<list>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_bgp_af_neighbor_prefix_list,
+ "remval": _tmplt_bgp_af_neighbor_delete,
+ "compval": "neighbors.address_family.prefix_list",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "neighbors": {
+ "{{ address }}": {
+ "neighbor_address": "{{ address }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "prefix_list": [
+ {
+ "action": "{{ action }}",
+ "prefix_list": "{{ list }}"
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "neighbors.filter_list",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+(?P<as_num>\d+)
+ \s+neighbor
+ \s+(?P<address>\S+)
+ \s+address-family
+ \s+(?P<afi>\S+)-unicast
+ \s+filter-list
+ \s+(?P<action>export|import)
+ \s+(?P<list>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_bgp_af_neighbor_filter_list,
+ "remval": _tmplt_bgp_af_neighbor_delete,
+ "compval": "neighbors.address_family.filter_list",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "neighbors": {
+ "{{ address }}": {
+ "neighbor_address": "{{ address }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "filter_list": [
+ {
+ "action": "{{ action }}",
+ "path_list": "{{ list }}"
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "neighbors.maximum_prefix",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+(?P<as_num>\d+)
+ \s+neighbor
+ \s+(?P<address>\S+)
+ \s+address-family
+ \s+(?P<afi>\S+)-unicast
+ \s+maximum-prefix
+ \s+(?P<num>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_bgp_af_neighbor,
+ "remval": _tmplt_bgp_af_neighbor_delete,
+ "compval": "neighbors.address_family.maximum_prefix",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "neighbors": {
+ "{{ address }}": {
+ "neighbor_address": "{{ address }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "maximum_prefix": "{{ num }}"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "neighbors.nexthop_local",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+(?P<as_num>\d+)
+ \s+neighbor
+ \s+(?P<address>\S+)
+ \s+address-family
+ \s+(?P<afi>\S+)-unicast
+ \s+nexthop-local
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_bgp_af_neighbor,
+ "remval": _tmplt_bgp_af_neighbor_delete,
+ "compval": "neighbors.address_family.nexthop_local",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "neighbors": {
+ "{{ address }}": {
+ "neighbor_address": "{{ address }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "nexthop_local": "{{ True }}"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "neighbors.nexthop_self",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+(?P<as_num>\d+)
+ \s+neighbor
+ \s+(?P<address>\S+)
+ \s+address-family
+ \s+(?P<afi>\S+)-unicast
+ \s+nexthop-self
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_bgp_af_neighbor,
+ "remval": _tmplt_bgp_af_neighbor_delete,
+ "compval": "neighbors.address_family.nexthop_self",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "neighbors": {
+ "{{ address }}": {
+ "neighbor_address": "{{ address }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "nexthop_self": "{{ True }}"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "neighbors.peer_group",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+(?P<as_num>\d+)
+ \s+neighbor
+ \s+(?P<address>\S+)
+ \s+address-family
+ \s+(?P<afi>\S+)-unicast
+ \s+peer-group
+ \s+(?P<name>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_bgp_af_neighbor,
+ "remval": _tmplt_bgp_af_neighbor_delete,
+ "compval": "neighbors.address_family.peer_group",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "neighbors": {
+ "{{ address }}": {
+ "neighbor_address": "{{ address }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "peer_group": "{{ name }}"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "neighbors.remove_private_as",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+(?P<as_num>\d+)
+ \s+neighbor
+ \s+(?P<address>\S+)
+ \s+address-family
+ \s+(?P<afi>\S+)-unicast
+ \s+remove-private-as
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_bgp_af_neighbor,
+ "remval": _tmplt_bgp_af_neighbor_delete,
+ "compval": "neighbors.address_family.remove_private_as",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "neighbors": {
+ "{{ address }}": {
+ "neighbor_address": "{{ address }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "remove_private_as": "{{ True }}"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "neighbors.route_map",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+(?P<as_num>\d+)
+ \s+neighbor
+ \s+(?P<address>\S+)
+ \s+address-family
+ \s+(?P<afi>\S+)-unicast
+ \s+route-map
+ \s+(?P<action>export|import)
+ \s+(?P<map>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_bgp_af_neighbor_route_map,
+ "remval": _tmplt_bgp_af_neighbor_delete,
+ "compval": "neighbors.address_family.route_map",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "neighbors": {
+ "{{ address }}": {
+ "neighbor_address": "{{ address }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "route_map": [
+ {
+ "action": "{{ action }}",
+ "route_map": "{{ map }}"
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "neighbors.route_reflector_client",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+(?P<as_num>\d+)
+ \s+neighbor
+ \s+(?P<address>\S+)
+ \s+address-family
+ \s+(?P<afi>\S+)-unicast
+ \s+route-reflector-client
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_bgp_af_neighbor,
+ "remval": _tmplt_bgp_af_neighbor_delete,
+ "compval": "neighbors.address_family.route_reflector_client",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "neighbors": {
+ "{{ address }}": {
+ "neighbor_address": "{{ address }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "route_reflector_client": "{{ True }}"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "neighbors.route_server_client",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+(?P<as_num>\d+)
+ \s+neighbor
+ \s+(?P<address>\S+)
+ \s+address-family
+ \s+(?P<afi>\S+)-unicast
+ \s+route-server-client
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_bgp_af_neighbor,
+ "remval": _tmplt_bgp_af_neighbor_delete,
+ "compval": "neighbors.address_family.route_server_client",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "neighbors": {
+ "{{ address }}": {
+ "neighbor_address": "{{ address }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "route_server_client": "{{ True }}"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "neighbors.soft_reconfiguration",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+(?P<as_num>\d+)
+ \s+neighbor
+ \s+(?P<address>\S+)
+ \s+address-family
+ \s+(?P<afi>\S+)-unicast
+ \s+soft-reconfiguration
+ \s+inbound
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_bgp_af_neighbor,
+ "remval": _tmplt_bgp_af_neighbor_delete,
+ "compval": "neighbors.address_family.soft_reconfiguration",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "neighbors": {
+ "{{ address }}": {
+ "neighbor_address": "{{ address }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "soft_reconfiguration": "{{ True }}"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "neighbors.unsuppress_map",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+(?P<as_num>\d+)
+ \s+neighbor
+ \s+(?P<address>\S+)
+ \s+address-family
+ \s+(?P<afi>\S+)-unicast
+ \s+unsuppress-map
+ \s+(?P<map>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_bgp_af_neighbor,
+ "remval": _tmplt_bgp_af_neighbor_delete,
+ "compval": "neighbors.address_family.unsuppress_map",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "neighbors": {
+ "{{ address }}": {
+ "neighbor_address": "{{ address }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "unsuppress_map": "{{ map }}"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "neighbors.weight",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+(?P<as_num>\d+)
+ \s+neighbor
+ \s+(?P<address>\S+)
+ \s+address-family
+ \s+(?P<afi>\S+)-unicast
+ \s+weight
+ \s+(?P<num>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_bgp_af_neighbor,
+ "remval": _tmplt_bgp_af_neighbor_delete,
+ "compval": "neighbors.address_family.weight",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "neighbors": {
+ "{{ address }}": {
+ "neighbor_address": "{{ address }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "weight": "{{ num }}"
+ }
+ }
+ }
+ }
+ }
+ },
+ ]
+ # fmt: on
diff --git a/plugins/modules/vyos_bgp_address_family.py b/plugins/modules/vyos_bgp_address_family.py
new file mode 100644
index 0000000..80c6807
--- /dev/null
+++ b/plugins/modules/vyos_bgp_address_family.py
@@ -0,0 +1,1192 @@
+#!/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)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+
+"""
+The module file for vyos_bgp_address_family
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+DOCUMENTATION = """
+module: vyos_bgp_address_family
+version_added: 2.1.0
+short_description: BGP Address Family Resource Module.
+description:
+- This module manages BGP address family configuration of interfaces on devices running VYOS.
+author: Gomathi Selvi Srinivasan (@GomathiselviS)
+options:
+ config:
+ description: A dict of BGP global configuration for interfaces.
+ type: dict
+ suboptions:
+ as_number:
+ description:
+ - AS number.
+ type: int
+ address_family:
+ description: BGP address-family parameters.
+ type: list
+ elements: dict
+ suboptions:
+ afi:
+ description: BGP address family settings.
+ type: str
+ choices: ['ipv4', 'ipv6']
+ aggregate_address:
+ description:
+ - BGP aggregate network.
+ type: list
+ elements: dict
+ suboptions:
+ prefix:
+ description: BGP aggregate network.
+ type: str
+ as_set:
+ description: Generate AS-set path information for this aggregate address.
+ type: bool
+ summary_only:
+ description: Announce the aggregate summary network only.
+ type: bool
+ networks:
+ description: BGP network
+ type: list
+ elements: dict
+ suboptions:
+ prefix:
+ description: BGP network address
+ type: str
+ path_limit:
+ description: AS path hop count limit
+ type: int
+ backdoor:
+ description: Network as a backdoor route.
+ type: bool
+ route_map:
+ description: Route-map to modify route attributes
+ type: str
+ redistribute:
+ description: Redistribute routes from other protocols into BGP
+ type: list
+ elements: dict
+ suboptions:
+ protocol:
+ description: types of routes to be redistributed.
+ type: str
+ choices: ['connected', 'kernel', 'ospf', 'ospfv3', 'rip', 'ripng', 'static']
+ table:
+ description: Redistribute non-main Kernel Routing Table.
+ type: str
+ route_map:
+ description: Route map to filter redistributed routes
+ type: str
+ metric:
+ description: Metric for redistributed routes.
+ type: int
+ neighbors:
+ description: BGP neighbor
+ type: list
+ elements: dict
+ suboptions:
+ neighbor_address:
+ description: BGP neighbor address (v4/v6).
+ type: str
+ address_family:
+ description: address family.
+ type: list
+ elements: dict
+ suboptions:
+ afi:
+ description: BGP neighbor parameters.
+ type: str
+ choices: ['ipv4', 'ipv6']
+ allowas_in:
+ description: Number of occurrences of AS number.
+ type: int
+ as_override:
+ description: AS for routes sent to this neighbor to be the local AS.
+ type: bool
+ attribute_unchanged:
+ description: BGP attributes are sent unchanged.
+ type: dict
+ suboptions:
+ as_path:
+ description: as_path attribute
+ type: bool
+ med:
+ description: med attribute
+ type: bool
+ next_hop:
+ description: next_hop attribute
+ type: bool
+ capability:
+ description: Advertise capabilities to this neighbor.
+ type: dict
+ suboptions:
+ dynamic:
+ description: Advertise dynamic capability to this neighbor.
+ type: bool
+ orf:
+ description: Advertise ORF capability to this neighbor.
+ type: str
+ choices: ['send', 'receive']
+ default_originate:
+ description: Send default route to this neighbor
+ type: str
+ distribute_list:
+ description: Access-list to filter route updates to/from this neighbor.
+ type: list
+ elements: dict
+ suboptions:
+ action:
+ description: Access-list to filter outgoing/incoming route updates to this neighbor
+ type: str
+ choices: ['export', 'import']
+ acl:
+ description: Acess-list number.
+ type: int
+ filter_list:
+ description: As-path-list to filter route updates to/from this neighbor.
+ type: list
+ elements: dict
+ suboptions:
+ action:
+ description: filter outgoing/incoming route updates
+ type: str
+ choices: ['export', 'import']
+ path_list:
+ description: As-path-list to filter
+ type: str
+ maximum_prefix:
+ description: Maximum number of prefixes to accept from this neighbor
+ nexthop-self Nexthop for routes sent to this neighbor to be the local router.
+ type: int
+ nexthop_local:
+ description: Nexthop attributes.
+ type: bool
+ nexthop_self:
+ description: Nexthop for routes sent to this neighbor to be the local router.
+ type: bool
+ peer_group:
+ description: IPv4 peer group for this peer
+ type: str
+ prefix_list:
+ description: Prefix-list to filter route updates to/from this neighbor.
+ type: list
+ elements: dict
+ suboptions:
+ action:
+ description: filter outgoing/incoming route updates
+ type: str
+ choices: ['export', 'import']
+ prefix_list:
+ description: Prefix-list to filter
+ type: str
+ remove_private_as:
+ description: Remove private AS numbers from AS path in outbound route updates
+ type: bool
+ route_map:
+ description: Route-map to filter route updates to/from this neighbor.
+ type: list
+ elements: dict
+ suboptions:
+ action:
+ description: filter outgoing/incoming route updates
+ type: str
+ choices: ['export', 'import']
+ route_map:
+ description: route-map to filter
+ type: str
+ route_reflector_client:
+ description: Neighbor as a route reflector client
+ type: bool
+ route_server_client:
+ description: Neighbor is route server client
+ type: bool
+ soft_reconfiguration:
+ description: Soft reconfiguration for neighbor
+ type: bool
+ unsupress_map:
+ description: Route-map to selectively unsuppress suppressed routes
+ type: str
+ weight:
+ description: Default weight for routes from this neighbor
+ type: int
+ running_config:
+ type: str
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the IOS device by
+ executing the command B(show configuration command | match bgp).
+ - The state I(parsed) reads the configuration from C(running_config) 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.
+ state:
+ description:
+ - The state the configuration should be left in.
+ type: str
+ choices:
+ - merged
+ - replaced
+ - deleted
+ - gathered
+ - parsed
+ - rendered
+ - purged
+ - overridden
+ default: merged
+"""
+EXAMPLES = """
+# Using merged
+# Before state
+# vyos@vyos:~$ show configuration commands | match "set protocols bgp"
+# vyos@vyos:~$
+
+ - name: Merge provided configuration with device configuration
+ vyos.vyos.vyos_bgp_address_family:
+ config:
+ as_number: "100"
+ address_family:
+ - afi: "ipv4"
+ redistribute:
+ - protocol: "static"
+ metric: 50
+ neighbors:
+ - neighbor_address: "20.33.1.1/24"
+ address_family:
+ - afi: "ipv4"
+ allowas_in: 4
+ as_override: True
+ attribute_unchanged:
+ med: True
+ - afi: "ipv6"
+ default_originate: "map01"
+ distribute_list:
+ - action: "export"
+ acl: 10
+ - neighbor_address: "100.11.34.12"
+ address_family:
+ - afi: "ipv4"
+ maximum_prefix: 45
+ nexthop_self: True
+ route_map:
+ - action: "export"
+ route_map: "map01"
+ - action: "import"
+ route_map: "map01"
+ weight: 50
+
+# After State:
+# vyos@vyos:~$ show configuration commands | match "set protocols bgp"
+# set protocols bgp 100 address-family ipv4-unicast redistribute static metric '50'
+# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number '4'
+# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast as-override
+# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med
+# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast default-originate route-map 'map01'
+# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast distribute-list export '10'
+# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast maximum-prefix '45'
+# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast nexthop-self
+# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast route-map export 'map01'
+# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast route-map import 'map01'
+# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast weight '50'
+# vyos@vyos:~$
+#
+# Module Execution:
+#
+# "after": {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "redistribute": [
+# {
+# "metric": 50,
+# "protocol": "static"
+# }
+# ]
+# }
+# ],
+# "as_number": 100,
+# "neighbors": [
+# {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "maximum_prefix": 45,
+# "nexthop_self": true,
+# "route_map": [
+# {
+# "action": "export",
+# "route_map": "map01"
+# },
+# {
+# "action": "import",
+# "route_map": "map01"
+# }
+# ],
+# "weight": 50
+# }
+# ],
+# "neighbor_address": "100.11.34.12"
+# },
+# {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "allowas_in": 4,
+# "as_override": true,
+# "attribute_unchanged": {
+# "med": true
+# }
+# },
+# {
+# "afi": "ipv6",
+# "default_originate": "map01",
+# "distribute_list": [
+# {
+# "acl": 10,
+# "action": "export"
+# }
+# ]
+# }
+# ],
+# "neighbor_address": "20.33.1.1/24"
+# }
+# ]
+# },
+# "before": {},
+# "changed": true,
+# "commands": [
+# "set protocols bgp 100 address-family ipv4-unicast redistribute static metric 50",
+# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number 4",
+# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast as-override",
+# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med",
+# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast default-originate route-map map01",
+# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast distribute-list export 10",
+# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast maximum-prefix 45",
+# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast nexthop-self",
+# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast route-map export map01",
+# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast route-map import map01",
+# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast weight 50"
+# ],
+#
+
+# Using replaced:
+
+# Before state:
+
+# vyos@vyos:~$ show configuration commands | match "set protocols bgp"
+# set protocols bgp 100 address-family ipv4-unicast redistribute static metric '50'
+# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number '4'
+# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast as-override
+# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med
+# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast default-originate route-map 'map01'
+# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast distribute-list export '10'
+# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast maximum-prefix '45'
+# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast nexthop-self
+# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast route-map export 'map01'
+# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast route-map import 'map01'
+# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast weight '50'
+# vyos@vyos:~$
+
+ - name: Replace provided configuration with device configuration
+ vyos.vyos.vyos_bgp_address_family:
+ config:
+ as_number: "100"
+ neighbors:
+ - neighbor_address: "100.11.34.12"
+ address_family:
+ - afi: "ipv4"
+ allowas_in: 4
+ as_override: True
+ attribute_unchanged:
+ med: True
+ - afi: "ipv6"
+ default_originate: "map01"
+ distribute_list:
+ - action: "export"
+ acl: 10
+ - neighbor_address: "20.33.1.1/24"
+ address_family:
+ - afi: "ipv6"
+ maximum_prefix: 45
+ nexthop_self: True
+
+ state: replaced
+
+# After State:
+
+# vyos@vyos:~$ show configuration commands | match "set protocols bgp"
+# set protocols bgp 100 address-family ipv4-unicast redistribute static metric '50'
+# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast
+# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast maximum-prefix '45'
+# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast nexthop-self
+# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast allowas-in number '4'
+# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast as-override
+# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast attribute-unchanged med
+# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast default-originate route-map 'map01'
+# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast distribute-list export '10'
+# vyos@vyos:~$
+#
+#
+# # Module Execution:
+# "after": {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "redistribute": [
+# {
+# "metric": 50,
+# "protocol": "static"
+# }
+# ]
+# }
+# ],
+# "as_number": 100,
+# "neighbors": [
+# {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "allowas_in": 4,
+# "as_override": true,
+# "attribute_unchanged": {
+# "med": true
+# }
+# },
+# {
+# "afi": "ipv6",
+# "default_originate": "map01",
+# "distribute_list": [
+# {
+# "acl": 10,
+# "action": "export"
+# }
+# ]
+# }
+# ],
+# "neighbor_address": "100.11.34.12"
+# },
+# {
+# "address_family": [
+# {
+# "afi": "ipv4"
+# },
+# {
+# "afi": "ipv6",
+# "maximum_prefix": 45,
+# "nexthop_self": true
+# }
+# ],
+# "neighbor_address": "20.33.1.1/24"
+# }
+# ]
+# },
+# "before": {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "redistribute": [
+# {
+# "metric": 50,
+# "protocol": "static"
+# }
+# ]
+# }
+# ],
+# "as_number": 100,
+# "neighbors": [
+# {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "maximum_prefix": 45,
+# "nexthop_self": true,
+# "route_map": [
+# {
+# "action": "export",
+# "route_map": "map01"
+# },
+# {
+# "action": "import",
+# "route_map": "map01"
+# }
+# ],
+# "weight": 50
+# }
+# ],
+# "neighbor_address": "100.11.34.12"
+# },
+# {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "allowas_in": 4,
+# "as_override": true,
+# "attribute_unchanged": {
+# "med": true
+# }
+# },
+# {
+# "afi": "ipv6",
+# "default_originate": "map01",
+# "distribute_list": [
+# {
+# "acl": 10,
+# "action": "export"
+# }
+# ]
+# }
+# ],
+# "neighbor_address": "20.33.1.1/24"
+# }
+# ]
+# },
+# "changed": true,
+# "commands": [
+# "delete protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast distribute-list",
+# "delete protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast default-originate",
+# "delete protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged",
+# "delete protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast as-override",
+# "delete protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in",
+# "delete protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast weight",
+# "delete protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast route-map",
+# "delete protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast nexthop-self",
+# "delete protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast maximum-prefix",
+# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast allowas-in number 4",
+# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast as-override",
+# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast attribute-unchanged med",
+# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast default-originate route-map map01",
+# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast distribute-list export 10",
+# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast maximum-prefix 45",
+# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast nexthop-self"
+# ],
+
+
+# Using overridden
+# vyos@vyos:~$ show configuration commands | match "set protocols bgp"
+# set protocols bgp 100 address-family ipv4-unicast network 35.1.1.0/24 backdoor
+# set protocols bgp 100 address-family ipv4-unicast redistribute static metric '50'
+# set protocols bgp 100 address-family ipv6-unicast aggregate-address 6601:1:1:1::/64 summary-only
+# set protocols bgp 100 address-family ipv6-unicast network 5001:1:1:1::/64 route-map 'map01'
+# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast
+# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast maximum-prefix '45'
+# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast nexthop-self
+# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast allowas-in number '4'
+# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast as-override
+# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast attribute-unchanged med
+# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast default-originate route-map 'map01'
+# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast distribute-list export '10'
+# vyos@vyos:~$
+
+ - name: Override
+ vyos.vyos.vyos_bgp_address_family:
+ config:
+ as_number: "100"
+ neighbors:
+ - neighbor_address: "100.11.34.12"
+ address_family:
+ - afi: "ipv6"
+ maximum_prefix: 45
+ nexthop_self: True
+ route_map:
+ - action: "import"
+ route_map: "map01"
+ address_family:
+ - afi: "ipv4"
+ aggregate_address:
+ - prefix: "60.9.2.0/24"
+ summary_only: True
+ - afi: "ipv6"
+ redistribute:
+ - protocol: "static"
+ metric: 50
+ state: overridden
+
+# Aft=validate-moduleser State
+
+# vyos@vyos:~$ show configuration commands | match "set protocols bgp"
+# set protocols bgp 100 address-family ipv4-unicast aggregate-address 60.9.2.0/24 summary-only
+# set protocols bgp 100 address-family ipv6-unicast redistribute static metric '50'
+# set protocols bgp 100 neighbor 20.33.1.1/24
+# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast
+# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast maximum-prefix '45'
+# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast nexthop-self
+# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast route-map import 'map01'
+# vyos@vyos:~$
+
+
+# Module Execution:
+
+# "after": {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "aggregate_address": [
+# {
+# "prefix": "60.9.2.0/24",
+# "summary_only": true
+# }
+# ]
+# },
+# {
+# "afi": "ipv6",
+# "redistribute": [
+# {
+# "metric": 50,
+# "protocol": "static"
+# }
+# ]
+# }
+# ],
+# "as_number": 100,
+# "neighbors": [
+# {
+# "address_family": [
+# {
+# "afi": "ipv4"
+# },
+# {
+# "afi": "ipv6",
+# "maximum_prefix": 45,
+# "nexthop_self": true,
+# "route_map": [
+# {
+# "action": "import",
+# "route_map": "map01"
+# }
+# ]
+# }
+# ],
+# "neighbor_address": "100.11.34.12"
+# }
+# ]
+# },
+# "before": {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "networks": [
+# {
+# "backdoor": true,
+# "prefix": "35.1.1.0/24"
+# }
+# ],
+# "redistribute": [
+# {
+# "metric": 50,
+# "protocol": "static"
+# }
+# ]
+# },
+# {
+# "afi": "ipv6",
+# "aggregate_address": [
+# {
+# "prefix": "6601:1:1:1::/64",
+# "summary_only": true
+# }
+# ],
+# "networks": [
+# {
+# "prefix": "5001:1:1:1::/64",
+# "route_map": "map01"
+# }
+# ]
+# }
+# ],
+# "as_number": 100,
+# "neighbors": [
+# {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "allowas_in": 4,
+# "as_override": true,
+# "attribute_unchanged": {
+# "med": true
+# }
+# },
+# {
+# "afi": "ipv6",
+# "default_originate": "map01",
+# "distribute_list": [
+# {
+# "acl": 10,
+# "action": "export"
+# }
+# ]
+# }
+# ],
+# "neighbor_address": "100.11.34.12"
+# },
+# {
+# "address_family": [
+# {
+# "afi": "ipv4"
+# },
+# {
+# "afi": "ipv6",
+# "maximum_prefix": 45,
+# "nexthop_self": true
+# }
+# ],
+# "neighbor_address": "20.33.1.1/24"
+# }
+# ]
+# },
+# "changed": true,
+# "commands": [
+# "delete protocols bgp 100 neighbor 20.33.1.1/24 address-family",
+# "delete protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast distribute-list",
+# "delete protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast default-originate",
+# "delete protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast attribute-unchanged",
+# "delete protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast as-override",
+# "delete protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast allowas-in",
+# "delete protocols bgp 100 address-family ipv6 aggregate-address",
+# "delete protocols bgp 100 address-family ipv6 network",
+# "delete protocols bgp 100 address-family ipv4 network",
+# "delete protocols bgp 100 address-family ipv4 redistribute",
+# "set protocols bgp 100 address-family ipv4-unicast aggregate-address 60.9.2.0/24 summary-only",
+# "set protocols bgp 100 address-family ipv6-unicast redistribute static metric 50",
+# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast maximum-prefix 45",
+# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast nexthop-self",
+# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast route-map import map01"
+# ],
+#
+
+# Using deleted:
+
+# Before State:
+
+# vyos@vyos:~$ show configuration commands | match "set protocols bgp"
+# set protocols bgp 100 address-family ipv4-unicast aggregate-address 60.9.2.0/24 summary-only
+# set protocols bgp 100 address-family ipv4-unicast redistribute static metric '50'
+# set protocols bgp 100 address-family ipv6-unicast redistribute static metric '50'
+# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number '4'
+# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast as-override
+# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med
+# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast default-originate route-map 'map01'
+# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast distribute-list export '10'
+# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast maximum-prefix '45'
+# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast nexthop-self
+# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast route-map export 'map01'
+# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast route-map import 'map01'
+# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast weight '50'
+# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast maximum-prefix '45'
+# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast nexthop-self
+# set protocols bgp 100 neighbor 100.11.34.12 address-family ipv6-unicast route-map import 'map01'
+# vyos@vyos:~$
+
+ - name: Delete
+ vyos.vyos.vyos_bgp_address_family:
+ config:
+ as_number: "100"
+ neighbors:
+ - neighbor_address: "20.33.1.1/24"
+ address_family:
+ - afi: "ipv6"
+ - neighbor_address: "100.11.34.12"
+ address_family:
+ - afi: "ipv4"
+ state: deleted
+
+
+# After State:
+
+# vyos@vyos:~$ show configuration commands | match "set protocols bgp"
+# set protocols bgp 100 address-family ipv6-unicast redistribute static metric '50'
+# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number '4'
+# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast as-override
+# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med
+# set protocols bgp 100 neighbor 100.11.34.12
+# vyos@vyos:~$
+#
+#
+# Module Execution:
+#
+# "after": {
+# "address_family": [
+# {
+# "afi": "ipv6",
+# "redistribute": [
+# {
+# "metric": 50,
+# "protocol": "static"
+# }
+# ]
+# }
+# ],
+# "as_number": 100,
+# "neighbors": [
+# {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "allowas_in": 4,
+# "as_override": true,
+# "attribute_unchanged": {
+# "med": true
+# }
+# }
+# ],
+# "neighbor_address": "20.33.1.1/24"
+# }
+# ]
+# },
+# "before": {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "aggregate_address": [
+# {
+# "prefix": "60.9.2.0/24",
+# "summary_only": true
+# }
+# ],
+# "redistribute": [
+# {
+# "metric": 50,
+# "protocol": "static"
+# }
+# ]
+# },
+# {
+# "afi": "ipv6",
+# "redistribute": [
+# {
+# "metric": 50,
+# "protocol": "static"
+# }
+# ]
+# }
+# ],
+# "as_number": 100,
+# "neighbors": [
+# {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "maximum_prefix": 45,
+# "nexthop_self": true,
+# "route_map": [
+# {
+# "action": "export",
+# "route_map": "map01"
+# },
+# {
+# "action": "import",
+# "route_map": "map01"
+# }
+# ],
+# "weight": 50
+# },
+# {
+# "afi": "ipv6",
+# "maximum_prefix": 45,
+# "nexthop_self": true,
+# "route_map": [
+# {
+# "action": "import",
+# "route_map": "map01"
+# }
+# ]
+# }
+# ],
+# "neighbor_address": "100.11.34.12"
+# },
+# {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "allowas_in": 4,
+# "as_override": true,
+# "attribute_unchanged": {
+# "med": true
+# }
+# },
+# {
+# "afi": "ipv6",
+# "default_originate": "map01",
+# "distribute_list": [
+# {
+# "acl": 10,
+# "action": "export"
+# }
+# ]
+# }
+# ],
+# "neighbor_address": "20.33.1.1/24"
+# }
+# ]
+# },
+# "changed": true,
+# "commands": [
+# "delete protocols bgp 100 address-family ipv4-unicast",
+# "delete protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast",
+# "delete protocols bgp 100 neighbor 100.11.34.12 address-family"
+# ],
+#
+
+# using parsed:
+
+# parsed.cfg
+# set protocols bgp 65536 address-family ipv4-unicast aggregate-address 192.0.2.0/24 as-set
+# set protocols bgp 65536 address-family ipv4-unicast network 192.1.13.0/24 route-map 'map01'
+# set protocols bgp 65536 address-family ipv4-unicast network 192.2.13.0/24 backdoor
+# set protocols bgp 65536 address-family ipv6-unicast redistribute ripng metric '20'
+# set protocols bgp 65536 neighbor 192.0.2.25 address-family ipv4-unicast route-map export 'map01'
+# set protocols bgp 65536 neighbor 192.0.2.25 address-family ipv4-unicast soft-reconfiguration inbound
+# set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast attribute-unchanged next-hop
+
+
+ - name: parse configs
+ vyos.vyos.vyos_bgp_address_family:
+ running_config: "{{ lookup('file', './parsed.cfg') }}"
+ state: parsed
+
+# Module Execution:
+# "parsed": {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "aggregate_address": [
+# {
+# "as_set": true,
+# "prefix": "192.0.2.0/24"
+# }
+# ],
+# "networks": [
+# {
+# "prefix": "192.1.13.0/24",
+# "route_map": "map01"
+# },
+# {
+# "backdoor": true,
+# "prefix": "192.2.13.0/24"
+# }
+# ]
+# },
+# {
+# "afi": "ipv6",
+# "redistribute": [
+# {
+# "metric": 20,
+# "protocol": "ripng"
+# }
+# ]
+# }
+# ],
+# "as_number": 65536,
+# "neighbors": [
+# {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "route_map": [
+# {
+# "action": "export",
+# "route_map": "map01"
+# }
+# ],
+# "soft_reconfiguration": true
+# }
+# ],
+# "neighbor_address": "192.0.2.25"
+# },
+# {
+# "address_family": [
+# {
+# "afi": "ipv6",
+# "attribute_unchanged": {
+# "next_hop": true
+# }
+# }
+# ],
+# "neighbor_address": "203.0.113.5"
+# }
+# ]
+#
+
+# Using gathered:
+
+# Native config:
+
+# vyos@vyos:~$ show configuration commands | match "set protocols bgp"
+# set protocols bgp 100 address-family ipv4-unicast network 35.1.1.0/24 backdoor
+# set protocols bgp 100 address-family ipv4-unicast redistribute static metric '50'
+# set protocols bgp 100 address-family ipv6-unicast aggregate-address 6601:1:1:1::/64 summary-only
+# set protocols bgp 100 address-family ipv6-unicast network 5001:1:1:1::/64 route-map 'map01'
+# set protocols bgp 100 address-family ipv6-unicast redistribute static metric '50'
+# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number '4'
+# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast as-override
+# set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med
+# set protocols bgp 100 neighbor 100.11.34.12
+
+ - name: gather configs
+ vyos.vyos.vyos_bgp_address_family:
+ state: gathered
+
+# Module Execution:
+
+# "gathered": {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "networks": [
+# {
+# "backdoor": true,
+# "prefix": "35.1.1.0/24"
+# }
+# ],
+# "redistribute": [
+# {
+# "metric": 50,
+# "protocol": "static"
+# }
+# ]
+# },
+# {
+# "afi": "ipv6",
+# "aggregate_address": [
+# {
+# "prefix": "6601:1:1:1::/64",
+# "summary_only": true
+# }
+# ],
+# "networks": [
+# {
+# "prefix": "5001:1:1:1::/64",
+# "route_map": "map01"
+# }
+# ],
+# "redistribute": [
+# {
+# "metric": 50,
+# "protocol": "static"
+# }
+# ]
+# }
+# ],
+# "as_number": 100,
+# "neighbors": [
+# {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "allowas_in": 4,
+# "as_override": true,
+# "attribute_unchanged": {
+# "med": true
+# }
+# }
+# ],
+# "neighbor_address": "20.33.1.1/24"
+# }
+# ]
+
+# Using rendered:
+
+ - name: Render
+ vyos.vyos.vyos_bgp_address_family:
+ config:
+ as_number: "100"
+ address_family:
+ - afi: "ipv4"
+ redistribute:
+ - protocol: "static"
+ metric: 50
+ neighbors:
+ - neighbor_address: "20.33.1.1/24"
+ address_family:
+ - afi: "ipv4"
+ allowas_in: 4
+ as_override: True
+ attribute_unchanged:
+ med: True
+ - afi: "ipv6"
+ default_originate: "map01"
+ distribute_list:
+ - action: "export"
+ acl: 10
+ - neighbor_address: "100.11.34.12"
+ address_family:
+ - afi: "ipv4"
+ maximum_prefix: 45
+ nexthop_self: True
+ route_map:
+ - action: "export"
+ route_map: "map01"
+ - action: "import"
+ route_map: "map01"
+ weight: 50
+ state: rendered
+
+# Module Execution:
+
+# "rendered": [
+# "set protocols bgp 100 address-family ipv4-unicast redistribute static metric 50",
+# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast allowas-in number 4",
+# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast as-override",
+# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv4-unicast attribute-unchanged med",
+# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast default-originate route-map map01",
+# "set protocols bgp 100 neighbor 20.33.1.1/24 address-family ipv6-unicast distribute-list export 10",
+# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast maximum-prefix 45",
+# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast nexthop-self",
+# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast route-map export map01",
+# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast route-map import map01",
+# "set protocols bgp 100 neighbor 100.11.34.12 address-family ipv4-unicast weight 50"
+# ]
+
+
+"""
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.bgp_address_family.bgp_address_family import (
+ Bgp_address_familyArgs,
+)
+from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.config.bgp_address_family.bgp_address_family import (
+ Bgp_address_family,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: the result form module invocation
+ """
+ module = AnsibleModule(
+ argument_spec=Bgp_address_familyArgs.argument_spec,
+ mutually_exclusive=[],
+ required_if=[],
+ supports_check_mode=False,
+ )
+
+ result = Bgp_address_family(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tests/integration/targets/vyos_bgp_address_family/defaults/main.yaml b/tests/integration/targets/vyos_bgp_address_family/defaults/main.yaml
new file mode 100644
index 0000000..852a6be
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/defaults/main.yaml
@@ -0,0 +1,3 @@
+---
+testcase: '[^_].*'
+test_items: []
diff --git a/tests/integration/targets/vyos_bgp_address_family/meta/main.yaml b/tests/integration/targets/vyos_bgp_address_family/meta/main.yaml
new file mode 100644
index 0000000..7413320
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/meta/main.yaml
@@ -0,0 +1,3 @@
+---
+dependencies:
+ - prepare_vyos_tests
diff --git a/tests/integration/targets/vyos_bgp_address_family/tasks/cli.yaml b/tests/integration/targets/vyos_bgp_address_family/tasks/cli.yaml
new file mode 100644
index 0000000..93eb2fe
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/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_bgp_address_family/tasks/main.yaml b/tests/integration/targets/vyos_bgp_address_family/tasks/main.yaml
new file mode 100644
index 0000000..b957d2f
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/tasks/main.yaml
@@ -0,0 +1,4 @@
+---
+- include: cli.yaml
+ tags:
+ - network_cli
diff --git a/tests/integration/targets/vyos_bgp_address_family/tests/cli/_parsed_config.cfg b/tests/integration/targets/vyos_bgp_address_family/tests/cli/_parsed_config.cfg
new file mode 100644
index 0000000..2aecc80
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/tests/cli/_parsed_config.cfg
@@ -0,0 +1,9 @@
+set policy access-list 20 description 'acl20'
+set policy access-list 40 description 'acl40'
+set policy route-map map01 description 'map01'
+set protocols bgp 65536 address-family ipv6-unicast aggregate-address 5000:1:1::/64 summary-only
+set protocols bgp 65536 address-family ipv6-unicast network 21e0:1:1::/64 route-map 'map01'
+set protocols bgp 65536 address-family ipv6-unicast redistribute ripng metric '20'
+set protocols bgp 65536 neighbor 192.0.2.25 address-family ipv6-unicast route-map export 'map01'
+set protocols bgp 65536 neighbor 192.0.2.25 address-family ipv6-unicast soft-reconfiguration inbound
+set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast attribute-unchanged next-hop
diff --git a/tests/integration/targets/vyos_bgp_address_family/tests/cli/_populate.yaml b/tests/integration/targets/vyos_bgp_address_family/tests/cli/_populate.yaml
new file mode 100644
index 0000000..3aca916
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/tests/cli/_populate.yaml
@@ -0,0 +1,17 @@
+---
+- name: setup
+ vyos.vyos.vyos_config:
+ lines:
+ - set policy access-list 20 description 'acl20'
+ - set policy access-list 40 description 'acl40'
+ - set policy access-list6 10 description 'acl10'
+ - set policy route-map map01 description 'map01'
+ - set protocols bgp 65536 address-family ipv6-unicast aggregate-address 5000:1:1::/64 summary-only
+ - set protocols bgp 65536 address-family ipv6-unicast network 21e0:1:1::/64 route-map 'map01'
+ - set protocols bgp 65536 address-family ipv6-unicast redistribute ripng metric '20'
+ - set protocols bgp 65536 neighbor 192.0.2.25 address-family ipv6-unicast route-map export 'map01'
+ - set protocols bgp 65536 neighbor 192.0.2.25 address-family ipv6-unicast soft-reconfiguration inbound
+ - set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast attribute-unchanged next-hop
+ ignore_errors: true
+ vars:
+ ansible_connection: ansible.netcommon.network_cli
diff --git a/tests/integration/targets/vyos_bgp_address_family/tests/cli/_preconfig.yaml b/tests/integration/targets/vyos_bgp_address_family/tests/cli/_preconfig.yaml
new file mode 100644
index 0000000..5024a70
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/tests/cli/_preconfig.yaml
@@ -0,0 +1,11 @@
+---
+- name: setup
+ vyos.vyos.vyos_config:
+ lines:
+ - set policy access-list 20 description 'acl20'
+ - set policy access-list 40 description 'acl40'
+ - set policy access-list6 10 description 'acl10'
+ - set policy route-map map01 description 'map01'
+ ignore_errors: true
+ vars:
+ ansible_connection: ansible.netcommon.network_cli
diff --git a/tests/integration/targets/vyos_bgp_address_family/tests/cli/_remove_config.yaml b/tests/integration/targets/vyos_bgp_address_family/tests/cli/_remove_config.yaml
new file mode 100644
index 0000000..39d8bd0
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/tests/cli/_remove_config.yaml
@@ -0,0 +1,12 @@
+---
+- name: Remove pre-existing bgp processes
+ vyos.vyos.vyos_config:
+ lines:
+ - delete protocols bgp 65536
+ - delete policy access-list 20
+ - delete policy access-list 40
+ - delete policy access-list6 10
+ - delete policy route-map map01
+ ignore_errors: true
+ vars:
+ ansible_connection: ansible.netcommon.network_cli
diff --git a/tests/integration/targets/vyos_bgp_address_family/tests/cli/deleted.yaml b/tests/integration/targets/vyos_bgp_address_family/tests/cli/deleted.yaml
new file mode 100644
index 0000000..7fb8e10
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/tests/cli/deleted.yaml
@@ -0,0 +1,49 @@
+---
+- debug:
+ msg: START vyos_bgp_address_family 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_bgp_address_family: &id001
+ config:
+ as_number: "65536"
+ address_family:
+ - afi: "ipv6"
+ neighbors:
+ - neighbor_address: "203.0.113.5"
+ - neighbor_address: "192.0.2.25"
+ address_family:
+ - afi: "ipv6"
+ state: deleted
+
+ - become: true
+ vyos.vyos.vyos_facts:
+ gather_network_resources: bgp_address_family
+
+ - assert:
+ that:
+ - result.commands|length == 3
+ - result.changed == true
+ - result.commands|symmetric_difference(deleted.commands) == []
+ - result.after == ansible_facts['network_resources']['bgp_address_family']
+
+ - name: Delete the existing configuration with the provided running configuration
+ (IDEMPOTENT)
+ register: result
+ vyos.vyos.vyos_bgp_address_family: *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_bgp_address_family/tests/cli/empty_config.yaml b/tests/integration/targets/vyos_bgp_address_family/tests/cli/empty_config.yaml
new file mode 100644
index 0000000..3a12be9
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/tests/cli/empty_config.yaml
@@ -0,0 +1,60 @@
+---
+- debug:
+ msg: START vyos_bgp_address_family 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_bgp_address_family:
+ 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_bgp_address_family:
+ 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_bgp_address_family:
+ 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_bgp_address_family:
+ 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_bgp_address_family:
+ 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_bgp_address_family/tests/cli/gathered.yaml b/tests/integration/targets/vyos_bgp_address_family/tests/cli/gathered.yaml
new file mode 100644
index 0000000..7176a48
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/tests/cli/gathered.yaml
@@ -0,0 +1,24 @@
+---
+- debug:
+ msg: START vyos_bgp_address_family 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_bgp_address_family:
+ state: gathered
+
+ - become: true
+ vyos.vyos.vyos_facts:
+ gather_network_resources: bgp_address_family
+
+ - assert:
+ that:
+ - result.changed == false
+ - result.gathered == ansible_facts['network_resources']['bgp_address_family']
diff --git a/tests/integration/targets/vyos_bgp_address_family/tests/cli/merged.yaml b/tests/integration/targets/vyos_bgp_address_family/tests/cli/merged.yaml
new file mode 100644
index 0000000..45870c6
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/tests/cli/merged.yaml
@@ -0,0 +1,70 @@
+---
+- debug:
+ msg: START vyos_bgp_address_family merged integration tests on connection={{
+ ansible_connection }}
+
+- include_tasks: _remove_config.yaml
+
+- include_tasks: _preconfig.yaml
+
+- block:
+
+ - name: Merge the provided configuration with the exisiting running configuration
+ register: result
+ vyos.vyos.vyos_bgp_address_family: &id001
+ config:
+ as_number: "65536"
+ address_family:
+ - afi: "ipv6"
+ redistribute:
+ - protocol: "static"
+ metric: 50
+ neighbors:
+ - neighbor_address: "203.0.113.5"
+ address_family:
+ - afi: "ipv6"
+ allowas_in: 4
+ attribute_unchanged:
+ med: true
+ default_originate: "map01"
+ distribute_list:
+ - action: "export"
+ acl: 10
+ - neighbor_address: "192.0.2.25"
+ address_family:
+ - afi: "ipv6"
+ maximum_prefix: 45
+ nexthop_self: true
+ route_map:
+ - action: "export"
+ route_map: "map01"
+ - action: "import"
+ route_map: "map01"
+ state: merged
+
+ - become: true
+ vyos.vyos.vyos_facts:
+ gather_network_resources: bgp_address_family
+
+ - assert:
+ that:
+ - result.commands|length == 9
+ - result.changed == true
+ - result.commands|symmetric_difference(merged.commands) == []
+ - result.after == ansible_facts['network_resources']['bgp_address_family']
+ - result.before == {}
+ - result.after == merged.after
+
+ - name: Merge the provided configuration with the existing running configuration
+ (IDEMPOTENT)
+ register: result
+ vyos.vyos.vyos_bgp_address_family: *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_bgp_address_family/tests/cli/overridden.yaml b/tests/integration/targets/vyos_bgp_address_family/tests/cli/overridden.yaml
new file mode 100644
index 0000000..77ba5b4
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/tests/cli/overridden.yaml
@@ -0,0 +1,58 @@
+---
+- debug:
+ msg: START vyos_bgp_address_family overridden integration tests on connection={{
+ ansible_connection }}
+
+- include_tasks: _remove_config.yaml
+
+- include_tasks: _populate.yaml
+
+- block:
+
+ - name: Replace the existing configuration with the provided running configuration
+ register: result
+ vyos.vyos.vyos_bgp_address_family: &id001
+ config:
+ as_number: "65536"
+ address_family:
+ - afi: "ipv6"
+ redistribute:
+ - protocol: "static"
+ metric: 50
+ neighbors:
+ - neighbor_address: "203.0.113.5"
+ address_family:
+ - afi: "ipv6"
+ allowas_in: 4
+ attribute_unchanged:
+ med: true
+ default_originate: "map01"
+ distribute_list:
+ - action: "export"
+ acl: 10
+ state: overridden
+
+ - become: true
+ vyos.vyos.vyos_facts:
+ gather_network_resources: bgp_address_family
+
+ - assert:
+ that:
+ - result.commands|length == 10
+ - result.changed == true
+ - result.commands|symmetric_difference(overridden.commands) == []
+ - result.after == ansible_facts['network_resources']['bgp_address_family']
+
+ - name: Replace the existing configuration with the provided running configuration
+ (IDEMPOTENT)
+ register: result
+ vyos.vyos.vyos_bgp_address_family: *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_bgp_address_family/tests/cli/parsed.yaml b/tests/integration/targets/vyos_bgp_address_family/tests/cli/parsed.yaml
new file mode 100644
index 0000000..d20684f
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/tests/cli/parsed.yaml
@@ -0,0 +1,16 @@
+---
+- debug:
+ msg: START vyos_bgp_address_family 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_bgp_address_family:
+ running_config: "{{ lookup('file', '_parsed_config.cfg') }}"
+ state: parsed
+
+- assert:
+ that:
+ - result.changed == false
+ - result.parsed == populate.config
diff --git a/tests/integration/targets/vyos_bgp_address_family/tests/cli/rendered.yaml b/tests/integration/targets/vyos_bgp_address_family/tests/cli/rendered.yaml
new file mode 100644
index 0000000..1071657
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/tests/cli/rendered.yaml
@@ -0,0 +1,44 @@
+---
+- debug:
+ msg: START vyos_bgp_address_family rendered integration tests on connection={{
+ ansible_connection }}
+
+- block:
+
+ - name: Render the given config in the form of native config.
+ register: result
+ vyos.vyos.vyos_bgp_address_family: &id001
+ config:
+ as_number: "65536"
+ address_family:
+ - afi: "ipv6"
+ redistribute:
+ - protocol: "static"
+ metric: 50
+ neighbors:
+ - neighbor_address: "203.0.113.5"
+ address_family:
+ - afi: "ipv6"
+ allowas_in: 4
+ attribute_unchanged:
+ med: true
+ default_originate: "map01"
+ distribute_list:
+ - action: "export"
+ acl: 10
+ - neighbor_address: "192.0.2.25"
+ address_family:
+ - afi: "ipv6"
+ maximum_prefix: 45
+ nexthop_self: true
+ route_map:
+ - action: "export"
+ route_map: "map01"
+ - action: "import"
+ route_map: "map01"
+ state: rendered
+
+ - assert:
+ that:
+ - result.changed == false
+ - result.rendered|symmetric_difference(merged.commands) == []
diff --git a/tests/integration/targets/vyos_bgp_address_family/tests/cli/replaced.yaml b/tests/integration/targets/vyos_bgp_address_family/tests/cli/replaced.yaml
new file mode 100644
index 0000000..001c997
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/tests/cli/replaced.yaml
@@ -0,0 +1,58 @@
+---
+- debug:
+ msg: START vyos_bgp_address_family replaced integration tests on connection={{
+ ansible_connection }}
+
+- include_tasks: _remove_config.yaml
+
+- include_tasks: _populate.yaml
+
+- block:
+
+ - name: Replace the existing configuration with the provided running configuration
+ register: result
+ vyos.vyos.vyos_bgp_address_family: &id001
+ config:
+ as_number: "65536"
+ address_family:
+ - afi: "ipv6"
+ redistribute:
+ - protocol: "static"
+ metric: 50
+ neighbors:
+ - neighbor_address: "203.0.113.5"
+ address_family:
+ - afi: "ipv6"
+ allowas_in: 4
+ attribute_unchanged:
+ med: true
+ default_originate: "map01"
+ distribute_list:
+ - action: "export"
+ acl: 10
+ state: replaced
+
+ - become: true
+ vyos.vyos.vyos_facts:
+ gather_network_resources: bgp_address_family
+
+ - assert:
+ that:
+ - result.commands|length == 9
+ - result.changed == true
+ - result.commands|symmetric_difference(replaced.commands) == []
+ - result.after == ansible_facts['network_resources']['bgp_address_family']
+
+ - name: Replace the existing configuration with the provided running configuration
+ (IDEMPOTENT)
+ register: result
+ vyos.vyos.vyos_bgp_address_family: *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_bgp_address_family/tests/cli/rtt.yaml b/tests/integration/targets/vyos_bgp_address_family/tests/cli/rtt.yaml
new file mode 100644
index 0000000..3ef93c4
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/tests/cli/rtt.yaml
@@ -0,0 +1,90 @@
+---
+- debug:
+ msg: START vyos_bgp_address_family rtt integration tests on connection={{
+ ansible_connection }}
+
+- include_tasks: _remove_config.yaml
+
+- include_tasks: _preconfig.yaml
+
+- block:
+
+ - name: Merge the provided configuration with the exisiting running configuration
+ register: baseconfig
+ vyos.vyos.vyos_bgp_address_family:
+ config:
+ as_number: "65536"
+ address_family:
+ - afi: "ipv6"
+ redistribute:
+ - protocol: "static"
+ metric: 50
+ neighbors:
+ - neighbor_address: "203.0.113.5"
+ address_family:
+ - afi: "ipv6"
+ allowas_in: 4
+ attribute_unchanged:
+ med: true
+ default_originate: "map01"
+ distribute_list:
+ - action: "export"
+ acl: 10
+ - neighbor_address: "192.0.2.25"
+ address_family:
+ - afi: "ipv6"
+ maximum_prefix: 45
+ nexthop_self: true
+ route_map:
+ - action: "export"
+ route_map: "map01"
+ - action: "import"
+ route_map: "map01"
+ state: merged
+
+ - become: true
+ vyos.vyos.vyos_facts:
+ gather_network_resources: bgp_address_family
+
+ - assert:
+ that:
+ - baseconfig.commands|length == 9
+ - baseconfig.changed == true
+ - baseconfig.commands|symmetric_difference(merged.commands) == []
+ - baseconfig.after == ansible_facts['network_resources']['bgp_address_family']
+
+ - name: Apply the provided configuration (config to be reverted)
+ become: true
+ register: result
+ vyos.vyos.vyos_bgp_address_family:
+ config:
+ as_number: "65536"
+ address_family:
+ - afi: "ipv6"
+ aggregate_address:
+ - summary_only: true
+ prefix: "21e0:1:1::/64"
+ networks:
+ - prefix: "21e0:1:1::/64"
+ route_map: "map01"
+ neighbors:
+ - address_family:
+ - afi: "ipv6"
+ remove_private_as: true
+ neighbor_address: "203.0.113.5"
+
+ - name: Revert back to base config using facts round trip
+ become: true
+ register: revert
+ vyos.vyos.vyos_bgp_address_family:
+ config: "{{ ansible_facts['network_resources']['bgp_address_family'] }}"
+ 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_bgp_address_family/vars/main.yaml b/tests/integration/targets/vyos_bgp_address_family/vars/main.yaml
new file mode 100644
index 0000000..aed6de6
--- /dev/null
+++ b/tests/integration/targets/vyos_bgp_address_family/vars/main.yaml
@@ -0,0 +1,99 @@
+---
+merged:
+ commands:
+ - set protocols bgp 65536 address-family ipv6-unicast redistribute static metric 50
+ - set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast allowas-in number 4
+ - set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast attribute-unchanged med
+ - set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast default-originate route-map map01
+ - set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast distribute-list export 10
+ - set protocols bgp 65536 neighbor 192.0.2.25 address-family ipv6-unicast maximum-prefix 45
+ - set protocols bgp 65536 neighbor 192.0.2.25 address-family ipv6-unicast nexthop-self
+ - set protocols bgp 65536 neighbor 192.0.2.25 address-family ipv6-unicast route-map export map01
+ - set protocols bgp 65536 neighbor 192.0.2.25 address-family ipv6-unicast route-map import map01
+ after:
+ address_family:
+ - afi: "ipv6"
+ redistribute:
+ - metric: 50
+ protocol: "static"
+ as_number: 65536
+ neighbors:
+ - address_family:
+ - afi: "ipv6"
+ maximum_prefix: 45
+ nexthop_self: true
+ route_map:
+ - action: "export"
+ route_map: "map01"
+ - action: "import"
+ route_map: "map01"
+ neighbor_address: "192.0.2.25"
+ - address_family:
+ - afi: "ipv6"
+ allowas_in: 4
+ attribute_unchanged:
+ med: true
+ default_originate: "map01"
+ distribute_list:
+ - acl: 10
+ action: "export"
+ neighbor_address: "203.0.113.5"
+
+replaced:
+ commands:
+ - delete protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast attribute-unchanged
+ - delete protocols bgp 65536 address-family ipv6 aggregate-address
+ - delete protocols bgp 65536 address-family ipv6 network
+ - delete protocols bgp 65536 address-family ipv6-unicast redistribute ripng
+ - set protocols bgp 65536 address-family ipv6-unicast redistribute static metric 50
+ - set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast allowas-in number 4
+ - set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast attribute-unchanged med
+ - set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast default-originate route-map map01
+ - set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast distribute-list export 10
+
+overridden:
+ commands:
+ - delete protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast attribute-unchanged
+ - delete protocols bgp 65536 neighbor 192.0.2.25 address-family
+ - delete protocols bgp 65536 address-family ipv6-unicast redistribute ripng
+ - delete protocols bgp 65536 address-family ipv6 aggregate-address
+ - delete protocols bgp 65536 address-family ipv6 network
+ - set protocols bgp 65536 address-family ipv6-unicast redistribute static metric 50
+ - set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast allowas-in number 4
+ - set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast attribute-unchanged med
+ - set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast default-originate route-map map01
+ - set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast distribute-list export 10
+
+deleted:
+ commands:
+ - delete protocols bgp 65536 address-family ipv6-unicast
+ - delete protocols bgp 65536 neighbor 203.0.113.5 address-family
+ - delete protocols bgp 65536 neighbor 192.0.2.25 address-family ipv6-unicast
+
+populate:
+ config:
+ address_family:
+ - afi: "ipv6"
+ aggregate_address:
+ - summary_only: true
+ prefix: "5000:1:1::/64"
+ networks:
+ - prefix: "21e0:1:1::/64"
+ route_map: "map01"
+ redistribute:
+ - metric: 20
+ protocol: "ripng"
+ as_number: 65536
+ neighbors:
+ - address_family:
+ - afi: "ipv6"
+ route_map:
+ - action: "export"
+ route_map: "map01"
+ soft_reconfiguration: true
+ neighbor_address: "192.0.2.25"
+ - address_family:
+ - afi: "ipv6"
+ attribute_unchanged:
+ next_hop: true
+ neighbor_address: "203.0.113.5"
diff --git a/tests/unit/modules/network/vyos/fixtures/vyos_bgp_address_family_config.cfg b/tests/unit/modules/network/vyos/fixtures/vyos_bgp_address_family_config.cfg
new file mode 100644
index 0000000..a59878f
--- /dev/null
+++ b/tests/unit/modules/network/vyos/fixtures/vyos_bgp_address_family_config.cfg
@@ -0,0 +1,7 @@
+set protocols bgp 65536 address-family ipv4-unicast aggregate-address 192.0.2.0/24 as-set
+set protocols bgp 65536 address-family ipv4-unicast network 192.1.13.0/24 route-map 'map01'
+set protocols bgp 65536 address-family ipv4-unicast network 192.2.13.0/24 backdoor
+set protocols bgp 65536 address-family ipv6-unicast redistribute ripng metric '20'
+set protocols bgp 65536 neighbor 192.0.2.25 address-family ipv4-unicast route-map export 'map01'
+set protocols bgp 65536 neighbor 192.0.2.25 address-family ipv4-unicast soft-reconfiguration inbound
+set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast attribute-unchanged next-hop
diff --git a/tests/unit/modules/network/vyos/test_vyos_bgp_address_family.py b/tests/unit/modules/network/vyos/test_vyos_bgp_address_family.py
new file mode 100644
index 0000000..5fc7e35
--- /dev/null
+++ b/tests/unit/modules/network/vyos/test_vyos_bgp_address_family.py
@@ -0,0 +1,684 @@
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+from ansible_collections.vyos.vyos.tests.unit.compat.mock import patch
+from ansible_collections.vyos.vyos.plugins.modules import (
+ vyos_bgp_address_family,
+)
+from ansible_collections.vyos.vyos.tests.unit.modules.utils import (
+ set_module_args,
+)
+from .vyos_module import TestVyosModule, load_fixture
+
+
+class TestVyosBgpafModule(TestVyosModule):
+
+ module = vyos_bgp_address_family
+
+ def setUp(self):
+ super(TestVyosBgpafModule, self).setUp()
+ self.mock_get_resource_connection_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module_base.get_resource_connection"
+ )
+ self.get_resource_connection_config = (
+ self.mock_get_resource_connection_config.start()
+ )
+
+ self.mock_execute_show_command = patch(
+ "ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts."
+ + "bgp_address_family.bgp_address_family.Bgp_address_familyFacts.get_device_data"
+ )
+ self.execute_show_command = self.mock_execute_show_command.start()
+
+ def tearDown(self):
+ super(TestVyosBgpafModule, self).tearDown()
+ self.mock_get_resource_connection_config.stop()
+ self.mock_execute_show_command.stop()
+
+ def load_fixtures(self, commands=None, transport="cli", filename=None):
+ if filename is None:
+ filename = "vyos_bgp_address_family_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_bgp_address_family_merged_idempotent(self):
+ set_module_args(
+ dict(
+ config=dict(
+ as_number=65536,
+ address_family=[
+ dict(
+ afi="ipv4",
+ aggregate_address=[
+ dict(prefix="192.0.2.0/24", as_set=True)
+ ],
+ networks=[
+ dict(
+ prefix="192.1.13.0/24", route_map="map01"
+ ),
+ dict(prefix="192.2.13.0/24", backdoor=True),
+ ],
+ ),
+ dict(
+ afi="ipv6",
+ redistribute=[dict(protocol="ripng", metric=20)],
+ ),
+ ],
+ neighbors=[
+ dict(
+ neighbor_address="192.0.2.25",
+ address_family=[
+ dict(
+ afi="ipv4",
+ route_map=[
+ dict(
+ action="export", route_map="map01"
+ )
+ ],
+ soft_reconfiguration=True,
+ ),
+ ],
+ ),
+ dict(
+ neighbor_address="203.0.113.5",
+ address_family=[
+ dict(
+ afi="ipv6",
+ attribute_unchanged=dict(next_hop=True),
+ )
+ ],
+ ),
+ ],
+ )
+ )
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_vyos_bgp_address_family_merged(self):
+ set_module_args(
+ dict(
+ config=dict(
+ as_number=65536,
+ address_family=[
+ dict(
+ afi="ipv4",
+ aggregate_address=[
+ dict(prefix="192.0.2.0/24", summary_only=True)
+ ],
+ networks=[
+ dict(
+ prefix="192.1.13.0/24", route_map="map01"
+ ),
+ ],
+ ),
+ dict(
+ afi="ipv6",
+ redistribute=[dict(protocol="ospfv3", metric=20)],
+ ),
+ ],
+ neighbors=[
+ dict(
+ neighbor_address="192.10.21.25",
+ address_family=[
+ dict(
+ afi="ipv6",
+ distribute_list=[
+ dict(action="export", acl=10)
+ ],
+ route_server_client=True,
+ ),
+ ],
+ ),
+ dict(
+ neighbor_address="203.0.113.5",
+ address_family=[
+ dict(
+ afi="ipv4",
+ filter_list=[
+ dict(
+ action="export", path_list="list01"
+ ),
+ ],
+ capability=dict(orf="send"),
+ )
+ ],
+ ),
+ ],
+ )
+ )
+ )
+ commands = [
+ "set protocols bgp 65536 address-family ipv4-unicast aggregate-address 192.0.2.0/24 as-setipv4-unicast aggregate-address 192.0.2.0/24 summary-only",
+ "set protocols bgp 65536 address-family ipv6-unicast redistribute ospfv3 metric 20",
+ "set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv4-unicast filter-list export list01",
+ "set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv4-unicast capability prefix-list send",
+ "set protocols bgp 65536 neighbor 192.10.21.25 address-family ipv6-unicast distribute-list export 10",
+ "set protocols bgp 65536 neighbor 192.10.21.25 address-family ipv6-unicast route-server-client",
+ ]
+ self.execute_module(changed=True, commands=commands)
+
+ def test_vyos_bgp_address_family_replaced_idempotent(self):
+ set_module_args(
+ dict(
+ state="replaced",
+ config=dict(
+ as_number=65536,
+ address_family=[
+ dict(
+ afi="ipv4",
+ aggregate_address=[
+ dict(prefix="192.0.2.0/24", as_set=True)
+ ],
+ networks=[
+ dict(
+ prefix="192.1.13.0/24", route_map="map01"
+ ),
+ dict(prefix="192.2.13.0/24", backdoor=True),
+ ],
+ ),
+ dict(
+ afi="ipv6",
+ redistribute=[dict(protocol="ripng", metric=20)],
+ ),
+ ],
+ neighbors=[
+ dict(
+ neighbor_address="192.0.2.25",
+ address_family=[
+ dict(
+ afi="ipv4",
+ route_map=[
+ dict(
+ action="export", route_map="map01"
+ )
+ ],
+ soft_reconfiguration=True,
+ ),
+ ],
+ ),
+ dict(
+ neighbor_address="203.0.113.5",
+ address_family=[
+ dict(
+ afi="ipv6",
+ attribute_unchanged=dict(next_hop=True),
+ )
+ ],
+ ),
+ ],
+ ),
+ )
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_vyos_bgp_address_family_replaced(self):
+ set_module_args(
+ dict(
+ state="replaced",
+ config=dict(
+ as_number=65536,
+ address_family=[
+ dict(
+ afi="ipv4",
+ aggregate_address=[
+ dict(prefix="192.0.2.0/24", summary_only=True)
+ ],
+ networks=[
+ dict(
+ prefix="192.1.13.0/24", route_map="map01"
+ ),
+ ],
+ ),
+ dict(
+ afi="ipv6",
+ redistribute=[dict(protocol="ospfv3", metric=20)],
+ ),
+ ],
+ neighbors=[
+ dict(
+ neighbor_address="192.10.21.25",
+ address_family=[
+ dict(
+ afi="ipv4",
+ route_map=[
+ dict(
+ action="import", route_map="map01"
+ )
+ ],
+ ),
+ dict(
+ afi="ipv6",
+ distribute_list=[
+ dict(action="export", acl=10)
+ ],
+ route_server_client=True,
+ ),
+ ],
+ ),
+ dict(
+ neighbor_address="192.0.2.25",
+ address_family=[
+ dict(
+ afi="ipv4",
+ route_map=[
+ dict(
+ action="export", route_map="map01"
+ )
+ ],
+ ),
+ ],
+ ),
+ dict(
+ neighbor_address="203.0.113.5",
+ address_family=[
+ dict(
+ afi="ipv4",
+ filter_list=[
+ dict(
+ action="export", path_list="list01"
+ ),
+ ],
+ capability=dict(orf="send"),
+ )
+ ],
+ ),
+ ],
+ ),
+ )
+ )
+ commands = [
+ "delete protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast attribute-unchanged",
+ "delete protocols bgp 65536 neighbor 192.0.2.25 address-family ipv4-unicast soft-reconfiguration",
+ "delete protocols bgp 65536 address-family ipv6-unicast redistribute ripng",
+ "delete protocols bgp 65536 address-family ipv4-unicast network 192.2.13.0/24",
+ "set protocols bgp 65536 address-family ipv4-unicast aggregate-address 192.0.2.0/24 summary-only",
+ "set protocols bgp 65536 address-family ipv6-unicast redistribute ospfv3 metric 20",
+ "set protocols bgp 65536 neighbor 192.10.21.25 address-family ipv4-unicast route-map import map01",
+ "set protocols bgp 65536 neighbor 192.10.21.25 address-family ipv6-unicast distribute-list export 10",
+ "set protocols bgp 65536 neighbor 192.10.21.25 address-family ipv6-unicast route-server-client",
+ "set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv4-unicast filter-list export list01",
+ "set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv4-unicast capability prefix-list send",
+ ]
+ self.execute_module(changed=True, commands=commands)
+
+ def test_vyos_bgp_address_family_overridden_idempotent(self):
+ set_module_args(
+ dict(
+ state="overridden",
+ config=dict(
+ as_number=65536,
+ address_family=[
+ dict(
+ afi="ipv4",
+ aggregate_address=[
+ dict(prefix="192.0.2.0/24", as_set=True)
+ ],
+ networks=[
+ dict(
+ prefix="192.1.13.0/24", route_map="map01"
+ ),
+ dict(prefix="192.2.13.0/24", backdoor=True),
+ ],
+ ),
+ dict(
+ afi="ipv6",
+ redistribute=[dict(protocol="ripng", metric=20)],
+ ),
+ ],
+ neighbors=[
+ dict(
+ neighbor_address="192.0.2.25",
+ address_family=[
+ dict(
+ afi="ipv4",
+ route_map=[
+ dict(
+ action="export", route_map="map01"
+ )
+ ],
+ soft_reconfiguration=True,
+ ),
+ ],
+ ),
+ dict(
+ neighbor_address="203.0.113.5",
+ address_family=[
+ dict(
+ afi="ipv6",
+ attribute_unchanged=dict(next_hop=True),
+ )
+ ],
+ ),
+ ],
+ ),
+ )
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_vyos_bgp_address_family_overridden(self):
+ set_module_args(
+ dict(
+ state="overridden",
+ config=dict(
+ as_number=65536,
+ address_family=[
+ dict(
+ afi="ipv4",
+ networks=[
+ dict(
+ prefix="192.1.13.0/24", route_map="map01"
+ ),
+ ],
+ ),
+ dict(
+ afi="ipv6",
+ redistribute=[dict(protocol="ospfv3", metric=20)],
+ ),
+ ],
+ neighbors=[
+ dict(
+ neighbor_address="192.10.21.25",
+ address_family=[
+ dict(
+ afi="ipv4",
+ route_map=[
+ dict(
+ action="import", route_map="map01"
+ )
+ ],
+ ),
+ dict(
+ afi="ipv6",
+ distribute_list=[
+ dict(action="export", acl=10)
+ ],
+ route_server_client=True,
+ ),
+ ],
+ ),
+ ],
+ ),
+ )
+ )
+ commands = [
+ "delete protocols bgp 65536 neighbor 203.0.113.5 address-family",
+ "delete protocols bgp 65536 neighbor 192.0.2.25 address-family",
+ "delete protocols bgp 65536 address-family ipv6-unicast redistribute ripng",
+ "delete protocols bgp 65536 address-family ipv4 aggregate-address",
+ "delete protocols bgp 65536 address-family ipv4-unicast network 192.2.13.0/24",
+ "set protocols bgp 65536 address-family ipv6-unicast redistribute ospfv3 metric 20",
+ "set protocols bgp 65536 neighbor 192.10.21.25 address-family ipv4-unicast route-map import map01",
+ "set protocols bgp 65536 neighbor 192.10.21.25 address-family ipv6-unicast distribute-list export 10",
+ "set protocols bgp 65536 neighbor 192.10.21.25 address-family ipv6-unicast route-server-client",
+ ]
+ self.execute_module(changed=True, commands=commands)
+
+ def test_vyos_bgp_address_family_deleted(self):
+ set_module_args(
+ dict(
+ state="deleted",
+ config=dict(
+ as_number=65536,
+ address_family=[
+ dict(
+ afi="ipv4",
+ ),
+ ],
+ neighbors=[
+ dict(
+ neighbor_address="192.0.2.25",
+ address_family=[
+ dict(
+ afi="ipv4",
+ ),
+ ],
+ ),
+ dict(
+ neighbor_address="203.0.113.5",
+ ),
+ ],
+ ),
+ )
+ )
+ commands = [
+ "delete protocols bgp 65536 address-family ipv4-unicast",
+ "delete protocols bgp 65536 neighbor 192.0.2.25 address-family ipv4-unicast",
+ "delete protocols bgp 65536 neighbor 203.0.113.5 address-family",
+ ]
+
+ self.execute_module(changed=True, commands=commands)
+
+ def test_vyos_bgp_address_family_incorrect_instance(self):
+ set_module_args(
+ dict(
+ state="overridden",
+ config=dict(
+ as_number=100,
+ address_family=[
+ dict(
+ afi="ipv4",
+ networks=[
+ dict(
+ prefix="192.1.13.0/24", route_map="map01"
+ ),
+ ],
+ ),
+ dict(
+ afi="ipv6",
+ redistribute=[dict(protocol="ospfv3", metric=20)],
+ ),
+ ],
+ neighbors=[
+ dict(
+ neighbor_address="192.10.21.25",
+ address_family=[
+ dict(
+ afi="ipv4",
+ route_map=[
+ dict(
+ action="import", route_map="map01"
+ )
+ ],
+ ),
+ dict(
+ afi="ipv6",
+ distribute_list=[
+ dict(action="export", acl=10)
+ ],
+ route_server_client=True,
+ ),
+ ],
+ ),
+ ],
+ ),
+ )
+ )
+ result = self.execute_module(failed=True)
+ self.assertIn(
+ "Only one bgp instance is allowed per device", result["msg"]
+ )
+
+ def test_vyos_bgp_address_family_rendered(self):
+ set_module_args(
+ dict(
+ state="rendered",
+ config=dict(
+ as_number=65536,
+ address_family=[
+ dict(
+ afi="ipv4",
+ aggregate_address=[
+ dict(prefix="192.0.2.0/24", as_set=True)
+ ],
+ networks=[
+ dict(
+ prefix="192.1.13.0/24", route_map="map01"
+ ),
+ dict(prefix="192.2.13.0/24", backdoor=True),
+ ],
+ ),
+ dict(
+ afi="ipv6",
+ redistribute=[dict(protocol="ripng", metric=20)],
+ ),
+ ],
+ neighbors=[
+ dict(
+ neighbor_address="192.0.2.25",
+ address_family=[
+ dict(
+ afi="ipv4",
+ route_map=[
+ dict(
+ action="export", route_map="map01"
+ )
+ ],
+ soft_reconfiguration=True,
+ ),
+ ],
+ ),
+ dict(
+ neighbor_address="203.0.113.5",
+ address_family=[
+ dict(
+ afi="ipv6",
+ attribute_unchanged=dict(next_hop=True),
+ )
+ ],
+ ),
+ ],
+ ),
+ )
+ )
+
+ rendered_cmds = [
+ "set protocols bgp 65536 address-family ipv4-unicast network 192.1.13.0/24 route-map map01",
+ "set protocols bgp 65536 address-family ipv4-unicast network 192.2.13.0/24 backdoor",
+ "set protocols bgp 65536 address-family ipv4-unicast aggregate-address 192.0.2.0/24 as-set",
+ "set protocols bgp 65536 address-family ipv6-unicast redistribute ripng metric 20",
+ "set protocols bgp 65536 neighbor 192.0.2.25 address-family ipv4-unicast route-map export map01",
+ "set protocols bgp 65536 neighbor 192.0.2.25 address-family ipv4-unicast soft-reconfiguration inbound",
+ "set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast attribute-unchanged next-hop",
+ ]
+ result = self.execute_module(changed=False)
+ self.assertEqual(
+ sorted(result["rendered"]),
+ sorted(rendered_cmds),
+ result["rendered"],
+ )
+
+ def test_vyos_bgp_address_family_parsed(self):
+ commands = [
+ "set protocols bgp 65536 address-family ipv4-unicast network 192.1.13.0/24 route-map map01",
+ "set protocols bgp 65536 address-family ipv4-unicast network 192.2.13.0/24 backdoor",
+ "set protocols bgp 65536 address-family ipv4-unicast aggregate-address 192.0.2.0/24 as-set",
+ "set protocols bgp 65536 address-family ipv6-unicast redistribute ripng metric 20",
+ "set protocols bgp 65536 neighbor 192.0.2.25 address-family ipv4-unicast route-map export map01",
+ "set protocols bgp 65536 neighbor 192.0.2.25 address-family ipv4-unicast soft-reconfiguration inbound",
+ "set protocols bgp 65536 neighbor 203.0.113.5 address-family ipv6-unicast attribute-unchanged next-hop",
+ ]
+
+ parsed_str = "\n".join(commands)
+ set_module_args(dict(running_config=parsed_str, state="parsed"))
+ result = self.execute_module(changed=False)
+ parsed_list = {
+ "as_number": 65536,
+ "address_family": [
+ {
+ "afi": "ipv4",
+ "networks": [
+ {"prefix": "192.1.13.0/24", "route_map": "map01"},
+ {"prefix": "192.2.13.0/24", "backdoor": True},
+ ],
+ "aggregate_address": [
+ {"prefix": "192.0.2.0/24", "as_set": True}
+ ],
+ },
+ {
+ "afi": "ipv6",
+ "redistribute": [{"protocol": "ripng", "metric": 20}],
+ },
+ ],
+ "neighbors": [
+ {
+ "neighbor_address": "192.0.2.25",
+ "address_family": [
+ {"afi": "ipv4", "soft_reconfiguration": True},
+ ],
+ },
+ {
+ "neighbor_address": "203.0.113.5",
+ "address_family": [
+ {
+ "afi": "ipv6",
+ "attribute_unchanged": {"next_hop": True},
+ }
+ ],
+ },
+ ],
+ }
+ self.assertEqual(sorted(parsed_list), sorted(result["parsed"]))
+
+ def test_vyos_bgp_address_family_gathered(self):
+ set_module_args(dict(state="gathered"))
+ result = self.execute_module(changed=False)
+ gather_list = {
+ "as_number": 65536,
+ "address_family": [
+ {
+ "afi": "ipv4",
+ "networks": [
+ {"prefix": "192.1.13.0/24", "route_map": "map01"},
+ {"prefix": "192.2.13.0/24", "backdoor": True},
+ ],
+ "aggregate_address": [
+ {"prefix": "192.0.2.0/24", "as_set": True}
+ ],
+ },
+ {
+ "afi": "ipv6",
+ "redistribute": [{"protocol": "ripng", "metric": 20}],
+ },
+ ],
+ "neighbors": [
+ {
+ "neighbor_address": "192.0.2.25",
+ "address_family": [
+ {"afi": "ipv4", "soft_reconfiguration": True},
+ ],
+ },
+ {
+ "neighbor_address": "203.0.113.5",
+ "address_family": [
+ {
+ "afi": "ipv6",
+ "attribute_unchanged": {"next_hop": True},
+ }
+ ],
+ },
+ ],
+ }
+ self.assertEqual(sorted(gather_list), sorted(result["gathered"]))
diff --git a/tox.ini b/tox.ini
index 3da0118..49e9b1d 100644
--- a/tox.ini
+++ b/tox.ini
@@ -26,7 +26,7 @@ commands = {posargs}
# E123, E125 skipped as they are invalid PEP-8.
show-source = True
-ignore = E123,E125,E402,W503
+ignore = E123,E125,E402,W503,W504
max-line-length = 160
builtins = _
exclude = .git,.tox,tests/unit/compat/