当ansible查找失败时如何回退到默认值?

问题描述 投票:0回答:6

我有点惊讶地发现他的代码片段因 IOError 异常而失败,而不是默认省略该值。

#!/usr/bin/env ansible-playbook -i localhost,
---
- hosts: localhost
  tasks:
    - debug: msg="{{ lookup('ini', 'foo section=DEFAULT file=missing-file.conf') | default(omit) }}"

如何在不引发异常的情况下加载值?

请注意,查找模块支持默认值参数,但这对我来说没有用,因为它仅在可以打开文件时才起作用。

我需要一个即使无法打开文件也能工作的默认值。

ansible jinja2
6个回答
8
投票

据我所知,不幸的是 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
占位符。


4
投票

万一像我这样的人在 2022 年偶然发现这个问题, Ansible 现在支持救援块,类似于编程语言中的 try-catch-finally。

示例可以在官方文档中找到使用块进行错误处理


1
投票

您可以按如下方式使用阻止/救援:

- hosts: localhost
  tasks:
    - block:
        - debug: msg="{{ lookup('ini', 'foo section=DEFAULT file=missing-file.conf') }}"
      rescue:
        - debug: msg="omit"

0
投票

在使用默认过滤器之前,您还可以使用

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) }}"

0
投票

为避免路径不存在时出现错误,请在尝试查找之前使用条件检查路径:

---

- 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'

0
投票

根据上面的信息,可以将“,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 }} }}')}}"
© www.soinside.com 2019 - 2024. All rights reserved.