Merge "Allow in-place update of nested stack"
This commit is contained in:
commit
d719d0b072
@ -16,6 +16,7 @@
|
||||
from heat.common import exception
|
||||
from heat.common import template_format
|
||||
from heat.common import urlfetch
|
||||
from heat.engine.properties import Properties
|
||||
from heat.engine import stack_resource
|
||||
|
||||
from heat.openstack.common import log as logging
|
||||
@ -38,6 +39,10 @@ class NestedStack(stack_resource.StackResource):
|
||||
PROP_TIMEOUT_MINS: {'Type': 'Number'},
|
||||
PROP_PARAMETERS: {'Type': 'Map'}}
|
||||
|
||||
update_allowed_keys = ('Properties',)
|
||||
update_allowed_properties = (PROP_TEMPLATE_URL, PROP_TIMEOUT_MINS,
|
||||
PROP_PARAMETERS)
|
||||
|
||||
def handle_create(self):
|
||||
template_data = urlfetch.get(self.properties[PROP_TEMPLATE_URL])
|
||||
template = template_format.parse(template_data)
|
||||
@ -58,6 +63,20 @@ class NestedStack(stack_resource.StackResource):
|
||||
def FnGetRefId(self):
|
||||
return self.nested().identifier().arn()
|
||||
|
||||
def handle_update(self, json_snippet, tmpl_diff, prop_diff):
|
||||
# Nested stack template may be changed even if the prop_diff is empty.
|
||||
self.properties = Properties(self.properties_schema,
|
||||
json_snippet.get('Properties', {}),
|
||||
self.stack.resolve_runtime_data,
|
||||
self.name)
|
||||
|
||||
template_data = urlfetch.get(self.properties[PROP_TEMPLATE_URL])
|
||||
template = template_format.parse(template_data)
|
||||
|
||||
self.update_with_template(template,
|
||||
self.properties[PROP_PARAMETERS],
|
||||
self.properties[PROP_TIMEOUT_MINS])
|
||||
|
||||
|
||||
def resource_mapping():
|
||||
return {
|
||||
|
@ -13,6 +13,8 @@
|
||||
# under the License.
|
||||
|
||||
|
||||
import copy
|
||||
|
||||
from heat.common import exception
|
||||
from heat.common import template_format
|
||||
from heat.common import urlfetch
|
||||
@ -47,6 +49,16 @@ Outputs:
|
||||
Value: bar
|
||||
'''
|
||||
|
||||
update_template = '''
|
||||
HeatTemplateFormatVersion: '2012-12-12'
|
||||
Parameters:
|
||||
KeyName:
|
||||
Type: String
|
||||
Outputs:
|
||||
Bar:
|
||||
Value: foo
|
||||
'''
|
||||
|
||||
def setUp(self):
|
||||
super(NestedStackTest, self).setUp()
|
||||
self.m.StubOutWithMock(urlfetch, 'get')
|
||||
@ -67,9 +79,9 @@ Outputs:
|
||||
stack.store()
|
||||
return stack
|
||||
|
||||
def test_nested_stack(self):
|
||||
urlfetch.get('https://localhost/the.template').AndReturn(
|
||||
self.nested_template)
|
||||
def test_nested_stack_create(self):
|
||||
urlfetch.get('https://localhost/the.template').MultipleTimes().\
|
||||
AndReturn(self.nested_template)
|
||||
self.m.ReplayAll()
|
||||
|
||||
stack = self.create_stack(self.test_template)
|
||||
@ -80,9 +92,6 @@ Outputs:
|
||||
rsrc.physical_resource_name())
|
||||
self.assertTrue(rsrc.FnGetRefId().startswith(arn_prefix))
|
||||
|
||||
self.assertRaises(resource.UpdateReplace,
|
||||
rsrc.handle_update, {}, {}, {})
|
||||
|
||||
self.assertEqual('bar', rsrc.FnGetAtt('Outputs.Foo'))
|
||||
self.assertRaises(
|
||||
exception.InvalidTemplateAttribute, rsrc.FnGetAtt, 'Foo')
|
||||
@ -96,6 +105,44 @@ Outputs:
|
||||
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_nested_stack_update(self):
|
||||
urlfetch.get('https://localhost/the.template').MultipleTimes().\
|
||||
AndReturn(self.nested_template)
|
||||
urlfetch.get('https://localhost/new.template').MultipleTimes().\
|
||||
AndReturn(self.update_template)
|
||||
|
||||
self.m.ReplayAll()
|
||||
|
||||
stack = self.create_stack(self.test_template)
|
||||
rsrc = stack['the_nested']
|
||||
|
||||
original_nested_id = rsrc.resource_id
|
||||
t = template_format.parse(self.test_template)
|
||||
new_res = copy.deepcopy(t['Resources']['the_nested'])
|
||||
new_res['Properties']['TemplateURL'] = 'https://localhost/new.template'
|
||||
prop_diff = {'TemplateURL': 'https://localhost/new.template'}
|
||||
rsrc.handle_update(new_res, {}, prop_diff)
|
||||
|
||||
# Expect the physical resource name staying the same after update,
|
||||
# so that the nested was actually updated instead of replaced.
|
||||
self.assertEqual(original_nested_id, rsrc.resource_id)
|
||||
db_nested = db_api.stack_get(stack.context,
|
||||
rsrc.resource_id)
|
||||
# Owner_id should be preserved during the update process.
|
||||
self.assertEqual(stack.id, db_nested.owner_id)
|
||||
|
||||
self.assertEqual('foo', rsrc.FnGetAtt('Outputs.Bar'))
|
||||
self.assertRaises(
|
||||
exception.InvalidTemplateAttribute, rsrc.FnGetAtt, 'Foo')
|
||||
self.assertRaises(
|
||||
exception.InvalidTemplateAttribute, rsrc.FnGetAtt, 'Outputs.Foo')
|
||||
self.assertRaises(
|
||||
exception.InvalidTemplateAttribute, rsrc.FnGetAtt, 'Bar')
|
||||
|
||||
rsrc.delete()
|
||||
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_nested_stack_suspend_resume(self):
|
||||
urlfetch.get('https://localhost/the.template').AndReturn(
|
||||
self.nested_template)
|
||||
|
Loading…
Reference in New Issue
Block a user