我必须根据一些条件修改自动生成的 nginx 配置:现在在配方中我包含模板:
template "#{node['nginx']['dir']}/sites-available/#{node['fqdn']}" do
source 'nginx-site.erb'
owner 'root'
group node['root_group']
mode '0600'
notifies :reload, 'service[nginx]'
end
然后在模板中我使用正则表达式更改文件内容:
<% node['nginx']['sites'].each do |site|
if File::exist?(site['include_path'])
%>
<% if not node['nginx']['edperl'] %>
<%= File::read(site['include_path']) %>
<% else %>
<%= File::read(site['include_path']).gsub(/(access_log.*?;)/, '\1' + "\n set $pseclvl $seclvl;") %>
<% end -%>
<% end
end
%>
`
现在我需要添加另外 2 个 if 语句。如果我这样做,结果文件将包含 3 个相同的站点定义,每个定义都在不同的 if 语句中进行修改。
处理现有文件的最佳方法是什么?我尝试在文件模板中使用 ruby 代码,但没有成功,并找到了“line”食谱。如果我使用 line cookbook - 如何在 nginx cookbook 配方中使用它?
感谢您的回答。
所以,我需要对自动生成的文件执行此逻辑:
if node['nginx']['attribute1']
add to a file line1 after access_log statement
end
if node['nginx']['attribute2']
add to a file line2 after access_log statement
end
if node['nginx']['attribute3']
add to a file line3 after access_log statement
end
答案1
Chef 对于如何做到这一点有自己的看法。您应该在 Chef 中管理整个文件,并将逻辑放在模板中或传递到模板的数据中。无论如何,“Chef 方式”是管理整个文件和您正在调用的文件File::read
。
在你的情况下,逻辑有点复杂,所以我建议提前计算你想要的东西,例如
included_str = ''
node['nginx']['sites'].each do |site|
next unless ::File::exist?(site['include_path'])
if not node['nginx']['edperl']
included_str << File::read(site['include_path'])
else
included_str << File::read(site['include_path']).gsub(/(access_log.*?;)/, '\1' + "\n set $pseclvl $seclvl;") %>
end
included_str << "\n"
end
然后,当您渲染模板时,将其传入:
template "#{node['nginx']['dir']}/sites-available/#{node['fqdn']}" do
source 'nginx-site.erb'
owner 'root'
group node['root_group']
mode '0600'
notifies :reload, 'service[nginx]'
variables(included_sites: included_str)
end
然后在您的模板中,只需输出该字符串:
<%= included_sites %>
如果您没有在 Chef 中管理整个事情,您也可能会遇到操作顺序问题,例如,您将调用File::read
Chef 复制的文件,但由于 Chef 的编译然后收敛模型,您将尝试在收敛复制之前读取文件。