diff --git a/plugins/module_utils/network/vyos/argspec/ospfv2/ospfv2.py b/plugins/module_utils/network/vyos/argspec/ospfv2/ospfv2.py
index 1b11d3c..a2a6e04 100644
--- a/plugins/module_utils/network/vyos/argspec/ospfv2/ospfv2.py
+++ b/plugins/module_utils/network/vyos/argspec/ospfv2/ospfv2.py
@@ -1,359 +1,365 @@
#
# -*- 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': {
- 'elements': 'dict',
'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'
}
},
'type': 'dict'
}
},
'type': 'dict'
},
'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'
},
'log_adjacency_changes': {
'choices': ['detail'],
'type': 'str'
},
'max_metric': {
'options': {
'router_lsa': {
'options': {
'administrative': {
'type': 'bool'
},
'on_shutdown': {
'type': 'int'
},
'on_startup': {
'type': 'int'
}
},
'type': 'dict'
}
},
'type': 'dict'
},
'mpls_te': {
'options': {
'enabled': {
'type': 'bool'
},
'router_address': {
'type': 'str'
}
},
'type': 'dict'
},
'neighbor': {
'elements': 'dict',
'options': {
'neighbor_id': {
'type': 'str'
},
'poll_interval': {
'type': 'int'
},
'priority': {
'type': 'int'
}
},
'type': 'list'
},
- 'ospf_area': {
+ 'areas': {
'elements': 'dict',
'options': {
- 'area': {
+ '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'
}
},
'type': 'dict'
},
'stub': {
'options': {
'default_cost': {
'type': 'int'
},
'no_summary': {
'type': 'bool'
+ },
+ 'set': {
+ 'type': 'bool'
}
},
'type': 'dict'
}
},
'type': 'dict'
},
'authentication': {
'choices': ['plaintext-password', 'md5'],
'type': 'str'
},
'network': {
'elements': 'dict',
'options': {
'address': {
'required': True,
'type': 'str'
}
},
'type': 'list'
},
'range': {
'elements': 'dict',
'options': {
'address': {
'type': 'str'
},
'cost': {
'type': 'int'
},
'not_advertise': {
'type': 'bool'
},
'substitute': {
'type': 'str'
}
},
'type': 'list'
},
'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'
}
},
- 'type': 'dict'
+ 'type': 'list'
},
'plaintext_password': {
'type': 'str'
}
},
'type': 'dict'
},
'dead_interval': {
'type': 'int'
},
'hello_interval': {
'type': 'int'
},
'retransmit_interval': {
'type': 'int'
},
'transmit_delay': {
'type': 'int'
}
},
'type': 'list'
}
},
'type': 'list'
},
'parameters': {
'options': {
'abr_type': {
'choices':
['cisco', 'ibm', 'shortcut', 'standard'],
'type': 'str'
},
'opaque_lsa': {
'type': 'bool'
},
'rfc1583_compatibility': {
'type': 'bool'
},
'router_id': {
'type': 'str'
}
},
'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'
},
'route_type': {
'choices':
['bgp', 'connected', 'kernel', 'rip', 'static'],
'type':
'str'
}
},
'type': 'list'
},
'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'
}
},
'type': 'dict'
}
},
'type': 'dict'
}
},
'type': 'dict'
}
},
- 'type': 'list'
+ 'type': 'dict'
},
"running_config": {"type": "str"},
'state': {
'choices': [
'merged', 'replaced', 'deleted', 'parsed', 'gathered',
'rendered'
],
'default':
'merged',
'type':
'str'
}
} # pylint: disable=C0301
diff --git a/plugins/module_utils/network/vyos/config/ospfv2/ospfv2.py b/plugins/module_utils/network/vyos/config/ospfv2/ospfv2.py
index 0109ca1..13645cd 100644
--- a/plugins/module_utils/network/vyos/config/ospfv2/ospfv2.py
+++ b/plugins/module_utils/network/vyos/config/ospfv2/ospfv2.py
@@ -1,570 +1,729 @@
#
# -*- 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.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
)
+
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)
+
+ (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 []
return ospfv2_facts
def execute_module(self):
""" Execute the module
:rtype: A dictionary
:returns: The result from module execution
"""
+
result = {'changed': False}
warnings = list()
commands = list()
if self.state in self.ACTION_STATES:
existing_ospfv2_facts = self.get_ospfv2_facts()
else:
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 = []
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']
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 == "overridden":
- commands.extend(self._state_overridden(w, h))
- elif self.state == "deleted":
+ 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 w:
- if self.state == "merged" or self.state == "rendered":
- for w_item in w:
- commands.extend(self._state_merged(w_item, h))
- elif self.state == "replaced":
- for w_item in w:
- commands.extend(self._state_replaced(w_item, h))
+ elif self.state in ('merged', 'rendered'):
+ commands.extend(self._state_merged(w, h))
+ elif self.state == 'replaced':
+ commands.extend(self._state_replaced(w, h))
return commands
def 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 = []
- h_item = {}
if have:
- h_item = have[0]
- commands.extend(self._render_ospf_param(h_item, want, opr=False))
- commands.extend(self._render_ospf_param(want, h_item))
+ 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 = []
- h_item = {}
- if have:
- h_item = have[0]
- commands.extend(self._render_ospf_param(want, h_item))
+ commands.extend(self._render_ospf_param(want, have))
return commands
def _state_deleted(self, want, have):
""" The command generator when state is deleted
:rtype: A list
:returns: the commands necessary to remove the current configuration
of the provided objects
"""
+
commands = []
- if want:
- for w in want:
- if have:
- h = have[0]
- if h:
- for key, val in iteritems(w):
- if key in h:
- if key == 'ospf_area':
- key = 'area'
- commands.append(self._compute_command(attr=key, opr=False))
- elif have and have[0]:
+ 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')
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):
+ 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))
else:
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 == "ospf_area":
- commands.extend(self._render_ospf_area(key, w, h, opr=opr))
- elif key == "timers":
- commands.extend(self._render_timers(key, w, h, opr=opr, remove=remove))
- elif key == "distance":
- commands.extend(self._render_distance(key, w, h, opr=opr, remove=remove))
+ elif key == 'areas':
+ commands.extend(self._render_areas(key, w, h, opr=opr))
+ elif key == 'timers':
+ commands.extend(self._render_timers(key, w, h, opr=opr))
+ 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")}
+ 'parameters': ('router_id', 'abr_type',
+ 'opaque_lsa', 'rfc1583_compatibility')}
leaf = leaf_dict[attr]
- for item, value in iteritems(want[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":
+ if item == 'enabled':
item = 'enable'
- if item in ("opaque_lsa", "enable", "rfc1583_compatibility"):
+ 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))
elif not opr and item in leaf and not _in_target(h, item):
- if item == "enabled":
+ 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))
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("_","-") + " "
+ 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'])
+ 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')}
+ 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('_', '-'))
+ 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))
+ 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))
+ 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,
+ ))
+ return commands
+
+ 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))
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',
- 'vlink': 'address'}
- leaf_dict = {'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")
- }
+ name = {
+ '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'),
+ }
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):
+ 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 == '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 in ('route_type', 'neighbor_id', 'address'):
+ if key in ('route_type', 'neighbor_id',
+ 'address', 'key_id'):
commands.append(cmd + attr + ' ' + str(val))
- elif key == 'authentication':
- commands.append(self._render_vlink(key, w_item, h_item, cmd, opr))
+ 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'):
+ 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': ("always", "metric", "metric_type", "route_map"),
- }
+ '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]):
+ 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'):
- commands.append(cmd + (attr.replace("_","-") + " " + key.replace("_","-") + " " + item.replace("_","-")))
- else:
- 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 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_ospf_area(self, attr, want, have, opr=True):
+ 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", "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))
elif w_lst:
for w_area in w_lst:
- cmd = self._compute_command(key='area', attr=_bool_to_str(w_area['area']), opr=opr) + ' '
- h_area = self.search_obj_in_have(h_lst, w_area, 'area')
+ 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'], 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):
+ 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':
- commands.append(self._form_attr_cmd(attr=key, val=_bool_to_str(val), opr=opr))
+ 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' 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' and not _in_target(h_area, key):
+ 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"
+ key = 'normal'
if opr and key in w_type.keys() and not _is_w_same(w_type, h_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': ("default_cost", "no_summary", "translate"),
- 'stub': ("default_cost", "no_summary")}
+ if not w_type[key] and h_type and h_type[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')}
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):
- 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):
- commands.append(cmd + (want['area'] + ' ' + attr.replace("_","-") + " " + key + " " + item.replace("_","-")))
+ 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)
+ 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)
+ else:
+ 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)
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("_", "-")
- if val and opr:
+ 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/ospfv2/ospfv2.py b/plugins/module_utils/network/vyos/facts/ospfv2/ospfv2.py
index 3457fac..0467b72 100644
--- a/plugins/module_utils/network/vyos/facts/ospfv2/ospfv2.py
+++ b/plugins/module_utils/network/vyos/facts/ospfv2/ospfv2.py
@@ -1,395 +1,464 @@
#
# -*- coding: utf-8 -*-
# Copyright 2019 Red Hat
# GNU General Public License v3.0+
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
"""
The vyos 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
class Ospfv2Facts(object):
+
""" The vyos ospfv2 fact class
"""
- def __init__(self, module, subspec='config', options='options'):
+ def __init__(
+ 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 = []
+
+ objs = {}
ospfv2 = findall(r"^set protocols ospf (.+)", data, M)
if ospfv2:
- config = self.render_config(ospfv2)
- if config:
- objs.append(config)
- ansible_facts["ansible_network_resources"].pop("ospfv2", None)
+ objs = self.render_config(ospfv2)
facts = {}
- if objs:
- facts["ospfv2"] = []
- params = utils.validate_config(self.argument_spec, {"config": objs})
- for cfg in params["config"]:
- facts["ospfv2"].append(utils.remove_empties(cfg))
- 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["mpls_te"] = self.parse_attrib(conf, "mpls_te", "mpls-te")
- config["default_information"] = self.parse_def_info(conf)
- config["parameters"] = self.parse_attrib(conf, "parameters", "parameters")
- config["route_map"] = self.parse_leaf_list(conf, "route-map")
- config["ospf_area"] = self.parse_attrib_list(conf, "area", "area")
- 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, attrib=None):
+ def parse_timers(self, conf):
"""
This function triggers the parsing of 'timers' attributes
:param conf: configuration
- :param attrib: attribute name
: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)
- 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 + " (?:\'*)(\S+)(?:\'*)", conf, M)
- else:
- items = findall(r"" + attrib + " (?:\'*)(\S+)(?:\'*)", conf, M)
- if items:
- a_lst = []
- for item in set(items):
- i_regex = r" %s .+$" % item
- cfg = "\n".join(findall(i_regex, conf, M))
- if attrib == 'area':
- obj = self.parse_area(cfg, item)
- elif attrib == 'virtual-link':
- obj = self.parse_vlink(cfg)
- 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
+ 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("'"))
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)
return cfg_dict
- def parse_max_metric(self, conf, attrib=None):
+ def parse_max_metric(self, conf):
"""
This function triggers the parsing of 'max_metric' attributes
:param conf: configuration
- :param attrib: attribute name
: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, attrib=None):
+ def parse_def_info(self, conf):
"""
This function triggers the parsing of 'default_information' attributes
:param conf: configuration
- :param attrib: attribute name
: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", 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)
+ 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")
- cfg_dict["stub"] = self.parse_attrib(conf, "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 'vitual_link' attributes
+ 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")}
+ 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_md5(conf, "md5")
+
+ 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_md5(self, conf, attrib=None):
+ def parse_attrib_list(self, conf, attrib, param):
"""
- This function triggers the parsing of 'md5' attributes
- :param conf: configuration
- :param attrib: 'md5'
- :return: generated config dictionary
+ 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
"""
- cfg_dict = self.parse_attr(conf, ["key_id"], match=attrib)
- return cfg_dict
+
+ 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)
+ else:
+ items = findall(r"" + attrib + " (?:\'*)(\\S+)(?:\'*)", conf, M)
+ if items:
+ a_lst = []
+ for item in set(items):
+ i_regex = r" %s .+$" % item
+ cfg = '\n'.join(findall(i_regex, conf, M))
+ if attrib == 'area':
+ obj = self.parse_area(cfg, item)
+ elif attrib == 'virtual-link':
+ obj = self.parse_vlink(cfg)
+ 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 = {
- 'stub': ["default_cost", "no_summary"],
- 'area': ["shortcut", "authentication"],
- 'mpls_te': ["enabled", "router_address"],
- 'neighbor': ["priority", "poll_interval"],
- 'ospf': ["external", "inter_area", "intra_area"],
- 'nssa': ["translate", "default_cost", "no_summary"],
- 'redistribute': ["metric", "metric_type", "route_map"],
- 'spf': ["delay", "max_holdtime", "initial_holdtime"],
- 'range': ["cost", "substitute", "not_advertise"],
- 'originate': ["always", "metric", "metric_type", "route_map"],
- 'router_lsa': ["administrative", "on_shutdown", "on_startup"],
- 'config_routes': ["default_metric", "log_adjacency_changes"],
- '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:
+ 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 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 = ("always", "normal", "enabled", "opaque_lsa", "not_advertise", "administrative", "rfc1583_compatibility")
+
+ bool_set = (
+ '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", "default_metric", "initial_holdtime")
+
+ 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',
+ )
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 c7dc575..c539beb 100644
--- a/plugins/module_utils/network/vyos/utils/utils.py
+++ b/plugins/module_utils/network/vyos/utils/utils.py
@@ -1,264 +1,263 @@
# -*- 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
-import q
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
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 73528eb..866ed76 100644
--- a/plugins/modules/vyos_ospfv2.py
+++ b/plugins/modules/vyos_ospfv2.py
@@ -1,1369 +1,1981 @@
#!/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'
}
DOCUMENTATION = """
---
module: vyos_ospfv2
version_added: 2.10
-short_description: Manages attributes of OSPF IPv4 routes on VyOS network devices.
-description: This module manages attributes of OSPF IPv4 routes on VyOS network devices.
-author: Rohit Thakur (@rohitthakur2590)
+short_description: This resource module configures and manages attributes of OSPFv2 routes on VyOS network devices.
+description: This resource module configures and manages attributes of OSPFv2 routes on VyOS network devices.
+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 OSPF route configuration.
- type: list
- elements: dict
+ description: A provided OSPFv2 route configuration.
+ type: dict
suboptions:
- ospf_area:
- description: OSPF area.
+ areas:
+ description: OSPFv2 area.
type: list
elements: dict
suboptions:
- area:
+ area_id:
description: Configured to discard packets.
type: str
area_type:
description: Area type.
type: dict
suboptions:
normal:
- description: Normal OSPF area.
+ description: Normal OSPFv2 area.
type: bool
nssa:
- description: Nssa OSPF area.
+ description: Nssa OSPFv2 area.
type: dict
suboptions:
+ set:
+ description: Enabling nssa.
+ type: bool
default_cost:
description: Summary-default cost of nssa area.
type: int
no_summary:
description: Do not inject inter-area routes into stub.
type: bool
translate:
description: Nssa-abr.
type: str
choices: ['always', 'candidate', 'never']
stub:
- description: Stub OSPF area.
+ description: Stub OSPFv2 area.
type: dict
suboptions:
+ set:
+ description: Enabling stub.
+ type: bool
default_cost:
description: Summary-default cost of stub area.
type: int
no_summary:
description: Do not inject inter-area routes into stub.
type: bool
authentication:
- description: OSPF area authentication type.
+ description: OSPFv2 area authentication type.
type: str
choices: ['plaintext-password', 'md5']
network:
- description: OSPF network.
+ description: OSPFv2 network.
type: list
elements: dict
suboptions:
address:
required: True
- description: OSPF IPv4 network address.
+ description: OSPFv2 IPv4 network address.
type: str
range:
description: Summarize routes matching prefix (border routers only).
type: list
elements: dict
suboptions:
address:
description: border router IPv4 address.
type: str
cost:
description: Metric for this range.
type: int
not_advertise:
description: Don't advertise this range.
type: bool
substitute:
description: Announce area range (IPv4 address) as another prefix.
type: str
shortcut:
description: Area's shortcut mode.
type: str
choices: ['default', 'disable', 'enable']
virtual_link:
description: Virtual link address.
type: list
elements: dict
suboptions:
address:
description: virtual link address.
type: str
authentication:
- description: OSPF area authentication type.
+ description: OSPFv2 area authentication type.
type: dict
suboptions:
md5:
description: MD5 key id based authentication.
- type: dict
+ type: list
+ elements: dict
suboptions:
key_id:
description: MD5 key id.
type: int
md5_key:
description: MD5 key.
type: str
plaintext_password:
description: Plain text password.
type: str
dead_interval:
description: Interval after which a neighbor is declared dead.
type: int
hello_interval:
description: Interval between hello packets.
type: int
retransmit_interval:
description: Interval between retransmitting lost link state advertisements.
type: int
transmit_delay:
description: Link state transmit delay.
type: int
log_adjacency_changes:
description: Log changes in adjacency state.
type: str
choices: ['detail']
max_metric:
- description: OSPF maximum/infinite-distance metric.
+ description: OSPFv2 maximum/infinite-distance metric.
type: dict
suboptions:
router_lsa:
description: Advertise own Router-LSA with infinite distance (stub router).
type: dict
suboptions:
administrative:
description: Administratively apply, for an indefinite period.
type: bool
on_shutdown:
description: Time to advertise self as stub-router.
type: int
on_startup:
description: Time to advertise self as stub-router
type: int
auto_cost:
- description: Calculate OSPF interface cost according to bandwidth.
+ 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: OSPF default metric.
+ description: OSPFv2 default metric.
type: int
metric_type:
- description: OSPF Metric types for default routes.
+ description: OSPFv2 Metric types for default routes.
type: int
route_map:
description: Route map references.
type: str
default_metric:
description: Metric of redistributed routes
type: int
distance:
description: Administrative distance.
type: dict
suboptions:
global:
- description: Global OSPF administrative distance.
+ description: Global OSPFv2 administrative distance.
type: int
ospf:
- description: OSPF administrative distance.
+ description: OSPFv2 administrative distance.
type: dict
suboptions:
external:
description: Distance for external routes.
type: int
inter_area:
description: Distance for inter-area routes.
type: int
intra_area:
description: Distance for intra-area routes.
type: int
mpls_te:
description: MultiProtocol Label Switching-Traffic Engineering (MPLS-TE) parameters.
type: dict
suboptions:
enabled:
description: Enable MPLS-TE functionality.
type: bool
router_address:
description: Stable IP address of the advertising router.
type: str
neighbor:
description: Neighbor IP address.
type: list
elements: dict
suboptions:
neighbor_id:
description: Identity (number/IP address) of neighbor.
type: str
poll_interval:
description: Seconds between dead neighbor polling interval.
type: int
priority:
description: Neighbor priority.
type: int
parameters:
- descriptions: OSPF specific parameters.
+ descriptions: OSPFv2 specific parameters.
type: dict
suboptions:
abr_type:
- description: OSPF ABR Type.
+ description: OSPFv2 ABR Type.
type: str
choices: ['cisco', 'ibm', 'shortcut', 'standard']
opaque_lsa:
description: Enable the Opaque-LSA capability (rfc2370).
type: bool
rfc1583_compatibility:
description: Enable rfc1583 criteria for handling AS external routes.
type: bool
router_id:
description: Override the default router identifier.
type: str
passive_interface:
description: Suppress routing updates on an interface.
type: list
passive_interface_exclude:
description: Interface to exclude when using passive-interface default.
type: list
redistribute:
description: Redistribute information from another routing protocol.
type: list
elements: dict
suboptions:
route_type:
description: Route type to redistribute.
type: str
choices: ['bgp', 'connected', 'kernel', 'rip', 'static']
metric:
description: Metric for redistribution routes.
type: int
metric_type:
- description: OSPF Metric types.
+ description: OSPFv2 Metric types.
type: int
route_map:
description: Route map references.
type: str
route_map:
description: Filter routes installed in local route map.
type: list
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: OSPF SPF timers.
+ 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')
+ 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@192# run show configuration commands | grep ospf
+# vyos@vyos# run show configuration commands | grep ospf
+#
#
-- name: Merge the provided configuration with the existing running configuration
- vyos_ospf_routes:
+- name: Merge the provided configuration with the exisiting running configuration
+ vyos.vyos.vyos_ospfv2:
config:
- - afi: 'ipv4'
- ospf_area:
- - area: 0
- network: 192.168.0.0/24
- default_information:
- originate:
- always: true
- metric: 2
- metric_type: 10
- log_adjacency_changes: "details"
- parameters:
- router_id: 10.1.1.1
- redistribute:
- - route_type: 'connected'
- metric_type: 2
- route_map: 'CONNECT'
- - afi: 'ipv6'
- ospf_area:
- - area: 0.0.0.0
- range: 2001:db8:1::/64
- parameters:
- router-id 192.168.1.1
- redistribute:
- - route_type: 'connected'
+ 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": []
#
# "commands": [
-# "set interfaces ethernet eth1 firewall in name 'INBOUND'",
-# "set protocols ospf area 0 network 192.168.0.0/24",
+# "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 metric-type 2",
-# "set protocols ospf log-adjacency-changes",
-# "set protocols ospf parameters router-id 10.1.1.1",
-# "set protocols ospf redistribute connected metric-type 2",
-# "set protocols ospf redistribute connected route-map CONNECT",
-# "set protocols ospfv3 area 0.0.0.0 range 2001:db8:1::/64,
-# "set protocols ospfv3 parameters router-id 192.168.1.1,
-# "set protocols ospfv3 redistribute connected
+# "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": [
-# {
-# {
-# "afi": "ipv4",
-# "ospf_area":[
-# {
-# "area": "0",
-# "network": "192.168.0.0/24"
-# }
-# ],
-# "default_information":
-# {
-# "originate":
-# {
-# always: true,
-# metric: 2,
-# metric_type: 10
-# }
-# },
-# "log_adjacency_changes": "details"
-# "parameters":
-# {
-# "router_id": "10.1.1.1"
-# },
-# "redistribute":[
-# {
-# "route_type": "connetced",
-# "metric_type": 2
-# "route_map": "CONNECT"
-# }
-# ]
-# },
-# {
-# "afi": "ipv6",
-# "ospf_area":[
-# {
-# "area": "0.0.0.0",
-# }
-# ],
-# "range": "2001:db8:1::/64",
-# "parameters":
-# {
-# "router_id": "192.168.1.1"
-# },
-# "redistribute":
-# [
-# {
-# "route_type": "connetced",
-# }
-# ]
+# "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@vyos:~$ show configuration commands| grep firewall
-# set protocols ospf area 0 network 192.168.0.0/24
-# 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 log-adjacency-changes details
-# set protocols ospf parameters router-id 10.1.1.1
-# set protocols ospf redistribute connected metric-type 2
-# set protocols ospf redistribute connected route-map CONNECT
-# set protocols ospfv3 area 0.0.0.0 range 2001:db8:1::/64
-# set protocols ospfv3 parameters router-id 192.168.1.1
-# set protocols ospfv3 redistribute connected
+# 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 replaced
+# Using merged
#
# Before state:
# -------------
#
-# vyos@192# run show configuration commands | grep ospf
-# set protocols ospf area 0 network 192.168.0.0/24
-# 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 log-adjacency-changes details
-# set protocols ospf parameters router-id 10.1.1.1
-# set protocols ospf redistribute connected metric-type 2
-# set protocols ospf redistribute connected route-map CONNECT
-# set protocols ospfv3 area 0.0.0.0 range 2001:db8:1::/64
-# set protocols ospfv3 parameters router-id 192.168.1.1
-# set protocols ospfv3 redistribute connected
-#
-- name: Replace the provided configuration with the existing running configuration
- vyos_ospf_routes:
+# vyos@vyos# run show configuration commands | grep ospf
+#
+#
+- name: Merge the provided configuration to update exisiting running configuration
+ vyos.vyos.vyos_ospfv2:
config:
- - afi: 'ipv4'
- ospf_area:
- - area: 0
- network: 192.168.0.0/24
- area_type:
- normal: True
- default_information:
- originate:
- always: true
- metric: 2
- metric_type: 10
- log_adjacency_changes: "details"
- parameters:
- router_id: 10.1.1.1
- redistribute:
- - route_type: 'static'
- metric_type: 2
- route_map: 'STATIC'
- - afi: 'ipv6'
- ospf_area:
- - area: 0.0.0.0
- range: 2001:db8:1::/64
- parameters:
- router-id 192.168.1.1
- redistribute:
- - route_type: 'connected'
- state: replaced
+ 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": [
-# {
-# {
-# "afi": "ipv4",
-# "ospf_area":[
-# {
-# "area": "0",
-# "network": "192.168.0.0/24"
-# }
-# ],
-# "default_information":
-# {
-# "originate":
-# {
-# always: true,
-# metric: 2,
-# metric_type: 10
-# }
-# },
-# "log_adjacency_changes": "details"
-# "parameters":
-# {
-# "router_id": "10.1.1.1"
-# },
-# "redistribute":[
-# {
-# "route_type": "connetced",
-# "metric_type": 2
-# "route_map": "CONNECT"
-# }
-# ]
-# },
-# {
-# "afi": "ipv6",
-# "ospf_area":[
-# {
-# "area": "0.0.0.0",
-# }
-# ],
-# "range": "2001:db8:1::/64",
-# "parameters":
-# {
-# "router_id": "192.168.1.1"
-# },
-# "redistribute":
-# [
-# {
-# "route_type": "connetced",
-# }
-# ]
+# "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 redistribute connected",
-# "set protocols ospf area 0 area_type normal",
-# "set protocols ospf redistribute static metric-type 2",
-# "set protocols ospf redistribute static route-map CONNECT"
+# "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": [
-# {
-# {
-# "afi": "ipv4",
-# "ospf_area":[
-# {
-# "area": "0",
-# "area_type":
-# {
-# normal: true
-# }
-# "network": "192.168.0.0/24"
-# }
-# ],
-# "default_information":
-# {
-# "originate":
-# {
-# always: true,
-# metric: 2,
-# metric_type: 10
-# }
-# },
-# "log_adjacency_changes": "details"
-# "parameters":
-# {
-# "router_id": "10.1.1.1"
-# },
-# "redistribute":[
-# {
-# "route_type": "static",
-# "metric_type": 2
-# "route_map": "STATIC"
-# }
-# ]
-# },
-# {
-# "afi": "ipv6",
-# "ospf_area":[
-# {
-# "area": "0.0.0.0",
-# }
-# ],
-# "range": "2001:db8:1::/64",
-# "parameters":
-# {
-# "router_id": "192.168.1.1"
-# },
-# "redistribute":
-# [
-# {
-# "route_type": "connected",
-# }
-# ]
+# "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@vyos:~$ show configuration commands| grep firewall
-# set protocols ospf area 0 network 192.168.0.0/24
-# 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 log-adjacency-changes details
-# set protocols ospf parameters router-id 10.1.1.1
-# set protocols ospf redistribute static metric-type 2
-# set protocols ospf redistribute static route-map CONNECT
-# set protocols ospfv3 area 0.0.0.0 range 2001:db8:2::/64
-# set protocols ospfv3 parameters router-id 192.168.2.1
-# set protocols ospfv3 redistribute connected
+# 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 0 network 192.168.0.0/24
-# 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 log-adjacency-changes details
-# set protocols ospf parameters router-id 10.1.1.1
-# set protocols ospf redistribute connected metric-type 2
-# set protocols ospf redistribute connected route-map CONNECT
-# set protocols ospfv3 area 0.0.0.0 range 2001:db8:1::/64
-# set protocols ospfv3 parameters router-id 192.168.1.1
-# set protocols ospfv3 redistribute connected
-#
-- name: Replace the provided configuration with the existing running configuration
- vyos_ospf_routes:
+# 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:
- - afi: 'ipv4'
- ospf_area:
- - area: 0
- network: 192.168.0.0/24
- area_type:
- normal: True
- default_information:
- originate:
- always: true
- metric: 2
- metric_type: 10
- log_adjacency_changes: "details"
- parameters:
- router_id: 10.1.1.1
- redistribute:
- - route_type: 'static'
- metric_type: 2
- route_map: 'STATIC'
- - afi: 'ipv6'
- ospf_area:
- - area: 0.0.0.0
- range: 2001:db8:1::/64
- parameters:
- router-id 192.168.1.1
- redistribute:
- - route_type: 'connected'
+ 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": [
-# {
-# {
-# "afi": "ipv4",
-# "ospf_area":[
-# {
-# "area": "0",
-# "network": "192.168.0.0/24"
-# }
-# ],
-# "default_information":
-# {
-# "originate":
-# {
-# always: true,
-# metric: 2,
-# metric_type: 10
-# }
-# },
-# "log_adjacency_changes": "details"
-# "parameters":
-# {
-# "router_id": "10.1.1.1"
-# },
-# "redistribute":[
-# {
-# "route_type": "connetced",
-# "metric_type": 2
-# "route_map": "CONNECT"
-# }
-# ]
-# },
-# {
-# "afi": "ipv6",
-# "ospf_area":[
-# {
-# "area": "0.0.0.0",
-# }
-# ],
-# "range": "2001:db8:1::/64",
-# "parameters":
-# {
-# "router_id": "192.168.1.1"
-# },
-# "redistribute":
-# [
-# {
-# "route_type": "connetced",
-# }
-# ]
-# }
-# ]
-#
-# "commands": [
-# "delete protocols ospf redistribute connected",
-# "set protocols ospf area 0 area_type normal",
-# "set protocols ospf redistribute static metric-type 2",
-# "set protocols ospf redistribute static route-map CONNECT"
-# ]
-#
-# "after": [
-# {
-# {
-# "afi": "ipv4",
-# "ospf_area":[
-# {
-# "area": "0",
-# "area_type":
-# {
-# normal: true
-# }
-# "network": "192.168.0.0/24"
-# }
-# ],
-# "default_information":
-# {
-# "originate":
-# {
-# always: true,
-# metric: 2,
-# metric_type: 10
-# }
-# },
-# "log_adjacency_changes": "details"
-# "parameters":
-# {
-# "router_id": "10.1.1.1"
-# },
-# "redistribute":[
-# {
-# "route_type": "static",
-# "metric_type": 2
-# "route_map": "STATIC"
-# }
-# ]
-# },
-# {
-# "afi": "ipv6",
-# "ospf_area":[
-# {
-# "area": "0.0.0.0",
-# }
-# ],
-# "range": "2001:db8:1::/64",
-# "parameters":
-# {
-# "router_id": "192.168.1.1"
-# },
-# "redistribute":
-# [
-# {
-# "route_type": "connected",
-# }
-# ]
+# "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@vyos:~$ show configuration commands| grep firewall
-# set protocols ospf area 0 network 192.168.0.0/24
-# 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 log-adjacency-changes details
-# set protocols ospf parameters router-id 10.1.1.1
-# set protocols ospf redistribute static metric-type 2
-# set protocols ospf redistribute static route-map CONNECT
-# set protocols ospfv3 area 0.0.0.0 range 2001:db8:2::/64
-# set protocols ospfv3 parameters router-id 192.168.2.1
-# set protocols ospfv3 redistribute connected
+# 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 replaced
+# Using rendered
#
-# Before state:
-# -------------
#
-# vyos@192# run show configuration commands | grep ospf
-# set protocols ospf area 0 network 192.168.0.0/24
-# 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 log-adjacency-changes details
-# set protocols ospf parameters router-id 10.1.1.1
-# set protocols ospf redistribute connected metric-type 2
-# set protocols ospf redistribute connected route-map CONNECT
-# set protocols ospfv3 area 0.0.0.0 range 2001:db8:1::/64
-# set protocols ospfv3 parameters router-id 192.168.1.1
-# set protocols ospfv3 redistribute connected
-#
-- name: Replace the provided configuration with the existing running configuration
- vyos_ospf_routes:
+- name: Render the commands for provided configuration
+ vyos.vyos.vyos_ospfv2:
config:
- - afi: 'ipv4'
- ospf_area:
- - area: 0
- network: 192.168.0.0/24
- area_type:
- normal: True
- default_information:
- originate:
- always: true
- metric: 2
- metric_type: 10
- log_adjacency_changes: "details"
- parameters:
- router_id: 10.1.1.1
- redistribute:
- - route_type: 'static'
- metric_type: 2
- route_map: 'STATIC'
- - afi: 'ipv6'
- ospf_area:
- - area: 0.0.0.0
- range: 2001:db8:1::/64
- parameters:
- router-id 192.168.1.1
- redistribute:
- - route_type: 'connected'
- state: replaced
+ 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
# -------------------------
#
-# before": [
-# {
-# {
-# "afi": "ipv4",
-# "ospf_area":[
-# {
-# "area": "0",
-# "network": "192.168.0.0/24"
-# }
-# ],
-# "default_information":
-# {
-# "originate":
-# {
-# always: true,
-# metric: 2,
-# metric_type: 10
-# }
-# },
-# "log_adjacency_changes": "details"
-# "parameters":
-# {
-# "router_id": "10.1.1.1"
-# },
-# "redistribute":[
-# {
-# "route_type": "connetced",
-# "metric_type": 2
-# "route_map": "CONNECT"
-# }
-# ]
-# },
-# {
-# "afi": "ipv6",
-# "ospf_area":[
-# {
-# "area": "0.0.0.0",
-# }
-# ],
-# "range": "2001:db8:1::/64",
-# "parameters":
-# {
-# "router_id": "192.168.1.1"
-# },
-# "redistribute":
-# [
-# {
-# "route_type": "connetced",
-# }
-# ]
-# }
-# ]
#
-# "commands": [
-# "delete protocols ospf redistribute connected",
-# "set protocols ospf area 0 area_type normal",
-# "set protocols ospf redistribute static metric-type 2",
-# "set protocols ospf redistribute static route-map CONNECT"
+# "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'
+ 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
#
-# "after": [
-# {
-# {
-# "afi": "ipv4",
-# "ospf_area":[
-# {
-# "area": "0",
-# "area_type":
-# {
-# normal: true
-# }
-# "network": "192.168.0.0/24"
-# }
-# ],
-# "default_information":
-# {
-# "originate":
-# {
-# always: true,
-# metric: 2,
-# metric_type: 10
-# }
-# },
-# "log_adjacency_changes": "details"
-# "parameters":
-# {
-# "router_id": "10.1.1.1"
-# },
-# "redistribute":[
-# {
-# "route_type": "static",
-# "metric_type": 2
-# "route_map": "STATIC"
-# }
-# ]
-# },
-# {
-# "afi": "ipv6",
-# "ospf_area":[
-# {
-# "area": "0.0.0.0",
-# }
-# ],
-# "range": "2001:db8:1::/64",
-# "parameters":
-# {
-# "router_id": "192.168.1.1"
-# },
-# "redistribute":
-# [
-# {
-# "route_type": "connected",
-# }
-# ]
-# }
-# ]
#
-# After state:
-# -------------
+# -------------------------
+# Module Execution Result
+# -------------------------
+#
#
-# vyos@vyos:~$ show configuration commands| grep firewall
-# set protocols ospf area 0 network 192.168.0.0/24
-# 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 log-adjacency-changes details
-# set protocols ospf parameters router-id 10.1.1.1
-# set protocols ospf redistribute static metric-type 2
-# set protocols ospf redistribute static route-map CONNECT
-# set protocols ospfv3 area 0.0.0.0 range 2001:db8:2::/64
-# set protocols ospfv3 parameters router-id 192.168.2.1
-# set protocols ospfv3 redistribute connected
+# "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 replaced
+# Using gathered
#
# Before state:
# -------------
#
# vyos@192# run show configuration commands | grep ospf
-# set protocols ospf area 0 network 192.168.0.0/24
-# 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 log-adjacency-changes details
-# set protocols ospf parameters router-id 10.1.1.1
-# set protocols ospf redistribute connected metric-type 2
-# set protocols ospf redistribute connected route-map CONNECT
-# set protocols ospfv3 area 0.0.0.0 range 2001:db8:1::/64
-# set protocols ospfv3 parameters router-id 192.168.1.1
-# set protocols ospfv3 redistribute connected
-#
-- name: Replace the provided configuration with the existing running configuration
- vyos_ospf_routes:
- config:
- - afi: 'ipv4'
- ospf_area:
- - area: 0
- network: 192.168.0.0/24
- area_type:
- normal: True
- default_information:
- originate:
- always: true
- metric: 2
- metric_type: 10
- log_adjacency_changes: "details"
- parameters:
- router_id: 10.1.1.1
- redistribute:
- - route_type: 'static'
- metric_type: 2
- route_map: 'STATIC'
- - afi: 'ipv6'
- ospf_area:
- - area: 0.0.0.0
- range: 2001:db8:1::/64
- parameters:
- router-id 192.168.1.1
- redistribute:
- - route_type: 'connected'
- state: replaced
+# 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
#
#
# -------------------------
# Module Execution Result
# -------------------------
#
-# before": [
-# {
-# {
-# "afi": "ipv4",
-# "ospf_area":[
-# {
-# "area": "0",
-# "network": "192.168.0.0/24"
-# }
-# ],
-# "default_information":
-# {
-# "originate":
-# {
-# always: true,
-# metric: 2,
-# metric_type: 10
-# }
-# },
-# "log_adjacency_changes": "details"
-# "parameters":
-# {
-# "router_id": "10.1.1.1"
-# },
-# "redistribute":[
-# {
-# "route_type": "connetced",
-# "metric_type": 2
-# "route_map": "CONNECT"
-# }
-# ]
-# },
-# {
-# "afi": "ipv6",
-# "ospf_area":[
-# {
-# "area": "0.0.0.0",
-# }
-# ],
-# "range": "2001:db8:1::/64",
-# "parameters":
-# {
-# "router_id": "192.168.1.1"
-# },
-# "redistribute":
-# [
-# {
-# "route_type": "connetced",
-# }
-# ]
-# }
-# ]
-#
-# "commands": [
-# "delete protocols ospf redistribute connected",
-# "set protocols ospf area 0 area_type normal",
-# "set protocols ospf redistribute static metric-type 2",
-# "set protocols ospf redistribute static route-map CONNECT"
-# ]
-#
-# "after": [
-# {
-# {
-# "afi": "ipv4",
-# "ospf_area":[
-# {
-# "area": "0",
-# "area_type":
-# {
-# normal: true
-# }
-# "network": "192.168.0.0/24"
-# }
-# ],
-# "default_information":
-# {
-# "originate":
-# {
-# always: true,
-# metric: 2,
-# metric_type: 10
-# }
-# },
-# "log_adjacency_changes": "details"
-# "parameters":
-# {
-# "router_id": "10.1.1.1"
-# },
-# "redistribute":[
-# {
-# "route_type": "static",
-# "metric_type": 2
-# "route_map": "STATIC"
-# }
-# ]
-# },
-# {
-# "afi": "ipv6",
-# "ospf_area":[
-# {
-# "area": "0.0.0.0",
-# }
-# ],
-# "range": "2001:db8:1::/64",
-# "parameters":
-# {
-# "router_id": "192.168.1.1"
-# },
-# "redistribute":
-# [
-# {
-# "route_type": "connected",
-# }
-# ]
+# "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@vyos:~$ show configuration commands| grep firewall
-# set protocols ospf area 0 network 192.168.0.0/24
-# 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 log-adjacency-changes details
-# set protocols ospf parameters router-id 10.1.1.1
-# set protocols ospf redistribute static metric-type 2
-# set protocols ospf redistribute static route-map CONNECT
-# set protocols ospfv3 area 0.0.0.0 range 2001:db8:2::/64
-# set protocols ospfv3 parameters router-id 192.168.2.1
-# set protocols ospfv3 redistribute connected
+# 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:
+# Before state
# -------------
#
# vyos@192# run show configuration commands | grep ospf
-# set protocols ospf area 0 network 192.168.0.0/24
-# 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 log-adjacency-changes details
-# set protocols ospf parameters router-id 10.1.1.1
-# set protocols ospf redistribute connected metric-type 2
-# set protocols ospf redistribute connected route-map CONNECT
-# set protocols ospfv3 area 0.0.0.0 range 2001:db8:1::/64
-# set protocols ospfv3 parameters router-id 192.168.1.1
-# set protocols ospfv3 redistribute connected
-#
-- name: Delete all the configuration
- vyos_ospf_routes:
+# 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 Result
-# -------------------------
-#
-# before": [
-# {
-# {
-# "afi": "ipv4",
-# "ospf_area":[
-# {
-# "area": "0",
-# "network": "192.168.0.0/24"
-# }
-# ],
-# "default_information":
-# {
-# "originate":
-# {
-# always: true,
-# metric: 2,
-# metric_type: 10
-# }
-# },
-# "log_adjacency_changes": "details"
-# "parameters":
-# {
-# "router_id": "10.1.1.1"
-# },
-# "redistribute":[
-# {
-# "route_type": "connetced",
-# "metric_type": 2
-# "route_map": "CONNECT"
-# }
-# ]
-# },
-# {
-# "afi": "ipv6",
-# "ospf_area":[
-# {
-# "area": "0.0.0.0",
-# }
-# ],
-# "range": "2001:db8:1::/64",
-# "parameters":
-# {
-# "router_id": "192.168.1.1"
-# },
-# "redistribute":
-# [
-# {
-# "route_type": "connetced",
-# }
-# ]
+# ------------------------
+# 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
+# }
# }
-# ]
-#
-# "commands": [
-# "delete protocols ospf",
-# "delete protocols ospfv3",
+# },
+# {
+# "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
#
-# After state:
+# Before state
# -------------
#
-# vyos@vyos:~$ show configuration commands| grep firewall
+# 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
+#
+#
+# ------------------------
+# 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 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: ['command 1', 'command 2', 'command 3']
+ 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
def main():
"""
Main entry point for module execution
:returns: the result form module invocation
"""
required_if = [
("state", "merged", ("config",)),
("state", "replaced", ("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__':
main()
diff --git a/tests/integration/targets/vyos_ospfv2/defaults/main.yaml b/tests/integration/targets/vyos_ospfv2/defaults/main.yaml
new file mode 100644
index 0000000..852a6be
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv2/defaults/main.yaml
@@ -0,0 +1,3 @@
+---
+testcase: '[^_].*'
+test_items: []
diff --git a/tests/integration/targets/vyos_ospfv2/meta/main.yaml b/tests/integration/targets/vyos_ospfv2/meta/main.yaml
new file mode 100644
index 0000000..7413320
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv2/meta/main.yaml
@@ -0,0 +1,3 @@
+---
+dependencies:
+ - prepare_vyos_tests
diff --git a/tests/integration/targets/vyos_ospfv2/tasks/cli.yaml b/tests/integration/targets/vyos_ospfv2/tasks/cli.yaml
new file mode 100644
index 0000000..93eb2fe
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv2/tasks/cli.yaml
@@ -0,0 +1,19 @@
+---
+- name: Collect all cli test cases
+ find:
+ paths: '{{ role_path }}/tests/cli'
+ patterns: '{{ testcase }}.yaml'
+ use_regex: true
+ register: test_cases
+ delegate_to: localhost
+
+- name: Set test_items
+ set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
+
+- name: Run test case (connection=ansible.netcommon.network_cli)
+ include: '{{ test_case_to_run }}'
+ vars:
+ ansible_connection: ansible.netcommon.network_cli
+ with_items: '{{ test_items }}'
+ loop_control:
+ loop_var: test_case_to_run
diff --git a/tests/integration/targets/vyos_ospfv2/tasks/main.yaml b/tests/integration/targets/vyos_ospfv2/tasks/main.yaml
new file mode 100644
index 0000000..a3db933
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv2/tasks/main.yaml
@@ -0,0 +1,4 @@
+---
+- include: cli.yaml
+ tags:
+ - cli
diff --git a/tests/integration/targets/vyos_ospfv2/tests/cli/_parsed_config.cfg b/tests/integration/targets/vyos_ospfv2/tests/cli/_parsed_config.cfg
new file mode 100644
index 0000000..9cc720b
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv2/tests/cli/_parsed_config.cfg
@@ -0,0 +1,29 @@
+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'
diff --git a/tests/integration/targets/vyos_ospfv2/tests/cli/_populate.yaml b/tests/integration/targets/vyos_ospfv2/tests/cli/_populate.yaml
new file mode 100644
index 0000000..9f358d5
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv2/tests/cli/_populate.yaml
@@ -0,0 +1,35 @@
+---
+- name: Setup
+ vars:
+ lines: "set protocols ospf mpls-te 'enable' \n
+ set protocols ospf mpls-te router-address '192.0.11.11' \n
+ set protocols ospf redistribute bgp metric-type '2' \n
+ set protocols ospf redistribute bgp metric '10'\n
+ set protocols ospf default-information originate metric-type '2' \n
+ set protocols ospf default-information originate 'always' \n
+ set protocols ospf default-information originate metric '10' \n
+ set protocols ospf default-information originate route-map 'ingress' \n
+ set protocols ospf auto-cost reference-bandwidth '2' \n
+ set protocols ospf parameters router-id '192.0.1.1' \n
+ set protocols ospf parameters 'opaque-lsa' \n
+ set protocols ospf parameters abr-type 'cisco' \n
+ set protocols ospf parameters 'rfc1583-compatibility' \n
+ set protocols ospf passive-interface 'eth1' \n
+ set protocols ospf passive-interface 'eth2' \n
+ set protocols ospf max-metric router-lsa on-shutdown '10' \n
+ set protocols ospf max-metric router-lsa 'administrative' \n
+ set protocols ospf max-metric router-lsa on-startup '10' \n
+ set protocols ospf log-adjacency-changes 'detail' \n
+ set protocols ospf neighbor 192.0.11.12 priority '2' \n
+ set protocols ospf neighbor 192.0.11.12 poll-interval '10' \n
+ set protocols ospf area 2 authentication 'plaintext-password' \n
+ set protocols ospf area 2 shortcut 'enable' \n
+ set protocols ospf area 2 area-type 'normal' \n
+ set protocols ospf area 3 area-type 'nssa' \n
+ set protocols ospf area 4 range 192.0.3.0/24 cost '10' \n
+ set protocols ospf area 4 range 192.0.4.0/24 cost '12' \n
+ set protocols ospf area 4 area-type stub default-cost '20' \n
+ set protocols ospf area 4 network '192.0.2.0/24'"
+
+ ansible.netcommon.cli_config:
+ config: '{{ lines }}'
diff --git a/tests/integration/targets/vyos_ospfv2/tests/cli/_remove_config.yaml b/tests/integration/targets/vyos_ospfv2/tests/cli/_remove_config.yaml
new file mode 100644
index 0000000..7360870
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv2/tests/cli/_remove_config.yaml
@@ -0,0 +1,6 @@
+---
+- name: Remove Config
+ vars:
+ lines: "delete protocols ospf\n"
+ ansible.netcommon.cli_config:
+ config: '{{ lines }}'
diff --git a/tests/integration/targets/vyos_ospfv2/tests/cli/delete_single.yaml b/tests/integration/targets/vyos_ospfv2/tests/cli/delete_single.yaml
new file mode 100644
index 0000000..150242a
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv2/tests/cli/delete_single.yaml
@@ -0,0 +1,57 @@
+---
+- 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/deleted.yaml b/tests/integration/targets/vyos_ospfv2/tests/cli/deleted.yaml
new file mode 100644
index 0000000..a61f5a7
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv2/tests/cli/deleted.yaml
@@ -0,0 +1,48 @@
+---
+- 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:
+ state: deleted
+
+ - name: Assert that the before dicts were correctly generated
+ assert:
+ that:
+ - "{{ populate == result['before'] }}"
+
+ - name: Assert that the correct set of commands were generated
+ assert:
+ that:
+ - "{{ deleted['commands'] | symmetric_difference(result['commands']) |length\
+ \ == 0 }}"
+
+ - name: Assert that the after dicts were correctly generated
+ assert:
+ that:
+ - "{{ deleted['after'] == result['after'] }}"
+
+ - name: Delete 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['after'] == result['before'] }}"
+ always:
+
+ - include_tasks: _remove_config.yaml
diff --git a/tests/integration/targets/vyos_ospfv2/tests/cli/empty_config.yaml b/tests/integration/targets/vyos_ospfv2/tests/cli/empty_config.yaml
new file mode 100644
index 0000000..4566bf4
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv2/tests/cli/empty_config.yaml
@@ -0,0 +1,49 @@
+---
+- debug:
+ msg: START vyos_ospfv2 empty_config integration tests on connection={{
+ ansible_connection }}
+
+- name: Merged with empty config should give appropriate error message
+ register: result
+ ignore_errors: true
+ vyos.vyos.vyos_ospfv2:
+ config:
+ state: merged
+
+- assert:
+ that:
+ - result.msg == 'value of config parameter must not be empty for state merged'
+
+- name: Replaced with empty config should give appropriate error message
+ register: result
+ ignore_errors: true
+ vyos.vyos.vyos_ospfv2:
+ config:
+ state: replaced
+
+- assert:
+ that:
+ - result.msg == 'value of config parameter must not be empty for state replaced'
+
+- name: Parsed with empty running_config should give appropriate error message
+ register: result
+ ignore_errors: true
+ vyos.vyos.vyos_ospfv2:
+ running_config:
+ state: parsed
+
+- assert:
+ that:
+ - result.msg == 'value of running_config parameter must not be empty for state
+ parsed'
+
+- name: Rendered with empty config should give appropriate error message
+ register: result
+ ignore_errors: true
+ vyos.vyos.vyos_ospfv2:
+ config:
+ state: rendered
+
+- assert:
+ that:
+ - result.msg == 'value of config parameter must not be empty for state rendered'
diff --git a/tests/integration/targets/vyos_ospfv2/tests/cli/gathered.yaml b/tests/integration/targets/vyos_ospfv2/tests/cli/gathered.yaml
new file mode 100644
index 0000000..22c378b
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv2/tests/cli/gathered.yaml
@@ -0,0 +1,33 @@
+---
+- 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
+ register: result
+ vyos.vyos.vyos_ospfv2: &id001
+ 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.yaml b/tests/integration/targets/vyos_ospfv2/tests/cli/merged.yaml
new file mode 100644
index 0000000..6a58bb5
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv2/tests/cli/merged.yaml
@@ -0,0 +1,101 @@
+---
+- debug:
+ msg: START vyos_ospfv2 merged integration tests on connection={{ ansible_connection
+ }}
+
+- include_tasks: _remove_config.yaml
+
+- block:
+
+ - name: Merge the provided configuration with the exisiting running configuration
+ register: result
+ vyos.vyos.vyos_ospfv2: &id001
+ 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
+
+ - name: Assert that before dicts were correctly generated
+ assert:
+ that: "{{ merged['before'] == result['before'] }}"
+
+ - name: Assert that correct set of commands were generated
+ assert:
+ that:
+ - "{{ merged['commands'] | symmetric_difference(result['commands']) |length\
+ \ == 0 }}"
+
+ - name: Assert that after dicts was correctly generated
+ assert:
+ that:
+ - "{{ merged['after'] == result['after'] }}"
+
+ - name: Merge the provided configuration with the existing running configuration
+ (IDEMPOTENT)
+ register: result
+ vyos.vyos.vyos_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['after'] == result['before'] }}"
+ 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
new file mode 100644
index 0000000..453dbb0
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv2/tests/cli/merged_update.yaml
@@ -0,0 +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
diff --git a/tests/integration/targets/vyos_ospfv2/tests/cli/parsed.yaml b/tests/integration/targets/vyos_ospfv2/tests/cli/parsed.yaml
new file mode 100644
index 0000000..6fbe2f9
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv2/tests/cli/parsed.yaml
@@ -0,0 +1,41 @@
+---
+- 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
diff --git a/tests/integration/targets/vyos_ospfv2/tests/cli/rendered.yaml b/tests/integration/targets/vyos_ospfv2/tests/cli/rendered.yaml
new file mode 100644
index 0000000..86c07cf
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv2/tests/cli/rendered.yaml
@@ -0,0 +1,88 @@
+---
+- 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
+ 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
diff --git a/tests/integration/targets/vyos_ospfv2/tests/cli/replaced.yaml b/tests/integration/targets/vyos_ospfv2/tests/cli/replaced.yaml
new file mode 100644
index 0000000..07606f9
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv2/tests/cli/replaced.yaml
@@ -0,0 +1,100 @@
+---
+- debug:
+ msg: START vyos_ospfv2 replaced integration tests on connection={{
+ ansible_connection }}
+
+- include_tasks: _remove_config.yaml
+
+- include_tasks: _populate.yaml
+
+- block:
+
+ - name: Replace device configurations of listed ospfv2 routes with provided configurations
+ register: result
+ vyos.vyos.vyos_ospfv2: &id001
+ 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: '1.1.2.0/24'
+ cost: 10
+ state: replaced
+
+ - name: Assert that correct set of commands were generated
+ assert:
+ that:
+ - "{{ replaced['commands'] | symmetric_difference(result['commands'])\
+ \ |length == 0 }}"
+
+ - name: Assert that before dicts are correctly generated
+ assert:
+ that:
+ - "{{ populate == result['before'] }}"
+
+ - name: Assert that after dict is correctly generated
+ assert:
+ that:
+ - "{{ replaced['after'] == result['after'] }}"
+
+ - name: Replace device configurations of listed ospfv2 routes with provided configurarions
+ (IDEMPOTENT)
+ register: result
+ vyos.vyos.vyos_ospfv2: *id001
+
+ - name: Assert that task was idempotent
+ assert:
+ that:
+ - result['changed'] == false
+
+ - name: Assert that before dict is correctly generated
+ assert:
+ that:
+ - "{{ replaced['after'] == result['before'] }}"
+ always:
+
+ - include_tasks: _remove_config.yaml
diff --git a/tests/integration/targets/vyos_ospfv2/tests/cli/rtt.yaml b/tests/integration/targets/vyos_ospfv2/tests/cli/rtt.yaml
new file mode 100644
index 0000000..7efc2a7
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv2/tests/cli/rtt.yaml
@@ -0,0 +1,149 @@
+---
+- debug:
+ msg: START vyos_ospfv2 round trip integration tests on connection={{
+ ansible_connection }}
+
+- include_tasks: _remove_config.yaml
+
+- block:
+
+ - name: Apply the provided configuration (base config)
+ register: base_config
+ vyos.vyos.vyos_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
+
+ - name: Gather ospfv2 facts
+ vyos.vyos.vyos_facts:
+ gather_subset:
+ - default
+ gather_network_resources:
+ - ospfv2
+
+ - name: Apply the provided configuration (config to be reverted)
+ register: result
+ vyos.vyos.vyos_ospfv2:
+ config:
+ 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'
+ state: replaced
+
+ - name: Assert that changes were applied
+ assert:
+ that: "{{ round_trip['after'] == result['after'] }}"
+
+ - name: Revert back to base config using facts round trip
+ register: revert
+ vyos.vyos.vyos_ospfv2:
+ config: "{{ ansible_facts['network_resources']['ospfv2'] }}"
+ state: replaced
+
+ - name: Assert that config was reverted
+ assert:
+ that: "{{ base_config['after'] == revert['after']}}"
+ always:
+
+ - include_tasks: _remove_config.yaml
diff --git a/tests/integration/targets/vyos_ospfv2/vars/main.yaml b/tests/integration/targets/vyos_ospfv2/vars/main.yaml
new file mode 100644
index 0000000..76a54e3
--- /dev/null
+++ b/tests/integration/targets/vyos_ospfv2/vars/main.yaml
@@ -0,0 +1,444 @@
+---
+merged:
+ 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'
+ redistribute:
+ - metric: 10
+ metric_type: 2
+ route_type: 'bgp'
+ 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'
+ 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:
+ - 'eth2'
+ - 'eth1'
+ 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'
+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: []
+deleted:
+ commands:
+ - 'delete protocols ospf'
+ 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/fixtures/vyos_ospfv2_config.cfg b/tests/unit/modules/network/vyos/fixtures/vyos_ospfv2_config.cfg
new file mode 100644
index 0000000..297671b
--- /dev/null
+++ b/tests/unit/modules/network/vyos/fixtures/vyos_ospfv2_config.cfg
@@ -0,0 +1,9 @@
+set protocols ospf area 12 area-type normal
+set protocols ospf area 12 authentication plaintext-password
+set protocols ospf area 12 shortcut enable
+set protocols ospf area 14 range 192.0.13.0/24 cost 10
+set protocols ospf area 14 range 192.0.13.0/24
+set protocols ospf area 14 range 192.0.14.0/24 cost 12
+set protocols ospf area 14 range 192.0.14.0/24
+set protocols ospf area 14 area-type stub default-cost 20
+set protocols ospf area 14 network 192.0.12.0/24
diff --git a/tests/unit/modules/network/vyos/test_vyos_ospfv2.py b/tests/unit/modules/network/vyos/test_vyos_ospfv2.py
new file mode 100644
index 0000000..8e6b095
--- /dev/null
+++ b/tests/unit/modules/network/vyos/test_vyos_ospfv2.py
@@ -0,0 +1,526 @@
+# (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'),
+ auto_cost=dict(reference_bandwidth=2),
+ areas=[
+ dict(
+ area_id="2",
+ area_type=dict(normal=True),
+ authentication="plaintext-password",
+ shortcut='enable',
+ ),
+ dict(
+ area_id="4",
+ 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)
+ ]
+ ),
+ ],
+ ),
+ 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"
+ ]
+ 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',
+ ),
+ dict(
+ area_id="14",
+ 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)
+ ]
+ ),
+ ],
+ ),
+ 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',
+ ),
+ dict(
+ area_id="14",
+ 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)
+ ]
+ ),
+ ],
+ ),
+ state="merged",
+ )
+ )
+ commands = [
+ "delete protocols ospf area 14 area-type stub",
+ "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'),
+ auto_cost=dict(reference_bandwidth=2),
+ areas=[
+ dict(
+ area_id="12",
+ area_type=dict(normal=True),
+ authentication="plaintext-password",
+ shortcut='enable',
+ ),
+ dict(
+ area_id="15",
+ 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)
+ ]
+ ),
+ ],
+ ),
+ 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"
+ ]
+ 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',
+ ),
+ dict(
+ area_id="14",
+ 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)
+ ]
+ ),
+ ],
+ ),
+ 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
+ }
+ ]
+ }
+ ],
+ }
+ 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
+ },
+ "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"
+ }
+ ]
+ }
+ 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'),
+ auto_cost=dict(reference_bandwidth=2),
+ areas=[
+ dict(
+ area_id="2",
+ area_type=dict(normal=True),
+ authentication="plaintext-password",
+ shortcut='enable',
+ ),
+ dict(
+ area_id="4",
+ 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)
+ ]
+ ),
+ ],
+ ),
+ 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"
+ ]
+ 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 49d4652..e0ab699 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