如何将哈希传递给 Puppet 中的自定义函数?
How do I pass a hash to a custom function in puppet?
我已经根据这里非常简单的例子定义了一个自定义函数:https://docs.puppet.com/guides/custom_functions.html
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
我收到以下错误:"Error 400 on SERVER: can't convert Hash into String" 行引用指向 "transform_service_hash($my_hash)"
我对 puppet 和 ruby 都是新手...所以我不确定我没有正确传递元素,如果我没有正确接收它,或者如果它是 puppet 无法处理的东西。请注意,我使用的是 puppet 的 3.8 版和 ruby.
的 1.8.7 版
感谢您的帮助。我一直在反对这个,google 还没有出现。
---编辑以阐明我的目标(我也对我的代码进行了一些特殊性的编辑):我试图将散列传递到 puppet 中的自定义 ruby 函数中。 "test" 散列有两个元素:一个字符串和一个数组。它是这样定义的:
$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
很明显,这里有些不对劲,因为我的文本没有被添加,完整的散列只打印一次,而且看起来是字符串形式。
我认为这可能与我没有传入文件名时出现的错误有关(见上文)。我认为我的散列被解释(或传递)为字符串,因此我无法访问这些元素。不幸的是,我仍然无法验证这一点或弄清楚为什么会发生这种情况。
---根据下面马特的回答编辑2。
我决定简化我的代码以隔离这个 "can't convert Hash into String error"。我还进行了他建议的更改,以消除我的密钥声明中的歧义。
$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
但是,我仍然得到相同的 "Hash to String error"。值得注意的是,我还尝试将哈希简化为:
$my_hash = { 'key' => "value1" , 'key2' => "value2" }
我仍然得到 "Hash to String error"。
我很快将您的自定义解析器函数转换为纯 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'] }
有 implicit/ambiguous 类型的键。在我用来测试的 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" }
应该解决这个问题。
顺便说一句,我建议使用 linters 来帮助您学习这些语言。 Puppet-Lint、Rubocop 和 Reek 都会帮助指出代码中次优和混乱的部分,以帮助您学习新语言。
在相关说明中,您可能希望在自定义解析器函数的顶部放置类似这样的内容:
raise(Puppet::ParseError, 'newfunction expects two arguments') if args.length != 2
在咬牙切齿(以及来自@MattSchuchard 的一些非常有用的指示)之后,我意识到 none 对我的功能所做的更改正在生效。每次更改自定义函数后都需要重新启动 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*
我已经根据这里非常简单的例子定义了一个自定义函数:https://docs.puppet.com/guides/custom_functions.html
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
我收到以下错误:"Error 400 on SERVER: can't convert Hash into String" 行引用指向 "transform_service_hash($my_hash)"
我对 puppet 和 ruby 都是新手...所以我不确定我没有正确传递元素,如果我没有正确接收它,或者如果它是 puppet 无法处理的东西。请注意,我使用的是 puppet 的 3.8 版和 ruby.
的 1.8.7 版感谢您的帮助。我一直在反对这个,google 还没有出现。
---编辑以阐明我的目标(我也对我的代码进行了一些特殊性的编辑):我试图将散列传递到 puppet 中的自定义 ruby 函数中。 "test" 散列有两个元素:一个字符串和一个数组。它是这样定义的:
$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
很明显,这里有些不对劲,因为我的文本没有被添加,完整的散列只打印一次,而且看起来是字符串形式。
我认为这可能与我没有传入文件名时出现的错误有关(见上文)。我认为我的散列被解释(或传递)为字符串,因此我无法访问这些元素。不幸的是,我仍然无法验证这一点或弄清楚为什么会发生这种情况。
---根据下面马特的回答编辑2。
我决定简化我的代码以隔离这个 "can't convert Hash into String error"。我还进行了他建议的更改,以消除我的密钥声明中的歧义。
$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
但是,我仍然得到相同的 "Hash to String error"。值得注意的是,我还尝试将哈希简化为:
$my_hash = { 'key' => "value1" , 'key2' => "value2" }
我仍然得到 "Hash to String error"。
我很快将您的自定义解析器函数转换为纯 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'] }
有 implicit/ambiguous 类型的键。在我用来测试的 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" }
应该解决这个问题。
顺便说一句,我建议使用 linters 来帮助您学习这些语言。 Puppet-Lint、Rubocop 和 Reek 都会帮助指出代码中次优和混乱的部分,以帮助您学习新语言。
在相关说明中,您可能希望在自定义解析器函数的顶部放置类似这样的内容:
raise(Puppet::ParseError, 'newfunction expects two arguments') if args.length != 2
在咬牙切齿(以及来自@MattSchuchard 的一些非常有用的指示)之后,我意识到 none 对我的功能所做的更改正在生效。每次更改自定义函数后都需要重新启动 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*