How do I call a role from within another role in Ansible? - ansible

My playbook runs a list of roles:
roles:
- common
- postgres
- nginx
- supervisord
- { role: deploy_app, app_name: myapp }
- { role: deploy_app, app_name: otherapp }
I have another role, celery, that I only want to run when the app named myapp is created using deploy_app. I was thinking I should pass a parameter into the role like this:
- { role: deploy_app, app_name: myapp, celery: yes }
Then within my deploy_app role, I would use a when conditional:
- name: create celery worker for application
<RUN ROLE HERE>
when: '{{ celery }}' == 'yes'
How can I conditionally run a role from within a task list?

I think ansible depenencies would help here. Just create a
/meta/main.yml inside your role with the following:
---
dependencies:
- { role: celery, tags: ["sometag"], when: "celery == 'yes'" }

I would suggest to not call from within a playbook and either use a condition in your entry books
- { role: celery, tags: ["sometag"], when: "celery == 'yes'" }
or simply convert it into a group of tasks in a file and do a conditional import
Hope that helps.

Related

Ansible: execute role only for some hosts

Let's say I have a single playbook with some roles for the installation of an appserver and I like to apply the same playbook on both production and testing servers.
Both production and testing servers have the same list of roles, with the exception of one, that only should be applied on production servers.
Is it possible to specify somehow that this role will only be applied to production servers using the same playbook?
For example, if the playbook is:
---
- hosts: appserver
roles:
- { role: mail, tags: ["mail"] }
- { role: firewall, tags: ["firewall"] }
- { role: webserver, tags: ["webserver"] }
- { role: cache, tags: ["cache"] }
and I have two inventories: one for production and one for testing.
When I run the playbook using the testing inventory, I don't want the role 'firewall' to be executed.
My idea is do something like setting a variable in the 'production' inventory and use something like 'if <var> is set, then execute role 'firewall'' ... I don't know if this is possible, and if it is, how to do it?
You can define a variable, for example production_environment, in your inventory files, assign true or false value and use a when conditional in the playbook:
---
- hosts: appserver
roles:
- { role: mail, tags: ["mail"] }
- { role: firewall, tags: ["firewall"], when: production_environment }
- { role: webserver, tags: ["webserver"] }
- { role: cache, tags: ["cache"] }
Or you can access inventory_file variable directly. For example if you use -i production:
---
- hosts: appserver
roles:
- { role: mail, tags: ["mail"] }
- { role: firewall, tags: ["firewall"], when: inventory_file == "production" }
- { role: webserver, tags: ["webserver"] }
- { role: cache, tags: ["cache"] }
Which way you go is an administrative decision. The second method uses less steps, but requires the inventory file name to be "hardcoded" in the playbook.
Why don't you just use inventory groups?
Make two inventories:
testing:
[application]
my-dev-server
production:
[application]
company-prod-server
[firewall]
company-prod-server
And change your playbook as follows:
---
- hosts: firewall
roles:
- { role: firewall, tags: ["firewall"] }
- hosts: application
roles:
- { role: mail, tags: ["mail"] }
- { role: webserver, tags: ["webserver"] }
- { role: cache, tags: ["cache"] }
- { role: firewall, tags: ["firewall"], when: MyVar }
See Applying ‘when’ to roles and includes.

Is it possible to apply an other tag to a dependency role?

I have a playbook like that, with one role per client.
- hosts: hosting
roles:
- { role: client1, tags: ['client1'] }
- { role: client2, tags: ['client2'] }
And on each role, I have a dependency on nginx for example.
/roles/client1/meta/main.yml
dependencies:
- nginx
I would like to not launch the nginx role when it is not necessary. So I have added the nginx tag to the dependency.
/roles/client1/meta/main.yml
dependencies:
- { role: nginx, tags: ['system'] }
But when I launch the playbook with the tag client1, the nginx role is executed.
Is there a solution to avoid that ?
I know a can "export" the dependency on the playbook, it works good, but it's not a nice solution I think.
- hosts: hosting
roles:
- { role: nginx, tags: ['system'] }
- { role: client1, tags: ['client1'] }
- { role: client2, tags: ['client2'] }
Tags do not override each other but are cummulative. Your dependency now has the tags client1 and system.
But that already is enough. Just tell Ansible to skip the system tag when calling your playbook:
ansible-playbook ... --tags client1 --skip-tags system

variable does not recognized by ansible while calling role with variable

top_level_main.yml
roles:
- { role: deploy_nds }
roles/deploy_nds/vars/main.yml
artifact_url: urlsomething
roles/deploy_nds/meta/main.yml
dependencies:
- {role: download_artifact, url: artifact_url }
roles/download_artifactory/tasks/main.yml
- name: download artifact from jfrog
get_url:
url: "{{ url }}"
dest: /var/tmp
I tried using variable name as "{{ artifact_url }}" but still it does not work as expect. Can someone please help?
I have explicitly included vars file of perticular role in playbook then it worked.
vars_files:
- roles/deploy_nds/vars/main.yml
roles:
- { role: deploy_nds }

Is it possible to import roles into an ansible playbook?

I have a bunch of playbooks where a big percentage of roles are common to all servers. So I'd like to do something like:
---
- hosts: nfs2pre2
sudo: true
gather_facts: no
roles:
- include: initial_setup.yml
- { role: role10, tags: ['role10' ] }
- { role: role11, tags: ['role11' ] }
The initial_setup.yml would be something like:
- { role: role1, tags: ['role1' ] }
- { role: role2, tags: ['role2' ] }
Is it possible?
That's not possible as far as I know, but there is a simple workaround. You can create a role which will only have dependencies on other roles. To follow your example, you can create a role initial_setup, by creating a directory roles/initial_setup and in it create a directory meta with a file main.yml:
# roles/initial_setup/meta/main.yml
---
dependencies:
- { role: 'role1', tags: 'role1' }
- { role: 'role2', tags: 'role2' }
Now you can use initial_setup as any regular role:
- hosts: nfs2pre2
sudo: true
gather_facts: no
roles:
- { role: initial_setup, tags: ['initial_setup' ] }
- { role: role10, tags: ['role10' ] }
- { role: role11, tags: ['role11' ] }

ansible: recursive loop detected in template string

In a playbook, I am using a role this way:
- { role: project, project_name: "{{project_name}}" }
And in the "project" role, I actually have a dependency that wants to use the project_name variable of the "project" role:
---
dependencies:
- {
role: users,
users: [
{
name: "{{project_name}}",
home: "/home/{{project_name}}",
shell: "/bin/bash",
group: "{{project_name}}",
}
]
}
But I get an error:
recursive loop detected in template string: {{project_name}}
Is changing the name of the "project_name" variable the only solution?
Thanks
External variables are inherited into roles automatically, so project_name: "{{ project_name }}" isn't necessary. Change your role declaration to:
- project
... and the {{ project_name }} variable will be available within your role as-is.

Resources