Pro Puppet (43 page)

Read Pro Puppet Online

Authors: Jeffrey McCune James Turnbull

BOOK: Pro Puppet
5.62Mb size Format: txt, pdf, ePub

Listing 8-6.
Placing a custom module into the Puppet module path

$ puppet-module build
========================================
Building /root/site-firewall for release
----------------------------------------
Done. Built: pkg/site-firewall-0.0.1.tar.gz
$ mv pkg/site-firewall-0.0.1 /etc/puppet/modules/firewall

The first command builds the module package and fills in the metadata for the module. The second command moves the built module into the puppet-module search path. We're now ready to try out the module and make sure the search path is working correctly. The operator uses
puppet apply –e
, shown in
Listing 8-7
, to evaluate a single class declaration.

Listing 8-7.
Using the iptables module by loading the firewall class

$ puppet apply -e 'include firewall' --noop
notice: /Iptables[100 Puppet Prod]: rules would have changed... (noop) in 0.00 seconds
$ puppet apply -e 'include firewall'
Saving firewall rules to /etc/sysconfig/iptables:          [  OK  ]
notice: /Iptables[100 Puppet Prod]: rules have changed... in 0.39 seconds

Finally, in
Listing 8-8
, the operator verifies the rules are properly being managed using the
iptables
command.

Listing 8-8.
Verifying that the iptables rules are being managed by Puppet

$ iptables -L INPUT -n
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     tcp  --  0.0.0.0              0.0.0.0             tcp dpt:8140 /* 100 Puppet
 Prod */
ACCEPT     tcp  --  0.0.0.0              0.0.0.0             tcp dpt:8142 /* 101 Puppet Dev */
ACCEPT     tcp  --  0.0.0.0              0.0.0.0             tcp dpt:8141 /* 101 Puppet
 Test */

Using the iptables command, we're able to see Puppet is correctly using the iptables module to manage the host-based firewall. In the next section we'll learn how the operator uses the puppet-module tool to build his own Puppet modules.

Creating a Module with the Puppet-Module Tool

The Puppet Forge is an excellent resource to download and re-use Puppet modules from the community. Modules you develop may also easily be published to the Forge. There are a number of benefits to publishing modules. First, people who use your modules may add functionality and help fix bugs, saving you time and effort. In addition, providing re-usable modules allows the Puppet community to focus on developing new functionality that could directly benefit you. Publishing your own modules also allows other Puppet users to save time and effort.

In this section, we'll see how the operator develops and publishes a small module to manage the NTP service on Debian and Redhat systems. It is important to keep in mind that modules published to the forge may be used on a wide variety of platforms. We'll learn how the operator uses conditionals in the Puppet manifests to clearly indicate when a particular platform is or is not supported.

Managing Modules with Git

As we learned in the previous section, the
puppet-module generate
command is useful for generating a skeleton module structure. This module structure is not directly usable by Puppet, and must first be built into a module package using the
build
action. To get started, the Example.com operator generates the skeleton structure and adds the tree to a Git repository to track changes and history, as shown in
Listing 8-9
.

Listing 8-9.
Using puppet-module generate and git add

$ cd ~/src/modules/
$ puppet-module generate operator-ntp
=====================================================
Generating module at /root/src/modules/operator-ntp
-----------------------------------------------------

$ cd operator-ntp
$ git init
Initialized empty Git repository in .git/
$ git add .
$ git commit -a -m 'Initial commit'
Created initial commit fb7d7b2: Initial commit
 17 files changed, 223 insertions(+), 0 deletions(-)
 create mode 100644 Modulefile
 create mode 100644 README
 create mode 100644 files/README.markdown
 create mode 100644 lib/puppet/facter/README.markdown
 create mode 100644 lib/puppet/parser/functions/README.markdown
 create mode 100644 lib/puppet/provider/README.markdown
 create mode 100644 lib/puppet/type/README.markdown
 create mode 100644 manifests/README.markdown
 create mode 100644 manifests/init.pp
 create mode 100644 metadata.json
 create mode 100644 spec/README.markdown
 create mode 100644 spec/spec.opts
 create mode 100644 spec/spec_helper.rb
 create mode 100644 spec/unit/puppet/provider/README.markdown
 create mode 100644 spec/unit/puppet/type/README.markdown
 create mode 100644 templates/README.markdown
 create mode 100644 tests/init.pp

With the newly generated NTP module, the operator uses the
git init
,
add
and
commit
actions to track the history of changes to the module. The module source code may then be published to the Internet using
http://github.com/
. Many module authors in the Puppet community publish their source code to github. Storing the module inside of a Git repository also allows the operator to track changes, tag releases, and quickly test out topic branches for new functionality.

Managing Platform-Specific Resources

The next step is to add functionality for a specific platform to the module. This module is designed to manage the NTP service and bind to a configurable set of upstream NTP servers. First, the operator adds support for Debian based systems. In
Listing 8-10
, he uses the new parameterized class feature of Puppet 2.6 to allow people using the module to specify the list of servers to synchronize against.

Listing 8-10.
Debian-specific functionality in the NTP module

$ vim manifests/init.pp
# Class: ntp
#
#   This module manages the ntp service.
#
#   Tested platforms:
#    - Debian 6.0 Squeeze
#
# Parameters:
#
#   $servers = [ "0.debian.pool.ntp.org iburst",
#                "1.debian.pool.ntp.org iburst",
#                "2.debian.pool.ntp.org iburst",
#                "3.debian.pool.ntp.org iburst", ]
#
# Actions:
#
#  Installs, configures, and manages the ntp service.
#
# Requires:
#
# Sample Usage:
#
#   class { "ntp": servers => [ 'time.apple.com' ] }
#
# [Remember: No empty lines between comments and class definition]
class ntp($servers=[ "0.debian.pool.ntp.org iburst",
                     "1.debian.pool.ntp.org iburst",
                     "2.debian.pool.ntp.org iburst",
                     "3.debian.pool.ntp.org iburst",],
          $ensure="running",
          $autoupdate=false
) {
  if ! ($ensure in [ "running", "stopped" ]) {
    fail("ensure parameter must be running or stopped")
  }
  if $autoupdate == true {
    $package_ensure = latest
  } elsif $autoupdate == false {
    $package_ensure = present
  } else {
    fail("autoupdate parameter must be true or false")
  }
  case $operatingsystem {
    debian, ubuntu: {
      $supported  = true
      $pkg_name   = [ "ntp" ]
      $svc_name   = "ntp"
      $config     = "/etc/ntp.conf"
      $config_tpl = "ntp.conf.debian.erb"
    }
    default: {
      $supported = false
      notify { "${module_name}_unsupported":
        message => "The ${module_name} module is not supported on ${operatingsystem}",
      }
    }
  }
  if ($supported == true) {
    package { $pkg_name:
      ensure => $package_ensure,
    }
    file { $config:
      ensure => file,
      owner  => 0,
      group  => 0,
      mode   => 0644,
      content => template("${module_name}/${config_tpl}"),
      require => Package[$pkg_name],
    }
    service { "ntp":
      ensure     => $ensure,
      name       => $svc_name,
      hasstatus  => true,
      hasrestart => true,
      subscribe  => [ Package[$pkg_name], File[$config] ],
    }
  }
}
Building and Testing a Puppet Module

Once the main NTP class has been filled in, the operator builds the module using the
puppet-module build
command. The process shown in
Listing 8-11
fills in the metadata for the module and creates a module usable by Puppet. He then moves this module into the module search path at
/etc/puppet/modules/ntp
to test the module. When building the module, make sure you are in the top level of the module directory structure containing the
Modulefile
file.

Listing 8-11.
Using the puppet-module build and install commands

$ puppet-module build
=======================================================
Building /root/src/modules/operator-ntp for release
-------------------------------------------------------
Done. Built: pkg/operator-ntp-0.0.1.tar.gz
$ cd /etc/puppet/modules
$ puppet-module install ~/src/modules/operator-ntp/pkg/operator-ntp-0.0.1.tar.gz
$ ln -s operator-ntp ntp

The operator first builds a new module package using the
puppet-module build
command. Once built, the operator changes directories to
/etc/puppet/modules
to install the module. The Puppet autoloader will not find the module unless it is in the “ntp” directory, because the main class is named ntp. To address this problem, the operator simply creates a symbolic link from NTP to the forge module name. This will allow future versions to easily replace the existing version.

A NOTE ABOUT MODULE NAMES

If Puppet cannot find a module with a name exactly matching the module being created, the following errors may be encountered. While building the NTP module, puppet-module creates a module named operator-ntp. This module should be renamed when installing the module to ensure the autoloader properly loads the class.

# puppet apply --verbose -e 'class { ntp: ensure => stopped }'
Puppet::Parser::AST::Resource failed with error ArgumentError: Invalid resource type class at line 1 on node debian.puppetlabs.vm
# puppet apply --verbose -e 'include ntp'
info: Could not find class ntp for debian.puppetlabs.vm
Could not find class ntp at line 1 on node debian.puppetlabs.vm

Both of these errors may be corrected by symbolically linking /etc/puppet/modules/ntp to /etc/puppet/modules/operator-ntp after installing the module with puppet-module install.

It's now time to test out the newly developed module. To make sure the autoloader properly finds the NTP module, in
Listing 8-12
the operator executes a simple
puppet apply
command evaluating a single class declaration.

Listing 8-12.
Testing a new Puppet module with puppet apply on Debian

$ puppet apply --verbose -e 'class { ntp: ensure => running}'
info: Applying configuration version '1298492452'
notice: /Stage[main]/Ntp/Package[ntp]/ensure: ensure changed 'purged' to 'present'
info: /Stage[main]/Ntp/Package[ntp]: Scheduling refresh of Service[ntp]
info: FileBucket got a duplicate file /etc/ntp.conf ({md5}3e250ecaf470e1d3a2b68edd5de46bfd)
info: /Stage[main]/Ntp/File[/etc/ntp.conf]: Filebucketed /etc/ntp.conf to puppet with sum
 3e250ecaf470e1d3a2b68edd5de46bfd
notice: /Stage[main]/Ntp/File[/etc/ntp.conf]/content: content changed
 '{md5}3e250ecaf470e1d3a2b68edd5de46bfd' to '{md5}6e3461437c627101cf53e634abc62400'
info: /Stage[main]/Ntp/File[/etc/ntp.conf]: Scheduling refresh of Service[ntp]
notice: /Stage[main]/Ntp/Service[ntp]: Triggered 'refresh' from 2 events
$ puppet apply --verbose -e 'class { ntp: ensure => running }'
info: Applying configuration version '1298492574'

Other books

Shopgirls by Pamela Cox
Conspiracy by Black, Dana
Old Sins by Penny Vincenzi
Remembering Smell by Bonnie Blodgett
El Rabino by Noah Gordon
Unlucky in Law by Perri O'Shaughnessy
Lord of Light by Roger Zelazny