Puppet: System Administration Automated

Support

Some example subversion commit hooks

Pre-commit Parse Check

Here's a sanity check script which pulls out every file in the commit transaction, matches filenames(this example only looks for all .pp files under /puppet/trunk), and runs a parseonly on each of them:

#!/usr/bin/env ruby

TRUNK_REGEX    = /puppet\/trunk/
MANIFEST_REGEX = /\.pp$/

class CommitCmd
  attr_reader :status, :output, :cmd

  def initialize(cmd)
    @cmd    = cmd
    @status = nil
  end

  def run
    @output = `#{@cmd} 2>&1`
    @status = $?
  end
end

repos = ARGV[0]
txn   = ARGV[1]

if repos.nil? or txn.nil?
  puts "Invalid commands"
  exit(1)
end

filelistcmd = CommitCmd.new("/usr/bin/svnlook changed -t #{txn} #{repos}")
filelistcmd.run

if filelistcmd.status.exitstatus != 0
  puts "Error getting change list:"
  puts filelistcmd.output
  exit(1)
end

errors = []

workdir = "/tmp/puppet.commit.#{$$}"
Dir.mkdir(workdir)
ENV["HOME"] = workdir
ENV["RUBYLIB"] = "/path/to/libdir"

filestocleanup = []
filelistcmd.output.split("\n").each do |l|
  op = l[0..3].strip
  f  = l[4..-1].strip
  next if not ["U", "A"].include?(op)
  next if TRUNK_REGEX    !~ l
  next if MANIFEST_REGEX !~ l
  wf = f.gsub("/", ".")
  filestocleanup << wf
  filecatcmd = CommitCmd.new("/usr/bin/svnlook cat -t #{txn} #{repos} #{f} > #{workdir}/#{wf}")
  filecatcmd.run
  if filecatcmd.status.exitstatus != 0
    errors << "Error reading #{f}:\n  #{filecatcmd.output.gsub("\n", "\n  ")}"
    next
  end

  puppetcmd = CommitCmd.new("/usr/scea/puppet/bin/puppet --noop --color=false --parseonly --ignoreimport #{workdir}/#{wf}")
  puppetcmd.run
  if puppetcmd.status.exitstatus != 0
    errors << "Puppet errors in #{f}:\n  #{puppetcmd.output.gsub("\n", "\n  ")}"
    next
  end

end

 # cleanup
 begin
   filestocleanup.each do |f|
     File.unlink("#{workdir}/#{f}")
   end
   Dir.rmdir(workdir)
 rescue StandardError => e
   puts "Error cleaning up: #{e}"
end

# print errors
if not errors.empty?
  puts
  errors.each do |e|
    puts e
  end
  exit(errors.length)
end

exit(0)

It can be used as the pre-commit script, or you can reference it in a pre-commit script like:

#!/bin/bash

REPOS=$1
TXN=$2

exec $REPOS/hooks/manifestcheck $REPOS $TXN 1>&2