summaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
authorJason Dunsmore <jasondunsmore@gmail.com>2016-01-29 11:43:19 -0600
committerJason Dunsmore <jasondunsmore@gmail.com>2016-02-15 11:43:56 -0600
commit268e6a10d6c3d718406bcebf5f86936c8961d853 (patch)
treee4af9efff7044f6260d8374a2957c1cd220a6688 /contrib
parent681df8eb00f77d08619beb2d82c5bbdbe74870c1 (diff)
downloadheat-268e6a10d6c3d718406bcebf5f86936c8961d853.tar.gz
Add support for launch_stack launchConfiguration type
Rackspace AutoScale Groups now support a "launch_stack" launchConfiguration type. This adds support to the Rackspace::AutoScale::Group resource. Change-Id: I20d2d9d4f317d726ccbb21275984f096ba300767
Diffstat (limited to 'contrib')
-rw-r--r--contrib/rackspace/rackspace/resources/auto_scale.py135
-rw-r--r--contrib/rackspace/rackspace/tests/test_auto_scale.py447
2 files changed, 567 insertions, 15 deletions
diff --git a/contrib/rackspace/rackspace/resources/auto_scale.py b/contrib/rackspace/rackspace/resources/auto_scale.py
index 3230f01be..86cafed14 100644
--- a/contrib/rackspace/rackspace/resources/auto_scale.py
+++ b/contrib/rackspace/rackspace/resources/auto_scale.py
@@ -14,6 +14,7 @@
"""Resources for Rackspace Auto Scale."""
import copy
+import six
from heat.common import exception
from heat.common.i18n import _
@@ -22,6 +23,7 @@ from heat.engine import constraints
from heat.engine import properties
from heat.engine import resource
from heat.engine import support
+from heat.engine import template as templatem
try:
from pyrax.exceptions import Forbidden
@@ -74,9 +76,11 @@ class Group(resource.Resource):
_LAUNCH_CONFIG_ARGS_KEYS = (
LAUNCH_CONFIG_ARGS_LOAD_BALANCERS,
LAUNCH_CONFIG_ARGS_SERVER,
+ LAUNCH_CONFIG_ARGS_STACK,
) = (
'loadBalancers',
'server',
+ 'stack',
)
_LAUNCH_CONFIG_ARGS_LOAD_BALANCER_KEYS = (
@@ -115,6 +119,24 @@ class Group(resource.Resource):
'uuid',
)
+ _LAUNCH_CONFIG_ARGS_STACK_KEYS = (
+ LAUNCH_CONFIG_ARGS_STACK_TEMPLATE,
+ LAUNCH_CONFIG_ARGS_STACK_TEMPLATE_URL,
+ LAUNCH_CONFIG_ARGS_STACK_DISABLE_ROLLBACK,
+ LAUNCH_CONFIG_ARGS_STACK_ENVIRONMENT,
+ LAUNCH_CONFIG_ARGS_STACK_FILES,
+ LAUNCH_CONFIG_ARGS_STACK_PARAMETERS,
+ LAUNCH_CONFIG_ARGS_STACK_TIMEOUT_MINS
+ ) = (
+ 'template',
+ 'template_url',
+ 'disable_rollback',
+ 'environment',
+ 'files',
+ 'parameters',
+ 'timeout_mins'
+ )
+
_launch_configuration_args_schema = {
LAUNCH_CONFIG_ARGS_LOAD_BALANCERS: properties.Schema(
properties.Schema.LIST,
@@ -141,6 +163,7 @@ class Group(resource.Resource):
properties.Schema.MAP,
_('Server creation arguments, as accepted by the Cloud Servers '
'server creation API.'),
+ required=False,
schema={
LAUNCH_CONFIG_ARGS_SERVER_NAME: properties.Schema(
properties.Schema.STRING,
@@ -211,8 +234,49 @@ class Group(resource.Resource):
'key-based authentication to the server.')
),
},
- required=True
),
+ LAUNCH_CONFIG_ARGS_STACK: properties.Schema(
+ properties.Schema.MAP,
+ _('The attributes that Auto Scale uses to create a new stack. The '
+ 'attributes that you specify for the stack entity apply to all '
+ 'new stacks in the scaling group. Note the stack arguments are '
+ 'directly passed to Heat when creating a stack.'),
+ schema={
+ LAUNCH_CONFIG_ARGS_STACK_TEMPLATE: properties.Schema(
+ properties.Schema.MAP,
+ _('The template that describes the stack. Either the '
+ 'template or template_url property must be specified.'),
+ ),
+ LAUNCH_CONFIG_ARGS_STACK_TEMPLATE_URL: properties.Schema(
+ properties.Schema.STRING,
+ _('A URI to a template. Either the template or '
+ 'template_url property must be specified.')
+ ),
+ LAUNCH_CONFIG_ARGS_STACK_DISABLE_ROLLBACK: properties.Schema(
+ properties.Schema.BOOLEAN,
+ _('Keep the resources that have been created if the stack '
+ 'fails to create. Defaults to True.'),
+ default=True
+ ),
+ LAUNCH_CONFIG_ARGS_STACK_ENVIRONMENT: properties.Schema(
+ properties.Schema.MAP,
+ _('The environment for the stack.'),
+ ),
+ LAUNCH_CONFIG_ARGS_STACK_FILES: properties.Schema(
+ properties.Schema.MAP,
+ _('The contents of files that the template references.')
+ ),
+ LAUNCH_CONFIG_ARGS_STACK_PARAMETERS: properties.Schema(
+ properties.Schema.MAP,
+ _('Key/value pairs of the parameters and their values to '
+ 'pass to the parameters in the template.')
+ ),
+ LAUNCH_CONFIG_ARGS_STACK_TIMEOUT_MINS: properties.Schema(
+ properties.Schema.INTEGER,
+ _('The stack creation timeout in minutes.')
+ )
+ }
+ )
}
properties_schema = {
@@ -256,17 +320,18 @@ class Group(resource.Resource):
schema={
LAUNCH_CONFIG_ARGS: properties.Schema(
properties.Schema.MAP,
- _('Type-specific server launching arguments.'),
+ _('Type-specific launch arguments.'),
schema=_launch_configuration_args_schema,
required=True
),
LAUNCH_CONFIG_TYPE: properties.Schema(
properties.Schema.STRING,
- _('Launch configuration method. Only launch_server '
- 'is currently supported.'),
+ _('Launch configuration method. Only launch_server and '
+ 'launch_stack are currently supported.'),
required=True,
constraints=[
- constraints.AllowedValues(['launch_server']),
+ constraints.AllowedValues(['launch_server',
+ 'launch_stack']),
]
),
},
@@ -287,8 +352,7 @@ class Group(resource.Resource):
max_entities=groupconf[self.GROUP_CONFIGURATION_MAX_ENTITIES],
metadata=groupconf.get(self.GROUP_CONFIGURATION_METADATA, None))
- def _get_launch_config_args(self, launchconf):
- """Get the launchConfiguration-related pyrax arguments."""
+ def _get_launch_config_server_args(self, launchconf):
lcargs = launchconf[self.LAUNCH_CONFIG_ARGS]
server_args = lcargs[self.LAUNCH_CONFIG_ARGS_SERVER]
lb_args = lcargs.get(self.LAUNCH_CONFIG_ARGS_LOAD_BALANCERS)
@@ -330,6 +394,30 @@ class Group(resource.Resource):
key_name=server_args.get(self.LAUNCH_CONFIG_ARGS_SERVER_KEY_NAME),
)
+ def _get_launch_config_stack_args(self, launchconf):
+ lcargs = launchconf[self.LAUNCH_CONFIG_ARGS]
+ stack_args = lcargs[self.LAUNCH_CONFIG_ARGS_STACK]
+ return dict(
+ launch_config_type=launchconf[self.LAUNCH_CONFIG_TYPE],
+ template=stack_args[self.LAUNCH_CONFIG_ARGS_STACK_TEMPLATE],
+ template_url=stack_args[
+ self.LAUNCH_CONFIG_ARGS_STACK_TEMPLATE_URL],
+ disable_rollback=stack_args[
+ self.LAUNCH_CONFIG_ARGS_STACK_DISABLE_ROLLBACK],
+ environment=stack_args[self.LAUNCH_CONFIG_ARGS_STACK_ENVIRONMENT],
+ files=stack_args[self.LAUNCH_CONFIG_ARGS_STACK_FILES],
+ parameters=stack_args[self.LAUNCH_CONFIG_ARGS_STACK_PARAMETERS],
+ timeout_mins=stack_args[self.LAUNCH_CONFIG_ARGS_STACK_TIMEOUT_MINS]
+ )
+
+ def _get_launch_config_args(self, launchconf):
+ """Get the launchConfiguration-related pyrax arguments."""
+ if launchconf[self.LAUNCH_CONFIG_ARGS].get(
+ self.LAUNCH_CONFIG_ARGS_SERVER):
+ return self._get_launch_config_server_args(launchconf)
+ else:
+ return self._get_launch_config_stack_args(launchconf)
+
def _get_create_args(self):
"""Get pyrax-style arguments for creating a scaling group."""
args = self._get_group_config_args(
@@ -406,6 +494,19 @@ class Group(resource.Resource):
super(Group, self).validate()
launchconf = self.properties[self.LAUNCH_CONFIGURATION]
lcargs = launchconf[self.LAUNCH_CONFIG_ARGS]
+
+ server_args = lcargs.get(self.LAUNCH_CONFIG_ARGS_SERVER)
+ st_args = lcargs.get(self.LAUNCH_CONFIG_ARGS_STACK)
+
+ # launch_server and launch_stack are required and mutually exclusive.
+ if ((not server_args and not st_args) or
+ (server_args and st_args)):
+ msg = (_('Must provide one of %(server)s or %(stack)s in %(conf)s')
+ % {'server': self.LAUNCH_CONFIG_ARGS_SERVER,
+ 'stack': self.LAUNCH_CONFIG_ARGS_STACK,
+ 'conf': self.LAUNCH_CONFIGURATION})
+ raise exception.StackValidationFailed(msg)
+
lb_args = lcargs.get(self.LAUNCH_CONFIG_ARGS_LOAD_BALANCERS)
lbs = copy.deepcopy(lb_args)
for lb in lbs:
@@ -418,6 +519,26 @@ class Group(resource.Resource):
'with id %s') % (lb_id)
raise exception.StackValidationFailed(msg)
+ if st_args:
+ st_tmpl = st_args.get(self.LAUNCH_CONFIG_ARGS_STACK_TEMPLATE)
+ st_tmpl_url = st_args.get(
+ self.LAUNCH_CONFIG_ARGS_STACK_TEMPLATE_URL)
+ st_env = st_args.get(self.LAUNCH_CONFIG_ARGS_STACK_ENVIRONMENT)
+ # template and template_url are required and mutually exclusive.
+ if ((not st_tmpl and not st_tmpl_url) or
+ (st_tmpl and st_tmpl_url)):
+ msg = _('Must provide one of template or template_url.')
+ raise exception.StackValidationFailed(msg)
+
+ if st_tmpl:
+ st_files = st_args.get(self.LAUNCH_CONFIG_ARGS_STACK_FILES)
+ try:
+ templatem.Template(st_tmpl, files=st_files, env=st_env)
+ except Exception as exc:
+ msg = (_('Encountered error while loading template: %s') %
+ six.text_type(exc))
+ raise exception.StackValidationFailed(msg)
+
def auto_scale(self):
return self.client('auto_scale')
diff --git a/contrib/rackspace/rackspace/tests/test_auto_scale.py b/contrib/rackspace/rackspace/tests/test_auto_scale.py
index bd8343c7b..f86cc28c4 100644
--- a/contrib/rackspace/rackspace/tests/test_auto_scale.py
+++ b/contrib/rackspace/rackspace/tests/test_auto_scale.py
@@ -102,9 +102,15 @@ class FakeAutoScale(object):
def replace_launch_config(self, group_id, **kwargs):
"""Update the launch configuration on a scaling group."""
- allowed = ['launch_config_type', 'server_name', 'image', 'flavor',
- 'disk_config', 'metadata', 'personality', 'networks',
- 'load_balancers', 'key_name', 'user_data', 'config_drive']
+ if kwargs.get('launch_config_type') == 'launch_server':
+ allowed = ['launch_config_type', 'server_name', 'image', 'flavor',
+ 'disk_config', 'metadata', 'personality', 'networks',
+ 'load_balancers', 'key_name', 'user_data',
+ 'config_drive']
+ elif kwargs.get('launch_config_type') == 'launch_stack':
+ allowed = ['launch_config_type', 'template', 'template_url',
+ 'disable_rollback', 'environment', 'files',
+ 'parameters', 'timeout_mins']
self._check_args(kwargs, allowed)
self._get_group(group_id).kwargs = kwargs
@@ -171,7 +177,7 @@ class FakeAutoScale(object):
class ScalingGroupTest(common.HeatTestCase):
- group_template = template_format.parse('''
+ server_template = template_format.parse('''
HeatTemplateFormatVersion: "2012-12-12"
Description: "Rackspace Auto Scale"
Parameters: {}
@@ -207,6 +213,53 @@ class ScalingGroupTest(common.HeatTestCase):
''')
+ stack_template = template_format.parse('''
+ HeatTemplateFormatVersion: "2012-12-12"
+ Description: "Rackspace Auto Scale"
+ Parameters: {}
+ Resources:
+ my_group:
+ Type: Rackspace::AutoScale::Group
+ Properties:
+ groupConfiguration:
+ name: "My Group"
+ cooldown: 60
+ minEntities: 1
+ maxEntities: 25
+ metadata:
+ group: metadata
+ launchConfiguration:
+ type: launch_stack
+ args:
+ stack:
+ template:
+ heat_template_version: 2015-10-15
+ description: This is a Heat template
+ parameters:
+ image:
+ default: cirros-0.3.4-x86_64-uec
+ type: string
+ flavor:
+ default: m1.tiny
+ type: string
+ resources:
+ rand:
+ type: OS::Heat::RandomString
+ disable_rollback: False
+ environment:
+ parameters:
+ image: Ubuntu 14.04 LTS (Trusty Tahr) (PVHVM)
+ resource_registry:
+ Heat::InstallConfigAgent:
+ https://myhost.com/bootconfig.yaml
+ files:
+ fileA.yaml: Contents of the file
+ file:///usr/fileB.template: Contents of the file
+ parameters:
+ flavor: 4 GB Performance
+ timeout_mins: 30
+ ''')
+
def setUp(self):
super(ScalingGroupTest, self).setUp()
for res_name, res_class in auto_scale.resource_mapping().items():
@@ -222,14 +275,16 @@ class ScalingGroupTest(common.HeatTestCase):
'find_flavor_by_name_or_id')
mock_fl.return_value = 'flavor-ref'
- def _setup_test_stack(self):
- self.stack = utils.parse_stack(self.group_template)
+ def _setup_test_stack(self, template=None):
+ if template is None:
+ template = self.server_template
+ self.stack = utils.parse_stack(template)
self.stack.create()
self.assertEqual(
('CREATE', 'COMPLETE'), self.stack.state,
self.stack.status_reason)
- def test_group_create(self):
+ def test_group_create_server(self):
"""Creating a group passes all the correct arguments to pyrax.
Also saves the group ID as the resource ID.
@@ -266,6 +321,62 @@ class ScalingGroupTest(common.HeatTestCase):
resource = self.stack['my_group']
self.assertEqual('0', resource.FnGetRefId())
+ def test_group_create_stack(self):
+ """Creating a group passes all the correct arguments to pyrax.
+
+ Also saves the group ID as the resource ID.
+ """
+ self._setup_test_stack(self.stack_template)
+ self.assertEqual(1, len(self.fake_auto_scale.groups))
+ self.assertEqual(
+ {
+ 'cooldown': 60,
+ 'min_entities': 1,
+ 'max_entities': 25,
+ 'group_metadata': {'group': 'metadata'},
+ 'name': 'My Group',
+ 'launch_config_type': u'launch_stack',
+ 'template': {
+ 'heat_template_version': '2015-10-15',
+ 'description': 'This is a Heat template',
+ 'parameters': {
+ 'flavor': {
+ 'default': 'm1.tiny',
+ 'type': 'string'},
+ 'image': {
+ 'default': 'cirros-0.3.4-x86_64-uec',
+ 'type': 'string'}},
+ 'resources': {
+ 'rand': {'type': u'OS::Heat::RandomString'}
+ }
+ },
+ 'template_url': None,
+ 'disable_rollback': False,
+ 'environment': {
+ 'parameters': {
+ 'image':
+ 'Ubuntu 14.04 LTS (Trusty Tahr) (PVHVM)',
+ },
+ 'resource_registry': {
+ 'Heat::InstallConfigAgent': ('https://myhost.com/'
+ 'bootconfig.yaml')
+ }
+ },
+ 'files': {
+ 'fileA.yaml': 'Contents of the file',
+ 'file:///usr/fileB.template': 'Contents of the file'
+ },
+ 'parameters': {
+ 'flavor': '4 GB Performance',
+ },
+ 'timeout_mins': 30,
+ },
+ self.fake_auto_scale.groups['0'].kwargs
+ )
+
+ resource = self.stack['my_group']
+ self.assertEqual('0', resource.FnGetRefId())
+
def test_group_create_no_personality(self):
template = template_format.parse('''
@@ -366,7 +477,7 @@ Resources:
self.assertEqual(
5, self.fake_auto_scale.groups['0'].kwargs['min_entities'])
- def test_update_launch_config(self):
+ def test_update_launch_config_server(self):
"""Updates the launchConfigresults section.
Updates the launchConfigresults section in a template results in a
@@ -389,6 +500,24 @@ Resources:
[{'loadBalancerId': 1, 'port': 80}],
self.fake_auto_scale.groups['0'].kwargs['load_balancers'])
+ def test_update_launch_config_stack(self):
+ self._setup_test_stack(self.stack_template)
+
+ resource = self.stack['my_group']
+ uprops = copy.deepcopy(dict(resource.properties.data))
+ lcargs = uprops['launchConfiguration']['args']
+ lcargs['stack']['timeout_mins'] = 60
+ new_template = rsrc_defn.ResourceDefinition(resource.name,
+ resource.type(),
+ uprops)
+
+ scheduler.TaskRunner(resource.update, new_template)()
+
+ self.assertEqual(1, len(self.fake_auto_scale.groups))
+ self.assertEqual(
+ 60,
+ self.fake_auto_scale.groups['0'].kwargs['timeout_mins'])
+
def test_delete(self):
"""Deleting a ScalingGroup resource invokes pyrax API to delete it."""
self._setup_test_stack()
@@ -786,3 +915,305 @@ class AutoScaleGroupValidationTests(common.HeatTestCase):
asg = auto_scale.Group("test", rsrcdef, self.mockstack)
self.assertIsNone(asg.validate())
+
+ def test_validate_launch_stack(self, mock_client, mock_plugin):
+ asg_properties = {
+ "groupConfiguration": {
+ "name": "My Group",
+ "cooldown": 60,
+ "minEntities": 1,
+ "maxEntities": 25,
+ "metadata": {
+ "group": "metadata",
+ },
+ },
+ "launchConfiguration": {
+ "type": "launch_stack",
+ "args": {
+ "stack": {
+ 'template': {
+ 'heat_template_version': '2015-10-15',
+ 'description': 'This is a Heat template',
+ 'parameters': {
+ 'flavor': {
+ 'default': 'm1.tiny',
+ 'type': 'string'},
+ 'image': {
+ 'default': 'cirros-0.3.4-x86_64-uec',
+ 'type': 'string'}},
+ 'resources': {
+ 'rand': {'type': u'OS::Heat::RandomString'}
+ }
+ },
+ 'template_url': None,
+ 'disable_rollback': False,
+ 'environment': {
+ 'parameters': {
+ 'image':
+ 'Ubuntu 14.04 LTS (Trusty Tahr) (PVHVM)',
+ },
+ 'resource_registry': {
+ 'Heat::InstallConfigAgent': (
+ 'https://myhost.com/bootconfig.yaml')
+ }
+ },
+ 'files': {
+ 'fileA.yaml': 'Contents of the file',
+ 'file:///usr/fileB.yaml': 'Contents of the file'
+ },
+ 'parameters': {
+ 'flavor': '4 GB Performance',
+ },
+ 'timeout_mins': 30,
+ }
+ }
+ }
+ }
+ rsrcdef = rsrc_defn.ResourceDefinition(
+ "test", auto_scale.Group, properties=asg_properties)
+ asg = auto_scale.Group("test", rsrcdef, self.mockstack)
+
+ self.assertIsNone(asg.validate())
+
+ def test_validate_launch_server_and_stack(self, mock_client, mock_plugin):
+ asg_properties = {
+ "groupConfiguration": {
+ "name": "My Group",
+ "cooldown": 60,
+ "minEntities": 1,
+ "maxEntities": 25,
+ "metadata": {
+ "group": "metadata",
+ },
+ },
+ "launchConfiguration": {
+ "type": "launch_server",
+ "args": {
+ "server": {
+ "name": "sdfsdf",
+ "flavorRef": "ffdgdf",
+ "imageRef": "image-ref",
+ },
+ "stack": {
+ 'template': {
+ 'heat_template_version': '2015-10-15',
+ 'description': 'This is a Heat template',
+ 'parameters': {
+ 'flavor': {
+ 'default': 'm1.tiny',
+ 'type': 'string'},
+ 'image': {
+ 'default': 'cirros-0.3.4-x86_64-uec',
+ 'type': 'string'}},
+ 'resources': {
+ 'rand': {'type': u'OS::Heat::RandomString'}
+ }
+ },
+ 'template_url': None,
+ 'disable_rollback': False,
+ 'environment': {
+ 'parameters': {
+ 'image':
+ 'Ubuntu 14.04 LTS (Trusty Tahr) (PVHVM)',
+ },
+ 'resource_registry': {
+ 'Heat::InstallConfigAgent': (
+ 'https://myhost.com/bootconfig.yaml')
+ }
+ },
+ 'files': {
+ 'fileA.yaml': 'Contents of the file',
+ 'file:///usr/fileB.yaml': 'Contents of the file'
+ },
+ 'parameters': {
+ 'flavor': '4 GB Performance',
+ },
+ 'timeout_mins': 30,
+ }
+ }
+ }
+ }
+ rsrcdef = rsrc_defn.ResourceDefinition(
+ "test", auto_scale.Group, properties=asg_properties)
+ asg = auto_scale.Group("test", rsrcdef, self.mockstack)
+
+ error = self.assertRaises(
+ exception.StackValidationFailed, asg.validate)
+ self.assertIn(
+ 'Must provide one of server or stack in launchConfiguration',
+ six.text_type(error))
+
+ def test_validate_no_launch_server_or_stack(self, mock_client,
+ mock_plugin):
+ asg_properties = {
+ "groupConfiguration": {
+ "name": "My Group",
+ "cooldown": 60,
+ "minEntities": 1,
+ "maxEntities": 25,
+ "metadata": {
+ "group": "metadata",
+ },
+ },
+ "launchConfiguration": {
+ "type": "launch_server",
+ "args": {}
+ }
+ }
+ rsrcdef = rsrc_defn.ResourceDefinition(
+ "test", auto_scale.Group, properties=asg_properties)
+ asg = auto_scale.Group("test", rsrcdef, self.mockstack)
+
+ error = self.assertRaises(
+ exception.StackValidationFailed, asg.validate)
+ self.assertIn(
+ 'Must provide one of server or stack in launchConfiguration',
+ six.text_type(error))
+
+ def test_validate_stack_template_and_template_url(self, mock_client,
+ mock_plugin):
+ asg_properties = {
+ "groupConfiguration": {
+ "name": "My Group",
+ "cooldown": 60,
+ "minEntities": 1,
+ "maxEntities": 25,
+ "metadata": {
+ "group": "metadata",
+ },
+ },
+ "launchConfiguration": {
+ "type": "launch_server",
+ "args": {
+ "stack": {
+ 'template': {
+ 'heat_template_version': '2015-10-15',
+ 'description': 'This is a Heat template',
+ 'parameters': {
+ 'flavor': {
+ 'default': 'm1.tiny',
+ 'type': 'string'},
+ 'image': {
+ 'default': 'cirros-0.3.4-x86_64-uec',
+ 'type': 'string'}},
+ 'resources': {
+ 'rand': {'type': 'OS::Heat::RandomString'}
+ }
+ },
+ 'template_url': 'https://myhost.com/template.yaml',
+ }
+ }
+ }
+ }
+ rsrcdef = rsrc_defn.ResourceDefinition(
+ "test", auto_scale.Group, properties=asg_properties)
+ asg = auto_scale.Group("test", rsrcdef, self.mockstack)
+
+ error = self.assertRaises(
+ exception.StackValidationFailed, asg.validate)
+ self.assertIn(
+ 'Must provide one of template or template_url',
+ six.text_type(error))
+
+ def test_validate_stack_no_template_or_template_url(self, mock_client,
+ mock_plugin):
+ asg_properties = {
+ "groupConfiguration": {
+ "name": "My Group",
+ "cooldown": 60,
+ "minEntities": 1,
+ "maxEntities": 25,
+ "metadata": {
+ "group": "metadata",
+ },
+ },
+ "launchConfiguration": {
+ "type": "launch_server",
+ "args": {
+ "stack": {
+ 'disable_rollback': False,
+ 'environment': {
+ 'parameters': {
+ 'image':
+ 'Ubuntu 14.04 LTS (Trusty Tahr) (PVHVM)',
+ },
+ 'resource_registry': {
+ 'Heat::InstallConfigAgent': (
+ 'https://myhost.com/bootconfig.yaml')
+ }
+ },
+ 'files': {
+ 'fileA.yaml': 'Contents of the file',
+ 'file:///usr/fileB.yaml': 'Contents of the file'
+ },
+ 'parameters': {
+ 'flavor': '4 GB Performance',
+ },
+ 'timeout_mins': 30,
+ }
+ }
+ }
+ }
+ rsrcdef = rsrc_defn.ResourceDefinition(
+ "test", auto_scale.Group, properties=asg_properties)
+ asg = auto_scale.Group("test", rsrcdef, self.mockstack)
+
+ error = self.assertRaises(
+ exception.StackValidationFailed, asg.validate)
+ self.assertIn(
+ 'Must provide one of template or template_url',
+ six.text_type(error))
+
+ def test_validate_invalid_template(self, mock_client, mock_plugin):
+ asg_properties = {
+ "groupConfiguration": {
+ "name": "My Group",
+ "cooldown": 60,
+ "minEntities": 1,
+ "maxEntities": 25,
+ "metadata": {
+ "group": "metadata",
+ },
+ },
+ "launchConfiguration": {
+ "type": "launch_stack",
+ "args": {
+ "stack": {
+ 'template': {
+ 'SJDADKJAJKLSheat_template_version': '2015-10-15',
+ 'description': 'This is a Heat template',
+ 'parameters': {
+ 'flavor': {
+ 'default': 'm1.tiny',
+ 'type': 'string'},
+ 'image': {
+ 'default': 'cirros-0.3.4-x86_64-uec',
+ 'type': 'string'}},
+ 'resources': {
+ 'rand': {'type': u'OS::Heat::RandomString'}
+ }
+ },
+ 'template_url': None,
+ 'disable_rollback': False,
+ 'environment': {'Foo': 'Bar'},
+ 'files': {
+ 'fileA.yaml': 'Contents of the file',
+ 'file:///usr/fileB.yaml': 'Contents of the file'
+ },
+ 'parameters': {
+ 'flavor': '4 GB Performance',
+ },
+ 'timeout_mins': 30,
+ }
+ }
+ }
+ }
+ rsrcdef = rsrc_defn.ResourceDefinition(
+ "test", auto_scale.Group, properties=asg_properties)
+ asg = auto_scale.Group("test", rsrcdef, self.mockstack)
+
+ error = self.assertRaises(
+ exception.StackValidationFailed, asg.validate)
+ self.assertIn(
+ 'Encountered error while loading template:',
+ six.text_type(error))