Merge "add spinner to highlight progress"

This commit is contained in:
Zuul 2021-07-14 00:02:06 +00:00 committed by Gerrit Code Review
commit d1899b71ba
3 changed files with 135 additions and 20 deletions

View File

@ -18,6 +18,9 @@ import json
import logging
from prettytable import PrettyTable
import re
import sys
import time
import threading
import yaml
try:
@ -110,3 +113,38 @@ def read_extra_vars_file(extra_vars_file):
"The extra_vars file must be properly formatted YAML/JSON."
"Details: {}.").format(error)
raise RuntimeError(error_msg)
class Spinner(object):
"""Animated spinner to indicate activity during processing"""
busy = False
delay = 0.1
@staticmethod
def spinning_cursor():
while 1:
for cursor in '|/-\\':
yield cursor
def __init__(self, delay=None):
self.spinner_generator = self.spinning_cursor()
if delay and float(delay):
self.delay = delay
def spinner_task(self):
while self.busy:
sys.stdout.write(next(self.spinner_generator))
sys.stdout.flush()
time.sleep(self.delay)
sys.stdout.write('\b')
sys.stdout.flush()
def __enter__(self):
self.busy = True
threading.Thread(target=self.spinner_task).start()
def __exit__(self, exception, value, tb):
self.busy = False
time.sleep(self.delay)
if exception is not None:
return False

View File

@ -273,6 +273,58 @@ class TestValidationActions(TestCase):
validations_dir='/tmp/foo')
self.assertEqual(run_return, expected_run_return)
@mock.patch('validations_libs.ansible.Ansible._playbook_check',
side_effect=RuntimeError)
@mock.patch('validations_libs.utils.os.makedirs')
@mock.patch('validations_libs.utils.os.access', return_value=True)
@mock.patch('validations_libs.utils.os.path.exists', return_value=True)
@mock.patch('validations_libs.utils.parse_all_validations_on_disk')
def test_spinner_exception_failure_condition(self, mock_validation_dir,
mock_exists, mock_access,
mock_makedirs,
mock_playbook_check):
mock_validation_dir.return_value = [{
'description': 'My Validation One Description',
'groups': ['prep', 'pre-deployment'],
'id': 'foo',
'name': 'My Validition One Name',
'parameters': {}}]
playbook = ['fake.yaml']
inventory = 'tmp/inventory.yaml'
run = ValidationActions()
self.assertRaises(RuntimeError, run.run_validations, playbook,
inventory, group=fakes.GROUPS_LIST,
validations_dir='/tmp/foo')
@mock.patch('validations_libs.ansible.Ansible._playbook_check',
side_effect=RuntimeError)
@mock.patch('validations_libs.utils.os.makedirs')
@mock.patch('validations_libs.utils.os.access', return_value=True)
@mock.patch('validations_libs.utils.os.path.exists', return_value=True)
@mock.patch('validations_libs.utils.parse_all_validations_on_disk')
@mock.patch('sys.__stdin__.isatty', return_value=True)
def test_spinner_forced_run(self, mock_stdin_isatty, mock_validation_dir,
mock_exists, mock_access, mock_makedirs,
mock_playbook_check):
mock_validation_dir.return_value = [{
'description': 'My Validation One Description',
'groups': ['prep', 'pre-deployment'],
'id': 'foo',
'name': 'My Validition One Name',
'parameters': {}}]
playbook = ['fake.yaml']
inventory = 'tmp/inventory.yaml'
run = ValidationActions()
self.assertRaises(RuntimeError, run.run_validations, playbook,
inventory, group=fakes.GROUPS_LIST,
validations_dir='/tmp/foo')
@mock.patch('validations_libs.utils.get_validations_playbook',
return_value=[])
def test_validation_run_no_validation(self, mock_get_val):

View File

@ -14,11 +14,13 @@
#
import logging
import os
import sys
import json
import yaml
from validations_libs.ansible import Ansible as v_ansible
from validations_libs.group import Group
from validations_libs.cli.common import Spinner
from validations_libs.validation_logs import ValidationLogs, ValidationLog
from validations_libs import constants
from validations_libs import utils as v_utils
@ -374,26 +376,49 @@ class ValidationActions(object):
validation_uuid, artifacts_dir = v_utils.create_artifacts_dir(
log_path=log_path, prefix=os.path.basename(playbook))
run_ansible = v_ansible(validation_uuid)
_playbook, _rc, _status = run_ansible.run(
workdir=artifacts_dir,
playbook=playbook,
base_dir=base_dir,
playbook_dir=validations_dir,
parallel_run=True,
inventory=inventory,
output_callback=output_callback,
callback_whitelist=callback_whitelist,
quiet=quiet,
extra_vars=extra_vars,
limit_hosts=_hosts,
extra_env_variables=extra_env_vars,
ansible_cfg=ansible_cfg,
gathering_policy='explicit',
ansible_artifact_path=artifacts_dir,
log_path=log_path,
run_async=run_async,
python_interpreter=python_interpreter,
ssh_user=ssh_user)
if sys.__stdin__.isatty():
with Spinner():
_playbook, _rc, _status = run_ansible.run(
workdir=artifacts_dir,
playbook=playbook,
base_dir=base_dir,
playbook_dir=validations_dir,
parallel_run=True,
inventory=inventory,
output_callback=output_callback,
callback_whitelist=callback_whitelist,
quiet=quiet,
extra_vars=extra_vars,
limit_hosts=_hosts,
extra_env_variables=extra_env_vars,
ansible_cfg=ansible_cfg,
gathering_policy='explicit',
ansible_artifact_path=artifacts_dir,
log_path=log_path,
run_async=run_async,
python_interpreter=python_interpreter,
ssh_user=ssh_user)
else:
_playbook, _rc, _status = run_ansible.run(
workdir=artifacts_dir,
playbook=playbook,
base_dir=base_dir,
playbook_dir=validations_dir,
parallel_run=True,
inventory=inventory,
output_callback=output_callback,
callback_whitelist=callback_whitelist,
quiet=quiet,
extra_vars=extra_vars,
limit_hosts=_hosts,
extra_env_variables=extra_env_vars,
ansible_cfg=ansible_cfg,
gathering_policy='explicit',
ansible_artifact_path=artifacts_dir,
log_path=log_path,
run_async=run_async,
python_interpreter=python_interpreter,
ssh_user=ssh_user)
results.append({'playbook': _playbook,
'rc_code': _rc,
'status': _status,