【问题标题】:Attribute precedence in chef cookbook厨师食谱中的属性优先级
【发布时间】:2014-01-26 19:35:28
【问题描述】:

我正在尝试通过从 How to Write Reusable Chef Cookbooks, Gangnam Style 获取灵感来实现一个包装食谱。我希望在没有管理器应用程序的情况下在我的节点上安装 tomcat 7。我创建了一个包含以下attributes/default.rb 文件的包装食谱:

default["tomcat"]["base_version"] = 7
default["tomcat"]["deploy_manager_apps"] = false

tomcat/attributes/default.rb 中提供的默认属性为:

default["tomcat"]["base_version"] = 6
#other attributes
default["tomcat"]["deploy_manager_apps"] = true
default["tomcat"]["user"] = "tomcat#{node["tomcat"]["base_version"]}

我希望在所有属性中覆盖这些值。但是,["tomcat"]["user"] 等属性不会被覆盖。以上在node["tomcat"]["user"] 中仍有tomcat6 的值。

我是否必须覆盖所有引用["tomcat"]["base_version"]}" 的属性?如果我的attributes/default.rb 是在 tomcat 食谱的default.rb 之前加载的,这会很好用。

我正在单独使用 Berkshelf、Vagrant 和 Chef 进行开发。在我的食谱的metadata.rb 中,我提到了depends "tomcat"

我的自定义食谱位于https://github.com/vaibhavguptaIITD/hcentive-ops/tree/master/hc-tomcat,tomcat 社区食谱位于https://github.com/opscode-cookbooks/tomcat

【问题讨论】:

    标签: chef-infra cookbook


    【解决方案1】:

    这是由于在 Chef 运行期间评估 ruby​​ 代码的方式/时间。在典型的 Chef 运行中,首先按照 run_list 规定的依赖顺序评估属性文件,如下所述:Chef 11 In-Depth: Attributes Changes

    Chef 检测到对 tomcat 食谱的依赖并首先加载/评估它的属性。所以default["tomcat"]["user"] = "tomcat#{node["tomcat"]["base_version"]} 设置为tomcat6 因为当时node["tomcat"]["base_version"] 的值是6。

    稍后,Chef 会评估您的包装食谱并将 node["tomcat"]["base_version"] 属性正确设置为 7,但永远不会重新评估 node["tomcat"]["user"]

    因此,如果您想更改 node["tomcat"]["user"] 的值,则需要在包装食谱中设置它的值。

    【讨论】:

    • 感谢您的回复。只是好奇,在编写包装食谱时,这个过程是不是有点麻烦。在包装的说明书之前先加载包装说明书的属性不应该是合乎逻辑的吗?
    • tickets.opscode.com/browse/CHEF-4837中有关于这种行为的讨论
    • 这篇博文很好地定义了它getchef.com/blog/2013/12/03/doing-wrapper-cookbooks-right 希望他们在下一个客户中修复它。此问题将 2 行属性文件转换为 50 行以上属性文件
    【解决方案2】:

    我遇到了同样的问题。设置一个基本变量并从中设置其他变量对我来说也很有意义:

    default["apache"]["apache_docroot"] = '/var/www'
    
    #other attributes:
    default['apache']['webapp1_docroot'] = "#{node['apache']['apache_docroot']/webapp1}"
    

    获取:/var/www/webapp1

    正如所指出的,Chef 会首先找到您的依赖食谱并加载它们的属性。在某种意义上似乎是错误的。为什么不加载我的父母

    override["apache"]["apache_docroot"] = '/net1/websites'
    

    首先,depends 会正常工作。它们较低,不会被覆盖。

    我找到了解决这个问题的方法。这不是很好,但它有效。 你最终会这样做:

    • 加载依赖于 tomcat *.rb
    • 加载父包装 *.rb
    • 重新加载依赖于 tomcat specific.rb

    您可以使用此命令node.from_file 从另一个文件重新加载属性:

    puts "*** RUNNING bundle-apache-java-tomcat-example default.rb"
    
    # Reload bundle-apache-java-jboss::default attributes to reset var's depending on apache_docroot value
    node.from_file(run_context.resolve_attribute( "bundle-apache-java-tomcat", "default" ) )
    

    正在加载cookbook: bundle-apache-java-tomcat, attribs file: default.rb

    旁注:我最终将其留在了我的食谱中,但我想使用哈希以“更简单”的方式设置网站属性。当我同时初始化一个哈希时,我无法设置一个属性,但我把那个代码留在了那里,以防我仍然需要它。

    我创建了 2 个新的捆绑食谱,希望可以轻松设置多个网站。您也可以设置或不设置从 apache 到 tomcat 的代理链接。

    https://github.com/stant/bundle-apache-java-tomcat-example(主要怎么用) https://github.com/stant/bundle-apache-java-tomcat(主一)

    【讨论】:

      【解决方案3】:

      这不是 chef-client 解析顺序中的错误。如果我们将其反转,那么您将永远无法读取基类中设置的默认值,因为这些值还没有被解析。

      它还允许您在默认优先级中设置的属性优先于您正在包装的说明书。如果我们反转拓扑排序,这将迫使包装食谱使用覆盖级别。如果您在包装器说明书之上有包装器说明书,那么现在您已经用完了标准属性优先级。最终你用完了优先级,你搞得一团糟。

      使用从属优先而不是父母优先解析属性的顺序可以正确解决这些优先级问题,以便每个人都可以在他们的包装手册中使用默认级别。

      这里的博文更详细地探讨了派生属性问题并提出了解决方案:

      https://coderanger.net/derived-attributes/

      我已经解决了一个针对 chef-client 的问题,以便在此处正式添加对惰性属性的支持(从该博客中引用的平衡派生 repo 已被废弃且不应使用):

      https://github.com/chef/chef/issues/10345

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-05-04
        • 2017-08-21
        • 2015-02-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-29
        相关资源
        最近更新 更多