10

我有一个这样的 vars 定义:

sites:
 - site: mysite1.com
   exec_init:
    - "command1 to exec"
    - "command2 to exec"
 - site: mysite2.com

然后我玩了以下任务

- name: Execute init scripts for all sites
  shell: "{{item.1}}"
  with_subelements: 
    - sites
    - exec_init
  when: item.0.exec_init is defined

这里的想法是我将有多个“站点”定义以及我的变量中的许多其他属性,然后我想为那些定义了“exec_init”的站点执行多个 Shell 脚本命令

这样做它总是跳过执行任务,我已经尝试了我能想象到的所有组合,但我就是无法让它工作......

这是正确的做法吗?也许我正在尝试实现一些没有意义的事情?

谢谢你的帮助

4

5 回答 5

17

还有一种方法,试试:

- debug: "var=item"
  with_subelements:
    - "{{ sites | selectattr('exec_init', 'defined') | list }}"
    - exec_init

感谢:https ://github.com/PublicaMundi/ansible-plugins/blob/master/lookup_plugins/subelements_if_exist.py

于 2015-06-30T18:39:37.963 回答
6

嗯,看起来元素的结构不统一siteswith_subelements不喜欢的。而且item它也不包含您在 with_subelements 列表中指定的子元素。你可以做几件事:

  1. 确保有一个exec_init列表,即使它是空的。with_subelements将跳过具有空子元素的项目。我认为这是最好的选择,虽然在编写剧本时有点不方便。

  2. 不要使用with_subelements和批量执行自己(有点难看):

    - name: Execute init scripts for all sites
      shell: "echo '{{item.exec_init | join(';')}}' | bash"
      when: item.exec_init is defined
      with_items: sites
    
  3. 自定义with_subelements,以便它包含缺少子元素的项目。您可以复制原件(我的在 中/usr/local/lib/python2.7/dist-packages/ansible/runner/lookup_plugins/with_subelements.py)并将其放在lookup_plugins您的剧本旁边的目录中,使用不同的名称(例如subelements_missingok.py)。然后将第 59 行从:

    raise errors.AnsibleError("could not find '%s' key in iterated item '%s'" % (subelement, item0))
    

    至:

    continue
    

    然后你的任务可能如下所示:

    - name: Execute init scripts for all sites
      debug: "msg={{item.1}}"
      with_subelements_missingok:
        - sites
        - exec_init
    
于 2014-09-15T07:59:07.683 回答
5

还有另一种方式,使用 skip_missing 标志(Ansible 2.0+):

- name: nested loop skip missing elements
  with_subelements:
    - sites
    - exec_init
    - flags:
      skip_missing: true
于 2016-08-02T09:55:17.487 回答
5

这里的有效解决方案(考虑 ansible 2.7+)是使用loop而不是with_subelements. 与循环一样,您可以应用subelements过滤器,它具有skip_missing选项(即@hkariti 在选项 3 中建议的内容,但方式正确)。

因此,代码应如下所示:

- name: Execute init scripts for all sites
  shell: "{{ item.1 }}"
  loop: "{{ sites | subelements('exec_init', skip_missing=True) }}"
于 2020-11-18T12:14:06.940 回答
4

这对我有用。我使用的是 2.1.1 版本,只需在 subelements 列表中添加第三个元素,如图所示

- name: Iterate over something
  with_subelements:
     - "{{ unit }}"
     - config
     - skip_missing: True
于 2016-12-05T08:16:15.507 回答