Quick and Dirty Jinja templating from CLI with YAML
This is a work in progress, subject to many changes and new instabilities / brokenness.
This project was made because I liked the templating workflow that's present in Ansible, but I found that installing Ansible just for the templating is kind of inconvenient.
So here we have the jinja templating system ingesting YAML, all run via some click CLI commands.
No inventory, group_vars, hostnames, or other Ansible-related considerations necessary.
python3 -m venv venv
source venv/bin/activate
pip install git+https://github.com/camratchford/easy-template
external_function_dir: ./path/to/jinja_functions
force_overwrite: True
load_env_vars: True
debug: False
# Parameters from https://jinja.palletsprojects.com/en/3.1.x/api/#high-level-api are passed to the Jinja environment object
jinja_config:
trim_blocks: False
newline_sequence: '\n'
keep_trailing_newline: False
auto_reload: False
optimized: True
# Will be applied to every template, but can be over-ridden by var files
global_variables:
name: Person McPersonface
email: Person.McPersonface@example.com
github_profile: https://github.com/pmcpface
Ex: example_files/readme_template.md.j2
# {{ title }}
{{ description }}
> {{ disclaimer }}
{% if toc %}
{% for t in toc %}
- [{{ t.label }}]({{ t.link }})
{% endfor %}
{% endif %}
Author: [{{ name }}]({{ github_profile }})
Contact: [{{ email }}](mailto:{{ email }})
title: How to make a cheeseburger
description: A simple step by step guide on how to make juicy burgers
disclaimer: I am not a professional. Any injury, disablement, or deaths caused by the burgers you consume are not my fault.
toc:
- label: Get meat
link: ./docs/meats.md
- label: Cook meat
link: ./docs/cooking.md
- label: Enjoy
link: ./docs/enjoy.md
Ex: example_files/example_script.sh
# Config path arg is absolute, var and template args are relative to their respective directories defined in the config file
ezt.exe --force \
-c "example_files/config.yml" \
-t "example_files/readme_template.md.j2" \
-v "title=How do you make a cheeseburger?" \
--var-file "example_files/vars.yml" \
-o "example_files/README.md"
This command reads in the config file ~/ezt/config.yml
, parses the variables in ~/vars/templatesreadme.yml
,
loads the variables defined in the -v
argument, then processes the template with the loaded variables, outputting the file
in the path defined with the -o
argument
The command outputs a file README.md
to the output directory defined in your config.
Ex: The contents of example_files/README.md
# How do you make a cheeseburger?
A simple step by step guide on how to make juicy burgers
> I am not a professional. Any injury, disablement, or deaths caused by the burgers you consume are not my fault.
- [Get meat](./docs/meats.md)
- [Cook meat](./docs/cooking.md)
- [Enjoy](./docs/enjoy.md)
Author: [Person McPersonface](https://github.com/pmcpface)
Contact: [Person.McPersonface@example.com](mailto:Person.McPersonface@example.com)
Configuration Item | Abrv | Keyword Argument | Config File Key | Default | Required | Description |
---|---|---|---|---|---|---|
config_file | -c | --config | N/A | N/A | No | The location of the yaml configuration file. |
variables | -v | --variables | variables | [] | No | A 'a_variable=some value' pair representing a variable, Variable arguments |
var_file | -V | --var-file | var_file | "" | No | The path to a yaml file containing key: value pairs, representing variables |
output | -o | --output | output | "" | No* | The path where you'll find the output of ezt |
template_file | -t | --template-file | N/A | "" | No** | The path pointing toward the jinja template that ezt will use to create it's output |
tree_dir | -d | --tree-dir | tree_directory | "" | No** | Specifies the directory to recursively perform templating on |
external_function_dir | -e | --external-function-dir | external_function_dir | "" | No | The path pointing toward a folder of python files which contain jinja2 filter/test functions |
force_overwrite | -f | --force | force_overwrite | False | No | When true, output will overwrite any file in that path |
load_env_vars | --env | --load-environment-vars | load_env_vars | False | No | Will load Environment variables in as jinja variables |
jinja_config | N/A | N/A | jinja_config | "" | No | Jinja templating engine options |
log_config | N/A | N/A | log_config | {} | No | logging.dictConfig |
global_variables | N/A | N/A | global_variables | {} | No | Another, more static, way to set variables.*** |
rich_std_out | N/A | --no-rich-stdout | rich_std_out | True | No | Formats output string with Rich |
rich_markdown_stdout | N/A | --markdown | rich_markdown_stdout | False | No | Formats output string with Rich's Markdown module |
rich_theme | N/A | --rich-theme | rich_theme | "zenburn" | No | Changes the output theme for Rich to one of the Pygment Styles |
export_config | N/A | --export-config | export_config | False | No | When true, the current set of configuration items will be exported to ./export_config.yml |
Key | Notes |
---|---|
* | Unless rich_stdout is disabled. |
** | You must use either the --tree or --template-file option. Using both or neither will result in an error. |
*** | Variables declared in this way will be over-ridden by any successive variable declarations. It is advised to use this method to store default values. |
The variables are applied in the following order, with each instance of a variable being overwritten by any subsequent instances.
- Global variables (defined in the config file under the key
global_variables
) - Environment variables (If the
load_env_vars
configuration item is set to True) - Variable file (Variables within a yaml file defined in the --var-file argument)
- Variable arguments (Variables defined using the
-v
argument)
To use external Jinja2 filter functions, you may the switch --external-function-dir path/to/function/dir
or the config file key external_function_dir: some/path/to/function/
,
to point to a path containing any number of the 2 python modules "filters" and "tests".
Setting the variable
--external-function-dir ~\ezt\example_external_functions
# Example directory tree:
~\ezt\example_external_functions\
~\ezt\example_external_functions\filters\
~\ezt\example_external_functions\filters\filters.py
~\ezt\example_external_functions\tests\
~\ezt\example_external_functions\tests\tests.py
Each function contained in either "filters" or "tests" modules will be merged into the set of filters and tests available to the user in jinja template tags It will be helpful to read the official Jinja2 documentation on the subjects
Easy-Template has the ability to keep and store logs. This might be useful for debugging templating errors, and other record keeping tasks.
Configuration of Python's logging module is done bia the logging.dictConfig
method
Examples of how to implement this can be found in the official documentation
Simply add the requisite configuration in your ezt config file under the key logging_config:
Ex: ~/example_files/config.yml
# ...
# Your normal config keys above
log_config:
version: 1
disable_existing_loggers: True
formatters:
verbose:
fmt: |
%(process)s -> %(filename)s -> %(levelprefix)s -> %(module)s -> %(funcName)s -> %(lineno)s ->> %(message)s
use_colors: True
handlers:
default:
class : logging.handlers.RotatingFileHandler
formatter: verbose
filename: ez_temp.log
maxBytes: 1024
backupCount: 3
loggers:
ez_temp:
handlers: default
level: DEBUG
propagate: True
- Make sure you have the python & python-dev >= 3.8 installed
- Create a virtual environment
- Install the package
cd ./EasyTemplate
python3 -m venv venv
source venv/bin/activate
pip install .
- Compile
cd ./compilation
bash ./compile.sh
- Copy it somewhere in $PATH
cp ./build/ezt /usr/bin/ezt
- Make sure Python >= 3.8 is installed
- (for some reason) Install pyinstaller to your system Python interpreter's library
pip install pyinstaller
- Run the PowerShell script
cd .\EasyTemplate\compilation\
# It will create the venv and test the program
.\compile.ps1