Jason Cowley
Jason Cowley

Reputation: 103

Cannot get ansible to recognize group variables

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

Upvotes: 5

Views: 16943

Answers (1)

user2746634
user2746634

Reputation:

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.

Upvotes: 4

Related Questions