[HOSTVARS][MERGED] Unexpected behavior with merge variables of different host which are in several groups

Hi Everybody,

I have a problem that I can’t resolve on my own.
I want to deploy an etcd cluster with postgresql on the same servers
I have three servers and this is my inventory file:


all:
children:
etcd_cluster: # recommendation: 3 or 5-7 nodes
hosts:
demo_postgres1:
vars:
etcd_ip: '***'
demo_postgres2:
vars:
etcd_ip: '***'
demo_postgres3:
vars:
etcd_ip: '***'
master:
hosts:
demo_postgres1:
vars:
postgres_ip: '***'
postgresql_exists: 'false'
replica:
hosts:
demo_postgres2:
vars:
postgres_ip: '***'
postgresql_exists: 'false'
demo_postgres3:
vars:
postgres_ip: '***'
postgresql_exists: 'false'
balancers:
hosts:
demo_haproxy1:
vars:
haproxy_ip: '***'
demo_haproxy2:
vars:
haproxy_ip: '***'
demo:
vars:
ansible_ssh_common_args: "-F ../../ssh_config/demo_config"
children:
balancers:
etcd_cluster:
postgres_cluster:
children:
master:
replica:

I have the demo_postgres[0-3] servers that run etcd and postgres. Just to prepare an external instance for etcd cluster, I have separated its in two distinct groups: etcd_cluster and postgres_cluster.
I have etcd_ip vars and postgres_ip vars respectively on these groups.

My problem is when I run my playbook with hosts: etcd_cluster and I print hostvars, I get the hostvars of postgres_cluster:

PLAY [etcd_cluster] ***************************************************************************************************************************************************************************

TASK [Gathering Facts] ************************************************************************************************************************************************************************
ok: [demo_postgres1]
ok: [demo_postgres3]
ok: [demo_postgres2]

TASK [Ansible | List all known variables and facts] *******************************************************************************************************************************************
ok: [demo_postgres1] => {
"hostvars[inventory_hostname]['vars']": {
"postgres_ip": "***",
"postgresql_exists": "false"
}
}
ok: [demo_postgres2] => {
"hostvars[inventory_hostname]['vars']": {
"postgres_ip": "***",
"postgresql_exists": "false"
}
}
ok: [demo_postgres3] => {
"hostvars[inventory_hostname]['vars']": {
"postgres_ip": "***",
"postgresql_exists": "false"
}
}

I didn’t find any information about the merging of hostvars when the host is in multiple groups and when I have tested to remove the postgres_cluster group, I get the correct hostvars:

PLAY [etcd_cluster] ***************************************************************************************************************************************************************************

TASK [Gathering Facts] ************************************************************************************************************************************************************************
ok: [demo_postgres1]
ok: [demo_postgres3]
ok: [demo_postgres2]

TASK [Ansible | List all known variables and facts] *******************************************************************************************************************************************
ok: [demo_postgres1] => {
"hostvars[inventory_hostname]['vars']": {
"etcd_ip": "***"
}
}
ok: [demo_postgres2] => {
"hostvars[inventory_hostname]['vars']": {
"etcd_ip": "***"
}
}
ok: [demo_postgres3] => {
"hostvars[inventory_hostname]['vars']": {
"etcd_ip": "***"
}
}

I would expect that my etcd_ip was merged with postgres_ip ? I can resolve this by adding the etcd_ip in postgres_cluster hostvars but I want to understand why merge is not working.

If you need more information, feel free to ask.

Best regards,

BDO

Hi,

As I understand etc_ip and postgresql_ip are variable specific for each host, and so they should be in hosts parts of your inventory file (Here you are doing a mix).

postgresql_exists can be setup in a your postgresql group, but I’m not sure if it is really necessary to have it

See there for example : https://docs.ansible.com/ansible/latest/plugins/inventory/yaml.html

If you want further help, please provide your playbooks used for your outputs.

And for the record, no needs to use a playbook to list variables, command “ansible-inventory” can be used successfully for this

Regards,

Hi,

thanks for your reply.

Yeah that’s it. etcd_ip and postgresql_ip are in separate host. But I don’t understand, there are already on the host part, aren’t it ?
what is the syntax you think of ?

This is the playbook which should get the etcd_ip


- hosts: etcd_cluster
become: true
become_method: sudo
any_errors_fatal: true
gather_facts: true
vars_files:
- vars/main.yml
- vars/system.yml
- "vars/{{ ansible_os_family }}.yml"

tasks:
- meta: flush_handlers

- import_tasks: tasks/sysctl.yml
tags: [ sysctl, kernel ]

- import_tasks: tasks/timezone.yml
when: timezone is defined and timezone | length > 0
ignore_errors: yes
tags: [ timezone, configure ]

- import_tasks: tasks/ntp.yml
when: ntp_enabled is defined and ntp_enabled == "true"
ignore_errors: yes
tags: [ ntp, configure ]

- import_tasks: tasks/etcd.yml
when: dcs_exists == "false" and dcs_type == "etcd"
tags: [ etcd, etcd_cluster ]

Hi,

thanks for your reply.

Yeah that's it. etcd_ip and postgresql_ip are in separate host. But I don't understand, there are already on the host
part, aren't it ?
what is the syntax you think of ?

Try to remove vars: from your inventory when you specify host variables, e.g.

etcd_cluster: # recommendation: 3 or 5-7 nodes
      hosts:
        demo_postgres1:
            etcd_ip: '***'

Regards
         Racke

Hi,

That did the job:
etcd_cluster: # recommendation: 3 or 5-7 nodes
hosts:
demo_postgres1:
etcd_ip: ‘***’

I don’t know why I used vars, maybe because I read a lot of ansible documentation like How to build your inventory and that cursed my brain ^^

atlanta:
  hosts:
    host1:
    host2:
  vars:
    ntp_server: ntp.atlanta.example.com
    proxy: proxy.atlanta.example.com

Thanks again Racke !

Hi,

That did the job:
etcd_cluster: # recommendation: 3 or 5-7 nodes
hosts:
demo_postgres1:
etcd_ip: '***'

I don't know why I used vars, maybe because I read a lot of ansible documentation like How to build your inventory and
that cursed my brain ^^

While the documentation covers a lot of good thing, it doesn't note the differences between group variables (with vars:
) and host vars (without vars:).

In order to avoid confusion, you can use separate files for the host variables.

Regards
         Racke