Add nxos_lacp_interfaces resource module (#60313)

Signed-off-by: Trishna Guha <trishnaguha17@gmail.com>
pull/60421/head
Trishna Guha 5 years ago committed by GitHub
parent 4512f664a7
commit 0acf7be56a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -13,6 +13,7 @@ CHOICES = [
'telemetry',
'vlans',
'lacp',
'lacp_interfaces',
]

@ -0,0 +1,90 @@
#
# -*- 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 nxos_lacp_interfaces module
"""
from __future__ import absolute_import, division, print_function
__metaclass__ = type
class Lacp_interfacesArgs(object):
"""The arg spec for the nxos_lacp_interfaces module
"""
def __init__(self, **kwargs):
pass
argument_spec = {
'config': {
'elements': 'dict',
'options': {
'convergence': {
'options': {
'graceful': {
'type': 'bool'
},
'vpc': {
'type': 'bool'
}
},
'type': 'dict'
},
'links': {
'options': {
'max': {
'type': 'int'
},
'min': {
'type': 'int'
}
},
'type': 'dict'
},
'mode': {
'choices': ['delay'],
'type': 'str'
},
'name': {
'required': True,
'type': 'str'
},
'port_priority': {
'type': 'int'
},
'rate': {
'choices': ['fast', 'normal'],
'type': 'str'
},
'suspend_individual': {
'type': 'bool'
}
},
'type': 'list'
},
'state': {
'choices': ['merged', 'replaced', 'overridden', 'deleted'],
'default': 'merged',
'type': 'str'
}
}

@ -0,0 +1,284 @@
#
# -*- 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 nxos_lacp_interfaces 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 ansible.module_utils.network.common.cfg.base import ConfigBase
from ansible.module_utils.network.common.utils import to_list, dict_diff, remove_empties
from ansible.module_utils.network.nxos.facts.facts import Facts
from ansible.module_utils.network.nxos.utils.utils import flatten_dict, search_obj_in_list, get_interface_type, normalize_interface
class Lacp_interfaces(ConfigBase):
"""
The nxos_lacp_interfaces class
"""
gather_subset = [
'!all',
'!min',
]
gather_network_resources = [
'lacp_interfaces',
]
exclude_params = [
'port_priority',
'rate',
'min',
'max',
]
def __init__(self, module):
super(Lacp_interfaces, self).__init__(module)
def get_lacp_interfaces_facts(self):
""" 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)
lacp_interfaces_facts = facts['ansible_network_resources'].get('lacp_interfaces')
if not lacp_interfaces_facts:
return []
return lacp_interfaces_facts
def execute_module(self):
""" Execute the module
:rtype: A dictionary
:returns: The result from module execution
"""
result = {'changed': False}
commands = list()
warnings = list()
existing_lacp_interfaces_facts = self.get_lacp_interfaces_facts()
commands.extend(self.set_config(existing_lacp_interfaces_facts))
if commands:
if not self._module.check_mode:
self._connection.edit_config(commands)
result['changed'] = True
result['commands'] = commands
changed_lacp_interfaces_facts = self.get_lacp_interfaces_facts()
result['before'] = existing_lacp_interfaces_facts
if result['changed']:
result['after'] = changed_lacp_interfaces_facts
result['warnings'] = warnings
return result
def set_config(self, existing_lacp_interfaces_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
"""
config = self._module.params.get('config')
want = []
if config:
for w in config:
if get_interface_type(w['name']) not in ('portchannel', 'ethernet'):
self._module.fail_json(msg='This module works with either portchannel or ethernet')
w.update({'name': normalize_interface(w['name'])})
want.append(remove_empties(w))
have = existing_lacp_interfaces_facts
resp = self.set_state(want, have)
return to_list(resp)
def set_state(self, want, have):
""" 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
"""
state = self._module.params['state']
if state in ('overridden', 'merged', 'replaced') and not want:
self._module.fail_json(msg='config is required for state {0}'.format(state))
commands = list()
if state == 'overridden':
commands.extend(self._state_overridden(want, have))
elif state == 'deleted':
commands.extend(self._state_deleted(want, have))
else:
for w in want:
if state == 'merged':
commands.extend(self._state_merged(flatten_dict(w), have))
elif state == 'replaced':
commands.extend(self._state_replaced(flatten_dict(w), have))
return commands
def _state_replaced(self, w, 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 = []
obj_in_have = flatten_dict(search_obj_in_list(w['name'], have, 'name'))
diff = dict_diff(w, obj_in_have)
merged_commands = self.set_commands(w, have)
if 'name' not in diff:
diff['name'] = w['name']
wkeys = w.keys()
dkeys = diff.keys()
for k in wkeys:
if k in self.exclude_params and k in dkeys:
del diff[k]
replaced_commands = self.del_attribs(diff)
if merged_commands:
cmds = set(replaced_commands).intersection(set(merged_commands))
for cmd in cmds:
merged_commands.remove(cmd)
commands.extend(replaced_commands)
commands.extend(merged_commands)
return commands
def _state_overridden(self, want, have):
""" The command generator when state is overridden
:rtype: A list
:returns: the commands necessary to migrate the current configuration
to the desired configuration
"""
commands = []
for h in have:
h = flatten_dict(h)
obj_in_want = flatten_dict(search_obj_in_list(h['name'], want, 'name'))
if h == obj_in_want:
continue
for w in want:
w = flatten_dict(w)
if h['name'] == w['name']:
wkeys = w.keys()
hkeys = h.keys()
for k in wkeys:
if k in self.exclude_params and k in hkeys:
del h[k]
commands.extend(self.del_attribs(h))
for w in want:
commands.extend(self.set_commands(flatten_dict(w), have))
return commands
def _state_merged(self, w, have):
""" The command generator when state is merged
:rtype: A list
:returns: the commands necessary to merge the provided into
the current configuration
"""
return self.set_commands(w, have)
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:
obj_in_have = flatten_dict(search_obj_in_list(w['name'], have, 'name'))
commands.extend(self.del_attribs(obj_in_have))
else:
if not have:
return commands
for h in have:
commands.extend(self.del_attribs(flatten_dict(h)))
return commands
def del_attribs(self, obj):
commands = []
if not obj or len(obj.keys()) == 1:
return commands
commands.append('interface ' + obj['name'])
if 'graceful' in obj:
commands.append('lacp graceful-convergence')
if 'vpc' in obj:
commands.append('no lacp vpn-convergence')
if 'suspend_individual' in obj:
commands.append('lacp suspend_individual')
if 'mode' in obj:
commands.append('no lacp mode ' + obj['mode'])
if 'max' in obj:
commands.append('no lacp max-bundle')
if 'min' in obj:
commands.append('no lacp min-links')
if 'port_priority' in obj:
commands.append('no lacp port-priority')
if 'rate' in obj:
commands.append('no lacp rate')
return commands
def diff_of_dicts(self, w, obj):
diff = set(w.items()) - set(obj.items())
diff = dict(diff)
if diff and w['name'] == obj['name']:
diff.update({'name': w['name']})
return diff
def add_commands(self, d):
commands = []
if not d:
return commands
commands.append('interface' + ' ' + d['name'])
if 'port_priority' in d:
commands.append('lacp port-priority ' + str(d['port_priority']))
if 'rate' in d:
commands.append('lacp rate ' + str(d['rate']))
if 'min' in d:
commands.append('lacp min-links ' + str(d['min']))
if 'max' in d:
commands.append('lacp max-bundle ' + str(d['max']))
if 'mode' in d:
commands.append('lacp mode ' + d['mode'])
if 'suspend_individual' in d:
if d['suspend_individual'] is True:
commands.append('lacp suspend-individual')
else:
commands.append('no lacp suspend-individual')
if 'graceful' in d:
if d['graceful'] is True:
commands.append('lacp graceful-convergence')
else:
commands.append('no lacp graceful-convergence')
if 'vpc' in d:
if d['vpc'] is True:
commands.append('lacp vpc-convergence')
else:
commands.append('no lacp vpc-convergence')
return commands
def set_commands(self, w, have):
commands = []
obj_in_have = flatten_dict(search_obj_in_list(w['name'], have, 'name'))
if not obj_in_have:
commands = self.add_commands(w)
else:
diff = self.diff_of_dicts(w, obj_in_have)
commands = self.add_commands(diff)
return commands

@ -16,6 +16,7 @@ from ansible.module_utils.network.nxos.facts.lacp.lacp import LacpFacts
from ansible.module_utils.network.nxos.facts.lag_interfaces.lag_interfaces import Lag_interfacesFacts
from ansible.module_utils.network.nxos.facts.telemetry.telemetry import TelemetryFacts
from ansible.module_utils.network.nxos.facts.vlans.vlans import VlansFacts
from ansible.module_utils.network.nxos.facts.lacp_interfaces.lacp_interfaces import Lacp_interfacesFacts
FACT_LEGACY_SUBSETS = dict(
@ -31,6 +32,7 @@ FACT_RESOURCE_SUBSETS = dict(
telemetry=TelemetryFacts,
vlans=VlansFacts,
lacp=LacpFacts,
lacp_interfaces=Lacp_interfacesFacts,
)

@ -0,0 +1,108 @@
#
# -*- 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 nxos lacp_interfaces 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
import re
from copy import deepcopy
from ansible.module_utils.network.common import utils
from ansible.module_utils.network.nxos.argspec.lacp_interfaces.lacp_interfaces import Lacp_interfacesArgs
from ansible.module_utils.network.nxos.utils.utils import get_interface_type
class Lacp_interfacesFacts(object):
""" The nxos lacp_interfaces fact class
"""
def __init__(self, module, subspec='config', options='options'):
self._module = module
self.argument_spec = Lacp_interfacesArgs.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 populate_facts(self, connection, ansible_facts, data=None):
""" Populate the facts for lacp_interfaces
:param connection: the device connection
:param ansible_facts: Facts dictionary
:param data: previously collected conf
:rtype: dictionary
:returns: facts
"""
objs = []
if not data:
data = connection.get('show running-config | section ^interface')
resources = data.split('interface ')
for resource in resources:
if resource and re.search(r'lacp', resource):
obj = self.render_config(self.generated_spec, resource)
if obj and len(obj.keys()) > 1:
objs.append(obj)
ansible_facts['ansible_network_resources'].pop('lacp_interfaces', None)
facts = {}
if objs:
facts['lacp_interfaces'] = []
params = utils.validate_config(self.argument_spec, {'config': objs})
for cfg in params['config']:
facts['lacp_interfaces'].append(utils.remove_empties(cfg))
ansible_facts['ansible_network_resources'].update(facts)
return ansible_facts
def render_config(self, spec, conf):
"""
Render config as dictionary structure and delete keys
from spec for null values
:param spec: The facts tree, generated from the argspec
:param conf: The configuration
:rtype: dictionary
:returns: The generated config
"""
config = deepcopy(spec)
match = re.search(r'^(\S+)', conf)
intf = match.group(1)
if get_interface_type(intf) == 'unknown':
return {}
config['name'] = intf
config['port_priority'] = utils.parse_conf_arg(conf, 'lacp port-priority')
config['rate'] = utils.parse_conf_arg(conf, 'lacp rate')
config['mode'] = utils.parse_conf_arg(conf, 'mode')
suspend_individual = re.search(r'no lacp suspend-individual', conf)
if suspend_individual:
config['suspend_individual'] = False
max_links = utils.parse_conf_arg(conf, 'lacp max-bundle')
if max_links:
config['links']['max'] = max_links
min_links = utils.parse_conf_arg(conf, 'lacp min-links')
if min_links:
config['links']['min'] = min_links
graceful = re.search(r'no lacp graceful-convergence', conf)
if graceful:
config['convergence']['gracefule'] = False
vpc = re.search(r'lacp vpc-convergence', conf)
if vpc:
config['convergence']['vpc'] = True
return utils.remove_empties(config)

@ -10,6 +10,20 @@ def search_obj_in_list(name, lst, identifier):
return None
def flatten_dict(x):
result = {}
if not isinstance(x, dict):
return result
for key, value in iteritems(x):
if isinstance(value, dict):
result.update(flatten_dict(value))
else:
result[key] = value
return result
def validate_ipv4_addr(address):
address = address.split('/')[0]
try:

@ -57,7 +57,7 @@ options:
to a given subset. Possible values for this argument include
all and the resources like interfaces, vlans etc.
Can specify a list of values to include a larger subset.
choices: ['all', 'lag_interfaces', 'telemetry', 'vlans', 'lacp']
choices: ['all', 'lag_interfaces', 'telemetry', 'vlans', 'lacp', 'lacp_interfaces']
required: false
version_added: "2.9"
"""

@ -0,0 +1,258 @@
#!/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 nxos_lacp_interfaces
"""
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'network'}
DOCUMENTATION = """
---
module: nxos_lacp_interfaces
version_added: 2.9
short_description: Manage Link Aggregation Control Protocol (LACP) attributes of interfaces on Cisco NX-OS devices.
description: This module manages Link Aggregation Control Protocol (LACP) attributes of NX-OS Interfaces.
author: Trishna Guha (@trishnaguha)
notes:
- Tested against NXOS 7.3.(0)D1(1) on VIRL
options:
config:
description: A dictionary of LACP interfaces options.
type: list
elements: dict
suboptions:
name:
description:
- Name of the interface.
required: true
type: str
port_priority:
description:
- LACP port priority for the interface. Range 1-65535.
Applicable only for Ethernet.
type: int
rate:
description:
- Rate at which PDUs are sent by LACP. Applicable only for Ethernet.
At fast rate LACP is transmitted once every 1 second.
At normal rate LACP is transmitted every 30 seconds after the link is bundled.
type: str
choices: ['fast', 'normal']
links:
description:
- This dict contains configurable options related to max and min port-channel links.
Applicable only for Port-channel.
type: dict
suboptions:
max:
description:
- Port-channel max bundle.
type: int
min:
description:
- Port-channel min links.
type: int
mode:
description:
- LACP mode. Applicable only for Port-channel.
type: str
choices: ['delay']
suspend_individual:
description:
- port-channel lacp state. Disabling this will cause lacp to put the
port to individual state and not suspend the port in case it does not get
LACP BPDU from the peer ports in the port-channel.
type: bool
convergence:
description:
- This dict contains configurable options related to convergence.
Applicable only for Port-channel.
type: dict
suboptions:
graceful:
description:
- port-channel lacp graceful convergence. Disable this only with lacp ports
connected to Non-Nexus peer. Disabling this with Nexus peer can lead
to port suspension.
type: bool
vpc:
description:
- Enable lacp convergence for vPC port channels.
type: bool
state:
description:
- The state the configuration should be left in.
type: str
choices:
- merged
- replaced
- overridden
- deleted
default: merged
"""
EXAMPLES = """
# Using merged
# Before state:
# -------------
#
- name: Merge provided configuration with device configuration.
nxos_lacp_interfaces:
config:
- name: Ethernet1/3
port_priority: 5
rate: fast
state: merged
# After state:
# ------------
#
# interface Ethernet1/3
# lacp port-priority 5
# lacp rate fast
# Using replaced
# Before state:
# -------------
#
# interface Ethernet1/3
# lacp port-priority 5
# interface port-channel11
# lacp mode delay
- name: Replace device lacp interfaces configuration with the given configuration.
nxos_lacp_interfaces:
config:
- name: port-channel11
links:
min: 4
state: replaced
# After state:
# ------------
#
# interface Ethernet1/3
# lacp port-priority 5
# interface port-channel11
# lacp min-links 4
# Using overridden
# Before state:
# -------------
#
# interface Ethernet1/3
# lacp port-priority 5
# interface port-channel11
# lacp mode delay
- name: Override device configuration of all LACP interfaces attributes of given interfaces on device with provided configuration.
nxos_lacp_interfaces:
config:
- name: port-channel11
links:
min: 4
state: overridden
# After state:
# ------------
#
# interface port-channel11
# lacp min-links 4
# Using deleted
# Before state:
# -------------
#
# interface Ethernet1/3
# lacp port-priority 5
# interface port-channel11
# lacp mode delay
- name: Delete LACP interfaces configurations.
nxos_lacp_interfaces:
state: deleted
# After state:
# ------------
#
"""
RETURN = """
before:
description: The configuration prior to the model invocation.
returned: always
type: list
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: list
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: ['interface port-channel10', 'lacp min-links 5', 'lacp mode delay']
"""
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.nxos.argspec.lacp_interfaces.lacp_interfaces import Lacp_interfacesArgs
from ansible.module_utils.network.nxos.config.lacp_interfaces.lacp_interfaces import Lacp_interfaces
def main():
"""
Main entry point for module execution
:returns: the result form module invocation
"""
module = AnsibleModule(argument_spec=Lacp_interfacesArgs.argument_spec,
supports_check_mode=True)
result = Lacp_interfaces(module).execute_module()
module.exit_json(**result)
if __name__ == '__main__':
main()

@ -0,0 +1,20 @@
---
- name: collect common test cases
find:
paths: "{{ role_path }}/tests/cli"
patterns: "{{ testcase }}.yaml"
connection: local
register: test_cases
- set_fact:
test_cases:
files: "{{ test_cases.files }}"
- name: set test_items
set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
- name: run test cases (connection=network_cli)
include: "{{ test_case_to_run }} ansible_connection=network_cli connection={{ cli }}"
with_items: "{{ test_items }}"
loop_control:
loop_var: test_case_to_run

@ -0,0 +1,2 @@
---
- { include: cli.yaml, tags: ['cli'] }

@ -0,0 +1,33 @@
---
- name: collect common test cases
find:
paths: "{{ role_path }}/tests/common"
patterns: "{{ testcase }}.yaml"
connection: local
register: test_cases
- name: collect nxapi test cases
find:
paths: "{{ role_path }}/tests/nxapi"
patterns: "{{ testcase }}.yaml"
connection: local
register: nxapi_cases
- set_fact:
test_cases:
files: "{{ test_cases.files }} + {{ nxapi_cases.files }}"
- name: set test_items
set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
- name: run test cases (connection=httpapi)
include: "{{ test_case_to_run }} ansible_connection=httpapi connection={{ nxapi }}"
with_items: "{{ test_items }}"
loop_control:
loop_var: test_case_to_run
- name: run test cases (connection=local)
include: "{{ test_case_to_run }} ansible_connection=local connection={{ nxapi }}"
with_items: "{{ test_items }}"
loop_control:
loop_var: test_case_to_run

@ -0,0 +1,56 @@
---
- debug:
msg: "Start nxos_lacp_interfaces deleted integration tests connection={{ ansible_connection }}"
- name: setup1
cli_config: &cleanup
config: |
no interface port-channel5
no interface port-channel10
no feature lacp
- block:
- name: setup2
cli_config:
config: |
feature lacp
interface port-channel5
lacp min-links 5
interface port-channel10
lacp mode delay
- name: Gather lacp_interfaces facts
nxos_facts: &facts
gather_subset:
- '!all'
- '!min'
gather_network_resources: lacp_interfaces
- name: deleted
nxos_lacp_interfaces: &deleted
state: deleted
register: result
- assert:
that:
- "ansible_facts.network_resources.lacp_interfaces|symmetric_difference(result.before)|length == 0"
- "result.after|length == 0"
- "result.changed == true"
- "'interface port-channel5' in result.commands"
- "'no lacp min-links' in result.commands"
- "'interface port-channel10' in result.commands"
- "'no lacp mode delay' in result.commands"
- "result.commands|length == 4"
- name: Idempotence - deleted
nxos_lacp_interfaces: *deleted
register: result
- assert:
that:
- "result.changed == false"
- "result.commands|length == 0"
always:
- name: teardown
cli_config: *cleanup

@ -0,0 +1,61 @@
---
- debug:
msg: "Start nxos_lacp_interfaces merged integration tests connection={{ ansible_connection }}"
- name: setup1
cli_config: &cleanup
config: |
no interface port-channel5
no interface port-channel10
no feature lacp
- block:
- name: setup2
cli_config:
config: |
feature lacp
- name: Merged
nxos_lacp_interfaces: &merged
config:
- name: port-channel10
links:
min: 5
- name: port-channel5
mode: delay
state: merged
register: result
- assert:
that:
- "result.changed == true"
- "result.before|length == 0"
- "'interface port-channel10' in result.commands"
- "'lacp min-links 5' in result.commands"
- "'interface port-channel5' in result.commands"
- "'lacp mode delay' in result.commands"
- "result.commands|length == 4"
- name: Gather lacp_interfaces facts
nxos_facts:
gather_subset:
- '!all'
- '!min'
gather_network_resources: lacp_interfaces
- assert:
that:
- "ansible_facts.network_resources.lacp_interfaces|symmetric_difference(result.after)|length == 0"
- name: Idempotence - Merged
nxos_lacp_interfaces: *merged
register: result
- assert:
that:
- "result.changed == false"
- "result.commands|length == 0"
always:
- name: teardown
cli_config: *cleanup

@ -0,0 +1,68 @@
---
- debug:
msg: "Start nxos_lacp_interfaces overridden integration tests connection={{ ansible_connection }}"
- name: setup1
cli_config: &cleanup
config: |
no interface port-channel5
no interface port-channel10
no interface port-channel11
no feature lacp
- block:
- name: setup2
cli_config:
config: |
feature lacp
interface port-channel10
lacp min-links 5
interface port-channel5
lacp max-bundle 10
- name: Gather lacp_interfaces facts
nxos_facts: &facts
gather_subset:
- '!all'
- '!min'
gather_network_resources: lacp_interfaces
- name: Overridden
nxos_lacp_interfaces: &overridden
config:
- name: port-channel11
mode: delay
state: overridden
register: result
- assert:
that:
- "ansible_facts.network_resources.lacp_interfaces|symmetric_difference(result.before)|length == 0"
- "result.changed == true"
- "'interface port-channel10' in result.commands"
- "'no lacp min-links' in result.commands"
- "'interface port-channel5' in result.commands"
- "'no lacp max-bundle' in result.commands"
- "'interface port-channel11' in result.commands"
- "'lacp mode delay' in result.commands"
- "result.commands|length == 6"
- name: Gather lacp_interfaces post facts
nxos_facts: *facts
- assert:
that:
- "ansible_facts.network_resources.lacp_interfaces|symmetric_difference(result.after)|length == 0"
- name: Idempotence - Overridden
nxos_lacp_interfaces: *overridden
register: result
- assert:
that:
- "result.changed == false"
- "result.commands|length == 0"
always:
- name: teardown
cli_config: *cleanup

@ -0,0 +1,62 @@
---
- debug:
msg: "Start nxos_lacp_interfaces replaced integration tests connection={{ ansible_connection }}"
- name: setup1
cli_config: &cleanup
config: |
no interface port-channel10
no feature lacp
- block:
- name: setup2
cli_config:
config: |
feature lacp
interface port-channel10
lacp min-links 5
- name: Gather lacp_interfaces facts
nxos_facts: &facts
gather_subset:
- '!all'
- '!min'
gather_network_resources: lacp_interfaces
- name: Replaced
nxos_lacp_interfaces: &replaced
config:
- name: port-channel10
links:
max: 10
state: replaced
register: result
- assert:
that:
- "ansible_facts.network_resources.lacp_interfaces|symmetric_difference(result.before)|length == 0"
- "result.changed == true"
- "'interface port-channel10' in result.commands"
- "'no lacp min-links' in result.commands"
- "'lacp max-bundle 10' in result.commands"
- "result.commands|length == 3"
- name: Gather lacp_interfaces post facts
nxos_facts: *facts
- assert:
that:
- "ansible_facts.network_resources.lacp_interfaces|symmetric_difference(result.after)|length == 0"
- name: Idempotence - Replaced
nxos_lacp_interfaces: *replaced
register: result
- assert:
that:
- "result.changed == false"
- "result.commands|length == 0"
always:
- name: teardown
cli_config: *cleanup
Loading…
Cancel
Save