我有厨师问题。我需要更新模板中的目录路径并将其复制到两个不同的位置。尽管模板文件相同,但每个实例的目录路径都不同。
我有以下属性文件(default.rb):
node['conf_dir'] = '/opt/app/etc'
我有以下模板文件(myconfig.conf.erb):
ConfigDir = <%= node['conf_dir'] %>
我的食谱文件中有以下内容:
template '/opt/app/etc/myconfig.conf' do
source 'myconfig.conf.erb'
owner 'root'
group 'root'
mode '0644'
end
# update conf dir for new app
node['conf_dir'] = '/opt/newapp/etc'
template '/opt/newapp/etc/myconfig.conf' do
source 'myconfig.conf.erb'
owner 'root'
group 'root'
mode '0644'
end
我想在/opt/app/etc/myconfig.conf中看到ConfigDir的值为'/ opt / app / etc',我想在/ opt / newapp /中看到ConfigDir etc / myconfig.conf的值为'/ opt / newapp / etc'。当我尝试运行配方时,两个app的configDir都指向newapp目录。为什么我对属性的更新没有生效?厨师可以这样吗?如果是这样,任何指针都非常感激。感谢。
答案 0 :(得分:2)
这个答案分为两个部分,一个修复了原始问题,第二部分为这个用例提供了更好的方法。
1)
由于我高度劝阻其他答案中提到的方式,我会写一个利用lazy evaluation的人:
模板:
ConfigDir = <%= @conf_dir %>
配方:
template '/opt/app/etc/myconfig.conf' do
source 'myconfig.conf.erb'
owner 'root'
group 'root'
mode '0644'
variables( conf_dir: node['conf_dir'] )
end
# update conf dir for new app
ruby_block "update conf dir" do
block
node['conf_dir'] = '/opt/newapp/etc'
end
end
template '/opt/newapp/etc/myconfig.conf' do
source 'myconfig.conf.erb'
owner 'root'
group 'root'
mode '0644'
variables(lazy { conf_dir: node['conf_dir'] } )
end
这样,模板的变量实际上是由配方配置的,无论环境,角色或其他配方如何做,因为节点对象的更改是在模板渲染之前完成的,延迟评估不同于什么值的分辨率在需要之前(在收敛阶段)是node['config']
2)
旁注:你做事的方式很容易出错,并且会成为维护的噩梦,我建议你回顾一下你做事的方式:
属性文件:
node['apps']['app']['conf_dir'] = '/opt/app/etc'
node['apps']['app']['owner'] = 'root'
node['apps']['app']['group'] = 'root'
node['apps']['newapp']['conf_dir'] = '/opt/newapp/etc'
node['apps']['newapp']['owner'] = 'root'
node['apps']['newapp']['group'] = 'root'
替代定义哈希的属性的替代语法:
node['apps']['app'] = { conf_dir: '/opt/app/etc',
owner: 'root',
group: 'root'
}
模板:
ConfigDir = <%= @conf_dir %>
配方:
node['apps'].each do |app,properties|
template "/opt/#{app}/etc/myconfig.conf" do
source 'myconfig.conf.erb'
owner properties['owner']
group properties['group']
mode '0644'
variables( conf_dir: properties['conf_dir'] )
end
end
这样你就不会在运行时/编译时弄乱节点对象了,你可以轻松地添加另一个应用程序,而无需再次粘贴模板定义。
对于那些想知道双引号和单引号之间混合的人来说,变量#{var}
的插值仅在双引号内发生,并且用于在固定字符串上保留单引号以区分它们。
答案 1 :(得分:1)
不建议您尝试做什么。如果两个不同的文件需要两个不同的值,那么你真的应该使用两个不同的节点属性。
属性/ default.rb
default['app']['conf_dir'] = '/opt/app/etc'
default['new_app']['conf_dir'] = '/opt/new_app/etc'
模板
ConfigDir = <%= @conf_dir %>
配方
template '/opt/app/etc/myconfig.conf' do
source 'myconfig.conf.erb'
mode '0644'
variables({
:conf_dir => node['app']['conf_dir']
})
end
template '/opt/app/etc/myconfig.conf' do
source 'myconfig.conf.erb'
mode '0644'
variables({
:conf_dir => node['new_app']['conf_dir']
})
end
答案 2 :(得分:-1)
[不健全的解决方案] 在配方中以相同优先级定义的属性优先于在属性文件中定义的属性(Ohai的自动优先级永远不会更改)。您可以查看attributes precedence in details。在你的情况下,我会采用模板和变量方法,所以你的食谱看起来像是:
require 'pp'
node.override['conf_dir'] = '/tmp'
pp node.debug_value('conf_dir')
template '/opt/app/etc/myconfig.conf' do
source 'myconfig.conf.erb'
mode '0644'
variables({
:conf_dir => node.default['conf_dir']
})
end
template '/opt/app/etc/myconfig.conf' do
source 'myconfig.conf.erb'
mode '0644'
variables({
:conf_dir => node.override['conf_dir']
})
end
您的属性文件也需要明确指定优先级,因此它将是node.default['conf_dir'] = '/opt/app/etc'
,模板文件将使用变量ConfigDir = <%= @conf_dir %>
。在上面的代码片段中,我还留下了pp node.debug_value('conf_dir')
行,极对调试非常有用。
如果您使用的是include_recipe
,则可以在运行时覆盖属性,但在您的情况下我发现它无用。