it-swarm.com.de

Ansible: filtert eine Liste nach ihren Attributen

Ich habe die Variable "network" in Ansible registriert:

{
    "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"
            }
        ]
    }
}

Ist es möglich, die IP-Adresse ("addr") mit type = "floating" zu ermitteln, wenn Sie so etwas tun?

- debug: var={{ network.addresses.private_man | filter type="fixed" | get "addr" }}

Ich weiß, dass die Syntax falsch ist, aber Sie bekommen die Idee.

65
Guido

Ich habe eine Pull-Anforderung (verfügbar in Ansible 2.2+) gesendet, die diese Art von Situationen erleichtert, indem jmespath Abfrageunterstützung für Ansible hinzugefügt wird. In Ihrem Fall würde es so aussehen:

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

würden zurückkehren:

ok: [localhost] => {
    "msg": [
        "172.16.1.100"
    ]
}
30
Filipe

Um eine Liste von Dikten zu filtern, können Sie das selectattr filter zusammen mit dem equalto test verwenden:

network.addresses.private_man | selectattr("type", "equalto", "fixed")

Für das oben Genannte ist Jinja2 v2.8 oder höher erforderlich (unabhängig von der Ansible-Version).


Ansible auch hat die Tests match und search , die reguläre Ausdrücke annehmen:

match erfordert eine vollständige Übereinstimmung in der Zeichenfolge, während search eine Übereinstimmung innerhalb der Zeichenfolge erfordert.

network.addresses.private_man | selectattr("type", "match", "^fixed$")

Um die Liste der Dikte auf eine Liste von Zeichenfolgen zu reduzieren, sodass Sie nur eine Liste der Felder addr erhalten, können Sie den Kartenfilter verwenden:

... | map(attribute='addr') | list

Oder wenn Sie eine durch Kommas getrennte Zeichenfolge wünschen:

... | map(attribute='addr') | join(',')

Zusammen würde es so aussehen.

- debug: msg={{ network.addresses.private_man | selectattr("type", "equalto", "fixed") | map(attribute='addr') | join(',') }}
96
udondan

Nicht unbedingt besser, aber da es schön ist, Optionen zu haben, erfahren Sie hier, wie Sie dies mit Jinja-Anweisungen tun :

- debug:
    msg: "{% for address in network.addresses.private_man %}\
        {% if address.type == 'fixed' %}\
          {{ address.addr }}\
        {% endif %}\
      {% endfor %}"

Oder wenn Sie es vorziehen, alles auf eine Zeile zu setzen:

- debug:
    msg: "{% for address in network.addresses.private_man if address.type == 'fixed' %}{{ address.addr }}{% endfor %}"

Welches gibt zurück:

ok: [localhost] => {
    "msg": "172.16.1.100"
}
15
bmaupin