木偶:如何在文件中设置行顺序?

我公司的Linux服务器由Puppetpipe理。

有一个DNS模块,它根据物理位置configuration所有服务器上的/etc/resolv.confconfiguration为facter值。

如你所知,一个/etc/resolv.conf文件看起来像这样:

 search domain.local nameserver 1.1.1.1 nameserver 2.2.2.2 

公司中所有服务器的主机名以两位数字结尾,例如:

 proxy73 

为了分离两个DNS服务器之间的DNSnetworkingstream量,我已经写了一个新的puppet模块来剪切主机名的最后两位数字,如果是奇数,那么/etc/resolv.conf文件应该如上所示,但是如果数字创build了一个不均匀的数字,那么/etc/resolv.conf文件应该如下所示:

 search domain.local nameserver 2.2.2.2 nameserver 1.1.1.1 

但我的问题是,不pipe我怎么写清单,行总是作为第一个服务器,然后第二个而不是第二个服务器,然后第一个服务器。

我写的清单的相关部分看起来是这样的(请参阅if $::oddip == false的部分,因为这是不起作用的部分):

 class dns_new::config { case $::dcd { 'ny4': { if $::oddip == 'true' { file_line { "ny4 search domain": ensure => present, line => "${::dns_new::params::searchdomny4}", path => "/etc/resolv.conf", } file_line { "ny4dns1 first": ensure => present, line => "${::dns_new::params::ny4dns1}", path => "/etc/resolv.conf", } file_line { "ny4dns2 second": ensure => present, line => "${::dns_new::params::ny4dns2}", path => "/etc/resolv.conf", } } elsif $::oddip == 'false' { file_line { "ny4 search domain": ensure => present, line => "${::dns_new::params::searchdomny4}", path => "/etc/resolv.conf", } file_line { "ny4dns2 first": ensure => present, line => "${::dns_new::params::ny4dns2}", path => "/etc/resolv.conf", require => File_line["ny4 search domain"], before => File_line["ny4dns1 second"], } file_line { "ny4dns1 second": ensure => present, line => "${::dns_new::params::ny4dns1}", path => "/etc/resolv.conf", require => File_line["ny4dns2 first"], } } } 

你可以看到我已经尝试使用before指令设置顺序。

这一切都是关于设置一个新的服务器,但我怎样才能设置已安装服务器的线路顺序?

编辑#2:

sysadmin1183,我已经添加了“你”显示,现在错误是这样的:

 [root@nyproxy33 ~]# puppet agent -t Info: Retrieving plugin Info: Loading facts Error: Could not retrieve catalog from remote server: Error 400 on SERVER: compile error /etc/puppet/environments/production/modules/dns_new/templates/resolv.conf.erb:27: syntax error, unexpected $end, expecting kEND ; _erbout ^ Warning: Not using cache on failed catalog Error: Could not retrieve catalog; skipping run 

第二十七行是:

 <% end %> 

试图编辑它:

 <% end -%> 

但获得相同的输出…

编辑#3: config.pp看起来像这样:

 class dns_new::config { file { "/etc/resolv.conf": path => '/etc/resolv.conf', ensure => present, owner => "root", group => "root", mode => "775", content => template("dns_new/resolv.conf.erb"), } case $::dcd { 'ny4': { $search_dom = $::dns_new::params::searchdomny4 if $::oddip == 'true' { $dns_list = [ "${::dns_new::params::ny4dns1}", "${::dns_new::params::ny4dns2}" ] } elsif $::oddip == 'false' { $dns_list = [ "${::dns_new::params::ny4dns2}", "${::dns_new::params::ny4dns1}" ] } } 

resolv.conf.erb文件如下所示:

 search <%= @search_dom %> <% dns_list.each do |serv| -%> nameserver <%= serv %> <% end -%> 

运行木偶:

 [root@nyproxy33 ~]# puppet agent -t Info: Retrieving plugin Info: Loading facts Error: Could not retrieve catalog from remote server: Error 400 on SERVER: Failed to parse template dns_new/resolv.conf.erb: Filepath: /usr/lib/ruby/site_ruby/1.8/puppet/parser/templatewrapper.rb Line: 81 Detail: Could not find value for 'dns_list' at /etc/puppet/environments/production/modules/dns_new/templates/resolv.conf.erb:2 at /etc/puppet/environments/production/modules/dns_new/manifests/config.pp:8 on node nyproxy33.ny4.peer39.com Warning: Not using cache on failed catalog Error: Could not retrieve catalog; skipping run 

在这种情况下,您可能会更好地使用模板。 就像是…

 # This is done to bring the variable into scope. $search_dom = $::dns_new::params::searchdomny4 if $::oddip == 'true' { $dns_order = [ '1.1.1.1', '2.2.2.2' ] } elsif $::oddip == 'false' { $dns_order = [ '2.2.2.2', '1.1.1.1' ] } file { '/etc/resolv.conf': [usual stuff] content => template('dns_new/resolv.conf.erb'), } 

用一个ERB模板看起来像这样:

new_dns/templates/resolv.conf.erb

 search <%= @search_dom %> <% @dns_order.each do |serv| %> nameserver <%= serv %> <% end -%> 

哪个应该按照你想要的顺序发出一个resolv.conf文件。

另一个select是只对模块中的DNS服务器列表进行编码,然后在ERB模板中使用ruby代码来确定是否走下数组(每个)或向上走(reverse.each)。 这看起来像:

 $search_dom = $::dns_new::params::searchdomny4 $dns_list = $::dns_new::params::dnslist $oddip = $::oddip file { '/etc/resolv.conf': [usual stuff] content => template('dns_new/resolv.conf.erb') } 

使用更复杂的ERB格式如下:

 search <%= @search_dom %> <% if @odd_ip == 'true' %> <% @dns_list.each do |srv| -%> nameserver <%= srv %> <% end -%> <% elsif @odd_ip == 'false' -%> <% @dns_list.reverse.each do |srv| -%> nameserver <%= srv %> <% end -%> <% end -%> 

如果您以前没有完成模板,标记的关键是粗略的:

 <% : Here is ruby code. <%= : Here is an evaluated value. Replace this block with the result, or enter a blank line. -%> : End a block. Don't render a blank line if it doesn't evaluate to anything. 

该模板将逐行进行评估。 第一行是一个简单的东西,将resolv conf的“服务器”部分删除。 第二行是事情变得更复杂的地方:我们正在调用ruby函数。 这就是允许我们放置尽可能多的nameserver行的数组。


我明白你在再培训局所要做的是什么,但我认为你过于复杂了。 您正在编码ERB本身的本地化逻辑(nj vs ams vs lax)。 可以这样做,但是在傀儡代码中你可能会有更好的运气。 如果这部分逻辑与傀儡代码在一起,那么对其他人来说就更可能是可读的。

dns_new/manifests/config.pp

 case $::dcd { 'ny4': { $search_domain = $::dns_new::params::searchdomny4 $dns_list = [ "${::dns_new::params::ny4dns1}", "${::dns_new::params::ny4dns2}" ] } 'nj': { $search_domain = $::dns_new::params::searchdomnj $dns_list = [ "${::dns_new::params::njdns1}", "${::dns_new::params::njdns2}" ] } 'ams2': { $search_domain = $::dns_new::params::searchdomams2 $dns_list = [ "${::dns_new::params::ams2dns1}", "${::dns_new::params::ams2dns2}" ] } } file { '/etc/resolv.conf': [the usual stuff] content = template('dns_new/resolv.conf.erb') } 

你现在在再培训局有两个可处理的变数。 search_domaindns_list 。 这使ERB缩短了很多:

dns_new/templates/resolv.conf.erb

 search <%= @search_domain %> <% dns_list.each do |serv| -%> nameserver <%= serv %> <% end -%> 

如果您想知道为什么我要在类中分配variables并在ERB中使用这些variables,而不是在params类中使用variables,那么这是因为超出范围的variables在ERB文件中起作用的非直观方式。 在调用模板的同一个类中分配一个ERB文件中使用的variables要容易得多,风格也不错。

“之前”的metaparameter实际上只是说了一些关于资源的执行顺序,而不是文件中的行的顺序。

如果我是你的话,我的目标是用一stream的木偶构造来pipe理resolv.conf:一个将它作为一个文件资源pipe理的单独模块(可能有几个伪造木偶),或者编写你自己的小模板,指定名称服务器参数。

另一种select是使用\n将两个名称服务器指定在一个file_line资源中,以便将它们分开:

 file_line { "ny4dns2 first": ensure => present, line => "${::dns_new::params::ny4dns1}\n${::dns_new::params::ny4dns2}", path => "/etc/resolv.conf", require => File_line["ny4 search domain"], after => "${::dns_new::params::searchdomny4}" } 

如果顺序错误,它们将不会重新sorting,但它至less会在search语句正下方以正确顺序添加(可能列出大于3的4个名称服务器(在resolv.h中为MAXNS),但只有file_line资源避免这可能是困难的或不可能的)。

另外, after参数特定于file_line资源,暗示插入行的位置, before是参考资源sorting的一般资源参数。