Ansible 仅当文件存在时才允许包含任务

Ansible 仅当文件存在时才允许包含任务,ansible,Ansible,我试图仅在文件存在时才包含该文件。如果我的角色的用户需要,这允许在现有“任务/角色”之间自定义“任务/角色”。我发现: - include: ... when: condition 但Ansible文件指出: “所有任务都得到评估,但条件应用于每个任务”—— 所以 如果包含的文件不存在,则将失败。我想可能还有另一种机制允许用户向现有配方中添加任务。我不能让用户在我的角色之后添加角色,因为他们无法控制顺序:他们的角色将在我的角色之后执行。如果我没有错,你想继续剧本,即使when语句为fals

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

- include: ...
  when: condition
但Ansible文件指出:

“所有任务都得到评估,但条件应用于每个任务”——

所以


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

如果我没有错,你想继续剧本,即使when语句为false

如果是,请在:

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

请让我知道,如果我理解正确您的问题,或可以进一步帮助。谢谢

到目前为止,我想到的最好的选择是:

- include: "{{ hook_variable | default(lookup('pipe', 'pwd') ~ '/hooks/empty.yml') }}"
它并不完全是一个“如果存在”,但它会给角色的用户相同的结果。在您的角色中创建一些变量和默认的空文件。Jinja过滤器“default”和“lookup”负责在未设置变量的情况下返回空文件

为方便起见,用户可以使用
{{playbook\u dir}}
变量设置路径:

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

我可以在这里花些时间来抨击ansible的错误处理规定,但简而言之,您是对的,由于声明的原因,您不能为此目的使用
stat
模块

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

- 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

*
失败\u当添加
以避免主机在文件不存在时被排除在进一步的任务之外时。

我使用了类似的方法,但对于文件模块,我的诀窍是检查变量定义,请尝试以下操作:

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

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

谢谢大家的帮助!在今天的Ansible:Ansible 2.0.1.0

我的原始代码现在似乎可以工作了,除了我在本地机器中查找的可选文件外,所以我必须通过本地_操作运行stat,并为特定任务设置
been:no
,这样ansible就不会尝试在本地机器中执行sudo,并出现错误:“sudo:需要密码\n”


找到第一个_的条件可以在不使用统计或本地_操作的情况下完成此操作。此条件将遍历本地文件列表并执行任务,将
项设置为存在的第一个文件的路径。
如果在
中包含
skip:true
,并首先找到
选项,则可以防止文件不存在时失败

例如:

- hosts: localhost
  connection: local
  gather_facts: false

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

使用ansible-2.1.0,我可以在我的剧本中使用这样的片段:

- hosts: all
  gather_facts: false
  tasks:
    - name: Determine if local playbook exists
      local_action: stat path=local.yml
      register: st

- include: local.yml
  when: st.stat.exists
local.yml
不存在并且playbook被执行时(作为playbook,意味着它以
主机:
行开始,等等),我没有收到任何错误/失败

您可以在任务级别使用类似的代码执行相同的操作。
使用
stat
似乎可以正常工作。

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

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

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

在Ansible 2.5及以上版本中,可以使用以下测试进行:

- stat: path=/home/user/optional/file.yml
  register: optional_file
- include: /home/user/optional/file.yml
  when: optional_file.stat.exists
  ignore_errors: True
-包括:/home/user/optional/file.yml
当:“'/home/user/optional/file.yml”为文件时

更多详细信息:

我花了一点时间研究这个问题,看起来您是正确的,即使
条件为false,它也肯定会失败。谢谢,您似乎理解这个问题,但这不起作用。忽略\u错误不会忽略文件丢失的事实。当它说:“请注意,上面的系统只控制特定任务的失败,因此如果使用了未定义的变量,它仍然会引发用户需要解决的错误。”这个错误是会阻止用户的错误之一。这只适用于Ansible v1.9及以下版本。Ansible v2.0及更高版本应在@olluchThank建议定义:include\u file\u变量时使用
!我在我的真实代码中使用了
{{playbook\u dir}}
,为了简单起见,我只是将其排除在示例之外。谢谢,似乎没有定义
可选的\u file.stat.exists时,when将起作用。我仍在试图确定什么样的更改允许这样做。是否可以对角色执行类似的操作:仅当角色存在时才“包括”角色?我尝试使用pre_tast检查主文件中是否存在角色,保存一个变量,然后在角色包含中使用该变量,但ansible失败,因为
找不到角色“debian_stock_config”
。谢谢你,这超出了这个问题的范围,你可能想开始你自己的,在你的具体问题上获得更多的关注。尝试这个,我看到了这个:错误with_first_found'不是PlaybookInclude的有效属性我将
include
语句作为任务,而不是playbook级别的任务。它以这种方式作为一项任务工作。但包含的文件仅包含任务。如果您需要包含单独的以主机为目标的剧本,那么您必须在本地统计该文件,然后将该结果作为条件使用。这是Ansible的一个隐藏良好的功能,但非常棒,谢谢!请注意,Ansible的较新版本已切换到使用
lookup
first\u found
过滤器。看,这是一个惊人的方法。谢谢我使用test-d检查目录,后来意识到failed_when标志的值。再次感谢Ansible 2.9.1,我得到
没有名为“exists”的筛选器
您是否尝试使用
is exists
而不是
| exists
?刚才我尝试了您的建议,但无法使其工作。您的意思是使用
local\u action:stat…
,如
 - set_fact: optional_file="/home/user/optional/file.yml"

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