如何将散列传递给puppet中的自定义函数?

问题描述:

我已经定义了目前基于这里很简单的例子一个自定义函数:https://docs.puppet.com/guides/custom_functions.html如何将散列传递给puppet中的自定义函数?

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 

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

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 

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

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

$my_hash = { key => "value1" , key2 => "value2" } 
    notify{ "new hash!! $my_hash. element1 is: $my_hash.key" :} 
    transform_service_hash($my_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 

我得到以下错误:“错误400服务器: ($ my_hash)“

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

感谢您的任何帮助。我一直在抨击我的头,谷歌还没有到来。

---编辑,以澄清我的目标(我也编辑了我的代码一点特异性):我试图传递一个散列到木偶内的自定义ruby函数。 “测试”散列有两个元素:一个字符串和一个数组。它被定义为这样的:

$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 

然而,在输出文件中,我看到:

mgt21 ~ # cat /var/tmp/blah 
keyvalue1key2array_value1array_value2 

显然,事情是在这里过的没有被加了我的文字完整的散列只是打印出来一次,看起来像字符串形式。

我相信这可能与我没有传入文件名时得到的错误有关(见上文)。我认为我的散列正在被解释(或传递)为一个字符串,因此,我无法访问这些元素。不幸的是,我仍然无法验证这一点或找出它可能发生的原因。

--- Edit2基于Matt的回答如下。

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

$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) 

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 

但是,我还是结了相同的 “散列到字符串错误”。值得注意的是,我也尝试简化我的散列:

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

我仍然得到“哈希到字符串错误”。

+0

你能做出更正你的代码,以准确反映你做了什么?当你的开始的例子有一个方法需要两个参数,你只提供一个参数,然后你在执行过程中显示的代码没有致命错误时,它不可能是准确的。 –

+0

对不起,我必须粘贴第二个例子的调用(在函数本身中定义filepath之后)。我修复了它。 – brbcoffee

+0

你能告诉我们你想要什么格式的“/ var/tmp/blah”吗?你似乎正在传递一个哈希,但我不知道你想如何在文件中查找。 – kcdragon

牙多少咬牙切齿(从@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* 

我赶紧把你的自定义分析器功能,将它转换成纯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 

这似乎证实我最初怀疑这里出了什么问题。您在木偶中的散列:

$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代码指定。改变你的木偶散列为:

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

应该解决这个问题。

在一个不相关的说明中,我建议使用棉绒帮助您学习这些语言。 Puppet-Lint,Rubocop和Reek都会帮助您指出代码中不理想和凌乱的部分,以帮助您学习新的语言。

在一个相关的说明,您可能希望把这样的事情在你自定义的解析器函数的顶部:

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

非常感谢您的继续帮助。我尝试了同样的纯红宝石功能,并且按预期工作(当然)。 我绝对同意你的看法,当传递这个散列值时它似乎是不正确的语法。我决定简化我的代码,专注于“无法将哈希转换为字符串错误。” 我将在上面的编辑部分中添加最新的代码块。 – brbcoffee

+1

为了上天,我需要每次重新启动puppetmaster服务第二个要点在这里:https://docs.puppet.com/guides/custom_functions.html /facepalm – brbcoffee

+0

@EricYoung是的重新启动Puppetmaster是自定义分析器函数中的主要烦恼之一在Puppet 4.3中此外,您还可以执行Puppet DSL函数和Puppet非分析器自定义函数(后者的设置非常奇怪),不需要重新启动。 –