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"
]
这与以下 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"
]