如何用Chef懒惰地求一个任意变量 [英] How to lazily evaluate an arbitrary variable with Chef

查看:40
本文介绍了如何用Chef懒惰地求一个任意变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm writing a Chef recipe to install our application code and execute it. The recipe needs to be particular about the directory this code ends up in (for running templates, setting log forwarding etc.). Thus the directory itself pops up in a lot of places in different recipes.

我正在尝试获取/定义变量,以便可以在资源块中重用它与字符串插值。这很简单:

I am trying to fetch/define a variable so I can re-use it in my resource block with string interpolation. This is pretty straightforward:

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

示例运行 npm install ,同时告诉它在主目录中分配回购下载,例如:

With an example usage being to run npm install while telling it to plunk the repo downloads in the home directory, like this:

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

除了定义 home 变量的第一个块将在编译时运行以外,其他所有内容都将在编译时运行。在可能还没有我的nodejs用户帐户的新服务器上,这是一个问题,为

Except that the first block which defines the home variable will run at compile time. On a fresh server, where my nodejs user account may not exist yet, this is a problem, giving a

NoMethodError undefined method '[]' for nil:NilClass

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

I have a few workarounds, but I would like a specific solution to make the home variable only be fetched at recipe execute time, not compile time.

动态评估红宝石块中的home变量,如下所示:

Dynamically evaluate the home variable inside a ruby block, like so:

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

这似乎并不实际,给出了 NoMethodError Chef :: Resource :: Directory的未定义方法主页,当您尝试执行以下操作时:

This does not seem to actually work, giving a NoMethodError undefined method home for Chef::Resource::Directory when you try to do something like this:

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

我觉得我在

懒惰地在需要它的每个资源上评估参数。因此,相反:

Lazily evaluate a parameter on every single resource that needs it. So instead do this:

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

但是,仅需维护该行代码一次,将其存储在变量中并完成该操作确实很棒。

But it would be really great to just have to maintain that line of code once, store it in a variable and be done with it.

在编译时创建用户。使用通知链接在这里的技巧,例如:

Create the user at compile time. This of course works, using the notify trick linked here, like this:

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)

这完全解决了我的问题,但是还有其他情况在我可以想象的地方想要延迟对变量的求值,因此让我的问题站起来。

This solves my problem exactly, but there are other cases where I can imagine wanting the ability to delay evaluation of a variable, so I let my question stand.

我真的很想做

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

但是这不是合法的语法,会导致 NameError在ubuntu版本13.10上找不到家庭资源(这是一个奇怪的语法错误,但无论如何)。有没有合法的方法可以做到这一点?

But that's not legal syntax, giving NameError Cannot find a resource for home on ubuntu version 13.10 (which is an odd syntax error, but whatever). Is there a legal way to accomplish this?

推荐答案

我没有测试过此特定代码,但我在食谱中做了类似的操作并使用lambda延迟评估,如下所示:

I haven't tested this particular code but I have done something similar in cookbooks and used a lambda to delay evaluation as follows:

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

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

这篇关于如何用Chef懒惰地求一个任意变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆