MRE/scripts/render_templates.py
2025-03-28 14:08:58 -06:00

100 lines
4.0 KiB
Python

import os
import jinja2
import argparse
import traceback
def render_template(template_file: str,
out_path: str,
**kwargs) -> None:
folder, file = os.path.split(template_file)
template_path = os.path.abspath(folder)
env = jinja2.Environment(loader=jinja2.FileSystemLoader(template_path),
trim_blocks=True,
lstrip_blocks=True)
template = env.get_template(file)
with open(out_path, 'w+') as save:
save.write(template.render(**kwargs))
def load_template_vars_file(var_file_path: str) -> dict:
result = {}
with open(var_file_path) as reader:
for line in reader:
key, value = line.split('=', 1)
result[key] = value
return result
if __name__ == '__main__':
parser = argparse.ArgumentParser(prog='render_templates.py',
description='A script to render the docker jinja templates.',
add_help=True)
parser.add_argument('template_path',
help='The path to the template(s) to render (Can be either a directory or a file).')
parser.add_argument('var_file_path',
help='The path to the file containing the variables to use for rendering the tempalte(s).')
parser.add_argument('out_path',
help='The path to write the rendered template (MUST be a directory).')
parser.add_argument('-k',
'--kwargs',
required=False,
type=str,
default='',
help='Additional kwargs to include if needed (format: key1=value1,key2=value2...).')
parser.add_argument('-o',
'--overwrite',
action='store_true',
help='If set the previous template will be overwritten.')
args = parser.parse_args()
# make sure we have a template file and a variable file.
if not os.path.exists(args.template_path):
print(f'The given template path {args.template_path} does not exist.')
exit(1)
if not os.path.exists(args.var_file_path):
print(f'The given template path {args.var_file_path} does not exist.')
exit(1)
run_on_dir = False
# if the template path is a directory, make sure output path exists
if os.path.isdir(args.template_path):
run_on_dir = True
if not os.path.exists(args.out_path):
os.makedirs(args.out_path)
else:
print('The output path must be a directory since the template path is.')
exit(1)
args.template_path = [os.path.join(args.template_path, p)
for p in filter(lambda x: x.ends_with('.tmpl'),
os.listdir(args.template_path))]
# if the tempalte path is a file
else:
# wrap it in a list
args.template_path = [args.template_path]
# load the variables from the variable file
kwargs = load_template_vars_file(args.var_file_path)
args.kwargs = {a.split('=')[0]: a.split('=')[1] for a in args.kwargs.split(',')} if args.kwargs else {}
for k in kwargs:
# The assumption made here is that anything passed on the commandline should be prioritized
# over values that appear in the template variables file.
if k not in args.kwargs:
args.kwargs[k] = kwargs[k]
for template in args.template_path:
out_file_name = os.path.join(args.out_path,
os.path.split(template.remove('.tmpl')))
# if the output exists and we aren't overwritting files, then move on.
if os.path.exists(out_file_name) and not args.overwrite:
continue
try:
render_template(template, out_file_name, **args.kwargs)
except Exception as ex:
print(f'Failed to render template "{template}":')
print(f'Error: {str(ex)}\n{traceback.format_exec()}')