Allow a resource to be added to a template

Add a method that allows a ResourceDefinition to be inserted into an
existing template.

Change-Id: Ia418127d72d26a77d731f93cc0eb3a45d983cc82
This commit is contained in:
Zane Bitter 2014-04-28 18:33:33 -04:00
parent 599dd3869e
commit 69187601c7
5 changed files with 84 additions and 0 deletions

View File

@ -128,6 +128,25 @@ class CfnTemplate(template.Template):
resources = self.t.get(self.RESOURCES, {}).items()
return dict(rsrc_defn_item(name, data) for name, data in resources)
def add_resource(self, definition, name=None):
if name is None:
name = definition.name
hot_tmpl = definition.render_hot()
HOT_TO_CFN_ATTRS = {'type': RES_TYPE,
'properties': RES_PROPERTIES,
'metadata': RES_METADATA,
'depends_on': RES_DEPENDS_ON,
'deletion_policy': RES_DELETION_POLICY,
'update_policy': RES_UPDATE_POLICY}
cfn_tmpl = dict((HOT_TO_CFN_ATTRS[k], v) for k, v in hot_tmpl.items())
if len(cfn_tmpl.get(RES_DEPENDS_ON, [])) == 1:
cfn_tmpl[RES_DEPENDS_ON] = cfn_tmpl[RES_DEPENDS_ON][0]
self.t.setdefault(self.RESOURCES, {})[name] = cfn_tmpl
def template_mapping():
return {

View File

@ -217,6 +217,12 @@ class HOTemplate(template.Template):
resources = self.t.get(self.RESOURCES, {}).items()
return dict(rsrc_defn_item(name, data) for name, data in resources)
def add_resource(self, definition, name=None):
if name is None:
name = definition.name
self.t.setdefault(self.RESOURCES, {})[name] = definition.render_hot()
def template_mapping():
return {

View File

@ -166,6 +166,15 @@ class Template(collections.Mapping):
'''Return a dictionary of ResourceDefinition objects.'''
pass
@abc.abstractmethod
def add_resource(self, definition, name=None):
'''Add a resource to the template.
The resource is passed as a ResourceDefinition object. If no name is
specified, the name from the ResourceDefinition should be used.
'''
pass
def functions(self):
'''Return a dict of template functions keyed by name.'''
if self.version not in self._functionmaps:

View File

@ -11,6 +11,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import copy
import six
from heat.common import exception
@ -616,6 +617,31 @@ class HOTemplateTest(HeatTestCase):
parent_resource=parent_resource)
self.assertEqual('Delete', self.resolve(snippet, stack.t, stack))
def test_add_resource(self):
hot_tpl = template_format.parse('''
heat_template_version: 2013-05-23
resources:
resource1:
type: AWS::EC2::Instance
properties:
property1: value1
metadata:
foo: bar
depends_on:
- dummy
deletion_policy: Retain
update_policy:
foo: bar
''')
source = parser.Template(hot_tpl)
empty = parser.Template(copy.deepcopy(hot_tpl_empty))
stack = parser.Stack(utils.dummy_context(), 'test_stack', source)
for defn in source.resource_definitions(stack).values():
empty.add_resource(defn)
self.assertEqual(hot_tpl['resources'], empty.t['resources'])
class StackTest(test_parser.StackTest):
"""Test stack function when stack was created from HOT template."""

View File

@ -619,6 +619,30 @@ Mappings:
self.assertEqual(expected_description, tmpl['Description'])
self.assertNotIn('Parameters', tmpl.keys())
def test_add_resource(self):
cfn_tpl = template_format.parse('''
AWSTemplateFormatVersion: 2010-09-09
Resources:
resource1:
Type: AWS::EC2::Instance
Properties:
property1: value1
Metadata:
foo: bar
DependsOn: dummy
DeletionPolicy: Retain
UpdatePolicy:
foo: bar
''')
source = parser.Template(cfn_tpl)
empty = parser.Template(copy.deepcopy(empty_template))
stack = parser.Stack(self.ctx, 'test_stack', source)
for defn in source.resource_definitions(stack).values():
empty.add_resource(defn)
self.assertEqual(cfn_tpl['Resources'], empty.t['Resources'])
class TemplateFnErrorTest(HeatTestCase):
scenarios = [