Шаблоны Ansible Jinja2

AnsibleAnsibleBeginner
Практиковаться сейчас

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Введение

В этом лабораторном занятии (lab) вы познакомитесь с Jinja2, мощным шаблонизатором, используемым в Ansible. Jinja2 позволяет создавать динамическое содержимое, делая ваши Ansible-плейбуки более гибкими и адаптивными. К концу этого лабораторного занятия вы научитесь использовать синтаксис Jinja2 в Ansible, включая переменные, фильтры, условные операторы и циклы. Эти знания позволят вам создавать более динамичные и эффективные Ansible-плейбуки и роли.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL ansible(("Ansible")) -.-> ansible/ModuleOperationsGroup(["Module Operations"]) ansible(("Ansible")) -.-> ansible/PlaybookEssentialsGroup(["Playbook Essentials"]) ansible/ModuleOperationsGroup -.-> ansible/template("Generate Files from Templates") ansible/PlaybookEssentialsGroup -.-> ansible/loop("Iteration") ansible/PlaybookEssentialsGroup -.-> ansible/playbook("Execute Playbook") subgraph Lab Skills ansible/template -.-> lab-390470{{"Шаблоны Ansible Jinja2"}} ansible/loop -.-> lab-390470{{"Шаблоны Ansible Jinja2"}} ansible/playbook -.-> lab-390470{{"Шаблоны Ansible Jinja2"}} end

Понимание основ Jinja2

Jinja2 — это современный и удобный для дизайнеров шаблонизатор для Python, вдохновлённый шаблонами Django. В Ansible Jinja2 используется для создания шаблонов файлов, динамических структур плейбуков и многое другое.

Начнём с создания простого шаблона Jinja2. Сначала перейдите в каталог проекта:

cd ~/project

Теперь создадим каталог для наших шаблонов:

mkdir templates
cd templates

Создайте новый файл с именем hello.j2:

nano hello.j2

Добавьте следующее содержимое:

Hello, {{ name }}!

Today is {{ ansible_date_time.date }}.
Your home directory is {{ ansible_env.HOME }}.

Сохраните изменения и выйдите из редактора nano (Ctrl+X, затем Y, затем Enter).

В этом шаблоне:

  • {{ name }} — это переменная, которая будет заменена на фактическое значение при рендеринге шаблона.
  • {{ ansible_date_time.date }} и {{ ansible_env.HOME }} — это факты Ansible, которые будут автоматически заполнены.

Теперь создадим плейбук для использования этого шаблона. Вернитесь в корень проекта и создайте новый файл с именем use_template.yml:

cd ~/project
nano use_template.yml

Добавьте следующее содержимое:

---
- 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

Этот плейбук использует модуль template для рендеринга нашего шаблона Jinja2 и создания файла по пути /tmp/hello.txt.

Запустите плейбук:

ansible-playbook use_template.yml

После запуска плейбука проверьте содержимое созданного файла:

cat /tmp/hello.txt

Вы должны увидеть отрендеренный шаблон с заменёнными переменными и фактами на фактические значения.

Использование фильтров Jinja2

Фильтры Jinja2 — это функции, которые можно применять к переменным. Они отделяются от переменной вертикальной чертой (|). Ansible включает в себя множество встроенных фильтров, а вы также можете создавать свои собственные.

Создадим новый шаблон, который демонстрирует некоторые распространенные фильтры. Создайте новый файл с именем filters.j2:

cd ~/project/templates
nano filters.j2

Добавьте следующее содержимое:

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 }}

Теперь создадим плейбук для использования этого шаблона. Вернитесь в корень проекта и создайте новый файл с именем use_filters.yml:

cd ~/project
nano use_filters.yml

Добавьте следующее содержимое:

---
- 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

Этот плейбук применяет различные фильтры Jinja2 к нашим переменным и отображает результаты.

Запустите плейбук:

ansible-playbook use_filters.yml

Вывод показывает, как каждый фильтр изменяет входные данные. Это демонстрирует, как фильтры можно использовать для манипуляции данными в шаблонах.

Условные операторы Jinja2

Jinja2 позволяет использовать условные операторы в своих шаблонах. Это особенно полезно, когда необходимо включать или исключать контент в зависимости от определенных условий.

Создайте новый файл шаблона с именем conditionals.j2:

cd ~/project/templates
nano conditionals.j2

Добавьте следующее содержимое:

{% if user_type == 'admin' %}
Welcome, Administrator!
You have full access to the system.
{% elif user_type == 'user' %}
Welcome, User!
You have limited access to the system.
{% else %}
Welcome, Guest!
You have read-only access to the system.
{% endif %}

{% if fruits %}
Available fruits:
{% for fruit in fruits %}
  - {{ fruit }}
{% endfor %}
{% else %}
No fruits available.
{% endif %}

Теперь создадим плейбук для использования этого шаблона. Вернитесь в корень проекта и создайте новый файл с именем use_conditionals.yml:

cd ~/project
nano use_conditionals.yml

Добавьте следующее содержимое:

---
- 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]

Этот плейбук создает три разных файла, используя один и тот же шаблон, но с разными значениями переменных, демонстрируя, как работают условные операторы в шаблоне.

Запустите плейбук:

ansible-playbook use_conditionals.yml

Вывод показывает, как содержимое шаблона меняется в зависимости от разных условий.

Циклы в Jinja2

Jinja2 предоставляет конструкции для циклов, которые позволяют перебирать списки и словари. Это особенно полезно, когда вам нужно генерировать повторяющийся контент на основе переменных данных.

Создайте новый файл шаблона с именем loops.j2:

cd ~/project/templates
nano loops.j2

Добавьте следующее содержимое:

1. Simple loop:
{% for item in simple_list %}
   - {{ item }}
{% endfor %}

2. Loop with index:
{% for item in simple_list %}
   {{ loop.index }}. {{ item }}
{% endfor %}

3. Loop over a dictionary:
{% for key, value in simple_dict.items() %}
   {{ key }}: {{ value }}
{% endfor %}

4. Nested loop:
{% for category, items in nested_dict.items() %}
   {{ category }}:
   {% for item in items %}
     - {{ item }}
   {% endfor %}
{% endfor %}

5. Conditional in loop:
{% for item in simple_list %}
   {% if loop.first %}First item: {% endif %}
   {% if loop.last %}Last item: {% endif %}
   {{ item }}
{% endfor %}

Теперь создадим плейбук для использования этого шаблона. Вернитесь в корень проекта и создайте новый файл с именем use_loops.yml:

cd ~/project
nano use_loops.yml

Добавьте следующее содержимое:

---
- 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

Этот плейбук демонстрирует различные способы использования циклов в шаблонах Jinja2.

Запустите плейбук:

ansible-playbook use_loops.yml

Вывод показывает, как различные конструкции циклов в шаблоне генерируют контент на основе предоставленных переменных.

Продвинутые техники Jinja2

В этом последнем шаге мы рассмотрим некоторые продвинутые техники Jinja2, включая макросы и фильтры. Макросы — это повторно используемые фрагменты шаблонов, аналогичные функциям в языках программирования.

Создайте новый файл шаблона с именем advanced.j2:

cd ~/project/templates
nano advanced.j2

Добавьте следующее содержимое:

{% macro render_list(title, items) %}
{{ title }}:
{% for item in items %}
  - {{ item }}
{% endfor %}
{% endmacro %}

1. Using a macro:
{{ render_list("Fruits", fruits) }}

{{ render_list("Vegetables", vegetables) }}

2. Using set:
{% set greeting = "Hello, " + name + "!" %}
{{ greeting }}

3. Custom filter (defined in playbook):
{{ complex_data | to_nice_json }}

4. Whitespace control:
{% for item in fruits -%}
    {{ item }}
{%- if not loop.last %}, {% endif %}
{%- endfor %}

5. Raw block (no processing):
{% raw %}
This {{ will_not_be_processed }}
{% endraw %}

6. Include another template:
{% include 'simple_include.j2' %}

Теперь создадим простой включаемый файл. Создайте новый файл с именем simple_include.j2:

nano simple_include.j2

Добавьте следующее содержимое:

This is content from an included template.
Current user: {{ ansible_user_id }}

Теперь создадим плейбук для использования этого продвинутого шаблона. Вернитесь в корень проекта и создайте новый файл с именем use_advanced.yml:

cd ~/project
nano use_advanced.yml

Добавьте следующее содержимое:

---
- 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

Этот плейбук демонстрирует продвинутые техники Jinja2, включая макросы, пользовательские фильтры, управление пробелами и включение других шаблонов.

Запустите плейбук:

ansible-playbook use_advanced.yml

Вывод показывает, как эти продвинутые техники Jinja2 работают на практике.

Итоги

В этом практическом занятии вы изучили использование шаблонов Jinja2 в Ansible, рассмотрев широкий спектр возможностей и техник. Вот основные выводы:

  1. Базовый синтаксис Jinja2: Вы узнали, как использовать переменные и факты Ansible в шаблонах.
  2. Фильтры Jinja2: Вы исследовали различные встроенные фильтры для манипуляции данными в шаблонах.
  3. Условные операторы: Вы использовали конструкции if-elif-else для создания динамического контента в зависимости от условий.
  4. Циклы: Вы научились перебирать списки и словари, включая вложенные циклы и управление циклами.
  5. Продвинутые техники: Вы изучили макросы, пользовательские фильтры, управление пробелами, блоки raw и включение других шаблонов.

Эти возможности Jinja2 позволяют создавать высоко динамические и гибкие шаблоны в Ansible. Они дают возможность генерировать конфигурационные файлы, скрипты и другой контент, который может адаптироваться к различным сценариям и входным данным.

По мере продолжения работы с Ansible вы заметите, что овладение шаблонированием Jinja2 является важным условием для создания эффективных и адаптивных плейбуков и ролей. Это позволяет писать более компактный и поддерживаемый код, уменьшая дублирование и делая ваши проекты на Ansible более масштабируемыми.

Не забывайте, что хотя Jinja2 является мощным инструментом, важно найти баланс между гибкостью и читаемостью. Слишком сложные шаблоны могут быть трудными для поддержки, поэтому всегда стремитесь к ясности в дизайне своих шаблонов.

Практикуйте использование этих возможностей Jinja2 в своих проектах на Ansible, и вы сможете легко справляться с все более сложными задачами автоматизации.