diff --git a/doc/source/ext/resources.py b/doc/source/ext/resources.py index 50db470afb..76d821b391 100644 --- a/doc/source/ext/resources.py +++ b/doc/source/ext/resources.py @@ -289,6 +289,8 @@ resources: default = nodes.literal('', json.dumps(prop.default)) para.append(default) definition.append(para) + elif prop_key == 'description' and prop.update_allowed: + para = nodes.line('', _('Defaults to the resource description')) for constraint in prop.constraints: para = nodes.line('', str(constraint)) diff --git a/heat/engine/properties.py b/heat/engine/properties.py index 14d688fa1c..3e3cf5a437 100644 --- a/heat/engine/properties.py +++ b/heat/engine/properties.py @@ -377,7 +377,8 @@ class Property(object): class Properties(collections.Mapping): def __init__(self, schema, data, resolver=lambda d: d, parent_name=None, - context=None, section=None, translation=None): + context=None, section=None, translation=None, + rsrc_description=None): self.props = dict((k, Property(s, k, context, path=parent_name)) for k, s in schema.items()) self.resolve = resolver @@ -387,6 +388,7 @@ class Properties(collections.Mapping): self.context = context self.translation = (trans.Translation(properties=self) if translation is None else translation) + self.rsrc_description = rsrc_description or None def update_translation(self, rules, client_resolve=True, ignore_resolve_error=False): @@ -507,6 +509,10 @@ class Properties(collections.Mapping): translation=self.translation) elif prop.required(): raise ValueError(_('Property %s not assigned') % key) + elif key == 'description' and prop.schema.update_allowed: + return self.rsrc_description + else: + return None def __getitem__(self, key): return self._get_property_value(key) diff --git a/heat/engine/rsrc_defn.py b/heat/engine/rsrc_defn.py index 6de61c3732..2933631e9b 100644 --- a/heat/engine/rsrc_defn.py +++ b/heat/engine/rsrc_defn.py @@ -306,7 +306,8 @@ class ResourceDefinition(object): """ props = properties.Properties(schema, self._properties or {}, function.resolve, context=context, - section=PROPERTIES) + section=PROPERTIES, + rsrc_description=self.description) props.update_translation(self._rules, self._client_resolve) return props diff --git a/heat/tests/test_properties.py b/heat/tests/test_properties.py index cf5dd14ece..166856617b 100644 --- a/heat/tests/test_properties.py +++ b/heat/tests/test_properties.py @@ -23,6 +23,7 @@ from heat.engine import parameters from heat.engine import plugin_manager from heat.engine import properties from heat.engine import resources +from heat.engine import rsrc_defn from heat.engine import support from heat.engine import translation from heat.tests import common @@ -1651,6 +1652,30 @@ class PropertiesTest(common.HeatTestCase): props_b = properties.Properties(schema, {'foo': 1}) self.assertTrue(props_a != props_b) + def test_description_substitution(self): + schema = { + 'description': properties.Schema('String', + update_allowed=True), + 'not_description': properties.Schema('String', + update_allowed=True), + } + blank_rsrc = rsrc_defn.ResourceDefinition('foo', 'FooResource', {}, + description='Foo resource') + bar_rsrc = rsrc_defn.ResourceDefinition('foo', 'FooResource', + {'description': 'bar'}, + description='Foo resource') + + blank_props = blank_rsrc.properties(schema) + self.assertEqual('Foo resource', blank_props['description']) + self.assertEqual(None, blank_props['not_description']) + + replace_schema = {'description': properties.Schema('String')} + empty_props = blank_rsrc.properties(replace_schema) + self.assertEqual(None, empty_props['description']) + + bar_props = bar_rsrc.properties(schema) + self.assertEqual('bar', bar_props['description']) + class PropertiesValidationTest(common.HeatTestCase): def test_required(self):