Repository: ansible/ansible

Issue:
iosxr_facts can't parse interface duplex status on ARS9001 and 9904 with older firmware
<!---
Verify first that your issue/request is not already reported on GitHub.
Also test if the latest release, and devel branch are affected too.
Always add information AFTER of these html comments.
-->

##### ISSUE TYPE
<!--- Pick one below and delete the rest -->
 - Bug Report

##### COMPONENT NAME
<!---
Insert below this comment the 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
-->
iosxr_facts

##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes below -->
```
ansible 2.4.3.0
  config file = /home/deussers/bbiptesting/ansible.cfg
  configured module search path = [u'/home/deussers/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/dist-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.13 (default, Jan 19 2017, 14:48:08) [GCC 6.3.0 20170118]
```

##### 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.
-->
Managed Systems are ASR 9001 and ASR 9904 running on IOS XR version 5.3.2

##### SUMMARY
<!--- Explain the problem briefly -->
iosxr_facts doesn't parse duplex information correctly on ASR9001 and ASR9904. On every interface it only lists "duplex: null". I took a look at iosxr_facts.py, the problem is the regex in parse_duplex(self, data), it's `re.search(r'(\w+) Duplex', data, re.M)`. But the lines with duplex in our show interfaces output read i.e. `  Full-duplex, 1000Mb/s, link type is force-up`. Our IOS XR version is not the freshest (5.3.2 on both models), so perhaps that changed in newer versions. But it probably wouldn't hurt to make the regex a bit more flexible. As that part of iosxr_facts.py is still the same in the development version of Ansible it should be the same problem there.

##### STEPS TO REPRODUCE
<!---
For bugs, show exactly how to reproduce the problem, using a minimal test-case.
For new features, show how the feature would be used.
-->
Gather facts with iosxr_facts from a ASR9001 or 9904 (or probably other models) with firmware version 5.3.2 and look at the values for duplex in ansible_net_interfaces.
<!--- Paste example playbooks or commands between quotes below -->
```yaml

```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
Correct duplex values in ansible_net_interfaces.

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->
All duplex values in ansible_net_interfaces are "null".
<!--- Paste verbatim command output between quotes below -->
```

```



Discussion:
Files identified in the description:
* [lib/ansible/modules/network/iosxr/iosxr_facts.py](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/network/iosxr/iosxr_facts.py)

If these files are inaccurate, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
cc @gdpak @privateip @rcarrillocruz
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->

Resolving patch:
diff --git a/lib/ansible/modules/network/iosxr/iosxr_facts.py b/lib/ansible/modules/network/iosxr/iosxr_facts.py
--- a/lib/ansible/modules/network/iosxr/iosxr_facts.py
+++ b/lib/ansible/modules/network/iosxr/iosxr_facts.py
@@ -307,7 +307,7 @@ def parse_bandwidth(self, data):
             return int(match.group(1))
 
     def parse_duplex(self, data):
-        match = re.search(r'(\w+) Duplex', data, re.M)
+        match = re.search(r'(\w+)(?: D|-d)uplex', data, re.M)
         if match:
             return match.group(1)
 


Test patch: