I''m sure some will see this as downright sinful and ugly and un-scalable, all of which are probably true, but I''ve found this to be a really handy hack lately and thought I''d share in case it scratches anyone else''s itch. I started to explain all the reasons why I did this, but it started looking very "TL; DR" :). The short version is that in our puppet-controlled EC2-hosted clusters, often a templated config file on one node needs Facter facts from all other nodes (or a subset of them), such as their randomly-ec2-assigned ipaddress_eth0''s, or the ec2_instance_id, etc. There are probably more efficient ways to implement this, but it works for me right now. This technique makes a hostclass-scoped variable available named "rfacts", which is a hash by hostname of the Facter facts of all other nodes in the environment (using the same puppetmaster), which stays up to date as all of the clients do their puppet runs. It does this by parsing up all the facts data available on the master from the yaml files in /var/lib/puppet/yaml/facts/*. First, a new Ruby DSL manifest which defines a magic hostclass named "rfbase": ----- manifests/rfbase.rb: ---- class RFacter @@rfcache = {} def self.get_rfacts path = ''/var/lib/puppet/yaml/facts'' rfacts = {} Dir.foreach(path) {|fn| m = fn.match(/(.*)\.yaml$/) or next hn = m[1] fullpath = path + ''/'' + fn mtime = File.stat(fullpath).mtime if(@@rfcache.key?(hn) && @@rfcache[hn][''mtime''] == mtime) then rfacts[hn] = @@rfcache[hn][''data''] else rfacts[hn] = YAML.load_file(fullpath).values @@rfcache[hn] = { ''mtime'' => mtime, ''data'' => rfacts[hn] } end } return rfacts end end hostclass :rfbase do scope.setvar(''rfacts'', RFacter.get_rfacts()) end Next, all of my role/location-specific hostclasses inherent (directly or indirectly) from rfbase, e.g.: manifests/node_classes.pp: --- # Low-level magic for cross-node fact access via $rfacts hash import "rfbase.rb" class node_foo inherits rfbase { # .... } And finally, my erb config templates can now across cross-node facts via the rfacts hash. For example, this one-liner erb template defines a file stored at /etc/nodes/instancemap on all nodes, and that file contains a hostname:instance_id map of all nodes in the cluster (for other administrative scripts to work from): templates/etc/nodes/instancemap.erb: --- <% imap = rfacts.sort.map{|x| x[1][''hostname'']+'':''+x[1][''ec2_instance_id'']}.join("\n") %><%= imap %> A much uglier and more complex example that pulls out the ipaddress_eth0 and a custom fact of ours called server_tokens from all nodes whose hostnames begin with the string "apps", and uses this to form some configuration lines for a custom proxy daemon: <% svrs = [] nprocs = Integer(node_nprocs) sport = Integer(node_start_port) rfacts.select{|k,v| k.match(/^apps/)}.sort.each{|x| ip = x[1][''ipaddress_eth0''] stokens = x[1][''server_tokens''].split(/,/) i = 0 while i < nprocs do svrs.push(sprintf(''%s:%u/%s'', ip, sport + i, stokens[i])) i += 1 end } servers = svrs.join("\n") %><%= servers %> -- Brandon -- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com. To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.