2017-07-10 223 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'。 –