我的目标是有一个灵活的不可接受的角色,在这个角色中,变量的值可以按照优先级的顺序(从最大到最少)来提供:
1&3符合Ansible变量(variables.html#variable-precedence-where-should-i-put-a-variable)的优先级顺序,因此我将注意力集中在环境变量上。使用lookup('env',...)插件,我能够在vars/main.yml中读取环境变量,并且优先顺序正是我想要的。
但是,当未定义环境变量时,lookup插件将返回一个空字符串。这意味着变量被分配为空字符串,而不是未定义的字符串,这样就可以分配默认值。
Playbook (var-exp.yml)
- name: Variable experiment
  hosts: all
  tasks:
  - import_role:
      name: ansible-role-variable-experiment(ansible-role-variable-experiment)角色
任务/main.yml
- name: Display value of 'location'
  debug:
    msg: 'location is {{ location }}'默认值/main.yml
location: from-defaults-main-ymlvars/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“区域而不是在”默认“区域中定义了”缺省值“。
Ansible文档中写着“如果你做的事情看起来太复杂了,很可能是这样的。”
所以,我的问题是:是否有一种更容易/更好/更正确的方法来完成这个任务?或者,我是否在当前实现Ansible 2.4.2 (或lookup('env')插件)的方式上遇到了限制?
发布于 2017-12-12 22:22:26
没有办法使用一个变量名来完成这个任务。
我唯一能想到的解决办法就是使用set_fact。
- set_fact:
    location: "{{ lookup('env', 'LOCATION' ) | ternary (lookup('env', 'LOCATION' ), omit) }}"这样,如果环境变量LOCATION不存在/为空,则任务将不分配值(omit),并且将使用角色的默认值(即不会被重写)。
您可以在调用角色之前将其放在pre_tasks中,也可以在角色tasks/main.yml的顶部运行。
理由:
您带来的整个问题是在整个过程中使用一个变量名,但是:
vars部分中定义了变量,它将优先于在defaults中定义的变量(即使计算将在稍后进行-查找插件与问题无关)。Ansible处理变量的“优先级链”(在运行任何任务之前),一旦遇到定义,它就停止了。在计算实际值时,在执行时没有进一步的“回溯”。
备注:
我想出了一种方法来“解决”这个问题: 现在,我在"vars“区域而不是在”默认“区域中定义”缺省值“。
但你不必这么做。不需要将default_location变量放入vars中。您可以在defaults中定义它(该值在执行时使用)。
https://stackoverflow.com/questions/47782280
复制相似问题