Puppet exported resources for .erb file variables

puppet

Scenario: my configuration file is defined by a .erb file which includes the snippet below.

<% backupclients.each do |backup_files| -%>
Job {
  Name = "Server"
  JobDefs = "DefaultJob"
  Client = <%= backup_files %>-fd
  Pool = TeraMonth
  Write Bootstrap = "/var/lib/bacula/<%= backup_files %>.bsr"
}
<% end -%>

The server's configuration file needs a repeated entry for each client host. If I were to create a simple array, this would work without issue. What I want to do, however, is have each host register itself and then collect the data using the <<| |>> pragma similar to what one would do with the nagios_* types.

The standard example for this involves exporting a type.

class ssh {
  @@sshkey { $hostname: type => dsa, key => $sshdsakey }
  Sshkey <<| |>>
}

However, I can't quite figure out how to write a type or reference it in a way that would allow me to read that array of values from the .erb template. Is there a way I can use exported resources in combination with a variable loop in a .erb file?

Best Answer

So, to answer your question directly, I don't believe getting a list of exported resources directly from erb is possible. This is due to the nature of exported resources. To Puppet, they're just more resources that need to be created on the host.

But, there is a way to accomplish what you're looking to do. I do it in a few places in my environment.

Here we create a directory of files, one for each host we want to flag as a "bacula_client". We use the purge, force, and recurse options to remove files that are not managed by Puppet (i.e. if you want to remove a system from this "list").

class bacula::client {

  @@file { "/etc/bacula_clients/$fqdn":
    ensure => present,
    content => "",
    require => File['/etc/bacula_clients'],
    tag => "bacula_client",
  }

}

class bacula::server {

  #
  # .. include whatever else the server requires, like package {} file {} service {}
  #

  file { "/etc/bacula_clients":
    ensure => directory,
    purge => true,
    recurse => true,
    force => true,
  }

  # Populate directory of client files.
  File <<| tag == "bacula_client" |>>

}

Next, we use some Ruby code in the .erb to scan this directory for files, and act on them:

<% 
bacula_clients_dir = '/etc/bacula_clients'
d = Dir.open(bacula_clients_dir)

# Remove directories from the list of entries in the directory (specifically '.' and '..'):
backupclients = d.entries.delete_if { |e| File.directory? "#{bacula_clients_dir}/#{e}" }

backupclients.each do |backup_files| 
-%>
Job {
  Name = "Server"
  JobDefs = "DefaultJob"
  Client = <%= backup_files %>-fd
  Pool = TeraMonth
  Write Bootstrap = "/var/lib/bacula/<%= backup_files %>.bsr"
}
<% end -%>
Related Topic