Chef – 用动态变量创建模板?

我对厨师食谱有点挑战。 我是厨师的新手,所以请耐心等待。

第1步:我的厨师食谱安装Ruby Passenger,然后编译Passenger nginx模块和Nginx。

# Install passenger and nginx module bash "Install Passenger" do code < 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 

第2步:之后,我使用模板创建nginx配置文件。 此配置需要Passenger的位置,这取决于步骤1的完成。

 template "/opt/nginx/conf/nginx.conf" do source "nginx.conf.erb" action :create 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] ) end 

问题:Chef似乎在运行开始时编译模板。 所以最终发生的事情是在步骤1运行之前实际编译了第2步。 这意味着passenger_root变量为空。 它需要步骤1才能获得passenger_root,然后运行模板。

我尝试将第2步代码包装在ruby_block但这不起作用: undefined method模板’for Chef :: Resource :: RubyBlock`。

不知道该怎么做,或者对于像这样的东西,最佳做法是什么?

提前致谢,

伦纳德

更简洁和推荐的方法是使用延迟属性评估 。

 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 

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

只要将代码包装在ruby_block中,就不ruby_block使用普通的配方资源声明了。 你必须编写纯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 

PS。 我想你想用strip而不是chomp来删除空格。

是的,厨师是一头野兽。 我认为问题的一部分是有一百万种方法可以做同样的事情,但实际上没有详细介绍最佳方法的文档。 您可能想要的是使用通知 ,以便块1首先运行而不是通知块2运行。 这意味着块2需要action :none以便在得到通知之前不会触发。

我在块1中将通知添加到您的示例中,并将操作: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