【问题标题】:Overriding attributes in the recipe覆盖配方中的属性
【发布时间】:2013-01-15 03:41:53
【问题描述】:

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

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

但这感觉就像一个黑客。除了this page,我在node.set() 上找不到任何文档,这也表明您可以在配方中设置普通属性和覆盖属性,但没有说明如何设置。

那么...您如何从配方中正确设置属性(与其他所有内容一起深度合并)? node.set() 调用实际上做了什么,我可以告诉它我想要合并的优先级吗?

【问题讨论】:

  • 由@Draco Ater 提供的快速答案是node.default["key"] = "value"node.set["key"] = "value"node.override["key"] = "value",分别代表默认、正常和覆盖优先级

标签: chef-infra chef-recipe


【解决方案1】:

default.nginx_upstreamsdefault[:nginx_upstreams]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']

如果您需要更改优先级,您可以在此处使用setoverride 而不是default。省略优先级名称(node['nginx_upstreams']node.nginx_upstreams)将使用 set 优先级。但这已被弃用并且很快将被删除 - 这就是警告的全部内容。 查看manual page about attributes,因为一切都在那里。

【讨论】:

    【解决方案2】:

    只是想进一步了解 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 在厨师客户端运行开始时识别的自动属性

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

    这意味着OHAI属性的优先级最高,而cookbook属性文件中的默认属性优先级最低。

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

    【讨论】:

      【解决方案3】:

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

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

      Normal 和 override 属性在 chef-client 运行开始时被清除,然后根据当时的食谱和食谱中的代码作为运行的一部分重新构建。

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

      【讨论】:

        猜你喜欢
        • 2019-07-25
        • 2010-09-27
        • 2021-06-22
        • 1970-01-01
        • 1970-01-01
        • 2021-09-14
        • 2018-09-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多