可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have variable named "network" registered in Ansible:
{ "addresses": { "private_ext": [ { "type": "fixed", "addr": "172.16.2.100" } ], "private_man": [ { "type": "fixed", "addr": "172.16.1.100" }, { "type": "floating", "addr": "10.90.80.10" } ] } }
Is it possible to get the IP address ("addr") with type="floating" doing something like this?
- debug: var={{ network.addresses.private_man | filter type="fixed" | get "addr" }}
I know the syntax is wrong but you get the idea.
回答1:
I've submitted a pull request (available in Ansible 2.2+) that will make this kinds of situations easier by adding jmespath query support on Ansible. In your case it would work like:
- debug: msg="{{ addresses | json_query(\"private_man[?type=='fixed'].addr\") }}"
would return:
ok: [localhost] => { "msg": [ "172.16.1.100" ] }
回答2:
To filter a list of dicts you can use the selectattr filter together with the equalto test:
network.addresses.private_man | selectattr("type", "equalto", "fixed")
The above requires Jinja2 v2.8 or later (regardless of Ansible version).
Ansible also has the tests match and search, which take regular expressions:
match will require a complete match in the string, while search will require a match inside of the string.
network.addresses.private_man | selectattr("type", "match", "^fixed$")
To reduce the list of dicts to a list of strings, so you only get a list of the addr fields, you can use the map filter:
... | map(attribute='addr') | list
Or if you want a comma separated string:
... | map(attribute='addr') | join(',')
Combined, it would look like this.
- debug: msg={{ network.addresses.private_man | selectattr("type", "equalto", "fixed") | map(attribute='addr') | join(',') }}
回答3:
Not necessarily better, but since it's nice to have options here's how to do it using Jinja statements:
- debug: msg: "{% for address in network.addresses.private_man %}\ {% if address.type == 'fixed' %}\ {{ address.addr }}\ {% endif %}\ {% endfor %}"
Or if you prefer to put it all on one line:
- debug: msg: "{% for address in network.addresses.private_man if address.type == 'fixed' %}{{ address.addr }}{% endfor %}"
Which returns:
ok: [localhost] => { "msg": "172.16.1.100" }