问题描述
是否可以编写JMESPath表达式以返回设置了特定子属性值的对象名称列表?在下面的示例中,我想获取将 fileexists.stat.exists 设置为true的所有主机名的列表.
Is it possible to write JMESPath expression to return a list of object names where a specific subproperty value is set? In the example below I'd like to get a list of all hostsnames where fileexists.stat.exists is set to true.
我的目标是使用Ansible hostvars结构获取存在特定文件的所有主机的列表.
My goal is to use Ansible hostvars structure to get a list of all hosts where a specific file is present.
{
"hostvars": {
"oclab1n01.example.org": {
"fileexists": {
"changed": false,
"failed": false,
"stat": {
"exists": false
}
}
},
"oclab1n02.example.org": {
"fileexists": {
"changed": false,
"failed": false,
"stat": {
"exists": true
}
}
},
"oclab1n03.example.org": {
"fileexists": {
"changed": false,
"failed": false,
"stat": {
"exists": true
}
}
}
} }
在此示例中,我想获得以下输出
In this example I'd like to get the following output
["oclab1n02.example.org", "oclab1n03.example.org"]
推荐答案
简短答案(TL; DR)
是的,这是可能的,但是它非常麻烦,因为对于这种通用查询,源数据集被标准化程度很差.
- jmespath查询语言
- 查询深度嵌套对象的对象属性
- 如何使用过滤器表达式构建jmespath查询
- 目标是过滤具有任意嵌套的对象属性的对象
- 这可以通过jmespath完成,但操作麻烦
- 一个有问题的问题:针对这种jmespath查询,源数据集的标准化程度很差
- 为了构造jmespath查询,我们必须假设在创建查询之前预先知道所有主对象键
- 在此特定示例中,我们必须知道在构造jmespath查询之前只有三个且只有三个主机名 ...如果我们希望灵活地指定,那么这不是一个有利的情况任意数量的主机名
- This can be done with jmespath, but the operation will be cumbersome
- One problematic issue: the source dataset is poorly normalized for this kind of jmespath query
- In order to construct the jmespath query, we have to assume all the primary object keys are known in advance of creating the query
- In this specific example, we have to know that there are three and only three hostnames in advance of constructing the jmespath query ... this is not a favorable circumstance if we want the flexibility to specify any arbitrary number of hostnames
以下(太大)的jmespath查询...
The following (way-too-huge) jmespath query ...
[
{
"hostname": `oclab1n01.example.org`
,"fileexists_stat_exists": @.hostvars."oclab1n01.example.org".fileexists.stat.exists
}
,{
"hostname": `oclab1n02.example.org`
,"fileexists_stat_exists": @.hostvars."oclab1n02.example.org".fileexists.stat.exists
}
,{
"hostname": `oclab1n03.example.org`
,"fileexists_stat_exists": @.hostvars."oclab1n02.example.org".fileexists.stat.exists
}
]|[? @.fileexists_stat_exists == `true`]|[*].hostname
返回以下期望结果
[
"oclab1n02.example.org",
"oclab1n03.example.org"
]
陷阱
- 这种用例的一个主要陷阱是对这种查询的源数据集进行了标准化较差
- 更扁平的数据结构将更易于查询
- 因此,如果可能的话,一种更好的方法是展平源数据集,然后对它运行jmespath查询
- One major pitfall with this use-case is the source dataset is poorly normalized for this kind of query
- A more flattened data structure would be easier to query
- Consequently, if possible, a better approach would be to flatten the source dataset before running jmespath queries against it
Pitfalls
如果原始数据被组织为一个对象列表,而不是对象中的一组嵌套对象,那么搜索,排序和过滤列表将变得更加容易,而无需事先了解 涉及多少个主机名条目.
If the original data were organized as a list of objects, instead of a set of nested objects within objects, it would be easier to search, sort and filter the list without having to know in advance how many hostname entries are involved.
{"hostvars": [
{"hostname":"oclab1n01.example.org"
,"fileexists": true
,"filechanged": false
,"filefailed": false
,"filestat_exists": false
,"we_can_even_still_deeply_nest":{"however":
{"im_only_doing":"it here","to":"prove a point"}
}
}
,{"hostname":"oclab1n02.example.org"
,"fileexists": true
,"filechanged": false
,"filefailed": false
,"filestat_exists": true
}
,{"hostname":"oclab1n03.example.org"
,"fileexists": true
,"filechanged": false
,"filefailed": false
,"filestat_exists": true
}
]
}
上面的重新规范化数据集现在可以轻松查询
The above re-normalized dataset can now be easily queried
hostvars|[? @.filestat_exists == `true`]|[*].hostname
这篇关于JMESpath表达式按属性过滤对象并返回设置了该属性的对象名称列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!