Using Ruby in the Puppet Ruby DSL

DEPRECATION NOTICE: This article is no longer relevant and exists for historical purposes only. The Ruby DSL was an experimental project that added the ability to write Puppet code in pure Ruby. It was never widely adopted and was eventually completely removed in Puppet 4.0. The new Ruby DSL for Puppet (available in 2.6.0 and later) has introduced lots of interesting new ways you can articulate Puppet code.  One of the more interesting new ways is the ability to mix and match Ruby code with the Puppet Ruby DSL.  I'm going to show you an example of this using stand-alone Puppet and a CMDB in a MySQL database. This probably isn't something you'd do on a production host, rather you'd store this data in an external node classifier, but it shows what sort of extensibility is available. I've assumed you've got Puppet installed on your host and that you've got a MySQL server running somewhere that we can add a database (and some data) to.  We're going to start by installing the mysql gem that allows us to interact with MySQL databases in Ruby.
$ gem install mysql
You'll need the MySQL development libraries to install the gem.  You can install these via your distribution's packaging system, on Ubuntu for example the libmysqlclient-dev package needs to be installed. Next, we're going to sign into our MySQL server and create a database.
$ mysql -u root -p
mysql> create database cmdb;
mysql> use cmdb;
mysql> create table packages (id VARCHAR(2), name VARCHAR(40), version VARCHAR(20));
mysql> insert into packages values ( 1,"vim","2:7.2.330-1ubuntu4");
mysql> quit;
Here we've signed into MySQL, created a database called cmdb and a table called packages. We've then added just one package to our table: vim with a version of 2:7.2.330-1ubuntu4. Now that we've got our CMDB (you've hopefully got a more sophisticated one...) we can use its data in Puppet. To do we're going to write a Puppet manifest in the new Ruby DSL. Let's start by creating a new file to hold our manifest.
$ touch packages.rb
You'll notice rather than the usual .pp manifest file we've created a file with a Ruby or .rb suffix. This lets us and Puppet know that this is a Ruby DSL file. Now let's put some code into our packages.rb file:
require 'mysql'

hostclass :packages do
  conn ='localhost', 'user', 'password', 'cmdb')
  pkgs = conn.query('select * from packages')
  pkgs.each_hash { |p| package p['name'], :ensure => p['version'] }

node 'default' do
  include 'packages'
You'll notice we've created something that looks just like a normal Ruby program. First required the mysql gem and then created a new Puppet class, called packages, using the hostclass block. Inside this class we've connected to our MySQL server, passing it the server, username, password and the database to connect to. We've assumed our server is located locally but you could easily specify a remote MySQL server. We've then selected all the records in the packages table and added the values to a hash called pkgs. Taking this hash we've iterated through it, passing the results to a block. Inside our block is some more Puppet Ruby DSL, this time we've defined some package resources:
package p['name'], :ensure => p['version']
Each resource uses the name of the name and version fields from the packages table to create a new package resource. This is the equivalent of creating a standard Puppet package resource like so:
package { "vim":
  ensure => "2:7.2.330-1ubuntu4",
Lastly, we've closed the MySQL connection and specified that the packages class should be included in the default node. Once we've saved this file we can use Puppet in stand-alone mode to run and install our packages:
$ puppet apply --verbose packages.rb
notice: /Stage[main]/Packages/Package[vim]/ensure: ensure changed 'purged' to '2:7.2.330-1ubuntu4'
notice: Finished catalog run in 0.51 seconds
Notice our results? Yep, Puppet happily installed the vim package at the required version. It did this by connecting to the MySQL database, retrieving the required data, creating a Puppet resource using the Ruby DSL, and then executing that resource and installing the package. That's just a small example of how powerful the new Ruby DSL (in combination with the power of Ruby itself) can be!
Puppet sites use proprietary and third-party cookies. By using our sites, you agree to our cookie policy.