如何将哈希传递给puppet中的自定义函数?

时间:2016-08-19 21:18:07

标签: ruby hash puppet

我已根据这里非常简单的示例定义了一个自定义函数:https://docs.puppet.com/guides/custom_functions.html

var estadoSchema = Schema({
    estado_nome: {
        type :String,
        unique : true
    }
});

这种方式有效。我可以这样称呼它:

module Puppet::Parser::Functions
  newfunction(:transform_service_hash) do |args|
    filename = args[0]
    hash_to_be_transformed = args[1]
    File.open(filename, 'a') {|fd| fd.puts hash_to_be_transformed }
  end
end

,文件显示:

  $my_hash = { key => "value1" , key2 => "value2" }
  notify{ "new hash!! $my_hash" :}
  transform_service_hash('/var/tmp/blah',$my_hash)

但是,如果我尝试访问哈希的元素,则没有任何变化:

mgt21 ~ # cat /var/tmp/blah
keyvalue1key2value2

上述块将完全相同的数据输出到/ var / tmp / blah。

而且,有趣的是,如果我删除文件名pass并在模块中静态定义它:

module Puppet::Parser::Functions
  newfunction(:transform_service_hash) do |args|
    filename = args[0]
    hash_to_be_transformed = args[1]
    element1 = hash_to_be_transformed["key"] 
    File.open(filename, 'a') {|fd| fd.puts element1 }
  end
end

  $my_hash = { key => "value1" , key2 => "value2" }
  notify{ "new hash!! $my_hash. element1 is: $my_hash.key" :}
  transform_service_hash($my_hash)

我收到以下错误:" SERVER上的错误400:无法将哈希转换为字符串"使用指向" transform_service_hash($ my_hash)"

的行引用

我是傀儡和红宝石的新手...所以我不确定我是不是正确地传递了元素,如果我没有正确地接收它,或者它是木偶无法处理的东西。请注意,我使用的是3.8版的木偶和1.8.7的红宝石。

感谢您的帮助。我一直在反对这一点,谷歌还没有到来。

---编辑以澄清我的目标(我还编辑了一些特殊的代码):我试图将一个哈希传递给puppet中的自定义ruby函数。 "测试" hash有两个元素:一个字符串和一个数组。它定义如下:

module Puppet::Parser::Functions
  newfunction(:transform_service_hash) do |args|
    hash_to_be_transformed = args[0]
    element1 = hash_to_be_transformed["key"] 
    File.open('/var/tmp/blah2', 'a') {|fd| fd.puts element1 }
  end
end

该功能如下所示:

  $my_hash = { key => "value1" , key2 => ['array_value1', 'array_value2'] }
  $my_display_element=$my_hash["key2"][0]
  notify{ "new hash!! $my_hash. the first value of the array stored in element2 is: $my_display_element" :}
  transform_service_hash('/var/tmp/blah',$my_hash)

现在,我只是希望能够看到我能够像哈希一样访问传递的哈希中的元素。所以我喜欢输出文件看起来像:

module Puppet::Parser::Functions
  newfunction(:transform_service_hash) do |args|
    filename = args[0]
    hash_to_be_transformed = args[1]
    element1 = args[1]["key"]
    element2 = args[1]["key2"][0]
    #element1 = hash_to_be_transformed["key"]
    #element2 = hash_to_be_transformed["key2"][0] 
    File.open(filename, 'a') {|fd| fd.puts "hash_to_be_transformed: #{hash_to_be_transformed}\n" }
    File.open(filename, 'a') {|fd| fd.puts "element1: #{element1}\n" }
    File.open(filename, 'a') {|fd| fd.puts "element2: #{element2}\n" }        
  end
end

但是,在输出文件中,我看到:

hash_to_be_transformed: keyvalue1key2array_value1array_value2
element1: value1
element2: array_value1

显然,由于我的文本没有被添加,所以有些东西在这里,完整的哈希只打印出一次,看起来像字符串形式。

我认为这可能与我在传递文件名时所得到的错误有关(见上文)。我认为我的哈希被解释(或传递)为一个字符串,因此,我无法访问这些元素。不幸的是,我仍然无法验证这一点或弄清楚为什么会发生这种情况。

--- Edit2基于马特的答案。

我决定简化我的代码以隔离这个"无法将哈希转换为字符串错误"。我还提出了他的建议更改,以消除我的密钥声明中的含糊不清。

mgt21 ~ # cat /var/tmp/blah 
keyvalue1key2array_value1array_value2

  $my_hash = { 'key' => "value1" , 'key2' => ['array_value1', 'array_value2'] }
  $my_display_element=$my_hash["key2"][0]
  notify{ "new hash!! $my_hash. the first value of the array stored in element2 is: $my_display_element" :}
  transform_service_hash($my_hash)

但是,我仍然会遇到相同的" Hash to String错误"。值得注意的是,我也尝试将哈希简化为:

module Puppet::Parser::Functions
  newfunction(:transform_service_hash) do |args|
    hash_to_be_transformed = args[0]
    element1 = args[0]['key']
    element2 = args[0]['key2'][0]
    File.open('/var/tmp/blah', 'a') {|fd| fd.puts "hash_to_be_transformed: #{hash_to_be_transformed}\n" }
    File.open('/var/tmp/blah', 'a') {|fd| fd.puts "element1: #{element1}\n" }
    File.open('/var/tmp/blah', 'a') {|fd| fd.puts "element2: #{element2}\n" }
  end
end

我仍然得到" Hash to String错误"。

2 个答案:

答案 0 :(得分:1)

我快速获取了自定义解析器函数并将其转换为纯ruby,如下所示:

hash = { 'key' => 'value1', 'key2' => %w(array_value1 array_value2) }

def newfunction(filename, a_hash)
  element1 = a_hash['key']
  element2 = a_hash['key2'][0]
  File.open(filename, 'a') do |fd|
    fd.puts "hash_to_be_transformed: #{a_hash}"
    fd.puts "element1: #{element1}"
    fd.puts "element2: #{element2}"
  end
end

newfunction('foo.txt', hash)

这会导致输出文本文件如下所示:

hash_to_be_transformed: {"key"=>"value1", "key2"=>["array_value1", "array_value2"]}
element1: value1
element2: array_value1

这似乎证实了我最初怀疑这里出了什么问题。你在Puppet中的哈希:

$my_hash = { key => "value1" , key2 => ['array_value1', 'array_value2'] }

具有隐式/模糊类型的键。在我用来测试的ruby代码中,我明确地将它们建立为字符串。这也与代码失败时的这些行强烈相关:

element1 = args[1]["key"]
element2 = args[1]["key2"][0]

和您的错误消息:

Error 400 on SERVER: can't convert Hash into String

因为您在ruby代码中指定了您希望键是字符串的。将Puppet中的哈希值更改为:

$my_hash = { 'key' => "value1" , 'key2' => "value2" }

应该解决这个问题。

在不相关的说明中,我建议使用短裤来帮助您学习这些语言。 Puppet-Lint,Rubocop和Reek都会帮助您指出代码的次优和杂乱部分,以帮助您学习新语言。

在相关的说明中,您可能希望在自定义解析器函数的顶部放置类似的内容:

raise(Puppet::ParseError, 'newfunction expects two arguments') if args.length != 2

答案 1 :(得分:0)

在咬牙切齿之后(以及来自@MattSchuchard的一些非常有用的指针),我意识到我的功能没有任何变化生效。每次更改自定义函数后,都需要重新启动puppetmaster服务:docs.puppet.com/guides/custom_functions.html(适当地在" Gotchas")。

一旦我在每次更改函数后开始重新启动此服务,我的哈希都能够正确解析:

来自.pp文件:

  $filename = "/var/tmp/test"
  $my_hash = { 'key' => "value1" , 'key2' => ["M\'lady\n*doffs cap*", 'array_value2'] }
  transform_service_hash($filename, $my_hash)
来自ruby文件的

module Puppet::Parser::Functions
  newfunction(:transform_service_hash) do |args|
    filename = args[0]
    hash_to_be_transformed = args[1]
    array_val = hash_to_be_transformed['key2'][0]
    File.open(filename, 'a') {|fd| fd.puts "#{array_val}\n" }
  end
end

并输出:

mgt21 tmp # cat test 
M'lady
*doffs cap*