Ansible Playbook:如何基于when条件运行Play?

7
我有一个包含多个play的playbook。下面是它的样子:
- name: Play A
  hosts: localhost
  roles:
    - do task to get either B or C

- name: Play B
  hosts: Host B
  roles:
    - do necessary task

- name: Play C
  hosts: Host C
  roles:
    - do necessary task

- name: Play D
  host: localhost
  roles:
    - create_logs

每当playbook被触发时,它将首先运行第一个play以获取B或C结果。
结果是确定运行play的主机属性的,如主机的IP地址和操作系统。
之后,基于结果,例如如果结果是B,我将运行Play B并跳过Play C。
否则,如果结果是C,我将跳过Play B并运行Play C。
无论前面的Plays结果如何,Play D都将作为最后一个Play运行。
我该怎么做呢? 我已经尝试使用“when”条件,但它说这不是Play的属性。
5个回答

7

我想我终于理解了问题。下面是我的原始答案,如果跳过一个角色仍然可以使用。


这是我基本上理解你要做的事情:

  1. 根据一组条件确定需要使用的主机
  2. 根据上述选择的主机来运行一个或另一个play
  3. 最后无条件执行其他任务

以下是一个非常基本但完全功能的示例,以满足您的要求。我将其简化为最小任务集,使其适合于提问。但是,您可以使用相同的概念添加回您的角色,并注入真实任务以选择目标。

剧本中的关键是使用add_host模块将所需的主机推送到内存库存中的所需组中。对于此示例,任何主机都将使用“local”连接,以便它伪造一个主机,但仍然使用localhost运行。请注意,您可以很好地将几个主机添加到几个组中。

我还添加了一个基本检查,以确保我们通过虚拟主机选择传递的值在预期值的集合内。默认情况下,playbook使用主机B,但是您可以通过在命令行上传递-e host_we_need=C来更改它。

足够的交谈:看示例吧!为了避免一些警告,让我们创建一个包含我们需要的两个组但为空的虚拟inventory.yml

---
group_B:
group_C:

然后是playbook:

---
- name: Determine the hosts we need
  hosts: localhost
  gather_facts: false

  tasks:
    - name: dummy task to fake you choice
      command: "echo {{ host_we_need | default('B') }}"
      register: host_choice

    - name: check condition to go on
      vars:
        allowed_hosts:
          - B
          - C
      assert:
        that:
          - host_choice.stdout in allowed_hosts
        fail_msg:
          - "Found host value is: {{ host_choice.stdout }}"
          - "It should be one of: {{ allowed_hosts | join(', ') }}"

    - name: add the needed host to in-memory inventory
      add_host:
        name: "{{ host_choice.stdout }}"
        groups:
          - "group_{{ host_choice.stdout }}"
        ansible_connection: local  # This is for a fake host for test only.

- name: play tasks for group_B
  hosts: group_B
  gather_facts: false

  tasks:
    - debug:
        msg: This a task for group_B

- name: play tasks for group_C
  hosts: group_C
  gather_facts: false

  tasks:
    - debug:
        msg: This is a task for group_C

- name: whatever leftover tasks on localhost
  hosts: localhost
  gather_facts: false

  tasks:
    - debug:
        msg: leftover localhost tasks

提供(每种情况的示例运行)
$ ansible-playbook -i add inventory.yml playbook.yml

PLAY [Determine the hosts we need] **********************************

TASK [dummy task to fake you choice] ********************************
changed: [localhost]

TASK [check condition to go on] *************************************
ok: [localhost]

TASK [add the needed host to in-memory inventory] *******************
changed: [localhost]

PLAY [play tasks for group_B] ***************************************

TASK [debug] ********************************************************
ok: [B] => {
    "msg": "This a task for group_B"
}

PLAY [play tasks for group_C] ***************************************
skipping: no hosts matched

PLAY [whatever leftover tasks on localhost] *************************

TASK [debug] ********************************************************
ok: [localhost] => {
    "msg": "leftover localhost tasks"
}

PLAY RECAP **********************************************************
B         : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
localhost : ok=4    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 


$ ansible-playbook -i inventory.yml playbook.yml -e host_we_need=C

PLAY [Determine the hosts we need] **********************************

TASK [dummy task to fake you choice] ********************************
changed: [localhost]

TASK [check condition to go on] *************************************
ok: [localhost]

TASK [add the needed host to in-memory inventory] *******************
changed: [localhost]

PLAY [play tasks for group_B] ***************************************
skipping: no hosts matched

PLAY [play tasks for group_C] ***************************************

TASK [debug] ********************************************************
ok: [C] => {
    "msg": "This is a task for group_C"
}

PLAY [whatever leftover tasks on localhost] *************************

TASK [debug] ********************************************************
ok: [localhost] => {
    "msg": "leftover localhost tasks"
}

PLAY RECAP **********************************************************
C         : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
localhost : ok=4    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
 

您可以在您的角色中添加when条件。
- name: Play B
  hosts: Host B
  roles:
    - role: my_b_role
      when: my_condition | bool

缺点是您需要将这个条件添加到您的播放中的任何角色或任务中。

嗨,谢谢你的建议。但我认为我还没有解释清楚Play A所做的任务是确定它将去哪个主机。这意味着,我打算根本不启动不必要的Play。 - Fitri Izuan
@Zeitounator,“when”不是Play的有效属性,你测试过了吗? - Rizwan Javid
@RizwanJavid 你为什么认为我在play中添加了when属性?正如我在第一句话中所述,并且在我的示例中编写的一样,它被添加到play中的角色声明中。是的,以上内容经过测试(并从每天在生产中使用的playbook中复制/调整)。 - Zeitounator
@Zeitounator,你可以跳过角色,但不能跳过这个方法的执行,这就是我的意思。正如问题中所述,如果他按照你的方法执行,那么在此playbook中提到的所有主机,Host A、Host B、Host C、Host D,都将被执行,角色可以被跳过,但plays的执行不能被跳过。而且,在Play A中设置的条件变量如何在Play B中使用,这一解释并没有写明。 - Rizwan Javid
@RizwanJavid可能有点晚了,但看到这个答案,我觉得我看到了光明...然后更新了它。 - Zeitounator
@Zeitounator 迟做总比不做好。干杯,老兄。 - Rizwan Javid

2
你可以将剧本拆分成不同的剧本文件,为Play A添加一个任务,使用include模块有条件地包含Play B或Play C。然后在“include Play B/C”任务之后添加“include play D”任务。

1

0

1 - 您可以添加一个带有分配给ansible_host参数的null主机的播放。 在清单中,您有一个名为xyz的主机,其ansible_host为null

2 - 您可以为每个任务添加条件,因此如果发送一个值,则条件应为true,否则它将使用null值,在这种情况下,条件为false,任务将被跳过。

示例:

---
 - name: NTU CONFIGURATION 
   hosts: NTU
   vars:
     ansible_host: "{{ NTU_IP }}" 
   connection: local
   gather_facts: no
   tasks:

     - name: TASK 1 CREAT VLAN 1000 CONFIGURATION
       ios_config:
         lines: 
           - name cust_inet
         parents:
           - vlan 1000
       when: 
           - NTU == true
 - name: another play
   hosts: CPE
   vars:
     ansible_host: "{{ IP_MGMT }}" 
   connection: local
   gather_facts: no


   tasks:

-1

我已经找到了另一种方法来完成它。主机B和主机C之间的区别仅在于IP地址和操作系统类型。

因此,在playbook运行时,我正在编辑inventory/hosts文件并刷新清单,完成必要任务后,然后在完成最后一个任务之前,将inventory/hosts文件编辑回我设置的默认值。

父playbook:

- name: Play A
  hosts: localhost
  roles:
    - do task to get either B or C
    - edit/replace ip address & host type for the targeted hosts in inventory/hosts file with using when condition
    - refresh_inventory

- name: Play B_C
  hosts: switches_host
  roles:
    - do necessary task

- name: Play D
  host: localhost
  roles:
    - create_logs
    - - edit/replace back to initial value

库存:

switches_host:
      ansible_host: s.s.s.s
      ansible_user: user
      ansible_ssh_pass: pswd
      ansible_network_os: xo.sx


如果您同时有两个并发的playbook更改清单,它将无法正常工作。最好使用add_host模块和内存清单。请参阅https://docs.catalystcloud.nz/tutorials/compute/ansible-create-x-servers-using-in-memory-inventory.html。 - Oliver Gaida

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接