Ansible: Filtern Sie eine Liste nach ihren Attributen

84

Ich habe eine Variable namens "Netzwerk" 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 = "float" abzurufen?

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

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

Guido
quelle

Antworten:

41

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

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

würden zurückkehren:

ok: [localhost] => {
    "msg": [
        "172.16.1.100"
    ]
}
Filipe
quelle
3
Sie müssen "jmespath" installieren, bevor Sie den Filter json_query ausführen.
Ceving
Und ich habe den Versuch, jmespath zu installieren, aufgrund von Unterschieden in der Python-Version aufgegeben. Es ist keine so triviale Lösung, wie es auf Ansible 2.4+
Stuart Watt
1
@StuartWatt Möglicherweise benötigen Sie pyenv, um sich von der Python-Version des Betriebssystems zu entfernen. Sie können pyenv, pyenv virtualenvs ausprobieren, oder einige Leute bevorzugen pipenv. Sie werden trotzdem funktionieren.
Jepper
@Jepper Wenn Sie ein ganz neues Python benötigen, um Ansible zu verwenden, ist es ein verlorener Kampf. (Und ich benutzte Pyenv und hatte immer noch diese Probleme :-)
Stuart Watt
128

Um eine Liste von Diktaten zu filtern, können Sie den Selectattr-Filter zusammen mit dem Equalto-Test verwenden :

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

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


Ansible hat auch die Tests matchundsearch , die reguläre Ausdrücke nehmen:

matcherfordert eine vollständige Übereinstimmung in der Zeichenfolge, während searcheine Übereinstimmung innerhalb der Zeichenfolge erforderlich ist.

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

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

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

Oder wenn Sie eine durch Kommas getrennte Zeichenfolge möchten:

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

Zusammen würde es so aussehen.

- debug: msg={{ network.addresses.private_man | selectattr("type", "equalto", "fixed") | map(attribute='addr') | join(',') }}
Udondan
quelle
1
Wenn Sie sie als Liste und nicht als durch Kommas getrennte Zeichenfolge verwenden möchten, können Sie auch {{ network.addresses.private_man | selectattr("type", "equalto", "fixed") | map(attribute='addr') | list }}
Folgendes
1
Hat sich der von Ihnen bereitgestellte Link geändert? Ich kann "Übereinstimmung" und "Suche" auf dieser Seite nicht finden
activedecay
1
@activedecay Sieht so aus, als wäre es von dieser Seite verschwunden, ja. Die einzige Erwähnung, die ich jetzt finden konnte, ist auf dieser Seite: docs.ansible.com/ansible/latest/user_guide/… Ich habe den Link aktualisiert, danke!
Udondan
19

Nicht unbedingt besser, aber da es schön ist, Optionen zu haben, geht es hier mit Jinja-Anweisungen so :

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

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

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

Welches kehrt zurück:

ok: [localhost] => {
    "msg": "172.16.1.100"
}
Bmaupin
quelle