diff --git a/Gemfile b/Gemfile index 783e522..d5738af 100644 --- a/Gemfile +++ b/Gemfile @@ -1,21 +1,20 @@ source 'https://rubygems.org' group :development, :test do gem 'rake', :require => false gem 'rspec-puppet', :require => false gem 'puppetlabs_spec_helper', :require => false gem 'rspec-system-puppet', :require => false gem 'puppet-lint', :require => false gem 'serverspec', :require => false gem 'rspec-system-serverspec', :require => false gem 'pry', :require => false - gem 'vagrant-wrapper', :require => false end if puppetversion = ENV['PUPPET_GEM_VERSION'] gem 'puppet', puppetversion, :require => false else gem 'puppet', :require => false end # vim:ft=ruby diff --git a/README.markdown b/README.markdown index c9a52b3..9580c9d 100644 --- a/README.markdown +++ b/README.markdown @@ -1,154 +1,154 @@ What is it? =========== A Puppet module that can construct files from fragments. Please see the comments in the various .pp files for details as well as posts on my blog at http://www.devco.net/ Released under the Apache 2.0 licence Usage: ------ If you wanted a /etc/motd file that listed all the major modules on the machine. And that would be maintained automatically even if you just remove the include lines for other modules you could use code like below, a sample /etc/motd would be:
 Puppet modules on this server:
 
     -- Apache
     -- MySQL
 
Local sysadmins can also append to the file by just editing /etc/motd.local their changes will be incorporated into the puppet managed motd.
 # class to setup basic motd, include on all nodes
 class motd {
    $motd = "/etc/motd"
 
    concat{$motd:
       owner => root,
       group => root,
       mode  => '0644',
    }
 
    concat::fragment{"motd_header":
       target => $motd,
       content => "\nPuppet modules on this server:\n\n",
       order   => 01,
    }
 
    # local users on the machine can append to motd by just creating
    # /etc/motd.local
    concat::fragment{"motd_local":
       target => $motd,
       ensure  => "/etc/motd.local",
       order   => 15
    }
 }
 
 # used by other modules to register themselves in the motd
 define motd::register($content="", $order=10) {
    if $content == "" {
       $body = $name
    } else {
       $body = $content
    }
 
    concat::fragment{"motd_fragment_$name":
       target  => "/etc/motd",
       content => "    -- $body\n"
    }
 }
 
 # a sample apache module
 class apache {
    include apache::install, apache::config, apache::service
 
    motd::register{"Apache": }
 }
 
Detailed documentation of the class options can be found in the manifest files. Known Issues: ------------- * Since puppet-concat now relies on a fact for the concat directory, - you will need to set up pluginsync = true on the [master] section of your + you will need to set up pluginsync = true on both the master and client node's '/etc/puppet/puppet.conf' for at least the first run. You have this issue if puppet fails to run on the client and you have a message similar to "err: Failed to apply catalog: Parameter path failed: File paths must be fully qualified, not 'undef' at [...]/concat/manifests/setup.pp:44". Contributors: ------------- **Paul Elliot** * Provided 0.24.8 support, shell warnings and empty file creation support. **Chad Netzer** * Various patches to improve safety of file operations * Symlink support **David Schmitt** * Patch to remove hard coded paths relying on OS path * Patch to use file{} to copy the resulting file to the final destination. This means Puppet client will show diffs and that hopefully we can change file ownerships now **Peter Meier** * Basedir as a fact * Unprivileged user support **Sharif Nassar** * Solaris/Nexenta support * Better error reporting **Christian G. Warden** * Style improvements **Reid Vandewiele** * Support non GNU systems by default **Erik Dalén** * Style improvements **Gildas Le Nadan** * Documentation improvements **Paul Belanger** * Testing improvements and Travis support **Branan Purvine-Riley** * Support Puppet Module Tool better **Dustin J. Mitchell** * Always include setup when using the concat define **Andreas Jaggi** * Puppet Lint support **Jan Vansteenkiste** * Configurable paths Contact: -------- puppet-users@ mailing list. diff --git a/files/concatfragments.sh b/files/concatfragments.sh index 570d553..88fe0e7 100755 --- a/files/concatfragments.sh +++ b/files/concatfragments.sh @@ -1,140 +1,140 @@ #!/bin/sh # Script to concat files to a config file. # # Given a directory like this: # /path/to/conf.d # |-- fragments # | |-- 00_named.conf # | |-- 10_domain.net # | `-- zz_footer # # The script supports a test option that will build the concat file to a temp location and # use /usr/bin/cmp to verify if it should be run or not. This would result in the concat happening # twice on each run but gives you the option to have an unless option in your execs to inhibit rebuilds. # # Without the test option and the unless combo your services that depend on the final file would end up # restarting on each run, or in other manifest models some changes might get missed. # # OPTIONS: # -o The file to create from the sources # -d The directory where the fragments are kept # -t Test to find out if a build is needed, basically concats the files to a temp # location and compare with what's in the final location, return codes are designed # for use with unless on an exec resource # -w Add a shell style comment at the top of the created file to warn users that it # is generated by puppet # -f Enables the creation of empty output files when no fragments are found # -n Sort the output numerically rather than the default alpha sort # # the command: # # concatfragments.sh -o /path/to/conffile.cfg -d /path/to/conf.d # # creates /path/to/conf.d/fragments.concat and copies the resulting # file to /path/to/conffile.cfg. The files will be sorted alphabetically # pass the -n switch to sort numerically. # # The script does error checking on the various dirs and files to make # sure things don't fail. OUTFILE="" WORKDIR="" TEST="" FORCE="" WARN="" SORTARG="" ENSURE_NEWLINE="" PATH=/sbin:/usr/sbin:/bin:/usr/bin ## Well, if there's ever a bad way to do things, Nexenta has it. ## http://nexenta.org/projects/site/wiki/Personalities unset SUN_PERSONALITY while getopts "o:s:d:tnw:fl" options; do case $options in o ) OUTFILE=$OPTARG;; d ) WORKDIR=$OPTARG;; n ) SORTARG="-n";; w ) WARNMSG="$OPTARG";; f ) FORCE="true";; t ) TEST="true";; l ) ENSURE_NEWLINE="true";; * ) echo "Specify output file with -o and fragments directory with -d" exit 1;; esac done # do we have -o? if [ x${OUTFILE} = "x" ]; then echo "Please specify an output file with -o" exit 1 fi # do we have -d? if [ x${WORKDIR} = "x" ]; then echo "Please fragments directory with -d" exit 1 fi # can we write to -o? if [ -f ${OUTFILE} ]; then if [ ! -w ${OUTFILE} ]; then echo "Cannot write to ${OUTFILE}" exit 1 fi else if [ ! -w `dirname ${OUTFILE}` ]; then echo "Cannot write to `dirname ${OUTFILE}` to create ${OUTFILE}" exit 1 fi fi # do we have a fragments subdir inside the work dir? if [ ! -d "${WORKDIR}/fragments" ] && [ ! -x "${WORKDIR}/fragments" ]; then echo "Cannot access the fragments directory" exit 1 fi # are there actually any fragments? if [ ! "$(ls -A ${WORKDIR}/fragments)" ]; then if [ x${FORCE} = "x" ]; then echo "The fragments directory is empty, cowardly refusing to make empty config files" exit 1 fi fi cd ${WORKDIR} if [ "x${WARNMSG}" = "x" ]; then : > "fragments.concat" else printf '%s\n' "$WARNMSG" > "fragments.concat" fi if [ x${ENSURE_NEWLINE} != x ]; then find fragments/ -type f -follow -print0 | xargs -0 -I '{}' sh -c 'if [ -n "$(tail -c 1 < {} )" ]; then echo >> {} ; fi' fi # find all the files in the fragments directory, sort them numerically and concat to fragments.concat in the working dir IFS_BACKUP=$IFS IFS=' ' -for fragfile in `find fragments/ -type f -follow | LANG=C sort ${SORTARG}` +for fragfile in `find fragments/ -type f -follow | LC_ALL=C sort ${SORTARG}` do cat $fragfile >> "fragments.concat" done IFS=$IFS_BACKUP if [ x${TEST} = "x" ]; then # This is a real run, copy the file to outfile cp fragments.concat ${OUTFILE} RETVAL=$? else # Just compare the result to outfile to help the exec decide cmp ${OUTFILE} fragments.concat RETVAL=$? fi exit $RETVAL diff --git a/manifests/setup.pp b/manifests/setup.pp index 2d29bf8..55d7197 100644 --- a/manifests/setup.pp +++ b/manifests/setup.pp @@ -1,55 +1,59 @@ # === Class: concat::setup # # Sets up the concat system. # # [$concatdir] # is where the fragments live and is set on the fact concat_basedir. # Since puppet should always manage files in $concatdir and they should # not be deleted ever, /tmp is not an option. # # [$puppetversion] # should be either 24 or 25 to enable a 24 compatible # mode, in 24 mode you might see phantom notifies this is a side effect # of the method we use to clear the fragments directory. # # The regular expression below will try to figure out your puppet version # but this code will only work in 0.24.8 and newer. # # It also copies out the concatfragments.sh file to ${concatdir}/bin # class concat::setup { $id = $::id $root_group = $id ? { root => 0, default => $id } if $::concat_basedir { $concatdir = $::concat_basedir } else { - fail ("\$concat_basedir not defined. Try running again with pluginsync=true on the [master] section of your node's '/etc/puppet/puppet.conf'.") + fail ("\$concat_basedir not defined. Try running again with pluginsync=true on the [master] and/or [main] section of your node's '/etc/puppet/puppet.conf'.") } $majorversion = regsubst($::puppetversion, '^[0-9]+[.]([0-9]+)[.][0-9]+$', '\1') $fragments_source = $majorversion ? { 24 => 'puppet:///concat/concatfragments.sh', default => 'puppet:///modules/concat/concatfragments.sh' } file{"${concatdir}/bin/concatfragments.sh": owner => $id, group => $root_group, mode => '0755', source => $fragments_source; [ $concatdir, "${concatdir}/bin" ]: ensure => directory, owner => $id, group => $root_group, mode => '0750'; ## Old versions of this module used a different path. '/usr/local/bin/concatfragments.sh': ensure => absent; } + + # Ensure we run setup first. + Class['concat::setup'] -> Concat::Fragment<| |> + }