TT Lab
Get started
Learn Learning paths Courses

Ansible in Practice

Generating Config Files With Jinja2

Continue in TT Lab

Goal

You break a configuration file that differs per environment into one template and data, and make sure the rendered result is put in place clean and validated.

Why it matters

If you keep as many configuration files as there are environments, those files will inevitably diverge. A template removes that divergence with "one frame, many sets of data." What ruins templates in practice is not syntax but two things. One is whitespace — blank lines left by control statements break a YAML configuration. The other is a rendered result that changes every time — because of one timestamp line, the file changes on every run, the handler runs every time, and the service restarts every time. Finally, validate is the cheapest safeguard that blocks the path by which a bad configuration kills the service. Once you turn on automatic deployment, this option is no longer optional.

Steps

  1. This lab uses a single playbook, /root/ans/tpl/site.yml. Use /root/ans/tpl/templates/basic.j2 to create /root/ans/tpl/out/basic.conf. The result must contain the line service = checkout.
  2. Use /root/ans/tpl/templates/filters.j2 to create /root/ans/tpl/out/filters.conf. It must contain three lines: UPPER=CHECKOUT, TIMEOUT=30 (the default for an undefined variable), and REPLICAS=3.
  3. Use /root/ans/tpl/templates/upstream.j2 to create /root/ans/tpl/out/upstream.conf. The 3 backends must each appear on its own line in the form server 10.0.0.11:8080;.
  4. Render the same template with different variables to create /root/ans/tpl/out/prod.conf (tls = on, no debug) and /root/ans/tpl/out/dev.conf (tls = off, with debug).
  5. Control whitespace so that upstream.conf has no blank lines at all and no unnecessary indentation before the server lines. You can use {%- -%}, or turn on trim_blocks/lstrip_blocks in the template task of /root/ans/tpl/site.yml.
  6. Use /root/ans/tpl/templates/node.j2 to create /root/ans/tpl/out/node.conf. hostname and arch come from facts, and generated_for comes from inventory_hostname (=web1).
  7. Add validate and backup: true to the template task in /root/ans/tpl/site.yml to create /root/ans/tpl/out/validated.conf. Its content is a single key=value line.
  8. Create /root/ans/tpl/out/site.nginx. Inside the upstream checkout_backend { block, put 3 server lines indented by 4 spaces, and then listen 8080; and server_name checkout.labhub.internal;, each indented by 4 spaces. There must be at most 1 blank line.

Notes

Render a basic template with a variable

This lab uses a single playbook, /root/ans/tpl/site.yml. Use /root/ans/tpl/templates/basic.j2 to create /root/ans/tpl/out/basic.conf. The result must contain the line service = checkout.

Use {{ 변수 }} (the Korean placeholder stands for the variable name) to print a value. If Jinja2 syntax remains in the result, it was not rendered.

Use the upper and default filters

Use /root/ans/tpl/templates/filters.j2 to create /root/ans/tpl/out/filters.conf. It must contain three lines: UPPER=CHECKOUT, TIMEOUT=30 (the default for an undefined variable), and REPLICAS=3.

Filters are chained with a pipe. Think about which filter gives a default value to an undefined variable.

Add a loop over a list

Use /root/ans/tpl/templates/upstream.j2 to create /root/ans/tpl/out/upstream.conf. The 3 backends must each appear on its own line in the form server 10.0.0.11:8080;.

Put the line to repeat between {% for %} and {% endfor %}. The 3 backends must each become one line.

Emit different configuration depending on the environment

Render the same template with different variables to create /root/ans/tpl/out/prod.conf (tls = on, no debug) and /root/ans/tpl/out/dev.conf (tls = off, with debug).

Render the same template twice with different variables. debug must not appear in prod.

Remove blank lines with whitespace control

Control whitespace so that upstream.conf has no blank lines at all and no unnecessary indentation before the server lines. You can use {%- -%}, or turn on trim_blocks/lstrip_blocks in the template task of /root/ans/tpl/site.yml.

Use {%- / -%} or the trim_blocks/lstrip_blocks of the template module. The result must have no blank lines at all.

Use facts and inventory_hostname

Use /root/ans/tpl/templates/node.j2 to create /root/ans/tpl/out/node.conf. hostname and arch come from facts, and generated_for comes from inventory_hostname (=web1).

Fact variables start with ansible_. The name of the target is inventory_hostname.

Add validate and backup

Add validate and backup: true to the template task in /root/ans/tpl/site.yml to create /root/ans/tpl/out/validated.conf. Its content is a single key=value line.

In validate, the path of a temporary file goes where %s is. If the check fails, the file is not put in place.

Generate a whole nginx configuration from group variables

Create /root/ans/tpl/out/site.nginx. Inside the upstream checkout_backend { block, put 3 server lines indented by 4 spaces, and then listen 8080; and server_name checkout.labhub.internal;, each indented by 4 spaces. There must be at most 1 blank line.

The server lines inside the upstream block are indented by 4 spaces. You need to use whitespace control and a loop together.