Puppet Notes
Puppet failed my “First 5 Minutes Test” (TM), so I feel obliged to write down what I expect from a software distribution to offer me during our first five minutes together.
The Good
What are my objectives and therefore, what do I want to know during the first 5 minutes I start working with a new software tool? Simple: I want to install it on my localhost and use it to do something simple, end-to-end.
In the case of Puppet I wanted to install it and use it to install OpenLDAP, which I had done the day before manually.
The Bad
Even Google doesn’t really help here… There doesn’t seem to be an official introduction-like tutorial that quickly glances over the concepts, simply states what is needed and why and where to get it. I had to look for non-official blogposts to collect pieces of information to get to …
The Ugly
What I got was:
- download links to Virtual Machines
- requirements for three host-networks
- required DNS servers
- …
Really?
First 5 Minutes…
- Download Facter, Hiera and Puppet from http://downloads.puppetlabs.com/mac/ and install them in that order.
- Facter is a system profiling library.
- Hiera is a key/value store for site-wide configuration
- Puppet … duh … the installation system itself of course ;-)
- Perform manual (??!!) install/configuration (via: https://docs.puppetlabs.com/guides/install_puppet/install_osx.html)
$ sudo puppet resource group puppet ensure=present
group { 'puppet':
ensure => 'present',
}
$ sudo puppet resource user puppet ensure=present gid=puppet shell='/sbin/nologin'
Notice: /User[puppet]/shell: defined 'shell' as '/sbin/nologin'
user { 'puppet':
ensure => 'present',
gid => '495',
}
- Create
/Library/LaunchDaemons/com.puppetlabs.puppet.plist
:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.puppetlabs.puppet</string>
<key>OnDemand</key>
<false/>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/puppet</string>
<string>agent</string>
<string>--no-daemonize</string>
<string>--logdest</string>
<string>syslog</string>
<string>--color</string>
<string>false</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>ServiceDescription</key>
<string>Puppet agent service</string>
<key>ServiceIPC</key>
<false/>
<!-- added to log to own files, not system.log -->
<key>StandardErrorPath</key>
<string>/var/log/puppet/puppet.err</string>
<key>StandardOutPath</key>
<string>/var/log/puppet/puppet.out</string>
</dict>
</plist>
$ sudo chown root:wheel /Library/LaunchDaemons/com.puppetlabs.puppet.plist
$ sudo chmod 644 /Library/LaunchDaemons/com.puppetlabs.puppet.plist
$ sudo mkdir /var/log/puppet
$ sudo chown puppet:puppet /var/log/puppet
$ sudo chmod 755 /var/log/puppet
-
Perform manual (??!!) post-install configuration (via: https://docs.puppetlabs.com/guides/install_puppet/post_install.html)
-
Create
/etc/puppet/puppet.conf
:
[main]
dns_alt_names = playground.local
server=playground.local
[agent]
report=true
$ sudo puppet master --verbose --no-daemonize
Info: Creating a new SSL key for ca
Info: Creating a new SSL certificate request for ca
Info: Certificate Request fingerprint (SHA256): BC:FF:43:B5:5D:87:E7:FB:43:...
Notice: Signed certificate request for ca
Info: Creating a new certificate revocation list
Info: Creating a new SSL key for playground.local
Info: csr_attributes file loading from /etc/puppet/csr_attributes.yaml
Info: Creating a new SSL certificate request for playground.local
Info: Certificate Request fingerprint (SHA256): 69:A9:0D:A1:7D:C3:08:B4:83:...
Notice: playground.local has a waiting certificate request
Notice: Signed certificate request for playground.local
Notice: Removing file Puppet::SSL::CertificateRequest playground.local at '/etc/puppet/ssl/ca/requests/playground.local.pem'
Notice: Removing file Puppet::SSL::CertificateRequest playground.local at '/etc/puppet/ssl/certificate_requests/playground.local.pem'
Notice: Starting Puppet master version 3.7.4
^CNotice: Caught INT; calling stop
- Create an (for now) empty
site.pp
:
$ sudo touch /etc/puppet/manifests/site.pp
- Create
/Library/LaunchDaemons/com.puppetlabs.puppetmaster.plist
:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.puppetlabs.puppetmaster</string>
<key>OnDemand</key>
<false/>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/puppet</string>
<string>master</string>
<string>--verbose</string>
<string>--no-daemonize</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>ServiceDescription</key>
<string>Puppetmaster service</string>
<key>ServiceIPC</key>
<false/>
<!-- added to log to own files, not system.log -->
<key>StandardErrorPath</key>
<string>/var/log/puppet/puppet.err</string>
<key>StandardOutPath</key>
<string>/var/log/puppet/puppet.out</string>
</dict>
</plist>
$ sudo chown root:wheel /Library/LaunchDaemons/com.puppetlabs.puppet.plist
$ sudo chmod 644 /Library/LaunchDaemons/com.puppetlabs.puppet.plist
- Start master and agent …
$ sudo puppet resource service com.puppetlabs.puppet ensure=running enable=true
Notice: /Service[com.puppetlabs.puppet]/ensure: ensure changed 'stopped' to 'running'
service { 'com.puppetlabs.puppet':
ensure => 'absent',
}
$ sudo puppet resource service com.puppetlabs.puppetmaster ensure=running Notice: /Service[com.puppetlabs.puppetmaster]/ensure: ensure changed 'stopped' to 'running'
service { 'com.puppetlabs.puppetmaster':
ensure => 'absent',
}
- To avoid error messages … create a dummy module
foo
and afact.d
directory in it:
$ sudo mkdir -p /etc/puppet/modules/foo/facts.d
- test …
$ sudo puppet agent --test
Info: Retrieving pluginfacts
Notice: /File[/var/lib/puppet/facts.d]/group: group changed 'puppet' to 'wheel'
Info: Retrieving plugin
Notice: /File[/var/lib/puppet/lib]/group: group changed 'puppet' to 'wheel'
Info: Caching catalog for playground.local
Info: Applying configuration version '1423825915'
Notice: Finished catalog run in 0.01 seconds
The notices can safely be ignored. That’s puppet improving on its own configuration :-)
Installing OpenLDAP using Puppet
- Prepare the module tree structure:
$ sudo mkdir -p /etc/puppet/modules/openldap/{facts.d,manifests}
- Create
/etc/puppet/modules/openldap/manifests/init.pp
:
class openldap {
package { 'openldap':
ensure => installed,
provider => 'macports'
}
}
- Configure the agent/client in
/etc/puppet/manifests/site.pp
:
node default { }
node 'playground.local' {
include openldap
}
- Now wait .. until the agent and master talk to each other and update the agent’s configuration, or trigger the update yourself:
$ sudo port uninstall openldap
---> Deactivating openldap @2.4.40_0
---> Cleaning openldap
---> Uninstalling openldap @2.4.40_0
---> Cleaning openldap
$ port contents openldap
Port openldap is not installed.
$ sudo puppet agent --test
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Caching catalog for playground.local
Info: Applying configuration version '1423832966'
Notice: /Stage[main]/Openldap/Package[openldap]/ensure: created
Notice: Finished catalog run in 4.37 seconds
$ port contents openldap
Port openldap contains:
/Library/LaunchDaemons/org.macports.slapd.plist
/opt/local/bin/ldapadd
/opt/local/bin/ldapcompare
...
Intermezzo
Puppet’s architecture with agents and master(s) makes sense, but if the end goal is to manage a single host, a more basic setup can be constructed, just with puppet
and a manifest file.
Given openldap.pp
, e.g. in ~/manifests
:
package { 'openldap':
ensure => installed,
provider => 'macports'
}
We can simply use puppet apply
…
$ sudo puppet apply --test openldap.pp
Notice: Compiled catalog for playground.local in environment production in 0.38 seconds
Info: Applying configuration version '1423833802'
Notice: /Stage[main]/Main/Package[openldap]/ensure: created
Notice: Finished catalog run in 3.23 seconds
Now add Git(Hub) in the mix … :-)
TODO
- add configuration using templates + variables
- start/stop service
- add more background