Ansible - read inventory hosts and variables to group_vars/all file
Asked Answered
P

7

30

I have a dummy doubt that keeps me stuck for a long time. I have a very banal inventory file with hosts and variables:

[lb]
10.112.84.122

[tomcat]
10.112.84.124

[jboss5]
10.112.84.122

...

[tests:children]
lb
tomcat
jboss5

[default:children]
tests

[tests:vars]
data_base_user=NETWIN-4.3
data_base_password=NETWIN
data_base_encrypted_password=
data_base_host=10.112.69.48
data_base_port=1521
data_base_service=ssdenwdb
data_base_url=jdbc:oracle:thin:@10.112.69.48:1521/ssdenwdb

The problem is that I need to access all these hosts and variables, in the inventory file, from the group_vars/all file.

I've tried the following manners to access the host IP:

{{ lb }}
"{{ hostvars[lb] }}"
"{{ hostvars['lb'] }}"
{{ hostvars[lb] }}

To access a host variable I tried:

"{{ hostvars[tests].['data_base_host'] }}"

All of them are wrong!!! Can anyone help me find out the best practice to access hosts and variables, not from a playbook but from a variables file?

EDIT:

Ok. Let's clarify.

Problem: Use a host declared in the inventory file in a variable file, let's say: group_vars/all.

Example: I have a DB host with IP:10.112.83.37.

Inventory file:

[db]
10.112.83.37

In the group:vars/all file I want to use that IP to build a variable.

group_vars/all file:

data_base_url=jdbc:oracle:thin:@{{ db }}:1521/ssdenwdb

In a template I use the variable built in the group_vars/all file.

Template file:

oracle_url = {{ data_base_url }}

The problem is that the {{ db }} variable in the group_vars/all file is not replaced by the DB host IP. The user can only edit the inventory file.

Police answered 20/2, 2014 at 12:51 Comment(3)
I don't think you can. Variables can be accessed from actions and templates. I suppose you generate some config files from those variables ? So the place to take advantage of them is in templates. Can you elaborate on why you need to "access" them from group_vars.all ?Punjabi
Thanks for your reply. Ok, i want to have a central file where i put all the variables i need. The inventory file only contains the hosts IP, all the rest are in the group_vars.all file. But some of these variables (in the group_vars.all file) contain the IP of some host and that's why i need to access the host' IP in the inventory file.Police
Just to complete the explanation, my goal is to enable any user, that wants to configure the system, to only add the hosts IPs in the inventory file. All the rest, namely all the other variables, are built in the group_vars.all file. Thanks.Police
M
31
- name: host
   debug: msg="{{ item }}" 
   with_items:
    - "{{ groups['tests'] }}"

This piece of code will give the message:

'10.112.84.122'
'10.112.84.124'

as groups['tests'] basically return a list of unique ip addresses ['10.112.84.122','10.112.84.124'] whereas groups['tomcat'][0] returns 10.112.84.124.

Malek answered 8/6, 2014 at 19:24 Comment(2)
we can access each IP address by its index eg: {{ groups['lb'][0] }} get 10.112.84.122 as the result.Playroom
@Playroom You comment should be explicit in the answer.Arcature
T
21

If you want to programmatically access the inventory entries to include them in a task for example. You can refer to it like this:

{{ hostvars.tomcat }}

This returns you a structure with all variables related with that host. If you want just an IP address (or hostname), you can refer to it like this:

{{ hostvars.jboss5.ansible_ssh_host }}

Here is a list of variables which you can refer to: click. Moreover, you can declare a variable and set it with for example result of some step in a playbook.

- name: Change owner and group of some file
  file: path=/tmp/my-file owner=new-owner group=new-group
  register: chown_result

Then if you play this step on tomcat, you can access it from jboss5 like this:

- name: Print out the result of chown
  debug: msg="{{ hostvars.tomcat.chown_result }}"
Tantalite answered 20/8, 2014 at 16:28 Comment(2)
Above didn't work for me. i had to use {{ groups['database'][0] }} to get first IP address of database hosts group.Playroom
In newer ansible versions (2.x IIRC) it's just called ansible_host instead of ansible_ssh_host.Uhland
Q
17

Just in case if the problem is still there, You can refer to ansible inventory through ‘hostvars’, ‘group_names’, and ‘groups’ ansible variables.

Example:

To be able to get ip addresses of all servers within group "mygroup", use the below construction:

- debug: msg="{{ hostvars[item]['ansible_eth0']['ipv4']['address'] }}" 
  with_items:
     - "{{ groups['mygroup'] }}"
Qumran answered 24/4, 2014 at 0:13 Comment(0)
M
3

Considering your previous example:

inventory file:

[db]
10.112.83.37

group_vars/all

data_base_url=jdbc:oracle:thin:@{{ db }}:1521/ssdenwdb

template file:

oracle_url = {{ data_base_url }}

You might want to replace your group_vars/all with

data_base_url="jdbc:oracle:thin:@{{ groups['db'][0] }}:1521/ssdenwdb"
Magdalen answered 27/9, 2016 at 11:6 Comment(0)
N
3

Yes the example by nixlike works very well.

Inventory:

[docker-host]
myhost1 user=barbara
myhost2 user=heather

playbook:

---

- hosts: localhost
  connection: local         

     tasks:    
        - name: loop debug inventory hostnames
          debug: 
            msg: "the docker host is {{ item }}"
          with_inventory_hostnames: docker-host
        - name: loop debug items
          debug: 
            msg: "the docker host is {{ hostvars[item]['user'] }}"
          with_items: "{{ groups['docker-host'] }}"

output:

ansible-playbook ansible/tests/vars-test-local.yml

PLAY [localhost]


TASK [setup] ******************************************************************* ok: [localhost]

TASK [loop debug inventory hostnames] ****************************************** ok: [localhost] => (item=myhost2) => { "item": "myhost2", "msg": "the docker host is myhost2" } ok: [localhost] => (item=myhost1) => { "item": "myhost1", "msg": "the docker host is myhost1" }

TASK [loop debug items] ******************************************************** ok: [localhost] => (item=myhost1) => { "item": "myhost1", "msg": "the docker host is barbara" } ok: [localhost] => (item=myhost2) => { "item": "myhost2", "msg": "the docker host is heather" }

PLAY RECAP ********************************************************************* localhost : ok=3 changed=0 unreachable=0
failed=0

thanks!

Nide answered 19/1, 2017 at 15:54 Comment(0)
O
0

If you want to refer one host define under /etc/ansible/host in a task or role, the bellow link might help:

https://www.middlewareinventory.com/blog/ansible-get-ip-address/

Otalgia answered 14/9, 2020 at 14:55 Comment(0)
P
-1

If you want to have your vars in files under group_vars, just move them here. Vars can be in the inventory ([group:vars] section) but also (and foremost) in files under group_vars or hosts_vars.

For instance, with your example above, you can move your vars for group tests in the file group_vars/tests :

Inventory file :

[lb]
10.112.84.122

[tomcat]
10.112.84.124

[jboss5]
10.112.84.122

...

[tests:children]
lb
tomcat
jboss5

[default:children]
tests

group_vars/tests file :

data_base_user=NETWIN-4.3
data_base_password=NETWIN
data_base_encrypted_password=
data_base_host=10.112.69.48
data_base_port=1521
data_base_service=ssdenwdb
data_base_url=jdbc:oracle:thin:@10.112.69.48:1521/ssdenwdb
Punjabi answered 20/2, 2014 at 14:30 Comment(8)
Thanks for your reply. The problem with that approach is that i need to edit both files (inventory and group vars) when i want to change, for example, the IP of a host (remember that a have variables in the group vars that contains the IP of a host). One requirement that i have is that a user only has to edit the inventory file (adding the hosts IPs) to reconfigure the system or to install in other environment.Police
Mmhh, okay, but the inventory file showned in your question already solves this, and don't see anything in tests:vars that uses information from above, so I'm having hard time figuring out what problem needs to be solved, sorry :( Could you write what you want in the end (even if it doesn't work), including an inventory file, a group_vars/all file an a small playbook (an action, a template) ?Punjabi
inventory file: [db] 10.112.83.37 group_vars/all data_base_url=jdbc:oracle:thin:@{{ db }}:1521/ssdenwdb playbook: {{ data_base_url }} This is a very basic example but shows the need to use an inventory host in a variable in the group_vars/all.Police
And users can only change inventory, not group_vars, right ?Punjabi
And you will use these variables where ? Template ? Actions ?Punjabi
Mostly in templates but also in actions.Police
I started editing my first answer, but the more I write, the less I understand your problem. I just don't see the issue. You have vars, you just use them in templates. Period. I suggest you rework your question saying explicitely what you want to achieve, showing an small , eventually fake but consistent example of inventory + group_vars/all + template you'd like to have and explaining who can change what. Then I'd be glad to reply. Until then, I just can't. Whatever you want, it is feasible. I've never been stuck with ansible. The problem is really about explaining what you want in the end.Punjabi
I was trying this. But variables not reading from group_vars/tests file...Trinitytrinket

© 2022 - 2024 — McMap. All rights reserved.