Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ansible: playbook calling Role in a directory that is in the roles directory

I would like to shape my directory structure of my ansible roles and playbooks.

Currently I have a directory structure like.

group_vars
    * all 
    * group-one
        - group-vars.yml
        - group-vault.yml
    ...
host_vars
  - server1.yml
plays
    - java_plays
       * deploy_fun_java_stuff.yml
    * deploy_playbook.yml
roles
    - role1 
            - tasks
               * main.yml
            - handlers 
            - (the rest of the needed directories)
    - role2
    - java 
        - java_role1
            - tasks
               * main.yml
            - handlers 
            - (the rest of the needed directories)

I would like to be able to call upon the role java_role1 in the play deploy_fun_java_stuff.yml

I can call

 ---
 - name: deploy fun java stuff
   hosts: java
   roles:
    - { role: role1 }

but I cannot call (I've tried multiple ways). Is this possible?


 - name: deploy fun java stuff
   hosts: java
   roles:
    - { role: java/java_role1 }

What I really want to accomplish is to be able to structure my plays in an orderly fashion along with my roles. I will end up with a large number of both roles and plays I would like to organize them.

I can handle this with a separate ansible.cfg file for each play directory but I cannot add those cfg files to ansible tower (So I'm looking for an alternate solution).

like image 493
Eddie Avatar asked May 20 '16 20:05

Eddie


3 Answers

I think the problem is that you need to set the relative path properly. Ansible first applies the given path relative to the called playbooks directory, then looks in the current working path (from which you are executing the ansible-playbook command) and finally checks in /etc/ansible/roles, so instead of { role: java/java_role1 } in your dir structure you could use { role: ../../roles/java/java_role1 } or { role: roles/java/java_role1 }. Yet another option would be to configure the paths in which ansible is looking for roles. For that you could set the roles_path inside your projects ansible.cfg as described in the Ansible docs.

Based on your example:

Dir tree:

ansible/
├── hosts
│   └── dev
├── plays
│   └── java_plays
│       └── java.yml
└── roles
    ├── java
    │   └── java_role1
    │       └── tasks
    │           └── main.yml
    └── role1
        └── tasks
            └── main.yml

To test it, the play would include java_role1 and role1.

plays/java_plays/java.yml:

---
 - name: deploy java stuff
   hosts: java
   roles:
    - { role: roles/role1 }
    - { role: roles/java/java_role1 }

For testing purposes these roles simply print a debug msg.

role1/tasks/main.yml:

---
- debug: msg="Inside role1"

The dev hosts file simply sets localhost to the java group. Now I can use the playbook:

fishi@zeus:~/workspace/ansible$ ansible-playbook -i hosts/dev plays/java_plays/java.yml

PLAY [deploy java stuff] *******************************************************

TASK [setup] *******************************************************************
ok: [localhost]

TASK [role1 : debug] ***********************************************
ok: [localhost] => {
    "msg": "Inside role1"
}

TASK [java_role1 : debug] *************************************
ok: [localhost] => {
    "msg": "Inside java_role1"
}

PLAY RECAP *********************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0

Now doing the same when you use { role: ../../roles/java/java_role1 } and { role: ../../roles/role1 } your log output inside the TASK brackets would show the whole relative path instead of just the role name:

fishi@zeus:~/workspace/ansible$ ansible-playbook -i hosts/dev plays/java_plays/java.yml

PLAY [deploy java stuff] *******************************************************

TASK [setup] *******************************************************************
ok: [localhost]

TASK [../../roles/role1 : debug] ***********************************************
ok: [localhost] => {
    "msg": "Inside role1"
}

TASK [../../roles/java/java_role1 : debug] *************************************
ok: [localhost] => {
    "msg": "Inside java_role1"
}

PLAY RECAP *********************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0
like image 146
fishi0x01 Avatar answered Oct 08 '22 22:10

fishi0x01


A more elegant solution (imo) is symlinking your roles directory to inside the playbooks directory.

My directory structure is as follows:

inventory/
playbooks/
  |-> roles -> ../roles
  |-> group_vars -> ../group_vars
  |-> host_vars -> ../host_vars
roles/
group_vars/
host_vars/

In my case, I created the symlink by running ln -s ../roles playbooks/roles

like image 32
Rystraum Avatar answered Oct 08 '22 22:10

Rystraum


Another option and one that I use is to create an ansible.cfg file in your playbook directory and place the following in it:

[defaults]

roles_path = /etc/ansible/roles: :

or in your case:

[defaults]

roles_path = /etc/ansible/roles:/etc/ansible/roles/java

Then don't use any relative paths.

like image 30
prankin Avatar answered Oct 08 '22 21:10

prankin