Thu, 17 Mar 2011
Puppet Cucumber Providers
At work we try, and sometimes even succeed, in using Test Driven Deployment so as one of my background projects I've been wrapping certain tools in to cucumber friendly forms. Over the last couple of days I've been grabbing ten minutes here and there to incorporate Puppet 2.6 in to the pile.
Feature: Puppetwrappers Puppet Provider Examples Scenario: Confirming package installation When a machine has been puppeted Then the bash package should be installed Scenario: Confirm doodoodoo package is absent When a machine has been puppeted Then the doodoodoo package should not be installed Scenario: Confirm cron service is running When a machine has been puppeted Then the cron service should be running Scenario: Confirm tomcat6 service is not running When a machine has been puppeted Then the tomcat6 service should not be running Scenario: Confirm dwilson is in libvirtd group When a machine has been puppeted Then dwilson should be a member of libvirtd Scenario: Confirm dwilson has a uid of 1000 When a machine has been puppeted Then dwilson should have a uid of 1000 Scenario: Confirm dwilson has a given shell When a machine has been puppeted Then dwilson should have the /bin/bash shell
I really like using the puppet providers for this because of the abstraction benefits they provide. I can write steps to test packages, services or aspects of a user and not have to worry if a developer runs it on Fedora or Debian.
This is only a first draft, and the cucumber wording needs changing, but I thought I'd put it online to show how expressive cucumber can be for system tasks and how easy, and concise, it is to reuse the puppet providers. You can grab the puppet step code and the Puppet providers features to drop in to your own test harnesses and have a play with. The implementation is pretty simple, for example the code below is everything you need for the service scenarios:
Then /^the (.+) service should be running$/ do | service | service_status = Puppet::Type.type(:service).new(:name => service, :hasstatus => true).provider.status service_status.should == :running end Then /^the (.+) service should not be running$/ do | service | service_status = Puppet::Type.type(:service).new(:name =>service).provider.status service_status.should == :stopped end
It's worth mentioning that all the above will only work in 2.6 and above as the internal details returned by the providers are different to those in 2.5.