Назад | Перейти на главную страницу

Поварский порядок исполнения

У меня есть код, который устанавливает атрибуты узлов на основе поиска. Затем я хочу использовать эти атрибуты в шаблоне. Похоже, что шаблон компилируется раньше моего кода, который вычисляет значения. Итак, чтобы добраться до состояния, которое я хочу, требуется 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']?) Есть несколько способов, которыми я бы занялся.

  1. Шеф-повар должен предупреждать вас при попытке заменить значение 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'] = ... чтобы установить результат на уровне явного атрибута.

  2. Разверните атрибут узла до переменной 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 %>

Подробнее о ленивой оценке атрибутов Вот.