廚師的執行順序
我有一些基於搜尋設置節點屬性的程式碼。然後我想在模板中使用這些屬性。看來模板是在我計算出值的程式碼之前編譯的。所以需要執行 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']
?)我有幾種方法可以解決這個問題。
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.rboverride
,並確保屬性文件被正確載入命令。您可能還想嘗試在呈現模板時強制屬性進行惰性評估,如下所示:
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 %>
更多關於惰性屬性評估的資訊。