Ensure Clear Linux parsing is actually parsing a Clear Linux host and all others fall back to NA (#53298)

Fixes a bug where parse_distribution_file_ClearLinux() was called on CoreOS (and probably many other distros) and it returned True since it successfully parses the distribution file. Since this file exists on many Linux distributions and they are a very similar format, add an additional check to make sure it is Clear Linux.

Change the order in which distribution files are processed so NA is last. This prevents a match on CoreOS hosts since they also have /etc/os-release and the called matching function for NA is very general and will match CoreOS.

* Add changelog

* Add unit tests

Only add tests for Clear Linux parsing since that was the cause of this issue.
This commit is contained in:
Sam Doran 2019-03-08 10:40:49 -05:00 committed by GitHub
parent ba3345b52b
commit 1d91e03119
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 87 additions and 5 deletions

View file

@ -0,0 +1,2 @@
bugfixes:
- distribution - add check to remove incorrect matches of Clear Linux when processing distribution files (https://github.com/ansible/ansible/issues/50009)

View file

@ -70,8 +70,8 @@ class DistributionFiles:
{'path': '/etc/lsb-release', 'name': 'Mandriva'},
{'path': '/etc/sourcemage-release', 'name': 'SMGL'},
{'path': '/usr/lib/os-release', 'name': 'ClearLinux'},
{'path': '/etc/os-release', 'name': 'NA'},
{'path': '/etc/coreos/update.conf', 'name': 'Coreos'},
{'path': '/etc/os-release', 'name': 'NA'},
)
SEARCH_STRING = {
@ -406,6 +406,11 @@ class DistributionFiles:
if "clearlinux" not in name.lower():
return False, clear_facts
pname = re.search('NAME="(.*)"', data)
if pname:
if 'Clear Linux' not in pname.groups()[0]:
return False, clear_facts
clear_facts['distribution'] = pname.groups()[0]
version = re.search('VERSION_ID=(.*)', data)
if version:
clear_facts['distribution_major_version'] = version.groups()[0]
@ -413,9 +418,6 @@ class DistributionFiles:
release = re.search('ID=(.*)', data)
if release:
clear_facts['distribution_release'] = release.groups()[0]
pname = re.search('NAME="(.*)"', data)
if pname:
clear_facts['distribution'] = pname.groups()[0]
return True, clear_facts
@ -449,8 +451,8 @@ class Distribution(object):
{'path': '/etc/altlinux-release', 'name': 'Altlinux'},
{'path': '/etc/sourcemage-release', 'name': 'SMGL'},
{'path': '/usr/lib/os-release', 'name': 'ClearLinux'},
{'path': '/etc/os-release', 'name': 'NA'},
{'path': '/etc/coreos/update.conf', 'name': 'Coreos'},
{'path': '/etc/os-release', 'name': 'NA'},
)
SEARCH_STRING = {

View file

@ -0,0 +1,78 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
from units.compat.mock import Mock
from ansible.module_utils.facts.system.distribution import DistributionFiles
def mock_module():
mock_module = Mock()
mock_module.params = {'gather_subset': ['all'],
'gather_timeout': 5,
'filter': '*'}
mock_module.get_bin_path = Mock(return_value=None)
return mock_module
def test_parse_distribution_file_clear_linux():
test_input = {
'name': 'Clearlinux',
'data': 'NAME="Clear Linux OS"\nVERSION=1\nID=clear-linux-os\nID_LIKE=clear-linux-os\nVERSION_ID=28120\nPRETTY_NAME="Clear Linux OS"\nANSI_COLOR="1;35"'
'\nHOME_URL="https://clearlinux.org"\nSUPPORT_URL="https://clearlinux.org"\nBUG_REPORT_URL="mailto:dev@lists.clearlinux.org"',
'path': '/usr/lib/os-release',
'collected_facts': None,
}
result = (
True,
{
'distribution': 'Clear Linux OS',
'distribution_major_version': '28120',
'distribution_release': 'clear-linux-os',
'distribution_version': '28120'
}
)
distribution = DistributionFiles(module=mock_module())
assert result == distribution.parse_distribution_file_ClearLinux(**test_input)
def test_parse_distribution_file_clear_linux_no_match():
# Test against data from Linux Mint and CoreOS to ensure we do not get a reported
# match from parse_distribution_file_ClearLinux()
scenarios = [
{
# CoreOS
'case': {
'name': 'Clearlinux',
'data': 'NAME="Container Linux by CoreOS"\nID=coreos\nVERSION=1911.5.0\nVERSION_ID=1911.5.0\nBUILD_ID=2018-12-15-2317\nPRETTY_NAME="Container L'
'inux by CoreOS 1911.5.0 (Rhyolite)"\nANSI_COLOR="38;5;75"\nHOME_URL="https://coreos.com/"\nBUG_REPORT_URL="https://issues.coreos.com"'
'\nCOREOS_BOARD="amd64-usr"',
'path': '/usr/lib/os-release',
'collected_facts': None,
},
'result': (False, {}),
},
{
# Linux Mint
'case': {
'name': 'Clearlinux',
'data': 'NAME="Linux Mint"\nVERSION="19.1 (Tessa)"\nID=linuxmint\nID_LIKE=ubuntu\nPRETTY_NAME="Linux Mint 19.1"\nVERSION_ID="19.1"\nHOME_URL="h'
'ttps://www.linuxmint.com/"\nSUPPORT_URL="https://forums.ubuntu.com/"\nBUG_REPORT_URL="http://linuxmint-troubleshooting-guide.readthedo'
'cs.io/en/latest/"\nPRIVACY_POLICY_URL="https://www.linuxmint.com/"\nVERSION_CODENAME=tessa\nUBUNTU_CODENAME=bionic',
'path': '/usr/lib/os-release',
'collected_facts': None,
},
'result': (False, {}),
},
]
distribution = DistributionFiles(module=mock_module())
for scenario in scenarios:
assert scenario['result'] == distribution.parse_distribution_file_ClearLinux(**scenario['case'])