简体   繁体   中英

Issue passing variable to Ansible playbook for hosts: with double quotes

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM