67 lines
2.0 KiB
Python
67 lines
2.0 KiB
Python
|
|
#!/usr/bin/env python3
|
||
|
|
"""Copied from phosphor-settings-manager
|
||
|
|
Loads a "target" YAML file and overwrites its values with values from
|
||
|
|
"override" YAML files.
|
||
|
|
|
||
|
|
Override files are processed in the order given.
|
||
|
|
|
||
|
|
Usage:
|
||
|
|
merge_settings.py <target yaml> [override yamls]
|
||
|
|
"""
|
||
|
|
import sys
|
||
|
|
import yaml
|
||
|
|
import copy
|
||
|
|
|
||
|
|
# Custom representer for None types. This is to handle empty dictionaries.
|
||
|
|
# By default Pyyaml outputs these as "null", whereas we want an empty character.
|
||
|
|
def represent_none(self, _):
|
||
|
|
return self.represent_scalar('tag:yaml.org,2002:null', '')
|
||
|
|
|
||
|
|
def dict_merge(target, source):
|
||
|
|
"""Deep merge for dicts.
|
||
|
|
|
||
|
|
Works like dict.update() that recursively updates any dict values present in
|
||
|
|
both parameters.
|
||
|
|
|
||
|
|
Args:
|
||
|
|
target (dict): Values to be overwritten by corresponding values from
|
||
|
|
`source`.
|
||
|
|
source (dict): Overriding values. Not changed by call.
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
`target` with values overwritten from those in `source` at any and all
|
||
|
|
levels of nested dicts.
|
||
|
|
"""
|
||
|
|
if not isinstance(source, dict):
|
||
|
|
return source
|
||
|
|
for k, v in source.items():
|
||
|
|
if k in target and isinstance(target[k], dict):
|
||
|
|
dict_merge(target[k], v)
|
||
|
|
else:
|
||
|
|
target[k] = copy.deepcopy(v)
|
||
|
|
return target
|
||
|
|
|
||
|
|
if len(sys.argv) < 2:
|
||
|
|
sys.exit('Argument required: target yaml')
|
||
|
|
|
||
|
|
if len(sys.argv) == 2:
|
||
|
|
# No overrides to handle
|
||
|
|
sys.exit(0)
|
||
|
|
|
||
|
|
yaml.add_representer(type(None), represent_none)
|
||
|
|
|
||
|
|
target_filename = sys.argv[1]
|
||
|
|
with open(target_filename) as target_file:
|
||
|
|
data = yaml.safe_load(target_file)
|
||
|
|
print('Loaded target YAML file ' + target_filename)
|
||
|
|
|
||
|
|
for override_filename in sys.argv[2:]:
|
||
|
|
with open(override_filename) as override_file:
|
||
|
|
override = yaml.safe_load(override_file)
|
||
|
|
dict_merge(data, override)
|
||
|
|
print('Merged override YAML file ' + override_filename)
|
||
|
|
|
||
|
|
with open(target_filename, 'w') as target_file:
|
||
|
|
yaml.dump(data, target_file, default_flow_style=False)
|
||
|
|
print('Wrote merged target YAML file ' + target_filename)
|