2017-07-10 218 views
0

我構建了以下列表,但我沒有成功迭代它。 我應該使用with_items嗎? with_elements?或者是其他東西?Ansible - 遍歷字典列表

我的目標是迭代庫存中的所有主機,獲取其名稱和IP,最後打印出來。

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

這是我名單時,我調試它:

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

這裏是錯誤,但它不是真正相關:

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

回答

0

請原諒我的直率,但所提出的實現方式使得它能夠理解這個想法實際上是什麼。這很簡單:打印hostvars[host]中的一些變量,以獲得按各種標準挑選的主機列表。 如果我們保持實現接近這個想法,實現更簡單。

所以我會做什麼來創建一個由組成員身份選出的主機列表,或者可能是「手選」,實際上是做我剛剛寫的東西:)。 考慮這個任務列表:

# 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}}' 

此外,還可以通過驗證你定義訪問鍵添加安全when: ..

而且,打印選擇的變量約每臺主機,你應該使用神社過濾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 

如果你想增加可讀性不過,你最好寫一個過濾器插件,它會做上述的東西,藏在迭代可讀的方式醜陋,所以你可以有:

是(對於一般的做法,即不重命名屬性)

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

或者具體做法(讓您使用屬性的特定硬編碼重映射...)

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

另外,您更好地使用'ansible_default_ipv4.address'。 –