# How do I keep role vars from leaking out?

**URL:** <https://forum.ansible.com/t/how-do-i-keep-role-vars-from-leaking-out/15582>\
**Category:** Ansible Project\
**Created:** [July 1, 2014, 10:17am UTC](https://forum.ansible.com/t/how-do-i-keep-role-vars-from-leaking-out/15582 "2014-07-01T10:17:41Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![John\_Anderson](https://avatars.discourse-cdn.com/v4/letter/j/e68b1a/32.png) [@John\_Anderson](https://forum.ansible.com/u/John_Anderson)\
**Post date:** [July 1, 2014, 10:17am UTC](https://forum.ansible.com/t/how-do-i-keep-role-vars-from-leaking-out/15582/1 "2014-07-01T10:17:41Z")

</div>

I have the following structure:

roles/pythonapp/  
roles/billingsvc/  
roles/usersvc/

pythonapp is a generic set of instructions like cloning and installing a python package, billingsvc and usersvc both include it in their tasks.

I have a variable that I set in billingsvc/vars/main.yml and I don’t want usersvc to see this var but as soon as billingsvc finishes it runs usersvc and the var is there.

Is there anyway to prevent this leaking of information? I’ve defined the var in the role vars section specifically to keep it isolated from everything else.

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan1](https://avatars.discourse-cdn.com/v4/letter/m/5e9695/32.png) [@Michael\_DeHaan1](https://forum.ansible.com/u/Michael_DeHaan1)\
**Post date:** [July 1, 2014, 2:52pm UTC](https://forum.ansible.com/t/how-do-i-keep-role-vars-from-leaking-out/15582/2 "2014-07-01T14:52:54Z")

</div>

It doesn’t leak information in any way that is a problem, but rather the variable is still in scope.

Variables from roles are available in other roles, but always guaranteed to be used WITHIN that role.

Thus if you set in one role X, “a: 42”

and another role Y, “a: 44”

ansible is so written that role X always gets 42 and tasks in role Y always get 44.

They won’t clobber one another.

Having one role being able to define variables for another is however important, for instance, a role might define presensce in a particular datacenter and define a server address used in other roles.

---

<div class="post-metadata">

**Author:** ![John\_Anderson](https://avatars.discourse-cdn.com/v4/letter/j/e68b1a/32.png) [@John\_Anderson](https://forum.ansible.com/u/John_Anderson)\
**Post date:** [July 1, 2014, 4:07pm UTC](https://forum.ansible.com/t/how-do-i-keep-role-vars-from-leaking-out/15582/3 "2014-07-01T16:07:23Z")

</div>

I understand having the ability to set a variable at a more global scope is important but I think by default it should not.

So with my minor example, the pythonapp is generic configuration and one of the checks it does is "when: use\_req\_text is defined" and each role can decide if it should use a requirements.txt to install.

My problem now is that only half of my 40 projects use requirements.txt but since Ansible is leaking the information it tries to use requirements.txt for all of them.

Is my only option to have to explicitly set this var in every role and accept the fact that forgetting to do so will have bad consequences?

---

<div class="post-metadata">

**Author:** ![John\_Anderson](https://avatars.discourse-cdn.com/v4/letter/j/e68b1a/32.png) [@John\_Anderson](https://forum.ansible.com/u/John_Anderson)\
**Post date:** [July 1, 2014, 4:52pm UTC](https://forum.ansible.com/t/how-do-i-keep-role-vars-from-leaking-out/15582/4 "2014-07-01T16:52:06Z")

</div>

Maybe if I discuss what I’m trying to do there will be a better solution so that variable scope doesn’t matter.

I have an SOA architecture (40 python web services) and want each one defined as their own role because they can be deployed on their own nodes or on shared nodes.

So my tree structure looks like this:

[http://paste.ofcode.org/aWr2A77wxXezkanhWHm5nC](http://paste.ofcode.org/aWr2A77wxXezkanhWHm5nC)

For every role I have a line in my group\_vars/all file that defines metadata about the role like what nginx port they use, if they use requirements.txt, etc. This looks like this:

$ cat group\_vars/all.yml

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan1](https://avatars.discourse-cdn.com/v4/letter/m/5e9695/32.png) [@Michael\_DeHaan1](https://forum.ansible.com/u/Michael_DeHaan1)\
**Post date:** [July 1, 2014, 6:39pm UTC](https://forum.ansible.com/t/how-do-i-keep-role-vars-from-leaking-out/15582/5 "2014-07-01T18:39:13Z")

</div>

“I understand having the ability to set a variable at a more global scope is important but I think by default it should not.”

Opinion noted, though we’re not going to be changing things.

Sounds like your roles should use variables like rolename\_varname if you want to build things this way.

---

<div class="post-metadata">

**Author:** ![John\_Anderson](https://avatars.discourse-cdn.com/v4/letter/j/e68b1a/32.png) [@John\_Anderson](https://forum.ansible.com/u/John_Anderson)\
**Post date:** [July 1, 2014, 7:27pm UTC](https://forum.ansible.com/t/how-do-i-keep-role-vars-from-leaking-out/15582/6 "2014-07-01T19:27:11Z")

</div>

The problem with doing \_var is that you can no longer have generic configuration. Here is what I currently have:

# roles/nginx/tasks/main.yml

- name: setup the nginx conf  
sudo: true  
action: template src=nginx.jinja2 dest=/etc/nginx/sites-enabled/{{ role }}.conf  
notify: restart nginx  
when: deploy\_env is not defined  
tags:
- nginx

# roles/nginx/templates/nginx.jinja2

{% set application = role %}

upstream {{ application }}\_pool {  
server 127.0.0.1:{{ services[role].port }};  
}

server {  
listen {{ services[role].nginx\_port }} default;  
server\_name\_in\_redirect off;  
port\_in\_redirect off;  
access\_log /var/log/sm/{{ application }}.access.log sm;

location / {  
proxy\_set\_header host $host;  
real\_ip\_header X-True-Origin;  
proxy\_pass http://{{ application }}\_pool;  
}  
}

# roles/app1/tasks/main.yml

- include: ../../../roles/nginx/tasks/main.yml

# roles/app2/tasks/main.yml

- include: ../../../roles/nginx/tasks/main.yml

and so lets say I want to deploy app1 and app2 each to 3 of their own nodes and 1 shared node that they are both on. I could make this happen by creates roles//vars/main.yml that look like this:

# roles/app1/vars/main.yml

nginx\_port: 6005  
port: 8500

# roles/app2/vars/main.yml

nginx\_port: 6014  
port: 8765

but now when I want to configure my load balancers I have no access to those vars to be able to get what nginx\_port I need to proxy to for each role. So exposing the variables globally for the load balancer works:

# group\_vars/all

services:  
app1:  
port: 8500

nginx\_port: 6005

app2:  
port: 8765

nginx\_port: 6014

but now the app roles don’t have access to it because they don’t know what role they are. So then if you mix both approaches, keep that previous group\_vars/all and change the app vars to look like this:

# roles/app1/vars/main.yml

role: app1

# roles/app2/vars/main.yml

role: app2

Now everything will just work, unless you create “app3” and forget to set the role: app3 in it, because you wont be alerted that you forgot to set the var, it’ll just happily take whatever the previous app that was configured  
said it was and use it.

That is where I am at today, I had this all working and then added app3 and the load balancer was sending all traffic to app3 and there wasn’t a clear reason _why_ the app3 loadbalancer pool thought it should route to app2.

So this is what I’m trying to solve.

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan1](https://avatars.discourse-cdn.com/v4/letter/m/5e9695/32.png) [@Michael\_DeHaan1](https://forum.ansible.com/u/Michael_DeHaan1)\
**Post date:** [July 1, 2014, 7:31pm UTC](https://forum.ansible.com/t/how-do-i-keep-role-vars-from-leaking-out/15582/7 "2014-07-01T19:31:01Z")

</div>

“The problem with doing \_var is that you can no longer have generic configuration. Here is what I currently have:”

I don’t believe this is a problem, and think some of your complexity comes with how you are modelling things.

If you define a role, a role can take parameterized variables as inputs, for instance, which will override any defaults the role sets.

---

<div class="post-metadata">

**Author:** ![drybjed](https://avatars.discourse-cdn.com/v4/letter/d/48db29/32.png) [@drybjed](https://forum.ansible.com/u/drybjed)\
**Post date:** [July 1, 2014, 7:38pm UTC](https://forum.ansible.com/t/how-do-i-keep-role-vars-from-leaking-out/15582/8 "2014-07-01T19:38:08Z")

</div>

John, I think you might be interested in role dependency variables - these are variables which you can pass to role that your current role has as a dependency. I use this method to configure general roles like nginx from app roles like GitLab or ownCloud. Nginx role expects a list of hashes which it then uses to generate /etc/nginx/sites-available/\*.conf files from templates - one hash per template. This way, in GitLab or ownCloud I can have separate configuration for each application and nginx role (when it’s called as a dependency from other roles) knows what configuration to generate.

Maciej

---

<div class="post-metadata">

**Author:** ![John\_Anderson](https://avatars.discourse-cdn.com/v4/letter/j/e68b1a/32.png) [@John\_Anderson](https://forum.ansible.com/u/John_Anderson)\
**Post date:** [July 1, 2014, 7:45pm UTC](https://forum.ansible.com/t/how-do-i-keep-role-vars-from-leaking-out/15582/9 "2014-07-01T19:45:50Z")

</div>

Yeah, that is why I’m trying to explain my needs as well as how I’ve currently modeled so people with more experience can suggest better ways to solve the problem.

I tried to use the the parameterized variables as inputs as well but that also leaks. For example if you do:

# app1

- include: nginx port=8500

# app2

- include: nginx

Now app2 is configured on port 8500, instead of complaining that the port var isn’t defined or using the default 80. You can’t have logic that is when: port is defined,  
because it _is_ defined even though I feel it shouldn’t be.

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan1](https://avatars.discourse-cdn.com/v4/letter/m/5e9695/32.png) [@Michael\_DeHaan1](https://forum.ansible.com/u/Michael_DeHaan1)\
**Post date:** [July 1, 2014, 8:45pm UTC](https://forum.ansible.com/t/how-do-i-keep-role-vars-from-leaking-out/15582/10 "2014-07-01T20:45:37Z")

</div>

Don’t worry about it being a “leak”.

Know that that this variable will be guaranteed to be as passed in within the scope of that roll.

Namespace your variables if you feel the need, etc.
