The Puppet Labs Issue Tracker has Moved: https://tickets.puppetlabs.com

Version 1/2 - Next ยป - Current version
Anonymous, 03/13/2010 08:02 pm


Puppet Syntax Checking

Puppet can perform a syntax check of your manifests using the —parseonly option. This is a great way to very quickly check all of your manifests to make sure you have not made syntax errors. The checking will not, however, verify things such as misspelled file names and other values in strings. One way you can perform a more thorough check is to generate the catalog using the “puppetmasterd —compile node-name” command. Here is a simple script which you can adapt to your needs to check all your manifests.

A script to test your nodes

This script runs through all the files in the manifests/nodes directory and presumes each node has a file named the same as the node_name.pp.:

#! /usr/bin/env ruby
exit_code = 0
Dir[File.expand_path(File.dirname(__FILE__)) + '/manifests/nodes/*'].each do |file|
  node= File.basename(file, '.pp')
  puts "Processing  #{node}"
  `puppetmasterd --compile #{node}`
  exit_code =  $? unless exit_code != 0
end

exit exit_code

Although you can use a script like this as your pre-commit hook be aware that this will take significantly longer than a simple syntax check and may be inappropriate if you have lots of nodes.

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