【问题标题】:Double loop Ansible双循环 Ansible
【发布时间】:2015-10-12 12:45:05
【问题描述】:

我有一个这样的对象

objs:
    - { key1: value1, key2: [value2, value3] }
    - { key1: value4, key2: [value5, value6] }

我想创建以下文件

value1/value2
value1/value3
value4/value5
value4/value6

但我不知道如何使用with_items 进行双循环

【问题讨论】:

    标签: ansible ansible-playbook


    【解决方案1】:

    看看with_subelements中的Ansible's docs for loops

    1. 您需要创建目录:
    2. 迭代 objs 并创建文件:

    这是一个例子:

    ---
    
    - hosts: localhost
      gather_facts: no
      vars:
        objs:
          - { key1: value1, key2: [ value2, value3] }
          - { key1: value4, key2: [ value5, value6] }
      tasks:
        - name: create directories
          file: path="{{ item.key1 }}"  state=directory
          with_items:
            objs
    
        - name: create files
          file: path="{{ item.0.key1 }}/{{ item.1 }}"  state=touch
          with_subelements:
            - objs
            - key2
    

    输出很容易解释,第二个循环以您需要的方式遍历值:

    PLAY [localhost] ************************************************************** 
    
    TASK: [create files] ********************************************************** 
    changed: [localhost] => (item={'key2': ['value2', 'value3'], 'key1': 'value1'})
    changed: [localhost] => (item={'key2': ['value5', 'value6'], 'key1': 'value4'})
    
    TASK: [create files] ********************************************************** 
    changed: [localhost] => (item=({'key1': 'value1'}, 'value2'))
    changed: [localhost] => (item=({'key1': 'value1'}, 'value3'))
    changed: [localhost] => (item=({'key1': 'value4'}, 'value5'))
    changed: [localhost] => (item=({'key1': 'value4'}, 'value6'))
    
    PLAY RECAP ******************************************************************** 
    localhost                  : ok=2    changed=2    unreachable=0    failed=0 
    

    【讨论】:

    • 请注意,从 Ansible v2.7 开始,最好将 loop 构造与 subelements filter 一起使用,而不是 with_X 构造。有关如何迁移,请参阅 Loops 文档。
    • 当我尝试这个时,我得到一个错误。我认为with_subelements下的第一项需要{{ }},即with_subelements: ["{{ objs }}", "key2"]
    【解决方案2】:

    事实上你不能。 Ansible 中的循环是一维的。有一个技巧曾经在以前的版本中有效,并且在 Ansible 2.0 中再次有效:

    您可以将一个循环与include 语句一起使用,并且在包含的 yml 中您有第二个循环。所以沿着这些思路:

    ma​​in.yml:

    - include: nested_loop.yml obj={{ item }}
      with_items: objs
    

    nested_loop.yml:

    - name: create files
      file: path={{obj.key1 }}/{{ item }} state=touch
      with_items: obj.key2
    

    同样,这在 Ansible 的当前版本 (1.9.2) 中不起作用。该功能已被删除,因为它会导致一些问题,但会在 Ansible 2.0 中再次得到支持,因此当您使用 devel branch from github 时应该可以使用它。

    你可以从 github 源码安装:

    git clone https://github.com/ansible/ansible.git --recursive
    cd ./ansible
    source ./hacking/env-setup
    sudo make install
    

    【讨论】:

      【解决方案3】:

      添加到 udondan 的答案(没有代表在上面发表评论):

      使用 with_items 可能会导致意外结果,因为外部循环和内部循环共享一个公共变量“item”。

      您将需要使用“循环控制”来防止变量冲突。

      例如

      - include: nested_loop.yml obj={{ outside_item }}
        with_items: objs
        loop_control:
          loop_var: outside_item
      

      【讨论】:

      • obj={{ outside_item }} 这里甚至不需要,outside_item 可以直接在nested_loop.yml 文件中使用。
      • 我在执行时使用“include_tasks”而不是“include”来解析所有变量
      • 这是loop_var的文档
      猜你喜欢
      • 1970-01-01
      • 2022-06-10
      • 2019-04-06
      • 2021-09-14
      • 1970-01-01
      • 2015-12-10
      • 2017-06-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多