使厨师食谱配方只运行一次

时间:2013-02-26 02:08:02

标签: ruby chef vagrant chef-recipe

所以我使用以下食谱:

include_recipe "build-essential"

node_packages = value_for_platform(
  [ "debian", "ubuntu" ]                      => { "default" => [ "libssl-dev" ] },
  [ "amazon", "centos", "fedora", "centos" ]  => { "default" => [ "openssl-devel" ] },
  "default"   => [ "libssl-dev" ]
)

node_packages.each do |node_package|
  package node_package do
    action :install
  end
end

bash "install-node" do
  cwd Chef::Config[:file_cache_path]
  code <<-EOH
    tar -xzf node-v#{node["nodejs"]["version"]}.tar.gz
    (cd node-v#{node["nodejs"]["version"]} && ./configure --prefix=#{node["nodejs"]["dir"]} && make && make install)
  EOH
  action :nothing
  not_if "#{node["nodejs"]["dir"]}/bin/node --version 2>&1 | grep #{node["nodejs"]["version"]}"
end

remote_file "#{Chef::Config[:file_cache_path]}/node-v#{node["nodejs"]["version"]}.tar.gz" do
  source node["nodejs"]["url"]
  checksum node["nodejs"]["checksum"]
  notifies :run, resources(:bash => "install-node"), :immediately
end

它成功地在我的Vagrant VM上安装了nodejs但是在重新启动时它再次被执行。我该如何防止这种情况?我在阅读红宝石代码时并不是那么好。

5 个答案:

答案 0 :(得分:8)

要使remote_file资源具有幂等性(即不再下载已经存在的文件),您必须正确指定文件的校验和。您可以使用node["nodejs"]["checksum"]属性在代码中执行此操作。但是,这仅适用,如果校验和被正确指定为下载文件的SHA256哈希,则不支持其他算法(尤其不是MD5)。

如果校验和不正确,您的食谱仍然有效。但是,在下一次运行时,Chef会注意到现有文件的校验和与您指定的文件不同,并会再次下载文件,从而通知install node资源并完成整个编译工作。

答案 1 :(得分:2)

对于厨师来说,食谱必须是幂等的。这意味着他们应该能够在不改变结果的情况下反复运行。 Chef希望能够定期运行节点上的所有配方,这应该没问题。

您是否有办法知道该配方中的哪个资源导致您出现问题? remote_file是唯一一个我怀疑是非幂等的,但我不确定。

看着厨师维基,我发现了这个:

  

不推荐使用的行为在Chef 0.8.x及更早版本中,远程文件也是   用于从cookbook中的files /目录中获取文件。这个   行为现在由#Cookbook文件提供,并使用远程文件   在Chef 0.9.0和。中,这个目的已被弃用(尽管仍然有效)   后面。

无论如何,厨师倾向于工作的方式,它会查看是否存在"#{Chef::Config[:file_cache_path]}/node-v#{node["nodejs"]["version"]}.tar.gz"解析为什么,如果存在,它应该跳过该资源。 install-node完成安装后是否可能删除该文件?如果是这样,厨师每次都会重新获取它。

答案 2 :(得分:1)

根据我的经验remote_file总是在执行chef-client时运行,即使目标文件已经存在。我不确定为什么(没有挖掘Chef代码来找到错误的确切原因)。

您始终可以编写not_ifonly_if来控制remote_file资源的执行,但通常每次都让它运行是无害的。

其余代码看起来已经是幂等的,因此重复运行客户端没有任何害处。

您可以为remote_file指定一项操作,使其有条件地运行:

remote_file 'target' do
  source 'wherever'
  action :create_if_missing
end

请参阅the docs

答案 3 :(得分:1)

只能使用 -o 修饰符覆盖运行列表一次运行配方。

sudo chef-client -o "recipe[cookbook::recipe]"
  

-o RunlistItem,RunlistItem ...,用指定的项目替换当前运行列表

     

- 覆盖-运行列表

答案 4 :(得分:0)

如果你想测试你的食谱是否是幂等的,你可能会对ToASTER感兴趣,这是一个系统测试Chef脚本的框架。

http://cloud-toaster.github.io/

在隔离容器环境(Docker VM)中使用不同配置执行Chef配方,ToASTER报告各种指标,如系统状态更改,收敛属性和幂等性问题。