Ansible:遍历嵌套字典?

Ansible:遍历嵌套字典?

我有如下数据:

nova_flavors:
- disk: 10
  name: m1.tiny
  properties:
    disk_read_bytes_sec: 12500000
    disk_read_iops_sec: 1000
    disk_write_bytes_sec: 3125000
    disk_write_iops_sec: 250
    vif_inbound_average: 2500
    vif_inbound_burst: 3750000
    vif_inbound_peak: 12500
    vif_outbound_average: 2500
    vif_outbound_burst: 3750000
    vif_outbound_peak: 12500
  ram: 1
- disk: 10
  name: m1.small
  properties:
    disk_read_bytes_sec: 25000000
    disk_read_iops_sec: 2000
    disk_write_bytes_sec: 6250000
    disk_write_iops_sec: 500
    vif_inbound_average: 5000
    vif_inbound_burst: 7500000
    vif_inbound_peak: 25000
    vif_outbound_average: 5000
    vif_outbound_burst: 7500000
    vif_outbound_peak: 25000
  ram: 2

我需要以下 Python 循环的 Ansible 等效版本:

for flavor in nova_flavors:
  for propname, propval in flavor['properties'].items():
    # do something with (flavor['name'], propname, propval)

我希望我能做到这一点:

- debug:
    msg: "{{ item }}"
  with_subelements:
    - "{{ nova_flavors }}"
    - "properties"

但这样做会失败,因为properties这是字典,而不是列表。你也不能这样做:

- debug:
    msg: "{{ item }}"
  with_subelements:
    - "{{ nova_flavors }}"
    - "properties.items()"

有什么指点吗?

答案1

好吧,我可以建议一个半黑客解决方案,其中您使用 set_fact 几次来构建您可能使用的字典列表?

- hosts: localhost
  vars:
    nova_flavors:
    - disk: 10
      name: m1.tiny
      properties:
        disk_read_bytes_sec: 12500000
        disk_read_iops_sec: 1000
        disk_write_bytes_sec: 3125000
      ram: 1
    - disk: 10
      name: m1.small
      properties:
        vif_outbound_burst: 7500000
        vif_outbound_peak: 25000
      ram: 2
  tasks:
  - set_fact:
      aslist: |
        [
        {% for item in nova_flavors %}
        {% for prop in item.properties.keys() %}
        {{ '{' }} 'name':'{{ item.name }}','propname':'{{ prop }}','propvalue':{{item.properties[prop]}} {{ '}' }},
        {% endfor %}
        {% endfor %}
        ]

  - debug:
      var: aslist

结果。

TASK [debug] *******************************************************************
ok: [localhost] => {
    "aslist": [
        {
            "name": "m1.tiny", 
            "propname": "disk_write_bytes_sec", 
            "propvalue": 3125000
        }, 
        {
            "name": "m1.tiny", 
            "propname": "disk_read_iops_sec", 
            "propvalue": 1000
        }, 
        {
            "name": "m1.tiny", 
            "propname": "disk_read_bytes_sec", 
            "propvalue": 12500000
        }, 
        {
            "name": "m1.small", 
            "propname": "vif_outbound_peak", 
            "propvalue": 25000
        }, 
        {
            "name": "m1.small", 
            "propname": "vif_outbound_burst", 
            "propvalue": 7500000
        }
    ]
}

PLAY RECAP *********************************************************************
localhost                  : ok=4    changed=0    unreachable=0    failed=0   

我相信这将使您能够轻松地循环构造列表并设置每个属性。

答案2

如果我忽略“我想先检查值”部分,我可以通过模板来解决这个问题,如下所示:

- name: set flavor properties:
  command: >-
    openstack flavor set
    {%for prop in item.properties.items()%}--property
    {{prop.0}}={{prop.1}} {%endfor %} {{ item.name }}
  loop: "{{ nova_flavors }}"

这可行,但很丑陋,并且会导致 changed每次运行剧本时一切都如此。我可以在将数据传递给 ansible 之前对其进行处理,以便properties键是列表列表而不是字典列表,如下所示:

- disk: 10
  name: m1.tiny
  properties:
    - [disk_read_bytes_sec,  12500000]
    - [disk_read_iops_sec,  1000]
    - [disk_write_bytes_sec,  3125000]
    - [disk_write_iops_sec,  250]
    - [vif_inbound_average,  2500]
    - [vif_inbound_burst,  3750000]
    - [vif_inbound_peak,  12500]
    - [vif_outbound_average,  2500]
    - [vif_outbound_burst,  3750000]
    - [vif_outbound_peak,  12500]
  ram: 1
  vcpus: 1
- disk: 10
  name: m1.small
  properties:
    - [disk_read_bytes_sec: 25000000]
    - [disk_read_iops_sec: 2000]
    - [disk_write_bytes_sec: 6250000]
    - [disk_write_iops_sec: 500]
    - [vif_inbound_average: 5000]
    - [vif_inbound_burst: 7500000]
    - [vif_inbound_peak: 25000]
    - [vif_outbound_average: 5000]
    - [vif_outbound_burst: 7500000]
    - [vif_outbound_peak: 25000]
  ram: 2
  vcpus: 1

但读写起来不太直观......而且它实际上是.items()手动重新实现该方法。

相关内容