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

Leo*_*Teo 8 ruby chef-infra knife

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

第1步:我的厨师食谱安装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
Run Code Online (Sandbox Code Playgroud)

第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
Run Code Online (Sandbox Code Playgroud)

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

我尝试将第2步代码包装在一个ruby_block但不起作用:undefined methodtemplate'for Chef :: Resource :: RubyBlock`.

不知道该怎么做,或者这样的厨师最好的做法是什么?

提前致谢,

伦纳德

Gre*_*reg 11

更简洁和推荐的方法是使用惰性属性评估.

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
Run Code Online (Sandbox Code Playgroud)

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


mgu*_*mon 1

是的,厨师是个野兽。我认为问题的一部分是有一百万种方法可以做同样的事情,但实际上没有文档详细说明最佳方法。您可能想要的是使用“通知”,以便块 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
Run Code Online (Sandbox Code Playgroud)