Apr 102014

One thing that the Puppet language doesn’t do – and apparently this is entirely by design – is iteration. There’s no way to loop a block – no foreach, while or repeat. While this function would seem to be a natural language construct, Puppet is about prototyping, and configuration should be specific, rather than derived. However, there are ways of performing an iteration, should it become necessary, and this is one example.

This example pertains to the AMANDA backup server software. It requires a definition for a sequence of virtual tapes. These are just empty directories that need to be created and then registered using the AMANDA “amlabel” command. All I wanted to do was to say to Puppet, “Create me n virtual disks, where n is an integer variable”. If it was a simple matter of creating an array [ 1..n ] and then passing this to a define, there wouldn’t be a problem, but there’s no way in Puppet to create a variable-length array. One can only do something like this:

$array = [ 1,2,3,4,5 ]

which is no use when the number of elements is not known.

But one simple way to accomplish a variable length sequence is through recursion. Consider this puppet define:

define amanda_create_slot ($backup_set, $slot_path, $slot_num ) {
  if "${slot_num}" > '0' {
    exec { "slot${slot_num}":
      creates => "${slot_path}/slot${slot_num}",
      user => "amandabackup",
      command => "/bin/mkdir $slot_path/slot${slot_num};
	/usr/sbin/amlabel $backup_set $backup_set-${slot_num} slot $slot_num"
    $decrement = inline_template('<%= @slot_num.to_i - 1 %>')
    $amanda_create_slot { "slots-${decrement}": backup_set => $backup_set,
		                                slot_num => $decrement,
			                        slot_path => $slot_path }

It checks that the slot number passed to it is greater than zero, and if so, creates a slot with that index. It then decrements the argument “slot_num”, and then invokes itself again. It will continue to do this until the variable slot_num is reduced to zero, at which point the if-block will fail and the recursive loop will collapse.

In a manifest, this function is initially invoked like this:

amanda_create_slot { "slots": backup_set => Daily,
			      slot_num => "10",
			      slot_path => "/var/amanda/slots" }


The result will be a nice series of virtual tape slots, all numbered from 1 to 10.

Matt Parsons is a freelance Linux specialist who has designed, built and supported Unix and Linux systems in the finance, telecommunications and media industries.

He lives and works in London.

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>