Dhruvaraj Subhashchandran | a03c56d | 2017-07-12 06:45:14 -0500 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | """Copied from phosphor-settings-manager |
| 3 | Loads a "target" YAML file and overwrites its values with values from |
| 4 | "override" YAML files. |
| 5 | |
| 6 | Override files are processed in the order given. |
| 7 | |
| 8 | Usage: |
| 9 | merge_settings.py <target yaml> [override yamls] |
| 10 | """ |
| 11 | import sys |
| 12 | import yaml |
| 13 | import copy |
| 14 | |
Santosh Puranik | 7106ecf | 2019-07-11 14:04:39 +0530 | [diff] [blame] | 15 | # Custom representer for None types. This is to handle empty dictionaries. |
| 16 | # By default Pyyaml outputs these as "null", whereas we want an empty character. |
| 17 | def represent_none(self, _): |
| 18 | return self.represent_scalar('tag:yaml.org,2002:null', '') |
| 19 | |
Dhruvaraj Subhashchandran | a03c56d | 2017-07-12 06:45:14 -0500 | [diff] [blame] | 20 | def dict_merge(target, source): |
| 21 | """Deep merge for dicts. |
| 22 | |
| 23 | Works like dict.update() that recursively updates any dict values present in |
| 24 | both parameters. |
| 25 | |
| 26 | Args: |
| 27 | target (dict): Values to be overwritten by corresponding values from |
| 28 | `source`. |
| 29 | source (dict): Overriding values. Not changed by call. |
| 30 | |
| 31 | Returns: |
| 32 | `target` with values overwritten from those in `source` at any and all |
| 33 | levels of nested dicts. |
| 34 | """ |
| 35 | if not isinstance(source, dict): |
| 36 | return source |
| 37 | for k, v in source.iteritems(): |
| 38 | if k in target and isinstance(target[k], dict): |
| 39 | dict_merge(target[k], v) |
| 40 | else: |
| 41 | target[k] = copy.deepcopy(v) |
| 42 | return target |
| 43 | |
| 44 | if len(sys.argv) < 2: |
| 45 | sys.exit('Argument required: target yaml') |
| 46 | |
| 47 | if len(sys.argv) == 2: |
| 48 | # No overrides to handle |
| 49 | sys.exit(0) |
| 50 | |
Santosh Puranik | 7106ecf | 2019-07-11 14:04:39 +0530 | [diff] [blame] | 51 | yaml.add_representer(type(None), represent_none) |
| 52 | |
Dhruvaraj Subhashchandran | a03c56d | 2017-07-12 06:45:14 -0500 | [diff] [blame] | 53 | target_filename = sys.argv[1] |
| 54 | with open(target_filename) as target_file: |
| 55 | data = yaml.safe_load(target_file) |
| 56 | print('Loaded target YAML file ' + target_filename) |
| 57 | |
| 58 | for override_filename in sys.argv[2:]: |
| 59 | with open(override_filename) as override_file: |
| 60 | override = yaml.safe_load(override_file) |
| 61 | dict_merge(data, override) |
| 62 | print('Merged override YAML file ' + override_filename) |
| 63 | |
| 64 | with open(target_filename, 'w') as target_file: |
| 65 | yaml.dump(data, target_file, default_flow_style=False) |
| 66 | print('Wrote merged target YAML file ' + target_filename) |