当从命令行用“-e”覆盖时,Ansible 似乎忽略了有条件的变量

Ansible seems to be ignoring variable in when conditional when it is overridden with "-e" from the command line

我正在编写一个使用 when 条件的 Ansible 剧本,我正在尝试测试将默认值指定为播放变量的场景,然后可以使用以下命令从命令行有选择地覆盖该默认值ansible-playbook 的 -e 参数。但这并没有像我预期的那样工作,而且我没有看到任何明显的原因。

这是设置(这是一个超级精简的示例,只是为了说明这一点,而不是我的真实剧本)。

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  

如果我编辑 playbook 将注定的 var 的值更改为 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

并收到“未命中”消息。我得到的是:

$ 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”。然而“when”条件语句忽略了这一点。

我把命令行改成

也没关系
$ ansible-playbook -e doomed=True conditional_task.yml

在那种情况下,我仍然没有执行任何条件任务。但同样,调试语句显示 doomed 存在并且值为“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 上的全部内容! OS:

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

按预期工作。变量 doomed 的类型是布尔型。然后,只需在条件中使用变量。不需要比较。将跳过调试任务

shell> ansible-playbook pb.yml

PLAY [localhost] ******************************************************************************

TASK [debug] **********************************************************************************
ok: [localhost] => 
  doomed|type_debug: bool

TASK [debug] **********************************************************************************
skipping: [localhost]

当您从命令行传递变量时,情况会发生变化。现在,变量 doomed 的类型是一个字符串。 non-empty 字符串在条件中的计算结果为 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。除此之外,为了简化代码,default改为falsetrue,取决于use-case,而是的明确声明。这样你就可以快速编写代码,并且条件将始终按照你的意愿进行

shell> cat pb.yml
- hosts: localhost
  tasks:
    - debug:
        msg: We are doomed
      when: doomed|d(false)|bool