Repository: ansible/ansible

Issue:
nxos_vxlan_vtep errors out for both transports (nxapi anc cli)
##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
 - nxos_vxlan_vtep

##### NXOS VERSION
7.0(3)I3(1)

##### ANSIBLE VERSION
```
ansible-playbook 2.4.0 (devel 781bb44b02) last updated 2017/06/08 15:20:16 (GMT -400)
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/usr/share/ansible']
  ansible python module location = /root/agents-ci/ansible/lib/ansible
  executable location = /root/agents-ci/ansible/bin/ansible-playbook
  python version = 2.7.6 (default, Oct 26 2016, 20:30:19) [GCC 4.8.4]
```

##### OS / ENVIRONMENT
running on Ubuntu 14.04

##### SUMMARY
The module errors out in latest `devel` when using transport `nxapi` or `cli` but it errors out differently for each.

##### STEPS TO REPRODUCE
* CLI yaml file
```yaml
---
- debug: msg="START TRANSPORT:CLI nxos_vxlan_vtep sanity test"

- name: vxlan_vtep
  nxos_vxlan_vtep:
    interface: nve1
    description: default
    host_reachability: true
    source_interface: Loopback0
    source_interface_hold_down_time: 30
    shutdown: true
    provider: "{{ cli }}"

- debug: msg="END TRANSPORT:CLI nxos_vxlan_vtep sanity test"
```

* NXAPI yaml file
```yaml
---
- debug: msg="START TRANSPORT:NXAPI nxos_vxlan_vtep sanity test"

- name: vxlan_vtep
  nxos_vxlan_vtep:
    interface: nve1
    description: default
    host_reachability: true
    source_interface: Loopback0
    source_interface_hold_down_time: 30
    shutdown: true
    provider: "{{ nxapi }}"

- debug: msg="END TRANSPORT:NXAPI nxos_vxlan_vtep sanity test"
```

##### EXPECTED RESULTS
Expect module to run properly.

##### ACTUAL RESULTS FOR TRANSPORT CLI

```shell
TASK [nxos_vxlan_vtep : debug] ****************************************************************************************************************************************************************************************************************
task path: /root/agents-ci/ansible/test/integration/targets/nxos_vxlan_vtep/tests/cli/sanity.yaml:2
ok: [n9k] => {
    "failed": false, 
    "msg": "START TRANSPORT:CLI nxos_vxlan_vtep sanity test"
}

TASK [nxos_vxlan_vtep : vxlan_vtep] ***********************************************************************************************************************************************************************************************************
task path: /root/agents-ci/ansible/test/integration/targets/nxos_vxlan_vtep/tests/cli/sanity.yaml:4
<n9k> connection transport is cli
<n9k> using connection plugin network_cli
<n9k> socket_path: /root/.ansible/pc/4cc10f215f
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/basic.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/netcfg.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/nxos.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/_text.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/pycompat24.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/six/__init__.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/six/_six.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/network_common.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/connection.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/urls.py
Using module file /root/agents-ci/ansible/lib/ansible/modules/network/nxos/nxos_vxlan_vtep.py
<n9k> ESTABLISH LOCAL CONNECTION FOR USER: root
<n9k> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo $HOME/.ansible/tmp/ansible-tmp-1496954945.36-174796920177207 `" && echo ansible-tmp-1496954945.36-174796920177207="` echo $HOME/.ansible/tmp/ansible-tmp-1496954945.36-174796920177207 `" ) && sleep 0'
<n9k> PUT /tmp/tmpNOGL3_ TO /root/.ansible/tmp/ansible-tmp-1496954945.36-174796920177207/nxos_vxlan_vtep.py
<n9k> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1496954945.36-174796920177207/ /root/.ansible/tmp/ansible-tmp-1496954945.36-174796920177207/nxos_vxlan_vtep.py && sleep 0'
<n9k> EXEC /bin/sh -c '/usr/bin/python /root/.ansible/tmp/ansible-tmp-1496954945.36-174796920177207/nxos_vxlan_vtep.py; rm -rf "/root/.ansible/tmp/ansible-tmp-1496954945.36-174796920177207/" > /dev/null 2>&1 && sleep 0'
The full traceback is:
Traceback (most recent call last):
  File "/tmp/ansible_PDjD0d/ansible_module_nxos_vxlan_vtep.py", line 385, in <module>
    main()
  File "/tmp/ansible_PDjD0d/ansible_module_nxos_vxlan_vtep.py", line 367, in main
    result.update(response)
TypeError: 'NoneType' object is not iterable

fatal: [n9k]: FAILED! => {
    "changed": false, 
    "failed": true, 
    "module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_PDjD0d/ansible_module_nxos_vxlan_vtep.py\", line 385, in <module>\n    main()\n  File \"/tmp/ansible_PDjD0d/ansible_module_nxos_vxlan_vtep.py\", line 367, in main\n    result.update(response)\nTypeError: 'NoneType' object is not iterable\n", 
    "module_stdout": "", 
    "msg": "MODULE FAILURE", 
    "rc": 0
}
	to retry, use: --limit @/root/agents-ci/ansible/test/integration/nxos.retry

PLAY RECAP ************************************************************************************************************************************************************************************************************************************
n9k          : ok=5    changed=0    unreachable=0    failed=1   

```

##### ACTUAL RESULTS FOR TRANSPORT NXAPI

```shell
TASK [nxos_vxlan_vtep : debug] ****************************************************************************************************************************************************************************************************************
task path: /root/agents-ci/ansible/test/integration/targets/nxos_vxlan_vtep/tests/nxapi/sanity.yaml:2
ok: [n9k] => {
    "failed": false, 
    "msg": "START TRANSPORT:NXAPI nxos_vxlan_vtep sanity test"
}

TASK [nxos_vxlan_vtep : vxlan_vtep] ***********************************************************************************************************************************************************************************************************
task path: /root/agents-ci/ansible/test/integration/targets/nxos_vxlan_vtep/tests/nxapi/sanity.yaml:4
<n9k> connection transport is nxapi
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/basic.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/netcfg.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/nxos.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/_text.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/pycompat24.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/six/__init__.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/six/_six.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/network_common.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/connection.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/urls.py
Using module file /root/agents-ci/ansible/lib/ansible/modules/network/nxos/nxos_vxlan_vtep.py
<n9k> ESTABLISH LOCAL CONNECTION FOR USER: root
<n9k> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo $HOME/.ansible/tmp/ansible-tmp-1496954720.87-110679870281891 `" && echo ansible-tmp-1496954720.87-110679870281891="` echo $HOME/.ansible/tmp/ansible-tmp-1496954720.87-110679870281891 `" ) && sleep 0'
<n9k> PUT /tmp/tmp6VADQg TO /root/.ansible/tmp/ansible-tmp-1496954720.87-110679870281891/nxos_vxlan_vtep.py
<n9k> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1496954720.87-110679870281891/ /root/.ansible/tmp/ansible-tmp-1496954720.87-110679870281891/nxos_vxlan_vtep.py && sleep 0'
<n9k> EXEC /bin/sh -c '/usr/bin/python /root/.ansible/tmp/ansible-tmp-1496954720.87-110679870281891/nxos_vxlan_vtep.py; rm -rf "/root/.ansible/tmp/ansible-tmp-1496954720.87-110679870281891/" > /dev/null 2>&1 && sleep 0'
The full traceback is:
Traceback (most recent call last):
  File "/tmp/ansible_IUUcWC/ansible_module_nxos_vxlan_vtep.py", line 385, in <module>
    main()
  File "/tmp/ansible_IUUcWC/ansible_module_nxos_vxlan_vtep.py", line 366, in main
    response = load_config(module, candidate)
  File "/tmp/ansible_IUUcWC/ansible_modlib.zip/ansible/module_utils/nxos.py", line 399, in load_config
  File "/tmp/ansible_IUUcWC/ansible_modlib.zip/ansible/module_utils/nxos.py", line 346, in load_config
  File "/tmp/ansible_IUUcWC/ansible_modlib.zip/ansible/module_utils/nxos.py", line 262, in send_request
  File "/tmp/ansible_IUUcWC/ansible_modlib.zip/ansible/module_utils/nxos.py", line 227, in _request_builder
TypeError: sequence item 0: expected string, CustomNetworkConfig found

fatal: [n9k]: FAILED! => {
    "changed": false, 
    "failed": true, 
    "module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_IUUcWC/ansible_module_nxos_vxlan_vtep.py\", line 385, in <module>\n    main()\n  File \"/tmp/ansible_IUUcWC/ansible_module_nxos_vxlan_vtep.py\", line 366, in main\n    response = load_config(module, candidate)\n  File \"/tmp/ansible_IUUcWC/ansible_modlib.zip/ansible/module_utils/nxos.py\", line 399, in load_config\n  File \"/tmp/ansible_IUUcWC/ansible_modlib.zip/ansible/module_utils/nxos.py\", line 346, in load_config\n  File \"/tmp/ansible_IUUcWC/ansible_modlib.zip/ansible/module_utils/nxos.py\", line 262, in send_request\n  File \"/tmp/ansible_IUUcWC/ansible_modlib.zip/ansible/module_utils/nxos.py\", line 227, in _request_builder\nTypeError: sequence item 0: expected string, CustomNetworkConfig found\n", 
    "module_stdout": "", 
    "msg": "MODULE FAILURE", 
    "rc": 0
}
	to retry, use: --limit @/root/agents-ci/ansible/test/integration/nxos.retry

PLAY RECAP ************************************************************************************************************************************************************************************************************************************
n9k          : ok=6    changed=0    unreachable=0    failed=1   

```


Discussion:
cc @jedelman8 @GGabriele @rahushen @privateip @rcarrillocruz @trishnaguha
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
Add me to the chorus on this one as well, however for nxos_bgp rather than nxos_vxlan_vtep. The root seems to be the same as the errors are the exact same, with the bottom of the stack in `module-utilities/nxos.py` and hitting the same messages for cli and nxapi messages, respectively. Some other differences:

**COMPONENT NAME**

* nxos_bgp

**NXOS VERSION**

* 7.0(3)I6(1)
* note: this was tested against NX-OSv9k, not physical hardware

**ANSIBLE VERSION**

```
$ ansible --version
ansible 2.3.1.0
  config file = /home/hslabbert/repos/network_ansible/ansible.cfg
  configured module search path = Default w/o overrides
  python version = 2.7.13 (default, Jan 19 2017, 14:48:08) [GCC 6.3.0 20170118]
```

*note*: Tested and currently working against `devel` branch, which has the following version info:

```
$ ansible --version
ansible 2.4.0
  config file = /home/hslabbert/repos/network_ansible/ansible.cfg
  configured module search path = [u'/home/hslabbert/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /home/hslabbert/.virtualenvs/network_ansible_dev/local/lib/python2.7/site-packages/ansible-2.4.0-py2.7.egg/ansible
  executable location = /home/hslabbert/.virtualenvs/network_ansible_dev/bin/ansible
  python version = 2.7.13 (default, Jan 19 2017, 14:48:08) [GCC 6.3.0 20170118]
```

`devel` was checked out against commit a4f173808281637b94949baf97f5236323f8c189.

**OS / ENVIRONMENT**

```
$ lsb_release -a
Distributor ID: Debian
Description:    Debian GNU/Linux 9.0 (stretch)
Release:        9.0
Codename:       stretch
```
**COMMENTS**

From what I can gather, there seems to be boilerplate in several of the nxos_* modules. Chatted with @dgjustice about this in Slack. For the nxapi transport issue, it appears that `candidate` is being created as a `CustomNetworkConfig` object.  However, `load_config` wants it as a string.

The NoneType error in when using the cli transport seems to be because, as far as I can tell, `load_config()` in module-utilities/nxos.py doesn't actually return anything. So, when nxos_bgp.py tries to do load_config starting at around line 846:

```
    result = {}
    if (state == 'present' or (state == 'absent' and
            existing.get('asn') == module.params['asn'])):
        candidate = CustomNetworkConfig(indent=3)
        invoke('state_%s' % state, module, existing, proposed, candidate)

        try:
            response = load_config(module, candidate)
            result.update(response)
        except ShellError:
            exc = get_exception()
            module.fail_json(msg=str(exc))
    else:
        result['updates'] = []
```

Well, as `load_config` doesn't return anything, `response` is empty, so it makes sense to hit a NoneType error when trying to do anything with it.

Also: nxos_bgp.py doesn't import ShellError from `module_utils/shell.py`, so that needs to get imported first in order to hit that NoneType error. The ShellError issue seems to be https://github.com/ansible/ansible/issues/23890, which was fixed in https://github.com/ansible/ansible/pull/24008 as best I can tell.

Resolving patch:
diff --git a/lib/ansible/modules/network/nxos/nxos_vxlan_vtep.py b/lib/ansible/modules/network/nxos/nxos_vxlan_vtep.py
--- a/lib/ansible/modules/network/nxos/nxos_vxlan_vtep.py
+++ b/lib/ansible/modules/network/nxos/nxos_vxlan_vtep.py
@@ -16,9 +16,11 @@
 # along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
 #
 
-ANSIBLE_METADATA = {'metadata_version': '1.0',
-                    'status': ['preview'],
-                    'supported_by': 'community'}
+ANSIBLE_METADATA = {
+    'metadata_version': '1.0',
+    'status': ['preview'],
+    'supported_by': 'community',
+}
 
 
 DOCUMENTATION = '''
@@ -28,55 +30,55 @@
 version_added: "2.2"
 short_description: Manages VXLAN Network Virtualization Endpoint (NVE).
 description:
-    - Manages VXLAN Network Virtualization Endpoint (NVE) overlay interface
-      that terminates VXLAN tunnels.
+  - Manages VXLAN Network Virtualization Endpoint (NVE) overlay interface
+    that terminates VXLAN tunnels.
 author: Gabriele Gerbino (@GGabriele)
 notes:
-    - The module is used to manage NVE properties, not to create NVE
-      interfaces. Use M(nxos_interface) if you wish to do so.
-    - C(state=absent) removes the interface.
-    - Default, where supported, restores params default value.
+  - The module is used to manage NVE properties, not to create NVE
+    interfaces. Use M(nxos_interface) if you wish to do so.
+  - C(state=absent) removes the interface.
+  - Default, where supported, restores params default value.
 options:
-    interface:
-        description:
-            - Interface name for the VXLAN Network Virtualization Endpoint.
-        required: true
+  interface:
+    description:
+      - Interface name for the VXLAN Network Virtualization Endpoint.
+    required: true
+  description:
+    description:
+      - Description of the NVE interface.
+    required: false
+    default: null
+  host_reachability:
+    description:
+      - Specify mechanism for host reachability advertisement.
+    required: false
+    choices: ['true', 'false']
+    default: null
+  shutdown:
+    description:
+      - Administratively shutdown the NVE interface.
+    required: false
+    choices: ['true','false']
+    default: false
+  source_interface:
     description:
-        description:
-            - Description of the NVE interface.
-        required: false
-        default: null
-    host_reachability:
-        description:
-            - Specify mechanism for host reachability advertisement.
-        required: false
-        choices: ['true', 'false']
-        default: null
-    shutdown:
-        description:
-            - Administratively shutdown the NVE interface.
-        required: false
-        choices: ['true','false']
-        default: false
-    source_interface:
-        description:
-            - Specify the loopback interface whose IP address should be
-              used for the NVE interface.
-        required: false
-        default: null
-    source_interface_hold_down_time:
-        description:
-            - Suppresses advertisement of the NVE loopback address until
-              the overlay has converged.
-        required: false
-        default: null
-    state:
-        description:
-            - Determines whether the config should be present or not
-              on the device.
-        required: false
-        default: present
-        choices: ['present','absent']
+      - Specify the loopback interface whose IP address should be
+        used for the NVE interface.
+    required: false
+    default: null
+  source_interface_hold_down_time:
+    description:
+      - Suppresses advertisement of the NVE loopback address until
+        the overlay has converged.
+    required: false
+    default: null
+  state:
+    description:
+      - Determines whether the config should be present or not
+        on the device.
+    required: false
+    default: present
+    choices: ['present','absent']
 '''
 EXAMPLES = '''
 - nxos_vxlan_vtep:
@@ -86,47 +88,20 @@
     source_interface: Loopback0
     source_interface_hold_down_time: 30
     shutdown: default
-    username: "{{ un }}"
-    password: "{{ pwd }}"
-    host: "{{ inventory_hostname }}"
 '''
 
 RETURN = '''
-proposed:
-    description: k/v pairs of parameters passed into module
-    returned: verbose mode
-    type: dict
-    sample: {"description": "simple description", "host_reachability": true,
-        "interface": "nve1", "shutdown": true, "source_interface": "loopback0",
-        "source_interface_hold_down_time": "30"}
-existing:
-    description: k/v pairs of existing VXLAN VTEP configuration
-    returned: verbose mode
-    type: dict
-    sample: {}
-end_state:
-    description: k/v pairs of VXLAN VTEP configuration after module execution
-    returned: verbose mode
-    type: dict
-    sample: {"description": "simple description", "host_reachability": true,
-        "interface": "nve1", "shutdown": true, "source_interface": "loopback0",
-        "source_interface_hold_down_time": "30"}
-updates:
+commands:
     description: commands sent to the device
     returned: always
     type: list
     sample: ["interface nve1", "source-interface loopback0",
         "source-interface hold-down-time 30", "description simple description",
         "shutdown", "host-reachability protocol bgp"]
-changed:
-    description: check to see if a change was made on the device
-    returned: always
-    type: boolean
-    sample: true
 '''
 
 import re
-from ansible.module_utils.nxos import get_config, load_config, run_commands
+from ansible.module_utils.nxos import get_config, load_config
 from ansible.module_utils.nxos import nxos_argument_spec, check_args
 from ansible.module_utils.basic import AnsibleModule
 from ansible.module_utils.netcfg import CustomNetworkConfig
@@ -148,14 +123,6 @@
     'shutdown': True,
 }
 
-WARNINGS = []
-
-
-def invoke(name, *args, **kwargs):
-    func = globals().get(name)
-    if func:
-        return func(*args, **kwargs)
-
 
 def get_value(arg, config, module):
     if arg in BOOL_PARAMS:
@@ -305,38 +272,24 @@ def main():
         source_interface=dict(required=False, type='str'),
         source_interface_hold_down_time=dict(required=False, type='str'),
         m_facts=dict(required=False, default=False, type='bool'),
-        state=dict(choices=['present', 'absent'], default='present',
-                       required=False),
-        include_defaults=dict(default=True),
-        config=dict(),
-        save=dict(type='bool', default=False)
+        state=dict(choices=['present', 'absent'], default='present', required=False),
     )
 
     argument_spec.update(nxos_argument_spec)
 
-    module = AnsibleModule(argument_spec=argument_spec,
-                                supports_check_mode=True)
+    module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
 
     warnings = list()
+    result = {'changed': False, 'commands': [], 'warnings': warnings}
     check_args(module, warnings)
 
-
     state = module.params['state']
-    interface = module.params['interface'].lower()
-
-    args =  [
-        'interface',
-        'description',
-        'host_reachability',
-        'shutdown',
-        'source_interface',
-        'source_interface_hold_down_time'
-    ]
-
-    existing = invoke('get_existing', module, args)
-    end_state = existing
+
+    args = PARAM_TO_DEFAULT_KEYMAP.keys()
+
+    existing = get_existing(module, args)
     proposed_args = dict((k, v) for k, v in module.params.items()
-                    if v is not None and k in args)
+                         if v is not None and k in args)
 
     proposed = {}
     for key, value in proposed_args.items():
@@ -352,35 +305,27 @@ def main():
                         value = False
                     else:
                         value = 'default'
-            if existing.get(key) or (not existing.get(key) and value):
+            if existing.get(key) != value:
                 proposed[key] = value
 
-    result = {}
-    if state == 'present' or (state == 'absent' and existing):
+    candidate = CustomNetworkConfig(indent=3)
+    if state == 'present':
         if not existing:
-            WARNINGS.append("The proposed NVE interface did not exist. "
+            warnings.append("The proposed NVE interface did not exist. "
                             "It's recommended to use nxos_interface to create "
                             "all logical interfaces.")
-        candidate = CustomNetworkConfig(indent=3)
-        invoke('state_%s' % state, module, existing, proposed, candidate)
-        response = load_config(module, candidate)
-        result.update(response)
+        state_present(module, existing, proposed, candidate)
+    elif state == 'absent' and existing:
+        state_absent(module, existing, proposed, candidate)
 
-    else:
-        result['updates'] = []
-
-    if module._verbosity > 0:
-        end_state = invoke('get_existing', module, args)
-        result['end_state'] = end_state
-        result['existing'] = existing
-        result['proposed'] = proposed_args
-
-    if WARNINGS:
-        result['warnings'] = WARNINGS
+    if candidate:
+        candidate = candidate.items_text()
+        result['commands'] = candidate
+        result['changed'] = True
+        load_config(module, candidate)
 
     module.exit_json(**result)
 
 
 if __name__ == '__main__':
     main()
-


Test patch:
diff --git a/test/sanity/pep8/legacy-files.txt b/test/sanity/pep8/legacy-files.txt
--- a/test/sanity/pep8/legacy-files.txt
+++ b/test/sanity/pep8/legacy-files.txt
@@ -402,7 +402,6 @@ lib/ansible/modules/network/nxos/nxos_vrrp.py
 lib/ansible/modules/network/nxos/nxos_vtp_domain.py
 lib/ansible/modules/network/nxos/nxos_vtp_password.py
 lib/ansible/modules/network/nxos/nxos_vtp_version.py
-lib/ansible/modules/network/nxos/nxos_vxlan_vtep.py
 lib/ansible/modules/network/nxos/nxos_vxlan_vtep_vni.py
 lib/ansible/modules/net_tools/omapi_host.py
 lib/ansible/modules/network/openswitch/_ops_template.py
diff --git a/test/units/modules/network/nxos/fixtures/nxos_vxlan_vtep/config.cfg b/test/units/modules/network/nxos/fixtures/nxos_vxlan_vtep/config.cfg
new file mode 100644
--- /dev/null
+++ b/test/units/modules/network/nxos/fixtures/nxos_vxlan_vtep/config.cfg
@@ -0,0 +1,2 @@
+interface nve1
+  member vni 6000
diff --git a/test/units/modules/network/nxos/test_nxos_vxlan_vtep.py b/test/units/modules/network/nxos/test_nxos_vxlan_vtep.py
new file mode 100644
--- /dev/null
+++ b/test/units/modules/network/nxos/test_nxos_vxlan_vtep.py
@@ -0,0 +1,62 @@
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import json
+
+from ansible.compat.tests.mock import patch
+from ansible.modules.network.nxos import nxos_vxlan_vtep
+from .nxos_module import TestNxosModule, load_fixture, set_module_args
+
+
+class TestNxosVxlanVtepVniModule(TestNxosModule):
+
+    module = nxos_vxlan_vtep
+
+    def setUp(self):
+        self.mock_load_config = patch('ansible.modules.network.nxos.nxos_vxlan_vtep.load_config')
+        self.load_config = self.mock_load_config.start()
+
+        self.mock_get_config = patch('ansible.modules.network.nxos.nxos_vxlan_vtep.get_config')
+        self.get_config = self.mock_get_config.start()
+
+    def tearDown(self):
+        self.mock_get_config.stop()
+        self.mock_load_config.stop()
+
+    def load_fixtures(self, commands=None, device=''):
+        self.get_config.return_value = load_fixture('nxos_vxlan_vtep/config.cfg')
+        self.load_config.return_value = None
+
+    def test_nxos_vxlan_vtep(self):
+        set_module_args(dict(interface='nve1', description='simple description'))
+        self.execute_module(changed=True, commands=['interface nve1', 'description simple description'])
+
+    def test_nxos_vxlan_vtep_present_no_change(self):
+        set_module_args(dict(interface='nve1'))
+        self.execute_module(changed=False, commands=[])
+
+    def test_nxos_vxlan_vtep_absent(self):
+        set_module_args(dict(interface='nve1', state='absent'))
+        self.execute_module(changed=True, commands=['no interface nve1'])
+
+    def test_nxos_vxlan_vtep_absent_no_change(self):
+        set_module_args(dict(interface='nve2', state='absent'))
+        self.execute_module(changed=False, commands=[])