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.

+4


source to share


3 answers


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 .

+4


source


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

      

0


source


You can also convert your input file with a filter from_yaml

before using the default filter

- name: "load a yaml file or a default value"
  set_fact:
    myvar: "{{ lookup('file', 'myfile.yml', errors='ignore') | from_yaml | default(mydefaultObject, true) }}"

      

0


source







All Articles