Add in the capability to merge two config dicts (so that manually set settings aren't overwritten).

This commit is contained in:
Mike Auty
2017-07-20 00:49:36 +01:00
parent fe66301cf3
commit 03cdd91fbf
3 changed files with 33 additions and 1 deletions
+11
View File
@@ -48,6 +48,9 @@ class CommandLine(object):
description = "An open-source memory forensics framework")
parser.add_argument("-c", "--config", help = "Load the configuration from a json file", default = None,
type = str)
parser.add_argument("-e", "--extend", help = "Extend the configuration with a new (or changed) setting",
default = None,
action = 'append')
parser.add_argument("-p", "--plugins", help = "Semi-colon separated list of paths to find plugins",
default = "", type = str)
parser.add_argument("-v", "--verbosity", help = "Increase output verbosity", default = 0, action = "count")
@@ -134,6 +137,14 @@ class CommandLine(object):
extended_path = interfaces.configuration.path_join(config_path, requirement.name)
ctx.config[extended_path] = value
if args.extend:
for extension in args.extend:
if '=' not in extension:
raise ValueError(
"Invalid extension (extensions must be of the format \"conf.path.value='value'\")")
address, value = extension[:extension.find('=')], json.loads(extension[extension.find('=') + 1:])
ctx.config[address] = value
###
# BACK TO THE FRAMEWORK
###
+3 -1
View File
@@ -100,7 +100,9 @@ class LayerStacker(interfaces.automagic.AutomagicInterface):
if result:
path, layer = result
# splice in the new configuration into the original context
context.config.splice(path, new_context.memory[layer].build_configuration())
print("BEFORE", dict(context.config))
context.config.merge(path, new_context.memory[layer].build_configuration())
print("AFTER ", dict(context.config))
# Call the construction magic now we may have new things to construct
constructor = construct_layers.ConstructionMagic(context,
interfaces.configuration.path_join(self.config_path,
@@ -186,6 +186,25 @@ class HierarchicalDict(collections.abc.Mapping):
raise TypeError("Splice requires a string key and HierarchicalDict value")
self._setitem(key, value, False)
def merge(self, key, value, overwrite = False):
"""Acts similarly to splice, but maintains previous values
If overwrite is true, then entries in the new value are used over those that exist within key already
@param key: The location within the hierarchy at which to merge the `value`
@type key: str
@param value: HierarchicalDict to be merged under the key node
@type value: HierarchicalDict
"""
if not isinstance(key, str) or not isinstance(value, HierarchicalDict):
raise TypeError("Splice requires a string key and HierarchicalDict value")
for item in dict(value):
if self.get(key + self._separator + item, None):
if overwrite:
self[key + self._separator + item] = value[item]
else:
self[key + self._separator + item] = value[item]
def clone(self):
"""Duplicates the configuration, allowing changes without affecting the original"""
return copy.deepcopy(self)