From b55a54469c23bbec4909eadd5e526ba055ed119f Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Mon, 19 Aug 2019 16:03:29 +0530 Subject: [PATCH] Resource module for ios_vlans (#59640) * ios_vlans resource module * fix shippable error * fix shippable Signed-off-by: Sumit Jaiswal * fix vlans resource * fix facts doc Signed-off-by: Sumit Jaiswal * fix shippable n review * fix test Signed-off-by: Sumit Jaiswal * fix indentation Signed-off-by: Sumit Jaiswal * fix review * fix shebang Signed-off-by: Sumit Jaiswal --- .../network/ios/argspec/facts/facts.py | 4 +- .../network/ios/argspec/vlans/__init__.py | 0 .../network/ios/argspec/vlans/vlans.py | 50 ++ .../network/ios/config/vlans/__init__.py | 0 .../network/ios/config/vlans/vlans.py | 277 +++++++++++ .../module_utils/network/ios/facts/facts.py | 2 + .../network/ios/facts/vlans/__init__.py | 0 .../network/ios/facts/vlans/vlans.py | 144 ++++++ .../module_utils/network/ios/utils/utils.py | 2 +- .../network/ios/{ios_vlan.py => _ios_vlan.py} | 6 +- lib/ansible/modules/network/ios/ios_facts.py | 2 +- lib/ansible/modules/network/ios/ios_vlans.py | 459 ++++++++++++++++++ .../targets/ios_vlans/defaults/main.yaml | 3 + .../targets/ios_vlans/meta/main.yaml | 1 + .../targets/ios_vlans/tasks/cli.yaml | 24 + .../targets/ios_vlans/tasks/main.yaml | 2 + .../ios_vlans/tests/cli/_populate_config.yaml | 10 + .../ios_vlans/tests/cli/_remove_config.yaml | 10 + .../targets/ios_vlans/tests/cli/deleted.yaml | 42 ++ .../targets/ios_vlans/tests/cli/merged.yaml | 54 +++ .../ios_vlans/tests/cli/overridden.yaml | 45 ++ .../targets/ios_vlans/tests/cli/replaced.yaml | 49 ++ .../targets/ios_vlans/vars/main.yaml | 337 +++++++++++++ test/sanity/ignore.txt | 12 +- .../modules/network/ios/test_ios_vlan.py | 10 +- 25 files changed, 1530 insertions(+), 15 deletions(-) create mode 100644 lib/ansible/module_utils/network/ios/argspec/vlans/__init__.py create mode 100644 lib/ansible/module_utils/network/ios/argspec/vlans/vlans.py create mode 100644 lib/ansible/module_utils/network/ios/config/vlans/__init__.py create mode 100644 lib/ansible/module_utils/network/ios/config/vlans/vlans.py create mode 100644 lib/ansible/module_utils/network/ios/facts/vlans/__init__.py create mode 100644 lib/ansible/module_utils/network/ios/facts/vlans/vlans.py rename lib/ansible/modules/network/ios/{ios_vlan.py => _ios_vlan.py} (98%) create mode 100644 lib/ansible/modules/network/ios/ios_vlans.py create mode 100644 test/integration/targets/ios_vlans/defaults/main.yaml create mode 100644 test/integration/targets/ios_vlans/meta/main.yaml create mode 100644 test/integration/targets/ios_vlans/tasks/cli.yaml create mode 100644 test/integration/targets/ios_vlans/tasks/main.yaml create mode 100644 test/integration/targets/ios_vlans/tests/cli/_populate_config.yaml create mode 100644 test/integration/targets/ios_vlans/tests/cli/_remove_config.yaml create mode 100644 test/integration/targets/ios_vlans/tests/cli/deleted.yaml create mode 100644 test/integration/targets/ios_vlans/tests/cli/merged.yaml create mode 100644 test/integration/targets/ios_vlans/tests/cli/overridden.yaml create mode 100644 test/integration/targets/ios_vlans/tests/cli/replaced.yaml create mode 100644 test/integration/targets/ios_vlans/vars/main.yaml diff --git a/lib/ansible/module_utils/network/ios/argspec/facts/facts.py b/lib/ansible/module_utils/network/ios/argspec/facts/facts.py index 00bc062b0f2..dcc22b347cd 100644 --- a/lib/ansible/module_utils/network/ios/argspec/facts/facts.py +++ b/lib/ansible/module_utils/network/ios/argspec/facts/facts.py @@ -24,7 +24,9 @@ class FactsArgs(object): 'interfaces', '!interfaces', 'l2_interfaces', - '!l2_interfaces' + '!l2_interfaces', + 'vlans', + '!vlans', ] argument_spec = { diff --git a/lib/ansible/module_utils/network/ios/argspec/vlans/__init__.py b/lib/ansible/module_utils/network/ios/argspec/vlans/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/lib/ansible/module_utils/network/ios/argspec/vlans/vlans.py b/lib/ansible/module_utils/network/ios/argspec/vlans/vlans.py new file mode 100644 index 00000000000..893904cfe74 --- /dev/null +++ b/lib/ansible/module_utils/network/ios/argspec/vlans/vlans.py @@ -0,0 +1,50 @@ +# +# -*- 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 ios_vlans module +""" + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +class VlansArgs(object): + """The arg spec for the ios_vlans module + """ + + def __init__(self, **kwargs): + pass + + argument_spec = {'config': {'elements': 'dict', + 'options': {'name': {'type': 'str'}, + 'vlan_id': {'required': True, 'type': 'int'}, + 'mtu': {'type': 'int'}, + 'remote_span': {'type': 'bool'}, + 'state': {'type': 'str', 'choices': ['active', 'suspend']}, + 'shutdown': {'type': 'str', 'choices': ['enabled', 'disabled']}}, + 'type': 'list'}, + 'state': {'choices': ['merged', 'replaced', 'overridden', 'deleted'], + 'default': 'merged', + 'type': 'str'}} diff --git a/lib/ansible/module_utils/network/ios/config/vlans/__init__.py b/lib/ansible/module_utils/network/ios/config/vlans/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/lib/ansible/module_utils/network/ios/config/vlans/vlans.py b/lib/ansible/module_utils/network/ios/config/vlans/vlans.py new file mode 100644 index 00000000000..6b1d90a9f05 --- /dev/null +++ b/lib/ansible/module_utils/network/ios/config/vlans/vlans.py @@ -0,0 +1,277 @@ +# +# -*- 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 ios_vlans 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 +from ansible.module_utils.network.ios.facts.facts import Facts +from ansible.module_utils.network.ios.utils.utils import dict_to_set + + +class Vlans(ConfigBase): + """ + The ios_vlans class + """ + + gather_subset = [ + '!all', + '!min', + ] + + gather_network_resources = [ + 'vlans', + ] + + def __init__(self, module): + super(Vlans, self).__init__(module) + + def get_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) + interfaces_facts = facts['ansible_network_resources'].get('vlans') + if not interfaces_facts: + return [] + return 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_interfaces_facts = self.get_interfaces_facts() + commands.extend(self.set_config(existing_interfaces_facts)) + if commands: + if not self._module.check_mode: + self._connection.edit_config(commands) + result['changed'] = True + result['commands'] = commands + + changed_interfaces_facts = self.get_interfaces_facts() + + result['before'] = existing_interfaces_facts + if result['changed']: + result['after'] = changed_interfaces_facts + + result['warnings'] = warnings + return result + + def set_config(self, existing_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 + """ + want = self._module.params['config'] + have = existing_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 == 'overridden': + commands = self._state_overridden(want, have, state) + elif state == 'deleted': + commands = self._state_deleted(want, have, state) + elif state == 'merged': + commands = self._state_merged(want, have) + elif state == 'replaced': + commands = self._state_replaced(want, have) + return commands + + def _state_replaced(self, want, have): + """ The command generator when state is replaced + + :rtype: A list + :returns: the commands necessary to migrate the current configuration + to the desired configuration + """ + commands = [] + + check = False + for each in want: + for every in have: + if every['vlan_id'] == each['vlan_id']: + check = True + break + else: + continue + if check: + commands.extend(self._set_config(each, every)) + else: + commands.extend(self._set_config(each, dict())) + + return commands + + def _state_overridden(self, want, have, state): + """ 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 each in have: + for every in want: + if each['vlan_id'] == every['vlan_id']: + break + else: + # We didn't find a matching desired state, which means we can + # pretend we recieved an empty desired state. + commands.extend(self._clear_config(every, each, state)) + continue + commands.extend(self._set_config(every, each)) + + 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 = [] + + check = False + for each in want: + for every in have: + if each.get('vlan_id') == every.get('vlan_id'): + check = True + break + else: + continue + if check: + commands.extend(self._set_config(each, every)) + else: + commands.extend(self._set_config(each, dict())) + + return commands + + def _state_deleted(self, want, have, state): + """ 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: + check = False + for each in want: + for every in have: + if each.get('vlan_id') == every.get('vlan_id'): + check = True + break + else: + check = False + continue + if check: + commands.extend(self._clear_config(each, every, state)) + else: + for each in have: + commands.extend(self._clear_config(dict(), each, state)) + + return commands + + def remove_command_from_config_list(self, vlan, cmd, commands): + if vlan not in commands and cmd != 'vlan': + commands.insert(0, vlan) + elif cmd == 'vlan': + commands.append('no %s' % vlan) + return commands + commands.append('no %s' % cmd) + return commands + + def add_command_to_config_list(self, vlan_id, cmd, commands): + if vlan_id not in commands: + commands.insert(0, vlan_id) + if cmd not in commands: + commands.append(cmd) + + def _set_config(self, want, have): + # Set the interface config based on the want and have config + commands = [] + vlan = 'vlan {0}'.format(want.get('vlan_id')) + + # Get the diff b/w want n have + want_dict = dict_to_set(want) + have_dict = dict_to_set(have) + diff = want_dict - have_dict + + if diff: + name = dict(diff).get('name') + state = dict(diff).get('state') + shutdown = dict(diff).get('shutdown') + mtu = dict(diff).get('mtu') + remote_span = dict(diff).get('remote_span') + if name: + cmd = 'name {0}'.format(name) + self.add_command_to_config_list(vlan, cmd, commands) + if state: + cmd = 'state {0}'.format(state) + self.add_command_to_config_list(vlan, cmd, commands) + if mtu: + cmd = 'mtu {0}'.format(mtu) + self.add_command_to_config_list(vlan, cmd, commands) + if remote_span: + self.add_command_to_config_list(vlan, 'remote-span', commands) + if shutdown == 'enabled': + self.add_command_to_config_list(vlan, 'shutdown', commands) + elif shutdown == 'disabled': + self.add_command_to_config_list(vlan, 'no shutdown', commands) + + return commands + + def _clear_config(self, want, have, state): + # Delete the interface config based on the want and have config + commands = [] + vlan = 'vlan {0}'.format(have.get('vlan_id')) + + if have.get('vlan_id') and 'default' not in have.get('name')\ + and (have.get('vlan_id') != want.get('vlan_id') or state == 'deleted'): + self.remove_command_from_config_list(vlan, 'vlan', commands) + elif 'default' not in have.get('name'): + if have.get('mtu') != want.get('mtu'): + self.remove_command_from_config_list(vlan, 'mtu', commands) + if have.get('remote_span') != want.get('remote_span') and want.get('remote_span'): + self.remove_command_from_config_list(vlan, 'remote-span', commands) + if have.get('shutdown') != want.get('shutdown') and want.get('shutdown'): + self.remove_command_from_config_list(vlan, 'shutdown', commands) + if have.get('state') != want.get('state') and want.get('state'): + self.remove_command_from_config_list(vlan, 'state', commands) + + return commands diff --git a/lib/ansible/module_utils/network/ios/facts/facts.py b/lib/ansible/module_utils/network/ios/facts/facts.py index a8a9eae7934..37f31cdcf5e 100644 --- a/lib/ansible/module_utils/network/ios/facts/facts.py +++ b/lib/ansible/module_utils/network/ios/facts/facts.py @@ -17,6 +17,7 @@ from ansible.module_utils.network.ios.argspec.facts.facts import FactsArgs from ansible.module_utils.network.common.facts.facts import FactsBase from ansible.module_utils.network.ios.facts.interfaces.interfaces import InterfacesFacts from ansible.module_utils.network.ios.facts.l2_interfaces.l2_interfaces import L2_InterfacesFacts +from ansible.module_utils.network.ios.facts.vlans.vlans import VlansFacts from ansible.module_utils.network.ios.facts.legacy.base import Default, Hardware, Interfaces, Config @@ -30,6 +31,7 @@ FACT_LEGACY_SUBSETS = dict( FACT_RESOURCE_SUBSETS = dict( interfaces=InterfacesFacts, l2_interfaces=L2_InterfacesFacts, + vlans=VlansFacts ) diff --git a/lib/ansible/module_utils/network/ios/facts/vlans/__init__.py b/lib/ansible/module_utils/network/ios/facts/vlans/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/lib/ansible/module_utils/network/ios/facts/vlans/vlans.py b/lib/ansible/module_utils/network/ios/facts/vlans/vlans.py new file mode 100644 index 00000000000..0450ad9a398 --- /dev/null +++ b/lib/ansible/module_utils/network/ios/facts/vlans/vlans.py @@ -0,0 +1,144 @@ +# +# -*- 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 ios vlans 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 copy import deepcopy +from ansible.module_utils.network.common import utils +from ansible.module_utils.network.ios.argspec.vlans.vlans import VlansArgs + + +class VlansFacts(object): + """ The ios vlans fact class + """ + + def __init__(self, module, subspec='config', options='options'): + self._module = module + self.argument_spec = VlansArgs.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 vlans + :param connection: the device connection + :param ansible_facts: Facts dictionary + :param data: previously collected conf + :rtype: dictionary + :returns: facts + """ + if connection: + pass + + objs = [] + mtu_objs = [] + remote_objs = [] + final_objs = [] + if not data: + data = connection.get('show vlan') + # operate on a collection of resource x + config = data.split('\n') + # Get individual vlan configs separately + vlan_info = '' + for conf in config: + if 'Name' in conf: + vlan_info = 'Name' + elif 'Type' in conf: + vlan_info = 'Type' + elif 'Remote' in conf: + vlan_info = 'Remote' + if conf and ' ' not in filter(None, conf.split('-')): + obj = self.render_config(self.generated_spec, conf, vlan_info) + if 'mtu' in obj: + mtu_objs.append(obj) + elif 'remote_span' in obj: + remote_objs = obj + elif obj: + objs.append(obj) + # Appending MTU value to the retrieved dictionary + for o, m in zip(objs, mtu_objs): + o.update(m) + final_objs.append(o) + + # Appending Remote Span value to related VLAN: + if remote_objs: + if remote_objs.get('remote_span'): + for each in remote_objs.get('remote_span'): + for every in final_objs: + if each == every.get('vlan_id'): + every.update({'remote_span': True}) + break + + facts = {} + if final_objs: + facts['vlans'] = [] + params = utils.validate_config(self.argument_spec, {'config': objs}) + + for cfg in params['config']: + facts['vlans'].append(utils.remove_empties(cfg)) + ansible_facts['ansible_network_resources'].update(facts) + + return ansible_facts + + def render_config(self, spec, conf, vlan_info): + """ + 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) + + if vlan_info == 'Name' and 'Name' not in conf: + conf = filter(None, conf.split(' ')) + config['vlan_id'] = int(conf[0]) + config['name'] = conf[1] + if len(conf[2].split('/')) > 1: + if conf[2].split('/')[0] == 'sus': + config['state'] = 'suspend' + elif conf[2].split('/')[0] == 'act': + config['state'] = 'active' + config['shutdown'] = 'enabled' + else: + if conf[2] == 'suspended': + config['state'] = 'suspend' + elif conf[2] == 'active': + config['state'] = 'active' + config['shutdown'] = 'disabled' + elif vlan_info == 'Type' and 'Type' not in conf: + conf = filter(None, conf.split(' ')) + config['mtu'] = int(conf[3]) + elif vlan_info == 'Remote': + if len(conf.split(',')) > 1 or conf.isdigit(): + remote_span_vlan = [] + if len(conf.split(',')) > 1: + remote_span_vlan = conf.split(',') + else: + remote_span_vlan.append(conf) + remote_span = [] + for each in remote_span_vlan: + remote_span.append(int(each)) + config['remote_span'] = remote_span + + return utils.remove_empties(config) diff --git a/lib/ansible/module_utils/network/ios/utils/utils.py b/lib/ansible/module_utils/network/ios/utils/utils.py index 16a05602e65..6ce572d6152 100644 --- a/lib/ansible/module_utils/network/ios/utils/utils.py +++ b/lib/ansible/module_utils/network/ios/utils/utils.py @@ -39,7 +39,7 @@ def dict_to_set(sample_dict): for key, value in iteritems(each): if isinstance(value, list): each[key] = tuple(value) - li.extend(tuple(each.items())) + li.append(tuple(each.items())) v = tuple(li) else: v = tuple(v) diff --git a/lib/ansible/modules/network/ios/ios_vlan.py b/lib/ansible/modules/network/ios/_ios_vlan.py similarity index 98% rename from lib/ansible/modules/network/ios/ios_vlan.py rename to lib/ansible/modules/network/ios/_ios_vlan.py index a7005da377b..d2b3dcf043b 100644 --- a/lib/ansible/modules/network/ios/ios_vlan.py +++ b/lib/ansible/modules/network/ios/_ios_vlan.py @@ -9,7 +9,7 @@ __metaclass__ = type ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], + 'status': ['deprecated'], 'supported_by': 'network'} DOCUMENTATION = """ @@ -21,6 +21,10 @@ short_description: Manage VLANs on IOS network devices description: - This module provides declarative management of VLANs on Cisco IOS network devices. +deprecated: + removed_in: '2.13' + alternative: ios_vlans + why: Newer and updated modules released with more functionality in Ansible 2.9 notes: - Tested against IOS 15.2 options: diff --git a/lib/ansible/modules/network/ios/ios_facts.py b/lib/ansible/modules/network/ios/ios_facts.py index 7bf72fdef20..bc75d1886f9 100644 --- a/lib/ansible/modules/network/ios/ios_facts.py +++ b/lib/ansible/modules/network/ios/ios_facts.py @@ -54,7 +54,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', '!all', 'interfaces', '!interfaces', 'l2_interfaces', '!l2_interfaces'] + choices: ['all', '!all', 'interfaces', '!interfaces', 'l2_interfaces', '!l2_interfaces', 'vlans', '!vlans'] version_added: "2.9" """ diff --git a/lib/ansible/modules/network/ios/ios_vlans.py b/lib/ansible/modules/network/ios/ios_vlans.py new file mode 100644 index 00000000000..a716f493621 --- /dev/null +++ b/lib/ansible/modules/network/ios/ios_vlans.py @@ -0,0 +1,459 @@ +#!/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 ios_vlans +""" + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +ANSIBLE_METADATA = { + 'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'network' +} + +DOCUMENTATION = """ +module: ios_vlans +version_added: 2.9 +short_description: Manage VLANs on Cisco IOS devices. +description: This module provides declarative management of VLANs on Cisco IOS network devices. +author: Sumit Jaiswal (@justjais) +notes: + - Tested against Cisco IOSv Version 15.2 on VIRL + - This module works with connection C(network_cli). + See L(IOS Platform Options,../network/user_guide/platform_ios.html). +options: + config: + description: A dictionary of VLANs options + type: list + elements: dict + suboptions: + name: + description: + - Ascii name of the VLAN. + - NOTE, I(name) should not be named/appended with I(default) as it is reserved for device default vlans. + type: str + vlan_id: + description: + - ID of the VLAN. Range 1-4094 + type: int + required: True + mtu: + description: + - VLAN Maximum Transmission Unit. + - Refer to vendor documentation for valid values. + type: int + state: + description: + - Operational state of the VLAN + type: str + choices: + - active + - suspend + remote_span: + description: + - Configure as Remote SPAN VLAN + type: bool + shutdown: + description: + - Shutdown VLAN switching. + type: str + choices: + - enabled + - disabled + state: + description: + - The state the configuration should be left in + type: str + choices: + - merged + - replaced + - overridden + - deleted + default: merged +""" +EXAMPLES = """ +--- +# Using merged + +# Before state: +# ------------- +# +# vios#show vlan +# VLAN Name Status Ports +# ---- -------------------------------- --------- ------------------------------- +# 1 default active Gi0/1, Gi0/2 +# 1002 fddi-default act/unsup +# 1003 token-ring-default act/unsup +# 1004 fddinet-default act/unsup +# 1005 trnet-default act/unsup +# +# VLAN Type SAID MTU Parent RingNo BridgeNo Stp BrdgMode Trans1 Trans2 +# ---- ----- ---------- ----- ------ ------ -------- ---- -------- ------ ------ +# 1 enet 100001 1500 - - - - - 0 0 +# 1002 fddi 101002 1500 - - - - - 0 0 +# 1003 tr 101003 1500 - - - - - 0 0 +# 1004 fdnet 101004 1500 - - - ieee - 0 0 +# 1005 trnet 101005 1500 - - - ibm - 0 0 + +- name: Merge provided configuration with device configuration + ios_vlans: + config: + - name: Vlan_10 + vlan_id: 10 + state: active + shutdown: disabled + remote_span: 10 + - name: Vlan_20 + vlan_id: 20 + mtu: 610 + state: active + shutdown: enabled + - name: Vlan_30 + vlan_id: 30 + state: suspend + shutdown: enabled + state: merged + +# After state: +# ------------ +# +# vios#show vlan +# VLAN Name Status Ports +# ---- -------------------------------- --------- ------------------------------- +# 1 default active Gi0/1, Gi0/2 +# 10 vlan_10 active +# 20 vlan_20 act/lshut +# 30 vlan_30 sus/lshut +# 1002 fddi-default act/unsup +# 1003 token-ring-default act/unsup +# 1004 fddinet-default act/unsup +# 1005 trnet-default act/unsup +# +# VLAN Type SAID MTU Parent RingNo BridgeNo Stp BrdgMode Trans1 Trans2 +# ---- ----- ---------- ----- ------ ------ -------- ---- -------- ------ ------ +# 1 enet 100001 1500 - - - - - 0 0 +# 10 enet 100010 1500 - - - - - 0 0 +# 20 enet 100020 610 - - - - - 0 0 +# 30 enet 100030 1500 - - - - - 0 0 +# 1002 fddi 101002 1500 - - - - - 0 0 +# 1003 tr 101003 1500 - - - - - 0 0 +# 1004 fdnet 101004 1500 - - - ieee - 0 0 +# 1005 trnet 101005 1500 - - - ibm - 0 0 +# +# Remote SPAN VLANs +# ------------------------------------------------------------------------------ +# 10 + +# Using overridden + +# Before state: +# ------------- +# +# vios#show vlan +# VLAN Name Status Ports +# ---- -------------------------------- --------- ------------------------------- +# 1 default active Gi0/1, Gi0/2 +# 10 vlan_10 active +# 20 vlan_20 act/lshut +# 30 vlan_30 sus/lshut +# 1002 fddi-default act/unsup +# 1003 token-ring-default act/unsup +# 1004 fddinet-default act/unsup +# 1005 trnet-default act/unsup +# +# VLAN Type SAID MTU Parent RingNo BridgeNo Stp BrdgMode Trans1 Trans2 +# ---- ----- ---------- ----- ------ ------ -------- ---- -------- ------ ------ +# 1 enet 100001 1500 - - - - - 0 0 +# 10 enet 100010 1500 - - - - - 0 0 +# 20 enet 100020 610 - - - - - 0 0 +# 30 enet 100030 1500 - - - - - 0 0 +# 1002 fddi 101002 1500 - - - - - 0 0 +# 1003 tr 101003 1500 - - - - - 0 0 +# 1004 fdnet 101004 1500 - - - ieee - 0 0 +# 1005 trnet 101005 1500 - - - ibm - 0 0 +# +# Remote SPAN VLANs +# ------------------------------------------------------------------------------ +# 10 + +- name: Override device configuration of all VLANs with provided configuration + ios_vlans: + config: + - name: Vlan_10 + vlan_id: 10 + mtu: 1000 + state: overridden + +# After state: +# ------------ +# +# vios#show vlan +# VLAN Name Status Ports +# ---- -------------------------------- --------- ------------------------------- +# 10 Vlan_10 active +# +# VLAN Type SAID MTU Parent RingNo BridgeNo Stp BrdgMode Trans1 Trans2 +# ---- ----- ---------- ----- ------ ------ -------- ---- -------- ------ ------ +# 10 enet 100010 1000 - - - - - 0 0 + +# Using replaced + +# Before state: +# ------------- +# +# vios#show vlan +# VLAN Name Status Ports +# ---- -------------------------------- --------- ------------------------------- +# 1 default active Gi0/1, Gi0/2 +# 10 vlan_10 active +# 20 vlan_20 act/lshut +# 30 vlan_30 sus/lshut +# 1002 fddi-default act/unsup +# 1003 token-ring-default act/unsup +# 1004 fddinet-default act/unsup +# 1005 trnet-default act/unsup +# +# VLAN Type SAID MTU Parent RingNo BridgeNo Stp BrdgMode Trans1 Trans2 +# ---- ----- ---------- ----- ------ ------ -------- ---- -------- ------ ------ +# 1 enet 100001 1500 - - - - - 0 0 +# 10 enet 100010 1500 - - - - - 0 0 +# 20 enet 100020 610 - - - - - 0 0 +# 30 enet 100030 1500 - - - - - 0 0 +# 1002 fddi 101002 1500 - - - - - 0 0 +# 1003 tr 101003 1500 - - - - - 0 0 +# 1004 fdnet 101004 1500 - - - ieee - 0 0 +# 1005 trnet 101005 1500 - - - ibm - 0 0 +# +# Remote SPAN VLANs +# ------------------------------------------------------------------------------ +# 10 + +- name: Replaces device configuration of listed VLANs with provided configuration + ios_vlans: + config: + - vlan_id: 20 + name: Test_VLAN20 + mtu: 700 + shutdown: disabled + - vlan_id: 30 + name: Test_VLAN30 + mtu: 1000 + state: replaced + +# After state: +# ------------ +# +# vios#show vlan +# VLAN Name Status Ports +# ---- -------------------------------- --------- ------------------------------- +# 1 default active Gi0/1, Gi0/2 +# 10 vlan_10 active +# 20 Test_VLAN20 active +# 30 Test_VLAN30 sus/lshut +# 1002 fddi-default act/unsup +# 1003 token-ring-default act/unsup +# 1004 fddinet-default act/unsup +# 1005 trnet-default act/unsup +# +# VLAN Type SAID MTU Parent RingNo BridgeNo Stp BrdgMode Trans1 Trans2 +# ---- ----- ---------- ----- ------ ------ -------- ---- -------- ------ ------ +# 1 enet 100001 1500 - - - - - 0 0 +# 10 enet 100010 1500 - - - - - 0 0 +# 20 enet 100020 700 - - - - - 0 0 +# 30 enet 100030 1000 - - - - - 0 0 +# 1002 fddi 101002 1500 - - - - - 0 0 +# 1003 tr 101003 1500 - - - - - 0 0 +# 1004 fdnet 101004 1500 - - - ieee - 0 0 +# 1005 trnet 101005 1500 - - - ibm - 0 0 +# +# Remote SPAN VLANs +# ------------------------------------------------------------------------------ +# 10 + +# Using deleted + +# Before state: +# ------------- +# +# vios#show vlan +# VLAN Name Status Ports +# ---- -------------------------------- --------- ------------------------------- +# 1 default active Gi0/1, Gi0/2 +# 10 vlan_10 active +# 20 vlan_20 act/lshut +# 30 vlan_30 sus/lshut +# 1002 fddi-default act/unsup +# 1003 token-ring-default act/unsup +# 1004 fddinet-default act/unsup +# 1005 trnet-default act/unsup +# +# VLAN Type SAID MTU Parent RingNo BridgeNo Stp BrdgMode Trans1 Trans2 +# ---- ----- ---------- ----- ------ ------ -------- ---- -------- ------ ------ +# 1 enet 100001 1500 - - - - - 0 0 +# 10 enet 100010 1500 - - - - - 0 0 +# 20 enet 100020 610 - - - - - 0 0 +# 30 enet 100030 1500 - - - - - 0 0 +# 1002 fddi 101002 1500 - - - - - 0 0 +# 1003 tr 101003 1500 - - - - - 0 0 +# 1004 fdnet 101004 1500 - - - ieee - 0 0 +# 1005 trnet 101005 1500 - - - ibm - 0 0 +# +# Remote SPAN VLANs +# ------------------------------------------------------------------------------ +# 10 + +- name: Delete attributes of given VLANs + ios_vlans: + config: + - vlan_id: 10 + - vlan_id: 20 + state: deleted + +# After state: +# ------------- +# +# vios#show vlan +# VLAN Name Status Ports +# ---- -------------------------------- --------- ------------------------------- +# 1 default active Gi0/1, Gi0/2 +# 30 vlan_30 sus/lshut +# 1002 fddi-default act/unsup +# 1003 token-ring-default act/unsup +# 1004 fddinet-default act/unsup +# 1005 trnet-default act/unsup +# +# VLAN Type SAID MTU Parent RingNo BridgeNo Stp BrdgMode Trans1 Trans2 +# ---- ----- ---------- ----- ------ ------ -------- ---- -------- ------ ------ +# 1 enet 100001 1500 - - - - - 0 0 +# 30 enet 100030 1500 - - - - - 0 0 +# 1002 fddi 101002 1500 - - - - - 0 0 +# 1003 tr 101003 1500 - - - - - 0 0 +# 1004 fdnet 101004 1500 - - - ieee - 0 0 +# 1005 trnet 101005 1500 - - - ibm - 0 0 + +# Using Deleted without any config passed +#"(NOTE: This will delete all of configured vlans attributes)" + +# Before state: +# ------------- +# +# vios#show vlan +# VLAN Name Status Ports +# ---- -------------------------------- --------- ------------------------------- +# 1 default active Gi0/1, Gi0/2 +# 10 vlan_10 active +# 20 vlan_20 act/lshut +# 30 vlan_30 sus/lshut +# 1002 fddi-default act/unsup +# 1003 token-ring-default act/unsup +# 1004 fddinet-default act/unsup +# 1005 trnet-default act/unsup +# +# VLAN Type SAID MTU Parent RingNo BridgeNo Stp BrdgMode Trans1 Trans2 +# ---- ----- ---------- ----- ------ ------ -------- ---- -------- ------ ------ +# 1 enet 100001 1500 - - - - - 0 0 +# 10 enet 100010 1500 - - - - - 0 0 +# 20 enet 100020 610 - - - - - 0 0 +# 30 enet 100030 1500 - - - - - 0 0 +# 1002 fddi 101002 1500 - - - - - 0 0 +# 1003 tr 101003 1500 - - - - - 0 0 +# 1004 fdnet 101004 1500 - - - ieee - 0 0 +# 1005 trnet 101005 1500 - - - ibm - 0 0 +# +# Remote SPAN VLANs +# ------------------------------------------------------------------------------ +# 10 + +- name: Delete attributes of ALL VLANs + ios_vlans: + state: deleted + +# After state: +# ------------- +# +# vios#show vlan +# VLAN Name Status Ports +# ---- -------------------------------- --------- ------------------------------- +# 1 default active Gi0/1, Gi0/2 +# 1002 fddi-default act/unsup +# 1003 token-ring-default act/unsup +# 1004 fddinet-default act/unsup +# 1005 trnet-default act/unsup +# +# VLAN Type SAID MTU Parent RingNo BridgeNo Stp BrdgMode Trans1 Trans2 +# ---- ----- ---------- ----- ------ ------ -------- ---- -------- ------ ------ +# 1 enet 100001 1500 - - - - - 0 0 +# 1002 fddi 101002 1500 - - - - - 0 0 +# 1003 tr 101003 1500 - - - - - 0 0 +# 1004 fdnet 101004 1500 - - - ieee - 0 0 +# 1005 trnet 101005 1500 - - - ibm - 0 0 + +""" +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: ['vlan 20', 'name vlan_20', 'mtu 600', 'remote-span'] +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.network.ios.argspec.vlans.vlans import VlansArgs +from ansible.module_utils.network.ios.config.vlans.vlans import Vlans + + +def main(): + """ + Main entry point for module execution + + :returns: the result form module invocation + """ + module = AnsibleModule(argument_spec=VlansArgs.argument_spec, + supports_check_mode=True) + + result = Vlans(module).execute_module() + module.exit_json(**result) + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/ios_vlans/defaults/main.yaml b/test/integration/targets/ios_vlans/defaults/main.yaml new file mode 100644 index 00000000000..164afead284 --- /dev/null +++ b/test/integration/targets/ios_vlans/defaults/main.yaml @@ -0,0 +1,3 @@ +--- +testcase: "[^_].*" +test_items: [] diff --git a/test/integration/targets/ios_vlans/meta/main.yaml b/test/integration/targets/ios_vlans/meta/main.yaml new file mode 100644 index 00000000000..32cf5dda7ed --- /dev/null +++ b/test/integration/targets/ios_vlans/meta/main.yaml @@ -0,0 +1 @@ +dependencies: [] diff --git a/test/integration/targets/ios_vlans/tasks/cli.yaml b/test/integration/targets/ios_vlans/tasks/cli.yaml new file mode 100644 index 00000000000..55d04130400 --- /dev/null +++ b/test/integration/targets/ios_vlans/tasks/cli.yaml @@ -0,0 +1,24 @@ +--- +- 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 }}" + delegate_to: localhost + +- name: Get the IOS version + ios_facts: + gather_subset: all + +- name: Run test case (connection=network_cli) + include: "{{ test_case_to_run }}" + vars: + ansible_connection: network_cli + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run diff --git a/test/integration/targets/ios_vlans/tasks/main.yaml b/test/integration/targets/ios_vlans/tasks/main.yaml new file mode 100644 index 00000000000..415c99d8b12 --- /dev/null +++ b/test/integration/targets/ios_vlans/tasks/main.yaml @@ -0,0 +1,2 @@ +--- +- { include: cli.yaml, tags: ['cli'] } diff --git a/test/integration/targets/ios_vlans/tests/cli/_populate_config.yaml b/test/integration/targets/ios_vlans/tests/cli/_populate_config.yaml new file mode 100644 index 00000000000..c8c7402ee5b --- /dev/null +++ b/test/integration/targets/ios_vlans/tests/cli/_populate_config.yaml @@ -0,0 +1,10 @@ +--- +- name: Setup + cli_config: + config: "{{ lines }}" + vars: + lines: | + vlan 10 + vlan 20 + vlan 30 + when: ansible_net_version != "15.6(2)T" diff --git a/test/integration/targets/ios_vlans/tests/cli/_remove_config.yaml b/test/integration/targets/ios_vlans/tests/cli/_remove_config.yaml new file mode 100644 index 00000000000..ca4953bf152 --- /dev/null +++ b/test/integration/targets/ios_vlans/tests/cli/_remove_config.yaml @@ -0,0 +1,10 @@ +--- +- name: Remove Config + cli_config: + config: "{{ lines }}" + vars: + lines: | + no vlan 10 + no vlan 20 + no vlan 30 + when: ansible_net_version != "15.6(2)T" diff --git a/test/integration/targets/ios_vlans/tests/cli/deleted.yaml b/test/integration/targets/ios_vlans/tests/cli/deleted.yaml new file mode 100644 index 00000000000..99ca146fd51 --- /dev/null +++ b/test/integration/targets/ios_vlans/tests/cli/deleted.yaml @@ -0,0 +1,42 @@ +--- +- debug: + msg: "Start Deleted integration state for ios_vlans ansible_connection={{ ansible_connection }}" + +- include_tasks: _remove_config.yaml + +- include_tasks: _populate_config.yaml + +- block: + - name: Delete VLANs attributes for all configured VLANs + ios_vlans: &deleted + state: deleted + register: result + + - name: Assert that correct set of commands were generated + assert: + that: + - "{{ deleted['commands'] | symmetric_difference(result['commands']) | length == 0 }}" + + - name: Assert that before dicts are correctly generated + assert: + that: + - "{{ deleted['before'] | symmetric_difference(result['before']) | length == 0 }}" + + - name: Assert that after dict is correctly generated + assert: + that: + - "{{ deleted['after'] | symmetric_difference(result['after']) | length == 0 }}" + + - name: Delete VLANs attributes for all configured VLANs (IDEMPOTENT) + ios_vlans: *deleted + register: result + + - name: Assert that the previous task was idempotent + assert: + that: + - "result.changed == false" + + when: ansible_net_version != "15.6(2)T" + + always: + - include_tasks: _remove_config.yaml diff --git a/test/integration/targets/ios_vlans/tests/cli/merged.yaml b/test/integration/targets/ios_vlans/tests/cli/merged.yaml new file mode 100644 index 00000000000..05cb9014a65 --- /dev/null +++ b/test/integration/targets/ios_vlans/tests/cli/merged.yaml @@ -0,0 +1,54 @@ +--- +- debug: + msg: "START Merged ios_vlans state for integration tests on connection={{ ansible_connection }}" + +- include_tasks: _remove_config.yaml + +- block: + - name: Merge provided configuration with device configuration + ios_vlans: &merged + config: + - name: Vlan_10 + vlan_id: 10 + state: active + shutdown: disabled + remote_span: 10 + - name: Vlan_20 + vlan_id: 20 + mtu: 610 + state: active + shutdown: enabled + - name: Vlan_30 + vlan_id: 30 + state: suspend + shutdown: enabled + state: merged + register: result + + - name: Assert that correct set of commands were generated + assert: + that: + - "{{ merged['commands'] | symmetric_difference(result['commands']) | length == 0 }}" + + - name: Assert that before dicts are correctly generated + assert: + that: + - "{{ merged['before'] | symmetric_difference(result['before']) | length == 0 }}" + + - name: Assert that after dict is correctly generated + assert: + that: + - "{{ merged['after'] | symmetric_difference(result['after']) | length == 0 }}" + + - name: Merge provided configuration with device configuration (IDEMPOTENT) + ios_vlans: *merged + register: result + + - name: Assert that the previous task was idempotent + assert: + that: + - "result['changed'] == false" + when: ansible_net_version != "15.6(2)T" + + always: + - include_tasks: _remove_config.yaml diff --git a/test/integration/targets/ios_vlans/tests/cli/overridden.yaml b/test/integration/targets/ios_vlans/tests/cli/overridden.yaml new file mode 100644 index 00000000000..c1395cac87f --- /dev/null +++ b/test/integration/targets/ios_vlans/tests/cli/overridden.yaml @@ -0,0 +1,45 @@ +--- +- debug: + msg: "START Overridden ios_vlans state for integration tests on connection={{ ansible_connection }}" + +- include_tasks: _remove_config.yaml + +- include_tasks: _populate_config.yaml + +- block: + - name: Override device configuration of all VLANs with provided configuration + ios_vlans: &overridden + config: + - name: VLAN_10 + vlan_id: 10 + mtu: 1000 + state: overridden + register: result + + - name: Assert that correct set of commands were generated + assert: + that: + - "{{ overridden['commands'] | symmetric_difference(result['commands']) | length == 0 }}" + + - name: Assert that before dicts are correctly generated + assert: + that: + - "{{ overridden['before'] | symmetric_difference(result['before']) | length == 0 }}" + + - name: Assert that after dict is correctly generated + assert: + that: + - "{{ overridden['after'] | symmetric_difference(result['after']) | length == 0 }}" + + - name: Override device configuration of all interfaces with provided configuration (IDEMPOTENT) + ios_vlans: *overridden + register: result + + - name: Assert that task was idempotent + assert: + that: + - "result['changed'] == false" + when: ansible_net_version != "15.6(2)T" + + always: + - include_tasks: _remove_config.yaml diff --git a/test/integration/targets/ios_vlans/tests/cli/replaced.yaml b/test/integration/targets/ios_vlans/tests/cli/replaced.yaml new file mode 100644 index 00000000000..3fbeef796ce --- /dev/null +++ b/test/integration/targets/ios_vlans/tests/cli/replaced.yaml @@ -0,0 +1,49 @@ +--- +- debug: + msg: "START Replaced ios_vlans state for integration tests on connection={{ ansible_connection }}" + +- include_tasks: _remove_config.yaml + +- include_tasks: _populate_config.yaml + +- block: + - name: Replaces device configuration of listed VLANs with provided configuration + ios_vlans: &replaced + config: + - vlan_id: 20 + name: Test_VLAN20 + mtu: 700 + shutdown: disabled + - vlan_id: 30 + name: Test_VLAN30 + mtu: 1000 + state: replaced + register: result + + - 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: + - "{{ replaced['before'] | symmetric_difference(result['before']) | length == 0 }}" + + - name: Assert that after dict is correctly generated + assert: + that: + - "{{ replaced['after'] | symmetric_difference(result['after']) | length == 0 }}" + + - name: Replaces device configuration of listed interfaces with provided configuration (IDEMPOTENT) + ios_vlans: *replaced + register: result + + - name: Assert that task was idempotent + assert: + that: + - "result['changed'] == false" + when: ansible_net_version != "15.6(2)T" + + always: + - include_tasks: _remove_config.yaml diff --git a/test/integration/targets/ios_vlans/vars/main.yaml b/test/integration/targets/ios_vlans/vars/main.yaml new file mode 100644 index 00000000000..1e6aa17e2ca --- /dev/null +++ b/test/integration/targets/ios_vlans/vars/main.yaml @@ -0,0 +1,337 @@ +--- +merged: + before: + - mtu: 1500 + name: default + shutdown: disabled + state: active + vlan_id: 1 + - mtu: 1500 + name: fddi-default + shutdown: enabled + state: active + vlan_id: 1002 + - mtu: 1500 + name: token-ring-default + shutdown: enabled + state: active + vlan_id: 1003 + - mtu: 1500 + name: fddinet-default + shutdown: enabled + state: active + vlan_id: 1004 + - mtu: 1500 + name: trnet-default + shutdown: enabled + state: active + vlan_id: 1005 + + commands: + - "vlan 10" + - "name Vlan_10" + - "state active" + - "remote-span" + - "no shutdown" + - "vlan 20" + - "name Vlan_20" + - "state active" + - "mtu 610" + - "shutdown" + - "vlan 30" + - "name Vlan_30" + - "state suspend" + - "shutdown" + + after: + - mtu: 1500 + name: default + shutdown: disabled + state: active + vlan_id: 1 + - mtu: 1500 + name: Vlan_10 + remote_span: true + shutdown: disabled + state: active + vlan_id: 10 + - mtu: 610 + name: Vlan_20 + shutdown: enabled + state: active + vlan_id: 20 + - mtu: 1500 + name: Vlan_30 + shutdown: enabled + state: suspend + vlan_id: 30 + - mtu: 1500 + name: fddi-default + shutdown: enabled + state: active + vlan_id: 1002 + - mtu: 1500 + name: token-ring-default + shutdown: enabled + state: active + vlan_id: 1003 + - mtu: 1500 + name: fddinet-default + shutdown: enabled + state: active + vlan_id: 1004 + - mtu: 1500 + name: trnet-default + shutdown: enabled + state: active + vlan_id: 1005 + +replaced: + before: + - mtu: 1500 + name: default + shutdown: disabled + state: active + vlan_id: 1 + - mtu: 1500 + name: VLAN0010 + shutdown: disabled + state: active + vlan_id: 10 + - mtu: 1500 + name: VLAN0020 + shutdown: disabled + state: active + vlan_id: 20 + - mtu: 1500 + name: VLAN0030 + shutdown: disabled + state: active + vlan_id: 30 + - mtu: 1500 + name: fddi-default + shutdown: enabled + state: active + vlan_id: 1002 + - mtu: 1500 + name: token-ring-default + shutdown: enabled + state: active + vlan_id: 1003 + - mtu: 1500 + name: fddinet-default + shutdown: enabled + state: active + vlan_id: 1004 + - mtu: 1500 + name: trnet-default + shutdown: enabled + state: active + vlan_id: 1005 + + commands: + - "vlan 20" + - "name Test_VLAN20" + - "mtu 700" + - "vlan 30" + - "name Test_VLAN30" + - "mtu 1000" + + after: + - mtu: 1500 + name: default + shutdown: disabled + state: active + vlan_id: 1 + - mtu: 1500 + name: VLAN0010 + shutdown: disabled + state: active + vlan_id: 10 + - mtu: 700 + name: Test_VLAN20 + shutdown: disabled + state: active + vlan_id: 20 + - mtu: 1000 + name: Test_VLAN30 + shutdown: disabled + state: active + vlan_id: 30 + - mtu: 1500 + name: fddi-default + shutdown: enabled + state: active + vlan_id: 1002 + - mtu: 1500 + name: token-ring-default + shutdown: enabled + state: active + vlan_id: 1003 + - mtu: 1500 + name: fddinet-default + shutdown: enabled + state: active + vlan_id: 1004 + - mtu: 1500 + name: trnet-default + shutdown: enabled + state: active + vlan_id: 1005 + +overridden: + before: + - mtu: 1500 + name: default + shutdown: disabled + state: active + vlan_id: 1 + - mtu: 1500 + name: VLAN0010 + shutdown: disabled + state: active + vlan_id: 10 + - mtu: 1500 + name: VLAN0020 + shutdown: disabled + state: active + vlan_id: 20 + - mtu: 1500 + name: VLAN0030 + shutdown: disabled + state: active + vlan_id: 30 + - mtu: 1500 + name: fddi-default + shutdown: enabled + state: active + vlan_id: 1002 + - mtu: 1500 + name: token-ring-default + shutdown: enabled + state: active + vlan_id: 1003 + - mtu: 1500 + name: fddinet-default + shutdown: enabled + state: active + vlan_id: 1004 + - mtu: 1500 + name: trnet-default + shutdown: enabled + state: active + vlan_id: 1005 + + commands: + - "vlan 10" + - "name VLAN_10" + - "mtu 1000" + - "no vlan 20" + - "no vlan 30" + + after: + - mtu: 1500 + name: default + shutdown: disabled + state: active + vlan_id: 1 + - mtu: 1000 + name: VLAN_10 + shutdown: disabled + state: active + vlan_id: 10 + - mtu: 1500 + name: fddi-default + shutdown: enabled + state: active + vlan_id: 1002 + - mtu: 1500 + name: token-ring-default + shutdown: enabled + state: active + vlan_id: 1003 + - mtu: 1500 + name: fddinet-default + shutdown: enabled + state: active + vlan_id: 1004 + - mtu: 1500 + name: trnet-default + shutdown: enabled + state: active + vlan_id: 1005 + +deleted: + before: + - mtu: 1500 + name: default + shutdown: disabled + state: active + vlan_id: 1 + - mtu: 1500 + name: VLAN0010 + shutdown: disabled + state: active + vlan_id: 10 + - mtu: 1500 + name: VLAN0020 + shutdown: disabled + state: active + vlan_id: 20 + - mtu: 1500 + name: VLAN0030 + shutdown: disabled + state: active + vlan_id: 30 + - mtu: 1500 + name: fddi-default + shutdown: enabled + state: active + vlan_id: 1002 + - mtu: 1500 + name: token-ring-default + shutdown: enabled + state: active + vlan_id: 1003 + - mtu: 1500 + name: fddinet-default + shutdown: enabled + state: active + vlan_id: 1004 + - mtu: 1500 + name: trnet-default + shutdown: enabled + state: active + vlan_id: 1005 + + commands: + - "no vlan 10" + - "no vlan 20" + - "no vlan 30" + + after: + - mtu: 1500 + name: default + shutdown: disabled + state: active + vlan_id: 1 + - mtu: 1500 + name: fddi-default + shutdown: enabled + state: active + vlan_id: 1002 + - mtu: 1500 + name: token-ring-default + shutdown: enabled + state: active + vlan_id: 1003 + - mtu: 1500 + name: fddinet-default + shutdown: enabled + state: active + vlan_id: 1004 + - mtu: 1500 + name: trnet-default + shutdown: enabled + state: active + vlan_id: 1005 diff --git a/test/sanity/ignore.txt b/test/sanity/ignore.txt index ac52ed16307..aff7866e038 100644 --- a/test/sanity/ignore.txt +++ b/test/sanity/ignore.txt @@ -4164,12 +4164,12 @@ lib/ansible/modules/network/ios/ios_user.py validate-modules:E326 lib/ansible/modules/network/ios/ios_user.py validate-modules:E337 lib/ansible/modules/network/ios/ios_user.py validate-modules:E338 lib/ansible/modules/network/ios/ios_user.py validate-modules:E340 -lib/ansible/modules/network/ios/ios_vlan.py validate-modules:E322 -lib/ansible/modules/network/ios/ios_vlan.py validate-modules:E324 -lib/ansible/modules/network/ios/ios_vlan.py validate-modules:E326 -lib/ansible/modules/network/ios/ios_vlan.py validate-modules:E337 -lib/ansible/modules/network/ios/ios_vlan.py validate-modules:E338 -lib/ansible/modules/network/ios/ios_vlan.py validate-modules:E340 +lib/ansible/modules/network/ios/_ios_vlan.py validate-modules:E322 +lib/ansible/modules/network/ios/_ios_vlan.py validate-modules:E324 +lib/ansible/modules/network/ios/_ios_vlan.py validate-modules:E326 +lib/ansible/modules/network/ios/_ios_vlan.py validate-modules:E337 +lib/ansible/modules/network/ios/_ios_vlan.py validate-modules:E338 +lib/ansible/modules/network/ios/_ios_vlan.py validate-modules:E340 lib/ansible/modules/network/ios/ios_vrf.py future-import-boilerplate lib/ansible/modules/network/ios/ios_vrf.py metaclass-boilerplate lib/ansible/modules/network/ios/ios_vrf.py validate-modules:E324 diff --git a/test/units/modules/network/ios/test_ios_vlan.py b/test/units/modules/network/ios/test_ios_vlan.py index 3c7974ba8c2..201efd1ad49 100644 --- a/test/units/modules/network/ios/test_ios_vlan.py +++ b/test/units/modules/network/ios/test_ios_vlan.py @@ -20,23 +20,23 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type from units.compat.mock import patch -from ansible.modules.network.ios import ios_vlan -from ansible.modules.network.ios.ios_vlan import parse_vlan_brief +from ansible.modules.network.ios import _ios_vlan +from ansible.modules.network.ios._ios_vlan import parse_vlan_brief from units.modules.utils import set_module_args from .ios_module import TestIosModule, load_fixture class TestIosVlanModule(TestIosModule): - module = ios_vlan + module = _ios_vlan def setUp(self): super(TestIosVlanModule, self).setUp() - self.mock_run_commands = patch('ansible.modules.network.ios.ios_vlan.run_commands') + self.mock_run_commands = patch('ansible.modules.network.ios._ios_vlan.run_commands') self.run_commands = self.mock_run_commands.start() - self.mock_load_config = patch('ansible.modules.network.ios.ios_vlan.load_config') + self.mock_load_config = patch('ansible.modules.network.ios._ios_vlan.load_config') self.load_config = self.mock_load_config.start() def tearDown(self):