我正在尝试以云中的 JMS 服务器为目标,puppet 模块 init.pp 需要向哈希添加一个 key 。
我正在读取 hiera block ,并且必须提取其中的一部分以形成新的哈希值。 .each 不返回任何值,因此我使用 .map。 我得到的值正是我想要的,但是当我尝试 deep_merge 时,我发现 .map 输出为数组。
服务.yaml
jms_subdeployment_instances:
'BPMJMSModuleUDDs:BPMJMSSubDM':
ensure: 'present'
target:
- 'BPMJMSServer_auto_1'
- "BPMJMSServer_auto_%{::ec2_tag_name}"
targettype:
- 'JMSServer'
- 'JMSServer'
初始化.pp
$jms_subdeployments = lookup('jms_subdeployment_instances', $default_params)
$jms_target_args = $jms_subdeployments.map |$subdep, $value| {
$jms_short_name = $subdep[0, 3]
$jms_subdeployment_inst = $array_domain_jmsserver_addresses.map |$index, $server| {
"${jms_short_name}JMSServer_auto_${server}"
if defined('$jms_subdeployment_inst') {
$jmsTargetArg = {
"${subdep}" => {
'target' => $jms_subdeployment_inst
}
}
}
}
$merge_subdeployment_targets = merge($jms_subdeployments, $jms_target_args)
```Output
New JMS targets are : [{BPMJMSModuleUDDs:BPMJMSSubDM => {target => [BPMJMSServer_auto_server101, BPMJMSServer_auto_server102]}}]
封闭的 [ ] 给我带来了麻烦。据我所知,在 puppet .to_h 中也不起作用
谢谢
2019 年 7 月 22 日更新:
感谢您的回复,我不得不稍微调整它,因为 puppet 因“服务器错误:评估错误:评估方法调用时出错,‘值’参数‘hsh’需要哈希值,得到元组而失败”
$array_domain_jmsserver_addresses =
any2array(hiera('pdb_domain_msserver_addresses'))
$array_domain_jmsserver_addresses.sort()
$jms_subdeployments = lookup('jms_subdeployment_instances', $default_params)
$hash_domain_jmsserver_addresses = Hash($array_domain_jmsserver_addresses)
if $hash_domain_jmsserver_addresses.length > 0 {
$jms_target_arg_tuples = $jms_subdeployments.keys.map |$subdep| {
$jms_short_name = $subdep[0, 3]
$jms_subdeployment_inst = regsubst(
$hash_domain_jmsserver_addresses.values, /^/, "${jms_short_name}JMSServer_auto_")
# the (key, value) tuple to which this element maps
[ $subdep, { 'target' => $jms_subdeployment_inst } ]
}
$jms_target_args = Hash($jms_target_arg_tuples)
} else {
$jms_target_args = {}
}
notify{"Normal array is : ${jms_subdeployments}": }
notify{"Second array is : ${jms_target_args}": }
$merge_subdeployment_targets = deep_merge($jms_subdeployments, $jms_target_args)
notify{"Merged array is : ${merge_subdeployment_targets}": }
Normal is : {BPMJMSModuleUDDs:BPMJMSSubDM => {ensure => present, target => [BPMJMSServer_auto_1, BPMJMSServer_auto_server1], targettype => [JMSServer, JMSServer]},
Second is : {BPMJMSModuleUDDs:BPMJMSSubDM => {target => [BPMJMSServer_auto_server2]}
Merged is : {BPMJMSModuleUDDs:BPMJMSSubDM => {ensure => present, target => [BPMJMSServer_auto_server2], targettype => [JMSServer, JMSServer]}
期望的输出:
{BPMJMSModuleUDDs:BPMJMSSubDM => {ensure => present, target => [BPMJMSServer_auto_1, BPMJMSServer_auto_server1, BPMJMSServer_auto_server2], targettype => [JMSServer, JMSServer, JMSServer]}
最佳答案
when I tried a deep_merge I discovered that .map outputs as an array.
是的,这是its documented behavior 。 map()
应被视为集合元素上的函数,而不是整个集合上的函数,并且结果始终以数组形式提供。
查看 converting values to hashes 的替代方案可能会很有用。 。特别有吸引力的是这个:
- An
Array
matchingArray[Tuple[Any,Any], 1]
is converted to a hash where each tuple describes a key/value entry
要利用此功能,请将每个条目映射到一个(键,值)元组,并将生成的元组数组转换为哈希值。您对该方法的尝试转换可能如下所示:
if $array_domain_jmsserver_addresses.length > 0 {
$jms_target_arg_tuples = $jms_subdeployments.keys.map |$subdep| {
$jms_short_name = $subdep[0, 3]
$jms_subdeployment_inst = regsubst(
$array_domain_jmsserver_addresses.sort, /^/, "${jms_short_name}JMSServer_auto_")
# the (key, value) tuple to which this element maps
[ $subdep, { 'target' => $jms_subdeployment_inst } ]
}
$jms_target_args = Hash($jms_target_arg_tuples)
} else {
$jms_target_args = {}
}
$merge_subdeployment_targets = merge($jms_subdeployments, $jms_target_args)
请注意,由于您不使用 $jms_subdeployments
的值,因此我冒昧地通过应用 keys()
函数来稍微简化您的代码。我还使用 regsubst()
而不是 map()
从 $array_domain_jmsserver_addresses
的元素形成目标名称,我个人认为更具可读性在这种情况下,特别是因为您没有使用索引。
我还推断出您的 if Defined()
测试要完成的意思,并将其替换为 $array_domain_jmsserver_addresses
长度的最外层测试大批。人们还可以以更函数式的形式编写它,通过构建哈希而不考虑是否有任何目标,然后对其进行过滤,但这似乎很浪费,因为看起来要么全部条目将具有(相同的)目标,或者没有。
关于arrays - 使用 .map (或另一个 stdlib 功能)创建哈希而不是数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57114636/