У меня есть код, который устанавливает атрибуты узлов на основе поиска. Затем я хочу использовать эти атрибуты в шаблоне. Похоже, что шаблон компилируется раньше моего кода, который вычисляет значения. Итак, чтобы добраться до состояния, которое я хочу, требуется 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 / 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 / по умолчанию / 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::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'] = ...
чтобы установить результат на уровне явного атрибута.
Разверните атрибут узла до переменной 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 Server, что означает, что параметр что-нибудь в атрибутах или переопределениях в дальнейшем не будет иметь значения, поскольку атрибут узла обычно побеждает их, поскольку он наиболее явный.
Знайте, как они установлены и как их удалить - при неправильном использовании они могут вызвать путаницу. Следить за публикациями Приоритет атрибутов.
На свой атрибут.
Файлы атрибутов загружаются в порядке зависимостей и лексической сортировки, поэтому cook_b всегда будет вычисляться после cook_a, и вам, вероятно, лучше переместить node.set
в атрибуты cook_b / default.rb как override
attribute и убедитесь, что файлы атрибутов загружены в правильном порядке.
Вы также можете попробовать принудительно выполнять ленивую оценку атрибута при рендеринге шаблона, например:
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 / по умолчанию / cook_a.conf.erb
some_var = <%= @some_var %>
Подробнее о ленивой оценке атрибутов Вот.