Introdução
Neste laboratório, você explorará o Jinja2, o poderoso motor de templates usado pelo Ansible. O Jinja2 permite criar conteúdo dinâmico, tornando seus playbooks Ansible mais flexíveis e adaptáveis. Ao final deste laboratório, você entenderá como usar a sintaxe Jinja2 no Ansible, incluindo variáveis, filtros, condicionais e loops. Este conhecimento permitirá que você crie playbooks e roles Ansible mais dinâmicos e eficientes.
Entendendo os Fundamentos do Jinja2
Jinja2 é uma linguagem de templates moderna e amigável para designers, modelada a partir dos templates do Django. No Ansible, o Jinja2 é usado para criar templates de arquivos, criar estruturas de play dinâmicas e muito mais.
Vamos começar criando um template Jinja2 simples. Primeiro, navegue até o diretório do seu projeto:
cd ~/project
Agora, vamos criar um diretório para nossos templates:
mkdir templates
cd templates
Crie um novo arquivo chamado hello.j2:
nano hello.j2
Adicione o seguinte conteúdo:
Hello, {{ name }}!
Today is {{ ansible_date_time.date }}.
Your home directory is {{ ansible_env.HOME }}.
Salve e saia do editor nano (Ctrl+X, depois Y, depois Enter).
Neste template:
{{ name }}é uma variável que será substituída por um valor real quando o template for renderizado.{{ ansible_date_time.date }}e{{ ansible_env.HOME }}são fatos do Ansible que serão preenchidos automaticamente.
Agora, vamos criar um playbook para usar este template. Volte para a raiz do projeto e crie um novo arquivo chamado use_template.yml:
cd ~/project
nano use_template.yml
Adicione o seguinte conteúdo:
---
- name: Use Jinja2 template
hosts: localhost
vars:
name: "Ansible Learner"
tasks:
- name: Create file from template
template:
src: templates/hello.j2
dest: /tmp/hello.txt
Este playbook usa o módulo template para renderizar nosso template Jinja2 e criar um arquivo em /tmp/hello.txt.
Execute o playbook:
ansible-playbook use_template.yml
Após executar o playbook, verifique o conteúdo do arquivo criado:
cat /tmp/hello.txt
Você deve ver o template renderizado com a variável e os fatos substituídos por valores reais.
Usando Filtros Jinja2
Os filtros Jinja2 são funções que podem ser aplicadas a variáveis. Eles são separados da variável por um símbolo de pipe (|). O Ansible inclui muitos filtros embutidos, e você também pode criar filtros personalizados.
Vamos criar um novo template que demonstra alguns filtros comuns. Crie um novo arquivo chamado filters.j2:
cd ~/project/templates
nano filters.j2
Adicione o seguinte conteúdo:
1. Uppercase filter: {{ name | upper }}
2. Length filter: {{ name | length }}
3. Default filter: {{ optional_var | default('No value provided') }}
4. Join filter: {{ fruits | join(', ') }}
5. Random item: {{ fruits | random }}
6. First item: {{ fruits | first }}
7. JSON encode: {{ complex_data | to_json }}
Agora, vamos criar um playbook para usar este template. Volte para a raiz do projeto e crie um novo arquivo chamado use_filters.yml:
cd ~/project
nano use_filters.yml
Adicione o seguinte conteúdo:
---
- name: Use Jinja2 filters
hosts: localhost
vars:
name: "ansible learner"
fruits:
- apple
- banana
- cherry
complex_data:
key1: value1
key2:
- item1
- item2
tasks:
- name: Create file from template
template:
src: templates/filters.j2
dest: /tmp/filters.txt
- name: Display file contents
command: cat /tmp/filters.txt
register: file_contents
- name: Show file contents
debug:
var: file_contents.stdout_lines
Este playbook aplica vários filtros Jinja2 às nossas variáveis e exibe os resultados.
Execute o playbook:
ansible-playbook use_filters.yml
A saída mostrará como cada filtro modifica os dados de entrada. Isso demonstra como os filtros podem ser usados para manipular dados dentro de seus templates.
Condicionais Jinja2
Jinja2 permite que você use declarações condicionais em seus templates. Isso é particularmente útil quando você precisa incluir ou excluir conteúdo com base em certas condições.
Crie um novo arquivo de template chamado conditionals.j2:
cd ~/project/templates
nano conditionals.j2
Adicione o seguinte conteúdo:
{% if user_type == 'admin' %}
Bem-vindo, Administrador!
Você tem acesso total ao sistema.
{% elif user_type == 'user' %}
Bem-vindo, Usuário!
Você tem acesso limitado ao sistema.
{% else %}
Bem-vindo, Convidado!
Você tem acesso somente leitura ao sistema.
{% endif %}
{% if fruits %}
Frutas disponíveis:
{% for fruit in fruits %}
- {{ fruit }}
{% endfor %}
{% else %}
Nenhuma fruta disponível.
{% endif %}
Agora, vamos criar um playbook para usar este template. Volte para a raiz do projeto e crie um novo arquivo chamado use_conditionals.yml:
cd ~/project
nano use_conditionals.yml
Adicione o seguinte conteúdo:
---
- name: Use Jinja2 conditionals
hosts: localhost
vars:
user_type: "admin"
fruits:
- apple
- banana
- cherry
tasks:
- name: Create file from template (admin)
template:
src: templates/conditionals.j2
dest: /tmp/conditionals_admin.txt
- name: Create file from template (user)
template:
src: templates/conditionals.j2
dest: /tmp/conditionals_user.txt
vars:
user_type: "user"
- name: Create file from template (guest)
template:
src: templates/conditionals.j2
dest: /tmp/conditionals_guest.txt
vars:
user_type: "guest"
fruits: []
- name: Display file contents
command: "cat {{ item }}"
loop:
- /tmp/conditionals_admin.txt
- /tmp/conditionals_user.txt
- /tmp/conditionals_guest.txt
register: file_contents
- name: Show file contents
debug:
var: file_contents.results[item].stdout_lines
loop: [0, 1, 2]
Este playbook cria três arquivos diferentes usando o mesmo template, mas com diferentes valores de variável, demonstrando como as declarações condicionais no template funcionam.
Execute o playbook:
ansible-playbook use_conditionals.yml
A saída mostrará como o conteúdo do template muda com base nas diferentes condições.
Loops Jinja2
Jinja2 fornece construções de loop que permitem iterar sobre listas e dicionários. Isso é particularmente útil quando você precisa gerar conteúdo repetitivo com base em dados variáveis.
Crie um novo arquivo de template chamado loops.j2:
cd ~/project/templates
nano loops.j2
Adicione o seguinte conteúdo:
1. Loop simples:
{% for item in simple_list %}
- {{ item }}
{% endfor %}
2. Loop com índice:
{% for item in simple_list %}
{{ loop.index }}. {{ item }}
{% endfor %}
3. Loop sobre um dicionário:
{% for key, value in simple_dict.items() %}
{{ key }}: {{ value }}
{% endfor %}
4. Loop aninhado:
{% for category, items in nested_dict.items() %}
{{ category }}:
{% for item in items %}
- {{ item }}
{% endfor %}
{% endfor %}
5. Condicional em loop:
{% for item in simple_list %}
{% if loop.first %}Primeiro item: {% endif %}
{% if loop.last %}Último item: {% endif %}
{{ item }}
{% endfor %}
Agora, vamos criar um playbook para usar este template. Volte para a raiz do projeto e crie um novo arquivo chamado use_loops.yml:
cd ~/project
nano use_loops.yml
Adicione o seguinte conteúdo:
---
- name: Use Jinja2 loops
hosts: localhost
vars:
simple_list:
- apple
- banana
- cherry
simple_dict:
name: John Doe
age: 30
city: New York
nested_dict:
fruits:
- apple
- banana
vegetables:
- carrot
- potato
tasks:
- name: Create file from template
template:
src: templates/loops.j2
dest: /tmp/loops.txt
- name: Display file contents
command: cat /tmp/loops.txt
register: file_contents
- name: Show file contents
debug:
var: file_contents.stdout_lines
Este playbook demonstra várias maneiras de usar loops em templates Jinja2.
Execute o playbook:
ansible-playbook use_loops.yml
A saída mostrará como as diferentes construções de loop no template geram conteúdo com base nas variáveis fornecidas.
Técnicas Avançadas Jinja2
Nesta etapa final, exploraremos algumas técnicas avançadas de Jinja2, incluindo macros e filtros. Macros são trechos de template reutilizáveis, semelhantes a funções em linguagens de programação.
Crie um novo arquivo de template chamado advanced.j2:
cd ~/project/templates
nano advanced.j2
Adicione o seguinte conteúdo:
{% macro render_list(title, items) %}
{{ title }}:
{% for item in items %}
- {{ item }}
{% endfor %}
{% endmacro %}
1. Usando uma macro:
{{ render_list("Fruits", fruits) }}
{{ render_list("Vegetables", vegetables) }}
2. Usando set:
{% set greeting = "Hello, " + name + "!" %}
{{ greeting }}
3. Filtro personalizado (definido no playbook):
{{ complex_data | to_nice_json }}
4. Controle de espaço em branco:
{% for item in fruits -%}
{{ item }}
{%- if not loop.last %}, {% endif %}
{%- endfor %}
5. Bloco raw (sem processamento):
{% raw %}
This {{ will_not_be_processed }}
{% endraw %}
6. Incluir outro template:
{% include 'simple_include.j2' %}
Agora, vamos criar o arquivo de inclusão simples. Crie um novo arquivo chamado simple_include.j2:
nano simple_include.j2
Adicione o seguinte conteúdo:
This is content from an included template.
Current user: {{ ansible_user_id }}
Agora, vamos criar um playbook para usar este template avançado. Volte para a raiz do projeto e crie um novo arquivo chamado use_advanced.yml:
cd ~/project
nano use_advanced.yml
Adicione o seguinte conteúdo:
---
- name: Use advanced Jinja2 techniques
hosts: localhost
vars:
name: "Ansible Expert"
fruits:
- apple
- banana
- cherry
vegetables:
- carrot
- potato
- broccoli
complex_data:
key1: value1
key2:
- item1
- item2
custom_filters:
to_nice_json: "{{ '(' ~ ((complex_data | to_json) | replace('\"', '\\\"')) ~ ')' | from_json | to_nice_json }}"
tasks:
- name: Create file from template
template:
src: templates/advanced.j2
dest: /tmp/advanced.txt
- name: Display file contents
command: cat /tmp/advanced.txt
register: file_contents
- name: Show file contents
debug:
var: file_contents.stdout_lines
Este playbook demonstra técnicas avançadas de Jinja2, incluindo macros, filtros personalizados, controle de espaço em branco e inclusão de outros templates.
Execute o playbook:
ansible-playbook use_advanced.yml
A saída mostrará como essas técnicas avançadas de Jinja2 funcionam na prática.
Resumo
Neste laboratório, você explorou a criação de templates Jinja2 no Ansible, cobrindo uma ampla gama de recursos e técnicas. Aqui estão os principais pontos a serem lembrados:
- Sintaxe básica de Jinja2: Você aprendeu a usar variáveis e fatos do Ansible em templates.
- Filtros Jinja2: Você explorou vários filtros embutidos para manipular dados dentro dos templates.
- Condicionais: Você usou as instruções if-elif-else para criar conteúdo dinâmico com base em condições.
- Loops: Você aprendeu a iterar sobre listas e dicionários, incluindo loops aninhados e controles de loop.
- Técnicas avançadas: Você explorou macros, filtros personalizados, controle de espaço em branco, blocos raw e inclusão de templates.
Esses recursos do Jinja2 permitem que você crie templates altamente dinâmicos e flexíveis no Ansible. Eles permitem que você gere arquivos de configuração, scripts e outros conteúdos que podem se adaptar a diferentes cenários e entradas de dados.
À medida que você continua trabalhando com o Ansible, descobrirá que dominar a criação de templates Jinja2 é crucial para criar playbooks e roles eficientes e adaptáveis. Isso permite que você escreva um código mais conciso e fácil de manter, reduzindo a repetição e tornando seus projetos Ansible mais escaláveis.
Lembre-se de que, embora o Jinja2 seja poderoso, é importante equilibrar a flexibilidade com a legibilidade. Templates excessivamente complexos podem ser difíceis de manter, portanto, sempre se esforce pela clareza no design de seus templates.
Pratique o uso desses recursos do Jinja2 em seus projetos Ansible, e você poderá lidar com tarefas de automação cada vez mais complexas com facilidade.


