I'm trying to set up environment specific variables in ansible (e.g. production, staging, development). For some reason, ansible is not picking up variables in group_vars/[environment].
I'm using ansible 1.9.1
Here's a stripped down example of what I'm trying to do.
Directory structure:
.
├── group_vars
│ └── staging
├── hosts
│ └── staging
└── site.yml
group_vars/staging:
test_var: "this is a test"
site.yml:
---
- hosts: localhost
tasks:
- debug: msg="test variable = {{ test_var }}"
hosts/staging is an empty file
Output of running ansible-playbook -i hosts/staging site.yml
:
PLAY [localhost] **************************************************************
GATHERING FACTS ***************************************************************
ok: [localhost]
TASK: [debug msg="test variable = {{ test_var }}"] ****************************
fatal: [localhost] => One or more undefined variables: 'test_var' is undefined
FATAL: all hosts have already failed -- aborting
PLAY RECAP ********************************************************************
to retry, use: --limit @/Users/jcowley/site.retry
localhost : ok=1 changed=0 unreachable=1 failed=0
If I move group_vars/staging to group_vars/all, it works as expected and outputs the value of test_var. But I'm trying to understand how I can separate environments per the documentation in Ansible's Best Practices
EDIT:
To answer your question more specifically, please have a look at this github exemple project. This is, I think, what you tried to do.
I might be wrong, but I think the problem comes from your inventory file. You actually named your group_vars
files (staging
) after your inventory filename (staging
too).
But, you must name it after the section inside your inventory file, which is, I suppose, localhost
looking at your playbook.
Thus, this is what you should have:
hosts/staging:
[staging]
X.X.X.X
Here is, according to me, a more viable solution to organize your project. It is based on roles.
Directory structure:
.
├── group_vars
│ └── all
├── hosts
│ └── local
│ └── staging
│ └── prod
├── roles
│ └── exemple
│ └── tasks
│ └── vars
│ └── local.yml
│ └── staging.yml
│ └── prod.yml
└── site.yml
The group_vars/all
could have an env variable:
# The application environment
# Possible values are : prod, staging or local
env: local
# Other global variables
...
Your inventory file:
[local]
X.X.X.X
[staging]
X.X.X.X
[prod]
X.X.X.X
Then, your playbook sites.yml
could look like this:
---
- name: Server(s) configuration
hosts: "{{env}}"
roles:
- exemple
vars_files:
- "roles/example/vars/{{env}}.yml"
Doing it this way gives you multiple benefits:
- you can reuse the env variable anywhere in your project, in jinja templates or as a condition in tasks which is very practical;
- your project is split into separate roles. It’s cleaner this way for big project (you can have an apache role, ssh role, etc.);
- you can create env-specific variables in separate files in
roles/exemple/vars/
directory.