deb-heat/heat/tests/test_rsrc_defn.py
Zane Bitter 75b56789e6 Implement diffs of ResourceDefinitions
The last remaining code using the deprecated methods in the
ResourceDefinition class to treat the definition like a CloudFormation
template snippet is the tmpl_diff in the Resource class. Replace the dict
diff with a Diff object that has an API which can be queried instead. For
backward compatibility with existing resource plugins, the current diff
objects are for now able to be treated like dicts. However, this is marked
deprecated and can be removed along with the equivalent support for
ResourceDefinitions in the future.

Change-Id: I9ef50f0d9b142d464a1b02da7a46536c532d2ebd
2016-04-13 19:49:04 -04:00

360 lines
15 KiB
Python

#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import six
import warnings
from heat.common import exception
from heat.engine.cfn import functions as cfn_funcs
from heat.engine.hot import functions as hot_funcs
from heat.engine import properties
from heat.engine import rsrc_defn
from heat.tests import common
class ResourceDefinitionTest(common.HeatTestCase):
def make_me_one_with_everything(self):
return rsrc_defn.ResourceDefinition(
'rsrc', 'SomeType',
properties={'Foo': cfn_funcs.Join(None,
'Fn::Join',
['a', ['b', 'r']]),
'Blarg': 'wibble'},
metadata={'Baz': cfn_funcs.Join(None,
'Fn::Join',
['u', ['q', '', 'x']])},
depends=['other_resource'],
deletion_policy='Retain',
update_policy={'SomePolicy': {}})
def test_properties_default(self):
rd = rsrc_defn.ResourceDefinition('rsrc', 'SomeType')
self.assertEqual({}, rd.properties({}))
def test_properties(self):
rd = self.make_me_one_with_everything()
schema = {
'Foo': properties.Schema(properties.Schema.STRING),
'Blarg': properties.Schema(properties.Schema.STRING, default=''),
'Baz': properties.Schema(properties.Schema.STRING, default='quux'),
}
props = rd.properties(schema)
self.assertEqual('bar', props['Foo'])
self.assertEqual('wibble', props['Blarg'])
self.assertEqual('quux', props['Baz'])
def test_metadata_default(self):
rd = rsrc_defn.ResourceDefinition('rsrc', 'SomeType')
self.assertEqual({}, rd.metadata())
def test_metadata(self):
rd = self.make_me_one_with_everything()
metadata = rd.metadata()
self.assertEqual({'Baz': 'quux'}, metadata)
self.assertIsInstance(metadata['Baz'], six.string_types)
def test_dependencies_default(self):
rd = rsrc_defn.ResourceDefinition('rsrc', 'SomeType')
stack = {'foo': 'FOO', 'bar': 'BAR'}
self.assertEqual([], list(rd.dependencies(stack)))
def test_dependencies_explicit(self):
rd = rsrc_defn.ResourceDefinition('rsrc', 'SomeType', depends=['foo'])
stack = {'foo': 'FOO', 'bar': 'BAR'}
self.assertEqual(['FOO'], list(rd.dependencies(stack)))
def test_dependencies_explicit_invalid(self):
rd = rsrc_defn.ResourceDefinition('rsrc', 'SomeType', depends=['baz'])
stack = {'foo': 'FOO', 'bar': 'BAR'}
self.assertRaises(exception.InvalidTemplateReference,
lambda: list(rd.dependencies(stack)))
def test_deletion_policy_default(self):
rd = rsrc_defn.ResourceDefinition('rsrc', 'SomeType')
self.assertEqual(rsrc_defn.ResourceDefinition.DELETE,
rd.deletion_policy())
def test_deletion_policy(self):
for policy in rsrc_defn.ResourceDefinition.DELETION_POLICIES:
rd = rsrc_defn.ResourceDefinition('rsrc', 'SomeType',
deletion_policy=policy)
self.assertEqual(policy, rd.deletion_policy())
def test_deletion_policy_invalid(self):
self.assertRaises(AssertionError,
rsrc_defn.ResourceDefinition,
'rsrc', 'SomeType', deletion_policy='foo')
def test_update_policy_default(self):
rd = rsrc_defn.ResourceDefinition('rsrc', 'SomeType')
self.assertEqual({}, rd.update_policy({}))
def test_update_policy(self):
rd = self.make_me_one_with_everything()
policy_schema = {'Foo': properties.Schema(properties.Schema.STRING,
default='bar')}
schema = {
'SomePolicy': properties.Schema(properties.Schema.MAP,
schema=policy_schema),
}
up = rd.update_policy(schema)
self.assertEqual('bar', up['SomePolicy']['Foo'])
def test_freeze(self):
rd = self.make_me_one_with_everything()
frozen = rd.freeze()
self.assertEqual('bar', frozen._properties['Foo'])
self.assertEqual('quux', frozen._metadata['Baz'])
def test_freeze_override(self):
rd = self.make_me_one_with_everything()
frozen = rd.freeze(metadata={'Baz': 'wibble'})
self.assertEqual('bar', frozen._properties['Foo'])
self.assertEqual('wibble', frozen._metadata['Baz'])
def test_render_hot(self):
rd = self.make_me_one_with_everything()
expected_hot = {
'type': 'SomeType',
'properties': {'Foo': {'Fn::Join': ['a', ['b', 'r']]},
'Blarg': 'wibble'},
'metadata': {'Baz': {'Fn::Join': ['u', ['q', '', 'x']]}},
'depends_on': ['other_resource'],
'deletion_policy': 'Retain',
'update_policy': {'SomePolicy': {}},
}
self.assertEqual(expected_hot, rd.render_hot())
def test_render_hot_empty(self):
rd = rsrc_defn.ResourceDefinition('rsrc', 'SomeType')
expected_hot = {
'type': 'SomeType',
}
self.assertEqual(expected_hot, rd.render_hot())
def test_template_equality(self):
class FakeStack(object):
def __init__(self, params):
self.parameters = params
def get_param_defn(value):
stack = FakeStack({'Foo': value})
param_func = hot_funcs.GetParam(stack, 'get_param', 'Foo')
return rsrc_defn.ResourceDefinition('rsrc', 'SomeType',
{'Foo': param_func})
self.assertEqual(get_param_defn('bar'), get_param_defn('baz'))
def test_hash_equal(self):
rd1 = self.make_me_one_with_everything()
rd2 = self.make_me_one_with_everything()
self.assertEqual(rd1, rd2)
self.assertEqual(hash(rd1), hash(rd2))
def test_hash_names(self):
rd1 = rsrc_defn.ResourceDefinition('rsrc1', 'SomeType')
rd2 = rsrc_defn.ResourceDefinition('rsrc2', 'SomeType')
self.assertEqual(rd1, rd2)
self.assertEqual(hash(rd1), hash(rd2))
def test_hash_types(self):
rd1 = rsrc_defn.ResourceDefinition('rsrc', 'SomeType1')
rd2 = rsrc_defn.ResourceDefinition('rsrc', 'SomeType2')
self.assertNotEqual(rd1, rd2)
self.assertNotEqual(hash(rd1), hash(rd2))
class ResourceDefinitionDiffTest(common.HeatTestCase):
def test_properties_diff(self):
before = rsrc_defn.ResourceDefinition('rsrc', 'SomeType',
properties={'Foo': 'blarg'},
update_policy={'baz': 'quux'},
metadata={'baz': 'quux'})
after = rsrc_defn.ResourceDefinition('rsrc', 'SomeType',
properties={'Foo': 'wibble'},
update_policy={'baz': 'quux'},
metadata={'baz': 'quux'})
diff = after - before
self.assertTrue(diff.properties_changed())
self.assertFalse(diff.update_policy_changed())
self.assertFalse(diff.metadata_changed())
self.assertTrue(diff)
def test_update_policy_diff(self):
before = rsrc_defn.ResourceDefinition('rsrc', 'SomeType',
properties={'baz': 'quux'},
update_policy={'Foo': 'blarg'},
metadata={'baz': 'quux'})
after = rsrc_defn.ResourceDefinition('rsrc', 'SomeType',
properties={'baz': 'quux'},
update_policy={'Foo': 'wibble'},
metadata={'baz': 'quux'})
diff = after - before
self.assertFalse(diff.properties_changed())
self.assertTrue(diff.update_policy_changed())
self.assertFalse(diff.metadata_changed())
self.assertTrue(diff)
def test_metadata_diff(self):
before = rsrc_defn.ResourceDefinition('rsrc', 'SomeType',
properties={'baz': 'quux'},
update_policy={'baz': 'quux'},
metadata={'Foo': 'blarg'})
after = rsrc_defn.ResourceDefinition('rsrc', 'SomeType',
properties={'baz': 'quux'},
update_policy={'baz': 'quux'},
metadata={'Foo': 'wibble'})
diff = after - before
self.assertFalse(diff.properties_changed())
self.assertFalse(diff.update_policy_changed())
self.assertTrue(diff.metadata_changed())
self.assertTrue(diff)
def test_no_diff(self):
before = rsrc_defn.ResourceDefinition('rsrc', 'SomeType',
properties={'Foo': 'blarg'},
update_policy={'bar': 'quux'},
metadata={'baz': 'wibble'},
depends=['other_resource'],
deletion_policy='Delete')
after = rsrc_defn.ResourceDefinition('rsrc', 'SomeType',
properties={'Foo': 'blarg'},
update_policy={'bar': 'quux'},
metadata={'baz': 'wibble'},
depends=['other_other_resource'],
deletion_policy='Retain')
diff = after - before
self.assertFalse(diff.properties_changed())
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))
class ResourceDefinitionDiffSnippetTest(common.HeatTestCase):
def test_properties_diff(self):
before = rsrc_defn.ResourceDefinition('rsrc', 'SomeType',
properties={'Foo': 'blarg'},
update_policy={'baz': 'quux'},
metadata={'baz': 'quux'})
after = rsrc_defn.ResourceDefinition('rsrc', 'SomeType',
properties={'Foo': 'wibble'},
update_policy={'baz': 'quux'},
metadata={'baz': 'quux'})
diff = after - before
self.assertEqual({'Properties': after['Properties']}, dict(diff))
def test_update_policy_diff(self):
before = rsrc_defn.ResourceDefinition('rsrc', 'SomeType',
properties={'baz': 'quux'},
update_policy={'Foo': 'blarg'},
metadata={'baz': 'quux'})
after = rsrc_defn.ResourceDefinition('rsrc', 'SomeType',
properties={'baz': 'quux'},
update_policy={'Foo': 'wibble'},
metadata={'baz': 'quux'})
diff = after - before
self.assertEqual({'UpdatePolicy': after['UpdatePolicy']}, dict(diff))
def test_metadata_diff(self):
before = rsrc_defn.ResourceDefinition('rsrc', 'SomeType',
properties={'baz': 'quux'},
update_policy={'baz': 'quux'},
metadata={'Foo': 'blarg'})
after = rsrc_defn.ResourceDefinition('rsrc', 'SomeType',
properties={'baz': 'quux'},
update_policy={'baz': 'quux'},
metadata={'Foo': 'wibble'})
diff = after - before
self.assertEqual({'Metadata': after['Metadata']}, dict(diff))
def test_all_diff(self):
before = rsrc_defn.ResourceDefinition('rsrc', 'SomeType',
properties={'Foo': 'blarg'},
update_policy={'bar': 'quux'},
metadata={'baz': 'wibble'},
depends=['other_resource'],
deletion_policy='Delete')
after = rsrc_defn.ResourceDefinition('rsrc', 'SomeType',
properties={'Foo': 'wibble'},
update_policy={'bar': 'blarg'},
metadata={'baz': 'quux'},
depends=['other_other_resource'],
deletion_policy='Retain')
diff = after - before
self.assertEqual({'Properties': after['Properties'],
'UpdatePolicy': after['UpdatePolicy'],
'Metadata': after['Metadata']},
dict(diff))