Ansible:按属性过滤列表

Gui*_*ido 66 jinja2 ansible

我在Ansible中注册了名为"network"的变量:

{
    "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"
            }
        ]
    }
}
Run Code Online (Sandbox Code Playgroud)

是否有可能获得类型="浮动"的IP地址("addr")做这样的事情?

- debug: var={{ network.addresses.private_man | filter type="fixed" | get "addr" }}
Run Code Online (Sandbox Code Playgroud)

我知道语法错了,但你明白了.

udo*_*dan 100

要过滤dicts列表,可以使用selectattr过滤器equalto test:

network.addresses.private_man | selectattr("type", "equalto", "fixed")
Run Code Online (Sandbox Code Playgroud)

以上要求Jinja2 v2.8或更高版本(无论Ansible版本).


Ansible也有测试matchsearch,内搭的正则表达式:

match将需要字符串中的完全匹配,同时search需要在字符串内匹配.

network.addresses.private_man | selectattr("type", "match", "^fixed$")
Run Code Online (Sandbox Code Playgroud)

要将字典列表缩减为字符串列表,以便只获取addr字段列表,可以使用地图过滤器:

... | map(attribute='addr') | list
Run Code Online (Sandbox Code Playgroud)

或者,如果您想要逗号分隔的字符串:

... | map(attribute='addr') | join(',')
Run Code Online (Sandbox Code Playgroud)

结合起来,它看起来像这样.

- debug: msg={{ network.addresses.private_man | selectattr("type", "equalto", "fixed") | map(attribute='addr') | join(',') }}
Run Code Online (Sandbox Code Playgroud)


Fil*_*ipe 33

我已经提交了一个pull请求(在Ansible 2.2+中提供),通过在Ansible上添加jmespath查询支持,可以使这种情况更容易.在你的情况下,它将像:

- debug: msg="{{ addresses | json_query(\"private_man[?type=='fixed'].addr\") }}"
Run Code Online (Sandbox Code Playgroud)

会回来:

ok: [localhost] => {
    "msg": [
        "172.16.1.100"
    ]
}
Run Code Online (Sandbox Code Playgroud)

  • 您需要在运行json_query过滤器之前安装“ jmespath”。 (2认同)

bma*_*pin 15

不一定更好,但是因为在这里有选项是如何使用Jinja语句做的很好:

- debug:
    msg: "{% for address in network.addresses.private_man %}\
        {% if address.type == 'fixed' %}\
          {{ address.addr }}\
        {% endif %}\
      {% endfor %}"
Run Code Online (Sandbox Code Playgroud)

或者,如果您希望将其全部放在一行:

- debug:
    msg: "{% for address in network.addresses.private_man if address.type == 'fixed' %}{{ address.addr }}{% endfor %}"
Run Code Online (Sandbox Code Playgroud)

哪个回报:

ok: [localhost] => {
    "msg": "172.16.1.100"
}
Run Code Online (Sandbox Code Playgroud)