gpt4 book ai didi

ansible - 当环境变量不存在时,如何分配默认的 Ansible 值?

转载 作者:行者123 更新时间:2023-12-04 16:08:09 28 4
gpt4 key购买 nike

我的目标是拥有一个灵活的 Ansible 角色,其中可以按以下优先顺序(从大到小)提供变量的值:

  1. 从命令行使用“--extra-vars”
  2. 来自环境变量
  3. 来自角色的默认设置

1 和 3 与为 Ansible 变量 ( http://docs.ansible.com/ansible/latest/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable ) 记录的优先顺序相匹配,因此我将注意力集中在环境变量上。使用 lookup('env',...) 插件,我能够读取 vars/main.yml 中的环境变量并且优先顺序完全正确我想要什么。

但是,当未定义环境变量时,lookup 插件返回一个空字符串。这意味着变量被分配了空字符串而不是保持未定义状态,以便可以分配默认值。

剧本(var-exp.yml)

- name: Variable experiment
hosts: all

tasks:
- import_role:
name: ansible-role-variable-experiment

角色(ansible-role-variable-experiment)

tasks/main.yml

- name: Display value of 'location'
debug:
msg: 'location is {{ location }}'

defaults/main.yml

location: from-defaults-main-yml

vars/main.yml

# If used, this will override the value in defaults/main.yml, as expected
# location: from-vars-main-yml

# Since lookup returns '' when the environment variable doesn't exist,
# location gets set to '' instead of being left undefined so that the
# default can be used:
# location: "{{ lookup('env', 'LOCATION' ) }}" # -> location == ''

# When the environment variable does not exist, all of these options generate
# some value assigned to location so that the default cannot be assigned:
# location: "{{ lookup('env', 'LOCATION' ) | default(None, true) }}" # -> location == ''
# location: "{{ lookup('env', 'LOCATION' ) | default(omit, true) }}" # -> location == __omit_place_holder__3e8bdbb6cebc653a758afca99607fcf9ec1f99f4
# location: "{{ lookup('env', 'LOCATION' ) | default('undefined') }}" # -> location == ''
# location: "{{ lookup('env', 'LOCATION' ) | reject('undefined') }}" # -> location == <generator object select_or_reject at 0x10caaef00>

# When the environment variable does not exist, these generate a recursive
# loop that crashes the play:
# location: "{{ lookup('env', 'LOCATION' ) | default(location) }}"
# location: "{{ lookup('env', 'LOCATION' ) | default(location, true) }}"

执行示例

使用环境变量:

LOCATION=from-env-variable ansible-playbook ./var-exp.yml

没有环境变量:

ansible-playbook ./var-exp.yml

我无法找到一种干净的方法来实现我的目标。我已经能够想出一种方法来“解决”这个问题:

vars/main.yml

default_location: from-default-array-in-vars-main-yml

location: "{{ lookup('env', 'LOCATION' ) | default(default_location, true) }}"

虽然这似乎完成了我想要的,但现在我在“vars”区域而不是“defaults”区域中定义“defaults”。

Ansible 文档说“如果你正在做的事情看起来太复杂,它可能是。”

那么,我的问题是: 是否有更简单/更好/正确的方法来完成此任务?或者,我是否遇到了 Ansible 2.4.2(或 lookup('env') 插件)当前实现方式的限制?

最佳答案

没有办法使用单个变量名来做到这一点。

我能想到的唯一解决方法是使用 set_fact:

- set_fact:
location: "{{ lookup('env', 'LOCATION' ) | ternary (lookup('env', 'LOCATION' ), omit) }}"

这样,如果环境变量 LOCATION 不存在/为空,任务将不会分配一个值(省略)并且将使用角色的默认值(即它不会被覆盖)。

您可以在调用角色之前将其放在 pre_tasks 中,或者在角色顶部 tasks/main.yml


理由:

您带来的整个问题是在整个过程中使用单个变量名称,但是:

  • Ansible 中的变量是惰性求值的
  • 一旦您在 vars 部分定义了一个变量,它就优先于 defaults 中定义的变量(即使评估将在稍后进行 - 查找插件与问题)
  • 无法在 Ansible 中取消定义变量

Ansible 处理变量的“优先链”(在运行任何任务之前),一旦遇到定义,它就会停止。在评估实际值时,执行时不会再“返回”。


备注:

 I have been able to come up with a way to "work around" this:

[ ]

now I am defining "defaults" in the "vars" area instead of in "defaults" area.

但你不必这样做。无需将 default_location 变量放入 vars。您可以在 defaults 中定义它(该值在执行时使用)。

关于ansible - 当环境变量不存在时,如何分配默认的 Ansible 值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47782280/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com