Repository: ansible/ansible

Issue:
NXOS Facts error
<!---
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
**nxos_facts**

##### ANSIBLE VERSION
<!--- Paste verbatim output from “ansible --version” between quotes below -->
```
ansible 2.3.1.0
  config file = /home/ansible/ansible.cfg
  configured module search path = Default w/o overrides
  python version = 2.7.5 (default, Nov  6 2016, 00:28:07) [GCC 4.8.5 20150623 (Red Hat 4.8.5-11)]

```

##### CONFIGURATION
<!---
```
- nxos_facts:
     gather_subset: all
```
-->

##### OS / ENVIRONMENT
NXOS

##### SUMMARY
There is a parsing problem in line 352 of ansible_module_nxos_facts.py when parsing parse_ipv6_interfaces. In my case the output of `show ipv6 interface` is empty.

##### STEPS TO REPRODUCE
just run `nxos_facts` to gather all subsets.

<!--- Paste example playbooks or commands between quotes below -->
```yaml
- nxos_facts:
     gather_subset: all
```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
To gather all facts from the box.
##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes below -->
```
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: TypeError: string indices must be integers, not str
fatal: [N9396-Leaf1]: FAILED! => {"changed": false, "failed": true, "module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_Lull7D/ansible_module_nxos_facts.py\", line 530, in <module>\n    main()\n  File \"/tmp/ansible_Lull7D/ansible_module_nxos_facts.py\", line 513, in main\n    inst.populate()\n  File \"/tmp/ansible_Lull7D/ansible_module_nxos_facts.py\", line 294, in populate\n    self.parse_ipv6_interfaces(data)\n  File \"/tmp/ansible_Lull7D/ansible_module_nxos_facts.py\", line 352, in parse_ipv6_interfaces\n    data = data['TABLE_intf']\nTypeError: string indices must be integers, not str\n", "module_stdout": "", "msg": "MODULE FAILURE", "rc": 0}
	to retry, use: --limit @/home/ansible/playbook.retry

```



Discussion:
cc @GGabriele @jedelman8 @mikewiebe @privateip @rahushen @rcarrillocruz @trishnaguha
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
@rogerscuall this is fixed in 2.4 and devel. Closing the issue.
https://groups.google.com/forum/#!topic/ansible-project/A946L8Jlf_0
Hi @trishnaguha, I don't think is solved just tested in version 2.4 exactly the same problem. This is very particular to this module.
Looks to me the problem is that there is a check missing somewhere for when there is no IPv6 address configured on the system. Once I added an IPv6 address in one interface, I got no errors.

Resolving patch:
diff --git a/lib/ansible/modules/network/nxos/nxos_facts.py b/lib/ansible/modules/network/nxos/nxos_facts.py
--- a/lib/ansible/modules/network/nxos/nxos_facts.py
+++ b/lib/ansible/modules/network/nxos/nxos_facts.py
@@ -348,14 +348,20 @@ def populate_neighbors(self, data):
         return objects
 
     def parse_ipv6_interfaces(self, data):
-        data = data['TABLE_intf']
-        if isinstance(data, dict):
-            data = [data]
-        for item in data:
-            name = item['ROW_intf']['intf-name']
-            intf = self.facts['interfaces'][name]
-            intf['ipv6'] = self.transform_dict(item, self.INTERFACE_IPV6_MAP)
-            self.facts['all_ipv6_addresses'].append(item['ROW_intf']['addr'])
+        try:
+            data = data['TABLE_intf']
+            if data:
+                if isinstance(data, dict):
+                    data = [data]
+                for item in data:
+                    name = item['ROW_intf']['intf-name']
+                    intf = self.facts['interfaces'][name]
+                    intf['ipv6'] = self.transform_dict(item, self.INTERFACE_IPV6_MAP)
+                    self.facts['all_ipv6_addresses'].append(item['ROW_intf']['addr'])
+            else:
+                return ""
+        except TypeError:
+            return ""
 
 
 class Legacy(FactsBase):


Test patch: