Merge the roles of two plays into one

I’ve a setup of multiple projects, where each project specified the roles it works with via a playbook like the following:

`

Ansible playbook.

Has to be included in a top level playbook and the hosts variable set.

I don’t know what “stopped working” means, so when you say something doesn’t work, I’d need to see output. I’m also unclear what the value for playbook was and would need to see the file in context, whereas it seems to be an incomplete snippet above, so it’s hard to say what I should suggest.

I also do not understand this part of the equation: “Besides that, the solution isn’t optimal as afterwards I’ve to run some more roles on the same hosts, but if the dependencies of both roles overlap the dependencies get now executed twice.”

It sounds like you are applying the same role to the same hosts in more than one play, in which case they will run twice, basically because they were asked to do so :slight_smile:

I don’t know what “stopped working” means, so when you say something doesn’t work, I’d need to see output.

I posted about that issue over at https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!msg/ansible-project/Fd8HJ2bgTeE/a51DBhXmavgJ - the problem is the variable in the playbook include.

I’m also unclear what the value for playbook was and would need to see the file in context, whereas it seems to be an incomplete snippet above, so it’s hard to say what I should suggest.

The include playbook does not include more than a list of roles I want to apply. The use case is the following:

  • We have multiple projects/apps in our company, where each project requires some different roles as environment. So in additiona to a file with custom variables, I want to be able to define the roles being necessary for the project. Right now we have a simple playbook which only consists of a short list of required roles for that (see first example playbook). Then, this playbook is picked up to provision different machines for the project, e.g. a vagrant box or some staging environment. For that we’ve got different master playbooks (vagrant, staging, …) where it provisions the environment + includes the project specific playbook to take care of project specifics.

For that, having a simple playbook which only consists of a short list of required roles seems a good fit here. Having the roles specified in some sort of variable would be possible as well, but I’d prefer to not have to pre-define the list of possible roles somewhere.

It sounds like you are applying the same role to the same hosts in more than one play, in which case they will run twice, basically because they were asked to do so :slight_smile:

If the project specific playbook contains role A depending on role B and the environment-provision playbook (e.g. staging) contains role C depending on role B, role B will unnecessarily run twice as it runs in two different plays. If I could merge the list of roles into a single play, ansible would detect the shared dependency and run role B only once. That would be optimal then - that’s why I’m asking whether there is a way the roles somehow?

Thanks for your help!

Sorry I’m having trouble processing the above, can you simplify the question?

Let me try:

I’ve got project-specific playbooks like the following. They just specify the roles which the projects need to work with:


# Ansible playbook.
# Has to be included in a top level playbook and the hosts variable set.
---
- hosts: "{{ hosts }}"
roles:
- { role: my.lamp }
- { role: my.solr }
# ...


Then, I’ve got environment specific playbooks which setup the environment and run the project specific playbook, like for vagrant:

`

Do some initial vagrant specific setup.

  • hosts: vagrant
    roles:
  • { role: my.vagrant_guest, tags: vagrant_guest }
  • { role: my.nullmailer, tags: nullmailer }
    #…

Provision vagrant nodes.

  • include: …/path/to/above-playbook.yml hosts=“vagrant”

`

So problem with that is now that shared-dependencies between the two plays are not detected as shared dependencies: If the project specific playbook lamp depends on role PHP and the vagrant playbook contains another role depending on role PHP, role PHP will unnecessarily run twice :-/

I’ve tried to provide only variables including the list of the roles in there - instead of having a simple playbook, but I found no way to merge the roles later in the master playbook (e.g. vagrant). I tried the following (does not work):

`
roles: project_roles +

  • { role: vagrant_guest }

`

Is there any way to avoid that or to achieve the same in a better way? Thinking about it, includes on the role level would be a good way to solve it. Could something like the following work?

`
roles:

  • include: project-roles.yml
  • { role: vagrant_guest }

`

“So problem with that is now that shared-dependencies between the two plays are not detected as shared dependencies: If the project specific playbook lamp depends on role PHP and the vagrant playbook contains another role depending on role PHP, role PHP will unnecessarily run twice :-/”

The metadata of the role can specify “allow_duplicates” or not. If this is set, duplicates pulled in from role dependencies will not run twice.

This is not the case with parameterized roles used with different parameters, of course.

"roles: project_roles +

  • { role: vagrant_guest }
    "

I would strongly caution to not attempt to experiment with syntax not in the documentation, as this doesn’t mean anything and the syntax is not part of YAML either :slight_smile:

“So problem with that is now that shared-dependencies between the two plays are not detected as shared dependencies: If the project specific playbook lamp depends on role PHP and the vagrant playbook contains another role depending on role PHP, role PHP will unnecessarily run twice :-/”

The metadata of the role can specify “allow_duplicates” or not. If this is set, duplicates pulled in from role dependencies will not run twice.

Yes, but allow_duplicates does default to FALSE anyway - so there shouldn’t be any duplicates. But are you saying that the role dependencies should be detected accross multiple plays already?

I did check again, it’s not detected for me although I have no role parameters set. I do specify tags though - might be different tags be the problem for the role running twice? As the tags from the parent-role get passed on to the dependency the role ends up with different tag combinations, obviously.