Reputation: 12710
I have an array as follows:
$servers = [
{name => 'server1', address => '10.10.10.11', port => 8081},
{name => 'server2', address => '10.10.10.12', port => 8082},
]
and I need to programmatically convert it into a hash based on the 'name' key:
$serversMap = {
server1 => {address => '10.10.10.11', port => 8081},
server2 => {address => '10.10.10.12', port => 8082},
}
this works in puppet 3:
$serversMap = $servers.reduce({}) |$cumulate, $server| {
$key = "${server['name']}"
$value = $server.filter |$entry| { $entry[0] != 'name' }
$tmp = merge($cumulate, {"$key" => $value })
$tmp
}
however, is there an easier way?
and why I need to create the temporal variable $tmp?
without that, I get at Error: Function 'merge' must be the value of a statement
error.
ps: it's obvious but I will say it anyway: the $servers variable is given to me, I cannot change its structure. and I need that same data but in the form of $serversMap. and so, I am asking how to programmatically convert from $servers to $serversMap.
Upvotes: 4
Views: 9556
Reputation: 19987
Except for the $tmp variable this code is optimal.
The $tmp variable needs to be there, because the merge function is an rvalue
. From the docs:
There are actually two completely different types of functions available — rvalues (which return a value) and statements (which do not). If you are writing an rvalue function, you must pass :type => :rvalue when creating the function; see the examples below.
The puppet source that produces this error is pretty self explanatory when it comes to rvalue statements:
# It is harmless to produce an ignored rvalue, the alternative is to mark functions
# as appropriate for both rvalue and statements
# Keeping the old behavior when a pblock is not present. This since it is not known
# if the lambda contains a statement or not (at least not without a costly search).
# The purpose of the check is to protect a user for producing a meaningless rvalue where the
# operation has no side effects.
#
if !pblock && Puppet::Parser::Functions.rvalue?(@name)
raise Puppet::ParseError,
"Function '#{@name}' must be the value of a statement"
end
The real reason is that Puppet is just not that sophisticated as a language. If you want real power switch to Ruby.
Upvotes: 4