Using Ruby Functions in EPP
Written: 2017-08-29
Author: WhatsARanjit
Link: WhatsARanjit/ruby_functions
The problem
Let’s look at a hash like this:
{"one"=>{"oneA"=>"A", "oneB"=>{"oneB1"=>"1", "oneB2"=>"2"}}, "two"=>["twoA", "twoB"]}
Using this data, our usecase is that we want to print this into a file as YAML.
Normally, using ERB, we can do something like:
file { '/tmp/somefile.yaml':
ensure => file,
content => inline_template('<%= @some_hash.to_yaml %>'),
}
The to_yaml()
method is readily availble. Now to exercise the new features in Puppet, you want to convert your templates over to EPP format. If you do this, you realize you gain the functionality of using the Puppet DSL in your templates, but you lose all the direct access to Ruby functionality that you had. You can only use functions written for Puppet, not just any Ruby functions that are available.
The fix
One way to make this happen, is to add Puppet functions that create the to_yaml
functionality. You can see this here. This will create only the functions that you’d like. In this example, to_json()
, to_json_pretty()
, and to_yaml()
. But what about any other functions? What about take()
, first()
, last()
, etc? Each of these require a newly created function in Ruby. Maybe there’s a way to open a door to all the Ruby functions that are available to Ruby? That is here.
This ruby_function()
from my module let you call any function/method that is relevant to the Object
that you’re operating on. Here are some examples:
Call first()
on an Array:
[root@puppet ~]# puppet apply -e 'notice(ruby_function([1,2], "first"))'
Notice: Scope(Class[main]): 1
Notice: Compiled catalog for puppet.whatsaranjit.com in environment production in 0.02 seconds
Notice: Applied catalog in 0.24 seconds
Call values_at()
on a Hash:
[root@puppet ~]# puppet apply <<'PP'
$h = { 'cat' => 'feline', 'dog' => 'canine', 'cow' => 'bovine' }
notice(ruby_function($h, 'values_at', 'cow', 'cat'))
PP
Notice: Scope(Class[main]): [bovine, feline]
Notice: Compiled catalog for puppet.whatsaranjit.com in environment production in 0.02 seconds
Notice: Applied catalog in 0.24 seconds
Call take()
within an EPP template using the $thing.function()
notation:
[root@puppet ~]# puppet apply <<'PP'
$template = '<%= [1,2,3,4].ruby_function("take", 2) %>'
notice(inline_epp($template))
PP
Notice: Scope(Class[main]): [1, 2]
Notice: Compiled catalog for puppet.whatsaranjit.com in environment production in 0.03 seconds
Notice: Applied catalog in 0.24 seconds