Jinja2 templates
Using Jinja2 Templates
- A template is a configuration file that contains variables and, based on the variables, is generated on the managed hosts according to host-specific requirements.
- Using templates allows for a structural way to generate configuration files, which is much more powerful than changing specific lines from specific files.
- Ansible uses Jinja2 to generate templates.
- Jinja2 is a generic templating language for Python developers.
- It is used in Ansible templates, but Jinja2-based approaches are also found in other parts of Ansible. For instance, the way variables are referred to is based on Jinja2.
In a Jinja2 template, three elements can be used. data
sample textcomment{# sample text #}variable{{ ansible_facts['default_ipv4']['address'] }}expression
- To work with a template, you must create a template file, written in Jinja2.
- Template file must be included in an Ansible playbook that uses the template module.
Sample Template:
-
starts with # {{ ansible_managed }}.
-
This string is commonly used to identify that a file is managed by Ansible so that administrators are not going to change file contents by accident.
-
While processing the template, this string is replaced with the value of the ansible_managed variable.
-
This variable can be set in ansible.cfg.
-
For instance, you can use ansible_managed = This file is managed by Ansible to substitute the variable with its value while generating the template.
-
template file is just a text file that uses variables to substitute specific variables to their values.
Calling a template:
Applying Control Structures in Jinja2 Using for
- Control structures can be used to dynamically generate contents.
- A for statement can be used to iterate over all elements that exist as the value of a variable.
- variable with the name host_ports is defined on the second line (which is the line that will be written to the target file).
- To produce its value, the host group all is processed in the for statement on the first line.
- While processing the host group, a temporary variable with the name node is defined.
- This value of the node variable is replaced with the name of the host while it is processed, and after the host name, the string :8080 is copied, which will result in a separate line for each host that was found.
- As the last element, {% endfor %} is used to close the for loop.
LAB: Generating a Template with a Conditional Statement
To verify, you can use the ad hoc command ansible ansible2 -a "cat /tmp/hostports.txt"
Using Conditional Statements with if
- The for statement can be used in templates to iterate over a series of values.
- The if statement can be used to include text only if a variable contains a specific value or evaluates to a Boolean true.
Template Example with if if.j2
Using Filters
- In Jinja2 templates, you can use filters.
- Filters are a way to perform an operation on the value of a template expression, such as a variable.
- The filter is included in the variable definition itself, and the result of the variable and its filter is used in the file that is generated.
Common filters {{ myvar | to_json }}
- writes the contents of myvar in JSON format {{ myvar || to_yaml }}
- writes the contents of myvar in YAML format {{ myvar | ipaddr }}
- tests whether myvar contains an IP address
From https://docs.ansible.com:
How do I loop over a list of hosts in a group, inside of a template?
A pretty common pattern is to iterate over a list of hosts inside of a host group, perhaps to populate a template configuration file with a list of servers. To do this, you can just access the “$groups” dictionary in your template, like this:
If you need to access facts about these hosts, for example, the IP address of each hostname, you need to make sure that the facts have been populated. For example, make sure you have a play that talks to db_servers:
Then you can use the facts inside your template, like this:
Lab: Working with Conditional Statements in Templates
1. Use your editor to create the file exercise83.j2. Include the following line to open the Jinja2 conditional statement:
2. This statement defines a variable with the name host. This variable iterates over the magic variable groups, which holds all Ansible host groups as defined in inventory. Of these groups, the all group (which holds all inventory host names) is processed.
3. Add the following line (write it as one line; it will wrap over two lines, but do not press Enter to insert a newline character):
- This line writes a single line for each inventory host, containing three items.
- To do so, you use the magic variable hostvars, which can be used to identify Ansible facts that were discovered on the inventory host.
- The [host] part is replaced with the name of the current host, and after that, the specific facts are referred to. As a result, for each host a line is produced that holds the IP address, the FQDN, and next the host name.
4. Add the following line to close the for loop:
5. Verify that the complete file contents look like the following and write and quit the file:
6. Use your editor to create the file exercise83.yaml. It should contain the following lines:
7. Run the playbook by using ansible-playbook exercise83.yaml
8. Verify the /tmp/hosts file was generated by using ansible all -a "cat /tmp/hosts"
This lab only worked if every host in the inventory file was reachable.
Lab: Generate an /etc/hosts File
Write a playbook that generates an /etc/hosts file on all managed hosts. Apply the following requirements:
• All hosts that are defined in inventory should be added to the /etc/hosts file.
Lab: Manage a vsftpd Service
- Write a playbook that uses at least two plays to install a vsftpd service
- configure the vsftpd service using templates
- configure permissions as well as SELinux.
- Install, start, and enable the vsftpd service.
- open a port in the firewall to make it accessible.
- Use the /etc/vsftpd/vsftpd.conf file to generate a template.
- In this template, you should use the following variables to configure specific settings.
- Replace these settings with the variables and leave all else unmodified:
- Set permissions on the /var/ftp/pub directory to mode 0777.
- Configure the ftpd_anon_write Boolean to allow anonymous user writes.
- Set the public_content_rw_t SELinux context type to the /var/ftp/pub directory.
- If any additional tasks are required to get this done, take care of them.
vim vsftpd.yaml
vsftpd.j2