Hello,
Is there any magic variable that can be used inside templates to access
variables of an arbitrary group (the equivalent of hostvars, but for
groups) ?
Hello,
Is there any magic variable that can be used inside templates to access
variables of an arbitrary group (the equivalent of hostvars, but for
groups) ?
Group_vars?
Yeah that doesn’t exist, because you always want to get the variables that have host overrides applied.
You can of course do stuff like:
hostvars[groups[‘webservers’][0]][‘foo’]
Maybe that 'always' is not always 'always'.
Also, hostvars[groups['webservers'][0]]['foo'] would be different from a
hypothetical groupvars['webservers']. The first one returns group vars
overridden with first webserver's vars, while we may want to access the
'default' webservers group variables. Actually, I think
'default_groupvars' would be a better name.
Can you explain your use case for needing this?
It may help me better understand what a solution may be.
–Michael
Some hosts are managed through a management API, using a common
management account. The authentication data for that account is stored
in the group variables of a group consisting of these hosts. Some other
hosts, which cannot be in a common group with the first group, need to
do things on the first group, using that management account. The
solution of having the authentication data in many places is quite
'dirty'. The solution of having different authentication data for that
host is also not wanted.
I think that there can be other cases that this might come handy too.
For example, how can you handle the case in which you want to
dynamically (e.g. based on some task result or fact) fallback to a
default group variable and not use the overridden host variable?
“For example, how can you handle the case in which you want to
dynamically (e.g. based on some task result or fact) fallback to a
default group variable and not use the overridden host variable?”
This sounds like a technical feature rather than a use case. If I may ask, in what situation would you want this?
If you overrode the host variable, you did it because you didn’t want the default.
By the nature of the word “default” it means the value to be used if another preference is not specified. If the default takes priority over
a host setting it’s no longer a default
I can think of cases such as falling back to a default continent or country mirroring service in case the local one is down, falling back to using a default storage path in case the more-specific one has not enough space, as well as fallback to a local stand-by backup server in case it is needed to take a snapshot of a great amount of data, but it is not good time to transfer it over the network to a remote site. This is true for the decision flow you have in mind. Another decision flow, however, is falling back to sensible defaults in case the preferred or more specific preselections are not applicable or available.
Ok, so the idea of just taking a value and deciding which to use based on some other criteria is not really a ‘default’ scenario.
Sounds like you want stuff like, vaguely
{% if x > 5 %}{{ y }}{% else %}{{ z }}{% endif %}
etc
I would write:
{% if requirements_are_met %}{{ host_specific_var }}{% else %}{{
default_group_var }}{% endif %}
or
{% if host_resources_cannot_be_used %}{{ default_group_var }}{% else
%}{{ host_specific_var }}{% endif %}
Don' t forget that the need is to have vars that are specific to a host
or host group, but not to write different templates for every possible
group.
I would also like to see comments on that discussion from other ansible
users too.
Ok, so this is already easily done in your case by this:
{% if requirements_are_met %}{{ foo_port }}{% else %}{{
foo_port_if_requirements_not_met }}{% endif %}
Obviously variable names are arbitrary.
Just use different variables for the second.
Sure, it can be done with different variable names in group variables. But their values are not going to be different from the defaults, since you have cases in which you do want to use the default values instead of the host-specific ones. Having two differently named variables holding the same values is not an elegant solution in my opinion. Also, there is no protection for a specific group variable not to be overridden with a host-specific variable. So, even these duplicate variables can be overridden in a host by mistake and not give a chance to be able to fall back to a group’s default value. Even from a language expressiveness perspective, imho, it can be seen as a limitation of Ansible the fact that it can only express the last computed state of its variables and not the initial state or the intermediate states.
This conversation strikes me as increasingly theoretical, so I’m not getting it.
Even C can’t express the “previous state of a variable”
I think we’ll have to agree to disagree about the magnitude of importance of this use case as I’ve offered a few ways to handle your scenario.
I still think you are modelling things a bit strangely to have this requirement.
The solutions that now work involve the overloading of ansible
inventory, just because there is no direct way to access the group
variables of an arbitrary group.
For example, how would you avoid the inventory overloading in the
following model:
There is GroupA with hosts HostA1, HostA2, HostA3 managed through an API
using a common account. So, the authentication data for this account is
stored in the group variables of GroupA. When deploying hosts HostA1
through HostA3, their management account is configured with the
authentication data that is inherited from GroupA variables.
Now, you want to configure a management client software in HostB to
connect to hosts in GroupA through the management API. So, you must
deploy a configuration file for that client from a template that must
have access to GroupA variables, because that' s where the
authentication data is. You could, of course, overload the ansible
inventory and create a common group with HostB and hosts in GroupA, and
move authentication data in that group. And you would have to create a
different common group for every different group of hosts with a common
management account that HostB needs to access. Also, solutions like
using hostvars[groups['group_name'][0]]['somevar'] are neither clean nor
safe.