Thanks for posting Azul. It's interesting to see another way of handling it. I ended up with this structure, which I'm liking a lot:
env
├── defaults
├── dev
│ ├── group_vars
│ │ ├── backend
│ │ ├── defaults
│ │ ├── ingest
│ │ ├── monitoring
│ │ └── zookeeper
│ └── inventory.py
└── production
├── group_vars
│ ├── backend
│ ├── defaults
│ ├── ingest
│ ├── monitoring
│ └── zookeeper
└── inventory.py
1. I completely eschew Ansible's "all" supergroup because precedence was not behaving as I expected.
2. I use a dynamic inventory script which adds all my groups to a "defaults" supergroup. This is my "all" replacement, so env/defaults is my new group_vars/all. The script also manually reads in env/defaults and sets the vars in the JSON output.
3. env/defaults can specify site-wide defaults which can be overridden by env/dev/group_vars/defaults. There's a third level of specificity at env/dev/group_vars/$group, e.g. env/dev/group_vars/zookeeper, which would override anything in env/dev/group_vars/defaults.
I'd really like to see Ansible create an official solution to this common problem. It'd take the burden off devs and increase uniformity in Ansible automation.
One awkward piece of my setup is having to set all my vars at the inventory level, when much of it belongs at the playbook level.