43

假设我在食谱中有一个默认属性:

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()调用实际上做了什么,我可以告诉它我想要合并的优先级吗?

4

3 回答 3

46

default.nginx_upstreamsdefault[:nginx_upstreams]与and相同default['nginx_upstreams']- 惯例是使用后两者中的 1 个。当您进一步使用字符串时,也请在此处使用它们。

在属性文件中初始化的方式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']

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

于 2013-01-31T08:24:26.310 回答
13

只是想进一步了解 Chef 属性,这对用户来说非常重要,他们将在节点属性覆盖上参考这个问题。

文件方法对应属性

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

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

属性优先级

厨师客户端始终按以下顺序应用属性:

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

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

这意味着,OHAI 属性将具有最高优先级,而食谱属性文件中的默认属性将具有最低优先级。

注意:为了用户的利益,提供了来自 Chef 文档的属性的重要详细信息。因为有时 URL 会被移动或无效。

于 2015-11-19T12:00:17.317 回答
6

所以在四处挖掘之后,我找到了答案:

node.set
使用node.default(或者可能是 node.override)而不是 node.set,因为 node.set 是 node.normal 的别名。普通数据保存在节点对象上。因此,使用 node.set 会将数据持久化到节点对象中。如果稍后删除使用 node.set 的代码,如果该数据已经在节点上设置,它将保留。

正常和覆盖属性在厨师客户端运行开始时被清除,然后根据当时食谱和食谱中的代码作为运行的一部分重新构建。

node.set(and node.normal) 只能用于在第一次运行 chef-client 时为数据库生成密码,然后记住它(而不是持久化)。即使是这种情况也应该避免,因为推荐使用数据包来存储此类数据。

于 2015-04-17T14:34:19.717 回答