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
This commit is contained in:
parent
681df8eb00
commit
268e6a10d6
@ -14,6 +14,7 @@
|
|||||||
"""Resources for Rackspace Auto Scale."""
|
"""Resources for Rackspace Auto Scale."""
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
|
import six
|
||||||
|
|
||||||
from heat.common import exception
|
from heat.common import exception
|
||||||
from heat.common.i18n import _
|
from heat.common.i18n import _
|
||||||
@ -22,6 +23,7 @@ from heat.engine import constraints
|
|||||||
from heat.engine import properties
|
from heat.engine import properties
|
||||||
from heat.engine import resource
|
from heat.engine import resource
|
||||||
from heat.engine import support
|
from heat.engine import support
|
||||||
|
from heat.engine import template as templatem
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from pyrax.exceptions import Forbidden
|
from pyrax.exceptions import Forbidden
|
||||||
@ -74,9 +76,11 @@ class Group(resource.Resource):
|
|||||||
_LAUNCH_CONFIG_ARGS_KEYS = (
|
_LAUNCH_CONFIG_ARGS_KEYS = (
|
||||||
LAUNCH_CONFIG_ARGS_LOAD_BALANCERS,
|
LAUNCH_CONFIG_ARGS_LOAD_BALANCERS,
|
||||||
LAUNCH_CONFIG_ARGS_SERVER,
|
LAUNCH_CONFIG_ARGS_SERVER,
|
||||||
|
LAUNCH_CONFIG_ARGS_STACK,
|
||||||
) = (
|
) = (
|
||||||
'loadBalancers',
|
'loadBalancers',
|
||||||
'server',
|
'server',
|
||||||
|
'stack',
|
||||||
)
|
)
|
||||||
|
|
||||||
_LAUNCH_CONFIG_ARGS_LOAD_BALANCER_KEYS = (
|
_LAUNCH_CONFIG_ARGS_LOAD_BALANCER_KEYS = (
|
||||||
@ -115,6 +119,24 @@ class Group(resource.Resource):
|
|||||||
'uuid',
|
'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_configuration_args_schema = {
|
||||||
LAUNCH_CONFIG_ARGS_LOAD_BALANCERS: properties.Schema(
|
LAUNCH_CONFIG_ARGS_LOAD_BALANCERS: properties.Schema(
|
||||||
properties.Schema.LIST,
|
properties.Schema.LIST,
|
||||||
@ -141,6 +163,7 @@ class Group(resource.Resource):
|
|||||||
properties.Schema.MAP,
|
properties.Schema.MAP,
|
||||||
_('Server creation arguments, as accepted by the Cloud Servers '
|
_('Server creation arguments, as accepted by the Cloud Servers '
|
||||||
'server creation API.'),
|
'server creation API.'),
|
||||||
|
required=False,
|
||||||
schema={
|
schema={
|
||||||
LAUNCH_CONFIG_ARGS_SERVER_NAME: properties.Schema(
|
LAUNCH_CONFIG_ARGS_SERVER_NAME: properties.Schema(
|
||||||
properties.Schema.STRING,
|
properties.Schema.STRING,
|
||||||
@ -211,8 +234,49 @@ class Group(resource.Resource):
|
|||||||
'key-based authentication to the server.')
|
'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 = {
|
properties_schema = {
|
||||||
@ -256,17 +320,18 @@ class Group(resource.Resource):
|
|||||||
schema={
|
schema={
|
||||||
LAUNCH_CONFIG_ARGS: properties.Schema(
|
LAUNCH_CONFIG_ARGS: properties.Schema(
|
||||||
properties.Schema.MAP,
|
properties.Schema.MAP,
|
||||||
_('Type-specific server launching arguments.'),
|
_('Type-specific launch arguments.'),
|
||||||
schema=_launch_configuration_args_schema,
|
schema=_launch_configuration_args_schema,
|
||||||
required=True
|
required=True
|
||||||
),
|
),
|
||||||
LAUNCH_CONFIG_TYPE: properties.Schema(
|
LAUNCH_CONFIG_TYPE: properties.Schema(
|
||||||
properties.Schema.STRING,
|
properties.Schema.STRING,
|
||||||
_('Launch configuration method. Only launch_server '
|
_('Launch configuration method. Only launch_server and '
|
||||||
'is currently supported.'),
|
'launch_stack are currently supported.'),
|
||||||
required=True,
|
required=True,
|
||||||
constraints=[
|
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],
|
max_entities=groupconf[self.GROUP_CONFIGURATION_MAX_ENTITIES],
|
||||||
metadata=groupconf.get(self.GROUP_CONFIGURATION_METADATA, None))
|
metadata=groupconf.get(self.GROUP_CONFIGURATION_METADATA, None))
|
||||||
|
|
||||||
def _get_launch_config_args(self, launchconf):
|
def _get_launch_config_server_args(self, launchconf):
|
||||||
"""Get the launchConfiguration-related pyrax arguments."""
|
|
||||||
lcargs = launchconf[self.LAUNCH_CONFIG_ARGS]
|
lcargs = launchconf[self.LAUNCH_CONFIG_ARGS]
|
||||||
server_args = lcargs[self.LAUNCH_CONFIG_ARGS_SERVER]
|
server_args = lcargs[self.LAUNCH_CONFIG_ARGS_SERVER]
|
||||||
lb_args = lcargs.get(self.LAUNCH_CONFIG_ARGS_LOAD_BALANCERS)
|
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),
|
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):
|
def _get_create_args(self):
|
||||||
"""Get pyrax-style arguments for creating a scaling group."""
|
"""Get pyrax-style arguments for creating a scaling group."""
|
||||||
args = self._get_group_config_args(
|
args = self._get_group_config_args(
|
||||||
@ -406,6 +494,19 @@ class Group(resource.Resource):
|
|||||||
super(Group, self).validate()
|
super(Group, self).validate()
|
||||||
launchconf = self.properties[self.LAUNCH_CONFIGURATION]
|
launchconf = self.properties[self.LAUNCH_CONFIGURATION]
|
||||||
lcargs = launchconf[self.LAUNCH_CONFIG_ARGS]
|
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)
|
lb_args = lcargs.get(self.LAUNCH_CONFIG_ARGS_LOAD_BALANCERS)
|
||||||
lbs = copy.deepcopy(lb_args)
|
lbs = copy.deepcopy(lb_args)
|
||||||
for lb in lbs:
|
for lb in lbs:
|
||||||
@ -418,6 +519,26 @@ class Group(resource.Resource):
|
|||||||
'with id %s') % (lb_id)
|
'with id %s') % (lb_id)
|
||||||
raise exception.StackValidationFailed(msg)
|
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):
|
def auto_scale(self):
|
||||||
return self.client('auto_scale')
|
return self.client('auto_scale')
|
||||||
|
|
||||||
|
@ -102,9 +102,15 @@ class FakeAutoScale(object):
|
|||||||
|
|
||||||
def replace_launch_config(self, group_id, **kwargs):
|
def replace_launch_config(self, group_id, **kwargs):
|
||||||
"""Update the launch configuration on a scaling group."""
|
"""Update the launch configuration on a scaling group."""
|
||||||
|
if kwargs.get('launch_config_type') == 'launch_server':
|
||||||
allowed = ['launch_config_type', 'server_name', 'image', 'flavor',
|
allowed = ['launch_config_type', 'server_name', 'image', 'flavor',
|
||||||
'disk_config', 'metadata', 'personality', 'networks',
|
'disk_config', 'metadata', 'personality', 'networks',
|
||||||
'load_balancers', 'key_name', 'user_data', 'config_drive']
|
'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._check_args(kwargs, allowed)
|
||||||
self._get_group(group_id).kwargs = kwargs
|
self._get_group(group_id).kwargs = kwargs
|
||||||
|
|
||||||
@ -171,7 +177,7 @@ class FakeAutoScale(object):
|
|||||||
|
|
||||||
class ScalingGroupTest(common.HeatTestCase):
|
class ScalingGroupTest(common.HeatTestCase):
|
||||||
|
|
||||||
group_template = template_format.parse('''
|
server_template = template_format.parse('''
|
||||||
HeatTemplateFormatVersion: "2012-12-12"
|
HeatTemplateFormatVersion: "2012-12-12"
|
||||||
Description: "Rackspace Auto Scale"
|
Description: "Rackspace Auto Scale"
|
||||||
Parameters: {}
|
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):
|
def setUp(self):
|
||||||
super(ScalingGroupTest, self).setUp()
|
super(ScalingGroupTest, self).setUp()
|
||||||
for res_name, res_class in auto_scale.resource_mapping().items():
|
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')
|
'find_flavor_by_name_or_id')
|
||||||
mock_fl.return_value = 'flavor-ref'
|
mock_fl.return_value = 'flavor-ref'
|
||||||
|
|
||||||
def _setup_test_stack(self):
|
def _setup_test_stack(self, template=None):
|
||||||
self.stack = utils.parse_stack(self.group_template)
|
if template is None:
|
||||||
|
template = self.server_template
|
||||||
|
self.stack = utils.parse_stack(template)
|
||||||
self.stack.create()
|
self.stack.create()
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
('CREATE', 'COMPLETE'), self.stack.state,
|
('CREATE', 'COMPLETE'), self.stack.state,
|
||||||
self.stack.status_reason)
|
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.
|
"""Creating a group passes all the correct arguments to pyrax.
|
||||||
|
|
||||||
Also saves the group ID as the resource ID.
|
Also saves the group ID as the resource ID.
|
||||||
@ -266,6 +321,62 @@ class ScalingGroupTest(common.HeatTestCase):
|
|||||||
resource = self.stack['my_group']
|
resource = self.stack['my_group']
|
||||||
self.assertEqual('0', resource.FnGetRefId())
|
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):
|
def test_group_create_no_personality(self):
|
||||||
|
|
||||||
template = template_format.parse('''
|
template = template_format.parse('''
|
||||||
@ -366,7 +477,7 @@ Resources:
|
|||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
5, self.fake_auto_scale.groups['0'].kwargs['min_entities'])
|
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.
|
||||||
|
|
||||||
Updates the launchConfigresults section in a template results in a
|
Updates the launchConfigresults section in a template results in a
|
||||||
@ -389,6 +500,24 @@ Resources:
|
|||||||
[{'loadBalancerId': 1, 'port': 80}],
|
[{'loadBalancerId': 1, 'port': 80}],
|
||||||
self.fake_auto_scale.groups['0'].kwargs['load_balancers'])
|
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):
|
def test_delete(self):
|
||||||
"""Deleting a ScalingGroup resource invokes pyrax API to delete it."""
|
"""Deleting a ScalingGroup resource invokes pyrax API to delete it."""
|
||||||
self._setup_test_stack()
|
self._setup_test_stack()
|
||||||
@ -786,3 +915,305 @@ class AutoScaleGroupValidationTests(common.HeatTestCase):
|
|||||||
asg = auto_scale.Group("test", rsrcdef, self.mockstack)
|
asg = auto_scale.Group("test", rsrcdef, self.mockstack)
|
||||||
|
|
||||||
self.assertIsNone(asg.validate())
|
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))
|
||||||
|
Loading…
Reference in New Issue
Block a user