소개
이 랩에서는 Ansible 에서 사용되는 강력한 템플릿 엔진인 Jinja2 를 탐구합니다. Jinja2 를 사용하면 동적 콘텐츠를 생성하여 Ansible 플레이북의 유연성과 적응성을 높일 수 있습니다. 이 랩을 마치면 변수, 필터, 조건문 및 루프를 포함하여 Ansible 에서 Jinja2 구문을 사용하는 방법을 이해하게 됩니다. 이 지식을 통해 더욱 동적이고 효율적인 Ansible 플레이북과 역할을 만들 수 있습니다.
이 랩에서는 Ansible 에서 사용되는 강력한 템플릿 엔진인 Jinja2 를 탐구합니다. Jinja2 를 사용하면 동적 콘텐츠를 생성하여 Ansible 플레이북의 유연성과 적응성을 높일 수 있습니다. 이 랩을 마치면 변수, 필터, 조건문 및 루프를 포함하여 Ansible 에서 Jinja2 구문을 사용하는 방법을 이해하게 됩니다. 이 지식을 통해 더욱 동적이고 효율적인 Ansible 플레이북과 역할을 만들 수 있습니다.
Jinja2 는 Django 의 템플릿을 모델로 한 Python 용 현대적이고 디자이너 친화적인 템플릿 언어입니다. 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 팩트 (fact) 입니다.이제 이 템플릿을 사용하기 위한 플레이북을 만들어 보겠습니다. 프로젝트 루트로 돌아가서 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 필터는 변수에 적용할 수 있는 함수입니다. 파이프 기호 (|) 로 변수와 구분됩니다. 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 를 사용하면 템플릿에서 조건문을 사용할 수 있습니다. 이는 특정 조건에 따라 콘텐츠를 포함하거나 제외해야 할 때 특히 유용합니다.
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 는 리스트 (list) 와 딕셔너리 (dictionary) 를 반복 처리할 수 있는 루프 구문을 제공합니다. 이는 변수 데이터를 기반으로 반복적인 콘텐츠를 생성해야 할 때 특히 유용합니다.
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
출력 결과는 템플릿의 다양한 루프 구문이 제공된 변수를 기반으로 어떻게 콘텐츠를 생성하는지 보여줍니다.
이 마지막 단계에서는 매크로 (macros) 와 필터 (filters) 를 포함한 몇 가지 고급 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' %}
이제 간단한 include 파일을 만들어 보겠습니다. 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 기술이 실제로 어떻게 작동하는지 보여줍니다.
이 랩에서는 Ansible 에서 Jinja2 템플릿을 탐구하여 광범위한 기능과 기술을 다루었습니다. 다음은 주요 내용입니다.
이러한 Jinja2 기능을 사용하면 Ansible 에서 매우 동적이고 유연한 템플릿을 만들 수 있습니다. 이를 통해 다양한 시나리오와 데이터 입력에 적응할 수 있는 구성 파일, 스크립트 및 기타 콘텐츠를 생성할 수 있습니다.
Ansible 작업을 계속하면서 Jinja2 템플릿을 마스터하는 것이 효율적이고 적응 가능한 플레이북 (playbooks) 과 롤 (roles) 을 만드는 데 매우 중요하다는 것을 알게 될 것입니다. 이를 통해 더 간결하고 유지 관리 가능한 코드를 작성하여 반복을 줄이고 Ansible 프로젝트의 확장성을 높일 수 있습니다.
Jinja2 가 강력하지만 유연성과 가독성의 균형을 맞추는 것이 중요합니다. 지나치게 복잡한 템플릿은 유지 관리가 어려울 수 있으므로 템플릿 디자인에서 항상 명확성을 추구하십시오.
Ansible 프로젝트에서 이러한 Jinja2 기능을 연습하면 점점 더 복잡한 자동화 작업을 쉽게 처리할 수 있습니다.