Pro Puppet (45 page)

Read Pro Puppet Online

Authors: Jeffrey McCune James Turnbull

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

As we can see, the NTP service is being properly managed and brought online for both Enterprise Linux and Debian systems. The operator commits this change to the Git repository using the commands in
Listing 8-20
before publishing the module to the Forge.

Listing 8-20.
Final commit before publishing to the Forge

$ cd ~/src/modules/operator-ntp
$ git add *
$ git commit -m 'Add Enterprise Linux support'
$ git tag 0.0.2

The operator is able to track when this version of the NTP module was released to the Forge by using the
git tag
action. Finally, he's ready to publish the package created by the
puppet-module build
command. Doing so requires registration at
http://forge.puppetlabs.com/
. For up-to-date information about how to publish a module, please log into the Forge and use the “Add a Module” link located at:
http://forge.puppetlabs.com/modules/new.

You've just seen how the Example.com operator uses the puppet-module tool to install a module from the Puppet Forge. The iptables module allowed the operator to quickly manage host-based firewall rules without writing his own module from scratch. In addition, we saw how the operator quickly generated a skeleton module structure, and added a few resources to the NTP class to manage time synchronization. In the next section you'll see how the Ruby DSL allows the Example.com developer to leverage Ruby to declare resources and classes in the configuration catalog.

Puppet Ruby DSL

The Ruby DSL included in Puppet 2.6 provides the full power of the Ruby language directly in Puppet Modules. Within a single module, manifest files may be written in either of the Puppet or Ruby languages. These manifest files may be intermixed in the same catalog compilation. The file extension determines the language used; manifests with a “pp” or “rb” extension indicate a Puppet or Ruby manifest, respectively. For most problems and configurations, the simple language of Puppet manifests are more than adequate. However, in the situation where a dynamic data set is accessed through the ENC API, the Ruby DSL is an ideal solution to the problem of declaring resources from the data. Ruby's ability to iterate over Hashes and Arrays with the
each
method provides a convenient way to declare a large number of resources. This solution would be difficult to implement using the Puppet language, which lacks loops and iterators.

The Ruby DSL in Puppet is currently a subset of the Puppet DSL. As such, there are a number of limitations when using the Ruby DSL. Specifically, the run-stages feature of Puppet 2.6 is not supported when declaring classes from Ruby. However, declaring a class using the Puppet DSL does allow association with a stage. In this situation, the Ruby DSL may be used to define a class that is then declared in the Puppet DSL.

In addition, the Ruby DSL in Puppet 2.6.4 cannot easily declare resources and variables in top scope. To work around this issue, we recommended that you use an External Node Classifier or a Puppet syntax
site.pp
to define variables at top scope. The Ruby DSL works particularly well when declaring resources inside of a class.

In this section we'll see how the Example.com developer uses the Ruby DSL to manage an arbitrary number of resources by reading data from an external location. The Puppet Ruby DSL is a subset of the full Puppet DSL, so not every feature of Puppet is supported. For example, the Ruby DSL does not work well with the new Run Stages feature of Puppet 2.6. In these situations, the resources should be declared using the Puppet DSL rather than Ruby.

The Problem: Resources from Data

It can be difficult to pull in data external to Puppet, but it is required for configuration management. R.I. Pienaar wrote the
extlookup
function to address this concern, but it too has problems if the number of resources to declare is not known in advance. For example, most Puppet deployments have an
accounts
module to manage system and login accounts on systems managed by Puppet. As people join and leave the company, the number of account resources change. Ideally, the data related to a person could be defined in once place and the configuration automatically updates itself to reflect this change. Without the Ruby DSL, Puppet manifests need to be edited to declare or remove account resources.

Puppet 2.6 also supports a new data type in the form of a hash table. Let's see how the Example.com developer uses a hash of hashes set by an external node classifier to declare an arbitrary number of account resources using the Ruby DSL.

Declaring Resources from Data

To get started with the Ruby DSL, the Example.com developer decides to write a very simple module using Ruby rather than Puppet syntax. The goal of this module it to modify the message of the day file. The
/etc/motd
file will contain a parameter set by an External Node Classifier script. Once he's comfortable with this configuration, he plans to extend the ENC script to contain a hash of user accounts. With the account information coming from the ENC, he can iterate over each entry, managing the appropriate resources with Puppet. First, let's take a look at the output of this basic ENC script in
Listing 8-21
.

Listing 8-21.
Basic ENC script output for the Ruby DSL

$ cd /etc/puppet
$ ./resources_enc.rb
---
parameters:
  enc_location: Florida
classes:
    -   motd_location

This simple ENC script declares the
motd_location
class the developer will write using the Ruby DSL. It also sets a single parameter, named
enc_location,
to the string “Florida.” The ENC script the developer is using for this simple test is shown in
Listing 8-22
.

Listing 8-22.
Basic ENC script for Ruby DSL

#!/usr/bin/env ruby
#
# Load the YAML library in ruby. Provide the to_yaml method for all
# Ruby objects.
require 'yaml'
# The output hash. Must contain the "parameters" and "classes" key.
# See: http://docs.puppetlabs.com/guides/external_nodes.html
@out = Hash.new
# Output Array of classes, Hash of Parameters
@out["classes"]    = Array.new
@out["parameters"] = Hash.new
# Add the motd_location class to the catalogs
@out["classes"] << "motd_location"
# Add a location parameter
@out["parameters"]["enc_location"] = "Florida"
# Output the YAML node classification to standard output.
puts @out.to_yaml
# Must exit with a status of zero for classification to succeed.
exit(0)
A Small Puppet Module Using the Ruby DSL

Finally, in
Listing 8-23
the developer creates a small basic module using the Ruby DSL rather than the Puppet DSL. This module manages the file resource for the message of the day. This is implemented as a standard Puppet module except the
init.pp
file is replaced with an
init.rb
file in the manifests directory. The module looks like:

Listing 8-23.
motd_location Ruby DSL module

# cd /etc/puppet/modules
# tree motd_location
motd_location
manifests
    
init.rb

Notice instead of the
init.pp
file, the developer has named the file
init.rb
to indicate the Ruby DSL is being used. The basic
motd_location
class is defined in this file and looks like
Listing 8-24
.

Listing 8-24.
motd_location Ruby DSL

# /motd_location/manifests/init.rb
# Message of the Day class implemented in the Ruby DSL
hostclass :motd_location do
  # Lookup the enc_location parameter set by the ENC
  # Assign it to the location variable in Ruby
  location = scope.lookupvar("enc_location")
  # Set a Ruby String variable to represent the contents
  # of the message of the day file
  motd_content = "This system is in: #{location}\n"
  # Declare a file resource using Ruby syntax
  # This is equivalent to the Puppet Syntax:
  # file { motd:
  #   ensure  => "file",
  #   path    => "/etc/motd",
  #   content => $motd_content,
  #   owner   => 0,
  #   group   => 0,
  #   mode    => 0644,
  # }
  file("motd",
    :ensure  => "file",
    :path    => "/etc/motd",
    :content => motd_content,
    :owner   => 0,
    :group   => 0,
    :mode    => 0644)
End

Other books

Out of the Cold by Norah McClintock
His Inspiration by Ava Lore
Lie Still by David Farris
Borderline by Liza Marklund
Archer's Quest by Linda Sue Park
Sick by Brett Battles
Murder at Whitehall by Amanda Carmack
A Far Justice by Richard Herman
Sam I Am by Heather Killough-Walden
Mack (King #4) by Mimi Jean Pamfiloff