Puppet
Introduction
Puppet is a well-known open source configuration & system management tool.
Puppet Issues
Random issues noted by puppet users.
- Naginator in recent versions is broken on nagios < 3.0
- the Interface type has gone away (use templates - see http://reductivelabs.com/trac/puppet/wiki/NetworkInterfacesTemplate)
- Caching issues - these seem to crop up all the time. Possible fixes depending on the case:
- Restart puppetmasterd
- Clear out state files e.g. /var/lib/puppet/state/* on the client
- Clear out cached node(s) and/or facts e.g. /var/lib/puppet/yaml/*/* on the puppetmaster server(s)
- contact_groups not a valid attribute of Nagios_host?! WTF? Bug in 0.24.4
Puppet Links
- Puppet Home
- Puppet at Google - RedMonk Radio Episode 48
- Puppet Video Interview with Luke Kanies - Part 1
- Puppet Video Interview with Luke Kanies - Part 2 Bootstrapping on Open Source Company
- Puppet on FreeBSD
- Puppet on Debian
- Puppet For Mac Workstation Configuration Management - a presentation from Ski Kacoroski about BitPusher's deployment of Puppet for Northshore School District.
Installation
Operations
Trigger a client run
You can send puppetd (client) a USR1 signal to trigger it to run. I usually tack on the syslog tailer to see what it's doing.
# ps ax | grep pupp 9605 ? Ssl 3:43 ruby /usr/sbin/puppetd -w 0 ... # kill -USR1 9605; tail -f /var/log/syslog
This way also works (e.g. on Debian) if you know the pid path...
kill -USR1 `cat /var/run/puppet/puppetd.pid`; tail -f /var/log/syslog
Parsing a (class) file
This is how to do a a syntax check on a file.
puppet --parseonly --ignoreimport <filename> #e.g. ruby-server.pp err: Could not parse for environment development: Syntax error at ';'; expected ']' at /etc/puppet/manifests/classes/ruby-server.pp:2
Providers
Users
Make sure to install libshadow-ruby1.8 on Debian/Ubuntu or libshadow on Fedora/Red Hat/CentOS
In a @user declaration, when specifying a password, do not use double-quote... instead use single-quotes, e.g.
password => '$1$LU.r1qgx$XbcRiNjgXc3ZDtuJaOu4n0'
Otherwise the $ will trigger interpolation.
Packages
Gems
This example shows how to install a specific version of a gem.
package { "cached_model": ensure => "1.2.1", provider => gem }
Resource Relationships
Metaparameters such as before, subscribe, notify and ensure can be used to designate relationships between resources.
before
Use before to indicate that this resource has to be applied first, before something else.
require
This should be used to indicate that some other resource is a prerequisite.
file { sshd_config: ... require => Package[ssh] }
This says "make sure the ssh package (defined elsewhere as a package resource) is installed before applying this file resource".
ensure
Ways to use ensure.
Ensure the latest version of a package is installed.
package { ssh: ensure => latest, ... }
Ensure a specific version of a packages is installed
(See the gem example above)
Ensure a service is running.
service { snmpd: ensure => running, ... }
Ensure a file exists.
file { "/some/file": ensure => exists, ... }
Ensure a directory exists. (Confusing as it appears in a file resource.
file { "/some/folder": ensure => directory, ... }
Ensure a soft-link exists.
file { "/some/file": ensure => link, target => "/some/existing/file" }
Ensure a package is absent i.e. not installed
package { "smartd": ensure => absent }
subscribe
The 'subscribe' attribute in a service causes the service to restart if the configuration file changes.
service { "foo": subscribe => File["foo.conf"], ... }
Puppet Types
file
Create a soft-link (Example)
file { "/var/log/apache": ensure => link, target => "/var/log/apache2", }
Overloading
You can do things like this with existing types...
Package { require => Exec["apt-get update]" }
For inherited resource types, you can modify attributes. Don't try this with (simply) included resources.
File["/etc/nsswitch.conf] { group => foo }
Puppet development
In order to work on new features and bugfixes for puppet here is how I set that up. (See this link also.
First, install the pre-reqs.
aptitude install libxmlrpc-ruby, libopenssl-ruby libshadow-ruby
Check out the puppet code
mkdir -p ~/git && cd ~/git git clone git://github.com/puppetlabs/puppet
This puts everything in ~/git/puppet
.
cd puppet sudo ./install.rb
I proceed to make my changes.
mdf@sushi:~/git/puppet$ vi lib/puppet/type/package.rb mdf@sushi:~/git/puppet$ ruby -c lib/puppet/type/package.rb Syntax OK
- Test changes (TBD)
sudo /usr/sbin/puppetd --no-daemonize --verbose
- Create diffs for my changes
cd ~/git/puppet git diff
Package install problems
Various packages will fail to install via puppet.
Java
Most common difficulty is install java automatically under Ubuntu, because apt wants some interaction to accept the license agreement. The exec below will lay down the file indicating acceptance (via require). Same methodology can be used for other packages which enforce user interaction.
case $operatingsystem { debian,ubuntu: { exec {"pre-accept-sun-dlj": path => "/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin", cwd => "/tmp", command => 'echo "sun-java6-bin shared/accepted-sun-dlj-v1-1 boolean true" | debconf-set-selections && touch /var/lib/puppet/state/accepted-sun-dlj-v1-1', unless => "test -e /var/lib/puppet/state/accepted-sun-dlj-v1-1", } } }
Dell OMSA
Another case is OMSA and any packages that are either un-signed or signed by an untrusted source. If it an a PPA repo (see launchpad) you can require the key be installed.
file {"bp-ppa": name => "/etc/apt/sources.list.d/bp-ppa.list", content => template("bitpusher/etc/apt/sources.list.d/bp-ppa.list"), owner => root, group => root, notify => Exec["install-ppa-key"], } exec { "install-ppa-key": command => "/usr/bin/wget -O - http://www.bitpusher.com/ppa.key | /usr/bin/apt-key add -", refreshonly => true, unless => "/usr/bin/apt-key list | grep 63FF8D62", notify => Exec["apt-update"], require => Package[gnupg], }