diff --git a/plugins/module_utils/network/vyos/argspec/ospfv2/ospfv2.py b/plugins/module_utils/network/vyos/argspec/ospfv2/ospfv2.py
index a2a6e04..275aaf3 100644
--- a/plugins/module_utils/network/vyos/argspec/ospfv2/ospfv2.py
+++ b/plugins/module_utils/network/vyos/argspec/ospfv2/ospfv2.py
@@ -1,365 +1,269 @@
#
# -*- 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_ospfv2 module
"""
class Ospfv2Args(object): # pylint: disable=R0903
"""The arg spec for the vyos_ospfv2 module
"""
+
def __init__(self, **kwargs):
pass
argument_spec = {
- 'config': {
- 'options': {
- 'auto_cost': {
- 'options': {
- 'reference_bandwidth': {
- 'type': 'int'
- }
- },
- 'type': 'dict'
+ "config": {
+ "options": {
+ "auto_cost": {
+ "options": {"reference_bandwidth": {"type": "int"}},
+ "type": "dict",
},
- 'default_information': {
- 'options': {
- 'originate': {
- 'options': {
- 'always': {
- 'type': 'bool'
- },
- 'metric': {
- 'type': 'int'
- },
- 'metric_type': {
- 'type': 'int'
- },
- 'route_map': {
- 'type': 'str'
- }
+ "default_information": {
+ "options": {
+ "originate": {
+ "options": {
+ "always": {"type": "bool"},
+ "metric": {"type": "int"},
+ "metric_type": {"type": "int"},
+ "route_map": {"type": "str"},
},
- 'type': 'dict'
+ "type": "dict",
}
},
- 'type': 'dict'
- },
- 'default_metric': {
- 'type': 'int'
+ "type": "dict",
},
- 'distance': {
- 'options': {
- 'global': {
- 'type': 'int'
- },
- 'ospf': {
- 'options': {
- 'external': {
- 'type': 'int'
- },
- 'inter_area': {
- 'type': 'int'
- },
- 'intra_area': {
- 'type': 'int'
- }
+ "default_metric": {"type": "int"},
+ "distance": {
+ "options": {
+ "global": {"type": "int"},
+ "ospf": {
+ "options": {
+ "external": {"type": "int"},
+ "inter_area": {"type": "int"},
+ "intra_area": {"type": "int"},
},
- 'type': 'dict'
- }
+ "type": "dict",
+ },
},
- 'type': 'dict'
+ "type": "dict",
},
- 'log_adjacency_changes': {
- 'choices': ['detail'],
- 'type': 'str'
+ "log_adjacency_changes": {
+ "choices": ["detail"],
+ "type": "str",
},
- 'max_metric': {
- 'options': {
- 'router_lsa': {
- 'options': {
- 'administrative': {
- 'type': 'bool'
- },
- 'on_shutdown': {
- 'type': 'int'
- },
- 'on_startup': {
- 'type': 'int'
- }
+ "max_metric": {
+ "options": {
+ "router_lsa": {
+ "options": {
+ "administrative": {"type": "bool"},
+ "on_shutdown": {"type": "int"},
+ "on_startup": {"type": "int"},
},
- 'type': 'dict'
+ "type": "dict",
}
},
- 'type': 'dict'
+ "type": "dict",
},
- 'mpls_te': {
- 'options': {
- 'enabled': {
- 'type': 'bool'
- },
- 'router_address': {
- 'type': 'str'
- }
+ "mpls_te": {
+ "options": {
+ "enabled": {"type": "bool"},
+ "router_address": {"type": "str"},
},
- 'type': 'dict'
+ "type": "dict",
},
- 'neighbor': {
- 'elements': 'dict',
- 'options': {
- 'neighbor_id': {
- 'type': 'str'
- },
- 'poll_interval': {
- 'type': 'int'
- },
- 'priority': {
- 'type': 'int'
- }
+ "neighbor": {
+ "elements": "dict",
+ "options": {
+ "neighbor_id": {"type": "str"},
+ "poll_interval": {"type": "int"},
+ "priority": {"type": "int"},
},
- 'type': 'list'
+ "type": "list",
},
- 'areas': {
- 'elements': 'dict',
- 'options': {
- 'area_id': {
- 'type': 'str'
- },
- 'area_type': {
- 'options': {
- 'normal': {
- 'type': 'bool'
- },
- 'nssa': {
- 'options': {
- 'default_cost': {
- 'type': 'int'
- },
- 'no_summary': {
- 'type': 'bool'
+ "areas": {
+ "elements": "dict",
+ "options": {
+ "area_id": {"type": "str"},
+ "area_type": {
+ "options": {
+ "normal": {"type": "bool"},
+ "nssa": {
+ "options": {
+ "default_cost": {"type": "int"},
+ "no_summary": {"type": "bool"},
+ "set": {"type": "bool"},
+ "translate": {
+ "choices": [
+ "always",
+ "candidate",
+ "never",
+ ],
+ "type": "str",
},
- 'set': {
- 'type': 'bool'
- },
- 'translate': {
- 'choices':
- ['always', 'candidate', 'never'],
- 'type':
- 'str'
- }
},
- 'type': 'dict'
+ "type": "dict",
},
- 'stub': {
- 'options': {
- 'default_cost': {
- 'type': 'int'
- },
- 'no_summary': {
- 'type': 'bool'
- },
- 'set': {
- 'type': 'bool'
- }
+ "stub": {
+ "options": {
+ "default_cost": {"type": "int"},
+ "no_summary": {"type": "bool"},
+ "set": {"type": "bool"},
},
- 'type': 'dict'
- }
+ "type": "dict",
+ },
},
- 'type': 'dict'
+ "type": "dict",
},
- 'authentication': {
- 'choices': ['plaintext-password', 'md5'],
- 'type': 'str'
+ "authentication": {
+ "choices": ["plaintext-password", "md5"],
+ "type": "str",
},
- 'network': {
- 'elements': 'dict',
- 'options': {
- 'address': {
- 'required': True,
- 'type': 'str'
- }
+ "network": {
+ "elements": "dict",
+ "options": {
+ "address": {"required": True, "type": "str"}
},
- 'type': 'list'
+ "type": "list",
},
- 'range': {
- 'elements': 'dict',
- 'options': {
- 'address': {
- 'type': 'str'
- },
- 'cost': {
- 'type': 'int'
- },
- 'not_advertise': {
- 'type': 'bool'
- },
- 'substitute': {
- 'type': 'str'
- }
+ "range": {
+ "elements": "dict",
+ "options": {
+ "address": {"type": "str"},
+ "cost": {"type": "int"},
+ "not_advertise": {"type": "bool"},
+ "substitute": {"type": "str"},
},
- 'type': 'list'
+ "type": "list",
},
- 'shortcut': {
- 'choices': ['default', 'disable', 'enable'],
- 'type': 'str'
+ "shortcut": {
+ "choices": ["default", "disable", "enable"],
+ "type": "str",
},
- 'virtual_link': {
- 'elements': 'dict',
- 'options': {
- 'address': {
- 'type': 'str'
- },
- 'authentication': {
- 'options': {
- 'md5': {
- 'elements': 'dict',
- 'options': {
- 'key_id': {
- 'type': 'int'
- },
- 'md5_key': {
- 'type': 'str'
- }
+ "virtual_link": {
+ "elements": "dict",
+ "options": {
+ "address": {"type": "str"},
+ "authentication": {
+ "options": {
+ "md5": {
+ "elements": "dict",
+ "options": {
+ "key_id": {"type": "int"},
+ "md5_key": {"type": "str"},
},
- 'type': 'list'
+ "type": "list",
},
- 'plaintext_password': {
- 'type': 'str'
- }
+ "plaintext_password": {"type": "str"},
},
- 'type': 'dict'
- },
- 'dead_interval': {
- 'type': 'int'
- },
- 'hello_interval': {
- 'type': 'int'
+ "type": "dict",
},
- 'retransmit_interval': {
- 'type': 'int'
- },
- 'transmit_delay': {
- 'type': 'int'
- }
+ "dead_interval": {"type": "int"},
+ "hello_interval": {"type": "int"},
+ "retransmit_interval": {"type": "int"},
+ "transmit_delay": {"type": "int"},
},
- 'type': 'list'
- }
+ "type": "list",
+ },
},
- 'type': 'list'
+ "type": "list",
},
- 'parameters': {
- 'options': {
- 'abr_type': {
- 'choices':
- ['cisco', 'ibm', 'shortcut', 'standard'],
- 'type': 'str'
+ "parameters": {
+ "options": {
+ "abr_type": {
+ "choices": [
+ "cisco",
+ "ibm",
+ "shortcut",
+ "standard",
+ ],
+ "type": "str",
},
- 'opaque_lsa': {
- 'type': 'bool'
- },
- 'rfc1583_compatibility': {
- 'type': 'bool'
- },
- 'router_id': {
- 'type': 'str'
- }
+ "opaque_lsa": {"type": "bool"},
+ "rfc1583_compatibility": {"type": "bool"},
+ "router_id": {"type": "str"},
},
- 'type': 'dict'
+ "type": "dict",
},
- 'passive_interface': {
- 'type': 'list'
- },
- 'passive_interface_exclude': {
- 'type': 'list'
- },
- 'redistribute': {
- 'elements': 'dict',
- 'options': {
- 'metric': {
- 'type': 'int'
- },
- 'metric_type': {
- 'type': 'int'
- },
- 'route_map': {
- 'type': 'str'
+ "passive_interface": {"type": "list"},
+ "passive_interface_exclude": {"type": "list"},
+ "redistribute": {
+ "elements": "dict",
+ "options": {
+ "metric": {"type": "int"},
+ "metric_type": {"type": "int"},
+ "route_map": {"type": "str"},
+ "route_type": {
+ "choices": [
+ "bgp",
+ "connected",
+ "kernel",
+ "rip",
+ "static",
+ ],
+ "type": "str",
},
- 'route_type': {
- 'choices':
- ['bgp', 'connected', 'kernel', 'rip', 'static'],
- 'type':
- 'str'
- }
},
- 'type': 'list'
- },
- 'route_map': {
- 'type': 'list'
+ "type": "list",
},
- 'timers': {
- 'options': {
- 'refresh': {
- 'options': {
- 'timers': {
- 'type': 'int'
- }
- },
- 'type': 'dict'
+ "route_map": {"type": "list"},
+ "timers": {
+ "options": {
+ "refresh": {
+ "options": {"timers": {"type": "int"}},
+ "type": "dict",
},
- 'throttle': {
- 'options': {
- 'spf': {
- 'options': {
- 'delay': {
- 'type': 'int'
- },
- 'initial_holdtime': {
- 'type': 'int'
- },
- 'max_holdtime': {
- 'type': 'int'
- }
+ "throttle": {
+ "options": {
+ "spf": {
+ "options": {
+ "delay": {"type": "int"},
+ "initial_holdtime": {"type": "int"},
+ "max_holdtime": {"type": "int"},
},
- 'type': 'dict'
+ "type": "dict",
}
},
- 'type': 'dict'
- }
+ "type": "dict",
+ },
},
- 'type': 'dict'
- }
+ "type": "dict",
+ },
},
- 'type': 'dict'
+ "type": "dict",
},
"running_config": {"type": "str"},
- 'state': {
- 'choices': [
- 'merged', 'replaced', 'deleted', 'parsed', 'gathered',
- 'rendered'
+ "state": {
+ "choices": [
+ "merged",
+ "replaced",
+ "deleted",
+ "parsed",
+ "gathered",
+ "rendered",
],
- 'default':
- 'merged',
- 'type':
- 'str'
- }
+ "default": "merged",
+ "type": "str",
+ },
} # pylint: disable=C0301
diff --git a/plugins/module_utils/network/vyos/config/ospfv2/ospfv2.py b/plugins/module_utils/network/vyos/config/ospfv2/ospfv2.py
index 13645cd..fd25c17 100644
--- a/plugins/module_utils/network/vyos/config/ospfv2/ospfv2.py
+++ b/plugins/module_utils/network/vyos/config/ospfv2/ospfv2.py
@@ -1,729 +1,949 @@
#
# -*- 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_ospfv2 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,
)
-from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.facts import Facts
+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 (
- list_diff_want_only, _in_target, _is_w_same, _bool_to_str
+ list_diff_want_only,
+ _in_target,
+ _is_w_same,
+ _bool_to_str,
)
class Ospfv2(ConfigBase):
"""
The vyos_ospfv2 class
"""
- gather_subset = ['!all', '!min']
+ gather_subset = ["!all", "!min"]
- gather_network_resources = ['ospfv2']
+ gather_network_resources = ["ospfv2"]
def __init__(self, module):
super(Ospfv2, self).__init__(module)
def get_ospfv2_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)
- ospfv2_facts = facts['ansible_network_resources'].get('ospfv2')
- if not ospfv2_facts:
- return []
+ (facts, _warnings) = Facts(self._module).get_facts(
+ self.gather_subset, self.gather_network_resources, data=data
+ )
+ ospfv2_facts = facts["ansible_network_resources"].get("ospfv2", {})
return ospfv2_facts
def execute_module(self):
""" Execute the module
:rtype: A dictionary
:returns: The result from module execution
"""
- result = {'changed': False}
+ result = {"changed": False}
warnings = list()
commands = list()
if self.state in self.ACTION_STATES:
existing_ospfv2_facts = self.get_ospfv2_facts()
else:
- existing_ospfv2_facts = []
+ existing_ospfv2_facts = {}
- if self.state in self.ACTION_STATES or self.state == 'rendered':
+ if self.state in self.ACTION_STATES or self.state == "rendered":
commands.extend(self.set_config(existing_ospfv2_facts))
if commands and self.state in self.ACTION_STATES:
if not self._module.check_mode:
self._connection.edit_config(commands)
- result['changed'] = True
+ result["changed"] = True
if self.state in self.ACTION_STATES:
- result['commands'] = commands
+ result["commands"] = commands
- if self.state in self.ACTION_STATES or self.state == 'gathered':
+ if self.state in self.ACTION_STATES or self.state == "gathered":
changed_ospfv2_facts = self.get_ospfv2_facts()
- elif self.state == 'rendered':
- result['rendered'] = commands
- elif self.state == 'parsed':
- running_config = self._module.params['running_config']
+ 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_ospfv2_facts(data=running_config)
+ self._module.fail_json(
+ msg="value of running_config parameter must not be empty for state parsed"
+ )
+ result["parsed"] = self.get_ospfv2_facts(data=running_config)
else:
- changed_ospfv2_facts = []
+ changed_ospfv2_facts = {}
if self.state in self.ACTION_STATES:
- result['before'] = existing_ospfv2_facts
- if result['changed']:
- result['after'] = changed_ospfv2_facts
- elif self.state == 'gathered':
- result['gathered'] = changed_ospfv2_facts
+ result["before"] = existing_ospfv2_facts
+ if result["changed"]:
+ result["after"] = changed_ospfv2_facts
+ elif self.state == "gathered":
+ result["gathered"] = changed_ospfv2_facts
- result['warnings'] = warnings
+ result["warnings"] = warnings
return result
def set_config(self, existing_ospfv2_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']
+ want = self._module.params["config"]
have = existing_ospfv2_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'):
+ 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(h))
+ elif self.state in ("merged", "rendered"):
commands.extend(self._state_merged(w, h))
- elif self.state == 'replaced':
+ elif self.state == "replaced":
commands.extend(self._state_replaced(w, h))
return commands
def search_obj_in_have(self, have, w_name, key):
"""
This function returns the rule-set/rule if it is present in target config.
:param have: target config.
:param w_name: rule-set name.
:param type: rule_sets/rule/r_list.
:return: rule-set/rule.
"""
if have:
for item in have:
if item[key] == w_name[key]:
return item
return None
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(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):
+ def _state_deleted(self, 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 want and have:
- for (key, val) in iteritems(want):
- if key in have:
- if key == 'areas':
- h_areas = have.get(key) or []
- key = 'area'
- for area in h_areas:
- h_vlist = area.get('virtual_link') or []
- if h_vlist:
- for vlink in h_vlist:
- cmd = self._compute_command(
- key=key + ' ' + area['area_id'], attr='virtual_link',
- val=vlink['address'], opr=False)
- commands.append(cmd)
- commands.append(self._compute_command(key=key,
- attr=area['area_id'], opr=False))
- commands.append(self._compute_command(attr=key,
- opr=False))
- elif have:
- commands.append('delete protocols ospf')
+ if have:
+ commands.append("delete protocols ospf")
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))
- leaf = ('default_metric', 'log_adjacency_changes')
+ leaf = ("default_metric", "log_adjacency_changes")
if w:
for (key, val) in iteritems(w):
if opr and key in leaf and not _is_w_same(w, have, key):
- commands.append(self._form_attr_cmd(attr=key,
- val=_bool_to_str(val), opr=opr))
+ commands.append(
+ self._form_attr_cmd(
+ attr=key, val=_bool_to_str(val), opr=opr
+ )
+ )
elif not opr and key in leaf and not _in_target(have, key):
- commands.append(self._form_attr_cmd(attr=key, val=_bool_to_str(val), opr=opr))
+ commands.append(
+ self._form_attr_cmd(
+ attr=key, val=_bool_to_str(val), opr=opr
+ )
+ )
else:
- commands.extend(self._render_child_param(w, have, key, opr))
+ 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 in ('neighbor', 'redistribute'):
- commands.extend(self._render_list_dict_param(key, w, h,
- opr=opr))
- elif key in ('default_information', 'max_metric'):
- commands.extend(self._render_nested_dict_param(key, w, h,
- opr=opr))
- elif key in ('mpls_te', 'auto_cost', 'parameters', 'auto_cost'):
+ if key in ("neighbor", "redistribute"):
+ commands.extend(self._render_list_dict_param(key, w, h, opr=opr))
+ elif key in ("default_information", "max_metric"):
+ commands.extend(self._render_nested_dict_param(key, w, h, opr=opr))
+ elif key in ("mpls_te", "auto_cost", "parameters", "auto_cost"):
commands.extend(self._render_dict_param(key, w, h, opr=opr))
- elif key in ('route_map', 'passive_interface',
- 'passive_interface_exclude'):
+ elif key in (
+ "route_map",
+ "passive_interface",
+ "passive_interface_exclude",
+ ):
commands.extend(self._render_list_param(key, w, h, opr=opr))
- elif key == 'areas':
+ elif key == "areas":
commands.extend(self._render_areas(key, w, h, opr=opr))
- elif key == 'timers':
+ elif key == "timers":
commands.extend(self._render_timers(key, w, h, opr=opr))
- elif key == 'distance':
+ elif key == "distance":
commands.extend(self._render_distance(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 = {'auto_cost': 'reference_bandwidth',
- 'mpls_te': ('enabled', 'router_address'),
- 'parameters': ('router_id', 'abr_type',
- 'opaque_lsa', 'rfc1583_compatibility')}
+ leaf_dict = {
+ "auto_cost": "reference_bandwidth",
+ "mpls_te": ("enabled", "router_address"),
+ "parameters": (
+ "router_id",
+ "abr_type",
+ "opaque_lsa",
+ "rfc1583_compatibility",
+ ),
+ }
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):
- if item == 'enabled':
- item = 'enable'
- if item in ('opaque_lsa', 'enable', 'rfc1583_compatibility'):
- commands.append(self._form_attr_cmd(key=attr, attr=item, opr=opr))
+ if (
+ opr
+ and item in leaf
+ and not _is_w_same(want[attr], h, item)
+ ):
+ if item == "enabled":
+ item = "enable"
+ if item in (
+ "opaque_lsa",
+ "enable",
+ "rfc1583_compatibility",
+ ):
+ commands.append(
+ self._form_attr_cmd(key=attr, attr=item, opr=opr)
+ )
else:
- commands.append(self._form_attr_cmd(key=attr, attr=item, val=value, opr=opr))
+ 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):
- if item == 'enabled':
- commands.append(self._form_attr_cmd(key=attr, attr='enable', opr=opr))
+ if item == "enabled":
+ commands.append(
+ self._form_attr_cmd(
+ key=attr, attr="enable", opr=opr
+ )
+ )
else:
- commands.append(self._form_attr_cmd(key=attr, attr=item, opr=opr))
+ commands.append(
+ self._form_attr_cmd(key=attr, attr=item, opr=opr)
+ )
return commands
def _render_list_param(self, attr, want, have, cmd=None, opr=True):
"""
This function forms the commands for passed target list attributes'.
: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 list of commands.
"""
commands = []
h = []
if want:
w = want.get(attr) or []
if have:
h = have.get(attr) or []
if not cmd:
cmd = self._compute_command(opr=opr)
if w:
if opr:
members = list_diff_want_only(w, h)
for member in members:
- command = cmd + attr.replace('_', '-') + ' '
- if attr == 'network':
- command += member['address']
+ command = cmd + attr.replace("_", "-") + " "
+ if attr == "network":
+ command += member["address"]
else:
command += member
commands.append(command)
elif not opr:
if h:
for member in w:
- if attr == 'network':
- if not self.search_obj_in_have(h, member, 'address'):
- commands.append(cmd + attr.replace('_','-') +
- ' ' + member['address'])
+ if attr == "network":
+ if not self.search_obj_in_have(
+ h, member, "address"
+ ):
+ commands.append(
+ cmd
+ + attr.replace("_", "-")
+ + " "
+ + member["address"]
+ )
elif member not in h:
- commands.append(cmd + attr.replace('_', '-') +
- ' ' + member)
+ commands.append(
+ cmd + attr.replace("_", "-") + " " + member
+ )
else:
- commands.append(cmd + ' ' + attr.replace('_', '-'))
+ commands.append(cmd + " " + attr.replace("_", "-"))
return commands
def _render_vlink(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 = {'virtual_link': 'address'}
- leaf_dict = {'virtual_link': ('address', 'dead_interval',
- 'transmit_delay', 'hello_interval',
- 'retransmit_interval')}
+ name = {"virtual_link": "address"}
+ leaf_dict = {
+ "virtual_link": (
+ "address",
+ "dead_interval",
+ "transmit_delay",
+ "hello_interval",
+ "retransmit_interval",
+ )
+ }
leaf = leaf_dict[attr]
w = want.get(attr) or []
if have:
h = have.get(attr) or []
if not opr and not h:
- commands.append(cmd + attr.replace('_', '-'))
+ commands.append(cmd + attr.replace("_", "-"))
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 = self.search_obj_in_have(h, w_item, name[attr])
- if opr and key in leaf and not _is_w_same(w_item, h_item, key):
- if key in 'address':
- commands.append(cmd
- + attr.replace('_', '-')
- + ' ' + str(val))
+ if (
+ opr
+ and key in leaf
+ and not _is_w_same(w_item, h_item, key)
+ ):
+ if key in "address":
+ commands.append(
+ cmd + attr.replace("_", "-") + " " + str(val)
+ )
else:
- commands.append(cmd + attr.replace('_', '-')
- + ' ' + 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 'address':
- commands.append(cmd + attr.replace('_', '-')
- + ' ' + str(val))
+ commands.append(
+ cmd
+ + attr.replace("_", "-")
+ + " "
+ + 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 "address":
+ commands.append(
+ cmd + attr.replace("_", "-") + " " + str(val)
+ )
else:
- commands.append(cmd + attr.replace('_', '-')
- + ' ' + w_item[name[attr]]
- + ' ' + key)
- elif key == 'authentication':
- commands.extend(self._render_vlink_auth(
- attr,
- key,
- w_item,
- h_item,
- w_item['address'],
- cmd,
- opr,
- ))
+ commands.append(
+ cmd
+ + attr.replace("_", "-")
+ + " "
+ + w_item[name[attr]]
+ + " "
+ + key
+ )
+ elif key == "authentication":
+ commands.extend(
+ self._render_vlink_auth(
+ attr,
+ key,
+ w_item,
+ h_item,
+ w_item["address"],
+ cmd,
+ opr,
+ )
+ )
return commands
- def _render_vlink_auth(self, attr, key, want, have, address, cmd=None, opr=True):
+ def _render_vlink_auth(
+ self, attr, key, want, have, address, 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 = []
w = want.get(key) or {}
if have:
h = have.get(key) or {}
- cmd += attr.replace('_', '-') + ' ' + address + ' ' + key + ' '
- commands.extend(self._render_list_dict_param('md5', w, h, cmd,
- opr))
+ cmd += attr.replace("_", "-") + " " + address + " " + key + " "
+ commands.extend(self._render_list_dict_param("md5", w, h, cmd, 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',
- 'neighbor': 'neighbor_id',
- 'range': 'address',
- 'md5': 'key_id',
- 'vlink': 'address',
- }
+ "redistribute": "route_type",
+ "neighbor": "neighbor_id",
+ "range": "address",
+ "md5": "key_id",
+ "vlink": "address",
+ }
leaf_dict = {
- 'md5': 'md5_key',
- 'redistribute': ('metric', 'route_map', 'route_type', 'metric_type'),
- 'neighbor': ('priority', 'poll_interval', 'neighbor_id'),
- 'range': ('cost', 'address', 'substitute', 'not_advertise'),
- 'vlink': ('address', 'dead_interval', 'transmit_delay',
- 'hello_interval', 'retransmit_interval'),
- }
+ "md5": "md5_key",
+ "redistribute": (
+ "metric",
+ "route_map",
+ "route_type",
+ "metric_type",
+ ),
+ "neighbor": ("priority", "poll_interval", "neighbor_id"),
+ "range": ("cost", "address", "substitute", "not_advertise"),
+ "vlink": (
+ "address",
+ "dead_interval",
+ "transmit_delay",
+ "hello_interval",
+ "retransmit_interval",
+ ),
+ }
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 = self.search_obj_in_have(h, w_item, name[attr])
- if opr and key in leaf and not _is_w_same(w_item, h_item, key):
- if key in ('route_type', 'neighbor_id',
- 'address', 'key_id'):
- commands.append(cmd + attr + ' ' + str(val))
- elif key == 'cost':
- commands.append(cmd + attr
- + ' ' + w_item[name[attr]]
- + ' ' + key
- + ' ' + str(val))
- elif key == 'not_advertise':
- commands.append(cmd + attr
- + ' ' + w_item[name[attr]]
- + ' ' + key.replace('_', '-'))
- elif key == 'md5_key':
- commands.append(cmd + attr
- + ' ' + 'key-id'
- + ' ' + str(w_item[name[attr]])
- + ' ' + key.replace('_', '-')
- + ' ' + w_item[key])
+ if (
+ opr
+ and key in leaf
+ and not _is_w_same(w_item, h_item, key)
+ ):
+ if key in (
+ "route_type",
+ "neighbor_id",
+ "address",
+ "key_id",
+ ):
+ commands.append(cmd + attr + " " + str(val))
+ elif key == "cost":
+ commands.append(
+ cmd
+ + attr
+ + " "
+ + w_item[name[attr]]
+ + " "
+ + key
+ + " "
+ + str(val)
+ )
+ elif key == "not_advertise":
+ commands.append(
+ cmd
+ + attr
+ + " "
+ + w_item[name[attr]]
+ + " "
+ + key.replace("_", "-")
+ )
+ elif key == "md5_key":
+ commands.append(
+ cmd
+ + attr
+ + " "
+ + "key-id"
+ + " "
+ + str(w_item[name[attr]])
+ + " "
+ + key.replace("_", "-")
+ + " "
+ + w_item[key]
+ )
else:
- 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', 'neighbor_id',
- 'address', 'key_id'):
- commands.append(cmd + attr + ' ' + str(val))
+ 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",
+ "neighbor_id",
+ "address",
+ "key_id",
+ ):
+ commands.append(cmd + attr + " " + str(val))
else:
- commands.append(cmd + attr
- + ' ' + w_item[name[attr]]
- + ' ' + key)
+ commands.append(
+ cmd
+ + attr
+ + " "
+ + w_item[name[attr]]
+ + " "
+ + key
+ )
return commands
def _render_nested_dict_param(self, attr, want, have, opr=True):
"""
This function forms the set/delete commands based on the 'opr' type
for attributes with in desired nested dicts.
: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 = []
- attr_dict = {'default_information': 'originate',
- 'max_metric': 'router_lsa'}
- leaf_dict = {'default_information': ('always', 'metric', 'metric_type', 'route_map'),
- 'max_metric': ('administrative', 'on_startup', 'on_shutdown')}
+ attr_dict = {
+ "default_information": "originate",
+ "max_metric": "router_lsa",
+ }
+ leaf_dict = {
+ "default_information": (
+ "always",
+ "metric",
+ "metric_type",
+ "route_map",
+ ),
+ "max_metric": ("administrative", "on_startup", "on_shutdown"),
+ }
h = {}
w = want.get(attr) or {}
if have:
h = have.get(attr) or {}
if not opr and not h:
commands.append(self._form_attr_cmd(attr=attr, opr=opr))
elif w:
key = attr_dict[attr]
w_attrib = want[attr].get(key) or {}
cmd = self._compute_command(opr=opr)
h_attrib = {}
if w_attrib:
leaf = leaf_dict[attr]
if h and key in h.keys():
h_attrib = h.get(key) or {}
for (item, val) in iteritems(w[key]):
- if opr and item in leaf and not _is_w_same(w[key], h_attrib, item):
- if item in ('administrative', 'always') and val:
- commands.append(cmd + attr.replace('_', '-')
- + ' ' + key.replace('_', '-')
- + ' ' + item.replace('_', '-'))
- elif item not in ('administrative', 'always'):
- commands.append(cmd + attr.replace('_', '-')
- + ' ' + key.replace('_', '-')
- + ' ' + item.replace('_', '-')
- + ' ' + str(val))
- elif not opr and item in leaf \
- and not _in_target(h_attrib, item):
-
- commands.append(cmd + attr + ' ' + item)
+ if (
+ opr
+ and item in leaf
+ and not _is_w_same(w[key], h_attrib, item)
+ ):
+ if item in ("administrative", "always") and val:
+ commands.append(
+ cmd
+ + attr.replace("_", "-")
+ + " "
+ + key.replace("_", "-")
+ + " "
+ + item.replace("_", "-")
+ )
+ elif item not in ("administrative", "always"):
+ commands.append(
+ cmd
+ + attr.replace("_", "-")
+ + " "
+ + key.replace("_", "-")
+ + " "
+ + item.replace("_", "-")
+ + " "
+ + str(val)
+ )
+ elif (
+ not opr
+ and item in leaf
+ and not _in_target(h_attrib, item)
+ ):
+
+ commands.append(cmd + attr + " " + item)
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', 'shortcut', 'authentication')
+ l_set = ("area_id", "shortcut", "authentication")
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))
+ 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 = self.search_obj_in_have(h_lst, w_area, 'area_id')
+ cmd = (
+ self._compute_command(
+ key="area",
+ attr=_bool_to_str(w_area["area_id"]),
+ opr=opr,
+ )
+ + " "
+ )
+ h_area = self.search_obj_in_have(h_lst, w_area, "area_id")
if not opr and not h_area:
- commands.append(self._form_attr_cmd(key='area',
- attr=w_area['area_id'], opr=opr))
+ 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))
+ 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 + ' ' +
- _bool_to_str(val).replace('_', '-'))
+ commands.append(
+ cmd
+ + key
+ + " "
+ + _bool_to_str(val).replace("_", "-")
+ )
elif not opr and key in l_set:
- if key == 'area_id' and not _in_target(h_area, key):
+ 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 == 'area_type':
- commands.extend(self._render_area_type(w_area, h_area, key, cmd, opr))
- elif key == 'network':
- commands.extend(self._render_list_param(key, w_area, h_area, cmd, opr))
- elif key == 'range':
- commands.extend(self._render_list_dict_param(key, w_area, h_area, cmd, opr))
- elif key == 'virtual_link':
- commands.extend(self._render_vlink(key, w_area, h_area, cmd, opr))
+ elif key != "area_id" and not _in_target(
+ h_area, key
+ ):
+ commands.append(cmd + val + " " + key)
+ elif key == "area_type":
+ commands.extend(
+ self._render_area_type(
+ w_area, h_area, key, cmd, opr
+ )
+ )
+ elif key == "network":
+ commands.extend(
+ self._render_list_param(
+ key, w_area, h_area, cmd, opr
+ )
+ )
+ elif key == "range":
+ commands.extend(
+ self._render_list_dict_param(
+ key, w_area, h_area, cmd, opr
+ )
+ )
+ elif key == "virtual_link":
+ commands.extend(
+ self._render_vlink(
+ key, w_area, h_area, cmd, opr
+ )
+ )
return commands
def _render_area_type(self, want, have, attr, cmd, opr=True):
"""
This function forms the set/delete commands based on the 'opr' type
for area_types attributes.
:param attr: attribute name.
:param w: the desired config.
:param h: the target config.
:param cmd: command to prepend.
:param opr: True/False.
:return: generated commands list.
"""
commands = []
h_type = {}
w_type = want.get(attr) or []
if have:
h_type = have.get(attr) or {}
if not opr and not h_type:
- commands.append(cmd + attr.replace('_', '-'))
+ commands.append(cmd + attr.replace("_", "-"))
elif w_type:
- key = 'normal'
- if opr and key in w_type.keys() and not _is_w_same(w_type, h_type, key):
+ key = "normal"
+ if (
+ opr
+ and key in w_type.keys()
+ and not _is_w_same(w_type, h_type, key)
+ ):
if not w_type[key] and h_type and h_type[key]:
- commands.append(cmd.replace('set', 'delete')
- + attr.replace('_', '-')
- + ' ' + key)
+ commands.append(
+ cmd.replace("set", "delete")
+ + attr.replace("_", "-")
+ + " "
+ + key
+ )
elif w_type[key]:
- commands.append(cmd + attr.replace('_', '-')
- + ' ' + key)
- elif not opr and key in w_type.keys() and not (h_type
- and key in h_type.keys()):
- commands.append(cmd + want['area']
- + ' ' + attr.replace('_', '-'))
-
- a_type = {'nssa': ('set', 'default_cost', 'no_summary', 'translate'),
- 'stub': ('set', 'default_cost', 'no_summary')}
+ commands.append(cmd + attr.replace("_", "-") + " " + key)
+ elif (
+ not opr
+ and key in w_type.keys()
+ and not (h_type and key in h_type.keys())
+ ):
+ commands.append(
+ cmd + want["area"] + " " + attr.replace("_", "-")
+ )
+
+ a_type = {
+ "nssa": ("set", "default_cost", "no_summary", "translate"),
+ "stub": ("set", "default_cost", "no_summary"),
+ }
for key in a_type:
w_area = want[attr].get(key) or {}
h_area = {}
if w_area:
if h_type and key in h_type.keys():
h_area = h_type.get(key) or {}
for (item, val) in iteritems(w_type[key]):
- if opr and item in a_type[key] \
- and not _is_w_same(w_type[key], h_area, item):
- if item == 'set' and val:
- commands.append(cmd + attr.replace('_', '-')
- + ' ' + key)
+ if (
+ opr
+ and item in a_type[key]
+ and not _is_w_same(w_type[key], h_area, item)
+ ):
+ if item == "set" and val:
+ commands.append(
+ cmd + attr.replace("_", "-") + " " + key
+ )
elif not val and h_area and h_area[item]:
- commands.append(cmd.replace('set', 'delete')
- + attr.replace('_', '-')
- + ' ' + key)
- elif item != 'set':
- commands.append(cmd + attr.replace('_', '-')
- + ' ' + key
- + ' ' + item.replace('_', '-')
- + ' ' + str(val))
- elif not opr and item in a_type[key] \
- and not (h_type and key in h_type):
- if item == 'set':
- commands.append(cmd + attr.replace('_', '-')
- + ' ' + key)
+ commands.append(
+ cmd.replace("set", "delete")
+ + attr.replace("_", "-")
+ + " "
+ + key
+ )
+ elif item != "set":
+ commands.append(
+ cmd
+ + attr.replace("_", "-")
+ + " "
+ + key
+ + " "
+ + item.replace("_", "-")
+ + " "
+ + str(val)
+ )
+ elif (
+ not opr
+ and item in a_type[key]
+ and not (h_type and key in h_type)
+ ):
+ if item == "set":
+ commands.append(
+ cmd + attr.replace("_", "-") + " " + key
+ )
else:
- commands.append(cmd + want['area']
- + ' ' + attr.replace('_', '-')
- + ' ' + key + ' ' + item.replace('_', '-'))
+ commands.append(
+ cmd
+ + want["area"]
+ + " "
+ + attr.replace("_", "-")
+ + " "
+ + key
+ + " "
+ + item.replace("_", "-")
+ )
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)
+ 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):
+ 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 ospf '
+ cmd = "delete protocols ospf "
else:
- cmd = 'set protocols ospf '
+ cmd = "set protocols ospf "
if key:
- cmd += key.replace('_', '-') + ' '
+ cmd += key.replace("_", "-") + " "
if attr:
- cmd += attr.replace('_', '-')
+ cmd += attr.replace("_", "-")
if val:
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('_', '-'))
+ 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 17c7aa3..f1221f6 100644
--- a/plugins/module_utils/network/vyos/facts/facts.py
+++ b/plugins/module_utils/network/vyos/facts/facts.py
@@ -1,99 +1,99 @@
# Copyright 2019 Red Hat
# GNU General Public License v3.0+
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
"""
The facts class for vyos
this file validates each subset of facts and selectively
calls the appropriate facts gathering function
"""
from __future__ import absolute_import, division, print_function
__metaclass__ = type
from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts import (
FactsBase,
)
from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.interfaces.interfaces import (
InterfacesFacts,
)
from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.l3_interfaces.l3_interfaces import (
L3_interfacesFacts,
)
from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.lag_interfaces.lag_interfaces import (
Lag_interfacesFacts,
)
from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.lldp_global.lldp_global import (
Lldp_globalFacts,
)
from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.lldp_interfaces.lldp_interfaces import (
Lldp_interfacesFacts,
)
from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.firewall_rules.firewall_rules import (
Firewall_rulesFacts,
)
from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.static_routes.static_routes import (
Static_routesFacts,
)
from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.firewall_global.firewall_global import (
Firewall_globalFacts,
)
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.ospfv2.ospfv2 import (
- Ospfv2Facts,
+ Ospfv2Facts,
)
from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.legacy.base import (
Default,
Neighbors,
Config,
)
FACT_LEGACY_SUBSETS = dict(default=Default, neighbors=Neighbors, config=Config)
FACT_RESOURCE_SUBSETS = dict(
interfaces=InterfacesFacts,
l3_interfaces=L3_interfacesFacts,
lag_interfaces=Lag_interfacesFacts,
lldp_global=Lldp_globalFacts,
lldp_interfaces=Lldp_interfacesFacts,
static_routes=Static_routesFacts,
firewall_rules=Firewall_rulesFacts,
firewall_global=Firewall_globalFacts,
firewall_interfaces=Firewall_interfacesFacts,
ospfv3=Ospfv3Facts,
ospfv2=Ospfv2Facts,
)
class Facts(FactsBase):
""" The fact class for vyos
"""
VALID_LEGACY_GATHER_SUBSETS = frozenset(FACT_LEGACY_SUBSETS.keys())
VALID_RESOURCE_SUBSETS = frozenset(FACT_RESOURCE_SUBSETS.keys())
def __init__(self, module):
super(Facts, self).__init__(module)
def get_facts(
self, legacy_facts_type=None, resource_facts_type=None, data=None
):
""" Collect the facts for vyos
:param legacy_facts_type: List of legacy facts types
:param resource_facts_type: List of resource fact types
:param data: previously collected conf
:rtype: dict
:return: the facts gathered
"""
if self.VALID_RESOURCE_SUBSETS:
self.get_network_resources_facts(
FACT_RESOURCE_SUBSETS, resource_facts_type, data
)
if self.VALID_LEGACY_GATHER_SUBSETS:
self.get_network_legacy_facts(
FACT_LEGACY_SUBSETS, legacy_facts_type
)
return self.ansible_facts, self._warnings
diff --git a/plugins/module_utils/network/vyos/facts/ospfv2/ospfv2.py b/plugins/module_utils/network/vyos/facts/ospfv2/ospfv2.py
index 0467b72..d62fa9a 100644
--- a/plugins/module_utils/network/vyos/facts/ospfv2/ospfv2.py
+++ b/plugins/module_utils/network/vyos/facts/ospfv2/ospfv2.py
@@ -1,464 +1,499 @@
#
# -*- 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 ospfv2 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.ansible.netcommon.plugins.module_utils.network.common import (
+ utils,
+)
-from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.ospfv2.ospfv2 import Ospfv2Args
+from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.ospfv2.ospfv2 import (
+ Ospfv2Args,
+)
class Ospfv2Facts(object):
""" The vyos ospfv2 fact class
"""
def __init__(
- self,
- module,
- subspec='config',
- options='options',
- ):
+ self, module, subspec="config", options="options",
+ ):
self._module = module
self.argument_spec = Ospfv2Args.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 ospfv2
: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 = {}
ospfv2 = findall(r"^set protocols ospf (.+)", data, M)
if ospfv2:
objs = self.render_config(ospfv2)
facts = {}
- params = utils.validate_config(self.argument_spec,{'config': objs})
- facts['ospfv2'] = utils.remove_empties(params['config'])
- ansible_facts['ansible_network_resources'].update(facts)
+ params = utils.validate_config(self.argument_spec, {"config": objs})
+ facts["ospfv2"] = 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))
- a_lst = ['default_metric', 'log_adjacency_changes']
+ conf = "\n".join(filter(lambda x: x, conf))
+ a_lst = ["default_metric", "log_adjacency_changes"]
config = self.parse_attr(conf, a_lst)
if not config:
config = {}
- config['timers'] = self.parse_timers(conf)
- config['auto_cost'] = self.parse_auto_cost(conf)
- config['distance'] = self.parse_distance(conf)
- config['max_metric'] = self.parse_max_metric(conf)
- config['default_information'] = self.parse_def_info(conf)
- config['route_map'] = self.parse_leaf_list(conf, 'route-map')
- config['mpls_te'] = self.parse_attrib(conf, 'mpls_te', 'mpls-te')
- config['areas'] = self.parse_attrib_list(conf, 'area', 'area_id')
- config['parameters'] = self.parse_attrib(conf, 'parameters', 'parameters')
- config['neighbor'] = self.parse_attrib_list(conf, 'neighbor', 'neighbor_id')
- config['passive_interface'] = self.parse_leaf_list(conf, 'passive-interface')
- config['redistribute'] = self.parse_attrib_list(conf, 'redistribute', 'route_type')
- config['passive_interface_exclude'] = self.parse_leaf_list(conf, 'passive-interface-exclude')
+ config["timers"] = self.parse_timers(conf)
+ config["auto_cost"] = self.parse_auto_cost(conf)
+ config["distance"] = self.parse_distance(conf)
+ config["max_metric"] = self.parse_max_metric(conf)
+ config["default_information"] = self.parse_def_info(conf)
+ config["route_map"] = self.parse_leaf_list(conf, "route-map")
+ config["mpls_te"] = self.parse_attrib(conf, "mpls_te", "mpls-te")
+ config["areas"] = self.parse_attrib_list(conf, "area", "area_id")
+ config["parameters"] = self.parse_attrib(
+ conf, "parameters", "parameters"
+ )
+ config["neighbor"] = self.parse_attrib_list(
+ conf, "neighbor", "neighbor_id"
+ )
+ config["passive_interface"] = self.parse_leaf_list(
+ conf, "passive-interface"
+ )
+ config["redistribute"] = self.parse_attrib_list(
+ conf, "redistribute", "route_type"
+ )
+ config["passive_interface_exclude"] = self.parse_leaf_list(
+ conf, "passive-interface-exclude"
+ )
return config
def parse_timers(self, conf):
"""
This function triggers the parsing of 'timers' attributes
:param conf: configuration
:return: generated config dictionary
"""
cfg_dict = {}
- cfg_dict['refresh'] = self.parse_refresh(conf, 'refresh')
- cfg_dict['throttle'] = self.parse_throttle(conf, 'spf')
+ cfg_dict["refresh"] = self.parse_refresh(conf, "refresh")
+ cfg_dict["throttle"] = self.parse_throttle(conf, "spf")
return cfg_dict
def parse_throttle(self, conf, attrib=None):
"""
This function triggers the parsing of 'throttle' attributes
:param conf: configuration
:param attrib: 'spf'
:return: generated config dictionary
"""
cfg_dict = {}
cfg_dict[attrib] = self.parse_attrib(conf, attrib, match=attrib)
return cfg_dict
def parse_refresh(self, conf, attrib=None):
"""
This function triggers the parsing of 'refresh' attributes
:param conf: configuration
:param attrib: 'refresh'
:return: generated config dictionary
"""
- cfg_dict = self.parse_attr(conf, ['timers'], match=attrib)
+ cfg_dict = self.parse_attr(conf, ["timers"], match=attrib)
return cfg_dict
def parse_leaf_list(self, conf, attrib):
"""
This function forms the regex to fetch the listed attributes
from the configuration data
:param conf: configuration data
:param attrib: attribute name
:return: generated rule list configuration
"""
lst = []
- items = findall(r"^" + attrib + " (?:\'*)(\\S+)(?:\'*)", conf, M)
+ items = findall(r"^" + attrib + " (?:'*)(\\S+)(?:'*)", conf, M)
if items:
for i in set(items):
lst.append(i.strip("'"))
+ lst.sort()
return lst
def parse_distance(self, conf, attrib=None):
"""
This function triggers the parsing of 'distance' attributes
:param conf: configuration
:param attrib: attribute name
:return: generated config dictionary
"""
- cfg_dict = self.parse_attr(conf, ['global'], match=attrib)
- cfg_dict['ospf'] = self.parse_ospf(conf, 'ospf')
+ cfg_dict = self.parse_attr(conf, ["global"], match=attrib)
+ cfg_dict["ospf"] = self.parse_ospf(conf, "ospf")
return cfg_dict
def parse_ospf(self, conf, attrib=None):
"""
This function triggers the parsing of 'distance ospf' attributes
:param conf: configuration
:param attrib: 'ospf'
:return: generated config dictionary
"""
- cfg_dict = self.parse_attrib(conf, 'ospf', match=attrib)
+ cfg_dict = self.parse_attrib(conf, "ospf", match=attrib)
return cfg_dict
def parse_max_metric(self, conf):
"""
This function triggers the parsing of 'max_metric' attributes
:param conf: configuration
:return: generated config dictionary
"""
cfg_dict = {}
- cfg_dict['router_lsa'] = self.parse_attrib(conf, 'router_lsa', match='router-lsa')
+ cfg_dict["router_lsa"] = self.parse_attrib(
+ conf, "router_lsa", match="router-lsa"
+ )
return cfg_dict
def parse_auto_cost(self, conf, attrib=None):
"""
This function triggers the parsing of 'auto_cost' attributes
:param conf: configuration
:param attrib: attribute name
:return: generated config dictionary
"""
- cfg_dict = self.parse_attr(conf, ['reference_bandwidth'],
- match=attrib)
+ cfg_dict = self.parse_attr(conf, ["reference_bandwidth"], match=attrib)
return cfg_dict
def parse_def_info(self, conf):
"""
This function triggers the parsing of 'default_information' attributes
:param conf: configuration
:return: generated config dictionary
"""
cfg_dict = {}
- cfg_dict['originate'] = self.parse_attrib(conf, 'originate', 'originate')
+ cfg_dict["originate"] = self.parse_attrib(
+ conf, "originate", "originate"
+ )
return cfg_dict
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)
+ rule = self.parse_attrib(conf, "area_id", match=area_id)
r_sub = {
- 'area_type': self.parse_area_type(conf, 'area-type'),
- 'network': self.parse_network(conf),
- 'range': self.parse_attrib_list(conf, 'range', 'address'),
- 'virtual_link': self.parse_attrib_list(conf, 'virtual-link', 'address'),
- }
+ "area_type": self.parse_area_type(conf, "area-type"),
+ "network": self.parse_network(conf),
+ "range": self.parse_attrib_list(conf, "range", "address"),
+ "virtual_link": self.parse_attrib_list(
+ conf, "virtual-link", "address"
+ ),
+ }
rule.update(r_sub)
return rule
def parse_key(self, conf, key_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, 'key_id', match=key_id)
+ rule = self.parse_attrib(conf, "key_id", match=key_id)
return rule
def parse_area_type(self, conf, attrib=None):
"""
This function triggers the parsing of 'area_type' attributes
:param conf: configuration
:param attrib: 'area-type'
:return: generated config dictionary
"""
- cfg_dict = self.parse_attr(conf, ['normal'], match=attrib)
- cfg_dict['nssa'] = self.parse_attrib(conf, 'nssa', match='nssa')
- cfg_dict['stub'] = self.parse_attrib(conf, 'stub', match='stub')
+ cfg_dict = self.parse_attr(conf, ["normal"], match=attrib)
+ cfg_dict["nssa"] = self.parse_attrib(conf, "nssa", match="nssa")
+ cfg_dict["stub"] = self.parse_attrib(conf, "stub", match="stub")
return cfg_dict
def parse_network(self, conf):
"""
This function forms the regex to fetch the 'network'
:param conf: configuration data
:return: generated rule list configuration
"""
a_lst = []
applications = findall(r"network (.+)", conf, M)
if applications:
app_lst = []
for r in set(applications):
- obj = {'address': r.strip("'")}
+ obj = {"address": r.strip("'")}
app_lst.append(obj)
- a_lst = sorted(app_lst, key=lambda i: i['address'])
+ a_lst = sorted(app_lst, key=lambda i: i["address"])
return a_lst
def parse_vlink(self, conf):
"""
This function triggers the parsing of 'virtual_link' attributes
:param conf: configuration data
:return: generated rule configuration dictionary
"""
- rule = self.parse_attrib(conf, 'vlink')
- r_sub = {'authentication': self.parse_authentication(conf,
- 'authentication')}
+ rule = self.parse_attrib(conf, "vlink")
+ r_sub = {
+ "authentication": self.parse_authentication(conf, "authentication")
+ }
rule.update(r_sub)
return rule
def parse_authentication(self, conf, attrib=None):
"""
This function triggers the parsing of 'authentication' attributes.
:param conf: configuration
:param attrib: 'authentication'
:return: generated config dictionary
"""
- cfg_dict = self.parse_attr(conf, ['plaintext_password'],
- match=attrib)
- cfg_dict['md5'] = self.parse_attrib_list(conf, 'key-id', 'key_id')
+ cfg_dict = self.parse_attr(conf, ["plaintext_password"], match=attrib)
+ cfg_dict["md5"] = self.parse_attrib_list(conf, "key-id", "key_id")
return cfg_dict
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.replace('_', '-')
- + " (?:\'*)(\\S+)(?:\'*)", conf, M)
- elif attrib == 'key-id':
- items = findall(r"^.*" + attrib.replace('_', '-')
- + " (?:\'*)(\\S+)(?:\'*)", conf, M)
+ if attrib == "area":
+ items = findall(
+ r"^" + attrib.replace("_", "-") + " (?:'*)(\\S+)(?:'*)",
+ conf,
+ M,
+ )
+ elif attrib == "key-id":
+ items = findall(
+ r"^.*" + attrib.replace("_", "-") + " (?:'*)(\\S+)(?:'*)",
+ conf,
+ M,
+ )
else:
- items = findall(r"" + attrib + " (?:\'*)(\\S+)(?:\'*)", conf, M)
+ 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':
+ cfg = "\n".join(findall(i_regex, conf, M))
+ if attrib == "area":
obj = self.parse_area(cfg, item)
- elif attrib == 'virtual-link':
+ elif attrib == "virtual-link":
obj = self.parse_vlink(cfg)
- elif attrib == 'key-id':
+ elif attrib == "key-id":
obj = self.parse_key(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_attrib(self, conf, param, match=None):
"""
This function triggers the parsing of 'ospf' attributes
:param conf: configuration data
:return: generated configuration dictionary
"""
param_lst = {
- 'key_id': ['md5_key'],
- 'mpls_te': ['enabled', 'router_address'],
- 'area_id': ['shortcut', 'authentication'],
- 'neighbor': ['priority', 'poll_interval'],
- 'stub': ['set', 'default_cost', 'no_summary'],
- 'range': ['cost', 'substitute', 'not_advertise'],
- 'ospf': ['external', 'inter_area', 'intra_area'],
- 'spf': ['delay', 'max_holdtime', 'initial_holdtime'],
- 'redistribute': ['metric', 'metric_type', 'route_map'],
- 'nssa': ['set', 'translate', 'default_cost', 'no_summary'],
- 'config_routes': ['default_metric', 'log_adjacency_changes'
- ],
- 'originate': ['always', 'metric', 'metric_type', 'route_map'
- ],
- 'router_lsa': ['administrative', 'on_shutdown', 'on_startup'
- ],
- 'parameters': ['abr_type', 'opaque_lsa', 'router_id',
- 'rfc1583_compatibility'],
- 'vlink': ['dead_interval', 'hello_interval',
- 'transmit_delay', 'retransmit_interval'],
- }
+ "key_id": ["md5_key"],
+ "mpls_te": ["enabled", "router_address"],
+ "area_id": ["shortcut", "authentication"],
+ "neighbor": ["priority", "poll_interval"],
+ "stub": ["set", "default_cost", "no_summary"],
+ "range": ["cost", "substitute", "not_advertise"],
+ "ospf": ["external", "inter_area", "intra_area"],
+ "spf": ["delay", "max_holdtime", "initial_holdtime"],
+ "redistribute": ["metric", "metric_type", "route_map"],
+ "nssa": ["set", "translate", "default_cost", "no_summary"],
+ "config_routes": ["default_metric", "log_adjacency_changes"],
+ "originate": ["always", "metric", "metric_type", "route_map"],
+ "router_lsa": ["administrative", "on_shutdown", "on_startup"],
+ "parameters": [
+ "abr_type",
+ "opaque_lsa",
+ "router_id",
+ "rfc1583_compatibility",
+ ],
+ "vlink": [
+ "dead_interval",
+ "hello_interval",
+ "transmit_delay",
+ "retransmit_interval",
+ ],
+ }
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
+ regex = match.replace("_", "-") + " " + regex
if conf:
if self.is_bool(attrib):
- out = conf.find(attrib.replace('_', '-'))
- dis = conf.find(attrib.replace('_', '-')
- + " 'disable'")
+ out = conf.find(attrib.replace("_", "-"))
+ dis = conf.find(attrib.replace("_", "-") + " 'disable'")
if match:
- if attrib == 'set' and conf.find(match) >= 1:
+ if attrib == "set" and conf.find(match) >= 1:
config[attrib] = True
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)
+ 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 ('area' if attrib
- == 'area_id' else attrib.replace('_', '-'))))
+ return (
+ "disable"
+ if attrib == "disabled"
+ else (
+ "enable"
+ if attrib == "enabled"
+ else (
+ "area" if attrib == "area_id" 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 = (
- 'set',
- 'always',
- 'normal',
- 'enabled',
- 'opaque_lsa',
- 'not_advertise',
- 'administrative',
- 'rfc1583_compatibility',
- )
+ "set",
+ "always",
+ "normal",
+ "enabled",
+ "opaque_lsa",
+ "not_advertise",
+ "administrative",
+ "rfc1583_compatibility",
+ )
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',
- 'delay',
- 'metric',
- 'inter_area',
- 'intra_area',
- 'on_startup',
- 'metric_type',
- 'on_shutdown',
- 'max_holdtime',
- 'poll_interval',
- 'default_metric',
- 'initial_holdtime',
- 'key_id',
- )
+ "ospf",
+ "delay",
+ "metric",
+ "inter_area",
+ "intra_area",
+ "on_startup",
+ "metric_type",
+ "on_shutdown",
+ "max_holdtime",
+ "poll_interval",
+ "default_metric",
+ "initial_holdtime",
+ "key_id",
+ )
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 c539beb..8fa2bfd 100644
--- a/plugins/module_utils/network/vyos/utils/utils.py
+++ b/plugins/module_utils/network/vyos/utils/utils.py
@@ -1,263 +1,270 @@
# -*- 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)
# utils
from __future__ import absolute_import, division, print_function
__metaclass__ = type
from ansible.module_utils.six import iteritems
from ansible_collections.ansible.netcommon.plugins.module_utils.compat import (
ipaddress,
)
def search_obj_in_list(name, lst, key="name"):
if lst:
for item in lst:
if item[key] == name:
return item
return None
def get_interface_type(interface):
"""Gets the type of interface
"""
if interface.startswith("eth"):
return "ethernet"
elif interface.startswith("bond"):
return "bonding"
elif interface.startswith("vti"):
return "vti"
elif interface.startswith("lo"):
return "loopback"
def dict_delete(base, comparable):
"""
This function generates a dict containing key, value pairs for keys
that are present in the `base` dict but not present in the `comparable`
dict.
:param base: dict object to base the diff on
:param comparable: dict object to compare against base
:returns: new dict object with key, value pairs that needs to be deleted.
"""
to_delete = dict()
for key in base:
if isinstance(base[key], dict):
sub_diff = dict_delete(base[key], comparable.get(key, {}))
if sub_diff:
to_delete[key] = sub_diff
else:
if key not in comparable:
to_delete[key] = base[key]
return to_delete
def diff_list_of_dicts(want, have):
diff = []
set_w = set(tuple(d.items()) for d in want)
set_h = set(tuple(d.items()) for d in have)
difference = set_w.difference(set_h)
for element in difference:
diff.append(dict((x, y) for x, y in element))
return diff
def get_lst_diff_for_dicts(want, have, lst):
"""
This function generates a list containing values
that are only in want and not in list in have dict
:param want: dict object to want
:param have: dict object to have
:param lst: list the diff on
:return: new list object with values which are only in want.
"""
if not have:
diff = want.get(lst) or []
else:
want_elements = want.get(lst) or {}
have_elements = have.get(lst) or {}
diff = list_diff_want_only(want_elements, have_elements)
return diff
def get_lst_same_for_dicts(want, have, lst):
"""
This function generates a list containing values
that are common for list in want and list in have dict
:param want: dict object to want
:param have: dict object to have
:param lst: list the comparison on
:return: new list object with values which are common in want and have.
"""
diff = None
if want and have:
want_list = want.get(lst) or {}
have_list = have.get(lst) or {}
diff = [
i
for i in want_list and have_list
if i in have_list and i in want_list
]
return diff
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:
:param have_list:
:return: new list with values which are only in have list
"""
if have_list and not want_list:
diff = have_list
elif not have_list:
diff = None
else:
diff = [
i
for i in have_list + want_list
if i in have_list and i not in want_list
]
return diff
def list_diff_want_only(want_list, have_list):
"""
This function generated the list containing values
that are only in want list.
:param want_list:
:param have_list:
:return: new list with values which are only in want list
"""
if have_list and not want_list:
diff = None
elif not have_list:
diff = want_list
else:
diff = [
i
for i in have_list + want_list
if i in want_list and i not in have_list
]
return diff
def search_dict_tv_in_list(d_val1, d_val2, lst, key1, key2):
"""
This function return the dict object if it exist in list.
:param d_val1:
:param d_val2:
:param lst:
:param key1:
:param key2:
:return:
"""
obj = next(
(
item
for item in lst
if item[key1] == d_val1 and item[key2] == d_val2
),
None,
)
if obj:
return obj
else:
return None
def key_value_in_dict(have_key, have_value, want_dict):
"""
This function checks whether the key and values exist in dict
:param have_key:
:param have_value:
:param want_dict:
:return:
"""
for key, value in iteritems(want_dict):
if key == have_key and value == have_value:
return True
return False
def is_dict_element_present(dict, key):
"""
This function checks whether the key is present in dict.
:param dict:
:param key:
:return:
"""
for item in dict:
if item == key:
return True
return False
def get_ip_address_version(address):
"""
This function returns the version of IP address
:param address: IP address
:return:
"""
try:
address = unicode(address)
except NameError:
address = str(address)
version = ipaddress.ip_address(address.split("/")[0]).version
return version
def get_route_type(address):
"""
This function returns the route type based on IP address
:param address:
:return:
"""
version = get_ip_address_version(address)
if version == 6:
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
+ 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_ospfv2.py b/plugins/modules/vyos_ospfv2.py
index 866ed76..9c40d9c 100644
--- a/plugins/modules/vyos_ospfv2.py
+++ b/plugins/modules/vyos_ospfv2.py
@@ -1,1981 +1,1814 @@
#!/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_ospfv2
"""
from __future__ import absolute_import, division, print_function
+
__metaclass__ = type
-ANSIBLE_METADATA = {
- 'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'network'
-}
+ANSIBLE_METADATA = {"metadata_version": "1.1", "supported_by": "Ansible"}
DOCUMENTATION = """
---
module: vyos_ospfv2
version_added: 2.10
-short_description: This resource module configures and manages attributes of OSPFv2 routes on VyOS network devices.
+short_description: OSPFV2 resource module
description: This resource module configures and manages attributes of OSPFv2 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 OSPFv2 route configuration.
type: dict
suboptions:
areas:
description: OSPFv2 area.
type: list
elements: dict
suboptions:
area_id:
- description: Configured to discard packets.
+ description: OSPFv2 area identity.
type: str
area_type:
description: Area type.
type: dict
suboptions:
normal:
description: Normal OSPFv2 area.
type: bool
nssa:
- description: Nssa OSPFv2 area.
+ description: NSSA OSPFv2 area.
type: dict
suboptions:
- set:
- description: Enabling nssa.
+ set:
+ description: Enabling NSSA.
type: bool
default_cost:
- description: Summary-default cost of nssa area.
+ description: Summary-default cost of NSSA area.
type: int
no_summary:
description: Do not inject inter-area routes into stub.
type: bool
- translate:
- description: Nssa-abr.
+ translate:
+ description: NSSA-ABR.
type: str
choices: ['always', 'candidate', 'never']
- stub:
+ stub:
description: Stub OSPFv2 area.
type: dict
suboptions:
- set:
+ set:
description: Enabling stub.
type: bool
default_cost:
description: Summary-default cost of stub area.
type: int
no_summary:
description: Do not inject inter-area routes into stub.
type: bool
authentication:
description: OSPFv2 area authentication type.
type: str
choices: ['plaintext-password', 'md5']
network:
description: OSPFv2 network.
type: list
elements: dict
suboptions:
address:
required: True
description: OSPFv2 IPv4 network address.
- type: str
+ type: str
range:
description: Summarize routes matching prefix (border routers only).
type: list
elements: dict
suboptions:
address:
description: border router IPv4 address.
type: str
cost:
description: Metric for this range.
type: int
not_advertise:
description: Don't advertise this range.
type: bool
substitute:
description: Announce area range (IPv4 address) as another prefix.
type: str
shortcut:
description: Area's shortcut mode.
type: str
choices: ['default', 'disable', 'enable']
virtual_link:
description: Virtual link address.
type: list
elements: dict
suboptions:
address:
description: virtual link address.
type: str
authentication:
description: OSPFv2 area authentication type.
type: dict
suboptions:
md5:
description: MD5 key id based authentication.
type: list
elements: dict
suboptions:
key_id:
description: MD5 key id.
type: int
md5_key:
description: MD5 key.
type: str
plaintext_password:
description: Plain text password.
type: str
dead_interval:
description: Interval after which a neighbor is declared dead.
type: int
hello_interval:
description: Interval between hello packets.
type: int
- retransmit_interval:
+ retransmit_interval:
description: Interval between retransmitting lost link state advertisements.
type: int
transmit_delay:
description: Link state transmit delay.
type: int
log_adjacency_changes:
description: Log changes in adjacency state.
type: str
choices: ['detail']
- max_metric:
+ max_metric:
description: OSPFv2 maximum/infinite-distance metric.
type: dict
suboptions:
router_lsa:
description: Advertise own Router-LSA with infinite distance (stub router).
type: dict
suboptions:
administrative:
description: Administratively apply, for an indefinite period.
type: bool
on_shutdown:
description: Time to advertise self as stub-router.
- type: int
+ type: int
on_startup:
description: Time to advertise self as stub-router
- type: int
+ type: int
auto_cost:
description: Calculate OSPFv2 interface cost according to bandwidth.
type: dict
suboptions:
reference_bandwidth:
description: Reference bandwidth cost in Mbits/sec.
type: int
default_information:
description: Control distribution of default information.
type: dict
suboptions:
originate:
description: Distribute a default route.
type: dict
suboptions:
always:
description: Always advertise default route.
type: bool
metric:
description: OSPFv2 default metric.
type: int
metric_type:
description: OSPFv2 Metric types for default routes.
type: int
route_map:
description: Route map references.
- type: str
+ type: str
default_metric:
description: Metric of redistributed routes
type: int
distance:
description: Administrative distance.
type: dict
suboptions:
global:
description: Global OSPFv2 administrative distance.
type: int
- ospf:
+ ospf:
description: OSPFv2 administrative distance.
type: dict
suboptions:
- external:
+ external:
description: Distance for external routes.
type: int
inter_area:
description: Distance for inter-area routes.
type: int
intra_area:
description: Distance for intra-area routes.
type: int
mpls_te:
description: MultiProtocol Label Switching-Traffic Engineering (MPLS-TE) parameters.
type: dict
suboptions:
enabled:
description: Enable MPLS-TE functionality.
type: bool
router_address:
description: Stable IP address of the advertising router.
type: str
neighbor:
description: Neighbor IP address.
type: list
elements: dict
suboptions:
neighbor_id:
description: Identity (number/IP address) of neighbor.
- type: str
+ type: str
poll_interval:
description: Seconds between dead neighbor polling interval.
type: int
priority:
description: Neighbor priority.
- type: int
+ type: int
parameters:
descriptions: OSPFv2 specific parameters.
type: dict
- suboptions:
- abr_type:
+ suboptions:
+ abr_type:
description: OSPFv2 ABR Type.
type: str
choices: ['cisco', 'ibm', 'shortcut', 'standard']
opaque_lsa:
description: Enable the Opaque-LSA capability (rfc2370).
type: bool
rfc1583_compatibility:
description: Enable rfc1583 criteria for handling AS external routes.
type: bool
- router_id:
+ router_id:
description: Override the default router identifier.
type: str
passive_interface:
description: Suppress routing updates on an interface.
type: list
passive_interface_exclude:
description: Interface to exclude when using passive-interface default.
type: list
- redistribute:
+ redistribute:
description: Redistribute information from another routing protocol.
type: list
elements: dict
- suboptions:
+ suboptions:
route_type:
description: Route type to redistribute.
type: str
choices: ['bgp', 'connected', 'kernel', 'rip', 'static']
metric:
description: Metric for redistribution routes.
type: int
metric_type:
description: OSPFv2 Metric types.
type: int
route_map:
description: Route map references.
- type: str
-
+ type: str
route_map:
- description: Filter routes installed in local route map.
+ description: Filter routes installed in local route map.
type: list
timers:
description: Adjust routing timers.
type: dict
suboptions:
refresh:
description: Adjust refresh parameters.
type: dict
suboptions:
timers:
description: refresh timer.
type: int
throttle:
description: Throttling adaptive timers.
type: dict
suboptions:
spf:
description: OSPFv2 SPF timers.
type: dict
suboptions:
delay:
description: Delay (msec) from first change received till SPF calculation.
type: int
initial_holdtime:
description: Initial hold time(msec) between consecutive SPF calculations.
type: int
max_holdtime:
description: maximum hold time (sec).
type: int
running_config:
description:
- - The module, by default, will connect to the remote device and retrieve the current
- running-config to use as a base for comparing against the contents of source.
- There are times when it is not desirable to have the task get the current running-config
- for every task in a playbook. The I(running_config) argument allows the implementer
- to pass in the configuration to use as the base config for comparison. This
- value of this option should be the output received from device by executing
- command C(show configuration commands | grep 'ospf')
+ - 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 ospf).
+ - 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 ospf
-#
-#
-- name: Merge the provided configuration with the exisiting running configuration
- vyos.vyos.vyos_ospfv2:
- config:
- log_adjacency_changes: 'detail'
- max_metric:
- router_lsa:
- administrative: true
- on_shutdown: 10
- on_startup: 10
- default_information:
- originate:
- always: true
- metric: 10
- metric_type: 2
- route_map: 'ingress'
- mpls_te:
- enabled: true
- router_address: '192.0.11.11'
- auto_cost:
- reference_bandwidth: 2
- neighbor:
- - neighbor_id: '192.0.11.12'
- poll_interval: 10
- priority: 2
- redistribute:
- - route_type: 'bgp'
- metric: 10
- metric_type: 2
- passive_interface:
- - 'eth1'
- - 'eth2'
- parameters:
- router_id: '192.0.1.1'
- opaque_lsa: true
- rfc1583_compatibility: true
- abr_type: 'cisco'
- areas:
- - area_id: '2'
- area_type:
- normal: true
- authentication: "plaintext-password"
- shortcut: 'enable'
- - area_id: '3'
- area_type:
- nssa:
- set: true
- - area_id: '4'
- area_type:
- stub:
- default_cost: 20
- network:
- - address: '192.0.2.0/24'
- range:
- - address: '192.0.3.0/24'
- cost: 10
- - address: '192.0.4.0/24'
- cost: 12
- state: merged
+# vyos@vyos# run show configuration commands | grep ospf
+#
+#
+- name: Merge the provided configuration with the existing running configuration
+ vyos.vyos.vyos_ospfv2:
+ config:
+ log_adjacency_changes: 'detail'
+ max_metric:
+ router_lsa:
+ administrative: true
+ on_shutdown: 10
+ on_startup: 10
+ default_information:
+ originate:
+ always: true
+ metric: 10
+ metric_type: 2
+ route_map: 'ingress'
+ mpls_te:
+ enabled: true
+ router_address: '192.0.11.11'
+ auto_cost:
+ reference_bandwidth: 2
+ neighbor:
+ - neighbor_id: '192.0.11.12'
+ poll_interval: 10
+ priority: 2
+ redistribute:
+ - route_type: 'bgp'
+ metric: 10
+ metric_type: 2
+ passive_interface:
+ - 'eth1'
+ - 'eth2'
+ parameters:
+ router_id: '192.0.1.1'
+ opaque_lsa: true
+ rfc1583_compatibility: true
+ abr_type: 'cisco'
+ areas:
+ - area_id: '2'
+ area_type:
+ normal: true
+ authentication: "plaintext-password"
+ shortcut: 'enable'
+ - area_id: '3'
+ area_type:
+ nssa:
+ set: true
+ - area_id: '4'
+ area_type:
+ stub:
+ default_cost: 20
+ network:
+ - address: '192.0.2.0/24'
+ range:
+ - address: '192.0.3.0/24'
+ cost: 10
+ - address: '192.0.4.0/24'
+ cost: 12
+ state: merged
#
#
# -------------------------
# Module Execution Result
# -------------------------
#
-# before": []
+# before": {}
#
# "commands": [
# "set protocols ospf mpls-te enable",
# "set protocols ospf mpls-te router-address '192.0.11.11'",
# "set protocols ospf redistribute bgp",
# "set protocols ospf redistribute bgp metric-type 2",
# "set protocols ospf redistribute bgp metric 10",
# "set protocols ospf default-information originate metric-type 2",
# "set protocols ospf default-information originate always",
# "set protocols ospf default-information originate metric 10",
# "set protocols ospf default-information originate route-map ingress",
# "set protocols ospf auto-cost reference-bandwidth '2'",
# "set protocols ospf parameters router-id '192.0.1.1'",
# "set protocols ospf parameters opaque-lsa",
# "set protocols ospf parameters abr-type 'cisco'",
# "set protocols ospf parameters rfc1583-compatibility",
# "set protocols ospf passive-interface eth1",
# "set protocols ospf passive-interface eth2",
# "set protocols ospf max-metric router-lsa on-shutdown 10",
# "set protocols ospf max-metric router-lsa administrative",
# "set protocols ospf max-metric router-lsa on-startup 10",
# "set protocols ospf log-adjacency-changes 'detail'",
# "set protocols ospf neighbor 192.0.11.12 priority 2",
# "set protocols ospf neighbor 192.0.11.12 poll-interval 10",
# "set protocols ospf neighbor 192.0.11.12",
# "set protocols ospf area '2'",
# "set protocols ospf area 2 authentication plaintext-password",
# "set protocols ospf area 2 shortcut enable",
# "set protocols ospf area 2 area-type normal",
# "set protocols ospf area '3'",
# "set protocols ospf area 3 area-type nssa",
# "set protocols ospf area 4 range 192.0.3.0/24 cost 10",
# "set protocols ospf area 4 range 192.0.3.0/24",
# "set protocols ospf area 4 range 192.0.4.0/24 cost 12",
# "set protocols ospf area 4 range 192.0.4.0/24",
# "set protocols ospf area 4 area-type stub default-cost 20",
# "set protocols ospf area '4'",
# "set protocols ospf area 4 network 192.0.2.0/24"
# ]
#
# "after": {
# "areas": [
# {
# "area_id": "2",
# "area_type": {
# "normal": true
# },
# "authentication": "plaintext-password",
# "shortcut": "enable"
# },
# {
# "area_id": "3",
# "area_type": {
# "nssa": {
# "set": true
# }
# }
# },
# {
# "area_id": "4",
# "area_type": {
# "stub": {
# "default_cost": 20,
# "set": true
# }
# },
# "network": [
# {
# "address": "192.0.2.0/24"
# }
# ],
# "range": [
# {
# "address": "192.0.3.0/24",
# "cost": 10
# },
# {
# "address": "192.0.4.0/24",
# "cost": 12
# }
# ]
# }
# ],
# "auto_cost": {
# "reference_bandwidth": 2
# },
# "default_information": {
# "originate": {
# "always": true,
# "metric": 10,
# "metric_type": 2,
# "route_map": "ingress"
# }
# },
# "log_adjacency_changes": "detail",
# "max_metric": {
# "router_lsa": {
# "administrative": true,
# "on_shutdown": 10,
# "on_startup": 10
# }
# },
# "mpls_te": {
# "enabled": true,
# "router_address": "192.0.11.11"
# },
# "neighbor": [
# {
# "neighbor_id": "192.0.11.12",
# "poll_interval": 10,
# "priority": 2
# }
# ],
# "parameters": {
# "abr_type": "cisco",
# "opaque_lsa": true,
# "rfc1583_compatibility": true,
# "router_id": "192.0.1.1"
# },
# "passive_interface": [
# "eth2",
# "eth1"
# ],
# "redistribute": [
# {
# "metric": 10,
# "metric_type": 2,
# "route_type": "bgp"
# }
# ]
# }
#
# After state:
# -------------
#
# vyos@192# run show configuration commands | grep ospf
# set protocols ospf area 2 area-type 'normal'
# set protocols ospf area 2 authentication 'plaintext-password'
# set protocols ospf area 2 shortcut 'enable'
# set protocols ospf area 3 area-type 'nssa'
# set protocols ospf area 4 area-type stub default-cost '20'
# set protocols ospf area 4 network '192.0.2.0/24'
# set protocols ospf area 4 range 192.0.3.0/24 cost '10'
# set protocols ospf area 4 range 192.0.4.0/24 cost '12'
# set protocols ospf auto-cost reference-bandwidth '2'
# set protocols ospf default-information originate 'always'
# set protocols ospf default-information originate metric '10'
# set protocols ospf default-information originate metric-type '2'
# set protocols ospf default-information originate route-map 'ingress'
# set protocols ospf log-adjacency-changes 'detail'
# set protocols ospf max-metric router-lsa 'administrative'
# set protocols ospf max-metric router-lsa on-shutdown '10'
# set protocols ospf max-metric router-lsa on-startup '10'
# set protocols ospf mpls-te 'enable'
# set protocols ospf mpls-te router-address '192.0.11.11'
# set protocols ospf neighbor 192.0.11.12 poll-interval '10'
# set protocols ospf neighbor 192.0.11.12 priority '2'
# set protocols ospf parameters abr-type 'cisco'
# set protocols ospf parameters 'opaque-lsa'
# set protocols ospf parameters 'rfc1583-compatibility'
# set protocols ospf parameters router-id '192.0.1.1'
# set protocols ospf passive-interface 'eth1'
# set protocols ospf passive-interface 'eth2'
# set protocols ospf redistribute bgp metric '10'
# set protocols ospf redistribute bgp metric-type '2'
# Using merged
#
# Before state:
# -------------
#
-# vyos@vyos# run show configuration commands | grep ospf
-#
-#
-- name: Merge the provided configuration to update exisiting running configuration
- vyos.vyos.vyos_ospfv2:
- config:
- areas:
- - area_id: '2'
- area_type:
- normal: true
- authentication: "plaintext-password"
- shortcut: 'enable'
- - area_id: '3'
- area_type:
- nssa:
- set: false
- - area_id: '4'
- area_type:
- stub:
- default_cost: 20
- network:
- - address: '192.0.2.0/24'
- - address: '192.0.22.0/24'
- - address: '192.0.32.0/24'
- state: merged
+# vyos@vyos# run show configuration commands | grep ospf
+#
+#
+- name: Merge the provided configuration to update existing running configuration
+ vyos.vyos.vyos_ospfv2:
+ config:
+ areas:
+ - area_id: '2'
+ area_type:
+ normal: true
+ authentication: "plaintext-password"
+ shortcut: 'enable'
+ - area_id: '3'
+ area_type:
+ nssa:
+ set: false
+ - area_id: '4'
+ area_type:
+ stub:
+ default_cost: 20
+ network:
+ - address: '192.0.2.0/24'
+ - address: '192.0.22.0/24'
+ - address: '192.0.32.0/24'
+ state: merged
#
#
# -------------------------
# Module Execution Result
# -------------------------
#
# "before": {
# "areas": [
# {
# "area_id": "2",
# "area_type": {
# "normal": true
# },
# "authentication": "plaintext-password",
# "shortcut": "enable"
# },
# {
# "area_id": "3",
# "area_type": {
# "nssa": {
# "set": true
# }
# }
# },
# {
# "area_id": "4",
# "area_type": {
# "stub": {
# "default_cost": 20,
# "set": true
# }
# },
# "network": [
# {
# "address": "192.0.2.0/24"
# }
# ],
# "range": [
# {
# "address": "192.0.3.0/24",
# "cost": 10
# },
# {
# "address": "192.0.4.0/24",
# "cost": 12
# }
# ]
# }
# ],
# "auto_cost": {
# "reference_bandwidth": 2
# },
# "default_information": {
# "originate": {
# "always": true,
# "metric": 10,
# "metric_type": 2,
# "route_map": "ingress"
# }
# },
# "log_adjacency_changes": "detail",
# "max_metric": {
# "router_lsa": {
# "administrative": true,
# "on_shutdown": 10,
# "on_startup": 10
# }
# },
# "mpls_te": {
# "enabled": true,
# "router_address": "192.0.11.11"
# },
# "neighbor": [
# {
# "neighbor_id": "192.0.11.12",
# "poll_interval": 10,
# "priority": 2
# }
# ],
# "parameters": {
# "abr_type": "cisco",
# "opaque_lsa": true,
# "rfc1583_compatibility": true,
# "router_id": "192.0.1.1"
# },
# "passive_interface": [
# "eth2",
# "eth1"
# ],
# "redistribute": [
# {
# "metric": 10,
# "metric_type": 2,
# "route_type": "bgp"
# }
# ]
# }
#
# "commands": [
# "delete protocols ospf area 4 area-type stub",
# "set protocols ospf area 4 network 192.0.22.0/24"
# "set protocols ospf area 4 network 192.0.32.0/24"
# ]
#
# "after": {
# "areas": [
# {
# "area_id": "2",
# "area_type": {
# "normal": true
# },
# "authentication": "plaintext-password",
# "shortcut": "enable"
# },
# {
# "area_id": "3",
# "area_type": {
# "nssa": {
# "set": true
# }
# }
# },
# {
# "area_id": "4",
# },
# "network": [
# {
# "address": "192.0.2.0/24"
# },
# {
# "address": "192.0.22.0/24"
# },
# {
# "address": "192.0.32.0/24"
# }
# ],
# "range": [
# {
# "address": "192.0.3.0/24",
# "cost": 10
# },
# {
# "address": "192.0.4.0/24",
# "cost": 12
# }
# ]
# }
# ],
# "auto_cost": {
# "reference_bandwidth": 2
# },
# "default_information": {
# "originate": {
# "always": true,
# "metric": 10,
# "metric_type": 2,
# "route_map": "ingress"
# }
# },
# "log_adjacency_changes": "detail",
# "max_metric": {
# "router_lsa": {
# "administrative": true,
# "on_shutdown": 10,
# "on_startup": 10
# }
# },
# "mpls_te": {
# "enabled": true,
# "router_address": "192.0.11.11"
# },
# "neighbor": [
# {
# "neighbor_id": "192.0.11.12",
# "poll_interval": 10,
# "priority": 2
# }
# ],
# "parameters": {
# "abr_type": "cisco",
# "opaque_lsa": true,
# "rfc1583_compatibility": true,
# "router_id": "192.0.1.1"
# },
# "passive_interface": [
# "eth2",
# "eth1"
# ],
# "redistribute": [
# {
# "metric": 10,
# "metric_type": 2,
# "route_type": "bgp"
# }
# ]
# }
#
# After state:
# -------------
#
# vyos@192# run show configuration commands | grep ospf
# set protocols ospf area 2 area-type 'normal'
# set protocols ospf area 2 authentication 'plaintext-password'
# set protocols ospf area 2 shortcut 'enable'
# set protocols ospf area 3 area-type 'nssa'
# set protocols ospf area 4 network '192.0.2.0/24'
# set protocols ospf area 4 network '192.0.22.0/24'
# set protocols ospf area 4 network '192.0.32.0/24'
# set protocols ospf area 4 range 192.0.3.0/24 cost '10'
# set protocols ospf area 4 range 192.0.4.0/24 cost '12'
# set protocols ospf auto-cost reference-bandwidth '2'
# set protocols ospf default-information originate 'always'
# set protocols ospf default-information originate metric '10'
# set protocols ospf default-information originate metric-type '2'
# set protocols ospf default-information originate route-map 'ingress'
# set protocols ospf log-adjacency-changes 'detail'
# set protocols ospf max-metric router-lsa 'administrative'
# set protocols ospf max-metric router-lsa on-shutdown '10'
# set protocols ospf max-metric router-lsa on-startup '10'
# set protocols ospf mpls-te 'enable'
# set protocols ospf mpls-te router-address '192.0.11.11'
# set protocols ospf neighbor 192.0.11.12 poll-interval '10'
# set protocols ospf neighbor 192.0.11.12 priority '2'
# set protocols ospf parameters abr-type 'cisco'
# set protocols ospf parameters 'opaque-lsa'
# set protocols ospf parameters 'rfc1583-compatibility'
# set protocols ospf parameters router-id '192.0.1.1'
# set protocols ospf passive-interface 'eth1'
# set protocols ospf passive-interface 'eth2'
# set protocols ospf redistribute bgp metric '10'
# set protocols ospf redistribute bgp metric-type '2'
# Using replaced
#
# Before state:
# -------------
#
# vyos@192# run show configuration commands | grep ospf
# set protocols ospf area 2 area-type 'normal'
# set protocols ospf area 2 authentication 'plaintext-password'
# set protocols ospf area 2 shortcut 'enable'
# set protocols ospf area 3 area-type 'nssa'
# set protocols ospf area 4 area-type stub default-cost '20'
# set protocols ospf area 4 network '192.0.2.0/24'
# set protocols ospf area 4 range 192.0.3.0/24 cost '10'
# set protocols ospf area 4 range 192.0.4.0/24 cost '12'
# set protocols ospf auto-cost reference-bandwidth '2'
# set protocols ospf default-information originate 'always'
# set protocols ospf default-information originate metric '10'
# set protocols ospf default-information originate metric-type '2'
# set protocols ospf default-information originate route-map 'ingress'
# set protocols ospf log-adjacency-changes 'detail'
# set protocols ospf max-metric router-lsa 'administrative'
# set protocols ospf max-metric router-lsa on-shutdown '10'
# set protocols ospf max-metric router-lsa on-startup '10'
# set protocols ospf mpls-te 'enable'
# set protocols ospf mpls-te router-address '192.0.11.11'
# set protocols ospf neighbor 192.0.11.12 poll-interval '10'
# set protocols ospf neighbor 192.0.11.12 priority '2'
# set protocols ospf parameters abr-type 'cisco'
# set protocols ospf parameters 'opaque-lsa'
# set protocols ospf parameters 'rfc1583-compatibility'
# set protocols ospf parameters router-id '192.0.1.1'
# set protocols ospf passive-interface 'eth1'
# set protocols ospf passive-interface 'eth2'
# set protocols ospf redistribute bgp metric '10'
# set protocols ospf redistribute bgp metric-type '2'
#
- name: Replace ospfv2 routes attributes configuration.
- vyos.vyos.vyos_ospfv2:
- config:
- log_adjacency_changes: 'detail'
- max_metric:
- router_lsa:
- administrative: true
- on_shutdown: 10
- on_startup: 10
- default_information:
- originate:
- always: true
- metric: 10
- metric_type: 2
- route_map: 'ingress'
- mpls_te:
- enabled: true
- router_address: '192.0.22.22'
- auto_cost:
- reference_bandwidth: 2
- neighbor:
- - neighbor_id: '192.0.11.12'
- poll_interval: 10
- priority: 2
- redistribute:
- - route_type: 'bgp'
- metric: 10
- metric_type: 2
- passive_interface:
- - 'eth1'
- parameters:
- router_id: '192.0.1.1'
- opaque_lsa: true
- rfc1583_compatibility: true
- abr_type: 'cisco'
- areas:
- - area_id: '2'
- area_type:
- normal: true
- authentication: "plaintext-password"
- shortcut: 'enable'
- - area_id: '4'
- area_type:
- stub:
- default_cost: 20
- network:
- - address: '192.0.2.0/24'
- - address: '192.0.12.0/24'
- - address: '192.0.22.0/24'
- - address: '192.0.32.0/24'
- range:
- - address: '192.0.42.0/24'
- cost: 10
- state: replaced
+ vyos.vyos.vyos_ospfv2:
+ config:
+ log_adjacency_changes: 'detail'
+ max_metric:
+ router_lsa:
+ administrative: true
+ on_shutdown: 10
+ on_startup: 10
+ default_information:
+ originate:
+ always: true
+ metric: 10
+ metric_type: 2
+ route_map: 'ingress'
+ mpls_te:
+ enabled: true
+ router_address: '192.0.22.22'
+ auto_cost:
+ reference_bandwidth: 2
+ neighbor:
+ - neighbor_id: '192.0.11.12'
+ poll_interval: 10
+ priority: 2
+ redistribute:
+ - route_type: 'bgp'
+ metric: 10
+ metric_type: 2
+ passive_interface:
+ - 'eth1'
+ parameters:
+ router_id: '192.0.1.1'
+ opaque_lsa: true
+ rfc1583_compatibility: true
+ abr_type: 'cisco'
+ areas:
+ - area_id: '2'
+ area_type:
+ normal: true
+ authentication: "plaintext-password"
+ shortcut: 'enable'
+ - area_id: '4'
+ area_type:
+ stub:
+ default_cost: 20
+ network:
+ - address: '192.0.2.0/24'
+ - address: '192.0.12.0/24'
+ - address: '192.0.22.0/24'
+ - address: '192.0.32.0/24'
+ range:
+ - address: '192.0.42.0/24'
+ cost: 10
+ state: replaced
#
#
# -------------------------
# Module Execution Result
# -------------------------
#
# "before": {
# "areas": [
# {
# "area_id": "2",
# "area_type": {
# "normal": true
# },
# "authentication": "plaintext-password",
# "shortcut": "enable"
# },
# {
# "area_id": "3",
# "area_type": {
# "nssa": {
# "set": true
# }
# }
# },
# {
# "area_id": "4",
# "area_type": {
# "stub": {
# "default_cost": 20,
# "set": true
# }
# },
# "network": [
# {
# "address": "192.0.2.0/24"
# }
# ],
# "range": [
# {
# "address": "192.0.3.0/24",
# "cost": 10
# },
# {
# "address": "192.0.4.0/24",
# "cost": 12
# }
# ]
# }
# ],
# "auto_cost": {
# "reference_bandwidth": 2
# },
# "default_information": {
# "originate": {
# "always": true,
# "metric": 10,
# "metric_type": 2,
# "route_map": "ingress"
# }
# },
# "log_adjacency_changes": "detail",
# "max_metric": {
# "router_lsa": {
# "administrative": true,
# "on_shutdown": 10,
# "on_startup": 10
# }
# },
# "mpls_te": {
# "enabled": true,
# "router_address": "192.0.11.11"
# },
# "neighbor": [
# {
# "neighbor_id": "192.0.11.12",
# "poll_interval": 10,
# "priority": 2
# }
# ],
# "parameters": {
# "abr_type": "cisco",
# "opaque_lsa": true,
# "rfc1583_compatibility": true,
# "router_id": "192.0.1.1"
# },
# "passive_interface": [
# "eth2",
# "eth1"
# ],
# "redistribute": [
# {
# "metric": 10,
# "metric_type": 2,
# "route_type": "bgp"
# }
# ]
# }
#
# "commands": [
# "delete protocols ospf passive-interface eth2",
# "delete protocols ospf area 3",
# "delete protocols ospf area 4 range 192.0.3.0/24 cost",
# "delete protocols ospf area 4 range 192.0.3.0/24",
# "delete protocols ospf area 4 range 192.0.4.0/24 cost",
# "delete protocols ospf area 4 range 192.0.4.0/24",
# "set protocols ospf mpls-te router-address '192.0.22.22'",
# "set protocols ospf area 4 range 192.0.42.0/24 cost 10",
# "set protocols ospf area 4 range 192.0.42.0/24",
# "set protocols ospf area 4 network 192.0.12.0/24",
# "set protocols ospf area 4 network 192.0.22.0/24",
# "set protocols ospf area 4 network 192.0.32.0/24"
# ]
#
# "after": {
# "areas": [
# {
# "area_id": "2",
# "area_type": {
# "normal": true
# },
# "authentication": "plaintext-password",
# "shortcut": "enable"
# },
# {
# "area_id": "4",
# "area_type": {
# "stub": {
# "default_cost": 20,
# "set": true
# }
# },
# "network": [
# {
# "address": "192.0.12.0/24"
# },
# {
# "address": "192.0.2.0/24"
# },
# {
# "address": "192.0.22.0/24"
# },
# {
# "address": "192.0.32.0/24"
# }
# ],
# "range": [
# {
# "address": "192.0.42.0/24",
# "cost": 10
# }
# ]
# }
# ],
# "auto_cost": {
# "reference_bandwidth": 2
# },
# "default_information": {
# "originate": {
# "always": true,
# "metric": 10,
# "metric_type": 2,
# "route_map": "ingress"
# }
# },
# "log_adjacency_changes": "detail",
# "max_metric": {
# "router_lsa": {
# "administrative": true,
# "on_shutdown": 10,
# "on_startup": 10
# }
# },
# "mpls_te": {
# "enabled": true,
# "router_address": "192.0.22.22"
# },
# "neighbor": [
# {
# "neighbor_id": "192.0.11.12",
# "poll_interval": 10,
# "priority": 2
# }
# ],
# "parameters": {
# "abr_type": "cisco",
# "opaque_lsa": true,
# "rfc1583_compatibility": true,
# "router_id": "192.0.1.1"
# },
# "passive_interface": [
# "eth1"
# ],
# "redistribute": [
# {
# "metric": 10,
# "metric_type": 2,
# "route_type": "bgp"
# }
# ]
# }
-#
+#
# After state:
# -------------
#
# vyos@192# run show configuration commands | grep ospf
# set protocols ospf area 2 area-type 'normal'
# set protocols ospf area 2 authentication 'plaintext-password'
# set protocols ospf area 2 shortcut 'enable'
# set protocols ospf area 4 area-type stub default-cost '20'
# set protocols ospf area 4 network '192.0.2.0/24'
# set protocols ospf area 4 network '192.0.12.0/24'
# set protocols ospf area 4 network '192.0.22.0/24'
# set protocols ospf area 4 network '192.0.32.0/24'
# set protocols ospf area 4 range 192.0.42.0/24 cost '10'
# set protocols ospf auto-cost reference-bandwidth '2'
# set protocols ospf default-information originate 'always'
# set protocols ospf default-information originate metric '10'
# set protocols ospf default-information originate metric-type '2'
# set protocols ospf default-information originate route-map 'ingress'
# set protocols ospf log-adjacency-changes 'detail'
# set protocols ospf max-metric router-lsa 'administrative'
# set protocols ospf max-metric router-lsa on-shutdown '10'
# set protocols ospf max-metric router-lsa on-startup '10'
# set protocols ospf mpls-te 'enable'
# set protocols ospf mpls-te router-address '192.0.22.22'
# set protocols ospf neighbor 192.0.11.12 poll-interval '10'
# set protocols ospf neighbor 192.0.11.12 priority '2'
# set protocols ospf parameters abr-type 'cisco'
# set protocols ospf parameters 'opaque-lsa'
# set protocols ospf parameters 'rfc1583-compatibility'
# set protocols ospf parameters router-id '192.0.1.1'
# set protocols ospf passive-interface 'eth1'
# set protocols ospf redistribute bgp metric '10'
# set protocols ospf redistribute bgp metric-type '2'
# Using rendered
#
#
- name: Render the commands for provided configuration
- vyos.vyos.vyos_ospfv2:
- config:
- log_adjacency_changes: 'detail'
- max_metric:
- router_lsa:
- administrative: true
- on_shutdown: 10
- on_startup: 10
- default_information:
- originate:
- always: true
- metric: 10
- metric_type: 2
- route_map: 'ingress'
- mpls_te:
- enabled: true
- router_address: '192.0.11.11'
- auto_cost:
- reference_bandwidth: 2
- neighbor:
- - neighbor_id: '192.0.11.12'
- poll_interval: 10
- priority: 2
- redistribute:
- - route_type: 'bgp'
- metric: 10
- metric_type: 2
- passive_interface:
- - 'eth1'
- - 'eth2'
- parameters:
- router_id: '192.0.1.1'
- opaque_lsa: true
- rfc1583_compatibility: true
- abr_type: 'cisco'
- areas:
- - area_id: '2'
- area_type:
- normal: true
- authentication: "plaintext-password"
- shortcut: 'enable'
- - area_id: '3'
- area_type:
- nssa:
- set: true
- - area_id: '4'
- area_type:
- stub:
- default_cost: 20
- network:
- - address: '192.0.2.0/24'
- range:
- - address: '192.0.3.0/24'
- cost: 10
- - address: '192.0.4.0/24'
- cost: 12
- state: rendered
+ vyos.vyos.vyos_ospfv2:
+ config:
+ log_adjacency_changes: 'detail'
+ max_metric:
+ router_lsa:
+ administrative: true
+ on_shutdown: 10
+ on_startup: 10
+ default_information:
+ originate:
+ always: true
+ metric: 10
+ metric_type: 2
+ route_map: 'ingress'
+ mpls_te:
+ enabled: true
+ router_address: '192.0.11.11'
+ auto_cost:
+ reference_bandwidth: 2
+ neighbor:
+ - neighbor_id: '192.0.11.12'
+ poll_interval: 10
+ priority: 2
+ redistribute:
+ - route_type: 'bgp'
+ metric: 10
+ metric_type: 2
+ passive_interface:
+ - 'eth1'
+ - 'eth2'
+ parameters:
+ router_id: '192.0.1.1'
+ opaque_lsa: true
+ rfc1583_compatibility: true
+ abr_type: 'cisco'
+ areas:
+ - area_id: '2'
+ area_type:
+ normal: true
+ authentication: "plaintext-password"
+ shortcut: 'enable'
+ - area_id: '3'
+ area_type:
+ nssa:
+ set: true
+ - area_id: '4'
+ area_type:
+ stub:
+ default_cost: 20
+ network:
+ - address: '192.0.2.0/24'
+ range:
+ - address: '192.0.3.0/24'
+ cost: 10
+ - address: '192.0.4.0/24'
+ cost: 12
+ state: rendered
#
#
# -------------------------
# Module Execution Result
# -------------------------
#
#
# "rendered": [
# [
# "set protocols ospf mpls-te enable",
# "set protocols ospf mpls-te router-address '192.0.11.11'",
# "set protocols ospf redistribute bgp",
# "set protocols ospf redistribute bgp metric-type 2",
# "set protocols ospf redistribute bgp metric 10",
# "set protocols ospf default-information originate metric-type 2",
# "set protocols ospf default-information originate always",
# "set protocols ospf default-information originate metric 10",
# "set protocols ospf default-information originate route-map ingress",
# "set protocols ospf auto-cost reference-bandwidth '2'",
# "set protocols ospf parameters router-id '192.0.1.1'",
# "set protocols ospf parameters opaque-lsa",
# "set protocols ospf parameters abr-type 'cisco'",
# "set protocols ospf parameters rfc1583-compatibility",
# "set protocols ospf passive-interface eth1",
# "set protocols ospf passive-interface eth2",
# "set protocols ospf max-metric router-lsa on-shutdown 10",
# "set protocols ospf max-metric router-lsa administrative",
# "set protocols ospf max-metric router-lsa on-startup 10",
# "set protocols ospf log-adjacency-changes 'detail'",
# "set protocols ospf neighbor 192.0.11.12 priority 2",
# "set protocols ospf neighbor 192.0.11.12 poll-interval 10",
# "set protocols ospf neighbor 192.0.11.12",
# "set protocols ospf area '2'",
# "set protocols ospf area 2 authentication plaintext-password",
# "set protocols ospf area 2 shortcut enable",
# "set protocols ospf area 2 area-type normal",
# "set protocols ospf area '3'",
# "set protocols ospf area 3 area-type nssa",
# "set protocols ospf area 4 range 192.0.3.0/24 cost 10",
# "set protocols ospf area 4 range 192.0.3.0/24",
# "set protocols ospf area 4 range 192.0.4.0/24 cost 12",
# "set protocols ospf area 4 range 192.0.4.0/24",
# "set protocols ospf area 4 area-type stub default-cost 20",
# "set protocols ospf area '4'",
# "set protocols ospf area 4 network 192.0.2.0/24"
# ]
# Using parsed
#
#
-- name: Render the commands for provided configuration
- vyos.vyos.vyos_ospfv2:
- running_config:
- "set protocols ospf area 2 area-type 'normal'
+- name: Parse the commands for provided structured configuration
+ vyos.vyos.vyos_ospfv2:
+ running_config:
+ "set protocols ospf area 2 area-type 'normal'
set protocols ospf area 2 authentication 'plaintext-password'
set protocols ospf area 2 shortcut 'enable'
set protocols ospf area 3 area-type 'nssa'
set protocols ospf area 4 area-type stub default-cost '20'
set protocols ospf area 4 network '192.0.2.0/24'
set protocols ospf area 4 range 192.0.3.0/24 cost '10'
set protocols ospf area 4 range 192.0.4.0/24 cost '12'
set protocols ospf auto-cost reference-bandwidth '2'
set protocols ospf default-information originate 'always'
set protocols ospf default-information originate metric '10'
set protocols ospf default-information originate metric-type '2'
set protocols ospf default-information originate route-map 'ingress'
set protocols ospf log-adjacency-changes 'detail'
set protocols ospf max-metric router-lsa 'administrative'
set protocols ospf max-metric router-lsa on-shutdown '10'
set protocols ospf max-metric router-lsa on-startup '10'
set protocols ospf mpls-te 'enable'
set protocols ospf mpls-te router-address '192.0.11.11'
set protocols ospf neighbor 192.0.11.12 poll-interval '10'
set protocols ospf neighbor 192.0.11.12 priority '2'
set protocols ospf parameters abr-type 'cisco'
set protocols ospf parameters 'opaque-lsa'
set protocols ospf parameters 'rfc1583-compatibility'
set protocols ospf parameters router-id '192.0.1.1'
set protocols ospf passive-interface 'eth1'
set protocols ospf passive-interface 'eth2'
set protocols ospf redistribute bgp metric '10'
set protocols ospf redistribute bgp metric-type '2'"
- state: parsed
+ state: parsed
#
#
# -------------------------
# Module Execution Result
# -------------------------
#
#
# "parsed": {
# "areas": [
# {
# "area_id": "2",
# "area_type": {
# "normal": true
# },
# "authentication": "plaintext-password",
# "shortcut": "enable"
# },
# {
# "area_id": "3",
# "area_type": {
# "nssa": {
# "set": true
# }
# }
# },
# {
# "area_id": "4",
# "area_type": {
# "stub": {
# "default_cost": 20,
# "set": true
# }
# },
# "network": [
# {
# "address": "192.0.2.0/24"
# }
# ],
# "range": [
# {
# "address": "192.0.3.0/24",
# "cost": 10
# },
# {
# "address": "192.0.4.0/24",
# "cost": 12
# }
# ]
# }
# ],
# "auto_cost": {
# "reference_bandwidth": 2
# },
# "default_information": {
# "originate": {
# "always": true,
# "metric": 10,
# "metric_type": 2,
# "route_map": "ingress"
# }
# },
# "log_adjacency_changes": "detail",
# "max_metric": {
# "router_lsa": {
# "administrative": true,
# "on_shutdown": 10,
# "on_startup": 10
# }
# },
# "mpls_te": {
# "enabled": true,
# "router_address": "192.0.11.11"
# },
# "neighbor": [
# {
# "neighbor_id": "192.0.11.12",
# "poll_interval": 10,
# "priority": 2
# }
# ],
# "parameters": {
# "abr_type": "cisco",
# "opaque_lsa": true,
# "rfc1583_compatibility": true,
# "router_id": "192.0.1.1"
# },
# "passive_interface": [
# "eth2",
# "eth1"
# ],
# "redistribute": [
# {
# "metric": 10,
# "metric_type": 2,
# "route_type": "bgp"
# }
# ]
# }
# }
# Using gathered
#
# Before state:
# -------------
#
# vyos@192# run show configuration commands | grep ospf
# set protocols ospf area 2 area-type 'normal'
# set protocols ospf area 2 authentication 'plaintext-password'
# set protocols ospf area 2 shortcut 'enable'
# set protocols ospf area 3 area-type 'nssa'
# set protocols ospf area 4 area-type stub default-cost '20'
# set protocols ospf area 4 network '192.0.2.0/24'
# set protocols ospf area 4 range 192.0.3.0/24 cost '10'
# set protocols ospf area 4 range 192.0.4.0/24 cost '12'
# set protocols ospf auto-cost reference-bandwidth '2'
# set protocols ospf default-information originate 'always'
# set protocols ospf default-information originate metric '10'
# set protocols ospf default-information originate metric-type '2'
# set protocols ospf default-information originate route-map 'ingress'
# set protocols ospf log-adjacency-changes 'detail'
# set protocols ospf max-metric router-lsa 'administrative'
# set protocols ospf max-metric router-lsa on-shutdown '10'
# set protocols ospf max-metric router-lsa on-startup '10'
# set protocols ospf mpls-te 'enable'
# set protocols ospf mpls-te router-address '192.0.11.11'
# set protocols ospf neighbor 192.0.11.12 poll-interval '10'
# set protocols ospf neighbor 192.0.11.12 priority '2'
# set protocols ospf parameters abr-type 'cisco'
# set protocols ospf parameters 'opaque-lsa'
# set protocols ospf parameters 'rfc1583-compatibility'
# set protocols ospf parameters router-id '192.0.1.1'
# set protocols ospf passive-interface 'eth1'
# set protocols ospf passive-interface 'eth2'
# set protocols ospf redistribute bgp metric '10'
# set protocols ospf redistribute bgp metric-type '2'
#
- name: Gather ospfv2 routes config with provided configurations
- vyos.vyos.vyos_ospfv2:
- config:
- state: gathered
+ vyos.vyos.vyos_ospfv2:
+ config:
+ state: gathered
#
#
# -------------------------
# Module Execution Result
# -------------------------
#
# "gathered": {
# "areas": [
# {
# "area_id": "2",
# "area_type": {
# "normal": true
# },
# "authentication": "plaintext-password",
# "shortcut": "enable"
# },
# {
# "area_id": "3",
# "area_type": {
# "nssa": {
# "set": true
# }
# }
# },
# {
# "area_id": "4",
# "area_type": {
# "stub": {
# "default_cost": 20,
# "set": true
# }
# },
# "network": [
# {
# "address": "192.0.2.0/24"
# }
# ],
# "range": [
# {
# "address": "192.0.3.0/24",
# "cost": 10
# },
# {
# "address": "192.0.4.0/24",
# "cost": 12
# }
# ]
# }
# ],
# "auto_cost": {
# "reference_bandwidth": 2
# },
# "default_information": {
# "originate": {
# "always": true,
# "metric": 10,
# "metric_type": 2,
# "route_map": "ingress"
# }
# },
# "log_adjacency_changes": "detail",
# "max_metric": {
# "router_lsa": {
# "administrative": true,
# "on_shutdown": 10,
# "on_startup": 10
# }
# },
# "mpls_te": {
# "enabled": true,
# "router_address": "192.0.11.11"
# },
# "neighbor": [
# {
# "neighbor_id": "192.0.11.12",
# "poll_interval": 10,
# "priority": 2
# }
# ],
# "parameters": {
# "abr_type": "cisco",
# "opaque_lsa": true,
# "rfc1583_compatibility": true,
# "router_id": "192.0.1.1"
# },
# "passive_interface": [
# "eth2",
# "eth1"
# ],
# "redistribute": [
# {
# "metric": 10,
# "metric_type": 2,
# "route_type": "bgp"
# }
# ]
# }
#
# After state:
# -------------
#
# vyos@192# run show configuration commands | grep ospf
# set protocols ospf area 2 area-type 'normal'
# set protocols ospf area 2 authentication 'plaintext-password'
# set protocols ospf area 2 shortcut 'enable'
# set protocols ospf area 3 area-type 'nssa'
# set protocols ospf area 4 area-type stub default-cost '20'
# set protocols ospf area 4 network '192.0.2.0/24'
# set protocols ospf area 4 range 192.0.3.0/24 cost '10'
# set protocols ospf area 4 range 192.0.4.0/24 cost '12'
# set protocols ospf auto-cost reference-bandwidth '2'
# set protocols ospf default-information originate 'always'
# set protocols ospf default-information originate metric '10'
# set protocols ospf default-information originate metric-type '2'
# set protocols ospf default-information originate route-map 'ingress'
# set protocols ospf log-adjacency-changes 'detail'
# set protocols ospf max-metric router-lsa 'administrative'
# set protocols ospf max-metric router-lsa on-shutdown '10'
# set protocols ospf max-metric router-lsa on-startup '10'
# set protocols ospf mpls-te 'enable'
# set protocols ospf mpls-te router-address '192.0.11.11'
# set protocols ospf neighbor 192.0.11.12 poll-interval '10'
# set protocols ospf neighbor 192.0.11.12 priority '2'
# set protocols ospf parameters abr-type 'cisco'
# set protocols ospf parameters 'opaque-lsa'
# set protocols ospf parameters 'rfc1583-compatibility'
# set protocols ospf parameters router-id '192.0.1.1'
# set protocols ospf passive-interface 'eth1'
# set protocols ospf passive-interface 'eth2'
# set protocols ospf redistribute bgp metric '10'
# set protocols ospf redistribute bgp metric-type '2'
-# Using deleted
-#
-# Before state
-# -------------
-#
-# vyos@192# run show configuration commands | grep ospf
-# set protocols ospf area 2 area-type 'normal'
-# set protocols ospf area 2 authentication 'plaintext-password'
-# set protocols ospf area 2 shortcut 'enable'
-# set protocols ospf area 3 area-type 'nssa'
-# set protocols ospf area 4 area-type stub default-cost '20'
-# set protocols ospf area 4 network '192.0.2.0/24'
-# set protocols ospf area 4 range 192.0.3.0/24 cost '10'
-# set protocols ospf area 4 range 192.0.4.0/24 cost '12'
-# set protocols ospf auto-cost reference-bandwidth '2'
-# set protocols ospf default-information originate 'always'
-# set protocols ospf default-information originate metric '10'
-# set protocols ospf default-information originate metric-type '2'
-# set protocols ospf default-information originate route-map 'ingress'
-# set protocols ospf log-adjacency-changes 'detail'
-# set protocols ospf max-metric router-lsa 'administrative'
-# set protocols ospf max-metric router-lsa on-shutdown '10'
-# set protocols ospf max-metric router-lsa on-startup '10'
-# set protocols ospf mpls-te 'enable'
-# set protocols ospf mpls-te router-address '192.0.11.11'
-# set protocols ospf neighbor 192.0.11.12 poll-interval '10'
-# set protocols ospf neighbor 192.0.11.12 priority '2'
-# set protocols ospf parameters abr-type 'cisco'
-# set protocols ospf parameters 'opaque-lsa'
-# set protocols ospf parameters 'rfc1583-compatibility'
-# set protocols ospf parameters router-id '192.0.1.1'
-# set protocols ospf passive-interface 'eth1'
-# set protocols ospf passive-interface 'eth2'
-# set protocols ospf redistribute bgp metric '10'
-# set protocols ospf redistribute bgp metric-type '2'
-#
-- name: Delete single attributes of ospfv2 routes.
- vyos.vyos.vyos_ospfv2:
- config:
- log_adjacency_changes: 'detail'
- max_metric:
- default_information:
- mpls_te:
- neighbor:
- redistribute:
- parameters:
- passive_interface:
- areas:
- state: deleted
-#
-#
-# ------------------------
-# Module Execution Results
-# ------------------------
-#
-# "before": {
-# "areas": [
-# {
-# "area_id": "2",
-# "area_type": {
-# "normal": true
-# },
-# "authentication": "plaintext-password",
-# "shortcut": "enable"
-# },
-# {
-# "area_id": "3",
-# "area_type": {
-# "nssa": {
-# "set": true
-# }
-# }
-# },
-# {
-# "area_id": "4",
-# "area_type": {
-# "stub": {
-# "default_cost": 20,
-# "set": true
-# }
-# },
-# "network": [
-# {
-# "address": "192.0.2.0/24"
-# }
-# ],
-# "range": [
-# {
-# "address": "192.0.3.0/24",
-# "cost": 10
-# },
-# {
-# "address": "192.0.4.0/24",
-# "cost": 12
-# }
-# ]
-# }
-# ],
-# "auto_cost": {
-# "reference_bandwidth": 2
-# },
-# "default_information": {
-# "originate": {
-# "always": true,
-# "metric": 10,
-# "metric_type": 2,
-# "route_map": "ingress"
-# }
-# },
-# "log_adjacency_changes": "detail",
-# "max_metric": {
-# "router_lsa": {
-# "administrative": true,
-# "on_shutdown": 10,
-# "on_startup": 10
-# }
-# },
-# "mpls_te": {
-# "enabled": true,
-# "router_address": "192.0.11.11"
-# },
-# "neighbor": [
-# {
-# "neighbor_id": "192.0.11.12",
-# "poll_interval": 10,
-# "priority": 2
-# }
-# ],
-# "parameters": {
-# "abr_type": "cisco",
-# "opaque_lsa": true,
-# "rfc1583_compatibility": true,
-# "router_id": "192.0.1.1"
-# },
-# "passive_interface": [
-# "eth2",
-# "eth1"
-# ],
-# "redistribute": [
-# {
-# "metric": 10,
-# "metric_type": 2,
-# "route_type": "bgp"
-# }
-# ]
-# }
-# "commands": [
-# "delete protocols ospf mpls-te",
-# "delete protocols ospf redistribute",
-# "delete protocols ospf auto-cost",
-# "delete protocols ospf passive-interface",
-# "delete protocols ospf parameters",
-# "delete protocols ospf default-information",
-# "delete protocols ospf max-metric",
-# "delete protocols ospf log-adjacency-changes",
-# "delete protocols ospf neighbor",
-# "delete protocols ospf area 2",
-# "delete protocols ospf area 3",
-# "delete protocols ospf area 4",
-# "delete protocols ospf area"
-# ]
-#
-# "after": []
-# After state
-# ------------
-# vyos@192# run show configuration commands | grep ospf
-
-
# Using deleted
#
# Before state
# -------------
#
# vyos@192# run show configuration commands | grep ospf
# set protocols ospf area 2 area-type 'normal'
# set protocols ospf area 2 authentication 'plaintext-password'
# set protocols ospf area 2 shortcut 'enable'
# set protocols ospf area 3 area-type 'nssa'
# set protocols ospf area 4 area-type stub default-cost '20'
# set protocols ospf area 4 network '192.0.2.0/24'
# set protocols ospf area 4 range 192.0.3.0/24 cost '10'
# set protocols ospf area 4 range 192.0.4.0/24 cost '12'
# set protocols ospf auto-cost reference-bandwidth '2'
# set protocols ospf default-information originate 'always'
# set protocols ospf default-information originate metric '10'
# set protocols ospf default-information originate metric-type '2'
# set protocols ospf default-information originate route-map 'ingress'
# set protocols ospf log-adjacency-changes 'detail'
# set protocols ospf max-metric router-lsa 'administrative'
# set protocols ospf max-metric router-lsa on-shutdown '10'
# set protocols ospf max-metric router-lsa on-startup '10'
# set protocols ospf mpls-te 'enable'
# set protocols ospf mpls-te router-address '192.0.11.11'
# set protocols ospf neighbor 192.0.11.12 poll-interval '10'
# set protocols ospf neighbor 192.0.11.12 priority '2'
# set protocols ospf parameters abr-type 'cisco'
# set protocols ospf parameters 'opaque-lsa'
# set protocols ospf parameters 'rfc1583-compatibility'
# set protocols ospf parameters router-id '192.0.1.1'
# set protocols ospf passive-interface 'eth1'
# set protocols ospf passive-interface 'eth2'
# set protocols ospf redistribute bgp metric '10'
# set protocols ospf redistribute bgp metric-type '2'
#
- name: Delete attributes of ospfv2 routes.
- vyos.vyos.vyos_ospfv2:
- config:
- state: deleted
+ vyos.vyos.vyos_ospfv2:
+ config:
+ state: deleted
#
#
# ------------------------
# Module Execution Results
# ------------------------
#
# "before": {
# "areas": [
# {
# "area_id": "2",
# "area_type": {
# "normal": true
# },
# "authentication": "plaintext-password",
# "shortcut": "enable"
# },
# {
# "area_id": "3",
# "area_type": {
# "nssa": {
# "set": true
# }
# }
# },
# {
# "area_id": "4",
# "area_type": {
# "stub": {
# "default_cost": 20,
# "set": true
# }
# },
# "network": [
# {
# "address": "192.0.2.0/24"
# }
# ],
# "range": [
# {
# "address": "192.0.3.0/24",
# "cost": 10
# },
# {
# "address": "192.0.4.0/24",
# "cost": 12
# }
# ]
# }
# ],
# "auto_cost": {
# "reference_bandwidth": 2
# },
# "default_information": {
# "originate": {
# "always": true,
# "metric": 10,
# "metric_type": 2,
# "route_map": "ingress"
# }
# },
# "log_adjacency_changes": "detail",
# "max_metric": {
# "router_lsa": {
# "administrative": true,
# "on_shutdown": 10,
# "on_startup": 10
# }
# },
# "mpls_te": {
# "enabled": true,
# "router_address": "192.0.11.11"
# },
# "neighbor": [
# {
# "neighbor_id": "192.0.11.12",
# "poll_interval": 10,
# "priority": 2
# }
# ],
# "parameters": {
# "abr_type": "cisco",
# "opaque_lsa": true,
# "rfc1583_compatibility": true,
# "router_id": "192.0.1.1"
# },
# "passive_interface": [
# "eth2",
# "eth1"
# ],
# "redistribute": [
# {
# "metric": 10,
# "metric_type": 2,
# "route_type": "bgp"
# }
# ]
# }
# "commands": [
# "delete protocols ospf"
# ]
#
-# "after": []
+# "after": {}
# After state
# ------------
# vyos@192# run show configuration commands | grep ospf
-
+#
"""
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 ospf passive-interface 'eth1']
"""
from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.ospfv2.ospfv2 import Ospfv2Args
-from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.config.ospfv2.ospfv2 import Ospfv2
+from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.ospfv2.ospfv2 import (
+ Ospfv2Args,
+)
+from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.config.ospfv2.ospfv2 import (
+ Ospfv2,
+)
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=Ospfv2Args.argument_spec,
required_if=required_if,
supports_check_mode=True,
mutually_exclusive=mutually_exclusive,
)
result = Ospfv2(module).execute_module()
module.exit_json(**result)
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/tests/integration/targets/vyos_ospfv2/tests/cli/delete_single.yaml b/tests/integration/targets/vyos_ospfv2/tests/cli/delete_single.yaml
deleted file mode 100644
index 150242a..0000000
--- a/tests/integration/targets/vyos_ospfv2/tests/cli/delete_single.yaml
+++ /dev/null
@@ -1,57 +0,0 @@
----
-- debug:
- msg: Start vyos_ospfv2 deleted integration tests ansible_connection={{
- ansible_connection }}
-
-- include_tasks: _populate.yaml
-
-- block:
-
- - name: Delete attributes of ospfv2.
- register: result
- vyos.vyos.vyos_ospfv2: &id001
- config:
- log_adjacency_changes: 'detail'
- max_metric:
- default_information:
- mpls_te:
- neighbor:
- redistribute:
- parameters:
- passive_interface:
- areas:
- 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_single['commands'] | symmetric_difference(result['commands']) |length\
- \ == 0 }}"
-
- - name: Assert that the after dicts were correctly generated
- assert:
- that:
- - "{{ deleted_single['after'] == result['after'] }}"
-
- - name: Delete attributes of given interfaces (IDEMPOTENT)
- register: result
- vyos.vyos.vyos_ospfv2: *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_single['after'] == result['before'] }}"
- always:
-
- - include_tasks: _remove_config.yaml
diff --git a/tests/integration/targets/vyos_ospfv2/tests/cli/gathered.yaml b/tests/integration/targets/vyos_ospfv2/tests/cli/gathered.yaml
index 22c378b..bc5e1e2 100644
--- a/tests/integration/targets/vyos_ospfv2/tests/cli/gathered.yaml
+++ b/tests/integration/targets/vyos_ospfv2/tests/cli/gathered.yaml
@@ -1,33 +1,24 @@
---
- debug:
msg: START vyos_ospfv2 gathered 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
+ - name: Gather the provided configuration with the exisiting running configuration
register: result
- vyos.vyos.vyos_ospfv2: &id001
+ vyos.vyos.vyos_ospfv2:
config:
state: gathered
- name: Assert that gathered dicts was correctly generated
assert:
that:
- "{{ populate == result['gathered'] }}"
-
- - name: Gather the existing running configuration (IDEMPOTENT)
- register: result
- vyos.vyos.vyos_ospfv2: *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_ospfv2/tests/cli/merged_update.yaml b/tests/integration/targets/vyos_ospfv2/tests/cli/merged_update.yaml
index 453dbb0..9b6823c 100644
--- a/tests/integration/targets/vyos_ospfv2/tests/cli/merged_update.yaml
+++ b/tests/integration/targets/vyos_ospfv2/tests/cli/merged_update.yaml
@@ -1,70 +1,70 @@
---
- debug:
msg: START vyos_ospfv2 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_ospfv2: &id001
config:
log_adjacency_changes: 'detail'
max_metric:
router_lsa:
administrative: true
on_shutdown: 10
on_startup: 10
passive_interface:
- 'eth1'
areas:
- area_id: '3'
area_type:
nssa:
set: true
- area_id: '4'
area_type:
stub:
set: false
network:
- address: '192.0.2.0/24'
- address: '192.0.22.0/24'
- address: '192.0.32.0/24'
state: merged
- name: Assert that before dicts were correctly generated
assert:
that: "{{ merged_update['before'] == 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_ospfv2: *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
\ No newline at end of file
+ - include_tasks: _remove_config.yaml
diff --git a/tests/integration/targets/vyos_ospfv2/tests/cli/parsed.yaml b/tests/integration/targets/vyos_ospfv2/tests/cli/parsed.yaml
index 6fbe2f9..cfa29f9 100644
--- a/tests/integration/targets/vyos_ospfv2/tests/cli/parsed.yaml
+++ b/tests/integration/targets/vyos_ospfv2/tests/cli/parsed.yaml
@@ -1,41 +1,15 @@
---
- debug:
msg: START vyos_ospfv2 parsed integration tests on connection={{ ansible_connection
}}
-- include_tasks: _remove_config.yaml
-
-- include_tasks: _populate.yaml
-
-- block:
-
- - name: Gather ospfv2 facts
- register: ospfv2_facts
- vyos.vyos.vyos_facts:
- gather_subset:
- - default
- gather_network_resources:
- - ospfv2
-
- - name: Provide the running configuration for parsing (config to be parsed)
- register: result
- vyos.vyos.vyos_ospfv2: &id001
- running_config: "{{ lookup('file', '_parsed_config.cfg') }}"
- state: parsed
-
- - name: Assert that correct parsing done
- assert:
- that: "{{ ansible_facts['network_resources']['ospfv2'] == result['parsed']\
- \ }}"
-
- - name: Gather the existing running configuration (IDEMPOTENT)
- register: result
- vyos.vyos.vyos_ospfv2: *id001
-
- - name: Assert that the previous task was idempotent
- assert:
- that:
- - result['changed'] == false
- always:
-
- - include_tasks: _remove_config.yaml
+- name: Parse externally provided ospfv2 config to agnostic model
+ register: result
+ vyos.vyos.vyos_ospfv2:
+ 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_ospfv2/tests/cli/rendered.yaml b/tests/integration/targets/vyos_ospfv2/tests/cli/rendered.yaml
index 86c07cf..8a805a6 100644
--- a/tests/integration/targets/vyos_ospfv2/tests/cli/rendered.yaml
+++ b/tests/integration/targets/vyos_ospfv2/tests/cli/rendered.yaml
@@ -1,88 +1,76 @@
---
- debug:
msg: START vyos_ospfv2 rendered integration tests on connection={{
ansible_connection }}
- include_tasks: _remove_config.yaml
-- include_tasks: _populate.yaml
-
- block:
- name: Structure provided configuration into device specific commands
register: result
- vyos.vyos.vyos_ospfv2: &id001
+ vyos.vyos.vyos_ospfv2:
config:
log_adjacency_changes: 'detail'
max_metric:
router_lsa:
administrative: true
on_shutdown: 10
on_startup: 10
default_information:
originate:
always: true
metric: 10
metric_type: 2
route_map: 'ingress'
mpls_te:
enabled: true
router_address: '192.0.11.11'
auto_cost:
reference_bandwidth: 2
neighbor:
- neighbor_id: '192.0.11.12'
poll_interval: 10
priority: 2
redistribute:
- route_type: 'bgp'
metric: 10
metric_type: 2
passive_interface:
- 'eth1'
- 'eth2'
parameters:
router_id: '192.0.1.1'
opaque_lsa: true
rfc1583_compatibility: true
abr_type: 'cisco'
areas:
- area_id: '2'
area_type:
normal: true
authentication: "plaintext-password"
shortcut: 'enable'
- area_id: '3'
area_type:
nssa:
set: true
- area_id: '4'
area_type:
stub:
default_cost: 20
network:
- address: '192.0.2.0/24'
range:
- address: '192.0.3.0/24'
cost: 10
- address: '192.0.4.0/24'
cost: 12
state: rendered
- name: Assert that correct set of commands were generated
assert:
that:
- "{{ rendered['commands'] | symmetric_difference(result['rendered'])\
\ |length == 0 }}"
-
- - name: Structure provided configuration into device specific commands (IDEMPOTENT)
- register: result
- vyos.vyos.vyos_ospfv2: *id001
-
- - name: Assert that the previous task was idempotent
- assert:
- that:
- - result['changed'] == false
- always:
-
- - include_tasks: _remove_config.yaml
+- debug:
+ msg: END vyos_ospfv2 rendered integration tests on connection={{ ansible_connection }}
diff --git a/tests/integration/targets/vyos_ospfv2/vars/main.yaml b/tests/integration/targets/vyos_ospfv2/vars/main.yaml
index 76a54e3..e55da20 100644
--- a/tests/integration/targets/vyos_ospfv2/vars/main.yaml
+++ b/tests/integration/targets/vyos_ospfv2/vars/main.yaml
@@ -1,444 +1,485 @@
---
merged:
- before: []
+ before: {}
commands:
- set protocols ospf mpls-te enable
- set protocols ospf mpls-te router-address '192.0.11.11'
- set protocols ospf redistribute bgp
- set protocols ospf redistribute bgp metric-type 2
- set protocols ospf redistribute bgp metric 10
- set protocols ospf default-information originate metric-type 2
- set protocols ospf default-information originate always
- set protocols ospf default-information originate metric 10
- set protocols ospf default-information originate route-map ingress
- set protocols ospf auto-cost reference-bandwidth '2'
- set protocols ospf parameters router-id '192.0.1.1'
- set protocols ospf parameters opaque-lsa
- set protocols ospf parameters abr-type 'cisco'
- set protocols ospf parameters rfc1583-compatibility
- set protocols ospf passive-interface eth1
- set protocols ospf passive-interface eth2
- set protocols ospf max-metric router-lsa on-shutdown 10
- set protocols ospf max-metric router-lsa administrative
- set protocols ospf max-metric router-lsa on-startup 10
- set protocols ospf log-adjacency-changes 'detail'
- set protocols ospf neighbor 192.0.11.12 priority 2
- set protocols ospf neighbor 192.0.11.12 poll-interval 10
- set protocols ospf neighbor 192.0.11.12
- set protocols ospf area '2'
- set protocols ospf area 2 authentication plaintext-password
- set protocols ospf area 2 shortcut enable
- set protocols ospf area 2 area-type normal
- set protocols ospf area '3'
- set protocols ospf area 3 area-type nssa
- set protocols ospf area 4 range 192.0.3.0/24 cost 10
- set protocols ospf area 4 range 192.0.3.0/24
- set protocols ospf area 4 range 192.0.4.0/24 cost 12
- set protocols ospf area 4 range 192.0.4.0/24
- set protocols ospf area 4 area-type stub default-cost 20
- set protocols ospf area '4'
- set protocols ospf area 4 network 192.0.2.0/24
after:
- areas:
- - area_id: '2'
- area_type:
- normal: true
- authentication: "plaintext-password"
- shortcut: 'enable'
- - area_id: '3'
- area_type:
- nssa:
- set: true
- - area_id: '4'
- area_type:
- stub:
- default_cost: 20
- set: true
- network:
- - address: '192.0.2.0/24'
- range:
- - address: '192.0.3.0/24'
- cost: 10
- - address: '192.0.4.0/24'
- cost: 12
- auto_cost:
- reference_bandwidth: 2
- default_information:
- originate:
- always: true
- metric: 10
- metric_type: 2
- route_map: 'ingress'
- log_adjacency_changes: 'detail'
- max_metric:
- router_lsa:
- administrative: true
- on_shutdown: 10
- on_startup: 10
- mpls_te:
- enabled: true
- router_address: '192.0.11.11'
- neighbor:
- - neighbor_id: '192.0.11.12'
- poll_interval: 10
- priority: 2
- parameters:
- abr_type: 'cisco'
- opaque_lsa: true
- rfc1583_compatibility: true
- router_id: '192.0.1.1'
- passive_interface:
- - 'eth2'
- - 'eth1'
- redistribute:
- - metric: 10
- metric_type: 2
- route_type: 'bgp'
-merged_update:
- before:
areas:
- area_id: '2'
area_type:
normal: true
authentication: "plaintext-password"
shortcut: 'enable'
- area_id: '3'
area_type:
nssa:
set: true
- area_id: '4'
area_type:
stub:
default_cost: 20
set: true
network:
- address: '192.0.2.0/24'
range:
- address: '192.0.3.0/24'
cost: 10
- address: '192.0.4.0/24'
cost: 12
auto_cost:
reference_bandwidth: 2
default_information:
originate:
always: true
metric: 10
metric_type: 2
route_map: 'ingress'
log_adjacency_changes: 'detail'
max_metric:
router_lsa:
administrative: true
on_shutdown: 10
on_startup: 10
mpls_te:
enabled: true
router_address: '192.0.11.11'
neighbor:
- neighbor_id: '192.0.11.12'
poll_interval: 10
priority: 2
parameters:
abr_type: 'cisco'
opaque_lsa: true
rfc1583_compatibility: true
router_id: '192.0.1.1'
passive_interface:
- - 'eth2'
- 'eth1'
+ - 'eth2'
redistribute:
- metric: 10
metric_type: 2
route_type: 'bgp'
- after:
+merged_update:
+ before:
areas:
- area_id: '2'
area_type:
normal: true
authentication: "plaintext-password"
shortcut: 'enable'
- area_id: '3'
area_type:
nssa:
set: true
- area_id: '4'
+ area_type:
+ stub:
+ default_cost: 20
+ set: true
network:
- address: '192.0.2.0/24'
- - address: '192.0.22.0/24'
- - address: '192.0.32.0/24'
range:
- address: '192.0.3.0/24'
cost: 10
- address: '192.0.4.0/24'
cost: 12
auto_cost:
reference_bandwidth: 2
default_information:
originate:
always: true
metric: 10
metric_type: 2
route_map: 'ingress'
log_adjacency_changes: 'detail'
max_metric:
router_lsa:
administrative: true
on_shutdown: 10
on_startup: 10
mpls_te:
enabled: true
router_address: '192.0.11.11'
neighbor:
- neighbor_id: '192.0.11.12'
poll_interval: 10
priority: 2
parameters:
abr_type: 'cisco'
opaque_lsa: true
rfc1583_compatibility: true
router_id: '192.0.1.1'
passive_interface:
- - 'eth2'
- 'eth1'
+ - 'eth2'
redistribute:
- metric: 10
metric_type: 2
route_type: 'bgp'
- commands:
- - delete protocols ospf area 4 area-type stub
- - set protocols ospf area 4 network 192.0.22.0/24
- - set protocols ospf area 4 network 192.0.32.0/24
-populate:
+ after:
areas:
- area_id: '2'
area_type:
normal: true
authentication: "plaintext-password"
shortcut: 'enable'
- area_id: '3'
area_type:
nssa:
set: true
- area_id: '4'
- area_type:
- stub:
- default_cost: 20
- set: true
network:
- address: '192.0.2.0/24'
+ - address: '192.0.22.0/24'
+ - address: '192.0.32.0/24'
range:
- address: '192.0.3.0/24'
cost: 10
- address: '192.0.4.0/24'
cost: 12
auto_cost:
reference_bandwidth: 2
default_information:
originate:
always: true
metric: 10
metric_type: 2
route_map: 'ingress'
log_adjacency_changes: 'detail'
max_metric:
router_lsa:
administrative: true
on_shutdown: 10
on_startup: 10
mpls_te:
enabled: true
router_address: '192.0.11.11'
neighbor:
- neighbor_id: '192.0.11.12'
poll_interval: 10
priority: 2
parameters:
abr_type: 'cisco'
opaque_lsa: true
rfc1583_compatibility: true
router_id: '192.0.1.1'
passive_interface:
- - 'eth2'
- 'eth1'
+ - 'eth2'
redistribute:
- metric: 10
metric_type: 2
route_type: 'bgp'
+ commands:
+ - delete protocols ospf area 4 area-type stub
+ - set protocols ospf area 4 network 192.0.22.0/24
+ - set protocols ospf area 4 network 192.0.32.0/24
+populate:
+ areas:
+ - area_id: '2'
+ area_type:
+ normal: true
+ authentication: "plaintext-password"
+ shortcut: 'enable'
+ - area_id: '3'
+ area_type:
+ nssa:
+ set: true
+ - area_id: '4'
+ area_type:
+ stub:
+ default_cost: 20
+ set: true
+ network:
+ - address: '192.0.2.0/24'
+ range:
+ - address: '192.0.3.0/24'
+ cost: 10
+ - address: '192.0.4.0/24'
+ cost: 12
+ auto_cost:
+ reference_bandwidth: 2
+ default_information:
+ originate:
+ always: true
+ metric: 10
+ metric_type: 2
+ route_map: 'ingress'
+ log_adjacency_changes: 'detail'
+ max_metric:
+ router_lsa:
+ administrative: true
+ on_shutdown: 10
+ on_startup: 10
+ mpls_te:
+ enabled: true
+ router_address: '192.0.11.11'
+ neighbor:
+ - neighbor_id: '192.0.11.12'
+ poll_interval: 10
+ priority: 2
+ parameters:
+ abr_type: 'cisco'
+ opaque_lsa: true
+ rfc1583_compatibility: true
+ router_id: '192.0.1.1'
+ passive_interface:
+ - 'eth1'
+ - 'eth2'
+ redistribute:
+ - metric: 10
+ metric_type: 2
+ route_type: 'bgp'
replaced:
commands:
- delete protocols ospf passive-interface eth2
- delete protocols ospf area 3
- delete protocols ospf area 4 range 192.0.3.0/24 cost
- delete protocols ospf area 4 range 192.0.3.0/24
- delete protocols ospf area 4 range 192.0.4.0/24 cost
- delete protocols ospf area 4 range 192.0.4.0/24
- set protocols ospf mpls-te router-address '192.0.22.22'
- set protocols ospf area 4 range 1.1.2.0/24 cost 10
- set protocols ospf area 4 range 1.1.2.0/24
- set protocols ospf area 4 network 192.0.12.0/24
- set protocols ospf area 4 network 192.0.22.0/24
- set protocols ospf area 4 network 192.0.32.0/24
after:
- areas:
- - area_id: '2'
- area_type:
- normal: true
- authentication: "plaintext-password"
- shortcut: 'enable'
- - area_id: '4'
- area_type:
- stub:
- default_cost: 20
- set: true
- network:
- - address: '192.0.12.0/24'
- - address: '192.0.2.0/24'
- - address: '192.0.22.0/24'
- - address: '192.0.32.0/24'
- range:
- - address: '1.1.2.0/24'
- cost: 10
- auto_cost:
- reference_bandwidth: 2
- default_information:
- originate:
- always: true
- metric: 10
- metric_type: 2
- route_map: 'ingress'
- log_adjacency_changes: 'detail'
- max_metric:
- router_lsa:
- administrative: true
- on_shutdown: 10
- on_startup: 10
- mpls_te:
- enabled: true
- router_address: '192.0.22.22'
- neighbor:
- - neighbor_id: '192.0.11.12'
- poll_interval: 10
- priority: 2
- parameters:
- abr_type: 'cisco'
- opaque_lsa: true
- rfc1583_compatibility: true
- router_id: '192.0.1.1'
- passive_interface:
- - 'eth1'
- redistribute:
- - metric: 10
- metric_type: 2
- route_type: 'bgp'
+ areas:
+ - area_id: '2'
+ area_type:
+ normal: true
+ authentication: "plaintext-password"
+ shortcut: 'enable'
+ - area_id: '4'
+ area_type:
+ stub:
+ default_cost: 20
+ set: true
+ network:
+ - address: '192.0.12.0/24'
+ - address: '192.0.2.0/24'
+ - address: '192.0.22.0/24'
+ - address: '192.0.32.0/24'
+ range:
+ - address: '1.1.2.0/24'
+ cost: 10
+ auto_cost:
+ reference_bandwidth: 2
+ default_information:
+ originate:
+ always: true
+ metric: 10
+ metric_type: 2
+ route_map: 'ingress'
+ log_adjacency_changes: 'detail'
+ max_metric:
+ router_lsa:
+ administrative: true
+ on_shutdown: 10
+ on_startup: 10
+ mpls_te:
+ enabled: true
+ router_address: '192.0.22.22'
+ neighbor:
+ - neighbor_id: '192.0.11.12'
+ poll_interval: 10
+ priority: 2
+ parameters:
+ abr_type: 'cisco'
+ opaque_lsa: true
+ rfc1583_compatibility: true
+ router_id: '192.0.1.1'
+ passive_interface:
+ - 'eth1'
+ redistribute:
+ - metric: 10
+ metric_type: 2
+ route_type: 'bgp'
rendered:
commands:
- set protocols ospf mpls-te enable
- set protocols ospf mpls-te router-address '192.0.11.11'
- set protocols ospf redistribute bgp
- set protocols ospf redistribute bgp metric-type 2
- set protocols ospf redistribute bgp metric 10
- set protocols ospf default-information originate metric-type 2
- set protocols ospf default-information originate always
- set protocols ospf default-information originate metric 10
- set protocols ospf default-information originate route-map ingress
- set protocols ospf auto-cost reference-bandwidth '2'
- set protocols ospf parameters router-id '192.0.1.1'
- set protocols ospf parameters opaque-lsa
- set protocols ospf parameters abr-type 'cisco'
- set protocols ospf parameters rfc1583-compatibility
- set protocols ospf passive-interface eth1
- set protocols ospf passive-interface eth2
- set protocols ospf max-metric router-lsa on-shutdown 10
- set protocols ospf max-metric router-lsa administrative
- set protocols ospf max-metric router-lsa on-startup 10
- set protocols ospf log-adjacency-changes 'detail'
- set protocols ospf neighbor 192.0.11.12 priority 2
- set protocols ospf neighbor 192.0.11.12 poll-interval 10
- set protocols ospf neighbor 192.0.11.12
- set protocols ospf area '2'
- set protocols ospf area 2 authentication plaintext-password
- set protocols ospf area 2 shortcut enable
- set protocols ospf area 2 area-type normal
- set protocols ospf area '3'
- set protocols ospf area 3 area-type nssa
- set protocols ospf area 4 range 192.0.3.0/24 cost 10
- set protocols ospf area 4 range 192.0.3.0/24
- set protocols ospf area 4 range 192.0.4.0/24 cost 12
- set protocols ospf area 4 range 192.0.4.0/24
- set protocols ospf area 4 area-type stub default-cost 20
- set protocols ospf area '4'
- set protocols ospf area 4 network 192.0.2.0/24
-deleted_single:
- commands:
- - delete protocols ospf mpls-te
- - delete protocols ospf redistribute
- - delete protocols ospf auto-cost
- - delete protocols ospf passive-interface
- - delete protocols ospf parameters
- - delete protocols ospf default-information
- - delete protocols ospf max-metric
- - delete protocols ospf log-adjacency-changes
- - delete protocols ospf neighbor
- - delete protocols ospf area 2
- - delete protocols ospf area 3
- - delete protocols ospf area 4
- - delete protocols ospf area
- after: []
+parsed:
+ after:
+ areas:
+ - area_id: '2'
+ area_type:
+ normal: true
+ authentication: "plaintext-password"
+ shortcut: 'enable'
+ - area_id: '3'
+ area_type:
+ nssa:
+ set: true
+ - area_id: '4'
+ area_type:
+ stub:
+ default_cost: 20
+ set: true
+ network:
+ - address: '192.0.2.0/24'
+ range:
+ - address: '192.0.3.0/24'
+ cost: 10
+ - address: '192.0.4.0/24'
+ cost: 12
+ auto_cost:
+ reference_bandwidth: 2
+ default_information:
+ originate:
+ always: true
+ metric: 10
+ metric_type: 2
+ route_map: 'ingress'
+ log_adjacency_changes: 'detail'
+ max_metric:
+ router_lsa:
+ administrative: true
+ on_shutdown: 10
+ on_startup: 10
+ mpls_te:
+ enabled: true
+ router_address: '192.0.11.11'
+ neighbor:
+ - neighbor_id: '192.0.11.12'
+ poll_interval: 10
+ priority: 2
+ parameters:
+ abr_type: 'cisco'
+ opaque_lsa: true
+ rfc1583_compatibility: true
+ router_id: '192.0.1.1'
+ passive_interface:
+ - 'eth1'
+ - 'eth2'
+ redistribute:
+ - metric: 10
+ metric_type: 2
+ route_type: 'bgp'
deleted:
commands:
- 'delete protocols ospf'
- after: []
+ after: {}
round_trip:
after:
areas:
- area_id: '2'
area_type:
normal: true
authentication: "plaintext-password"
shortcut: 'enable'
- area_id: '4'
area_type:
stub:
default_cost: 20
set: true
network:
- address: '192.0.12.0/24'
- address: '192.0.2.0/24'
- address: '192.0.22.0/24'
- address: '192.0.32.0/24'
range:
- address: '1.1.2.0/24'
cost: 10
auto_cost:
reference_bandwidth: 2
default_information:
originate:
always: true
metric: 10
metric_type: 2
route_map: 'ingress'
log_adjacency_changes: 'detail'
max_metric:
router_lsa:
administrative: true
on_shutdown: 10
on_startup: 10
mpls_te:
enabled: true
router_address: '192.0.22.22'
neighbor:
- neighbor_id: '192.0.11.12'
poll_interval: 10
priority: 2
parameters:
abr_type: 'cisco'
opaque_lsa: true
rfc1583_compatibility: true
router_id: '192.0.1.1'
passive_interface:
- 'eth1'
redistribute:
- metric: 10
metric_type: 2
route_type: 'bgp'
diff --git a/tests/unit/modules/network/vyos/test_vyos_ospfv2.py b/tests/unit/modules/network/vyos/test_vyos_ospfv2.py
index 8e6b095..b825066 100644
--- a/tests/unit/modules/network/vyos/test_vyos_ospfv2.py
+++ b/tests/unit/modules/network/vyos/test_vyos_ospfv2.py
@@ -1,526 +1,435 @@
# (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 .
# 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_ospfv2
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_ospfv2
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.ospfv2.ospfv2.Ospfv2Facts.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_ospfv2_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_ospfv2_merged_new_config(self):
set_module_args(
dict(
config=dict(
log_adjacency_changes="detail",
- mpls_te=dict(enabled=True, router_address='192.0.11.11'),
+ mpls_te=dict(enabled=True, router_address="192.0.11.11"),
auto_cost=dict(reference_bandwidth=2),
areas=[
dict(
area_id="2",
area_type=dict(normal=True),
authentication="plaintext-password",
- shortcut='enable',
+ shortcut="enable",
),
dict(
area_id="4",
- area_type=dict(
- stub=dict(default_cost=10)
- ),
- network=[
- dict(address="192.0.2.0/24"),
- ],
+ area_type=dict(stub=dict(default_cost=10)),
+ network=[dict(address="192.0.2.0/24"),],
range=[
dict(address="192.0.3.0/24", cost=10),
- dict(address="192.0.4.0/24", cost=12)
- ]
+ dict(address="192.0.4.0/24", cost=12),
+ ],
),
],
),
state="merged",
)
)
commands = [
- "set protocols ospf mpls-te enable",
- "set protocols ospf mpls-te router-address '192.0.11.11'",
- "set protocols ospf auto-cost reference-bandwidth '2'",
- "set protocols ospf log-adjacency-changes 'detail'",
- "set protocols ospf area '2'",
- "set protocols ospf area 2 authentication plaintext-password",
- "set protocols ospf area 2 shortcut enable",
- "set protocols ospf area 2 area-type normal",
- "set protocols ospf area 4 range 192.0.3.0/24 cost 10",
- "set protocols ospf area 4 range 192.0.3.0/24",
- "set protocols ospf area 4 range 192.0.4.0/24 cost 12",
- "set protocols ospf area 4 range 192.0.4.0/24",
- "set protocols ospf area 4 area-type stub default-cost 10",
- "set protocols ospf area '4'",
- "set protocols ospf area 4 network 192.0.2.0/24"
+ "set protocols ospf mpls-te enable",
+ "set protocols ospf mpls-te router-address '192.0.11.11'",
+ "set protocols ospf auto-cost reference-bandwidth '2'",
+ "set protocols ospf log-adjacency-changes 'detail'",
+ "set protocols ospf area '2'",
+ "set protocols ospf area 2 authentication plaintext-password",
+ "set protocols ospf area 2 shortcut enable",
+ "set protocols ospf area 2 area-type normal",
+ "set protocols ospf area 4 range 192.0.3.0/24 cost 10",
+ "set protocols ospf area 4 range 192.0.3.0/24",
+ "set protocols ospf area 4 range 192.0.4.0/24 cost 12",
+ "set protocols ospf area 4 range 192.0.4.0/24",
+ "set protocols ospf area 4 area-type stub default-cost 10",
+ "set protocols ospf area '4'",
+ "set protocols ospf area 4 network 192.0.2.0/24",
]
self.execute_module(changed=True, commands=commands)
def test_vyos_ospfv2_merged_idem(self):
set_module_args(
dict(
config=dict(
areas=[
dict(
area_id="12",
area_type=dict(normal=True),
authentication="plaintext-password",
- shortcut='enable',
+ shortcut="enable",
),
dict(
area_id="14",
- area_type=dict(
- stub=dict(default_cost=20)
- ),
- network=[
- dict(address="192.0.12.0/24"),
- ],
+ area_type=dict(stub=dict(default_cost=20)),
+ network=[dict(address="192.0.12.0/24"),],
range=[
dict(address="192.0.13.0/24", cost=10),
- dict(address="192.0.14.0/24", cost=12)
- ]
+ dict(address="192.0.14.0/24", cost=12),
+ ],
),
],
),
state="merged",
)
)
self.execute_module(changed=False, commands=[])
def test_vyos_ospfv2_merged_update_existing(self):
set_module_args(
dict(
config=dict(
areas=[
dict(
area_id="12",
area_type=dict(normal=True),
authentication="plaintext-password",
- shortcut='enable',
+ shortcut="enable",
),
dict(
area_id="14",
- area_type=dict(
- stub=dict(set=False)
- ),
+ area_type=dict(stub=dict(set=False)),
network=[
dict(address="192.0.12.0/24"),
dict(address="192.0.22.0/24"),
],
range=[
dict(address="192.0.13.0/24", cost=10),
- dict(address="192.0.14.0/24", cost=12)
- ]
+ dict(address="192.0.14.0/24", cost=12),
+ ],
),
],
),
state="merged",
)
)
commands = [
"delete protocols ospf area 14 area-type stub",
- "set protocols ospf area 14 network 192.0.22.0/24"
+ "set protocols ospf area 14 network 192.0.22.0/24",
]
self.execute_module(changed=True, commands=commands)
def test_vyos_ospfv2_replaced(self):
set_module_args(
dict(
config=dict(
log_adjacency_changes="detail",
- mpls_te=dict(enabled=True, router_address='192.0.11.11'),
+ mpls_te=dict(enabled=True, router_address="192.0.11.11"),
auto_cost=dict(reference_bandwidth=2),
areas=[
dict(
area_id="12",
area_type=dict(normal=True),
authentication="plaintext-password",
- shortcut='enable',
+ shortcut="enable",
),
dict(
area_id="15",
- area_type=dict(
- stub=dict(default_cost=10)
- ),
- network=[
- dict(address="192.0.12.0/24"),
- ],
+ area_type=dict(stub=dict(default_cost=10)),
+ network=[dict(address="192.0.12.0/24"),],
range=[
dict(address="192.0.13.0/24", cost=10),
dict(address="192.0.14.0/24", cost=12),
- dict(address="192.0.15.0/24", cost=14)
- ]
+ dict(address="192.0.15.0/24", cost=14),
+ ],
),
],
),
state="replaced",
)
)
commands = [
"set protocols ospf mpls-te enable",
"set protocols ospf mpls-te router-address '192.0.11.11'",
"set protocols ospf auto-cost reference-bandwidth '2'",
"set protocols ospf log-adjacency-changes 'detail'",
"delete protocols ospf area 14",
"set protocols ospf area 15 range 192.0.13.0/24 cost 10",
"set protocols ospf area 15 range 192.0.13.0/24",
"set protocols ospf area 15 range 192.0.14.0/24 cost 12",
"set protocols ospf area 15 range 192.0.14.0/24",
"set protocols ospf area 15 range 192.0.15.0/24 cost 14",
"set protocols ospf area 15 range 192.0.15.0/24",
"set protocols ospf area 15 area-type stub default-cost 10",
"set protocols ospf area '15'",
- "set protocols ospf area 15 network 192.0.12.0/24"
+ "set protocols ospf area 15 network 192.0.12.0/24",
]
self.execute_module(changed=True, commands=commands)
def test_vyos_ospfv2_replaced_idem(self):
set_module_args(
dict(
config=dict(
areas=[
dict(
area_id="12",
area_type=dict(normal=True),
authentication="plaintext-password",
- shortcut='enable',
+ shortcut="enable",
),
dict(
area_id="14",
- area_type=dict(
- stub=dict(default_cost=20)
- ),
- network=[
- dict(address="192.0.12.0/24"),
- ],
+ area_type=dict(stub=dict(default_cost=20)),
+ network=[dict(address="192.0.12.0/24"),],
range=[
dict(address="192.0.13.0/24", cost=10),
- dict(address="192.0.14.0/24", cost=12)
- ]
+ dict(address="192.0.14.0/24", cost=12),
+ ],
),
],
),
state="replaced",
)
)
self.execute_module(changed=False, commands=[])
def test_vyos_ospfv2_deleted_no_config(self):
set_module_args(dict(config=None, state="deleted"))
commands = ["delete protocols ospf"]
self.execute_module(changed=True, commands=commands)
- def test_vyos_ospfv2_set_01_deleted_single_attributes(self):
- set_module_args(
- dict(
- config=dict(
- mpls_te=dict(),
- auto_cost=dict(),
- areas=[]
- ),
- state="deleted",
- )
- )
- commands = ["delete protocols ospf area 12",
- "delete protocols ospf area 14",
- "delete protocols ospf area"]
- self.execute_module(changed=True, commands=commands)
-
def test_vyos_ospfv2_gathered(self):
set_module_args(dict(state="gathered"))
result = self.execute_module(
changed=False, filename="vyos_ospfv2_config.cfg"
)
gather_dict = {
- "areas": [
- {
- "area_id": "2",
- "area_type": {
- "normal": True
- },
- "authentication": "plaintext-password",
- "shortcut": "enable"
- },
- {
- "area_id": "14",
- "area_type": {
- "stub": {
- "default_cost": 20,
- "set": True
- }
- },
- "network": [
- {
- "address": "192.0.12.0/24"
- }
- ],
- "range": [
- {
- "address": "192.0.13.0/24",
- "cost": 10
- },
- {
- "address": "192.0.14.0/24",
- "cost": 12
- }
- ]
- }
- ],
- }
+ "areas": [
+ {
+ "area_id": "2",
+ "area_type": {"normal": True},
+ "authentication": "plaintext-password",
+ "shortcut": "enable",
+ },
+ {
+ "area_id": "14",
+ "area_type": {"stub": {"default_cost": 20, "set": True}},
+ "network": [{"address": "192.0.12.0/24"}],
+ "range": [
+ {"address": "192.0.13.0/24", "cost": 10},
+ {"address": "192.0.14.0/24", "cost": 12},
+ ],
+ },
+ ],
+ }
self.assertEqual(sorted(gather_dict), sorted(result["gathered"]))
def test_vyos_ospfv2_parsed(self):
parsed_str = """set protocols ospf area 2 area-type 'normal'
set protocols ospf area 2 authentication 'plaintext-password'
set protocols ospf area 2 shortcut 'enable'
set protocols ospf area 3 area-type 'nssa'
set protocols ospf area 4 area-type stub default-cost '20'
set protocols ospf area 4 network '192.0.2.0/24'
set protocols ospf area 4 range 192.0.3.0/24 cost '10'
set protocols ospf area 4 range 192.0.4.0/24 cost '12'
set protocols ospf default-information originate 'always'
set protocols ospf default-information originate metric '10'
set protocols ospf default-information originate metric-type '2'
set protocols ospf auto-cost reference-bandwidth '2'
set protocols ospf default-information originate route-map 'ingress'
set protocols ospf log-adjacency-changes 'detail'
set protocols ospf max-metric router-lsa 'administrative'
set protocols ospf max-metric router-lsa on-shutdown '10'
set protocols ospf max-metric router-lsa on-startup '10'
set protocols ospf mpls-te 'enable'
set protocols ospf mpls-te router-address '192.0.11.11'
set protocols ospf neighbor 192.0.11.12 poll-interval '10'
set protocols ospf neighbor 192.0.11.12 priority '2'
set protocols ospf parameters abr-type 'cisco'
set protocols ospf parameters 'opaque-lsa'
set protocols ospf parameters 'rfc1583-compatibility'
set protocols ospf parameters router-id '192.0.1.1'
set protocols ospf passive-interface 'eth1'
set protocols ospf passive-interface 'eth2'
set protocols ospf redistribute bgp metric '10'
set protocols ospf redistribute bgp metric-type '2'"""
set_module_args(dict(running_config=parsed_str, state="parsed"))
result = self.execute_module(changed=False)
parsed_list = {
"areas": [
{
"area_id": "2",
- "area_type": {
- "normal": True
- },
+ "area_type": {"normal": True},
"authentication": "plaintext-password",
- "shortcut": "enable"
- },
- {
- "area_id": "3",
- "area_type": {
- "nssa": {
- "set": True
- }
- }
+ "shortcut": "enable",
},
+ {"area_id": "3", "area_type": {"nssa": {"set": True}}},
{
"area_id": "4",
- "area_type": {
- "stub": {
- "default_cost": 20,
- "set": True
- }
- },
- "network": [
- {
- "address": "192.0.2.0/24"
- }
- ],
+ "area_type": {"stub": {"default_cost": 20, "set": True}},
+ "network": [{"address": "192.0.2.0/24"}],
"range": [
- {
- "address": "192.0.3.0/24",
- "cost": 10
- },
- {
- "address": "192.0.4.0/24",
- "cost": 12
- }
- ]
- }
+ {"address": "192.0.3.0/24", "cost": 10},
+ {"address": "192.0.4.0/24", "cost": 12},
+ ],
+ },
],
- "auto_cost": {
- "reference_bandwidth": 2
- },
+ "auto_cost": {"reference_bandwidth": 2},
"default_information": {
"originate": {
"always": True,
"metric": 10,
"metric_type": 2,
- "route_map": "ingress"
+ "route_map": "ingress",
}
},
"log_adjacency_changes": "detail",
"max_metric": {
"router_lsa": {
"administrative": True,
"on_shutdown": 10,
- "on_startup": 10
+ "on_startup": 10,
}
},
- "mpls_te": {
- "enabled": True,
- "router_address": "192.0.11.11"
- },
+ "mpls_te": {"enabled": True, "router_address": "192.0.11.11"},
"neighbor": [
{
"neighbor_id": "192.0.11.12",
"poll_interval": 10,
- "priority": 2
+ "priority": 2,
}
],
"parameters": {
"abr_type": "cisco",
"opaque_lsa": True,
"rfc1583_compatibility": True,
- "router_id": "192.0.1.1"
+ "router_id": "192.0.1.1",
},
- "passive_interface": [
- "eth2",
- "eth1"
- ],
+ "passive_interface": ["eth2", "eth1"],
"redistribute": [
- {
- "metric": 10,
- "metric_type": 2,
- "route_type": "bgp"
- }
- ]
+ {"metric": 10, "metric_type": 2, "route_type": "bgp"}
+ ],
}
self.assertEqual(sorted(parsed_list), sorted(result["parsed"]))
def test_vyos_ospfv2_rendered(self):
set_module_args(
dict(
config=dict(
log_adjacency_changes="detail",
- mpls_te=dict(enabled=True, router_address='192.0.11.11'),
+ mpls_te=dict(enabled=True, router_address="192.0.11.11"),
auto_cost=dict(reference_bandwidth=2),
areas=[
dict(
area_id="2",
area_type=dict(normal=True),
authentication="plaintext-password",
- shortcut='enable',
+ shortcut="enable",
),
dict(
area_id="4",
- area_type=dict(
- stub=dict(default_cost=10)
- ),
- network=[
- dict(address="192.0.2.0/24"),
- ],
+ area_type=dict(stub=dict(default_cost=10)),
+ network=[dict(address="192.0.2.0/24"),],
range=[
dict(address="192.0.3.0/24", cost=10),
- dict(address="192.0.4.0/24", cost=12)
- ]
+ dict(address="192.0.4.0/24", cost=12),
+ ],
),
],
),
state="rendered",
)
)
commands = [
"set protocols ospf mpls-te enable",
"set protocols ospf mpls-te router-address '192.0.11.11'",
"set protocols ospf auto-cost reference-bandwidth '2'",
"set protocols ospf log-adjacency-changes 'detail'",
"set protocols ospf area '2'",
"set protocols ospf area 2 authentication plaintext-password",
"set protocols ospf area 2 shortcut enable",
"set protocols ospf area 2 area-type normal",
"set protocols ospf area 4 range 192.0.3.0/24 cost 10",
"set protocols ospf area 4 range 192.0.3.0/24",
"set protocols ospf area 4 range 192.0.4.0/24 cost 12",
"set protocols ospf area 4 range 192.0.4.0/24",
"set protocols ospf area 4 area-type stub default-cost 10",
"set protocols ospf area '4'",
- "set protocols ospf area 4 network 192.0.2.0/24"
+ "set protocols ospf area 4 network 192.0.2.0/24",
]
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 e0ab699..49d4652 100644
--- a/tests/unit/modules/network/vyos/vyos_module.py
+++ b/tests/unit/modules/network/vyos/vyos_module.py
@@ -1,105 +1,105 @@
# (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 .
# Make coding more python3-ish
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import os
import json
from ansible_collections.vyos.vyos.tests.unit.modules.utils import (
AnsibleExitJson,
AnsibleFailJson,
ModuleTestCase,
)
fixture_path = os.path.join(os.path.dirname(__file__), "fixtures")
fixture_data = {}
def load_fixture(name):
path = os.path.join(fixture_path, name)
if path in fixture_data:
return fixture_data[path]
with open(path) as f:
data = f.read()
try:
data = json.loads(data)
except Exception:
pass
fixture_data[path] = data
return data
class TestVyosModule(ModuleTestCase):
def execute_module(
self,
failed=False,
changed=False,
commands=None,
sort=True,
defaults=False,
- filename=None
+ filename=None,
):
self.load_fixtures(commands)
if failed:
result = self.failed()
self.assertTrue(result["failed"], result)
else:
result = self.changed(changed)
self.assertEqual(result["changed"], changed, result)
if commands is not None:
if sort:
self.assertEqual(
sorted(commands),
sorted(result["commands"]),
result["commands"],
)
else:
self.assertEqual(
commands, result["commands"], result["commands"]
)
return result
def failed(self):
with self.assertRaises(AnsibleFailJson) as exc:
self.module.main()
result = exc.exception.args[0]
self.assertTrue(result["failed"], result)
return result
def changed(self, changed=False):
with self.assertRaises(AnsibleExitJson) as exc:
self.module.main()
result = exc.exception.args[0]
self.assertEqual(result["changed"], changed, result)
return result
def load_fixtures(self, commands=None):
pass