Ansible include task only if file exists

2019-03-23 03:18发布

I'm trying to include a file only if it exists. This allows for custom "tasks/roles" between existing "tasks/roles" if needed by the user of my role. I found this:

- include: ...
  when: condition

But the Ansible docs state that:

"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

So

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

Will fail if the file being included doesn't exist. I guess there might be another mechanism for allowing a user to add tasks to an existing recipe. I can't let the user to add a role after mine, because they wouldn't have control of the order: their role will be executed after mine.

标签: ansible
8条回答
Rolldiameter
2楼-- · 2019-03-23 03:51

The with_first_found conditional can accomplish this without a stat or local_action. This conditional will go through a list of local files and execute the task with item set to the path of the first file that exists. Including skip: true on the with_first_found options will prevent it from failing if the file does not exist.

Example:

- hosts: localhost
  connection: local
  gather_facts: false

  tasks:
    - include: "{{ item }}"
      with_first_found:
        - files:
            - /home/user/optional/file.yml
          skip: true
查看更多
啃猪蹄的小仙女
3楼-- · 2019-03-23 03:55

If I am not wrong, you want to continue the playbook even the when statement false?

If so, please add this line after when:

ignore_errors: True

So your tasks will be look like this:

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

Please let me know, if I understand your question correctly, or can help further. Thanks

查看更多
The star\"
4楼-- · 2019-03-23 03:57

Thanks all for your help! I'm aswering my own question after finally trying all responses and my own question's code back in today's Ansible: ansible 2.0.1.0

My original code seems to work now, except the optional file I was looking was in my local machine, so I had to run stat through local_action and set become: no for that particular tasks, so ansible wouldn't attempt to do sudo in my local machine and error with: "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
查看更多
倾城 Initia
5楼-- · 2019-03-23 03:57

The best option I have come up with so far is this:

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

It's not exactly an "if-exists", but it gives users of your role the same result. Create a few variables within your role and a default empty file. The Jinja filters "default" and "lookup" take care of falling back on the empty file in case the variable was not set.

For convenience, a user could use the {{ playbook_dir }} variable for setting the paths:

hook_variable: "{{ playbook_dir }}/hooks/tasks-file.yml" 
查看更多
\"骚年 ilove
6楼-- · 2019-03-23 04:02

I using something similar but for the file module and what did the trick for me is to check for the variable definition, try something like:

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

the task will run only when the variable exists.

查看更多
forever°为你锁心
7楼-- · 2019-03-23 04:03

Using ansible-2.1.0, I'm able to use snippets like this in my playbook:

- 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

I get no errors/failures when local.yml does not exist, and the playbook is executed (as a playbook, meaning it starts with the hosts: line, etc.)

You can do the same at the task level instead with similar code. Using stat appears to work correctly.

查看更多
登录 后发表回答