【发布时间】:2018-05-26 17:00:36
【问题描述】:
我的目标是拥有一个灵活的 Ansible 角色,其中可以按此优先顺序(从大到小)提供变量的值:
- 从命令行使用“--extra-vars”
- 来自环境变量
- 来自角色的默认值
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') 插件)的方式上遇到了限制?
【问题讨论】:
标签: ansible environment-variables