Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 303
Jason Cowley Avatar asked Jun 26 '15 14:06

Jason Cowley


1 Answers

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.
like image 94
Gui-Don Avatar answered Sep 28 '22 06:09

Gui-Don