1
votes

Is it possible to set variables for specific hosts in Ansible in the playbook itself, using the the global vars?

So the playbook would be configured something like this:

---
- hosts:
    - host-1
    - host-2
  vars:
    host-1: # < - set vars for host-1 specifically
      a_var: yes
    host-2: # < - set vars for host-2 specifically
      a_var: no

I know I using either group_vars, host_vars, an inventory file, or set_fact during runtime is possible, but this is not what I want.

The docs describe "playbook host_vars", but I haven't figured out how that is configured.

2

2 Answers

1
votes

Q: "Set variables for specific hosts in Ansible in the playbook itself, using the global vars."

A: Put the host-specific variables into a global dictionary, e.g. my_hostvars. (De facto, create your own hostvars). For example

- hosts: host-1,host-2
  vars:
    my_hostvars:
      host-1: # < - set vars for host-1 specifically
        a_var: yes
      host-2: # < - set vars for host-2 specifically
        a_var: no
  tasks:
    - debug:
        msg: "{{ my_hostvars[inventory_hostname]['a_var'] }}"

gives

ok: [host-1] => 
  msg: true
ok: [host-2] => 
  msg: false

It's up to you where you declare the dictionary and how you reference it in the playbook. See Variable precedence: Where should I put a variable?.


Put the variables into your own facts to simplify the access. For example

    - set_fact:
        my_facts: "{{ my_hostvars[inventory_hostname] }}"
    - debug:
        var: my_facts.a_var

give

ok: [host-1] => 
  my_facts.a_var: true
ok: [host-2] => 
  my_facts.a_var: false

You can simplify the access further by setting the variables if needed. (For example, to avoid rewriting a code already using the variables).

    - set_fact:
        a_var: "{{ my_facts.a_var }}"
        b_var: "{{ my_facts.b_var }}"
        c_var: "{{ my_facts.c_var }}"

You can use it to set or customize (precedence 19.) the default values if needed. For example,

    - set_fact:
        a_var: "{{ my_facts.a_var|default('a') }}"
        b_var: "{{ my_facts.b_var }}"
        c_var: "{{ my_facts.c_var }}"
0
votes

What you are referring to is not really in the playbook, per se. But it can be in the directory structure next to the playbook itself.

This is further explained in Organizing host and group variables.

Although you can store variables in the main inventory file, storing separate host and group variables files may help you organize your variable values more easily. Host and group variable files must use YAML syntax. Valid file extensions include ‘.yml’, ‘.yaml’, ‘.json’, or no file extension. See YAML Syntax if you are new to YAML.

Ansible loads host and group variable files by searching paths relative to the inventory file or the playbook file.

Source: https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html#organizing-host-and-group-variables, emphasis, mine


So, what you can have is this:

.
├── host_vars
│   └── localhost.yml
└── play.yml

Where localhost.yml matches the name of the host we want to target and would contain something like:

foo: bar

And the file play.yml would be the playbook:

- hosts: all
  gather_facts: no

  tasks:
    - debug:
        var: foo

Then running it would give the expected:

PLAY [all] **********************************************************************************************************

TASK [debug] ********************************************************************************************************
ok: [localhost] => {
    "foo": "bar"
}

PLAY RECAP **********************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0