homeblogruby dsl

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:

  1. Developers can generate puppet resources without having to learn the Puppet DSL.
  2. Possible to overcome any limitations of the Puppet DSL.
  3. Ruby already has well known unit testing frameworks.

Methods:

Puppet's Ruby DSL introduces two types of methods:

Methods that create scopes:

  • define
    • 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.

  • hostclass
    • Creates a class.


      hostclass :fooclass, :foo do

      end


  • node
    • Creates a node scope which can be used to associate resources with a certain node.


      node 'mynode' do
      include apache
      end
      


    Each of these methods accepts a block in which resources can be declared. Resources can only be declared in one of these blocks.

    Methods that create resources

  • Resources are create by calling a method with the same name as the resource.


    #/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