Ansible. 任务重复执行

Ansible. 任务重复执行

简单的剧本:

- hosts: all
  vars:
    ulogin: login
    upasswd: passwd
    user_login_with_password:
      - user_login: "{{ ulogin }}"
        user_passwd: "{{ upasswd }}"
  tasks:
    - debug: msg="{{ item.user_login }} -- {{ item.user_passwd }}"
      when: item.user_passwd != None
      loop: "{{ user_login_with_password }}"
      loop_control:
        label: "{{ item.user_login }}"

结果:

TASK [debug] *****************************************************************************************
ok: [host1] => (item=login) => {
    "msg": "login -- passwd"
}

一切安好!


我们删除密码:

- hosts: all
  vars:
    ulogin: login
    upasswd: 
    user_login_with_password:
      - user_login: "{{ ulogin }}"
        user_passwd: "{{ upasswd }}"
  tasks:
    - debug: msg="{{ item.user_login }} -- {{ item.user_passwd }}"
      when: item.user_passwd != None
      loop: "{{ user_login_with_password }}"
      loop_control:
        label: "{{ item.user_login }}"

结果:

TASK [debug] *****************************************************************************************
skipping: [host1] => (item=login) 
skipping: [host1]

为什么会出现双重“跳过”动作???

PS 详细输出:

skipping: [host1] => (item=login)  => {
    "ansible_loop_var": "item",
    "item": {
        "user_login": "login",
        "user_passwd": null
    }
}
skipping: [host1] => {
    "msg": "All items skipped"
}

答案1

这不是双重操作。最后一条消息表示循环中的所有项目都被跳过。例如,给定包含更多项目的简化列表

    user:
      - passwd: 
      - passwd: 
      - passwd:

调试任务

    - debug:
        var: item.passwd
      loop: "{{ user }}"
      when: item.passwd != None
      register: out

给出

skipping: [host1] => (item={'passwd': None}) 
skipping: [host1] => (item={'passwd': None}) 
skipping: [host1] => (item={'passwd': None}) 
skipping: [host1]

或更详细 (-v)

skipping: [host1] => (item={'passwd': None})  => 
  ansible_loop_var: item
  false_condition: item.passwd != None
  item:
    passwd: null
skipping: [host1] => (item={'passwd': None})  => 
  ansible_loop_var: item
  false_condition: item.passwd != None
  item:
    passwd: null
skipping: [host1] => (item={'passwd': None})  => 
  ansible_loop_var: item
  false_condition: item.passwd != None
  item:
    passwd: null
skipping: [host1] => 
  msg: All items skipped

您看到最后一条消息msg: All items skipped是因为开发人员决定报告此事

     if res['skipped']:
         res['msg'] = 'All items skipped'

查看注册的变量

  out:
    changed: false
    msg: All items skipped
    results:
    - ansible_loop_var: item
      changed: false
      false_condition: item.passwd != None
      item:
        passwd: null
      skip_reason: Conditional result was False
      skipped: true
    - ansible_loop_var: item
      changed: false
      false_condition: item.passwd != None
      item:
        passwd: null
      skip_reason: Conditional result was False
      skipped: true
    - ansible_loop_var: item
      changed: false
      false_condition: item.passwd != None
      item:
        passwd: null
      skip_reason: Conditional result was False
      skipped: true
    skipped: true

的值out.skipped真的因为所有项目都被跳过了。否则,该值将是错误的最后一个skipping: [host1]将会丢失。例如,

     user:
      - passwd: a
      - passwd: b
      - passwd:

给出

ok: [host1] => (item={'passwd': 'a'}) => 
  ansible_loop_var: item
  item:
    passwd: a
  item.passwd: a
ok: [host1] => (item={'passwd': 'b'}) => 
  ansible_loop_var: item
  item:
    passwd: b
  item.passwd: b
skipping: [host1] => (item={'passwd': None})

您可以避免这种复杂性。最佳做法是选择列表中的项目,而不是在每次迭代时测试条件。例如,

    - debug:
        var: item.passwd
      loop: "{{ user | selectattr('passwd') }}"
      register: out

在这种情况下,所有密码如果为无,您将看到简单的报告

skipping: [host1]

和注册变量

  out:
    changed: false
    results: []
    skipped: true
    skipped_reason: No items in the list

答案2

如果使用 ssh-keys 列表,可以这样做:

- hosts: all
  gather_facts: false
  vars:
    ulogin1: login1
    usshkeys1: [sshkey1]
    ulogin2: login2
    usshkeys2: []
    ulogin3: login3
    usshkeys3:
      - sshkey31
      - sshkey32
      - sshkey33
    user_login_with_sshkeys:
      - user_login: "{{ ulogin1 }}"
        ssh_keys: "{{ usshkeys1 }}"
      - user_login: "{{ ulogin2 }}"
        ssh_keys: "{{ usshkeys2 }}"
      - user_login: "{{ ulogin3 }}"
        ssh_keys: "{{ usshkeys3 }}"
  tasks:
    - debug: msg="{{ item.0.user_login }} -- {{ item.1 }}"
      loop: "{{ user_login_with_sshkeys | ansible.builtin.subelements('ssh_keys') }}"
      loop_control:
        label: "{{ item.0.user_login }}"

结果:

ok: [host1] => (item=login1) => {
    "msg": "login1 -- sshkey1"
}
ok: [host1] => (item=login3) => {
    "msg": "login3 -- sshkey31"
}
ok: [host1] => (item=login3) => {
    "msg": "login3 -- sshkey32"
}
ok: [astra175] => (item=login3) => {
    "msg": "login3 -- sshkey33"
}

留下一个空变量:

- hosts: all
  gather_facts: false
  vars:
    ulogin1: login1
    usshkeys1: [sshkey1]
    ulogin2: login2
    usshkeys2: []
    ulogin3: login3
    usshkeys3:
      - sshkey31
      - sshkey32
      - sshkey33
    user_login_with_sshkeys:
#      - user_login: "{{ ulogin1 }}"
#        ssh_keys: "{{ usshkeys1 }}"
      - user_login: "{{ ulogin2 }}"
        ssh_keys: "{{ usshkeys2 }}"
#      - user_login: "{{ ulogin3 }}"
#        ssh_keys: "{{ usshkeys3 }}"
  tasks:
    - debug: msg="{{ item.0.user_login }} -- {{ item.1 }}"
      loop: "{{ user_login_with_sshkeys | ansible.builtin.subelements('ssh_keys') }}"
      loop_control:
        label: "{{ item.0.user_login }}"

结果:

skipping: [host1]

相关内容