Ansible group_vars referencing and loading another var file - ansible

Based on the following Ansible inventory directory tree:
inventories/region
├── staging
│ ├── group_vars
│ │ ├── all.yml
│ │
│ │── hosts.yml
│ └── site1
│ ├── group_vars
│ │ ├── all.yml
│ │
│ ├── hosts.yml
│
├── group_vars
│ └── all.yml
└── prod
├── group_vars
│ ├── all.yml
│── hosts.yml
├── site1
│ ├── group_vars
│ │ ├── all.yml
│── hosts.yml
└──site2
├── group_vars
│ ├── all.yml
│── hosts.yml
Is there a way for me to load vars from inventories/region/group_vars/all.yml and inventories/region/env/group_vars/all.yml inside inventories/region/env/siteX/group_vars/all.yml? I will be calling playbooks with the reference to the site-specific inventory files, such as inventories/region/prod/site2/group_vars/all.yml. I'm trying to avoid maintaining the same variables with the same values across multiple var files (group_vars/all.yml in this example) for each site and environment.
The value of the variables will change for different regions.
Thanks

Related

Ansible not recognising variables not found under host_vars

Ι have the following inventory
[foo]
foosrv ansible_host=11.22.33.44
[bar]
barsrv ansible_host=44.11.22.33
[zoo]
zoosrv ansible_host=21.21.21.21
and the following file structure
.
├── ansible.cfg
├── files
│ └── aws.yaml
├── host_vars
│ ├── foosrv
│ │ ├── templates
│ │ │ └── repoConf.yaml.j2
│ │ └── vault
│ └── barsrv
│ ├── templates
│ │ └── repoConf.yaml.j2
│ └── vault
├── inventory
├── site.yaml
├── templates
│ ├── amend.py.j2
│ └── config.j2
└── vars
├── ansible_vars.yaml
└── vault
My problem is that any variables under ./vars/vault are not recognized by ansible.
Any hints about what might be the issue here?
Ansible doesn't automatically load variables from a vars directory.
You have several options for loading variables:
Ansible will load variables from a file (or directory) in host_vars matching the inventory hostname.
Ansible will load variables from a file (or directory) in group_vars matching the names of groups of which a host is a member.
You can use the include_vars task to explicitly load variables from a file.
If you want to load the variables for all hosts automatically, then place them in group_vars/all.yaml (or a subdirectory of group_vars/all).
Ansible will automatically detect (and decrypt, if you've provided a password) files that are vault encrypted.

Using environment specific group/host_vars and mapping to var subdirectories in Ansible

I'm having issues finding good documentation for how to use environment specific (i.e. dev & test) group_vars and host_vars, then map down to subdirectories that are specific to large chunks of infrastructure (the wso2 directories).
Ideally, I should be able to say somewhere in my inventory or playbook dev or test and it should just route to dev or test then specify wso2 and have it look there.
.
├── group_vars
│ ├── dev
│ │ └── wso2
│ │ ├── apim-analytics.yml
│ │ ├── apim-is-as-km.yml
│ │ └── apim.yml
│ └── test
│ └── wso2
│ ├── apim-analytics.yml
│ ├── apim-is-as-km.yml
│ └── apim.yml
├── host_vars
│ ├── dev
│ │ └── wso2
│ │ ├── apim-analytics-dashboard_1.yml
│ │ ├── apim-analytics-worker_1.yml
│ │ ├── apim-gateway_1.yml
│ │ ├── apim-is-as-km_1.yml
│ │ ├── apim-km_1.yml
│ │ ├── apim-publisher_1.yml
│ │ ├── apim-store_1.yml
│ │ ├── apim-tm_1.yml
│ │ ├── wso2-apim-01.yml
│ │ └── wso2-apim-02.yml
│ └── test
│ └── wso2
│ ├── apim-analytics-dashboard_1.yml
│ ├── apim-analytics-worker_1.yml
│ ├── apim-gateway_1.yml
│ ├── apim-is-as-km_1.yml
│ ├── apim-km_1.yml
│ ├── apim-publisher_1.yml
│ ├── apim-store_1.yml
│ ├── apim-tm_1.yml
│ ├── wso2-apim-01.yml
│ └── wso2-apim-02.yml
There is great documentation about all other subjects around ansible... just not this, so any help is appreciated.
Thanks all :)

Ansible ask for password to ansible vault from other group vars

I have problem with ansible.
I have couple of group_vars folders and in this folders there is files encrypted by ansible-vault with difference passwords between prod and test:
├── group_vars
│   ├── app1_prod
│   │   ├── application.yml <- Ancryptes by Ansible Vault prod pass
│   │   └── service.yml
│   ├── app1_test
│   │   ├── application.yml <- Ancryptes by Ansible Vault test pass
│   │   └── service.yml
│   ├── app2_prod
│   │   ├── application.yml <- Ancryptes by Ansible Vault prod pass
│   │   └── service.yml
│   └── app2_test
│   ├── application.yml <- Ancryptes by Ansible Vault test pass
│   └── service.yml
And my inventory file looks like:
[test_hosts]
test_host1
test_host2
[prod_hosts]
prod_host1
prod_host2
[app1_test:children]
test_hosts
[app2_test:children]
test_hosts
[app1_prod:children]
prod_hosts
[app2_prod:children]
prod_hosts
When I running playbook command:
ansible-playbook app1_playbook.yml -i ./inventory/hosts -l app1_test -u ssh_user -k --vault-password-file path_to_vault_key
I get error that saying the vault password is wrong for file and pointing for file in prod and from other group:
Decryption failed on ansible/group_vars/app1_prod/application.yml
I don't know how to fix this.
Personally, I think your inventory structure is a Bad Idea. I do not condone having PROD and TEST servers in the same inventory, and I see no good reason for it.
I would restructure your system like this:
├── prod
│ ├── ansible.cfg
│ ├── group_vars
│ │ ├── app1
│ │ │ ├── application.yml <- Ancryptes by Ansible Vault prod pass
│ │ │ └── service.yml
│ │ ├── app2
│ │ │ ├── application.yml <- Ancryptes by Ansible Vault prod pass
│ │ │ └── service.yml
├── test
│ ├── ansible.cfg
│ ├── group_vars
│ │ ├── app1
│ │ │ ├── application.yml <- Ancryptes by Ansible Vault prod pass
│ │ │ └── service.yml
│ │ ├── app2
│ │ │ ├── application.yml <- Ancryptes by Ansible Vault prod pass
│ │ │ └── service.yml
And, of course, there would be two host files:
PROD:
[hosts]
prod_host1
prod_host2
[app1:children]
hosts
[app2:children]
hosts
TEST:
[hosts]
test_host1
test_host2
[app1:children]
hosts
[app2:children]
hosts
Have an ansible.cfg file in each inventory directory with the lines:
inventory = .
vault_password_file = /path/to/vault_password_file
remote_user = ssh_user
ask_pass = True
(Best if you just copy /etc/ansible/ansible.cfg to the inventory directory and change what you need to change.)
Once you have that setup, you go into the prod or test directory, and execute the playbook from there. Of course, you will need to specify the path to the playbooks:
cd prod
ansible-playbook /path/to/playbooks/app_playbook.yml
cd test
ansible-playbook /path/to/playbooks/app_playbook.yml
Trust me, life is much easier with inventory separation.
Good luck!

ansible: how to share varibles between roles

I need to permform few task on same hosts but wanted to group the tasks into the different roles which need to share some output to each other. Consider below example
│── hosts
├── playbooks
│ ├── Playbook1.yml
│
├── roles
│ └── role1
│ ├── files
│ │ └── project1.conf
│ ├── handlers
│ │ └── main.yml
│ ├── meta
│ │ └── main.yml
│ ├── tasks
│ │ └── main.yml [Creates variable role1_a, role1_b]
│ ├── templates
│ └── vars
│ └── main.yml
│ └── role2
│ ├── handlers
│ │ └── main.yml
│ ├── meta
│ │ └── main.yml
│ ├── tasks
│ │ └── main.yml [uses variable from role1 role1_a and creates variable role2_c]
│ ├── templates
│ └── vars
│ └── main.yml
│ └── role3
│ ├── handlers
│ │ └── main.yml
│ ├── meta
│ │ └── main.yml
│ ├── tasks
│ │ └── main.yml [uses variable from role1 role1_b and role2 role2_c]
│ ├── templates
│ └── vars
│ └── main.yml
│
Is there any way to collect output of role1 and pass it to role2 and role3 like
- hosts: localhost
roles:
- role: role1_a, role1_b = {role1}
- role: role2_c = {role2 role1_a: role1_a, role1_b: role1_b}
- role: {role2 role1_b: role1_b role2_c: role2_c}
or anyother mechanism to share the variable between the roles ?
What about including tasks in role1 to store the value of role1_a and role1_b into the variable definition of role2 and role3, by combining local_action with lineinfile
- name: Copy value of role1_a to var definition of role2
local_action:
module: lineinfile
path: ~/ansible/roles/role2/vars/main.yml
regexp: '^role1_a'
line: "role1_a: {{ role1_a }}"
- name: Copy value of role1_b to var definition of role3
local_action:
module: lineinfile
dest: ~/ansible/roles/role3/vars/main.yml
regexp: '^role1_b'
line: "role1_b: {{ role1_b }}"

How do you specify environment specific inventory files?

I have a folder structure like so:
.
├── ansible.cfg
├── etc
│   ├── dev
│   │   ├── common
│   │   │   ├── graphite.yml
│   │   │   ├── mongo.yml
│   │   │   ├── mysql.yml
│   │   │   └── rs4.yml
│   │   ├── inventory
│   │   └── products
│   │   ├── a.yml
│   │   ├── b.yml
│   │   └── c.yml
│   └── prod
│   ├── common
│   │   ├── graphite.yml
│   │   ├── mongo.yml
│   │   ├── redis.yml
│   │   └── rs4.yml
│   ├── inventory
│   └── products
│   ├── a.yml
│   ├── b.yml
│   └── c.yml
├── globals.yml
├── startup.yml
├── roles
| └── [...]
└── requirements.txt
And in my ansible.cfg, I would like to do something like: hostfile=./etc/{{ env }}/inventory, but this doesn't work. Is there a way I can go about specifying environment specific inventory files in Ansible?
I assume common and products are variable files.
As #Deepali Mittal already mentioned your inventory should look like inventory/{{ env }}.
In inventory/prod you would define a group prod and in inventory/dev you would define a group dev:
[prod]
host1
host2
hostN
This enables you to define group vars for prod and dev. For this simply create a folder group_vars/prod and place your vars files inside.
Re-ordered your structure would look like this:
.
├── ansible.cfg
├── inventory
│ ├── dev
│ └── prod
├── group_vars
│ ├── dev
│ │ ├── common
│ │ │ ├── graphite.yml
│ │ │ ├── mongo.yml
│ │ │ ├── mysql.yml
│ │ │ └── rs4.yml
│ │ └── products
│ │ ├── a.yml
│ │ ├── b.yml
│ │ └── c.yml
│ └── prod
│ ├── common
│ │ ├── graphite.yml
│ │ ├── mongo.yml
│ │ ├── mysql.yml
│ │ └── rs4.yml
│ └── products
│ ├── a.yml
│ ├── b.yml
│ └── c.yml
├── globals.yml
├── startup.yml
├── roles
| └── [...]
└── requirements.txt
I'm not sure what globals.yml is. If it is a playbook, it is in the correct location. If it is a variable file with global definitions it should be saved as group_vars/all.yml and automatically would be loaded for all hosts.
Now you call ansible-playbook with the correct inventory file:
ansible-playbook -i inventory/prod startup.yml
I don't think it's possible to evaluate the environment inside the ansible.cfg like you asked.
I think instead of {{ env }}/inventory, /inventory/{{ env }} should work. Also if you can please share how you use it right now and the error you get when you change the configuration to envs one

Resources