Entries filed under: Systems Management

Back to Index

Introducing Puppet Labs Boundary Module

Posted on
By
James Turnbull
in
Blog, Community, Extending Puppet, Modules, Systems Management
Responses
0 Comments

Boundary is a network analysis tool that allows fast analysis and an ultra-fine resolution of data. To achieve this speed and resolution of data, Boundary employs software meters, installed on your application servers, that examine the header information of every packet and securely stream it to the Boundary service once a second. We’re excited to announce our Boundary module to install and manage Boundary network meters, developed in conjunction with the Boundary team and the Puppet community, has reached v1 and is released onto the Puppet Forge! The module also contains support for sending reports from Puppet to Boundary.

To use the module you need to download it from the Puppet Forge onto your Puppet master using the module tools:

# puppet module install puppetlabs-boundary

You can then use the module to install and manage the Boundary meters that monitor your network traffic and send the results to Boundary.  To create a new meter you will need your Boundary ID and API key and create a `boundary_meter` resource like so:

boundary_meter { "db.example.com":
  ensure => present,
  id => "abcde12345",
  apikey => "abcde12345",
  tags => [ "production", "newyork", "mysql", "appcluster1" ],
}

This resource will create a meter called “db.example.com” and add the tags production, newyork, mysql and appcluster1 (or the tags of your choice).  After you run Puppet you will be able to see your meter in the Boundary console.  We can also easily delete the meter by ensuring it is `absent`.

You can find the source code on GitHub and we welcome bug reports, ideas and features from the Puppet community. Thanks to Joe Williams, Jeff Hulten, W. Andrew Loe III, Alessandro Franceschi and Scott Smith for their contributions to the current module.

Module of the Week: Puppet Module Tool – Part 2

Posted on
By
Kelsey Hightower
in
Blog, DevOps, How to, Module of the Week, Modules, Systems Management
Responses
3 Comments »

This week we’ll wrap up our coverage of the Puppet Module Tool (PMT) by exploring the install, upgrade, and uninstall commands. Lets jump right in.

PMT Install

The install command installs modules from the Forge using the full name of the module (author-module). We can install the “puppetlabs-apache” module like this:

Installing a specific version

We can also install a specific version of a module using the --version (-v) flag:

PMT now enforces SemVer when installing modules. If a module does not meet SemVer requirements it will fail to install.

Automatic dependencies resolution

One of the major enhancements to PMT is the ability to automatically resolve and install module dependencies. Once a manual process is now completely automated:

Notice that the install command grabs the requested module, puppetlabs-bacula, and its depenedencies: puppetlabs-mysql, puppetlabs-sqlite, and puppetlabs-stdlib.

PMT Upgrade

PMT also sports the ability to upgrade installed modules:

From the output we can see that we have upgraded the “puppetlabs-stdlib” module from version 2.2.1 to 2.3.1.

PMT Uninstall

Before this release of PMT, users had to manually remove modules from their module paths. While something like “rm -rf /etc/puppet/modules/stdlib” works, it’s not what we call user friendly. This version of the module tool greatly improves the experience around uninstalling modules.

Be sure to use the full module name when uninstalling modules or you’ll get the following error:

Notice the helpful error message suggesting that maybe you meant “puppetlabs-stdlib”, and in fact we did:

Look before you leap

The uninstall commands also checks for local changes and broken dependenices before uninstalling a module. Check out what happens if I try and uninstall the “puppetlabs-mysql” module:

PMT stops you with an error because uninstalling puppetlabs-mysql would leave the puppetlabs-bacula module with an unmet a dependency. You can by-pass this error by using the --force flag, but you can’t say we didn’t warn you!

Conclusion

PMT has been greatly enhanced to provide a much better experience when consuming modulew from the Puppet Forge. With the new list, search, install, upgrade, and uninstall commands managing modules couldn’t be easier.

Additional Resources

Module of the Week: Puppet Module Tool – Part 1

Posted on
By
Kelsey Hightower
in
Blog, Community, Module of the Week, Modules, Systems Management, Tips
Responses
3 Comments »

This week we’re going to begin our coverage of the Puppet Module Tool (PMT). The PMT is the command-line interface to the Puppet Forge—an online repository for re-usable Puppet modules. As of Puppet 2.7.14 and Puppet Enterprise 2.5 PMT is no longer a separate product; it’s now part of Puppet Core. What this means for you is that PMT is ready-to-go out of the box.

New features

The latest version of PMT offers a few new features over the previous stand-alone tool:

  • Search the Puppet Forge from the command line
  • List, upgrade, and uninstall modules
  • Automatically resolve and install module dependencies

In this post we’ll take a look at the new search and list commands.

PMT Search

The search command searches a repository for modules whose names, descriptions, or keywords match the provided search term. For example, if we search for the term “tomcat”, we would get the following output:

Notice the results include modules that match based on keywords and the module name.

PMT List

The list command lists the installed Puppet modules in our modulepath.

Notice the apache module has a version number of (???). This is because an apache module is installed but does not have a valid metadata file. If you would like to see how the installed modules relate to each other, use the --tree flag:

Highlighting problems

The list command will also report any issues with your module path:

The warning message is telling us that we are missing the puppetlabs-mysql module, which is required by the puppetlabs-bacula module. The PMT list command even lets us know which version of puppetlabs-mysql is required. A lot of work when into making the output communicate effectively. Notice the visual label used to highlight the “UNMET DEPENDENCY” in the tree output.

Conclusion

The new PMT is now bundled with Puppet and is ready to use out of the box. The new list and search commands allow you to search for modules on the Forge, and list currently installed modules. The list command also sports the ability to report issues with our installed modules.

Join us next week as we discover how to streamline the installation and maintenance of modules available on the Puppet Forge. We’ll wrap up our coverage of the PMT by taking look at the new upgrade and uninstall commands. We’ll also explore the enhancements made to the install command which greatly simplifies installing modules and their dependencies.

Additional Resources

Module of the Week: puppetlabs/stdlib – Puppet Labs Standard Library Part 4

Posted on
By
Kelsey Hightower
in
Blog, Community, DevOps, Extending Puppet, How to, Module of the Week, Modules, Open Source, Systems Management, Tips
Responses
2 Comments »
Purpose Standard library for creating Puppet modules
Module puppetlabs/stdlib
Puppet Version 2.6+
Platforms Redhat, Debian, Solaris, Mac OS X, Windows

Welcome back to the module of the week! Previously we covered facter-dot-d. This week we’re switching our focus to the puppetlabs/stdlib data functions: getvar, loadyaml, and merge.

The data functions provide the ability to dynamically lookup data from Puppet namespaces, load data from external YAML files, and merge Hashes. These powerful features make it easy to separate Puppet code from data without the complexity of using an External Node Classifier or Custom Facts; leaving your manifests more readable and maintainable as a result.

Example Usage

In this brief tutorial I’m going to cover the loadyaml and merge functions to show you just how easy it is to work with external data:

The loadyaml function

As its name implies the loadyaml function allows us to load data from an external YAML file.

/etc/puppet/data/webservers/data.yaml

ports:
  http: 80
  https: 443
  tomcat: 8080
 
webdir: /var/www/html

/etc/puppet/modules/webservers/manifests/init.pp

class webservers {
  include 'stdlib'
 
  $data = loadyaml('/etc/puppet/data/webservers/data.yaml')
 
  $http_port  = $data[ports][http]   # => 80
  $https_port = $data[ports][https]  # => 443
  $webdir     = $data[webdir]        # => '/var/www/html'
 
  ...
}

Lets step through this:

  • First we create a data file /etc/puppet/data/webservers/data.yaml
  • Then we make a call to loadyaml with the full path to our data file
  • Next loadyaml processes data.yaml and returns a Hash, which is then assigned to $data
  • Finally we set the $http, $https, and $webdir variables by referencing the $data Hash

The merge function

The merge function allows us to merge two or more Hashes:

/etc/puppet/data/webservers/data.yaml

ports:
  http: 80
  https: 443
  tomcat: 8080
 
webdir: /var/www/html

/etc/puppet/data/database/data.yaml

ports:
  db: 5432

/etc/puppet/modules/webservers/manifests/init.pp

class webservers {
  include 'stdlib'
 
  $myhash         = { database_user => 'webdata', webdir => '/var/html' }
  $webserver_data = loadyaml('/etc/puppet/data/webservers/data.yaml')
  $database_data  = loadyaml('/etc/puppet/data/database/data.yaml')
 
  $data = merge($myhash, $webserver_data, $database_data)
 
  $http_port  = $data[ports][http]   # => 80
  $https_port = $data[ports][https]  # => 443
  $webdir     = $data[webdir]        # => '/var/www/html'
  $db_port    = $data[ports][db]     # => 5432
  ...
}

Here we are calling the merge function with three Hashes ($myhash, $webserver_data, and $database_data) which yields a single $data Hash.

Note, the merge function overrides duplicate keys with the argument farthest to the right “winning”. In the above example the webdir value provided by $myhash is overridden by the value provided by $webserver_data.

Conclusion

The data functions provided by puppetlabs/stdlib makes it easy to work with internal and external data. While great for simple use-cases, this mode of operation doesn’t scale. Once the number of external data files or Puppet modules grows, you’ll find your modules littered with lots of getvar, loadyaml, and merge function calls.

A better solution for more complex requirements is Hiera. While providing all the features of getvar, loadyaml, and merge, Hiera includes the ability to load data from virtually anywhere. Via Hiera’s pluggable backend interface, you’ll be able to pull data from external databases such as Redis, or JSON files; the possibilities are endless.

That wraps up our coverage of the puppetlabs/stdlib module. Hopefully you can now leverage some of its features in your own modules and have a sense of how robust Puppet modules can be.

Additional Resources

Why Puppet Isn’t a File Management Tool

Posted on
By
luke
in
Blog, DevOps, General News, Solutions, Systems Management, Tips
Responses
0 Comments

One of the criticisms of Puppet we see from time to time is that it is not that great at editing and managing files. While our goal for Puppet is for it to be a management platform you can use to build a solution to any problem, it’s true that it’s not as good at just editing and generating files as it could be. What’s not necessarily obvious as that we intentionally made a trade-off between being good at managing everything, or just being good at managing files. This article will hopefully explain why we made that trade-off, and how it helps you get more done with less pain.

Puppet was built originally as an automation tool for primarily UNIX-like machines, such as Solaris, Red Hat Linux, and Mac OS X, and one of the great things about UNIX is that nearly everything can be treated as a file. Thus, it would have made sense in a way for most of Puppet’s functionality to focus on managing files. In fact, that was the major focus of most of the tools around when Puppet was started—files, templates, and managing large sets of files across many machines.

However, while Puppet is reasonably good at file management, including a decent templating system, it does everything it can to force you to think less about files and more about abstract concepts like users, packages, and services. This can often feel awkward if you are approaching Puppet thinking that you really just need to manage files, and it doesn’t want you to. Why doesn’t it just manage files?

It all goes back to frustration I had with these file-centric tools when I was a sysadmin and then a consultant. Yes, nearly everything that the UNIX kernel cares about can be treated like a file—files, pipes, sockets, etc.—but there are a lot of things above the layer of the kernel that aren’t treated as a file. For instance, where can I remove the file corresponding to a user? Or edit the file corresponding to a running service? Yes, this information is in files somewhere, but there isn’t a file-per-user or file-per-filesystem mapping, which makes life very complicated.

Just look at users for example. This starts out easy and gets very painful very quickly. You might start by having the same file on all of your Solaris machines, but what happens when your database servers need accounts for your DBAs but your web servers don’t? Even worse, what happens when you need the same DBA accounts on both your Solaris and Red Hat machines? “Ah hah!”, you think, “that’s why I use templates!”

Yes, templates can be used to make a lot of this pain go away. Or rather, using templates to make your file management system not as painful absolutely does work. But why not pick a management methodology actually built for your problems, as opposed to one built because it was easy for its developer to build? This becomes especially apparent once you have to support Mac OS X. It’s POSIX-compliant (at least, as far as I know), but all of its user tables are stored in some kind of directory service (with the specifics varying by version). You can absolutely build a template that can generate NetInfo tables for OS X and passwd files for Debian, but you can’t do it and stay sane.

It’s not just the file contents that are the problem. File locations are also a big issue. Everyone runs SSH, and basically everyone is running the standard OpenSSH tool. However, nearly everyone names the service differently (sshd? opensshd? ssh?), and puts the files in different locations (/etc/ssh, /etc/openssh, /opt/local/etc/sshd). Again, you can absolutely build a file templating system that provides the flexibility to pick the right location for a given platform (although shockingly few templating systems actually do this—most stick to real filesystem paths, and thus only work on one platform), but you can’t do it and stay sane.

But these are still the easy problems, the things you can reasonably manage with files. The hard stuff—or really, the fun stuff—all gets done with shell scripts. Oh, you might be wrapping those shell scripts in perl or ruby scripts, but in the end, you’re exec-ing a bunch of commands to do your work. You could even go so far as to say what Puppet is really best at is generating and running tiny shell scripts, since the shell is where the rubber really meets the road on UNIX. (It’s obviously different on Windows, but it’s not as different as you’d like it to be.) These little shell scripts are where the file management tools really fall down.

What do you need scripts for? Well, nearly everything, actually. In my experience, the vast majority of work follows some portion of the pattern ‘install package, configure service, run service’. You might only need the configuration part, or the installation part, but you often need all three. At best, files are okay at configuration, but they’re horrible at running services or installing packages. The only real way to do this is using the system commands for, well, managing packages and services.

See, that’s the other thing that the file management tools get wrong—they think we’re still in 1991, before apt, SMF, Yum, RPM, launchd, NetInfo, NFS, and all of the other great tools that make our operating systems modern and awesome, and coincidentally less and less like files. You can either manage your system like a bunch of files, or you can use these modern tools to make your life easier and stay sane; you can’t do both.

So, that’s why Puppet’s not a file management tool. We wanted to leverage all of these great tools your operating system vendors are building, and we wanted you to be able to focus on the problems—running services, deploying software, providing access to users—rather than the implementation, which may or may not be files. This can be confusing to people who really just see their OS as a bunch of files, but if you just want the problem to go away, and you want the solution to actually work with your operating system instead of against it, we think you’ll find Puppet a much simpler and easier solution than file management.

Additional Resources

Module of the Week: puppetlabs/stdlib – Puppetlabs standard library – Part 3

Posted on
By
Kelsey Hightower
in
Blog, Community, DevOps, Extending Puppet, Module of the Week, Modules, Open Source, Systems Management, Tips
Responses
4 Comments »
Purpose Standard library for creating Puppet modules
Module puppetlabs/stdlib
Puppet Version 2.6+
Platforms Redhat, Debian, Solaris, Mac OS X, Windows

Welcome back to the Puppet Module of the Week! Previously we covered the validation functions provided by puppetlabs/stdlib. This week we’re switching our focus to facter-dot-d; a simple way of pulling facts from external sources.

From the docs:

A simple little framework to get facts from external sources.
You can create files in /etc/facter/facts.d which can be text, yaml, json or executables. In the case of executables it supports caching so you only need to run your expensive scripts every now and then.

facter-dot-d is great for people who already have information about their nodes and would like to reuse that data without writing custom facts. facter-dot-d makes this possible by scanning the /etc/facter/facts.d directory for data files(YAML, JSON, or plain text) and scripts and then processes them to create new facts.

This may seem like magic, but facter-dot-d is really just a custom fact. By using the Facter API, facter-dot-d converts external data into custom facts instead of returning a single fact.

Neat huh? We thought so too, so it’ll be built into the next major release of Facter 1.7.0.

Example usage

Before we get started with the examples we need to create the /etc/facter/facts.d directory:

$ mkdir /etc/facter/facts.d

Next we need to ensure the node uses the stdlib class:

node 'pmotw.puppetlabs.com' {
  include stdlib
}

Then we use pluginsync to sync the facter-dot-d fact to the agent:

$ puppet agent -t --pluginsync
…
info: Loading downloaded plugin /var/lib/puppet/lib/facter/facter_dot_d.rb
…
info: Loading facts in facter_dot_d
info: Loading facts in root_home
info: Loading facts in facter_dot_d
info: Loading facts in root_home
info: Caching catalog for pmotw.puppetlabs.com
info: Applying configuration version '1331932291'
notice: Finished catalog run in 0.07 seconds

Adding a custom fact using JSON

In order to use JSON files as a source for facter-dot-d you need to ensure the json gem is installed on your system. On my test system, Debian 6, the json gem is not installed by default:

$ gem list
 
*** LOCAL GEMS ***
 
puppet-lint (0.1.12)
puppet-module (0.3.4)

We can use the gem command to install it:

$ gem install json
Building native extensions.  This could take a while...
Successfully installed json-1.6.5
1 gem installed
Installing ri documentation for json-1.6.5...
Installing RDoc documentation for json-1.6.5...
 
$ gem list
 
*** LOCAL GEMS ***
 
json (1.6.5)
puppet-lint (0.1.12)
puppet-module (0.3.4)

Now that we have the json gem installed we can simply drop our JSON file into the /etc/facter/facts.d directory:

$ cat /etc/facter/facts.d/datacenter.json
{
  "location": "Portland",
  "cluster": "Web"
}

On the next use of Facter, the datacenter.json file will be processed by facter-dot-d adding custom Facts for the location and cluster keys as a result. It should also be noted that since facter-dot-d was distributed via pluginsync, we must use the --puppet flag. The following will not work:

$ facter location

Using the --puppet flag produces the desired results:

$ facter --puppet location cluster
cluster => web
location => portland

We can achieve the same results using a YAML or TXT file:

$ cat /etc/facter/facts.d/datacenter.yaml
---
location: portland
cluster: web
 
$ facter -p location cluster
cluster => web
location => portland
$ cat /etc/facter/facts.d/datacenter.txt
location=portland
cluster=web
 
$ facter -p location cluster
cluster => web
location => portland

Staying out of trouble

Be sure to use either JSON, YAML, or TXT files consistently. While the following will work:

$ cat /etc/facter/facts.d/datacenter.yaml
---
location: portland
cluster: web
 
$ cat /etc/facter/facts.d/web.json
{
  "api_version": 2.1,
  "web_port": 8080
}
 
$ facter -p location cluster api_version web_port
api_version => 2.1
cluster => web
location => portland
web_port => 8080

The follow will lead to unexpected behavior:

$ cat /etc/facter/facts.d/datacenter.json
{
  "location": "atlanta",
  "cluster": "database"
}
 
$ cat /etc/facter/facts.d/datacenter.yaml
---
location: portland
cluster: web

With both datacenter.json and datacenter.yaml specifying the same data, there is no reliable way to tell which values cluster and location will be set to.

$ facter -p location cluster
cluster => database
location => atlanta

Silent failures

Invalid JSON, YAML, and TXT files will silently fail:

$ cat /etc/facter/facts.d/web.json
{
  "api_version": 2.1,
  "web_port": 8080,
}
 
$ facter -p web_port

Notice we do not get the expected output of 8080 here. We can get more insight into what’s going on by using the --debug flag:

$ facter -p --debug
...
Parsing /etc/facter/facts.d/datacenter.json using json_parser
Failed to handle /etc/facter/facts.d/datacenter.json as json facts: JSON::ParserError: 618: unexpected token at '{
 
  "api_version": 2.1,
 
  "web_port": 8080,
 
}
 
'

Though not clear from this error message, datacenter.json is not a valid JSON file. Notice the extra ‘,’ after 8080.

Fixing this yields the expected result:

$ facter -p web_port
web_port => 8080

Conclusion

The Facter Ruby API is the standard way of creating custom facts, which sets the bar pretty high for creating new facts. facter-dot-d lowers the bar significantly by adding the ability to use flat files as well as scripts in any language to produce custom facts. This is a huge win for people just getting started and for people who have existing data they would like to use as Facts.

Join us next week as we wrap up our coverage of the puppetlabs/stdlib module. We’ll be taking a look at the remaining functionality by exploring some data functions that allow you to do things like load external data from YAML files and merge parameter values inside of Puppet manifests.

Additional Resources

Module of the Week: puppetlabs/stdlib – Puppet Labs Standard Library Part 2

Posted on
By
Kelsey Hightower
in
Blog, Community, DevOps, Extending Puppet, How to, Module of the Week, Modules, Open Source, Systems Management, Tips
Responses
1 Comment »
Purpose Standard library for creating Puppet modules
Module puppetlabs/stdlib
Puppet Version 2.6+
Platforms Redhat, Debian, Solaris, Mac OS X, Windows

Welcome back to the module of the week! Last week we began our coverage of the puppetlabs/stdlib module by examining the file_line resource, which allows you to manage individual lines in a file.

We’ll pick up where we left off by covering the data validation functions provided by the puppetlabs/stdlib module and how to use them to make our Puppet manifests more resilient to runtime failures.

There are five validation functions in total. The following four functions: validate_array, validate_bool, validate_hash and validate_string allow you to validate the type of data used in your manifests. These are useful when you want to be sure the input value is an Array, Hash, Boolean, or a String.

Sometimes you need to go beyond type validation and ensure something more specific like an ipaddress or hostname. The validate_re function helps here by validating input using regular expressions. With access to the full power of Ruby’s regular expressions, you can validate just about anything.

Resource Overview – validation functions


Function validate_array
validate_bool
validate_hash
validate_re
validate_string

Example usage

In the following example we use the validate_array and validate_bool functions to validate the input types used by the ntp module.

$ cat /etc/puppet/modules/ntp/manifests/init.pp
 
# Example Usage
# 
# class { "ntp":
#   servers    => ['0.debian.pool.ntp.org'],
#   autoupdate => false,
# }
#
class ntp ($servers="UNSET",
           $ensure="running",
           $autoupdate=false,
) {
  validate_array($servers)
  validate_bool($autoupdate)
}

In the above example we are using the validate_array function to ensure the $severs class parameter is an array: ['0.debian.pool.ntp.org'], and not a String: '0.debian.pool.ntp.org'.

We’re also using the validate_bool function to ensure $autoupdate is a Boolean value: true or false, and not: 'true', 'false', or 'string'.

Lets see what happens if I use a String value for the $server class parameter:

$ cat /etc/puppet/manifests/site.pp
 
node 'pmotw.puppetlabs.com' {
  class { "ntp":
    servers => '0.debian.pool.ntp.org'
  }
}
 
$ puppet agent -t
…
err: Could not retrieve catalog from remote server: Error 400 on SERVER: "0.debian.pool.ntp.org" is not an Array.  It looks to be a String at /etc/puppet/modules/ntp/manifests/init.pp:5 on node pmotw.puppetlabs.com
warning: Not using cache on failed catalog
err: Could not retrieve catalog; skipping run

Yikes! Looks like we’ve managed to piss off our Puppetmaster. It’s basically yelling at us for using a String and not an Array. It’s Puppet’s way of saying, “You’re doing it wrong!”, and indeed we are. The fix is pretty simple:

node 'pmotw.puppetlabs.com' {
  class { "ntp":
    servers => ['0.debian.pool.ntp.org']
  }
}

When the concern is not the type, but the actual value, then the validate_re function is the right tool for the job. From the docs:

Perform simple validation of a string against one or more regular expressions. The first argument of this function should be a string to test, and the second argument should be a stringified regular expression (without the // delimiters) or an array of regular expressions. If none of the regular expressions match the string passed in, compilation will abort with a parse error.

A “real” world example

You just got a job at the Federation, an organization committed to space exploration. You’re a rising star! You’ve been put in charge of the Intergalactic Compute Bay (ICB), aka the datacenter. Your job is to take things to the next level, so you start by creating a Puppet module to manage space probes. Yeah, space probes.

Your manifest looks like this:

$ cat /etc/puppet/modules/voyager/manifests/init.pp
 
# Class: voyager
#
#   This module manages billion dollar space probes, use with caution.
#   Please do not send probes to non-planets, avoid things like black holes!
#
#   Tested probes:
#    - Voyager 1
#    - Voyager 2
#    - Voyager 3
#
# Parameters:
#  
#   $destination
#
# Actions:
#  
#  Configures and manages space probes.
#
# Example Usage:
# 
# class { "voyager":
#    destination => 'Mars'
# }
#
class voyager ($destination) {
  define space_mission ($destination) {
    # Top secret stuff we cannot show
    $message = "Sending probe to ${destination}"
    notify { $message: }
  }
 
  space_mission { 'voyager3':
    destination => $destination
  }
}

Wow, that’s awesome! You have a module that makes it easy to configure a space probe to go anywhere. Your well documented module even warns people that probes should not be sent into Black Holes. After a few rounds of QA, the voyager module is ready for production.

Egor Homakov, the new security lead, has reviewed your module and pointed out some possible bugs. You ignore him—your module is badass and passed QA. Plus, you give clear instructions on how to use it, right there in the module.

It’s show time. It’s time to launch 1000 new Voyager 3 space probes, and instead of using the old manual system of strategic button pushing, the Voyager Puppet module has been called to action.

Egor has volunteered to help out, his part of the configuration looks like this:

# lots of node definitions omitted
node 'voyager3.federation.org' {
  class { "voyager":
    destination => 'Sun'
  }
}
…

With little time to review each entry you spot check things and give the green light.

During the launch you notice this scroll by the screen:

notice: Sending probe to Sun
notice: /Stage[main]/Voyager/Voyager::Space_mission[voyager3]/Notify[Sending probe to Sun]/message: defined 'message' as 'Sending probe to Sun'
notice: Finished catalog run in 0.03 seconds

Yes my friend, you are indeed sending one of those billion dollar probes to the Sun. In case it’s not entirely obvious, the Sun is not a planet. Your attempt to play it off is short-lived; you just witnessed a space probe burst into flames!

You made two mistakes here. First you trusted Egor with your Puppet configurations, and second you did not validate the input for the $destination class parameter. At this point your only option is to resign. Yep, not even Puppet can help you recover from this.

Even though it’s to late for you, lets see how you could have saved your job.

class voyager ($destination) {
  $approved_planets = [
    'Mercury',
    'Venus',
    'Earth',
    'Mars',
    'Jupiter',
    'Saturn',
    'Uranus',
    'Neptune'
  ]
 
  validate_re($destination, $approved_planets)
 
  define space_mission ($destination) {
    # Top secret stuff we cannot show
    $message = "Sending probe to ${destination}"
    notify { $message: }
  }
 
  space_mission { 'voyager3':
    destination => $destination
  }
}

This time we catch the error before destroying a billion-dollar space probe:

$ puppet agent -t
…
Error 400 on SERVER: validate_re(): "Sun" does not match ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"] at /etc/puppet/modules/voyager/manifests/init.pp:37 on node voyager3.federation.org

More validate_re examples

The regular expressions can be more complex than we have shown so far. For example, if you wanted to validate a mac address you could do the following:

validate_re($macaddress, '^([0-9a-f]{2}[:]){5}([0-9a-f]{2})$')

You can also use the validate_re function in combination with other validation functions such as the validate_hash function like this:

$network_device = { macaddress => '00:0c:29:0d:1d:970' }
validate_hash($network_device)
validate_re($network_device['macaddress'], '^([0-9a-f]{2}[:]){5}([0-9a-f]{2})$')

The above validates that the macaddress key of the $network_device hash contains a valid mac address string value.

Reading and writing regular expressions can be a challenge, one tool that I use to help with the process is Rubular, an online Ruby regular expression editor:

Rubular allows me to play around with an expression until I get it right.

Conclusion

Using the validation functions provided by puppetlabs/stdlib can help catch issues quickly and prevent disaster from striking. Try not to get carried away by validating everything under the Sun; start with things that are critical and be sure to document what valid values should look like.

Join us next week as we continue our coverage of the puppetlabs/stdlib module with a quick look at facts-dot-d and discover how we can get Facts from external sources and cache them in a central location so Facter can find them.

Additional Resources:

Using Puppet Modules to Install and Manage WordPress

Posted on
By
Daniel Sauble
in
Blog, Community, DevOps, Extending Puppet, How to, Modules, Puppet Enterprise, Systems Management, Tips, User Experience
Responses
1 Comment »

Puppet modules are a fantastic way to deploy and manage specific applications. The Puppet Forge contains a wealth of third-party modules that allow you to do some awesome stuff with a minimum of work. In this post, we use a module from the Forge to solve a common task—using Puppet to set up a WordPress blog. Finding the best way to accomplish this with Puppet was a challenge, and helped us feel the joys and pains of those who use our software on a daily basis.

The first step is to install Puppet, Facter, and RubyGems. Since we’re using Ubuntu, we’ll use apt-get to install these packages. If you decide to use a different OS (or the Learning Puppet VM), use whatever package manager is appropriate for your platform.

  1. Open a terminal window and type the following command:
    apt-get install puppet puppetmaster facter rubygems
  2. Next, install the puppet-module gem. We’ll need this in order to pull the WordPress module from the Forge and install it.
    gem install puppet-module
  3. Switch to your Puppet module directory. This is where you’ll run the puppet-module install command.
    cd /etc/puppet/modules
  4. Choosing the right module can be tricky. Usually, multiple modules are available that seem to do the same thing, but some are minimal and others are more fully featured (and sometimes a lightweight, minimal module is what you want).

    In our case, we needed a module that would allow us to customize the WordPress MySQL database (so user name and password could be configured without manual intervention). Unfortunately, there isn’t currently a way to determine what functionality modules expose without downloading and experimenting with them. After some trial and error, we discovered a module that worked for our purposes—and we got there by a simple search of “wordpress” at forge.puppetlabs.com.

    The WordPress module written by Jon Hadfield (jonhadfield/wordpress) is a good, functional module to use for setting up the blog. Switch back to your terminal window and type the following command:

    puppet-module install jonhadfield/wordpress
  5. Edit /etc/puppet/manifests/site.pp with your favorite editor and add the following lines, where `hostname` is output of hostname on your system and `domain.com` is the suffix for fully qualified domain names on your network:
    node '`hostname`.`domain.com`' {
        include wordpress
    }
  6. Up to this point, you’ve installed Puppet on your system, used puppet-module to download and extract the WordPress module, and configured your site.pp such that Puppet will manage WordPress on your system. Now, do a Puppet run to kick off the WordPress install:
    puppet agent --test
  7. Go to http://hostname:80 and enter the login credentials for the admin account. This will populate the WordPress database with whatever credentials you used.
  8. Okay, so, say you want to have future WordPress installations configured with this password/email combo by default. One approach is to dump your WordPress database to the template used by the WordPress module:
    mysqldump wordpress >> wordpress/templates/create_wordpress_db.erb
  9. You’ll need to insert one line for this to work properly, so edit create_wordpress_db.erb and insert the following line right after CREATE <%= db_name %>:
    USE <%= db_name %>;
  10. Now, test this template by dropping the current database and doing another Puppet agent run. First, drop the existing database:
    mysql -u root -e 'drop database wordpress;'
  11. Then, do an agent run:

    puppet agent --test

That’s it! You’ve got a running WordPress blog!

Interaction with Puppet and its related tools should be a seamless and enjoyable experience–no matter what you’re managing or how complicated the task. We used open-source Puppet to complete this task, but you can easily do the same with our enterprise software. Get the free download at http://info.puppetlabs.com/download-pe2.html.

Additional Resources

2012 FOSDEM Wrap-up

Posted on
By
Nigel Kersten
in
Blog, Community, Conferences and Workshops, DevOps, General News, Open Source, Systems Management
Responses
3 Comments »

Just over a week ago, we (Nigel and Carl) spent an awesome (but very cold!) weekend hosting the Configuration Management Dev Room at FOSDEM, the Free and Open Source Software Developer’s European Meeting in absolutely-not-sunny Brussels, Belgium.

There were over 430 speakers sharing their knowledge of this space on topics ranging from Linux on the desktop to open cloud computing and kernel development. For the second year running we had a very successful Dev Room, where we again packed out the room (and unfortunately had to turn people away due to hitting capacity).

We had a great range of talks covering a variety of solutions in the Config Management space, the Normation team showed off their Rudder GUI for CFEngine, Zane from RedHat introduced us to the Matahari project for remote API access, Mikhail from CFEngine gave us a simplified explanation of Promise Theory, and Ralph demonstrated the Immobilien Scout 24 home-grown system built around RPM.

A highlight for us as Puppet folks was R. Tyler Croy’s talk on running the Jenkins project with Puppet, and how it helped him bring sanity to infrastructure running out of control. He packed the house out and his hand-drawn slides really stood out. It was also great to see the OpenNMS team show two integrations between OpenNMS and Puppet to consolidate node views.

At a higher level, another packed room saw Mitchell Hashimoto, the creator of Vagrant, explain DevOps as a range, not an absolute. It was a very insightful talk on how IT shops can move towards devops practices one step at a time, making small investments towards a larger goal.

We thank everyone who participated at FOSDEM and thank the organizers for allowing us to be part of such an amazing conference. As Dev Room organizers we have nothing but positive feedback to the FOSDEM crew about how well-run everything was, it was definitely one of the smoother conference experiences I’ve been part of. Given the challenge involved in running a conference of this size, that’s no mean feat.

Unfortunately the Dev Rooms aren’t recorded to video by default, but if you’re interested in seeing some of the many other talks that went on, there is a FOSDEM YouTube channel for streaming, and a video archive for direct download.

We’re sure FOSDEM 2013 will be even grander, and we look forward to hopefully being involved again.

Cloud Infrastructure and DevOps with Puppet Enterprise 2.0 and Citrix CloudStack 3

Posted on
By
teyo
in
Blog, Community, DevOps, General News, Systems Management, Tips
Responses
2 Comments »

Cloud Operations

Efficient IT operations are becoming more and more critical to business success. Businesses are looking for solutions that enable rapid provisioning and management of the application life cycle so they can deliver new products and services faster and more efficiently. Citrix CloudStack 3 provides core enabling functionality for businesses to move to a Cloud operations model. Citrix CloudStack 3 empowers organizations to dynamically allocate, computational, network and storage resources and reduce the provisioning bottlenecks associated with conventional data-center management.

Reusable Infrastructure Components

With Puppet Enterprise, administrators and developers can build unified models for application deployment. Puppet Enterprise is built for the cloud and with almost 300 community contributed modules the dream of fully automated infrastructure and application deployment has never been easier to realize. Puppet makes it easy to build reuse and share application and system configuration models.

Transitioning to the Cloud

Citrix CloudStack 3 and Puppet Enterprise 2.0 deliver an operational tool kit that enables businesses to transition workloads between traditional bare metal infrastructure and internal or external clouds. Puppet Enterprise enables users to model applications, infrastructure, and security requirements. Those models can be used to seamlessly migrate development, testing, and production infrastructures from traditional bare-metal infrastructure to internal or external clouds.

Living the DevOps Dream

DevOps is a cultural shift from silo-ed operational and development team to integrated DevOps teams. Automated configuration management and on demand infrastructure are enabling technologies for this shift. On demand infrastructure enables developers to develop and test their applications in environments that mirror their ultimate production environments. Automating configuration management tasks and managing infrastructure as reusable code allows the infrastructure requirements to carry through the development and testing phases and cleanly into production. With these tools, organizations can deploy often and with confidence. Puppet Enterprise and Citrix CloudStack 3 enable customers to make the shift to DevOps today!

Additional Resource