DNM First steps towards new validations

Signed-off-by: Jiri Podivin <jpodivin@redhat.com>
Change-Id: Id7eaebc7bd9a4a80d09f9c98ca6fb58173488003
This commit is contained in:
Jiri Podivin 2023-01-27 16:47:17 +01:00
parent 430530fad5
commit f49b52e346
17 changed files with 413 additions and 601 deletions

View File

@ -320,7 +320,7 @@ class Ansible:
def run(self, playbook, inventory, workdir, playbook_dir=None, def run(self, playbook, inventory, workdir, playbook_dir=None,
connection='smart', output_callback=None, connection='smart', output_callback=None,
base_dir=constants.DEFAULT_VALIDATIONS_BASEDIR, base_dir=constants.DEFAULT_ANSIBLE_BASEDIR,
ssh_user=None, key=None, module_path=None, ssh_user=None, key=None, module_path=None,
limit_hosts=None, tags=None, skip_tags=None, limit_hosts=None, tags=None, skip_tags=None,
verbosity=0, quiet=False, extra_vars=None, verbosity=0, quiet=False, extra_vars=None,

View File

@ -56,7 +56,7 @@ class CommunityValidationInit(BaseCommand):
"is located.")) "is located."))
parser.add_argument('--ansible-base-dir', dest='ansible_base_dir', parser.add_argument('--ansible-base-dir', dest='ansible_base_dir',
default=constants.DEFAULT_VALIDATIONS_BASEDIR, default=constants.DEFAULT_ANSIBLE_BASEDIR,
help=("Path where the ansible roles, library " help=("Path where the ansible roles, library "
"and plugins are located.")) "and plugins are located."))
return parser return parser
@ -71,7 +71,7 @@ class CommunityValidationInit(BaseCommand):
validation_dir=parsed_args.validation_dir, validation_dir=parsed_args.validation_dir,
ansible_base_dir=parsed_args.ansible_base_dir) ansible_base_dir=parsed_args.ansible_base_dir)
if co_validation.is_community_validations_enabled(self.base.config): if utils.community_validations_on(self.base.config):
LOG.debug( LOG.debug(
( (
"Checking the presence of the community validations " "Checking the presence of the community validations "
@ -96,7 +96,7 @@ class CommunityValidationInit(BaseCommand):
) )
) )
if co_validation.is_playbook_exists(): if co_validation.validation_exists(self.base.config):
raise RuntimeError( raise RuntimeError(
( (
"An Ansible playbook called {} " "An Ansible playbook called {} "

View File

@ -58,7 +58,7 @@ class ValidationList(BaseLister):
validation_dir = parsed_args.validation_dir validation_dir = parsed_args.validation_dir
group = parsed_args.group group = parsed_args.group
v_actions = ValidationActions(validation_path=validation_dir) v_actions = ValidationActions(base_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,

View File

@ -52,7 +52,7 @@ class Run(BaseCommand):
help=cli_constants.PLAY_PATH_DESC) help=cli_constants.PLAY_PATH_DESC)
parser.add_argument('--ansible-base-dir', dest='ansible_base_dir', parser.add_argument('--ansible-base-dir', dest='ansible_base_dir',
default=constants.DEFAULT_VALIDATIONS_BASEDIR, default=constants.DEFAULT_ANSIBLE_BASEDIR,
help=("Path where the ansible roles, library " help=("Path where the ansible roles, library "
"and plugins are located.\n")) "and plugins are located.\n"))

View File

@ -44,7 +44,7 @@ class Show(BaseShow):
validation_dir = parsed_args.validation_dir validation_dir = parsed_args.validation_dir
validation_name = parsed_args.validation_name validation_name = parsed_args.validation_name
v_actions = ValidationActions(validation_path=validation_dir) v_actions = ValidationActions(base_validation_path=validation_dir)
data = v_actions.show_validations( data = v_actions.show_validations(
validation_name, validation_config=self.base.config) validation_name, validation_config=self.base.config)

View File

@ -15,16 +15,12 @@
# under the License. # under the License.
# #
from validations_libs.logger import getLogger
import re
import os import os
# @matbu backward compatibility for stable/train import re
try: from pathlib import Path
from pathlib import Path
except ImportError:
from pathlib2 import Path
from validations_libs import constants, utils from validations_libs import constants, utils
from validations_libs.logger import getLogger
LOG = getLogger(__name__) LOG = getLogger(__name__)
@ -40,7 +36,7 @@ class CommunityValidation:
self, self,
validation_name, validation_name,
validation_dir=constants.ANSIBLE_VALIDATION_DIR, validation_dir=constants.ANSIBLE_VALIDATION_DIR,
ansible_base_dir=constants.DEFAULT_VALIDATIONS_BASEDIR): ansible_base_dir=constants.DEFAULT_ANSIBLE_BASEDIR):
"""Construct Role and Playbook.""" """Construct Role and Playbook."""
self._validation_name = validation_name self._validation_name = validation_name
@ -126,42 +122,32 @@ class CommunityValidation:
return Path(self.role_dir_path).exists() or \ return Path(self.role_dir_path).exists() or \
self.role_name in non_community_roles self.role_name in non_community_roles
def is_playbook_exists(self): def validation_exists(self, validation_config=None):
"""New playbook existence check """New validation existence check
This class method checks if the new playbook file is already existing This class method checks if the requested playbook file already exists
in the official validations catalog and in the current community in any of the validation playbook paths.
validations directory.
First, it gets the list of the playbooks yaml file available in Method first checks if the validation is in the default path,
``constants.ANSIBLE_VALIDATIONS_DIR``. If there is a match in at least afterwards it retrieves information about validation playbooks
one of the directories, it returns ``True``, otherwise ``False``. in locations defined by ``constants.VALIDATION_PLAYBOOK_DIRS``,
and compares their ids with that of a new validation.
If there is any match it returns ``True``, otherwise ``False``.
:validation_config: parsed validation.cfg file
:dtype: ``dict``
:rtype: ``Boolean`` :rtype: ``Boolean``
""" """
non_community_playbooks = [] if Path(self.playbook_path).exists():
if Path(self.validation_dir).exists(): return True
non_community_playbooks = [
Path(x).name
for x in Path(self.validation_dir).iterdir()
if x.is_file()
]
return Path(self.playbook_path).exists() or \ existing_validations = utils.parse_validations(
self.playbook_name in non_community_playbooks str(self.playbook_basedir.resolve()),
validation_config=validation_config)
def is_community_validations_enabled(self, base_config): return self._validation_name in [val.id for val in existing_validations]
"""Checks if the community validations are enabled in the config file
:param base_config: Contents of the configuration file
:type base_config: ``Dict``
:rtype: ``Boolean``
"""
config = base_config
default_conf = (config.get('default', {})
if isinstance(config, dict) else {})
return default_conf.get('enable_community_validations', True)
@property @property
def role_name(self): def role_name(self):

View File

@ -22,25 +22,29 @@ or as a fallback, when custom locations fail.
import os import os
# @matbu backward compatibility for stable/train from pathlib import Path
try:
from pathlib import Path
except ImportError:
from pathlib2 import Path
DEFAULT_VALIDATIONS_BASEDIR = '/usr/share/ansible' DEFAULT_ANSIBLE_BASEDIR = '/usr/share/ansible'
ANSIBLE_VALIDATION_DIR = os.path.join( ANSIBLE_VALIDATION_DIR = os.path.join(
DEFAULT_VALIDATIONS_BASEDIR, DEFAULT_ANSIBLE_BASEDIR,
'validation-playbooks') 'validation-playbooks')
ANSIBLE_ROLES_DIR = Path.joinpath(Path(DEFAULT_VALIDATIONS_BASEDIR), ANSIBLE_ROLES_DIR = Path.joinpath(Path(DEFAULT_ANSIBLE_BASEDIR),
'roles') 'roles')
VALIDATION_GROUPS_INFO = os.path.join( VALIDATION_GROUPS_INFO = os.path.join(
DEFAULT_VALIDATIONS_BASEDIR, DEFAULT_ANSIBLE_BASEDIR,
'groups.yaml') 'groups.yaml')
COLLECTION_VALIDATIONS_PATH = 'collections/ansible-collections/validations/*/playbooks/'
VALIDATION_PLAYBOOK_DIRS = [
ANSIBLE_VALIDATION_DIR,
os.path.join(os.path.expanduser('~'), COLLECTION_VALIDATIONS_PATH),
os.path.join(DEFAULT_ANSIBLE_BASEDIR, COLLECTION_VALIDATIONS_PATH)
]
# NOTE(fressi) The HOME folder environment variable may be undefined. # NOTE(fressi) The HOME folder environment variable may be undefined.
VALIDATIONS_LOG_BASEDIR = os.path.expanduser('~/validations') VALIDATIONS_LOG_BASEDIR = os.path.expanduser('~/validations')

View File

@ -39,3 +39,13 @@ class ValidationShowException(Exception):
of the `ValidationsActions` class, cause unacceptable behavior of the `ValidationsActions` class, cause unacceptable behavior
from which it is impossible to recover. from which it is impossible to recover.
""" """
class ValidationParsingException(Exception):
"""ValidationParsingException is to be raised when playbook
retrieved from storage and parsed in the `__init__` method
of the `Validation` object is malformed, or incompatible with
the requirements of validation runtime.
The exception should be raised as soon as possible after parsing
of the file, in order to ensure the fastest report and recovery.
"""

View File

@ -32,7 +32,7 @@ class TestCommunityValidationInit(BaseCommand):
@mock.patch( @mock.patch(
'validations_libs.community.init_validation.CommunityValidation.execute') 'validations_libs.community.init_validation.CommunityValidation.execute')
@mock.patch( @mock.patch(
'validations_libs.community.init_validation.CommunityValidation.is_playbook_exists', 'validations_libs.community.init_validation.CommunityValidation.validation_exists',
return_value=False) return_value=False)
@mock.patch( @mock.patch(
'validations_libs.community.init_validation.CommunityValidation.is_role_exists', 'validations_libs.community.init_validation.CommunityValidation.is_role_exists',
@ -50,7 +50,7 @@ class TestCommunityValidationInit(BaseCommand):
self.cmd.take_action(parsed_args) self.cmd.take_action(parsed_args)
@mock.patch( @mock.patch(
'validations_libs.community.init_validation.CommunityValidation.is_community_validations_enabled', 'validations_libs.utils.community_validations_on',
return_value=False) return_value=False)
def test_validation_init_with_com_val_disabled(self, mock_config): def test_validation_init_with_com_val_disabled(self, mock_config):
args = self._set_args(['my_new_community_val']) args = self._set_args(['my_new_community_val'])
@ -64,7 +64,7 @@ class TestCommunityValidationInit(BaseCommand):
'validations_libs.community.init_validation.CommunityValidation.is_role_exists', 'validations_libs.community.init_validation.CommunityValidation.is_role_exists',
return_value=True) return_value=True)
@mock.patch( @mock.patch(
'validations_libs.community.init_validation.CommunityValidation.is_playbook_exists', 'validations_libs.community.init_validation.CommunityValidation.validation_exists',
return_value=False) return_value=False)
@mock.patch('validations_libs.utils.check_community_validations_dir') @mock.patch('validations_libs.utils.check_community_validations_dir')
def test_validation_init_with_role_existing(self, def test_validation_init_with_role_existing(self,
@ -82,7 +82,7 @@ class TestCommunityValidationInit(BaseCommand):
'validations_libs.community.init_validation.CommunityValidation.is_role_exists', 'validations_libs.community.init_validation.CommunityValidation.is_role_exists',
return_value=False) return_value=False)
@mock.patch( @mock.patch(
'validations_libs.community.init_validation.CommunityValidation.is_playbook_exists', 'validations_libs.community.init_validation.CommunityValidation.validation_exists',
return_value=True) return_value=True)
@mock.patch('validations_libs.utils.check_community_validations_dir') @mock.patch('validations_libs.utils.check_community_validations_dir')
def test_validation_init_with_playbook_existing(self, def test_validation_init_with_playbook_existing(self,

View File

@ -70,7 +70,7 @@ class TestList(BaseCommand):
result = self.cmd.take_action(parsed_args) result = self.cmd.take_action(parsed_args)
self.assertEqual(result, []) self.assertEqual(result, [])
@mock.patch('validations_libs.utils.parse_all_validations_on_disk', @mock.patch('validations_libs.utils.parse_validations',
return_value=fakes.VALIDATIONS_LIST_GROUP, return_value=fakes.VALIDATIONS_LIST_GROUP,
autospec=True) autospec=True)
def test_list_validations_group(self, mock_list): def test_list_validations_group(self, mock_list):
@ -84,7 +84,7 @@ class TestList(BaseCommand):
result = self.cmd.take_action(parsed_args) result = self.cmd.take_action(parsed_args)
self.assertEqual(result, val_list) self.assertEqual(result, val_list)
@mock.patch('validations_libs.utils.parse_all_validations_on_disk', @mock.patch('validations_libs.utils.parse_validations',
return_value=fakes.VALIDATIONS_LIST_GROUP, return_value=fakes.VALIDATIONS_LIST_GROUP,
autospec=True) autospec=True)
def test_list_validations_by_category(self, mock_list): def test_list_validations_by_category(self, mock_list):
@ -98,7 +98,7 @@ class TestList(BaseCommand):
result = self.cmd.take_action(parsed_args) result = self.cmd.take_action(parsed_args)
self.assertEqual(result, val_list) self.assertEqual(result, val_list)
@mock.patch('validations_libs.utils.parse_all_validations_on_disk', @mock.patch('validations_libs.utils.parse_validations',
return_value=fakes.VALIDATIONS_LIST_GROUP, return_value=fakes.VALIDATIONS_LIST_GROUP,
autospec=True) autospec=True)
def test_list_validations_by_product(self, mock_list): def test_list_validations_by_product(self, mock_list):

View File

@ -13,20 +13,8 @@
# under the License. # under the License.
# #
try: from pathlib import PosixPath
from unittest import mock from unittest import TestCase, mock
except ImportError:
import mock
# @matbu backward compatibility for stable/train
try:
from pathlib import PosixPath
PATHLIB = 'pathlib'
except ImportError:
from pathlib2 import PosixPath
PATHLIB = 'pathlib2'
from unittest import TestCase
from validations_libs import constants from validations_libs import constants
from validations_libs.community.init_validation import \ from validations_libs.community.init_validation import \
@ -90,10 +78,10 @@ class TestCommunityValidation(TestCase):
self.assertEqual(co_val.playbook_basedir, self.assertEqual(co_val.playbook_basedir,
constants.COMMUNITY_PLAYBOOKS_DIR) constants.COMMUNITY_PLAYBOOKS_DIR)
@mock.patch('{}.Path.iterdir'.format(PATHLIB), @mock.patch('pathlib.Path.iterdir',
return_value=fakes.FAKE_ROLES_ITERDIR2) return_value=fakes.FAKE_ROLES_ITERDIR2)
@mock.patch('{}.Path.is_dir'.format(PATHLIB)) @mock.patch('pathlib.Path.is_dir')
@mock.patch('{}.Path.exists'.format(PATHLIB), side_effect=[False, True]) @mock.patch('pathlib.Path.exists', side_effect=[False, True])
def test_role_already_exists_in_comval(self, def test_role_already_exists_in_comval(self,
mock_play_path_exists, mock_play_path_exists,
mock_path_is_dir, mock_path_is_dir,
@ -102,10 +90,10 @@ class TestCommunityValidation(TestCase):
co_val = cv(validation_name) co_val = cv(validation_name)
self.assertTrue(co_val.is_role_exists()) self.assertTrue(co_val.is_role_exists())
@mock.patch('{}.Path.iterdir'.format(PATHLIB), @mock.patch('pathlib.Path.iterdir',
return_value=fakes.FAKE_ROLES_ITERDIR1) return_value=fakes.FAKE_ROLES_ITERDIR1)
@mock.patch('{}.Path.is_dir'.format(PATHLIB)) @mock.patch('pathlib.Path.is_dir')
@mock.patch('{}.Path.exists'.format(PATHLIB), side_effect=[True, False]) @mock.patch('pathlib.Path.exists', side_effect=[True, False])
def test_role_already_exists_in_non_comval(self, def test_role_already_exists_in_non_comval(self,
mock_play_path_exists, mock_play_path_exists,
mock_path_is_dir, mock_path_is_dir,
@ -114,10 +102,10 @@ class TestCommunityValidation(TestCase):
co_val = cv(validation_name) co_val = cv(validation_name)
self.assertTrue(co_val.is_role_exists()) self.assertTrue(co_val.is_role_exists())
@mock.patch('{}.Path.iterdir'.format(PATHLIB), @mock.patch('pathlib.Path.iterdir',
return_value=fakes.FAKE_ROLES_ITERDIR2) return_value=fakes.FAKE_ROLES_ITERDIR2)
@mock.patch('{}.Path.is_dir'.format(PATHLIB)) @mock.patch('pathlib.Path.is_dir')
@mock.patch('{}.Path.exists'.format(PATHLIB), side_effect=[True, False]) @mock.patch('pathlib.Path.exists', side_effect=[True, False])
def test_role_not_exists(self, def test_role_not_exists(self,
mock_path_exists, mock_path_exists,
mock_path_is_dir, mock_path_is_dir,
@ -126,41 +114,38 @@ class TestCommunityValidation(TestCase):
co_val = cv(validation_name) co_val = cv(validation_name)
self.assertFalse(co_val.is_role_exists()) self.assertFalse(co_val.is_role_exists())
@mock.patch('{}.Path.iterdir'.format(PATHLIB), @mock.patch('pathlib.Path.iterdir',
return_value=fakes.FAKE_PLAYBOOKS_ITERDIR1) return_value=fakes.FAKE_PLAYBOOKS_ITERDIR1)
@mock.patch('{}.Path.is_file'.format(PATHLIB)) @mock.patch('pathlib.Path.is_file')
@mock.patch('{}.Path.exists'.format(PATHLIB), side_effect=[True, False]) @mock.patch('pathlib.Path.exists', side_effect=[True, False])
def test_playbook_already_exists_in_non_comval(self, def test_playbook_already_exists_in_non_comval(self,
mock_path_exists, mock_path_exists,
mock_path_is_file, mock_path_is_file,
mock_path_iterdir): mock_path_iterdir):
validation_name = "my_val" validation_name = "my_val"
co_val = cv(validation_name) co_val = cv(validation_name)
self.assertTrue(co_val.is_playbook_exists()) self.assertTrue(co_val.validation_exists())
@mock.patch('{}.Path.iterdir'.format(PATHLIB), @mock.patch('glob.glob')
return_value=fakes.FAKE_PLAYBOOKS_ITERDIR2) @mock.patch('pathlib.Path.is_file')
@mock.patch('{}.Path.is_file'.format(PATHLIB)) @mock.patch('pathlib.Path.exists', side_effect=[True])
@mock.patch('{}.Path.exists'.format(PATHLIB), side_effect=[False, True])
def test_playbook_already_exists_in_comval(self, def test_playbook_already_exists_in_comval(self,
mock_path_exists, mock_path_exists,
mock_path_is_file, mock_path_is_file,
mock_path_iterdir): mock_glob):
validation_name = "my_val" validation_name = "my_val"
co_val = cv(validation_name)
self.assertTrue(co_val.is_playbook_exists())
@mock.patch('{}.Path.iterdir'.format(PATHLIB), co_val = cv(validation_name)
return_value=fakes.FAKE_PLAYBOOKS_ITERDIR2) self.assertTrue(co_val.validation_exists())
@mock.patch('{}.Path.is_file'.format(PATHLIB))
@mock.patch('{}.Path.exists'.format(PATHLIB), side_effect=[True, False]) @mock.patch('pathlib.Path.is_file')
@mock.patch('pathlib.Path.exists', side_effect=[False, False])
def test_playbook_not_exists(self, def test_playbook_not_exists(self,
mock_path_exists, mock_path_exists,
mock_path_is_file, mock_path_is_file):
mock_path_iterdir):
validation_name = "my_val" validation_name = "my_val"
co_val = cv(validation_name) co_val = cv(validation_name)
self.assertFalse(co_val.is_playbook_exists()) self.assertFalse(co_val.validation_exists())
def test_execute_with_role_name_not_compliant(self): def test_execute_with_role_name_not_compliant(self):
validation_name = "3_my-val" validation_name = "3_my-val"

View File

@ -16,23 +16,11 @@
import logging import logging
import os import os
import subprocess import subprocess
from pathlib import PosixPath
from unittest import TestCase, mock
try: from validations_libs import constants, utils
from unittest import mock from validations_libs.validation import Validation
except ImportError:
import mock
# @matbu backward compatibility for stable/train
try:
from pathlib import PosixPath
PATHLIB = 'pathlib'
except ImportError:
from pathlib2 import PosixPath
PATHLIB = 'pathlib2'
from unittest import TestCase
from validations_libs import utils, constants
from validations_libs.tests import fakes from validations_libs.tests import fakes
@ -41,6 +29,23 @@ class TestUtils(TestCase):
def setUp(self): def setUp(self):
super(TestUtils, self).setUp() super(TestUtils, self).setUp()
self.logger = mock.patch('validations_libs.logger.getLogger') self.logger = mock.patch('validations_libs.logger.getLogger')
# Mocking all glob calls, so that only the first path will
# return any items
globs = [['/foo/playbook/foo.yaml'], []]
globs.extend(len(constants.VALIDATION_PLAYBOOK_DIRS)*[[]])
def _return_empty_list(_=None):
while True:
yield []
def return_on_community(path):
if 'community' in path:
return ['/home/foo/community-validations/playbooks/foo.yaml']
return []
self.globs_first_only = globs
self.return_empty_list = _return_empty_list
self.return_on_community = return_on_community
@mock.patch('validations_libs.validation.Validation._get_content', @mock.patch('validations_libs.validation.Validation._get_content',
return_value=fakes.FAKE_PLAYBOOK[0]) return_value=fakes.FAKE_PLAYBOOK[0])
@ -101,200 +106,202 @@ class TestUtils(TestCase):
utils.get_validations_data, utils.get_validations_data,
validation) validation)
@mock.patch('os.path.isfile', return_value=True)
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK) @mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK)
@mock.patch('builtins.open') @mock.patch('builtins.open')
@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_is_file):
mock_glob.side_effect = \ mock_glob.side_effect = self.globs_first_only
(['/foo/playbook/foo.yaml'], [])
result = utils.parse_all_validations_on_disk('/foo/playbook')
self.assertEqual(result, [fakes.FAKE_METADATA])
result = utils.parse_validations('/foo/playbook')
self.assertTrue(isinstance(result[0], Validation))
self.assertEqual(result[0].get_metadata, fakes.FAKE_METADATA)
@mock.patch('os.path.isfile', return_value=True)
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK) @mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK)
@mock.patch('builtins.open') @mock.patch('builtins.open')
@mock.patch('glob.glob') @mock.patch('glob.glob')
def test_parse_community_validations_on_disk( def test_parse_community_validations_on_disk(
self, mock_glob, mock_open, mock_load): self, mock_glob, mock_open, mock_load, mock_is_file):
mock_glob.side_effect = \ mock_glob.side_effect = self.globs_first_only
([], ['/foo/playbook/foo.yaml'])
result = utils.parse_all_validations_on_disk('/foo/playbook') result = utils.parse_validations('/foo/playbook')
self.assertEqual(result, [fakes.FAKE_METADATA]) self.assertTrue(isinstance(result[0], Validation))
self.assertEqual(result[0].get_metadata, fakes.FAKE_METADATA)
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK) @mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK)
@mock.patch('builtins.open') @mock.patch('builtins.open')
@mock.patch('glob.glob') @mock.patch('glob.glob')
def test_parse_all_community_disabled_validations_on_disk( def test_parse_all_community_disabled_validations_on_disk(
self, mock_glob, mock_open, mock_load): self, mock_glob, mock_open, mock_load):
mock_glob.side_effect = \ mock_glob.side_effect = self.return_empty_list()
([], ['/foo/playbook/foo.yaml']) result = utils.parse_validations(
result = utils.parse_all_validations_on_disk(
'/foo/playbook', '/foo/playbook',
validation_config={'default': {"enable_community_validations": False}}) validation_config={'default': {"enable_community_validations": False}})
self.assertEqual(result, []) 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_validations,
path=['/foo/playbook']) path=['/foo/playbook'])
def test_parse_all_validations_on_disk_wrong_groups_type(self): def test_parse_all_validations_on_disk_wrong_groups_type(self):
self.assertRaises(TypeError, self.assertRaises(TypeError,
utils.parse_all_validations_on_disk, utils.parse_validations,
path='/foo/playbook', path='/foo/playbook',
groups='foo1,foo2') groups='foo1,foo2')
def test_parse_all_validations_on_disk_wrong_categories_type(self): def test_parse_all_validations_on_disk_wrong_categories_type(self):
self.assertRaises(TypeError, self.assertRaises(TypeError,
utils.parse_all_validations_on_disk, utils.parse_validations,
path='/foo/playbook', path='/foo/playbook',
categories='foo1,foo2') categories='foo1,foo2')
def test_parse_all_validations_on_disk_wrong_products_type(self): def test_parse_all_validations_on_disk_wrong_products_type(self):
self.assertRaises(TypeError, self.assertRaises(TypeError,
utils.parse_all_validations_on_disk, utils.parse_validations,
path='/foo/playbook', path='/foo/playbook',
products='foo1,foo2') products='foo1,foo2')
def test_get_validations_playbook_wrong_validation_id_type(self): def test_get_validations_playbook_wrong_validation_id_type(self):
self.assertRaises(TypeError, self.assertRaises(TypeError,
utils.get_validations_playbook, utils.get_validations_playbook_paths,
path='/foo/playbook', path='/foo/playbook',
validation_id='foo1,foo2') validation_id='foo1,foo2')
def test_get_validations_playbook_wrong_groups_type(self): def test_get_validations_playbook_wrong_groups_type(self):
self.assertRaises(TypeError, self.assertRaises(TypeError,
utils.get_validations_playbook, utils.get_validations_playbook_paths,
path='/foo/playbook', path='/foo/playbook',
groups='foo1,foo2') groups='foo1,foo2')
def test_get_validations_playbook_wrong_categories_type(self): def test_get_validations_playbook_wrong_categories_type(self):
self.assertRaises(TypeError, self.assertRaises(TypeError,
utils.get_validations_playbook, utils.get_validations_playbook_paths,
path='/foo/playbook', path='/foo/playbook',
categories='foo1,foo2') categories='foo1,foo2')
def test_get_validations_playbook_wrong_products_type(self): def test_get_validations_playbook_wrong_products_type(self):
self.assertRaises(TypeError, self.assertRaises(TypeError,
utils.get_validations_playbook, utils.get_validations_playbook_paths,
path='/foo/playbook', path='/foo/playbook',
products='foo1,foo2') products='foo1,foo2')
@mock.patch('os.path.isfile', return_value=True)
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK) @mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK)
@mock.patch('builtins.open') @mock.patch('builtins.open')
@mock.patch('glob.glob') @mock.patch('glob.glob')
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.side_effect = \ mock_isfile):
(['/foo/playbook/foo.yaml'], []) mock_glob.side_effect = self.globs_first_only
result = utils.parse_all_validations_on_disk('/foo/playbook', result = utils.parse_validations('/foo/playbook', groups=['prep'])
['prep']) self.assertEqual(result[0].get_metadata, fakes.FAKE_METADATA)
self.assertEqual(result, [fakes.FAKE_METADATA])
@mock.patch('os.path.isfile', return_value=True)
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK) @mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK)
@mock.patch('builtins.open') @mock.patch('builtins.open')
@mock.patch('glob.glob') @mock.patch('glob.glob')
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.side_effect = \ mock_isfile):
(['/foo/playbook/foo.yaml'], []) mock_glob.side_effect = self.globs_first_only
result = utils.parse_all_validations_on_disk('/foo/playbook', result = utils.parse_validations('/foo/playbook',
categories=['os']) categories=['os'])
self.assertEqual(result, [fakes.FAKE_METADATA]) self.assertEqual(result[0].get_metadata, fakes.FAKE_METADATA)
def test_get_validations_playbook_wrong_path_type(self): def test_get_validations_playbook_wrong_path_type(self):
self.assertRaises(TypeError, self.assertRaises(TypeError,
utils.get_validations_playbook, utils.get_validations_playbook_paths,
path=['/foo/playbook']) path=['/foo/playbook'])
@mock.patch('os.path.isfile', return_value=True)
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK) @mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK)
@mock.patch('builtins.open') @mock.patch('builtins.open')
@mock.patch('glob.glob') @mock.patch('glob.glob')
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.side_effect = (['/foo/playbook/foo.yaml'], []) mock_isfile):
result = utils.parse_all_validations_on_disk('/foo/playbook', mock_glob.side_effect = self.globs_first_only
products=['product1']) result = utils.parse_validations('/foo/playbook',
self.assertEqual(result, [fakes.FAKE_METADATA]) products=['product1'])
self.assertEqual(result[0].get_metadata, fakes.FAKE_METADATA)
@mock.patch('os.path.isfile') @mock.patch('yaml.safe_load', return_value=fakes.FAKE_WRONG_PLAYBOOK)
@mock.patch('builtins.open')
@mock.patch('glob.glob')
def test_parse_all_validations_on_disk_parsing_error(self, mock_glob,
mock_open, mock_load):
globs_t = self.globs_first_only
globs_t[-1] = ['/usr/ansible/playbooks/nonsense.yaml']
mock_glob.side_effect = globs_t
result = utils.parse_validations('/foo/playbook')
self.assertEqual(result, [])
@mock.patch('os.path.isfile', return_value=True)
@mock.patch('glob.glob') @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('builtins.open') @mock.patch('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_glob, mock_isfile): mock_glob, mock_isfile):
mock_glob.side_effect = (['/foo/playbook/foo.yaml'], []) mock_glob.side_effect = self.globs_first_only
mock_isfile.return_value = True result = utils.parse_validations('/foo/playbook', validation_ids=['foo'])
result = utils.get_validations_playbook('/foo/playbook', self.assertEqual(result[0].path, '/foo/playbook/foo.yaml')
validation_id=['foo'])
self.assertEqual(result, ['/foo/playbook/foo.yaml'])
@mock.patch('os.path.isfile') @mock.patch('os.path.isfile', return_value=True)
@mock.patch('glob.glob') @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('builtins.open') @mock.patch('builtins.open')
def test_get_community_playbook_by_id(self, mock_open, mock_load, def test_get_community_playbook_by_id(self, mock_open, mock_load,
mock_glob, mock_isfile): mock_glob, mock_isfile):
mock_glob.side_effect = ( mock_glob.side_effect = self.return_on_community
[],
['/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 # the /foo/playbook directory but the community validation path is
# implicit and we find there the id that we are looking for. # implicit and we find there the id that we are looking for.
result = utils.get_validations_playbook('/foo/playbook', result = utils.parse_validations('/foo/playbook')
validation_id=['foo']) self.assertEqual(result[0].path, '/home/foo/community-validations/playbooks/foo.yaml')
self.assertEqual(result, ['/home/foo/community-validations/playbooks/foo.yaml'])
@mock.patch('os.path.isfile') @mock.patch('os.path.isfile', return_value=True)
@mock.patch('glob.glob') @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('builtins.open') @mock.patch('builtins.open')
def test_get_community_disabled_playbook_by_id( def test_get_community_disabled_playbook_by_id(
self, mock_open, mock_load, mock_glob, mock_isfile): self, mock_open, mock_load, mock_glob, mock_isfile):
mock_glob.side_effect = ( mock_glob.side_effect = self.return_on_community
[],
['/home/foo/community-validations/playbooks/foo.yaml'])
mock_isfile.return_value = True
# The validations_commons validation is not found and community_vals is disabled # The validations_commons validation is not found and community_vals is disabled
# So no validation should be found. # So no validation should be found.
result = utils.get_validations_playbook( result = utils.parse_validations(
'/foo/playbook', '/foo/playbook',
validation_id=['foo'], validation_ids=['foo'],
validation_config={'default': {"enable_community_validations": False}}) validation_config={'default': {"enable_community_validations": False}})
self.assertEqual(result, []) self.assertEqual(result, [])
@mock.patch('os.path.isfile') @mock.patch('os.path.isfile', return_value=False)
@mock.patch('glob.glob') @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('builtins.open') @mock.patch('builtins.open')
def test_get_community_playbook_by_id_not_found( def test_get_community_playbook_by_id_not_found(
self, mock_open, mock_load, mock_glob, mock_isfile): self, mock_open, mock_load, mock_glob, mock_isfile):
mock_glob.side_effect = ( mock_glob.side_effect = self.return_on_community
[], # the is_file fails
['/home/foo/community-validations/playbooks/foo.yaml/']) result = utils.parse_validations('/foo/playbook',
# the is file fails validation_ids=['foo'])
mock_isfile.return_value = False
result = utils.get_validations_playbook('/foo/playbook',
validation_id=['foo'])
self.assertEqual(result, []) self.assertEqual(result, [])
@mock.patch('os.path.isfile') @mock.patch('os.path.isfile', return_value=True)
@mock.patch('glob.glob') @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('builtins.open') @mock.patch('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_glob, mock_isfile): mock_glob, mock_isfile):
mock_glob.side_effect = (['/foo/playbook/foo.yaml'], []) mock_glob.side_effect = self.globs_first_only
mock_isfile.return_value = True result = utils.parse_validations('/foo/playbook', ['foo'], ['prep'])
result = utils.get_validations_playbook('/foo/playbook', ['foo'], ['prep']) self.assertEqual(result[0].path, '/foo/playbook/foo.yaml')
self.assertEqual(result, ['/foo/playbook/foo.yaml',
'/foo/playbook/foo.yaml'])
@mock.patch('os.path.isfile') @mock.patch('os.path.isfile', return_value=True)
@mock.patch('os.listdir') @mock.patch('os.listdir')
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK) @mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK)
@mock.patch('builtins.open') @mock.patch('builtins.open')
@ -303,34 +310,31 @@ class TestUtils(TestCase):
mock_listdir, mock_listdir,
mock_isfile): mock_isfile):
mock_listdir.return_value = ['foo.yaml'] mock_listdir.return_value = ['foo.yaml']
mock_isfile.return_value = True result = utils.parse_validations('/foo/playbook',
result = utils.get_validations_playbook('/foo/playbook', groups=['no_group'])
groups=['no_group'])
self.assertEqual(result, []) self.assertEqual(result, [])
@mock.patch('os.path.isfile') @mock.patch('os.path.isfile', return_value=True)
@mock.patch('glob.glob') @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('builtins.open') @mock.patch('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_glob, mock_isfile): mock_glob, mock_isfile):
mock_glob.side_effect = (['/foo/playbook/foo.yaml'], []) mock_glob.side_effect = self.globs_first_only
mock_isfile.return_value = True result = utils.parse_validations('/foo/playbook',
result = utils.get_validations_playbook('/foo/playbook', categories=['os', 'storage'])
categories=['os', 'storage']) self.assertEqual(result[0].path, '/foo/playbook/foo.yaml')
self.assertEqual(result, ['/foo/playbook/foo.yaml'])
@mock.patch('os.path.isfile') @mock.patch('os.path.isfile', return_value=True)
@mock.patch('glob.glob') @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('builtins.open') @mock.patch('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_glob, mock_isfile): mock_glob, mock_isfile):
mock_glob.side_effect = (['/foo/playbook/foo.yaml'], []) mock_glob.side_effect = self.globs_first_only
mock_isfile.return_value = True result = utils.parse_validations('/foo/playbook',
result = utils.get_validations_playbook('/foo/playbook', products=['product1'])
products=['product1']) self.assertEqual(result[0].path, '/foo/playbook/foo.yaml')
self.assertEqual(result, ['/foo/playbook/foo.yaml'])
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK) @mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK)
@mock.patch('builtins.open') @mock.patch('builtins.open')
@ -376,30 +380,12 @@ class TestUtils(TestCase):
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK2) @mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK2)
@mock.patch('builtins.open') @mock.patch('builtins.open')
def test_get_validations_parameters_no_group(self, mock_open, mock_load): def test_get_validations_parameters(self, mock_open, mock_load):
test_validation = Validation('/foo/playbook/foo.yaml')
result = utils.get_validations_parameters(['/foo/playbook/foo.yaml'], result = utils.get_validations_parameters([test_validation])
['foo'])
output = {'foo': {'parameters': {'foo': 'bar'}}} output = {'foo': {'parameters': {'foo': 'bar'}}}
self.assertEqual(result, output) self.assertEqual(result, output)
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK2)
@mock.patch('builtins.open')
def test_get_validations_parameters_no_val(self, mock_open, mock_load):
result = utils.get_validations_parameters(['/foo/playbook/foo.yaml'],
[], ['prep'])
output = {'foo': {'parameters': {'foo': 'bar'}}}
self.assertEqual(result, output)
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK)
@mock.patch('builtins.open')
def test_get_validations_parameters_nothing(self, mock_open, mock_load):
result = utils.get_validations_parameters(['/foo/playbook/foo.yaml'],
[], [])
self.assertEqual(result, {})
@mock.patch('validations_libs.utils.os.makedirs') @mock.patch('validations_libs.utils.os.makedirs')
@mock.patch( @mock.patch(
'validations_libs.utils.os.access', 'validations_libs.utils.os.access',
@ -521,13 +507,13 @@ class TestUtils(TestCase):
results['ansible_environment']['ANSIBLE_STDOUT_CALLBACK'], results['ansible_environment']['ANSIBLE_STDOUT_CALLBACK'],
fakes.ANSIBLE_ENVIRONNMENT_CONFIG['ANSIBLE_STDOUT_CALLBACK']) fakes.ANSIBLE_ENVIRONNMENT_CONFIG['ANSIBLE_STDOUT_CALLBACK'])
@mock.patch('{}.Path.exists'.format(PATHLIB), @mock.patch('pathlib.Path.exists',
return_value=False) return_value=False)
@mock.patch('{}.Path.is_dir'.format(PATHLIB), @mock.patch('pathlib.Path.is_dir',
return_value=False) return_value=False)
@mock.patch('{}.Path.iterdir'.format(PATHLIB), @mock.patch('pathlib.Path.iterdir',
return_value=iter([])) return_value=iter([]))
@mock.patch('{}.Path.mkdir'.format(PATHLIB)) @mock.patch('pathlib.Path.mkdir')
def test_check_creation_community_validations_dir(self, mock_mkdir, def test_check_creation_community_validations_dir(self, mock_mkdir,
mock_iterdir, mock_iterdir,
mock_isdir, mock_isdir,
@ -543,11 +529,11 @@ class TestUtils(TestCase):
PosixPath("/foo/bar/community-validations/lookup_plugins")] PosixPath("/foo/bar/community-validations/lookup_plugins")]
) )
@mock.patch('{}.Path.is_dir'.format(PATHLIB), return_value=True) @mock.patch('pathlib.Path.is_dir', return_value=True)
@mock.patch('{}.Path.exists'.format(PATHLIB), return_value=True) @mock.patch('pathlib.Path.exists', return_value=True)
@mock.patch('{}.Path.iterdir'.format(PATHLIB), @mock.patch('pathlib.Path.iterdir',
return_value=fakes.FAKE_COVAL_MISSING_SUBDIR_ITERDIR1) return_value=fakes.FAKE_COVAL_MISSING_SUBDIR_ITERDIR1)
@mock.patch('{}.Path.mkdir'.format(PATHLIB)) @mock.patch('pathlib.Path.mkdir')
def test_check_community_validations_dir_with_missing_subdir(self, def test_check_community_validations_dir_with_missing_subdir(self,
mock_mkdir, mock_mkdir,
mock_iterdir, mock_iterdir,

View File

@ -21,6 +21,7 @@ from unittest import TestCase
from validations_libs.validation import Validation from validations_libs.validation import Validation
from validations_libs.tests import fakes from validations_libs.tests import fakes
from validations_libs import exceptions
class TestValidation(TestCase): class TestValidation(TestCase):
@ -44,10 +45,10 @@ class TestValidation(TestCase):
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_WRONG_PLAYBOOK) @mock.patch('yaml.safe_load', return_value=fakes.FAKE_WRONG_PLAYBOOK)
@mock.patch('builtins.open') @mock.patch('builtins.open')
def test_get_metadata_wrong_playbook(self, mock_open, mock_yaml): def test_no_metadata(self, mock_open, mock_yaml):
with self.assertRaises(NameError) as exc_mgr: with self.assertRaises(exceptions.ValidationParsingException) as exc_mgr:
Validation('/tmp/foo').get_metadata Validation('/tmp/foo')
self.assertEqual('No metadata found in validation foo', self.assertEqual('No metadata found in validation /tmp/foo',
str(exc_mgr.exception)) str(exc_mgr.exception))
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK2) @mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK2)
@ -64,14 +65,6 @@ class TestValidation(TestCase):
data = val.get_vars data = val.get_vars
self.assertEqual(data, {}) self.assertEqual(data, {})
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_WRONG_PLAYBOOK)
@mock.patch('builtins.open')
def test_get_vars_no_metadata(self, mock_open, mock_yaml):
with self.assertRaises(NameError) as exc_mgr:
Validation('/tmp/foo').get_vars
self.assertEqual('No metadata found in validation foo',
str(exc_mgr.exception))
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK) @mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK)
@mock.patch('builtins.open') @mock.patch('builtins.open')
def test_get_id(self, mock_open, mock_yaml): def test_get_id(self, mock_open, mock_yaml):
@ -88,14 +81,6 @@ class TestValidation(TestCase):
groups = val.groups groups = val.groups
self.assertEqual(groups, ['prep', 'pre-deployment']) self.assertEqual(groups, ['prep', 'pre-deployment'])
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_WRONG_PLAYBOOK)
@mock.patch('builtins.open')
def test_groups_with_no_metadata(self, mock_open, mock_yaml):
with self.assertRaises(NameError) as exc_mgr:
Validation('/tmp/foo').groups
self.assertEqual('No metadata found in validation foo',
str(exc_mgr.exception))
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK3) @mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK3)
@mock.patch('builtins.open') @mock.patch('builtins.open')
def test_groups_with_no_existing_groups(self, mock_open, mock_yaml): def test_groups_with_no_existing_groups(self, mock_open, mock_yaml):
@ -110,14 +95,6 @@ class TestValidation(TestCase):
categories = val.categories categories = val.categories
self.assertEqual(categories, ['os', 'storage']) self.assertEqual(categories, ['os', 'storage'])
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_WRONG_PLAYBOOK)
@mock.patch('builtins.open')
def test_categories_with_no_metadata(self, mock_open, mock_yaml):
with self.assertRaises(NameError) as exc_mgr:
Validation('/tmp/foo').categories
self.assertEqual('No metadata found in validation foo',
str(exc_mgr.exception))
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK3) @mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK3)
@mock.patch('builtins.open') @mock.patch('builtins.open')
def test_categories_with_no_existing_categories(self, mock_open, mock_yaml): def test_categories_with_no_existing_categories(self, mock_open, mock_yaml):
@ -132,14 +109,6 @@ class TestValidation(TestCase):
products = val.products products = val.products
self.assertEqual(products, ['product1']) self.assertEqual(products, ['product1'])
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_WRONG_PLAYBOOK)
@mock.patch('builtins.open')
def test_products_with_no_metadata(self, mock_open, mock_yaml):
with self.assertRaises(NameError) as exc_mgr:
Validation('/tmp/foo').products
self.assertEqual('No metadata found in validation foo',
str(exc_mgr.exception))
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK3) @mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK3)
@mock.patch('builtins.open') @mock.patch('builtins.open')
def test_products_with_no_existing_products(self, mock_open, mock_yaml): def test_products_with_no_existing_products(self, mock_open, mock_yaml):
@ -161,14 +130,6 @@ class TestValidation(TestCase):
data = val.get_formated_data data = val.get_formated_data
self.assertEqual(data, fakes.FORMATED_DATA) self.assertEqual(data, fakes.FORMATED_DATA)
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_WRONG_PLAYBOOK)
@mock.patch('builtins.open')
def test_get_formated_data_no_metadata(self, mock_open, mock_yaml):
with self.assertRaises(NameError) as exc_mgr:
Validation('/tmp/foo').get_formated_data
self.assertEqual('No metadata found in validation foo',
str(exc_mgr.exception))
@mock.patch('builtins.open') @mock.patch('builtins.open')
def test_validation_not_found(self, mock_open): def test_validation_not_found(self, mock_open):
mock_open.side_effect = IOError() mock_open.side_effect = IOError()

View File

@ -13,18 +13,14 @@
# under the License. # under the License.
# #
try: from unittest import TestCase, mock
from unittest import mock from unittest.mock import ANY
from unittest.mock import ANY
except ImportError:
import mock
from mock import ANY
from unittest import TestCase
from validations_libs.exceptions import (ValidationRunException,
ValidationShowException)
from validations_libs.tests import fakes from validations_libs.tests import fakes
from validations_libs.validation import Validation
from validations_libs.validation_actions import ValidationActions from validations_libs.validation_actions import ValidationActions
from validations_libs.exceptions import ValidationRunException, ValidationShowException
class TestValidationActions(TestCase): class TestValidationActions(TestCase):
@ -33,7 +29,7 @@ class TestValidationActions(TestCase):
super(TestValidationActions, self).setUp() super(TestValidationActions, self).setUp()
self.column_name = ('ID', 'Name', 'Groups', 'Categories', 'Products') self.column_name = ('ID', 'Name', 'Groups', 'Categories', 'Products')
@mock.patch('validations_libs.utils.parse_all_validations_on_disk', @mock.patch('validations_libs.utils.parse_validations',
return_value=fakes.VALIDATIONS_LIST) return_value=fakes.VALIDATIONS_LIST)
def test_validation_list(self, mock_validation_dir): def test_validation_list(self, mock_validation_dir):
validations_list = ValidationActions('/tmp/foo') validations_list = ValidationActions('/tmp/foo')
@ -50,11 +46,14 @@ class TestValidationActions(TestCase):
['networking'], ['networking'],
['product1'])])) ['product1'])]))
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK)
@mock.patch('builtins.open')
@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)
@mock.patch('validations_libs.utils.get_validations_playbook', @mock.patch('validations_libs.utils.get_validations_playbook_paths',
return_value=['/tmp/foo/fake.yaml']) return_value=['/tmp/foo/fake.yaml'])
def test_validation_skip_validation(self, mock_validation_play, mock_exists, mock_access): def test_validation_skip_validation(self, mock_validation_play, mock_exists, mock_access,
mock_open, mock_yaml_load):
playbook = ['fake.yaml'] playbook = ['fake.yaml']
inventory = 'tmp/inventory.yaml' inventory = 'tmp/inventory.yaml'
@ -70,6 +69,8 @@ class TestValidationActions(TestCase):
limit_hosts=None) limit_hosts=None)
self.assertEqual(run_return, []) self.assertEqual(run_return, [])
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK)
@mock.patch('builtins.open')
@mock.patch('validations_libs.utils.current_time', @mock.patch('validations_libs.utils.current_time',
return_value='time') return_value='time')
@mock.patch('validations_libs.utils.uuid.uuid4', @mock.patch('validations_libs.utils.uuid.uuid4',
@ -79,16 +80,15 @@ class TestValidationActions(TestCase):
return_value=True) return_value=True)
@mock.patch('validations_libs.utils.os.path.exists', @mock.patch('validations_libs.utils.os.path.exists',
return_value=True) return_value=True)
@mock.patch('validations_libs.utils.get_validations_playbook', @mock.patch('validations_libs.utils.get_validations_playbook_paths',
return_value=['/tmp/foo/fake.yaml']) return_value=['/tmp/foo/fake.yaml'])
@mock.patch('validations_libs.ansible.Ansible.run') @mock.patch('validations_libs.ansible.Ansible.run')
def test_validation_skip_on_specific_host(self, mock_ansible_run, def test_validation_skip_on_specific_host(self, mock_ansible_run,
mock_validation_play, mock_validation_play,
mock_exists, mock_exists, mock_access,
mock_access, mock_makedirs, mock_uuid,
mock_makedirs, mock_time, mock_open,
mock_uuid, mock_yaml_load):
mock_time):
mock_ansible_run.return_value = ('fake.yaml', 0, 'successful') mock_ansible_run.return_value = ('fake.yaml', 0, 'successful')
run_called_args = { run_called_args = {
@ -130,6 +130,8 @@ class TestValidationActions(TestCase):
mock_ansible_run.assert_called_with(**run_called_args) mock_ansible_run.assert_called_with(**run_called_args)
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK)
@mock.patch('builtins.open')
@mock.patch('validations_libs.utils.current_time', @mock.patch('validations_libs.utils.current_time',
return_value='time') return_value='time')
@mock.patch('validations_libs.utils.uuid.uuid4', @mock.patch('validations_libs.utils.uuid.uuid4',
@ -139,7 +141,7 @@ class TestValidationActions(TestCase):
return_value=True) return_value=True)
@mock.patch('validations_libs.utils.os.path.exists', @mock.patch('validations_libs.utils.os.path.exists',
return_value=True) return_value=True)
@mock.patch('validations_libs.utils.get_validations_playbook', @mock.patch('validations_libs.utils.get_validations_playbook_paths',
return_value=['/tmp/foo/fake.yaml']) return_value=['/tmp/foo/fake.yaml'])
@mock.patch('validations_libs.ansible.Ansible.run') @mock.patch('validations_libs.ansible.Ansible.run')
def test_validation_skip_with_limit_host(self, mock_ansible_run, def test_validation_skip_with_limit_host(self, mock_ansible_run,
@ -148,7 +150,9 @@ class TestValidationActions(TestCase):
mock_access, mock_access,
mock_makedirs, mock_makedirs,
mock_uuid, mock_uuid,
mock_time): mock_time,
mock_open,
mock_yaml_load):
mock_ansible_run.return_value = ('fake.yaml', 0, 'successful') mock_ansible_run.return_value = ('fake.yaml', 0, 'successful')
run_called_args = { run_called_args = {
@ -190,31 +194,28 @@ class TestValidationActions(TestCase):
mock_ansible_run.assert_called_with(**run_called_args) mock_ansible_run.assert_called_with(**run_called_args)
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK)
@mock.patch('builtins.open')
@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)
@mock.patch('validations_libs.validation_actions.ValidationLogs.get_results', @mock.patch('validations_libs.validation_actions.ValidationLogs.get_results',
side_effect=fakes.FAKE_SUCCESS_RUN) side_effect=fakes.FAKE_SUCCESS_RUN)
@mock.patch('validations_libs.utils.parse_all_validations_on_disk') @mock.patch('validations_libs.utils.parse_validations')
@mock.patch('validations_libs.ansible.Ansible.run') @mock.patch('validations_libs.ansible.Ansible.run')
def test_validation_run_success(self, mock_ansible_run, def test_validation_run_success(self, mock_ansible_run,
mock_validation_dir, mock_validation_dir,
mock_results, mock_exists, mock_access, mock_results, mock_exists, mock_access,
mock_makedirs): mock_makedirs, mock_open, mock_safe_load):
mock_validation_dir.return_value = [{ mock_validation = Validation('/tmp/foobar/validation-playbooks/foo.yaml')
'description': 'My Validation One Description', mock_validation_dir.return_value = [mock_validation]
'groups': ['prep', 'pre-deployment'],
'id': 'foo',
'name': 'My Validition One Name',
'parameters': {},
'path': '/tmp/foobar/validation-playbooks'}]
mock_ansible_run.return_value = ('foo.yaml', 0, 'successful') mock_ansible_run.return_value = ('foo.yaml', 0, 'successful')
expected_run_return = fakes.FAKE_SUCCESS_RUN[0] expected_run_return = fakes.FAKE_SUCCESS_RUN[0]
playbook = ['fake.yaml'] playbook = ['foo.yaml']
inventory = 'tmp/inventory.yaml' inventory = 'tmp/inventory.yaml'
run = ValidationActions() run = ValidationActions()
@ -246,7 +247,7 @@ class TestValidationActions(TestCase):
validation_cfg_file=None validation_cfg_file=None
) )
@mock.patch('validations_libs.utils.get_validations_playbook') @mock.patch('validations_libs.utils.get_validations_playbook_paths')
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 = []
@ -255,23 +256,15 @@ class TestValidationActions(TestCase):
validation_name=['fake'], validation_name=['fake'],
validations_dir='/tmp/foo') validations_dir='/tmp/foo')
@mock.patch('validations_libs.utils.get_validations_playbook') @mock.patch('builtins.open', side_effect=IOError)
def test_validation_run_not_all_found(self, mock_validation_play): @mock.patch('validations_libs.utils.get_validations_playbook_paths')
def test_validation_run_not_all_found(self, mock_validation_play, mock_open):
mock_validation_play.return_value = ['/tmp/foo/fake.yaml'] mock_validation_play.return_value = ['/tmp/foo/fake.yaml']
run = ValidationActions() run = ValidationActions()
try: self.assertRaises(OSError, run.run_validations, validation_name=['fake', 'foo'], validations_dir='/tmp/foo')
run.run_validations(
validation_name=['fake', 'foo'],
validations_dir='/tmp/foo')
except ValidationRunException as run_exception:
self.assertEqual(
"Following validations were not found in '/tmp/foo': foo",
str(run_exception))
else:
self.fail("Runtime error exception should have been raised")
@mock.patch('validations_libs.utils.parse_all_validations_on_disk') @mock.patch('validations_libs.utils.parse_validations')
def test_validation_run_not_enough_params(self, mock_validation_play): def test_validation_run_not_enough_params(self, mock_validation_play):
mock_validation_play.return_value = [] mock_validation_play.return_value = []
@ -280,24 +273,22 @@ class TestValidationActions(TestCase):
validations_dir='/tmp/foo' validations_dir='/tmp/foo'
) )
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK)
@mock.patch('builtins.open')
@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)
@mock.patch('validations_libs.validation_logs.ValidationLogs.get_results') @mock.patch('validations_libs.validation_logs.ValidationLogs.get_results')
@mock.patch('validations_libs.utils.parse_all_validations_on_disk') @mock.patch('validations_libs.utils.parse_validations')
@mock.patch('validations_libs.ansible.Ansible.run') @mock.patch('validations_libs.ansible.Ansible.run')
def test_validation_run_failed(self, mock_ansible_run, def test_validation_run_failed(self, mock_ansible_run,
mock_validation_dir, mock_results, mock_validation_dir, mock_results,
mock_exists, mock_access, mock_exists, mock_access,
mock_makedirs): mock_makedirs, mock_open,
mock_yaml_load):
mock_validation_dir.return_value = [{ mock_validation = Validation('/tmp/foobar/validation-playbooks/foo.yaml')
'description': 'My Validation One Description', mock_validation_dir.return_value = [mock_validation]
'groups': ['prep', 'pre-deployment'],
'id': 'foo',
'name': 'My Validition One Name',
'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')
@ -326,24 +317,22 @@ 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.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK)
@mock.patch('builtins.open')
@mock.patch('validations_libs.ansible.Ansible._playbook_check', @mock.patch('validations_libs.ansible.Ansible._playbook_check',
side_effect=RuntimeError) side_effect=RuntimeError)
@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)
@mock.patch('validations_libs.utils.parse_all_validations_on_disk') @mock.patch('validations_libs.utils.parse_validations')
def test_spinner_exception_failure_condition(self, mock_validation_dir, def test_spinner_exception_failure_condition(self, mock_validation_dir,
mock_exists, mock_access, mock_exists, mock_access,
mock_makedirs, mock_makedirs,
mock_playbook_check): mock_playbook_check,
mock_open,
mock_validation_dir.return_value = [{ mock_yaml_load):
'description': 'My Validation One Description', mock_validation = Validation('/tmp/foobar/validation-playbooks/foo.yaml')
'groups': ['prep', 'pre-deployment'], mock_validation_dir.return_value = [mock_validation]
'id': 'foo',
'name': 'My Validition One Name',
'parameters': {},
'path': '/usr/share/ansible/validation-playbooks'}]
playbook = ['fake.yaml'] playbook = ['fake.yaml']
inventory = 'tmp/inventory.yaml' inventory = 'tmp/inventory.yaml'
@ -353,24 +342,22 @@ class TestValidationActions(TestCase):
inventory, group=fakes.GROUPS_LIST, inventory, group=fakes.GROUPS_LIST,
validations_dir='/tmp/foo') validations_dir='/tmp/foo')
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK)
@mock.patch('builtins.open')
@mock.patch('validations_libs.ansible.Ansible._playbook_check', @mock.patch('validations_libs.ansible.Ansible._playbook_check',
side_effect=RuntimeError) side_effect=RuntimeError)
@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)
@mock.patch('validations_libs.utils.parse_all_validations_on_disk') @mock.patch('validations_libs.utils.parse_validations')
@mock.patch('sys.__stdin__.isatty', return_value=True) @mock.patch('sys.__stdin__.isatty', return_value=True)
def test_spinner_forced_run(self, mock_stdin_isatty, mock_validation_dir, def test_spinner_forced_run(self, mock_stdin_isatty, mock_validation_dir,
mock_exists, mock_access, mock_makedirs, mock_exists, mock_access, mock_makedirs,
mock_playbook_check): mock_playbook_check, mock_open,
mock_yaml_load):
mock_validation_dir.return_value = [{ mock_validation = Validation('/tmp/foobar/validation-playbooks/foo.yaml')
'description': 'My Validation One Description', mock_validation_dir.return_value = [mock_validation]
'groups': ['prep', 'pre-deployment'],
'id': 'foo',
'name': 'My Validition One Name',
'parameters': {},
'path': '/usr/share/ansible/validation-playbooks'}]
playbook = ['fake.yaml'] playbook = ['fake.yaml']
inventory = 'tmp/inventory.yaml' inventory = 'tmp/inventory.yaml'
@ -380,7 +367,7 @@ class TestValidationActions(TestCase):
inventory, group=fakes.GROUPS_LIST, inventory, group=fakes.GROUPS_LIST,
validations_dir='/tmp/foo') validations_dir='/tmp/foo')
@mock.patch('validations_libs.utils.get_validations_playbook', @mock.patch('validations_libs.utils.get_validations_playbook_paths',
return_value=[]) return_value=[])
def test_validation_run_no_validation(self, mock_get_val): def test_validation_run_no_validation(self, mock_get_val):
playbook = ['fake.yaml'] playbook = ['fake.yaml']
@ -390,7 +377,7 @@ class TestValidationActions(TestCase):
self.assertRaises(ValidationRunException, run.run_validations, playbook, self.assertRaises(ValidationRunException, run.run_validations, playbook,
inventory) inventory)
@mock.patch('validations_libs.utils.parse_all_validations_on_disk', @mock.patch('validations_libs.utils.parse_validations',
return_value=fakes.VALIDATIONS_LIST) return_value=fakes.VALIDATIONS_LIST)
@mock.patch('validations_libs.validation.Validation._get_content', @mock.patch('validations_libs.validation.Validation._get_content',
return_value=fakes.FAKE_PLAYBOOK[0]) return_value=fakes.FAKE_PLAYBOOK[0])
@ -424,7 +411,7 @@ class TestValidationActions(TestCase):
'512e' '512e'
) )
@mock.patch('validations_libs.utils.parse_all_validations_on_disk', @mock.patch('validations_libs.utils.parse_validations',
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)
@mock.patch('builtins.open') @mock.patch('builtins.open')
@ -465,7 +452,7 @@ class TestValidationActions(TestCase):
v_actions.show_validations_parameters, v_actions.show_validations_parameters,
products={'foo': 'bar'}) products={'foo': 'bar'})
@mock.patch('validations_libs.utils.get_validations_playbook', @mock.patch('validations_libs.utils.get_validations_playbook_paths',
return_value=['/foo/playbook/foo.yaml']) return_value=['/foo/playbook/foo.yaml'])
@mock.patch('validations_libs.utils.get_validations_parameters') @mock.patch('validations_libs.utils.get_validations_parameters')
@mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK) @mock.patch('yaml.safe_load', return_value=fakes.FAKE_PLAYBOOK)

View File

@ -31,6 +31,7 @@ from validations_libs import constants
from validations_libs.group import Group from validations_libs.group import Group
from validations_libs.validation import Validation from validations_libs.validation import Validation
from validations_libs.logger import getLogger from validations_libs.logger import getLogger
from validations_libs import exceptions
LOG = getLogger(__name__ + ".utils") LOG = getLogger(__name__ + ".utils")
@ -151,13 +152,14 @@ def create_artifacts_dir(log_path=constants.VALIDATIONS_LOG_BASEDIR,
raise RuntimeError() raise RuntimeError()
def parse_all_validations_on_disk(path, def parse_validations(path,
groups=None, validation_ids=None,
categories=None, groups=None,
products=None, categories=None,
validation_config=None): products=None,
"""Return a list of validations metadata which can be sorted by Groups, by validation_config=None):
Categories or by Products. """Return a list of validations metadata dictionaries which
can be sorted by Groups, Categories or Products.
:param path: The absolute path of the validations directory :param path: The absolute path of the validations directory
:type path: `string` :type path: `string`
@ -175,8 +177,8 @@ def parse_all_validations_on_disk(path,
loaded from an validation.cfg file. loaded from an validation.cfg file.
:type validation_config: ``dict`` :type validation_config: ``dict``
:return: A list of validations metadata. :return: A list of `Validation` objects
:rtype: `list` :rtype: ``list``
:Example: :Example:
@ -198,6 +200,11 @@ def parse_all_validations_on_disk(path,
if not isinstance(path, str): if not isinstance(path, str):
raise TypeError("The 'path' argument must be a String") raise TypeError("The 'path' argument must be a String")
if not validation_ids:
validation_ids = []
elif not isinstance(validation_ids, list):
raise TypeError("The 'validation_ids' argument must be a List")
if not groups: if not groups:
groups = [] groups = []
elif not isinstance(groups, list): elif not isinstance(groups, list):
@ -214,62 +221,63 @@ def parse_all_validations_on_disk(path,
raise TypeError("The 'products' argument must be a List") raise TypeError("The 'products' argument must be a List")
results = [] results = []
validations_abspath = glob.glob("{path}/*.yaml".format(path=path)) validations_abspaths = get_validations_playbook_paths(
if community_validations_on(validation_config): path=path,
validations_abspath.extend(glob.glob("{}/*.yaml".format( validation_config=validation_config)
constants.COMMUNITY_PLAYBOOKS_DIR)))
LOG.debug( LOG.debug(
"Attempting to parse validations by:\n" "Attempting to parse validations by:\n"
" - ids: {}\n"
" - groups: {}\n" " - groups: {}\n"
" - categories: {}\n" " - categories: {}\n"
" - products: {}\n" " - products: {}\n"
"from {}".format(groups, categories, products, validations_abspath) "from {}".format(validation_ids, groups,
categories, products, validations_abspaths)
) )
for playbook in validations_abspath: for playbook in validations_abspaths:
val = Validation(playbook) try:
val = Validation(playbook)
if not groups and not categories and not products: except exceptions.ValidationParsingException:
results.append(val.get_metadata) LOG.error(
"Attempt to parse playbook at location {} has failed."
"Playbooks is either not a properly formatted validation "
"or a generic ansible playbook.".format(playbook))
continue continue
# Skip further evaluation and return all if we have nothing to select by.
if not (validation_ids or groups or categories or products):
results.append(val)
continue
if validation_ids:
if val.id in validation_ids:
results.append(val)
if groups:
if set(groups).intersection(val.groups):
results.append(val)
if categories:
if set(categories).intersection(val.categories):
results.append(val)
if products:
if set(products).intersection(val.products):
results.append(val)
if set(groups).intersection(val.groups) or \ LOG.debug("Retrieved {v_count} validations in pre-defined paths: {paths}".format(
set(categories).intersection(val.categories) or \ v_count=len(results),
set(products).intersection(val.products): paths=':'.join(constants.VALIDATION_PLAYBOOK_DIRS)))
results.append(val.get_metadata)
return results return results
def get_validations_playbook(path, def get_validations_playbook_paths(path,
validation_id=None, validation_config=None):
groups=None, """Get a list of validations playbooks paths.
categories=None,
products=None,
validation_config=None):
"""Get a list of validations playbooks paths either by their names,
their groups, by their categories or by their products.
:param path: Path of the validations playbooks :param path: Path of the validations playbooks
:type path: `string` :type path: `string`
:param validation_id: List of validation name
:type validation_id: `list`
:param groups: List of validation group
:type groups: `list`
:param categories: List of validation category
:type categories: `list`
:param products: List of validation product
:type products: `list`
: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 absolute validations playbooks path :return: A list of absolute validations playbooks paths
:rtype: `list` :rtype: `list`
:Example: :Example:
@ -290,49 +298,18 @@ def get_validations_playbook(path,
if not isinstance(path, str): if not isinstance(path, str):
raise TypeError("The 'path' argument must be a String") raise TypeError("The 'path' argument must be a String")
if not validation_id:
validation_id = []
elif not isinstance(validation_id, list):
raise TypeError("The 'validation_id' argument must be a List")
if not groups:
groups = []
elif not isinstance(groups, list):
raise TypeError("The 'groups' argument must be a List")
if not categories:
categories = []
elif not isinstance(categories, list):
raise TypeError("The 'categories' argument must be a List")
if not products:
products = []
elif not isinstance(products, list):
raise TypeError("The 'products' argument must be a List")
pl = []
validations_abspath = glob.glob("{path}/*.yaml".format(path=path)) validations_abspath = glob.glob("{path}/*.yaml".format(path=path))
if community_validations_on(validation_config): if community_validations_on(validation_config):
validations_abspath.extend(glob.glob("{}/*.yaml".format( validations_abspath.extend(glob.glob("{}/*.yaml".format(
constants.COMMUNITY_PLAYBOOKS_DIR))) constants.COMMUNITY_PLAYBOOKS_DIR)))
for pl_path in validations_abspath:
if os.path.isfile(pl_path):
if validation_id:
if os.path.splitext(os.path.basename(pl_path))[0] in validation_id or \
os.path.basename(pl_path) in validation_id:
pl.append(pl_path)
val = Validation(pl_path) for possible_path in constants.VALIDATION_PLAYBOOK_DIRS:
if groups: validations_abspath.extend(glob.glob("{}/*.yaml".format(possible_path)))
if set(groups).intersection(val.groups):
pl.append(pl_path) # Filter out all non files that somehow got in
if categories: validations_abspath = [path for path in validations_abspath if os.path.isfile(path)]
if set(categories).intersection(val.categories):
pl.append(pl_path) return validations_abspath
if products:
if set(products).intersection(val.products):
pl.append(pl_path)
return pl
def get_validation_parameters(validation): def get_validation_parameters(validation):
@ -439,75 +416,33 @@ def get_validations_data(
return data return data
def get_validations_parameters(validations_data, def get_validations_parameters(validations_data):
validation_name=None,
groups=None,
categories=None,
products=None):
"""Return parameters for a list of validations """Return parameters for a list of validations
:param validations_data: A list of absolute validations playbooks path :param validations_data: A list of `Validation` objects
:type validations_data: `list` :type validations_data: `list`
:param validation_name: A list of validation name
:type validation_name: `list`
:param groups: A list of validation groups
:type groups: `list`
:param categories: A list of validation categories
:type categories: `list`
:param products: A list of validation products
:type products: `list`
:return: a dictionary containing the current parameters for :return: a dictionary containing the current parameters for
each `validation_name` or `groups` each `Validation` object
:rtype: `dict` :rtype: `dict`
:Example: :Example:
>>> validations_data = ['/foo/bar/check-ram.yaml', >>> validations_data = [Validation('/foo/bar/check-ram.yaml),
'/foo/bar/check-cpu.yaml'] Validation('/foo/bar/check-cpu.yaml)]
>>> validation_name = ['check-ram', 'check-cpu'] >>> get_validations_parameters(validations_data)
>>> get_validations_parameters(validations_data, validation_name)
{'check-cpu': {'parameters': {'minimal_cpu_count': 8}}, {'check-cpu': {'parameters': {'minimal_cpu_count': 8}},
'check-ram': {'parameters': {'minimal_ram_gb': 24}}} 'check-ram': {'parameters': {'minimal_ram_gb': 24}}}
""" """
if not isinstance(validations_data, list): if not isinstance(validations_data, list):
raise TypeError("The 'validations_data' argument must be a List") raise TypeError("The 'validations_data' argument must be a List")
if not validation_name:
validation_name = []
elif not isinstance(validation_name, list):
raise TypeError("The 'validation_name' argument must be a List")
if not groups:
groups = []
elif not isinstance(groups, list):
raise TypeError("The 'groups' argument must be a List")
if not categories:
categories = []
elif not isinstance(categories, list):
raise TypeError("The 'categories' argument must be a List")
if not products:
products = []
elif not isinstance(products, list):
raise TypeError("The 'products' argument must be a List")
params = {} params = {}
for val in validations_data: for val in validations_data:
v = Validation(val) params[val.id] = {
if v.id in validation_name or \ 'parameters': val.get_vars
set(groups).intersection(v.groups) or \ }
set(categories).intersection(v.categories) or \
set(products).intersection(v.products):
params[v.id] = {
'parameters': v.get_vars
}
return params return params

View File

@ -14,6 +14,7 @@
# #
from validations_libs.logger import getLogger from validations_libs.logger import getLogger
import validations_libs.exceptions as exceptions
import os import os
import yaml import yaml
from collections import OrderedDict from collections import OrderedDict
@ -88,8 +89,11 @@ class Validation:
def __init__(self, validation_path): def __init__(self, validation_path):
self.dict = self._get_content(validation_path) self.dict = self._get_content(validation_path)
if not self.has_metadata_dict:
raise exceptions.ValidationParsingException(
"No metadata found in validation {}".format(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) self.path = validation_path
def _get_content(self, val_path): def _get_content(self, val_path):
try: try:
@ -163,9 +167,7 @@ class Validation:
"""Get the metadata of a validation """Get the metadata of a validation
:return: The validation metadata :return: The validation metadata
:rtype: `dict` or `None` if no metadata has been found :rtype: `dict`
:raise: A `NameError` exception if no metadata has been found in the
playbook
:Example: :Example:
@ -178,25 +180,18 @@ class Validation:
'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/'} 'path': '/tmp/foo/val1.yaml'}
""" """
if self.has_metadata_dict: self.metadata = {'id': self.id, 'path': self.path}
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:
raise NameError(
"No metadata found in validation {}".format(self.id)
)
@property @property
def get_vars(self): def get_vars(self):
"""Get only the variables of a validation """Get only the variables of a validation
:return: All the variables belonging to a validation :return: All the variables belonging to a validation
:rtype: `dict` or `None` if no metadata has been found :rtype: `dict`
:raise: A `NameError` exception if no metadata has been found in the
playbook
:Example: :Example:
@ -206,14 +201,9 @@ class Validation:
{'var_name1': 'value1', {'var_name1': 'value1',
'var_name2': 'value2'} 'var_name2': 'value2'}
""" """
if self.has_metadata_dict: validation_vars = self.dict['vars'].copy()
validation_vars = self.dict['vars'].copy() validation_vars.pop('metadata')
validation_vars.pop('metadata') return validation_vars
return validation_vars
else:
raise NameError(
"No metadata found in validation {}".format(self.id)
)
@property @property
def get_data(self): def get_data(self):
@ -244,9 +234,7 @@ class Validation:
"""Get the validation list of groups """Get the validation list of groups
:return: A list of groups for the validation :return: A list of groups for the validation
:rtype: `list` or `None` if no metadata has been found :rtype: `list`
:raise: A `NameError` exception if no metadata has been found in the
playbook
:Example: :Example:
@ -255,21 +243,14 @@ class Validation:
>>> print(val.groups) >>> print(val.groups)
['group1', 'group2'] ['group1', 'group2']
""" """
if self.has_metadata_dict: return self.dict['vars']['metadata'].get('groups', [])
return self.dict['vars']['metadata'].get('groups', [])
else:
raise NameError(
"No metadata found in validation {}".format(self.id)
)
@property @property
def categories(self): def categories(self):
"""Get the validation list of categories """Get the validation list of categories
:return: A list of categories for the validation :return: A list of categories for the validation
:rtype: `list` or `None` if no metadata has been found :rtype: `list`
:raise: A `NameError` exception if no metadata has been found in the
playbook
:Example: :Example:
@ -278,21 +259,14 @@ class Validation:
>>> print(val.categories) >>> print(val.categories)
['category1', 'category2'] ['category1', 'category2']
""" """
if self.has_metadata_dict: return self.dict['vars']['metadata'].get('categories', [])
return self.dict['vars']['metadata'].get('categories', [])
else:
raise NameError(
"No metadata found in validation {}".format(self.id)
)
@property @property
def products(self): def products(self):
"""Get the validation list of products """Get the validation list of products
:return: A list of products for the validation :return: A list of products for the validation
:rtype: `list` or `None` if no metadata has been found :rtype: `list`
:raise: A `NameError` exception if no metadata has been found in the
playbook
:Example: :Example:
@ -301,12 +275,7 @@ class Validation:
>>> print(val.products) >>> print(val.products)
['product1', 'product2'] ['product1', 'product2']
""" """
if self.has_metadata_dict: return self.dict['vars']['metadata'].get('products', [])
return self.dict['vars']['metadata'].get('products', [])
else:
raise NameError(
"No metadata found in validation {}".format(self.id)
)
@property @property
def get_id(self): def get_id(self):
@ -342,8 +311,6 @@ class Validation:
the list of 'Categories', the list of `Groups`, the `ID` and the list of 'Categories', the list of `Groups`, the `ID` and
the `Name`. the `Name`.
:rtype: `dict` :rtype: `dict`
:raise: A `NameError` exception if no metadata has been found in the
playbook
:Example: :Example:

View File

@ -12,19 +12,21 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
# #
from validations_libs.logger import getLogger import json
import os import os
import sys import sys
import json
import yaml 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 constants
from validations_libs import utils as v_utils from validations_libs import utils as v_utils
from validations_libs.exceptions import ValidationRunException, ValidationShowException from validations_libs.ansible import Ansible as v_ansible
from validations_libs.cli.common import Spinner
from validations_libs.exceptions import (ValidationRunException,
ValidationShowException)
from validations_libs.group import Group
from validations_libs.logger import getLogger
from validations_libs.validation_logs import ValidationLog, ValidationLogs
LOG = getLogger(__name__ + ".validation_actions") LOG = getLogger(__name__ + ".validation_actions")
@ -43,7 +45,7 @@ class ValidationActions:
""" """
def __init__(self, validation_path=constants.ANSIBLE_VALIDATION_DIR, def __init__(self, base_validation_path=constants.ANSIBLE_VALIDATION_DIR,
groups_path=constants.VALIDATION_GROUPS_INFO, groups_path=constants.VALIDATION_GROUPS_INFO,
log_path=constants.VALIDATIONS_LOG_BASEDIR): log_path=constants.VALIDATIONS_LOG_BASEDIR):
""" """
@ -56,7 +58,7 @@ class ValidationActions:
:type log_path: ``string`` :type log_path: ``string``
""" """
self.log = getLogger(__name__ + ".ValidationActions") self.log = getLogger(__name__ + ".ValidationActions")
self.validation_path = validation_path self.base_validation_path = base_validation_path
self.log_path = log_path self.log_path = log_path
self.groups_path = groups_path self.groups_path = groups_path
@ -121,8 +123,8 @@ class ValidationActions:
""" """
self.log = getLogger(__name__ + ".list_validations") self.log = getLogger(__name__ + ".list_validations")
validations = v_utils.parse_all_validations_on_disk( validations = v_utils.parse_validations(
path=self.validation_path, path=self.base_validation_path,
groups=groups, groups=groups,
categories=categories, categories=categories,
products=products, products=products,
@ -182,7 +184,7 @@ class ValidationActions:
vlog = ValidationLogs(self.log_path) vlog = ValidationLogs(self.log_path)
data = v_utils.get_validations_data( data = v_utils.get_validations_data(
validation, validation,
self.validation_path, self.base_validation_path,
validation_config=validation_config) validation_config=validation_config)
if not data: if not data:
extra_msg = "" extra_msg = ""
@ -190,7 +192,7 @@ class ValidationActions:
extra_msg = " or {}".format(constants.COMMUNITY_LIBRARY_DIR) extra_msg = " or {}".format(constants.COMMUNITY_LIBRARY_DIR)
msg = "Validation {} not found in the path: {}{}".format( msg = "Validation {} not found in the path: {}{}".format(
validation, validation,
self.validation_path, self.base_validation_path,
extra_msg) extra_msg)
raise ValidationShowException(msg) raise ValidationShowException(msg)
@ -319,7 +321,7 @@ class ValidationActions:
extra_vars=None, validations_dir=None, extra_vars=None, validations_dir=None,
extra_env_vars=None, ansible_cfg=None, quiet=True, extra_env_vars=None, ansible_cfg=None, quiet=True,
limit_hosts=None, run_async=False, limit_hosts=None, run_async=False,
base_dir=constants.DEFAULT_VALIDATIONS_BASEDIR, base_dir=constants.DEFAULT_ANSIBLE_BASEDIR,
python_interpreter=None, skip_list=None, python_interpreter=None, skip_list=None,
callback_whitelist=None, callback_whitelist=None,
output_callback='vf_validation_stdout', ssh_user=None, output_callback='vf_validation_stdout', ssh_user=None,
@ -418,48 +420,43 @@ class ValidationActions:
self.log = getLogger(__name__ + ".run_validations") self.log = getLogger(__name__ + ".run_validations")
playbooks = [] playbooks = []
validations_dir = (validations_dir if validations_dir validations_dir = (validations_dir if validations_dir
else self.validation_path) else self.base_validation_path)
if group or category or product: self.log.debug(
self.log.debug( "Getting the validations list by:\n"
"Getting the validations list by:\n" " - ids: {}\n"
" - groups: {}\n" " - groups: {}\n"
" - categories: {}\n" " - categories: {}\n"
" - products: {}".format(group, category, product) " - products: {}".format(validation_name, group, category, product)
) )
validations = v_utils.parse_all_validations_on_disk( validations = v_utils.parse_validations(
path=validations_dir, groups=group, path=validations_dir, groups=group,
categories=category, products=product, categories=category, products=product,
validation_config=validation_config validation_config=validation_config)
)
for val in validations: if validation_name:
playbooks.append("{path}/{id}.yaml".format(**val))
elif validation_name:
self.log.debug( self.log.debug(
"Getting the {} validation.".format( "Getting the {} validation.".format(
validation_name)) validation_name))
playbooks = v_utils.get_validations_playbook( if not validations or len(validation_name) != len(validations):
validations_dir, found_validations = []
validation_name, for val in validations:
validation_config=validation_config) found_validations.append(val.id)
if not playbooks or len(validation_name) != len(playbooks): missing_validations = list(
found_playbooks = [] set(validation_name) - set(found_validations))
for play in playbooks:
found_playbooks.append(
os.path.basename(os.path.splitext(play)[0]))
unknown_validations = list(
set(validation_name) - set(found_playbooks))
msg = ( msg = (
"Following validations were not found in '{}': {}" "Following validations were not found in '{}': {}"
).format(validations_dir, ', '.join(unknown_validations)) ).format(validations_dir, ', '.join(missing_validations))
raise ValidationRunException(msg) raise ValidationRunException(msg)
else: if len(validations) == 0:
raise ValidationRunException("No validations found") raise ValidationRunException("No validations found")
for val in validations:
playbooks.append("{path}".format(path=val.path))
log_path = v_utils.create_log_dir(self.log_path) log_path = v_utils.create_log_dir(self.log_path)
self.log.debug(( self.log.debug((
@ -589,8 +586,8 @@ class ValidationActions:
group_info = [] group_info = []
validations = v_utils.parse_all_validations_on_disk( validations = v_utils.parse_validations(
path=self.validation_path, path=self.base_validation_path,
groups=[group[0] for group in group_definitions], groups=[group[0] for group in group_definitions],
validation_config=validation_config) validation_config=validation_config)
@ -675,22 +672,16 @@ class ValidationActions:
if output_format not in supported_format: if output_format not in supported_format:
raise ValidationShowException("{} output format not supported".format(output_format)) raise ValidationShowException("{} output format not supported".format(output_format))
validation_playbooks = v_utils.get_validations_playbook( validations = v_utils.parse_validations(
path=self.validation_path, path=self.base_validation_path,
validation_id=validations, validation_ids=validations,
groups=groups, groups=groups,
categories=categories, categories=categories,
products=products, products=products,
validation_config=validation_config validation_config=validation_config
) )
params = v_utils.get_validations_parameters( params = v_utils.get_validations_parameters(validations_data=validations)
validations_data=validation_playbooks,
validation_name=validations,
groups=groups,
categories=categories,
products=products
)
if download_file: if download_file:
params_only = {} params_only = {}