diff --git a/doc/source/ext/resources.py b/doc/source/ext/resources.py index 7031e4776b..f09901bce5 100644 --- a/doc/source/ext/resources.py +++ b/doc/source/ext/resources.py @@ -186,7 +186,7 @@ resources: return cmp(x_prop.support_status.status, y_prop.support_status.status) - def contribute_property(self, prop_list, prop_key, prop): + def contribute_property(self, prop_list, prop_key, prop, upd_para=None): prop_item = nodes.definition_list_item( '', nodes.term('', prop_key)) prop_list.append(prop_item) @@ -208,18 +208,22 @@ resources: para = nodes.paragraph('', prop.description) definition.append(para) - if prop.update_allowed: - para = nodes.paragraph('', - _('Can be updated without replacement.')) - definition.append(para) - elif prop.immutable: - para = nodes.paragraph('', _('Updates are not supported. ' - 'Resource update will fail on any ' - 'attempt to update this property.')) - definition.append(para) + if upd_para is not None: + definition.append(upd_para) else: - para = nodes.paragraph('', _('Updates cause replacement.')) - definition.append(para) + if prop.update_allowed: + upd_para = nodes.paragraph( + '', _('Can be updated without replacement.')) + definition.append(upd_para) + elif prop.immutable: + upd_para = nodes.paragraph('', _('Updates are not supported. ' + 'Resource update will fail on' + ' any attempt to update this ' + 'property.')) + definition.append(upd_para) + else: + upd_para = nodes.paragraph('', _('Updates cause replacement.')) + definition.append(upd_para) if prop.required: para = nodes.paragraph('', _('Required property.')) @@ -257,7 +261,7 @@ resources: self.cmp_prop): if sub_prop.support_status.status != support.HIDDEN: self.contribute_property( - sub_prop_list, sub_prop_key, sub_prop) + sub_prop_list, sub_prop_key, sub_prop, upd_para) def contribute_properties(self, parent): if not self.props_schemata: diff --git a/heat/tests/test_properties.py b/heat/tests/test_properties.py index c3c8d8b622..8a24018e72 100644 --- a/heat/tests/test_properties.py +++ b/heat/tests/test_properties.py @@ -20,6 +20,7 @@ from heat.engine.cfn import functions as cfn_funcs from heat.engine import constraints from heat.engine.hot import parameters as hot_param 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 support @@ -582,6 +583,43 @@ class PropertySchemaTest(common.HeatTestCase): self.assertFalse(schema.required) self.assertTrue(schema.allow_conversion) + def test_no_mismatch_in_update_policy(self): + manager = plugin_manager.PluginManager('heat.engine.resources') + resource_mapping = plugin_manager.PluginMapping('resource') + res_plugin_mappings = resource_mapping.load_all(manager) + all_resources = {} + for mapping in res_plugin_mappings: + name, cls = mapping + all_resources[name] = cls + + def check_update_policy(resource_type, prop_key, prop, update=False): + if prop.update_allowed: + update = True + sub_schema = prop.schema + if sub_schema: + for sub_prop_key, sub_prop in six.iteritems(sub_schema): + if not update: + self.assertEqual(update, sub_prop.update_allowed, + "Mismatch in update policies: " + "resource %(res)s, properties " + "'%(prop)s' and '%(nested_prop)s'." % + {'res': resource_type, + 'prop': prop_key, + 'nested_prop': sub_prop_key}) + if sub_prop_key is '*': + check_update_policy(resource_type, prop_key, + sub_prop, update) + else: + check_update_policy(resource_type, sub_prop_key, + sub_prop, update) + + for resource_type, resource_class in six.iteritems(all_resources): + props_schemata = properties.schemata( + resource_class.properties_schema) + + for prop_key, prop in six.iteritems(props_schemata): + check_update_policy(resource_type, prop_key, prop) + class PropertyTest(common.HeatTestCase): def test_required_default(self):