diff --git a/doc/source/template_guide/composition.rst b/doc/source/template_guide/composition.rst index 75caf86c9d..3cc372f068 100644 --- a/doc/source/template_guide/composition.rst +++ b/doc/source/template_guide/composition.rst @@ -138,3 +138,23 @@ accessable as follows: outputs: test_out: value: {get_attr: my_server, resource.server, first_address} + + +Making your template resource more "transparent" +------------------------------------------------ +If you wish to be able to return the ID of one of the inner resources +instead of the nested stack's ARN, you can add the following special +output to your template resource. + +.. code-block:: yaml + + resources: + server: + type: OS::Nova::Server + + outputs: + OS::stack_id: + value: {get_resource: server} + +Now when you use "get_resource" or "get_attr" from the outer template heat +will use nova server and not the template resource. diff --git a/heat/engine/resources/template_resource.py b/heat/engine/resources/template_resource.py index f1841d04ca..e7486208c4 100644 --- a/heat/engine/resources/template_resource.py +++ b/heat/engine/resources/template_resource.py @@ -263,6 +263,10 @@ class TemplateResource(stack_resource.StackResource): def FnGetRefId(self): if not self.nested(): return unicode(self.name) + + if 'OS::stack_id' in self.nested().outputs: + return self.nested().output('OS::stack_id') + return self.nested().identifier().arn() def FnGetAtt(self, key, *path): diff --git a/heat/tests/test_provider_template.py b/heat/tests/test_provider_template.py index a5001ed0b5..876ce4a1de 100644 --- a/heat/tests/test_provider_template.py +++ b/heat/tests/test_provider_template.py @@ -797,6 +797,8 @@ outputs: value: { get_attr: [secret2, resource.secret1, value]} test_attr2: value: { get_attr: [secret2, resource.secret1.value]} + test_ref: + value: { get_resource: secret2 } ''' env_templ = ''' @@ -821,6 +823,39 @@ resource_registry: self.assertEqual((stack.CREATE, stack.COMPLETE), stack.state) return stack + def test_stack_ref(self): + nested_templ = ''' +heat_template_version: 2014-10-16 +resources: + secret1: + type: OS::Heat::RandomString +''' + stack = self._create_dummy_stack(nested_templ) + test_ref = stack.output('test_ref') + self.assertIn('arn:openstack:heat:', test_ref) + + def test_transparent_ref(self): + """With the addition of OS::stack_id we can now use the nested resource + more transparently. + """ + nested_templ = ''' +heat_template_version: 2014-10-16 +resources: + secret1: + type: OS::Heat::RandomString +outputs: + OS::stack_id: + value: {get_resource: secret1} + nested_str: + value: {get_attr: [secret1, value]} +''' + stack = self._create_dummy_stack(nested_templ) + test_ref = stack.output('test_ref') + test_attr = stack.output('old_way') + + self.assertNotIn('arn:openstack:heat', test_ref) + self.assertEqual(test_attr, test_ref) + def test_nested_attributes(self): nested_templ = ''' heat_template_version: 2014-10-16