Ansible: iterando sobre um dicionário aninhado?

1

Eu tenho dados parecidos com isto:

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

Eu preciso do equivalente Ansible do seguinte loop de Python:

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

Eu esperava poder fazer isso:

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

Mas isso falha porque properties é um dicionário, não uma lista. E você não pode fazer isso:

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

Algum apontador?

    
por larsks 02.11.2018 / 19:56

2 respostas

2

Bem, posso sugerir uma solução semi-hacky onde você usa set_fact algumas vezes para construir uma lista de ditos que você provavelmente pode usar?

- 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

Resultados.

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   

Acredito que isso permitiria que você passasse as listas construídas definindo cada propriedade.

    
por 02.11.2018 / 22:18
1

Se eu ignorar a parte "Eu quero verificar o valor primeiro", eu poderia resolver isso através da criação de modelos, assim:

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

Isso funciona, mas é feio e vai resultar em tudo sendo changed a cada runbook. Eu poderia empurrar os dados antes de passar para ansible para que as chaves properties seja uma lista de listas de uma lista de ditos, como em:

- 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

Mas isso é um pouco menos intuitivo para ler e escrever ... e é Reimplementando efetivamente o método .items() manualmente.

    
por 02.11.2018 / 21:45

Tags