我有点惊讶地发现他的代码片段因 IOError 异常而失败,而不是默认省略该值。
#!/usr/bin/env ansible-playbook -i localhost,
---
- hosts: localhost
tasks:
- debug: msg="{{ lookup('ini', 'foo section=DEFAULT file=missing-file.conf') | default(omit) }}"
如何在不引发异常的情况下加载值?
请注意,查找模块支持默认值参数,但这对我来说没有用,因为它仅在可以打开文件时才起作用。
我需要一个即使无法打开文件也能工作的默认值。
据我所知,不幸的是 Jinja2 不支持任何 try/catch 机制。
因此,您要么向 Ansible 团队修补 ini 查找插件/文件问题,要么使用这个丑陋的解决方法:
---
- 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) }}"
在此示例中
first_found
如果文件存在则查找返回文件名,否则返回空列表。如果文件存在,ternary
过滤器调用ini
查找,否则返回omit
占位符。
万一像我这样的人在 2022 年偶然发现这个问题, Ansible 现在支持救援块,类似于编程语言中的 try-catch-finally。
示例可以在官方文档中找到使用块进行错误处理。
您可以按如下方式使用阻止/救援:
- hosts: localhost
tasks:
- block:
- debug: msg="{{ lookup('ini', 'foo section=DEFAULT file=missing-file.conf') }}"
rescue:
- debug: msg="omit"
在使用默认过滤器之前,您还可以使用
from_yaml
过滤器转换输入文件
- name: "load a yaml file or a default value"
set_fact:
myvar: "{{ lookup('file', 'myfile.yml', errors='ignore') | from_yaml | default(mydefaultObject, true) }}"
为避免路径不存在时出现错误,请在尝试查找之前使用条件检查路径:
---
- hosts: localhost
tasks:
- debug: msg="{{ lookup('ini', 'foo section=DEFAULT file=missing-file.conf') }}"
when: missing-file.conf | exists
您也可以将其与
set_fact
一起使用,然后根据需要在使用时省略未定义的 var:
- 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
请注意,查找和 Jinja2 测试 在 控制器 上运行。如果您需要检查主机上的路径,请使用
stat
以及 slurp
或 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
第二个注意点,在 Ansible
v2.5
中,使用路径测试的语法已更改,现在的格式为:
- set_fact:
foo: "{{ lookup('ini', 'foo section=DEFAULT file=missing-file.conf') }}"
when: '"missing-file.conf" is exists'
根据上面的信息,可以将“,errors='ignore'”添加到查找中,然后在其后添加
default
值。
例如在 with_items 的任务中
ansible.posix.authorized_key:
key: "{{ lookup('file', auth_key | default('./files/ssh-key-{{ item }}.pub'), errors='ignore') | default('NO-key-file-for {{ item }} }}')}}"