Improved merging of null-values
YAML returns 'None' when a key is parsed without a value. This is
properly handled by a95eaa35f5c48417420fe37472d8148fdbf5ddd5, except for
the recursive dict merger, which shouldn't overwrite existing data
structures when None is encountered. The solution is simply to provide
appropriate policy entries for when the second value is a NoneType.
Signed-off-by: martin f. krafft <madduck@madduck.net>
diff --git a/mergers/dict/recursive_policy_update.py b/mergers/dict/recursive_policy_update.py
index 01dfccb..e280889 100644
--- a/mergers/dict/recursive_policy_update.py
+++ b/mergers/dict/recursive_policy_update.py
@@ -13,10 +13,15 @@
def __init__(self, policy=None):
super(DictRecursivePolicyUpdate, self).__init__()
if policy is None:
- policy = {(dict,dict) : self.merge,
- (list,list) : lambda x,y: x+y,
- (dict,list) : lambda x,y: self.merge(x, dict(y)),
- None : lambda x,y: y
+ first = lambda first, second: first
+ second = lambda first, second: second
+
+ policy = {(dict,dict) : self.merge,
+ (list,list) : lambda x,y: x+y,
+ (dict,list) : lambda x,y: self.merge(x, dict(y)),
+ (dict,type(None)) : first,
+ (list,type(None)) : first,
+ None : second
}
self._policy = policy
@@ -27,8 +32,8 @@
ret = first.copy()
for k,v in second.iteritems():
if k in ret:
- pfn = self._policy.get((type(ret[k]), type(v)),
- self._policy.get(None))
+ lookup = (type(ret[k]), type(v))
+ pfn = self._policy.get(lookup, self._policy.get(None))
ret[k] = pfn(ret[k], v)
else:
ret[k] = v
diff --git a/storage/yaml_fs/tests/classes/debiannode.yml b/storage/yaml_fs/tests/classes/debiannode.yml
index 43e35e4..84837ff 100644
--- a/storage/yaml_fs/tests/classes/debiannode.yml
+++ b/storage/yaml_fs/tests/classes/debiannode.yml
@@ -2,3 +2,6 @@
- basenode
applications:
- apt
+parameters:
+ apt:
+ mirror_base: http://http.debian.net
diff --git a/storage/yaml_fs/tests/nodes/red.yml b/storage/yaml_fs/tests/nodes/red.yml
index 5fe618d..051d0f5 100644
--- a/storage/yaml_fs/tests/nodes/red.yml
+++ b/storage/yaml_fs/tests/nodes/red.yml
@@ -3,6 +3,7 @@
- hosted@zurich
- webserver
parameters:
+ apt: # null-value must not override inherited dictionary
motd:
greeting: This node is $nodename
colour: red
diff --git a/storage/yaml_fs/tests/test_yaml_fs.py b/storage/yaml_fs/tests/test_yaml_fs.py
index bb4ba12..89ae294 100644
--- a/storage/yaml_fs/tests/test_yaml_fs.py
+++ b/storage/yaml_fs/tests/test_yaml_fs.py
@@ -63,3 +63,7 @@
assert 'applications' in node
assert 'classes' in node
assert 'parameters' in node
+
+ def test_merge_empty_dict(self):
+ node = self._storage.nodeinfo(HOSTS[0])
+ assert node['parameters'].get('apt') is not None