Don't override sections in deep_update
When you comment all the elements in a YAML mapping, you end up with
None instead of an empty mapping, which can have bad side effect when
handling multiple environemnents. Let's handle that by ignoring the
latest None value.
MODIFY
heatclient/common/template_utils.py
heatclient/common/template_utils.py
@@ -198,6 +198,9 @@ def deep_update(old, new):
if isinstance(v, collections.Mapping):
r = deep_update(old.get(k, {}), v)
old[k] = r
+ elif v is None and isinstance(old.get(k), collections.Mapping):
+ # Don't override empty data, to work around yaml syntax issue
+ pass
else:
old[k] = new[k]
return old

MODIFY
heatclient/tests/unit/test_template_utils.py
heatclient/tests/unit/test_template_utils.py
@@ -448,6 +448,51 @@ class ShellEnvironmentTest(testtools.TestCase):
])
+ @mock.patch('six.moves.urllib.request.urlopen')
+ def test_process_multiple_environments_empty_registry(self, mock_url):
+ # Setup
+ env_file1 = '/home/my/dir/env1.yaml'
+ env_file2 = '/home/my/dir/env2.yaml'
+
+ env1 = b'''
+ resource_registry:
+ "OS::Thingy1": "file:///home/b/a.yaml"
+ '''
+ env2 = b'''
+ resource_registry:
+ '''
+ mock_url.side_effect = [six.BytesIO(env1),
+ six.BytesIO(self.template_a),
+ six.BytesIO(self.template_a),
+ six.BytesIO(env2)]
+
+ # Test
+ env_file_list = []
+ files, env = template_utils.process_multiple_environments_and_files(
+ [env_file1, env_file2], env_list_tracker=env_file_list)
+
+ # Verify
+ expected_env = {
+ 'resource_registry': {'OS::Thingy1': 'file:///home/b/a.yaml'}}
+ self.assertEqual(expected_env, env)
+
+ self.assertEqual(self.template_a.decode('utf-8'),
+ files['file:///home/b/a.yaml'])
+
+ self.assertEqual(['file:///home/my/dir/env1.yaml',
+ 'file:///home/my/dir/env2.yaml'], env_file_list)
+ self.assertIn('file:///home/my/dir/env1.yaml', files)
+ self.assertIn('file:///home/my/dir/env2.yaml', files)
+ self.assertEqual(expected_env,
+ json.loads(files['file:///home/my/dir/env1.yaml']))
+ mock_url.assert_has_calls([
+ mock.call('file://%s' % env_file1),
+ mock.call('file:///home/b/a.yaml'),
+ mock.call('file:///home/b/a.yaml'),
+ mock.call('file://%s' % env_file2),
+
+ ])
+
def test_global_files(self):
url = 'file:///home/b/a.yaml'
env = '''

Don't override sections in deep_update

When you comment all the elements in a YAML mapping, you end up with
None instead of an empty mapping, which can have bad side effect when
handling multiple environemnents. Let's handle that by ignoring the
latest None value.

Change-Id: I77ffabeb8d4cd2886ef4f41351e42ebe487b5d4b