Chef:在模板

时间:2015-08-31 23:37:34

标签: templates attributes chef

我有厨师问题。我需要更新模板中的目录路径并将其复制到两个不同的位置。尽管模板文件相同,但每个实例的目录路径都不同。

我有以下属性文件(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目录。为什么我对属性的更新没有生效?厨师可以这样吗?如果是这样,任何指针都非常感激。感谢。

3 个答案:

答案 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,则可以在运行时覆盖属性,但在您的情况下我发现它无用。