I’ve been working this issue for a week now. The code used to work perfectly and now it fails. Here is the error I get:
The task includes an option with an undefined variable. The error was: {‘CentOS’: ‘{{ iptables_directory[ansible_distribution] }}/iptables’,
‘Rocky’: ‘{{ iptables_directory[ansible_distribution] }}/iptables’, ‘Debian’: ‘{{ iptables_directory[ansible_distribution] }}/rules.v4’,
‘Ubuntu’: ‘{{ iptables_directory[ansible_distribution] }}/rules.v4’}: ‘dict object’ has no attribute ‘Debian’. ‘dict object’ has no attribute ‘Debian’.
The error appears to be in ‘/work/armory/roles/xxx/tasks/xxx.yml’: line 266, column 3, but may be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
The task includes an option with an undefined variable. The error was: {‘CentOS’: ‘{{ iptables_directory[ansible_distribution] }}/iptables’,
‘Rocky’: ‘{{ iptables_directory[ansible_distribution] }}/iptables’, ‘Debian’: ‘{{ iptables_directory[ansible_distribution] }}/rules.v4’,
‘Ubuntu’: ‘{{ iptables_directory[ansible_distribution] }}/rules.v4’}: ‘dict object’ has no attribute ‘CentOS’. ‘dict object’ has no attribute ‘CentOS’.
The error appears to be in ‘/work/armory/roles/xxx/tasks/xxx.yml’: line 266, column 3, but may be elsewhere in the file depending on the exact syntax problem.
Default.yml is at the playbook level in a folder called group_vars. It is being read in by my playbook like this:
(I added “Fedora” because that’s what I’m testing on; otherwise this doesn’t work at all.)
But, surly, the iptables_v4_rules[‘Rocky’] value is not going to change if I’m running on “Debian”? The way its written, if I’m on a Debian host, all of the iptables_v4_rules values will be “/etc/iptables/rules.v4”.
In any case, it looks like somehow you’ve tricked the “lazy evaluation” engine to be even more lazy than it’s supposed to be, because it looks like it isn’t resolving the templates in the values. Not sure how you’ve managed that, but I’d really like to know!
If ‘group_vars’ is adjacent to your playbook, then ‘group_vars/default.yml’ would also load if the host is in a group called ‘default’.
So this file name/location is a bit ambiguous.
In any case I would only use the ‘vars_files’ statement for files that are not automatically loaded.
So I would remove the vars_files statement from your playbook and then rename the vars file to ‘group_vars/all.yml’.
Or create a dir ‘group_vars/all’ and move it there: ‘group_vars/all/default.yml’ (or main.yml, doesn’t matter)
The error appears to be in ‘/work/armory/roles/xxx/tasks/xxx.yml’: line 266, column 3, but may be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
name: Save new iptables - IPv4
^ here
The error is being reported by a role.
Is the group_vars/default.yml being sourced by the role, or by the playbook that invokes the role? How are you invoking the role?
Yes.
It sounds like the vars file is somehow used twice, which I think (after Todd’s comment) may screw up the level of laziness.
(speculation on my side, but let’s see)
This bears repeating. I know I missed it the first few times I was told, and then the light came on.
All hosts are in the “all” group. (That much I got the first time.
Any files or directories in ./group_vars/ that match a host’s group names – including “all” – get loaded for that host. It was the “or directories” part I didn’t appreciate at first. For example, if a host is in the “foo” group, then the files ./group_vars/foo, or better, ./group_vars/foo.yml (the former won’t be ansible-linted; the latter will be) get loaded for that host. But more than that, if ./group_vars/foo/ is a directory, then all the files within ./group_vars/foo/ get loaded for all hosts in the foo group.
That works even for groups that don’t exist when the playbook starts but are created on-they-fly by, for example, the ansible.builtin.group_by module. This allows you to have amazingly crazy ad hoc groups – like “hosts the CEO has logged into in the last 30 minutes” – and still use relevant ./group_vars/ files in a straightforward way.
We suffered a bit initially because in some of our projects different competing interests clashed over ownership of the ./group_vars/all.yml file. When we realized we could have files ./group_vars/all/interest_aaa.yml, ./group_vars/all/interest_bbb.yml, ./group_vars/all/interest_ccc.yml, ./group_vars/all/interest_ddd.yml, etc., then the competition for that namespace became cooperation, and things just got much easier.
Do you still have that vars_files: thing? As Dick suggested, it feels like that file is getting loaded more than once, and you don’t want that.
Is it at all possible that variables iptables_v4_rules and/or iptables_directory are being set anywhere else?
[If you want to toss the whole thing in a private repo that I can clone, or some other way get to me, I’m willing to take a look; I’m really curious to know how this is happening.]