Ruby Chef-使用动态变量创建模板?

Ruby Chef-使用动态变量创建模板?,ruby,chef-infra,knife,Ruby,Chef Infra,Knife,我对厨师的食谱有点挑战。我是厨师新手,所以请容忍我 步骤1:My chef recipe安装Ruby Passenger,然后将Passenger nginx模块与nginx一起编译 # Install passenger and nginx module bash "Install Passenger" do code <<-EOF source /usr/local/rvm/scripts/rvm gem install passenger EOF user

我对厨师的食谱有点挑战。我是厨师新手,所以请容忍我

步骤1:My chef recipe安装Ruby Passenger,然后将Passenger nginx模块与nginx一起编译

# Install passenger and nginx module
bash "Install Passenger" do
  code <<-EOF
  source /usr/local/rvm/scripts/rvm
  gem install passenger
  EOF
  user "root"
  not_if { `gem list`.lines.grep(/^passenger \(.*\)/).count > 0 }
end

# Install passenger
# Note that we have to explicitly include the RVM script otherwise it won't setup the environment correctly
bash "Install passenger nginx module and nginx from source" do
  code <<-EOF
  source /usr/local/rvm/scripts/rvm
  passenger-install-nginx-module --auto --prefix=/opt/nginx --auto-download
  EOF
  user "root"
  not_if { File.directory? "/opt/nginx" }
end
问题:Chef似乎在运行开始时编译模板。所以最终的结果是,步骤2实际上是在步骤1运行之前编译的。这意味着passenger_根变量为空。它需要完成步骤1,然后才能获得passenger_root,然后运行模板

我尝试将步骤2的代码包装在
ruby_块中,但没有成功:
undefined method
template'for Chef::Resource::RubyBlock`

不知道在这里该做什么,或者对于厨师来说,这样做的最佳做法是什么

提前感谢,


莱纳德是的,厨师是个怪兽。我认为问题的一部分是有一百万种方法可以做同样的事情,但实际上没有详细说明最佳方法的文档。您可能希望使用的是,使块1首先运行,然后通知块2运行。这意味着块2需要
操作:无
,以便在收到通知之前不会触发

我将notify添加到块1中的示例中,并将action:none添加到块2

bash "Install Passenger" do
  code <<-EOF
  source /usr/local/rvm/scripts/rvm
  gem install passenger
  EOF
  user "root"
  not_if { `gem list`.lines.grep(/^passenger \(.*\)/).count > 0 }
  notifies :run, 'bash[Install passenger nginx module and nginx from source]', :immediately
end

bash "Install passenger nginx module and nginx from source" do
  code <<-EOF
  source /usr/local/rvm/scripts/rvm
  passenger-install-nginx-module --auto --prefix=/opt/nginx --auto-download
  EOF
  user "root"
  action :none
end
bash“安装乘客”do

代码一旦将代码包装到
ruby_块
中,就不能再使用普通的配方资源声明了。您必须编写纯ruby代码:

ruby_block "create /opt/nginx/conf/nginx.conf from template" do
  block do
    res = Chef::Resource::Template.new "/opt/nginx/conf/nginx.conf", run_context
    res.source "nginx.conf.erb"
    res.variables(
      deploy_user: deploy_user,
      passenger_root: `bash -c "source /usr/local/rvm/scripts/rvm; passenger-config --root"`.chomp,
      passenger_ruby: `bash -c "source /usr/local/rvm/scripts/rvm; which ruby"`.chomp,
      passenger: node[:passenger]
    )
    res.run_action :create
  end
end

另外,我想你应该用
strip
而不是
chomp
来去除空白。

一种更干净的推荐方法是使用

另外,我建议使用
strip
而不是
chomp
[谢谢Draco]

ruby_block "create /opt/nginx/conf/nginx.conf from template" do
  block do
    res = Chef::Resource::Template.new "/opt/nginx/conf/nginx.conf", run_context
    res.source "nginx.conf.erb"
    res.variables(
      deploy_user: deploy_user,
      passenger_root: `bash -c "source /usr/local/rvm/scripts/rvm; passenger-config --root"`.chomp,
      passenger_ruby: `bash -c "source /usr/local/rvm/scripts/rvm; which ruby"`.chomp,
      passenger: node[:passenger]
    )
    res.run_action :create
  end
end
template "/opt/nginx/conf/nginx.conf" do
  source "nginx.conf.erb"
  action :create
  variables lazy {
    { 
      deploy_user: deploy_user,
      passenger_root: `bash -c "source /usr/local/rvm/scripts/rvm; passenger-config --root"`.strip,
      passenger_ruby: `bash -c "source /usr/local/rvm/scripts/rvm; which ruby"`.strip,
      passenger: node[:passenger]
    }
  }
end