How are debug: var=vars / var=hostvars supposed to work?

Per the documentation and this thread: https://groups.google.com/d/msg/ansible-project/rE8aVu4LNS0/sGKweGPvffoJ
I think that debug: var=hostvars should print all the variables in scope (for each host). I’m not sure what var=vars is - non-host-specific variables?

In either case, I’m getting extremely odd behavior that I can’t figure out. I’m sorry this is long, but it is hopefully easy to follow and I suspect is either a simple answer or there is a bug.

(some stuff removed for brevity or security)

Here is my command line:
ansible-playbook playbook.yml --inventory-file dynamic_inventory.sh --limit stage --user xxx --private-key xxx.pub -e IS_VAGRANT=False -C

Here is the result of my dynamic inventory for host ‘stage’
{
“hosts”: [
“192.xxx.xxx.176”
],
“vars”: {
“HOST_NAME”: “stage.yyyyyyyyy.com”,
“SERVER_NAME”: “stage.yyyyyyyyy.com
}
}

Now here are the key plays, and results, from my playbook

  • debug: var=vars

This looks pretty good (but note it doesn’t show variables from my inventory)

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

TASK: [baseUbuntu | debug var=vars] *******************************************
ok: [192.xxx.xxx.176] => {
“vars”: {
“DIFFTOOL”: “git --no-pager diff”,
… <DELETED - but no HOST_NAME> …
“IS_VAGRANT”: “False”,
… <DELETED - but no SERVER_NAME> …
“_original_file”: “/Users/xxxxxx/tmp/thissite/ansible_config/roles/baseUbuntu/tasks/main.yml”,
“always_run”: false,
“changed_when”: null,
“delegate_to”: null,
… …
“role_uuid”: “160302ff-f06f-4a78-8204-f0fcc4a8c750”
}
}

  • debug: var=hostvars

This looks wrong to me. Shouldn’t it either be a superset of vars and my inventory variables?
(HOST_NAME and SERVER_NAME)

TASK: [baseUbuntu | debug var=hostvars] ***************************************
ok: [192.xxx.xxx.176] => {
“hostvars”: {
“192.xxx.xxx.176”: {
“IS_VAGRANT”: “False”
}
}
}

Hmmm… maybe I I’m not properly setting my inventory variables.
Nope! See ‘HOST_NAME’ is properly set. Why doesn’t it show up in vars or hostvars?

  • debug: msg=“HOST_NAME = {{ HOST_NAME }}
    TASK: [baseUbuntu | debug msg=“HOST_NAME = {{ HOST_NAME }}”] ****************
    ok: [192.xxx.xxx.176] => {
    “msg”: “HOST_NAME = stage.yyyyyyyyy.com
    }

And this one is even weirder. I use {{ HOST_NAME }} and in the “name” clause it doesn’t
render and in the hostname clause it does!

  • name: “Set hostname to {{ HOST_NAME }}”
    hostname: name=“{{ HOST_NAME }}”

TASK: [baseUbuntu | debug msg=“HOST_NAME = {{ HOST_NAME }}”] ****************
ok: [192.xxx.xxx.176] => {
“msg”: “HOST_NAME = stage.yyyyyyyyy.com
}

I’m baffled - I’d appreciate any tips. Thank you!

“I think that debug: var=hostvars should print all the variables in scope (for each host)”

It doesn’t do this, but rather looks for variable names inside hostvars.

You can think of the “hostvars” syntax as a way to reference variables for other hosts.

I guess whether it should work might be a technicality, but that’s what it was intended for.

Ive stopped doing
debug: var=hostvars
and do
debug: var=hostvars[inventory_hostname]
or
debug: var=hostvars[item]
with_items: play_hosts

As you do not get all the vars outputted in when you do it the first way, but the second way I do. I am completely guessing as I have not dug into the code to see, but I am suspecting that hostvars is coming from a cache that is not up to date, and when you access the specific element in hostvars that is coming from a cache that contains the latest.

Thanks!
Michael

​Yes, 'hostvars' is implemented as a caching dictionary, which means you
need to explicitly request vars for a particular key/host.​

I know there probably internal implementation details on why it is the way it is, but wouldn’t we want debug: var=hostvars to not come from the cache and be the latest truth of what is contained in hostvars? If I am doing a debug of the variable, I am already in a mode where performance is not a concern, I am trying to gather insight into the state of the system. So maybe if the debug task is used, the variable in the task should be fully interpolated, or unioned with the rest of dictionaries / lists that are accessed when specifying hostvars[hostname]

Thanks!
Michael

“but wouldn’t we want debug: var=hostvars to not come from the cache and be the latest truth of what is contained in hostvars”

Serge mispoke a bit above. The problem is not that hostvars is a cache, but rather that hostvars is an object that provides access to individual variables.

We aren’t really concerned with:

  • debug: var=hostvars

as it’s a very unusual thing to do.

typically this is how vars are shown with debug:

  • hosts: webservers
    tasks:
  • debug: var=foo

And the “hostvars” trick is only needed when accessing variables from other servers, typically in templates for instance when building out something like an iptables config.