ansible meta:refresh_inventory 在任务执行中不包括以前不存在的主机

ansible meta: refresh_inventory does not include previously absent hosts in task execution

前段时间,有人建议使用动态清单根据模板中的位置和其他变量生成不同的主机文件,但我遇到了一个相当大的问题:

从模板创建清单后,我需要刷新它(我使用 meta: refresh_inventory 进行刷新)以便 Ansible 在新添加的主机上执行任务,但是,如果主机最初不是在 hosts 文件中,ansible 不会在其上执行任务。另一方面,如果在更改主机文件后新形成的文件中没有主机,那么 Ansible 会像它应该的那样省略主机,所以 refresh_inventory 完成了一半的工作。有什么办法可以解决这个问题吗?

例如我有 1 个任务是从模板生成主机文件,然后刷新清单,然后在所有主机上执行一个简单的任务,比如显示消息:

 tasks:
  - name: Creating inventory template
    local_action:
         module: template
         src: hosts.j2
         dest: "/opt/ansible/inventories/{{location}}/hosts"
         mode: 0777
         force: yes
         backup: yes
    ignore_errors: yes
    run_once: true

  - name: "Refreshing hosts file for {{location}} location"
    meta: refresh_inventory

  - name: Force refresh of host errors
    meta: clear_host_errors

  - name: Show message
    debug: msg="This works for this host"

如果初始主机文件有主机 A、B、C、D,并且新创建的清单有 B、C、D,那么一切都很好:

ok: [B] => {
    "msg": "This works for this host"
}
ok: [C] => {
    "msg": "This works for this host"
}
ok: [D] => {
    "msg": "This works for this host"
}

但是,如果新形成的主机文件包含主机 B、C、D、E(E 不存在于初始主机文件中),那么结果还是:

ok: [B] => {
    "msg": "This works for this host"
}
ok: [C] => {
    "msg": "This works for this host"
}
ok: [D] => {
    "msg": "This works for this host"
}

缺少 E 的任务。现在,如果我重播剧本,只添加另一个主机,比如 F,那么结果如下:

ok: [B] => {
    "msg": "This works for this host"
}
ok: [C] => {
    "msg": "This works for this host"
}
ok: [D] => {
    "msg": "This works for this host"
}
ok: [E] => {
    "msg": "This works for this host"
}

但是没有F,刷新前已经添加到库存文件中了。

那么,有什么想法吗?

引用自Basics

For each play in a playbook, you get to choose which machines in your infrastructure to target ... The hosts line is a list of one or more groups or host patterns ...

例如,可以在第一局中创建库存并在第二局中使用它。下面的剧本

- hosts: localhost
  tasks:
    - template:
        src: hosts.j2
        dest: "{{ playbook_dir }}/hosts"
    - meta: refresh_inventory

- hosts: test
  tasks:
    - debug:
        var: inventory_hostname

使用模板(适合您的需要)

$ cat hosts.j2
[test]
test_01
test_02
test_03

[test:vars]
ansible_connection=ssh
ansible_user=admin
ansible_become=yes
ansible_become_user=root
ansible_become_method=sudo
ansible_python_interpreter=/usr/local/bin/python3.6
ansible_perl_interpreter=/usr/local/bin/perl

给予

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

TASK [Gathering Facts] **********************************************************************
ok: [localhost]

TASK [template] *****************************************************************************
changed: [localhost]

PLAY [test] *********************************************************************************

TASK [Gathering Facts] **********************************************************************
ok: [test_02]
ok: [test_01]
ok: [test_03]

TASK [debug] ********************************************************************************
ok: [test_01] => {
    "inventory_hostname": "test_01"
}
ok: [test_02] => {
    "inventory_hostname": "test_02"
}
ok: [test_03] => {
    "inventory_hostname": "test_03"
}

PLAY RECAP **********************************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0   
test_01                    : ok=2    changed=0    unreachable=0    failed=0   
test_02                    : ok=2    changed=0    unreachable=0    failed=0   
test_03                    : ok=2    changed=0    unreachable=0    failed=0