2017-07-10 6 views
0

Ich baute die folgende Liste, aber es gelingt mir nicht, darüber zu iterieren. Sollte ich with_items verwenden? mit_elementen? oder etwas anderes?Ansible - iterieren über eine Liste von Wörterbüchern

Mein Ziel ist es, über alle Hosts im Inventar zu iterieren, ihren Namen und ihre IP zu erhalten und schließlich zu drucken.

- set_fact: 
    list_of_hosts: | 
     {% set myList = [] %} 
     {% for host in groups['all'] %} 
     {% set ignored = myList.extend([{'server_name': host, 'server_ip': hostvars[host].ansible_eth0.ipv4.address }]) %} 
     {% endfor %} 
     {{ myList }} 


- debug: msg="{{ item.server_name }}" 
    with_items: "{{ list_of_hosts }}" 

Hier ist meine Liste, wenn ich es debuggen:

TASK [common : debug] ************************************************************************************************ 

ok: [my1stServer] => { 
    "msg": "   [{'server_ip': u'192.168.0.1', 'server_name': u'my1stServer'}, {'server_ip': u'192.168.0.2', 'server_name': u'my2ndServer'}]\n" 
} 

Und hier ist der Fehler, aber es ist nicht wirklich relevant:

fatal: [my1stServer]: FAILED! => {"failed": true, "msg": "the field 'args' has an invalid value, which appears to include a variable that is undefined. The error was: 'ansible.vars.unsafe_proxy.AnsibleUnsafeText object' has no attribute 'server_name'\n\nThe error appears to have been in 'hosts.yml': line 19, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- debug: msg=\"{{ item.server_name }}\"\n^here\nWe could be wrong, but this one looks like it might be an issue with\nmissing quotes. Always quote template expression brackets when they\nstart a value. For instance:\n\n with_items:\n  - {{ foo }}\n\nShould be written as:\n\n with_items:\n  - \"{{ foo }}\"\n"} 

Antwort

0

Bitte mich für Unverblümtheit vergeben, aber die Die vorgeschlagene Implementierung ist ein Versuch, zu verstehen, was die Idee eigentlich ist. Das ist einfach: um einige Variablen zu drucken, die in hostvars[host] vorhanden sind, für eine Liste von Hosts, die nach verschiedenen Kriterien ausgewählt wurden. Wenn wir die Implementierung nah an dieser Idee halten, ist die Implementierung einfacher.

Also, was ich tun würde, um eine Liste der Hosts von der Gruppenmitgliedschaft ausgewählt, oder möglicherweise "handverlesen" zu machen ist eigentlich tun, was ich gerade geschrieben habe :). Betrachten Sie diese Aufgabenliste:

# this task creates an empty list 
- name: create my_cool_list 
    set_fact: 
    my_cool_list: [] 
# this task adds to the list all hosts in groups we're iterating over 
- name: update my cool list with whole groups 
    set_fact: '{{my_cool_list + groups[curr_grp]}}' 
    with_items: 
    - grp1 
    - grp2 
    loop_control: 
    loop_var: curr_grp 
# this task adds to the list all hosts we're iterating over 
- name: update my cool list with specific hosts 
    set_fact: '{{my_cool_list + [curr_node]}}' 
    with_items: 
    - node001 
    - node101 
    loop_control: 
    loop_var: curr_node 

# now we can iterate over the list, accessing specific fields on each host 
- name: go over my cool list and print ansible_init_mgr 
    debug: 
    msg: 'hostvars["{{curr_host}}"].ansible_init_mgr: {{hostvars[curr_host].ansible_init_mgr}}' 
    with_items: '{{my_cool_list|default([], true)|list}}' 

Des Weiteren Sie Sicherheit when: durch die Validierung der Schlüssel hinzufügen, können Sie definiert sind Zugriff auf ..

Und eine Auswahl von Variablen zu jedem Host zu drucken, sollten Sie verwenden jinja Filter map('extract',...):

- name: print some vars from each host 
    debug: 
    msg: {'server_name': '{{hostvars[curr_node]|selectattr("ansible_hostname")}}', 'ip_address': '{{hostvars[curr_node]|selectattr("ansible_eth0.ipv4.address")}}'} 
    with_items: '{{my_cool_list|default([], true)|list}}' 
    loop_control: 
    loop_var: curr_node 

wENN Sie Lesbarkeit obwohl erhöhen wollen, sollten Sie besser einen Filter-Plugin schreiben, die die oben Sachen tun würde, und verstecken Iteration Hässlichkeit in lesbarer Weise, so können Sie haben:

Entweder (für generischen Ansatz, dh ohne Umbenennung Attribute)

- name: print some vars from each host 
    debug: 
    msg: '{{my_cool_list|multi_select_in_dict(["ansible_hostname", "ansible_eth0.ipv4.address")}}' 

Oder spezifischer Ansatz (so dass Sie bestimmt hart codiert Neuzuordnung von Attributen verwendet werden ...)

- name: print some vars from each host 
    debug: 
    msg: '{{my_cool_list|my_cool_filter}}' 
+0

Auch Sie verwende besser 'ansible_default_ipv4.address'. –

Verwandte Themen