Ansible:使用变量迭代和配对库存项目

Ansible: iterating and pairing inventory items with variables

这与以下 link 问题直接相关,larsks, that I tried, but it does not work: "

的回答

我试图做同样的事情,我测试了重命名 2 个由 Ansible 控制的虚拟机,但是当我尝试 运行 剧本时,我遇到了类似下一个的错误 (ansible-playbook -i hosts test_iterate_win.yml -vvv) ,我会说它实际上是用名字 'System.Object[]' 而不是,例如 wCloud2:

failed: [oldVM2] (item=[u'oldVM2', u'wCloud2']) => {
    "ansible_loop_var": "item", 
    "changed": false, 
    "item": [
        "oldVM2", 
        "wCloud2"
    ], 
    "msg": "Failed to rename computer to 'System.Object[]': Skip computer 'oldVM2' with new name 'System.Object[]' because the new name is not valid. The new computer name entered is not properly formatted. Standard names may contain letters (a-z, A-Z), numbers (0-9), and hyphens (-), but no spaces or periods (.). The name may not consist entirely of digits, and may not be longer than 63 characters.", 
    "old_name": "oldVM2", 
    "reboot_required": false
}

在我的库存文件中:

[windows]
oldVM1 ansible_host=192.168.122.6
oldVM2 ansible_host=192.168.122.139

我的剧本:

---
- hosts: windows
  gather_facts: false
  vars:
    hostnames:
      - wCloud1
      - wCloud2
  tasks:
    - name: change hostname
      win_hostname:
        name: "{{ item }}"
      loop: "{{ groups.windows|zip(hostnames)|list }}"

我做错了什么?

TL;DR;

我想说的是,你是在白白地为自己制造这个超级复杂的东西,其实可以有一个简单的解决方案。

只需在清单中使用 host variables 即可轻松解决您的任务:

[windows]
oldVM1 ansible_host=192.168.122.6 newName=wCloud1
oldVM2 ansible_host=192.168.122.139 newName=wCloud2

那么你的剧本就像:

---
- hosts: windows
  gather_facts: false

  tasks:
    - name: change hostname
      win_hostname:
        name: "{{ newName }}"

现在,我想说,您的尝试失败的原因实际上是由于您对 Ansible 在多个主机上的任务 运行 的一些误解。

也就是说,当 Ansible 在多个主机上有一个任务(或一组任务)要 运行 时,只需要定义一个任务。

根据上述任务,当清单主机实际上是一组主机时,任务将是 host 1 上的 运行,然后是 host 2,...直到 host n,才转到 运行 下一个任务(如果有的话)。

注意: 不过,不要认为这是理所当然的,已经知道 Ansible 不遵循清单中主机定义顺序的问题(参见: https://github.com/ansible/ansible/issues/34861), 所以它最终可能会变成 host 2, host n, host 1.

使用上述清单考虑此剧本:

---
- hosts: windows
  gather_facts: false

  tasks:
    - name: change hostname
      debug:
        msg: '{{ newName }}'

    - name: another task
      debug:
        msg: 'some example'

它的输出将是

$ansible-playbook test.yml

PLAY [windows] *****************************************************************

TASK [change hostname] *********************************************************
ok: [oldVM1] => {
    "msg": "wCloud1"
}
ok: [oldVM2] => {
    "msg": "wCloud2"
}

TASK [another task] ************************************************************
ok: [oldVM1] => {
    "msg": "some example"
}
ok: [oldVM2] => {
    "msg": "some example"
}

PLAY RECAP *********************************************************************
oldVM1                     : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
oldVM2                     : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

你可以清楚地看到第一个任务(已命名,更改主机名)在 Ansible 可以继续执行游戏中的其他任务之前在所有主机上处理。


实际上你的 System.Object[] 错误意味着你试图在 win_hostname 模块的 name 中提供一个对象(即列表),试图将其转换为字符串以某种方式严重失败,因为这是您的 item 变量包含的列表:

[
    "oldVM1",
    "wCloud1"
]