Ansible Playbook:如何根据条件运行 Play?

Fit*_*uan 7 case-when ansible

我有一本包含多个剧本的剧本。它看起来是这样的:

- 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
Run Code Online (Sandbox Code Playgroud)

每当 playbook 被触发时,它将首先运行第一个 play 以获得 B 或 C 结果。

结果是确定运行该游戏的主机属性,例如主机的IP地址和操作系统。

之后,根据结果,例如如果结果是B,我将运行播放B并跳过播放C。

否则,如果结果是 C,我将跳过 Play B 并运行 Play C。

无论先前 Play 的结果如何,Play D 将作为最后一个 Play 运行。

我怎样才能做到这一点?我尝试过使用“when”条件,但它说它不是 Play 的属性。

Zei*_*tor 7

我想我终于明白了这个问题。我将原来的答案保留在下面,跳过一个角色仍然可以


这就是我基本上理解你想要做的:

  1. 根据一组条件确定您需要使用的主机
  2. 根据上面选择的主机,运行一个戏剧或其他
  3. 最后无条件做一些其他的任务

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

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

我还添加了一个基本检查,以确保我们为这个假主机选择传递的值位于一组预期值之内。默认情况下,剧本使用主机B,但您可以通过传递-e host_we_need=C命令行来更改它。

说得够多了:举个例子吧!为了避免一些警告,让我们创建一个虚拟对象inventory.yml,其中包含我们需要的两个组,但为空:

---
group_B:
group_C:
Run Code Online (Sandbox Code Playgroud)

然后是剧本:

---
- 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
Run Code Online (Sandbox Code Playgroud)

给出(针对每种情况运行的示例)

$ 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   
 
Run Code Online (Sandbox Code Playgroud)

原答案不完全符合要求

您可以将when条件添加到您的角色中。

- name: Play B
  hosts: Host B
  roles:
    - role: my_b_role
      when: my_condition | bool
Run Code Online (Sandbox Code Playgroud)

缺点是您需要将条件添加到游戏中的任何角色或任务中。


Fit*_*uan -1

我已经找到了其他方法来做到这一点。Host B 和 Host C 之间的区别仅在于 IP 地址和操作系统类型。

因此,我在剧本运行时完成必要的任务后编辑清单/主机文件和refresh_inventory,然后在完成最后一个任务之前,我将清单/主机文件编辑回我设置的默认值。

家长剧本:

- 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
Run Code Online (Sandbox Code Playgroud)

库存:

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

Run Code Online (Sandbox Code Playgroud)