Chef

廚師的執行順序

  • October 21, 2014

我有一些基於搜尋設置節點屬性的程式碼。然後我想在模板中使用這些屬性。看來模板是在我計算出值的程式碼之前編譯的。所以需要執行 2 次 chef-client 才能達到我想要的狀態

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/attributes/default.rb

default['cook_a']['val_1'] = node['someval']

cook_a/recipes/default.rb

template "/etc/cook_a.conf" do
 source "cook_a.conf.erb"
end

cook_a/templates/default/cook_a.conf.erb

some_var = <% node['cook_a']['val_1'] %>

現在在另一本食譜中,我覆蓋了這個價值

coob_b/recipes/default.rb

node.set['someval'] = "foo"
include "cook_a"

但是現在更改為時已晚,因此模板在第一次執行期間node['cook_a']['val_1']寫入原始值。node['someval']在第二次執行期間,我得到了正確的值。

我不願意設置node['cook_a']['val_1'],因為該名稱可能會更改,並且我正在嘗試從 cook_a 的細節中抽像出來。

這有點難以理解,由於過度使用bla,並且缺少模板使用的內容。

假設模板中包含類似於以下內容的語句:

somevalue = <%= node['foo'] %>

而且您沒有node['foo']在模板中獲得覆蓋的值(這似乎是需要的bla['bla']?)我有幾種方法可以解決這個問題。

  1. node['foo']當試圖替換沒有屬性優先級的配方中的值時,Chef 實際上應該警告您。
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'] = ...在顯式屬性級別設置結果。 2. 將 node 屬性擴展為 Ruby 變數,並將其顯式傳遞給模板,以防止覆蓋和編譯時間與渲染時間衝突。

這看起來像這樣:

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 %>

還有其他編寫條件邏輯的方法,但總的來說,這意味著我們在配方中擴展節點屬性,並且只將我們想要的變數傳遞給模板,而不是更多的節點屬性。

最後,我與這個秘訣有關的一點是,搜尋的條件是node['foo']返回一個 nil 值,然後在賦值塊中使用相同的已知 nil 值作為比較。我認為這並沒有多大作用,好像進入塊一樣,它總是為零,因此比較沒有多大作用。

編輯:

問題後澄清,我相信你遇到了編譯時間與渲染時間屬性評估的“雞和蛋”問題,如前所述。

在第二次執行期間檢索到正確值的唯一原因是由於將node.set屬性保存在 Chef 伺服器上的節點對象本身中的操作,這意味著在屬性中設置任何內容或稍後在任何地方覆蓋都無關緊要,因為節點屬性通常會贏得這些,因為它是最明確的。

請注意如何設置以及如何刪除它們 - 如果濫用它們可能會導致混亂。閱讀Attribute Precedence

關於你的屬性。

屬性文件是按照依賴關係和詞法排序的順序載入的,所以cook_b總是在cook_a之後被評估,你最好把它node.set作為一個屬性移動到cook_b的attributes/default.rb override,並確保屬性文件被正確載入命令。

您可能還想嘗試在呈現模板時強制屬性進行惰性評估,如下所示:

cook_a/recipes/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/templates/default/cook_a.conf.erb

some_var = <%= @some_var %>

更多關於惰性屬性評估的資訊

引用自:https://serverfault.com/questions/633378