选择主机以根据多个条件执行任务

时间:2020-08-28 18:58:34

标签: ansible

使用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中摆弄,这有些相关,但无济于事。

1 个答案:

答案 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