summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoransible-zuul[bot] <48994755+ansible-zuul[bot]@users.noreply.github.com>2020-05-11 13:35:11 +0000
committerGitHub <noreply@github.com>2020-05-11 13:35:11 +0000
commit62ddab1affb33cb83b7a31ae6076e73c23dd1d0a (patch)
treeb3de8652c72a4c5e99e51459530d18b059c3ffc8
parenteff143edbc1347e608e4f462093bbcb9985bb57f (diff)
parent44a2e8c885b1d050f9a36fc095403c1568cc1cfd (diff)
downloadvyos-ansible-collection-62ddab1affb33cb83b7a31ae6076e73c23dd1d0a.tar.gz
vyos-ansible-collection-62ddab1affb33cb83b7a31ae6076e73c23dd1d0a.zip
Merge pull request #17 from rohitthakur2590/vyos_ospfv3
VyOS: OSPFv3 Resource Module Reviewed-by: https://github.com/apps/ansible-zuul
-rw-r--r--plugins/module_utils/network/vyos/argspec/ospfv3/__init__.py0
-rw-r--r--plugins/module_utils/network/vyos/argspec/ospfv3/ospfv3.py94
-rw-r--r--plugins/module_utils/network/vyos/config/ospfv3/__init__.py0
-rw-r--r--plugins/module_utils/network/vyos/config/ospfv3/ospfv3.py464
-rw-r--r--plugins/module_utils/network/vyos/facts/facts.py4
-rw-r--r--plugins/module_utils/network/vyos/facts/ospfv3/__init__.py0
-rw-r--r--plugins/module_utils/network/vyos/facts/ospfv3/ospfv3.py213
-rw-r--r--plugins/module_utils/network/vyos/utils/utils.py39
-rw-r--r--plugins/modules/vyos_facts.py2
-rw-r--r--plugins/modules/vyos_ospfv3.py667
-rw-r--r--tests/integration/targets/vyos_ospfv3/defaults/main.yaml3
-rw-r--r--tests/integration/targets/vyos_ospfv3/meta/main.yaml3
-rw-r--r--tests/integration/targets/vyos_ospfv3/tasks/cli.yaml19
-rw-r--r--tests/integration/targets/vyos_ospfv3/tasks/main.yaml4
-rw-r--r--tests/integration/targets/vyos_ospfv3/tests/cli/_parsed_config.cfg8
-rw-r--r--tests/integration/targets/vyos_ospfv3/tests/cli/_populate.yaml13
-rw-r--r--tests/integration/targets/vyos_ospfv3/tests/cli/_remove_config.yaml6
-rw-r--r--tests/integration/targets/vyos_ospfv3/tests/cli/deleted.yaml48
-rw-r--r--tests/integration/targets/vyos_ospfv3/tests/cli/empty_config.yaml49
-rw-r--r--tests/integration/targets/vyos_ospfv3/tests/cli/gathered.yaml25
-rw-r--r--tests/integration/targets/vyos_ospfv3/tests/cli/merged.yaml62
-rw-r--r--tests/integration/targets/vyos_ospfv3/tests/cli/merged_update.yaml61
-rw-r--r--tests/integration/targets/vyos_ospfv3/tests/cli/parsed.yaml15
-rw-r--r--tests/integration/targets/vyos_ospfv3/tests/cli/rendered.yaml38
-rw-r--r--tests/integration/targets/vyos_ospfv3/tests/cli/replaced.yaml66
-rw-r--r--tests/integration/targets/vyos_ospfv3/tests/cli/rtt.yaml75
-rw-r--r--tests/integration/targets/vyos_ospfv3/vars/main.yaml142
-rw-r--r--tests/unit/modules/network/vyos/fixtures/vyos_ospfv3_config.cfg6
-rw-r--r--tests/unit/modules/network/vyos/test_vyos_ospfv3.py348
-rw-r--r--tests/unit/modules/network/vyos/vyos_module.py1
30 files changed, 2473 insertions, 2 deletions
diff --git a/plugins/module_utils/network/vyos/argspec/ospfv3/__init__.py b/plugins/module_utils/network/vyos/argspec/ospfv3/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/module_utils/network/vyos/argspec/ospfv3/__init__.py
diff --git a/plugins/module_utils/network/vyos/argspec/ospfv3/ospfv3.py b/plugins/module_utils/network/vyos/argspec/ospfv3/ospfv3.py
new file mode 100644
index 0000000..66aaa8c
--- /dev/null
+++ b/plugins/module_utils/network/vyos/argspec/ospfv3/ospfv3.py
@@ -0,0 +1,94 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 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 arg spec for the vyos_ospfv3 module
+"""
+
+
+class Ospfv3Args(object): # pylint: disable=R0903
+ """The arg spec for the vyos_ospfv3 module
+ """
+
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "config": {
+ "options": {
+ "areas": {
+ "elements": "dict",
+ "options": {
+ "area_id": {"type": "str"},
+ "export_list": {"type": "str"},
+ "import_list": {"type": "str"},
+ "range": {
+ "elements": "dict",
+ "options": {
+ "address": {"type": "str"},
+ "advertise": {"type": "bool"},
+ "not_advertise": {"type": "bool"},
+ },
+ "type": "list",
+ },
+ },
+ "type": "list",
+ },
+ "parameters": {
+ "options": {"router_id": {"type": "str"}},
+ "type": "dict",
+ },
+ "redistribute": {
+ "elements": "dict",
+ "options": {
+ "route_map": {"type": "str"},
+ "route_type": {
+ "choices": [
+ "bgp",
+ "connected",
+ "kernel",
+ "ripng",
+ "static",
+ ],
+ "type": "str",
+ },
+ },
+ "type": "list",
+ },
+ },
+ "type": "dict",
+ },
+ "running_config": {"type": "str"},
+ "state": {
+ "choices": [
+ "merged",
+ "replaced",
+ "deleted",
+ "parsed",
+ "gathered",
+ "rendered",
+ ],
+ "default": "merged",
+ "type": "str",
+ },
+ } # pylint: disable=C0301
diff --git a/plugins/module_utils/network/vyos/config/ospfv3/__init__.py b/plugins/module_utils/network/vyos/config/ospfv3/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/module_utils/network/vyos/config/ospfv3/__init__.py
diff --git a/plugins/module_utils/network/vyos/config/ospfv3/ospfv3.py b/plugins/module_utils/network/vyos/config/ospfv3/ospfv3.py
new file mode 100644
index 0000000..acda380
--- /dev/null
+++ b/plugins/module_utils/network/vyos/config/ospfv3/ospfv3.py
@@ -0,0 +1,464 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The vyos_ospfv3 class
+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 it's desired end-state is
+created
+"""
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+from copy import deepcopy
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import (
+ ConfigBase,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
+ to_list,
+ remove_empties,
+ search_obj_in_list,
+)
+from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.facts import (
+ Facts,
+)
+from ansible.module_utils.six import iteritems
+
+from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.utils.utils import (
+ _in_target,
+ _is_w_same,
+ _bool_to_str,
+)
+
+
+class Ospfv3(ConfigBase):
+ """
+ The vyos_ospfv3 class
+ """
+
+ gather_subset = [
+ "!all",
+ "!min",
+ ]
+
+ gather_network_resources = [
+ "ospfv3",
+ ]
+
+ def __init__(self, module):
+ super(Ospfv3, self).__init__(module)
+
+ def get_ospfv3_facts(self, data=None):
+ """ Get the 'facts' (the current configuration)
+
+ :rtype: A dictionary
+ :returns: The current configuration as a dictionary
+ """
+ facts, _warnings = Facts(self._module).get_facts(
+ self.gather_subset, self.gather_network_resources, data=data
+ )
+ ospfv3_facts = facts["ansible_network_resources"].get("ospfv3", {})
+ return ospfv3_facts
+
+ def execute_module(self):
+ """ Execute the module
+
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ result = {"changed": False}
+ warnings = list()
+ commands = list()
+
+ if self.state in self.ACTION_STATES:
+ existing_ospfv3_facts = self.get_ospfv3_facts()
+ else:
+ existing_ospfv3_facts = {}
+
+ if self.state in self.ACTION_STATES or self.state == "rendered":
+ commands.extend(self.set_config(existing_ospfv3_facts))
+
+ if commands and self.state in self.ACTION_STATES:
+ if not self._module.check_mode:
+ self._connection.edit_config(commands)
+ result["changed"] = True
+
+ if self.state in self.ACTION_STATES:
+ result["commands"] = commands
+
+ if self.state in self.ACTION_STATES or self.state == "gathered":
+ changed_ospfv3_facts = self.get_ospfv3_facts()
+ elif self.state == "rendered":
+ result["rendered"] = commands
+ elif self.state == "parsed":
+ running_config = self._module.params["running_config"]
+ if not running_config:
+ self._module.fail_json(
+ msg="value of running_config parameter must not be empty for state parsed"
+ )
+ result["parsed"] = self.get_ospfv3_facts(data=running_config)
+ else:
+ changed_ospfv3_facts = {}
+
+ if self.state in self.ACTION_STATES:
+ result["before"] = existing_ospfv3_facts
+ if result["changed"]:
+ result["after"] = changed_ospfv3_facts
+ elif self.state == "gathered":
+ result["gathered"] = changed_ospfv3_facts
+
+ result["warnings"] = warnings
+ return result
+
+ def set_config(self, existing_ospfv3_facts):
+ """ Collect the configuration from the args passed to the module,
+ collect the current configuration (as a dict from facts)
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ want = self._module.params["config"]
+ have = existing_ospfv3_facts
+ resp = self.set_state(want, have)
+ return to_list(resp)
+
+ def set_state(self, w, h):
+ """ Select the appropriate function based on the state provided
+
+ :param want: the desired configuration as a dictionary
+ :param have: the current configuration as a dictionary
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+ if (
+ self.state in ("merged", "replaced", "overridden", "rendered")
+ and not w
+ ):
+ self._module.fail_json(
+ msg="value of config parameter must not be empty for state {0}".format(
+ self.state
+ )
+ )
+ if self.state == "deleted":
+ commands.extend(self._state_deleted(w, h))
+ elif self.state in ("merged", "rendered"):
+ commands.extend(self._state_merged(w, h))
+ elif self.state == "replaced":
+ commands.extend(self._state_replaced(w, h))
+ return commands
+
+ def _state_replaced(self, want, have):
+ """ The command generator when state is replaced
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+ if have:
+ commands.extend(self._render_ospf_param(have, want, opr=False))
+ commands.extend(self._render_ospf_param(want, have))
+ return commands
+
+ def _state_merged(self, want, have):
+ """ The command generator when state is merged
+
+ :rtype: A list
+ :returns: the commands necessary to merge the provided into
+ the current configuration
+ """
+ commands = []
+ commands.extend(self._render_ospf_param(want, have))
+ return commands
+
+ def _state_deleted(self, want, have):
+ """ The command generator when state is deleted
+
+ :rtype: A list
+ :returns: the commands necessary to remove the current configuration
+ of the provided objects
+ """
+ commands = []
+ if have:
+ commands.append("delete protocols ospfv3")
+ return commands
+
+ def _render_ospf_param(self, want, have, opr=True):
+ """
+ This function forms the set/delete commands for ospf leaf attributes
+ and triggers the process for other child attributes.
+ for firewall_global attributes.
+ :param w: the desired config.
+ :param h: the target config.
+ :param opr: True/False.
+ :return: generated commands list.
+ """
+ commands = []
+ w = deepcopy(remove_empties(want))
+ if w:
+ for key, val in iteritems(w):
+ commands.extend(self._render_child_param(w, have, key, opr))
+ return commands
+
+ def _render_child_param(self, w, h, key, opr=True):
+ """
+ This function invoke the function to extend commands
+ based on the key.
+ :param w: the desired configuration.
+ :param h: the current configuration.
+ :param key: attribute name.
+ :param opr: operation.
+ :return: list of commands.
+ """
+ commands = []
+ if key == "areas":
+ commands.extend(self._render_areas(key, w, h, opr=opr))
+ elif key == "parameters":
+ commands.extend(self._render_dict_param(key, w, h, opr=opr))
+ elif key == "redistribute":
+ commands.extend(self._render_list_dict_param(key, w, h, opr=opr))
+ return commands
+
+ def _render_dict_param(self, attr, want, have, opr=True):
+ """
+ This function generate the commands for dictionary elements.
+ :param attr: attribute name.
+ :param w: the desired configuration.
+ :param h: the target config.
+ :param opr: True/False.
+ :return: generated list of commands.
+ """
+ commands = []
+ h = {}
+ if have:
+ h = have.get(attr) or {}
+ if not opr and not h:
+ commands.append(self._form_attr_cmd(attr=attr, opr=opr))
+ elif want[attr]:
+ leaf_dict = {"parameters": "router_id"}
+ leaf = leaf_dict[attr]
+ for item, value in iteritems(want[attr]):
+ if (
+ opr
+ and item in leaf
+ and not _is_w_same(want[attr], h, item)
+ ):
+ commands.append(
+ self._form_attr_cmd(
+ key=attr, attr=item, val=value, opr=opr
+ )
+ )
+ elif not opr and item in leaf and not _in_target(h, item):
+ commands.append(
+ self._form_attr_cmd(key=attr, attr=item, opr=opr)
+ )
+ return commands
+
+ def _render_list_dict_param(self, attr, want, have, cmd=None, opr=True):
+ """
+ This function forms the set/delete commands based on the 'opr' type
+ for attributes with in desired list of dictionary.
+ :param attr: attribute name.
+ :param w: the desired config.
+ :param h: the target config.
+ :param cmd: commands to be prepend.
+ :param opr: True/False.
+ :return: generated commands list.
+ """
+ commands = []
+ h = []
+ name = {
+ "redistribute": "route_type",
+ "range": "address",
+ }
+ leaf_dict = {
+ "redistribute": ("route_map", "route_type"),
+ "range": ("address", "advertise", "not_advertise"),
+ }
+ leaf = leaf_dict[attr]
+ w = want.get(attr) or []
+ if have:
+ h = have.get(attr) or []
+ if not opr and not h:
+ commands.append(self._compute_command(attr=attr, opr=opr))
+ elif w:
+ for w_item in w:
+ for key, val in iteritems(w_item):
+ if not cmd:
+ cmd = self._compute_command(opr=opr)
+ h_item = search_obj_in_list(
+ w_item[name[attr]], h, name[attr]
+ )
+ if (
+ opr
+ and key in leaf
+ and not _is_w_same(w_item, h_item, key)
+ ):
+ if key == "route_type" or (
+ key == "address"
+ and "advertise" not in w_item
+ and "not-advertise" not in w_item
+ ):
+ if not val:
+ cmd = cmd.replace("set", "delete")
+ commands.append(cmd + attr + " " + str(val))
+ elif key in leaf_dict["range"] and key != "address":
+ commands.append(
+ cmd
+ + attr
+ + " "
+ + w_item[name[attr]]
+ + " "
+ + key.replace("_", "-")
+ )
+ elif key == "route_map":
+ commands.append(
+ cmd
+ + attr
+ + " "
+ + w_item[name[attr]]
+ + " "
+ + key.replace("_", "-")
+ + " "
+ + str(val)
+ )
+ elif (
+ not opr and key in leaf and not _in_target(h_item, key)
+ ):
+ if key in ("route_type", "address"):
+ commands.append(cmd + attr + " " + str(val))
+ else:
+ commands.append(
+ cmd
+ + (attr + " " + w_item[name[attr]] + " " + key)
+ )
+ return commands
+
+ def _render_areas(self, attr, want, have, opr=True):
+ """
+ This function forms the set/delete commands based on the 'opr' type
+ for ospf area attributes.
+ :param attr: attribute name.
+ :param w: the desired config.
+ :param h: the target config.
+ :param opr: True/False.
+ :return: generated commands list.
+ """
+ commands = []
+ h_lst = {}
+ w_lst = want.get(attr) or []
+ l_set = ("area_id", "export_list", "import_list")
+ if have:
+ h_lst = have.get(attr) or []
+ if not opr and not h_lst:
+ commands.append(self._form_attr_cmd(attr="area", opr=opr))
+ elif w_lst:
+ for w_area in w_lst:
+ cmd = (
+ self._compute_command(
+ key="area",
+ attr=_bool_to_str(w_area["area_id"]),
+ opr=opr,
+ )
+ + " "
+ )
+ h_area = search_obj_in_list(
+ w_area["area_id"], h_lst, "area_id"
+ )
+ if not opr and not h_area:
+ commands.append(
+ self._form_attr_cmd(
+ key="area", attr=w_area["area_id"], opr=opr
+ )
+ )
+ else:
+ for key, val in iteritems(w_area):
+ if (
+ opr
+ and key in l_set
+ and not _is_w_same(w_area, h_area, key)
+ ):
+ if key == "area_id":
+ commands.append(
+ self._form_attr_cmd(
+ attr="area",
+ val=_bool_to_str(val),
+ opr=opr,
+ )
+ )
+ else:
+ commands.append(
+ cmd
+ + key.replace("_", "-")
+ + " "
+ + _bool_to_str(val).replace("_", "-")
+ )
+ elif not opr and key in l_set:
+ if key == "area_id" and not _in_target(
+ h_area, key
+ ):
+ commands.append(cmd)
+ continue
+ elif key != "area_id" and not _in_target(
+ h_area, key
+ ):
+ commands.append(cmd + val + " " + key)
+ elif key == "range":
+ commands.extend(
+ self._render_list_dict_param(
+ key, w_area, h_area, cmd, opr
+ )
+ )
+ return commands
+
+ def _form_attr_cmd(self, key=None, attr=None, val=None, opr=True):
+ """
+ This function forms the command for leaf attribute.
+ :param key: parent key.
+ :param attr: attribute name
+ :param value: value
+ :param opr: True/False.
+ :return: generated command.
+ """
+ return self._compute_command(
+ key, attr=self._map_attrib(attr), val=val, opr=opr
+ )
+
+ def _compute_command(
+ self, key=None, attr=None, val=None, remove=False, opr=True
+ ):
+ """
+ This function construct the add/delete command based on passed attributes.
+ :param key: parent key.
+ :param attr: attribute name
+ :param value: value
+ :param opr: True/False.
+ :return: generated command.
+ """
+ if remove or not opr:
+ cmd = "delete protocols ospfv3 "
+ else:
+ cmd = "set protocols ospfv3 "
+ if key:
+ cmd += key.replace("_", "-") + " "
+ if attr:
+ cmd += attr.replace("_", "-")
+ if val and opr:
+ cmd += " '" + str(val) + "'"
+ return cmd
+
+ def _map_attrib(self, attrib):
+ """
+ - This function construct the regex string.
+ - replace the underscore with hyphen.
+ :param attrib: attribute
+ :return: regex string
+ """
+ return "disable" if attrib == "disabled" else attrib.replace("_", "-")
diff --git a/plugins/module_utils/network/vyos/facts/facts.py b/plugins/module_utils/network/vyos/facts/facts.py
index ff3d098..3c87be6 100644
--- a/plugins/module_utils/network/vyos/facts/facts.py
+++ b/plugins/module_utils/network/vyos/facts/facts.py
@@ -40,6 +40,9 @@ from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.firew
from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.firewall_interfaces.firewall_interfaces import (
Firewall_interfacesFacts,
)
+from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.ospfv3.ospfv3 import (
+ Ospfv3Facts,
+)
from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.legacy.base import (
Default,
Neighbors,
@@ -58,6 +61,7 @@ FACT_RESOURCE_SUBSETS = dict(
firewall_rules=Firewall_rulesFacts,
firewall_global=Firewall_globalFacts,
firewall_interfaces=Firewall_interfacesFacts,
+ ospfv3=Ospfv3Facts,
)
diff --git a/plugins/module_utils/network/vyos/facts/ospfv3/__init__.py b/plugins/module_utils/network/vyos/facts/ospfv3/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/module_utils/network/vyos/facts/ospfv3/__init__.py
diff --git a/plugins/module_utils/network/vyos/facts/ospfv3/ospfv3.py b/plugins/module_utils/network/vyos/facts/ospfv3/ospfv3.py
new file mode 100644
index 0000000..457a963
--- /dev/null
+++ b/plugins/module_utils/network/vyos/facts/ospfv3/ospfv3.py
@@ -0,0 +1,213 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The vyos ospfv3 fact class
+It is in this file the configuration is collected from the device
+for a given resource, parsed, and the facts tree is populated
+based on the configuration.
+"""
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+from re import findall, search, M
+from copy import deepcopy
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import (
+ utils,
+)
+from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.ospfv3.ospfv3 import (
+ Ospfv3Args,
+)
+
+
+class Ospfv3Facts(object):
+ """ The vyos ospfv3 fact class
+ """
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = Ospfv3Args.argument_spec
+ spec = deepcopy(self.argument_spec)
+ if subspec:
+ if options:
+ facts_argument_spec = spec[subspec][options]
+ else:
+ facts_argument_spec = spec[subspec]
+ else:
+ facts_argument_spec = spec
+
+ self.generated_spec = utils.generate_dict(facts_argument_spec)
+
+ def get_device_data(self, connection):
+ return connection.get_config()
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """ Populate the facts for ospfv3
+ :param connection: the device connection
+ :param ansible_facts: Facts dictionary
+ :param data: previously collected conf
+ :rtype: dictionary
+ :returns: facts
+ """
+ if not data:
+ data = self.get_device_data(connection)
+ # typically data is populated from the current device configuration
+ # data = connection.get('show running-config | section ^interface')
+ # using mock data instead
+ objs = {}
+ ospfv3 = findall(r"^set protocols ospfv3 (.+)", data, M)
+ if ospfv3:
+ objs = self.render_config(ospfv3)
+ facts = {}
+ params = utils.validate_config(self.argument_spec, {"config": objs})
+ facts["ospfv3"] = utils.remove_empties(params["config"])
+ ansible_facts["ansible_network_resources"].update(facts)
+ return ansible_facts
+
+ def render_config(self, conf):
+ """
+ Render config as dictionary structure
+
+ :param conf: The configuration
+ :returns: The generated config
+ """
+ conf = "\n".join(filter(lambda x: x, conf))
+ config = {}
+ config["parameters"] = self.parse_attrib(
+ conf, "parameters", "parameters"
+ )
+ config["areas"] = self.parse_attrib_list(conf, "area", "area_id")
+ config["redistribute"] = self.parse_attrib_list(
+ conf, "redistribute", "route_type"
+ )
+ return config
+
+ def parse_attrib_list(self, conf, attrib, param):
+ """
+ This function forms the regex to fetch the listed attributes
+ from config
+ :param conf: configuration data
+ :param attrib: attribute name
+ :param param: parameter data
+ :return: generated rule list configuration
+ """
+ r_lst = []
+ if attrib == "area":
+ items = findall(r"^" + attrib + " (?:'*)(\\S+)(?:'*)", conf, M)
+ else:
+ items = findall(r"" + attrib + " (?:'*)(\\S+)(?:'*)", conf, M)
+ if items:
+ a_lst = []
+ for item in set(items):
+ i_regex = r" %s .+$" % item
+ cfg = "\n".join(findall(i_regex, conf, M))
+ if attrib == "area":
+ obj = self.parse_area(cfg, item)
+ else:
+ obj = self.parse_attrib(cfg, attrib)
+ obj[param] = item.strip("'")
+ if obj:
+ a_lst.append(obj)
+ r_lst = sorted(a_lst, key=lambda i: i[param])
+ return r_lst
+
+ def parse_area(self, conf, area_id):
+ """
+ This function triggers the parsing of 'area' attributes.
+ :param conf: configuration data
+ :param area_id: area identity
+ :return: generated rule configuration dictionary.
+ """
+
+ rule = self.parse_attrib(conf, "area_id", match=area_id)
+ r_sub = {"range": self.parse_attrib_list(conf, "range", "address")}
+ rule.update(r_sub)
+ return rule
+
+ def parse_attrib(self, conf, param, match=None):
+ """
+ This function triggers the parsing of 'ospf' attributes
+ :param conf: configuration data
+ :return: generated configuration dictionary
+ """
+ param_lst = {
+ "area_id": ["export_list", "import_list"],
+ "redistribute": ["route_map"],
+ "range": ["advertise", "not_advertise"],
+ "parameters": ["router_id"],
+ }
+ cfg_dict = self.parse_attr(conf, param_lst[param], match)
+ return cfg_dict
+
+ def parse_attr(self, conf, attr_list, match=None):
+ """
+ This function peforms the following:
+ - Form the regex to fetch the required attribute config.
+ - Type cast the output in desired format.
+ :param conf: configuration.
+ :param attr_list: list of attributes.
+ :param match: parent node/attribute name.
+ :return: generated config dictionary.
+ """
+ config = {}
+ for attrib in attr_list:
+ regex = self.map_regex(attrib)
+ if match:
+ regex = match.replace("_", "-") + " " + regex
+ if conf:
+ if self.is_bool(attrib):
+ out = conf.find(attrib.replace("_", "-"))
+ dis = conf.find(attrib.replace("_", "-") + " 'disable'")
+ if match:
+ en = conf.find(match + " 'enable'")
+ if out >= 1:
+ if dis >= 1:
+ config[attrib] = False
+ else:
+ config[attrib] = True
+ elif match and en >= 1:
+ config[attrib] = True
+ else:
+ out = search(r"^.*" + regex + " (.+)", conf, M)
+ if out:
+ val = out.group(1).strip("'")
+ if self.is_num(attrib):
+ val = int(val)
+ config[attrib] = val
+ return config
+
+ def map_regex(self, attrib):
+ """
+ - This function construct the regex string.
+ - replace the underscore with hyphen.
+ :param attrib: attribute
+ :return: regex string
+ """
+ return (
+ "disable"
+ if attrib == "disabled"
+ else "enable"
+ if attrib == "enabled"
+ else attrib.replace("_", "-")
+ )
+
+ def is_bool(self, attrib):
+ """
+ This function looks for the attribute in predefined bool type set.
+ :param attrib: attribute.
+ :return: True/False
+ """
+ bool_set = ("enabled", "advertise", "not_advertise")
+ return True if attrib in bool_set else False
+
+ def is_num(self, attrib):
+ """
+ This function looks for the attribute in predefined integer type set.
+ :param attrib: attribute.
+ :return: True/false.
+ """
+ num_set = "ospf"
+ return True if attrib in num_set else False
diff --git a/plugins/module_utils/network/vyos/utils/utils.py b/plugins/module_utils/network/vyos/utils/utils.py
index 4635234..96feddd 100644
--- a/plugins/module_utils/network/vyos/utils/utils.py
+++ b/plugins/module_utils/network/vyos/utils/utils.py
@@ -113,7 +113,7 @@ def get_lst_same_for_dicts(want, have, lst):
def list_diff_have_only(want_list, have_list):
- """
+ """ -
This function generated the list containing values
that are only in have list.
:param want_list:
@@ -230,3 +230,40 @@ def get_route_type(address):
return "route6"
elif version == 4:
return "route"
+
+
+def _bool_to_str(val):
+ """
+ This function converts the bool value into string.
+ :param val: bool value.
+ :return: enable/disable.
+ """
+ return (
+ "enable"
+ if str(val) == "True"
+ else "disable"
+ if str(val) == "False"
+ else val
+ )
+
+
+def _is_w_same(w, h, key):
+ """
+ This function checks whether the key value is same in desired and
+ target config dictionary.
+ :param w: base config.
+ :param h: target config.
+ :param key:attribute name.
+ :return: True/False.
+ """
+ return True if h and key in h and h[key] == w[key] else False
+
+
+def _in_target(h, key):
+ """
+ This function checks whether the target exist and key present in target config.
+ :param h: target config.
+ :param key: attribute name.
+ :return: True/False.
+ """
+ return True if h and key in h else False
diff --git a/plugins/modules/vyos_facts.py b/plugins/modules/vyos_facts.py
index 4a64066..5849519 100644
--- a/plugins/modules/vyos_facts.py
+++ b/plugins/modules/vyos_facts.py
@@ -48,7 +48,7 @@ options:
used with an initial C(M(!)) to specify that a specific subset should not be
collected. Valid subsets are 'all', 'interfaces', 'l3_interfaces', 'lag_interfaces',
'lldp_global', 'lldp_interfaces', 'static_routes', 'firewall_rules', 'firewall_global',
- 'firewall_interfaces'.
+ 'firewall_interfaces', 'ospfv3'.
required: false
"""
diff --git a/plugins/modules/vyos_ospfv3.py b/plugins/modules/vyos_ospfv3.py
new file mode 100644
index 0000000..e2d3ff7
--- /dev/null
+++ b/plugins/modules/vyos_ospfv3.py
@@ -0,0 +1,667 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Copyright 2019 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_ospfv3
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+ANSIBLE_METADATA = {"metadata_version": "1.1", "supported_by": "Ansible"}
+
+DOCUMENTATION = """
+---
+module: vyos_ospfv3
+version_added: 2.10
+short_description: OSPFV3 resource module.
+description: This resource module configures and manages attributes of OSPFv3 routes on VyOS network devices.
+version_added: "1.0.0"
+notes:
+ - Tested against VyOS 1.1.8 (helium).
+ - This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html).
+author:
+- Rohit Thakur (@rohitthakur2590)
+options:
+ config:
+ description: A provided OSPFv3 route configuration.
+ type: dict
+ suboptions:
+ areas:
+ description: OSPFv3 area.
+ type: list
+ elements: dict
+ suboptions:
+ area_id:
+ description: OSPFv3 Area name/identity.
+ type: str
+ export_list:
+ description: Name of export-list.
+ type: str
+ import_list:
+ description: Name of import-list.
+ type: str
+ range:
+ description: Summarize routes matching prefix (border routers only).
+ type: list
+ elements: dict
+ suboptions:
+ address:
+ description: border router IPv4 address.
+ type: str
+ advertise:
+ description: Advertise this range.
+ type: bool
+ not_advertise:
+ description: Don't advertise this range.
+ type: bool
+ parameters:
+ descriptions: OSPFv3 specific parameters.
+ type: dict
+ suboptions:
+ router_id:
+ description: Override the default router identifier.
+ type: str
+ redistribute:
+ description: Redistribute information from another routing protocol.
+ type: list
+ elements: dict
+ suboptions:
+ route_type:
+ description: Route type to redistribute.
+ type: str
+ choices: ['bgp', 'connected', 'kernel', 'ripng', 'static']
+ route_map:
+ description: Route map references.
+ type: str
+ running_config:
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the VyOS device by executing
+ the command B(show configuration commands | grep ospfv3).
+ - 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.
+ type: str
+ state:
+ description:
+ - The state the configuration should be left in.
+ type: str
+ choices:
+ - merged
+ - replaced
+ - deleted
+ - parsed
+ - gathered
+ - rendered
+ default: merged
+"""
+EXAMPLES = """
+# Using merged
+#
+# Before state:
+# -------------
+#
+# vyos@vyos# run show configuration commands | grep ospfv3
+#
+#
+- name: Merge the provided configuration with the exisiting running configuration
+ vyos.vyos.vyos_ospfv3:
+ config:
+ redistribute:
+ - route_type: 'bgp'
+ parameters:
+ router_id: '192.0.2.10'
+ areas:
+ - area_id: '2'
+ export_list: 'export1'
+ import_list: 'import1'
+ range:
+ - address: '2001:db10::/32'
+ - address: '2001:db20::/32'
+ - address: '2001:db30::/32'
+ - area_id: '3'
+ range:
+ - address: '2001:db40::/32'
+ state: merged
+#
+#
+# -------------------------
+# Module Execution Result
+# -------------------------
+#
+# before": {}
+#
+# "commands": [
+# "set protocols ospfv3 redistribute bgp",
+# "set protocols ospfv3 parameters router-id '192.0.2.10'",
+# "set protocols ospfv3 area 2 range 2001:db10::/32",
+# "set protocols ospfv3 area 2 range 2001:db20::/32",
+# "set protocols ospfv3 area 2 range 2001:db30::/32",
+# "set protocols ospfv3 area '2'",
+# "set protocols ospfv3 area 2 export-list export1",
+# "set protocols ospfv3 area 2 import-list import1",
+# "set protocols ospfv3 area '3'",
+# "set protocols ospfv3 area 3 range 2001:db40::/32"
+# ]
+#
+# "after": {
+# "areas": [
+# {
+# "area_id": "2",
+# "export_list": "export1",
+# "import_list": "import1",
+# "range": [
+# {
+# "address": "2001:db10::/32"
+# },
+# {
+# "address": "2001:db20::/32"
+# },
+# {
+# "address": "2001:db30::/32"
+# }
+# ]
+# },
+# {
+# "area_id": "3",
+# "range": [
+# {
+# "address": "2001:db40::/32"
+# }
+# ]
+# }
+# ],
+# "parameters": {
+# "router_id": "192.0.2.10"
+# },
+# "redistribute": [
+# {
+# "route_type": "bgp"
+# }
+# ]
+# }
+#
+# After state:
+# -------------
+#
+# vyos@192# run show configuration commands | grep ospfv3
+# set protocols ospfv3 area 2 export-list 'export1'
+# set protocols ospfv3 area 2 import-list 'import1'
+# set protocols ospfv3 area 2 range '2001:db10::/32'
+# set protocols ospfv3 area 2 range '2001:db20::/32'
+# set protocols ospfv3 area 2 range '2001:db30::/32'
+# set protocols ospfv3 area 3 range '2001:db40::/32'
+# set protocols ospfv3 parameters router-id '192.0.2.10'
+# set protocols ospfv3 redistribute 'bgp'
+
+
+# Using replaced
+#
+# Before state:
+# -------------
+#
+# vyos@192# run show configuration commands | grep ospfv3
+# set protocols ospfv3 area 2 export-list 'export1'
+# set protocols ospfv3 area 2 import-list 'import1'
+# set protocols ospfv3 area 2 range '2001:db10::/32'
+# set protocols ospfv3 area 2 range '2001:db20::/32'
+# set protocols ospfv3 area 2 range '2001:db30::/32'
+# set protocols ospfv3 area 3 range '2001:db40::/32'
+# set protocols ospfv3 parameters router-id '192.0.2.10'
+# set protocols ospfv3 redistribute 'bgp'
+#
+- name: Replace ospfv3 routes attributes configuration.
+ vyos.vyos.vyos_ospfv3:
+ config:
+ redistribute:
+ - route_type: 'bgp'
+ parameters:
+ router_id: '192.0.2.10'
+ areas:
+ - area_id: '2'
+ export_list: 'export1'
+ import_list: 'import1'
+ range:
+ - address: '2001:db10::/32'
+ - address: '2001:db30::/32'
+ - address: '2001:db50::/32'
+ - area_id: '4'
+ range:
+ - address: '2001:db60::/32'
+ state: replaced
+#
+#
+# -------------------------
+# Module Execution Result
+# -------------------------
+#
+# "before": {
+# "areas": [
+# {
+# "area_id": "2",
+# "export_list": "export1",
+# "import_list": "import1",
+# "range": [
+# {
+# "address": "2001:db10::/32"
+# },
+# {
+# "address": "2001:db20::/32"
+# },
+# {
+# "address": "2001:db30::/32"
+# }
+# ]
+# },
+# {
+# "area_id": "3",
+# "range": [
+# {
+# "address": "2001:db40::/32"
+# }
+# ]
+# }
+# ],
+# "parameters": {
+# "router_id": "192.0.2.10"
+# },
+# "redistribute": [
+# {
+# "route_type": "bgp"
+# }
+# ]
+# }
+#
+# "commands": [
+# "delete protocols ospfv3 area 2 range 2001:db20::/32",
+# "delete protocols ospfv3 area 3",
+# "set protocols ospfv3 area 2 range 2001:db50::/32",
+# "set protocols ospfv3 area '4'",
+# "set protocols ospfv3 area 4 range 2001:db60::/32"
+# ]
+#
+# "after": {
+# "areas": [
+# {
+# "area_id": "2",
+# "export_list": "export1",
+# "import_list": "import1",
+# "range": [
+# {
+# "address": "2001:db10::/32"
+# },
+# {
+# "address": "2001:db30::/32"
+# },
+# {
+# "address": "2001:db50::/32"
+# }
+# ]
+# },
+# {
+# "area_id": "4",
+# "range": [
+# {
+# "address": "2001:db60::/32"
+# }
+# ]
+# }
+# ],
+# "parameters": {
+# "router_id": "192.0.2.10"
+# },
+# "redistribute": [
+# {
+# "route_type": "bgp"
+# }
+# ]
+# }
+#
+# After state:
+# -------------
+#
+# vyos@192# run show configuration commands | grep ospfv3
+# set protocols ospfv3 area 2 export-list 'export1'
+# set protocols ospfv3 area 2 import-list 'import1'
+# set protocols ospfv3 area 2 range '2001:db10::/32'
+# set protocols ospfv3 area 2 range '2001:db30::/32'
+# set protocols ospfv3 area 2 range '2001:db50::/32'
+# set protocols ospfv3 area 4 range '2001:db60::/32'
+# set protocols ospfv3 parameters router-id '192.0.2.10'
+# set protocols ospfv3 redistribute 'bgp'
+
+
+# Using rendered
+#
+#
+- name: Render the commands for provided configuration
+ vyos.vyos.vyos_ospfv3:
+ config:
+ redistribute:
+ - route_type: 'bgp'
+ parameters:
+ router_id: '192.0.2.10'
+ areas:
+ - area_id: '2'
+ export_list: 'export1'
+ import_list: 'import1'
+ range:
+ - address: '2001:db10::/32'
+ - address: '2001:db20::/32'
+ - address: '2001:db30::/32'
+ - area_id: '3'
+ range:
+ - address: '2001:db40::/32'
+ state: rendered
+#
+#
+# -------------------------
+# Module Execution Result
+# -------------------------
+#
+#
+# "rendered": [
+# [
+# "set protocols ospfv3 redistribute bgp",
+# "set protocols ospfv3 parameters router-id '192.0.2.10'",
+# "set protocols ospfv3 area 2 range 2001:db10::/32",
+# "set protocols ospfv3 area 2 range 2001:db20::/32",
+# "set protocols ospfv3 area 2 range 2001:db30::/32",
+# "set protocols ospfv3 area '2'",
+# "set protocols ospfv3 area 2 export-list export1",
+# "set protocols ospfv3 area 2 import-list import1",
+# "set protocols ospfv3 area '3'",
+# "set protocols ospfv3 area 3 range 2001:db40::/32"
+# ]
+
+
+# Using parsed
+#
+#
+- name: Parse the commands to provide structured configuration.
+ vyos.vyos.vyos_ospfv3:
+ running_config:
+ "set protocols ospfv3 area 2 export-list 'export1'
+set protocols ospfv3 area 2 import-list 'import1'
+set protocols ospfv3 area 2 range '2001:db10::/32'
+set protocols ospfv3 area 2 range '2001:db20::/32'
+set protocols ospfv3 area 2 range '2001:db30::/32'
+set protocols ospfv3 area 3 range '2001:db40::/32'
+set protocols ospfv3 parameters router-id '192.0.2.10'
+set protocols ospfv3 redistribute 'bgp'"
+ state: parsed
+#
+#
+# -------------------------
+# Module Execution Result
+# -------------------------
+#
+#
+# "parsed": {
+# "areas": [
+# {
+# "area_id": "2",
+# "export_list": "export1",
+# "import_list": "import1",
+# "range": [
+# {
+# "address": "2001:db10::/32"
+# },
+# {
+# "address": "2001:db20::/32"
+# },
+# {
+# "address": "2001:db30::/32"
+# }
+# ]
+# },
+# {
+# "area_id": "3",
+# "range": [
+# {
+# "address": "2001:db40::/32"
+# }
+# ]
+# }
+# ],
+# "parameters": {
+# "router_id": "192.0.2.10"
+# },
+# "redistribute": [
+# {
+# "route_type": "bgp"
+# }
+# ]
+# }
+
+
+# Using gathered
+#
+# Before state:
+# -------------
+#
+# vyos@192# run show configuration commands | grep ospfv3
+# set protocols ospfv3 area 2 export-list 'export1'
+# set protocols ospfv3 area 2 import-list 'import1'
+# set protocols ospfv3 area 2 range '2001:db10::/32'
+# set protocols ospfv3 area 2 range '2001:db20::/32'
+# set protocols ospfv3 area 2 range '2001:db30::/32'
+# set protocols ospfv3 area 3 range '2001:db40::/32'
+# set protocols ospfv3 parameters router-id '192.0.2.10'
+# set protocols ospfv3 redistribute 'bgp'
+#
+- name: Gather ospfv3 routes config with provided configurations
+ vyos.vyos.vyos_ospfv3:
+ config:
+ state: gathered
+#
+#
+# -------------------------
+# Module Execution Result
+# -------------------------
+#
+# "gathered": {
+# "areas": [
+# {
+# "area_id": "2",
+# "export_list": "export1",
+# "import_list": "import1",
+# "range": [
+# {
+# "address": "2001:db10::/32"
+# },
+# {
+# "address": "2001:db20::/32"
+# },
+# {
+# "address": "2001:db30::/32"
+# }
+# ]
+# },
+# {
+# "area_id": "3",
+# "range": [
+# {
+# "address": "2001:db40::/32"
+# }
+# ]
+# }
+# ],
+# "parameters": {
+# "router_id": "192.0.2.10"
+# },
+# "redistribute": [
+# {
+# "route_type": "bgp"
+# }
+# ]
+# }
+#
+# After state:
+# -------------
+#
+# vyos@192# run show configuration commands | grep ospfv3
+# set protocols ospfv3 area 2 export-list 'export1'
+# set protocols ospfv3 area 2 import-list 'import1'
+# set protocols ospfv3 area 2 range '2001:db10::/32'
+# set protocols ospfv3 area 2 range '2001:db20::/32'
+# set protocols ospfv3 area 2 range '2001:db30::/32'
+# set protocols ospfv3 area 3 range '2001:db40::/32'
+# set protocols ospfv3 parameters router-id '192.0.2.10'
+# set protocols ospfv3 redistribute 'bgp'
+
+
+# Using deleted
+#
+# Before state
+# -------------
+#
+# vyos@192# run show configuration commands | grep ospfv3
+# set protocols ospfv3 area 2 export-list 'export1'
+# set protocols ospfv3 area 2 import-list 'import1'
+# set protocols ospfv3 area 2 range '2001:db10::/32'
+# set protocols ospfv3 area 2 range '2001:db20::/32'
+# set protocols ospfv3 area 2 range '2001:db30::/32'
+# set protocols ospfv3 area 3 range '2001:db40::/32'
+# set protocols ospfv3 parameters router-id '192.0.2.10'
+# set protocols ospfv3 redistribute 'bgp'
+#
+- name: Delete attributes of ospfv3 routes.
+ vyos.vyos.vyos_ospfv3:
+ config:
+ state: deleted
+#
+#
+# ------------------------
+# Module Execution Results
+# ------------------------
+#
+# "before": {
+# "areas": [
+# {
+# "area_id": "2",
+# "export_list": "export1",
+# "import_list": "import1",
+# "range": [
+# {
+# "address": "2001:db10::/32"
+# },
+# {
+# "address": "2001:db20::/32"
+# },
+# {
+# "address": "2001:db30::/32"
+# }
+# ]
+# },
+# {
+# "area_id": "3",
+# "range": [
+# {
+# "address": "2001:db40::/32"
+# }
+# ]
+# }
+# ],
+# "parameters": {
+# "router_id": "192.0.2.10"
+# },
+# "redistribute": [
+# {
+# "route_type": "bgp"
+# }
+# ]
+# }
+# "commands": [
+# "delete protocols ospfv3"
+# ]
+#
+# "after": {}
+# After state
+# ------------
+# vyos@192# run show configuration commands | grep ospfv3
+
+
+"""
+RETURN = """
+before:
+ description: The configuration prior to the model invocation.
+ returned: always
+ type: dict
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+after:
+ description: The resulting configuration model invocation.
+ returned: when changed
+ type: dict
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+commands:
+ description: The set of commands pushed to the remote device.
+ returned: always
+ type: list
+ sample: ['set protocols ospf parameters router-id 192.0.1.1',
+ 'set protocols ospfv3 area 2 range '2001:db10::/32']
+"""
+
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.ospfv3.ospfv3 import (
+ Ospfv3Args,
+)
+from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.config.ospfv3.ospfv3 import (
+ Ospfv3,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: the result form module invocation
+ """
+ required_if = [
+ ("state", "merged", ("config",)),
+ ("state", "replaced", ("config",)),
+ ("state", "rendered", ("config",)),
+ ("state", "parsed", ("running_config",)),
+ ]
+ mutually_exclusive = [("config", "running_config")]
+ module = AnsibleModule(
+ argument_spec=Ospfv3Args.argument_spec,
+ required_if=required_if,
+ supports_check_mode=True,
+ mutually_exclusive=mutually_exclusive,
+ )
+
+ result = Ospfv3(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tests/integration/targets/vyos_ospfv3/defaults/main.yaml b/tests/integration/targets/vyos_ospfv3/defaults/main.yaml
new file mode 100644
index 0000000..852a6be
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv3/defaults/main.yaml
@@ -0,0 +1,3 @@
+---
+testcase: '[^_].*'
+test_items: []
diff --git a/tests/integration/targets/vyos_ospfv3/meta/main.yaml b/tests/integration/targets/vyos_ospfv3/meta/main.yaml
new file mode 100644
index 0000000..7413320
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv3/meta/main.yaml
@@ -0,0 +1,3 @@
+---
+dependencies:
+ - prepare_vyos_tests
diff --git a/tests/integration/targets/vyos_ospfv3/tasks/cli.yaml b/tests/integration/targets/vyos_ospfv3/tasks/cli.yaml
new file mode 100644
index 0000000..93eb2fe
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv3/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_ospfv3/tasks/main.yaml b/tests/integration/targets/vyos_ospfv3/tasks/main.yaml
new file mode 100644
index 0000000..a3db933
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv3/tasks/main.yaml
@@ -0,0 +1,4 @@
+---
+- include: cli.yaml
+ tags:
+ - cli
diff --git a/tests/integration/targets/vyos_ospfv3/tests/cli/_parsed_config.cfg b/tests/integration/targets/vyos_ospfv3/tests/cli/_parsed_config.cfg
new file mode 100644
index 0000000..5e012d5
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv3/tests/cli/_parsed_config.cfg
@@ -0,0 +1,8 @@
+set protocols ospfv3 area 2 export-list 'export1'
+set protocols ospfv3 area 2 import-list 'import1'
+set protocols ospfv3 area 2 range '2001:db10::/32'
+set protocols ospfv3 area 2 range '2001:db20::/32'
+set protocols ospfv3 area 2 range '2001:db30::/32'
+set protocols ospfv3 area 3 range '2001:db40::/32'
+set protocols ospfv3 parameters router-id '192.0.2.10'
+set protocols ospfv3 redistribute 'bgp'
diff --git a/tests/integration/targets/vyos_ospfv3/tests/cli/_populate.yaml b/tests/integration/targets/vyos_ospfv3/tests/cli/_populate.yaml
new file mode 100644
index 0000000..fb66d0a
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv3/tests/cli/_populate.yaml
@@ -0,0 +1,13 @@
+---
+- name: Setup
+ vars:
+ lines: "set protocols ospfv3 area 2 export-list 'export1' \n
+ set protocols ospfv3 area 2 import-list 'import1' \n
+ set protocols ospfv3 area 2 range '2001:db10::/32' \n
+ set protocols ospfv3 area 2 range '2001:db20::/32' \n
+ set protocols ospfv3 area 2 range '2001:db30::/32' \n
+ set protocols ospfv3 area 3 range '2001:db40::/32' \n
+ set protocols ospfv3 parameters router-id '192.0.2.10' \n
+ set protocols ospfv3 redistribute 'bgp'"
+ ansible.netcommon.cli_config:
+ config: '{{ lines }}'
diff --git a/tests/integration/targets/vyos_ospfv3/tests/cli/_remove_config.yaml b/tests/integration/targets/vyos_ospfv3/tests/cli/_remove_config.yaml
new file mode 100644
index 0000000..2a47505
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv3/tests/cli/_remove_config.yaml
@@ -0,0 +1,6 @@
+---
+- name: Remove Config
+ vars:
+ lines: "delete protocols ospfv3\n"
+ ansible.netcommon.cli_config:
+ config: '{{ lines }}'
diff --git a/tests/integration/targets/vyos_ospfv3/tests/cli/deleted.yaml b/tests/integration/targets/vyos_ospfv3/tests/cli/deleted.yaml
new file mode 100644
index 0000000..55bec18
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv3/tests/cli/deleted.yaml
@@ -0,0 +1,48 @@
+---
+- debug:
+ msg: Start vyos_ospfv3 deleted integration tests ansible_connection={{
+ ansible_connection }}
+
+- include_tasks: _populate.yaml
+
+- block:
+
+ - name: Delete ospfv3 routes
+ register: result
+ vyos.vyos.vyos_ospfv3: &id001
+ config:
+ state: deleted
+
+ - name: Assert that the before dicts were correctly generated
+ assert:
+ that:
+ - "{{ populate == result['before'] }}"
+
+ - name: Assert that the correct set of commands were generated
+ assert:
+ that:
+ - "{{ deleted['commands'] | symmetric_difference(result['commands']) |length\
+ \ == 0 }}"
+
+ - name: Assert that the after dicts were correctly generated
+ assert:
+ that:
+ - "{{ deleted['after'] == result['after'] }}"
+
+ - name: Delete ospfv3 routes (IDEMPOTENT)
+ register: result
+ vyos.vyos.vyos_ospfv3: *id001
+
+ - name: Assert that the previous task was idempotent
+ assert:
+ that:
+ - result.changed == false
+ - result.commands|length == 0
+
+ - name: Assert that the before dicts were correctly generated
+ assert:
+ that:
+ - "{{ deleted['after'] == result['before'] }}"
+ always:
+
+ - include_tasks: _remove_config.yaml
diff --git a/tests/integration/targets/vyos_ospfv3/tests/cli/empty_config.yaml b/tests/integration/targets/vyos_ospfv3/tests/cli/empty_config.yaml
new file mode 100644
index 0000000..fec61ab
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv3/tests/cli/empty_config.yaml
@@ -0,0 +1,49 @@
+---
+- debug:
+ msg: START vyos_ospfv3 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_ospfv3:
+ 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_ospfv3:
+ config:
+ state: replaced
+
+- assert:
+ that:
+ - result.msg == 'value of config parameter must not be empty for state replaced'
+
+- name: Parsed with empty running_config should give appropriate error message
+ register: result
+ ignore_errors: true
+ vyos.vyos.vyos_ospfv3:
+ 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_ospfv3:
+ 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_ospfv3/tests/cli/gathered.yaml b/tests/integration/targets/vyos_ospfv3/tests/cli/gathered.yaml
new file mode 100644
index 0000000..6645b99
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv3/tests/cli/gathered.yaml
@@ -0,0 +1,25 @@
+---
+- debug:
+ msg: START vyos_ospfv3 gathered integration tests on connection={{
+ ansible_connection }}
+
+- include_tasks: _remove_config.yaml
+
+- include_tasks: _populate.yaml
+
+- block:
+
+ - name: Gather the provided configuration with the exisiting running configuration
+ register: result
+ vyos.vyos.vyos_ospfv3:
+ config:
+ state: gathered
+
+ - name: Assert that gathered dicts was correctly generated
+ assert:
+ that:
+ - "{{ populate == result['gathered'] }}"
+
+ always:
+
+ - include_tasks: _remove_config.yaml
diff --git a/tests/integration/targets/vyos_ospfv3/tests/cli/merged.yaml b/tests/integration/targets/vyos_ospfv3/tests/cli/merged.yaml
new file mode 100644
index 0000000..9309500
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv3/tests/cli/merged.yaml
@@ -0,0 +1,62 @@
+---
+- debug:
+ msg: START vyos_ospfv3 merged integration tests on connection={{ ansible_connection
+ }}
+
+- include_tasks: _remove_config.yaml
+
+- block:
+
+ - name: Merge the provided configuration with the exisiting running configuration
+ register: result
+ vyos.vyos.vyos_ospfv3: &id001
+ config:
+ areas:
+ - area_id: '2'
+ export_list: 'export1'
+ import_list: 'import1'
+ range:
+ - address: '2001:db10::/32'
+ - address: '2001:db20::/32'
+ - address: '2001:db30::/32'
+ - area_id: '3'
+ range:
+ - address: '2001:db40::/32'
+ parameters:
+ router_id: '192.0.2.10'
+ redistribute:
+ - route_type: 'bgp'
+ state: merged
+
+ - name: Assert that before dicts were correctly generated
+ assert:
+ that: "{{ merged['before'] == result['before'] }}"
+
+ - name: Assert that correct set of commands were generated
+ assert:
+ that:
+ - "{{ merged['commands'] | symmetric_difference(result['commands']) |length\
+ \ == 0 }}"
+
+ - name: Assert that after dicts was correctly generated
+ assert:
+ that:
+ - "{{ merged['after'] == result['after'] }}"
+
+ - name: Merge the provided configuration with the existing running configuration
+ (IDEMPOTENT)
+ register: result
+ vyos.vyos.vyos_ospfv3: *id001
+
+ - name: Assert that the previous task was idempotent
+ assert:
+ that:
+ - result['changed'] == false
+
+ - name: Assert that before dicts were correctly generated
+ assert:
+ that:
+ - "{{ merged['after'] == result['before'] }}"
+ always:
+
+ - include_tasks: _remove_config.yaml
diff --git a/tests/integration/targets/vyos_ospfv3/tests/cli/merged_update.yaml b/tests/integration/targets/vyos_ospfv3/tests/cli/merged_update.yaml
new file mode 100644
index 0000000..0d506b3
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv3/tests/cli/merged_update.yaml
@@ -0,0 +1,61 @@
+---
+- debug:
+ msg: START vyos_ospfv3 merged integration tests on connection={{ ansible_connection
+ }}
+
+- include_tasks: _remove_config.yaml
+
+- include_tasks: _populate.yaml
+
+- block:
+
+ - name: Merge the provided configuration with the exisiting running configuration
+ register: result
+ vyos.vyos.vyos_ospfv3: &id001
+ config:
+ areas:
+ - area_id: '2'
+ range:
+ - address: '2001:db10::/32'
+ - area_id: '3'
+ range:
+ - address: '2001:db40::/32'
+ - address: '2001:db70::/32'
+ parameters:
+ router_id: '192.0.2.10'
+ redistribute:
+ - route_type: 'bgp'
+ state: merged
+
+ - name: Assert that before dicts were correctly generated
+ assert:
+ that: "{{ populate == result['before'] }}"
+
+ - name: Assert that correct set of commands were generated
+ assert:
+ that:
+ - "{{ merged_update['commands'] | symmetric_difference(result['commands']) |length\
+ \ == 0 }}"
+
+ - name: Assert that after dicts was correctly generated
+ assert:
+ that:
+ - "{{ merged_update['after'] == result['after'] }}"
+
+ - name: Merge the provided configuration with the existing running configuration
+ (IDEMPOTENT)
+ register: result
+ vyos.vyos.vyos_ospfv3: *id001
+
+ - name: Assert that the previous task was idempotent
+ assert:
+ that:
+ - result['changed'] == false
+
+ - name: Assert that before dicts were correctly generated
+ assert:
+ that:
+ - "{{ merged_update['after'] == result['before'] }}"
+ always:
+
+ - include_tasks: _remove_config.yaml
diff --git a/tests/integration/targets/vyos_ospfv3/tests/cli/parsed.yaml b/tests/integration/targets/vyos_ospfv3/tests/cli/parsed.yaml
new file mode 100644
index 0000000..6287083
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv3/tests/cli/parsed.yaml
@@ -0,0 +1,15 @@
+---
+- debug:
+ msg: START vyos_ospfv3 parsed integration tests on connection={{ ansible_connection
+ }}
+
+- name: Parse externally provided ospfv3 config to agnostic model
+ register: result
+ vyos.vyos.vyos_ospfv3:
+ running_config: "{{ lookup('file', '_parsed_config.cfg') }}"
+ state: parsed
+
+- name: Assert that config was correctly parsed
+ assert:
+ that:
+ - "{{ parsed['after'] == result['parsed'] }}"
diff --git a/tests/integration/targets/vyos_ospfv3/tests/cli/rendered.yaml b/tests/integration/targets/vyos_ospfv3/tests/cli/rendered.yaml
new file mode 100644
index 0000000..3f714ce
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv3/tests/cli/rendered.yaml
@@ -0,0 +1,38 @@
+---
+- debug:
+ msg: START vyos_ospfv3 rendered integration tests on connection={{
+ ansible_connection }}
+
+- include_tasks: _remove_config.yaml
+
+- block:
+
+ - name: Structure provided configuration into device specific commands
+ register: result
+ vyos.vyos.vyos_ospfv3:
+ config:
+ redistribute:
+ - route_type: 'bgp'
+ parameters:
+ router_id: '192.0.2.10'
+ areas:
+ - area_id: '2'
+ export_list: 'export1'
+ import_list: 'import1'
+ range:
+ - address: '2001:db10::/32'
+ - address: '2001:db20::/32'
+ - address: '2001:db30::/32'
+ - area_id: '3'
+ range:
+ - address: '2001:db40::/32'
+ state: rendered
+
+ - name: Assert that correct set of commands were generated
+ assert:
+ that:
+ - "{{ rendered['commands'] | symmetric_difference(result['rendered'])\
+ \ |length == 0 }}"
+
+- debug:
+ msg: END vyos_ospfv3 rendered integration tests on connection={{ ansible_connection }}
diff --git a/tests/integration/targets/vyos_ospfv3/tests/cli/replaced.yaml b/tests/integration/targets/vyos_ospfv3/tests/cli/replaced.yaml
new file mode 100644
index 0000000..74d25db
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv3/tests/cli/replaced.yaml
@@ -0,0 +1,66 @@
+---
+- debug:
+ msg: START vyos_ospfv3 replaced integration tests on connection={{
+ ansible_connection }}
+
+- include_tasks: _remove_config.yaml
+
+- include_tasks: _populate.yaml
+
+- block:
+
+ - name: Replace device configurations of listed ospfv3 routes with provided configurations
+ register: result
+ vyos.vyos.vyos_ospfv3: &id001
+ config:
+ redistribute:
+ - route_type: 'bgp'
+ parameters:
+ router_id: '192.0.2.10'
+ areas:
+ - area_id: '2'
+ export_list: 'export1'
+ import_list: 'import1'
+
+ range:
+ - address: '2001:db10::/32'
+ - address: '2001:db30::/32'
+ - address: '2001:db50::/32'
+ - area_id: '4'
+ range:
+ - address: '2001:db60::/32'
+ state: replaced
+
+ - name: Assert that correct set of commands were generated
+ assert:
+ that:
+ - "{{ replaced['commands'] | symmetric_difference(result['commands'])\
+ \ |length == 0 }}"
+
+ - name: Assert that before dicts are correctly generated
+ assert:
+ that:
+ - "{{ populate == result['before'] }}"
+
+ - name: Assert that after dict is correctly generated
+ assert:
+ that:
+ - "{{ replaced['after'] == result['after'] }}"
+
+ - name: Replace device configurations of listed ospfv3 routes with provided configurarions
+ (IDEMPOTENT)
+ register: result
+ vyos.vyos.vyos_ospfv3: *id001
+
+ - name: Assert that task was idempotent
+ assert:
+ that:
+ - result['changed'] == false
+
+ - name: Assert that before dict is correctly generated
+ assert:
+ that:
+ - "{{ replaced['after'] == result['before'] }}"
+ always:
+
+ - include_tasks: _remove_config.yaml
diff --git a/tests/integration/targets/vyos_ospfv3/tests/cli/rtt.yaml b/tests/integration/targets/vyos_ospfv3/tests/cli/rtt.yaml
new file mode 100644
index 0000000..d817554
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv3/tests/cli/rtt.yaml
@@ -0,0 +1,75 @@
+---
+- debug:
+ msg: START vyos_ospfv3 round trip integration tests on connection={{
+ ansible_connection }}
+
+- include_tasks: _remove_config.yaml
+
+- block:
+
+ - name: Apply the provided configuration (base config)
+ register: base_config
+ vyos.vyos.vyos_ospfv3:
+ config:
+ areas:
+ - area_id: '2'
+ export_list: 'export1'
+ import_list: 'import1'
+ range:
+ - address: '2001:db10::/32'
+ - address: '2001:db20::/32'
+ - address: '2001:db30::/32'
+ - area_id: '3'
+ range:
+ - address: '2001:db40::/32'
+ parameters:
+ router_id: '192.0.2.10'
+ redistribute:
+ - route_type: 'bgp'
+ state: merged
+
+ - name: Gather ospfv3 facts
+ vyos.vyos.vyos_facts:
+ gather_subset:
+ - default
+ gather_network_resources:
+ - ospfv3
+
+ - name: Apply the provided configuration (config to be reverted)
+ register: result
+ vyos.vyos.vyos_ospfv3:
+ config:
+ redistribute:
+ - route_type: 'bgp'
+ parameters:
+ router_id: '192.0.2.10'
+ areas:
+ - area_id: '2'
+ export_list: 'export1'
+ import_list: 'import1'
+
+ range:
+ - address: '2001:db10::/32'
+ - address: '2001:db30::/32'
+ - address: '2001:db50::/32'
+ - area_id: '4'
+ range:
+ - address: '2001:db60::/32'
+ state: replaced
+
+ - name: Assert that changes were applied
+ assert:
+ that: "{{ round_trip['after'] == result['after'] }}"
+
+ - name: Revert back to base config using facts round trip
+ register: revert
+ vyos.vyos.vyos_ospfv3:
+ config: "{{ ansible_facts['network_resources']['ospfv3'] }}"
+ state: replaced
+
+ - name: Assert that config was reverted
+ assert:
+ that: "{{ base_config['after'] == revert['after']}}"
+ always:
+
+ - include_tasks: _remove_config.yaml
diff --git a/tests/integration/targets/vyos_ospfv3/vars/main.yaml b/tests/integration/targets/vyos_ospfv3/vars/main.yaml
new file mode 100644
index 0000000..6ded89a
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv3/vars/main.yaml
@@ -0,0 +1,142 @@
+---
+merged:
+ before: {}
+ commands:
+ - set protocols ospfv3 redistribute bgp
+ - set protocols ospfv3 parameters router-id '192.0.2.10'
+ - set protocols ospfv3 area 2 range 2001:db10::/32
+ - set protocols ospfv3 area 2 range 2001:db20::/32
+ - set protocols ospfv3 area 2 range 2001:db30::/32
+ - set protocols ospfv3 area '2'
+ - set protocols ospfv3 area 2 export-list export1
+ - set protocols ospfv3 area 2 import-list import1
+ - set protocols ospfv3 area '3'
+ - set protocols ospfv3 area 3 range 2001:db40::/32
+ after:
+ areas:
+ - area_id: '2'
+ export_list: 'export1'
+ import_list: 'import1'
+ range:
+ - address: '2001:db10::/32'
+ - address: '2001:db20::/32'
+ - address: '2001:db30::/32'
+ - area_id: '3'
+ range:
+ - address: '2001:db40::/32'
+ parameters:
+ router_id: '192.0.2.10'
+ redistribute:
+ - route_type: 'bgp'
+
+
+merged_update:
+ commands:
+ - set protocols ospfv3 area 3 range 2001:db70::/32
+ after:
+ areas:
+ - area_id: '2'
+ export_list: 'export1'
+ import_list: 'import1'
+ range:
+ - address: '2001:db10::/32'
+ - address: '2001:db20::/32'
+ - address: '2001:db30::/32'
+ - area_id: '3'
+ range:
+ - address: '2001:db40::/32'
+ - address: '2001:db70::/32'
+ parameters:
+ router_id: '192.0.2.10'
+ redistribute:
+ - route_type: 'bgp'
+
+populate:
+ areas:
+ - area_id: '2'
+ export_list: 'export1'
+ import_list: 'import1'
+ range:
+ - address: '2001:db10::/32'
+ - address: '2001:db20::/32'
+ - address: '2001:db30::/32'
+ - area_id: '3'
+ range:
+ - address: '2001:db40::/32'
+ parameters:
+ router_id: '192.0.2.10'
+ redistribute:
+ - route_type: 'bgp'
+replaced:
+ commands:
+ - delete protocols ospfv3 area 2 range 2001:db20::/32
+ - delete protocols ospfv3 area 3
+ - set protocols ospfv3 area 2 range 2001:db50::/32
+ - set protocols ospfv3 area '4'
+ - set protocols ospfv3 area 4 range 2001:db60::/32
+ after:
+ areas:
+ - area_id: '2'
+ export_list: 'export1'
+ import_list: 'import1'
+ range:
+ - address: '2001:db10::/32'
+ - address: '2001:db30::/32'
+ - address: '2001:db50::/32'
+ - area_id: '4'
+ range:
+ - address: '2001:db60::/32'
+ parameters:
+ router_id: '192.0.2.10'
+ redistribute:
+ - route_type: 'bgp'
+rendered:
+ commands:
+ - set protocols ospfv3 redistribute bgp
+ - set protocols ospfv3 parameters router-id '192.0.2.10'
+ - set protocols ospfv3 area 2 range 2001:db10::/32
+ - set protocols ospfv3 area 2 range 2001:db20::/32
+ - set protocols ospfv3 area 2 range 2001:db30::/32
+ - set protocols ospfv3 area '2'
+ - set protocols ospfv3 area 2 export-list export1
+ - set protocols ospfv3 area 2 import-list import1
+ - set protocols ospfv3 area '3'
+ - set protocols ospfv3 area 3 range 2001:db40::/32
+parsed:
+ after:
+ areas:
+ - area_id: '2'
+ export_list: 'export1'
+ import_list: 'import1'
+ range:
+ - address: '2001:db10::/32'
+ - address: '2001:db20::/32'
+ - address: '2001:db30::/32'
+ - area_id: '3'
+ range:
+ - address: '2001:db40::/32'
+ parameters:
+ router_id: '192.0.2.10'
+ redistribute:
+ - route_type: 'bgp'
+deleted:
+ commands:
+ - 'delete protocols ospfv3'
+ after: {}
+round_trip:
+ after:
+ areas:
+ - area_id: '2'
+ export_list: 'export1'
+ import_list: 'import1'
+ range:
+ - address: '2001:db10::/32'
+ - address: '2001:db30::/32'
+ - address: '2001:db50::/32'
+ - area_id: '4'
+ range:
+ - address: '2001:db60::/32'
+ parameters:
+ router_id: '192.0.2.10'
+ redistribute:
+ - route_type: 'bgp'
diff --git a/tests/unit/modules/network/vyos/fixtures/vyos_ospfv3_config.cfg b/tests/unit/modules/network/vyos/fixtures/vyos_ospfv3_config.cfg
new file mode 100644
index 0000000..060b9b3
--- /dev/null
+++ b/tests/unit/modules/network/vyos/fixtures/vyos_ospfv3_config.cfg
@@ -0,0 +1,6 @@
+set protocols ospfv3 area 12 export-list 'export1'
+set protocols ospfv3 area 12 import-list 'import1'
+set protocols ospfv3 area 12 range '2001:db11::/32'
+set protocols ospfv3 area 12 range '2001:db22::/32'
+set protocols ospfv3 area 12 range '2001:db33::/32'
+set protocols ospfv3 area 13 range '2001:db44::/32' \ No newline at end of file
diff --git a/tests/unit/modules/network/vyos/test_vyos_ospfv3.py b/tests/unit/modules/network/vyos/test_vyos_ospfv3.py
new file mode 100644
index 0000000..1d9cb3a
--- /dev/null
+++ b/tests/unit/modules/network/vyos/test_vyos_ospfv3.py
@@ -0,0 +1,348 @@
+# (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_ospfv3
+from ansible_collections.vyos.vyos.tests.unit.modules.utils import (
+ set_module_args,
+)
+from .vyos_module import TestVyosModule, load_fixture
+
+
+class TestVyosFirewallRulesModule(TestVyosModule):
+
+ module = vyos_ospfv3
+
+ def setUp(self):
+ super(TestVyosFirewallRulesModule, self).setUp()
+ self.mock_get_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.get_config"
+ )
+ self.get_config = self.mock_get_config.start()
+
+ self.mock_load_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.load_config"
+ )
+ self.load_config = self.mock_load_config.start()
+
+ self.mock_get_resource_connection_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base.get_resource_connection"
+ )
+ self.get_resource_connection_config = (
+ self.mock_get_resource_connection_config.start()
+ )
+
+ self.mock_get_resource_connection_facts = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts.get_resource_connection"
+ )
+ self.get_resource_connection_facts = (
+ self.mock_get_resource_connection_facts.start()
+ )
+
+ self.mock_execute_show_command = patch(
+ "ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.ospfv3.ospfv3.Ospfv3Facts.get_device_data"
+ )
+
+ self.execute_show_command = self.mock_execute_show_command.start()
+
+ def tearDown(self):
+ super(TestVyosFirewallRulesModule, self).tearDown()
+ self.mock_get_resource_connection_config.stop()
+ self.mock_get_resource_connection_facts.stop()
+ self.mock_get_config.stop()
+ self.mock_load_config.stop()
+ self.mock_execute_show_command.stop()
+
+ def load_fixtures(self, commands=None, transport="cli", filename=None):
+ if filename is None:
+ filename = "vyos_ospfv3_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_ospfv3_merged_new_config(self):
+ set_module_args(
+ dict(
+ config=dict(
+ redistribute=[dict(route_type="bgp")],
+ parameters=dict(router_id="192.0.2.10"),
+ areas=[
+ dict(
+ area_id="2",
+ export_list="export1",
+ import_list="import1",
+ range=[
+ dict(address="2001:db10::/32"),
+ dict(address="2001:db20::/32"),
+ dict(address="2001:db30::/32"),
+ ],
+ ),
+ dict(
+ area_id="3",
+ range=[dict(address="2001:db40::/32"),],
+ ),
+ ],
+ ),
+ state="merged",
+ )
+ )
+ commands = [
+ "set protocols ospfv3 redistribute bgp",
+ "set protocols ospfv3 parameters router-id '192.0.2.10'",
+ "set protocols ospfv3 area 2 range 2001:db10::/32",
+ "set protocols ospfv3 area 2 range 2001:db20::/32",
+ "set protocols ospfv3 area 2 range 2001:db30::/32",
+ "set protocols ospfv3 area '2'",
+ "set protocols ospfv3 area 2 export-list export1",
+ "set protocols ospfv3 area 2 import-list import1",
+ "set protocols ospfv3 area '3'",
+ "set protocols ospfv3 area 3 range 2001:db40::/32",
+ ]
+ self.execute_module(changed=True, commands=commands)
+
+ def test_vyos_ospfv3_merged_idem(self):
+ set_module_args(
+ dict(
+ config=dict(
+ areas=[
+ dict(
+ area_id="12",
+ export_list="export1",
+ import_list="import1",
+ range=[
+ dict(address="2001:db11::/32"),
+ dict(address="2001:db22::/32"),
+ dict(address="2001:db33::/32"),
+ ],
+ ),
+ dict(
+ area_id="13",
+ range=[dict(address="2001:db44::/32"),],
+ ),
+ ],
+ ),
+ state="merged",
+ )
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_vyos_ospfv3_merged_update_existing(self):
+ set_module_args(
+ dict(
+ config=dict(
+ redistribute=[dict(route_type="bgp")],
+ parameters=dict(router_id="192.0.2.10"),
+ areas=[
+ dict(
+ area_id="12",
+ export_list="export1",
+ import_list="import1",
+ range=[
+ dict(address="2001:db11::/32"),
+ dict(address="2001:db22::/32"),
+ dict(address="2001:db33::/32"),
+ ],
+ ),
+ dict(
+ area_id="13",
+ range=[
+ dict(address="2001:db44::/32"),
+ dict(address="2001:db55::/32"),
+ ],
+ ),
+ ],
+ ),
+ state="merged",
+ )
+ )
+ commands = [
+ "set protocols ospfv3 redistribute bgp",
+ "set protocols ospfv3 parameters router-id '192.0.2.10'",
+ "set protocols ospfv3 area 13 range 2001:db55::/32",
+ ]
+ self.execute_module(changed=True, commands=commands)
+
+ def test_vyos_ospfv3_replaced(self):
+ set_module_args(
+ dict(
+ config=dict(
+ redistribute=[dict(route_type="bgp")],
+ parameters=dict(router_id="192.0.2.10"),
+ areas=[
+ dict(
+ area_id="12",
+ export_list="export1",
+ import_list="import1",
+ range=[
+ dict(address="2001:db10::/32"),
+ dict(address="2001:db22::/32"),
+ dict(address="2001:db33::/32"),
+ ],
+ ),
+ dict(
+ area_id="14",
+ range=[dict(address="2001:db40::/32"),],
+ ),
+ ],
+ ),
+ state="replaced",
+ )
+ )
+ commands = [
+ "set protocols ospfv3 redistribute bgp",
+ "set protocols ospfv3 parameters router-id '192.0.2.10'",
+ "delete protocols ospfv3 area 12 range 2001:db11::/32",
+ "set protocols ospfv3 area 12 range 2001:db10::/32",
+ "delete protocols ospfv3 area 13",
+ "set protocols ospfv3 area '14'",
+ "set protocols ospfv3 area 14 range 2001:db40::/32",
+ ]
+ self.execute_module(changed=True, commands=commands)
+
+ def test_vyos_ospfv3_replaced_idem(self):
+ set_module_args(
+ dict(
+ config=dict(
+ areas=[
+ dict(
+ area_id="12",
+ export_list="export1",
+ import_list="import1",
+ range=[
+ dict(address="2001:db11::/32"),
+ dict(address="2001:db22::/32"),
+ dict(address="2001:db33::/32"),
+ ],
+ ),
+ dict(
+ area_id="13",
+ range=[dict(address="2001:db44::/32"),],
+ ),
+ ],
+ ),
+ state="replaced",
+ )
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_vyos_ospfv3_deleted_no_config(self):
+ set_module_args(dict(config=None, state="deleted"))
+ commands = ["delete protocols ospfv3"]
+ self.execute_module(changed=True, commands=commands)
+
+ def test_vyos_ospfv3_gathered(self):
+ set_module_args(dict(state="gathered"))
+ result = self.execute_module(
+ changed=False, filename="vyos_ospfv3_config.cfg"
+ )
+ gather_dict = {
+ "areas": [
+ {
+ "area_id": "12",
+ "export_list": "export1",
+ "import_list": "import1",
+ "range": [
+ {"address": "2001:db11::/32"},
+ {"address": "2001:db22::/32"},
+ {"address": "2001:db33::/32"},
+ ],
+ },
+ {"area_id": "13", "range": [{"address": "2001:db44::/32"}]},
+ ],
+ }
+ self.assertEqual(sorted(gather_dict), sorted(result["gathered"]))
+
+ def test_vyos_ospfv3_parsed(self):
+ parsed_str = """set protocols ospfv3 area 2 export-list 'export1'
+set protocols ospfv3 area 2 import-list 'import1'
+set protocols ospfv3 area 2 range '2001:db10::/32'
+set protocols ospfv3 area 2 range '2001:db20::/32'
+set protocols ospfv3 area 2 range '2001:db30::/32'
+set protocols ospfv3 area 3 range '2001:db40::/32'
+set protocols ospfv3 parameters router-id '192.0.2.10'
+set protocols ospfv3 redistribute 'bgp'"""
+ set_module_args(dict(running_config=parsed_str, state="parsed"))
+ result = self.execute_module(changed=False)
+ parsed_dict = {
+ "areas": [
+ {
+ "area_id": "2",
+ "export_list": "export1",
+ "import_list": "import1",
+ "range": [
+ {"address": "2001:db10::/32"},
+ {"address": "2001:db20::/32"},
+ {"address": "2001:db30::/32"},
+ ],
+ },
+ {"area_id": "3", "range": [{"address": "2001:db40::/32"}]},
+ ],
+ "parameters": {"router_id": "192.0.2.10"},
+ "redistribute": [{"route_type": "bgp"}],
+ }
+ self.assertEqual(sorted(parsed_dict), sorted(result["parsed"]))
+
+ def test_vyos_ospfv3_rendered(self):
+ set_module_args(
+ dict(
+ config=dict(
+ redistribute=[dict(route_type="bgp")],
+ parameters=dict(router_id="192.0.2.10"),
+ areas=[
+ dict(
+ area_id="2",
+ export_list="export1",
+ import_list="import1",
+ range=[
+ dict(address="2001:db10::/32"),
+ dict(address="2001:db20::/32"),
+ dict(address="2001:db30::/32"),
+ ],
+ ),
+ dict(
+ area_id="3",
+ range=[dict(address="2001:db40::/32"),],
+ ),
+ ],
+ ),
+ state="rendered",
+ )
+ )
+ commands = [
+ "set protocols ospfv3 redistribute bgp",
+ "set protocols ospfv3 parameters router-id '192.0.2.10'",
+ "set protocols ospfv3 area 2 range 2001:db10::/32",
+ "set protocols ospfv3 area 2 range 2001:db20::/32",
+ "set protocols ospfv3 area 2 range 2001:db30::/32",
+ "set protocols ospfv3 area '2'",
+ "set protocols ospfv3 area 2 export-list export1",
+ "set protocols ospfv3 area 2 import-list import1",
+ "set protocols ospfv3 area '3'",
+ "set protocols ospfv3 area 3 range 2001:db40::/32",
+ ]
+ result = self.execute_module(changed=False)
+ self.assertEqual(
+ sorted(result["rendered"]), sorted(commands), result["rendered"]
+ )
diff --git a/tests/unit/modules/network/vyos/vyos_module.py b/tests/unit/modules/network/vyos/vyos_module.py
index fb15c71..49d4652 100644
--- a/tests/unit/modules/network/vyos/vyos_module.py
+++ b/tests/unit/modules/network/vyos/vyos_module.py
@@ -60,6 +60,7 @@ class TestVyosModule(ModuleTestCase):
commands=None,
sort=True,
defaults=False,
+ filename=None,
):
self.load_fixtures(commands)