summaryrefslogtreecommitdiffstats
path: root/roles/openshift_health_checker
diff options
context:
space:
mode:
Diffstat (limited to 'roles/openshift_health_checker')
-rw-r--r--roles/openshift_health_checker/action_plugins/openshift_health_check.py60
-rwxr-xr-xroles/openshift_health_checker/library/aos_version.py214
-rw-r--r--roles/openshift_health_checker/meta/main.yml1
-rw-r--r--roles/openshift_health_checker/openshift_checks/package_version.py8
-rw-r--r--roles/openshift_health_checker/test/action_plugin_test.py227
-rw-r--r--roles/openshift_health_checker/test/aos_version_test.py120
-rw-r--r--roles/openshift_health_checker/test/conftest.py10
-rw-r--r--roles/openshift_health_checker/test/package_version_test.py13
8 files changed, 562 insertions, 91 deletions
diff --git a/roles/openshift_health_checker/action_plugins/openshift_health_check.py b/roles/openshift_health_checker/action_plugins/openshift_health_check.py
index cf0fe19f1..03c40b78b 100644
--- a/roles/openshift_health_checker/action_plugins/openshift_health_check.py
+++ b/roles/openshift_health_checker/action_plugins/openshift_health_check.py
@@ -4,6 +4,7 @@ Ansible action plugin to execute health checks in OpenShift clusters.
# pylint: disable=wrong-import-position,missing-docstring,invalid-name
import sys
import os
+from collections import defaultdict
try:
from __main__ import display
@@ -41,20 +42,11 @@ class ActionModule(ActionBase):
return result
args = self._task.args
- requested_checks = resolve_checks(args.get("checks", []), known_checks.values())
-
- unknown_checks = requested_checks - set(known_checks)
- if unknown_checks:
- result["failed"] = True
- result["msg"] = (
- "One or more checks are unknown: {}. "
- "Make sure there is no typo in the playbook and no files are missing."
- ).format(", ".join(unknown_checks))
- return result
+ resolved_checks = resolve_checks(args.get("checks", []), known_checks.values())
result["checks"] = check_results = {}
- for check_name in requested_checks & set(known_checks):
+ for check_name in resolved_checks:
display.banner("CHECK [{} : {}]".format(check_name, task_vars["ansible_host"]))
check = known_checks[check_name]
@@ -81,10 +73,7 @@ class ActionModule(ActionBase):
load_checks()
known_checks = {}
-
- known_check_classes = set(cls for cls in OpenShiftCheck.subclasses())
-
- for cls in known_check_classes:
+ for cls in OpenShiftCheck.subclasses():
check_name = cls.name
if check_name in known_checks:
other_cls = known_checks[check_name].__class__
@@ -94,26 +83,45 @@ class ActionModule(ActionBase):
cls.__module__, cls.__name__,
other_cls.__module__, other_cls.__name__))
known_checks[check_name] = cls(execute_module=self._execute_module)
-
return known_checks
def resolve_checks(names, all_checks):
"""Returns a set of resolved check names.
- Resolving a check name involves expanding tag references (e.g., '@tag') with
- all the checks that contain the given tag.
+ Resolving a check name expands tag references (e.g., "@tag") to all the
+ checks that contain the given tag. OpenShiftCheckException is raised if
+ names contains an unknown check or tag name.
names should be a sequence of strings.
all_checks should be a sequence of check classes/instances.
"""
- resolved = set()
- for name in names:
- if name.startswith("@"):
- for check in all_checks:
- if name[1:] in check.tags:
- resolved.add(check.name)
- else:
- resolved.add(name)
+ known_check_names = set(check.name for check in all_checks)
+ known_tag_names = set(name for check in all_checks for name in check.tags)
+
+ check_names = set(name for name in names if not name.startswith('@'))
+ tag_names = set(name[1:] for name in names if name.startswith('@'))
+
+ unknown_check_names = check_names - known_check_names
+ unknown_tag_names = tag_names - known_tag_names
+
+ if unknown_check_names or unknown_tag_names:
+ msg = []
+ if unknown_check_names:
+ msg.append('Unknown check names: {}.'.format(', '.join(sorted(unknown_check_names))))
+ if unknown_tag_names:
+ msg.append('Unknown tag names: {}.'.format(', '.join(sorted(unknown_tag_names))))
+ msg.append('Make sure there is no typo in the playbook and no files are missing.')
+ raise OpenShiftCheckException('\n'.join(msg))
+
+ tag_to_checks = defaultdict(set)
+ for check in all_checks:
+ for tag in check.tags:
+ tag_to_checks[tag].add(check.name)
+
+ resolved = check_names.copy()
+ for tag in tag_names:
+ resolved.update(tag_to_checks[tag])
+
return resolved
diff --git a/roles/openshift_health_checker/library/aos_version.py b/roles/openshift_health_checker/library/aos_version.py
index 191a4b107..a46589443 100755
--- a/roles/openshift_health_checker/library/aos_version.py
+++ b/roles/openshift_health_checker/library/aos_version.py
@@ -1,91 +1,199 @@
#!/usr/bin/python
# vim: expandtab:tabstop=4:shiftwidth=4
'''
-Ansible module for determining if multiple versions of an OpenShift package are
-available, and if the version requested is available down to the given
-precision.
-
-Multiple versions available suggest that multiple repos are enabled for the
-different versions, which may cause installation problems.
+Ansible module for yum-based systems determining if multiple releases
+of an OpenShift package are available, and if the release requested
+(if any) is available down to the given precision.
+
+For Enterprise, multiple releases available suggest that multiple repos
+are enabled for the different releases, which may cause installation
+problems. With Origin, however, this is a normal state of affairs as
+all the releases are provided in a single repo with the expectation that
+only the latest can be installed.
+
+Code in the openshift_version role contains a lot of logic to pin down
+the exact package and image version to use and so does some validation
+of release availability already. Without duplicating all that, we would
+like the user to have a helpful error message if we detect things will
+not work out right. Note that if openshift_release is not specified in
+the inventory, the version comparison checks just pass.
+
+TODO: fail gracefully on non-yum systems (dnf in Fedora)
'''
-import yum # pylint: disable=import-error
-
from ansible.module_utils.basic import AnsibleModule
+IMPORT_EXCEPTION = None
+try:
+ import yum # pylint: disable=import-error
+except ImportError as err:
+ IMPORT_EXCEPTION = err # in tox test env, yum import fails
+
-def main(): # pylint: disable=missing-docstring,too-many-branches
+class AosVersionException(Exception):
+ '''Base exception class for package version problems'''
+ def __init__(self, message, problem_pkgs=None):
+ Exception.__init__(self, message)
+ self.problem_pkgs = problem_pkgs
+
+
+def main():
+ '''Entrypoint for this Ansible module'''
module = AnsibleModule(
argument_spec=dict(
- prefix=dict(required=True), # atomic-openshift, origin, ...
- version=dict(required=True),
+ requested_openshift_release=dict(type="str", default=''),
+ openshift_deployment_type=dict(required=True),
+ rpm_prefix=dict(required=True), # atomic-openshift, origin, ...?
),
supports_check_mode=True
)
- def bail(error): # pylint: disable=missing-docstring
- module.fail_json(msg=error)
-
- rpm_prefix = module.params['prefix']
+ if IMPORT_EXCEPTION:
+ module.fail_json(msg="aos_version module could not import yum: %s" % IMPORT_EXCEPTION)
+ # determine the packages we will look for
+ rpm_prefix = module.params['rpm_prefix']
if not rpm_prefix:
- bail("prefix must not be empty")
-
- yb = yum.YumBase() # pylint: disable=invalid-name
- yb.conf.disable_excludes = ["all"] # assume the openshift excluder will be managed, ignore current state
-
- # search for package versions available for aos pkgs
- expected_pkgs = [
+ module.fail_json(msg="rpm_prefix must not be empty")
+ expected_pkgs = set([
rpm_prefix,
rpm_prefix + '-master',
rpm_prefix + '-node',
- ]
+ ])
+
+ # determine what level of precision the user specified for the openshift version.
+ # should look like a version string with possibly many segments e.g. "3.4.1":
+ requested_openshift_release = module.params['requested_openshift_release']
+
+ # get the list of packages available and complain if anything is wrong
+ try:
+ pkgs = _retrieve_available_packages(expected_pkgs)
+ if requested_openshift_release:
+ _check_precise_version_found(pkgs, expected_pkgs, requested_openshift_release)
+ _check_higher_version_found(pkgs, expected_pkgs, requested_openshift_release)
+ if module.params['openshift_deployment_type'] in ['openshift-enterprise']:
+ _check_multi_minor_release(pkgs, expected_pkgs)
+ except AosVersionException as excinfo:
+ module.fail_json(msg=str(excinfo))
+ module.exit_json(changed=False)
+
+
+def _retrieve_available_packages(expected_pkgs):
+ # search for package versions available for openshift pkgs
+ yb = yum.YumBase() # pylint: disable=invalid-name
+
+ # The openshift excluder prevents unintended updates to openshift
+ # packages by setting yum excludes on those packages. See:
+ # https://wiki.centos.org/SpecialInterestGroup/PaaS/OpenShift-Origin-Control-Updates
+ # Excludes are then disabled during an install or upgrade, but
+ # this check will most likely be running outside either. When we
+ # attempt to determine what packages are available via yum they may
+ # be excluded. So, for our purposes here, disable excludes to see
+ # what will really be available during an install or upgrade.
+ yb.conf.disable_excludes = ['all']
+
try:
pkgs = yb.pkgSack.returnPackages(patterns=expected_pkgs)
- except yum.Errors.PackageSackError as e: # pylint: disable=invalid-name
+ except yum.Errors.PackageSackError as excinfo:
# you only hit this if *none* of the packages are available
- bail('Unable to find any OpenShift packages.\nCheck your subscription and repo settings.\n%s' % e)
+ raise AosVersionException('\n'.join([
+ 'Unable to find any OpenShift packages.',
+ 'Check your subscription and repo settings.',
+ str(excinfo),
+ ]))
+ return pkgs
- # determine what level of precision we're expecting for the version
- expected_version = module.params['version']
- if expected_version.startswith('v'): # v3.3 => 3.3
- expected_version = expected_version[1:]
- num_dots = expected_version.count('.')
- pkgs_by_name_version = {}
+class PreciseVersionNotFound(AosVersionException):
+ '''Exception for reporting packages not available at given release'''
+ def __init__(self, requested_release, not_found):
+ msg = ['Not all of the required packages are available at requested version %s:' % requested_release]
+ msg += [' ' + name for name in not_found]
+ msg += ['Please check your subscriptions and enabled repositories.']
+ AosVersionException.__init__(self, '\n'.join(msg), not_found)
+
+
+def _check_precise_version_found(pkgs, expected_pkgs, requested_openshift_release):
+ # see if any packages couldn't be found at requested release version
+ # we would like to verify that the latest available pkgs have however specific a version is given.
+ # so e.g. if there is a package version 3.4.1.5 the check passes; if only 3.4.0, it fails.
+
pkgs_precise_version_found = {}
for pkg in pkgs:
- # get expected version precision
- match_version = '.'.join(pkg.version.split('.')[:num_dots + 1])
- if match_version == expected_version:
+ if pkg.name not in expected_pkgs:
+ continue
+ # does the version match, to the precision requested?
+ # and, is it strictly greater, at the precision requested?
+ match_version = '.'.join(pkg.version.split('.')[:requested_openshift_release.count('.') + 1])
+ if match_version == requested_openshift_release:
pkgs_precise_version_found[pkg.name] = True
- # get x.y version precision
- minor_version = '.'.join(pkg.version.split('.')[:2])
- if pkg.name not in pkgs_by_name_version:
- pkgs_by_name_version[pkg.name] = {}
- pkgs_by_name_version[pkg.name][minor_version] = True
- # see if any packages couldn't be found at requested version
- # see if any packages are available in more than one minor version
not_found = []
- multi_found = []
for name in expected_pkgs:
if name not in pkgs_precise_version_found:
not_found.append(name)
+
+ if not_found:
+ raise PreciseVersionNotFound(requested_openshift_release, not_found)
+
+
+class FoundHigherVersion(AosVersionException):
+ '''Exception for reporting that a higher version than requested is available'''
+ def __init__(self, requested_release, higher_found):
+ msg = ['Some required package(s) are available at a version',
+ 'that is higher than requested %s:' % requested_release]
+ msg += [' ' + name for name in higher_found]
+ msg += ['This will prevent installing the version you requested.']
+ msg += ['Please check your enabled repositories or adjust openshift_release.']
+ AosVersionException.__init__(self, '\n'.join(msg), higher_found)
+
+
+def _check_higher_version_found(pkgs, expected_pkgs, requested_openshift_release):
+ req_release_arr = [int(segment) for segment in requested_openshift_release.split(".")]
+ # see if any packages are available in a version higher than requested
+ higher_version_for_pkg = {}
+ for pkg in pkgs:
+ if pkg.name not in expected_pkgs:
+ continue
+ version = [int(segment) for segment in pkg.version.split(".")]
+ too_high = version[:len(req_release_arr)] > req_release_arr
+ higher_than_seen = version > higher_version_for_pkg.get(pkg.name, [])
+ if too_high and higher_than_seen:
+ higher_version_for_pkg[pkg.name] = version
+
+ if higher_version_for_pkg:
+ higher_found = []
+ for name, version in higher_version_for_pkg.items():
+ higher_found.append(name + '-' + '.'.join(str(segment) for segment in version))
+ raise FoundHigherVersion(requested_openshift_release, higher_found)
+
+
+class FoundMultiRelease(AosVersionException):
+ '''Exception for reporting multiple minor releases found for same package'''
+ def __init__(self, multi_found):
+ msg = ['Multiple minor versions of these packages are available']
+ msg += [' ' + name for name in multi_found]
+ msg += ["There should only be one OpenShift release repository enabled at a time."]
+ AosVersionException.__init__(self, '\n'.join(msg), multi_found)
+
+
+def _check_multi_minor_release(pkgs, expected_pkgs):
+ # see if any packages are available in more than one minor version
+ pkgs_by_name_version = {}
+ for pkg in pkgs:
+ # keep track of x.y (minor release) versions seen
+ minor_release = '.'.join(pkg.version.split('.')[:2])
+ if pkg.name not in pkgs_by_name_version:
+ pkgs_by_name_version[pkg.name] = {}
+ pkgs_by_name_version[pkg.name][minor_release] = True
+
+ multi_found = []
+ for name in expected_pkgs:
if name in pkgs_by_name_version and len(pkgs_by_name_version[name]) > 1:
multi_found.append(name)
- if not_found:
- msg = 'Not all of the required packages are available at requested version %s:\n' % expected_version
- for name in not_found:
- msg += ' %s\n' % name
- bail(msg + 'Please check your subscriptions and enabled repositories.')
- if multi_found:
- msg = 'Multiple minor versions of these packages are available\n'
- for name in multi_found:
- msg += ' %s\n' % name
- bail(msg + "There should only be one OpenShift version's repository enabled at a time.")
- module.exit_json(changed=False)
+ if multi_found:
+ raise FoundMultiRelease(multi_found)
if __name__ == '__main__':
diff --git a/roles/openshift_health_checker/meta/main.yml b/roles/openshift_health_checker/meta/main.yml
index 0bbeadd34..cd9b55902 100644
--- a/roles/openshift_health_checker/meta/main.yml
+++ b/roles/openshift_health_checker/meta/main.yml
@@ -1,3 +1,4 @@
---
dependencies:
- role: openshift_facts
+ - role: openshift_repos
diff --git a/roles/openshift_health_checker/openshift_checks/package_version.py b/roles/openshift_health_checker/openshift_checks/package_version.py
index 42193a1c6..cca2d8b75 100644
--- a/roles/openshift_health_checker/openshift_checks/package_version.py
+++ b/roles/openshift_health_checker/openshift_checks/package_version.py
@@ -10,11 +10,9 @@ class PackageVersion(NotContainerizedMixin, OpenShiftCheck):
tags = ["preflight"]
def run(self, tmp, task_vars):
- rpm_prefix = get_var(task_vars, "openshift", "common", "service_type")
- openshift_release = get_var(task_vars, "openshift_release")
-
args = {
- "prefix": rpm_prefix,
- "version": openshift_release,
+ "requested_openshift_release": get_var(task_vars, "openshift_release", default=''),
+ "openshift_deployment_type": get_var(task_vars, "openshift_deployment_type"),
+ "rpm_prefix": get_var(task_vars, "openshift", "common", "service_type"),
}
return self.execute_module("aos_version", args, tmp, task_vars)
diff --git a/roles/openshift_health_checker/test/action_plugin_test.py b/roles/openshift_health_checker/test/action_plugin_test.py
new file mode 100644
index 000000000..a877246f4
--- /dev/null
+++ b/roles/openshift_health_checker/test/action_plugin_test.py
@@ -0,0 +1,227 @@
+import pytest
+
+from openshift_health_check import ActionModule, resolve_checks
+from openshift_checks import OpenShiftCheckException
+
+
+def fake_check(name='fake_check', tags=None, is_active=True, run_return=None, run_exception=None):
+ """Returns a new class that is compatible with OpenShiftCheck for testing."""
+
+ _name, _tags = name, tags
+
+ class FakeCheck(object):
+ name = _name
+ tags = _tags or []
+
+ def __init__(self, execute_module=None):
+ pass
+
+ @classmethod
+ def is_active(cls, task_vars):
+ return is_active
+
+ def run(self, tmp, task_vars):
+ if run_exception is not None:
+ raise run_exception
+ return run_return
+
+ return FakeCheck
+
+
+# Fixtures
+
+
+@pytest.fixture
+def plugin():
+ task = FakeTask('openshift_health_check', {'checks': ['fake_check']})
+ plugin = ActionModule(task, None, None, None, None, None)
+ return plugin
+
+
+class FakeTask(object):
+ def __init__(self, action, args):
+ self.action = action
+ self.args = args
+ self.async = 0
+
+
+@pytest.fixture
+def task_vars():
+ return dict(openshift=dict(), ansible_host='unit-test-host')
+
+
+# Assertion helpers
+
+
+def failed(result, msg_has=None):
+ if msg_has is not None:
+ assert 'msg' in result
+ for term in msg_has:
+ assert term in result['msg']
+ return result.get('failed', False)
+
+
+def changed(result):
+ return result.get('changed', False)
+
+
+def skipped(result):
+ return result.get('skipped', False)
+
+
+# Tests
+
+
+@pytest.mark.parametrize('task_vars', [
+ None,
+ {},
+])
+def test_action_plugin_missing_openshift_facts(plugin, task_vars):
+ result = plugin.run(tmp=None, task_vars=task_vars)
+
+ assert failed(result, msg_has=['openshift_facts'])
+
+
+def test_action_plugin_cannot_load_checks_with_the_same_name(plugin, task_vars, monkeypatch):
+ FakeCheck1 = fake_check('duplicate_name')
+ FakeCheck2 = fake_check('duplicate_name')
+ checks = [FakeCheck1, FakeCheck2]
+ monkeypatch.setattr('openshift_checks.OpenShiftCheck.subclasses', classmethod(lambda cls: checks))
+
+ result = plugin.run(tmp=None, task_vars=task_vars)
+
+ assert failed(result, msg_has=['unique', 'duplicate_name', 'FakeCheck'])
+
+
+def test_action_plugin_skip_non_active_checks(plugin, task_vars, monkeypatch):
+ checks = [fake_check(is_active=False)]
+ monkeypatch.setattr('openshift_checks.OpenShiftCheck.subclasses', classmethod(lambda cls: checks))
+
+ result = plugin.run(tmp=None, task_vars=task_vars)
+
+ assert result['checks']['fake_check'] == {'skipped': True}
+ assert not failed(result)
+ assert not changed(result)
+ assert not skipped(result)
+
+
+def test_action_plugin_run_check_ok(plugin, task_vars, monkeypatch):
+ check_return_value = {'ok': 'test'}
+ check_class = fake_check(run_return=check_return_value)
+ monkeypatch.setattr(plugin, 'load_known_checks', lambda: {'fake_check': check_class()})
+ monkeypatch.setattr('openshift_health_check.resolve_checks', lambda *args: ['fake_check'])
+
+ result = plugin.run(tmp=None, task_vars=task_vars)
+
+ assert result['checks']['fake_check'] == check_return_value
+ assert not failed(result)
+ assert not changed(result)
+ assert not skipped(result)
+
+
+def test_action_plugin_run_check_changed(plugin, task_vars, monkeypatch):
+ check_return_value = {'ok': 'test', 'changed': True}
+ check_class = fake_check(run_return=check_return_value)
+ monkeypatch.setattr(plugin, 'load_known_checks', lambda: {'fake_check': check_class()})
+ monkeypatch.setattr('openshift_health_check.resolve_checks', lambda *args: ['fake_check'])
+
+ result = plugin.run(tmp=None, task_vars=task_vars)
+
+ assert result['checks']['fake_check'] == check_return_value
+ assert not failed(result)
+ assert changed(result)
+ assert not skipped(result)
+
+
+def test_action_plugin_run_check_fail(plugin, task_vars, monkeypatch):
+ check_return_value = {'failed': True}
+ check_class = fake_check(run_return=check_return_value)
+ monkeypatch.setattr(plugin, 'load_known_checks', lambda: {'fake_check': check_class()})
+ monkeypatch.setattr('openshift_health_check.resolve_checks', lambda *args: ['fake_check'])
+
+ result = plugin.run(tmp=None, task_vars=task_vars)
+
+ assert result['checks']['fake_check'] == check_return_value
+ assert failed(result, msg_has=['failed'])
+ assert not changed(result)
+ assert not skipped(result)
+
+
+def test_action_plugin_run_check_exception(plugin, task_vars, monkeypatch):
+ exception_msg = 'fake check has an exception'
+ run_exception = OpenShiftCheckException(exception_msg)
+ check_class = fake_check(run_exception=run_exception)
+ monkeypatch.setattr(plugin, 'load_known_checks', lambda: {'fake_check': check_class()})
+ monkeypatch.setattr('openshift_health_check.resolve_checks', lambda *args: ['fake_check'])
+
+ result = plugin.run(tmp=None, task_vars=task_vars)
+
+ assert failed(result['checks']['fake_check'], msg_has=exception_msg)
+ assert failed(result, msg_has=['failed'])
+ assert not changed(result)
+ assert not skipped(result)
+
+
+@pytest.mark.parametrize('names,all_checks,expected', [
+ ([], [], set()),
+ (
+ ['a', 'b'],
+ [
+ fake_check('a'),
+ fake_check('b'),
+ ],
+ set(['a', 'b']),
+ ),
+ (
+ ['a', 'b', '@group'],
+ [
+ fake_check('from_group_1', ['group', 'another_group']),
+ fake_check('not_in_group', ['another_group']),
+ fake_check('from_group_2', ['preflight', 'group']),
+ fake_check('a'),
+ fake_check('b'),
+ ],
+ set(['a', 'b', 'from_group_1', 'from_group_2']),
+ ),
+])
+def test_resolve_checks_ok(names, all_checks, expected):
+ assert resolve_checks(names, all_checks) == expected
+
+
+@pytest.mark.parametrize('names,all_checks,words_in_exception,words_not_in_exception', [
+ (
+ ['testA', 'testB'],
+ [],
+ ['check', 'name', 'testA', 'testB'],
+ ['tag', 'group', '@'],
+ ),
+ (
+ ['@group'],
+ [],
+ ['tag', 'name', 'group'],
+ ['check', '@'],
+ ),
+ (
+ ['testA', 'testB', '@group'],
+ [],
+ ['check', 'name', 'testA', 'testB', 'tag', 'group'],
+ ['@'],
+ ),
+ (
+ ['testA', 'testB', '@group'],
+ [
+ fake_check('from_group_1', ['group', 'another_group']),
+ fake_check('not_in_group', ['another_group']),
+ fake_check('from_group_2', ['preflight', 'group']),
+ ],
+ ['check', 'name', 'testA', 'testB'],
+ ['tag', 'group', '@'],
+ ),
+])
+def test_resolve_checks_failure(names, all_checks, words_in_exception, words_not_in_exception):
+ with pytest.raises(Exception) as excinfo:
+ resolve_checks(names, all_checks)
+ for word in words_in_exception:
+ assert word in str(excinfo.value)
+ for word in words_not_in_exception:
+ assert word not in str(excinfo.value)
diff --git a/roles/openshift_health_checker/test/aos_version_test.py b/roles/openshift_health_checker/test/aos_version_test.py
new file mode 100644
index 000000000..39c86067a
--- /dev/null
+++ b/roles/openshift_health_checker/test/aos_version_test.py
@@ -0,0 +1,120 @@
+import pytest
+import aos_version
+
+from collections import namedtuple
+Package = namedtuple('Package', ['name', 'version'])
+
+expected_pkgs = set(['spam', 'eggs'])
+
+
+@pytest.mark.parametrize('pkgs, requested_release, expect_not_found', [
+ (
+ [],
+ '3.2.1',
+ expected_pkgs, # none found
+ ),
+ (
+ [Package('spam', '3.2.1')],
+ '3.2',
+ ['eggs'], # completely missing
+ ),
+ (
+ [Package('spam', '3.2.1'), Package('eggs', '3.3.2')],
+ '3.2',
+ ['eggs'], # not the right version
+ ),
+ (
+ [Package('spam', '3.2.1'), Package('eggs', '3.2.1')],
+ '3.2',
+ [], # all found
+ ),
+ (
+ [Package('spam', '3.2.1'), Package('eggs', '3.2.1.5')],
+ '3.2.1',
+ [], # found with more specific version
+ ),
+ (
+ [Package('eggs', '1.2.3'), Package('eggs', '3.2.1.5')],
+ '3.2.1',
+ ['spam'], # eggs found with multiple versions
+ ),
+])
+def test_check_pkgs_for_precise_version(pkgs, requested_release, expect_not_found):
+ if expect_not_found:
+ with pytest.raises(aos_version.PreciseVersionNotFound) as e:
+ aos_version._check_precise_version_found(pkgs, expected_pkgs, requested_release)
+ assert set(expect_not_found) == set(e.value.problem_pkgs)
+ else:
+ aos_version._check_precise_version_found(pkgs, expected_pkgs, requested_release)
+
+
+@pytest.mark.parametrize('pkgs, requested_release, expect_higher', [
+ (
+ [],
+ '3.2.1',
+ [],
+ ),
+ (
+ [Package('spam', '3.2.1')],
+ '3.2',
+ [], # more precise but not strictly higher
+ ),
+ (
+ [Package('spam', '3.3')],
+ '3.2.1',
+ ['spam-3.3'], # lower precision, but higher
+ ),
+ (
+ [Package('spam', '3.2.1'), Package('eggs', '3.3.2')],
+ '3.2',
+ ['eggs-3.3.2'], # one too high
+ ),
+ (
+ [Package('eggs', '1.2.3'), Package('eggs', '3.2.1.5'), Package('eggs', '3.4')],
+ '3.2.1',
+ ['eggs-3.4'], # multiple versions, one is higher
+ ),
+ (
+ [Package('eggs', '3.2.1'), Package('eggs', '3.4'), Package('eggs', '3.3')],
+ '3.2.1',
+ ['eggs-3.4'], # multiple versions, two are higher
+ ),
+])
+def test_check_pkgs_for_greater_version(pkgs, requested_release, expect_higher):
+ if expect_higher:
+ with pytest.raises(aos_version.FoundHigherVersion) as e:
+ aos_version._check_higher_version_found(pkgs, expected_pkgs, requested_release)
+ assert set(expect_higher) == set(e.value.problem_pkgs)
+ else:
+ aos_version._check_higher_version_found(pkgs, expected_pkgs, requested_release)
+
+
+@pytest.mark.parametrize('pkgs, expect_to_flag_pkgs', [
+ (
+ [],
+ [],
+ ),
+ (
+ [Package('spam', '3.2.1')],
+ [],
+ ),
+ (
+ [Package('spam', '3.2.1'), Package('eggs', '3.2.2')],
+ [],
+ ),
+ (
+ [Package('spam', '3.2.1'), Package('spam', '3.3.2')],
+ ['spam'],
+ ),
+ (
+ [Package('eggs', '1.2.3'), Package('eggs', '3.2.1.5'), Package('eggs', '3.4')],
+ ['eggs'],
+ ),
+])
+def test_check_pkgs_for_multi_release(pkgs, expect_to_flag_pkgs):
+ if expect_to_flag_pkgs:
+ with pytest.raises(aos_version.FoundMultiRelease) as e:
+ aos_version._check_multi_minor_release(pkgs, expected_pkgs)
+ assert set(expect_to_flag_pkgs) == set(e.value.problem_pkgs)
+ else:
+ aos_version._check_multi_minor_release(pkgs, expected_pkgs)
diff --git a/roles/openshift_health_checker/test/conftest.py b/roles/openshift_health_checker/test/conftest.py
index bf717ae85..3cbd65507 100644
--- a/roles/openshift_health_checker/test/conftest.py
+++ b/roles/openshift_health_checker/test/conftest.py
@@ -1,5 +1,11 @@
import os
import sys
-# extend sys.path so that tests can import openshift_checks
-sys.path.insert(1, os.path.dirname(os.path.dirname(__file__)))
+# extend sys.path so that tests can import openshift_checks and action plugins
+# from this role.
+openshift_health_checker_path = os.path.dirname(os.path.dirname(__file__))
+sys.path[1:1] = [
+ openshift_health_checker_path,
+ os.path.join(openshift_health_checker_path, 'action_plugins'),
+ os.path.join(openshift_health_checker_path, 'library'),
+]
diff --git a/roles/openshift_health_checker/test/package_version_test.py b/roles/openshift_health_checker/test/package_version_test.py
index cc1d263bc..c6889ee9b 100644
--- a/roles/openshift_health_checker/test/package_version_test.py
+++ b/roles/openshift_health_checker/test/package_version_test.py
@@ -4,16 +4,19 @@ from openshift_checks.package_version import PackageVersion
def test_package_version():
task_vars = dict(
openshift=dict(common=dict(service_type='origin')),
- openshift_release='v3.5',
+ openshift_release='3.5',
+ openshift_deployment_type='origin',
)
return_value = object()
def execute_module(module_name=None, module_args=None, tmp=None, task_vars=None):
assert module_name == 'aos_version'
- assert 'prefix' in module_args
- assert 'version' in module_args
- assert module_args['prefix'] == task_vars['openshift']['common']['service_type']
- assert module_args['version'] == task_vars['openshift_release']
+ assert 'requested_openshift_release' in module_args
+ assert 'openshift_deployment_type' in module_args
+ assert 'rpm_prefix' in module_args
+ assert module_args['requested_openshift_release'] == task_vars['openshift_release']
+ assert module_args['openshift_deployment_type'] == task_vars['openshift_deployment_type']
+ assert module_args['rpm_prefix'] == task_vars['openshift']['common']['service_type']
return return_value
check = PackageVersion(execute_module=execute_module)