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