Ruby DSL
Editor's Note: The Ruby DSL was deprecated in Puppet 3x, and is removed in Puppet 4.0.0.
Starting in Puppet 2.6.x, manifests can be written in Ruby.
Motivations:
- Developers can generate puppet resources without having to learn the Puppet DSL.
- Possible to overcome any limitations of the Puppet DSL.
- Ruby already has well known unit testing frameworks.
Methods:
Puppet's Ruby DSL introduces two types of methods:Methods that create scopes:
- Allows the user to implement a defined resource type in Ruby.
define "services::port", :port, :protocol => 'tcp' do ... end
port and protocols are accessible within the block as instance variables.
- Creates a class.
hostclass :fooclass, :foo do
end
- Creates a node scope which can be used to associate resources with a certain node.
node 'mynode' do include apache end
Methods that create resources
#/etc/puppet/manifests/blah.rb
hostclass :blah do
file '/tmp/blah', :content => 'bar'
end
node 'default' do
include 'blah'
end
Now I can run puppet apply on the Ruby file to create the file:
# puppet /etc/puppet/manifests/blah.rb
notice: /Stage[main]/Blah/File[/tmp/blah]/ensure: defined content as '{md5}37b51d194a7513e45b56f6524f2d51f2'
Attributes passed to a defined resource or hostclass will be available as instance variables within the block.
define :foo, :bar do
notify @name, :message => @bar
end
Examples
One of the oldest open tickets in Puppet requests mkdir_p functionality (It's #86 :) ). We can easily code this with the Ruby DSL since Ruby can iterate over all directory subpaths to create File resources.define :mkdir_p do
name = @name
until name == '/'
file name, :ensure => 'directory'
name = File.dirname(name)
end
end
node 'default' do
mkdir_p '/tmp/foo/bar/baz'
end
Now puppet will create all directories in this path!
$ puppet mkdir_p.rb
notice: /Stage[main]//Node[default]/Mkdir_p[/tmp/foo/bar/baz]/File[/tmp/foo]/ensure: ensure changed 'file' to 'directory'
notice: /Stage[main]//Node[default]/Mkdir_p[/tmp/foo/bar/baz]/File[/tmp/foo/bar]/ensure: created
notice: /Stage[main]//Node[default]/Mkdir_p[/tmp/foo/bar/baz]/File[/tmp/foo/bar/baz]/ensure: created
Now, we could use this defined resource type in a function to create a file with its parent directories:
define :with_parents do
mkdir_p File.dirname(@name)
file @name, :ensure => 'present'
end
define :mkdir_p do
name = @name
until name == '/'
file name, :ensure => 'directory'
name = File.dirname(name)
end
end
node 'default' do
with_parents '/tmp/foo/bar/baz/myfile'
end