콘텐츠로 이동

Ansible - 필터 작업

이 문서에서는 jinja 필터를 사용하여 데이터를 변환하는 방법을 배웁니다.


목적: 이 문서에서는 다음을 수행하는 방법에 대해 알아볼 것 입니다:

✔ 딕셔너리나 리스트와 같은 데이터 구조를 변환하는 방법 ✔ 변수를 변환하는 방법

🏁 ansible, jinja, 필터

지식: ⭐ ⭐ ⭐
복잡성: ⭐ ⭐ ⭐ ⭐

소요 시간: 20분


우리는 이미 이전 문서에서 jinja 필터를 사용하는 기회를 가졌습니다.

이러한 필터는 파이썬으로 작성되어 우리의 Ansible 변수를 조작하고 변환하는 데 사용됩니다.

참고

자세한 내용은 여기에서 확인할 수 있습니다.

이 문서에서는 다음 플레이북을 사용하여 제시된 다양한 필터를 테스트합니다:

- name: Manipulating the data
  hosts: localhost
  gather_facts: false
  vars:
    zero: 0
    zero_string: "0"
    non_zero: 4
    true_booleen: True
    true_non_booleen: "True"
    false_boolean: False
    false_non_boolean: "False"
    whatever: "It's false!"
    user_name: antoine
    my_dictionary:
      key1: value1
      key2: value2
    my_simple_list:
      - value_list_1
      - value_list_2
      - value_list_3
    my_simple_list_2:
      - value_list_3
      - value_list_4
      - value_list_5
    my_list:
      - element: element1
        value: value1
      - element: element2
        value: value2

  tasks:
    - name: Print an integer
      debug:
        var: zero

참고

다음은 가장 자주 만나게 되거나 필요한 필터의 비완전한 목록입니다. 다행히도 다른 필터도 많이 있습니다. 심지어 직접 만들 수도 있습니다!

플레이북은 다음과 같이 실행됩니다.

ansible-playbook play-filter.yml

데이터 변환하기

데이터는 한 유형에서 다른 유형으로 변환될 수 있습니다.

데이터의 유형(Python 언어의 유형)을 알려면 type_debug 필터를 사용해야 합니다.

예시:

- name: Display the type of a variable
  debug:
    var: true_boolean|type_debug

이는 우리에게 다음을 제공합니다.

TASK [Display the type of a variable] ******************************************************************
ok: [localhost] => {
    "true_boolean|type_debug": "bool"
}

정수를 문자열로 변환할 수 있습니다.

- name: Transforming a variable type
  debug:
    var: zero|string
TASK [Transforming a variable type] ***************************************************************
ok: [localhost] => {
    "zero|string": "0"
}

문자열을 정수로 변환:

- name: Transforming a variable type
  debug:
    var: zero_string|int

또는 boolean의 변수:

- name: Display an integer as a boolean
  debug:
    var: non_zero | bool

- name: Display a string as a boolean
  debug:
    var: true_non_boolean | bool

- name: Display a string as a boolean
  debug:
    var: false_non_boolean | bool

- name: Display a string as a boolean
  debug:
    var: whatever | bool

문자열은 대문자 또는 소문자로 변환할 수 있습니다.

- name: Lowercase a string of characters
  debug:
    var: whatever | lower

- name: Upercase a string of characters
  debug:
    var: whatever | upper

이는 우리에게 다음을 제공합니다.

TASK [Lowercase a string of characters] *****************************************************
ok: [localhost] => {
    "whatever | lower": "it's false!"
}

TASK [Upercase a string of characters] *****************************************************
ok: [localhost] => {
    "whatever | upper": "IT'S FALSE!"
}

replace 필터를 사용하면 문자를 다른 문자로 대체할 수 있습니다.

여기에서는 공백을 제거하거나 단어를 대체하는 예제입니다:

- name: Replace a character in a string
  debug:
    var: whatever | replace(" ", "")

- name: Replace a word in a string
  debug:
    var: whatever | replace("false", "true")

이는 우리에게 다음을 제공합니다.

TASK [Replace a character in a string] *****************************************************
ok: [localhost] => {
    "whatever | replace(\" \", \"\")": "It'sfalse!"
}

TASK [Replace a word in a string] *****************************************************
ok: [localhost] => {
    "whatever | replace(\"false\", \"true\")": "It's true !"
}

split 필터는 문자를 기준으로 문자열을 리스트로 분리합니다:

- name: Cutting a string of characters
  debug:
    var: whatever | split(" ", "")
TASK [Cutting a string of characters] *****************************************************
ok: [localhost] => {
    "whatever | split(\" \")": [
        "It's",
        "false!"
    ]
}

리스트의 구성 요소 결합

리스트의 요소를 결합하는 방법에 대해 설명합니다. 각 요소 사이에 삽입할 문자 또는 문자열을 지정할 수 있습니다.

- name: Joining elements of a list
  debug:
    var: my_simple_list|join(",")

- name: Joining elements of a list
  debug:
    var: my_simple_list|join(" | ")

이는 우리에게 다음을 제공합니다.

TASK [Joining elements of a list] *****************************************************************
ok: [localhost] => {
    "my_simple_list|join(\",\")": "value_list_1,value_list_2,value_list_3"
}

TASK [Joining elements of a list] *****************************************************************
ok: [localhost] => {
    "my_simple_list|join(\" | \")": "value_list_1 | value_list_2 | value_list_3"
}

딕셔너리를 리스트로 변환(또는 그 반대로)

필터 dict2itemsitemstodict는 구현하기가 조금 더 복잡합니다.

변환 과정에서 사용할 키와 값을 지정할 수 있습니다.

- name: Display a dictionary
  debug:
    var: my_dictionary

- name: Transforming a dictionary into a list
  debug:
    var: my_dictionary | dict2items

- name: Transforming a dictionary into a list
  debug:
    var: my_dictionary | dict2items(key_name='key', value_name='value')

- name: Transforming a list into a dictionary
  debug:
    var: my_list | items2dict(key_name='element', value_name='value')
TASK [Display a dictionary] *************************************************************************
ok: [localhost] => {
    "my_dictionary": {
        "key1": "value1",
        "key2": "value2"
    }
}

TASK [Transforming a dictionary into a list] *************************************************************
ok: [localhost] => {
    "my_dictionary | dict2items": [
        {
            "key": "key1",
            "value": "value1"
        },
        {
            "key": "key2",
            "value": "value2"
        }
    ]
}

TASK [Transforming a dictionary into a list] *************************************************************
ok: [localhost] => {
    "my_dictionary | dict2items (key_name = 'key', value_name = 'value')": [
        {
            "key": "key1",
            "value": "value1"
        },
        {
            "key": "key2",
            "value": "value2"
        }
    ]
}

TASK [Transforming a list into a dictionary] ************************************************************
ok: [localhost] => {
    "my_list | items2dict(key_name='element', value_name='value')": {
        "element1": "value1",
        "element2": "value2"
    }
}

리스트 작업

하나 이상의 리스트에서 데이터를 병합하거나 필터링할 수 있습니다.

- name: Merger of two lists
  debug:
    var: my_simple_list | union(my_simple_list_2)
ok: [localhost] => {
    "my_simple_list | union(my_simple_list_2)": [
        "value_list_1",
        "value_list_2",
        "value_list_3",
        "value_list_4",
        "value_list_5"
    ]
}

두 리스트의 교집합만 유지하려면 (두 리스트에 모두 있는 값):

- name: Merger of two lists
  debug:
    var: my_simple_list | intersect(my_simple_list_2)
TASK [Merger of two lists] *******************************************************************************
ok: [localhost] => {
    "my_simple_list | intersect(my_simple_list_2)": [
        "value_list_3"
    ]
}

또는 반대로 차이점만 유지하려면 (두 번째 리스트에 존재하지 않는 값):

- name: Merger of two lists
  debug:
    var: my_simple_list | difference(my_simple_list_2)
TASK [Merger of two lists] *******************************************************************************
ok: [localhost] => {
    "my_simple_list | difference(my_simple_list_2)": [
        "value_list_1",
        "value_list_2",
    ]
}

리스트에 중복되는 값이 포함되어 있는 경우, unique 필터를 사용하여 중복 값을 필터링할 수도 있습니다.

- name: Unique value in a list
  debug:
    var: my_simple_list | unique

json/yaml 변환

API에서 JSON 데이터를 가져오거나 데이터를 YAML 또는 JSON으로 내보내야 할 수도 있습니다.

- name: Display a variable in yaml
  debug:
    var: my_list | to_nice_yaml(indent=4)

- name: Display a variable in json
  debug:
    var: my_list | to_nice_json(indent=4)
TASK [Display a variable in yaml] ********************************************************************
ok: [localhost] => {
    "my_list | to_nice_yaml(indent=4)": "-   element: element1\n    value: value1\n-   element: element2\n    value: value2\n"
}

TASK [Display a variable in json] ********************************************************************
ok: [localhost] => {
    "my_list | to_nice_json(indent=4)": "[\n    {\n        \"element\": \"element1\",\n        \"value\": \"value1\"\n    },\n    {\n        \"element\": \"element2\",\n        \"value\": \"value2\"\n    }\n]"
}

기본값, 선택적 변수, 변수 보호

플레이북 실행 중에 변수에 기본값을 제공하지 않거나 보호하지 않으면 빠른 시간 내에 오류에 직면하게 됩니다.

변수 값은 default 필터와 함께 존재하지 않는 경우 다른 값으로 대체될 수 있습니다.

- name: Default value
  debug:
    var: variablethatdoesnotexists | default(whatever)
TASK [Default value] ********************************************************************************
ok: [localhost] => {
    "variablethatdoesnotexists | default(whatever)": "It's false!"
}

예를 들어 shell 모듈을 사용하는 경우 보호되어야 하는 아포스트로피 '가 있음에 유의하십시오.

- name: Default value
  debug:
    var: variablethatdoesnotexists | default(whatever| quote)
TASK [Default value] ********************************************************************************
ok: [localhost] => {
    "variablethatdoesnotexists | default(whatever|quote)": "'It'\"'\"'s false!'"
}

마지막으로 모듈의 선택적 변수는 default 필터에 omit 키워드를 사용하여 해당 변수가 존재하지 않는 경우 무시될 수 있으며, 이는 런타임 오류를 방지해줍니다.

- name: Add a new user
  ansible.builtin.user:
    name: "{{ user_name }}"
    comment: "{{ user_comment | default(omit) }}"

다른 값에 따라 값 연결(ternary)

가끔 조건에 따라 변수에 값을 할당해야 할 때가 있는데, 이 경우 set_fact 단계를 거치는 것이 일반적입니다.

ternary 필터를 사용하여 이를 피할 수 있습니다.

- name: Default value
  debug:
    var: (user_name == 'antoine') | ternary('admin', 'normal_user')
TASK [Default value] ********************************************************************************
ok: [localhost] => {
    "(user_name == 'antoine') | ternary('admin', 'normal_user')": "admin"
}

기타 필터

  • {{ 10000 | random }}: 이름에서 알 수 있듯이 임의의 값을 반환합니다.
  • {{ my_simple_list | first }}: 리스트의 첫 번째 요소를 추출합니다.
  • {{ my_simple_list | length }}: 길이를 반환합니다 (리스트 또는 문자열).
  • {{ ip_list | ansible.netcommon.ipv4 }}: v4 IP만 표시합니다. 자세히 설명하지 않겠지만, 필요하다면 네트워크에 관련된 많은 필터가 있습니다.
  • {{ user_password | password_hash('sha512') }}: sha512로 해시된 암호를 생성합니다.

Author: Antoine Le Morvan

Contributors: Steven Spencer