6

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?

techraf
  • 64,883
  • 27
  • 193
  • 198
tvs
  • 737
  • 2
  • 17
  • 33

3 Answers3

10

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.

techraf
  • 64,883
  • 27
  • 193
  • 198
  • Both gile's answer and yours were exactly what I was looking for (I've just accepted gile's answer because he posted it first :) ) Thanks for your help! – tvs Oct 13 '16 at 01:44
  • 1
    @tvs I added another way which might suit your case better. – techraf Oct 13 '16 at 01:54
7

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"] }
Konstantin Suvorov
  • 65,183
  • 9
  • 162
  • 193
  • nice option! can I use in 'production' inventory something like this? `[application] company-prod-server [firewall:children] application ` that way I avoid specifying all the servers twice, right? (it's very important to me because I have several servers in each category) – tvs Oct 13 '16 at 12:46
3
- { role: firewall, tags: ["firewall"], when: MyVar }

See Applying ‘when’ to roles and includes.

Samuel Harmer
  • 4,264
  • 5
  • 33
  • 67
gile
  • 5,580
  • 1
  • 25
  • 31