我目前正在尝试循环 k8s_facts 的子集。我的事实看起来像:
{
"resources": [
{
"metadata": {
"annotations": {
"com.foo.bar/name": "foo",
"com.foo.bar/foo-name": "baz"
},
"creationTimestamp": "2018-12-20T02:29:50Z",
"name": "foo-bar"
}
},
...
我想过滤
com.foo.bar/foo-name
键的特定值。因为按键有 .
、-
和 /
,所以与 Jinja2 selectattr
功能配合不好。我尝试做类似的事情,但徒劳:
- debug:
msg: "{{ item }}"
loop: "{{ my_fact.resources | selectattr('metadata.annotations[\\'com.foo.bar/foo-name\\']', 'defined') | selectattr('metadata.annotations[\\'com.foo.bar/foo-name\\']', 'match', 'baz') | list }}"
loop_control:
label: "{{ item.metadata.name }}"
执行前一个时,出现此错误:
fatal: [<redacted>]: FAILED! => {"msg": "template error while templating string: expected token ',', got 'com'. String: {{ my_fact.resources | selectattr('metadata.annotations[\\\\'com.foo.bar/foo-name\\\\']', 'defined') | selectattr('metadata.annotations[\\\\'com.foo.bar/foo-name\\\\']', 'match', 'baz') | list }}"}
我的问题是,如何转义 Jinja2 中包含点的复杂字符串?
当我在 ansible 中进入逃离地狱时,我倾向于利用 yaml 折叠和文字块语法。优点是它可以让你编写 jinja 块而不必用引号将它们括起来,这消除了一个引用级别,因此也消除了一个转义级别。
json_query
过滤器直接切入主题,而不是通过管道传递一长串过滤器。
这是一个演示手册:
---
- name: Test var names with dots
hosts: localhost
gather_facts: false
vars:
my_fact: {
"resources": [
{
"metadata": {
"annotations": {
"com.foo.bar/name": "foo",
"com.foo.bar/foo-name": "baz"
},
"creationTimestamp": "2018-12-20T02:29:50Z",
"name": "foo-bar"
}
},
{
"metadata": {
"annotations": {
"com.foo.bar/name": "toto",
"com.foo.bar/foo-name": "titi"
},
"creationTimestamp": "2018-12-21T02:30:50Z",
"name": "foo-bla"
}
},
{
"metadata": {
"annotations": {
"com.foo.bar/name": "johnsmith",
"com.foo.bar/foo-name": "baz"
},
"creationTimestamp": "2018-12-22T02:31:50Z",
"name": "foo-john"
}
}
]
}
tasks:
- name: Show results where metadata.annotations."com.foo.bar/foo-name"=='baz'
vars:
query: >-
[?(metadata.annotations."com.foo.bar/foo-name")=='baz']
debug:
msg: "{{ item }}"
loop: "{{ my_fact.resources | json_query(query) }}"
loop_control:
label: "{{ item.metadata.name }}"
结果
PLAY [Test var names with dots] *******************************************************************************************************************************************************************************************
TASK [Show results where metadata.annotations."com.foo.bar/foo-name"=='baz'] **********************************************************************************************************************************************
ok: [localhost] => (item=foo-bar) => {
"msg": {
"metadata": {
"annotations": {
"com.foo.bar/foo-name": "baz",
"com.foo.bar/name": "foo"
},
"creationTimestamp": "2018-12-20T02:29:50Z",
"name": "foo-bar"
}
}
}
ok: [localhost] => (item=foo-john) => {
"msg": {
"metadata": {
"annotations": {
"com.foo.bar/foo-name": "baz",
"com.foo.bar/name": "johnsmith"
},
"creationTimestamp": "2018-12-22T02:31:50Z",
"name": "foo-john"
}
}
}
PLAY RECAP ****************************************************************************************************************************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
问:“我想过滤 com.foo.bar/foo-name 键的特定值”
A:下面的json_query可以完成这项工作
q1: '[?metadata.annotations."com.foo.bar/foo-name"==`baz`]'
r1: "{{ resources|json_query(q1) }}"
给予
r1:
- metadata:
annotations:
com.foo.bar/foo-name: baz
com.foo.bar/name: foo
creationTimestamp: '2018-12-20T02:29:50Z'
name: foo-bar
用于测试的完整剧本示例
- hosts: all
vars:
resources:
- metadata:
annotations:
com.foo.bar/foo-name: baz
com.foo.bar/name: foo
creationTimestamp: '2018-12-20T02:29:50Z'
name: foo-bar
q1: '[?metadata.annotations."com.foo.bar/foo-name"==`baz`]'
r1: "{{ resources|json_query(q1) }}"
tasks:
- debug:
var: r1