使用Ansible v2.9.12
想象一个游戏中有4个主持人,并带有以下变量:
# host1
my_var:
one: true
two: master
# host2
my_var:
one: false
two: master
# host3
my_var:
one: false
two: master
# host4
my_var:
one: false
two: arbiter
我想在具有my_var.two == 'master'
且将my_var.one
设置为false
的单个主机上执行任务。在这种情况下,它将与host2或host3相关。
现在,这行不通:
- shell: echo
when:
- my_var.two == 'master'
- not my_var.one
run_once: true
因为Ansible仅在组中的第一台主机上执行任务,这很可能与host1有关,所以这是不希望的。我还在the answer described in my previous question中摆弄,这有些相关,但无济于事。
答案 0 :(得分:3)
在剧本中,没有什么可以阻止您扮演多个角色:
- hosts: all
gather_facts: no
tasks:
- debug:
msg: "{{ my_var }}"
- hosts: host2
gather_facts: no
tasks:
- debug:
msg: "{{ my_var }}"
# ^--- Off course, now the when become superfluous,
# since we target a host that we know have those conditions
- hosts: all
gather_facts: no
tasks:
- debug:
msg: "Keep on going with all hosts"
请回顾一下:
PLAY [all] **********************************************************************************************************
TASK [debug] ********************************************************************************************************
ok: [host1] => {
"msg": {
"one": true,
"two": "master"
}
}
ok: [host2] => {
"msg": {
"one": false,
"two": "master"
}
}
ok: [host3] => {
"msg": {
"one": false,
"two": "master"
}
}
ok: [host4] => {
"msg": {
"one": false,
"two": "arbiter"
}
}
PLAY [host2] ********************************************************************************************************
TASK [debug] ********************************************************************************************************
ok: [host2] => {
"msg": {
"one": false,
"two": "master"
}
}
PLAY [all] **********************************************************************************************************
TASK [debug] ********************************************************************************************************
ok: [host1] => {
"msg": "Keep on going with all hosts"
}
ok: [host2] => {
"msg": "Keep on going with all hosts"
}
ok: [host3] => {
"msg": "Keep on going with all hosts"
}
ok: [host4] => {
"msg": "Keep on going with all hosts"
}
PLAY RECAP **********************************************************************************************************
host1 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host2 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host3 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host4 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
或者,对于更动态的解决方案,您可以选择正确的主机,通过魔术变量hostvars
在主机变量中循环,然后使用delegate_to
将任务委托给该主机。 / p>
给出剧本:
- hosts: all
gather_facts: no
tasks:
- set_fact:
host_master_not_one: "{{ item }}"
when:
- host_master_not_one is not defined
- not hostvars[item].my_var.one
- "'master' == hostvars[item].my_var.two"
run_once: true
loop: "{{ ansible_play_hosts }}"
- debug:
msg: "Running only once, on host {{ host_master_not_one }}"
delegate_to: "{{ host_master_not_one }}"
run_once: true
它给出了回顾:
PLAY [all] **********************************************************************************************************
TASK [set_fact] *****************************************************************************************************
skipping: [host1] => (item=host1)
ok: [host1] => (item=host2)
skipping: [host1] => (item=host3)
skipping: [host1] => (item=host4)
TASK [debug] ********************************************************************************************************
ok: [host1 -> host2] => {
"msg": "Running only once, on host host2"
}
PLAY RECAP **********************************************************************************************************
host1 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
此概述的重要部分是[host1 -> host2]
,它指示任务已委派,因此可以在host2
上运行。
或者,即使是同一思路,也可以跳过与上述条件不匹配的主机:
- hosts: all
gather_facts: no
tasks:
- set_fact:
host_master_not_one: "{{ item }}"
when:
- host_master_not_one is not defined
- not hostvars[item].my_var.one
- "'master' == hostvars[item].my_var.two"
run_once: true
loop: "{{ ansible_play_hosts }}"
- debug:
msg: "Running only once, on host {{ host_master_not_one }}"
when: inventory_hostname == host_master_not_one
给出总结:
PLAY [all] **********************************************************************************************************
TASK [set_fact] *****************************************************************************************************
skipping: [host1] => (item=host1)
ok: [host1] => (item=host2)
skipping: [host1] => (item=host3)
skipping: [host1] => (item=host4)
TASK [debug] ********************************************************************************************************
skipping: [host1]
ok: [host2] => {
"msg": "Running only once, on host host2"
}
skipping: [host3]
skipping: [host4]
PLAY RECAP **********************************************************************************************************
host1 : ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
host2 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host3 : ok=0 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
host4 : ok=0 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0