diff --git a/heat/common/exception.py b/heat/common/exception.py index 49dcd5cda..4f0c08153 100644 --- a/heat/common/exception.py +++ b/heat/common/exception.py @@ -279,3 +279,11 @@ class ResourceFailure(OpenstackException): class NotSupported(OpenstackException): message = _("%(feature)s is not supported.") + + +class ResourcePropertyConflict(OpenstackException): + message = _('Cannot define the following properties at the same time: %s.') + + def __init__(self, *args): + self.message = self.message % ", ".join(args) + super(ResourcePropertyConflict, self).__init__() diff --git a/heat/engine/resources/instance.py b/heat/engine/resources/instance.py index 0ef36e69e..4a790da6d 100644 --- a/heat/engine/resources/instance.py +++ b/heat/engine/resources/instance.py @@ -480,26 +480,18 @@ class Instance(resource.Resource): if key_name: keypairs = self.nova().keypairs.list() if not any(k.name == key_name for k in keypairs): - return {'Error': - 'Provided KeyName is not registered with nova'} + raise exception.UserKeyPairMissing(key_name=key_name) # check validity of security groups vs. network interfaces security_groups = self._get_security_groups() if security_groups and self.properties.get('NetworkInterfaces'): - return {'Error': - 'Cannot define both SecurityGroups/SecurityGroupIds and ' - 'NetworkInterfaces properties.'} + raise exception.ResourcePropertyConflict( + 'SecurityGroups/SecurityGroupIds', + 'NetworkInterfaces') # make sure the image exists. image_identifier = self.properties['ImageId'] - try: - self._get_image_id(image_identifier) - except exception.ImageNotFound: - return {'Error': 'Image %s was not found in glance' % - image_identifier} - except exception.NoUniqueImageFound: - return {'Error': 'Multiple images were found with name %s' % - image_identifier} + self._get_image_id(image_identifier) return diff --git a/heat/tests/test_validate.py b/heat/tests/test_validate.py index c815d043d..69fb7561a 100644 --- a/heat/tests/test_validate.py +++ b/heat/tests/test_validate.py @@ -397,6 +397,34 @@ test_unregistered_key = ''' } ''' +test_template_image = ''' +{ + "AWSTemplateFormatVersion" : "2010-09-09", + "Description" : "test.", + "Parameters" : { + + "KeyName" : { +''' + \ + '"Description" : "Name of an existing EC2' + \ + 'KeyPair to enable SSH access to the instances",' + \ + ''' + "Type" : "String" + } + }, + + "Resources" : { + "Instance": { + "Type": "AWS::EC2::Instance", + "Properties": { + "ImageId": "image_name", + "InstanceType": "m1.large", + "KeyName": { "Ref" : "KeyName" } + } + } + } + } + ''' + test_template_invalid_secgroups = ''' { "AWSTemplateFormatVersion" : "2010-09-09", @@ -700,7 +728,55 @@ class validateTest(HeatTestCase): self.m.ReplayAll() resource = stack.resources['Instance'] - self.assertNotEqual(resource.validate(), None) + self.assertRaises(exception.UserKeyPairMissing, resource.validate) + + def test_unregistered_image(self): + t = template_format.parse(test_template_image) + template = parser.Template(t) + + stack = parser.Stack(self.ctx, 'test_stack', template, + environment.Environment({'KeyName': 'test'})) + + self.m.StubOutWithMock(instances.Instance, 'nova') + instances.Instance.nova().AndReturn(self.fc) + instances.Instance.nova().AndReturn(self.fc) + self.m.ReplayAll() + + resource = stack.resources['Instance'] + self.assertRaises(exception.ImageNotFound, resource.validate) + + self.m.VerifyAll() + + def test_duplicated_image(self): + t = template_format.parse(test_template_image) + template = parser.Template(t) + + stack = parser.Stack(self.ctx, 'test_stack', template, + environment.Environment({'KeyName': 'test'})) + + class image_type(object): + + def __init__(self, id, name): + self.id = id + self.name = name + + image_list = [image_type(id='768b5464-3df5-4abf-be33-63b60f8b99d0', + name='image_name'), + image_type(id='a57384f5-690f-48e1-bf46-c4291e6c887e', + name='image_name')] + + self.m.StubOutWithMock(self.fc.images, 'list') + self.fc.images.list().AndReturn(image_list) + + self.m.StubOutWithMock(instances.Instance, 'nova') + instances.Instance.nova().AndReturn(self.fc) + instances.Instance.nova().AndReturn(self.fc) + self.m.ReplayAll() + + resource = stack.resources['Instance'] + self.assertRaises(exception.NoUniqueImageFound, resource.validate) + + self.m.VerifyAll() def test_invalid_security_groups_with_nics(self): t = template_format.parse(test_template_invalid_secgroups) @@ -713,7 +789,8 @@ class validateTest(HeatTestCase): self.m.ReplayAll() resource = stack.resources['Instance'] - self.assertNotEqual(resource.validate(), None) + self.assertRaises(exception.ResourcePropertyConflict, + resource.validate) def test_invalid_security_group_ids_with_nics(self): t = template_format.parse(test_template_invalid_secgroupids) @@ -726,7 +803,8 @@ class validateTest(HeatTestCase): self.m.ReplayAll() resource = stack.resources['Instance'] - self.assertNotEqual(resource.validate(), None) + self.assertRaises(exception.ResourcePropertyConflict, + resource.validate) def test_client_exception_from_nova_client(self): t = template_format.parse(test_template_nova_client_exception)