1 # A system to construct files using fragments from other files or templates.
3 # This requires at least puppet 0.25 to work correctly as we use some
4 # enhancements in recursive directory management and regular expressions
8 # The basic use case is as below:
10 # concat{"/etc/named.conf":
11 # notify => Service["named"]
14 # concat::fragment{"foo.com_config":
15 # target => "/etc/named.conf",
17 # content => template("named_conf_zone.erb")
20 # # add a fragment not managed by puppet so local users
21 # # can add content to managed file
22 # concat::fragment{"foo.com_user_config":
23 # target => "/etc/named.conf",
25 # ensure => "/etc/named.conf.local"
28 # This will use the template named_conf_zone.erb to build a single
29 # bit of config up and put it into the fragments dir. The file
30 # will have an number prefix of 10, you can use the order option
31 # to control that and thus control the order the final file gets built in.
33 # You can also specify a path and use a different name for your resources:
35 # # You can make this something dynamic, based on whatever parameters your
36 # # module/class for example.
37 # $vhost_file = '/etc/httpd/vhosts/01-my-vhost.conf'
39 # concat{'apache-vhost-myvhost':
40 # path => $vhost_file,
43 # # We don't care where the file is located, just what to put in it.
44 # concat::fragment {'apache-vhost-myvhost-main':
45 # target => 'apache-vhost-myvhost',
46 # content => '<virtualhost *:80>',
50 # concat::fragment {'apache-vhost-myvhost-close':
51 # target => 'apache-vhost-myvhost',
52 # content => '</virtualhost>',
58 # The class concat::setup uses the fact concat_basedir to define the variable
59 # $concatdir, where all the temporary files and fragments will be
60 # durably stored. The fact concat_basedir will be set up on the client to
61 # <Puppet[:vardir]>/concat, so you will be able to run different setup/flavours
63 # However, since this requires the file lib/facter/concat_basedir.rb to be
64 # deployed on the clients, so you will have to set "pluginsync = true" on
65 # both the master and client, at least for the first run.
67 # There's some regular expression magic to figure out the puppet version but
68 # if you're on an older 0.24 version just set $puppetversion = 24
71 # We use a helper shell script called concatfragments.sh that gets placed
72 # in <Puppet[:vardir]>/concat/bin to do the concatenation. While this might
73 # seem more complex than some of the one-liner alternatives you might find on
74 # the net we do a lot of error checking and safety checks in the script to avoid
75 # problems that might be caused by complex escaping errors etc.
81 # http://github.com/ripienaar/puppet-concat/
84 # R.I.Pienaar <rip@devco.net>
86 # @ripienaar on twitter
90 # Sets up so that you can use fragments to build a final config file,
93 # - path The path to the final file. Use this in case you want to
94 # differentiate between the name of a resource and the file path.
95 # Note: Use the name you provided in the target of your
97 # - mode The mode of the final file
98 # - owner Who will own the file
99 # - group Who will own the file
100 # - force Enables creating empty files if no fragments are present
101 # - warn Adds a normal shell style comment top of the file indicating
102 # that it is built by puppet
103 # - backup Controls the filebucketing behavior of the final file and
104 # see File type reference for its use. Defaults to 'puppet'
105 # - replace Whether to replace a file that already exists on the local
109 # - Creates fragment directories if it didn't exist already
110 # - Executes the concatfragments.sh script to build the final file, this
111 # script will create directory/fragments.concat. Execution happens only
113 # * The directory changes
114 # * fragments.concat != final destination, this means rebuilds will happen
115 # whenever someone changes or deletes the final file. Checking is done
116 # using /usr/bin/cmp.
117 # * The Exec gets notified by something else - like the concat::fragment
119 # - Copies the file over to the final destination using a file resource
122 # - The exec can notified using Exec["concat_/path/to/file"] or
123 # Exec["concat_/path/to/directory"]
124 # - The final file can be referened as File["/path/to/file"] or
125 # File["concat_/path/to/file"]
129 $group = $concat::setup::root_group,
138 include concat::setup
140 $safe_name = regsubst($name, '/', '_', 'G')
141 $concatdir = $concat::setup::concatdir
142 $version = $concat::setup::majorversion
143 $fragdir = "${concatdir}/${safe_name}"
144 $concat_name = 'fragments.concat.out'
145 $default_warn_message = '# This file is managed by Puppet. DO NOT EDIT.'
148 'true', true, yes, on: {
149 $warnmsg = $default_warn_message
151 'false', false, no, off: {
159 $warnmsg_escaped = regsubst($warnmsg, "'", "'\\\\''", 'G')
160 $warnflag = $warnmsg_escaped ? {
162 default => "-w '${warnmsg_escaped}'"
166 'true', true, yes, on: {
169 'false', false, no, off: {
173 fail("Improper 'force' value given to concat: ${force}")
185 fail("Improper 'order' value given to concat: ${order}")
201 $source_real = $version ? {
202 24 => 'puppet:///concat/null',
206 file { "${fragdir}/fragments":
209 ignore => ['.svn', '.git', '.gitignore'],
210 notify => Exec["concat_${name}"],
213 source => $source_real,
216 file { "${fragdir}/fragments.concat":
220 file { "${fragdir}/${concat_name}":
227 alias => "concat_${name}",
231 source => "${fragdir}/${concat_name}",
234 exec { "concat_${name}":
235 alias => "concat_${fragdir}",
236 command => "${concat::setup::concatdir}/bin/concatfragments.sh -o ${fragdir}/${concat_name} -d ${fragdir} ${warnflag} ${forceflag} ${orderflag}",
237 notify => File[$name],
240 File["${fragdir}/fragments"],
241 File["${fragdir}/fragments.concat"],
243 subscribe => File[$fragdir],
244 unless => "${concat::setup::concatdir}/bin/concatfragments.sh -o ${fragdir}/${concat_name} -d ${fragdir} -t ${warnflag} ${forceflag} ${orderflag}",
248 Exec["concat_${name}"] {
255 # vim:sw=2:ts=2:expandtab:textwidth=79