4

I've got an Ansible role with several tasks that I run for several virtual hosts. My playbook works, and it looks like this:

---

- name: Create vhost configuration
  # action
  with_items: vhosts

- name: Ensure vhost is enabled
  # action  
  notify: restart apache2
  with_items: vhosts

# (Many more actions)

Is there a way to avoid having to write with_items for every action? Can I iterate over the vhost items for the whole playbook rather than running each command for all vhosts sequentially? (as I am with the above code)

2
  • I deleted my answer, because, as you pointed out, it was not applicable. If this code runs on the host system rather than on the virtual machines themselves, I don't know how you can do it without with_items. However, a real example instead of "# action" would have made your question clearer and it might make others think of alternative ways to do what you are trying. Oct 26, 2014 at 19:47
  • I tried to do that with include and with_dict. But unfortunatly thats deprecated. Now I'm searching for a solution, too.
    – Subito
    Feb 23, 2015 at 9:19

2 Answers 2

4

From what you're asking, it sounds like you just want to specify the vhosts group as the hosts to run a specific role on. So your playbook should start something like this:

---
- hosts: vhosts
  name: Tasks run on vhosts
  roles:
    - { role: somerole }

Keep in mind that you can have multiple plays in your playbook, so it's perfectly fine to do something like this:

---
- hosts: all
  name: Run roles for all servers
  roles:
    - { role: role1 }
    - { role: role2 }
    - etc.

- hosts: vhosts
  name: Run roles specific to vhosts
  roles:
    - { role: vhost-role }

- hosts: all
  name: Post-vhost roles for all servers
  roles:
    - { role: role3 }
    - etc.

If you have a single playbook that you want to run on different host groups at different times then you can use a variable for the hosts entry:

---
- hosts: "{{ somevar }}"
  name: Run roles against a user specified set of hosts
  roles:
    - { role: foo }

And then you'd invoke this last one in one of these ways:

$ ansible-playbook playbook.yml --extra-vars "somevar=vhosts"

$ ansible-playbook playbook.yml --extra-vars "somevar=host1,host2"
1

It's nowadays possible to include a role for each item in a list, using include_role in a loop. (Since Ansible 2.5, it is advised to use loop instead of with_items.)

First, create a role which iterates over a sub-role for each item in the vhosts list:

# vhosts/tasks/main.yml

- name: Iterate over all vhosts
  loop: "{{ vhosts }}"
  include_role:
    name: vhost
  vars:
    vhost: "{{ item }}"

For each vhost, the vhost role will be called, with a variable called vhost containing its data.

You can then write a sequence of tasks which operate on this, like so:

# vhost/tasks/main.yml

- name: Create vhost html directory
  file:
    path: "/var/www/vhosts/{{ vhost.domain }}/html"
    state: directory

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .