2015-08-08 12 views
42

ho variabile ho chiamato "rete" registrata in Ansible:Ansible: filtrare un elenco con i suoi attributi

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

E 'possibile ottenere l'indirizzo IP ("addr") con type = "galleggiante" fare qualcosa come questo?

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

So che la sintassi è sbagliato, ma si ottiene l'idea.

risposta

16

ho presentato una pull request (disponibile in Ansible 2.2+) che renderà questo tipo di situazioni più facili con l'aggiunta di jmespath supporto di query su Ansible. Nel tuo caso che avrebbe funzionato come:

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

sarebbero tornati:

ok: [localhost] => { 
    "msg": [ 
     "172.16.1.100" 
    ] 
} 
+0

È necessario installare" jmespath "prima di eseguire il filtro json_query. – ceving

64

per filtrare un elenco di dicts è possibile utilizzare il selectattr filter insieme al equalto test:

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

È possibile che questo richiede Jinja2 v2.8 o successiva (indipendentemente dalla versione Ansible).


Ansible anche has the tests match and search, che prendono le espressioni regolari:

match richiederà una corrispondenza completa nella stringa, mentre search richiederà un incontro all'interno della stringa.

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

Per ridurre l'elenco delle dicts ad una lista di stringhe, in modo da ottenere solo un elenco dei campi addr, è possibile utilizzare il map filter:

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

O se vuoi una stringa separata da virgola:

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

Combinato, sarebbe simile a questo.

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

Se loro vogliono come lista piuttosto che una stringa separati da virgola, è anche possibile utilizzare: '{{network.addresses.private_man | selectattr ("type", "equalto", "fixed") | map (attributo = 'addr') | lista}} ' – TrinitronX

8
Non

necessariamente migliore, ma dal momento che è bello avere opzioni qui come fare utilizzando Jinja statements:

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

Oppure se preferisci mettere tutto su una riga:

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

che restituisce:

ok: [localhost] => { 
    "msg": "172.16.1.100" 
} 
Problemi correlati