Рецепт рецепта шеф-повара исполнения

Учитывая следующий рецепт:

ruby_block "block1" do
    block do
        puts "in block1"
    end
    action :create
end


remote_file "/tmp/foo" do
    puts "in remote_file"
    source "https://yahoo.com"
end

Я бы ожидал, что ruby_block будет запущен первым (потому что он на первом месте), а затем удаленный_файл.

Я хотел бы использовать ruby_block для определения URL-адреса для файла remote_file для загрузки, поэтому порядок важен.

Если бы не мои инструкции puts (), я бы предположил, что они запускаются в ожидаемом порядке, потому что в журнале указано:

==> default: [2014-06-12T17:49:19+00:00] INFO: ruby_block[block1] called
==> default: [2014-06-12T17:49:19+00:00] INFO: remote_file[/tmp/foo] created file /tmp/foo
==> default: [2014-06-12T17:49:20+00:00] INFO: remote_file[/tmp/foo] updated file contents /tmp/foo

Но выше, мои предложения puts () выходят следующим образом:

==> default: in remote_file
==> default: in block1

Если вы считаете, что ресурсы выполняются в ожидаемом порядке, рассмотрите этот рецепт:

ruby_block "block1" do
    block do
        node.default['test'] = {}
        node.default['test']['foo'] ='https://google.com'
        puts "in block1"
    end
    action :create
end


remote_file "/tmp/foo" do
    puts "in remote_file"
    source node.default['test']['foo']
end

Это не работает следующим образом:

==> default: [2014-06-12T17:55:38+00:00] ERROR: {} is not a valid `source` parameter for remote_file. `source` must be an absolute URI or an array of URIs.
==> default: [2014-06-12T17:55:38+00:00] FATAL: Chef::Exceptions::ChildConvergeError: Chef run process exited unsuccessfully (exit code 1)

Строка «в блоке 1» не выводится на выходе, поэтому ruby_block никогда не запускался.

Итак, вопрос в том, как я могу заставить ruby_block работать и запускаться первым?

11 голосов | спросил Dan Tenenbaum 12 J0000006Europe/Moscow 2014, 21:57:34

1 ответ


15

Хороший вопрос - оба ваших примера работают так, как я ожидал бы, но это не сразу понятно почему.

Как писал Стивен Кинг в своем ответе, первое, что нужно понять, - это то, что рецепты скомпилированы (для создания набора ресурсов), а затем ресурсы сходятся (чтобы повлиять на изменения в вашей системе). Эти две фазы часто чередуются - некоторые из ваших ресурсов могут быть сближены до того, как Шеф закончит компилировать все ваши рецепты. Эрик Холленс об этом подробно рассказывает в своем посте « Queue Resource Run Queue ".


Вот ваш первый пример:

ruby_block "block1" do
    block do
        puts "in block1"
    end
    action :create
end    

remote_file "/tmp/foo" do
    puts "in remote_file"
    source "https://yahoo.com"
end

Это шаги, которые шеф-пот будет выполнять при обработке этого примера.

  1. Сначала объявляется объявление ruby_block, что приводит к добавлению ресурса с именем ruby_block[block1] в коллекцию ресурсов. Содержимое блока (первый оператор puts) еще не запущен - он сохраняется для запуска при конверсии этого ресурса.
  2. Затем выполняется компиляция объявления remote_file. Это приводит к добавлению ресурса с именем remote_file[/tmp/foo/] в источник ресурсов с источником " https://yahoo.com ". В процессе компиляции этого объявления будет выполнен второй оператор puts - это имеет побочный эффект печати "в файле remote_file", но он не влияет на ресурс, который помещается в коллекцию ресурсов.
  3. Не имея ничего общего с компиляцией, Chef начинает собирать ресурсы в коллекции ресурсов. Первый - ruby_block[block1], а Chef запускает код ruby ​​в блочной печати в блоке 1. После того, как он завершает работу блока, он регистрирует сообщение, чтобы сказать, что ресурс был вызван.
  4. Наконец, Шеф сходится remote_file[/tmp/foo]. Опять же, он регистрирует сообщение (или два), связанное с этим действием.

Это должно произвести следующую последовательность вывода:

  1. Ничего не печатается при компиляции ruby_block.
  2. "в файле remote_file" будет напечатан, когда файл remote_file будет скомпилирован.
  3. "в блоке 1" будет напечатан, пока ruby_block будет сходиться.
  4. Сообщение журнала шеф-повара будет напечатано после слияния ruby_block.
  5. Другие сообщения журналов Chef будут напечатаны во время /после смены файла remote_file.

На второй пример:

ruby_block "block1" do
    block do
        node.default['test'] = {}
        node.default['test']['foo'] ='https://google.com'
        puts "in block1"
    end
    action :create
end

remote_file "/tmp/foo" do
    puts "in remote_file"
    source node.default['test']['foo']
end

Как и в первом примере, мы не ожидаем, что что-либо будет напечатано, когда ruby_block будет скомпилирован - весь «блок» будет сохранен, и его содержимое не будет работать до тех пор, пока этот ресурс не будет скомпонован.

Первый вывод, который мы видим, «в файле remote_file», поскольку оператор puts выполняется, когда Chef компилирует ресурс remote_file. На следующей строке мы устанавливаем параметр source на значение node.default['test']['foo'], который, по-видимому, {}. Это недопустимое значение для source, поэтому выполнение Chef завершается в этой точке - перед кодом в ruby_block.

Следовательно, ожидаемый результат этого рецепта:

  1. Нет результата при компиляции ruby_block
  2. "в файле remote_file" при компиляции файла remote_file
  3. Ошибка из-за неверного параметра source

Надеюсь, это поможет вам понять поведение, которое вы видите, но нам все еще предстоит решить проблему.

Хотя вы спросили: «Как я могу заставить ruby_block работать первым?», ваш комментарий к StephenKing предполагает, что это не совсем то, что вы хотите - если бы вы действительно хотели, чтобы этот блок запускался первым, вы можете поместить его прямо в свой код рецепта. Кроме того, вы можете использовать . Метод run_action () для принудительно сгенерируйте ресурс, как только он будет скомпилирован, но вы говорите, что есть еще больше ресурсов, которые должны сходиться, прежде чем ruby_block может быть полезен.

Как мы видели выше, ресурсы не «запускаются», они сначала «скомпилированы», а затем «конвергированы». Имея это в виду, вам понадобится ресурс remote_file, чтобы использовать некоторые данные, которые неизвестны при компиляции, но будут быть известным, когда он сходится. Другими словами, что-то вроде параметра «block» в ruby_block - фрагмент кода, который не запускается дольше. Что-то вроде этого:

remote_file "/tmp/foo" do
    puts "in remote_file"
    # this syntax isn't valid...
    source do 
        node.default['test']['foo']
    end
end

К счастью, такая вещь существует - она ​​называется Оценка ленивого атрибута . Используя эту функцию, ваш второй пример будет выглядеть следующим образом:

ruby_block "block1" do
    block do
        node.default['test'] = {}
        node.default['test']['foo'] = 'https://google.com'
        puts "in block1"
    end
    action :create
end

remote_file "/tmp/foo" do
    puts "in remote_file"
    source lazy { node['test']['foo'] }
end

И ожидаемый результат этого рецепта?

  1. Нет результата при компиляции ruby_block
  2. "в файле remote_file" при компиляции файла remote_file
  3. "в блоке 1", напечатанном при сближении ruby_block
  4. Сообщение журнала шеф-повара, показывающее ruby_block, было конвертировано
  5. Сообщения журнала шеф-повара, показывающие удаленный_файл, были конвергированы
ответил zts 13 J0000006Europe/Moscow 2014, 19:50:46

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132