#!/usr/bin/env python import os import sys import datetime import yaml def contexts(device, config_contexts): # print(f'device: {device}') all_config_contexts = {} def remove_meta(data): try: del data['_metadata'] except KeyError: pass return data # get device context try: with open(f'./config_contexts/device/{device}.yml', 'r') as file: data = yaml.safe_load(file) all_config_contexts.update({'device': {'weight': 0, 'content': remove_meta(data)}}) except: pass # get config_contexts for k, v in config_contexts.items(): islist = False if isinstance(v, list): islist = True vlist = v else: vlist = [v] for i in vlist: try: if islist: context_name = f'{k}_{i}' else: context_name = k with open(f'./config_contexts/{k}/{i}.yml', 'r') as file: data = yaml.safe_load(file) if data['_metadata']['weight'] and data['_metadata']['is_active']: all_config_contexts.update({context_name: {'weight': data['_metadata']['weight'], 'content': remove_meta(data)}}) except: pass # get the all context all_weight = sorted([all_config_contexts[k]['weight'] for k, v in all_config_contexts.items()], reverse=True) dupe_weight = list(set([x for x in all_weight if all_weight.count(x) > 1])) max_weight = all_weight[0]+1 try: with open('./config_contexts/all.yml', 'r') as file: data = yaml.safe_load(file) if data['_metadata']['is_active']: all_config_contexts.update({'all': {'weight': max_weight, 'content': remove_meta(data)}}) except: pass # print(yaml.dump(all_config_contexts)) # check for equally weighted clashing keys equal_weight = {} for i in dupe_weight: equal_weight.update({i: []}) for k in all_config_contexts.keys(): if all_config_contexts[k]['weight'] == i: equal_weight[i].append(k) # print(f'equal weight contexts: {equal_weight}') # list all keys in equally weighted contexts keys_list = [] for k in equal_weight.keys(): for i in equal_weight[k]: for k in all_config_contexts[i]['content'].keys(): keys_list.append(k) keys_list = list(set(keys_list)) # print(f'all keys in equal weight contexts: {keys_list}') # check each equally weighted context for clashing keys equal_weight_key_clash_errors = [] for w in equal_weight: for k in keys_list: key_occurance = [] for i in equal_weight[w]: if k in all_config_contexts[i]['content']: key_occurance.append(i) if len(key_occurance) >1: equal_weight_key_clash_errors.append(f'clashing key found in equally weighted contexts: \nkey: {k} \ncontexts: {key_occurance}') if len(equal_weight_key_clash_errors) >0: error_log = f'device config_context render issue: {device}\n' for i in equal_weight_key_clash_errors: error_log = error_log + f'\n{i}\n' print(error_log) return # reorder all_config_contexts by weight, update the config_context with each context in order of precedence, overwriting keys where they exist (the last context being the lowest weight and highest precedence) config_context = {} all_config_contexts = {k: v for k, v in sorted(all_config_contexts.items(), key=lambda x: x[1]['weight'], reverse=True)} for k, v in all_config_contexts.items(): config_context = {**config_context, **v['content']} config_context = dict(sorted(config_context.items())) print(yaml.dump(config_context)) return config_context def main(): with open('./inventory.yml', 'r') as file: data = yaml.safe_load(file) for i in data.keys(): contexts(i, data[i]['config_contexts']) if __name__ == "__main__": main() # what does this need to do? # render a config_context # render a jinja2 template # print out a rendered context for someone when writing jinja2 templates