我有一些基于search设置节点属性的代码。 然后我想在模板中使用这些属性。 看来模板正在编译之前,我的代码,计算出值。 所以需要2次厨师 – 客户端才能到达我想要的状态
if !node['foo'] search(:node, "recipes:bla").each do |bla| if bla['bla'] > node['foo'] node['foo'] = bla['bla'] end end end template "/tm/foo" do source "foo" end
我试着把这个代码放在模板前后的配方中,并放在属性文件中。 我不认为search有一个行动,否则我可以尝试使用.run_action()。
有什么办法可以设置node['foo']的值,以便在模板中使用它吗?
cook_a /属性/ default.rb
default['cook_a']['val_1'] = node['someval']
cook_a /食谱/ default.rb
template "/etc/cook_a.conf" do source "cook_a.conf.erb" end
cook_a /模板/默认/ cook_a.conf.erb
some_var = <% node['cook_a']['val_1'] %>
现在在另一本食谱,我凌驾了那个价值
coob_b /食谱/ default.rb
node.set['someval'] = "foo" include "cook_a"
但是现在改变node['cook_a']['val_1'] ,所以模板在第一次运行期间写入了node['someval']的原始值。 在第二次运行,我得到正确的价值。
我不愿意设置node['cook_a']['val_1']因为这个名字可能会改变,我试图抽离cook_a的细节。
这有点难以理解,因为过度使用bla ,以及缺less模板使用的内容。
假设模板中有一个语句类似于:
somevalue = <%= node['foo'] %>
而且你没有得到模板中的node['foo']的overriden值(这似乎是bla['bla']所需要的)。我有几个方法可以设置这个。
尝试在没有属性优先级的配方中replacenode['foo']的值时,厨师实际上应当警告您。
Chef::Exceptions::ImmutableAttributeModification: Node attributes are read-only when you do not specify which precedence level to set. To set an attribute use code like `node.default["key"] = "value"'
所以在你的食谱中,你可以改变这个方法来使用node.default['foo'] = ...来设置结果在一个明确的属性级别。
将节点属性展开为一个Rubyvariables,并将其显式传递给模板,以防止覆盖和编译时间与渲染时间冲突。
这看起来像这样:
if !node['foo'] search(:node, "recipes:bla").each do |bla| if bla['bla'] > node['foo'] node_foo = bla['bla'] end end end template "/tmp/foo" do source "foo" variables( node_foo: node_foo || node['foo'] ) end
模板将会变成如下所示:
somevalue = <%= @node_foo %>
还有其他方法来编写条件逻辑,但总的来说,这意味着我们扩展配方中的节点属性,并且只将所需的variables传递给模板,而不是传递更多的节点属性。
最后,这个配方中涉及到的一点是,search是以node['foo']返回一个零值为条件的,然后在赋值块中使用相同的已知nil值作为比较。 我不认为这样做很好,就好像进入这个区块一样,它总是零,所以比较没有太大的作用。
编辑:
如前所述,问题后的澄清,我相信你正在遇到编译时间与rendertime属性评估的“鸡与蛋”问题。
在第二次运行期间检索正确的值的唯一原因是由于node.set操作在Chef Server上保存节点对象本身的属性,这意味着设置任何属性或覆盖以后的任何地方都无关紧要,因为节点属性通常会赢得这些,因为它是最明确的。
注意这些是如何设置的以及如何去除它们 – 如果被滥用,可能会造成混淆。 阅读属性优先 。
关于你的属性。
属性文件按依赖性和词法sorting的顺序加载,所以cook_b将总是在cook_a之后被评估,并且您可能更好地将node.set移到cook_b的attributes / default.rb作为override属性,并确保属性文件按正确顺序加载。
您可能还想尝试强制该属性在渲染模板时进行延迟评估,如下所示:
cook_a /食谱/ default.rb
template "/etc/cook_a.conf" do source "cook_a.conf.erb" variables lazy { { some_var: node['cook_a']['val_1'] } } end
cook_a /模板/默认/ cook_a.conf.erb
some_var = <%= @some_var %>
更多关于懒惰属性评估在这里 。