Подтвердить что ты не робот

Есть ли способ отложить разрешение атрибута ресурса до этапа "выполнить"?

У меня есть два LWRP. Первый касается создания тома диска, его форматирования и установки на виртуальной машине, мы будем называть этот ресурс cloud_volume. Второй ресурс (не очень важно, что он делает) нуждается в UUID для вновь отформатированного тома, который является обязательным атрибутом, мы будем называть этот ресурс foobar.

Ресурсы cloud_volume и foobar используются в рецепте примерно следующим образом.

volumes.each do |mount_point, volume|
  cloud_volume "#{mount_point}" do
    size volume['size']
    label volume['label']
    action [:create, :initialize]
  end
  foobar "#{mount_point}" do
    disk_uuid node[:volumes][mount_point][:uuid]   # This is set by cloud_volume
    action [:do_stuff]
  end
end

Итак, когда я выполняю работу шеф-повара, я получаю исключение Required argument disk_identifier is missing!.

После некоторого рытья я обнаружил, что рецепты обрабатываются в две фазы, фазу компиляции и фазу выполнения. Похоже, что проблема во время компиляции, так как это момент времени, когда node[:volumes][mount_point][:uuid] не установлен.

К сожалению, я не могу использовать трюк, который OpsCode имеет здесь, поскольку уведомления используются в LWRP cloud_volume (чтобы он попадал в анти-шаблон, показанный в документации)

Итак, в конце концов, мой вопрос в том, есть ли способ обойти требование о том, чтобы значение disk_uuid было известно во время компиляции?

4b9b3361

Ответ 1

Более чистый способ - использовать Lazy Attribute Evaluation. Это будет оценивать node[:volumes][mount_point][:uuid] во время выполнения, а не компилировать

foobar "#{mount_point}" do
  disk_uuid lazy { node[:volumes][mount_point][:uuid] }
  action [:do_stuff]
end

Ответ 2

Отказ от ответственности: это путь со старым шеф-поваром (< 11.6.0), прежде чем добавить ленивую оценку атрибутов.

Оберните свой ресурс foobar в ruby_block и определите foobar динамически. Таким образом, после этапа компиляции у вас будет код ruby ​​в коллекции ресурсов, и он будет оцениваться на этапе выполнения.

ruby_block "mount #{mount_point} using foobar" do
  block do
    res = Chef::Resource::Foobar.new( mount_point, run_context )
    res.disk_uuid node[:volumes][mount_point][:uuid]
    res.run_action :do_stuff
  end
end

Этот способ node[:volumes][mount_point][:uuid] не будет известен во время компиляции, но во время компиляции он также не будет доступен. Доступ к нему будет доступен только на стадии запуска, когда он уже должен быть установлен.