我正在研究一个使用when条件的Ansible剧本,我试图测试这样的场景,其中有一个默认值指定为一个游戏变量,然后可以使用-e参数从命令行选择性地覆盖到Ansible -playbook。但这并没有像我期望的那样工作,而且我没有看到任何明显的原因。
这里是设置(这是一个超级精简的示例,只是为了说明这一点,而不是我真正的剧本)。
conditional_task.yml
- name: A playbook to conditionally print some debug messages
hosts: localhost
gather_facts: False
vars:
doomed: False
tasks:
- name: print the value of doomed
debug: var=doomed
- name: print the message if we're doomed
debug:
msg: "We're f*****g doomed!"
when: doomed == True
- name: print the message if we're not doomed
debug:
msg: "Glory be to FSM, we are saved!"
when: doomed == False
如果我在ansible-playbook命令下运行这个命令,不带任何参数,我将得到预期的输出。
$ ansible-playbook conditional_task.yml
PLAY [A playbook to conditionally print some debug messages] ************************************************************************************
TASK [print the value of doomed] ****************************************************************************************************************
ok: [localhost] => {
"doomed": true
}
TASK [print the message if we're doomed] ********************************************************************************************************
ok: [localhost] => {
"msg": "We're f*****g doomed!"
}
TASK [print the message if we're not doomed] ****************************************************************************************************
skipping: [localhost]
PLAY RECAP **************************************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
如果我编辑剧本,将注定的变量的值更改为False,并重新运行它,我得到另一条消息。
$ ansible-playbook conditional_task.yml
PLAY [A playbook to conditionally print some debug messages] ************************************************************************************
TASK [print the value of doomed] ****************************************************************************************************************
ok: [localhost] => {
"doomed": false
}
TASK [print the message if we're doomed] ********************************************************************************************************
skipping: [localhost]
TASK [print the message if we're not doomed] ****************************************************************************************************
ok: [localhost] => {
"msg": "Glory be to FSM, we are saved!"
}
PLAY RECAP **************************************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
现在,考虑到所有这些,我希望能够做这样的事情:
$ ansible-playbook -e doomed=False conditional_task.yml
并获取"not doomed"消息。我得到的结果是:
$ ansible-playbook -e doomed=False conditional_task.yml
PLAY [A playbook to conditionally print some debug messages] ************************************************************************************
TASK [print the value of doomed] ****************************************************************************************************************
ok: [localhost] => {
"doomed": false
}
TASK [print the message if we're doomed] ********************************************************************************************************
skipping: [localhost]
TASK [print the message if we're not doomed] ****************************************************************************************************
skipping: [localhost]
PLAY RECAP **************************************************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0
如您所见,在本例中,当条件触发时,和都不存在。就好像这个变量根本不存在,或者有一些意想不到的值,或者别的什么。但是正如调试输出所示,变量是定义的,并且确实具有值&;false&;像预期的那样。然而,"当"条件语句忽略这个
如果我将命令行改为
也没关系$ ansible-playbook -e doomed=True conditional_task.yml
在这种情况下,我仍然没有得到条件任务执行。但是,再一次,调试语句显示了注定是存在的,并且其值为&;true&;
我也试着把我的条件改写为"注定是真的"。而"注定是假的";分别,而不是使用==操作符,这没有任何区别。在这一点上我被困住了。如果有人能解释一下,我将不胜感激。
这是我的Ansible版本信息:
$ ansible-playbook --version
ansible-playbook 2.10.8
config file = /extradrive1/development/experimental/ansible/ansible_experimental/ansible.cfg
configured module search path = ['/home/prhodes/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3/dist-packages/ansible
executable location = /usr/bin/ansible-playbook
python version = 3.9.7 (default, Sep 10 2021, 14:59:43) [GCC 11.2.0]
这都是在Pop上运行的!操作系统:
NAME="Pop!_OS"
VERSION="21.10"
这个问题是由于从命令行传递给Ansible的额外变量的类型总是string. 例如,
下面的剧本shell> cat pb.yml
- hosts: localhost
vars:
doomed: false
tasks:
- debug:
var: doomed|type_debug
- debug:
msg: We are doomed
when: doomed
按预期工作。变量注定的类型是布尔值。然后,只需在条件中使用该变量。不需要比较。调试任务将被跳过
shell> ansible-playbook pb.yml
PLAY [localhost] ******************************************************************************
TASK [debug] **********************************************************************************
ok: [localhost] =>
doomed|type_debug: bool
TASK [debug] **********************************************************************************
skipping: [localhost]
当您从命令行传递变量时,事情将发生变化。现在,变量注定的类型是字符串。非空字符串将在条件中求值为True,并且将执行调试任务
shell> ansible-playbook pb.yml -e doomed=false
PLAY [localhost] ******************************************************************************
TASK [debug] **********************************************************************************
ok: [localhost] =>
doomed|type_debug: str
TASK [debug] **********************************************************************************
ok: [localhost] =>
msg: We are doomed
有一个简单的通用解决方案。总是将这些变量强制转换为bool。除此之外,为了简化代码,默认为false或true,这取决于用例,而不是显式声明。这样可以快速编写代码,并且条件总是按照您的要求执行
shell> cat pb.yml
- hosts: localhost
tasks:
- debug:
msg: We are doomed
when: doomed|d(false)|bool