Ask Your Question
0

order of concat fragment in each loop

asked 2016-03-07 07:23:07 -0600

prototyp gravatar image

Atm I am writing a small module adding new interfaces to /etc/network/interfaces. Therefor a hash is placed in the hiera file which is parsed and concatenated to the file.

Each fragment gets a number which is incremented. How can i order the fragments numeric wise?

network_custom::interfaces:
  em4:
    ipaddress: '175.21.0.15'
    network: '175.21.0.0'
    broadcast: '175.21.0.255'
    dns-search: 'xxx.xxx.de'
  em5:
    ipaddress: '175.21.0.131'
    network: '175.21.0.0'
    broadcast: '175.21.0.255'
    dns-search: 'xxx-xxx.yyy.de'

  class network_custom::debian{                                                                                                                                          
      concat { '/etc/network/interfaces':                                                                              
        ensure => present,                                                                 
     }                                                                                                                                                                            
      $interfaceconfigs = hiera_hash(network_custom::interfaces)                                              
      $interfaceslist = keys($interfaceconfigs)                                                                            

      $count = inline_template( '<%= $c = $c || 0; $c = 0 %>' )                                                            
      each($interfaceslist) |$interfacename|{                                                                              
        $count = inline_template( '<%= $c = $c || 0; $c = $c + 1 %>' )                                                     
        concat::fragment { $interfacename:                                                                                 
          target  => '/etc/network/interfaces',                                                                        
          content => "auto ${interfacename}\niface ${interfacename} inet static\n",                                        
          order   => $count                                                                                               
        }                                                                                                                  

        $interfaceconf = $interfaceconfigs[$interfacename]                                                                 
        each($interfaceconf) |String $key, String $value|{                                                                 
          $count = inline_template( '<%= $c = $c || 0; $c = $c + 1 %>' )                                                   
           concat::fragment { "${interfacename}${key}":                       
             target  => '/tmp/etc/network/interfaces',                                                                      
             content => "    ${key} ${value}\n",                                                                            
             order   => $count                                                                                             
          }                                                                                                                
        }                                                                                                                 
      }
edit retag flag offensive close merge delete

2 Answers

Sort by ยป oldest newest most voted
1

answered 2016-03-07 23:16:44 -0600

updated 2016-03-08 03:42:17 -0600

Your code will be a lot simpler and clearer if you move all of the logic inside the template:

$content = inline_template('<% @interfaceconfigs.keys.sort.each do |interfacename| -%>
auto <%= interfacename %>
iface <%= interfacename %> inet static
<% end %>')

file { '/etc/network/interfaces':
  ensure  => file,
  content => $content,
}

Or if you need to support em0..em10, em11 etc:

$content = inline_template('<% @interfaceconfigs.keys.sort_by { |x| x[/\d+/].to_i }.each do |interfacename| -%>
auto <%= interfacename %>
iface <%= interfacename %> inet static
<% end %>')

file { '/etc/network/interfaces':
  ensure => file,
  content => $content,
}

Testing:

$interfaceconfigs = {
  'em11' => {
    ipaddress => '175.21.0.131',
    network => '175.21.0.0',
    broadcast => '175.21.0.255',
    dns-search => 'xxx-xxx.yyy.de',
  },
  'em1' => {
    ipaddress => '175.21.0.131',
    network => '175.21.0.0',
    broadcast => '175.21.0.255',
    dns-search => 'xxx-xxx.yyy.de',
  },
  'em5' => {
    ipaddress => '175.21.0.131',
    network => '175.21.0.0',
    broadcast => '175.21.0.255',
    dns-search => 'xxx-xxx.yyy.de',
  },
  'em4' => {
    ipaddress => '175.21.0.15',
    network => '175.21.0.0',
    broadcast => '175.21.0.255',
    dns-search => 'xxx.xxx.de',
  },
}

Apply:

[root@centos-66-x64 ~]# puppet apply /tmp/test.pp 
Warning: Facter: timeout option is not supported for custom facts and will be ignored.
Notice: Compiled catalog for centos-66-x64.local in environment production in 0.06 seconds
Notice: /Stage[main]/Main/File[/etc/network/interfaces]/content: content changed '{md5}13352d30ffccc7be50f60ac16af97be6' to '{md5}8a60ec927e86ad76617e220b39d8b440'
Notice: Applied catalog in 0.04 seconds

output:

auto em1
iface em1 inet static
auto em4
iface em4 inet static
auto em5
iface em5 inet static
auto em11
iface em11 inet static
edit flag offensive delete link more

Comments

The sort function won't help because the order of the keys is like in the hiera. The problem is that all the fragments are sorted by default by the pattern 'alpha' but i need 'numeric'. I don't know ruby so much but if <% end %> returns the rest of the key values they are still separated with ':'

prototyp gravatar imageprototyp ( 2016-03-08 02:30:53 -0600 )edit

No, the sort function does work, i.e. sorts an arbitrary list em4, em1, em11 etc as em1, em4, em11 and I tested both versions of the code above.

Alex Harvey gravatar imageAlex Harvey ( 2016-03-08 03:09:02 -0600 )edit

Ok, fixed.

Alex Harvey gravatar imageAlex Harvey ( 2016-03-08 03:23:18 -0600 )edit

Ah, I missed your point. Updated, bottom line, just do it this way - doesn't make sense to try something so complicated in the DSL when the full power of Ruby is available in the template.

Alex Harvey gravatar imageAlex Harvey ( 2016-03-08 03:43:08 -0600 )edit

Thx for your effort! How can I access each key value pair for the parameters of each interface and append them to the output?

prototyp gravatar imageprototyp ( 2016-03-08 04:30:57 -0600 )edit
0

answered 2016-03-08 02:37:08 -0600

prototyp gravatar image

updated 2016-03-08 09:35:33 -0600

Finally fragments and the static template has been dropped in favor of an inline_template. To let the old configuration be untouched the code from the static template got moved to the inline template. Further the template is dynamically extended via ERB code reading interface configuration from an hash out of hiera.

Hash from hiera:

lip_network::interfaces:
  em4:
    address: '123.456.0.13'
    netmask: '255.255.252.0'
    network: '123.456.0.0'
    broadcast: '123.456.0.255'
    dns-search: 'xxx.xxx.com

Module Code:

# Debian old school network settings
class lip_network::debian
{
  $ipaddress  = $::lip_network::ipaddress
  $netmask    = $::lip_network::netmask
  $gateway    = $::lip_network::gateway
  $dns1       = $::lip_network::dns1
  $domain     = $::lip_network::domain
  $iface      = $::lip_network::iface
  $interfaceconfigs = hiera_hash(lip_network::interfaces)

  package { 'resolvconf':
    ensure  => latest,
  }
# creates inline_template; 
# the first interface is defined via static vars read from hiera
# further interfaces are added via ERB and an hash from hiera
$content = inline_template('
auto lo
 iface lo inet loopback

auto <%= @iface %> 
iface <%= @iface %> inet static
    address <%= @ipaddress %>
    netmask <%= @netmask %> 
    gateway <%= @gateway %>
    dns-nameservers <%= @dns1 %>
    dns-search <%= @domain %>

<% @interfaceconfigs.each do |interfacename, interfaceparams| -%>
auto <%= interfacename %>
iface <%= interfacename %> inet static
<% interfaceparams.each do |key, value| -%>
    <%= key %> <%= value%>
<% end %>
<% end %>'
)
file { '/etc/network/interfaces':
  ensure  => file,
  mode    => '0644',
  owner   => 'root',
  content => $content,
}
  exec { 'iface restart':
    command     => "ifdown ${iface} ; ifup ${iface}",
    refreshonly => true,
    subscribe   => File['/etc/network/interfaces'],
  }
}
edit flag offensive delete link more

Comments

why not using the network_config module ?
https://forge.puppetlabs.com/adrien/network
I use options and *-up wrappers w/o any problems.
Also, modifying to your needs is no big deal.

FranzCC gravatar imageFranzCC ( 2016-03-08 04:13:17 -0600 )edit

yes this was also my first approach. But removing the old module which creates a network/interfaces conf out of every configuration for every server stop my doing that. so i decided to just extend the old module

prototyp gravatar imageprototyp ( 2016-03-08 04:33:41 -0600 )edit

With that much stuff in the inline template I think it's also time to move it to a normal template. Otherwise looks good.

Alex Harvey gravatar imageAlex Harvey ( 2016-03-08 09:43:39 -0600 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower

Stats

Asked: 2016-03-07 07:23:07 -0600

Seen: 315 times

Last updated: Mar 08 '16