红宝石 – 如何用厨师懒惰地评估任意变量

前端之家收集整理的这篇文章主要介绍了红宝石 – 如何用厨师懒惰地评估任意变量前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在写一个厨师食谱来安装我们的应用程序代码并执行它.该配方需要特别关于此代码最终的目录(运行模板,设置日志转发等).因此,目录本身在不同配方的很多地方弹出.

我试图获取/定义一个变量,所以我可以重新使用它在我的资源块与字符串插值.这很简单:

home = node['etc']['passwd'][node['nodejs']['user']]['dir']

以示例的用法来运行npm安装,同时告诉它在主目录中下载repo,如下所示:

execute "npm install" do
  command "npm install #{prefix}#{app} --prefix #{home}"
end

除了定义home变量的第一个块将在编译时运行.在一个新的服务器上,我的nodejs用户帐户可能不存在,这是一个问题,给出了一个

NoMethodError undefined method '[]' for nil:NilClass

我有几个解决方法,但我想要一个具体的解决方案,使家庭变量只在食谱执行时,而不是编译时提取.

解决方法1

动态评估一个红宝石块内的home变量,就像这样:

ruby_block "fetch home dir" do
  block do
    home = node['etc']['passwd'][node['nodejs']['user']]['dir']
  end
end

这似乎实际上不起作用,当您尝试执行以下操作时,为Chef :: Resource :: Directory提供一个NoMethodError undefined方法

directory ".npm" do
  path "#{home}/.npm"
end

我觉得我一定在这里做错事.

解决方法2

对需要它的每个资源进行懒惰评估.所以这样做:

directory ".npm" do
  path lazy "#{node['etc']['passwd'][node['nodejs']['user']]['dir']}/.npm"
end

但是,只需要保持一行代码一次,将其存储在一个变量中并完成它就真的很好.

解决方法3

在编译时创建用户.这当然是使用notify trick linked here,像这样:

u = user node['nodejs']['user'] do
  comment "The #{node['nodejs']['user']} is the user we want all our nodejs apps will run under."
  username node['nodejs']['user']
  home "/home/#{node['nodejs']['user']}"
end

u.run_action(:create)

这完全解决了我的问题,但还有其他一些情况,我可以想象想要延迟对变量进行评估的能力,所以我让我的问题立场.

我想要什么

我真的很想能做到

home lazy = node['etc']['passwd'][node['nodejs']['user']]['dir']

但是这不是合法的语法,给出NameError在ubuntu 13.10版找不到一个资源(这是一个奇怪的语法错误,但是无论如何).有没有法律的方式来实现这一点?

解决方法

我没有测试过这个特定的代码,但是我在烹饪书中做了类似的操作,并使用lambda来延迟评估,如下所示:
home = lambda {node['etc']['passwd'][node['nodejs']['user']]['dir']}

execute "npm install" do
  command "npm install #{prefix}#{app} --prefix #{home.call}"
end

猜你在找的Ruby相关文章