Repository: ansible/ansible

Issue:
ios_facts: Tunnel interface MAC address shows IP address/Prefix
<!---
Verify first that your issue/request is not already reported on GitHub.
THIS FORM WILL BE READ BY A MACHINE, COMPLETE ALL SECTIONS AS DESCRIBED.
Also test if the latest release, and devel branch are affected too.
ALWAYS add information AFTER (OUTSIDE) these html comments.
Otherwise it may end up being automatically closed by our bot. -->

##### SUMMARY
<!--- Explain the problem briefly -->
When running ios_facts to gather information on interfaces, a tunnel interface MAC address shows up as a IP address/prefix, such as `10.10.10.1/30` instead of null

##### ISSUE TYPE
 - 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-->
ios_facts

##### ANSIBLE VERSION
<!--- Paste, BELOW THIS COMMENT, verbatim output from "ansible --version" between quotes below -->
```
ansible --version
ansible 2.5.3
  config file = ../Documents/Ansible/ansible.cfg
  configured module search path = [u'../Documents/Ansible/library']
  ansible python module location = /Library/Python/2.7/site-packages/ansible
  executable location = /usr/local/bin/ansible
  python version = 2.7.10 (default, Oct  6 2017, 22:29:07) [GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.31)]
```

##### CONFIGURATION
<!--- If using Ansible 2.4 or above, paste, BELOW THIS COMMENT, the results of "ansible-config dump --only-changed"
Otherwise, mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).-->
```
ANSIBLE_SSH_ARGS(../Documents/Ansible/ansible.cfg) = -o ControlMaster=auto -o ControlPersist=60s -o UserKnownHostsFile=
DEFAULT_MODULE_PATH(/Users/jvanderaa/Documents/Ansible/ansible.cfg) = [u'../Documents/Ansible/library']
HOST_KEY_CHECKING(../Documents/Ansible/ansible.cfg) = False
```
##### OS / ENVIRONMENT
<!--- Mention, BELOW THIS COMMENT, 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.-->
MacOS --> IOS

##### 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. -->

<!--- Paste example playbooks or commands between quotes below -->
```yaml
- name: Check facts
  connection: network_cli
  hosts: ios
  gather_facts: no
  become: yes
  become_method: enable

  tasks:
    - name: IOS>> Get facts
      ios_facts:
        gather_subset: all

    - name: DEBUG>> Print facts
      debug:
        msg: "{{ ansible_net_interfaces }}"
```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
The information looks correct on physical interfaces. Virtual tunnel interfaces (`interface tunnel`) shows information that shouldn't be there.

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes below -->
```
        "GigabitEthernet0/2": {
            "bandwidth": 1000000,
            "description": "Trunk to sw01 (Gi1/0/48)",
            "duplex": "Full",
            "ipv4": [],
            "lineprotocol": "up ",
            "macaddress": "a0e0.afbe.cf82",
            "mediatype": "RJ45",
            "mtu": 1500,
            "operstatus": "up",
            "type": "CN Gigabit Ethernet"
        },
        "Tunnel1110": {
            "bandwidth": 100,
            "description": "IPSec VTI",
            "duplex": null,
            "ipv4": [
                {
                    "address": "10.10.10.2",
                    "subnet": "30"
                }
            ],
            "lineprotocol": "up ",
            "macaddress": "10.10.10.2/30",
            "mediatype": null,
            "mtu": 17878,
            "operstatus": "up",
            "type": null
        }

```



Discussion:
Files identified in the description:
* [lib/ansible/modules/network/ios/ios_facts.py](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/network/ios/ios_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 @privateip @rcarrillocruz
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
I dug a little bit into the .py file referenced by the bot. Perhaps changing the search string to `, address is` may be able to catch a MAC address better. Not sure if that would hurt other interfaces if the modification is made unfortunately.

**Hardware Interface**
```
GigabitEthernet0/0 is up, line protocol is up
  Hardware is CN Gigabit Ethernet, address is a44c.1167.c520 (bia a44c.1167.c520)
```
**Tunnel Interface**
```
Tunnel1310 is up, line protocol is up
  Hardware is Tunnel
  Internet address is 10.10.10.2/30
```

Resolving patch:
diff --git a/lib/ansible/modules/network/ios/ios_facts.py b/lib/ansible/modules/network/ios/ios_facts.py
--- a/lib/ansible/modules/network/ios/ios_facts.py
+++ b/lib/ansible/modules/network/ios/ios_facts.py
@@ -379,7 +379,7 @@ def parse_description(self, data):
             return match.group(1)
 
     def parse_macaddress(self, data):
-        match = re.search(r'address is (\S+)', data)
+        match = re.search(r'Hardware is (?:.*), address is (\S+)', data)
         if match:
             return match.group(1)
 


Test patch:
diff --git a/test/units/modules/network/ios/fixtures/ios_facts_show_interfaces b/test/units/modules/network/ios/fixtures/ios_facts_show_interfaces
new file mode 100644
--- /dev/null
+++ b/test/units/modules/network/ios/fixtures/ios_facts_show_interfaces
@@ -0,0 +1,61 @@
+GigabitEthernet0/0 is up, line protocol is up 
+  Hardware is iGbE, address is 5e00.0003.0000 (bia 5e00.0003.0000)
+  Description: OOB Management
+  Internet address is 10.8.38.66/24
+  MTU 1500 bytes, BW 1000000 Kbit/sec, DLY 10 usec, 
+     reliability 253/255, txload 1/255, rxload 1/255
+  Encapsulation ARPA, loopback not set
+  Keepalive set (10 sec)
+  Full Duplex, Auto Speed, link type is auto, media type is RJ45
+  output flow-control is unsupported, input flow-control is unsupported
+  ARP type: ARPA, ARP Timeout 04:00:00
+  Last input 00:00:00, output 00:00:00, output hang never
+  Last clearing of "show interface" counters never
+  Input queue: 0/75/0/0 (size/max/drops/flushes); Total output drops: 0
+  Queueing strategy: fifo
+  Output queue: 0/40 (size/max)
+  5 minute input rate 3000 bits/sec, 2 packets/sec
+  5 minute output rate 2000 bits/sec, 2 packets/sec
+     2226666 packets input, 398288440 bytes, 0 no buffer
+     Received 156442 broadcasts (0 IP multicasts)
+     25440 runts, 0 giants, 0 throttles 
+     25440 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored
+     0 watchdog, 0 multicast, 0 pause input
+     1304895 packets output, 119337031 bytes, 0 underruns
+     0 output errors, 0 collisions, 3 interface resets
+     1083697 unknown protocol drops
+     0 babbles, 0 late collision, 0 deferred
+     1 lost carrier, 0 no carrier, 0 pause output
+     0 output buffer failures, 0 output buffers swapped out
+GigabitEthernet1 is up, line protocol is up
+  Hardware is CSR vNIC, address is 5e00.0006.0000 (bia 5e00.0006.0000)
+  Description: OOB Management
+  Internet address is 10.8.38.67/24
+  MTU 1500 bytes, BW 1000000 Kbit/sec, DLY 10 usec,
+     reliability 255/255, txload 1/255, rxload 1/255
+  Encapsulation ARPA, loopback not set
+  Keepalive set (10 sec)
+  Full Duplex, 1000Mbps, link type is auto, media type is RJ45
+  output flow-control is unsupported, input flow-control is unsupported
+  ARP type: ARPA, ARP Timeout 04:00:00
+  Last input 00:00:01, output 00:00:07, output hang never
+  Last clearing of "show interface" counters never
+  Input queue: 0/375/0/0 (size/max/drops/flushes); Total output drops: 0
+  Queueing strategy: fifo
+  Output queue: 0/40 (size/max)
+  5 minute input rate 3000 bits/sec, 3 packets/sec
+  5 minute output rate 3000 bits/sec, 3 packets/sec
+     8463791 packets input, 1445150230 bytes, 0 no buffer
+     Received 0 broadcasts (0 IP multicasts)
+     0 runts, 0 giants, 0 throttles
+     0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored
+     0 watchdog, 0 multicast, 0 pause input
+     3521571 packets output, 348781823 bytes, 0 underruns
+     0 output errors, 0 collisions, 1 interface resets
+     4150764 unknown protocol drops
+     0 babbles, 0 late collision, 0 deferred
+     0 lost carrier, 0 no carrier, 0 pause output
+     0 output buffer failures, 0 output buffers swapped out
+Tunnel1110 is up, line protocol is up
+  Hardware is Tunnel
+  Internet address is 10.10.10.2/30
diff --git a/test/units/modules/network/ios/fixtures/ios_facts_show_ip_interface b/test/units/modules/network/ios/fixtures/ios_facts_show_ip_interface
new file mode 100644
diff --git a/test/units/modules/network/ios/fixtures/ios_facts_show_ipv6_interface b/test/units/modules/network/ios/fixtures/ios_facts_show_ipv6_interface
new file mode 100644
diff --git a/test/units/modules/network/ios/fixtures/ios_facts_show_lldp b/test/units/modules/network/ios/fixtures/ios_facts_show_lldp
new file mode 100644
diff --git a/test/units/modules/network/ios/test_ios_facts.py b/test/units/modules/network/ios/test_ios_facts.py
--- a/test/units/modules/network/ios/test_ios_facts.py
+++ b/test/units/modules/network/ios/test_ios_facts.py
@@ -64,3 +64,16 @@ def test_ios_facts_stacked(self):
         self.assertEqual(
             result['ansible_facts']['ansible_net_stacked_serialnums'], ['CAT0726R0ZU', 'CAT0726R10A', 'CAT0732R0M4']
         )
+
+    def test_ios_facts_tunnel_address(self):
+        set_module_args(dict(gather_subset='interfaces'))
+        result = self.execute_module()
+        self.assertEqual(
+            result['ansible_facts']['ansible_net_interfaces']['GigabitEthernet0/0']['macaddress'], '5e00.0003.0000'
+        )
+        self.assertEqual(
+            result['ansible_facts']['ansible_net_interfaces']['GigabitEthernet1']['macaddress'], '5e00.0006.0000'
+        )
+        self.assertIsNone(
+            result['ansible_facts']['ansible_net_interfaces']['Tunnel1110']['macaddress']
+        )