I'm using Ansible (V2.8) to build two different server environments that happen to support Drupal. They are very similar in terms of the settings for the OS, RDBMS, gluster, memcached, etc. But very different with regards to the use of Drupal (different versions, different number of drupal instances, etc.). Consequently while almost all of the playbooks, var files etc. are common, I have platform-specific playbooks for Drupal.

I have separate inventory files, but a common site.yml file that just contains a bunch of import_playbook: statements.

What I'm struggling with is the best way to choose the correct drupal playbook.

At the moment I'm using the following on the command line: -i /vagrant/inventories/inventory-env1.ini --extra-vars environment_name=env1

Which allows the following statement to work in site.yml - import_playbook: playbooks/drupal/drupal_{{environment_name}}.yml

But that means I'm specifying the environment twice on the same command line, once to choose the inventory file and once to set a variable. As I normally find tautology is evidence of poor programming, it makes me think I'm missing a better way of doing this.

Ideally I'd like to simply specify 'environment_name' in the inventory file. But I can't because it is not available to site.yml for reasons described here: https://github.com/ansible/ansible/issues/33659.

So, am I missing something, or is this just how it is?

  • Why haven't you used groups? – Michael Hampton Sep 16 '19 at 15:59
  • Sorry Michael I don't understand. I am using groups in the inventory file for web servers, database servers, etc. But I don't see how that solves my problem of not specifying the environment twice on the command line. – P Burke Sep 16 '19 at 16:12
  • Sorry, I mean use groups to select the environment. – Michael Hampton Sep 16 '19 at 16:40

If I understand correctly, you have a mostly shared ansible run between two servers, but each need to apply a different drupal playbook.

The best way to target hosts for a particular play is inside the playbook. Though it's logical to think that the import_playbook top level action should be targeted to specific hosts, That's not really the way ansible looks at it. Ansible builds a list of plays that contain tasks and roles (themselves containing takss), each of which targeting one or more hosts or groups, and then runs all the plays from the ansible controller host, ruuning each particular task only on the hosts it targets. Thus, what you want to do here is define separate drupal host groups for each site, and then add both playbooks to the main site, each targeting a specific group.

Here's a simplified example:


- import_playbook: shared.yaml
- import_playbook: drupal_1.yaml
- import_playbook: drupal_2.yaml

shared.yaml has the os setup etc that you refer to, and it needs no change.

drupal_1.yaml looks like this:

 - hosts: drupal_site_1
 - tasks: 
    [ ... set up drupal site 1 ... ]

and drupal_2.yaml looks like this:

 - hosts: drupal_site_2
 - tasks:
 [ ... set up drupal site 2 ... ]

Now we just need to make sure the groups are defined in your inventory, and the hosts that should get the first site are in drupal_site_1, and those that should get the second site are in drupal_site_2. You could even make a server be in both groups to serve both sites ( but of course the playbooks would have to be carefully crafted not to interfere). See https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html for information about how you can group your hosts.

Using host groups keeps the targeting logic out of the plays, so it's the ideal way to target different hosts in different plays. You can limit the play to those individual hosts, or you can have a more global site run that includes all the hosts' settings. Each play still only applies to the hosts / groups it targets.

  • 1
    Hi, thanks I'd not thought of doing it that way;calling both drupal playbooks and using an inventory group to effectively stop one from running. Currently the two inventory files are identical in terms of the group names, just different host names and IP addresses. But adding an extra drupal_site_1 group is not a big deal, and it allows me to drive platform selection just from the inventory file which is what I wanted. – P Burke Sep 17 '19 at 6:35

Well, there are a couple of ways you could solve your problem. First of all, I would recommend you to create two roles and one playbook. In that playbook, you can create two tasks, one for each role, and specify what group of hosts (or, create a regular expression if you've named your hosts in a particular way) you're gonna run that role. If you want to run that playbook just for a particular host, you could call ansible-playbook with the --limit flag.

It's gonna give you a little bit of work at the beginning, but as the infrastructure you manage through Ansible grows, it's gonna be easier to grow and expand your Ansible files in a organized way.

Hope that helps.

  • 1
    I do like the suggestion about creating a role with parameter that differentiate the installations, though sometimes in practice that isn't straight forward. It's usually best to err on the side of creating a role for your logically connected tasks so that you can decouple the tasks from the targeting. – Daniel Farrell Sep 17 '19 at 18:29
  • I don't really know your environment, but that works pretty good for me. I know, you can have some playbook repetition amongst roles (and I'm a by D.R.Y. fan), but once you use git or some other SCM to version your Ansible playbooks, and Ansible tags, it's not that hard to maintain. Actually, I believe it's easier to maintain in a DevOps group. – Stefano Martins Sep 17 '19 at 22:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.