ruby - 如何使用 Chef 延迟评估任意变量

标签 ruby variables chef-infra chef-recipe

我正在编写一个 Chef Recipe 来安装我们的应用程序代码并执行它。配方需要特别注意此代码最终所在的目录(用于运行模板、设置日志转发等)。因此,该目录本身会出现在不同 Recipe 的很多地方。

我正在尝试获取/定义一个变量,以便我可以通过字符串插值在我的资源 block 中重新使用它。这非常简单:

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

示例用法是运行 npm install,同时告诉它在主目录中插入 repo 下载,如下所示:

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

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

NoMethodError undefined method '[]' for nil:NilClass

我有一些解决方法,但我想要一个特定的解决方案来使 home 变量仅在配方执行时获取,而不是在编译时获取。


解决方法 1

动态评估 ruby​​ block 内的 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 Cannot find a resource for home on ubuntu version 13.10(这是一个奇怪的语法错误,但无论如何)。是否有合法的方式来实现这一目标?

最佳答案

我没有测试过这个特定的代码,但我在 Recipe 中做了类似的事情,并使用 lambda 来延迟评估,如下所示:

home = lambda {node['etc']['passwd'][node['nodejs']['user']]['dir']}

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

关于ruby - 如何使用 Chef 延迟评估任意变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20620724/

相关文章:

vagrant - 厨房创建 new_box 命令不起作用

ruby-on-rails - "No resource or method named ` windows_package ' "使用 chef 安装简单的 windows 包时

jquery 对元素变量执行选择器

asp.net - Page.RouteData 返回 WebResource.axd?

mysql - 如何返回查询函数内的值?

ruby-on-rails - 在 Rails 中接收电子邮件的最佳实践

windows - 无法使用 winrm 引导

ruby-on-rails - 如何对三元运算符使用多重赋值?

ruby - 获取创建另一个实例的实例

ruby - 为什么在顶层定义一个方法会影响其他用户定义的类?