import os.path import glob import random import string from bootstrapvz.common.tools import load_data partial_json = glob.glob(os.path.join(os.path.dirname(__file__), '*.yml')) partial_yaml = glob.glob(os.path.join(os.path.dirname(__file__), '*.json')) partials = {} for path in partial_json + partial_yaml: key = os.path.splitext(os.path.basename(path))[0] if key in partials: msg = 'Error when loading partial manifests: The partial {key} exists twice'.format(key=key) raise Exception(msg) partials[key] = load_data(path) pool = string.ascii_uppercase + string.ascii_lowercase + string.digits random_password = ''.join(random.choice(pool) for _ in range(16)) partials['root_password']['plugins']['root_password']['password'] = random_password def merge_manifest_data(standard_partials=[], custom=[]): import yaml manifest_data = [partials[name] for name in standard_partials] manifest_data.extend(yaml.load(data) for data in custom) return merge_dicts(*manifest_data) # Snatched from here: http://stackoverflow.com/a/7205107 def merge_dicts(*args): def clone(obj): copy = obj if isinstance(obj, dict): copy = {key: clone(value) for key, value in obj.iteritems()} if isinstance(obj, list): copy = [clone(value) for value in obj] if isinstance(obj, set): copy = set([clone(value) for value in obj]) return copy def merge(a, b, path=[]): # pylint: disable=redefined-outer-name for key in b: # pylint: disable=redefined-outer-name if key in a: if isinstance(a[key], dict) and isinstance(b[key], dict): merge(a[key], b[key], path + [str(key)]) elif a[key] == b[key]: pass else: raise Exception('Conflict at `{path}\''.format(path='.'.join(path + [str(key)]))) else: a[key] = clone(b[key]) return a return reduce(merge, args, {})