Repository: ansible/ansible

Issue:
Ansible v2  get_distribution_facts errors on coreos
<!--- Verify first that your issue/request is not already reported in GitHub -->
##### ISSUE TYPE

<!--- Pick one below and delete the rest: -->
- Bug Report
##### ANSIBLE VERSION

```
/srv/ansible-coreos # ansible --version
ansible 2.0.1.0 (detached HEAD bb6cadefa2) last updated 2016/02/25 09:21:00 (GMT +000)
  lib/ansible/modules/core: (detached HEAD 262e2a3302) last updated 2016/02/25 09:21:03 (GMT +000)
  lib/ansible/modules/extras: (detached HEAD e0be11da08) last updated 2016/02/25 09:21:06 (GMT +000)
  config file = /srv/ansible-coreos/ansible.cfg
  configured module search path = /opt/ansible/ansible/library
```
##### CONFIGURATION

This works in ansible 1.9.X but not in 2.X
##### OS / ENVIRONMENT

CoreOs - contents of /etc/os-release
NAME=CoreOS
ID=coreos
VERSION=976.0.0
VERSION_ID=976.0.0
BUILD_ID=2016-03-03-2324
PRETTY_NAME="CoreOS 976.0.0 (Coeur Rouge)"
ANSI_COLOR="1;32"
HOME_URL="https://coreos.com/"
BUG_REPORT_URL="https://github.com/coreos/bugs/issues"
##### SUMMARY

The updated facts.py for ansible v2 expects the file /etc/coreos/update.conf to exist.  This file only exists if the host is set to autoupdate itself.    As seen here
https://github.com/ansible/ansible/blob/devel/lib/ansible/module_utils/facts.py#L521-L522

It looks like the call to re.search("^GROUP=(.*)", data) is sending null data to the search method which ends up puking.   Here is the relevant piece of the error from running on a coreos node that doesn't have /etc/coreos/update.conf

```
self.get_distribution_facts()\r\n  File \"/home/core/.ansible/tmp/ansible-tmp-1459457632.46-56924359125586/setup\", line 2607, in get_distribution_facts\r\n    release = re.search(\"^GROUP=(.*)\", data)\r\n  File \"/opt/pypy/lib-python/2.7/re.py\", line 143, in search\r\n    print 'The value of string is ' + string\r\nTypeError: unsupported operand type(s) for +: 'str' and 'NoneType'\r\n",
    "msg": "MODULE FAILURE",
    "parsed": false
}
```
##### STEPS TO REPRODUCE

Run ansible setup on a coreos node that doesn't auto update

ansible all -i inventory/hosts -m setup

<!---
For bugs, show exactly how to reproduce the problem.
For new features, show how the feature would be used.
-->

```
<!--- Paste example playbooks or commands between quotes -->
```

<!--- You can also paste gist.github.com links for larger files -->
##### EXPECTED RESULTS

<!--- What did you expect to happen when running the steps above? -->

iicv00283.phx1.jivehosted.com | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "172.17.0.1",
            "10.190.92.102"
        ],
        "ansible_all_ipv6_addresses": [
            "fe80::250:56ff:fea7:61b0"
        ],
        "ansible_architecture": "x86_64",
        "ansible_bios_date": "09/30/2014",
        "ansible_bios_version": "6.00",
        "ansible_cmdline": {
            "BOOTIF": "01-00-50-56-a7-61-b0",
            "cloud-config-url": "http://10.160.113.14/tftpboot/xcat/netboot/coreos/cloud-config-common.yaml",
            "console": "ttyS1",
            "coreos.autologin": "ttyS1",
            "mount.usrflags": "ro",
            "rootflags": "rw"
        },
        "ansible_date_time": {
            "date": "2016-03-31",
            "day": "31",
            "epoch": "1459457707",
            "hour": "20",
            "iso8601": "2016-03-31T20:55:07Z",
            "iso8601_basic": "20160331T205507216468",
            "iso8601_basic_short": "20160331T205507",
            "iso8601_micro": "2016-03-31T20:55:07.217120Z",
            "minute": "55",
            "month": "03",
            "second": "07",
            "time": "20:55:07",
            "tz": "UTC",
            "tz_offset": "+0000",
            "weekday": "Thursday",
            "weekday_number": "4",
            "weeknumber": "13",
            "year": "2016"
        },
        "ansible_default_ipv4": {
            "address": "10.190.92.102",
            "alias": "ens192",
            "broadcast": "10.190.93.255",
            "gateway": "10.190.92.1",
            "interface": "ens192",
            "macaddress": "00:50:56:a7:61:b0",
            "mtu": 1500,
            "netmask": "255.255.254.0",
            "network": "10.190.92.0",
            "type": "ether"
        },
        "ansible_default_ipv6": {},
        "ansible_devices": {
            "sda": {
                "holders": [],
                "host": "Serial Attached SCSI controller: VMware PVSCSI SCSI Controller (rev 02)",
                "model": "Virtual disk",
                "partitions": {
                    "sda1": {
                        "sectors": "167770112",
                        "sectorsize": 512,
                        "size": "80.00 GB",
                        "start": "2048"
                    }
                },
                "removable": "0",
                "rotational": "1",
                "scheduler_mode": "cfq",
                "sectors": "167772160",
                "sectorsize": "512",
                "size": "80.00 GB",
                "support_discard": "0",
                "vendor": "VMware"
            },
            "sr0": {
                "holders": [],
                "host": "IDE interface: Intel Corporation 82371AB/EB/MB PIIX4 IDE (rev 01)",
                "model": "VMware IDE CDR10",
                "partitions": {},
                "removable": "1",
                "rotational": "1",
                "scheduler_mode": "cfq",
                "sectors": "2097151",
                "sectorsize": "512",
                "size": "1024.00 MB",
                "support_discard": "0",
                "vendor": "NECVMWar"
            }
        },
        "ansible_distribution": "CoreOS",
        "ansible_distribution_major_version": "NA",
        "ansible_distribution_release": "NA",
        "ansible_distribution_version": "976.0.0",
        "ansible_dns": {
            "domain": "phx1.jivehosted.com",
            "nameservers": [
                "10.160.112.11"
            ]
        },
        "ansible_docker0": {
            "active": false,
            "device": "docker0",
            "id": "8000.02421030b906",
            "interfaces": [],
            "ipv4": {
                "address": "172.17.0.1",
                "broadcast": "global",
                "netmask": "255.255.0.0",
                "network": "172.17.0.0"
            },
            "macaddress": "02:42:10:30:b9:06",
            "mtu": 1500,
            "promisc": false,
            "stp": false,
            "type": "bridge"
        },
        "ansible_domain": "phx1.jivehosted.com",
        "ansible_ens192": {
            "active": true,
            "device": "ens192",
            "ipv4": {
                "address": "10.190.92.102",
                "broadcast": "10.190.93.255",
                "netmask": "255.255.254.0",
                "network": "10.190.92.0"
            },
            "ipv6": [
                {
                    "address": "fe80::250:56ff:fea7:61b0",
                    "prefix": "64",
                    "scope": "link"
                }
            ],
            "macaddress": "00:50:56:a7:61:b0",
            "module": "vmxnet3",
            "mtu": 1500,
            "pciid": "0000:0b:00.0",
            "promisc": false,
            "type": "ether"
        },
        "ansible_env": {
            "HOME": "/home/core",
            "LANG": "C",
            "LC_ALL": "C",
            "LC_MESSAGES": "C",
            "LD_LIBRARY_PATH": "/opt/pypy/lib:",
            "LOGNAME": "core",
            "MAIL": "/var/mail/core",
            "PATH": "/opt/bin:/usr/bin:/bin:/usr/sbin:/sbin",
            "PWD": "/home/core",
            "SHELL": "/bin/bash",
            "SHLVL": "2",
            "SSH_CLIENT": "10.190.92.102 58946 22",
            "SSH_CONNECTION": "10.190.92.102 58946 10.190.92.102 22",
            "SSH_TTY": "/dev/pts/2",
            "TERM": "xterm",
            "USER": "core",
            "_": "/opt/bin/python"
        },
        "ansible_fips": false,
        "ansible_form_factor": "Other",
        "ansible_fqdn": "iicv00283.phx1.jivehosted.com",
        "ansible_hostname": "iicv00283",
        "ansible_interfaces": [
            "lo",
            "ens192",
            "docker0"
        ],
        "ansible_kernel": "4.4.3-coreos",
        "ansible_lo": {
            "active": true,
            "device": "lo",
            "ipv4": {
                "address": "127.0.0.1",
                "broadcast": "host",
                "netmask": "255.0.0.0",
                "network": "127.0.0.0"
            },
            "ipv6": [
                {
                    "address": "::1",
                    "prefix": "128",
                    "scope": "host"
                }
            ],
            "mtu": 65536,
            "promisc": false,
            "type": "loopback"
        },
        "ansible_lsb": {
            "codename": "\"Coeur Rouge\"",
            "description": "\"CoreOS 976.0.0 (Coeur Rouge)\"",
            "id": "CoreOS",
            "major_release": "976",
            "release": "976.0.0"
        },
        "ansible_machine": "x86_64",
        "ansible_machine_id": "e05ae7371ccb4d1fb24a58f30d068d55",
        "ansible_memfree_mb": 6403,
        "ansible_memory_mb": {
            "nocache": {
                "free": 7508,
                "used": 476
            },
            "real": {
                "free": 6403,
                "total": 7984,
                "used": 1581
            },
            "swap": {
                "cached": 0,
                "free": 0,
                "total": 0,
                "used": 0
            }
        },
        "ansible_memtotal_mb": 7984,
        "ansible_mounts": [
            {
                "device": "/dev/loop0",
                "fstype": "squashfs",
                "mount": "/usr",
                "options": "ro,seclabel,relatime",
                "size_available": 0,
                "size_total": 210763776,
                "uuid": ""
            },
            {
                "device": "/dev/sda1",
                "fstype": "ext4",
                "mount": "/var/lib/docker",
                "options": "rw,seclabel,relatime,data=ordered",
                "size_available": 70288629760,
                "size_total": 80389783552,
                "uuid": "a4121eba-ae66-42b7-96be-51ec45801e77"
            }
        ],
        "ansible_nodename": "iicv00283",
        "ansible_os_family": "CoreOS",
        "ansible_pkg_mgr": "unknown",
        "ansible_processor": [
            "GenuineIntel",
            "Intel(R) Xeon(R) CPU E5-2660 0 @ 2.20GHz",
            "GenuineIntel",
            "Intel(R) Xeon(R) CPU E5-2660 0 @ 2.20GHz",
            "GenuineIntel",
            "Intel(R) Xeon(R) CPU E5-2660 0 @ 2.20GHz",
            "GenuineIntel",
            "Intel(R) Xeon(R) CPU E5-2660 0 @ 2.20GHz"
        ],
        "ansible_processor_cores": 1,
        "ansible_processor_count": 4,
        "ansible_processor_threads_per_core": 1,
        "ansible_processor_vcpus": 4,
        "ansible_product_name": "VMware Virtual Platform",
        "ansible_product_serial": "NA",
        "ansible_product_uuid": "NA",
        "ansible_product_version": "None",
        "ansible_python_version": "2.7.8",
        "ansible_selinux": false,
        "ansible_service_mgr": "systemd",
        "ansible_ssh_host_key_dsa_public": "AAAAB3NzaC1kc3MAAACBAOhLIBqR9Qgv/RiGjjBvbCqpfgvvtafvUWx+Cn4MM0ysLyyNNLrLQ1aPPF2hem1ss6JW0YftqbtAKG7Yd/3g4zHpEbu97gU7qBo6EezcRREhiJO7kUJ+wpTKIVxQVKWGorE6ZOZSlzopl0LfNPou85wgi2imt0Jdw4hrjmgKp6xfAAAAFQDXU5tgw4RlEUji11/v7yiZZOfchQAAAIEAmKFiRedvJl2e2YbYo9COQCTBOH97w4BAcYKqgjzaMWP9TzlENQJxMkveHGLst5c17Y1Tiwb2JXH51lewdXcrvtTSccb25vZ8cC5d7XiyfDKWHfBJ6WppL2kwZ/nDSHY2gszaOdXfn0aKAMMZSnwYupr9XLr0XjMFzIwswpo38xMAAACAOyL9Ib2BFbKJrUv+o2S33Nyr+gxeTVqwwiaF+XLVDrf/pH/aK+qC3gEw15zRRSIQfDz1AHc4vUMoYIwVemvDZyRYHUSYSrjSyu2REey500dLpC7cY59qn+Uls2MoUywXJiMS8oK4L4m5hqovV00o3LhjNKWNdsKbOg1K9gUlLEM=",
        "ansible_ssh_host_key_ecdsa_public": "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBCiot58LsxbjEabWbevB96aS3B06OIgLeJfAegcDqzZ/WJlvN1N2oqOLcLk6/cjnrkUlcMSFPCjTYP5WPlkLPP4=",
        "ansible_ssh_host_key_ed25519_public": "AAAAC3NzaC1lZDI1NTE5AAAAIHys7Fk0W3L5Ucm7OHt4VeFo5scCiDFn0pAzOY84u8qS",
        "ansible_ssh_host_key_rsa_public": "AAAAB3NzaC1yc2EAAAADAQABAAABAQDabMezIhJ/hzG+83sXIVLwnNOMhvKgn+x2+EiKIb9i2RIxTrJi7UJ2fwj7RSW6P4tBWz+9OcCj7rpq+FSz3mHkBMIiX3GfISlAwn56iMv5iOnYD2q185WHJpHdGXbtJGC6YPGNUFTPNGapjTv67RYGdiz44BxAlXeXdy2FL/H9QNfyBSDQSRE9Y767JKrizQvCAk59/RfYlklY3O/S8B3pc+/VYrLqy7jhvuXhhxoMqXgxoyTFovWobAHwClWtoqbMJ/YRMVi4GG+UUvem6BlnG8UoQK2CJCcGvZsvMrslynNAH6pXYNvsQnAvKoeBtMNpzp5yEeHBZPWLP1IsaSgB",
        "ansible_swapfree_mb": 0,
        "ansible_swaptotal_mb": 0,
        "ansible_system": "Linux",
        "ansible_system_vendor": "VMware, Inc.",
        "ansible_uptime_seconds": 12779,
        "ansible_user_dir": "/home/core",
        "ansible_user_gecos": "CoreOS Admin",
        "ansible_user_gid": 500,
        "ansible_user_id": "core",
        "ansible_user_shell": "/bin/bash",
        "ansible_user_uid": 500,
        "ansible_userspace_architecture": "x86_64",
        "ansible_userspace_bits": "64",
        "ansible_virtualization_role": "guest",
        "ansible_virtualization_type": "VMware",
        "module_setup": true
    },
    "changed": false
}
##### ACTUAL RESULTS

<!--- What actually happened? If possible run with high verbosity (-vvvv) -->

```
iicv00283.phx1.jivehosted.com | FAILED! => {
    "changed": false,
    "failed": true,
    "module_stderr": "",
    "module_stdout": "/bin/bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)\r\n/opt/pypy/bin/pypy: /lib64/libssl.so.1.0.0: no version information available (required by /opt/pypy/bin/pypy)\r\n/opt/pypy/bin/pypy: /lib64/libcrypto.so.1.0.0: no version information available (required by /opt/pypy/bin/pypy)\r\n/bin/sh: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)\r\nThe value of pattern is \\s+(libc\\.[^\\s]+)\\s+\\(libc6,x86-64\r\nThe value of string is 260 libs found in cache `/etc/ld.so.cache'\r\n\tlibz.so.1 (libc6,x86-64) => /lib64/libz.so.1\r\n\tlibxtables.so.10 (libc6,x86-64) => /lib64/libxtables.so.10\r\n\tlibxml2.so.2 (libc6,x86-64) => /lib64/libxml2.so.2\r\n\tlibxml2.so (libc6,x86-64) => /lib64/libxml2.so\r\n\tlibxlog.so.0 (libc6,x86-64) => /lib64/libxlog.so.0\r\n\tlibxfs.so.0 (libc6,x86-64) => /lib64/libxfs.so.0\r\n\tlibxenstore.so.3.0 (libc6,x86-64) => /lib64/libxenstore.so.3.0\r\n\tlibxenstore.so (libc6,x86-64) => /lib64/libxenstore.so\r\n\tlibxcmd.so.0 (libc6,x86-64) => /lib64/libxcmd.so.0\r\n\tlibxcmd.so (libc6,x86-64) => /lib64/libxcmd.so\r\n\tlibvtv.so.0 (libc6,x86-64) => /lib64/libvtv.so.0\r\n\tlibvtv.so (libc6,x86-64) => /lib64/libvtv.so\r\n\tlibuuid.so.1 (libc6,x86-64) => /lib64/libuuid.so.1\r\n\tlibutil.so.1 (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libutil.so.1\r\n\tlibutil.so (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libutil.so\r\n\tlibustr-1.0.so.1 (libc6,x86-64) => /lib64/libustr-1.0.so.1\r\n\tlibustr-1.0.so (libc6,x86-64) => /lib64/libustr-1.0.so\r\n\tlibusb-1.0.so.0 (libc6,x86-64) => /lib64/libusb-1.0.so.0\r\n\tlibudev.so.1 (libc6,x86-64) => /lib64/libudev.so.1\r\n\tlibudev.so (libc6,x86-64) => /lib64/libudev.so\r\n\tlibtspi.so.1 (libc6,x86-64) => /lib64/libtspi.so.1\r\n\tlibtspi.so (libc6,x86-64) => /lib64/libtspi.so\r\n\tlibtirpc.so.1 (libc6,x86-64) => /lib64/libtirpc.so.1\r\n\tlibthread_db.so.1 (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libthread_db.so.1\r\n\tlibthread_db.so (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libthread_db.so\r\n\tlibsystemd.so.0 (libc6,x86-64) => /lib64/libsystemd.so.0\r\n\tlibsystemd.so (libc6,x86-64) => /lib64/libsystemd.so\r\n\tlibstdc++.so.6 (libc6,x86-64) => /lib64/libstdc++.so.6\r\n\tlibstdc++.so (libc6,x86-64) => /lib64/libstdc++.so\r\n\tlibssl.so.1.0.0 (libc6,x86-64) => /lib64/libssl.so.1.0.0\r\n\tlibssl.so (libc6,x86-64) => /lib64/libssl.so\r\n\tlibss.so.2 (libc6,x86-64) => /lib64/libss.so.2\r\n\tlibsqlite3.so.0 (libc6,x86-64) => /lib64/libsqlite3.so.0\r\n\tlibsqlite3.so (libc6,x86-64) => /lib64/libsqlite3.so\r\n\tlibsmartcols.so.1 (libc6,x86-64) => /lib64/libsmartcols.so.1\r\n\tlibsepol.so.1 (libc6,x86-64) => /lib64/libsepol.so.1\r\n\tlibsepol.so (libc6,x86-64) => /lib64/libsepol.so\r\n\tlibsemanage.so.1 (libc6,x86-64) => /lib64/libsemanage.so.1\r\n\tlibsemanage.so (libc6,x86-64) => /lib64/libsemanage.so\r\n\tlibselinux.so.1 (libc6,x86-64) => /lib64/libselinux.so.1\r\n\tlibselinux.so (libc6,x86-64) => /lib64/libselinux.so\r\n\tlibsefs.so.4 (libc6,x86-64) => /lib64/libsefs.so.4\r\n\tlibsefs.so (libc6,x86-64) => /lib64/libsefs.so\r\n\tlibseccomp.so.2 (libc6,x86-64) => /lib64/libseccomp.so.2\r\n\tlibseccomp.so (libc6,x86-64) => /lib64/libseccomp.so\r\n\tlibseaudit.so.4 (libc6,x86-64) => /lib64/libseaudit.so.4\r\n\tlibseaudit.so (libc6,x86-64) => /lib64/libseaudit.so\r\n\tlibrt.so.1 (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/librt.so.1\r\n\tlibrt.so (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/librt.so\r\n\tlibrootdev.so.1 (libc6,x86-64) => /lib64/librootdev.so.1\r\n\tlibrootdev.so (libc6,x86-64) => /lib64/librootdev.so\r\n\tlibresolv.so.2 (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libresolv.so.2\r\n\tlibresolv.so (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libresolv.so\r\n\tlibreadline.so.6 (libc6,x86-64) => /lib64/libreadline.so.6\r\n\tlibqpol.so.1 (libc6,x86-64) => /lib64/libqpol.so.1\r\n\tlibqpol.so (libc6,x86-64) => /lib64/libqpol.so\r\n\tlibpthread.so.0 (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libpthread.so.0\r\n\tlibpth.so.20 (libc6,x86-64) => /lib64/libpth.so.20\r\n\tlibpth.so (libc6,x86-64) => /lib64/libpth.so\r\n\tlibprotoc.so.8 (libc6,x86-64) => /lib64/libprotoc.so.8\r\n\tlibprotoc.so (libc6,x86-64) => /lib64/libprotoc.so\r\n\tlibprotobuf.so.8 (libc6,x86-64) => /lib64/libprotobuf.so.8\r\n\tlibprotobuf.so (libc6,x86-64) => /lib64/libprotobuf.so\r\n\tlibprotobuf-lite.so.8 (libc6,x86-64) => /lib64/libprotobuf-lite.so.8\r\n\tlibprotobuf-lite.so (libc6,x86-64) => /lib64/libprotobuf-lite.so\r\n\tlibprocps.so.3 (libc6,x86-64) => /lib64/libprocps.so.3\r\n\tlibpopt.so.0 (libc6,x86-64) => /lib64/libpopt.so.0\r\n\tlibpopt.so (libc6,x86-64) => /lib64/libpopt.so\r\n\tlibpolkit-gobject-1.so.0 (libc6,x86-64) => /lib64/libpolkit-gobject-1.so.0\r\n\tlibpolkit-gobject-1.so (libc6,x86-64) => /lib64/libpolkit-gobject-1.so\r\n\tlibpolkit-agent-1.so.0 (libc6,x86-64) => /lib64/libpolkit-agent-1.so.0\r\n\tlibpolkit-agent-1.so (libc6,x86-64) => /lib64/libpolkit-agent-1.so\r\n\tlibpoldiff.so.1 (libc6,x86-64) => /lib64/libpoldiff.so.1\r\n\tlibpoldiff.so (libc6,x86-64) => /lib64/libpoldiff.so\r\n\tlibplds4.so (libc6,x86-64) => /lib64/libplds4.so\r\n\tlibplc4.so (libc6,x86-64) => /lib64/libplc4.so\r\n\tlibpcreposix.so.0 (libc6,x86-64) => /lib64/libpcreposix.so.0\r\n\tlibpcreposix.so (libc6,x86-64) => /lib64/libpcreposix.so\r\n\tlibpcrecpp.so.0 (libc6,x86-64) => /lib64/libpcrecpp.so.0\r\n\tlibpcrecpp.so (libc6,x86-64) => /lib64/libpcrecpp.so\r\n\tlibpcre.so.1 (libc6,x86-64) => /lib64/libpcre.so.1\r\n\tlibpcprofile.so (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libpcprofile.so\r\n\tlibpci.so.3 (libc6,x86-64) => /lib64/libpci.so.3\r\n\tlibpci.so (libc6,x86-64) => /lib64/libpci.so\r\n\tlibpcap.so.1 (libc6,x86-64) => /lib64/libpcap.so.1\r\n\tlibpcap.so (libc6,x86-64) => /lib64/libpcap.so\r\n\tlibparted.so.2 (libc6,x86-64) => /lib64/libparted.so.2\r\n\tlibparted.so (libc6,x86-64) => /lib64/libparted.so\r\n\tlibparted-fs-resize.so.0 (libc6,x86-64) => /lib64/libparted-fs-resize.so.0\r\n\tlibparted-fs-resize.so (libc6,x86-64) => /lib64/libparted-fs-resize.so\r\n\tlibpanelw.so.5 (libc6,x86-64) => /lib64/libpanelw.so.5\r\n\tlibpanelw.so (libc6,x86-64) => /lib64/libpanelw.so\r\n\tlibpanel.so.5 (libc6,x86-64) => /lib64/libpanel.so.5\r\n\tlibpanel.so (libc6,x86-64) => /lib64/libpanel.so\r\n\tlibnss_usrfiles.so.2 (libc6,x86-64) => /lib64/libnss_usrfiles.so.2\r\n\tlibnss_resolve.so.2 (libc6,x86-64) => /lib64/libnss_resolve.so.2\r\n\tlibnss_nisplus.so.2 (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libnss_nisplus.so.2\r\n\tlibnss_nisplus.so (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libnss_nisplus.so\r\n\tlibnss_nis.so.2 (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libnss_nis.so.2\r\n\tlibnss_nis.so (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libnss_nis.so\r\n\tlibnss_mymachines.so.2 (libc6,x86-64) => /lib64/libnss_mymachines.so.2\r\n\tlibnss_myhostname.so.2 (libc6,x86-64) => /lib64/libnss_myhostname.so.2\r\n\tlibnss_hesiod.so.2 (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libnss_hesiod.so.2\r\n\tlibnss_hesiod.so (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libnss_hesiod.so\r\n\tlibnss_files.so.2 (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libnss_files.so.2\r\n\tlibnss_files.so (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libnss_files.so\r\n\tlibnss_dns.so.2 (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libnss_dns.so.2\r\n\tlibnss_dns.so (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libnss_dns.so\r\n\tlibnss_db.so.2 (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libnss_db.so.2\r\n\tlibnss_db.so (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libnss_db.so\r\n\tlibnss_compat.so.2 (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libnss_compat.so.2\r\n\tlibnss_compat.so (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libnss_compat.so\r\n\tlibnspr4.so (libc6,x86-64) => /lib64/libnspr4.so\r\n\tlibnsl.so.1 (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libnsl.so.1\r\n\tlibnsl.so (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libnsl.so\r\n\tlibnfsidmap.so.0 (libc6,x86-64) => /lib64/libnfsidmap.so.0\r\n\tlibnfsidmap.so (libc6,x86-64) => /lib64/libnfsidmap.so\r\n\tlibncursesw.so.5 (libc6,x86-64) => /lib64/libncursesw.so.5\r\n\tlibncurses.so.5 (libc6,x86-64) => /lib64/libncurses.so.5\r\n\tlibmozjs185.so.1.0 (libc6,x86-64) => /lib64/libmozjs185.so.1.0\r\n\tlibmozjs185.so (libc6,x86-64) => /lib64/libmozjs185.so\r\n\tlibmount.so.1 (libc6,x86-64) => /lib64/libmount.so.1\r\n\tlibmnl.so.0 (libc6,x86-64) => /lib64/libmnl.so.0\r\n\tlibmicrohttpd.so.10 (libc6,x86-64) => /lib64/libmicrohttpd.so.10\r\n\tlibmicrohttpd.so (libc6,x86-64) => /lib64/libmicrohttpd.so\r\n\tlibmenuw.so.5 (libc6,x86-64) => /lib64/libmenuw.so.5\r\n\tlibmenuw.so (libc6,x86-64) => /lib64/libmenuw.so\r\n\tlibmenu.so.5 (libc6,x86-64) => /lib64/libmenu.so.5\r\n\tlibmenu.so (libc6,x86-64) => /lib64/libmenu.so\r\n\tlibmemusage.so (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libmemusage.so\r\n\tlibm.so.6 (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libm.so.6\r\n\tlibm.so (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libm.so\r\n\tliblzo2.so.2 (libc6,x86-64) => /lib64/liblzo2.so.2\r\n\tliblzo2.so (libc6,x86-64) => /lib64/liblzo2.so\r\n\tliblzma.so.5 (libc6,x86-64) => /lib64/liblzma.so.5\r\n\tliblvm2cmd.so.2.02 (libc6,x86-64) => /lib64/liblvm2cmd.so.2.02\r\n\tliblvm2cmd.so (libc6,x86-64) => /lib64/liblvm2cmd.so\r\n\tliblvm2app.so.2.2 (libc6,x86-64) => /lib64/liblvm2app.so.2.2\r\n\tliblvm2app.so (libc6,x86-64) => /lib64/liblvm2app.so\r\n\tliblinear.so.2 (libc6,x86-64) => /lib64/liblinear.so.2\r\n\tliblinear.so (libc6,x86-64) => /lib64/liblinear.so\r\n\tlibksba.so.8 (libc6,x86-64) => /lib64/libksba.so.8\r\n\tlibksba.so (libc6,x86-64) => /lib64/libksba.so\r\n\tlibkmod.so.2 (libc6,x86-64) => /lib64/libkmod.so.2\r\n\tlibkmod.so (libc6,x86-64) => /lib64/libkmod.so\r\n\tlibkeyutils.so.1 (libc6,x86-64) => /lib64/libkeyutils.so.1\r\n\tlibjq.so.1 (libc6,x86-64) => /lib64/libjq.so.1\r\n\tlibjq.so (libc6,x86-64) => /lib64/libjq.so\r\n\tlibitm.so.1 (libc6,x86-64) => /lib64/libitm.so.1\r\n\tlibitm.so (libc6,x86-64) => /lib64/libitm.so\r\n\tlibip6tc.so.0 (libc6,x86-64) => /lib64/libip6tc.so.0\r\n\tlibip4tc.so.0 (libc6,x86-64) => /lib64/libip4tc.so.0\r\n\tlibiptc.so.0 (libc6,x86-64) => /lib64/libiptc.so.0\r\n\tlibipset.so.3 (libc6,x86-64) => /lib64/libipset.so.3\r\n\tlibipset.so (libc6,x86-64) => /lib64/libipset.so\r\n\tlibhistory.so.6 (libc6,x86-64) => /lib64/libhistory.so.6\r\n\tlibhandle.so.1 (libc6,x86-64) => /lib64/libhandle.so.1\r\n\tlibhandle.so (libc6,x86-64) => /lib64/libhandle.so\r\n\tlibgthread-2.0.so.0 (libc6,x86-64) => /lib64/libgthread-2.0.so.0\r\n\tlibgthread-2.0.so (libc6,x86-64) => /lib64/libgthread-2.0.so\r\n\tlibgpg-error.so.0 (libc6,x86-64) => /lib64/libgpg-error.so.0\r\n\tlibgpg-error.so (libc6,x86-64) => /lib64/libgpg-error.so\r\n\tlibgobject-2.0.so.0 (libc6,x86-64) => /lib64/libgobject-2.0.so.0\r\n\tlibgobject-2.0.so (libc6,x86-64) => /lib64/libgobject-2.0.so\r\n\tlibgmodule-2.0.so.0 (libc6,x86-64) => /lib64/libgmodule-2.0.so.0\r\n\tlibgmodule-2.0.so (libc6,x86-64) => /lib64/libgmodule-2.0.so\r\n\tlibglib-2.0.so.0 (libc6,x86-64) => /lib64/libglib-2.0.so.0\r\n\tlibglib-2.0.so (libc6,x86-64) => /lib64/libglib-2.0.so\r\n\tlibgio-2.0.so.0 (libc6,x86-64) => /lib64/libgio-2.0.so.0\r\n\tlibgio-2.0.so (libc6,x86-64) => /lib64/libgio-2.0.so\r\n\tlibgflags_nothreads.so.2 (libc6,x86-64) => /lib64/libgflags_nothreads.so.2\r\n\tlibgflags_nothreads.so (libc6,x86-64) => /lib64/libgflags_nothreads.so\r\n\tlibgflags.so.2 (libc6,x86-64) => /lib64/libgflags.so.2\r\n\tlibgflags.so (libc6,x86-64) => /lib64/libgflags.so\r\n\tlibgcrypt.so.20 (libc6,x86-64) => /lib64/libgcrypt.so.20\r\n\tlibgcrypt.so (libc6,x86-64) => /lib64/libgcrypt.so\r\n\tlibgcc_s.so.1 (libc6,x86-64) => /lib64/libgcc_s.so.1\r\n\tlibgcc_s.so (libc6,x86-64) => /lib64/libgcc_s.so\r\n\tlibformw.so.5 (libc6,x86-64) => /lib64/libformw.so.5\r\n\tlibformw.so (libc6,x86-64) => /lib64/libformw.so\r\n\tlibform.so.5 (libc6,x86-64) => /lib64/libform.so.5\r\n\tlibform.so (libc6,x86-64) => /lib64/libform.so\r\n\tlibffi.so.6 (libc6,x86-64) => /lib64/libffi.so.6\r\n\tlibffi.so (libc6,x86-64) => /lib64/libffi.so\r\n\tlibfdisk.so.1 (libc6,x86-64) => /lib64/libfdisk.so.1\r\n\tlibfdisk.so (libc6,x86-64) => /lib64/libfdisk.so\r\n\tlibe2p.so.2 (libc6,x86-64) => /lib64/libe2p.so.2\r\n\tlibext2fs.so.2 (libc6,x86-64) => /lib64/libext2fs.so.2\r\n\tlibexpatw.so.1 (libc6,x86-64) => /lib64/libexpatw.so.1\r\n\tlibexpatw.so (libc6,x86-64) => /lib64/libexpatw.so\r\n\tlibexpatu.so.1 (libc6,x86-64) => /lib64/libexpatu.so.1\r\n\tlibexpatu.so (libc6,x86-64) => /lib64/libexpatu.so\r\n\tlibexpat.so.1 (libc6,x86-64) => /lib64/libexpat.so.1\r\n\tlibexpat.so (libc6,x86-64) => /lib64/libexpat.so\r\n\tlibevent_pthreads-2.0.so.5 (libc6,x86-64) => /lib64/libevent_pthreads-2.0.so.5\r\n\tlibevent_openssl-2.0.so.5 (libc6,x86-64) => /lib64/libevent_openssl-2.0.so.5\r\n\tlibevent_extra-2.0.so.5 (libc6,x86-64) => /lib64/libevent_extra-2.0.so.5\r\n\tlibevent_core-2.0.so.5 (libc6,x86-64) => /lib64/libevent_core-2.0.so.5\r\n\tlibevent-2.0.so.5 (libc6,x86-64) => /lib64/libevent-2.0.so.5\r\n\tlibelf.so.1 (libc6,x86-64) => /lib64/libelf.so.1\r\n\tlibelf.so (libc6,x86-64) => /lib64/libelf.so\r\n\tlibdw.so.1 (libc6,x86-64) => /lib64/libdw.so.1\r\n\tlibdw.so (libc6,x86-64) => /lib64/libdw.so\r\n\tlibdl.so.2 (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libdl.so.2\r\n\tlibdl.so (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libdl.so\r\n\tlibdevmapper.so.1.02 (libc6,x86-64) => /lib64/libdevmapper.so.1.02\r\n\tlibdevmapper.so (libc6,x86-64) => /lib64/libdevmapper.so\r\n\tlibdevmapper-event.so.1.02 (libc6,x86-64) => /lib64/libdevmapper-event.so.1.02\r\n\tlibdevmapper-event.so (libc6,x86-64) => /lib64/libdevmapper-event.so\r\n\tlibdevmapper-event-lvm2thin.so (libc6,x86-64) => /lib64/libdevmapper-event-lvm2thin.so\r\n\tlibdevmapper-event-lvm2snapshot.so (libc6,x86-64) => /lib64/libdevmapper-event-lvm2snapshot.so\r\n\tlibdevmapper-event-lvm2raid.so (libc6,x86-64) => /lib64/libdevmapper-event-lvm2raid.so\r\n\tlibdevmapper-event-lvm2mirror.so (libc6,x86-64) => /lib64/libdevmapper-event-lvm2mirror.so\r\n\tlibdevmapper-event-lvm2.so.2.02 (libc6,x86-64) => /lib64/libdevmapper-event-lvm2.so.2.02\r\n\tlibdevmapper-event-lvm2.so (libc6,x86-64) => /lib64/libdevmapper-event-lvm2.so\r\n\tlibdbus-1.so.3 (libc6,x86-64) => /lib64/libdbus-1.so.3\r\n\tlibdbus-1.so (libc6,x86-64) => /lib64/libdbus-1.so\r\n\tlibdbus-glib-1.so.2 (libc6,x86-64) => /lib64/libdbus-glib-1.so.2\r\n\tlibdbus-glib-1.so (libc6,x86-64) => /lib64/libdbus-glib-1.so\r\n\tlibcurl.so.4 (libc6,x86-64) => /lib64/libcurl.so.4\r\n\tlibcurl.so (libc6,x86-64) => /lib64/libcurl.so\r\n\tlibcryptsetup.so.4 (libc6,x86-64) => /lib64/libcryptsetup.so.4\r\n\tlibcryptsetup.so (libc6,x86-64) => /lib64/libcryptsetup.so\r\n\tlibcrypto.so.1.0.0 (libc6,x86-64) => /lib64/libcrypto.so.1.0.0\r\n\tlibcrypto.so (libc6,x86-64) => /lib64/libcrypto.so\r\n\tlibcrypt.so.1 (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libcrypt.so.1\r\n\tlibcrypt.so (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libcrypt.so\r\n\tlibcom_err.so.2 (libc6,x86-64) => /lib64/libcom_err.so.2\r\n\tlibcidn.so.1 (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libcidn.so.1\r\n\tlibcidn.so (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libcidn.so\r\n\tlibcap.so.2 (libc6,x86-64) => /lib64/libcap.so.2\r\n\tlibcap-ng.so.0 (libc6,x86-64) => /lib64/libcap-ng.so.0\r\n\tlibcap-ng.so (libc6,x86-64) => /lib64/libcap-ng.so\r\n\tlibc.so.6 (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libc.so.6\r\n\tlibbz2.so.1 (libc6,x86-64) => /lib64/libbz2.so.1\r\n\tlibbtrfs.so.0 (libc6,x86-64) => /lib64/libbtrfs.so.0\r\n\tlibbtrfs.so (libc6,x86-64) => /lib64/libbtrfs.so\r\n\tlibblkid.so.1 (libc6,x86-64) => /lib64/libblkid.so.1\r\n\tlibbase-glib-180609.so (libc6,x86-64) => /lib64/libbase-glib-180609.so\r\n\tlibbase-event-180609.so (libc6,x86-64) => /lib64/libbase-event-180609.so\r\n\tlibbase-dl-180609.so (libc6,x86-64) => /lib64/libbase-dl-180609.so\r\n\tlibbase-core-180609.so (libc6,x86-64) => /lib64/libbase-core-180609.so\r\n\tlibauparse.so.0 (libc6,x86-64) => /lib64/libauparse.so.0\r\n\tlibaudit.so.1 (libc6,x86-64) => /lib64/libaudit.so.1\r\n\tlibattr.so.1 (libc6,x86-64) => /lib64/libattr.so.1\r\n\tlibatomic.so.1 (libc6,x86-64) => /lib64/libatomic.so.1\r\n\tlibatomic.so (libc6,x86-64) => /lib64/libatomic.so\r\n\tlibassuan.so.0 (libc6,x86-64) => /lib64/libassuan.so.0\r\n\tlibassuan.so (libc6,x86-64) => /lib64/libassuan.so\r\n\tlibasm.so.1 (libc6,x86-64) => /lib64/libasm.so.1\r\n\tlibasm.so (libc6,x86-64) => /lib64/libasm.so\r\n\tlibapol.so.4 (libc6,x86-64) => /lib64/libapol.so.4\r\n\tlibapol.so (libc6,x86-64) => /lib64/libapol.so\r\n\tlibanl.so.1 (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libanl.so.1\r\n\tlibanl.so (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libanl.so\r\n\tlibacl.so.1 (libc6,x86-64) => /lib64/libacl.so.1\r\n\tlibSegFault.so (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libSegFault.so\r\n\tlibBrokenLocale.so.1 (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libBrokenLocale.so.1\r\n\tlibBrokenLocale.so (libc6,x86-64, OS ABI: Linux 2.6.32) => /lib64/libBrokenLocale.so\r\n\tld-linux-x86-64.so.2 (libc6,x86-64) => /lib64/ld-linux-x86-64.so.2\r\n\r\n/bin/sh: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)\r\nThe value of pattern is ^NAME=(.*)\r\nThe value of string is NAME=CoreOS\r\nThe value of pattern is ^VERSION=(.*)\r\nThe value of string is NAME=CoreOS\r\nThe value of pattern is ^VERSION=(.*)\r\nThe value of string is ID=coreos\r\nThe value of pattern is ^VERSION=(.*)\r\nThe value of string is VERSION=976.0.0\r\nThe value of pattern is ^GROUP=(.*)\r\nTraceback (most recent call last):\r\n  File \"app_main.py\", line 75, in run_toplevel\r\n  File \"/home/core/.ansible/tmp/ansible-tmp-1459457632.46-56924359125586/setup\", line 5183, in <module>\r\n    main()\r\n  File \"/home/core/.ansible/tmp/ansible-tmp-1459457632.46-56924359125586/setup\", line 139, in main\r\n    data = run_setup(module)\r\n  File \"/home/core/.ansible/tmp/ansible-tmp-1459457632.46-56924359125586/setup\", line 83, in run_setup\r\n    facts = ansible_facts(module)\r\n  File \"/home/core/.ansible/tmp/ansible-tmp-1459457632.46-56924359125586/setup\", line 5118, in ansible_facts\r\n    facts.update(Facts().populate())\r\n  File \"/home/core/.ansible/tmp/ansible-tmp-1459457632.46-56924359125586/setup\", line 2258, in __init__\r\n    self.get_platform_facts()\r\n  File \"/home/core/.ansible/tmp/ansible-tmp-1459457632.46-56924359125586/setup\", line 2304, in get_platform_facts\r\n    self.get_distribution_facts()\r\n  File \"/home/core/.ansible/tmp/ansible-tmp-1459457632.46-56924359125586/setup\", line 2607, in get_distribution_facts\r\n    release = re.search(\"^GROUP=(.*)\", data)\r\n  File \"/opt/pypy/lib-python/2.7/re.py\", line 143, in search\r\n    print 'The value of string is ' + string\r\nTypeError: unsupported operand type(s) for +: 'str' and 'NoneType'\r\n",
    "msg": "MODULE FAILURE",
    "parsed": false
}

```



Discussion:
@someword I'm currently writing tests for the distribution_version code. Can you provide me with the output of `python -c 'import platform; print(platform.dist())'` for your above setup?
Also if you have this available: Can you provide an example where there the update.conf exists?
You could also directly use a script I wrote to generate all relevant data for the testcase: https://github.com/robinro/ansible/blob/refactor_os_version_parsing/test/units/module_utils/gen_distribution_version_testcase.py

Other (related) question: Are there docker images of coreos somewhere?

@robinro 
We run pypy as the python interpreter

```
python --version
Python 2.7.8 (f5dcc2477b97, Sep 18 2014, 11:33:30)
[PyPy 2.4.0 with GCC 4.6.3]

python -c 'import platform; print(platform.dist())'
('', '', '')
```

The thing about the update.conf file.     It only exists on CoreOS nodes if the node has been configured to do automatic operating system updates.    My nodes are configured not to do automatic OS updates so we do not have an update.conf.   The option to not do auto updates is a one of the supported CoreOS models so it's not that we are doing something that we just invented:) 

The content of the update.conf is just the name of which update channel you bind to (alpha, beta or stable).   The channels are here https://coreos.com/releases/.

Interesting thing about the CoreOS docker images.   I could not find any as CoreOS is pretty much just used to run containers so no one creates images.     Other options which require more effort are to use an CoreOS AMI in AWS as these are updated regularly.   Also vagrant is an option https://coreos.com/blog/coreos-vagrant-images/.

Here is some output from the testcase.py script.   I had to change your script a bit.   We don't actually have ansible installed on our hosts.    What we do is on the host we launch an docker container which has ansible in it.   From the container we ssh into the host itself and do ansible stuff.     So if I used your script as it is you would end up with information about the container and not the host. 

```
core@iiev00175 ~ $ python /var/tmp/some.py
/opt/pypy/bin/pypy: /lib64/libssl.so.1.0.0: no version information available (required by /opt/pypy/bin/pypy)
/opt/pypy/bin/pypy: /lib64/libcrypto.so.1.0.0: no version information available (required by /opt/pypy/bin/pypy)
{'input': {'/etc/lsb-release': 'DISTRIB_ID=CoreOS\nDISTRIB_RELEASE=976.0.0\nDISTRIB_CODENAME="Coeur Rouge"\nDISTRIB_DESCRIPTION="CoreOS 976.0.0 (Coeur Rouge)"\n',
           '/etc/os-release': 'NAME=CoreOS\nID=coreos\nVERSION=976.0.0\nVERSION_ID=976.0.0\nBUILD_ID=2016-03-03-2324\nPRETTY_NAME="CoreOS 976.0.0 (Coeur Rouge)"\nANSI_COLOR="1;32"\nHOME_URL="https://coreos.com/"\nBUG_REPORT_URL="https://github.com/coreos/bugs/issues"\n'},
 'platform.dist': ('', '', ''),
 'result': {'distribution': u'NA',
            'distribution_major_version': u'NA',
            'distribution_release': u'NA',
            'distribution_version': u'NA'}}
```

I'd be happy to answer further questions on this topic.

HTH.

Thanks @someword for the info. I updated the testcase accordingly. With lsb-release present it might also be interesting to use that to extract the information, but that's something for the next iteration.


Resolving patch:
diff --git a/lib/ansible/module_utils/facts.py b/lib/ansible/module_utils/facts.py
--- a/lib/ansible/module_utils/facts.py
+++ b/lib/ansible/module_utils/facts.py
@@ -126,8 +126,8 @@ class Facts(object):
                     ('/etc/alpine-release', 'Alpine'),
                     ('/etc/release', 'Solaris'),
                     ('/etc/arch-release', 'Archlinux'),
-                    ('/etc/SuSE-release', 'SuSE'),
                     ('/etc/os-release', 'SuSE'),
+                    ('/etc/SuSE-release', 'SuSE'),
                     ('/etc/gentoo-release', 'Gentoo'),
                     ('/etc/os-release', 'Debian'),
                     ('/etc/lsb-release', 'Mandriva'),
@@ -282,6 +282,11 @@ def get_local_facts(self):
     # platform.dist() is deprecated in 2.6
     # in 2.6 and newer, you should use platform.linux_distribution()
     def get_distribution_facts(self):
+        """
+        Fills facts about the distribution name and version.
+
+        This is unit tested. Please extend the tests to cover all distributions if you have them available.
+        """
 
         # A list with OS Family members
         OS_FAMILY = dict(
@@ -459,7 +464,7 @@ def get_distribution_facts(self):
                                                 self.facts['distribution_release'] = release.groups()[0]
                                         elif 'enterprise' in data.lower() and 'VERSION_ID' in line:
                                              release = re.search('^VERSION_ID="?[0-9]+\.?([0-9]*)"?', line) # SLES doesn't got funny release names
-                                             if release.group(1):
+                                             if release and release.group(1):
                                                  release = release.group(1)
                                              else:
                                                  release = "0" # no minor number, so it is the first release
@@ -521,9 +526,11 @@ def get_distribution_facts(self):
 
                             if self.facts['distribution'].lower() == 'coreos':
                                 data = get_file_content('/etc/coreos/update.conf')
-                                release = re.search("^GROUP=(.*)", data)
-                                if release:
-                                    self.facts['distribution_release'] = release.group(1).strip('"')
+                                if data:
+                                    release = re.search("^GROUP=(.*)", data)
+                                    if release:
+                                        self.facts['distribution_release'] = release.group(1).strip('"')
+
                     else:
                         self.facts['distribution'] = name
         machine_id = get_file_content("/var/lib/dbus/machine-id") or get_file_content("/etc/machine-id")


Test patch:
diff --git a/hacking/tests/gen_distribution_version_testcase.py b/hacking/tests/gen_distribution_version_testcase.py
new file mode 100755
--- /dev/null
+++ b/hacking/tests/gen_distribution_version_testcase.py
@@ -0,0 +1,65 @@
+#!/usr/bin/env python
+
+"""
+This script generated test_cases for test_distribution_version.py.
+
+To do so it outputs the relevant files from /etc/*release, the output of platform.dist() and the current ansible_facts regarding the distribution version.
+
+This assumes a working ansible version in the path.
+"""
+
+import platform
+import os.path
+import subprocess
+import json
+
+filelist = [
+        '/etc/oracle-release',
+        '/etc/slackware-version',
+        '/etc/redhat-release',
+        '/etc/vmware-release',
+        '/etc/openwrt_release',
+        '/etc/system-release',
+        '/etc/alpine-release',
+        '/etc/release',
+        '/etc/arch-release',
+        '/etc/os-release',
+        '/etc/SuSE-release',
+        '/etc/gentoo-release',
+        '/etc/os-release',
+        '/etc/lsb-release',
+        '/etc/altlinux-release',
+        '/etc/os-release',
+        '/etc/coreos/update.conf',
+]
+
+fcont = {}
+
+for f in filelist:
+    if os.path.exists(f):
+        s = os.path.getsize(f)
+        if s > 0 and s < 10000:
+            with open(f) as fh:
+                fcont[f] = fh.read()
+
+dist = platform.dist()
+
+
+facts = ['distribution', 'distribution_version', 'distribution_release', 'distribution_major_version']
+ansible_out = subprocess.check_output(['ansible', 'localhost', '-m', 'setup'])
+parsed = json.loads(ansible_out[ansible_out.index('{'):])
+ansible_facts = {}
+for fact in facts:
+    ansible_facts[fact] = parsed['ansible_facts']['ansible_'+fact]
+
+nicename = ansible_facts['distribution'] + ' ' + ansible_facts['distribution_version']
+
+output = {
+    'name': nicename,
+    'input': fcont,
+    'platform.dist': dist,
+    'result': ansible_facts,
+}
+
+print(json.dumps(output, indent=4))
+
diff --git a/test/units/module_utils/test_distribution_version.py b/test/units/module_utils/test_distribution_version.py
new file mode 100644
--- /dev/null
+++ b/test/units/module_utils/test_distribution_version.py
@@ -0,0 +1,391 @@
+# -*- coding: utf-8 -*-
+# 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)
+__metaclass__ = type
+
+import sys
+
+# to work around basic.py reading stdin
+import json
+from io import BytesIO, StringIO
+from ansible.compat.six import PY3
+from ansible.utils.unicode import to_bytes
+
+# for testing
+from ansible.compat.tests import unittest
+from ansible.compat.tests.mock import patch
+
+# the module we are actually testing
+
+
+# to generate the testcase data, you can use the script gen_distribution_version_testcase.py in hacking/tests
+TESTSETS = [
+    {
+        "name" : "openSUSE Leap 42.1",
+        "input": {
+            "/etc/os-release":
+            """
+NAME="openSUSE Leap"
+VERSION="42.1"
+VERSION_ID="42.1"
+PRETTY_NAME="openSUSE Leap 42.1 (x86_64)"
+ID=opensuse
+ANSI_COLOR="0;32"
+CPE_NAME="cpe:/o:opensuse:opensuse:42.1"
+BUG_REPORT_URL="https://bugs.opensuse.org"
+HOME_URL="https://opensuse.org/"
+ID_LIKE="suse"
+            """,
+            "/etc/SuSE-release":"""
+openSUSE 42.1 (x86_64)
+VERSION = 42.1
+CODENAME = Malachite
+# /etc/SuSE-release is deprecated and will be removed in the future, use /etc/os-release instead
+            """
+        },
+        "platform.dist": ['SuSE', '42.1', 'x86_64'],
+        "result":{
+            "distribution": "openSUSE Leap",
+            "distribution_major_version": "42",
+            "distribution_release": "x86_64",
+            "distribution_version": "42.1",
+        }
+    },
+                {
+        'name': 'openSUSE 13.2',
+        'input': {'/etc/SuSE-release': """openSUSE 13.2 (x86_64)
+VERSION = 13.2
+CODENAME = Harlequin
+# /etc/SuSE-release is deprecated and will be removed in the future, use /etc/os-release instead
+""",
+                  '/etc/os-release': """NAME=openSUSE
+VERSION="13.2 (Harlequin)"
+VERSION_ID="13.2"
+PRETTY_NAME="openSUSE 13.2 (Harlequin) (x86_64)"
+ID=opensuse
+ANSI_COLOR="0;32"
+CPE_NAME="cpe:/o:opensuse:opensuse:13.2"
+BUG_REPORT_URL="https://bugs.opensuse.org"
+HOME_URL="https://opensuse.org/"
+ID_LIKE="suse"
+"""},
+        'platform.dist': ('SuSE', '13.2', 'x86_64'),
+        'result': {'distribution': u'openSUSE',
+                   'distribution_major_version': u'13',
+                   'distribution_release': u'Harlequin',
+                   'distribution_version': u'13.2'}
+    },
+    { # see https://github.com/ansible/ansible/issues/14837
+        "name": "SLES 11.3",
+        "input": {
+            "/etc/SuSE-release":"""
+SUSE Linux Enterprise Server 11 (x86_64)
+VERSION = 11
+PATCHLEVEL = 3
+            """
+        },
+        "platform.dist": ['SuSE', '11', 'x86_64'],
+        "result":{
+            "distribution": "SLES",
+            "distribution_major_version": "11",
+            "distribution_release": "3",
+            "distribution_version": "11.3",
+        }
+    },
+    { # see https://github.com/ansible/ansible/issues/14837
+        "name": "SLES 11.4",
+        "input": {
+            "/etc/SuSE-release":"""
+SUSE Linux Enterprise Server 11 (x86_64)
+VERSION = 11
+PATCHLEVEL = 4
+            """,
+            "/etc/os-release":"""
+NAME="SLES"
+VERSION="11.4"
+VERSION_ID="11.4"
+PRETTY_NAME="SUSE Linux Enterprise Server 11 SP4"
+ID="sles"
+ANSI_COLOR="0;32"
+CPE_NAME="cpe:/o:suse:sles:11:4"
+            """,
+        },
+        "platform.dist": ['SuSE', '11', 'x86_64'],
+        "result":{
+            "distribution": "SLES",
+            "distribution_major_version": "11",
+            "distribution_release": "4",
+            "distribution_version": "11.4",
+        }
+    },
+    { # see https://github.com/ansible/ansible/issues/14837
+        "name": "SLES 12 SP0",
+        "input": {
+            "/etc/SuSE-release":"""
+SUSE Linux Enterprise Server 12 (x86_64)
+VERSION = 12
+PATCHLEVEL = 0
+# This file is deprecated and will be removed in a future service pack or release.
+# Please check /etc/os-release for details about this release.
+            """,
+            "/etc/os-release":"""
+NAME="SLES"
+VERSION="12"
+VERSION_ID="12"
+PRETTY_NAME="SUSE Linux Enterprise Server 12"
+ID="sles"
+ANSI_COLOR="0;32"
+CPE_NAME="cpe:/o:suse:sles:12"
+            """,
+        },
+        "platform.dist": ['SuSE', '12', 'x86_64'],
+        "result":{
+            "distribution": "SLES",
+            "distribution_major_version": "12",
+            "distribution_release": "0",
+            "distribution_version": "12",
+        }
+    },
+
+    { # see https://github.com/ansible/ansible/issues/14837
+        "name": "SLES 12 SP1",
+        "input": {
+            "/etc/SuSE-release":"""
+SUSE Linux Enterprise Server 12 (x86_64)
+VERSION = 12
+PATCHLEVEL = 0
+# This file is deprecated and will be removed in a future service pack or release.
+# Please check /etc/os-release for details about this release.
+            """,
+            "/etc/os-release":"""
+NAME="SLES"
+VERSION="12-SP1"
+VERSION_ID="12.1"
+PRETTY_NAME="SUSE Linux Enterprise Server 12 SP1"
+ID="sles"
+ANSI_COLOR="0;32"
+CPE_NAME="cpe:/o:suse:sles:12:sp1"
+            """,
+        },
+        "platform.dist": ['SuSE', '12', 'x86_64'],
+        "result":{
+            "distribution": "SLES",
+            "distribution_major_version": "12",
+            "distribution_release": "1",
+            "distribution_version": "12.1",
+        }
+    },
+
+    {
+        "name": "Debian stretch/sid",
+        "input": {
+            "/etc/os-release":"""
+PRETTY_NAME="Debian GNU/Linux stretch/sid"
+NAME="Debian GNU/Linux"
+ID=debian
+HOME_URL="https://www.debian.org/"
+SUPPORT_URL="https://www.debian.org/support"
+BUG_REPORT_URL="https://bugs.debian.org/"
+            """,
+            "/etc/debian_version":"""
+            stretch/sid
+            """,
+        },
+        "platform.dist": ('debian', 'stretch/sid', ''),
+        "result":{
+            "distribution": "Debian",
+            "distribution_major_version": "stretch/sid",
+            "distribution_release": "NA",
+            "distribution_version": "stretch/sid",
+        }
+    },
+    {
+        'name': "Debian 7.9",
+        'input': {'/etc/os-release': """PRETTY_NAME="Debian GNU/Linux 7 (wheezy)"
+NAME="Debian GNU/Linux"
+VERSION_ID="7"
+VERSION="7 (wheezy)"
+ID=debian
+ANSI_COLOR="1;31"
+HOME_URL="http://www.debian.org/"
+SUPPORT_URL="http://www.debian.org/support/"
+BUG_REPORT_URL="http://bugs.debian.org/"
+"""},
+        'platform.dist': ('debian', '7.9', ''),
+        'result': {'distribution': u'Debian',
+                   'distribution_major_version': u'7',
+                   'distribution_release': u'wheezy',
+                   'distribution_version': u'7.9'}
+    },
+    {
+        'name': "Ubuntu 14.04",
+        'input': {'/etc/lsb-release': """DISTRIB_ID=Ubuntu
+DISTRIB_RELEASE=14.04
+DISTRIB_CODENAME=trusty
+DISTRIB_DESCRIPTION="Ubuntu 14.04.4 LTS"
+""",
+                  '/etc/os-release': """NAME="Ubuntu"
+VERSION="14.04.4 LTS, Trusty Tahr"
+ID=ubuntu
+ID_LIKE=debian
+PRETTY_NAME="Ubuntu 14.04.4 LTS"
+VERSION_ID="14.04"
+HOME_URL="http://www.ubuntu.com/"
+SUPPORT_URL="http://help.ubuntu.com/"
+BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
+"""},
+        'platform.dist': ('Ubuntu', '14.04', 'trusty'),
+        'result': {'distribution': u'Ubuntu',
+                   'distribution_major_version': u'14',
+                   'distribution_release': u'trusty',
+                   'distribution_version': u'14.04'}
+    },
+    {
+        'name': "Ubuntu 12.04",
+        'input': {'/etc/lsb-release': """DISTRIB_ID=Ubuntu
+DISTRIB_RELEASE=12.04
+DISTRIB_CODENAME=precise
+DISTRIB_DESCRIPTION="Ubuntu 12.04.5 LTS"
+""",
+                  '/etc/os-release': """NAME="Ubuntu"
+VERSION="12.04.5 LTS, Precise Pangolin"
+ID=ubuntu
+ID_LIKE=debian
+PRETTY_NAME="Ubuntu precise (12.04.5 LTS)"
+VERSION_ID="12.04"
+"""},
+        'platform.dist': ('Ubuntu', '12.04', 'precise'),
+        'result': {'distribution': u'Ubuntu',
+                   'distribution_major_version': u'12',
+                   'distribution_release': u'precise',
+                   'distribution_version': u'12.04'}
+    },
+    {
+        'name': 'Core OS',
+        'input': {
+            '/etc/os-release':"""
+NAME=CoreOS
+ID=coreos
+VERSION=976.0.0
+VERSION_ID=976.0.0
+BUILD_ID=2016-03-03-2324
+PRETTY_NAME="CoreOS 976.0.0 (Coeur Rouge)"
+ANSI_COLOR="1;32"
+HOME_URL="https://coreos.com/"
+BUG_REPORT_URL="https://github.com/coreos/bugs/issues"
+            """,
+            '/etc/lsb-release':"""DISTRIB_ID=CoreOS
+DISTRIB_RELEASE=976.0.0
+DISTRIB_CODENAME="Coeur Rouge"
+DISTRIB_DESCRIPTION="CoreOS 976.0.0 (Coeur Rouge)"
+""",
+        },
+        'platform.dist': ('', '', ''),
+        'result' : {
+            "distribution": "CoreOS",
+            "distribution_major_version": "NA",
+            "distribution_release": "NA",
+            "distribution_version": "976.0.0",
+        }
+    }
+
+
+]
+
+@unittest.skipIf(sys.version_info[0] >= 3, "Python 3 is not supported on targets (yet)")
+def test_distribution_version():
+    """tests the distribution parsing code of the Facts class
+
+    testsets have
+    * a name (for output/debugging only)
+    * input files that are faked
+      * those should be complete and also include "irrelevant" files that might be mistaken as coming from other distributions
+      * all files that are not listed here are assumed to not exist at all
+    * the output of pythons platform.dist()
+    * results for the ansible variables distribution*
+    """
+
+    # needs to be in here, because the import fails with python3 still
+    import ansible.module_utils.facts as facts
+
+    real_stdin = sys.stdin
+    from ansible.module_utils import basic
+
+    args = json.dumps(dict(ANSIBLE_MODULE_ARGS={}, ANSIBLE_MODULE_CONSTANTS={}))
+    if PY3:
+        sys.stdin = StringIO(args)
+        sys.stdin.buffer = BytesIO(to_bytes(args))
+    else:
+        sys.stdin = BytesIO(to_bytes(args))
+    module = basic.AnsibleModule(argument_spec=dict())
+
+    for t in TESTSETS:
+        # run individual tests via generator
+        # set nicer stdout output for nosetest
+        _test_one_distribution.description = "check distribution_version for %s" % t['name']
+        yield _test_one_distribution, facts, module, t
+
+
+    sys.stdin = real_stdin
+
+
+def _test_one_distribution(facts, module, testcase):
+    """run the test on one distribution testcase
+    
+    * prepare some mock functions to get the testdata in
+    * run Facts()
+    * compare with the expected output
+    """
+
+    def mock_get_file_content(fname, default=None, strip=True):
+        """give fake content if it exists, otherwise pretend the file is empty"""
+        data = default
+        if fname in testcase['input']:
+            # for debugging
+            print('faked '+fname+' for '+testcase['name'])
+            data = testcase['input'][fname].strip()
+        if strip and data is not None:
+            data = data.strip()
+        return data
+
+    def mock_path_exists(fname):
+        return fname in testcase['input']
+
+    def mock_path_getsize(fname):
+        if fname in testcase['input']:
+            # the len is not used, but why not be honest if you can be?
+            return len(testcase['input'][fname])
+        else:
+            return 0
+
+    @patch('ansible.module_utils.facts.get_file_content', mock_get_file_content)
+    @patch('os.path.exists', mock_path_exists)
+    @patch('os.path.getsize', mock_path_getsize)
+    @patch('platform.dist', lambda: testcase['platform.dist'])
+    @patch('platform.system', lambda: 'Linux')
+    def get_facts(testcase):
+        return facts.Facts(module).populate()
+    
+    generated_facts = get_facts(testcase)
+
+    # testcase['result'] has a list of variables and values it expects Facts() to set
+    for key, val in testcase['result'].items():
+        assert key in generated_facts
+        msg = 'Comparing value of %s on %s, should: %s, is: %s' %\
+            (key, testcase['name'], val, generated_facts[key])
+        assert generated_facts[key] == val, msg