Chef 食谱执行无法逐步进行

Chef 食谱执行无法逐步进行

我的食谱配置如下:

package "scribe" do
  action :install
end

package "supervise-scripts" do
   action :install
end

remote_directory "/var/service/" do
   source "#{node['site-scribe']['cluster']}"
end

Dir.foreach('/var/service') do |dir|
next if dir == '..'|| dir == '.'
  execute "svc_add_#{dir}" do
    command "/usr/bin/svc-add #{dir}"
    not_if { ::Dir.exists?("/var/service/#{dir}/supervise") }
  end

  execute "svc_restart_#{dir}" do
    command "/usr/bin/svc-restart #{dir}"
  end
end

现在我遇到了奇怪的行为。在服务器上第一次运行 chef-client 时,它只执行remote_directory块,而不启动Dir.foreach循环。第二次运行时,它Dir.foreach正常运行(始终在remote_directory未下载时)。为什么Dir.foreach如果执行了块,我的循环就不会启动remote_directory

当我删除它时会出现同样的行为not_if

//holosian

答案1

在远程目录操作实际发生之前执行循环Dir.foreach。Chef 分为两个阶段执行。在第一阶段,运行所有配方代码,并将资源放置在数组中以供稍后评估。在第二阶段,然后运行这些资源以实际完成工作。正如 StephenKing 所暗示的那样,您的情况是:

  1. 您的remote_directory块运行,并在模板上放置一个资源来拉下该远程目录。
  2. 您的Dir.foreach循环已运行,但由于 #1 的资源仍在数组中(尚未执行),/var/service目录中没有子项。因此循环遍历 0 个元素并退出。
  3. 在第二次运行中chef-client,您将获得值,/var/service因此循环可以正常工作。

除非您需要在一次 Chef 运行中完成完全收敛,否则您实际上不会遇到问题。只需确保使用not_ifand语句来确保每个资源仅在需要时运行。但是,如果您需要在一次运行中完成所有操作,则必须破解解决方案。最简单的选择是通过执行以下操作来only_if强制立即评估您的资源:remote_directory

remote_directory "/var/service/" do
   source "#{node['site-scribe']['cluster']}"
end.run_action(:create)

这将强制操作在 Chef 执行的第一阶段实际执行,然后您的循环就会起作用。

相关内容