80

Is it possible to reuse a role in a role? I do not mean via defining a dependency in the meta/main.yml file of a role but by including the role in the tasks/main.yml of another role directly?

For example, I define a couple of basic roles in rolebooks and some more high level roles in roles. I want the high level roles to include some of the basic roles in addition to some specific tasks.

playbooks/

  rolebooks/
    some_role/
      
  roles/
    webtier/
      tasks/
        main.yml

In playbooks/roles/webtier/tasks/main.yml:

    - shell: echo 'hello'
    - { role: rolebooks/some_role }
    - shell: echo 'still busy'

Thanks

ThrowsError
  • 1,169
  • 1
  • 11
  • 43
Michael
  • 8,357
  • 20
  • 58
  • 86

3 Answers3

95

Old question BUT for the record: use Ansible 2.2+ and you're good to go with include_role. Exactly for this very purpose... see documentation here.

Check out import_role as well... see documentation here

brettinternet
  • 546
  • 7
  • 21
masu
  • 1,919
  • 21
  • 25
12

AFAIK, you can't. This is what dependencies are for.

If you want to avoid dependencies (because, for instance, you want 'role X' to run between two tasks), you can do this in the playbook itself if you think the tasks are related :

roles/webtier/tasks/main.yml:

- shell: echo 'hello'
- include: webtier.yml
- shell: echo 'role done'

All in all, it depends on what you're trying to do exactly. But in your example, 'still busy' seems to imply that the rolebooks/some_role is still running, which is not possible (there is no concurrency here).

Obviously, you can also sequence roles in a master playbook (which is probably what you do already) :

- name: Polite foo stuff
  hosts: foo_hosts
  roles:
    - say_hello
    - rolebooks/some_role
    - say_bye

- name: Unpolite foo stuff
  hosts: !foo_hosts
  roles:
    - rolebooks/some_role
slm
  • 15,396
  • 12
  • 109
  • 124
leucos
  • 17,661
  • 1
  • 44
  • 34
6

You can't, but you can do something kind of similar.

For a layout of:

roles/
    ...
    common/tasks/main.yml
    nginx/tasks/main.yml
    ...

In nginx/tasks/main.yml, you can call your common task:

- name: Call the 'common' role to do some general setup
  include: ../../common/tasks/main.yml

Note that because you're not using the typical import structure, you might run into some "weirdness" like role default variables not being accessible unless you included the role in the standard fashion earlier.

  • 2
    As noted, this fails to import role defaults, handlers, etc. which severely limits its usefulness. – augurar Oct 20 '15 at 22:34
  • yep, that note was included for a reason. them's the breaks. playbooks or the `meta/main.yml` are meant to be the unit of structure, even though some of us think roles fill this purpose better. –  Oct 20 '15 at 22:47
  • 2
    This solution does *not* show how to include a role. It shows how to include the main playbook of a role, which is very different. – marcv81 Jan 05 '16 at 08:36
  • 1
    See the comment above yours and the note that I left. For some people, this is still a workable thing. –  Jan 05 '16 at 13:25
  • 1
    thanks! same hack applies to consume files/templates from the the other role - `template: src=../../common/templates/src.template dest=dest.file` – keen Nov 03 '16 at 23:05
  • Regardless of the naysayers I found this extremely useful. Thank you! – TJ Zimmerman Apr 06 '20 at 18:46