Ansible 中的 JMESPath 查询
JMESPath Query in Ansible
--- 编辑 ---
部分解决方案:搞乱了 JMESPath 语法,并且能够使用以下方法成功地匹配第一个测试用例(没有可选变量):
jmesquery: "{{ datacenter }}{{ subcategory }}.{{ refine_hosts }}.[*][].[*][][]"
我正在编写一个 Ansible Playbook,它从网络服务器获取主机列表,解析 JSON 列表,并在用户将 playbook 作为 Jenkin 的作业部署时找到与用户输入匹配的主机名API.
我遇到的问题是无法成功查询JSON主机列表。目前,我只尝试 运行 以下测试用例:
datacenter: a
subcategory: bc
refine_hosts: QA
但是,此剧本的最终版本应该能够接受 datacenter
、subcategory
和 refine_hosts
的值,以及可选的输入值 host_type
.包含可选输入值的示例测试用例如下:
datacenter: a
subcategory: bc
refine_hosts: QA
host_type: WEBSITE
在我的剧本中,我在以下任务中使用 JMESPath:
- name: Build HOSTS list
set_fact:
hosts_list: "{{ jsondata | json_query(jmesquery) }}"
vars:
jmesquery: '%%datacenter%%-%%subcategory%%.%%refine_hosts%%.[*][*][][]'
JSON 主机列表的结构如下(我无法编辑主机列表的结构,但它将始终遵循以下结构):
{
"a-bc":{
"all":{
"webServer":[
],
"archive":[
"someHostAlias-123.privateDomain.com"
],
"central":[
"someHostAlias-456.privateDomain.com"
]
},
"QA":{
"xyz":{
"INBOUND_HTTP":[
"someHostAlias-789.privateDomain.com"
],
"WEBSITE":[
"someHostAlias-1011.privateDomain.com"
]
}
}
}
}
我一直在使用以下网站来解决这个问题:
- JMESPath Tutorial
- Ansible JMESPath Documentation
- JSONPath Expression Tester
- Whosebug: How to Use Variable in JMESPath Expression
- Gitter: JMESPath/chat
如果查询看起来很明显,我深表歉意,这是我第一次尝试使用 Ansible Playbook。非常感谢所有 help/feedback。
您的查询问题之一是您混淆了 [*]
— list projection — that selects all the elements of a list with .*
— an object projection — 选择字典的所有属性。
因此,JMESPath 中的一种解决方案是:
jmesquery: >-
"{{ datacenter }}-{{ subcategory }}".{{ refine_hosts }}.*.
{{ host_type if host_type | default('') != '' else '*' }}[] | []
鉴于剧本:
- hosts: localhost
gather_facts: no
tasks:
- debug:
msg: "{{ jsondata | json_query(jmesquery) }}"
loop: "{{ fake_user_input }}"
loop_control:
label: "{{ jmesquery }}"
vars:
jmesquery: >-
"{{ datacenter }}-{{ subcategory }}".{{ refine_hosts }}.*.
{{ host_type if host_type | default('') != '' else '*' }}[] | []
datacenter: "{{ item.datacenter }}"
subcategory: "{{ item.subcategory }}"
refine_hosts: "{{ item.refine_hosts }}"
host_type: "{{ item.host_type | default('') }}"
fake_user_input:
- datacenter: a
subcategory: bc
refine_hosts: QA
host_type: WEBSITE
- datacenter: a
subcategory: bc
refine_hosts: QA
jsondata:
a-bc:
all:
webServer: []
archive:
- someHostAlias-123.privateDomain.com
central:
- someHostAlias-456.privateDomain.com
QA:
xyz:
INBOUND_HTTP:
- someHostAlias-789.privateDomain.com
WEBSITE:
- someHostAlias-1011.privateDomain.com
这产生:
ok: [localhost] => (item="a-bc".QA.*. WEBSITE[] | []) =>
msg:
- someHostAlias-1011.privateDomain.com
ok: [localhost] => (item="a-bc".QA.*. *[] | []) =>
msg:
- someHostAlias-789.privateDomain.com
- someHostAlias-1011.privateDomain.com
--- 编辑 ---
部分解决方案:搞乱了 JMESPath 语法,并且能够使用以下方法成功地匹配第一个测试用例(没有可选变量):
jmesquery: "{{ datacenter }}{{ subcategory }}.{{ refine_hosts }}.[*][].[*][][]"
我正在编写一个 Ansible Playbook,它从网络服务器获取主机列表,解析 JSON 列表,并在用户将 playbook 作为 Jenkin 的作业部署时找到与用户输入匹配的主机名API.
我遇到的问题是无法成功查询JSON主机列表。目前,我只尝试 运行 以下测试用例:
datacenter: a
subcategory: bc
refine_hosts: QA
但是,此剧本的最终版本应该能够接受 datacenter
、subcategory
和 refine_hosts
的值,以及可选的输入值 host_type
.包含可选输入值的示例测试用例如下:
datacenter: a
subcategory: bc
refine_hosts: QA
host_type: WEBSITE
在我的剧本中,我在以下任务中使用 JMESPath:
- name: Build HOSTS list
set_fact:
hosts_list: "{{ jsondata | json_query(jmesquery) }}"
vars:
jmesquery: '%%datacenter%%-%%subcategory%%.%%refine_hosts%%.[*][*][][]'
JSON 主机列表的结构如下(我无法编辑主机列表的结构,但它将始终遵循以下结构):
{
"a-bc":{
"all":{
"webServer":[
],
"archive":[
"someHostAlias-123.privateDomain.com"
],
"central":[
"someHostAlias-456.privateDomain.com"
]
},
"QA":{
"xyz":{
"INBOUND_HTTP":[
"someHostAlias-789.privateDomain.com"
],
"WEBSITE":[
"someHostAlias-1011.privateDomain.com"
]
}
}
}
}
我一直在使用以下网站来解决这个问题:
- JMESPath Tutorial
- Ansible JMESPath Documentation
- JSONPath Expression Tester
- Whosebug: How to Use Variable in JMESPath Expression
- Gitter: JMESPath/chat
如果查询看起来很明显,我深表歉意,这是我第一次尝试使用 Ansible Playbook。非常感谢所有 help/feedback。
您的查询问题之一是您混淆了 [*]
— list projection — that selects all the elements of a list with .*
— an object projection — 选择字典的所有属性。
因此,JMESPath 中的一种解决方案是:
jmesquery: >-
"{{ datacenter }}-{{ subcategory }}".{{ refine_hosts }}.*.
{{ host_type if host_type | default('') != '' else '*' }}[] | []
鉴于剧本:
- hosts: localhost
gather_facts: no
tasks:
- debug:
msg: "{{ jsondata | json_query(jmesquery) }}"
loop: "{{ fake_user_input }}"
loop_control:
label: "{{ jmesquery }}"
vars:
jmesquery: >-
"{{ datacenter }}-{{ subcategory }}".{{ refine_hosts }}.*.
{{ host_type if host_type | default('') != '' else '*' }}[] | []
datacenter: "{{ item.datacenter }}"
subcategory: "{{ item.subcategory }}"
refine_hosts: "{{ item.refine_hosts }}"
host_type: "{{ item.host_type | default('') }}"
fake_user_input:
- datacenter: a
subcategory: bc
refine_hosts: QA
host_type: WEBSITE
- datacenter: a
subcategory: bc
refine_hosts: QA
jsondata:
a-bc:
all:
webServer: []
archive:
- someHostAlias-123.privateDomain.com
central:
- someHostAlias-456.privateDomain.com
QA:
xyz:
INBOUND_HTTP:
- someHostAlias-789.privateDomain.com
WEBSITE:
- someHostAlias-1011.privateDomain.com
这产生:
ok: [localhost] => (item="a-bc".QA.*. WEBSITE[] | []) =>
msg:
- someHostAlias-1011.privateDomain.com
ok: [localhost] => (item="a-bc".QA.*. *[] | []) =>
msg:
- someHostAlias-789.privateDomain.com
- someHostAlias-1011.privateDomain.com