Recipe for Building Multipart Files

Description

This is a simple recipe to show how to build multi-part files using Puppet. It also demonstrates how to restart a service when the files have been changed.

It is true that Augeas may have much, if not all, of this functionality for those cases where a lens is present, but I find this helpful for building files with distinct sections, such as /etc/nsswitch.conf.

Global Items

In this case, I’m using a couple of global variables to collect everything in one spot. You could, of course, specify the variables, but I find this to be simpler for most cases.

$compdir = "/tmp/foo"
$target_file = "/tmp/bar"

file { "$compdir":
   ensure => "directory"
}

Multibuild Class

class multibuild {

    # Clean it all up
    tidy { "$compdir/subdir":
        size => "0b",
        recurse => true,
        rmdirs => true
    }

    # The compilation directory
    file { "$compdir/subdir":
        ensure => "directory",
        require => Tidy["$compdir/subdir"]
    }

    # How to add stuff to the file
    define add_segment ( $content ) {
        file { "$compdir/subdir/${name}.content":
            ensure => "present",
            content => "$content\n",
            require => File["$compdir/subdir"],
            notify => Exec["compile_segments"]
        }
    }

    file { "$target_file":
        ensure => "present",
        checksum => "md5",
        require => Exec["compile_segments"],
        notify => Exec["demo_refresh_output"]
    }

    exec { "compile_segments":
        command => "/bin/cat *.content > $target_file",
        refreshonly => "true",
        cwd => "$compdir/subdir",
        notify => Exec["demo_refresh_output"]
    }

    exec { "demo_refresh_output":
        command => "/bin/echo 'This could be a service.'",
        refreshonly => "true",
        logoutput => "true"
    }
}

Sample Execution

include "multibuild"

multibuild::add_segment { "test1": content => "This is test 1" }
multibuild::add_segment { "test2": content => "This is test 2" }
multibuild::add_segment { "test4": content => "This is test 4" }
multibuild::add_segment { "test3": content => "This is test 3" }