Merge "Adding validation algorithm for get attr functions"

This commit is contained in:
Jenkins 2014-08-18 10:01:19 +00:00 committed by Gerrit Code Review
commit 1dfb9c880e
3 changed files with 122 additions and 0 deletions

View File

@ -20,6 +20,7 @@ import six
from heat.api.aws import utils as aws_utils
from heat.common import exception
from heat.engine import function
from heat.engine import resource
class FindInMap(function.Function):
@ -173,6 +174,15 @@ class GetAtt(function.Function):
return itertools.chain(super(GetAtt, self).dependencies(path),
[self._resource(path)])
def validate(self):
super(GetAtt, self).validate()
res = self._resource()
attr = function.resolve(self._attribute)
if (type(res).FnGetAtt == resource.Resource.FnGetAtt and
attr not in res.attributes_schema.keys()):
raise exception.InvalidTemplateAttribute(
resource=self._resource_name, key=attr)
def result(self):
attribute = function.resolve(self._attribute)

View File

@ -13,9 +13,18 @@
import copy
import six
import uuid
from heat.common import exception
from heat.engine.cfn import functions
from heat.engine import environment
from heat.engine import function
from heat.engine import parser
from heat.engine import resource
from heat.engine import rsrc_defn
from heat.tests.common import HeatTestCase
from heat.tests import generic_resource as generic_rsrc
from heat.tests import utils
class TestFunction(function.Function):
@ -143,3 +152,66 @@ class DependenciesTest(HeatTestCase):
self.assertIn('foo', deps)
self.assertIn('bar', deps)
self.assertEqual(2, len(deps))
class ValidateGetAttTest(HeatTestCase):
def setUp(self):
super(ValidateGetAttTest, self).setUp()
resource._register_class('GenericResourceType',
generic_rsrc.GenericResource)
env = environment.Environment()
env.load({u'resource_registry':
{u'OS::Test::GenericResource': u'GenericResourceType'}})
class FakeResource(generic_rsrc.GenericResource):
def FnGetAtt(self, name):
pass
resource._register_class('OverwrittenFnGetAttType', FakeResource)
env.load({u'resource_registry':
{u'OS::Test::FakeResource': u'OverwrittenFnGetAttType'}})
self.stack = parser.Stack(
utils.dummy_context(), 'test_stack',
parser.Template({"HeatTemplateFormatVersion": "2012-12-12"}),
env=env, stack_id=str(uuid.uuid4()))
res_defn = rsrc_defn.ResourceDefinition('test_rsrc',
'OS::Test::GenericResource')
self.rsrc = resource.Resource('test_rsrc', res_defn, self.stack)
self.stack.add_resource(self.rsrc)
def test_resource_is_appear_in_stack(self):
func = functions.GetAtt(self.stack, 'Fn::GetAtt',
[self.rsrc.name, 'Foo'])
self.assertIsNone(func.validate())
def test_resource_is_not_appear_in_stack(self):
self.stack.remove_resource(self.rsrc.name)
func = functions.GetAtt(self.stack, 'Fn::GetAtt',
[self.rsrc.name, 'Foo'])
ex = self.assertRaises(exception.InvalidTemplateReference,
func.validate)
self.assertEqual('The specified reference "test_rsrc" (in unknown) '
'is incorrect.', str(ex))
def test_resource_no_attribute_with_default_fn_get_att(self):
func = functions.GetAtt(self.stack, 'Fn::GetAtt',
[self.rsrc.name, 'Bar'])
ex = self.assertRaises(exception.InvalidTemplateAttribute,
func.validate)
self.assertEqual('The Referenced Attribute (test_rsrc Bar) '
'is incorrect.', str(ex))
def test_resource_no_attribute_with_overwritten_fn_get_att(self):
res_defn = rsrc_defn.ResourceDefinition('test_rsrc',
'OS::Test::FakeResource')
self.rsrc = resource.Resource('test_rsrc', res_defn, self.stack)
self.stack.add_resource(self.rsrc)
self.rsrc.attributes_schema = {}
func = functions.GetAtt(self.stack, 'Fn::GetAtt',
[self.rsrc.name, 'Foo'])
self.assertIsNone(func.validate())

View File

@ -3692,3 +3692,43 @@ class StackTest(HeatTestCase):
fake_snapshot = collections.namedtuple('Snapshot', ('data',))(data)
self.stack.delete_snapshot(fake_snapshot)
self.assertEqual([data['resources']['AResource']], snapshots)
def test_incorrect_outputs_cfn_get_attr(self):
tmpl = {'HeatTemplateFormatVersion': '2012-12-12',
'Resources': {
'AResource': {'Type': 'ResourceWithPropsType',
'Properties': {'Foo': 'abc'}}},
'Outputs': {
'Resource_attr': {
'Value': {
'Fn::GetAtt': ['AResource', 'Bar']}}}}
self.stack = parser.Stack(self.ctx, 'stack_with_correct_outputs',
template.Template(tmpl))
ex = self.assertRaises(exception.StackValidationFailed,
self.stack.validate)
self.assertEqual('Output validation error: The Referenced Attribute '
'(AResource Bar) is incorrect.',
str(ex))
def test_incorrect_outputs_hot_get_attr(self):
tmpl = {'heat_template_version': '2013-05-23',
'resources': {
'AResource': {'type': 'ResourceWithPropsType',
'properties': {'Foo': 'abc'}}},
'outputs': {
'resource_attr': {
'value': {
'get_attr': ['AResource', 'Bar']}}}}
self.stack = parser.Stack(self.ctx, 'stack_with_correct_outputs',
template.Template(tmpl))
ex = self.assertRaises(exception.StackValidationFailed,
self.stack.validate)
self.assertEqual('Output validation error: The Referenced Attribute '
'(AResource Bar) is incorrect.',
str(ex))