首页 文章

如何在Ansible中循环这个字典?

提问于
浏览
8

说我有这本词典

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 回答

  • 6

    现在Ansible允许这样做

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

    好吧,我找不到一个非常简单的方法来做到这一点,但是,通过一点点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 }}"
    

    而且,当剧本运行时:

    /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
    
  • 7

    这个怎么样

    - hosts: localhost
      vars:
        war_files:
          server1:
          - file1.war
          - file2.war
          server2:
          - file1.war
          - file2.war
          - file3.war
      tasks:
        - name: Loop over subelements of the dictionary
          debug:
            msg: "Key={{ item.0.key }} value={{ item.1 }}"
          loop: "{{ war_files | dict2items | subelements('value') }}"
    

    dict2itemssubelements 过滤器将在Ansible 2.6中出现 .

    仅供参考,如果您的目标的过滤器不存在,您可以在python中编写自己的过滤器,而不必诉诸于jinja2 hacks . Ansible很容易扩展;默认搜索 filter_plugins/*.py 中的过滤器,与您的播放/角色相邻,并自动包含 - 有关详细信息,请参阅Developing Plugins .

  • 5

    这是我循环遍历词典的首选方式:

    input_data.yml包含以下内容:

    ----
    input_data:
      item_1:
        id: 1
        info: "Info field number 1"
      item_2:
        id: 2
        info: "Info field number 2"
    

    然后我使用keys()函数在play中使用如上所述的数据结构,并使用with_items迭代数据:

    ---
    - hosts: localhost
      gather_facts: false
      connection: local
      tasks:
        - name: Include dictionary data
          include_vars:
            file: data.yml
    
        - name: Show info field from data.yml
          debug:
            msg: "Id: {{ input_data[item]['id'] }} - info: {{ input_data[item]['info'] }}"
          with_items: "{{ input_data.keys() }}"
    

    上面的剧本产生以下输出:

    PLAY [localhost] ***********************************************************
    
    TASK [Include dictionary data] *********************************************
    ok: [localhost]
    
    TASK [Show info field from data.yml] ***************************************
    ok: [localhost] => (item=item_2) => {
        "msg": "Id: 2 - info: Info field item 2"
    }
    ok: [localhost] => (item=item_3) => {
        "msg": "Id: 3 - info: Info field item 3"
    }
    ok: [localhost] => (item=item_1) => {
        "msg": "Id: 1 - info: Info field item 1"
    }
    
    PLAY RECAP *****************************************************************
    localhost                  : ok=2    changed=0    unreachable=0    failed=0
    

相关问题