2017-02-10 20 views
5

Скажем, у меня есть этот словарьКак перебрать этот словарь в Ansible?

war_files: 
    server1: 
    - file1.war 
    - file2.war 
    server2: 
    - file1.war 
    - file2.war 
    - file3.war 

и сейчас я просто хочу, чтобы петли по каждому пункту (ключ), а затем по каждому элементу ключа (значение). Я сделал это

- name: Loop over the dictionary 
    debug: msg="Key={{ item.key }} value={{ item.value }}" 
    with_dict: "{{ war_files }}" 

И я получаю это. Это, конечно, правильно, но НЕ то, что я хочу.

ok: [localhost] => (item={'value': [u'file1.war', u'file2.war'], 'key': u'server1'}) => { 
    "item": { 
     "key": "server1", 
     "value": [ 
      "file1.war", 
      "file2.war" 
     ] 
    }, 
    "msg": "Server=server1, WAR=[u'file1.war', u'file2.war']" 
} 
ok: [localhost] => (item={'value': [u'file1.war', u'file2.war', u'file3.war'], 'key': u'server2'}) => { 
    "item": { 
     "key": "server2", 
     "value": [ 
      "file1.war", 
      "file2.war", 
      "file3.war" 
     ] 
    }, 
    "msg": "Server=server2, WAR=[u'file1.war', u'file2.war', u'file3.war']" 
} 

Я хочу, чтобы получить результат, который говорит

"msg": "Server=server1, WAR=file1.war" 
"msg": "Server=server1, WAR=file2.war" 
"msg": "Server=server2, WAR=file1.war" 
"msg": "Server=server2, WAR=file2.war" 
"msg": "Server=server2, WAR=file3.war" 

IOW, как я могу написать задачу итерацию по словарю, так что проходит через каждую клавишу, а затем элементы внутри каждой клавиши? В сущности, у меня есть вложенный массив и вы хотите перебрать его?

ответ

4

Ну, я не мог найти очень простой способ сделать это, однако, с немного Jinja2, мы можем достичь чего-то в этом роде:

/tmp ❯❯❯ cat example.yml 
--- 
- hosts: 127.0.0.1 
    vars: 
    war_files: 
     server1: 
     - file1.war 
     - file2.war 
     server2: 
     - file1.war 
     - file2.war 
     - file3.war 
    tasks: 
    - set_fact: 
     war_files_list_of_dicts: | 
      {% set res = [] -%} 
      {% for key in war_files.keys() -%} 
      {% for value in war_files[key] -%} 
       {% set ignored = res.extend([{'Server': key, 'WAR':value}]) -%} 
      {%- endfor %} 
      {%- endfor %} 
      {{ res }} 

    - name: let's debug the crap out of this 
    debug: var=war_files_list_of_dicts 

    - name: Servers and their WARs!!! 
    debug: 
     msg: "Server={{ item.Server }}, WAR={{ item.WAR }}" 
    with_items: "{{ war_files_list_of_dicts }}" 

И, когда Playbook запускается :

/tmp ❯❯❯ ansible-playbook example.yml 
[WARNING]: provided hosts list is empty, only localhost is available 


PLAY [127.0.0.1] *************************************************************** 

TASK [setup] ******************************************************************* 
ok: [127.0.0.1] 

TASK [set_fact] **************************************************************** 
ok: [127.0.0.1] 

TASK [let's debug the crap out of this] **************************************** 
ok: [127.0.0.1] => { 
    "war_files_list_of_dicts": [ 
     { 
      "Server": "server1", 
      "WAR": "file1.war" 
     }, 
     { 
      "Server": "server1", 
      "WAR": "file2.war" 
     }, 
     { 
      "Server": "server2", 
      "WAR": "file1.war" 
     }, 
     { 
      "Server": "server2", 
      "WAR": "file2.war" 
     }, 
     { 
      "Server": "server2", 
      "WAR": "file3.war" 
     } 
    ] 
} 

TASK [Servers and their WARs!!!] *********************************************** 
ok: [127.0.0.1] => (item={'WAR': u'file1.war', 'Server': u'server1'}) => { 
    "item": { 
     "Server": "server1", 
     "WAR": "file1.war" 
    }, 
    "msg": "Server=server1, WAR=file1.war" 
} 
ok: [127.0.0.1] => (item={'WAR': u'file2.war', 'Server': u'server1'}) => { 
    "item": { 
     "Server": "server1", 
     "WAR": "file2.war" 
    }, 
    "msg": "Server=server1, WAR=file2.war" 
} 
ok: [127.0.0.1] => (item={'WAR': u'file1.war', 'Server': u'server2'}) => { 
    "item": { 
     "Server": "server2", 
     "WAR": "file1.war" 
    }, 
    "msg": "Server=server2, WAR=file1.war" 
} 
ok: [127.0.0.1] => (item={'WAR': u'file2.war', 'Server': u'server2'}) => { 
    "item": { 
     "Server": "server2", 
     "WAR": "file2.war" 
    }, 
    "msg": "Server=server2, WAR=file2.war" 
} 
ok: [127.0.0.1] => (item={'WAR': u'file3.war', 'Server': u'server2'}) => { 
    "item": { 
     "Server": "server2", 
     "WAR": "file3.war" 
    }, 
    "msg": "Server=server2, WAR=file3.war" 
} 

PLAY RECAP ********************************************************************* 
127.0.0.1     : ok=4 changed=0 unreachable=0 failed=0 
+0

Спасибо! Здесь я люблю шеф-повара над Ansible, где я могу просто написать Ruby для перебора структуры данных. По сути, это то, что вы сделали здесь с Python, но этот синтаксис просто уродлив. –

+1

@ChrisF Я написал jinja2, а не python. –

+0

Но да, я согласен с тобой. Из-за этого кукольный и шеф-повар имеют преимущество над Ansible. –

0

Теперь анзибль это позволяет

- name: add several users 
    user: 
    name: "{{ item.name }}" 
    state: present 
    groups: "{{ item.groups }}" 
    with_items: 
    - { name: 'testuser1', groups: 'wheel' } 
    - { name: 'testuser2', groups: 'root' }