Igo*_*any 38 chef-infra chef-recipe
假设我在食谱中有一个默认属性:
default.nginx_upstreams = {
'service1' => ['service1.server.com'],
'service2' => ['service2.server.com'],
}
Run Code Online (Sandbox Code Playgroud)
然后它会在角色和环境中被修改和覆盖,直到它最终到达我的配方.在那里,我计算了一些我想要添加到属性的附加服务.如果我做这样的事情:
node.nginx_upstreams.merge! {'service3' => ['service3.server.com']}
Run Code Online (Sandbox Code Playgroud)
然后当我尝试使用属性在我的模板,我得到了undefined method 'each' for nil:NilClass我的模板时,我尝试做
<% node.nginx_upstreams.each do |name, servers| %>
Run Code Online (Sandbox Code Playgroud)
另外,我也得到了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
Run Code Online (Sandbox Code Playgroud)
但这感觉就像一个黑客.我在这个页面node.set()之外找不到任何文档,这也表明你可以在配方中设置正常和覆盖属性,但没有说明如何.
那么......你如何从配方中正确设置属性(与其他所有东西深度融合)?这个node.set()电话实际上做了什么,我可以告诉它我想要合并的优先级吗?
Dra*_*ter 44
default.nginx_upstreamsdefault[:nginx_upstreams]和default['nginx_upstreams']- 相同- 惯例是使用后两者中的一个.当你进一步使用字符串时,也可以在这里使用它们.
nginx_upstreams在属性文件中初始化的方式与以这种方式执行相同:
default['nginx_upstreams']['service1'] = ['service1.server.com']
default['nginx_upstreams']['service2'] = ['service2.server.com']
Run Code Online (Sandbox Code Playgroud)
default['nginx_upstreams'] = {}在此之前你不必初始化.这些不是哈希,而是属性,而且它们更聪明.:)
修改配方内部的属性是这样的:
node.default['nginx_upstreams']['service3'] = ['service3.server.com']
Run Code Online (Sandbox Code Playgroud)
如果需要更改优先级,可以使用set或override代替default此处.省略优先名称(node['nginx_upstreams']或node.nginx_upstreams)将使用set优先级.但这已被弃用,很快就会被删除 - 这就是警告的全部内容.查看有关属性的手册页,因为一切都在那里.
Sar*_*n G 10
只是想进一步了解Chef属性,对于将要在节点属性覆盖上引用此问题的用户来说非常重要.
文件方法对应于属性
在菜谱的属性文件中或在配方中使用以下方法.这些方法对应于同名的属性类型:
属性优先
Chef-client始终按以下顺序应用属性:
其中列表中的最后一个属性是应用于节点的属性.
这意味着,OHAI属性将具有最高优先级,其中cookbook属性文件中的默认属性将具有最低优先级.
注意:为了用户的利益,从Chef文档中提供了有关属性的重要详细信息.因为有时URL会被移动或无效.
小智 6
所以在挖掘之后,我找到了答案:
node.set
使用node.default(或者可能是 node.override)代替 node.set 因为 node.set 是 node.normal 的别名。普通数据保存在节点对象上。因此,使用 node.set 会将数据保存在节点对象中。如果使用 node.set 的代码稍后被删除,如果该数据已经在节点上设置,它将保留。
Normal 和override 属性在chef-client 运行开始时被清除,然后根据当时食谱和食谱中的代码作为运行的一部分进行重建。
node.set(和node.normal) 应该只用于做一些事情,比如在第一次厨师客户端运行时为数据库生成密码,之后它会被记住(而不是持久化)。即使这种情况也应该避免,因为使用数据包是存储此类数据的推荐方式。