I'm trying to write a playbook that kicks off role playbooks and pass a list of hosts to it. The "master" playbook has some load balancing logic in it that I don't want to repeat in every role playbook and can't put into site.yml.
inventory.yml
[webservers]
Web1
Web2
Web3
Web4
master.yml
---
- name: Split Inventory into Odd/Even
hosts: all
gather_facts: false
tasks:
- name: Set Group Odd
set_fact:
group_type: "odd"
when: (inventory_hostname.split(".")[0])[-1] | int is odd
- name: Set Group Even
set_fact:
group_type: "even"
when: (inventory_hostname.split(".")[0])[-1] | int is even
- name: Make new groups "odd" or "even"
group_by:
key: "{{ group_type }}"
- name: Perform Roles on Odd
include: webservers.yml hosts={{ groups['odd'] | join(' ')}}
- name: Perform Roles on Even
include: webservers.yml hosts={{ groups['even'] | join(' ')}}
webservers.yml
- name: Perform Tasks on Webservers
hosts: webservers:&"{{ hosts | replace('\"','')}}"
roles:
- pause
The join(' ') flattens the list of hosts into a string with a space separating each one. When I run the playbook it passes the list of hosts to webservers.yml, however it adds double quotes to the beginning and end, causing webservers.yml to do nothing since no hosts match. I would assume the replace('\\"','') would remove the quotes around the string but doesn't seem to be the case. Here's an example output from webservers.yml:
[WARNING]: Could not match supplied host pattern, ignoring: Web4"
[WARNING]: Could not match supplied host pattern, ignoring: "Web2
Any ideas? Does hosts:
handle filtering differently?
I feel that you use a role and a play in a wrong way. When you do tasks you should not change list of hosts this task or role is been executed upon. Basically, only play (a thing with 'hosts: ..., tasks: ..., roles: ...') can control where to run.
There are few exceptions, fe you can play with delegation and so on. But for your case any attempt to use tasks or roles to control list of the host will only bring misery and hate (toward yourself, toward ansible, etc).
To do it right, just add yet another play in to your playbook (playbook is a list of plays).
Here is your code, slightly modified.
---
- name: Split Inventory into Odd/Even
hosts: all
gather_facts: false
tasks:
- name: Set Group Odd
set_fact:
group_type: "odd"
when: (inventory_hostname.split(".")[0])[-1] | int is odd
- name: Set Group Even
set_fact:
group_type: "even"
when: (inventory_hostname.split(".")[0])[-1] | int is even
- name: Make new groups "odd" or "even"
group_by:
key: "{{ group_type }}"
- name: Doing odd things
hosts: odd
gather_facts: false
tasks:
- name: Perform Roles
include: webservers.yml
- name: Doing even things
hosts: even
gather_facts: false
tasks:
- name: Perform Roles
include: webservers.yml
You can see, I've just assigned a playbook to two groups ('odd' and 'even'). Dynamic groups are preserved between plays in a playbook, and they are no different from any other group in this matter.
PS Do not use 'include', use 'import_tasks' (includes are dangerous in newer versions of ansible, avoid them if you could.).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.