Puppet class API verification and testing
I’ve been working recently on building up a more reliable, predictable Puppet infrastructure. I’m not a developer at heart, but I’ve been trying very hard to apply software development principles to what I do, since generally configuration management and software deployment is becoming more and more just another software problem. One of the end goals of the system I am building is to have a pretty GUI (isn’t that always the end goal?) that will let you know before you deploy something what kind of information it requires.
Applying the concept of encapsulation to our Puppet code, we are trying to keep all the details of each module relatively hidden from the outside so that you don’t need to look at the Puppet code to use it – not exactly revolutionary stuff. All that should matter is the interface to the code – and we’re going down the path of Puppet 2.6 parametrised classes here. So, you have a bunch of parametrised classes and you want to see what the interface is, or in my example, have some GUI figure out what variables you need to pass to the class in order to use it. I know many software tools already do this, but I have no idea exactly how they do it (although it is probably just a variation on the standard code parsing phase).
Armed with this information we can also do verification on the interface to a module, and see when it changes. Dan Bode and Luke Kanies of Puppet Labs helped me out with the following code.
Let’s set up a very basic class in a file:
# test API - test.pp
class test ($foobar) {
file { '/tmp/foo':
ensure => present,
content => $foobar;
}
}
Now we call Puppet directly from Ruby on this file, and render the class as PSON (although it could just as easily be YAML, or probably other formats):
#!/usr/bin/env ruby
require 'rubygems'
require 'puppet'
Puppet[:manifest]='/home/ohookins/test.pp'
puts Puppet::Resource::Type.find('test').render(:pson)
And here’s the output:
{"name":"test","arguments":{"foobar":null},"line":2,"doc":"test API - test.pp\n","code":"[File[\"/tmp/foo\"]]","type":"hostclass","file":"/home/ohookins/test.pp"}
This is ridiculously easy to use later to pretty-print our class interface or pre-load HTML forms etc etc. If we change that variable to have a pre-set default value, you can easily see the change in output PSON:
{"name":"test","arguments":{"foobar":"\"mydefault\""},"line":2,"doc":"test API - test.pp\n","code":"[File[\"/tmp/foo\"]]","type":"hostclass","file":"/home/ohookins/test.pp"}
What is even cooler is that comments preceding the class definition are parsed and included as a doc pair in the hash, which could have any number of cool uses. I assume this code would work equally well for printing interesting information about defined types or unparametrised classes (although in that case I’m not sure there would be as much value). Let me know if this helps you at all, or if you find more cool uses for it!
Leave a Reply
Pages
Archives
- March 2013
- February 2013
- January 2013
- December 2012
- November 2012
- October 2012
- September 2012
- August 2012
- July 2012
- June 2012
- May 2012
- April 2012
- March 2012
- February 2012
- December 2011
- November 2011
- October 2011
- September 2011
- August 2011
- July 2011
- June 2011
- May 2011
- April 2011
- March 2011
- February 2011
- January 2011
- November 2010
- October 2010
- September 2010