跳至内容

Ansible - 使用过滤器

在本章中,您将学习如何使用 jinja 过滤器转换数据。


目标:在本章中,您将学习如何

✔ 转换数据结构,如字典或列表;
✔ 转换变量。

🏁 ansiblejinja过滤器

知识⭐ ⭐ ⭐
复杂度⭐ ⭐ ⭐ ⭐

阅读时间:20 分钟


在前面的章节中,我们已经有机会使用 jinja 过滤器。

这些用 python 编写的过滤器允许我们操作和转换我们的 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

或者将变量转换为布尔值

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

仅保留两个列表的交集(两个列表中都存在的 value)

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

或者相反,只保留差集(在第二个列表中不存在的 value)

- 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

你可能需要导入 json 数据(例如来自 API)或将数据导出为 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]"
}

默认值、可选变量、保护变量

如果你没有为你的变量提供默认值,或者没有保护它们,那么在执行你的 playbook 时,你很快就会遇到错误。

如果一个变量不存在,可以使用 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 生成散列密码。

作者:Antoine Le Morvan

贡献者:Steven Spencer, Ganna Zhyrnova