# multi stage and variables

**URL:** <https://forum.ansible.com/t/multi-stage-and-variables/17409>\
**Category:** Ansible Project\
**Tags:** galaxy-ng\
**Created:** [February 1, 2015, 6:42pm UTC](https://forum.ansible.com/t/multi-stage-and-variables/17409 "2015-02-01T18:42:58Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Victor\_Volle](https://avatars.discourse-cdn.com/v4/letter/v/e8c25b/32.png) [@Victor\_Volle](https://forum.ansible.com/u/Victor_Volle)\
**Post date:** [February 1, 2015, 6:42pm UTC](https://forum.ansible.com/t/multi-stage-and-variables/17409/1 "2015-02-01T18:42:58Z")

</div>

Hi!

I tried to read up on everything I could find w.r.t. multi stage environments, but I haven’t found a solution that fits my needs yet.

Let’s say, I have 4 “environments”: dev, test, stage, production  
And 2 “kinds” of servers: web, db

To simplify things, I only have on variable, the size of the “ram”.  
In “dev”, “test” and “stage” the ram for “web” should be 1GB, and 4GB for “prod” (artificial example to show the issue!)  
And in “dev”, “test” and “stage” the ram for “db” should be 2GB, and 8GB for “prod”:

> dev test stage prod
> 
> ±----------+ ±----------+ ±----------+ ±----------+  
> web | (1GB) | | (1GB) | | (1GB) | | (4GB) |  
> ±----------+ ±----------+ ±----------+ ±----------+
> 
> ±----------+ ±----------+ ±----------+ ±----------+  
> db | (2GB) | | (2GB) | | (2GB) | | (8GB) |  
> ±----------+ ±----------+ ±----------+ ±----------+

The roles are centrally defined (say ansible-galaxy), and I cannot use the defaults from the roles.

Possible solutions:

1. I have an inventory for each stage, but then I have to maintain the “ram” variable duplicated everywhere,  
although I have a useful default value for each “kind” of server. I do not know where to put the default “ram” for “web”  
servers or for “db” servers:

> ├── dev/  
> │ ├── group\_vars/  
> │ │ ├── db  
> │ │ └── web  
> │ └── inventory

> …

> └── prod/  
> ├── group\_vars/  
> │ ├── db  
> │ └── web  
> └── inventory

1. I could merge the inventories, like this:

> [db-prod]  
> [web-prod]  
> [db-dev]  
> [web-prod]  
> …
> 
> [db:children]  
> db-prod  
> db-dev  
> …
> 
> [web:children]  
> …
> 
> [prod:children]  
> db-prod  
> web-prod
> 
> [dev:children]  
> …

But the problem is that group precedence is alphabetically, I cannot express that “prod” has precedence over “web”

1. I could use the fact that group-vars in the inventory vars have lower precedence than group\_vars in the file system, so that I define group vars for server “kinds” (db and web) in the inventory file and group vars for environment in the file system. But that feels rather artificial

2. I could use the alphabetical precedence of group names by using by using names like:

10env\_dev 10env\_test 10env\_stage 10env\_prod  
20kind\_db 20kind\_web

but this is quite ugly.

---

<div class="post-metadata">

**Author:** ![Giovanni\_Tirloni](https://avatars.discourse-cdn.com/v4/letter/g/71c47a/32.png) [@Giovanni\_Tirloni](https://forum.ansible.com/u/Giovanni_Tirloni)\
**Post date:** [February 2, 2015, 2:06pm UTC](https://forum.ansible.com/t/multi-stage-and-variables/17409/2 "2015-02-02T14:06:11Z")

</div>

If you can't really change the tasks and must use a single variable  
named 'ram', I would organize it this way:

# inventory file  
[prod-db]  
hostA

[prod-web]  
hostB

[dev-db]  
hostC

# group\_vars/prod-db.yml  
ram: 8

# group\_vars/prod-web.yml  
ram: 4

# group\_vars/dev-db.yml  
ram: 2

Giovanni

---

<div class="post-metadata">

**Author:** ![Victor\_Volle](https://avatars.discourse-cdn.com/v4/letter/v/e8c25b/32.png) [@Victor\_Volle](https://forum.ansible.com/u/Victor_Volle)\
**Post date:** [February 6, 2015, 9:00pm UTC](https://forum.ansible.com/t/multi-stage-and-variables/17409/3 "2015-02-06T21:00:44Z")

</div>

Hi Giovanni!

Thanks for your reply.

Even if I could rename the “ram” variable (the example is totally artificial):

1. 

I would need to add groups like:

> [web:children]  
> prod-web  
> dev-web

> [db:children]

> prod-db

> dev-db

> 

> [prod:children]  
> prod-web
> 
> prod-db

> [dev:children]  
> dev-web  
> dev-db
> 
> >

And group(-vars) preference is alphabetically! I.e. “db” has a higher precedence as “prod”. Ross Tuck (see [1] above)  
has discussed the same solution.

1. 

This still leads to quite some repetition, because I need to set the same value in dev & test & stage (and I might even have multiple dev & test environments). And whenever I need to add a variable, I have to remember to add to all these files.

---

<div class="post-metadata">

**Author:** ![Victor\_Volle](https://avatars.discourse-cdn.com/v4/letter/v/e8c25b/32.png) [@Victor\_Volle](https://forum.ansible.com/u/Victor_Volle)\
**Post date:** [February 7, 2015, 12:15pm UTC](https://forum.ansible.com/t/multi-stage-and-variables/17409/4 "2015-02-07T12:15:37Z")

</div>

So currently all my playbooks will use this (hack):

- include\_vars: “include\_{{ item }}.yml”  
with\_items: group\_names | intersect([‘dev’, ‘prod’, …])

So for “groups” that reference environments, I do not have group\_vars, but explicitly included files.  
For everything else I can use group vars. I still do not like this.

Especially since the documentation does not explicitly defines this precedence:

---

<div class="post-metadata">

**Author:** ![Barry\_Kaplan](https://avatars.discourse-cdn.com/v4/letter/b/48db29/32.png) [@Barry\_Kaplan](https://forum.ansible.com/u/Barry_Kaplan)\
**Post date:** [April 20, 2015, 1:25am UTC](https://forum.ansible.com/t/multi-stage-and-variables/17409/5 "2015-04-20T01:25:23Z")

</div>

I am in the process of converting a large system from Chef to Ansible, and this is pretty much my only blocker. I’ve read dozens of posts/articles where this problem is discussed.

So far the answer from Ansible (DaHaan really) has been “I like it this way so tough it up” or “its too late to change it”. But having general variables override specific variables simply does not make any sense. I have seen no argument from the Ansible team that supports this behavior on its merits.

Ansible’s variable setup is so much cleaner than Chef’s, but this really throws a wrench in the works.

---

<div class="post-metadata">

**Author:** ![Josh\_Smift1](https://avatars.discourse-cdn.com/v4/letter/j/bcef8e/32.png) [@Josh\_Smift1](https://forum.ansible.com/u/Josh_Smift1)\
**Post date:** [April 20, 2015, 11:45am UTC](https://forum.ansible.com/t/multi-stage-and-variables/17409/6 "2015-04-20T11:45:34Z")

</div>

> But having general variables override specific variables simply does  
> not make any sense. I have seen no argument from the Ansible team that  
> supports this behavior on its merits.

Is the issue that general variables override specific variables, or just  
that there isn't a way to express in the Ansibile INI inventory format  
whether "prod" or "web" is more general or more specific?

One thing you could do is write a dynamic inventory script that  
understands your particular precedence requirements.

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-Josh (jbs@care.com)

This email is intended for the person(s) to whom it is addressed and may contain information that is PRIVILEGED or CONFIDENTIAL. Any unauthorized use, distribution, copying, or disclosure by any person other than the addressee(s) is strictly prohibited. If you have received this email in error, please notify the sender immediately by return email and delete the message and any attachments from your system.

---

<div class="post-metadata">

**Author:** ![Mohamed\_Hazem](https://avatars.discourse-cdn.com/v4/letter/m/c5a1d2/32.png) [@Mohamed\_Hazem](https://forum.ansible.com/u/Mohamed_Hazem)\
**Post date:** [September 1, 2015, 10:44am UTC](https://forum.ansible.com/t/multi-stage-and-variables/17409/7 "2015-09-01T10:44:55Z")

</div>

Were you able to reach a proper solution to this problem ? I have the exact same problem that I can’t overcome.

---

<div class="post-metadata">

**Author:** ![Victor\_Volle](https://avatars.discourse-cdn.com/v4/letter/v/e8c25b/32.png) [@Victor\_Volle](https://forum.ansible.com/u/Victor_Volle)\
**Post date:** [September 1, 2015, 12:40pm UTC](https://forum.ansible.com/t/multi-stage-and-variables/17409/8 "2015-09-01T12:40:49Z")

</div>

I am still using the “hack” described above ([https://groups.google.com/d/msg/ansible-project/f4jaB5VZ5Dk/0B-ok7XHVMYJ](https://groups.google.com/d/msg/ansible-project/f4jaB5VZ5Dk/0B-ok7XHVMYJ))

I am waiting for Ansible 2.0 and have created an issue ([https://github.com/ansible/ansible/issues/12156](https://github.com/ansible/ansible/issues/12156))

See also the discussion here: [https://groups.google.com/forum/#!topic/ansible-project/ari8hggAaZk](https://groups.google.com/forum/#!topic/ansible-project/ari8hggAaZk)

---

<div class="post-metadata">

**Author:** ![Mohamed\_Hazem](https://avatars.discourse-cdn.com/v4/letter/m/c5a1d2/32.png) [@Mohamed\_Hazem](https://forum.ansible.com/u/Mohamed_Hazem)\
**Post date:** [September 1, 2015, 12:44pm UTC](https://forum.ansible.com/t/multi-stage-and-variables/17409/9 "2015-09-01T12:44:10Z")

</div>

I see … I’m currently trying to implement something like:

[10staging-webservers]  
webserver1-staging ansible\_ssh\_host=ip

[10staging-dbservers]  
dbserver1-staging ansible\_ssh\_host=ip

[15staging:children]  
10staging-webservers  
10staging-dbservers

[10production-webservers]  
webserver1-production ansible\_ssh\_host=ip

[10production-dbservers]  
dbserver1-production ansible\_ssh\_host=ip

[15production:children]  
10production-webservers  
10production-dbservers

[20webservers:children]  
10production-webservers  
10staging-webservers

[20dbservers:children]  
10production-dbservers  
10staging-dbservers

Not really sure if this will work or not yet.

---

<div class="post-metadata">

**Author:** ![esco\_real](https://avatars.discourse-cdn.com/v4/letter/e/c89c15/32.png) [@esco\_real](https://forum.ansible.com/u/esco_real)\
**Post date:** [September 1, 2015, 9:36pm UTC](https://forum.ansible.com/t/multi-stage-and-variables/17409/10 "2015-09-01T21:36:38Z")

</div>

Maybe not the best way. But for some cases I “misuse” host entries to address this.

So the host entry “web\_prod” in the group “web\_conf” could have the variable ram with “4GB” and in the group\_vars for web\_conf ram would have “1GB”. And to access this: {{ hostvars[tier + ‘\_’ + stage].ram }}.

In my case I do this with a generated inventory to manage app and database users/passwords from KeePass. And to separate this the entries have underscores and are in the “user” group.

esco
