覆盖配方中的属性

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)

如果需要更改优先级,可以使用setoverride代替default此处.省略优先名称(node['nginx_upstreams']node.nginx_upstreams)将使用set优先级.但这已被弃用,很快就会被删除 - 这就是警告的全部内容.查看有关属性手册页,因为一切都在那里.


Sar*_*n G 10

只是想进一步了解Chef属性,对于将要在节点属性覆盖上引用此问题的用户来说非常重要.

文件方法对应于属性

在菜谱的属性文件中或在配方中使用以下方法.这些方法对应于同名的属性类型:

  • 覆盖
  • 默认
  • normal(或set,其中set是normal的别名)
  • _除非
  • 属性?

属性优先

Chef-client始终按以下顺序应用属性:

  1. 位于cookbook属性文件中的默认属性
  2. 位于配方中的默认属性
  3. 位于环境中的默认属性
  4. 位于角色中的默认属性
  5. force_default属性位于cookbook属性文件中
  6. force_default属性位于配方中
  7. 位于cookbook属性文件中的普通属性
  8. 位于配方中的常规属性
  9. 覆盖属性位于cookbook属性文件中
  10. 位于配方中的覆盖属性
  11. 位于角色中的覆盖属性
  12. 位于环境中的覆盖属性
  13. force_override属性位于cookbook属性文件中
  14. 位于配方中的force_override属性
  15. Ohai在厨师 - 客户运行开始时识别的自动属性

其中列表中的最后一个属性是应用于节点的属性.

这意味着,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) 应该只用于做一些事情,比如在第一次厨师客户端运行时为数据库生成密码,之后它会被记住(而不是持久化)。即使这种情况也应该避免,因为使用数据包是存储此类数据的推荐方式。