How can I override the default on unsuccessful search?
I was a little surprised to find that his code snippet failed with an IOError instead of dropping the value by default.
#!/usr/bin/env ansible-playbook -i localhost,
---
- hosts: localhost
tasks:
- debug: msg="{{ lookup('ini', 'foo section=DEFAULT file=missing-file.conf') | default(omit) }}"
How do I load a value without raising an exception?
Note that the search module supports a default value parameter, but this one is useless to me because it only works when it can open the file.
I need a default that works even when it doesn't open.
source to share
As far as I know, Jinja2 unfortunately does not support try / catch mechanism.
So you either fix the popup file / file in the Ansible file or use this ugly workaround:
---
- hosts: localhost
gather_facts: no
tasks:
- debug: msg="{{ lookup('first_found', dict(files=['test-ini.conf'], skip=true)) | ternary(lookup('ini', 'foo section=DEFAULT file=test-ini.conf'), omit) }}"
This example first_found
searches for the name of the returned file if the file exists, or an empty list otherwise. If the file exists, the filter ternary
invokes a search ini
, otherwise a omit
placeholder is returned .
source to share
To avoid the error when the path does not exist, use a condition to check the path before trying to search:
---
- hosts: localhost
tasks:
- debug: msg="{{ lookup('ini', 'foo section=DEFAULT file=missing-file.conf') }}"
when: missing-file.conf | exists
You can also use this with set_fact
and then omit the undefined var when using:
- hosts: localhost
tasks:
- set_fact:
foo: "{{ lookup('ini', 'foo section=DEFAULT file=missing-file.conf') }}"
when: missing-file.conf | exists
- debug:
var: foo # undefined
msg: "{{ foo | default(omit) }}" # omitted
Please note that Jinja2 lookups and tests are done on the controller. If you need to check the path on the host, use modules stat
and slurp
or fetch
:
- stat:
file: missing-remote-file-with-text-i-want
register: file
- slurp:
src: missing-remote-file-with-text-i-want
register: slurp
when: file.stat.exists
- set_fact:
foo: "{{ slurp.content | b64decode }}"
when: file.stat.exists
- fetch:
src: missing-file.conf
dest: /tmp/fetched
fail_on_missing: False
- set_fact:
bar: "{{ lookup('ini', 'foo section=DEFAULT file=/tmp/fetched/' + inventory_hostname + '/missing-file.conf') }}"
when: ('/tmp/fetched/' + inventory_hostname + '/missing-file.conf') | exists
Second note: in Ansible, the v2.5
grammar for using path tests has been changed, the format is now:
- set_fact:
foo: "{{ lookup('ini', 'foo section=DEFAULT file=missing-file.conf') }}"
when: missing-file.conf is exists
source to share