Never cache the 'show' attribute

The 'show' attribute is used to get all data about a resource. There are
folks using this in lieu of having access to the underlying OpenStack APIs
themselves. By not caching it, we ensure that they will always see a live
value, even once we start storing attribute values in the database when
modifying a resource.

Change-Id: Id81a56f7d774bc18a2b5d62c80b369f1c12bcc5c
Co-Authored-By: Crag Wolfe <cwolfe@redhat.com>
Related-Bug: #1660831
changes/98/475098/3
Zane Bitter 5 years ago
parent a5ac2c3b1d
commit f47efe532d
  1. 1
      heat/engine/resource.py
  2. 24
      heat/tests/openstack/neutron/test_neutron.py

@ -123,6 +123,7 @@ class Resource(status.ResourceStatus):
base_attributes_schema = {
SHOW: attributes.Schema(
_("Detailed information about resource."),
cache_mode=attributes.Schema.CACHE_NONE,
type=attributes.Schema.MAP
)
}

@ -16,6 +16,7 @@ from neutronclient.common import exceptions as qe
import six
from heat.common import exception
from heat.engine import attributes
from heat.engine import properties
from heat.engine.resources.openstack.neutron import net
from heat.engine.resources.openstack.neutron import neutron as nr
@ -95,6 +96,9 @@ class NeutronTest(common.HeatTestCase):
def test_resolve_attribute(self):
res = self._get_some_neutron_resource()
res.attributes_schema.update(
{'attr2': attributes.Schema(type=attributes.Schema.STRING)})
res.attributes = res._init_attributes()
side_effect = [{'attr1': 'val1', 'attr2': 'val2'},
{'attr1': 'val1', 'attr2': 'val2'},
{'attr1': 'val1', 'attr2': 'val2'},
@ -103,19 +107,23 @@ class NeutronTest(common.HeatTestCase):
res.resource_id = 'resource_id'
self.assertEqual({'attr1': 'val1', 'attr2': 'val2'},
res.FnGetAtt('show'))
self.assertEqual('val2', res._resolve_all_attributes('attr2'))
self.assertEqual('val2', res.attributes['attr2'])
self.assertRaises(KeyError, res._resolve_all_attributes, 'attr3')
self.assertIsNone(res._resolve_all_attributes('attr2'))
self.assertIsNone(res._resolve_all_attributes('attr1'))
res.resource_id = None
# use local cached object
self.assertEqual({'attr1': 'val1', 'attr2': 'val2'},
res.FnGetAtt('show'))
# reset cache, so resolver should be used again
# and return None due to resource_id is None
res.attributes.reset_resolved_values()
# use local cached object for non-show attribute
self.assertEqual('val2',
res.FnGetAtt('attr2'))
# but the 'show' attribute is never cached
self.assertIsNone(res.FnGetAtt('show'))
# remove 'attr2' from res.attributes cache
res.attributes.reset_resolved_values()
# _resolve_attribute (in NeutronResource class) returns None
# due to no resource_id
self.assertIsNone(res.FnGetAtt('attr2'))
def test_needs_replace_failed(self):
res = self._get_some_neutron_resource()
res.state_set(res.CREATE, res.FAILED)

Loading…
Cancel
Save