summaryrefslogtreecommitdiffstats
path: root/meta-phosphor/common/recipes-phosphor/settings
diff options
context:
space:
mode:
authorXo Wang <xow@google.com>2017-03-17 18:15:10 -0700
committerPatrick Williams <patrick@stwcx.xyz>2017-04-09 12:00:50 +0000
commit49abd7e85f349a795e9eb9be65bdb8ac0da43897 (patch)
treea53f5a5ea756544b1008e10904e1dc0c965bc4d6 /meta-phosphor/common/recipes-phosphor/settings
parent615bdc1ef73ea08b92745c3985eb0e7654769fd3 (diff)
downloadtalos-openbmc-49abd7e85f349a795e9eb9be65bdb8ac0da43897.tar.gz
talos-openbmc-49abd7e85f349a795e9eb9be65bdb8ac0da43897.zip
phosphor-settings: Add task to handle settings overrides
Add a BitBake task that merges YAML fragments that overwrite the default settings YAML file. These fragments have the suffix ".override.yml" and allow e.g. machine layers to override the values in settings.yaml without replacing its entire contents. Fixes openbmc/openbmc#1269. Signed-off-by: Xo Wang <xow@google.com> Change-Id: I8d463630deee74ed6d5c18aa98e837a6ca7f7633
Diffstat (limited to 'meta-phosphor/common/recipes-phosphor/settings')
-rw-r--r--meta-phosphor/common/recipes-phosphor/settings/phosphor-settings.bb29
-rwxr-xr-xmeta-phosphor/common/recipes-phosphor/settings/phosphor-settings/merge_settings.py58
2 files changed, 87 insertions, 0 deletions
diff --git a/meta-phosphor/common/recipes-phosphor/settings/phosphor-settings.bb b/meta-phosphor/common/recipes-phosphor/settings/phosphor-settings.bb
index 686f3c083..d03eca86d 100644
--- a/meta-phosphor/common/recipes-phosphor/settings/phosphor-settings.bb
+++ b/meta-phosphor/common/recipes-phosphor/settings/phosphor-settings.bb
@@ -7,6 +7,7 @@ inherit allarch
inherit obmc-phosphor-license
inherit setuptools
inherit obmc-phosphor-dbus-service
+inherit pythonnative
DBUS_SERVICE_${PN} = "org.openbmc.settings.Host.service"
@@ -16,7 +17,35 @@ PROVIDES += "virtual/obmc-settings-mgmt"
RPROVIDES_${PN} += "virtual-obmc-settings-mgmt"
SRC_URI += "git://github.com/openbmc/phosphor-settingsd"
+SRC_URI += "file://merge_settings.py"
SRCREV = "3b8d055ca761a68c74dad01a306f238674d71878"
S = "${WORKDIR}/git"
+
+# Collect files in SRC_URI that end in ".override.yml" and call a script that
+# writes their contents over that of settings.yaml, which is then updated to
+# the merged data values.
+# This doesn't correctly handle globs in ".override.yml" entries in SRC_URI.
+python do_merge_settings () {
+ import subprocess
+
+ # TODO: Perform the merge in a temporary directory?
+ workdir = d.getVar('WORKDIR', True)
+ cmd = []
+ cmd.append(os.path.join(workdir, 'merge_settings.py'))
+ cmd.append(os.path.join(d.getVar('S', True), 'settings.yaml'))
+
+ fetch = bb.fetch2.Fetch([], d)
+ override_urls = filter(lambda f: f.endswith('.override.yml'), fetch.urls)
+ for url in override_urls:
+ bb.debug(2, 'Overriding with source: ' + url)
+ local_base = os.path.basename(fetch.localpath(url))
+ filename = os.path.join(workdir, local_base)
+ cmd.append(filename)
+
+ # Invoke the script and don't catch any resulting exception.
+ subprocess.check_call(cmd)
+}
+# python-pyyaml-native is installed by do_configure, so put this task after
+addtask merge_settings after do_configure before do_compile
diff --git a/meta-phosphor/common/recipes-phosphor/settings/phosphor-settings/merge_settings.py b/meta-phosphor/common/recipes-phosphor/settings/phosphor-settings/merge_settings.py
new file mode 100755
index 000000000..01f5e3552
--- /dev/null
+++ b/meta-phosphor/common/recipes-phosphor/settings/phosphor-settings/merge_settings.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python
+"""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
+
+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.iteritems():
+ 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()
+
+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)
+ print('Wrote merged target YAML file ' + target_filename)
OpenPOWER on IntegriCloud