首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >当环境变量不存在时,如何分配默认的不可失值?

当环境变量不存在时,如何分配默认的不可失值?
EN

Stack Overflow用户
提问于 2017-12-12 22:03:24
回答 1查看 5.6K关注 0票数 3

我的目标是有一个灵活的不可接受的角色,在这个角色中,变量的值可以按照优先级的顺序(从最大到最少)来提供:

  1. 命令行中使用
  2. 从环境变量
  3. 来自角色中的缺省值。

1&3符合Ansible变量(variables.html#variable-precedence-where-should-i-put-a-variable)的优先级顺序,因此我将注意力集中在环境变量上。使用lookup('env',...)插件,我能够在vars/main.yml中读取环境变量,并且优先顺序正是我想要的。

但是,当未定义环境变量时,lookup插件将返回一个空字符串。这意味着变量被分配为空字符串,而不是未定义的字符串,这样就可以分配默认值。

Playbook (var-exp.yml)

代码语言:javascript
运行
复制
- name: Variable experiment
  hosts: all

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

(ansible-role-variable-experiment)角色

任务/main.yml

代码语言:javascript
运行
复制
- name: Display value of 'location'
  debug:
    msg: 'location is {{ location }}'

默认值/main.yml

代码语言:javascript
运行
复制
location: from-defaults-main-yml

vars/main.yml

代码语言:javascript
运行
复制
# 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) }}"

执行示例

使用环境变量:

代码语言:javascript
运行
复制
LOCATION=from-env-variable ansible-playbook ./var-exp.yml

没有环境变量:

代码语言:javascript
运行
复制
ansible-playbook ./var-exp.yml

我还没能找出一种干净的方法来完成我的目标。我已经想出了一种“解决”的方法:

vars/main.yml

代码语言:javascript
运行
复制
default_location: from-default-array-in-vars-main-yml

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

虽然这似乎实现了我想要的,但现在我在"vars“区域而不是在”默认“区域中定义了”缺省值“。

Ansible文档中写着“如果你做的事情看起来太复杂了,很可能是这样的。”

所以,我的问题是:是否有一种更容易/更好/更正确的方法来完成这个任务?或者,我是否在当前实现Ansible 2.4.2 (或lookup('env')插件)的方式上遇到了限制?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-12-12 22:22:26

没有办法使用一个变量名来完成这个任务。

我唯一能想到的解决办法就是使用set_fact

代码语言:javascript
运行
复制
- set_fact:
    location: "{{ lookup('env', 'LOCATION' ) | ternary (lookup('env', 'LOCATION' ), omit) }}"

这样,如果环境变量LOCATION不存在/为空,则任务将不分配值(omit),并且将使用角色的默认值(即不会被重写)。

您可以在调用角色之前将其放在pre_tasks中,也可以在角色tasks/main.yml的顶部运行。

理由:

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

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

Ansible处理变量的“优先级链”(在运行任何任务之前),一旦遇到定义,它就停止了。在计算实际值时,在执行时没有进一步的“回溯”。

备注:

我想出了一种方法来“解决”这个问题: 现在,我在"vars“区域而不是在”默认“区域中定义”缺省值“。

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

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47782280

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档