What’s the correct way to reference hosts as variables in Ansible

ansible

I'm fairly new to Ansible, and am in a bit of a dilemma with our flow for this particular script. We have a list of certs that we want to deploy to each host; these are unique to each host, so 1:1 transfer.

# hostfile
[prod]
host_a
host_b
host_c

Currently, I'm doing this as part of the group_vars for my role:

haproxy:
  prod:
    certs:
      host_a:  a.my.endpoint.com.pem
      host_b:  b.my.endpoint.com.pem
      host_c:  c.my.endpoint.com.pem

And then referencing this in a task:

- name: upload haproxy server certificates
  copy:
    src: "{{haproxy[env].certs[inventory_hostname]}}"
    dest: "/etc/haproxy/ssl/{{haproxy[env].certs[inventory_hostname]}}"
    backup: yes
  notify:
    - restart haproxy
  tags:
    - haproxy

This works fine, but I don't like it. I primarily don't like it because it forces you to remember to update hosts in two places (the hostfile and the vars file). What I'd considered was to define the hosts as a var in group_vars, but I'm not entirely sure that I can reference vars within the file? So something like:

hosts:
  host_a
  host_b
  host_c

haproxy:
  prod:
    certs:
      {{ hosts.host_a }}:  a.my.endpoint.com.pem
      {{ hosts.host_b }}:  b.my.endpoint.com.pem
      {{ hosts.host_c }}:  c.my.endpoint.com.pem

And then this further complicates things a bit when I get into the task. I assume I could change my task to have a separate copy for each host, like with a when: {{ inventory_host }} == {{ hosts.host_a}} and just copy each file in it's own section. This seems equally as ugly to me though.

Is there a better, more intuitive way I could go about this?

Best Answer

Best practice would be to use host-vars. host-vars work exactly the same as group-vars but define variables per host.

So you could have a file host_vars/host_a with the content

cert: a.my.endpoint.com.pem

...and use cert as the variable in your task.

But your problem stays the same:

I primarily don't like it because it forces you to remember to update hosts in two places (the hostfile and the vars file).

But you as well can define host vars in your inventory. This gets ugly if you have more variables to define but if that's the only one and your goal is to manage all defintions in one place, you can do it like this:

# hostfile
[prod]
host_a   cert=a.my.endpoint.com.pem
host_b   cert=b.my.endpoint.com.pem
host_c   cert=c.my.endpoint.com.pem

In both cases your task would reduce to this:

- name: upload haproxy server certificates
  copy:
    src: "{{ cert }}"
    dest: "/etc/haproxy/ssl/{{ cert }}"
    backup: yes
  notify:
    - restart haproxy
  tags:
    - haproxy
Related Topic