Chef13升级至Chef16后cookbook迁移时node属性修改失败问题
问题根因
Chef 15及以上版本调整了属性的默认访问规则,直接读取的node属性返回的是只读的ImmutableMash实例,并非普通Ruby哈希:
- 你局部变量
app_params是直接从node属性赋值的只读对象,调用store、merge!都无法修改原有对象,所以会抛出不可变修改报错,或者看起来修改不生效 - 你显式修改
node.force_override!属性后没有更新局部变量app_params的取值,日志打印的仍是旧的局部变量,所以看不到更新效果 - 之前
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
相关产品推荐
相关产品推荐

