Merge "Add function to perform profile validation"
This commit is contained in:
commit
cfb3def6d1
@ -334,7 +334,7 @@ class EngineService(service.Service):
|
||||
return [p.to_dict() for p in profiles]
|
||||
|
||||
def _validate_profile(self, context, spec, name=None,
|
||||
metadata=None):
|
||||
metadata=None, validate_props=False):
|
||||
"""Validate a profile.
|
||||
|
||||
:param context: An instance of the request context.
|
||||
@ -342,6 +342,8 @@ class EngineService(service.Service):
|
||||
:param spec: A dictionary containing the spec for the profile.
|
||||
:param metadata: A dictionary containing optional key-value pairs to
|
||||
be associated with the profile.
|
||||
:param validate_props: Whether to validate if provide a valid Value
|
||||
to property.
|
||||
:return: Validated profile object.
|
||||
"""
|
||||
type_name, version = schema.get_spec_version(spec)
|
||||
@ -363,7 +365,7 @@ class EngineService(service.Service):
|
||||
name = 'validated_profile'
|
||||
profile = plugin(name, spec, **kwargs)
|
||||
try:
|
||||
profile.validate()
|
||||
profile.validate(validate_props=validate_props)
|
||||
except exception.InvalidSpec as ex:
|
||||
msg = six.text_type(ex)
|
||||
LOG.error(_LE("Failed in validating profile: %s"), msg)
|
||||
@ -402,6 +404,19 @@ class EngineService(service.Service):
|
||||
|
||||
return profile.to_dict()
|
||||
|
||||
@request_context
|
||||
def profile_validate(self, context, spec):
|
||||
"""Validate a profile with the given properties.
|
||||
|
||||
:param context: An instance of the request context.
|
||||
:param spec: A dictionary containing the spec for the profile.
|
||||
:return: A dictionary containing the details of the profile object
|
||||
validated.
|
||||
"""
|
||||
profile = self._validate_profile(context, spec, validate_props=True)
|
||||
|
||||
return profile.to_dict()
|
||||
|
||||
@request_context
|
||||
def profile_get(self, context, identity):
|
||||
"""Retrieve the details about a profile.
|
||||
|
@ -231,7 +231,7 @@ class Profile(object):
|
||||
profile = cls.load(ctx, profile_id=obj.profile_id)
|
||||
return profile.do_recover(obj, **options)
|
||||
|
||||
def validate(self):
|
||||
def validate(self, validate_props=False):
|
||||
'''Validate the schema and the data provided.'''
|
||||
# general validation
|
||||
self.spec_data.validate()
|
||||
@ -239,6 +239,9 @@ class Profile(object):
|
||||
|
||||
# TODO(Anyone): need to check the contents in self.CONTEXT
|
||||
|
||||
if validate_props:
|
||||
self.do_validate(obj=self.context)
|
||||
|
||||
@classmethod
|
||||
def get_schema(cls):
|
||||
return dict((name, dict(schema))
|
||||
@ -336,6 +339,11 @@ class Profile(object):
|
||||
|
||||
return res
|
||||
|
||||
def do_validate(self, obj):
|
||||
"""For subclass to override."""
|
||||
LOG.warning(_LW("Validate operation not supported."))
|
||||
return True
|
||||
|
||||
def to_dict(self):
|
||||
pb_dict = {
|
||||
'id': self.id,
|
||||
|
@ -283,6 +283,47 @@ class ProfileTest(base.SenlinTestCase):
|
||||
self.assertEqual('BOOM',
|
||||
six.text_type(ex.exc_info[1]))
|
||||
|
||||
def test_profile_validate_pass(self):
|
||||
self._setup_fakes()
|
||||
|
||||
expected_resp = {
|
||||
'created_at': None,
|
||||
'domain': '',
|
||||
'id': None,
|
||||
'metadata': None,
|
||||
'name': 'validated_profile',
|
||||
'project': 'profile_test_project',
|
||||
'type': 'TestProfile-1.0',
|
||||
'updated_at': None,
|
||||
'user': 'test_user_id',
|
||||
'spec': {
|
||||
'type': 'TestProfile',
|
||||
'version': '1.0',
|
||||
'properties': {
|
||||
'INT': 1,
|
||||
'STR': 'str',
|
||||
'LIST': ['v1', 'v2'],
|
||||
'MAP': {'KEY1': 1, 'KEY2': 'v2'},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resp = self.eng.profile_validate(self.ctx, self.spec)
|
||||
self.assertEqual(expected_resp, resp)
|
||||
|
||||
def test_profile_validate_failed(self):
|
||||
self._setup_fakes()
|
||||
|
||||
mock_do_validate = self.patchobject(fakes.TestProfile, 'do_validate')
|
||||
mock_do_validate.side_effect = exc.InvalidSpec(message='BOOM')
|
||||
|
||||
ex = self.assertRaises(rpc.ExpectedException,
|
||||
self.eng.profile_validate,
|
||||
self.ctx, self.spec)
|
||||
self.assertEqual(exc.SpecValidationFailed, ex.exc_info[0])
|
||||
self.assertEqual('BOOM',
|
||||
six.text_type(ex.exc_info[1]))
|
||||
|
||||
@mock.patch.object(pb.Profile, 'load')
|
||||
@mock.patch.object(service.EngineService, 'profile_find')
|
||||
def test_profile_get(self, mock_find, mock_load):
|
||||
|
@ -488,16 +488,31 @@ class TestProfileBase(base.SenlinTestCase):
|
||||
res_obj = profile.do_leave.return_value
|
||||
self.assertEqual(res_obj, res)
|
||||
|
||||
def test_validate(self):
|
||||
def test_validate_without_properties(self):
|
||||
profile = self._create_profile('test_profile')
|
||||
|
||||
profile.spec_data = mock.Mock()
|
||||
profile.properties = mock.Mock()
|
||||
profile.do_validate = mock.Mock()
|
||||
|
||||
profile.validate()
|
||||
|
||||
profile.spec_data.validate.assert_called_once_with()
|
||||
profile.properties.validate.assert_called_once_with()
|
||||
profile.do_validate.assert_not_called()
|
||||
|
||||
def test_validate_with_properties(self):
|
||||
profile = self._create_profile('test_profile')
|
||||
|
||||
profile.spec_data = mock.Mock()
|
||||
profile.properties = mock.Mock()
|
||||
profile.do_validate = mock.Mock()
|
||||
|
||||
profile.validate(validate_props=True)
|
||||
|
||||
profile.spec_data.validate.assert_called_once_with()
|
||||
profile.properties.validate.assert_called_once_with()
|
||||
profile.do_validate.assert_called_once_with(obj=profile.context)
|
||||
|
||||
@mock.patch.object(senlin_ctx, 'get_service_context')
|
||||
def test__init_context(self, mock_get):
|
||||
@ -609,6 +624,7 @@ class TestProfileBase(base.SenlinTestCase):
|
||||
self.assertEqual(True, profile.do_join(mock.Mock(), mock.Mock()))
|
||||
self.assertEqual(True, profile.do_leave(mock.Mock()))
|
||||
self.assertEqual(True, profile.do_rebuild(mock.Mock()))
|
||||
self.assertEqual(True, profile.do_validate(mock.Mock()))
|
||||
|
||||
def test_do_recover_default(self):
|
||||
profile = self._create_profile('test-profile')
|
||||
|
Loading…
Reference in New Issue
Block a user