#!/usr/bin/env python3 import importlib import json import os import os.path import sys import jinja2 import yaml NGX_JINJA_MODULES = sorted(set(os.getenv('NGX_JINJA_MODULES', 'os os.path sys netaddr psutil re wcmatch').split(sep=' '))) ME = sys.argv[0] NGX_JINJA_SUFFIX = os.getenv('NGX_JINJA_SUFFIX', '.j2') if NGX_JINJA_SUFFIX == '': raise ValueError('NGX_JINJA_SUFFIX is empty') if not NGX_JINJA_SUFFIX.startswith('.'): raise ValueError('NGX_JINJA_SUFFIX does not start with dot (".")') NGX_JINJA_CONFIG = os.getenv('NGX_JINJA_CONFIG', '') if (NGX_JINJA_CONFIG != '') and (not os.path.exists(NGX_JINJA_CONFIG)): print(f'{ME}: config does not exist, skipping: {NGX_JINJA_CONFIG}', file=sys.stderr) NGX_JINJA_CONFIG_NAMES = [ '/angie/jinja', '/etc/angie/jinja', ] if len(sys.argv) < 2: raise ValueError('not enough arguments (needed: 2)') if len(sys.argv) > 3: raise ValueError('too many arguments (needed: 2)') if not sys.argv[1]: raise ValueError('specify input file') input_file = sys.argv[1] if not os.path.exists(input_file): raise ValueError('input file does not exist') if len(sys.argv) == 3: if not sys.argv[2]: raise ValueError('specify output file') output_file = sys.argv[2] else: output_file, ext = os.path.splitext(input_file) if ext != NGX_JINJA_SUFFIX: raise ValueError(f'input file name extension mismatch (not a "{NGX_JINJA_SUFFIX}")') if input_file == output_file: raise ValueError('unable to process template inplace') kwargs = {} for m in NGX_JINJA_MODULES: kwargs[m] = importlib.import_module(m) kwargs['env'] = os.environ kwargs['cfg'] = {} def merge_dict_from_file(filename): if not filename: return False if not isinstance(filename, str): return False if filename == '': return False if not os.path.exists(filename): return False if not os.path.isfile(filename): print(f'{ME}: not a file, skipping: {filename}', file=sys.stderr) return False if filename.endswith('.yml') or filename.endswith('.yaml'): with open(filename, mode='r', encoding='utf-8') as fx: x = yaml.safe_load(fx) kwargs['cfg'] = kwargs['cfg'] | x return True if filename.endswith('.json'): with open(filename, mode='r', encoding='utf-8') as fx: x = json.load(fx) kwargs['cfg'] = kwargs['cfg'] | x return True print(f'{ME}: non-recognized name extension: {filename}', file=sys.stderr) return False for base_name in NGX_JINJA_CONFIG_NAMES: for file_name in [ base_name + '.' + ext for ext in [ 'yml', 'yaml', 'json' ] ]: if merge_dict_from_file(file_name): break continue merge_dict_from_file(NGX_JINJA_CONFIG) with open(input_file, mode='r', encoding='utf-8') as fin: template = jinja2.Template(fin.read()) rendered = template.render(**kwargs) with open(output_file, mode='w', encoding='utf-8') as fout: fout.write(rendered)