I am trying to write a very flexible playbook that targets hosts based on environment they are in. I am using as many variables as possible, so the playbook can be reused for other projects/environments with minimal changes.
I have a single application.yml
---
- name: Prepare app-server for "The app"
hosts: "{{'env'}}_super_app"
vars:
vars_files:
- "environments/{{env}}.yml"
sudo: yes
tasks:
- command: echo {{env}}
roles:
- common
- nginx
- php5-fpm
- nodejs
- newrelic
- users
- composer
- name: Install and configure mysql for "The super app"
hosts:
- "{{env}}_super_db"
vars:
vars_files:
- "environments/{{env}}.yml"
sudo: yes
roles:
- common
- mysql
- newrelic
Here is the playbook directory structure:
├── environments
│ ├── prod.yml << environment specific vars
│ ├── stag.yml << environment specific vars
│ └── uat.yml << environment specific vars
├── roles
│ ├── common
│ ├── composer
│ ├── mysql
│ ├── newrelic
│ ├── nginx
│ ├── nodejs
│ ├── php5-fpm
│ └── users
├── users
│ └── testo.yml
├── prod << inventory file for production
├── README.md
├── application.yml << application playbook
├── stag << inventory file for staging
├── uat << inventory file for uat
Here are the contents of the uat inventory file:
[uat_super_app]
10.10.10.4
[uat_super_db]
10.10.10.5
When I run my playbook, I pass the environment as an extra variable:
ansible-playbook -K -i uat application.yml -e="env=uat" --check
The idea being: If {{env}} is set to uat, then the environments/uat.yml vars will be used, AND hosts [uat_super_app] will be targeted based on {{env}}_super_app.
If I or anyone makes a mistake and tries to run the uat vars against a production inventory, the hosts will not match, and ansible will not run the playbook.
ansible-playbook -K -i prod application.yml -e="env=uat" --check
This playbook works when I do not use variables in hosts targeting. The problem is that no hosts match either way:
ansible-playbook -K -i uat application.yml -e="env=uat" --check -vvvv
SUDO password:
PLAY [Prepare app-server for "The app"] *******************************
skipping: no hosts matched
PLAY [Install and configure mysql for "The app"] **********************
skipping: no hosts matched
PLAY RECAP ********************************************************************
hosts: "{{'env'}}_super_app"
That looks like you are using the string env
, not the variable, which evaluates to env_super_app
. I think you meant:
hosts: "{{ env }}_super_app"
Thanks udondan, but that didn't work.
The solution was to pass the vars in a similar way that the playbook expects to see them.
If I were specifying the env in the playbook I would have:
---
- name: Prepare app-server for "The app"
hosts: uat_super_app
vars:
- env: uat
So the correct way of passing the variable is:
ansible-playbook -K -i uat application.yml -e='vars: env=uat'
To test this I used the --list-hosts option:
ansible-playbook -K -i uat application.yml -e='vars: env=uat' --list-hosts
playbook: application.yml
play #1 (Prepare app-server for "The super app"): host count=1
10.10.10.4
play #2 (Install and configure mysql for "The super app"): host count=1
10.10.10.5
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With