Here's how to access facts from other hosts (advanced feature)

11,498 views
Skip to first unread message

Michael DeHaan

unread,
Apr 21, 2012, 9:37:20 PM4/21/12
to ansible...@googlegroups.com
Suppose you are configuring a Java app server, and it was neccessary
to put something like an IP address + port number of a database server
in the XML configuration file for the app server. This is somewhat
of an advanced need as TYPICALLY, I'd
think you'd just stick a load balancer in front of things and use well
known ports. However, that's not ALWAYS the case, and you
occasionally need to get the data from facts on certain nodes to use
in templates for OTHER nodes.

I just implemented a way to access variables set or determined from
other hosts. If you are familiar with how this works in Puppet
(requiring storeconfigs (database) plus weird modified spaceship
operators), this is going to be REALLY nice. Orchestration between
multiple tiers of a software system is going to be incredibly easy
with this.

The change enabling this is now available on the integration branch,
but it works just like this:

# an example of accessing an ansible fact (which ARE somewhat nested)
{{ hostvars['bar.example.com']['ansible_eth0']['ipv4']['address'] }}

# an example of accessing a facter fact (which aren't nested)
{{ hostvars['foo.example.com']['facter_hostname']

# an example of defining a host variable via the new YAML host file
system, that was defined like so:

- host: asdf
vars:
database_port: 1234

{{ hostvar['127.0.0.1']['database_port'] }}

I'll update the web documentation on this after 0.0.3 is released,
along with documentation about available Ansible facts.

Note that because of the way this works, if you wish to use the
variables from one set of hosts in another set of hosts, you have
to have either included that host in the current play, or a previous
play. If your playbook needs the appservers to point at the
dbservers, you need to have at least a play with zero or more tasks
first calling the dbservers to load up their data.

I suspect most people won't need this, but the fact that we can do it
-- and that it required so little in terms of code changes -- is a
pretty big deal.

--Michael

Michael DeHaan

unread,
Apr 21, 2012, 9:44:04 PM4/21/12
to ansible...@googlegroups.com
Folks who don't code a lot of Python may also like to know that the
following syntax works:

{{ hostvars.get('127.0.0.1').get('some_fact') }}

# and with defaults, if you ever need this:

{{ hostvars.get('127.0.0.1', {}).get('some_fact', 'default') }}

Michel Blanc

unread,
Apr 22, 2012, 5:41:19 AM4/22/12
to ansible...@googlegroups.com
On 22/04/2012 03:37, Michael DeHaan wrote:

> The change enabling this is now available on the integration branch,
> but it works just like this:
>
> # an example of accessing an ansible fact (which ARE somewhat nested)
> {{ hostvars['bar.example.com']['ansible_eth0']['ipv4']['address'] }}
>
> # an example of accessing a facter fact (which aren't nested)
> {{ hostvars['foo.example.com']['facter_hostname']

Hello folks & Michael,

This sounds really nice. Does this mean I can do something like this :
(excuse my python)

$ cat hosts.j2
# Auto-generated /etc/hosts
{% for k,v in hostvars.iteritems() %}
{{v['ansible_eth0']['ipv4']['address']}} {{ k }}
{% endfor %}

?

Would be very useful for me to automatically generate monitoring
configuration for the host list.

Thanks,

M
--
Michel Blanc - netWorks
8A68 0871 747A 65B6 E87C 3BEA 187C 36BB 2CE5 68BD

Michael DeHaan

unread,
Apr 22, 2012, 8:57:17 AM4/22/12
to ansible...@googlegroups.com


Hello folks & Michael,

This sounds really nice. Does this mean I can do something like this :
(excuse my python)

$ cat hosts.j2
# Auto-generated /etc/hosts
{% for k,v in hostvars.iteritems() %}
{{v['ansible_eth0']['ipv4']['address']}} {{ k }}
{% endfor %}

Yes, exactly like that!

Side note -- That would include all of your hosts, so maybe you'd want a way to decide which ones not to include… I'll open up an RFE for including a node's group
membership in hostvars, so the templates can "know" what groups it is a part of.

--Michael


Michael DeHaan

unread,
Apr 22, 2012, 9:01:38 AM4/22/12
to ansible...@googlegroups.com
Here's what I was talking about about it being nice if the host could see what groups it was in:


Not super critical, just maybe nice to have.  For example if your monitoring application wanted to just monitor web servers and database servers, this would be an easy way
to get the list of all web servers and database servers in a template.
Reply all
Reply to author
Forward
0 new messages