summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathaniel Case <ncase@redhat.com>2019-08-19 09:02:38 -0400
committerGitHub <noreply@github.com>2019-08-19 09:02:38 -0400
commit446dcb7c963a3b3cd72410b572f4adb062b56a8e (patch)
tree75222243d7c53b2046640abc84beaa43744f9d13
parent256db658b711d9c15d3e04fd13f130fc507cdd40 (diff)
downloadansible-446dcb7c963a3b3cd72410b572f4adb062b56a8e.tar.gz
New module eos_vlans (#60652)
* Initial commit of module files * Add tests, implement facts * Implement config, fix issues * Handle vlan ranges from the device * Deprecate eos_vlan
-rw-r--r--lib/ansible/module_utils/network/eos/argspec/facts/facts.py2
-rw-r--r--lib/ansible/module_utils/network/eos/argspec/vlans/__init__.py0
-rw-r--r--lib/ansible/module_utils/network/eos/argspec/vlans/vlans.py54
-rw-r--r--lib/ansible/module_utils/network/eos/config/vlans/__init__.py0
-rw-r--r--lib/ansible/module_utils/network/eos/config/vlans/vlans.py208
-rw-r--r--lib/ansible/module_utils/network/eos/facts/facts.py2
-rw-r--r--lib/ansible/module_utils/network/eos/facts/vlans/__init__.py0
-rw-r--r--lib/ansible/module_utils/network/eos/facts/vlans/vlans.py108
-rw-r--r--lib/ansible/modules/network/eos/_eos_vlan.py (renamed from lib/ansible/modules/network/eos/eos_vlan.py)6
-rw-r--r--lib/ansible/modules/network/eos/eos_facts.py2
-rw-r--r--lib/ansible/modules/network/eos/eos_vlans.py240
-rw-r--r--test/integration/targets/eos_vlans/defaults/main.yaml2
-rw-r--r--test/integration/targets/eos_vlans/meta/main.yml2
-rw-r--r--test/integration/targets/eos_vlans/tasks/main.yaml16
-rw-r--r--test/integration/targets/eos_vlans/tests/cli/deleted.yaml39
-rw-r--r--test/integration/targets/eos_vlans/tests/cli/merged.yaml42
-rw-r--r--test/integration/targets/eos_vlans/tests/cli/overridden.yaml39
-rw-r--r--test/integration/targets/eos_vlans/tests/cli/replaced.yaml40
-rw-r--r--test/integration/targets/eos_vlans/tests/cli/reset_config.yml25
-rw-r--r--test/sanity/ignore.txt14
20 files changed, 832 insertions, 9 deletions
diff --git a/lib/ansible/module_utils/network/eos/argspec/facts/facts.py b/lib/ansible/module_utils/network/eos/argspec/facts/facts.py
index 0a4b5d2de8..da43943692 100644
--- a/lib/ansible/module_utils/network/eos/argspec/facts/facts.py
+++ b/lib/ansible/module_utils/network/eos/argspec/facts/facts.py
@@ -13,6 +13,8 @@ CHOICES = [
'!all',
'interfaces',
'!interfaces',
+ 'vlans',
+ '!vlans',
]
diff --git a/lib/ansible/module_utils/network/eos/argspec/vlans/__init__.py b/lib/ansible/module_utils/network/eos/argspec/vlans/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/ansible/module_utils/network/eos/argspec/vlans/__init__.py
diff --git a/lib/ansible/module_utils/network/eos/argspec/vlans/vlans.py b/lib/ansible/module_utils/network/eos/argspec/vlans/vlans.py
new file mode 100644
index 0000000000..ea2211ca3d
--- /dev/null
+++ b/lib/ansible/module_utils/network/eos/argspec/vlans/vlans.py
@@ -0,0 +1,54 @@
+# -*- 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 eos_vlans module
+"""
+
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+
+class VlansArgs(object):
+ """The arg spec for the eos_vlans module
+ """
+
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ 'config': {
+ 'elements': 'dict',
+ 'options': {
+ 'vlan_id': {'required': True, 'type': 'int'},
+ 'name': {'type': 'str'},
+ 'state': {'choices': ['active', 'suspend'], 'type': 'str'},
+ },
+ 'type': 'list',
+ },
+ 'state': {
+ 'choices': ['merged', 'replaced', 'overridden', 'deleted'],
+ 'default': 'merged',
+ 'type': 'str',
+ },
+ }
diff --git a/lib/ansible/module_utils/network/eos/config/vlans/__init__.py b/lib/ansible/module_utils/network/eos/config/vlans/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/ansible/module_utils/network/eos/config/vlans/__init__.py
diff --git a/lib/ansible/module_utils/network/eos/config/vlans/vlans.py b/lib/ansible/module_utils/network/eos/config/vlans/vlans.py
new file mode 100644
index 0000000000..bb1a065206
--- /dev/null
+++ b/lib/ansible/module_utils/network/eos/config/vlans/vlans.py
@@ -0,0 +1,208 @@
+# -*- 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 eos_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, dict_diff, param_list_to_dict
+from ansible.module_utils.network.eos.facts.facts import Facts
+
+
+class Vlans(ConfigBase):
+ """
+ The eos_vlans class
+ """
+
+ gather_subset = [
+ '!all',
+ '!min',
+ ]
+
+ gather_network_resources = [
+ 'vlans',
+ ]
+
+ def get_vlans_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)
+ vlans_facts = facts['ansible_network_resources'].get('vlans')
+ if not vlans_facts:
+ return []
+ return vlans_facts
+
+ def execute_module(self):
+ """ Execute the module
+
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ result = {'changed': False}
+ warnings = list()
+ commands = list()
+
+ existing_vlans_facts = self.get_vlans_facts()
+ commands.extend(self.set_config(existing_vlans_facts))
+ if commands:
+ if not self._module.check_mode:
+ self._connection.edit_config(commands)
+ result['changed'] = True
+ result['commands'] = commands
+
+ changed_vlans_facts = self.get_vlans_facts()
+
+ result['before'] = existing_vlans_facts
+ if result['changed']:
+ result['after'] = changed_vlans_facts
+
+ result['warnings'] = warnings
+ return result
+
+ def set_config(self, existing_vlans_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_vlans_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']
+ want = param_list_to_dict(want, "vlan_id", False)
+ have = param_list_to_dict(have, "vlan_id", False)
+ if state == 'overridden':
+ commands = self._state_overridden(want, have)
+ elif state == 'deleted':
+ commands = self._state_deleted(want, have)
+ elif state == 'merged':
+ commands = self._state_merged(want, have)
+ elif state == 'replaced':
+ commands = self._state_replaced(want, have)
+ return commands
+
+ @staticmethod
+ def _state_replaced(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 = []
+ for key, desired in want.items():
+ if key in have:
+ extant = have[key]
+ else:
+ extant = dict(vlan_id=key)
+
+ add_config = dict_diff(extant, desired)
+ del_config = dict_diff(desired, extant)
+
+ commands.extend(generate_commands(key, add_config, del_config))
+
+ return commands
+
+ @staticmethod
+ def _state_overridden(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 key, extant in have.items():
+ if key in want:
+ desired = want[key]
+ else:
+ desired = dict(vlan_id=key)
+
+ add_config = dict_diff(extant, desired)
+ del_config = dict_diff(desired, extant)
+
+ commands.extend(generate_commands(key, add_config, del_config))
+
+ return commands
+
+ @staticmethod
+ def _state_merged(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 = []
+ for key, desired in want.items():
+ if key in have:
+ extant = have[key]
+ else:
+ extant = dict(vlan_id=key)
+
+ add_config = dict_diff(extant, desired)
+
+ commands.extend(generate_commands(key, add_config, {}))
+
+ return commands
+
+ @staticmethod
+ def _state_deleted(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 = []
+ for key in want.keys():
+ desired = dict(vlan_id=key)
+ if key in have:
+ extant = have[key]
+ else:
+ extant = dict(vlan_id=key)
+
+ del_config = dict_diff(desired, extant)
+
+ commands.extend(generate_commands(key, {}, del_config))
+
+ return commands
+
+
+def generate_commands(vlan_id, to_set, to_remove):
+ commands = []
+ for key, value in to_set.items():
+ commands.append("{0} {1}".format(key, value))
+
+ for key in to_remove.keys():
+ commands.append("no {0}".format(key))
+
+ if commands:
+ commands.insert(0, "vlan {0}".format(vlan_id))
+
+ return commands
diff --git a/lib/ansible/module_utils/network/eos/facts/facts.py b/lib/ansible/module_utils/network/eos/facts/facts.py
index 41d35ae50b..9a66c0b1c2 100644
--- a/lib/ansible/module_utils/network/eos/facts/facts.py
+++ b/lib/ansible/module_utils/network/eos/facts/facts.py
@@ -13,6 +13,7 @@ __metaclass__ = type
from ansible.module_utils.network.common.facts.facts import FactsBase
from ansible.module_utils.network.eos.argspec.facts.facts import FactsArgs
from ansible.module_utils.network.eos.facts.interfaces.interfaces import InterfacesFacts
+from ansible.module_utils.network.eos.facts.vlans.vlans import VlansFacts
from ansible.module_utils.network.eos.facts.legacy.base import Default, Hardware, Config, Interfaces
@@ -24,6 +25,7 @@ FACT_LEGACY_SUBSETS = dict(
)
FACT_RESOURCE_SUBSETS = dict(
interfaces=InterfacesFacts,
+ vlans=VlansFacts,
)
diff --git a/lib/ansible/module_utils/network/eos/facts/vlans/__init__.py b/lib/ansible/module_utils/network/eos/facts/vlans/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/ansible/module_utils/network/eos/facts/vlans/__init__.py
diff --git a/lib/ansible/module_utils/network/eos/facts/vlans/vlans.py b/lib/ansible/module_utils/network/eos/facts/vlans/vlans.py
new file mode 100644
index 0000000000..0e01b6c216
--- /dev/null
+++ b/lib/ansible/module_utils/network/eos/facts/vlans/vlans.py
@@ -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 eos 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
+import re
+
+from ansible.module_utils.network.common import utils
+from ansible.module_utils.network.eos.argspec.vlans.vlans import VlansArgs
+
+
+class VlansFacts(object):
+ """ The eos 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 not data:
+ data = connection.get('show running-config | section ^vlan')
+
+ # split the config into instances of the resource
+ resource_delim = 'vlan'
+ find_pattern = r'(?:^|\n)%s.*?(?=(?:^|\n)%s|$)' % (resource_delim,
+ resource_delim)
+ resources = [p.strip() for p in re.findall(find_pattern,
+ data,
+ re.DOTALL)]
+
+ objs = []
+ for resource in resources:
+ if resource:
+ obj = self.render_config(self.generated_spec, resource)
+ if obj:
+ objs.extend(obj)
+
+ ansible_facts['ansible_network_resources'].pop('vlans', None)
+ facts = {}
+ if objs:
+ params = utils.validate_config(self.argument_spec, {'config': objs})
+ facts['vlans'] = [utils.remove_empties(cfg) for cfg in params['config']]
+
+ 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)
+ vlans = []
+
+ vlan_list = vlan_to_list(utils.parse_conf_arg(conf, 'vlan'))
+ for vlan in vlan_list:
+ config['vlan_id'] = vlan
+ config['name'] = utils.parse_conf_arg(conf, 'name')
+ config['state'] = utils.parse_conf_arg(conf, 'state')
+
+ vlans.append(utils.remove_empties(config))
+
+ return vlans
+
+
+def vlan_to_list(vlan_str):
+ vlans = []
+ for vlan in vlan_str.split(','):
+ if '-' in vlan:
+ start, stop = vlan.split('-')
+ vlans.extend(range(int(start), int(stop) + 1))
+ else:
+ vlans.append(int(vlan))
+
+ return vlans
diff --git a/lib/ansible/modules/network/eos/eos_vlan.py b/lib/ansible/modules/network/eos/_eos_vlan.py
index 72aa6edc63..c17fd77f78 100644
--- a/lib/ansible/modules/network/eos/eos_vlan.py
+++ b/lib/ansible/modules/network/eos/_eos_vlan.py
@@ -20,7 +20,7 @@
#
ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
+ 'status': ['deprecated'],
'supported_by': 'network'}
@@ -33,6 +33,10 @@ short_description: Manage VLANs on Arista EOS network devices
description:
- This module provides declarative management of VLANs
on Arista EOS network devices.
+deprecated:
+ removed_in: "2.13"
+ alternative: eos_vlans
+ why: Updated modules released with more functionality
notes:
- Tested against EOS 4.15
options:
diff --git a/lib/ansible/modules/network/eos/eos_facts.py b/lib/ansible/modules/network/eos/eos_facts.py
index 6d056f0dfb..fba1e4b6fa 100644
--- a/lib/ansible/modules/network/eos/eos_facts.py
+++ b/lib/ansible/modules/network/eos/eos_facts.py
@@ -47,7 +47,7 @@ options:
can also be used with an initial C(M(!)) to specify that a
specific subset should not be collected.
required: false
- choices: ['all', '!all', 'interfaces', '!interfaces']
+ choices: ['all', '!all', 'interfaces', '!interfaces', 'vlans', '!vlans']
type: list
version_added: "2.9"
"""
diff --git a/lib/ansible/modules/network/eos/eos_vlans.py b/lib/ansible/modules/network/eos/eos_vlans.py
new file mode 100644
index 0000000000..25db4a8497
--- /dev/null
+++ b/lib/ansible/modules/network/eos/eos_vlans.py
@@ -0,0 +1,240 @@
+#!/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 eos_vlans
+"""
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {
+ 'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'network'
+}
+
+DOCUMENTATION = """
+---
+module: eos_vlans
+version_added: 2.9
+short_description: Manage VLANs on Arista EOS devices.
+description: This module provides declarative management of VLANs on Arista EOS network devices.
+author: Nathaniel Case (@qalthos)
+notes:
+- Tested against Arista EOS 4.20.10M
+- This module works with connection C(network_cli). See the
+ L(EOS Platform Options,../network/user_guide/platform_eos.html).
+options:
+ config:
+ description: A dictionary of VLANs options
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description:
+ - Name of the VLAN.
+ type: str
+ vlan_id:
+ description:
+ - ID of the VLAN. Range 1-4094
+ type: int
+ required: true
+ state:
+ description:
+ - Operational state of the VLAN
+ type: str
+ choices:
+ - active
+ - suspend
+ state:
+ description:
+ - The state the configuration should be left in
+ type: str
+ choices:
+ - merged
+ - replaced
+ - overridden
+ - deleted
+ default: merged
+"""
+EXAMPLES = """
+# Using deleted
+
+# Before state:
+# -------------
+#
+# veos(config-vlan-20)#show running-config | section vlan
+# vlan 10
+# name ten
+# !
+# vlan 20
+# name twenty
+
+- name: Delete attributes of the given VLANs.
+ ios_vlans:
+ config:
+ - vlan_id: 20
+ state: deleted
+
+# After state:
+# ------------
+#
+# veos(config-vlan-20)#show running-config | section vlan
+# vlan 10
+# name ten
+
+
+# Using merged
+
+# Before state:
+# -------------
+#
+# veos(config-vlan-20)#show running-config | section vlan
+# vlan 10
+# name ten
+# !
+# vlan 20
+# name twenty
+
+- name: Merge given VLAN attributes with device configuration
+ ios_vlans:
+ config:
+ - vlan_id: 20
+ state: suspend
+ state: merged
+
+# After state:
+# ------------
+#
+# veos(config-vlan-20)#show running-config | section vlan
+# vlan 10
+# name ten
+# !
+# vlan 20
+# name twenty
+# state suspend
+
+
+# Using overridden
+
+# Before state:
+# -------------
+#
+# veos(config-vlan-20)#show running-config | section vlan
+# vlan 10
+# name ten
+# !
+# vlan 20
+# name twenty
+
+- name: Override device configuration of all VLANs with provided configuration
+ ios_vlans:
+ config:
+ - vlan_id: 20
+ state: suspend
+ state: overridden
+
+# After state:
+# ------------
+#
+# veos(config-vlan-20)#show running-config | section vlan
+# vlan 20
+# state suspend
+
+
+# Using replaced
+
+# Before state:
+# -------------
+#
+# veos(config-vlan-20)#show running-config | section vlan
+# vlan 10
+# name ten
+# !
+# vlan 20
+# name twenty
+
+- name: Replace all attributes of specified VLANs with provided configuration
+ ios_vlans:
+ config:
+ - vlan_id: 20
+ state: suspend
+ state: replaced
+
+# After state:
+# ------------
+#
+# veos(config-vlan-20)#show running-config | section vlan
+# vlan 10
+# name ten
+# !
+# vlan 20
+# state suspend
+
+
+"""
+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 10', 'no name', 'vlan 11', 'name Eleven']
+"""
+
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.network.eos.argspec.vlans.vlans import VlansArgs
+from ansible.module_utils.network.eos.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/eos_vlans/defaults/main.yaml b/test/integration/targets/eos_vlans/defaults/main.yaml
new file mode 100644
index 0000000000..5f709c5aac
--- /dev/null
+++ b/test/integration/targets/eos_vlans/defaults/main.yaml
@@ -0,0 +1,2 @@
+---
+testcase: "*"
diff --git a/test/integration/targets/eos_vlans/meta/main.yml b/test/integration/targets/eos_vlans/meta/main.yml
new file mode 100644
index 0000000000..e5c8cd02f0
--- /dev/null
+++ b/test/integration/targets/eos_vlans/meta/main.yml
@@ -0,0 +1,2 @@
+dependencies:
+ - prepare_eos_tests
diff --git a/test/integration/targets/eos_vlans/tasks/main.yaml b/test/integration/targets/eos_vlans/tasks/main.yaml
new file mode 100644
index 0000000000..af64d48ed8
--- /dev/null
+++ b/test/integration/targets/eos_vlans/tasks/main.yaml
@@ -0,0 +1,16 @@
+---
+- name: collect all cli test cases
+ find:
+ paths: "{{ role_path }}/tests/cli"
+ patterns: "{{ testcase }}.yaml"
+ delegate_to: localhost
+ register: test_cases
+
+- 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"
+ with_items: "{{ test_items }}"
+ loop_control:
+ loop_var: test_case_to_run
diff --git a/test/integration/targets/eos_vlans/tests/cli/deleted.yaml b/test/integration/targets/eos_vlans/tests/cli/deleted.yaml
new file mode 100644
index 0000000000..7abeda68be
--- /dev/null
+++ b/test/integration/targets/eos_vlans/tests/cli/deleted.yaml
@@ -0,0 +1,39 @@
+---
+- include_tasks: reset_config.yml
+
+- set_fact:
+ config:
+ - vlan_id: 20
+
+- eos_facts:
+ gather_network_resources: vlans
+ become: yes
+
+- name: Returns vlans to default parameters
+ eos_vlans:
+ config: "{{ config }}"
+ state: deleted
+ register: result
+ become: yes
+
+- assert:
+ that:
+ - "ansible_facts.network_resources.vlans|symmetric_difference(result.before) == []"
+
+- eos_facts:
+ gather_network_resources: vlans
+ become: yes
+
+- assert:
+ that:
+ - "ansible_facts.network_resources.vlans|symmetric_difference(result.after) == []"
+
+- set_fact:
+ expected_config:
+ - vlan_id: 10
+ name: ten
+ - vlan_id: 20
+
+- assert:
+ that:
+ - "expected_config|symmetric_difference(ansible_facts.network_resources.vlans) == []"
diff --git a/test/integration/targets/eos_vlans/tests/cli/merged.yaml b/test/integration/targets/eos_vlans/tests/cli/merged.yaml
new file mode 100644
index 0000000000..5ad3f08597
--- /dev/null
+++ b/test/integration/targets/eos_vlans/tests/cli/merged.yaml
@@ -0,0 +1,42 @@
+---
+- include_tasks: reset_config.yml
+
+- set_fact:
+ config:
+ - vlan_id: 20
+ state: suspend
+
+- eos_facts:
+ gather_network_resources: vlans
+ become: yes
+
+- name: Merge provided configuration with device configuration
+ eos_vlans:
+ config: "{{ config }}"
+ state: merged
+ register: result
+ become: yes
+
+- assert:
+ that:
+ - "ansible_facts.network_resources.vlans|symmetric_difference(result.before) == []"
+
+- eos_facts:
+ gather_network_resources: vlans
+ become: yes
+
+- assert:
+ that:
+ - "ansible_facts.network_resources.vlans|symmetric_difference(result.after) == []"
+
+- set_fact:
+ expected_config:
+ - vlan_id: 10
+ name: ten
+ - vlan_id: 20
+ name: twenty
+ state: suspend
+
+- assert:
+ that:
+ - "expected_config|symmetric_difference(ansible_facts.network_resources.vlans) == []"
diff --git a/test/integration/targets/eos_vlans/tests/cli/overridden.yaml b/test/integration/targets/eos_vlans/tests/cli/overridden.yaml
new file mode 100644
index 0000000000..edd3511ae0
--- /dev/null
+++ b/test/integration/targets/eos_vlans/tests/cli/overridden.yaml
@@ -0,0 +1,39 @@
+---
+- include_tasks: reset_config.yml
+
+- set_fact:
+ config:
+ - vlan_id: 20
+ state: suspend
+ other_config:
+ - vlan_id: 10
+
+- eos_facts:
+ gather_network_resources: vlans
+ become: yes
+
+- name: Overrides device configuration of all vlans with provided configuration
+ eos_vlans:
+ config: "{{ config }}"
+ state: overridden
+ register: result
+ become: yes
+
+- assert:
+ that:
+ - "ansible_facts.network_resources.vlans|symmetric_difference(result.before) == []"
+
+- eos_facts:
+ gather_network_resources: vlans
+ become: yes
+
+- assert:
+ that:
+ - "ansible_facts.network_resources.vlans|symmetric_difference(result.after) == []"
+
+- set_fact:
+ expected_config: "{{ config }} + {{ other_config }}"
+
+- assert:
+ that:
+ - "expected_config|symmetric_difference(ansible_facts.network_resources.vlans) == []"
diff --git a/test/integration/targets/eos_vlans/tests/cli/replaced.yaml b/test/integration/targets/eos_vlans/tests/cli/replaced.yaml
new file mode 100644
index 0000000000..ca502ff156
--- /dev/null
+++ b/test/integration/targets/eos_vlans/tests/cli/replaced.yaml
@@ -0,0 +1,40 @@
+---
+- include_tasks: reset_config.yml
+
+- set_fact:
+ config:
+ - vlan_id: 20
+ state: suspend
+ other_config:
+ - vlan_id: 10
+ name: ten
+
+- eos_facts:
+ gather_network_resources: vlans
+ become: yes
+
+- name: Replaces device configuration of listed vlans with provided configuration
+ eos_vlans:
+ config: "{{ config }}"
+ state: replaced
+ register: result
+ become: yes
+
+- assert:
+ that:
+ - "ansible_facts.network_resources.vlans|symmetric_difference(result.before) == []"
+
+- eos_facts:
+ gather_network_resources: vlans
+ become: yes
+
+- assert:
+ that:
+ - "ansible_facts.network_resources.vlans|symmetric_difference(result.after) == []"
+
+- set_fact:
+ expected_config: "{{ config }} + {{ other_config }}"
+
+- assert:
+ that:
+ - "expected_config|symmetric_difference(ansible_facts.network_resources.vlans) == []"
diff --git a/test/integration/targets/eos_vlans/tests/cli/reset_config.yml b/test/integration/targets/eos_vlans/tests/cli/reset_config.yml
new file mode 100644
index 0000000000..513a1199b1
--- /dev/null
+++ b/test/integration/targets/eos_vlans/tests/cli/reset_config.yml
@@ -0,0 +1,25 @@
+---
+- name: Reset initial config
+ cli_config:
+ config: |
+ no vlan 1-4094
+ vlan 10
+ name ten
+ vlan 20
+ name twenty
+ become: yes
+
+- eos_facts:
+ gather_network_resources: vlans
+ become: yes
+
+- set_fact:
+ expected_config:
+ - vlan_id: 10
+ name: ten
+ - vlan_id: 20
+ name: twenty
+
+- assert:
+ that:
+ - "expected_config|symmetric_difference(ansible_facts.network_resources.vlans) == []"
diff --git a/test/sanity/ignore.txt b/test/sanity/ignore.txt
index c8e2dd325a..5a60837190 100644
--- a/test/sanity/ignore.txt
+++ b/test/sanity/ignore.txt
@@ -3617,13 +3617,13 @@ lib/ansible/modules/network/eos/eos_user.py validate-modules:E326
lib/ansible/modules/network/eos/eos_user.py validate-modules:E337
lib/ansible/modules/network/eos/eos_user.py validate-modules:E338
lib/ansible/modules/network/eos/eos_user.py validate-modules:E340
-lib/ansible/modules/network/eos/eos_vlan.py future-import-boilerplate
-lib/ansible/modules/network/eos/eos_vlan.py metaclass-boilerplate
-lib/ansible/modules/network/eos/eos_vlan.py validate-modules:E322
-lib/ansible/modules/network/eos/eos_vlan.py validate-modules:E326
-lib/ansible/modules/network/eos/eos_vlan.py validate-modules:E337
-lib/ansible/modules/network/eos/eos_vlan.py validate-modules:E338
-lib/ansible/modules/network/eos/eos_vlan.py validate-modules:E340
+lib/ansible/modules/network/eos/_eos_vlan.py future-import-boilerplate
+lib/ansible/modules/network/eos/_eos_vlan.py metaclass-boilerplate
+lib/ansible/modules/network/eos/_eos_vlan.py validate-modules:E322
+lib/ansible/modules/network/eos/_eos_vlan.py validate-modules:E326
+lib/ansible/modules/network/eos/_eos_vlan.py validate-modules:E337
+lib/ansible/modules/network/eos/_eos_vlan.py validate-modules:E338
+lib/ansible/modules/network/eos/_eos_vlan.py validate-modules:E340
lib/ansible/modules/network/eos/eos_vrf.py future-import-boilerplate
lib/ansible/modules/network/eos/eos_vrf.py metaclass-boilerplate
lib/ansible/modules/network/eos/eos_vrf.py validate-modules:E322