action_plugin_test.py 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. import pytest
  2. from ansible.playbook.play_context import PlayContext
  3. from openshift_health_check import ActionModule, resolve_checks
  4. from openshift_checks import OpenShiftCheckException
  5. def fake_check(name='fake_check', tags=None, is_active=True, run_return=None, run_exception=None, changed=False):
  6. """Returns a new class that is compatible with OpenShiftCheck for testing."""
  7. _name, _tags = name, tags
  8. class FakeCheck(object):
  9. name = _name
  10. tags = _tags or []
  11. changed = False
  12. def __init__(self, execute_module=None, task_vars=None, tmp=None):
  13. pass
  14. def is_active(self):
  15. return is_active
  16. def run(self):
  17. self.changed = changed
  18. if run_exception is not None:
  19. raise run_exception
  20. return run_return
  21. return FakeCheck
  22. # Fixtures
  23. @pytest.fixture
  24. def plugin():
  25. task = FakeTask('openshift_health_check', {'checks': ['fake_check']})
  26. plugin = ActionModule(task, None, PlayContext(), None, None, None)
  27. return plugin
  28. class FakeTask(object):
  29. def __init__(self, action, args):
  30. self.action = action
  31. self.args = args
  32. self.async = 0
  33. @pytest.fixture
  34. def task_vars():
  35. return dict(openshift=dict(), ansible_host='unit-test-host')
  36. # Assertion helpers
  37. def failed(result, msg_has=None):
  38. if msg_has is not None:
  39. assert 'msg' in result
  40. for term in msg_has:
  41. assert term.lower() in result['msg'].lower()
  42. return result.get('failed', False)
  43. def changed(result):
  44. return result.get('changed', False)
  45. # tests whether task is skipped, not individual checks
  46. def skipped(result):
  47. return result.get('skipped', False)
  48. # Tests
  49. @pytest.mark.parametrize('task_vars', [
  50. None,
  51. {},
  52. ])
  53. def test_action_plugin_missing_openshift_facts(plugin, task_vars):
  54. result = plugin.run(tmp=None, task_vars=task_vars)
  55. assert failed(result, msg_has=['openshift_facts'])
  56. def test_action_plugin_cannot_load_checks_with_the_same_name(plugin, task_vars, monkeypatch):
  57. FakeCheck1 = fake_check('duplicate_name')
  58. FakeCheck2 = fake_check('duplicate_name')
  59. checks = [FakeCheck1, FakeCheck2]
  60. monkeypatch.setattr('openshift_checks.OpenShiftCheck.subclasses', classmethod(lambda cls: checks))
  61. result = plugin.run(tmp=None, task_vars=task_vars)
  62. assert failed(result, msg_has=['unique', 'duplicate_name', 'FakeCheck'])
  63. def test_action_plugin_skip_non_active_checks(plugin, task_vars, monkeypatch):
  64. checks = [fake_check(is_active=False)]
  65. monkeypatch.setattr('openshift_checks.OpenShiftCheck.subclasses', classmethod(lambda cls: checks))
  66. result = plugin.run(tmp=None, task_vars=task_vars)
  67. assert result['checks']['fake_check'] == dict(skipped=True, skipped_reason="Not active for this host")
  68. assert not failed(result)
  69. assert not changed(result)
  70. assert not skipped(result)
  71. def test_action_plugin_skip_disabled_checks(plugin, task_vars, monkeypatch):
  72. checks = [fake_check('fake_check', is_active=True)]
  73. monkeypatch.setattr('openshift_checks.OpenShiftCheck.subclasses', classmethod(lambda cls: checks))
  74. task_vars['openshift_disable_check'] = 'fake_check'
  75. result = plugin.run(tmp=None, task_vars=task_vars)
  76. assert result['checks']['fake_check'] == dict(skipped=True, skipped_reason="Disabled by user request")
  77. assert not failed(result)
  78. assert not changed(result)
  79. assert not skipped(result)
  80. def test_action_plugin_run_check_ok(plugin, task_vars, monkeypatch):
  81. check_return_value = {'ok': 'test'}
  82. check_class = fake_check(run_return=check_return_value)
  83. monkeypatch.setattr(plugin, 'load_known_checks', lambda tmp, task_vars: {'fake_check': check_class()})
  84. monkeypatch.setattr('openshift_health_check.resolve_checks', lambda *args: ['fake_check'])
  85. result = plugin.run(tmp=None, task_vars=task_vars)
  86. assert result['checks']['fake_check'] == check_return_value
  87. assert not failed(result)
  88. assert not changed(result)
  89. assert not skipped(result)
  90. def test_action_plugin_run_check_changed(plugin, task_vars, monkeypatch):
  91. check_return_value = {'ok': 'test'}
  92. check_class = fake_check(run_return=check_return_value, changed=True)
  93. monkeypatch.setattr(plugin, 'load_known_checks', lambda tmp, task_vars: {'fake_check': check_class()})
  94. monkeypatch.setattr('openshift_health_check.resolve_checks', lambda *args: ['fake_check'])
  95. result = plugin.run(tmp=None, task_vars=task_vars)
  96. assert result['checks']['fake_check'] == check_return_value
  97. assert changed(result['checks']['fake_check'])
  98. assert not failed(result)
  99. assert changed(result)
  100. assert not skipped(result)
  101. def test_action_plugin_run_check_fail(plugin, task_vars, monkeypatch):
  102. check_return_value = {'failed': True}
  103. check_class = fake_check(run_return=check_return_value)
  104. monkeypatch.setattr(plugin, 'load_known_checks', lambda tmp, task_vars: {'fake_check': check_class()})
  105. monkeypatch.setattr('openshift_health_check.resolve_checks', lambda *args: ['fake_check'])
  106. result = plugin.run(tmp=None, task_vars=task_vars)
  107. assert result['checks']['fake_check'] == check_return_value
  108. assert failed(result, msg_has=['failed'])
  109. assert not changed(result)
  110. assert not skipped(result)
  111. def test_action_plugin_run_check_exception(plugin, task_vars, monkeypatch):
  112. exception_msg = 'fake check has an exception'
  113. run_exception = OpenShiftCheckException(exception_msg)
  114. check_class = fake_check(run_exception=run_exception, changed=True)
  115. monkeypatch.setattr(plugin, 'load_known_checks', lambda tmp, task_vars: {'fake_check': check_class()})
  116. monkeypatch.setattr('openshift_health_check.resolve_checks', lambda *args: ['fake_check'])
  117. result = plugin.run(tmp=None, task_vars=task_vars)
  118. assert failed(result['checks']['fake_check'], msg_has=exception_msg)
  119. assert failed(result, msg_has=['failed'])
  120. assert changed(result['checks']['fake_check'])
  121. assert changed(result)
  122. assert not skipped(result)
  123. def test_action_plugin_resolve_checks_exception(plugin, task_vars, monkeypatch):
  124. monkeypatch.setattr(plugin, 'load_known_checks', lambda tmp, task_vars: {})
  125. result = plugin.run(tmp=None, task_vars=task_vars)
  126. assert failed(result, msg_has=['unknown', 'name'])
  127. assert not changed(result)
  128. assert not skipped(result)
  129. @pytest.mark.parametrize('names,all_checks,expected', [
  130. ([], [], set()),
  131. (
  132. ['a', 'b'],
  133. [
  134. fake_check('a'),
  135. fake_check('b'),
  136. ],
  137. set(['a', 'b']),
  138. ),
  139. (
  140. ['a', 'b', '@group'],
  141. [
  142. fake_check('from_group_1', ['group', 'another_group']),
  143. fake_check('not_in_group', ['another_group']),
  144. fake_check('from_group_2', ['preflight', 'group']),
  145. fake_check('a'),
  146. fake_check('b'),
  147. ],
  148. set(['a', 'b', 'from_group_1', 'from_group_2']),
  149. ),
  150. ])
  151. def test_resolve_checks_ok(names, all_checks, expected):
  152. assert resolve_checks(names, all_checks) == expected
  153. @pytest.mark.parametrize('names,all_checks,words_in_exception,words_not_in_exception', [
  154. (
  155. ['testA', 'testB'],
  156. [],
  157. ['check', 'name', 'testA', 'testB'],
  158. ['tag', 'group', '@'],
  159. ),
  160. (
  161. ['@group'],
  162. [],
  163. ['tag', 'name', 'group'],
  164. ['check', '@'],
  165. ),
  166. (
  167. ['testA', 'testB', '@group'],
  168. [],
  169. ['check', 'name', 'testA', 'testB', 'tag', 'group'],
  170. ['@'],
  171. ),
  172. (
  173. ['testA', 'testB', '@group'],
  174. [
  175. fake_check('from_group_1', ['group', 'another_group']),
  176. fake_check('not_in_group', ['another_group']),
  177. fake_check('from_group_2', ['preflight', 'group']),
  178. ],
  179. ['check', 'name', 'testA', 'testB'],
  180. ['tag', 'group', '@'],
  181. ),
  182. ])
  183. def test_resolve_checks_failure(names, all_checks, words_in_exception, words_not_in_exception):
  184. with pytest.raises(Exception) as excinfo:
  185. resolve_checks(names, all_checks)
  186. for word in words_in_exception:
  187. assert word in str(excinfo.value)
  188. for word in words_not_in_exception:
  189. assert word not in str(excinfo.value)