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

Chef13升级至Chef16后cookbook迁移时node属性修改失败问题

问题根因

Chef 15及以上版本调整了属性的默认访问规则,直接读取的node属性返回的是只读的ImmutableMash实例,并非普通Ruby哈希:

  1. 你局部变量app_params是直接从node属性赋值的只读对象,调用store、merge!都无法修改原有对象,所以会抛出不可变修改报错,或者看起来修改不生效
  2. 你显式修改node.force_override!属性后没有更新局部变量app_params的取值,日志打印的仍是旧的局部变量,所以看不到更新效果
  3. 之前merge!尝试用了符号键:product_guid,和原有属性的字符串键不匹配,也是不生效的原因之一

解决方案

分两种场景处理:

场景1:仅临时使用app_params新增字段,不需要持久化到node属性

直接将ImmutableMash转为普通哈希再操作即可:

# 第一步将读取的node属性转为普通可写哈希,替换你原来的app_params赋值逻辑
app_params = node['替换为你实际的属性前缀']['app_params'].to_h

guid = guid.gsub(/{/, '').gsub(/}/, '')
log "[#{role}][#{recipe_name}][#{app_name}]: GUID for installer #{app_name} is #{guid}"
# 普通哈希可以正常调用store方法,不会报错
app_params.store('product_guid', guid)

# 后续直接使用app_params即可,已经包含product_guid字段

场景2:需要将product_guid持久化存储到node属性,供后续其他recipe调用

先显式指定优先级修改node属性,再同步更新局部变量即可:

guid = guid.gsub(/{/, '').gsub(/}/, '')
log "[#{role}][#{recipe_name}][#{app_name}]: GUID for installer #{app_name} is #{guid}"

# 显式指定优先级修改node属性,default/override/force_override根据你的实际需求选择
node.default['替换为你实际的属性前缀']['app_params']['product_guid'] = guid
# 同步更新局部变量取值,或者直接给app_params新增字段也可以
app_params = node['替换为你实际的属性前缀']['app_params']

# 此时打印app_params即可看到新增的product_guid字段

验证说明

修改完成后重新运行kitchen测试,日志打印的app_params.keys会包含product_guid,符合预期结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 06:48:05