Port from plaform.dist to ansible.module_utils.distro.linux_distribution

ci_complete
This commit is contained in:
Toshio Kuratomi
2018-12-10 17:04:14 -08:00
parent be65d9cfe5
commit 61b1daa65f
10 changed files with 248 additions and 114 deletions

View File

@@ -47,6 +47,8 @@ MODULE_UTILS_BASIC_IMPORTS = frozenset((('_text',),
('common', 'file'),
('common', 'process'),
('common', 'sys_info'),
('distro', '__init__'),
('distro', '_distro'),
('parsing', '__init__'),
('parsing', 'convert_bool'),
('pycompat24',),
@@ -63,6 +65,8 @@ MODULE_UTILS_BASIC_FILES = frozenset(('ansible/module_utils/parsing/__init__.py'
'ansible/module_utils/common/__init__.py',
'ansible/module_utils/common/file.py',
'ansible/module_utils/common/sys_info.py',
'ansible/module_utils/distro/__init__.py',
'ansible/module_utils/distro/_distro.py',
'ansible/module_utils/pycompat24.py',
))

View File

@@ -1,108 +1,159 @@
# -*- coding: utf-8 -*-
# (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com>
# (c) 2016 Toshio Kuratomi <tkuratomi@ansible.com>
# (c) 2017 Ansible Project
# (c) 2017-2018 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
import pytest
from units.mock.procenv import ModuleTestCase
from units.compat.mock import patch
from ansible.module_utils.six.moves import builtins
# Functions being tested
from ansible.module_utils.common.sys_info import get_all_subclasses
from ansible.module_utils.common.sys_info import get_distribution
from ansible.module_utils.common.sys_info import get_distribution_version
from ansible.module_utils.common.sys_info import get_platform
from ansible.module_utils.common.sys_info import load_platform_subclass
realimport = builtins.__import__
class TestPlatform(ModuleTestCase):
def test_module_utils_basic_get_platform(self):
with patch('platform.system', return_value='foo'):
from ansible.module_utils.common.sys_info import get_platform
self.assertEqual(get_platform(), 'foo')
@pytest.fixture
def platform_linux(mocker):
mocker.patch('platform.system', return_value='Linux')
def test_module_utils_basic_get_distribution(self):
from ansible.module_utils.common.sys_info import get_distribution
with patch('platform.system', return_value='Foo'):
self.assertEqual(get_distribution(), None)
#
# get_platform tests
#
with patch('platform.system', return_value='Linux'):
with patch('platform.linux_distribution', return_value=["foo"]):
self.assertEqual(get_distribution(), "Foo")
def test_get_platform():
with patch('platform.system', return_value='foo'):
assert get_platform() == 'foo'
with patch('os.path.isfile', return_value=True):
with patch('platform.linux_distribution', side_effect=[("AmazonFooBar", )]):
self.assertEqual(get_distribution(), "Amazonfoobar")
with patch('platform.linux_distribution', side_effect=(("", ), ("AmazonFooBam",))):
self.assertEqual(get_distribution(), "Amazon")
#
# get_distribution tests
#
with patch('platform.linux_distribution', side_effect=[("", ), ("", )]):
self.assertEqual(get_distribution(), "OtherLinux")
def test_get_distribution_not_linux():
"""If it's not Linux, then it has no distribution"""
with patch('platform.system', return_value='Foo'):
assert get_distribution() is None
def _dist(distname='', version='', id='', supported_dists=(), full_distribution_name=1):
if supported_dists != ():
return ("Bar", "2", "Two")
else:
return ("", "", "")
with patch('platform.linux_distribution', side_effect=_dist):
self.assertEqual(get_distribution(), "Bar")
@pytest.mark.usefixtures("platform_linux")
class TestGetDistribution:
""" Tests for get_distribution that have to find somethine"""
def test_distro_known(self):
with patch('ansible.module_utils.distro.name', return_value="foo"):
assert get_distribution() == "Foo"
with patch('platform.linux_distribution', side_effect=Exception("boo")):
with patch('platform.dist', return_value=("bar", "2", "Two")):
self.assertEqual(get_distribution(), "Bar")
def test_distro_unknown(self):
with patch('ansible.module_utils.distro.name', return_value=""):
assert get_distribution() == "OtherLinux"
def test_module_utils_basic_get_distribution_version(self):
from ansible.module_utils.common.sys_info import get_distribution_version
def test_distro_amazon_part_of_another_name(self):
with patch('ansible.module_utils.distro.name', return_value="AmazonFooBar"):
assert get_distribution() == "Amazonfoobar"
with patch('platform.system', return_value='Foo'):
self.assertEqual(get_distribution_version(), None)
def test_distro_amazon_linux(self):
with patch('ansible.module_utils.distro.name', return_value="Amazon Linux AMI"):
assert get_distribution() == "Amazon"
with patch('platform.system', return_value='Linux'):
with patch('platform.linux_distribution', return_value=("foo", "1", "One")):
self.assertEqual(get_distribution_version(), "1")
with patch('os.path.isfile', return_value=True):
def _dist(distname='', version='', id='', supported_dists=(), full_distribution_name=1):
if supported_dists != ():
return ("AmazonFooBar", "2", "")
else:
return ("", "", "")
#
# get_distribution_version tests
#
with patch('platform.linux_distribution', side_effect=_dist):
self.assertEqual(get_distribution_version(), "2")
def test_get_distribution_version_not_linux():
"""If it's not Linux, then it has no distribution"""
with patch('platform.system', return_value='Foo'):
assert get_distribution_version() is None
with patch('platform.linux_distribution', side_effect=Exception("boo")):
with patch('platform.dist', return_value=("bar", "3", "Three")):
self.assertEqual(get_distribution_version(), "3")
def test_module_utils_basic_load_platform_subclass(self):
class LinuxTest:
pass
@pytest.mark.usefixtures("platform_linux")
def test_distro_found():
with patch('ansible.module_utils.distro.version', return_value="1"):
assert get_distribution_version() == "1"
class Foo(LinuxTest):
platform = "Linux"
distribution = None
class Bar(LinuxTest):
platform = "Linux"
distribution = "Bar"
#
# Tests for LoadPlatformSubclass
#
from ansible.module_utils.common.sys_info import load_platform_subclass
class TestLoadPlatformSubclass:
class LinuxTest:
pass
# match just the platform class, not a specific distribution
with patch('ansible.module_utils.common.sys_info.get_platform', return_value="Linux"):
with patch('ansible.module_utils.common.sys_info.get_distribution', return_value=None):
self.assertIs(type(load_platform_subclass(LinuxTest)), Foo)
class Foo(LinuxTest):
platform = "Linux"
distribution = None
# match both the distribution and platform class
with patch('ansible.module_utils.common.sys_info.get_platform', return_value="Linux"):
with patch('ansible.module_utils.common.sys_info.get_distribution', return_value="Bar"):
self.assertIs(type(load_platform_subclass(LinuxTest)), Bar)
class Bar(LinuxTest):
platform = "Linux"
distribution = "Bar"
def test_not_linux(self):
# if neither match, the fallback should be the top-level class
with patch('ansible.module_utils.common.sys_info.get_platform', return_value="Foo"):
with patch('ansible.module_utils.common.sys_info.get_distribution', return_value=None):
self.assertIs(type(load_platform_subclass(LinuxTest)), LinuxTest)
assert isinstance(load_platform_subclass(self.LinuxTest), self.LinuxTest)
@pytest.mark.usefixtures("platform_linux")
def test_get_distribution_none(self):
# match just the platform class, not a specific distribution
with patch('ansible.module_utils.common.sys_info.get_distribution', return_value=None):
assert isinstance(load_platform_subclass(self.LinuxTest), self.Foo)
@pytest.mark.usefixtures("platform_linux")
def test_get_distribution_found(self):
# match both the distribution and platform class
with patch('ansible.module_utils.common.sys_info.get_distribution', return_value="Bar"):
assert isinstance(load_platform_subclass(self.LinuxTest), self.Bar)
#
# Tests for get_all_subclasses
#
class TestGetAllSubclasses:
class Base:
pass
class BranchI(Base):
pass
class BranchII(Base):
pass
class BranchIA(BranchI):
pass
class BranchIB(BranchI):
pass
class BranchIIA(BranchII):
pass
class BranchIIB(BranchII):
pass
def test_bottom_level(self):
assert get_all_subclasses(self.BranchIIB) == []
def test_one_inheritance(self):
assert set(get_all_subclasses(self.BranchII)) == set([self.BranchIIA, self.BranchIIB])
def test_toplevel(self):
assert set(get_all_subclasses(self.Base)) == set([self.BranchI, self.BranchII,
self.BranchIA, self.BranchIB,
self.BranchIIA, self.BranchIIB])

View File

@@ -7,8 +7,11 @@ __metaclass__ = type
from itertools import product
import mock
import pytest
from ansible.module_utils.six.moves import builtins
# the module we are actually testing (sort of)
from ansible.module_utils.facts.system.distribution import DistributionFactCollector
@@ -1044,7 +1047,7 @@ def test_distribution_version(am, mocker, testcase):
* 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()
* the output of ansible.module_utils.distro.linux_distribution() [called platform.dist() for historical reasons]
* results for the ansible variables distribution* and os_family
"""
@@ -1081,14 +1084,43 @@ def test_distribution_version(am, mocker, testcase):
def mock_platform_version():
return testcase.get('platform.version', '')
def mock_distro_name():
return testcase['platform.dist'][0]
def mock_distro_version():
return testcase['platform.dist'][1]
def mock_distro_codename():
return testcase['platform.dist'][2]
def mock_open(filename, mode='r'):
if filename in testcase['input']:
file_object = mocker.mock_open(read_data=testcase['input'][filename]).return_value
file_object.__iter__.return_value = testcase['input'][filename].splitlines(True)
else:
file_object = real_open(filename, mode)
return file_object
def mock_os_path_is_file(filename):
if filename in testcase['input']:
return True
return False
mocker.patch('ansible.module_utils.facts.system.distribution.get_file_content', mock_get_file_content)
mocker.patch('ansible.module_utils.facts.system.distribution.get_uname_version', mock_get_uname_version)
mocker.patch('ansible.module_utils.facts.system.distribution._file_exists', mock_file_exists)
mocker.patch('platform.dist', lambda: testcase['platform.dist'])
mocker.patch('ansible.module_utils.distro.name', mock_distro_name)
mocker.patch('ansible.module_utils.distro.id', mock_distro_name)
mocker.patch('ansible.module_utils.distro.version', mock_distro_version)
mocker.patch('ansible.module_utils.distro.codename', mock_distro_codename)
mocker.patch('os.path.isfile', mock_os_path_is_file)
mocker.patch('platform.system', mock_platform_system)
mocker.patch('platform.release', mock_platform_release)
mocker.patch('platform.version', mock_platform_version)
real_open = builtins.open
mocker.patch.object(builtins, 'open', new=mock_open)
# run Facts()
distro_collector = DistributionFactCollector()
generated_facts = distro_collector.collect(am)

View File

@@ -16,6 +16,8 @@ import platform
import pytest
from ansible.module_utils import distro
from ansible.module_utils.common.sys_info import (get_distribution, get_distribution_version,
get_distribution_codename)
# Generic test case with minimal assertions about specific returned values.
@@ -42,11 +44,12 @@ class TestDistroCompat():
_platform_supported_dists = platform._supported_dists
def test_linux_distribution(self):
distro_linux_dist = (get_distribution(), get_distribution_version(), get_distribution_codename())
platform_linux_dist = platform.linux_distribution(supported_dists=self._platform_supported_dists)
distro_linux_dist = distro.linux_distribution()
assert isinstance(distro_linux_dist, type(platform_linux_dist)), \
'linux_distrution() returned type (%s) which is different from platform.linux_distribution type (%s)' % \
'linux_distribution() returned type (%s) which is different from platform.linux_distribution type (%s)' % \
(type(distro_linux_dist), type(platform_linux_dist))
# TODO: add the cases where we expect them to differ
@@ -55,6 +58,9 @@ class TestDistroCompat():
assert distro_linux_dist[0] == platform_linux_dist[0]
assert distro_linux_dist[1] == platform_linux_dist[1]
# FIXME: This fails on at least Fedora
# platform returns the 'id', while distro returns the 'codename'
if platform_linux_dist[0] == 'Fedora' and 20 < int(platform_linux_dist[1]) < 28:
pytest.skip("Fedora versions between 20 and 28 return the variant instead of the code name making this test unreliable")
# Fedora considers the platform_linux behaviour to have been a bug as it's finding the
# variant, not the code name. Fedora wants this to be the empty string.
platform_linux_dist = platform_linux_dist[:2] + ('',)
assert distro_linux_dist[2] == platform_linux_dist[2]