Ansible - 迭代字典列表

时间:2017-07-10 13:51:38

标签: ansible jinja2

我建立了以下列表,但我没有成功迭代它。 我应该使用with_items吗? with_elements?或其他什么?

我的目标是遍历广告资源中的所有主机,获取其名称和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"}

1 个答案:

答案 0 :(得分: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:

并且,要打印关于每个主机的一系列变量,您应该使用jinja过滤器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}}'