Running ansible-playbook with an inventories directory does no utilize the host_vars files

Hello,

I have run into an issues with my ansible installation wherein, if I run ansible-playbook -i inventories/userland site.yml, the playbook picks up all of the group_vars and host_vars files and fills in all of the variables where necessary so that I can use them in my roles and playbooks. However, if I instead run ansible-playbook -i inventories site.yml, none of the vars files are picked up and I consistently get errors to the effect of “The task includes an option with an undefined variable.” Even though the variable is very much defined and is working just fine under the other command.

One of my tasks which has the error is listed as such:

- name: Devine group_packages
set_fact:
group_packages: "{{ __group_packages | list }}"
when: group_packages is not defined

group_vars file, which defines that variable is laptops.yml and lists as such:

---
__group_packages:
- network-manager-openvpn

last but not least, my directory structure looks like this:

.
├── ansible.cfg
├── inventories
│ ├── production
│ │ ├── group_vars
│ │ ├── hosts.yml
│ │ └── host_vars
│ ├── staging
│ │ ├── group_vars
│ │ ├── hosts.yml
│ │ └── host_vars
│ └── userland
│ ├── group_vars
│ │ ├── all.yml
│ │ ├── desktops.yml
│ │ └── laptops.yml
│ ├── hosts.yml
│ └── host_vars
│ ├── base.yml
│ └── M142BK19I02569.yml
├── roles
│ ├── ansible
│ │ ├── defaults
│ │ │ └── main.yml
│ │ ├── files
│ │ ├── handlers
│ │ │ └── main.yml
│ │ ├── meta
│ │ │ └── main.yml
│ │ ├── README.md
│ │ ├── tasks
│ │ │ └── main.yml
│ │ ├── templates
│ │ ├── tests
│ │ │ ├── inventory
│ │ │ └── test.yml
│ │ ├── .travis.yml
│ │ └── vars
│ │ └── main.yml
│ ├── common
│ │ ├── defaults
│ │ │ └── main.yml
│ │ ├── files
│ │ ├── handlers
│ │ │ └── main.yml
│ │ ├── meta
│ │ │ └── main.yml
│ │ ├── README.md
│ │ ├── tasks
│ │ │ ├── main.yml
│ │ │ ├── setup-Archlinux.yml
│ │ │ └── setup-Debian.yml
│ │ ├── templates
│ │ ├── tests
│ │ │ ├── inventory
│ │ │ └── test.yml
│ │ ├── .travis.yml
│ │ └── vars
│ │ ├── Archlinux.yml
│ │ ├── Debian.yml
│ │ └── main.yml
│ ├── docker
│ │ ├── defaults
│ │ │ └── main.yml
│ │ ├── files
│ │ ├── handlers
│ │ │ └── main.yml
│ │ ├── meta
│ │ │ └── main.yml
│ │ ├── README.md
│ │ ├── tasks
│ │ │ └── main.yml
│ │ ├── templates
│ │ ├── tests
│ │ │ ├── inventory
│ │ │ └── test.yml
│ │ ├── .travis.yml
│ │ └── vars
│ │ └── main.yml
│ ├── gitlab
│ │ ├── defaults
│ │ │ └── main.yml
│ │ ├── files
│ │ ├── handlers
│ │ │ └── main.yml
│ │ ├── meta
│ │ │ └── main.yml
│ │ ├── README.md
│ │ ├── tasks
│ │ │ └── main.yml
│ │ ├── templates
│ │ ├── tests
│ │ │ ├── inventory
│ │ │ └── test.yml
│ │ ├── .travis.yml
│ │ └── vars
│ │ └── main.yml
│ ├── packageCache
│ │ ├── defaults
│ │ │ └── main.yml
│ │ ├── files
│ │ ├── handlers
│ │ │ └── main.yml
│ │ ├── meta
│ │ │ └── main.yml
│ │ ├── README.md
│ │ ├── tasks
│ │ │ ├── main.yml
│ │ │ ├── update-Archlinux.yml
│ │ │ └── update-Debian.yml
│ │ ├── templates
│ │ ├── tests
│ │ │ ├── inventory
│ │ │ └── test.yml
│ │ ├── .travis.yml
│ │ └── vars
│ │ └── main.yml
│ └── userApplications
│ ├── defaults
│ │ └── main.yml
│ ├── files
│ ├── handlers
│ │ └── main.yml
│ ├── meta
│ │ └── main.yml
│ ├── README.md
│ ├── tasks
│ │ ├── chromium-Archlinux.yml
│ │ ├── chromium-Debian.yml
│ │ ├── firefox-Archlinux.yml
│ │ ├── firefox-Debian.yml
│ │ └── main.yml
│ ├── templates
│ ├── tests
│ │ ├── inventory
│ │ └── test.yml
│ ├── .travis.yml
│ └── vars
│ └── main.yml
├── runTests.sh
├── site.yml
└── .yamllint

Thank you in advance for all the help.

... `ansible-playbook -i inventories site.yml`, none of the
vars files are picked up

├── inventories
│ ├── production
│ │ ├── group_vars
│ │ ├── hosts.yml
│ │ └── host_vars
│ ├── staging
│ │ ├── group_vars
│ │ ├── hosts.yml
│ │ └── host_vars
│ └── userland
│ ├── group_vars
│ │ ├── all.yml
│ │ ├── desktops.yml
│ │ └── laptops.yml
│ ├── hosts.yml
│ └── host_vars
│ ├── base.yml
│ └── M142BK19I02569.yml

IMHO, ansible-playbook should complain about the directory used in -i
parameter and exit with error.

man ansible-playbook says

  "-i, --inventory, --inventory-file
          specify inventory host path or comma separated host list."

On the contrary, ansible-inventory shows that all hosts.yml will be
included from the directory.

  > ansible-inventory -i inventories --list

But, the host_vars and group_vars will be ignored despite the fact
that doc says they should be included. Quoting from "Organizing host
and group variables"
https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html#organizing-host-and-group-variables

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

(Do you really want to combine production, staging, and userland
inventories and variables?)

- name: Devine group_packages
  set_fact:
    group_packages: "{{ __group_packages | list }}"
  when: group_packages is not defined

"__group_packages" is not valid name of a variable. Quoting from
"Creating valid variable names"
https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#creating-valid-variable-names

  "Variable names should be letters, numbers, and underscores.
  Variables should always start with a letter."

(list in the loop)

> IMHO, ansible-playbook should complain about the directory used in -i
> parameter and exit with error.
>
> man ansible-playbook says
>
> "-i, --inventory, --inventory-file
> specify inventory host path or comma separated host list."
>
> On the contrary, ansible-inventory shows that all hosts.yml will be
> included from the directory.
>
> > ansible-inventory -i inventories --list
>
> But, the host_vars and group_vars will be ignored despite the fact
> that doc says they should be included. Quoting from "Organizing host
> and group variables"
> https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html#organizing-host-and-group-variables
> "Ansible loads host and group variable files by searching paths
> relative to the inventory file or the playbook file."

Going from what you have said here, there is either a bug in
ansible-inventory, which does not take into account the way that
ansible-playbook actually works, or ansible-playbook has the bug and should
be updated to reflect that the host_vars and group_vars can actually be
used from the single inventories directory.

Short answer: The environment variable ANSIBLE_INVENTORY is an easy
and convenient workaround.

Details: Let's test it with the inventories and playbook below

  > cat inventories/userland/hosts
  test_01
  test_02
  > cat inventories/userland/host_vars/test_01
  my_var: test_01
  > cat inventories/userland/host_vars/test_02
  my_var: test_02

  > cat inventories/staging/hosts
  test_03
  > cat inventories/staging/host_vars/test_03.yml
  my_var: test_03

  > cat test.yml
  - hosts: all
    tasks:
      - debug:
          var: my_var

The environment ANSIBLE_INVENTORY works as described in
"DEFAULT_HOST_LIST"
https://docs.ansible.com/ansible/latest/reference_appendices/config.html#default-host-list
For example the command

  > ANSIBLE_INVENTORY="inventories/userland/hosts,\
         inventories/staging/hosts" ansible-playbook test.yml

gives

  ok: [test_01] =>
    my_var: test_01
  ok: [test_02] =>
    my_var: test_02
  ok: [test_03] =>
    my_var: test_03