Merge "Move required-api-versions validator to '../validators.py'"
This commit is contained in:
commit
32f481a1f2
|
@ -469,3 +469,52 @@ class RequiredCinderServicesValidator(validation.Validator):
|
||||||
|
|
||||||
msg = ("%s service is not available") % self.services
|
msg = ("%s service is not available") % self.services
|
||||||
return self.fail(msg)
|
return self.fail(msg)
|
||||||
|
|
||||||
|
|
||||||
|
@validation.add("required_platform", platform="openstack", users=True)
|
||||||
|
@validation.configure(name="required_api_versions",
|
||||||
|
namespace="openstack")
|
||||||
|
class RequiredAPIVersionsValidator(validation.Validator):
|
||||||
|
|
||||||
|
def __init__(self, component, versions):
|
||||||
|
"""Validator checks component API versions.
|
||||||
|
|
||||||
|
:param component: name of required component
|
||||||
|
:param versions: version of required component
|
||||||
|
"""
|
||||||
|
super(RequiredAPIVersionsValidator, self).__init__()
|
||||||
|
self.component = component
|
||||||
|
self.versions = versions
|
||||||
|
|
||||||
|
def validate(self, config, credentials, plugin_cls, plugin_cfg):
|
||||||
|
versions = [str(v) for v in self.versions]
|
||||||
|
versions_str = ", ".join(versions)
|
||||||
|
msg = ("Task was designed to be used with %(component)s "
|
||||||
|
"V%(version)s, but V%(found_version)s is "
|
||||||
|
"selected.")
|
||||||
|
for user in credentials["openstack"]["users"]:
|
||||||
|
clients = user["credential"].clients()
|
||||||
|
if self.component == "keystone":
|
||||||
|
if "2.0" not in versions and hasattr(
|
||||||
|
clients.keystone(), "tenants"):
|
||||||
|
return self.fail(msg % {"component": self.component,
|
||||||
|
"version": versions_str,
|
||||||
|
"found_version": "2.0"})
|
||||||
|
if "3" not in versions and hasattr(
|
||||||
|
clients.keystone(), "projects"):
|
||||||
|
return self.fail(msg % {"component": self.component,
|
||||||
|
"version": versions_str,
|
||||||
|
"found_version": "3"})
|
||||||
|
else:
|
||||||
|
used_version = config.get(
|
||||||
|
"context", {}).get(
|
||||||
|
"api_versions", {}).get(
|
||||||
|
self.component, {}).get(
|
||||||
|
"version", getattr(
|
||||||
|
clients, self.component).choose_version())
|
||||||
|
if not used_version:
|
||||||
|
return self.fail("Unable to determine the API version.")
|
||||||
|
if str(used_version) not in versions:
|
||||||
|
return self.fail(msg % {"component": self.component,
|
||||||
|
"version": versions_str,
|
||||||
|
"found_version": used_version})
|
||||||
|
|
|
@ -355,37 +355,6 @@ def required_param_or_context(config, clients, deployment,
|
||||||
return ValidationResult(False, message)
|
return ValidationResult(False, message)
|
||||||
|
|
||||||
|
|
||||||
@validator
|
|
||||||
def required_api_versions(config, clients, deployment, component, versions):
|
|
||||||
"""Validator checks component API versions."""
|
|
||||||
versions = [str(v) for v in versions]
|
|
||||||
versions_str = ", ".join(versions)
|
|
||||||
msg = _("Task was designed to be used with %(component)s "
|
|
||||||
"V%(version)s, but V%(found_version)s is "
|
|
||||||
"selected.")
|
|
||||||
if component == "keystone":
|
|
||||||
if "2.0" not in versions and hasattr(clients.keystone(), "tenants"):
|
|
||||||
return ValidationResult(False, msg % {"component": component,
|
|
||||||
"version": versions_str,
|
|
||||||
"found_version": "2.0"})
|
|
||||||
if "3" not in versions and hasattr(clients.keystone(), "projects"):
|
|
||||||
return ValidationResult(False, msg % {"component": component,
|
|
||||||
"version": versions_str,
|
|
||||||
"found_version": "3"})
|
|
||||||
else:
|
|
||||||
used_version = config.get("context", {}).get("api_versions", {}).get(
|
|
||||||
component, {}).get("version",
|
|
||||||
getattr(clients, component).choose_version())
|
|
||||||
if not used_version:
|
|
||||||
return ValidationResult(
|
|
||||||
False, _("Unable to determine the API version."))
|
|
||||||
if str(used_version) not in versions:
|
|
||||||
return ValidationResult(
|
|
||||||
False, msg % {"component": component,
|
|
||||||
"version": versions_str,
|
|
||||||
"found_version": used_version})
|
|
||||||
|
|
||||||
|
|
||||||
@validator
|
@validator
|
||||||
def volume_type_exists(config, clients, deployment, param_name):
|
def volume_type_exists(config, clients, deployment, param_name):
|
||||||
"""Returns validator for volume types.
|
"""Returns validator for volume types.
|
||||||
|
@ -478,6 +447,7 @@ required_services = deprecated_validator("required_services",
|
||||||
validate_heat_template = deprecated_validator("validate_heat_template",
|
validate_heat_template = deprecated_validator("validate_heat_template",
|
||||||
"validate_heat_template",
|
"validate_heat_template",
|
||||||
"0.10.0")
|
"0.10.0")
|
||||||
|
|
||||||
restricted_parameters = deprecated_validator("restricted_parameters",
|
restricted_parameters = deprecated_validator("restricted_parameters",
|
||||||
"restricted_parameters",
|
"restricted_parameters",
|
||||||
"0.10.0")
|
"0.10.0")
|
||||||
|
@ -485,3 +455,7 @@ restricted_parameters = deprecated_validator("restricted_parameters",
|
||||||
required_cinder_services = deprecated_validator("required_cinder_services",
|
required_cinder_services = deprecated_validator("required_cinder_services",
|
||||||
"required_cinder_services",
|
"required_cinder_services",
|
||||||
"0.10.0")
|
"0.10.0")
|
||||||
|
|
||||||
|
required_api_versions = deprecated_validator("required_api_versions",
|
||||||
|
"required_api_versions",
|
||||||
|
"0.10.0")
|
||||||
|
|
|
@ -53,8 +53,8 @@ class ImageExistsValidatorTestCase(test.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(ImageExistsValidatorTestCase, self).setUp()
|
super(ImageExistsValidatorTestCase, self).setUp()
|
||||||
self.validator = validators.ImageExistsValidator("image", True)
|
self.validator = validators.ImageExistsValidator("image", True)
|
||||||
self.config = config
|
self.config = copy.deepcopy(config)
|
||||||
self.credentials = credentials
|
self.credentials = copy.deepcopy(credentials)
|
||||||
|
|
||||||
@ddt.unpack
|
@ddt.unpack
|
||||||
@ddt.data(
|
@ddt.data(
|
||||||
|
@ -115,7 +115,8 @@ class ImageExistsValidatorTestCase(test.TestCase):
|
||||||
for ex in exs:
|
for ex in exs:
|
||||||
clients.glance().images.get.side_effect = ex
|
clients.glance().images.get.side_effect = ex
|
||||||
|
|
||||||
result = self.validator.validate(config, credentials, None, None)
|
result = self.validator.validate(config, self.credentials,
|
||||||
|
None, None)
|
||||||
|
|
||||||
self.assertEqual("Image 'fake_image' not found", result.msg)
|
self.assertEqual("Image 'fake_image' not found", result.msg)
|
||||||
|
|
||||||
|
@ -187,7 +188,7 @@ class RequiredNeutronExtensionsValidatorTestCase(test.TestCase):
|
||||||
|
|
||||||
clients.neutron().list_extensions.return_value = {
|
clients.neutron().list_extensions.return_value = {
|
||||||
"extensions": [{"alias": "existing_extension"}]}
|
"extensions": [{"alias": "existing_extension"}]}
|
||||||
result = validator.validate({}, self.credentials, {}, None)
|
result = validator.validate({}, self.credentials, None, None)
|
||||||
|
|
||||||
if err_msg:
|
if err_msg:
|
||||||
self.assertTrue(result)
|
self.assertTrue(result)
|
||||||
|
@ -683,3 +684,99 @@ class RequiredCinderServicesValidatorTestCase(test.TestCase):
|
||||||
self.assertTrue(result)
|
self.assertTrue(result)
|
||||||
self.assertEqual("cinder_service service is not available",
|
self.assertEqual("cinder_service service is not available",
|
||||||
result.msg)
|
result.msg)
|
||||||
|
|
||||||
|
|
||||||
|
@ddt.ddt
|
||||||
|
class RequiredAPIVersionsValidatorTestCase(test.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(RequiredAPIVersionsValidatorTestCase, self).setUp()
|
||||||
|
self.config = copy.deepcopy(config)
|
||||||
|
self.credentials = copy.deepcopy(credentials)
|
||||||
|
|
||||||
|
def _get_keystone_v2_mock_client(self):
|
||||||
|
keystone = mock.Mock()
|
||||||
|
del keystone.projects
|
||||||
|
keystone.tenants = mock.Mock()
|
||||||
|
return keystone
|
||||||
|
|
||||||
|
def _get_keystone_v3_mock_client(self):
|
||||||
|
keystone = mock.Mock()
|
||||||
|
del keystone.tenants
|
||||||
|
keystone.projects = mock.Mock()
|
||||||
|
return keystone
|
||||||
|
|
||||||
|
@ddt.unpack
|
||||||
|
@ddt.data(
|
||||||
|
{"versions": [2.0], "err_msg": "Task was designed to be used with"
|
||||||
|
" keystone V2.0, but V3 is selected."},
|
||||||
|
{"versions": [3], "err_msg": "Task was designed to be used with"
|
||||||
|
" keystone V3, but V2.0 is selected."},
|
||||||
|
{"versions": [2.0, 3], "err_msg": None}
|
||||||
|
)
|
||||||
|
def test_validate_keystone(self, versions, err_msg):
|
||||||
|
validator = validators.RequiredAPIVersionsValidator("keystone",
|
||||||
|
versions)
|
||||||
|
|
||||||
|
clients = self.credentials["openstack"]["users"][0][
|
||||||
|
"credential"].clients()
|
||||||
|
|
||||||
|
clients.keystone.return_value = self._get_keystone_v3_mock_client()
|
||||||
|
result = validator.validate(self.config, self.credentials, None, None)
|
||||||
|
|
||||||
|
if result:
|
||||||
|
self.assertEqual(err_msg, result.msg)
|
||||||
|
|
||||||
|
clients.keystone.return_value = self._get_keystone_v2_mock_client()
|
||||||
|
result = validator.validate(self.config, self.credentials, None, None)
|
||||||
|
|
||||||
|
if result:
|
||||||
|
self.assertEqual(err_msg, result.msg)
|
||||||
|
|
||||||
|
@ddt.unpack
|
||||||
|
@ddt.data(
|
||||||
|
{"nova": 2, "versions": [2], "err_msg": None},
|
||||||
|
{"nova": 3, "versions": [2],
|
||||||
|
"err_msg": "Task was designed to be used with nova V2, "
|
||||||
|
"but V3 is selected."},
|
||||||
|
{"nova": None, "versions": [2],
|
||||||
|
"err_msg": "Unable to determine the API version."},
|
||||||
|
{"nova": 2, "versions": [2, 3], "err_msg": None},
|
||||||
|
{"nova": 4, "versions": [2, 3],
|
||||||
|
"err_msg": "Task was designed to be used with nova V2, 3, "
|
||||||
|
"but V4 is selected."}
|
||||||
|
)
|
||||||
|
def test_validate_nova(self, nova, versions, err_msg):
|
||||||
|
validator = validators.RequiredAPIVersionsValidator("nova",
|
||||||
|
versions)
|
||||||
|
|
||||||
|
clients = self.credentials["openstack"]["users"][0][
|
||||||
|
"credential"].clients()
|
||||||
|
|
||||||
|
clients.nova.choose_version.return_value = nova
|
||||||
|
|
||||||
|
result = validator.validate(self.config, self.credentials, None, None)
|
||||||
|
|
||||||
|
if err_msg:
|
||||||
|
self.assertIsNotNone(result)
|
||||||
|
self.assertEqual(err_msg, result.msg)
|
||||||
|
else:
|
||||||
|
self.assertIsNone(result)
|
||||||
|
|
||||||
|
@ddt.unpack
|
||||||
|
@ddt.data({"version": 2, "err_msg": None},
|
||||||
|
{"version": 3, "err_msg": "Task was designed to be used with "
|
||||||
|
"nova V3, but V2 is selected."})
|
||||||
|
def test_validate_context(self, version, err_msg):
|
||||||
|
validator = validators.RequiredAPIVersionsValidator("nova",
|
||||||
|
[version])
|
||||||
|
|
||||||
|
config = {"context": {"api_versions": {"nova": {"version": 2}}}}
|
||||||
|
|
||||||
|
result = validator.validate(config, self.credentials, None, None)
|
||||||
|
|
||||||
|
if err_msg:
|
||||||
|
self.assertIsNotNone(result)
|
||||||
|
self.assertEqual(err_msg, result.msg)
|
||||||
|
else:
|
||||||
|
self.assertIsNone(result)
|
||||||
|
|
|
@ -571,83 +571,6 @@ class ValidatorsTestCase(test.TestCase):
|
||||||
result = validator(context, clients, mock.MagicMock())
|
result = validator(context, clients, mock.MagicMock())
|
||||||
self.assertFalse(result.is_valid, result.msg)
|
self.assertFalse(result.is_valid, result.msg)
|
||||||
|
|
||||||
def _get_keystone_v2_mock_client(self):
|
|
||||||
keystone = mock.Mock()
|
|
||||||
del keystone.projects
|
|
||||||
keystone.tenants = mock.Mock()
|
|
||||||
return keystone
|
|
||||||
|
|
||||||
def _get_keystone_v3_mock_client(self):
|
|
||||||
keystone = mock.Mock()
|
|
||||||
del keystone.tenants
|
|
||||||
keystone.projects = mock.Mock()
|
|
||||||
return keystone
|
|
||||||
|
|
||||||
def test_required_api_versions_keystonev2(self):
|
|
||||||
validator = self._unwrap_validator(
|
|
||||||
validation.required_api_versions, component="keystone",
|
|
||||||
versions=[2.0])
|
|
||||||
clients = mock.MagicMock()
|
|
||||||
clients.keystone.return_value = self._get_keystone_v3_mock_client()
|
|
||||||
self.assertFalse(validator({}, clients, None).is_valid)
|
|
||||||
|
|
||||||
clients.keystone.return_value = self._get_keystone_v2_mock_client()
|
|
||||||
self.assertTrue(validator({}, clients, None).is_valid)
|
|
||||||
|
|
||||||
def test_required_api_versions_keystonev3(self):
|
|
||||||
validator = self._unwrap_validator(
|
|
||||||
validation.required_api_versions, component="keystone",
|
|
||||||
versions=[3])
|
|
||||||
clients = mock.MagicMock()
|
|
||||||
|
|
||||||
clients.keystone.return_value = self._get_keystone_v2_mock_client()
|
|
||||||
self.assertFalse(validator({}, clients, None).is_valid)
|
|
||||||
|
|
||||||
clients.keystone.return_value = self._get_keystone_v3_mock_client()
|
|
||||||
self.assertTrue(validator({}, clients, None).is_valid)
|
|
||||||
|
|
||||||
def test_required_api_versions_keystone_all_versions(self):
|
|
||||||
validator = self._unwrap_validator(
|
|
||||||
validation.required_api_versions, component="keystone",
|
|
||||||
versions=[2.0, 3])
|
|
||||||
clients = mock.MagicMock()
|
|
||||||
|
|
||||||
clients.keystone.return_value = self._get_keystone_v3_mock_client()
|
|
||||||
self.assertTrue(validator({}, clients, None).is_valid)
|
|
||||||
|
|
||||||
clients.keystone.return_value = self._get_keystone_v2_mock_client()
|
|
||||||
self.assertTrue(validator({}, clients, None).is_valid)
|
|
||||||
|
|
||||||
@ddt.data({"nova_version": 2, "required_versions": [2], "valid": True},
|
|
||||||
{"nova_version": 3, "required_versions": [2], "valid": False},
|
|
||||||
{"nova_version": None, "required_versions": [2], "valid": False},
|
|
||||||
{"nova_version": 2, "required_versions": [2, 3], "valid": True},
|
|
||||||
{"nova_version": 4, "required_versions": [2, 3], "valid": False})
|
|
||||||
@ddt.unpack
|
|
||||||
def test_required_api_versions_choose_version(self, nova_version=None,
|
|
||||||
required_versions=(2,),
|
|
||||||
valid=False):
|
|
||||||
validator = self._unwrap_validator(
|
|
||||||
validation.required_api_versions, component="nova",
|
|
||||||
versions=required_versions)
|
|
||||||
clients = mock.MagicMock()
|
|
||||||
clients.nova.choose_version.return_value = nova_version
|
|
||||||
self.assertEqual(validator({}, clients, None).is_valid,
|
|
||||||
valid)
|
|
||||||
|
|
||||||
@ddt.data({"required_version": 2, "valid": True},
|
|
||||||
{"required_version": 3, "valid": False})
|
|
||||||
@ddt.unpack
|
|
||||||
def test_required_api_versions_context(self, required_version=None,
|
|
||||||
valid=False):
|
|
||||||
validator = self._unwrap_validator(
|
|
||||||
validation.required_api_versions, component="nova",
|
|
||||||
versions=[required_version])
|
|
||||||
clients = mock.MagicMock()
|
|
||||||
config = {"context": {"api_versions": {"nova": {"version": 2}}}}
|
|
||||||
self.assertEqual(validator(config, clients, None).is_valid,
|
|
||||||
valid)
|
|
||||||
|
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
"rally.common.yamlutils.safe_load",
|
"rally.common.yamlutils.safe_load",
|
||||||
return_value={
|
return_value={
|
||||||
|
|
Loading…
Reference in New Issue