published on 26 July 2012

My name is Mateusz Lenik, I study at Technical University in Wrocław, Poland. For the past two months, I've been working on expanding features of the Ruby DSL for Puppet. I’m a Ruby programmer and I was looking for Google Summer of Code projects in Ruby, which is how I came to Puppet Labs. My project goal is to release a version of the DSL that provides a feature parity between Puppet language and Ruby DSL. I’d also like to create a script that can (at least partially) convert manifests in Puppet language to Ruby DSL.

The previous version of DSL was introduced in 2006, but it was rarely used because it didn't have some features that exist in the Puppet language. The new version that I’m working on tries to address these issues.

Currently, the new Ruby DSL is functional and allows writing equivalent manifests in Ruby and in Puppet language, but it still lacks some features, like loading types dynamically from Ruby manifests. The syntax has been reworked and it's more Ruby-esque. It also allows the user to do more than the previous version. In the previous version there was no syntax defined that allowed setting defaults or overrides, referencing resources or supply a block when creating resources.

What's new?

I'm going to do a small walkthrough of the new features of Ruby DSL. Let's get started.

Calling functions

Improvements: Puppet functions can be called like regular Ruby functions, there is no need to put arguments into an Array now. Also functions can be called from the top level scope too.

Example:

notice "foo", "bar", "baz"

Creating resources

Improvements: Block parameters can be specified by passing a block (see example below). When creating multiple resources they no longer need to be put into an Array. Resources can be created in top level scope now too.

Example:

file "test", "foobar", :ensure => :present
# OR
file "test", "foobar" do |f|
  f.ensure = :present
end

Creating nodes

Improvements: The name of node can be any object that responds to '#to_s' method or is a 'Regexp'. Inheritance can be set up using ':inherits' option (see example below).

Example:

node "test" do
  # ...snip...
end

node "default", :inherits => "test" do
  # ...snip...
end

# OR

node /foobar/i do
  # ...snip...
end

Creating classes

Improvements: There is no need to wrap arguments of a class into 'Puppet::AST::String' objects now. A new keyword 'use' is introduced to instantiate a class. Parameters can be accessed via 'params' method.

Example:

hostclass :baz do
  notice "baz"
end

hostclass :foobar, :arguments => {:myparam => 42}, :inherits => :baz do
  notice params[:myparam]
end

node "default" do
  use :foobar, :myparam => 43
end

Creating definitions

Improvements: Arguments no longer have to be wrapped into 'Puppet::AST::String' instances. Arguments can be accessed via 'params' method.

Example:

define :foobarbaz, :arguments => {:msg => "Hello!"} do
  notify "foobarbaz-#{params[:title]}", :message => params[:msg]
end

foobarbaz "title"
Exporting

Improvements: New variants of supported calls to 'export' method. It allows passing a block, resources, resource references and strings.

Example:

export do
  foo "resource"
end

Foo.collect

# OR

foo "resource"

export Foo["resource"]
Foo.collect

# OR

export foo "resource"
Foo.collect

Virtualizing

Improvements: New variants of calls to 'virtual' method are supported. It allows passing a block, resources, resource references and strings.

Example:

virtual do
  foo "resource"
end

Foo.realize

# OR

foo "resource"

virtual Foo["resource"]
Foo.realize

# OR

virtual foo "resource"
Foo.realize

Resource references

Improvements: New syntax, similar to Puppet's DSL, is added to reference a resource. It strongly depends 'const_missing' method. For top level constants :: operator should be used. If the constant is already defined there is a 'type' method that does the same thing.

Example:

foo "resource"

virtual Foo["resource"]

# for Ruby 1.9
File["/tmp/test"]

# for Ruby 1.8 when constant is already defined elsewhere
type("file")["/tmp/test"]

Resource overrides

Improvements: New syntax is based on resource references. It supports passing both block and a hash.

Example:

notify "foo"

Notify["foo"].override :message => "foobar"

# or

Notify["foo"].override do |o|
  o.message = "foobar"
end

Resource defaults

Improvements: Similarly to resource overrides, the new syntax is based on resource references. It also supports passing a block or a hash.

Example:

Notify.defaults :message => "foobar"

# or

Notify.defaults do |d|
  d.message = "foobar"
end

'my' method

Improvements: Ruby DSL for Puppet strongly depends on 'method_missing', so for Ruby 1.9 it uses 'BasicObject' and for Ruby 1.8 'Object' with almost all methods undefined. 'my' method can be used to access methods from 'Object'.

Example:

my { puts "Hello" } # => nil and a printout
puts "Hello"        # => NoMethodError

Recap

That's all when it comes to the new features. A lot of things have changed when compared to previous version of the Ruby DSL, and I think the new version addresses some of the issues in the previous version. However, there are still some things that need to be implemented, like the type loader support. The DSL is still not ready for production use. Some parts of it may change.

The current revision of the code can be found on my fork on github in 'dsl' branch. Annotated source code can be found in 'lib/puppet/dsl' directory of the project. If you have any questions or suggestions, please open an issue on GitHub.

Learn More:

Share via:
Posted in:
Tagged:
Mateusz Lenik

In reply to by Gregory

Add new comment

The content of this field is kept private and will not be shown publicly.

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.