厨师食谱中的属性优先权

时间:2014-01-08 15:41:48

标签: chef cookbook

我试图从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"]等属性不会被覆盖。上述内容在tomcat6中仍具有node["tomcat"]["user"]的值。

我是否必须覆盖引用["tomcat"]["base_version"]}"的所有属性?如果我的attributes/default.rb在tomcat cookbook default.rb之前加载了,那么这样就可以了。

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

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

3 个答案:

答案 0 :(得分:9)

这是由于在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"]的值。

答案 1 :(得分:3)

这不是Chef-Client解析顺序中的错误。如果我们将其反转,则从包装器食谱中您将无法读取基类中设置的默认值,因为尚未解析这些值。

它还允许在默认优先级中设置的属性优先于要包装的食谱。如果我们颠倒了拓扑排序,这将迫使包装食谱使用替代级别。如果在包装食谱的顶部有包装食谱,那么现在您已经用完了标准属性优先级。最终,您的优先级用尽了,弄得一团糟。

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

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

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

我已经针对厨师客户提出了一个问题,以在此处正式添加对惰性属性的支持(该博客中引用的源于仓库的仓库已被放弃,不应使用):

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

答案 2 :(得分:1)

我遇到了同样的问题。我也有意义设置基本变量并从中设置其他变量,如:

default["apache"]["apache_docroot"] = '/var/www'

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

获取:/var/www/webapp1

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

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

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

我找到了解决这个问题的方法。它不是很好,但它的工作原理。 你最终做了:

  • 加载依赖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

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

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

https://github.com/stant/bundle-apache-java-tomcat-example(如何使用主要的) https://github.com/stant/bundle-apache-java-tomcat(主要的)