You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Puppet中用.map生成Hash而非数组及Hash合并的目标数组保留问题

解决Puppet中Hiera Hash合并时数组被覆盖的问题

听起来你在处理Puppet模块里的JMS配置时,遇到了两个核心问题:一是用.map返回数组导致合并操作异常,二是合并后原有target和targettype数组元素被覆盖,而不是追加。我来帮你一步步解决这个问题。

问题拆解

首先明确你的核心需求:

  1. 从Hiera读取jms_subdeployment_instances Hash结构
  2. 基于$array_domain_jmsserver_addresses生成新的target条目
  3. 将新条目追加到原有target数组,同时对应追加相同数量的JMSServer到targettype数组
  4. 最终合并后的Hash要完整保留所有原有和新增的元素

修正后的代码实现

先保持你的Hiera数据(service.yaml)不变:

jms_subdeployment_instances:
  'BPMJMSModuleUDDs:BPMJMSSubDM':
    ensure: 'present'
    target:
      - 'BPMJMSServer_auto_1'
      - "BPMJMSServer_auto_%{::ec2_tag_name}"
    targettype:
      - 'JMSServer'
      - 'JMSServer'

然后修改init.pp的代码,解决数组覆盖和类型不匹配的问题:

# 读取Hiera数据,确保默认参数配置正确
$jms_subdeployments = lookup('jms_subdeployment_instances', $default_params)

# 构建用于合并的更新Hash:针对每个子部署追加target和targettype
$jms_target_updates = $jms_subdeployments.reduce({}) |$accumulator, $subdep_entry| {
  # 解构当前子部署的名称和对应数据
  $subdep_name = $subdep_entry[0]
  $subdep_data = $subdep_entry[1]
  
  # 从服务器地址列表生成新的target条目
  $jms_short_name = $subdep_name[0, 3] # 取子部署名称前3个字符,示例中为"BPM"
  $new_targets = $array_domain_jmsserver_addresses.map |$server| {
    "${jms_short_name}JMSServer_auto_${server}"
  }
  
  # 合并原有数组与新数组:用concat保证是追加而非替换
  $updated_target = concat($subdep_data['target'], $new_targets)
  # 为每个新target生成对应的targettype条目,再合并到原有数组
  $updated_targettype = concat(
    $subdep_data['targettype'],
    Array.new($new_targets.size, 'JMSServer')
  )
  
  # 将更新后的子部署数据加入累积Hash
  $accumulator + {
    $subdep_name => {
      'target'     => $updated_target,
      'targettype' => $updated_targettype
    }
  }
}

# 使用deep_merge递归合并原始Hash和更新Hash,确保嵌套数组正确追加
$merge_subdeployment_targets = deep_merge($jms_subdeployments, $jms_target_updates)

关键改进点说明

  1. 用reduce构建Hash而非map返回数组:
    .map会返回数组,而我们需要的是和原始数据结构匹配的Hash,这样deep_merge才能正常工作。reduce({})从空Hash开始,每次迭代将更新后的子部署数据加入累积器,最终得到正确的Hash结构。

  2. 用concat实现数组追加:
    普通的Hash合并会直接替换键值,而concat可以把原有数组和新数组合并成一个,完美保留所有元素。

  3. 对应更新targettype数组:
    用Array.new($new_targets.size, 'JMSServer')生成和新target数量一致的JMSServer数组,再和原有targettype合并,保证每个target都有对应的类型。

  4. 使用deep_merge处理嵌套结构:
    普通的merge只会替换顶层键的值,而deep_merge会递归处理嵌套的Hash,确保target和targettype这些嵌套数组被正确合并,而不是被整体替换。

最终效果验证

假设$array_domain_jmsserver_addresses的值是['server1', 'server2'],最终$merge_subdeployment_targets会生成你期望的结构:

{
  'BPMJMSModuleUDDs:BPMJMSSubDM' => {
    'ensure'     => 'present',
    'target'     => [
      'BPMJMSServer_auto_1',
      'BPMJMSServer_auto_your-ec2-tag-name', # Puppet会自动解析ec2_tag_name变量
      'BPMJMSServer_auto_server1',
      'BPMJMSServer_auto_server2'
    ],
    'targettype' => [
      'JMSServer',
      'JMSServer',
      'JMSServer',
      'JMSServer'
    ]
  }
}

内容的提问来源于stack exchange,提问作者Dave Shaw

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:21:40