我们说我在食谱中有一个默认属性:
default.nginx_upstreams = {
'service1' => ['service1.server.com'],
'service2' => ['service2.server.com'],
}
然后它会在角色和环境中被修改和覆盖,直到它最终到达我的食谱。在那里,我计算了一些我想要添加到属性的附加服务。如果我做这样的事情:
node.nginx_upstreams.merge! {'service3' => ['service3.server.com']}
然后当我尝试在我的模板中使用该属性时,我尝试在模板中获得undefined method 'each' for nil:NilClass
<% node.nginx_upstreams.each do |name, servers| %>
另外,我还得到WARN: Setting attributes without specifying a precedence is deprecated and will be removed in Chef 11.0
。有用的警告告诉我如何以正常优先级设置属性(显然,使用node.set["key"] = "value"
,但不告诉我如何指定默认或覆盖属性。
我可以通过这样的方式解决这个问题:
upstreams = node.nginx_upstreams.to_hash
upstreams.merge! {'service3' => ['service3.server.com']}
template "nginx_config" do
variables({:upstreams=>upstreams})
end
但这感觉就像一个黑客。我找不到node.set()
node.set()
以外的任何文档,这也表明您可以在配方中设置正常和覆盖属性,但不会说明如何。
那么......你如何从配方中正确设置属性(与其他所有东西深度融合)? {{1}}调用实际上做了什么,我可以告诉它我想要合并的优先级吗?
答案 0 :(得分:43)
default.nginx_upstreams
与default[:nginx_upstreams]
和default['nginx_upstreams']
相同 - 惯例是使用后两者中的一个。当你进一步使用字符串时,也可以在这里使用它们。
在属性文件中初始化nginx_upstreams
的方式与以这种方式执行相同:
default['nginx_upstreams']['service1'] = ['service1.server.com']
default['nginx_upstreams']['service2'] = ['service2.server.com']
在此之前你不必初始化default['nginx_upstreams'] = {}
。这些不是哈希,而是属性,而且它们更聪明。 :)
从配方内部修改属性就像这样:
node.default['nginx_upstreams']['service3'] = ['service3.server.com']
如果您需要更改优先顺序,可以在此处使用set
或override
代替default
。省略优先名称(node['nginx_upstreams']
或node.nginx_upstreams
)将使用set
优先级。但这已被弃用,很快就会被删除 - 这就是警告的全部内容。
查看manual page about attributes,因为一切都在那里。
答案 1 :(得分:10)
只是想进一步了解Chef属性,对于将要在节点属性覆盖上引用此问题的用户来说非常重要。
文件方法对应属性
在菜谱的属性文件中或在配方中使用以下方法。这些方法对应于同名的属性类型:
属性优先
属性始终由chef-client按以下顺序应用:
其中列表中的最后一个属性是应用于节点的属性。
这意味着,OHAI属性将具有最高优先级,其中cookbook属性文件中的默认属性将具有最低优先级。
注意:为了用户的利益,为attributes的Chef文档提供了重要的详细信息。因为有时URL会被移动或无效。
答案 2 :(得分:4)
所以在挖掘之后,我找到了答案:
<强> node.set 强>
使用node.default
(或者可能是node.override)而不是node.set,因为node.set是node.normal的别名。正常数据保留在节点对象上。因此,使用node.set将持久保存节点对象中的数据。如果稍后删除使用node.set的代码,如果已在节点上设置了该数据,则该数据将保留。
正常和覆盖属性在chef-client运行开始时被清除,然后根据当时烹饪书和食谱中的代码重建为运行的一部分。
node.set
(和node.normal
)只应用于在第一次自选 - 客户端运行时为数据库生成密码,之后会记住(而不是保留)。即使是这种情况也应该避免,因为使用数据包是存储此类数据的推荐方法。