7

我正在尝试从如何编写可重复使用的厨师食谱,江南风格中获取灵感来实现一个包装食谱。我希望在没有管理器应用程序的情况下在我的节点上安装 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"]不会被覆盖。以上仍然具有tomcat6in的值node["tomcat"]["user"]

我是否必须覆盖所有引用的属性["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

4

3 回答 3

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"]因此,如果您想更改它的值,则需要在包装食谱中设置值。

于 2014-01-08T16:44:35.593 回答
3

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

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

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

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

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

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

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

于 2020-08-25T03:41:03.177 回答
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

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

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

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

于 2015-02-13T21:31:33.573 回答