Kęstutis
Kęstutis

Reputation: 1061

How to specify ansible pretasks for a role?

How should one go about defining a pretask for role dependencies. I currently have an apache role that has a user variable so in my own role in <role>/meta/main.yml I do something like:

---
dependencies:
  - { role: apache, user: proxy }

The problem at this point is that I still don't have the user I specify and when the role tries to start apache server under a non existent user, I get an error.

I tried creating a task in <role>/tasks/main.yml like:

---
- user: name=proxy

But the user gets created only after running the apache task in dependencies (which is to be expected). So, is there a way to create a task that would create a user before running roles in dependencies?

Upvotes: 67

Views: 114448

Answers (6)

kimamula
kimamula

Reputation: 12601

As of Ansible 2.2, you can use include_role. https://docs.ansible.com/ansible/include_role_module.html

- user: name=proxy

- include_role:
    name: apache
  vars:
    user: proxy

Upvotes: 13

Chu-Siang Lai
Chu-Siang Lai

Reputation: 2728

I use the pre_tasks to do some tasks before roles, thanks for Kashyap.

#!/usr/bin/env ansible-playbook

---
- hosts: all
  become: true
  pre_tasks:
    - name: start tasks and sent notifiaction to HipChat
      hipchat:
        color: purple
        token: "{{ hipchat_token }}"
        room: "{{ hipchat_room }}"
        msg: "[Start] Run 'foo/setup.yml' playbook on {{ ansible_nodename }}."

  roles:
    - chusiang.vim-and-vi-mode

  vars:
    ...

  tasks:
    - name: include main task
      include: tasks/main.yml

  post_tasks:
    - name: finish tasks and sent notifiaction to HipChat
      hipchat:
        color: green
        token: "{{ hipchat_token }}"
        room: "{{ hipchat_room }}"
        msg: "[Finish] Run 'foo/setup.yml' playbook on {{ ansible_nodename }}."

# vim:ft=ansible :

Upvotes: 73

J. M. Becker
J. M. Becker

Reputation: 2815

Just had to deal with the problem, the real issue is that the pre-task is very likely somewhat more specific than the role. Doing a post-task is easy, because you would simply make a new role dependant, this is known as a "wrapper role"... or at least that's what they call the idea in chef, for when your trying to extend something.

For a pre-task, you have to modify the hierarchy a bit, using a "wrapper role" and what I call a "sibling role". So the dependency logic would appear as,

  • wrapper role
    • sibling role
    • original role

The wrapper has two dependencies, but make sure to add the "sibling role" first in the dependency list. Since Ansible will go from top to bottom.

Finally, you should place your vars in the wrapper role, so that you could overwrite them from the playbook. You want the variables to follow the hierarchy, as much as possible, and not jump across the siblings.

Upvotes: 8

Javier Palacios
Javier Palacios

Reputation: 400

I have a similar need, and I solved it by defining the variable in the role vars. That is, creating a <role>/vars/main.yml with

---
user: proxy

that should override the user variable defined at apache module, while writing it in your module defaults directory doesn't.

I'm using ansible 1.9, not sure how long this behaviour has been present.

Upvotes: 1

udondan
udondan

Reputation: 59989

You could simply solve this with another dependency either in your unnamed <role> or in the apache role.

Whole content of a new proxy-user role:

---
- user: name=proxy
...

Then in roles/apache/meta/main.yml add a dependency to it.

---
dependencies:
  - proxy-user
...

Or set it in roles/<role>/meta/main.yml:

---
dependencies:
  - proxy-user
  - { role: apache, user: proxy }
...

Upvotes: 12

Kashyap
Kashyap

Reputation: 17441

Short answer: I don't think the language allows specifying pre_tasks for roles.

You could cheat/work-around by moving creation of user to a separate playbook and includeing the playbook instead of role. Something like this:

my_fake_role_playbooks/user_and_apache.yml:

- hosts: "{{p_hosts}}"
  pre_tasks:
    user: name=proxy
  roles: [ apache ]

actual_playbook.yml:

- include: my_fake_role_playbooks/user_and_apache.yml p_hosts=[host1, host2]

* code is untested.

HTH

Upvotes: 11

Related Questions