Puppet: System Administration Automated

Support

This is a design document for a minimal automated configuration file editor. The ideas here are puppet oriented refinements of things that can be done with cfengine's editfiles facility. David Schmitt? has implemented a crude prototype of this in perl at http://club.black.co.at/david/puppet/file_splice.

The Bracket Editor

Many configuration files do not support includes and even fewer support wildcard or directory inclusion. To workaround this omission, puppet provides a bracket editing facility, which replaces specially marked fragments of files with supplied content.

First a real world example.

$NODESDIR = "/var/local/puppet/munin_includes"

class munin_agent {
   @@file { "${NODESDIR}/$fqdn":
      ensure => present,
      content => template( "munin_fragment.erb" ),
   }
}

class munin_host {
   file{ $NODESDIR: ensure => directory, }
   File <<| |>>
   
   file_part { "munin_conf_includes":
      file => "/etc/munin/munin.conf",
      comment_char => '#',
      source => $NODESDIR,
   }
}

This ensures that /etc/munin/munin.conf contains the concatenated content of all files in the $NODESDIR directory. To be able to update and remove this section again, it is marked by the so called bracket:

# BEGIN munin_conf_includes
[content here]
# END munin_conf_includes

Where the brackets are formed by using the comment_char and the namevar from the definition.

When there are no brackets in the file yet, they are appended at the bottom of the file.

The type emits notifies every time the content between the brackets changes.

Parameters

The source parameter can either be a single file or a directory. In the latter case, all files in this directory are sorted by name and then concatenated.

Alternatively the inserted content can be specified directly as content => "string".

With ensure => absent the file_part can be removed again.

Discussion / Implementation notes

namevar

The namevar is used in the bracket tag and has to be puppet-globally unique since it is used as namevar. It would be nicer if one could write something like file_part { "/etc/munin/munin.conf#includes": and split the namevar on # (or any other sensible separator character to specify filename and tag.

Boundary conditions

The type should not modify the file or the containing directory if the current content and the target content match. This is important for integration with checksum.

If there is a definition for the whole file, this should emit notifies too, when the file_part changes. Perhaps a implicit definition could be created automatically?

The type should autorequire the source.