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
This commit is contained in:
Thomas Herve 2017-10-03 16:10:29 +02:00
parent bfa77b57c6
commit 2a8ce0d065
2 changed files with 48 additions and 0 deletions

View File

@ -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

View File

@ -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 = '''