尽管条件为假,Ansible仍尝试插入变量

时间:2019-04-05 19:29:06

标签: ansible

我正在尝试在一个块中执行以下几个任务:

- name: site.yml --> Handle existing' user's public SSH keys

  block:

  - name: site.yml --> Get client's existing public SSH key
    shell: "aws iam list-ssh-public-keys --user-name {{ client_name }}"
    register: rv_keylist

  - name: site.yml --> Conditionally delete client's public SSH key
    shell: "aws iam delete-ssh-public-key --user-name {{ client_name }} --ssh-public-key-id {{ item.SSHPublicKeyId }}"
    loop: "{{ (rv_keylist.stdout | from_json).SSHPublicKeys }}"

  when: rv_client_exists.rc == 0 and renew_client_key == 'True'

尽管when子句的计算结果为false(如下面的输出所示),但是该任务失败了,因为ansible试图对不存在的变量进行插值,当然失败了

TASK [site.yml --> Get client's existing public SSH key] **********************************************************************************************************************************************************
Friday 05 April 2019  22:23:41 +0300 (0:00:01.800)       0:00:08.818 ********** 
skipping: [127.0.0.0] => changed=false 
  skip_reason: Conditional result was False

TASK [site.yml --> Conditionally delete client's public SSH key] **************************************************************************************************************************************************
Friday 05 April 2019  22:23:41 +0300 (0:00:00.063)       0:00:08.882 ********** 
fatal: [127.0.0.0]: FAILED! => 
  msg: 'Unexpected templating type error occurred on ({{ (rv_keylist.stdout | from_json).SSHPublicKeys }}): expected string or buffer'

谁能解决这个问题?

1 个答案:

答案 0 :(得分:1)

问题是由两件事引起的:

  1. block的操作方式是将when条件分别应用于该块中的每个任务(不会导致整个block被跳过)。

  2. when的行为因您的任务是否有循环而有所不同。

对于非循环任务,例如您的“获取客户端现有的公共SSH密钥”任务,when条件确定Ansible是否应跳过任务

对于循环任务,when确定Ansible是否应跳过任务的特定迭代。换句话说,loop命令仍在评估中,这就是为什么您遇到此特定错误的原因。

您可以这样解决:

- name: site.yml --> Handle existing' user's public SSH keys
  when: rv_client_exists.rc == 0 and renew_client_key == 'True'
  block:

    - name: site.yml --> Get client's existing public SSH key
      shell: "aws iam list-ssh-public-keys --user-name {{ client_name }}"
      register: rv_keylist

    - name: site.yml --> Conditionally delete client's public SSH key
      shell: "aws iam delete-ssh-public-key --user-name {{ client_name }} --ssh-public-key-id {{ item.SSHPublicKeyId }}"
      loop: "{{ ((rv_keylist.stdout|default('{}'))|from_json).SSHPublicKeys|default([]) }}"

这在几个地方使用了default过滤器,以确保loop语句始终具有有效数据。如果rv_keylist.stdout不可用,则整个表达式将计算为空列表。