Repository: ansible/ansible
Pull request: fix nxos_vpc_interface peer_link idempotence
##### SUMMARY
<!--- Describe the change, including rationale and design decisions -->
Fixes #35736
<!---
If you are fixing an existing issue, please include "Fixes #nnn" in your
commit message and your description; but you should still explain what
the change does.
-->

##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
 - Bugfix Pull Request

##### COMPONENT NAME
<!--- Name of the module, plugin, module or task -->
nxos_vpc_interface

##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes below -->
```
ansible 2.5.0 (devel 788010d0f0) last updated 2018/01/08 11:49:21 (GMT -400)
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /root/agents-ci/ansible/lib/ansible
  executable location = /root/agents-ci/ansible/bin/ansible
  python version = 2.7.6 (default, Oct 26 2016, 20:30:19) [GCC 4.8.4]
```


##### ADDITIONAL INFORMATION
* This PR fixes issues in #35736
* Integration test cases are enhanced for nxos_vpc_interface module to include all parameters
* Tested on all possible platforms and versions.

<!--- Paste verbatim command output below, e.g. before and after your change -->
```

```


Problem statement:
nxos_vpc_interface peer_link is not idempotent
<!---
Verify first that your issue/request is not already reported on GitHub.
Also test if the latest release, and master branch are affected too.
-->

##### ISSUE TYPE
<!--- Pick one below and delete the rest -->
 - Bug Report

##### COMPONENT NAME
<!---
Name of the module, plugin, task or feature
Do not include extra details here, e.g. "vyos_command" not "the network module vyos_command" or the full path
-->
nxos_vpc_Interface
##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes below -->
```
ansible 2.5.0 (devel 788010d0f0) last updated 2018/01/08 11:49:21 (GMT -400)
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /root/agents-ci/ansible/lib/ansible
  executable location = /root/agents-ci/ansible/bin/ansible
  python version = 2.7.6 (default, Oct 26 2016, 20:30:19) [GCC 4.8.4]
```

##### OS / ENVIRONMENT
<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say "N/A" for anything that is not platform-specific.
Also mention the specific version of what you are trying to control,
e.g. if this is a network bug the version of firmware on the network device.
-->
Ansible Server : Ubuntu 14.04
Device: N9K running 7.0(3)I5(2)

##### SUMMARY
<!--- Explain the problem briefly -->

If we set peer_link to False, it is not idempotent. Setting it to True is ok.

Note: I will open a PR shortly to address the above issue

Hints from issue discussion:

Commit message: fix peer_link idempotence

Patch to review:
diff --git a/lib/ansible/modules/network/nxos/nxos_vpc_interface.py b/lib/ansible/modules/network/nxos/nxos_vpc_interface.py
index cbf445d110c608..c228456fbc7285 100644
--- a/lib/ansible/modules/network/nxos/nxos_vpc_interface.py
+++ b/lib/ansible/modules/network/nxos/nxos_vpc_interface.py
@@ -194,11 +194,14 @@ def get_commands_to_config_vpc_interface(portchannel, delta, config_value, exist
     commands = []
 
     if delta.get('peer-link') is False and existing.get('peer-link') is True:
-        command = 'no vpc peer-link'
         commands.append('no vpc peer-link')
         commands.insert(0, 'interface port-channel{0}'.format(portchannel))
 
-    elif delta.get('peer-link') or not existing.get('vpc'):
+    elif delta.get('peer-link') and existing.get('peer-link') is not True:
+        commands.append('vpc peer-link')
+        commands.insert(0, 'interface port-channel{0}'.format(portchannel))
+
+    elif delta.get('vpc') and not existing.get('vpc'):
         command = 'vpc {0}'.format(config_value)
         commands.append(command)
         commands.insert(0, 'interface port-channel{0}'.format(portchannel))
diff --git a/test/integration/targets/nxos_vpc_interface/tests/common/sanity.yaml b/test/integration/targets/nxos_vpc_interface/tests/common/sanity.yaml
index fa05b915e4df95..749d4ae23050c3 100644
--- a/test/integration/targets/nxos_vpc_interface/tests/common/sanity.yaml
+++ b/test/integration/targets/nxos_vpc_interface/tests/common/sanity.yaml
@@ -10,7 +10,7 @@
       state: enabled
       provider: "{{ connection }}"
 
-  - name: create port-channel
+  - name: create port-channel10
     nxos_config:
       commands:
         - interface port-channel10
@@ -18,6 +18,14 @@
       match: none
       provider: "{{ connection }}"
 
+  - name: create port-channel11
+    nxos_config:
+      commands:
+        - interface port-channel11
+        - switchport
+      match: none
+      provider: "{{ connection }}"
+
   - name: configure vpc
     nxos_vpc:
       state: present
@@ -33,7 +41,7 @@
   - name: Configure vpc port channel
     nxos_vpc_interface: &conf
       portchannel: 10
-      vpc: 100
+      vpc: 10
       provider: "{{ connection }}"
     register: result
 
@@ -49,10 +57,40 @@
       that:
         - "result.changed == false"
 
+  - name: Configure vpc port channel
+    nxos_vpc_interface: &conf1
+      portchannel: 11
+      peer_link: True
+      provider: "{{ connection }}"
+    register: result
+
+  - assert: *true
+
+  - name: "Conf Idempotence"
+    nxos_vpc_interface: *conf1
+    register: result
+
+  - assert: *false
+
+  - name: Configure vpc port channel
+    nxos_vpc_interface: &conf2
+      portchannel: 11
+      peer_link: False
+      provider: "{{ connection }}"
+    register: result
+
+  - assert: *true
+
+  - name: "Conf Idempotence"
+    nxos_vpc_interface: *conf2
+    register: result
+
+  - assert: *false
+
   - name: remove vpc port channel
     nxos_vpc_interface: &remove
       portchannel: 10
-      vpc: 100
+      vpc: 10
       state: absent
       provider: "{{ connection }}"
     register: result
@@ -82,7 +120,7 @@
   - name: remove vpc port channel
     nxos_vpc_interface:
       portchannel: 10
-      vpc: 100
+      vpc: 10
       state: absent
       provider: "{{ connection }}"
     ignore_errors: yes
@@ -91,6 +129,7 @@
     nxos_config:
       commands:
         - no interface port-channel10
+        - no interface port-channel11
       match: none
       provider: "{{ connection }}"
     ignore_errors: yes


Code review comments:
diff_hunk: @@ -194,11 +194,14 @@ def get_commands_to_config_vpc_interface(portchannel, delta, config_value, exist
     commands = []
 
     if delta.get('peer-link') is False and existing.get('peer-link') is True:
path: lib/ansible/modules/network/nxos/nxos_vpc_interface.py
text: @user1:
Modify this one as well? `if not delta.get('peer-link') and existing.get('peer-link'):`

diff_hunk: @@ -194,11 +194,14 @@ def get_commands_to_config_vpc_interface(portchannel, delta, config_value, exist
     commands = []
 
     if delta.get('peer-link') is False and existing.get('peer-link') is True:
-        command = 'no vpc peer-link'
         commands.append('no vpc peer-link')
         commands.insert(0, 'interface port-channel{0}'.format(portchannel))
 
-    elif delta.get('peer-link') or not existing.get('vpc'):
+    elif delta.get('peer-link') and existing.get('peer-link') is not True:
path: lib/ansible/modules/network/nxos/nxos_vpc_interface.py
text: @user1:
Please modify this to `elif delta.get('peer-link') and not existing.get('peer-link'):`