4

所以我使用以下配方:

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,但在重新启动时它又被执行了。我该如何防止这种情况?我不擅长阅读 ruby​​ 代码。

4

5 回答 5

8

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

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

于 2013-02-27T19:54:47.413 回答
2

对于厨师来说,食谱是幂等的很重要。这意味着他们应该能够在不改变结果的情况下一遍又一遍地奔跑。Chef 希望能够定期在节点上运行所有食谱,这应该没问题。

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

查看 Chef wiki,我发现:

弃用行为 在 Chef 0.8.x 及更早版本中,远程文件还用于从说明书中的 files/ 目录中获取文件。此行为现​​在由 #Cookbook File 提供,并且在 Chef 0.9.0 及更高版本中已弃用(尽管仍然有效)为此目的使用远程文件。

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

于 2013-02-26T02:11:00.170 回答
1

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

你总是可以写一个not_iforonly_if来控制remote_file资源的执行,但通常让它每次都运行是无害的。

您的其余代码看起来已经是幂等的,因此重复运行客户端并没有什么坏处。

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

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

请参阅文档

于 2013-02-26T02:33:22.563 回答
1

您只能在使用-o修饰符覆盖运行列表时运行配方。

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

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

--覆盖运行列表

于 2015-08-27T14:01:08.157 回答
0

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

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

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

于 2014-06-19T11:40:41.000 回答