124 lines
4.2 KiB
Python
124 lines
4.2 KiB
Python
#!/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()
|
|
|
|
# do a validation class
|
|
# do a device class - this should be added to a list that the render class does something with
|
|
|
|
|
|
# what does this need to do?
|
|
# render a config_context
|
|
# render a jinja2 template
|
|
# print out a rendered context for someone to develop a jinja2 template
|
|
|
|
# you can easily wrap this up as a class, it just needs to be called with some paths and have methods to return the config_contexts
|
|
# this really needs to be changed to validate all configs first, then start ingesting devices |