Merge "Add the community validation paths"
This commit is contained in:
commit
1b94c03ee7
|
@ -126,8 +126,16 @@ class Ansible(object):
|
||||||
gathering_policy, module_path, key,
|
gathering_policy, module_path, key,
|
||||||
extra_env_variables, ansible_timeout,
|
extra_env_variables, ansible_timeout,
|
||||||
callback_whitelist, base_dir, python_interpreter,
|
callback_whitelist, base_dir, python_interpreter,
|
||||||
env={}):
|
env={}, validation_cfg_file=None):
|
||||||
"""Handle Ansible env var for Ansible config execution"""
|
"""Handle Ansible env var for Ansible config execution"""
|
||||||
|
community_roles = ""
|
||||||
|
community_library = ""
|
||||||
|
community_lookup = ""
|
||||||
|
if utils.community_validations_on(validation_cfg_file):
|
||||||
|
community_roles = f"{constants.COMMUNITY_ROLES_DIR}:"
|
||||||
|
community_library = f"{constants.COMMUNITY_LIBRARY_DIR}:"
|
||||||
|
community_lookup = f"{constants.COMMUNITY_LOOKUP_DIR}:"
|
||||||
|
|
||||||
cwd = os.getcwd()
|
cwd = os.getcwd()
|
||||||
env['ANSIBLE_SSH_ARGS'] = (
|
env['ANSIBLE_SSH_ARGS'] = (
|
||||||
'-o UserKnownHostsFile={} '
|
'-o UserKnownHostsFile={} '
|
||||||
|
@ -159,10 +167,12 @@ class Ansible(object):
|
||||||
'{}:{}:'
|
'{}:{}:'
|
||||||
'/usr/share/ansible/plugins/modules:'
|
'/usr/share/ansible/plugins/modules:'
|
||||||
'/usr/share/ceph-ansible/library:'
|
'/usr/share/ceph-ansible/library:'
|
||||||
|
'{community_path}'
|
||||||
'{}/library'.format(
|
'{}/library'.format(
|
||||||
os.path.join(workdir, 'modules'),
|
os.path.join(workdir, 'modules'),
|
||||||
os.path.join(cwd, 'modules'),
|
os.path.join(cwd, 'modules'),
|
||||||
base_dir
|
base_dir,
|
||||||
|
community_path=community_library
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
env['ANSIBLE_LOOKUP_PLUGINS'] = os.path.expanduser(
|
env['ANSIBLE_LOOKUP_PLUGINS'] = os.path.expanduser(
|
||||||
|
@ -170,10 +180,12 @@ class Ansible(object):
|
||||||
'{}:{}:'
|
'{}:{}:'
|
||||||
'/usr/share/ansible/plugins/lookup:'
|
'/usr/share/ansible/plugins/lookup:'
|
||||||
'/usr/share/ceph-ansible/plugins/lookup:'
|
'/usr/share/ceph-ansible/plugins/lookup:'
|
||||||
|
'{community_path}'
|
||||||
'{}/lookup_plugins'.format(
|
'{}/lookup_plugins'.format(
|
||||||
os.path.join(workdir, 'lookup'),
|
os.path.join(workdir, 'lookup'),
|
||||||
os.path.join(cwd, 'lookup'),
|
os.path.join(cwd, 'lookup'),
|
||||||
base_dir
|
base_dir,
|
||||||
|
community_path=community_lookup
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
env['ANSIBLE_CALLBACK_PLUGINS'] = os.path.expanduser(
|
env['ANSIBLE_CALLBACK_PLUGINS'] = os.path.expanduser(
|
||||||
|
@ -215,10 +227,12 @@ class Ansible(object):
|
||||||
'/usr/share/ansible/roles:'
|
'/usr/share/ansible/roles:'
|
||||||
'/usr/share/ceph-ansible/roles:'
|
'/usr/share/ceph-ansible/roles:'
|
||||||
'/etc/ansible/roles:'
|
'/etc/ansible/roles:'
|
||||||
|
'{community_path}'
|
||||||
'{}/roles'.format(
|
'{}/roles'.format(
|
||||||
os.path.join(workdir, 'roles'),
|
os.path.join(workdir, 'roles'),
|
||||||
os.path.join(cwd, 'roles'),
|
os.path.join(cwd, 'roles'),
|
||||||
base_dir
|
base_dir,
|
||||||
|
community_path=community_roles
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
env['ANSIBLE_CALLBACK_WHITELIST'] = callback_whitelist
|
env['ANSIBLE_CALLBACK_WHITELIST'] = callback_whitelist
|
||||||
|
@ -421,7 +435,8 @@ class Ansible(object):
|
||||||
connection, gathering_policy,
|
connection, gathering_policy,
|
||||||
module_path, key, extra_env_variables,
|
module_path, key, extra_env_variables,
|
||||||
ansible_timeout, callback_whitelist,
|
ansible_timeout, callback_whitelist,
|
||||||
base_dir, python_interpreter))
|
base_dir, python_interpreter,
|
||||||
|
validation_cfg_file=validation_cfg_file))
|
||||||
|
|
||||||
if 'ANSIBLE_CONFIG' not in env and not ansible_cfg_file:
|
if 'ANSIBLE_CONFIG' not in env and not ansible_cfg_file:
|
||||||
ansible_cfg_file = os.path.join(ansible_artifact_path,
|
ansible_cfg_file = os.path.join(ansible_artifact_path,
|
||||||
|
|
|
@ -67,4 +67,5 @@ class ValidationList(BaseLister):
|
||||||
v_actions = ValidationActions(validation_path=validation_dir)
|
v_actions = ValidationActions(validation_path=validation_dir)
|
||||||
return (v_actions.list_validations(groups=group,
|
return (v_actions.list_validations(groups=group,
|
||||||
categories=category,
|
categories=category,
|
||||||
products=product))
|
products=product,
|
||||||
|
validation_config=self.base.config))
|
||||||
|
|
|
@ -45,7 +45,8 @@ class Show(BaseShow):
|
||||||
validation_name = parsed_args.validation_name
|
validation_name = parsed_args.validation_name
|
||||||
|
|
||||||
v_actions = ValidationActions(validation_path=validation_dir)
|
v_actions = ValidationActions(validation_path=validation_dir)
|
||||||
data = v_actions.show_validations(validation_name)
|
data = v_actions.show_validations(
|
||||||
|
validation_name, validation_config=self.base.config)
|
||||||
|
|
||||||
if data:
|
if data:
|
||||||
return data.keys(), data.values()
|
return data.keys(), data.values()
|
||||||
|
@ -70,7 +71,9 @@ class ShowGroup(BaseLister):
|
||||||
self.base.set_argument_parser(self, parsed_args)
|
self.base.set_argument_parser(self, parsed_args)
|
||||||
|
|
||||||
v_actions = ValidationActions(parsed_args.validation_dir)
|
v_actions = ValidationActions(parsed_args.validation_dir)
|
||||||
return v_actions.group_information(constants.VALIDATION_GROUPS_INFO)
|
return v_actions.group_information(
|
||||||
|
constants.VALIDATION_GROUPS_INFO,
|
||||||
|
validation_config=self.base.config)
|
||||||
|
|
||||||
|
|
||||||
class ShowParameter(BaseShow):
|
class ShowParameter(BaseShow):
|
||||||
|
@ -162,7 +165,8 @@ class ShowParameter(BaseShow):
|
||||||
categories=parsed_args.category,
|
categories=parsed_args.category,
|
||||||
products=parsed_args.product,
|
products=parsed_args.product,
|
||||||
output_format=parsed_args.format_output,
|
output_format=parsed_args.format_output,
|
||||||
download_file=parsed_args.download)
|
download_file=parsed_args.download,
|
||||||
|
validation_config=self.base.config)
|
||||||
|
|
||||||
if parsed_args.download:
|
if parsed_args.download:
|
||||||
self.app.LOG.info(
|
self.app.LOG.info(
|
||||||
|
|
|
@ -248,7 +248,8 @@ FAKE_PLAYBOOK = [{'hosts': 'undercloud',
|
||||||
'categories': ['os', 'storage'],
|
'categories': ['os', 'storage'],
|
||||||
'products': ['product1'],
|
'products': ['product1'],
|
||||||
'name':
|
'name':
|
||||||
'Advanced Format 512e Support'}}}]
|
'Advanced Format 512e Support',
|
||||||
|
'path': '/tmp'}}}]
|
||||||
|
|
||||||
FAKE_PLAYBOOK2 = [{'hosts': 'undercloud',
|
FAKE_PLAYBOOK2 = [{'hosts': 'undercloud',
|
||||||
'roles': ['advanced_format_512e_support'],
|
'roles': ['advanced_format_512e_support'],
|
||||||
|
@ -274,14 +275,16 @@ FAKE_METADATA = {'id': 'foo',
|
||||||
'groups': ['prep', 'pre-deployment'],
|
'groups': ['prep', 'pre-deployment'],
|
||||||
'categories': ['os', 'storage'],
|
'categories': ['os', 'storage'],
|
||||||
'products': ['product1'],
|
'products': ['product1'],
|
||||||
'name': 'Advanced Format 512e Support'}
|
'name': 'Advanced Format 512e Support',
|
||||||
|
'path': '/tmp'}
|
||||||
|
|
||||||
FORMATED_DATA = {'Description': 'foo',
|
FORMATED_DATA = {'Description': 'foo',
|
||||||
'Groups': ['prep', 'pre-deployment'],
|
'Groups': ['prep', 'pre-deployment'],
|
||||||
'Categories': ['os', 'storage'],
|
'Categories': ['os', 'storage'],
|
||||||
'Products': ['product1'],
|
'Products': ['product1'],
|
||||||
'ID': 'foo',
|
'ID': 'foo',
|
||||||
'Name': 'Advanced Format 512e Support'}
|
'Name': 'Advanced Format 512e Support',
|
||||||
|
'Path': '/tmp'}
|
||||||
|
|
||||||
GROUP = {'no-op': [{'description': 'noop-foo'}],
|
GROUP = {'no-op': [{'description': 'noop-foo'}],
|
||||||
'pre': [{'description': 'pre-foo'}],
|
'pre': [{'description': 'pre-foo'}],
|
||||||
|
|
|
@ -21,6 +21,7 @@ except ImportError:
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
|
|
||||||
from ansible_runner import Runner
|
from ansible_runner import Runner
|
||||||
|
from validations_libs import constants
|
||||||
from validations_libs.ansible import Ansible
|
from validations_libs.ansible import Ansible
|
||||||
from validations_libs.tests import fakes
|
from validations_libs.tests import fakes
|
||||||
|
|
||||||
|
@ -175,6 +176,56 @@ class TestAnsible(TestCase):
|
||||||
'/tmp/foo/fact_cache'
|
'/tmp/foo/fact_cache'
|
||||||
))
|
))
|
||||||
|
|
||||||
|
def test_ansible_env_var_with_community_validations(self):
|
||||||
|
# AP No config file (use the default True)
|
||||||
|
env = self.run._ansible_env_var(
|
||||||
|
output_callback="", ssh_user="", workdir="", connection="",
|
||||||
|
gathering_policy="", module_path="", key="",
|
||||||
|
extra_env_variables="", ansible_timeout="",
|
||||||
|
callback_whitelist="", base_dir="", python_interpreter="",
|
||||||
|
env={}, validation_cfg_file=None)
|
||||||
|
|
||||||
|
assert(f"{constants.COMMUNITY_LIBRARY_DIR}:" in env["ANSIBLE_LIBRARY"])
|
||||||
|
assert(f"{constants.COMMUNITY_ROLES_DIR}:" in env["ANSIBLE_ROLES_PATH"])
|
||||||
|
assert(f"{constants.COMMUNITY_LOOKUP_DIR}:" in env["ANSIBLE_LOOKUP_PLUGINS"])
|
||||||
|
|
||||||
|
# AP config file with no settting (use the default True)
|
||||||
|
env = self.run._ansible_env_var(
|
||||||
|
output_callback="", ssh_user="", workdir="", connection="",
|
||||||
|
gathering_policy="", module_path="", key="",
|
||||||
|
extra_env_variables="", ansible_timeout="",
|
||||||
|
callback_whitelist="", base_dir="", python_interpreter="",
|
||||||
|
env={}, validation_cfg_file={"default": {}})
|
||||||
|
|
||||||
|
assert(f"{constants.COMMUNITY_LIBRARY_DIR}:" in env["ANSIBLE_LIBRARY"])
|
||||||
|
assert(f"{constants.COMMUNITY_ROLES_DIR}:" in env["ANSIBLE_ROLES_PATH"])
|
||||||
|
assert(f"{constants.COMMUNITY_LOOKUP_DIR}:" in env["ANSIBLE_LOOKUP_PLUGINS"])
|
||||||
|
|
||||||
|
# AP config file with settting True
|
||||||
|
env = self.run._ansible_env_var(
|
||||||
|
output_callback="", ssh_user="", workdir="", connection="",
|
||||||
|
gathering_policy="", module_path="", key="",
|
||||||
|
extra_env_variables="", ansible_timeout="",
|
||||||
|
callback_whitelist="", base_dir="", python_interpreter="",
|
||||||
|
env={}, validation_cfg_file={"default": {"enable_community_validations": True}})
|
||||||
|
|
||||||
|
assert(f"{constants.COMMUNITY_LIBRARY_DIR}:" in env["ANSIBLE_LIBRARY"])
|
||||||
|
assert(f"{constants.COMMUNITY_ROLES_DIR}:" in env["ANSIBLE_ROLES_PATH"])
|
||||||
|
assert(f"{constants.COMMUNITY_LOOKUP_DIR}:" in env["ANSIBLE_LOOKUP_PLUGINS"])
|
||||||
|
|
||||||
|
def test_ansible_env_var_without_community_validations(self):
|
||||||
|
# AP config file with settting False
|
||||||
|
env = self.run._ansible_env_var(
|
||||||
|
output_callback="", ssh_user="", workdir="", connection="",
|
||||||
|
gathering_policy="", module_path="", key="",
|
||||||
|
extra_env_variables="", ansible_timeout="",
|
||||||
|
callback_whitelist="", base_dir="", python_interpreter="",
|
||||||
|
env={}, validation_cfg_file={"default": {"enable_community_validations": False}})
|
||||||
|
|
||||||
|
assert(f"{constants.COMMUNITY_LIBRARY_DIR}:" not in env["ANSIBLE_LIBRARY"])
|
||||||
|
assert(f"{constants.COMMUNITY_ROLES_DIR}:" not in env["ANSIBLE_ROLES_PATH"])
|
||||||
|
assert(f"{constants.COMMUNITY_LOOKUP_DIR}:" not in env["ANSIBLE_LOOKUP_PLUGINS"])
|
||||||
|
|
||||||
def test_get_extra_vars_dict(self):
|
def test_get_extra_vars_dict(self):
|
||||||
extra_vars = {
|
extra_vars = {
|
||||||
'foo': 'bar'
|
'foo': 'bar'
|
||||||
|
|
|
@ -44,10 +44,48 @@ class TestUtils(TestCase):
|
||||||
'Categories': ['os', 'storage'],
|
'Categories': ['os', 'storage'],
|
||||||
'Products': ['product1'],
|
'Products': ['product1'],
|
||||||
'ID': '512e',
|
'ID': '512e',
|
||||||
'Parameters': {}}
|
'Parameters': {},
|
||||||
|
'Path': '/tmp'}
|
||||||
res = utils.get_validations_data('512e')
|
res = utils.get_validations_data('512e')
|
||||||
self.assertEqual(res, output)
|
self.assertEqual(res, output)
|
||||||
|
|
||||||
|
@mock.patch('validations_libs.validation.Validation._get_content',
|
||||||
|
return_value=fakes.FAKE_PLAYBOOK[0])
|
||||||
|
@mock.patch('six.moves.builtins.open')
|
||||||
|
@mock.patch('os.path.exists', side_effect=(False, True))
|
||||||
|
def test_get_community_validations_data(self, mock_exists, mock_open, mock_data):
|
||||||
|
"""
|
||||||
|
The main difference between this test and test_get_validations_data
|
||||||
|
is that this one tries to load first the validations_commons validation
|
||||||
|
then it fails as os.path.exists returns false and then looks for it in the
|
||||||
|
community validations.
|
||||||
|
"""
|
||||||
|
output = {'Name': 'Advanced Format 512e Support',
|
||||||
|
'Description': 'foo', 'Groups': ['prep', 'pre-deployment'],
|
||||||
|
'Categories': ['os', 'storage'],
|
||||||
|
'Products': ['product1'],
|
||||||
|
'ID': '512e',
|
||||||
|
'Parameters': {},
|
||||||
|
'Path': '/tmp'}
|
||||||
|
res = utils.get_validations_data('512e')
|
||||||
|
self.assertEqual(res, output)
|
||||||
|
|
||||||
|
@mock.patch('validations_libs.validation.Validation._get_content',
|
||||||
|
return_value=fakes.FAKE_PLAYBOOK[0])
|
||||||
|
@mock.patch('six.moves.builtins.open')
|
||||||
|
@mock.patch('os.path.exists', side_effect=(False, True))
|
||||||
|
def test_get_community_disabled_validations_data(self, mock_exists, mock_open, mock_data):
|
||||||
|
"""
|
||||||
|
This test is similar to test_get_community_validations_data in the sense that it
|
||||||
|
doesn't find the validations_commons one and should look for community validations
|
||||||
|
but the setting is disabled by the config so it shouldn't find any validations
|
||||||
|
"""
|
||||||
|
output = {}
|
||||||
|
res = utils.get_validations_data(
|
||||||
|
'512e',
|
||||||
|
validation_config={'default': {"enable_community_validations": False}})
|
||||||
|
self.assertEqual(res, output)
|
||||||
|
|
||||||
@mock.patch('os.path.exists', return_value=True)
|
@mock.patch('os.path.exists', return_value=True)
|
||||||
def test_get_validations_data_wrong_type(self, mock_exists):
|
def test_get_validations_data_wrong_type(self, mock_exists):
|
||||||
validation = ['val1']
|
validation = ['val1']
|
||||||
|
@ -60,11 +98,33 @@ class TestUtils(TestCase):
|
||||||
@mock.patch('glob.glob')
|
@mock.patch('glob.glob')
|
||||||
def test_parse_all_validations_on_disk(self, mock_glob, mock_open,
|
def test_parse_all_validations_on_disk(self, mock_glob, mock_open,
|
||||||
mock_load):
|
mock_load):
|
||||||
mock_glob.return_value = \
|
mock_glob.side_effect = \
|
||||||
['/foo/playbook/foo.yaml']
|
(['/foo/playbook/foo.yaml'], [])
|
||||||
result = utils.parse_all_validations_on_disk('/foo/playbook')
|
result = utils.parse_all_validations_on_disk('/foo/playbook')
|
||||||
self.assertEqual(result, [fakes.FAKE_METADATA])
|
self.assertEqual(result, [fakes.FAKE_METADATA])
|
||||||
|
|
||||||
|
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK)
|
||||||
|
@mock.patch('six.moves.builtins.open')
|
||||||
|
@mock.patch('glob.glob')
|
||||||
|
def test_parse_community_validations_on_disk(
|
||||||
|
self, mock_glob, mock_open, mock_load):
|
||||||
|
mock_glob.side_effect = \
|
||||||
|
([], ['/foo/playbook/foo.yaml'])
|
||||||
|
result = utils.parse_all_validations_on_disk('/foo/playbook')
|
||||||
|
self.assertEqual(result, [fakes.FAKE_METADATA])
|
||||||
|
|
||||||
|
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK)
|
||||||
|
@mock.patch('six.moves.builtins.open')
|
||||||
|
@mock.patch('glob.glob')
|
||||||
|
def test_parse_all_community_disabled_validations_on_disk(
|
||||||
|
self, mock_glob, mock_open, mock_load):
|
||||||
|
mock_glob.side_effect = \
|
||||||
|
([], ['/foo/playbook/foo.yaml'])
|
||||||
|
result = utils.parse_all_validations_on_disk(
|
||||||
|
'/foo/playbook',
|
||||||
|
validation_config={'default': {"enable_community_validations": False}})
|
||||||
|
self.assertEqual(result, [])
|
||||||
|
|
||||||
def test_parse_all_validations_on_disk_wrong_path_type(self):
|
def test_parse_all_validations_on_disk_wrong_path_type(self):
|
||||||
self.assertRaises(TypeError,
|
self.assertRaises(TypeError,
|
||||||
utils.parse_all_validations_on_disk,
|
utils.parse_all_validations_on_disk,
|
||||||
|
@ -118,8 +178,8 @@ class TestUtils(TestCase):
|
||||||
def test_parse_all_validations_on_disk_by_group(self, mock_glob,
|
def test_parse_all_validations_on_disk_by_group(self, mock_glob,
|
||||||
mock_open,
|
mock_open,
|
||||||
mock_load):
|
mock_load):
|
||||||
mock_glob.return_value = \
|
mock_glob.side_effect = \
|
||||||
['/foo/playbook/foo.yaml']
|
(['/foo/playbook/foo.yaml'], [])
|
||||||
result = utils.parse_all_validations_on_disk('/foo/playbook',
|
result = utils.parse_all_validations_on_disk('/foo/playbook',
|
||||||
['prep'])
|
['prep'])
|
||||||
self.assertEqual(result, [fakes.FAKE_METADATA])
|
self.assertEqual(result, [fakes.FAKE_METADATA])
|
||||||
|
@ -130,8 +190,8 @@ class TestUtils(TestCase):
|
||||||
def test_parse_all_validations_on_disk_by_category(self, mock_glob,
|
def test_parse_all_validations_on_disk_by_category(self, mock_glob,
|
||||||
mock_open,
|
mock_open,
|
||||||
mock_load):
|
mock_load):
|
||||||
mock_glob.return_value = \
|
mock_glob.side_effect = \
|
||||||
['/foo/playbook/foo.yaml']
|
(['/foo/playbook/foo.yaml'], [])
|
||||||
result = utils.parse_all_validations_on_disk('/foo/playbook',
|
result = utils.parse_all_validations_on_disk('/foo/playbook',
|
||||||
categories=['os'])
|
categories=['os'])
|
||||||
self.assertEqual(result, [fakes.FAKE_METADATA])
|
self.assertEqual(result, [fakes.FAKE_METADATA])
|
||||||
|
@ -147,31 +207,80 @@ class TestUtils(TestCase):
|
||||||
def test_parse_all_validations_on_disk_by_product(self, mock_glob,
|
def test_parse_all_validations_on_disk_by_product(self, mock_glob,
|
||||||
mock_open,
|
mock_open,
|
||||||
mock_load):
|
mock_load):
|
||||||
mock_glob.return_value = \
|
mock_glob.side_effect = (['/foo/playbook/foo.yaml'], [])
|
||||||
['/foo/playbook/foo.yaml']
|
|
||||||
result = utils.parse_all_validations_on_disk('/foo/playbook',
|
result = utils.parse_all_validations_on_disk('/foo/playbook',
|
||||||
products=['product1'])
|
products=['product1'])
|
||||||
self.assertEqual(result, [fakes.FAKE_METADATA])
|
self.assertEqual(result, [fakes.FAKE_METADATA])
|
||||||
|
|
||||||
@mock.patch('os.path.isfile')
|
@mock.patch('os.path.isfile')
|
||||||
@mock.patch('os.listdir')
|
@mock.patch('glob.glob')
|
||||||
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK)
|
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK)
|
||||||
@mock.patch('six.moves.builtins.open')
|
@mock.patch('six.moves.builtins.open')
|
||||||
def test_get_validations_playbook_by_id(self, mock_open, mock_load,
|
def test_get_validations_playbook_by_id(self, mock_open, mock_load,
|
||||||
mock_listdir, mock_isfile):
|
mock_glob, mock_isfile):
|
||||||
mock_listdir.return_value = ['foo.yaml']
|
mock_glob.side_effect = (['/foo/playbook/foo.yaml'], [])
|
||||||
mock_isfile.return_value = True
|
mock_isfile.return_value = True
|
||||||
result = utils.get_validations_playbook('/foo/playbook',
|
result = utils.get_validations_playbook('/foo/playbook',
|
||||||
validation_id=['foo'])
|
validation_id=['foo'])
|
||||||
self.assertEqual(result, ['/foo/playbook/foo.yaml'])
|
self.assertEqual(result, ['/foo/playbook/foo.yaml'])
|
||||||
|
|
||||||
@mock.patch('os.path.isfile')
|
@mock.patch('os.path.isfile')
|
||||||
@mock.patch('os.listdir')
|
@mock.patch('glob.glob')
|
||||||
|
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK)
|
||||||
|
@mock.patch('six.moves.builtins.open')
|
||||||
|
def test_get_community_playbook_by_id(self, mock_open, mock_load,
|
||||||
|
mock_glob, mock_isfile):
|
||||||
|
mock_glob.side_effect = (
|
||||||
|
[],
|
||||||
|
['/home/foo/community-validations/playbooks/foo.yaml'])
|
||||||
|
mock_isfile.return_value = True
|
||||||
|
# AP this needs a bit of an explanation. We look at the explicity at
|
||||||
|
# the /foo/playbook directory but the community validation path is
|
||||||
|
# implicit and we find there the id that we are looking for.
|
||||||
|
result = utils.get_validations_playbook('/foo/playbook',
|
||||||
|
validation_id=['foo'])
|
||||||
|
self.assertEqual(result, ['/home/foo/community-validations/playbooks/foo.yaml'])
|
||||||
|
|
||||||
|
@mock.patch('os.path.isfile')
|
||||||
|
@mock.patch('glob.glob')
|
||||||
|
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK)
|
||||||
|
@mock.patch('six.moves.builtins.open')
|
||||||
|
def test_get_community_disabled_playbook_by_id(
|
||||||
|
self, mock_open, mock_load, mock_glob, mock_isfile):
|
||||||
|
mock_glob.side_effect = (
|
||||||
|
[],
|
||||||
|
['/home/foo/community-validations/playbooks/foo.yaml'])
|
||||||
|
mock_isfile.return_value = True
|
||||||
|
# The validations_commons validation is not found and community_vals is disabled
|
||||||
|
# So no validation should be found.
|
||||||
|
result = utils.get_validations_playbook(
|
||||||
|
'/foo/playbook',
|
||||||
|
validation_id=['foo'],
|
||||||
|
validation_config={'default': {"enable_community_validations": False}})
|
||||||
|
self.assertEqual(result, [])
|
||||||
|
|
||||||
|
@mock.patch('os.path.isfile')
|
||||||
|
@mock.patch('glob.glob')
|
||||||
|
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK)
|
||||||
|
@mock.patch('six.moves.builtins.open')
|
||||||
|
def test_get_community_playbook_by_id_not_found(
|
||||||
|
self, mock_open, mock_load, mock_glob, mock_isfile):
|
||||||
|
mock_glob.side_effect = (
|
||||||
|
[],
|
||||||
|
['/home/foo/community-validations/playbooks/foo.yaml/'])
|
||||||
|
# the is file fails
|
||||||
|
mock_isfile.return_value = False
|
||||||
|
result = utils.get_validations_playbook('/foo/playbook',
|
||||||
|
validation_id=['foo'])
|
||||||
|
self.assertEqual(result, [])
|
||||||
|
|
||||||
|
@mock.patch('os.path.isfile')
|
||||||
|
@mock.patch('glob.glob')
|
||||||
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK)
|
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK)
|
||||||
@mock.patch('six.moves.builtins.open')
|
@mock.patch('six.moves.builtins.open')
|
||||||
def test_get_validations_playbook_by_id_group(self, mock_open, mock_load,
|
def test_get_validations_playbook_by_id_group(self, mock_open, mock_load,
|
||||||
mock_listdir, mock_isfile):
|
mock_glob, mock_isfile):
|
||||||
mock_listdir.return_value = ['foo.yaml']
|
mock_glob.side_effect = (['/foo/playbook/foo.yaml'], [])
|
||||||
mock_isfile.return_value = True
|
mock_isfile.return_value = True
|
||||||
result = utils.get_validations_playbook('/foo/playbook', ['foo'], ['prep'])
|
result = utils.get_validations_playbook('/foo/playbook', ['foo'], ['prep'])
|
||||||
self.assertEqual(result, ['/foo/playbook/foo.yaml',
|
self.assertEqual(result, ['/foo/playbook/foo.yaml',
|
||||||
|
@ -192,24 +301,24 @@ class TestUtils(TestCase):
|
||||||
self.assertEqual(result, [])
|
self.assertEqual(result, [])
|
||||||
|
|
||||||
@mock.patch('os.path.isfile')
|
@mock.patch('os.path.isfile')
|
||||||
@mock.patch('os.listdir')
|
@mock.patch('glob.glob')
|
||||||
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK)
|
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK)
|
||||||
@mock.patch('six.moves.builtins.open')
|
@mock.patch('six.moves.builtins.open')
|
||||||
def test_get_validations_playbook_by_category(self, mock_open, mock_load,
|
def test_get_validations_playbook_by_category(self, mock_open, mock_load,
|
||||||
mock_listdir, mock_isfile):
|
mock_glob, mock_isfile):
|
||||||
mock_listdir.return_value = ['foo.yaml']
|
mock_glob.side_effect = (['/foo/playbook/foo.yaml'], [])
|
||||||
mock_isfile.return_value = True
|
mock_isfile.return_value = True
|
||||||
result = utils.get_validations_playbook('/foo/playbook',
|
result = utils.get_validations_playbook('/foo/playbook',
|
||||||
categories=['os', 'storage'])
|
categories=['os', 'storage'])
|
||||||
self.assertEqual(result, ['/foo/playbook/foo.yaml'])
|
self.assertEqual(result, ['/foo/playbook/foo.yaml'])
|
||||||
|
|
||||||
@mock.patch('os.path.isfile')
|
@mock.patch('os.path.isfile')
|
||||||
@mock.patch('os.listdir')
|
@mock.patch('glob.glob')
|
||||||
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK)
|
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK)
|
||||||
@mock.patch('six.moves.builtins.open')
|
@mock.patch('six.moves.builtins.open')
|
||||||
def test_get_validations_playbook_by_product(self, mock_open, mock_load,
|
def test_get_validations_playbook_by_product(self, mock_open, mock_load,
|
||||||
mock_listdir, mock_isfile):
|
mock_glob, mock_isfile):
|
||||||
mock_listdir.return_value = ['foo.yaml']
|
mock_glob.side_effect = (['/foo/playbook/foo.yaml'], [])
|
||||||
mock_isfile.return_value = True
|
mock_isfile.return_value = True
|
||||||
result = utils.get_validations_playbook('/foo/playbook',
|
result = utils.get_validations_playbook('/foo/playbook',
|
||||||
products=['product1'])
|
products=['product1'])
|
||||||
|
|
|
@ -15,8 +15,10 @@
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
from unittest.mock import ANY
|
||||||
except ImportError:
|
except ImportError:
|
||||||
import mock
|
import mock
|
||||||
|
from mock import ANY
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
@ -209,7 +211,8 @@ class TestValidationActions(TestCase):
|
||||||
'groups': ['prep', 'pre-deployment'],
|
'groups': ['prep', 'pre-deployment'],
|
||||||
'id': 'foo',
|
'id': 'foo',
|
||||||
'name': 'My Validition One Name',
|
'name': 'My Validition One Name',
|
||||||
'parameters': {}}]
|
'parameters': {},
|
||||||
|
'path': '/tmp/foobar/validation-playbooks'}]
|
||||||
|
|
||||||
mock_ansible_run.return_value = ('foo.yaml', 0, 'successful')
|
mock_ansible_run.return_value = ('foo.yaml', 0, 'successful')
|
||||||
|
|
||||||
|
@ -224,6 +227,29 @@ class TestValidationActions(TestCase):
|
||||||
validations_dir='/tmp/foo')
|
validations_dir='/tmp/foo')
|
||||||
self.assertEqual(run_return, expected_run_return)
|
self.assertEqual(run_return, expected_run_return)
|
||||||
|
|
||||||
|
mock_ansible_run.assert_called_with(
|
||||||
|
workdir=ANY,
|
||||||
|
playbook='/tmp/foobar/validation-playbooks/foo.yaml',
|
||||||
|
base_dir='/usr/share/ansible',
|
||||||
|
playbook_dir='/tmp/foobar/validation-playbooks',
|
||||||
|
parallel_run=True,
|
||||||
|
inventory='tmp/inventory.yaml',
|
||||||
|
output_callback='validation_stdout',
|
||||||
|
callback_whitelist=None,
|
||||||
|
quiet=True,
|
||||||
|
extra_vars=None,
|
||||||
|
limit_hosts=None,
|
||||||
|
extra_env_variables=None,
|
||||||
|
ansible_cfg_file=None,
|
||||||
|
gathering_policy='explicit',
|
||||||
|
ansible_artifact_path=ANY,
|
||||||
|
log_path=ANY,
|
||||||
|
run_async=False,
|
||||||
|
python_interpreter=None,
|
||||||
|
ssh_user=None,
|
||||||
|
validation_cfg_file=None
|
||||||
|
)
|
||||||
|
|
||||||
@mock.patch('validations_libs.utils.get_validations_playbook')
|
@mock.patch('validations_libs.utils.get_validations_playbook')
|
||||||
def test_validation_run_wrong_validation_name(self, mock_validation_play):
|
def test_validation_run_wrong_validation_name(self, mock_validation_play):
|
||||||
mock_validation_play.return_value = []
|
mock_validation_play.return_value = []
|
||||||
|
@ -234,6 +260,31 @@ class TestValidationActions(TestCase):
|
||||||
validations_dir='/tmp/foo'
|
validations_dir='/tmp/foo'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@mock.patch('validations_libs.utils.get_validations_playbook')
|
||||||
|
def test_validation_run_not_all_found(self, mock_validation_play):
|
||||||
|
|
||||||
|
mock_validation_play.return_value = ['/tmp/foo/fake.yaml']
|
||||||
|
run = ValidationActions()
|
||||||
|
try:
|
||||||
|
run.run_validations(
|
||||||
|
validation_name=['fake', 'foo'],
|
||||||
|
validations_dir='/tmp/foo')
|
||||||
|
except RuntimeError as runtime_error:
|
||||||
|
self.assertEqual(
|
||||||
|
"Validation ['foo'] not found in /tmp/foo.",
|
||||||
|
str(runtime_error))
|
||||||
|
else:
|
||||||
|
self.fail("Runtime error exception should have been raised")
|
||||||
|
|
||||||
|
@mock.patch('validations_libs.utils.parse_all_validations_on_disk')
|
||||||
|
def test_validation_run_not_enough_params(self, mock_validation_play):
|
||||||
|
mock_validation_play.return_value = []
|
||||||
|
|
||||||
|
run = ValidationActions()
|
||||||
|
self.assertRaises(RuntimeError, run.run_validations,
|
||||||
|
validations_dir='/tmp/foo'
|
||||||
|
)
|
||||||
|
|
||||||
@mock.patch('validations_libs.utils.os.makedirs')
|
@mock.patch('validations_libs.utils.os.makedirs')
|
||||||
@mock.patch('validations_libs.utils.os.access', return_value=True)
|
@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.os.path.exists', return_value=True)
|
||||||
|
@ -250,7 +301,8 @@ class TestValidationActions(TestCase):
|
||||||
'groups': ['prep', 'pre-deployment'],
|
'groups': ['prep', 'pre-deployment'],
|
||||||
'id': 'foo',
|
'id': 'foo',
|
||||||
'name': 'My Validition One Name',
|
'name': 'My Validition One Name',
|
||||||
'parameters': {}}]
|
'parameters': {},
|
||||||
|
'path': '/usr/share/ansible/validation-playbooks'}]
|
||||||
|
|
||||||
mock_ansible_run.return_value = ('foo.yaml', 0, 'failed')
|
mock_ansible_run.return_value = ('foo.yaml', 0, 'failed')
|
||||||
|
|
||||||
|
@ -295,7 +347,8 @@ class TestValidationActions(TestCase):
|
||||||
'groups': ['prep', 'pre-deployment'],
|
'groups': ['prep', 'pre-deployment'],
|
||||||
'id': 'foo',
|
'id': 'foo',
|
||||||
'name': 'My Validition One Name',
|
'name': 'My Validition One Name',
|
||||||
'parameters': {}}]
|
'parameters': {},
|
||||||
|
'path': '/usr/share/ansible/validation-playbooks'}]
|
||||||
playbook = ['fake.yaml']
|
playbook = ['fake.yaml']
|
||||||
inventory = 'tmp/inventory.yaml'
|
inventory = 'tmp/inventory.yaml'
|
||||||
|
|
||||||
|
@ -321,7 +374,8 @@ class TestValidationActions(TestCase):
|
||||||
'groups': ['prep', 'pre-deployment'],
|
'groups': ['prep', 'pre-deployment'],
|
||||||
'id': 'foo',
|
'id': 'foo',
|
||||||
'name': 'My Validition One Name',
|
'name': 'My Validition One Name',
|
||||||
'parameters': {}}]
|
'parameters': {},
|
||||||
|
'path': '/usr/share/ansible/validation-playbooks'}]
|
||||||
playbook = ['fake.yaml']
|
playbook = ['fake.yaml']
|
||||||
inventory = 'tmp/inventory.yaml'
|
inventory = 'tmp/inventory.yaml'
|
||||||
|
|
||||||
|
@ -357,7 +411,9 @@ class TestValidationActions(TestCase):
|
||||||
'Categories': ['os', 'storage'],
|
'Categories': ['os', 'storage'],
|
||||||
'Products': ['product1'],
|
'Products': ['product1'],
|
||||||
'ID': '512e',
|
'ID': '512e',
|
||||||
'Parameters': {}}
|
'Parameters': {},
|
||||||
|
'Path': '/tmp'
|
||||||
|
}
|
||||||
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: 0, Failed: 1'})
|
'Number of execution': 'Total: 1, Passed: 0, Failed: 1'})
|
||||||
validations_show = ValidationActions()
|
validations_show = ValidationActions()
|
||||||
|
|
|
@ -37,6 +37,21 @@ def current_time():
|
||||||
return '%sZ' % datetime.datetime.utcnow().isoformat()
|
return '%sZ' % datetime.datetime.utcnow().isoformat()
|
||||||
|
|
||||||
|
|
||||||
|
def community_validations_on(validation_config):
|
||||||
|
"""Check for flag for community validations to be enabled
|
||||||
|
The default value is true
|
||||||
|
|
||||||
|
:param validation_config: A dictionary of configuration for Validation
|
||||||
|
loaded from an validation.cfg file.
|
||||||
|
:type validation_config: ``dict``
|
||||||
|
:return: A boolean with the status of community validations flag
|
||||||
|
:rtype: `bool`
|
||||||
|
"""
|
||||||
|
if not validation_config:
|
||||||
|
return True
|
||||||
|
return validation_config.get("default", {}).get("enable_community_validations", True)
|
||||||
|
|
||||||
|
|
||||||
def create_log_dir(log_path=constants.VALIDATIONS_LOG_BASEDIR):
|
def create_log_dir(log_path=constants.VALIDATIONS_LOG_BASEDIR):
|
||||||
"""Check for presence of the selected validations log dir.
|
"""Check for presence of the selected validations log dir.
|
||||||
Create the directory if needed, and use fallback if that
|
Create the directory if needed, and use fallback if that
|
||||||
|
@ -136,7 +151,8 @@ def create_artifacts_dir(log_path=constants.VALIDATIONS_LOG_BASEDIR,
|
||||||
def parse_all_validations_on_disk(path,
|
def parse_all_validations_on_disk(path,
|
||||||
groups=None,
|
groups=None,
|
||||||
categories=None,
|
categories=None,
|
||||||
products=None):
|
products=None,
|
||||||
|
validation_config=None):
|
||||||
"""Return a list of validations metadata which can be sorted by Groups, by
|
"""Return a list of validations metadata which can be sorted by Groups, by
|
||||||
Categories or by Products.
|
Categories or by Products.
|
||||||
|
|
||||||
|
@ -152,6 +168,10 @@ def parse_all_validations_on_disk(path,
|
||||||
:param products: Products of validations
|
:param products: Products of validations
|
||||||
:type products: `list`
|
:type products: `list`
|
||||||
|
|
||||||
|
:param validation_config: A dictionary of configuration for Validation
|
||||||
|
loaded from an validation.cfg file.
|
||||||
|
:type validation_config: ``dict``
|
||||||
|
|
||||||
:return: A list of validations metadata.
|
:return: A list of validations metadata.
|
||||||
:rtype: `list`
|
:rtype: `list`
|
||||||
|
|
||||||
|
@ -192,6 +212,9 @@ def parse_all_validations_on_disk(path,
|
||||||
|
|
||||||
results = []
|
results = []
|
||||||
validations_abspath = glob.glob("{path}/*.yaml".format(path=path))
|
validations_abspath = glob.glob("{path}/*.yaml".format(path=path))
|
||||||
|
if community_validations_on(validation_config):
|
||||||
|
validations_abspath.extend(glob.glob("{}/*.yaml".format(
|
||||||
|
constants.COMMUNITY_PLAYBOOKS_DIR)))
|
||||||
|
|
||||||
LOG.debug(
|
LOG.debug(
|
||||||
"Attempting to parse validations by:\n"
|
"Attempting to parse validations by:\n"
|
||||||
|
@ -200,7 +223,6 @@ def parse_all_validations_on_disk(path,
|
||||||
" - products: {}\n"
|
" - products: {}\n"
|
||||||
"from {}".format(groups, categories, products, validations_abspath)
|
"from {}".format(groups, categories, products, validations_abspath)
|
||||||
)
|
)
|
||||||
|
|
||||||
for playbook in validations_abspath:
|
for playbook in validations_abspath:
|
||||||
val = Validation(playbook)
|
val = Validation(playbook)
|
||||||
|
|
||||||
|
@ -220,7 +242,8 @@ def get_validations_playbook(path,
|
||||||
validation_id=None,
|
validation_id=None,
|
||||||
groups=None,
|
groups=None,
|
||||||
categories=None,
|
categories=None,
|
||||||
products=None):
|
products=None,
|
||||||
|
validation_config=None):
|
||||||
"""Get a list of validations playbooks paths either by their names,
|
"""Get a list of validations playbooks paths either by their names,
|
||||||
their groups, by their categories or by their products.
|
their groups, by their categories or by their products.
|
||||||
|
|
||||||
|
@ -239,6 +262,10 @@ def get_validations_playbook(path,
|
||||||
:param products: List of validation product
|
:param products: List of validation product
|
||||||
:type products: `list`
|
:type products: `list`
|
||||||
|
|
||||||
|
:param validation_config: A dictionary of configuration for Validation
|
||||||
|
loaded from an validation.cfg file.
|
||||||
|
:type validation_config: ``dict``
|
||||||
|
|
||||||
:return: A list of absolute validations playbooks path
|
:return: A list of absolute validations playbooks path
|
||||||
:rtype: `list`
|
:rtype: `list`
|
||||||
|
|
||||||
|
@ -281,12 +308,15 @@ def get_validations_playbook(path,
|
||||||
raise TypeError("The 'products' argument must be a List")
|
raise TypeError("The 'products' argument must be a List")
|
||||||
|
|
||||||
pl = []
|
pl = []
|
||||||
for f in os.listdir(path):
|
validations_abspath = glob.glob("{path}/*.yaml".format(path=path))
|
||||||
pl_path = join(path, f)
|
if community_validations_on(validation_config):
|
||||||
|
validations_abspath.extend(glob.glob("{}/*.yaml".format(
|
||||||
|
constants.COMMUNITY_PLAYBOOKS_DIR)))
|
||||||
|
for pl_path in validations_abspath:
|
||||||
if os.path.isfile(pl_path):
|
if os.path.isfile(pl_path):
|
||||||
if validation_id:
|
if validation_id:
|
||||||
if os.path.splitext(f)[0] in validation_id or \
|
if os.path.splitext(os.path.basename(pl_path))[0] in validation_id or \
|
||||||
os.path.basename(f) in validation_id:
|
os.path.basename(pl_path) in validation_id:
|
||||||
pl.append(pl_path)
|
pl.append(pl_path)
|
||||||
|
|
||||||
val = Validation(pl_path)
|
val = Validation(pl_path)
|
||||||
|
@ -377,7 +407,10 @@ def get_validations_details(validation):
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|
||||||
def get_validations_data(validation, path=constants.ANSIBLE_VALIDATION_DIR):
|
def get_validations_data(
|
||||||
|
validation,
|
||||||
|
path=constants.ANSIBLE_VALIDATION_DIR,
|
||||||
|
validation_config=None):
|
||||||
"""Return validation data with format:
|
"""Return validation data with format:
|
||||||
|
|
||||||
ID, Name, Description, Groups, Parameters
|
ID, Name, Description, Groups, Parameters
|
||||||
|
@ -387,6 +420,9 @@ def get_validations_data(validation, path=constants.ANSIBLE_VALIDATION_DIR):
|
||||||
:type validation: `string`
|
:type validation: `string`
|
||||||
:param path: The path to the validations directory
|
:param path: The path to the validations directory
|
||||||
:type path: `string`
|
:type path: `string`
|
||||||
|
:param validation_config: A dictionary of configuration for Validation
|
||||||
|
loaded from an validation.cfg file.
|
||||||
|
:type validation_config: ``dict``
|
||||||
:return: The validation data with the format
|
:return: The validation data with the format
|
||||||
(ID, Name, Description, Groups, Parameters)
|
(ID, Name, Description, Groups, Parameters)
|
||||||
:rtype: `dict`
|
:rtype: `dict`
|
||||||
|
@ -408,6 +444,9 @@ def get_validations_data(validation, path=constants.ANSIBLE_VALIDATION_DIR):
|
||||||
|
|
||||||
data = {}
|
data = {}
|
||||||
val_path = "{}/{}.yaml".format(path, validation)
|
val_path = "{}/{}.yaml".format(path, validation)
|
||||||
|
comm_path = ""
|
||||||
|
if community_validations_on(validation_config):
|
||||||
|
comm_path = "{}/{}.yaml".format(constants.COMMUNITY_PLAYBOOKS_DIR, validation)
|
||||||
|
|
||||||
LOG.debug(
|
LOG.debug(
|
||||||
"Obtaining information about validation {} from {}".format(
|
"Obtaining information about validation {} from {}".format(
|
||||||
|
@ -419,6 +458,11 @@ def get_validations_data(validation, path=constants.ANSIBLE_VALIDATION_DIR):
|
||||||
val = Validation(val_path)
|
val = Validation(val_path)
|
||||||
data.update(val.get_formated_data)
|
data.update(val.get_formated_data)
|
||||||
data.update({'Parameters': val.get_vars})
|
data.update({'Parameters': val.get_vars})
|
||||||
|
if not data and comm_path:
|
||||||
|
if os.path.exists(comm_path):
|
||||||
|
val = Validation(comm_path)
|
||||||
|
data.update(val.get_formated_data)
|
||||||
|
data.update({'Parameters': val.get_vars})
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -89,6 +89,7 @@ class Validation(object):
|
||||||
def __init__(self, validation_path):
|
def __init__(self, validation_path):
|
||||||
self.dict = self._get_content(validation_path)
|
self.dict = self._get_content(validation_path)
|
||||||
self.id = os.path.splitext(os.path.basename(validation_path))[0]
|
self.id = os.path.splitext(os.path.basename(validation_path))[0]
|
||||||
|
self.path = os.path.dirname(validation_path)
|
||||||
|
|
||||||
def _get_content(self, val_path):
|
def _get_content(self, val_path):
|
||||||
try:
|
try:
|
||||||
|
@ -176,10 +177,11 @@ class Validation(object):
|
||||||
'categories': ['category1', 'category2'],
|
'categories': ['category1', 'category2'],
|
||||||
'products': ['product1', 'product2'],
|
'products': ['product1', 'product2'],
|
||||||
'id': 'val1',
|
'id': 'val1',
|
||||||
'name': 'The validation val1\'s name'}
|
'name': 'The validation val1\'s name',
|
||||||
|
'path': '/tmp/foo/'}
|
||||||
"""
|
"""
|
||||||
if self.has_metadata_dict:
|
if self.has_metadata_dict:
|
||||||
self.metadata = {'id': self.id}
|
self.metadata = {'id': self.id, 'path': self.path}
|
||||||
self.metadata.update(self.dict['vars'].get('metadata'))
|
self.metadata.update(self.dict['vars'].get('metadata'))
|
||||||
return self.metadata
|
return self.metadata
|
||||||
else:
|
else:
|
||||||
|
@ -353,7 +355,8 @@ class Validation(object):
|
||||||
'Description': 'description of val',
|
'Description': 'description of val',
|
||||||
'Groups': ['group1', 'group2'],
|
'Groups': ['group1', 'group2'],
|
||||||
'ID': 'val',
|
'ID': 'val',
|
||||||
'Name': 'validation one'}
|
'Name': 'validation one',
|
||||||
|
'path': '/tmp/foo/'}
|
||||||
"""
|
"""
|
||||||
data = {}
|
data = {}
|
||||||
metadata = self.get_metadata
|
metadata = self.get_metadata
|
||||||
|
|
|
@ -50,7 +50,8 @@ class ValidationActions(object):
|
||||||
def list_validations(self,
|
def list_validations(self,
|
||||||
groups=None,
|
groups=None,
|
||||||
categories=None,
|
categories=None,
|
||||||
products=None):
|
products=None,
|
||||||
|
validation_config=None):
|
||||||
"""Get a list of the validations selected by group membership or by
|
"""Get a list of the validations selected by group membership or by
|
||||||
category. With their names, group membership information, categories and
|
category. With their names, group membership information, categories and
|
||||||
products.
|
products.
|
||||||
|
@ -66,6 +67,10 @@ class ValidationActions(object):
|
||||||
:param products: List of validation products.
|
:param products: List of validation products.
|
||||||
:type products: `list`
|
:type products: `list`
|
||||||
|
|
||||||
|
:param validation_config: A dictionary of configuration for Validation
|
||||||
|
loaded from an validation.cfg file.
|
||||||
|
:type validation_config: ``dict``
|
||||||
|
|
||||||
:return: Column names and a list of the selected validations
|
:return: Column names and a list of the selected validations
|
||||||
:rtype: `tuple`
|
:rtype: `tuple`
|
||||||
|
|
||||||
|
@ -106,7 +111,8 @@ class ValidationActions(object):
|
||||||
path=self.validation_path,
|
path=self.validation_path,
|
||||||
groups=groups,
|
groups=groups,
|
||||||
categories=categories,
|
categories=categories,
|
||||||
products=products
|
products=products,
|
||||||
|
validation_config=validation_config
|
||||||
)
|
)
|
||||||
|
|
||||||
self.log.debug(
|
self.log.debug(
|
||||||
|
@ -124,13 +130,18 @@ class ValidationActions(object):
|
||||||
return (column_names, return_values)
|
return (column_names, return_values)
|
||||||
|
|
||||||
def show_validations(self, validation,
|
def show_validations(self, validation,
|
||||||
log_path=constants.VALIDATIONS_LOG_BASEDIR):
|
log_path=constants.VALIDATIONS_LOG_BASEDIR,
|
||||||
|
validation_config=None):
|
||||||
"""Display detailed information about a Validation
|
"""Display detailed information about a Validation
|
||||||
|
|
||||||
:param validation: The name of the validation
|
:param validation: The name of the validation
|
||||||
:type validation: `string`
|
:type validation: `string`
|
||||||
:param log_path: The absolute path of the validations logs
|
:param log_path: The absolute path of the validations logs
|
||||||
:type log_path: `string`
|
:type log_path: `string`
|
||||||
|
:param validation_config: A dictionary of configuration for Validation
|
||||||
|
loaded from an validation.cfg file.
|
||||||
|
:type validation_config: ``dict``
|
||||||
|
|
||||||
|
|
||||||
:return: The detailed information for a validation
|
:return: The detailed information for a validation
|
||||||
:rtype: `dict`
|
:rtype: `dict`
|
||||||
|
@ -156,11 +167,18 @@ class ValidationActions(object):
|
||||||
self.log = logging.getLogger(__name__ + ".show_validations")
|
self.log = logging.getLogger(__name__ + ".show_validations")
|
||||||
# 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(
|
||||||
if not data:
|
|
||||||
msg = "Validation {} not found in the path: {}".format(
|
|
||||||
validation,
|
validation,
|
||||||
self.validation_path)
|
self.validation_path,
|
||||||
|
validation_config=validation_config)
|
||||||
|
if not data:
|
||||||
|
extra_msg = ""
|
||||||
|
if v_utils.community_validations_on(validation_config):
|
||||||
|
extra_msg = " or {}".format(constants.COMMUNITY_LIBRARY_DIR)
|
||||||
|
msg = "Validation {} not found in the path: {}{}".format(
|
||||||
|
validation,
|
||||||
|
self.validation_path,
|
||||||
|
extra_msg)
|
||||||
raise RuntimeError(msg)
|
raise RuntimeError(msg)
|
||||||
logfiles = vlog.get_logfile_content_by_validation(validation)
|
logfiles = vlog.get_logfile_content_by_validation(validation)
|
||||||
data_format = vlog.get_validations_stats(logfiles)
|
data_format = vlog.get_validations_stats(logfiles)
|
||||||
|
@ -331,15 +349,15 @@ class ValidationActions(object):
|
||||||
(Defaults to 'None')
|
(Defaults to 'None')
|
||||||
:type skip_list: ``dict``
|
:type skip_list: ``dict``
|
||||||
|
|
||||||
:return: A list of dictionary containing the informations of the
|
|
||||||
validations executions (Validations, Duration, Host_Group,
|
|
||||||
Status, Status_by_Host, UUID and Unreachable_Hosts)
|
|
||||||
:rtype: ``list``
|
|
||||||
:param ssh_user: Ssh user for Ansible remote connection
|
:param ssh_user: Ssh user for Ansible remote connection
|
||||||
:type ssh_user: ``string``
|
:type ssh_user: ``string``
|
||||||
:param validation_config: A dictionary of configuration for Validation
|
:param validation_config: A dictionary of configuration for Validation
|
||||||
loaded from an validation.cfg file.
|
loaded from an validation.cfg file.
|
||||||
:type validation_config: ``dict``
|
:type validation_config: ``dict``
|
||||||
|
:return: A list of dictionary containing the informations of the
|
||||||
|
validations executions (Validations, Duration, Host_Group,
|
||||||
|
Status, Status_by_Host, UUID and Unreachable_Hosts)
|
||||||
|
:rtype: ``list``
|
||||||
|
|
||||||
:Example:
|
:Example:
|
||||||
|
|
||||||
|
@ -378,13 +396,16 @@ class ValidationActions(object):
|
||||||
)
|
)
|
||||||
validations = v_utils.parse_all_validations_on_disk(
|
validations = v_utils.parse_all_validations_on_disk(
|
||||||
path=validations_dir, groups=group,
|
path=validations_dir, groups=group,
|
||||||
categories=category, products=product
|
categories=category, products=product,
|
||||||
|
validation_config=validation_config
|
||||||
)
|
)
|
||||||
for val in validations:
|
for val in validations:
|
||||||
playbooks.append(val.get('id') + '.yaml')
|
playbooks.append("{path}/{id}.yaml".format(**val))
|
||||||
elif validation_name:
|
elif validation_name:
|
||||||
playbooks = v_utils.get_validations_playbook(validations_dir,
|
playbooks = v_utils.get_validations_playbook(
|
||||||
validation_name)
|
validations_dir,
|
||||||
|
validation_name,
|
||||||
|
validation_config=validation_config)
|
||||||
|
|
||||||
if not playbooks or len(validation_name) != len(playbooks):
|
if not playbooks or len(validation_name) != len(playbooks):
|
||||||
p = []
|
p = []
|
||||||
|
@ -419,7 +440,7 @@ class ValidationActions(object):
|
||||||
workdir=artifacts_dir,
|
workdir=artifacts_dir,
|
||||||
playbook=playbook,
|
playbook=playbook,
|
||||||
base_dir=base_dir,
|
base_dir=base_dir,
|
||||||
playbook_dir=validations_dir,
|
playbook_dir=os.path.dirname(playbook),
|
||||||
parallel_run=True,
|
parallel_run=True,
|
||||||
inventory=inventory,
|
inventory=inventory,
|
||||||
output_callback=output_callback,
|
output_callback=output_callback,
|
||||||
|
@ -441,7 +462,7 @@ class ValidationActions(object):
|
||||||
workdir=artifacts_dir,
|
workdir=artifacts_dir,
|
||||||
playbook=playbook,
|
playbook=playbook,
|
||||||
base_dir=base_dir,
|
base_dir=base_dir,
|
||||||
playbook_dir=validations_dir,
|
playbook_dir=os.path.dirname(playbook),
|
||||||
parallel_run=True,
|
parallel_run=True,
|
||||||
inventory=inventory,
|
inventory=inventory,
|
||||||
output_callback=output_callback,
|
output_callback=output_callback,
|
||||||
|
@ -483,7 +504,7 @@ class ValidationActions(object):
|
||||||
vlog = ValidationLogs(log_path)
|
vlog = ValidationLogs(log_path)
|
||||||
return vlog.get_results(uuid)
|
return vlog.get_results(uuid)
|
||||||
|
|
||||||
def group_information(self, groups):
|
def group_information(self, groups, validation_config=None):
|
||||||
"""Get Information about Validation Groups
|
"""Get Information about Validation Groups
|
||||||
|
|
||||||
This is used to print table from python ``Tuple`` with ``PrettyTable``.
|
This is used to print table from python ``Tuple`` with ``PrettyTable``.
|
||||||
|
@ -500,6 +521,9 @@ class ValidationActions(object):
|
||||||
|
|
||||||
:param groups: The absolute path of the groups.yaml file
|
:param groups: The absolute path of the groups.yaml file
|
||||||
:type groups: ``string``
|
:type groups: ``string``
|
||||||
|
:param validation_config: A dictionary of configuration for Validation
|
||||||
|
loaded from an validation.cfg file.
|
||||||
|
:type validation_config: ``dict``
|
||||||
|
|
||||||
:return: The list of the available groups with their description and
|
:return: The list of the available groups with their description and
|
||||||
the numbers of validation belonging to them.
|
the numbers of validation belonging to them.
|
||||||
|
@ -523,7 +547,8 @@ class ValidationActions(object):
|
||||||
|
|
||||||
validations = v_utils.parse_all_validations_on_disk(
|
validations = v_utils.parse_all_validations_on_disk(
|
||||||
path=self.validation_path,
|
path=self.validation_path,
|
||||||
groups=[group[0] for group in group_definitions])
|
groups=[group[0] for group in group_definitions],
|
||||||
|
validation_config=validation_config)
|
||||||
|
|
||||||
# Get validations number by group
|
# Get validations number by group
|
||||||
for group in group_definitions:
|
for group in group_definitions:
|
||||||
|
@ -543,7 +568,8 @@ class ValidationActions(object):
|
||||||
categories=None,
|
categories=None,
|
||||||
products=None,
|
products=None,
|
||||||
output_format='json',
|
output_format='json',
|
||||||
download_file=None):
|
download_file=None,
|
||||||
|
validation_config=None):
|
||||||
"""
|
"""
|
||||||
Return Validations Parameters for one or several validations by their
|
Return Validations Parameters for one or several validations by their
|
||||||
names, their groups, by their categories or by their products.
|
names, their groups, by their categories or by their products.
|
||||||
|
@ -566,6 +592,9 @@ class ValidationActions(object):
|
||||||
:param download_file: Path of a file in which the parameters will be
|
:param download_file: Path of a file in which the parameters will be
|
||||||
stored
|
stored
|
||||||
:type download_file: `string`
|
:type download_file: `string`
|
||||||
|
:param validation_config: A dictionary of configuration for Validation
|
||||||
|
loaded from an validation.cfg file.
|
||||||
|
:type validation_config: ``dict``
|
||||||
|
|
||||||
:return: A JSON or a YAML dump (By default, JSON).
|
:return: A JSON or a YAML dump (By default, JSON).
|
||||||
if `download_file` is used, a file containing only the
|
if `download_file` is used, a file containing only the
|
||||||
|
@ -622,7 +651,8 @@ class ValidationActions(object):
|
||||||
validation_id=validations,
|
validation_id=validations,
|
||||||
groups=groups,
|
groups=groups,
|
||||||
categories=categories,
|
categories=categories,
|
||||||
products=products
|
products=products,
|
||||||
|
validation_config=validation_config
|
||||||
)
|
)
|
||||||
|
|
||||||
params = v_utils.get_validations_parameters(
|
params = v_utils.get_validations_parameters(
|
||||||
|
|
Loading…
Reference in New Issue