Templates Jinja2 do Ansible

AnsibleBeginner
Pratique Agora

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.

Este é um Lab Guiado, que fornece instruções passo a passo para ajudá-lo a aprender e praticar. Siga as instruções cuidadosamente para completar cada etapa e ganhar experiência prática. Dados históricos mostram que este é um laboratório de nível iniciante com uma taxa de conclusão de 88%. Recebeu uma taxa de avaliações positivas de 97% dos estudantes.

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:

  1. Sintaxe básica de Jinja2: Você aprendeu a usar variáveis e fatos do Ansible em templates.
  2. Filtros Jinja2: Você explorou vários filtros embutidos para manipular dados dentro dos templates.
  3. Condicionais: Você usou as instruções if-elif-else para criar conteúdo dinâmico com base em condições.
  4. Loops: Você aprendeu a iterar sobre listas e dicionários, incluindo loops aninhados e controles de loop.
  5. 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.