仅当文件存在时,Ansible包括任务

时间:2015-01-23 22:07:10

标签: ansible

我正在尝试仅在文件存在时包含文件。如果我的角色的用户需要,这允许现有“任务/角色”之间的自定义“任务/角色”。我发现了这个:

- include: ...
  when: condition

但Ansible文档指出:

  

“评估所有任务,但条件适用于每项任务” - http://docs.ansible.com/playbooks_conditionals.html#applying-when-to-roles-and-includes

所以

- stat: path=/home/user/optional/file.yml
  register: optional_file
- include: /home/user/optional/file.yml
  when: optional_file.stat.exists

如果包含的文件不存在,则会失败。我想可能还有另一种允许用户将任务添加到现有配方的机制。我不能让用户在我之后添加一个角色,因为他们无法控制订单:他们的角色将在我之后执行。

8 个答案:

答案 0 :(得分:26)

with_first_found条件可以在没有statlocal_action的情况下完成此操作。此条件将通过本地文件列表执行任务,并将item设置为存在的第一个文件的路径。 如果文件不存在,在skip: true选项中包含with_first_found可以防止它失败。

示例:

- hosts: localhost
  connection: local
  gather_facts: false

  tasks:
    - include: "{{ item }}"
      with_first_found:
        - files:
            - /home/user/optional/file.yml
          skip: true

答案 1 :(得分:10)

感谢大家的帮助!我终于在今天的Ansible中尝试了所有回复和我自己的问题代码后,我正在回答自己的问题: ansible 2.0.1.0

我的原始代码似乎现在正常工作,除了我看到的可选文件在我的本地机器上,所以我必须通过 local_action 运行stat并为特定任务设置become: no ,所以ansible不会尝试在我的本地机器上执行sudo并且错误:“sudo:需要密码\ n”

- local_action: stat path=/home/user/optional/file.yml
  register: optional_file
  become: no
- include: /home/user/optional/file.yml
  when: optional_file.stat.exists

答案 2 :(得分:5)

我使用类似的东西,但对于文件模块,我的诀窍是检查变量定义,尝试类似:

when: optional_file.stat.exists is defined and optional_file.stat.exists

只有当变量存在时,任务才会运行。

答案 3 :(得分:2)

我可以花时间来抨击ansible的错误处理规定,但简而言之,你是对的,由于陈述的原因,你不能将stat模块用于此目的。

对于大多数安问问题,最简单的解决方案是在ansible之外进行。 E.g。

- shell: test -f /home/user/optional/file.yml     # or use -r if you're too particular.
  register: optional_file
  failed_when: False
- include: /home/user/optional/file.yml
  when: optional_file.rc == 0
- debug: msg="/home/user/optional/file.yml did not exist and was not included"
  when: optional_file.rc != 0
添加了

* failed_when ,以避免在文件不存在时主机被排除在进一步的任务之外。

答案 4 :(得分:1)

如果我没有错,你想继续剧本甚至是if语句错误吗?

如果是,请在when:

之后添加此行
ignore_errors: True

所以你的任务看起来像这样:

- stat: path=/home/user/optional/file.yml
  register: optional_file
- include: /home/user/optional/file.yml
  when: optional_file.stat.exists
  ignore_errors: True

如果我正确理解您的问题,请告知我们,或者可以进一步提供帮助。感谢

答案 5 :(得分:1)

到目前为止,我提出的最佳选择是:

- include: "{{ hook_variable | default(lookup('pipe', 'pwd') ~ '/hooks/empty.yml') }}"

它不完全是" if-exists",但它为您的角色用户提供了相同的结果。在您的角色中创建一些变量和一个默认的空文件。 Jinja过滤器"默认"和"查找"如果没有设置变量,请注意回退空文件。

为方便起见,用户可以使用{{ playbook_dir }}变量来设置路径:

hook_variable: "{{ playbook_dir }}/hooks/tasks-file.yml" 

答案 6 :(得分:1)

还可以选择使用Jinja2过滤器:

 - set_fact: optional_file="/home/user/optional/file.yml"

 - include: ....
   when: optional_file|exists

答案 7 :(得分:0)

在Ansible 2.5及更高版本中,可以使用以下测试来完成:

- include: /home/user/optional/file.yml
  when: "'/home/user/optional/file.yml' is file"

更多详细信息:https://docs.ansible.com/ansible/latest/user_guide/playbooks_tests.html#testing-paths