Ansible with_subelements的默认值

Ansible with_subelements default value

我有一个这样的vars定义:

1
2
3
4
5
6
sites:
 - site: mysite1.com
   exec_init:
    -"command1 to exec"
    -"command2 to exec"
 - site: mysite2.com

然后我玩以下任务

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

这里的想法是,我将在我的var中拥有多个"站点"定义以及许多其他属性,
那么我想为定义了" exec_init"的那些站点执行多个Shell脚本命令。

通过这种方式,它总是总是跳过执行任务,我已经尝试了所有我能想象的组合,但是我无法使它正常工作...

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

感谢您的帮助


还有另一种方法,请尝试:

1
2
3
4
- 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


嗯,with_subelements不喜欢sites中元素的结构不统一。而且item不包含您??在with_subelements列表中指定的子元素。您可以做几件事:

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

  • 不要使用with_subelements并批量执行自己(有点难看):

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

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

    至:

    1
    continue

    然后您的任务应如下所示:

    1
    2
    3
    4
    5
    - name: Execute init scripts for all sites
      debug:"msg={{item.1}}"
      with_subelements_missingok:
        - sites
        - exec_init

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

    1
    2
    3
    4
    5
    6
    - name: nested loop skip missing elements
      with_subelements:
        - sites
        - exec_init
        - flags:
          skip_missing: true

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

    因此,代码应类似于:

    1
    2
    3
    - name: Execute init scripts for all sites
      shell:"{{ item.1 }}"
      loop:"{{ sites | subelements('exec_init', skip_missing=True) }}"

    这对我有用。我正在使用2.1.1版
    只需在子元素列表中添加第三个元素,如

    所示

    1
    2
    3
    4
    5
    - name: Iterate over something
      with_subelements:
         -"{{ unit }}"
         - config
         - skip_missing: True