0

我有一本剧本,其中的一项任务是将模板文件复制到具有delegate_to的特定服务器:名为“grover”

此处包含重要服务器的清单列表是:bigbird、grover、oscar

这些模板文件必须有一个与每个服务器的主机名匹配的名称,并且委托服务器 grover 也必须有它自己的所述文件的实例。仅当文件不存在时,才应进行此模板复制操作。/tmp/grover 预先存在于服务器 grover 上,它需要保持不受剧本运行的影响。

最终除了server grover上的/tmp/grover,运行后应该还存在:/tmp/bigbird和/tmp/oscar也在server grover上。

我遇到的问题是,当剧本在没有任何条件的情况下运行时,它确实起作用,但它也会破坏/覆盖 /tmp/grover,这是不可接受的。

但是,如果我在以前的播放中添加任务以预先检查这些文件,然后在模板播放中添加条件以跳过 grover(如果文件已经存在),它不仅会跳过 grover,而且会跳过所有其他将运行的服务器格罗弗也为那场比赛而战。如果我尝试将其设置为在所有其他服务器上运行但 grover,它仍然会失败,因为委托服务器是 grover 并且将被跳过。

这是实际的示例代码片段,由于主机模式,playbook 正在所有 3 台服务器上运行:

- hosts: bigbird:grover:oscar

   - name: File clobber check.
     stat:
       path: /tmp/{{ansible_hostname}}
     register: clobber_check
     delegate_to: "{{ item }}"
     with_items:
       - "{{ grover }}"

   - name: Copy templates to grover.
     template:
       backup: yes
       src: /opt/template
       dest: /tmp/{{ansible_hostname}}
       group: root
       mode: "u=rw,g=rw"
       owner: root
     delegate_to: "{{ item }}"
     with_items:
       - "{{ grover }}"
     when: ( not clobber_check.stat.exists ) and ( clobber_check is defined )

如果我运行它,并且 /tmp/grover 存在于 grover 上,那么它将简单地跳过整个复制播放,因为 grover 上的条件失败。因此,由于此问题,其他服务器将永远不会将其 /tmp/bigbird 和 /tmp/oscar 模板复制到 grover。

最后,我想避免 ghetto 解决方案,例如保存 grover 的原始配置文件的备份,允许使用 clobber,然后将保存的文件复制回来作为最后一项任务。

我一定在这里遗漏了一些东西,我不可能是唯一遇到这种情况的人。任何人都知道如何为此编码?

4

1 回答 1

0

这个问题的答案是去掉代码中不必要的with_items。虽然按原样使用 with_items 确实允许您将_委托给主机模式组,但它也使变量无法正确定义/分配给该组中的主机。

为 delegate_to 定义单个主机实体可解决此问题,然后任务在所有定义的主机上按预期执行。

康斯坦丁·苏沃洛夫(Konstantin Suvorov)应该为此获得荣誉,因为他是最初的回答者。

此外,我很惊讶 Ansible 不允许轻松委派给一组主机。他们不允许这样做肯定是有原因的。

于 2017-04-04T14:10:19.980 回答