Entries filed under: Community

Back to Index

Puppet Camp Atlanta: Success!

Posted on
By
jose
in
Blog, Community, Conferences and Workshops, DevOps, General News, Puppet Camp, Users
Responses
1 Comment »

Puppet Camp Atlanta was a fantastic community event and is be the template for our continuing Puppet Camp series. In many ways Atlanta was an experiment to see if our community could support a 1-day event structure. It can, and the meeting was productive and filled with rich content. A loose speaking schedule allowed for a lot of great conversations over coffee and open Q&A sessions with Puppet Engineers. More than ever before, the Puppet team felt as though we were able to connect with participants to help tackle the tough issues that our users face in real world situations. I strongly encourage you to participate in an upcoming Puppet Camp in your city.

We have 7 Puppet Camps in the works, so look for your city on our complete list. If you don’t see your greater area represented and think you can help us find 100 puppeteers eager to converse, reach out and we’ll see what we can do to bring an event to your city.

And don’t forget PuppetConf is September 27th and 28th at the Mission Bay Conference Center in San Francisco, California. A call for participation, registration details, and sponsorship prospectus will be available by March. PuppetConf has an estimated 60 speaking opportunities and will span all topics operations, DevOps, Puppet, and the Puppet Ecosystem.

Managing F5 BIG-IP Network Devices with Puppet

Posted on
By
Nan Liu
in
Blog, Community, DevOps, Extending Puppet, How to, Modules, Open Source, Puppet Enterprise, Services, Tips
Responses
4 Comments »

Management of network devices is one of the exciting new features in Puppet Enterprise 2.0 and Puppet 2.7. In the initial release, support is limited to Cisco devices, but because Puppet is extensible via modules, we are able to build upon the existing framework and add support for F5 BIG-IP. Like most network appliances, installation of third party software is prohibited, which eliminates the ability to run an agent. Instead, Puppet takes advantage of F5 iControl API to interact and manage the device. F5 BIG-IP network appliances are capable of load balancing, SSL offloading, application monitoring, as well as many other advanced features, and now Puppet can manage these functionalities. Compared to traditional management methodologies and other third party tools that interact with F5, Puppet not only bridges the gap from deploying applications to bringing the service online to your customers, it also brings the unique benefit of the Puppet resource model to network devices. More specifically, the integration offers the ability to compare if a running configuration matches the desired configuration, and then enforce the changes once they’ve been reviewed.

In this blog post, we will step through the process of installing the F5 module, configuring connectivity, and writing a simple manifest to manage an F5 device with Puppet. If you are unfamiliar with BIG-IP devices, you may want to consult devcentral.f5.com for more information on F5 features such as iRules and iControl API.

In the following output, Puppet detects that the F5 device has the wrong iRule. We are running in simulation mode (--noop option) so Puppet only shows the changes that would be applied if we were enforcing the configuration.

$ puppet device --noop
...
notice: /Stage[main]//F5_rule[redirect_404]/definition: current_value: when HTTP_RESPONSE {
if { [HTTP::status] eq "404" } {
redirect to "http://www.puppetlabs.com/404/"
}
}, should be when HTTP_RESPONSE {
if { [HTTP::status] eq "404" } {
redirect to "http://www.puppetlabs.com/redirect/404/"
}
} (noop)
notice: Finished catalog run in 5.69 seconds

Now running Puppet with out the --noop option set, the iRules are changed to match our resource declaration.

$ puppet device
…
notice: /Stage[main]//F5_rule[redirect_404]/definition: definition changed when HTTP_RESPONSE {
if { [HTTP::status] eq "404" } {
redirect to "http://www.puppetlabs.com/404/"
}
}, to when HTTP_RESPONSE {
if { [HTTP::status] eq "404" } {
redirect to "http://www.puppetlabs.com/redirect/404/"
}
}
notice: Finished catalog run in 5.74 seconds

In addition to iRules, the initial release supports key features to configure the device certificate, manage applications pool/poolmember/virtualserver, and monitor application health. The module is published on the Puppet Forge, along with comprehensive documentation of supported F5 resources. The latest development release is available on GitHub. The ability to extend Puppet is not limited to network devices, and the commands shown later in this post to install the module is applicable for other Puppet modules available on the Puppet Forge and GitHub.

The puppet device command is a new application mode in Puppet intended to manage devices that can’t install Ruby/Puppet and run puppet agent. If you haven’t checked it out yet, I would review Brice’s introduction to network devices first. The high level overview of the entire communication process:

Devices are managed through an intermediate proxy system where Puppet agent is installed. The proxy system stores a certificate on behalf of the device. In the case of F5, it should have iControl gem installed, as well as the account information in device.conf to communicate with the device. The proxy connects to the Puppet master to retrieve the catalog on behalf of the F5 and applies changes as necessary.

F5 module installation

Before we get started with the installation process, there are two ways to install F5 module. First, via puppet-module tool which retrieves it from forge.puppetlabs.com (for stable releases of the module). The latest development release from GitHub is accessible via git. The instructions below are specific for Puppet Enterprise, but open source users can also install the module with some changes to the puppet module path. Puppet Enterprise currently ships with the puppet-module gem, and it’s freely available on rubygems.org. Eventually this will become a Puppet Face and turn into the command ‘puppet module’(expected in later release of 2.7). Onwards to the install process:

# Puppet Enterprise:
cd /etc/puppetlabs/puppet/modules
puppet-module install puppetlabs-f5

This should create a directory called f5. Older versions of puppet-module tool might create a puppetlabs-f5 directory in the modules directory—in that case, change it to f5.

Installing from GitHub:

# Puppet Enterprise:
cd /etc/puppetlabs/puppet/modules
git clone git@github.com:puppetlabs/puppetlabs-f5.git
ln -s puppetlabs-f5 f5

In Puppet 2.7, the transport between proxy agent and device supports telnet/ssh, however neither is suitable for F5 devices. Instead, we rely on F5’s iControl API. The iControl gem should be installed on both the master and the proxy system. This gem is available in the F5 module files directory.

# Puppet Enterprise:
/opt/puppet/bin/gem install /etc/puppetlabs/puppet/modules/f5/files/f5-icontrol-10.2.0.2.gem

Configuration and management

At this point we have the module installed, so we should configure connectivity for the device. The configuration for network devices by default are stored in /etc/puppet/device.conf:

[f5.puppetlabs.lan]
type f5
url https://username:password@f5.puppetlabs.lan/partition
[f5.dev.puppetlabs.lan]
type f5
url https://username:password@f5.dev.puppetlabs.lan/partition

You can also break down each device into it’s own configuration file such as /etc/puppet/f5_device1.conf, /etc/puppet/f5_device2.conf …, which is especially helpful if you wish to run against each device separately. In the square brackets is the device certificate name, and certificate management process is the same as puppet agent certs. The device type is f5, and the url is https instead of telnet/ssh. Because F5 supports different partitions we can optionally specify them at the end, and it will default to the ‘Common’ partition if it’s not provided. In the module, f5::config define resource type simplifies management of this configuration file on the proxy system:

f5::config { 'f5.puppetlabs.lan':
    username => 'admin',
    password => 'password',
    url      => 'f5.puppetlabs.lan',
    target   => '/etc/puppetlabs/puppet/device/f5.puppetlabs.lan.conf',
}

Once this configuration file is in place, we can initiate a puppet device run on the proxy server.

# execute on proxy server
$ puppet device --deviceconf /etc/puppetlabs/puppet/device/f5.puppetlabs.lan.conf

This should generate a certificate request on the master which should be signed:

# execute on puppet master
$ puppet cert -l
f5.puppetlabs.lan (2A:0C:A0:F8:C6:EE:EF:9B:B3:49:74:D1:27:31:1B:60)
$ puppet cert -s f5.puppetlabs.lan

At this point the master should have a node name f5.puppetlabs.lan in site.pp with the appropriate f5 resources:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
node f5.puppetlabs.lan {
  f5_rule { 'redirect_404':
    ensure     => 'present',
    definition => 'when HTTP_RESPONSE {
if { [HTTP::status] eq "404" } {
redirect to "http://www.puppetlabs.com/redirect/404"
}
}',
  }
 
  f5_pool { 'webapp':
    ensure                          => 'present',
    action_on_service_down          => 'SERVICE_DOWN_ACTION_NONE',
    allow_nat_state                 => 'STATE_ENABLED',
    allow_snat_state                => 'STATE_ENABLED',
    lb_method                       => 'LB_METHOD_ROUND_ROBIN',
    member                          => {
      '10.10.0.1:80' => {'connection_limit' => '0',
                         'dynamic_ratio'    => '1',
                         'priority'         => '0',
                         'ratio'            => '1'},
      '10.10.0.2:80' => {'connection_limit' => '0', 
                         'dynamic_ratio'    => '1', 
                         'priority'         => '0',
                         'ratio'            => '1'},
      '10.10.0.3:80' => {'connection_limit' => '0',
                         'dynamic_ratio'    => '1',
                         'priority'         => '0',
                         'ratio'            => '1'}
    },
    minimum_active_member           => '1',
    minimum_up_member               => '0',
  }
}

When the puppet device command is executed again this will update the iRule and ensure the appropriate members are in the webapp pool:

$ puppet device --deviceconf /etc/puppetlabs/puppet/device/f5.puppetlabs.lan.conf

A limitation to watch out for in the current Puppet release is that ‘puppet apply’ and ‘puppet resource’ cannot modify network resources. However, we implemented a feature to allow puppet resource to query a F5 device. (For authors of types/providers, making changes to resources aren’t supported until apply_to_device in resources type are handled differently by puppet apply/resource commands). For now we use url facts to establish connectivity to specific F5 devices:

export RUBYLIB=/etc/puppetlabs/puppet/modules/f5/lib/
export FACTER_url=https://admin:password@f5.puppetlabs.lan/Common
puppet resource f5_rule
f5_rule { '_sys_https_redirect':
  ensure     => 'present',
  definition => '    when HTTP_REQUEST {
set host [HTTP::host]
HTTP::respond 302 Location "https://$host/"
}',
}
f5_rule { '_sys_auth_ssl_cc_ldap':
  ensure     => 'present',
  definition => '    when CLIENT_ACCEPTED {
set tmm_auth_ssl_cc_ldap_sid 0
set tmm_auth_ssl_cc_ldap_done 0
}
when CLIENTSSL_CLIENTCERT {
…

If you don’t have Puppet Enterprise 2.0 in your environment yet, you can either download the Learning Puppet VM, or Puppet Enterprise installation packages. F5 also provides F5 LTM Virtual Edition (VE) for trial on VMWare. Please report any issues or bugs to http://projects.puppetlabs.com/projects/modules/issues under the modules section.

Additional Resources

First Look: Installing and Using Hiera (part 1 of 2)

Posted on
By
Hunter Haugen
in
Blog, Community, DevOps, Extending Puppet, Hiera, How to, Tips
Responses
2 Comments »

In a previous blog post, we introduced use cases for separating configuration data from Puppet code. This post (part one of a two part series) will go in-depth with installing, configuring, and using Hiera, but let’s first look at WHY we would need Hiera.

Introduction to the SSH module

One of the benefits of Hiera is its ability to take an existing module and adapt it to a hierarchical-based lookup system. Typically, one of the first modules that people adapt to Puppet code is the SSH module. Let’s look at a simple ssh class definition:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class ssh {
  $ssh_packages      = ['openssh','openssh-clients','openssh-server']
  $permit_root_login = 'no'
  $ssh_users         = ['root','jeff','gary','hunter']
 
  package { $ssh_packages:
    ensure => present,
    before => File['/etc/ssh/sshd_config'],
  }
 
  file { '/etc/ssh/sshd_config':
    ensure  => present,
    owner   => 'root',
    group   => 'root',
    mode    => '0644',
    # Template uses $permit_root_login and $ssh_users
    content => template('ssh/sshd_config.erb'),
  }
 
  service { 'sshd':
    ensure     => running,
    enable     => true,
    hasstatus  => true,
    hasrestart => true,
  }
}

The template used above looks like the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Protocol 2
SyslogFacility AUTHPRIV
PasswordAuthentication yes
ChallengeResponseAuthentication no
GSSAPIAuthentication yes
GSSAPICleanupCredentials yes
 
# PermitRootLogin Setting
PermitRootLogin <%= permit_root_login %>
 
# Allow individual Users
<% ssh_users.each do |user| -%>
AllowUser <%= user %>
<% end -%>
 
# Accept locale-related environment variables
AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
AcceptEnv LC_IDENTIFICATION LC_ALL
X11Forwarding yes
Subsystem	sftp	/usr/libexec/openssh/sftp-server

This module declares three packages (openssh, openssh-clients, openssh-server), ensures a proper sshd_config file, and starts the sshd service. While this works fine for RedHat distributions, there will be a problem with this module if we try and use it on other Linux variants (such as Debian or Ubuntu). Normally, logic is introduced into the module that decides which package names to use based on the operating system of the node. Instead of doing that, let’s use Hiera to solve our problem by changing three lines:

$ssh_packages      = hiera('ssh_packages')
$permit_root_login = hiera('permit_root_login')
$ssh_users         = hiera('ssh_users')

Instead of providing a simple array, we’re now going to utilize Hiera and do a data lookup for the packages to declare in our module, the users to permit, and the permit_root_login parameter that will be used in the sshd_config file. An array will still be returned by Hiera for the $ssh_packages and $ssh_users variables, but the elements in that array will change depending on the operating system of the node. Before we can do this, though, we need to setup Hiera, its hierarchy, and the data directory that it will use for parameter lookups.

Install Hiera

As of this writing, Hiera is not installed with Puppet or Puppet Enterprise and must be installed using RubyGems—though it will be included in the next version of Puppet. Hiera has two separate gems: hiera and hiera-puppet. The hiera gem contains the hiera library source code, the default YAML backend, and the hiera binary that can be used to execute lookups from the command line. The hiera-puppet gem contains the custom functions necessary to call Hiera from Puppet. To install these libraries, do the following:

1
gem install hiera hiera-puppet

(Note that if you’re running Puppet Enterprise, you will need to use the gem binary that’s located in /opt/puppet/bin)

The last step that’s necessary is to get the custom Hiera functions that Puppet needs to do a parameter lookup loaded into Puppet itself. These functions come bundled with the hiera-puppet gem, but they currently are placed into your system’s $GEMPATH and are not loaded by Puppet. To remedy this, let’s download a copy of hiera-puppet from source and place it in our Puppet Master’s modulepath so it can make the functions available from within Puppet.

    1. Get your Puppet Master’s module path by entering puppet master --configprint modulepath
    2. Change to the modulepath directory that was output from the previous step
    3. Enter the following command to download a tarball of the hiera-puppet source code, create a directory called ‘hiera-puppet’, expand the contents of the tarball to the ‘hiera-puppet’ directory, and remove the ‘hiera-puppet’ tarball:


curl -L https://github.com/puppetlabs/hiera-puppet/tarball/master -o \
'hiera-puppet.tar.gz' && mkdir hiera-puppet && tar -xzf hiera-puppet.tar.gz \
-C hiera-puppet --strip-components 1 && rm hiera-puppet.tar.gz

Now the custom Hiera functions are available to be used by the Puppet Master. Let’s move on to configuring Hiera.

Configuring Hiera with YAML & hiera.yaml

Hiera is configured through the /etc/puppetlabs/puppet/hiera.yaml configuration file. This file is written in the markup language called YAML which is simple, human-readable, and is widely supported by scripting languages. (You can read more about YAML here.)

The hiera.yaml configuration file is what Hiera uses to determine the order of its lookup, and the location of the data directory where the YAML files are located. Lets look at an example hiera.yaml configuration file that we can drop into place for our ssh module and break it down piece by piece:

1
2
3
4
5
6
7
8
---
:hierarchy:
    - %{operatingsystem}
    - common
:backends:
    - yaml
:yaml:
    :datadir: '/etc/puppetlabs/puppet/hieradata'

We see that our chosen backend is YAML, and that our data will be stored in /etc/puppetlabs/puppet/hieradata instead of embedding it in our modules. This is looking promising!

The last, and also the most important, piece is the hierarchy itself. We’ve chosen to have two levels: a common level that is common to all hosts, and a higher-priority level that contains any operating-system-specific data.

When we query a hiera() function in Puppet, Hiera looks in its hiera.yaml configuration file for backends to query, and for the directory where the backend data is kept. Lets look at how we might add configuration data to Hiera’s datadir.

Introduction to the YAML data backend

The YAML data backend is the quickest Hiera backend to begin using, and is included with Hiera. YAML is an extremely readable data serialization format, so it makes sense to utilize it if you don’t have a specific need for another format. In the hiera.yaml configuration file above, we created a hierarchy of two levels: %{operatingsystem} and common. Assuming that we are configuring a RedHat system, Hiera will look in the datadir directory for two files in this order: RedHat.yaml and common.yaml. Why? The highest level in the hierarchy queries Facter for the operatingsystem fact (which, in this case, returns ‘RedHat’), and then searches for a YAML file of that name. The second level is just the string common, so it looks for a file called ‘common.yaml’. Let’s take a look at those files:

RedHat.yaml

1
2
3
4
---
ssh_packages: - 'openssh'
              - 'openssh-clients'
              - 'openssh-server'

common.yaml

1
2
3
4
5
6
---
permit_root_login : 'no'
ssh_users         : - root
                    - jeff
                    - gary
                    - hunter

With the hiera.yaml configuration file setup and our Hiera data directory containing YAML files, we can actually begin performing lookups and inspecting the resultant data.

Hiera data lookups

Using our RedHat node and the current Hiera setup, what would be the value of $permit_root_login in this line from our ssh Puppet manifest:

$permit_root_login = hiera('permit_root_login')

The answer is ‘no’. How did we get that? Hiera performed a lookup for ‘permit_root_login’ and searched the highest priority file in the hierarchy – RedHat.yaml (based on the node’s ‘operatingsystem‘ fact being the string ‘RedHat‘). Hiera didn’t find the parameter in that file so it moved to the next, and final, level of the hierarchy and searched common.yaml. Because the parameter is defined in common.yaml, it returned the value back to Puppet.

What if we wanted all RedHat nodes to set the value of $permit_root_login to be ‘without-password’? Using Hiera, we would modify the RedHat.yaml file and add the following line:

permit_root_login : 'without-password'

Because the RedHat.yaml file is queried BEFORE the common.yaml file, RedHat nodes would get this value, while all other nodes would get the value of ‘no’ from common.yaml. Taking this example one step further, what if we wanted all Debian nodes to have the value of $permit_root_login set to ‘yes’? We would need to create a file called Debian.yaml, place it in the Hiera data directory, and enter the following:

1
2
---
permit_root_login : 'yes'

Now, when a Debian node contacted Puppet, Hiera would query the Debian.yaml file BEFORE common.yaml, and the value of $permit_root_login would get the value set in Debian.yaml (which, in this case, would be ‘yes’).

This logic could be repeated over and over for any parameter and with as many hierarchy levels as you desire.

Beyond Basic Lookups: Concatenating Values With Hiera

By default, Hiera uses a priority lookup—which means that the first time it encounters a parameter in the hierarchy it accepts that value and returns it to Puppet. This is how higher levels in the hierarchy can override values that might be set in lower levels of the hierarchy. What if you wanted to search through ALL levels of the hierarchy and return EVERY value for a specific parameter? Hiera has that ability with the hiera_hash() and hiera_array() functions.

There are two variables that currently return arrays: $ssh_packages and $ssh_users. Right now, the variables are being set with a priority lookup—so the ENTIRE contents of the array is being set when Hiera first encounters the ‘ssh_users’ and ‘ssh_packages’ parameter in its lookup. What if we wanted this value to always contain the root user, but other users should change depending on what operating system a node was using? The best way to do this would be to use the hiera_array() function that searches ALL hierarchy levels and returns an array containing the value of ssh_users from EVERY hierarchy level in which it encountered the parameter. Let’s modify our Hiera YAML files to reflect this change:

common.yaml

1
2
3
---
permit_root_login : 'no'
ssh_users         : - root

RedHat.yaml

1
2
3
4
5
6
---
ssh_packages: - 'openssh'
              - 'openssh-clients'
              - 'openssh-server'
ssh_users   : - 'gary'
              - 'jeff'

Debian.yaml

1
2
3
---
permit_root_login : 'yes'
ssh_users         : - 'hunter'

Finally, modify the following line in the ssh module:

$ssh_users         = hiera_array('ssh_users')

After making the changes, which users will be added to /etc/ssh/sshd_config file on a RedHat node? The answer is root, gary, and jeff. Why? The root user will ALWAYS be included in /etc/ssh/sshd_config because the common.yaml file that EVERY node evaluates contains the value of ‘root’ for the ssh_users parameter. Next, because this is a RedHat node, Hiera will concatenate the values of ‘gary’ and ‘jeff’ to the array because those are the values for the ssh_users parameter in RedHat.yaml. What if we run this on a Debian node? The answer is root and hunter (because the value of the ssh_users parameter in the Debian.yaml file is ‘hunter’).

Hiera Best Practices

Hiera is still new to many people, and the concept of a hierarchical lookup system can seem a bit foreign initially. Because of this, there are a couple of best practices that are important to observe when getting started with Hiera and Puppet.

Keep hierarchies to a minimum

This is the time-proven rule of “Just because you can, doesn’t mean you should.” Hierarchy levels are incredibly dynamic tools that will allow you to do a number of things that were previously difficult, but too many of them can lead to problems when debugging (i.e. “Where was that parameter set, again?”). Three to four hierarchy levels should be enough for most sites; if you have more than that, you might want to re-think your approach.

Version control your Hiera data directory separately from your Puppet repository

The benefit of the :datadir: parameter in hiera.yaml is that you can use Facter fact values to determine the path of your Hiera data directory. For example, a site using two Puppet environments called ‘development’ and ‘production’ that has implemented the ssh module we outlined above might have the following directory tree at /etc/puppetlabs/puppet/environments

environments/
    |-- development
    |   |-- hieradata
    |   |   |-- Debian.yaml
    |   |   |-- RedHat.yaml
    |   |   `-- common.yaml
    |   |-- manifests
    |   |   `-- site.pp
    |   `-- modules
    |       `-- ssh
    `-- production
        |-- hieradata
        |   |-- Debian.yaml
        |   |-- RedHat.yaml
        |   `-- common.yaml
        |-- manifests
        |   `-- site.pp
        `-- modules
            `-- ssh

This site’s hiera.yaml configuration file would look like the following:

1
2
3
4
5
6
7
8
---
:hierarchy:
    - %{operatingsystem}
    - common
:backends:
    - yaml
:yaml:
    :datadir: '/etc/puppetlabs/puppet/environments/%{environment}/hieradata'

Hiera automatically substitues the value of the current environment for %{environment} in hiera.yaml and allows for a Hiera data directory that’s completely separate from Puppet manifests/modules.

What now?

This post serves as an introduction to using Hiera with Puppet and familiarizes you with the concepts of hierarchical lookup systems, priority lookups, multilevel lookups, and data separation. The concepts in this post will walk you through getting a working Hiera setup, but there is much more that can be done (Hiera as an ENC, custom backends, etc…). The next post in this series will introduce these advanced Hiera concepts and much more. Until then, enjoy experimenting with Hiera!

Additional Resources

Verifying Puppet: Checking Syntax and Writing Automated Tests

Posted on
By
Adrien
in
Blog, Community, DevOps, How to, Systems Management, Tips
Responses
6 Comments »

One of the issues that crops up when working with Puppet is ensuring that your manifests do what you expect. Errors are bound to happen. A missed brace can make a manifest not compile, or forgetting to include a module or set a variable may mean that running Puppet on the host fails to enforce the expected state. All in all, it would help to have some tools to make sure we’re writing valid code, that it does what it expects, and that if it doesn’t we catch it as soon as possible.

Syntax Checking

At the lowest level of checking, you can use the Puppet parser to do syntax validation. Typos and errors are bound to creep into code, so syntax checking at the end of a long day can go far to improve the quality of your life.

There are a couple of places where you can insert syntax validation. One method is by manually running `puppet parser validate selinux.pp` to make sure that the manifest can be parsed before you commit your changes or deploy them to a live environment. If I left out a curly brace in a manifest and then used ‘puppet parser validate selinux.pp’, then:

    % puppet parser validate selinux.pp
    err: Could not parse for environment production: Syntax error at ‘{‘; expected '}' at /Users/adrien/puppetlabs-mrepo/manifests/repo.pp:252
    err: Try 'puppet help parser validate' for usage

Puppet parser tells me what went wrong, and which line contains the error.

In addition, you can integrate syntax checking into your editor. Vim has built in code compilation functionality that can be used to run error checking, so you can quickly validate your code and jump to sections of code with syntax errors. There are plugins like Syntastic that will do continuous checking so you’re immediately alerted when syntax errors are made. For example, if you used Syntastic with the same syntax error, you would see this:

Syntastic error output

Syntastic output identifies your syntax errors.

Lastly, there’s the puppet-lint tool developed by GitHub’s Tim Sharpe that will analyze your manifests and look for deviations from the Puppet style guide. It’s a quick and easy way to ensure that everybody is following a common set of conventions, so as your module collection grows, you’ll have a consistent set of modules instead of sections with cobwebs. Running puppet-lint against a manifest could produce something like the following:

% puppet-lint init.pp 
    WARNING: top-scope variable being used without an explicit namespace on line 79
    WARNING: top-scope variable being used without an explicit namespace on line 81
    WARNING: define defined inside a class on line 59
    ERROR: single quoted string containing a variable found on line 124
    WARNING: string containing only a variable on line 81
    WARNING: => on line isn't properly aligned for resource on line 71
    ERROR: two-space soft tabs not used on line 50
    WARNING: line has more than 80 characters on line 83
    WARNING: line has more than 80 characters on line 84
    ERROR: trailing whitespace found on line 163
    WARNING: mode should be represented as a 4 digit octal value on line 55

Be warned that these steps only validate syntax. If you have variables that are incorrectly spelled or have a bad value, your code will still be completely valid—and will not do what you want. That’s why we have additional tools available to make sure you code actually works as intended.

Writing Automated Tests

Automated testing is one of the key ways to ensure that your libraries and manifests are meeting your expectations. Out of all the ways that you could test your manifests, I’ll highlight two: testing modules and their catalogs, and testing entire systems.

Testing Modules

As mentioned in a previous post by our Release team, you can add rspec and cucumber tests to ensure that your modules are creating resources as you expect.

For example, you can write tests that ensure that when including a module to install Apache, the package Apache is installed and the service is started. If you were to further develop on that Apache module, you could move forward knowing that the tests would always ensure those basic behaviors would still exist, and if something changed by accident you would definitively know it had changed.

The puppet-apt module has been a focus of a lot of testing, and is a great example of how you can test your modules. Given rspec tests looking like this:

   it { should create_exec("apt_update")\
      .with_subscribe(['File[sources.list]','File[sources.list.d]'])\
      .with_refreshonly(true)}

would produce output like this:

  apt
    Apt class with no parameters, basic test
      should create Class["apt"]
      should create Exec["apt_update"]
 
Finished in 0.36027 seconds
2 example, 0 failures

Writing tests is a good way to verify your modules are functional and reusable. Testing also serves as a indicator of quality, demonstrating you have taken the time to ensure the module does what you want it to do. Additionally, you can verify modules in the Puppet Forge if they have tests, and more easily check them for correctness.

Testing Systems

Unit testing individual modules is a great step to take, but at the end of the day you want to know running Puppet on a host will build the host the way you want, and will have the behavior you expect. Being able to pragmatically verify that services like SSH, Postgres, and nginx are running and serving resources is powerful stuff.

You can use Cucumber in a standalone manner to ensure that if you run Puppet on a host, you get the host you asked for when all is said and done. You can couple unit tests with system tests, and run everything in a testing environment before your changes go to production systems.

Martin Englund has blogged about his experiences with “Behavior Driven Infrastructure” (a play on Behavior Driven Development or BDD) with Cucumber, and did an excellent PuppetConf presentation about his experiences with Puppet and Cucumber.

Benefits of Testing Puppet Code

Everybody wants to have as smooth and seamless a work flow as possible. Deploying changes to your Puppet manifests only to discover that you forgot a comma or brace, or writing a manifest that can’t actually run successfully, can require debugging time that would be better spent elsewhere. Adding a few proactive tools will prevent errors from propagating out, and being able to automatically verify your systems means that you can deploy changes fearlessly and become more agile in your day to day operations.

Additional Resources

Puppet Triage-A-Thon: The Results are In!

Posted on
By
James Turnbull
in
Blog, Community, General News, Open Source, Users
Responses
1 Comment »

The first Puppet Triage-a-thon was a huge success. Thank you so much to everyone who attended and contributed! Some of our favorite stats from the event:

  • We started the day with 2292 open tickets. Over the course of the day 565 tickets were triaged. We also closed 115 tickets. That’s almost 25% of the open tickets triaged and 5% closed!
  • Seventeen community patches were submitted! (And many of these were merged during the day.) Several patches were from people who’ve never contributed before, which is awesome.
  • We had about 50 people involved globally. Individuals and teams participated from Germany, Mexico, Australia, United Kingdom, France, and across the United States. And a big shout-out to the Atlanta Puppet Users group who had a team of five people!  We also had about 10 community members onsite in the Puppet Labs offices locally in Portland.

Our top contributors from the community were:

  1. Dominic Cleal
  2. Devon Peters
  3. Patrick Otto
  4. Oliver Hookins

They’ll be the recipients of $100 Amazon gift vouchers. The full list of participants is here, along with the tally of tickets triaged: http://triageathon.puppetlabs.com/

Everyone who contributed will receive a Puppet Labs t-shirt. If you participated you’ll receive an email shortly asking you for your preferred t-shirt size and where you’d like us to send it.

We’re going to continue to run these events in the future to keep the ticket database fresh and up-to-date.

Thanks again to everyone who came along and contributed and made it such a great success and an awesome amount of fun!

Puppet Triage-a-Thon

Posted on
By
jose
in
Blog, Community, General News, Puppet Camp, PuppetConf
Responses
0 Comments

The Puppet community has grown quickly, and a lot of you have logged tickets and issues. We’ve tried to give those tickets as much love as we could but some slip through the cracks, and sometimes we get overwhelmed. We’ve recognised this and want to get a handle on the backlog of tickets. But we need your help.

Enter Triage-a-thon, hosted locally in our offices, virtually on IRC (#puppethack) and the Web. We’re going to review all the open tickets in the Puppet project with a view to:

  • Update and confirm that issues are still relevant
  • Ensure tickets are in the right status and all the right information is present to help us resolve it
  • Close any invalid or no longer relevant tickets

We’ll assign blocks of tickets to every participant, have documentation explaining what you need to do and provide people on the ground to help you make decisions and answer questions.

We’ll also provide pizza, snacks and a venue locally in our Portland, Oregon offices. Virtually we’ll provide an IRC channel (#puppethack), IM, and rewards (t-shirts, patches, stickers, badges, and books) for people who triage tickets and get involved.


Register

Puppet Labs at SCALE 10x

Posted on
By
jose
in
Blog, Community, General News, Puppet Camp, PuppetConf
Responses
0 Comments

If you’re headed to SCALE 10x this weekend in Los Angeles, here’s a brief schedule to help you find us at the event:

  • Register using our discount code PUP12 for 40% discount!
  • Join us for a half-day training session on Friday 1/20 at SCALE University
  • Come by booth #42 for a Puppet Enterprise demo, t-shirts, and stickers
  • Stop by our BOF Friday 1/20 at 7pm for an informal Puppet discussion
  • See Professional Service Engineer Carl Caum speak about AWS and Puppet at 4:30 on Sunday

Hope to see you there!

Puppet Camp Atlanta, Feb. 3rd

Posted on
By
jose
in
Blog, Community, General News, Puppet Camp, PuppetConf
Responses
0 Comments

Puppet Camp Atlanta is only a few weeks away! If you’re in the Atlanta area or nearby region, this event is for you! Puppet Camps are local, 1-day events that feature a mix Puppet Labs engineers, local speakers, and unconference talks generated by the audience. We’d like to thank our Sponsor MomentumSI for helping make Puppet Camp Atlanta possible!

Registration is now open and the nearly-finalized schedule is available.

We hope you’ll join us for Puppet Camp Atlanta, the first of many new Puppet Camps sprouting up worldwide.

Check out the tentative schedule below—much of the afternoon will be devoted to unconference talks (ie, you can lead the charge on a topic you care about).

Speaker Presentation Time
Kelsey Hightower

Puppet Labs

There’s a Module for That!

An in depth look at the Puppet Forge and it’s companion, the Puppet Module Tool. During this talk a Puppet module will be created from the ground up and released on the Puppet Forge.

9 AM
Gary Larizza*

Puppet Labs

Examples for Separating Data from Puppet Code

One of the first, and biggest, hurdles that Puppet users encounter is ‘How do I make this Puppet code work across all my environments?’ There are several ways to solve this problem, and Gary will give examples of many of the popular methods. He’ll also introduce you to Hiera: the next-generation data lookup system that will be bundled with the next major release of Puppet.

10 AM
Clint Savage

Shadow-Soft

Centralized Authentication with Puppet, LDAP and Linux

This talks about using Active Directory or LDAP as the authentication source, using puppet to update when a new user is added and setting up proper authentications with pam, sssd, ssh and /etc/security/access.conf, among other considerations.

11 AM
Tom Hite

VP Solutions for MomentumSI

Using Puppet to Automate Amazon Deployments

As Amazon continues to grow market share in the public cloud, users are deploying more sophisticated multi-tiered applications. This presents a DevOps challenge related to consistent provisioning, configuring, scaling and locking down resources. This session will discuss the use of Puppet and CloudFormation to automate cloud deployments and system upgrades.

1 PM
Kenn Hussey

Cloudsmith

Geppetto – tooling for Puppet development

This talk will provide both an overview of current approaches to developing Puppet modules, as well as a look forward toward an expanded vision that includes publishing and consuming modules with the Puppet Forge.
We’ll review the current state of the art in tooling for working with modules, with a particular emphasis on Geppetto, a recently introduced “Puppet IDE” that simplifies the process of creating and editing manifests and modules. We’ll also demonstrate Geppetto’s key features and also show how Geppetto supports module development, publishing and consumption in an integrated workflow.

2 PM

*Gary is also teaching the Atlanta Puppet Master course. A ticket to this course is also good for admission to Puppet Camp Atlanta.
Hope to see you there! Register today.

Puppetizing OpenNebula

Posted on
By
Ken Barber
in
Blog, Community, Extending Puppet, How to, Tips, Virtualization
Responses
1 Comment »

Written in conjunction with Tino Vazquez from the OpenNebula Project, and cross-posted on the OpenNebula blog.

Puppet is used for managing the infrastructure for many IaaS software packages, including Eucalyptus, OpenStack, and OpenNebula. OpenNebula is an IaaS manager which can not only manage a large amount of different virtualization and public cloud platforms, it can also emulate the API’s provided by EC2 and OCCI. It’s great for creating private and public clouds, as well as hybrids of the two.

Puppet Labs (or, more specifically, Ken Barber) has developed a powerful integration between OpenNebula and Puppet. The installation and configuration of OpenNebula be managed with this solution, and a virtualized infrastructure can be provisioned starting from bare metal using only Puppet code. The module for Puppet that integrates with OpenNebula can be downloaded from the Forge here: http://forge.puppetlabs.com/puppetlabs/opennebula

Installation and Configuration

The Puppet module contains several classes, types and providers for managing OpenNebula resources and installing OpenNebula.

The class ‘opennebula::controller’ is used for managing the main controller node for OpenNebula and is a simple class. An example usage would be:

class { "opennebula::controller":
  oneadmin_password => "mypassword",
}

This will configure the necessary parts for the main controller node, applying the necessary password for the primary ‘oneadmin’ user.

The class opennebula::node can be applied to nodes that will act as hypervisors. This class configures the necessary package and SSH authorization that is used by the SSH transfer, information and virtualization driver in OpenNebula.

The class itself really needs to know the location of its master, and uses stored configurations for shipping the necessary SSH keys across:

class { "opennebula::node":
  controller => "one1.mydomain.com",
}

The Sunstone GUI can be remotely managed using the ‘opennebula::sunstone’ class. The module also can manage the EC2 gateway using ‘opennebula::econe’.

Managing OpenNebula Resources

OpenNebula has many elements that can be managed on the command line:

  • Hosts
  • Images
  • Virtual Networks
  • Virtual Machines

What’s great about OpenNebula is that the same resources can be managed using their own GUI, namely ‘Sunstone’:

Sunstone

We provide some resource types through the Puppet OpenNebula module that allow managing these elements via Puppet as well. The detailed documentation for each of these is provided in the README file for the module, but let’s talk about one in particular: the onevm resource.

The onevm resource allows you to actually manage a virtual machine as if it was a Puppet resource. An example usage in Puppet would be:

onevm { "db1.vms.cloud.bob.sh":
  memory => "256",
  cpu => 1,
  vcpu => 1,
  os_arch => "x86_64",
  disks => [
    { image => "debian-wheezy-amd64",
      driver => "qcow2",
      target => "vda" }
  ],
  graphics_type => "vnc",
  graphics_listen => "0.0.0.0",
  context => {
    hostname => '$NAME',
    gateway => '$NETWORK[GATEWAY]',
    dns => '$NETWORK[DNS]',
    ip => '$NIC[IP]',
    files => '/var/lib/one/context/init.sh',
    target => "vdb",
  }
}

As you can see, this mirrors all of the options made available via the template when creating virtual machines using the command line or Sunstone GUI in OpenNebula:

options

Using Puppet provides just another capability for managing OpenNebula. Upon creation, the VM will be created just like any other VM and now appear when running ‘onevm list’ or viewing the list of virtual machines in Sunstone:

the list of virtual machines in sunstone

Managing Applications End-to-End

An end-to-end example to demonstrate the capabilities of this integration is the deployment of a sample pastie/pastebin application with redundant web servers:

OG- application architecture

The sample content to build such an infrastructure is located here: http://github.com/kbarber/puppet-onedemo

In this demo content we deploy the IaaS manager OpenNebula, correctly configured and including its dependencies like libvirt. We then use the newly installed virtualization engine to start a virtualized application consisting of web servers behind a load balancer.

Combining OpenNebula and Puppet allows you to achieve a fairly complete end-to-end architecture for rapid deployment within a private cloud infrastructure. The following diagram shows some of the necessary elements in such an end-to-end architecture:

Development Progress

Currently the puppetlabs-opennebula module is OpenNebula 2.2 specific, but we are looking to add OpenNebula 3.0 support once it becomes available in the distributions (such as Debian). If you like the idea of having Puppet manage OpenNebula for installation, configuration or for management we are looking for more code contributors, testers and users.

Bugs can be raised in the Puppet Redmine project for our public modules here.

And the code is available here: https://github.com/puppetlabs/puppetlabs-opennebula

Any help or comments are much appreciated, your feedback will be used to refine the integration and make it more functional. We are confident that this integration adds value to your IaaS and Private Cloud projects, and we hope you enjoy using it as much as we did implementing it.

Additional Resources

  • More information on the Puppet/OpenNebula integration, in slides and video.

Thank You, O.S.S., for P.E. 2.0

Posted on
By
Randall Hansen
in
Blog, Community, General News, Open Source, Puppet Enterprise
Responses
0 Comments

With the launch of Puppet Enterprise 2.0, it’s easy to get lost in the scale of what we’ve enabled sysadmins to do. Besides shipping a world-class configuration management tool, we now make it easy to create managed servers from thin air. In addition, we’re providing command line tools that take fresh OS installs directly to production-ready application servers with no manual intervention, monitoring and reporting for when your configuration drifts, and a web interface that allows you to inspect the current state of resources across your entire population—fast.

For all the things that we’ve done with our software, there’s a much longer list of things that we just didn’t have to do thanks to the open source community at large. So, we’d like to acknowledge some of the open source software that have helped make P.E. 2.0 a great product.

Batman

batman.js

We made the decision early in the development cycle for live management that we wanted to build an application that was as lively and responsive as possible. Our search for an appropriate browser-based-site framework led us to several options, but Batman (who showed up fashionably late to the investigation) impressed us immediately.

Applications written against Batman were reasonably familiar to most of the live management team (including those who had little prior Javascript experience), but the real stars are the hard-working members of the Batman development team. From day one, the core developers were engaged, gracious, and actively involved in helping make our product the best it could be, even as we took Batman down roads they never expected anyone would. Our own Pieter van de Bruggen has made many contributions to Batman’s core.

Fog

fog

When we were building our first pass of cloud provisioning, we began with the single target of Amazon’s EC2 cloud. Fog provided an accessible way to interface with that target (in addition to a number of future targets), so the decision felt fairly obvious up front. After building our first prototype, we discovered we had also built a tool for installing Puppet Enterprise on real hardware with only an SSH connection. With a few small tweaks, it could also work on Rackspace, OpenStack, and a large number of other providers (coming soon, we promise!). Combined with the developer’s responsiveness and guidance, Fog has been an amazing asset to us. At Puppet, Jeff McCune, Kelsey Hightower, Carl Caum, and Pieter van de Bruggen have made many contributions to Fog.

Sinatra

sinatra

Sinatra’s not exactly an unknown in the Ruby web development community, but it has been fundamental to us in our live management development. With all of our presentation logic hidden away in a lightweight frontend application, we wanted to build the backend against a similarly lightweight framework. Sinatra gave us just the right balance between power and simplicity on a well-known, stable platform.

LESS

Less is a CSS abstraction tool, helping us make the Puppet Enterprise console CSS much lighter and more maintainable.

CoffeeScript

A browser-side language, compiling to Javascript, used extensively throughout live management. Batman.js is written in CoffeeScript.

ActiveMQ

A message queue, used by MCollective to distribute work to your entire infrastructure.

Puppet, Dashboard, MCollective, and Facter

Puppet Enterprise wasn’t developed in a vacuum: the core tools themselves are open source software, and have for years received significant contribution from the community outside our doors.

And so many others…

We don’t have the words or the space to properly say “thank you” to every project whose open source work has helped us reach this release. So let me just say once, to every contributor on every project that’s touched our work: thank you. Your work has not gone unnoticed nor unappreciated, and I hope that our own contributions to open source software can serve to pay the kindness forward.