Merge "Remove support for accessing ResourceDefinition like a dict"

This commit is contained in:
Jenkins 2016-12-07 10:57:44 +00:00 committed by Gerrit Code Review
commit e4d7819a1d
2 changed files with 9 additions and 167 deletions

View File

@ -14,7 +14,6 @@ import collections
import copy
import itertools
import operator
import warnings
import six
@ -28,15 +27,15 @@ __all__ = ['ResourceDefinition']
@repr_wrapper
class ResourceDefinitionCore(object):
class ResourceDefinition(object):
"""A definition of a resource, independent of any template format."""
class Diff(object):
"""A diff between two versions of the same resource definition."""
def __init__(self, old_defn, new_defn):
if not (isinstance(old_defn, ResourceDefinitionCore) and
isinstance(new_defn, ResourceDefinitionCore)):
if not (isinstance(old_defn, ResourceDefinition) and
isinstance(new_defn, ResourceDefinition)):
raise TypeError
self.old_defn = old_defn
@ -218,8 +217,8 @@ class ResourceDefinitionCore(object):
function.dependencies(data, datapath))
explicit_depends = [] if self._depends is None else self._depends
prop_deps = strict_func_deps(self._properties, path(PROPERTIES))
metadata_deps = strict_func_deps(self._metadata, path(METADATA))
prop_deps = strict_func_deps(self._properties, path('Properties'))
metadata_deps = strict_func_deps(self._metadata, path('Metadata'))
# (ricolin) External resource should not depend on any other resources.
# This operation is not allowed for now.
@ -242,7 +241,7 @@ class ResourceDefinitionCore(object):
"""
return properties.Properties(schema, self._properties or {},
function.resolve, self.name, context,
section=PROPERTIES)
section='Properties')
def deletion_policy(self):
"""Return the deletion policy for the resource.
@ -259,7 +258,7 @@ class ResourceDefinitionCore(object):
"""
return properties.Properties(schema, self._update_policy or {},
function.resolve, self.name, context,
section=UPDATE_POLICY)
section='UpdatePolicy')
def metadata(self):
"""Return the resource metadata."""
@ -307,7 +306,7 @@ class ResourceDefinitionCore(object):
Return a Diff object that can be used to establish differences between
this definition and a previous definition of the same resource.
"""
if not isinstance(previous, ResourceDefinitionCore):
if not isinstance(previous, ResourceDefinition):
return NotImplemented
return self.Diff(previous, self)
@ -320,7 +319,7 @@ class ResourceDefinitionCore(object):
ignored, as are the actual values that any included functions resolve
to.
"""
if not isinstance(other, ResourceDefinitionCore):
if not isinstance(other, ResourceDefinition):
return NotImplemented
return self.render_hot() == other.render_hot()
@ -362,120 +361,6 @@ class ResourceDefinitionCore(object):
return '%(classname)s(%(name)s, %(type)s, %(args)s)' % data
_KEYS = (
TYPE, PROPERTIES, METADATA, DELETION_POLICY, UPDATE_POLICY,
DEPENDS_ON, DESCRIPTION,
) = (
'Type', 'Properties', 'Metadata', 'DeletionPolicy', 'UpdatePolicy',
'DependsOn', 'Description',
)
class ResourceDefinition(ResourceDefinitionCore, collections.Mapping):
"""A resource definition that also acts like a cfn template snippet.
This class exists only for backwards compatibility with existing resource
plugins and unit tests; it is deprecated and will be replaced with
ResourceDefinitionCore, possibly as soon as the Ocata release.
"""
_deprecation_msg = (
'Reading the ResourceDefinition as if it were a snippet of a '
'CloudFormation template is deprecated, and the ability to treat it '
'as such will be removed in the future. Resource plugins should use '
'the ResourceDefinition API to work with the definition of the '
'resource instance.')
def __eq__(self, other):
"""Compare this resource definition for equality with another.
Two resource definitions are considered to be equal if they can be
generated from the same template snippet. The name of the resource is
ignored, as are the actual values that any included functions resolve
to.
This method can also compare the resource definition to a template
snippet. In this case, two snippets are considered equal if they
compare equal in a dictionary comparison. (Specifically, this means
that intrinsic functions are compared by their results.) This exists
solely to not break existing unit tests.
"""
if not isinstance(other, ResourceDefinitionCore):
if isinstance(other, collections.Mapping):
return dict(self) == other
return super(ResourceDefinition, self).__eq__(other)
__hash__ = ResourceDefinitionCore.__hash__
def __iter__(self):
"""Iterate over the available CFN template keys.
This is for backwards compatibility with existing code that expects a
parsed-JSON template snippet.
"""
warnings.warn(self._deprecation_msg, DeprecationWarning)
yield TYPE
if self._properties is not None:
yield PROPERTIES
if self._metadata is not None:
yield METADATA
if self._deletion_policy is not None:
yield DELETION_POLICY
if self._update_policy is not None:
yield UPDATE_POLICY
if self._depends:
yield DEPENDS_ON
if self.description:
yield DESCRIPTION
def __getitem__(self, key):
"""Get the specified item from a CFN template snippet.
This is for backwards compatibility with existing code that expects a
parsed-JSON template snippet.
"""
warnings.warn(self._deprecation_msg, DeprecationWarning)
if key == TYPE:
return self.resource_type
elif key == PROPERTIES:
if self._properties is not None:
return self._properties
elif key == METADATA:
if self._metadata is not None:
return self._metadata
elif key == DELETION_POLICY:
if self._deletion_policy is not None:
return self._deletion_policy
elif key == UPDATE_POLICY:
if self._update_policy is not None:
return self._update_policy
elif key == DEPENDS_ON:
if self._depends:
if len(self._depends) == 1:
return self._depends[0]
return self._depends
elif key == DESCRIPTION:
if self.description:
return self.description
raise KeyError(key)
def __len__(self):
"""Return the number of available CFN template keys.
This is for backwards compatibility with existing code that expects a
parsed-JSON template snippet.
"""
return len(list(iter(self)))
def __repr__(self):
"""Return a string representation of the resource definition."""
return 'ResourceDefinition %s' % repr(dict(self))
def _hash_data(data):
"""Return a stable hash value for an arbitrary parsed-JSON data snippet."""
if isinstance(data, function.Function):

View File

@ -12,7 +12,6 @@
# under the License.
import six
import warnings
from heat.common import exception
from heat.common import template_format
@ -282,45 +281,3 @@ class ResourceDefinitionDiffTest(common.HeatTestCase):
self.assertFalse(diff.update_policy_changed())
self.assertFalse(diff.metadata_changed())
self.assertFalse(diff)
class ResourceDefinitionSnippetTest(common.HeatTestCase):
scenarios = [
('type',
dict(
defn={},
expected={})),
('metadata',
dict(
defn={'metadata': {'Foo': 'bar'}},
expected={'Metadata': {'Foo': 'bar'}})),
('properties',
dict(
defn={'properties': {'Foo': 'bar'}},
expected={'Properties': {'Foo': 'bar'}})),
('deletion_policy',
dict(
defn={'deletion_policy': rsrc_defn.ResourceDefinition.RETAIN},
expected={'DeletionPolicy': 'Retain'})),
('update_policy',
dict(
defn={'update_policy': {'Foo': 'bar'}},
expected={'UpdatePolicy': {'Foo': 'bar'}}))
]
def test_resource_snippet(self):
rd = rsrc_defn.ResourceDefinition('rsrc', 'SomeType', **self.defn)
with warnings.catch_warnings(record=True) as ws:
warnings.filterwarnings('always')
# Work around http://bugs.python.org/issue4180
getattr(rsrc_defn, '__warningregistry__', {}).clear()
exp_result = {'Type': 'SomeType'}
exp_result.update(self.expected)
self.assertEqual(exp_result, rd)
self.assertTrue(ws)
for warn in ws:
self.assertTrue(issubclass(warn.category, DeprecationWarning))