Ansible 仅在文件存在时包含任务
Ansible include task only if file exists
我试图仅在文件存在的情况下包含该文件。如果我角色的用户需要,这允许在现有 "tasks/roles" 之间自定义 "tasks/roles"。我发现了这个:
- include: ...
when: condition
但是 Ansible 文档指出:
"All the tasks get evaluated, but the conditional is applied to each and every task" - 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
如果被包含的文件不存在,将会失败。我想可能还有另一种机制允许用户向现有食谱添加任务。我不能让用户在我的之后添加角色,因为他们无法控制顺序:他们的角色将在我的之后执行。
如果我没记错的话,即使 when 语句为假,你还想继续剧本吗?
如果是,请在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
如果我正确理解您的问题,或者可以提供进一步帮助,请告诉我。谢谢
到目前为止我想出的最佳选择是:
- include: "{{ hook_variable | default(lookup('pipe', 'pwd') ~ '/hooks/empty.yml') }}"
它不完全是 "if-exists",但它为您角色的用户提供了相同的结果。在您的角色和一个默认的空文件中创建一些变量。 Jinja 过滤器 "default" 和 "lookup" 负责在未设置变量的情况下回退到空文件。
为方便起见,用户可以使用 {{ playbook_dir }}
变量来设置路径:
hook_variable: "{{ playbook_dir }}/hooks/tasks-file.yml"
我可以在这里花时间了解 bash 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
* 添加 failed_when
以避免主机在文件不存在时被排除在进一步的任务之外。
我使用类似的东西,但用于文件模块,对我来说诀窍是检查变量定义,尝试类似的东西:
when: optional_file.stat.exists is defined and optional_file.stat.exists
只有当变量存在时,任务才会运行。
感谢大家的帮助!在今天的 Ansible 中终于尝试了所有回复和我自己的问题代码后,我正在回答我自己的问题:ansible 2.0.1.0
我的原始代码现在似乎可以工作了,除了我正在寻找的可选文件在我的本地机器上,所以我不得不 运行 stat through local_action 并为该特定任务设置 become: no
,因此 ansible 不会尝试在我的本地机器上执行 sudo 并出现错误:"sudo: a password is required\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
with_first_found
条件可以在没有 stat
或 local_action
的情况下完成此操作。此条件将遍历本地文件列表并执行任务,并将 item
设置为第一个存在的文件的路径。
在 with_first_found
选项中包含 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
不存在时,我没有得到 errors/failures,并且执行剧本(作为剧本,意味着它从 hosts:
行开始,等等)
您可以在任务级别执行相同的操作,而不是使用类似的代码。
使用 stat
似乎可以正常工作。
还可以选择为此使用 Jinja2 过滤器:
- set_fact: optional_file="/home/user/optional/file.yml"
- include: ....
when: optional_file|exists
在 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
我试图仅在文件存在的情况下包含该文件。如果我角色的用户需要,这允许在现有 "tasks/roles" 之间自定义 "tasks/roles"。我发现了这个:
- include: ...
when: condition
但是 Ansible 文档指出:
"All the tasks get evaluated, but the conditional is applied to each and every task" - 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
如果被包含的文件不存在,将会失败。我想可能还有另一种机制允许用户向现有食谱添加任务。我不能让用户在我的之后添加角色,因为他们无法控制顺序:他们的角色将在我的之后执行。
如果我没记错的话,即使 when 语句为假,你还想继续剧本吗?
如果是,请在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
如果我正确理解您的问题,或者可以提供进一步帮助,请告诉我。谢谢
到目前为止我想出的最佳选择是:
- include: "{{ hook_variable | default(lookup('pipe', 'pwd') ~ '/hooks/empty.yml') }}"
它不完全是 "if-exists",但它为您角色的用户提供了相同的结果。在您的角色和一个默认的空文件中创建一些变量。 Jinja 过滤器 "default" 和 "lookup" 负责在未设置变量的情况下回退到空文件。
为方便起见,用户可以使用 {{ playbook_dir }}
变量来设置路径:
hook_variable: "{{ playbook_dir }}/hooks/tasks-file.yml"
我可以在这里花时间了解 bash 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
* 添加 failed_when
以避免主机在文件不存在时被排除在进一步的任务之外。
我使用类似的东西,但用于文件模块,对我来说诀窍是检查变量定义,尝试类似的东西:
when: optional_file.stat.exists is defined and optional_file.stat.exists
只有当变量存在时,任务才会运行。
感谢大家的帮助!在今天的 Ansible 中终于尝试了所有回复和我自己的问题代码后,我正在回答我自己的问题:ansible 2.0.1.0
我的原始代码现在似乎可以工作了,除了我正在寻找的可选文件在我的本地机器上,所以我不得不 运行 stat through local_action 并为该特定任务设置 become: no
,因此 ansible 不会尝试在我的本地机器上执行 sudo 并出现错误:"sudo: a password is required\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
with_first_found
条件可以在没有 stat
或 local_action
的情况下完成此操作。此条件将遍历本地文件列表并执行任务,并将 item
设置为第一个存在的文件的路径。
在 with_first_found
选项中包含 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
不存在时,我没有得到 errors/failures,并且执行剧本(作为剧本,意味着它从 hosts:
行开始,等等)
您可以在任务级别执行相同的操作,而不是使用类似的代码。
使用 stat
似乎可以正常工作。
还可以选择为此使用 Jinja2 过滤器:
- set_fact: optional_file="/home/user/optional/file.yml"
- include: ....
when: optional_file|exists
在 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