using hostvars not resolving variables "calculated" from facts

306 views
Skip to first unread message

Matt Coddington

unread,
Mar 24, 2014, 10:58:50 PM3/24/14
to ansible...@googlegroups.com
Using Ansible 1.5.3

I'm having some trouble with a situation where I have a variable that I'd like to use in a template that uses "hostvars" but the variable in question is calculated from facts.

I have a template that looks like this:

{% for host in groups['uat4-webapp']|sort %}
BalancerMember ajp://{{ hostvars[host].webapp_ip }}:8009 loadfactor=20
{% endfor %}

The "webapp_ip" variable is calculated like this in a group_vars file:

webapp_ip: "{{ ansible_eth0.ipv4.address }}"

When I compile the template above, it ends up looking like this:

BalancerMember ajp://{{ ansible_eth0.ipv4.address }}:8009 loadfactor=20

When I expected it to look like this:

BalancerMember ajp://10.10.1.36:8009 loadfactor=20

The reason for this "webapp_ip" variable as opposed to using the facts directly is because I need it set to different things in different places (one group of hosts has it at ansible_eth0.ipv4.address, another at ansible_bond0.ipv4.address, etc).

Is this something that should work, or should I be looking to accomplish this a different way?

thanks!
matt

C. Morgan Hamill

unread,
Mar 25, 2014, 8:39:07 AM3/25/14
to ansible-project
Excerpts from Matt Coddington's message of 2014-03-24 22:58:50 -0400:
> Using Ansible 1.5.3
>
> I'm having some trouble with a situation where I have a variable that I'd
> like to use in a template that uses "hostvars" but the variable in question
> is calculated from facts.
>
> I have a template that looks like this:
>
> {% for host in groups['uat4-webapp']|sort %}
> BalancerMember ajp://{{ hostvars[host].webapp_ip }}:8009 loadfactor=20
> {% endfor %}
>
> The "webapp_ip" variable is calculated like this in a group_vars file:
>
> webapp_ip: "{{ ansible_eth0.ipv4.address }}"

> Is this something that should work, or should I be looking to accomplish
> this a different way?

Ansible seems to evaluate somewhat lazily, so "{{ansible_eth0.ipv4.address}}"
get evaluated in the context of the current host.

You'll probably need to be explicit:

{{ hostvars[host].ansible_eth0.ipv4.address }}
--
Morgan Hamill

Matt Coddington

unread,
Mar 25, 2014, 2:15:18 PM3/25/14
to ansible...@googlegroups.com
Thanks Morgan,
That's what i was afraid of... you're correct that explicitly referencing those does work, and I can do this in the template by having different cases for the different sets of servers (e.g. "if prod, use ansible_bond0.ipv4.address, if staging use ansible_eth0.ipv4.address, etc").  I was just hoping there was a way to abstract that if/then logic into a common variable outside the template.

thanks,
matt

C. Morgan Hamill

unread,
Mar 25, 2014, 2:27:09 PM3/25/14
to Matt Coddington, ansible-project
Excerpts from Matt Coddington's message of 2014-03-25 14:15:18 -0400:
> > > {% for host in groups['uat4-webapp']|sort %}
> > > BalancerMember ajp://{{ hostvars[host].webapp_ip }}:8009 loadfactor=20
> > > {% endfor %}
> > >
> > > The "webapp_ip" variable is calculated like this in a group_vars file:
> > >
> > > webapp_ip: "{{ ansible_eth0.ipv4.address }}"
> > {{ hostvars[host].ansible_eth0.ipv4.address }}
> That's what i was afraid of... you're correct that explicitly referencing
> those does work, and I can do this in the template by having different
> cases for the different sets of servers (e.g. "if prod, use
> ansible_bond0.ipv4.address, if staging use ansible_eth0.ipv4.address,
> etc"). I was just hoping there was a way to abstract that if/then logic
> into a common variable outside the template.

Idea, untested:

In your template:

{% for host in groups['uat-webapp']|sort %}
BalancerMember ajp://{{ hostvars[host][hostvars[host][webapp_iface]].ipv4.address }}
{% endfor %}

In your group_vars file:

webapp_iface: "ansible_bond0"

Or what have you.

Or this might work:

Leave your template as is, and try putting in your group_vars file:

webapp_ip: "{{ hostvars[inventory_hostname].ansible_eth0.ipv4.address }}"

Also, you might want to look into setting your own facts, as those are
per-host.
--
Morgan Hamill

Matt Coddington

unread,
Mar 25, 2014, 2:56:46 PM3/25/14
to C. Morgan Hamill, ansible-project
Hey Morgan,
Thanks so much for this... all very good ideas, I see how they may work outside of the current way I was thinking about this problem... will definitely try a few out and let the list know where I land :)

matt

Michael DeHaan

unread,
Mar 25, 2014, 2:58:53 PM3/25/14
to ansible...@googlegroups.com, C. Morgan Hamill
I would not expect you would need to do this above workaround if the current variable had an eth0 address.

If you are in fact seeing that, please file a ticket and we can take a look.





--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To post to this group, send email to ansible...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/CAMfrSccOdFYNG7Dpx6vN2sQv4pBBPwayWrXOhuuLM2pMGpM4nw%40mail.gmail.com.

For more options, visit https://groups.google.com/d/optout.

Matt Coddington

unread,
Mar 25, 2014, 3:04:37 PM3/25/14
to ansible-project
On Tue, Mar 25, 2014 at 2:58 PM, Michael DeHaan <mic...@ansible.com> wrote:
I would not expect you would need to do this above workaround if the current variable had an eth0 address.

Thanks Michael... I don't understand what "the current variable having an eth0 address" means...  you mean the current host i'm referring to in hostvars?  it definitely has an eth0 address and if that should in fact work i can submit a ticket with a pretty minimal setup to reproduce i think.

thanks,
matt

 

Michael DeHaan

unread,
Mar 25, 2014, 3:07:37 PM3/25/14
to ansible...@googlegroups.com
I mean if it's the current host in the host loop, for which you are writing the template.

(You shouldn't have to indirect through the hostvars structure unless you need the variables for another host).





Matt Coddington

unread,
Mar 25, 2014, 3:16:43 PM3/25/14
to ansible-project
gotcha, yeah i need the variables from another host so sounds like the indirect method is the way to go.

thanks!
matt



Michael DeHaan

unread,
Mar 25, 2014, 3:18:22 PM3/25/14
to ansible...@googlegroups.com
Right, looking back at the first post, I wouldn't expect webapp_ip to be something in hostvars like that.

    BalancerMember ajp://{{ hostvars[host][hostvars[host][webapp_iface]].ipv4.address }}

is the way to go

It can be shortened with a "set statement" in Jinja2 if you want, though, if you plan to reuse it throughout the file




Reply all
Reply to author
Forward
0 new messages