使用过滤器操作数据
过滤器允许您将 JSON 数据转换为 YAML 数据、拆分 URL 以提取主机名、获取字符串的 SHA1 哈希值、添加或乘以整数等等。您可以使用此处记录的特定于 Ansible 的过滤器来操作您的数据,或者使用与 Jinja2 一起提供的任何标准过滤器 - 请参阅官方 Jinja2 模板文档中 内置过滤器 的列表。您还可以使用 Python 方法 来转换数据。您可以 创建自定义 Ansible 过滤器作为插件,尽管我们通常欢迎将新过滤器添加到 ansible-core 存储库中,以便每个人都可以使用它们。
由于模板化是在 Ansible 控制节点上进行的,而不是在目标主机上进行的,因此过滤器在控制节点上执行并在本地转换数据。
处理未定义的变量
过滤器可以通过提供默认值或使某些变量可选来帮助您管理缺失或未定义的变量。如果您配置 Ansible 忽略大多数未定义的变量,则可以使用 mandatory
过滤器将某些变量标记为需要值。
提供默认值
您可以使用 Jinja2 的“default”过滤器直接在模板中为变量提供默认值。这通常比在未定义变量时失败更好的方法
{{ some_variable | default(5) }}
在上面的示例中,如果变量“some_variable”未定义,Ansible 将使用默认值 5,而不是引发“未定义变量”错误并失败。如果您在角色中工作,也可以添加角色默认值来定义角色中变量的默认值。要了解有关角色默认值的更多信息,请参阅 角色目录结构。
从版本 2.8 开始,尝试访问 Jinja 中 Undefined 值的属性将返回另一个 Undefined 值,而不是立即抛出错误。这意味着您现在可以简单地在嵌套数据结构中使用带有值的默认值(换句话说,{{ foo.bar.baz | default('DEFAULT') }}
),当您不知道中间值是否已定义时。
如果要在变量计算为 false 或空字符串时使用默认值,则必须将第二个参数设置为 true
{{ lookup('env', 'MY_USER') | default('admin', true) }}
使变量可选
默认情况下,Ansible 要求模板表达式中的所有变量都有值。但是,您可以使特定模块变量可选。例如,您可能希望对某些项目使用系统默认值,并控制其他项目的 value。要使模块变量可选,请将默认值设置为特殊变量 omit
- name: Touch files with an optional mode
ansible.builtin.file:
dest: "{{ item.path }}"
state: touch
mode: "{{ item.mode | default(omit) }}"
loop:
- path: /tmp/foo
- path: /tmp/bar
- path: /tmp/baz
mode: "0444"
在此示例中,文件 /tmp/foo
和 /tmp/bar
的默认模式由系统的 umask 决定。Ansible 不会为 mode
发送值。只有第三个文件 /tmp/baz
会收到 mode=0444 选项。
注意
如果您在 default(omit)
过滤器之后“链接”其他过滤器,您应该改为执行类似以下操作:"{{ foo | default(None) | some_filter or omit }}"
。在此示例中,默认 None
(Python 空)值将导致后面的过滤器失败,这将触发逻辑的 or omit
部分。但是,以这种方式使用 omit
对您正在链接的后面过滤器非常具体,因此如果您这样做,请准备好进行一些尝试和错误。
定义必填值
如果您配置 Ansible 忽略未定义的变量,您可能希望将某些值定义为必填的。默认情况下,如果剧本或命令中的变量未定义,Ansible 将失败。您可以通过将 DEFAULT_UNDEFINED_VAR_BEHAVIOR 设置为 false
来配置 Ansible 以允许未定义的变量。在这种情况下,您可能希望要求定义某些变量。您可以使用以下方法来实现:
{{ variable | mandatory }}
变量值将按原样使用,但如果变量未定义,模板评估将引发错误。
要求覆盖变量的一种便捷方法是使用 undef() 函数为其赋予未定义的值。
galaxy_url: "https://galaxy.ansible.com"
galaxy_api_key: "{{ undef(hint='You must specify your Galaxy API key') }}"
为 true/false/null 定义不同的值(三元运算符)
您可以创建一个测试,然后定义一个值在测试返回 true 时使用,另一个值在测试返回 false 时使用(版本 1.9 中的新增功能)
{{ (status == 'needs_restart') | ternary('restart', 'continue') }}
此外,您可以在 true 上定义一个值,在 false 上定义一个值,在 null 上定义第三个值(版本 2.8 中的新增功能)
{{ enabled | ternary('no shutdown', 'shutdown', omit) }}
管理数据类型
您可能需要了解、更改或设置变量的数据类型。例如,注册的变量可能包含字典,而您的下一个任务需要列表,或者用户 提示 可能返回字符串,而您的剧本需要布尔值。使用 ansible.builtin.type_debug、ansible.builtin.dict2items 和 ansible.builtin.items2dict 过滤器来管理数据类型。您也可以使用数据类型本身将值转换为特定数据类型。
发现数据类型
版本 2.3 中的新增功能。
如果您不确定变量的底层 Python 类型,可以使用 ansible.builtin.type_debug 过滤器来显示它。这在您需要特定类型变量的调试时很有用。
{{ myvar | type_debug }}
您应该注意,虽然这似乎是一个用于检查变量中是否具有正确数据类型的有用过滤器,但您通常应该优先使用 类型测试,这将允许您测试特定数据类型。
将字符串转换为列表
使用 ansible.builtin.split 过滤器将字符/字符串分隔的字符串转换为适合 循环 的项目列表。例如,如果您想通过逗号分割字符串变量 fruits,您可以使用
{{ fruits | split(',') }}
字符串数据(在应用 ansible.builtin.split 过滤器之前)
fruits: apple,banana,orange
列表数据(在应用 ansible.builtin.split 过滤器之后)
- apple
- banana
- orange
将字典转换为列表
版本 2.6 中的新功能。
使用 ansible.builtin.dict2items 过滤器将字典转换为适合 循环 的项目列表
{{ dict | dict2items }}
字典数据(在应用 ansible.builtin.dict2items 过滤器之前)
tags:
Application: payment
Environment: dev
列表数据(在应用 ansible.builtin.dict2items 过滤器之后)
- key: Application
value: payment
- key: Environment
value: dev
版本 2.8 中的新功能。
ansible.builtin.dict2items 过滤器是 ansible.builtin.items2dict 过滤器的反向。
如果您想配置键的名称,ansible.builtin.dict2items 过滤器接受 2 个关键字参数。传递 key_name
和 value_name
参数来配置列表输出中键的名称
{{ files | dict2items(key_name='file', value_name='path') }}
字典数据(在应用 ansible.builtin.dict2items 过滤器之前)
files:
users: /etc/passwd
groups: /etc/group
列表数据(在应用 ansible.builtin.dict2items 过滤器之后)
- file: users
path: /etc/passwd
- file: groups
path: /etc/group
将列表转换为字典
版本 2.7 中的新功能。
使用 ansible.builtin.items2dict 过滤器将列表转换为字典,将内容映射到 key: value
对
{{ tags | items2dict }}
列表数据(在应用 ansible.builtin.items2dict 过滤器之前)
tags:
- key: Application
value: payment
- key: Environment
value: dev
字典数据(在应用 ansible.builtin.items2dict 过滤器之后)
Application: payment
Environment: dev
ansible.builtin.items2dict 过滤器是 ansible.builtin.dict2items 过滤器的反向。
并非所有列表都使用 key
来指定键,并使用 value
来指定值。例如
fruits:
- fruit: apple
color: red
- fruit: pear
color: yellow
- fruit: grapefruit
color: yellow
在此示例中,您必须传递 key_name
和 value_name
参数来配置转换。例如
{{ fruits | items2dict(key_name='fruit', value_name='color') }}
如果您不传递这些参数,或者没有为您的列表传递正确的值,您将看到 KeyError: key
或 KeyError: my_typo
。
强制数据类型
您可以将值强制转换为特定类型。例如,如果您期望来自 vars_prompt 的输入“True”,并且您希望 Ansible 将其识别为布尔值而不是字符串
- ansible.builtin.debug:
msg: test
when: some_string_value | bool
如果您想对事实进行数学比较,并且您希望 Ansible 将其识别为整数而不是字符串
- shell: echo "only on Red Hat 6, derivatives, and later"
when: ansible_facts['os_family'] == "RedHat" and ansible_facts['lsb']['major_release'] | int >= 6
版本 1.6 中的新功能。
格式化数据:YAML 和 JSON
您可以将模板中的数据结构从 JSON 或 YAML 格式切换到或从 JSON 或 YAML 格式切换到,并提供格式化、缩进和加载数据的选项。基本过滤器偶尔用于调试
{{ some_variable | to_json }}
{{ some_variable | to_yaml }}
有关这些过滤器的文档,请参见 ansible.builtin.to_json 和 ansible.builtin.to_yaml。
对于人类可读的输出,您可以使用
{{ some_variable | to_nice_json }}
{{ some_variable | to_nice_yaml }}
有关这些过滤器的文档,请参见 ansible.builtin.to_nice_json 和 ansible.builtin.to_nice_yaml。
您可以更改两种格式的缩进
{{ some_variable | to_nice_json(indent=2) }}
{{ some_variable | to_nice_yaml(indent=8) }}
ansible.builtin.to_yaml 和 ansible.builtin.to_nice_yaml 过滤器使用 PyYAML 库,该库具有默认的 80 个符号字符串长度限制。这会导致在第 80 个符号之后出现意外的换行符(如果第 80 个符号之后有空格)。为了避免这种行为并生成长行,请使用 width
选项。您必须使用硬编码的数字来定义宽度,而不是像 float("inf")
这样的构造,因为过滤器不支持代理 Python 函数。例如
{{ some_variable | to_yaml(indent=8, width=1337) }}
{{ some_variable | to_nice_yaml(indent=8, width=1337) }}
过滤器支持传递其他 YAML 参数。有关完整列表,请参见 PyYAML 文档 中的 dump()
。
如果您正在读取一些已格式化的数据
{{ some_variable | from_json }}
{{ some_variable | from_yaml }}
例如
tasks:
- name: Register JSON output as a variable
ansible.builtin.shell: cat /some/path/to/file.json
register: result
- name: Set a variable
ansible.builtin.set_fact:
myvar: "{{ result.stdout | from_json }}"
过滤器 to_json 和 Unicode 支持
默认情况下,ansible.builtin.to_json 和 ansible.builtin.to_nice_json 将接收到的数据转换为 ASCII,因此
{{ 'München'| to_json }}
将返回
'M\u00fcnchen'
要保留 Unicode 字符,请将参数 ensure_ascii=False
传递给过滤器
{{ 'München'| to_json(ensure_ascii=False) }}
'München'
版本 2.7 中的新功能。
要解析多文档 YAML 字符串,提供了 ansible.builtin.from_yaml_all 过滤器。 ansible.builtin.from_yaml_all 过滤器将返回解析的 YAML 文档的生成器。
例如
tasks:
- name: Register a file content as a variable
ansible.builtin.shell: cat /some/path/to/multidoc-file.yaml
register: result
- name: Print the transformed variable
ansible.builtin.debug:
msg: '{{ item }}'
loop: '{{ result.stdout | from_yaml_all | list }}'
组合和选择数据
您可以组合来自多个源和类型的,并从大型数据结构中选择值,从而使您对复杂数据进行精确控制。
组合来自多个列表的项目:zip 和 zip_longest
版本 2.3 中的新增功能。
要获得一个组合了其他列表元素的列表,请使用 ansible.builtin.zip
- name: Give me list combo of two lists
ansible.builtin.debug:
msg: "{{ [1,2,3,4,5,6] | zip(['a','b','c','d','e','f']) | list }}"
# => [[1, "a"], [2, "b"], [3, "c"], [4, "d"], [5, "e"], [6, "f"]]
- name: Give me the shortest combo of two lists
ansible.builtin.debug:
msg: "{{ [1,2,3] | zip(['a','b','c','d','e','f']) | list }}"
# => [[1, "a"], [2, "b"], [3, "c"]]
要始终穷尽所有列表,请使用 ansible.builtin.zip_longest
- name: Give me the longest combo of three lists, fill with X
ansible.builtin.debug:
msg: "{{ [1,2,3] | zip_longest(['a','b','c','d','e','f'], [21, 22, 23], fillvalue='X') | list }}"
# => [[1, "a", 21], [2, "b", 22], [3, "c", 23], ["X", "d", "X"], ["X", "e", "X"], ["X", "f", "X"]]
与上面提到的 ansible.builtin.items2dict 过滤器的输出类似,这些过滤器可用于构建 dict
{{ dict(keys_list | zip(values_list)) }}
列表数据(在应用 ansible.builtin.zip 过滤器之前)
keys_list:
- one
- two
values_list:
- apple
- orange
字典数据(在应用 ansible.builtin.zip 过滤器之后)
one: apple
two: orange
组合对象和子元素
版本 2.7 中的新功能。
ansible.builtin.subelements 过滤器生成对象与其子元素值的乘积,类似于 ansible.builtin.subelements 查找。这使您能够指定在模板中使用的单个子元素。例如,此表达式
{{ users | subelements('groups', skip_missing=True) }}
应用 ansible.builtin.subelements 过滤器之前的 数据
users:
- name: alice
authorized:
- /tmp/alice/onekey.pub
- /tmp/alice/twokey.pub
groups:
- wheel
- docker
- name: bob
authorized:
- /tmp/bob/id_rsa.pub
groups:
- docker
应用 ansible.builtin.subelements 过滤器之后的数据
-
- name: alice
groups:
- wheel
- docker
authorized:
- /tmp/alice/onekey.pub
- /tmp/alice/twokey.pub
- wheel
-
- name: alice
groups:
- wheel
- docker
authorized:
- /tmp/alice/onekey.pub
- /tmp/alice/twokey.pub
- docker
-
- name: bob
authorized:
- /tmp/bob/id_rsa.pub
groups:
- docker
- docker
您可以使用转换后的数据与 loop
来迭代多个对象中的相同子元素
- name: Set authorized ssh key, extracting just that data from 'users'
ansible.posix.authorized_key:
user: "{{ item.0.name }}"
key: "{{ lookup('file', item.1) }}"
loop: "{{ users | subelements('authorized') }}"
组合哈希/字典
新增于 2.0 版本。
ansible.builtin.combine 过滤器允许合并哈希。例如,以下示例将覆盖一个哈希中的键
{{ {'a':1, 'b':2} | combine({'b':3}) }}
最终的哈希将是
{'a':1, 'b':3}
该过滤器还可以接受多个参数来合并
{{ a | combine(b, c, d) }}
{{ [a, b, c, d] | combine }}
在这种情况下,d
中的键将覆盖 c
中的键,而 c
中的键将覆盖 b
中的键,依此类推。
该过滤器还接受两个可选参数:recursive
和 list_merge
。
- recursive
是一个布尔值,默认为
False
。是否 ansible.builtin.combine 递归地合并嵌套的哈希。注意:它不依赖于ansible.cfg
中的hash_behaviour
设置的值。- list_merge
是一个字符串,其可能的值为
replace
(默认)、keep
、append
、prepend
、append_rp
或prepend_rp
。它修改了 ansible.builtin.combine 在要合并的哈希包含数组/列表时的行为。
default:
a:
x: default
y: default
b: default
c: default
patch:
a:
y: patch
z: patch
b: patch
如果 recursive=False
(默认),嵌套的哈希不会合并
{{ default | combine(patch) }}
这将导致
a:
y: patch
z: patch
b: patch
c: default
如果 recursive=True
,递归到嵌套的哈希中并合并它们的键
{{ default | combine(patch, recursive=True) }}
这将导致
a:
x: default
y: patch
z: patch
b: patch
c: default
如果 list_merge='replace'
(默认),右侧哈希中的数组将“替换”左侧哈希中的数组
default:
a:
- default
patch:
a:
- patch
{{ default | combine(patch) }}
这将导致
a:
- patch
如果 list_merge='keep'
,左侧哈希中的数组将被保留
{{ default | combine(patch, list_merge='keep') }}
这将导致
a:
- default
如果 list_merge='append'
,右侧哈希中的数组将被追加到左侧哈希中的数组
{{ default | combine(patch, list_merge='append') }}
这将导致
a:
- default
- patch
如果 list_merge='prepend'
,右侧哈希中的数组将被预置到左侧哈希中的数组
{{ default | combine(patch, list_merge='prepend') }}
这将导致
a:
- patch
- default
如果 list_merge='append_rp'
,右侧哈希中的数组将被追加到左侧哈希中的数组。左侧哈希中的数组中也出现在右侧哈希的相应数组中的元素将被删除(“rp”代表“删除存在”)。未出现在两个哈希中的重复元素将被保留
default:
a:
- 1
- 1
- 2
- 3
patch:
a:
- 3
- 4
- 5
- 5
{{ default | combine(patch, list_merge='append_rp') }}
这将导致
a:
- 1
- 1
- 2
- 3
- 4
- 5
- 5
如果 list_merge='prepend_rp'
,行为类似于 append_rp
,但右侧哈希中的数组元素将被预置
{{ default | combine(patch, list_merge='prepend_rp') }}
这将导致
a:
- 3
- 4
- 5
- 5
- 1
- 1
- 2
recursive
和 list_merge
可以一起使用
default:
a:
a':
x: default_value
y: default_value
list:
- default_value
b:
- 1
- 1
- 2
- 3
patch:
a:
a':
y: patch_value
z: patch_value
list:
- patch_value
b:
- 3
- 4
- 4
- key: value
{{ default | combine(patch, recursive=True, list_merge='append_rp') }}
这将导致
a:
a':
x: default_value
y: patch_value
z: patch_value
list:
- default_value
- patch_value
b:
- 1
- 1
- 2
- 3
- 4
- 4
- key: value
从数组或哈希表中选择值
新增于 2.1 版本。
extract 过滤器用于从容器(哈希或数组)中将索引列表映射到值列表
{{ [0,2] | map('extract', ['x','y','z']) | list }}
{{ ['x','y'] | map('extract', {'x': 42, 'y': 31}) | list }}
上述表达式的结果将是
['x', 'z']
[42, 31]
该过滤器可以接受另一个参数
{{ groups['x'] | map('extract', hostvars, 'ec2_ip_address') | list }}
这将在“x”组中获取主机列表,在 hostvars 中查找它们,然后查找结果的 ec2_ip_address。最终结果是“x”组中主机的 IP 地址列表。
该过滤器的第三个参数也可以是列表,用于在容器中进行递归查找
{{ ['a'] | map('extract', b, ['x','y']) | list }}
这将返回一个包含 b[‘a’][‘x’][‘y’] 值的列表。
组合列表
这组过滤器返回一个组合列表的列表。
permutations
要获取列表的排列
- name: Give me the largest permutations (order matters)
ansible.builtin.debug:
msg: "{{ [1,2,3,4,5] | ansible.builtin.permutations | list }}"
- name: Give me permutations of sets of three
ansible.builtin.debug:
msg: "{{ [1,2,3,4,5] | ansible.builtin.permutations(3) | list }}"
combinations
组合总是需要一个集合大小
- name: Give me combinations for sets of two
ansible.builtin.debug:
msg: "{{ [1,2,3,4,5] | ansible.builtin.combinations(2) | list }}"
另请参阅 zip_filter
products
product 过滤器返回输入可迭代对象的 笛卡尔积。这大致等同于生成器表达式中的嵌套 for 循环。
例如
- name: Generate multiple hostnames
ansible.builtin.debug:
msg: "{{ ['foo', 'bar'] | product(['com']) | map('join', '.') | join(',') }}"
这将导致
{ "msg": "foo.com,bar.com" }
选择 JSON 数据:JSON 查询
要从 JSON 格式的复杂数据结构(例如 Ansible 事实)中选择单个元素或数据子集,请使用 community.general.json_query 过滤器。community.general.json_query 过滤器允许您查询复杂的 JSON 结构并使用循环结构迭代它。
注意
此过滤器已迁移到 community.general 集合。请按照安装说明安装该集合。
注意
在使用此过滤器之前,您必须在 Ansible 控制节点上手动安装 jmespath 依赖项。此过滤器基于 jmespath,您可以使用相同的语法。有关示例,请参阅 jmespath 示例。
请考虑以下数据结构
{
"domain": {
"cluster": [
{
"name": "cluster1"
},
{
"name": "cluster2"
}
],
"server": [
{
"name": "server11",
"cluster": "cluster1",
"port": "8080"
},
{
"name": "server12",
"cluster": "cluster1",
"port": "8090"
},
{
"name": "server21",
"cluster": "cluster2",
"port": "9080"
},
{
"name": "server22",
"cluster": "cluster2",
"port": "9090"
}
],
"library": [
{
"name": "lib1",
"target": "cluster1"
},
{
"name": "lib2",
"target": "cluster2"
}
]
}
}
要从该结构中提取所有集群,可以使用以下查询
- name: Display all cluster names
ansible.builtin.debug:
var: item
loop: "{{ domain_definition | community.general.json_query('domain.cluster[*].name') }}"
要提取所有服务器名称
- name: Display all server names
ansible.builtin.debug:
var: item
loop: "{{ domain_definition | community.general.json_query('domain.server[*].name') }}"
要从 cluster1 中提取端口
- name: Display all ports from cluster1
ansible.builtin.debug:
var: item
loop: "{{ domain_definition | community.general.json_query(server_name_cluster1_query) }}"
vars:
server_name_cluster1_query: "domain.server[?cluster=='cluster1'].port"
注意
您可以使用变量使查询更具可读性。
要以逗号分隔的字符串形式打印 cluster1 中的端口
- name: Display all ports from cluster1 as a string
ansible.builtin.debug:
msg: "{{ domain_definition | community.general.json_query('domain.server[?cluster==`cluster1`].port') | join(', ') }}"
注意
在上面的示例中,使用反引号引用字面量可以避免转义引号并保持可读性。
您可以使用 YAML 单引号转义
- name: Display all ports from cluster1
ansible.builtin.debug:
var: item
loop: "{{ domain_definition | community.general.json_query('domain.server[?cluster==''cluster1''].port') }}"
注意
在 YAML 中,单引号内的单引号转义是通过将单引号加倍来完成的。
要获取一个包含所有集群端口和名称的哈希映射
- name: Display all server ports and names from cluster1
ansible.builtin.debug:
var: item
loop: "{{ domain_definition | community.general.json_query(server_name_cluster1_query) }}"
vars:
server_name_cluster1_query: "domain.server[?cluster=='cluster1'].{name: name, port: port}"
要从名称以“server1”开头的所有集群中提取端口
- name: Display ports from all clusters with the name starting with 'server1'
ansible.builtin.debug:
msg: "{{ domain_definition | to_json | from_json | community.general.json_query(server_name_query) }}"
vars:
server_name_query: "domain.server[?starts_with(name,'server1')].port"
要从名称包含“server1”的所有集群中提取端口
- name: Display ports from all clusters with the name containing 'server1'
ansible.builtin.debug:
msg: "{{ domain_definition | to_json | from_json | community.general.json_query(server_name_query) }}"
vars:
server_name_query: "domain.server[?contains(name,'server1')].port"
注意
在使用 starts_with
和 contains
时,您必须使用 `` to_json | from_json `` 过滤器来正确解析数据结构。
随机化数据
当您需要随机生成的值时,请使用以下过滤器之一。
随机 MAC 地址
版本 2.6 中的新功能。
此过滤器可用于从字符串前缀生成随机 MAC 地址。
注意
此过滤器已迁移到 community.general 集合。请按照安装说明安装该集合。
要从以“52:54:00”开头的字符串前缀获取随机 MAC 地址
"{{ '52:54:00' | community.general.random_mac }}"
# => '52:54:00:ef:1c:03'
请注意,如果前缀字符串有任何错误,该过滤器将发出错误。
新增于 2.9 版本。
从 Ansible 版本 2.9 开始,您还可以从种子初始化随机数生成器以创建随机但幂等的 MAC 地址
"{{ '52:54:00' | community.general.random_mac(seed=inventory_hostname) }}"
随机项目或数字
Ansible 中的 ansible.builtin.random 过滤器是对默认 Jinja2 随机过滤器的扩展,可用于从一系列项中返回随机项,或根据范围生成随机数。
从列表中获取随机项
"{{ ['a','b','c'] | random }}"
# => 'c'
获取 0(包含)到指定整数(不包含)之间的随机数
"{{ 60 | random }} * * * * root /script/from/cron"
# => '21 * * * * root /script/from/cron'
获取 0 到 100 之间的随机数,但步长为 10
{{ 101 | random(step=10) }}
# => 70
获取 1 到 100 之间的随机数,但步长为 10
{{ 101 | random(1, 10) }}
# => 31
{{ 101 | random(start=1, step=10) }}
# => 51
您可以从种子初始化随机数生成器,以创建随机但幂等的数字
"{{ 60 | random(seed=inventory_hostname) }} * * * * root /script/from/cron"
洗牌列表
The ansible.builtin.shuffle 过滤器随机化现有列表,在每次调用时提供不同的顺序。
从现有列表中获取随机列表
{{ ['a','b','c'] | shuffle }}
# => ['c','a','b']
{{ ['a','b','c'] | shuffle }}
# => ['b','c','a']
您可以从种子初始化洗牌生成器,以生成随机但幂等的顺序
{{ ['a','b','c'] | shuffle(seed=inventory_hostname) }}
# => ['b','a','c']
shuffle 过滤器在可能的情况下返回列表。如果您将其与非“可列表”项一起使用,则过滤器将不执行任何操作。
管理列表变量
您可以搜索列表中的最小值或最大值,或展平多级列表。
从数字列表中获取最小值
{{ list1 | min }}
版本 2.11 中的新增功能。
从对象列表中获取最小值
{{ [{'val': 1}, {'val': 2}] | min(attribute='val') }}
从数字列表中获取最大值
{{ [3, 4, 2] | max }}
版本 2.11 中的新增功能。
从对象列表中获取最大值
{{ [{'val': 1}, {'val': 2}] | max(attribute='val') }}
版本 2.5 中的新增功能。
展平列表(与 flatten 查找相同)
{{ [3, [4, 2] ] | flatten }}
# => [3, 4, 2]
仅展平列表的第一级(类似于 items 查找)
{{ [3, [4, [2]] ] | flatten(levels=1) }}
# => [3, 4, [2]]
版本 2.11 中的新增功能。
在列表中保留空值,默认情况下,展平会删除它们。
{{ [3, None, [4, [2]] ] | flatten(levels=1, skip_nulls=False) }}
# => [3, None, 4, [2]]
从集合或列表中选择(集合论)
您可以从集合或列表中选择或组合项。
版本 1.4 中的新增功能。
从列表中获取唯一集合
# list1: [1, 2, 5, 1, 3, 4, 10]
{{ list1 | unique }}
# => [1, 2, 5, 3, 4, 10]
获取两个列表的并集
# list1: [1, 2, 5, 1, 3, 4, 10]
# list2: [1, 2, 3, 4, 5, 11, 99]
{{ list1 | union(list2) }}
# => [1, 2, 5, 1, 3, 4, 10, 11, 99]
获取两个列表的交集(两个列表中所有项的唯一列表)
# list1: [1, 2, 5, 3, 4, 10]
# list2: [1, 2, 3, 4, 5, 11, 99]
{{ list1 | intersect(list2) }}
# => [1, 2, 5, 3, 4]
获取两个列表的差集(第一个列表中不存在于第二个列表中的项)
# list1: [1, 2, 5, 1, 3, 4, 10]
# list2: [1, 2, 3, 4, 5, 11, 99]
{{ list1 | difference(list2) }}
# => [10]
获取两个列表的对称差集(每个列表独有的项)
# list1: [1, 2, 5, 1, 3, 4, 10]
# list2: [1, 2, 3, 4, 5, 11, 99]
{{ list1 | symmetric_difference(list2) }}
# => [10, 11, 99]
计算数字(数学)
版本 1.9 中的新增功能。
您可以使用 Ansible 过滤器计算数字的对数、幂和根。Jinja2 提供其他数学函数,如 abs() 和 round()。
获取对数(默认值为 e)
{{ 8 | log }}
# => 2.0794415416798357
获取以 10 为底的对数
{{ 8 | log(10) }}
# => 0.9030899869919435
给我 2 的幂! (或 5)
{{ 8 | pow(5) }}
# => 32768.0
平方根或 5 次方
{{ 8 | root }}
# => 2.8284271247461903
{{ 8 | root(5) }}
# => 1.5157165665103982
管理网络交互
这些过滤器可以帮助您完成常见的网络任务。
注意
这些过滤器已迁移到 ansible.utils 集合。请按照安装说明安装该集合。
IP 地址过滤器
版本 1.9 中的新增功能。
测试字符串是否为有效的 IP 地址
{{ myvar | ansible.utils.ipaddr }}
您还可以要求特定的 IP 协议版本
{{ myvar | ansible.utils.ipv4 }}
{{ myvar | ansible.utils.ipv6 }}
IP 地址过滤器也可以用于从 IP 地址中提取特定信息。例如,要从 CIDR 中获取 IP 地址本身,您可以使用
{{ '192.0.2.1/24' | ansible.utils.ipaddr('address') }}
# => 192.0.2.1
有关 ansible.utils.ipaddr 过滤器的更多信息和完整使用指南,请参阅 Ansible.Utils。
网络 CLI 过滤器
版本 2.4 中的新增功能。
要将网络设备 CLI 命令的输出转换为结构化的 JSON 输出,请使用 ansible.netcommon.parse_cli 过滤器
{{ output | ansible.netcommon.parse_cli('path/to/spec') }}
The ansible.netcommon.parse_cli 过滤器将加载规范文件并将命令输出通过它传递,返回 JSON 输出。YAML 规范文件定义如何解析 CLI 输出。
规范文件应该是格式正确的 YAML。它定义了如何解析 CLI 输出并返回 JSON 数据。以下是一个有效的规范文件的示例,它将解析 show vlan
命令的输出。
---
vars:
vlan:
vlan_id: "{{ item.vlan_id }}"
name: "{{ item.name }}"
enabled: "{{ item.state != 'act/lshut' }}"
state: "{{ item.state }}"
keys:
vlans:
value: "{{ vlan }}"
items: "^(?P<vlan_id>\\d+)\\s+(?P<name>\\w+)\\s+(?P<state>active|act/lshut|suspended)"
state_static:
value: present
上面的规范文件将返回一个 JSON 数据结构,该结构是包含解析的 VLAN 信息的哈希列表。
可以使用 key 和 values 指令将相同命令解析为哈希。以下是如何使用相同的 show vlan
命令将输出解析为哈希值的示例。
---
vars:
vlan:
key: "{{ item.vlan_id }}"
values:
vlan_id: "{{ item.vlan_id }}"
name: "{{ item.name }}"
enabled: "{{ item.state != 'act/lshut' }}"
state: "{{ item.state }}"
keys:
vlans:
value: "{{ vlan }}"
items: "^(?P<vlan_id>\\d+)\\s+(?P<name>\\w+)\\s+(?P<state>active|act/lshut|suspended)"
state_static:
value: present
解析 CLI 命令的另一个常见用例是将大型命令分解为可以解析的块。这可以使用 start_block
和 end_block
指令来完成,这些指令可以将命令分解为可以解析的块。
---
vars:
interface:
name: "{{ item[0].match[0] }}"
state: "{{ item[1].state }}"
mode: "{{ item[2].match[0] }}"
keys:
interfaces:
value: "{{ interface }}"
start_block: "^Ethernet.*$"
end_block: "^$"
items:
- "^(?P<name>Ethernet\\d\\/\\d*)"
- "admin state is (?P<state>.+),"
- "Port mode is (.+)"
上面的示例将 show interface
的输出解析为哈希列表。
网络过滤器还支持使用 TextFSM 库解析 CLI 命令的输出。要使用 TextFSM 解析 CLI 输出,请使用以下过滤器
{{ output.stdout[0] | ansible.netcommon.parse_cli_textfsm('path/to/fsm') }}
使用 TextFSM 过滤器需要安装 TextFSM 库。
网络 XML 过滤器
版本 2.5 中的新增功能。
要将网络设备命令的 XML 输出转换为结构化的 JSON 输出,请使用 ansible.netcommon.parse_xml 过滤器
{{ output | ansible.netcommon.parse_xml('path/to/spec') }}
The ansible.netcommon.parse_xml 过滤器将加载规范文件并将命令输出通过它传递,格式化为 JSON。
规范文件应该是格式正确的 YAML。它定义了如何解析 XML 输出并返回 JSON 数据。
以下是一个有效的规范文件的示例,它将解析 show vlan | display xml
命令的输出。
---
vars:
vlan:
vlan_id: "{{ item.vlan_id }}"
name: "{{ item.name }}"
desc: "{{ item.desc }}"
enabled: "{{ item.state.get('inactive') != 'inactive' }}"
state: "{% if item.state.get('inactive') == 'inactive'%} inactive {% else %} active {% endif %}"
keys:
vlans:
value: "{{ vlan }}"
top: configuration/vlans/vlan
items:
vlan_id: vlan-id
name: name
desc: description
state: ".[@inactive='inactive']"
上面的规范文件将返回一个 JSON 数据结构,该结构是包含解析的 VLAN 信息的哈希列表。
可以使用 key 和 values 指令将相同命令解析为哈希。以下是如何使用相同的 show vlan | display xml
命令将输出解析为哈希值的示例。
---
vars:
vlan:
key: "{{ item.vlan_id }}"
values:
vlan_id: "{{ item.vlan_id }}"
name: "{{ item.name }}"
desc: "{{ item.desc }}"
enabled: "{{ item.state.get('inactive') != 'inactive' }}"
state: "{% if item.state.get('inactive') == 'inactive'%} inactive {% else %} active {% endif %}"
keys:
vlans:
value: "{{ vlan }}"
top: configuration/vlans/vlan
items:
vlan_id: vlan-id
name: name
desc: description
state: ".[@inactive='inactive']"
The value of top
是相对于 XML 根节点的 XPath。在下面的示例中,给出的 XML 输出,top
的值为 configuration/vlans/vlan
,它是相对于根节点 (<rpc-reply>) 的 XPath 表达式。 configuration
是 top
值中最外面的容器节点,而 vlan
是最里面的容器节点。
items
是一个键值对字典,它将用户定义的名称映射到选择元素的 XPath 表达式。Xpath 表达式是相对于包含在 top
中的 XPath 值的值。例如,规范文件中的 vlan_id
是一个用户定义的名称,其值为 vlan-id
,它是相对于 top
中的 XPath 值的值
可以使用 XPath 表达式提取 XML 标签的属性。规范文件中 state
的值是一个 XPath 表达式,用于获取输出 XML 中 vlan
标签的属性。
<rpc-reply>
<configuration>
<vlans>
<vlan inactive="inactive">
<name>vlan-1</name>
<vlan-id>200</vlan-id>
<description>This is vlan-1</description>
</vlan>
</vlans>
</configuration>
</rpc-reply>
注意
有关支持的 XPath 表达式的更多信息,请参阅 XPath 支持。
网络 VLAN 过滤器
版本 2.8 中的新功能。
使用 ansible.netcommon.vlan_parser 过滤器将 VLAN 整数的无序列表转换为根据类似 IOS 的 VLAN 列表规则排序的整数排序字符串列表。此列表具有以下属性
VLAN 按升序排列。
三个或更多连续的 VLAN 使用连字符列出。
列表的第一行可以有 first_line_len 个字符长。
后续列表行可以有 other_line_len 个字符长。
排序 VLAN 列表
{{ [3003, 3004, 3005, 100, 1688, 3002, 3999] | ansible.netcommon.vlan_parser }}
此示例呈现以下排序列表
['100,1688,3002-3005,3999']
另一个示例 Jinja 模板
{% set parsed_vlans = vlans | ansible.netcommon.vlan_parser %}
switchport trunk allowed vlan {{ parsed_vlans[0] }}
{% for i in range (1, parsed_vlans | count) %}
switchport trunk allowed vlan add {{ parsed_vlans[i] }}
{% endfor %}
这允许在 Cisco IOS 标记接口上动态生成 VLAN 列表。您可以存储接口所需的精确 VLAN 的详尽原始列表,然后将其与将实际为配置生成的已解析 IOS 输出进行比较。
对字符串和密码进行哈希处理和加密
版本 1.9 中的新增功能。
获取字符串的 sha1 哈希
{{ 'test1' | hash('sha1') }}
# => "b444ac06613fc8d63795be9ad0beaf55011936ac"
获取字符串的 md5 哈希
{{ 'test1' | hash('md5') }}
# => "5a105e8b9d40e1329780d62ea2265d8a"
获取字符串校验和
{{ 'test2' | checksum }}
# => "109f4b3c50d7b0df729d299bc6f8e9ef9066971f"
其他哈希(平台相关)
{{ 'test2' | hash('blowfish') }}
获取 sha512 密码哈希(随机盐)
{{ 'passwordsaresecret' | password_hash('sha512') }}
# => "$6$UIv3676O/ilZzWEE$ktEfFF19NQPF2zyxqxGkAceTnbEgpEKuGBtk6MlU4v2ZorWaVQUMyurgmHCh2Fr4wpmQ/Y.AlXMJkRnIS4RfH/"
获取使用特定盐的 sha256 密码哈希
{{ 'secretpassword' | password_hash('sha256', 'mysecretsalt') }}
# => "$5$mysecretsalt$ReKNyDYjkKNqRVwouShhsEqZ3VOE8eoVO4exihOfvG4"
一种幂等方法,可以为每个系统生成唯一的哈希,即使用在运行之间一致的盐
{{ 'secretpassword' | password_hash('sha512', 65534 | random(seed=inventory_hostname) | string) }}
# => "$6$43927$lQxPKz2M2X.NWO.gK.t7phLwOKQMcSq72XxDZQ0XzYV6DlL1OD72h417aj16OnHTGxNzhftXJQBcjbunLEepM0"
可用的哈希类型取决于运行 Ansible 的控制系统,ansible.builtin.hash 依赖于 hashlib,ansible.builtin.password_hash 依赖于 passlib。如果未安装 passlib
,则将 crypt 用作后备。
版本 2.7 中的新功能。
某些哈希类型允许提供 rounds 参数
{{ 'secretpassword' | password_hash('sha256', 'mysecretsalt', rounds=10000) }}
# => "$5$rounds=10000$mysecretsalt$Tkm80llAxD4YHll6AgNIztKn0vzAACsuuEfYeGP7tm7"
过滤器 password_hash 生成的结果取决于您是否安装了 passlib。
为了确保幂等性,请指定 rounds 不为 crypt 或 passlib 的默认值,对于 crypt 为 5000,对于 passlib 为可变值(对于 sha256 为 535000,对于 sha512 为 656000)
{{ 'secretpassword' | password_hash('sha256', 'mysecretsalt', rounds=5001) }}
# => "$5$rounds=5001$mysecretsalt$wXcTWWXbfcR8er5IVf7NuquLvnUA6s8/qdtOhAZ.xN."
哈希类型‘blowfish’ (BCrypt) 提供了指定 BCrypt 算法版本的功能。
{{ 'secretpassword' | password_hash('blowfish', '1234567890123456789012', ident='2b') }}
# => "$2b$12$123456789012345678901uuJ4qFdej6xnWjOQT.FStqfdoY8dYUPC"
注意
该参数仅适用于 blowfish (BCrypt)。其他哈希类型将简单地忽略此参数。此参数的有效值为:[‘2’, ‘2a’, ‘2y’, ‘2b’]
版本 2.12 中的新增功能。
您也可以使用 Ansible ansible.builtin.vault 过滤器来加密数据
# simply encrypt my key in a vault
vars:
myvaultedkey: "{{ keyrawdata|vault(passphrase) }}"
- name: save templated vaulted data
template: src=dump_template_data.j2 dest=/some/key/vault.txt
vars:
mysalt: '{{ 2**256|random(seed=inventory_hostname) }}'
template_data: '{{ secretdata|vault(vaultsecret, salt=mysalt) }}'
然后使用 unvault 过滤器对其进行解密
# simply decrypt my key from a vault
vars:
mykey: "{{ myvaultedkey|unvault(passphrase) }}"
- name: save templated unvaulted data
template: src=dump_template_data.j2 dest=/some/key/clear.txt
vars:
template_data: '{{ secretdata|unvault(vaultsecret) }}'
操作文本
多个过滤器可以处理文本,包括 URL、文件名和路径名。
向文件添加注释
The ansible.builtin.comment filter 允许您从模板中的文本创建文件中的注释,并提供多种注释样式。默认情况下,Ansible 使用 #
开始注释行并在注释文本的上方和下方添加一个空注释行。例如,以下内容
{{ "Plain style (default)" | comment }}
生成以下输出
#
# Plain style (default)
#
Ansible 提供 C (//...
)、C 块 (/*...*/
)、Erlang (%...
) 和 XML (<!--...-->
) 的注释样式
{{ "C style" | comment('c') }}
{{ "C block style" | comment('cblock') }}
{{ "Erlang style" | comment('erlang') }}
{{ "XML style" | comment('xml') }}
您可以定义自定义注释字符。此过滤器
{{ "My Special Case" | comment(decoration="! ") }}
生成
!
! My Special Case
!
您可以完全自定义注释样式
{{ "Custom style" | comment('plain', prefix='#######\n#', postfix='#\n#######\n ###\n #') }}
这将创建以下输出
#######
#
# Custom style
#
#######
###
#
过滤器也可以应用于任何 Ansible 变量。例如,为了使 ansible_managed
变量的输出更易读,我们可以将 ansible.cfg
文件中的定义更改为
[defaults]
ansible_managed = This file is managed by Ansible.%n
template: {file}
date: %Y-%m-%d %H:%M:%S
user: {uid}
host: {host}
然后使用带 comment 过滤器的变量
{{ ansible_managed | comment }}
生成以下输出
#
# This file is managed by Ansible.
#
# template: /home/ansible/env/dev/ansible_managed/roles/role1/templates/test.j2
# date: 2015-09-10 11:02:58
# user: ansible
# host: myhost
#
对 URL 进行编码变量
The urlencode
filter 使用 UTF-8 对数据进行引号以在 URL 路径或查询中使用
{{ 'Trollhättan' | urlencode }}
# => 'Trollh%C3%A4ttan'
分割 URL
版本 2.4 中的新增功能。
The ansible.builtin.urlsplit filter 从 URL 中提取片段、主机名、netloc、密码、路径、端口、查询、方案和用户名。没有参数时,返回所有字段的字典
{{ "http://user:[email protected]:9000/dir/index.html?query=term#fragment" | urlsplit('hostname') }}
# => 'www.acme.com'
{{ "http://user:[email protected]:9000/dir/index.html?query=term#fragment" | urlsplit('netloc') }}
# => 'user:[email protected]:9000'
{{ "http://user:[email protected]:9000/dir/index.html?query=term#fragment" | urlsplit('username') }}
# => 'user'
{{ "http://user:[email protected]:9000/dir/index.html?query=term#fragment" | urlsplit('password') }}
# => 'password'
{{ "http://user:[email protected]:9000/dir/index.html?query=term#fragment" | urlsplit('path') }}
# => '/dir/index.html'
{{ "http://user:[email protected]:9000/dir/index.html?query=term#fragment" | urlsplit('port') }}
# => '9000'
{{ "http://user:[email protected]:9000/dir/index.html?query=term#fragment" | urlsplit('scheme') }}
# => 'http'
{{ "http://user:[email protected]:9000/dir/index.html?query=term#fragment" | urlsplit('query') }}
# => 'query=term'
{{ "http://user:[email protected]:9000/dir/index.html?query=term#fragment" | urlsplit('fragment') }}
# => 'fragment'
{{ "http://user:[email protected]:9000/dir/index.html?query=term#fragment" | urlsplit }}
# =>
# {
# "fragment": "fragment",
# "hostname": "www.acme.com",
# "netloc": "user:[email protected]:9000",
# "password": "password",
# "path": "/dir/index.html",
# "port": 9000,
# "query": "query=term",
# "scheme": "http",
# "username": "user"
# }
使用正则表达式搜索字符串
要使用正则表达式在字符串中搜索或提取字符串的部分,请使用 ansible.builtin.regex_search filter
# Extracts the database name from a string
{{ 'server1/database42' | regex_search('database[0-9]+') }}
# => 'database42'
# Example for a case insensitive search in multiline mode
{{ 'foo\nBAR' | regex_search('^bar', multiline=True, ignorecase=True) }}
# => 'BAR'
# Example for a case insensitive search in multiline mode using inline regex flags
{{ 'foo\nBAR' | regex_search('(?im)^bar') }}
# => 'BAR'
# Extracts server and database id from a string
{{ 'server1/database42' | regex_search('server([0-9]+)/database([0-9]+)', '\\1', '\\2') }}
# => ['1', '42']
# Extracts dividend and divisor from a division
{{ '21/42' | regex_search('(?P<dividend>[0-9]+)/(?P<divisor>[0-9]+)', '\\g<dividend>', '\\g<divisor>') }}
# => ['21', '42']
The ansible.builtin.regex_search filter 如果找不到匹配项则返回一个空字符串
{{ 'ansible' | regex_search('foobar') }}
# => ''
注意
The ansible.builtin.regex_search filter 在 Jinja 表达式中使用时(例如,与运算符、其他过滤器等结合使用)返回 None
。请参阅下面的两个示例。
{{ 'ansible' | regex_search('foobar') == '' }}
# => False
{{ 'ansible' | regex_search('foobar') is none }}
# => True
这是由于历史行为和 Ansible 中对某些 Jinja 内部结构的自定义重新实现。如果希望 ansible.builtin.regex_search filter 始终返回 None
(如果找不到匹配项),则启用 jinja2_native
设置。有关详细信息,请参阅 为什么 regex_search 过滤器返回 None 而不是空字符串?。
要提取字符串中所有正则表达式匹配项的出现次数,请使用 ansible.builtin.regex_findall filter
# Returns a list of all IPv4 addresses in the string
{{ 'Some DNS servers are 8.8.8.8 and 8.8.4.4' | regex_findall('\\b(?:[0-9]{1,3}\\.){3}[0-9]{1,3}\\b') }}
# => ['8.8.8.8', '8.8.4.4']
# Returns all lines that end with "ar"
{{ 'CAR\ntar\nfoo\nbar\n' | regex_findall('^.ar$', multiline=True, ignorecase=True) }}
# => ['CAR', 'tar', 'bar']
# Returns all lines that end with "ar" using inline regex flags for multiline and ignorecase
{{ 'CAR\ntar\nfoo\nbar\n' | regex_findall('(?im)^.ar$') }}
# => ['CAR', 'tar', 'bar']
要使用正则表达式替换字符串中的文本,请使用 ansible.builtin.regex_replace filter
# Convert "ansible" to "able"
{{ 'ansible' | regex_replace('^a.*i(.*)$', 'a\\1') }}
# => 'able'
# Convert "foobar" to "bar"
{{ 'foobar' | regex_replace('^f.*o(.*)$', '\\1') }}
# => 'bar'
# Convert "localhost:80" to "localhost, 80" using named groups
{{ 'localhost:80' | regex_replace('^(?P<host>.+):(?P<port>\\d+)$', '\\g<host>, \\g<port>') }}
# => 'localhost, 80'
# Convert "localhost:80" to "localhost"
{{ 'localhost:80' | regex_replace(':80') }}
# => 'localhost'
# Comment all lines that end with "ar"
{{ 'CAR\ntar\nfoo\nbar\n' | regex_replace('^(.ar)$', '#\\1', multiline=True, ignorecase=True) }}
# => '#CAR\n#tar\nfoo\n#bar\n'
# Comment all lines that end with "ar" using inline regex flags for multiline and ignorecase
{{ 'CAR\ntar\nfoo\nbar\n' | regex_replace('(?im)^(.ar)$', '#\\1') }}
# => '#CAR\n#tar\nfoo\n#bar\n'
注意
如果要匹配整个字符串,并且您使用的是 *
,请确保始终用开始/结束锚点将您的正则表达式包围起来。例如,^(.*)$
将始终只匹配一个结果,而 (.*)
在某些 Python 版本上将匹配整个字符串和末尾的空字符串,这意味着它将进行两次替换
# add "https://" prefix to each item in a list
GOOD:
{{ hosts | map('regex_replace', '^(.*)$', 'https://\\1') | list }}
{{ hosts | map('regex_replace', '(.+)', 'https://\\1') | list }}
{{ hosts | map('regex_replace', '^', 'https://') | list }}
BAD:
{{ hosts | map('regex_replace', '(.*)', 'https://\\1') | list }}
# append ':80' to each item in a list
GOOD:
{{ hosts | map('regex_replace', '^(.*)$', '\\1:80') | list }}
{{ hosts | map('regex_replace', '(.+)', '\\1:80') | list }}
{{ hosts | map('regex_replace', '$', ':80') | list }}
BAD:
{{ hosts | map('regex_replace', '(.*)', '\\1:80') | list }}
注意
在 ansible 2.0 之前,如果 ansible.builtin.regex_replace 过滤器与 YAML 参数(而不是更简单的“键=值”参数)中的变量一起使用,那么您需要用 4 个反斜杠 (\\\\
) 来转义反向引用(例如,\\1
),而不是 2 个 (\\
)。
新增于 2.0 版本。
要转义标准 Python 正则表达式中的特殊字符,请使用 ansible.builtin.regex_escape filter(使用默认的 re_type='python'
选项)
# convert '^f.*o(.*)$' to '\^f\.\*o\(\.\*\)\$'
{{ '^f.*o(.*)$' | regex_escape() }}
版本 2.8 中的新功能。
要转义 POSIX 基本正则表达式中的特殊字符,请使用 ansible.builtin.regex_escape filter,并使用 re_type='posix_basic'
选项
# convert '^f.*o(.*)$' to '\^f\.\*o(\.\*)\$'
{{ '^f.*o(.*)$' | regex_escape('posix_basic') }}
管理文件名和路径名
要获取文件路径的最后一个名称,例如“/etc/asdf/foo.txt”中的“foo.txt”
{{ path | basename }}
要获取 Windows 样式文件路径的最后一个名称(版本 2.0 中新增)
{{ path | win_basename }}
要将 Windows 驱动器号与文件路径的其余部分分开(版本 2.0 中新增)
{{ path | win_splitdrive }}
要仅获取 Windows 驱动器号
{{ path | win_splitdrive | first }}
要获取路径的其余部分,不包括驱动器号
{{ path | win_splitdrive | last }}
要从路径获取目录
{{ path | dirname }}
要从 Windows 路径获取目录(版本 2.0 中新增)
{{ path | win_dirname }}
要展开包含波浪号 (~) 字符的路径(版本 1.5 中新增)
{{ path | expanduser }}
要展开包含环境变量的路径
{{ path | expandvars }}
注意
expandvars 展开本地变量;对远程路径使用它可能会导致错误。
版本 2.6 中的新功能。
要获取链接的真实路径(版本 1.8 中新增)
{{ path | realpath }}
要获取链接的相对路径,从起点开始(版本 1.7 中新增)
{{ path | relpath('/etc') }}
要获取路径或文件名的根目录和扩展名(版本 2.0 中新增)
# with path == 'nginx.conf' the return would be ('nginx', '.conf')
{{ path | splitext }}
The ansible.builtin.splitext filter 始终返回一对字符串。可以使用 first
和 last
过滤器访问各个组件
# with path == 'nginx.conf' the return would be 'nginx'
{{ path | splitext | first }}
# with path == 'nginx.conf' the return would be '.conf'
{{ path | splitext | last }}
要连接一个或多个路径组件
{{ ('/etc', path, 'subdir', file) | path_join }}
版本 2.10 中新增。
操作字符串
要为 shell 使用添加引号
- name: Run a shell command
ansible.builtin.shell: echo {{ string_value | quote }}
要将列表连接成字符串
{{ list | join(" ") }}
要将字符串拆分成列表
{{ csv_string | split(",") }}
版本 2.11 中的新增功能。
要处理 Base64 编码字符串
{{ encoded | b64decode }}
{{ decoded | string | b64encode }}
(文档:ansible.builtin.b64encode)
从版本 2.6 开始,您可以定义要使用的编码类型,默认值为 utf-8
{{ encoded | b64decode(encoding='utf-16-le') }}
{{ decoded | string | b64encode(encoding='utf-16-le') }}
(文档:ansible.builtin.b64decode)
注意
The string
filter 仅在 Python 2 中需要,并确保要编码的文本是 unicode 字符串。在 b64encode 之前没有该过滤器,将编码错误的值。
注意
b64decode 的返回值是字符串。如果您使用 b64decode 解密二进制 blob,然后尝试使用它(例如,使用 copy 将其写入文件),您很可能会发现您的二进制文件已损坏。如果您需要获取 base64 编码的二进制文件并将其写入磁盘,最好使用系统 base64
命令与 shell 模块 一起使用,使用 stdin
参数将编码数据传入。例如:shell: cmd="base64 --decode > myfile.bin" stdin="{{ encoded }}"
版本 2.6 中的新功能。
管理 UUID
要创建命名空间 UUIDv5
{{ string | to_uuid(namespace='11111111-2222-3333-4444-555555555555') }}
版本 2.10 中新增。
要使用默认的 Ansible 命名空间“361E6D51-FAEC-444A-9079-341386DA8E2E”创建命名空间 UUIDv5
{{ string | to_uuid }}
版本 1.9 中的新增功能。
要使用复杂变量列表中每个项目的某个属性,请使用 Jinja2 map filter
# get a comma-separated list of the mount points (for example, "/,/mnt/stuff") on a host
{{ ansible_mounts | map(attribute='mount') | join(',') }}
处理日期和时间
要从字符串获取日期对象,请使用 to_datetime 过滤器
# Get the total amount of seconds between two dates. Default date format is %Y-%m-%d %H:%M:%S but you can pass your own format
{{ (("2016-08-14 20:00:12" | to_datetime) - ("2015-12-25" | to_datetime('%Y-%m-%d'))).total_seconds() }}
# Get remaining seconds after delta has been calculated. NOTE: This does NOT convert years, days, hours, and so on to seconds. For that, use total_seconds()
{{ (("2016-08-14 20:00:12" | to_datetime) - ("2016-08-14 18:00:00" | to_datetime)).seconds }}
# This expression evaluates to "12" and not "132". Delta is 2 hours, 12 seconds
# get amount of days between two dates. This returns only the number of days and discards remaining hours, minutes, and seconds
{{ (("2016-08-14 20:00:12" | to_datetime) - ("2015-12-25" | to_datetime('%Y-%m-%d'))).days }}
注意
有关使用 Python 日期格式字符串的完整格式代码列表,请参阅 python 日期时间文档.
版本 2.4 中的新增功能。
要使用字符串格式化日期(如使用 shell date 命令),请使用“strftime”过滤器
# Display year-month-day
{{ '%Y-%m-%d' | strftime }}
# => "2021-03-19"
# Display hour:min:sec
{{ '%H:%M:%S' | strftime }}
# => "21:51:04"
# Use ansible_date_time.epoch fact
{{ '%Y-%m-%d %H:%M:%S' | strftime(ansible_date_time.epoch) }}
# => "2021-03-19 21:54:09"
# Use arbitrary epoch value
{{ '%Y-%m-%d' | strftime(0) }} # => 1970-01-01
{{ '%Y-%m-%d' | strftime(1441357287) }} # => 2015-09-04
版本 2.13 中的新功能。
strftime 接受一个可选的 utc 参数,默认值为 False,这意味着时间位于本地时区
{{ '%H:%M:%S' | strftime }} # time now in local timezone
{{ '%H:%M:%S' | strftime(utc=True) }} # time now in UTC
注意
要获取所有字符串可能性,请查看 https://docs.pythonlang.cn/3/library/time.html#time.strftime
获取 Kubernetes 资源名称
注意
这些过滤器已迁移到 kubernetes.core 集合。按照安装说明安装该集合。
使用“k8s_config_resource_name”过滤器获取 Kubernetes ConfigMap 或 Secret 的名称,包括其哈希值
{{ configmap_resource_definition | kubernetes.core.k8s_config_resource_name }}
然后可以使用它来引用 Pod 规范中的哈希值
my_secret:
kind: Secret
metadata:
name: my_secret_name
deployment_resource:
kind: Deployment
spec:
template:
spec:
containers:
- envFrom:
- secretRef:
name: {{ my_secret | kubernetes.core.k8s_config_resource_name }}
版本 2.8 中的新功能。
另请参阅
- Ansible 剧本
剧本简介
- 条件
剧本中的条件语句
- 使用变量
关于变量的一切
- 循环
剧本中的循环
- 角色
按角色组织剧本
- 一般提示
剧本的技巧和窍门
- 交流
有问题吗?需要帮助吗?想分享你的想法吗?访问 Ansible 交流指南
- Python 3 正则表达式操作
如何使用内联正则表达式标志