Merge "Pass and use the environment in validate_template"

This commit is contained in:
Jenkins 2014-04-08 02:14:20 +00:00 committed by Gerrit Code Review
commit a264a16102
7 changed files with 59 additions and 31 deletions

View File

@ -346,7 +346,8 @@ class StackController(object):
data = InstantiationData(body)
result = self.rpc_client.validate_template(req.context,
data.template())
data.template(),
data.environment())
if 'Error' in result:
raise exc.HTTPBadRequest(result['Error'])

View File

@ -583,13 +583,14 @@ class EngineService(service.Service):
return dict(current_stack.identifier())
@request_context
def validate_template(self, cnxt, template):
def validate_template(self, cnxt, template, params=None):
"""
The validate_template method uses the stack parser to check
the validity of a template.
:param cnxt: RPC context.
:param template: Template of stack you want to create.
:param params: Stack Input Params
"""
logger.info(_('validate_template'))
if template is None:
@ -608,6 +609,8 @@ class EngineService(service.Service):
if not tmpl_resources:
return {'Error': 'At least one Resources member must be defined.'}
env = environment.Environment(params)
for res in tmpl_resources.values():
try:
if not res.get('Type'):
@ -622,7 +625,7 @@ class EngineService(service.Service):
'Resources must contain Resource. '
'Found a [%s] instead' % type_res}
ResourceClass = resource.get_class(res['Type'])
ResourceClass = env.get_class(res['Type'])
if ResourceClass == resources.template_resource.TemplateResource:
# we can't validate a TemplateResource unless we instantiate
# it as we need to download the template and convert the

View File

@ -153,16 +153,18 @@ class EngineClient(heat.openstack.common.rpc.proxy.RpcProxy):
files=files,
args=args))
def validate_template(self, ctxt, template):
def validate_template(self, ctxt, template, params=None):
"""
The validate_template method uses the stack parser to check
the validity of a template.
:param ctxt: RPC context.
:param template: Template of stack you want to create.
:param params: Stack Input Params/Environment
"""
return self.call(ctxt, self.make_msg('validate_template',
template=template))
template=template,
params=params))
def authenticated_to_backend(self, ctxt):
"""

View File

@ -1146,7 +1146,7 @@ class CfnStackControllerTest(HeatTestCase):
rpc.call(dummy_req.context, self.topic,
{'namespace': None,
'method': 'validate_template',
'args': {'template': json_template},
'args': {'template': json_template, 'params': None},
'version': self.api_version}, None).AndReturn(response)
self.m.ReplayAll()

View File

@ -1442,7 +1442,9 @@ class StackControllerTest(ControllerTest, HeatTestCase):
rpc.call(req.context, self.topic,
{'namespace': None,
'method': 'validate_template',
'args': {'template': template},
'args': {'template': template,
'params': {'parameters': {},
'resource_registry': {}}},
'version': self.api_version},
None).AndReturn(engine_response)
self.m.ReplayAll()
@ -1464,7 +1466,9 @@ class StackControllerTest(ControllerTest, HeatTestCase):
rpc.call(req.context, self.topic,
{'namespace': None,
'method': 'validate_template',
'args': {'template': template},
'args': {'template': template,
'params': {'parameters': {},
'resource_registry': {}}},
'version': self.api_version},
None).AndReturn({'Error': 'fubar'})
self.m.ReplayAll()

View File

@ -142,7 +142,8 @@ class EngineRpcAPITestCase(testtools.TestCase):
def test_validate_template(self):
self._test_engine_api('validate_template', 'call',
template={u'Foo': u'bar'})
template={u'Foo': u'bar'},
params={u'Egg': u'spam'})
def test_list_resource_types(self):
self._test_engine_api('list_resource_types', 'call',

View File

@ -804,7 +804,24 @@ class validateTest(HeatTestCase):
self.m.ReplayAll()
engine = service.EngineService('a', 't')
res = dict(engine.validate_template(None, t))
res = dict(engine.validate_template(None, t, {}))
self.assertEqual('test.', res['Description'])
def test_validate_with_environment(self):
test_template = test_template_ref % 'WikiDatabase'
test_template = test_template.replace('AWS::EC2::Instance',
'My::Instance')
t = template_format.parse(test_template)
self.m.StubOutWithMock(instances.Instance, 'nova')
instances.Instance.nova().AndReturn(self.fc)
self.m.StubOutWithMock(service.EngineListener, 'start')
service.EngineListener.start().AndReturn(None)
self.m.ReplayAll()
engine = service.EngineService('a', 't')
params = {'resource_registry': {'My::Instance': 'AWS::EC2::Instance'}}
res = dict(engine.validate_template(None, t, params))
self.assertEqual('test.', res['Description'])
def test_validate_hot_valid(self):
@ -821,7 +838,7 @@ class validateTest(HeatTestCase):
self.m.ReplayAll()
engine = service.EngineService('a', 't')
res = dict(engine.validate_template(None, t))
res = dict(engine.validate_template(None, t, {}))
self.assertEqual('test.', res['Description'])
def test_validate_ref_invalid(self):
@ -832,7 +849,7 @@ class validateTest(HeatTestCase):
self.m.ReplayAll()
engine = service.EngineService('a', 't')
res = dict(engine.validate_template(None, t))
res = dict(engine.validate_template(None, t, {}))
self.assertNotEqual(res['Description'], 'Successfully validated')
def test_validate_findinmap_valid(self):
@ -843,7 +860,7 @@ class validateTest(HeatTestCase):
self.m.ReplayAll()
engine = service.EngineService('a', 't')
res = dict(engine.validate_template(None, t))
res = dict(engine.validate_template(None, t, {}))
self.assertEqual('test.', res['Description'])
def test_validate_findinmap_invalid(self):
@ -854,7 +871,7 @@ class validateTest(HeatTestCase):
self.m.ReplayAll()
engine = service.EngineService('a', 't')
res = dict(engine.validate_template(None, t))
res = dict(engine.validate_template(None, t, {}))
self.assertNotEqual(res['Description'], 'Successfully validated')
def test_validate_parameters(self):
@ -865,7 +882,7 @@ class validateTest(HeatTestCase):
self.m.ReplayAll()
engine = service.EngineService('a', 't')
res = dict(engine.validate_template(None, t))
res = dict(engine.validate_template(None, t, {}))
# Note: the assertion below does not expect a CFN dict of the parameter
# but a dict of the parameters.Schema object.
# For API CFN backward compatibility, formating to CFN is done in the
@ -885,7 +902,7 @@ class validateTest(HeatTestCase):
self.m.ReplayAll()
engine = service.EngineService('a', 't')
res = dict(engine.validate_template(None, t))
res = dict(engine.validate_template(None, t, {}))
parameters = res['Parameters']
expected = {'KeyName': {
@ -903,7 +920,7 @@ class validateTest(HeatTestCase):
self.m.ReplayAll()
engine = service.EngineService('a', 't')
res = dict(engine.validate_template(None, t))
res = dict(engine.validate_template(None, t, {}))
parameters = res['Parameters']
expected = {'KeyName': {
@ -921,7 +938,7 @@ class validateTest(HeatTestCase):
self.m.ReplayAll()
engine = service.EngineService('a', 't')
res = dict(engine.validate_template(None, t))
res = dict(engine.validate_template(None, t, {}))
parameters = res['Parameters']
expected = {'KeyName': {
@ -939,7 +956,7 @@ class validateTest(HeatTestCase):
self.m.ReplayAll()
engine = service.EngineService('a', 't')
res = dict(engine.validate_template(None, t))
res = dict(engine.validate_template(None, t, {}))
self.assertEqual({'Error': 'Unknown Property UnknownProperty'}, res)
def test_invalid_resources(self):
@ -949,7 +966,7 @@ class validateTest(HeatTestCase):
self.m.ReplayAll()
engine = service.EngineService('a', 't')
res = dict(engine.validate_template(None, t))
res = dict(engine.validate_template(None, t, {}))
self.assertEqual({'Error': 'Resources must contain Resource. '
'Found a [string] instead'},
res)
@ -1011,7 +1028,7 @@ class validateTest(HeatTestCase):
self.m.ReplayAll()
engine = service.EngineService('a', 't')
res = dict(engine.validate_template(None, t))
res = dict(engine.validate_template(None, t, {}))
self.assertEqual(
{'Error': 'Property SourceDestCheck not implemented yet'},
res)
@ -1023,7 +1040,7 @@ class validateTest(HeatTestCase):
self.m.ReplayAll()
engine = service.EngineService('a', 't')
res = dict(engine.validate_template(None, t))
res = dict(engine.validate_template(None, t, {}))
self.assertEqual({'Error': 'Invalid DeletionPolicy Destroy'}, res)
def test_snapshot_deletion_policy(self):
@ -1033,7 +1050,7 @@ class validateTest(HeatTestCase):
self.m.ReplayAll()
engine = service.EngineService('a', 't')
res = dict(engine.validate_template(None, t))
res = dict(engine.validate_template(None, t, {}))
self.assertEqual(
{'Error': 'Snapshot DeletionPolicy not supported'}, res)
@ -1046,7 +1063,7 @@ class validateTest(HeatTestCase):
self.m.ReplayAll()
engine = service.EngineService('a', 't')
res = dict(engine.validate_template(None, t))
res = dict(engine.validate_template(None, t, {}))
self.assertEqual({'Description': u'test.', 'Parameters': {}}, res)
def test_validate_template_without_resources(self):
@ -1059,7 +1076,7 @@ class validateTest(HeatTestCase):
self.m.ReplayAll()
engine = service.EngineService('a', 't')
res = dict(engine.validate_template(None, hot_tpl))
res = dict(engine.validate_template(None, hot_tpl, {}))
self.assertEqual({'Error': 'At least one Resources member '
'must be defined.'}, res)
@ -1084,7 +1101,7 @@ class validateTest(HeatTestCase):
self.m.ReplayAll()
engine = service.EngineService('a', 't')
res = dict(engine.validate_template(None, hot_tpl))
res = dict(engine.validate_template(None, hot_tpl, {}))
self.assertEqual({'Error': 'u\'"Type" is not a valid keyword '
'inside a resource definition\''}, res)
@ -1109,7 +1126,7 @@ class validateTest(HeatTestCase):
self.m.ReplayAll()
engine = service.EngineService('a', 't')
res = dict(engine.validate_template(None, hot_tpl))
res = dict(engine.validate_template(None, hot_tpl, {}))
self.assertEqual({'Error': 'u\'"Properties" is not a valid keyword '
'inside a resource definition\''}, res)
@ -1134,7 +1151,7 @@ class validateTest(HeatTestCase):
self.m.ReplayAll()
engine = service.EngineService('a', 't')
res = dict(engine.validate_template(None, hot_tpl))
res = dict(engine.validate_template(None, hot_tpl, {}))
self.assertEqual({'Error': 'u\'"Metadata" is not a valid keyword '
'inside a resource definition\''}, res)
@ -1159,7 +1176,7 @@ class validateTest(HeatTestCase):
self.m.ReplayAll()
engine = service.EngineService('a', 't')
res = dict(engine.validate_template(None, hot_tpl))
res = dict(engine.validate_template(None, hot_tpl, {}))
self.assertEqual({'Error': 'u\'"DependsOn" is not a valid keyword '
'inside a resource definition\''}, res)
@ -1184,7 +1201,7 @@ class validateTest(HeatTestCase):
self.m.ReplayAll()
engine = service.EngineService('a', 't')
res = dict(engine.validate_template(None, hot_tpl))
res = dict(engine.validate_template(None, hot_tpl, {}))
self.assertEqual({'Error': 'u\'"DeletionPolicy" is not a valid '
'keyword inside a resource definition\''},
res)
@ -1210,7 +1227,7 @@ class validateTest(HeatTestCase):
self.m.ReplayAll()
engine = service.EngineService('a', 't')
res = dict(engine.validate_template(None, hot_tpl))
res = dict(engine.validate_template(None, hot_tpl, {}))
self.assertEqual({'Error': 'u\'"UpdatePolicy" is not a valid '
'keyword inside a resource definition\''},
res)