Show history by play and add get status action
Show history filtered by plays to get a better view if a log file contains a lot of playbooks. Add get_status action in order to get debug information of a given validation failure Change-Id: I29ab90647d9ef9c86546065ca16a62c401be1969
This commit is contained in:
parent
47db76f3f3
commit
21a722adac
|
@ -159,7 +159,10 @@ VALIDATIONS_LOGS_CONTENTS_LIST = [{
|
||||||
'unreachable': 0
|
'unreachable': 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'validation_output': []
|
'validation_output': [{'task': {
|
||||||
|
'hosts': {u'foo': {}},
|
||||||
|
'name': u'Check if iscsi.service is enabled',
|
||||||
|
'status': u'FAILED'}}]
|
||||||
}]
|
}]
|
||||||
|
|
||||||
VALIDATIONS_DATA = {'Description': 'My Validation One Description',
|
VALIDATIONS_DATA = {'Description': 'My Validation One Description',
|
||||||
|
@ -169,7 +172,7 @@ VALIDATIONS_DATA = {'Description': 'My Validation One Description',
|
||||||
'parameters': {}}
|
'parameters': {}}
|
||||||
|
|
||||||
VALIDATIONS_STATS = {'Last execution date': '2019-11-25 13:40:14',
|
VALIDATIONS_STATS = {'Last execution date': '2019-11-25 13:40:14',
|
||||||
'Number of execution': 'Total: 1, Passed: 1, Failed: 0'}
|
'Number of execution': 'Total: 1, Passed: 0, Failed: 1'}
|
||||||
|
|
||||||
FAKE_PLAYBOOK = [{'hosts': 'undercloud',
|
FAKE_PLAYBOOK = [{'hosts': 'undercloud',
|
||||||
'roles': ['advanced_format_512e_support'],
|
'roles': ['advanced_format_512e_support'],
|
||||||
|
|
|
@ -154,11 +154,20 @@ class TestValidationActions(TestCase):
|
||||||
'Description': 'foo', 'Groups': ['prep', 'pre-deployment'],
|
'Description': 'foo', 'Groups': ['prep', 'pre-deployment'],
|
||||||
'ID': '512e'}
|
'ID': '512e'}
|
||||||
data.update({'Last execution date': '2019-11-25 13:40:14',
|
data.update({'Last execution date': '2019-11-25 13:40:14',
|
||||||
'Number of execution': 'Total: 1, Passed: 1, Failed: 0'})
|
'Number of execution': 'Total: 1, Passed: 0, Failed: 1'})
|
||||||
validations_show = ValidationActions()
|
validations_show = ValidationActions()
|
||||||
out = validations_show.show_validations('512e')
|
out = validations_show.show_validations('512e')
|
||||||
self.assertEqual(out, data)
|
self.assertEqual(out, data)
|
||||||
|
|
||||||
|
@mock.patch('os.path.exists', return_value=False)
|
||||||
|
def test_validation_show_not_found(self, mock_exists):
|
||||||
|
validations_show = ValidationActions()
|
||||||
|
self.assertRaises(
|
||||||
|
RuntimeError,
|
||||||
|
validations_show.show_validations,
|
||||||
|
'512e'
|
||||||
|
)
|
||||||
|
|
||||||
@mock.patch('validations_libs.utils.parse_all_validations_on_disk',
|
@mock.patch('validations_libs.utils.parse_all_validations_on_disk',
|
||||||
return_value=fakes.VALIDATIONS_LIST)
|
return_value=fakes.VALIDATIONS_LIST)
|
||||||
@mock.patch('yaml.safe_load', return_value=fakes.GROUP)
|
@mock.patch('yaml.safe_load', return_value=fakes.GROUP)
|
||||||
|
@ -193,11 +202,12 @@ class TestValidationActions(TestCase):
|
||||||
@mock.patch('six.moves.builtins.open')
|
@mock.patch('six.moves.builtins.open')
|
||||||
def test_show_history(self, mock_open, mock_load, mock_get_log):
|
def test_show_history(self, mock_open, mock_load, mock_get_log):
|
||||||
v_actions = ValidationActions()
|
v_actions = ValidationActions()
|
||||||
col, values = v_actions.show_history('foo')
|
col, values = v_actions.show_history('512e')
|
||||||
self.assertEqual(col, ('UUID', 'Validations',
|
self.assertEqual(col, ('UUID', 'Validations',
|
||||||
'Status', 'Execution at',
|
'Status', 'Execution at',
|
||||||
'Duration'))
|
'Duration'))
|
||||||
self.assertEqual(values, [('123', 'foo', 'PASSED',
|
self.assertEqual(values, [('008886df-d297-1eaa-2a74-000000000008',
|
||||||
|
'512e', 'PASSED',
|
||||||
'2019-11-25T13:40:14.404623Z',
|
'2019-11-25T13:40:14.404623Z',
|
||||||
'0:00:03.753')])
|
'0:00:03.753')])
|
||||||
|
|
||||||
|
@ -213,6 +223,24 @@ class TestValidationActions(TestCase):
|
||||||
self.assertEqual(col, ('UUID', 'Validations',
|
self.assertEqual(col, ('UUID', 'Validations',
|
||||||
'Status', 'Execution at',
|
'Status', 'Execution at',
|
||||||
'Duration'))
|
'Duration'))
|
||||||
self.assertEqual(values, [('123', 'foo', 'PASSED',
|
self.assertEqual(values, [('008886df-d297-1eaa-2a74-000000000008',
|
||||||
|
'512e', 'PASSED',
|
||||||
'2019-11-25T13:40:14.404623Z',
|
'2019-11-25T13:40:14.404623Z',
|
||||||
'0:00:03.753')])
|
'0:00:03.753')])
|
||||||
|
|
||||||
|
@mock.patch('validations_libs.validation_logs.ValidationLogs.'
|
||||||
|
'get_logfile_by_validation',
|
||||||
|
return_value=['/tmp/123_foo_2020-03-30T13:17:22.447857Z.json'])
|
||||||
|
@mock.patch('json.load',
|
||||||
|
return_value=fakes.VALIDATIONS_LOGS_CONTENTS_LIST[0])
|
||||||
|
@mock.patch('six.moves.builtins.open')
|
||||||
|
def test_get_status(self, mock_open, mock_load, mock_get_log):
|
||||||
|
v_actions = ValidationActions()
|
||||||
|
col, values = v_actions.get_status('foo')
|
||||||
|
self.assertEqual(col, ['name', 'host', 'status', 'task_data'])
|
||||||
|
self.assertEqual(values, [('Check if iscsi.service is enabled', 'foo',
|
||||||
|
'FAILED', {})])
|
||||||
|
|
||||||
|
def test_get_status_no_param(self):
|
||||||
|
v_actions = ValidationActions()
|
||||||
|
self.assertRaises(RuntimeError, v_actions.get_status)
|
||||||
|
|
|
@ -224,3 +224,26 @@ class TestValidationLog(TestCase):
|
||||||
val = ValidationLog(
|
val = ValidationLog(
|
||||||
logfile='/tmp/123_foo_2020-03-30T13:17:22.447857Z.json')
|
logfile='/tmp/123_foo_2020-03-30T13:17:22.447857Z.json')
|
||||||
self.assertTrue(val.is_valid_format())
|
self.assertTrue(val.is_valid_format())
|
||||||
|
|
||||||
|
@mock.patch('json.load',
|
||||||
|
return_value=fakes.VALIDATIONS_LOGS_CONTENTS_LIST[0])
|
||||||
|
@mock.patch('six.moves.builtins.open')
|
||||||
|
def test_get_plays(self, mock_open, mock_json):
|
||||||
|
val = ValidationLog(
|
||||||
|
logfile='/tmp/123_foo_2020-03-30T13:17:22.447857Z.json')
|
||||||
|
plays = val.get_plays
|
||||||
|
self.assertEquals(
|
||||||
|
plays,
|
||||||
|
[fakes.VALIDATIONS_LOGS_CONTENTS_LIST[0]['plays'][0]['play']])
|
||||||
|
|
||||||
|
@mock.patch('json.load',
|
||||||
|
return_value=fakes.VALIDATIONS_LOGS_CONTENTS_LIST[0])
|
||||||
|
@mock.patch('six.moves.builtins.open')
|
||||||
|
def test_get_tasks_data(self, mock_open, mock_json):
|
||||||
|
val = ValidationLog(
|
||||||
|
logfile='/tmp/123_foo_2020-03-30T13:17:22.447857Z.json')
|
||||||
|
tasks_data = val.get_tasks_data
|
||||||
|
self.assertEquals(
|
||||||
|
tasks_data,
|
||||||
|
[fakes.VALIDATIONS_LOGS_CONTENTS_LIST[0]
|
||||||
|
['validation_output'][0]['task']])
|
||||||
|
|
|
@ -53,6 +53,11 @@ class ValidationActions(object):
|
||||||
# Get validation data:
|
# Get validation data:
|
||||||
vlog = ValidationLogs(log_path)
|
vlog = ValidationLogs(log_path)
|
||||||
data = v_utils.get_validations_data(validation, self.validation_path)
|
data = v_utils.get_validations_data(validation, self.validation_path)
|
||||||
|
if not data:
|
||||||
|
msg = "Validation {} not found in the path: {}".format(
|
||||||
|
validation,
|
||||||
|
self.validation_path)
|
||||||
|
raise RuntimeError(msg)
|
||||||
logfiles = vlog.get_all_logfiles_content()
|
logfiles = vlog.get_all_logfiles_content()
|
||||||
format = vlog.get_validations_stats(logfiles)
|
format = vlog.get_validations_stats(logfiles)
|
||||||
data.update(format)
|
data.update(format)
|
||||||
|
@ -148,9 +153,10 @@ class ValidationActions(object):
|
||||||
f.write(params)
|
f.write(params)
|
||||||
return params
|
return params
|
||||||
|
|
||||||
def show_history(self, validation_id=None, extension='json'):
|
def show_history(self, validation_id=None, extension='json',
|
||||||
|
log_path=constants.VALIDATIONS_LOG_BASEDIR):
|
||||||
"""Return validations history"""
|
"""Return validations history"""
|
||||||
vlogs = ValidationLogs(self.validation_path)
|
vlogs = ValidationLogs(log_path)
|
||||||
logs = (vlogs.get_logfile_by_validation(validation_id)
|
logs = (vlogs.get_logfile_by_validation(validation_id)
|
||||||
if validation_id else vlogs.get_all_logfiles(extension))
|
if validation_id else vlogs.get_all_logfiles(extension))
|
||||||
|
|
||||||
|
@ -158,11 +164,35 @@ class ValidationActions(object):
|
||||||
column_name = ('UUID', 'Validations',
|
column_name = ('UUID', 'Validations',
|
||||||
'Status', 'Execution at',
|
'Status', 'Execution at',
|
||||||
'Duration')
|
'Duration')
|
||||||
|
|
||||||
for log in logs:
|
for log in logs:
|
||||||
vlog = ValidationLog(logfile=log)
|
vlog = ValidationLog(logfile=log)
|
||||||
if vlog.is_valid_format():
|
if vlog.is_valid_format():
|
||||||
values.append((vlog.get_uuid, vlog.validation_id,
|
for play in vlog.get_plays:
|
||||||
vlog.get_status, vlog.get_start_time,
|
values.append((play['id'], play['validation_id'],
|
||||||
vlog.get_duration))
|
vlog.get_status,
|
||||||
|
play['duration'].get('start'),
|
||||||
|
play['duration'].get('time_elapsed')))
|
||||||
|
return (column_name, values)
|
||||||
|
|
||||||
|
def get_status(self, validation_id=None, uuid=None, status='FAILED',
|
||||||
|
log_path=constants.VALIDATIONS_LOG_BASEDIR):
|
||||||
|
"""Return validations execution details by status"""
|
||||||
|
vlogs = ValidationLogs(log_path)
|
||||||
|
if validation_id:
|
||||||
|
logs = vlogs.get_logfile_by_validation(validation_id)
|
||||||
|
elif uuid:
|
||||||
|
logs = vlogs.get_logfile_by_uuid(uuid)
|
||||||
|
else:
|
||||||
|
raise RuntimeError("You need to provide a validation_id or a uuid")
|
||||||
|
|
||||||
|
values = []
|
||||||
|
column_name = ['name', 'host', 'status', 'task_data']
|
||||||
|
for log in logs:
|
||||||
|
vlog = ValidationLog(logfile=log)
|
||||||
|
if vlog.is_valid_format():
|
||||||
|
for task in vlog.get_tasks_data:
|
||||||
|
if task['status'] == status:
|
||||||
|
for host in task['hosts']:
|
||||||
|
values.append((task['name'], host, task['status'],
|
||||||
|
task['hosts'][host]))
|
||||||
return (column_name, values)
|
return (column_name, values)
|
||||||
|
|
|
@ -150,6 +150,16 @@ class ValidationLog(object):
|
||||||
play in self.content['plays']]
|
play in self.content['plays']]
|
||||||
return ', '.join(filter(None, start_time))
|
return ', '.join(filter(None, start_time))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def get_plays(self):
|
||||||
|
"""Return a list of Playbook data"""
|
||||||
|
return [play['play'] for play in self.content['plays']]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def get_tasks_data(self):
|
||||||
|
"""Return a list of task from validation output"""
|
||||||
|
return [output['task'] for output in self.content['validation_output']]
|
||||||
|
|
||||||
|
|
||||||
class ValidationLogs(object):
|
class ValidationLogs(object):
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue