Using hiera to access facts of another node

So you want certain hosts to get information from another host's facts, but which host the facts come from will vary depending on the configuration of the specific host. Is that correct?

If so, I would also recommend using exported resources and using tags to specify the particular resource to use. The reason for this is that there are basically two ways for a host to get at another host's facts. Both require enabling storeconfigs. One is for the puppet master to do explicit lookups on whatever your storeconfigs backend is; I don't know of any modules that encapsulate this, so you might have to write your own. The other is for the source host to export resources that contain their facts; this is easier and the one I'll describe below.

This will be easier if you make your own resource type to wrap the firewall rules. That prevents any collisions with any other classes that happen to be exporting firewall rules.

define site_firewall ($ipaddr) {
  firewall { '500 allow site access':
    chain       => 'OUTPUT',
    destination => $ipaddr,
    proto       => 'tcp',
    port        => 10000,
  }
}

Next, each of your sites should export its own definition for site_firewall:

@@site_firewall { $hostname:
  ipaddr => $ipaddress,
}

In hiera, you define somewhere in your hierarchy the site that each host is a member of:

sitename: site1

Then in your host classes, you instantiate the appropriate site_firewall definition:

Site_firewall <<| name == hiera('sitename', 'default') |>>

A similar setup would apply for the shared hosts.

If you need firewall rules on the site and shared hosts, you should use tags rather than names because there will be multiple firewall rules for a given host. On the specific hosts:

@@firewall { "500 allow site traffic from ${hostname}":
  tag    => hiera('sitename', 'default-site'),
  source => $ipaddress,
  proto  => 'tcp',
  port   => 10000,
}
@@firewall { "500 allow shared traffic from ${hostname}":
  tag    => hiera('sharedname', 'default-shared'),
  source => $ipaddress,
  proto  => 'tcp',
  port   => 8080,
}

On the site hosts, you just need to collect the firewall rules for those hosts:

Firewall <<| tag == $hostname |>>

Edit: Aha. I think I've found the problem you were running into with exported resources. At the very least this is a gotcha that I'll document here for good measure.

If you have a resource with default parameters and you export that resource without explicitly setting those parameters, the parameter defaults are provided by the host realizing the resource, not the one exporting it.

In other words, if you have this resource type definition:

define foo ($bar = $fqdn) {
  notice($bar)
}

And you export it from host baz.example.com:

@@foo { 'title': }

And you realize it on host quux.example.com:

Foo <<| |>>

Then the value of $bar will be "quux.example.com".

If, instead you export it from baz.example.com like this:

@@foo { 'title': bar => $fqdn }

Then the value of $bar will indeed be "baz.example.com".


Well, I think a good option for your use case is to enable "storeconfigs" and then use "exported resources".

Here you can find some documentation about this topic including some examples:

  • https://puppet.com/docs/puppet/latest/lang_exported.html
  • http://www.masterzen.fr/2009/03/08/all-about-puppet-storeconfigs/