Reputation: 2420
In my system provisioning with Ansible, I don't want to specify become=yes
in every task, so I created the following ansible.cfg in the project main directory, and Ansible automatically runs everything as root:
[privilege_escalation]
become = True
But as the project kept growing, some new roles should not be run as root. I would like to know if it is possible to have some instruction inside the role that all tasks whithin that role should be run as root (eg. something in vars/), instead of the global ansible.cfg solution above!
Upvotes: 59
Views: 67083
Reputation: 640
You can use a block to become_root on a series of import_tasks to separate file(s) in the role.
roles/my_fav_role/main.yml:
---
name: block to perform tasks defined below as root
become: true
block:
- import_tasks: task_file1.yml
- import_tasks: task_file2.yml
roles/my_fav_role/task_file1.yml:
---
- name: example task
debug:
msg: "yay"
See Also:
Upvotes: 0
Reputation: 1006
This is also possible using the include_task module
Create a main.yaml
which includes the yaml with the tasks
---
- name: main
include_tasks:
file: "my_tasks_that_needs_become_true.yaml"
apply:
become: true
Upvotes: 3
Reputation: 12751
You can also wrap your tasks in a block and put become: yes
on the block. So, inside your roles/role_name/tasks/main.yml
, you'd do this:
- block:
- name: Tasks go here as normal
...
become: yes
This will run all the tasks inside the block as root. More details of Ansible's blocks here (latest docs).
Upvotes: 60
Reputation: 485
Not really a fundamentally different answer, rather a cosmetic reformatting of what's already been said. Looks the shortest, cleanest and YAML-ishest to me:
- name: My play
hosts: myhosts
roles:
- role: role1
become: yes
- role: role2
Role1 will be run as root while role2 won't.
Upvotes: 18
Reputation: 41
In Ansible documentation for 2.4, you can find a way to define connection variables, such as ansible_become
and ansible_user
. They are defined as usual variables. Below is a snippet.
The first role prepare_user
connects to hosts
using user root without elevation rights. The second role register
connects to hosts
using the remote_user
set via ansible.cfg
(looked for in a defined order; search for "in the following order").
---
- hosts: all
name: Prepare VMs for cluster
roles:
- role: prepare_user
vars:
- ansible_become: false
- ansible_user: root
- role: register
...
Upvotes: 4
Reputation: 2420
I have found a solution, although I think a better solution should be implemented by the Ansible team. Rename main.yml to tasks.yml, and then write the following to main.yml:
---
- { include: tasks.yml, become: yes }
Another solution is to pass the parameter directly in site.yml, but the main idea of the question was reusing the role in other projects without forgetting it needs root:
---
- hosts: localhost
roles:
- { role: name, become: yes }
Upvotes: 94
Reputation: 3137
There is a way to do what you are asking, but you need to be careful with how you use it, because Ansible evaluates most vars before running any tasks. If you use this trick, you must be sure to use it consistently or you could unintentionally use become
where you don't want to.
Under the hood, Ansible uses the variable ansible_become
to determine whether to use become for that task. Within your role, you can create a defaults/main.yml
and set ansible_become: [true/false]
This will cause that entire role to accept that value, unless overwritten by a higher-precedence definition (important to understand variable precedence)
The critical "gotcha" here is that if you use a role where this is defined, it will affect all other roles called below it in the play, unless they also have it defined.
Examples:
role_default_become_true
has ansible_become: true
defined as true in defaults
role_default_become_false
has ansible_become: false
defined as true in defaults
role_no_default
has no default ansible_become
value
---
- name: test1
hosts: localhost
connection: local
roles:
- role_default_become_true
- role_default_become_false
- role_no_default
- name: test2
hosts: localhost
connection: local
roles:
- role_default_become_false
- role_default_become_true
- role_no_default
- name: test3
hosts: localhost
connection: local
roles:
- role_default_become_false
- role_default_become_true
- { role: role_no_default, become: false }
In test1, role_no_default
will run without become, because the previous role defined it as false, and it does not have its own definition.
In test2, role_no_default
will run with become, because the previous role defined it as true, and it does not have its own definition.
In test3, role_no_default
will run without become, because it has its own definition.
Upvotes: 3