callback adjustment for no hosts matched
The validation_json callback will now consider the no hosts being matched case as a validation failure. And record the result as such. To prevent unnecessary confusion, the host indicated in the created log file will be designated as 'No host matched'. And will be displayed as such on the VF stdout. Basic test coverage included. Signed-off-by: Jiri Podivin <jpodivin@redhat.com> Change-Id: I613203698b726941162239185de77949bf30254c
This commit is contained in:
parent
8dd362023d
commit
26ea5efffc
@ -187,6 +187,41 @@ class CallbackModule(CallbackBase):
|
|||||||
result['play']['duration']['end'] = end_time
|
result['play']['duration']['end'] = end_time
|
||||||
result['play']['duration']['time_elapsed'] = time_elapsed
|
result['play']['duration']['time_elapsed'] = time_elapsed
|
||||||
|
|
||||||
|
def v2_playbook_on_no_hosts_matched(self):
|
||||||
|
no_match_result = self._val_task('No tasks run')
|
||||||
|
no_match_result['task']['status'] = "FAILED"
|
||||||
|
no_match_result['task']['info'] = (
|
||||||
|
"None of the hosts specified"
|
||||||
|
" were matched in the inventory file")
|
||||||
|
|
||||||
|
output = {
|
||||||
|
'plays': self.results,
|
||||||
|
'stats': {
|
||||||
|
'No host matched':{
|
||||||
|
'changed': 0,
|
||||||
|
'failures': 1,
|
||||||
|
'ignored': 0,
|
||||||
|
'ok': 0,
|
||||||
|
'rescued': 0,
|
||||||
|
'skipped': 0,
|
||||||
|
'unreachable': 0}},
|
||||||
|
'validation_output': self.simple_results + [no_match_result]
|
||||||
|
}
|
||||||
|
|
||||||
|
log_file = "{}/{}_{}_{}.json".format(
|
||||||
|
VALIDATIONS_LOG_DIR,
|
||||||
|
os.getenv(
|
||||||
|
'ANSIBLE_UUID',
|
||||||
|
self.results[0].get('play').get('id')),
|
||||||
|
self.env['playbook_name'],
|
||||||
|
self.current_time)
|
||||||
|
|
||||||
|
with open(log_file, 'w') as js:
|
||||||
|
js.write(json.dumps(output,
|
||||||
|
cls=AnsibleJSONEncoder,
|
||||||
|
indent=4,
|
||||||
|
sort_keys=True))
|
||||||
|
|
||||||
def __getattribute__(self, name):
|
def __getattribute__(self, name):
|
||||||
"""Return ``_record_task_result`` partial with a dict
|
"""Return ``_record_task_result`` partial with a dict
|
||||||
containing skipped/failed if necessary
|
containing skipped/failed if necessary
|
||||||
|
@ -290,7 +290,10 @@ class TestValidationJson(base.TestCase):
|
|||||||
mock_new_task.assert_called_once_with(callback, mock_task)
|
mock_new_task.assert_called_once_with(callback, mock_task)
|
||||||
self.assertIn({'task': {'host': 'foo'}}, callback.results[0]['tasks'])
|
self.assertIn({'task': {'host': 'foo'}}, callback.results[0]['tasks'])
|
||||||
|
|
||||||
@mock.patch('json.dumps', return_value='json_dump_foo')
|
@mock.patch(
|
||||||
|
'json.dumps',
|
||||||
|
return_value='json_dump_foo',
|
||||||
|
autospec=True)
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
'validations_common.callback_plugins.validation_json.open',
|
'validations_common.callback_plugins.validation_json.open',
|
||||||
create=True)
|
create=True)
|
||||||
@ -349,6 +352,79 @@ class TestValidationJson(base.TestCase):
|
|||||||
mock_json_dumps.assert_called_once_with(output, **kwargs)
|
mock_json_dumps.assert_called_once_with(output, **kwargs)
|
||||||
mock_write.assert_called_once_with('json_dump_foo')
|
mock_write.assert_called_once_with('json_dump_foo')
|
||||||
|
|
||||||
|
@mock.patch(
|
||||||
|
'json.dumps',
|
||||||
|
return_value='json_dump_foo',
|
||||||
|
autospec=True)
|
||||||
|
@mock.patch(
|
||||||
|
'validations_common.callback_plugins.validation_json.open',
|
||||||
|
create=True)
|
||||||
|
def test_v2_playbook_on_no_hosts_matched(self, mock_open,
|
||||||
|
mock_json_dumps):
|
||||||
|
|
||||||
|
results = [
|
||||||
|
{
|
||||||
|
'play': {
|
||||||
|
'id': 'fizz'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
validation_task = {
|
||||||
|
'task': {
|
||||||
|
'name': 'No tasks run',
|
||||||
|
'hosts': {}}}
|
||||||
|
|
||||||
|
validation_json.VALIDATIONS_LOG_DIR = '/home/foo/validations'
|
||||||
|
|
||||||
|
callback = validation_json.CallbackModule()
|
||||||
|
dummy_stats = AggregateStats()
|
||||||
|
|
||||||
|
callback.results = results
|
||||||
|
callback.simple_results = results
|
||||||
|
callback.env['playbook_name'] = 'foo'
|
||||||
|
callback.current_time = 'foo-bar-fooTfoo:bar:foo.fizz'
|
||||||
|
|
||||||
|
dummy_stats.processed['foohost'] = 5
|
||||||
|
|
||||||
|
no_match_result = validation_task
|
||||||
|
no_match_result['task']['status'] = "FAILED"
|
||||||
|
no_match_result['task']['info'] = (
|
||||||
|
"None of the hosts specified"
|
||||||
|
" were matched in the inventory file")
|
||||||
|
|
||||||
|
output = {
|
||||||
|
'plays': results,
|
||||||
|
'stats': {
|
||||||
|
'No host matched':{
|
||||||
|
'changed': 0,
|
||||||
|
'failures': 1,
|
||||||
|
'ignored': 0,
|
||||||
|
'ok': 0,
|
||||||
|
'rescued': 0,
|
||||||
|
'skipped': 0,
|
||||||
|
'unreachable': 0}},
|
||||||
|
'validation_output': results + [no_match_result]
|
||||||
|
}
|
||||||
|
|
||||||
|
log_file = "{}/{}_{}_{}.json".format(
|
||||||
|
"/home/foo/validations",
|
||||||
|
'fizz',
|
||||||
|
'foo',
|
||||||
|
'foo-bar-fooTfoo:bar:foo.fizz')
|
||||||
|
|
||||||
|
kwargs = {
|
||||||
|
'cls': AnsibleJSONEncoder,
|
||||||
|
'indent': 4,
|
||||||
|
'sort_keys': True
|
||||||
|
}
|
||||||
|
|
||||||
|
callback.v2_playbook_on_no_hosts_matched()
|
||||||
|
mock_write = mock_open.return_value.__enter__.return_value.write
|
||||||
|
|
||||||
|
mock_open.assert_called_once_with(log_file, 'w')
|
||||||
|
mock_json_dumps.assert_called_once_with(output, **kwargs)
|
||||||
|
mock_write.assert_called_once_with('json_dump_foo')
|
||||||
|
|
||||||
@mock.patch('time.time', return_value=99.99)
|
@mock.patch('time.time', return_value=99.99)
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
'validations_common.callback_plugins.validation_json.secondsToStr',
|
'validations_common.callback_plugins.validation_json.secondsToStr',
|
||||||
|
Loading…
Reference in New Issue
Block a user