Ask Your Question

how to implement refreshonly for templated file

asked 2014-07-25 03:13:20 -0600

HBlock gravatar image

updated 2014-07-28 03:06:05 -0600

I am trying to automate the management of our bind dns zone configuration via puppet. My current approach is as follows: every zone consists of a zone file and an include file. the zone file should be template based with the serial and the include statement as configureable parameters. I would manage the include via another file resource delivered through the puppet file server.

Based on this approach I would need some kind of custom or defined type that updates the zone file, i.e. increases the serial only if the include file changes. The template looks like this: My template currently looks like this:

$TTL 300S
@                       IN SOA  dnsserver (
            <%= scope.function_get_serial([@domain])%>
                         28800          ; Refresh 8 hours
                         7200           ; Retry every 2 hours
                         604800         ; Expire after a week
                         3600 ) ; ttl of 1 hour

@                       IN NS   ns1
                        IN NS   ns2
                        IN NS   ns3
$INCLUDE <%= @includefile %>

As far as I understand it is not possible to implement a mechanism like exec's refreshonly for defined resource types or make it behave differently on refresh?

While I was able to write a Custom type that acts only on refresh I was not able to add another resource or templated file (by using Puppet::Util::ResourceTemplate) within that custom type. Is it possible to do so? If it is, how would that look? Would it be possible to extend the existing file type with a refresh method?

I would prefer the defined type solution but am open to any other suggestions.

I am aware that there might be other approaches to automate the configuration of a dns server but I'd like to try this first.

Thank you very much Henning

edit retag flag offensive close merge delete

3 Answers

Sort by ยป oldest newest most voted

answered 2014-07-28 16:02:22 -0600

timelord gravatar image

Just an idea.

Zone template (zonefile):

$TTL 300S
@                       IN SOA  dnsserver (
                              0 ; SERIAL
                          28800 ; Refresh 8 hours
                           7200 ; Retry every 2 hours
                         604800 ; Expire after a week
                         3600 ) ; ttl of 1 hour

@                       IN NS   ns1
                        IN NS   ns2
                        IN NS   ns3
$INCLUDE <%= @includefile %>

Puppet module (you can wrap the following section into 'define'):

file {"/path/to/${zonefile}":
   ensure  => present,
   replace => false,
   content => template('zonefile.erb'),

file {"/path/to/${includefile}":
   ensure  => present,
   content => template('includefile.erb')
   notify  => Exec["serial increment: ${zonefile}"],

exec {"serial incrememnt: ${zonefile}":
   command     => "NEW_SERIAL=\"$( /bin/date +%s )\"; /bin/sed -i.bak \"s/[0-9]\+ ; SERIAL/$NEW_SERIAL ; SERIAL/g\" /path/to/${zonefile}",
   refreshonly => true,
   require     => File["/path/to/${zonefile}"],
  1. Deploy 'zonefile' if it doesn't exist, but do not overwrite if it already exists
  2. Deploy 'includefile' and notify Exec to change the serial number in 'zonefile'
  3. If 'zonefile' already exists and if notified, generate a new serial (e.g. unix time) and replace it in the 'zonefile'

The 'Exec' pretty much performs the following bash command:

NEW_SERIAL="$( date +%s )"
sed -i.bak "s/[0-9]\+ ; SERIAL/$NEW_SERIAL ; SERIAL/g" /path/to/zonefile

I am pretty sure you could do the same thing with Puppet parser code (Ruby), but this is just a simple idea how to do what you need.

edit flag offensive delete link more

answered 2014-07-26 18:47:18 -0600

updated 2014-07-26 18:47:53 -0600

You should take a look at the Metaparameter Reference

If I am understanding you correctly, something like this show work:

file { 'includefile':
  ensure => present,
  content => template('foo/bar.erb')

zonefiledefine { 'zone':
  ensure => 'present',
  content => 'foo',
  subscribe => File['includefile']

This is assuming that I understand your dilemma.

edit flag offensive delete link more


I am afraid this doesn't help me. My dilemma is finding a way to either incrementing the serial (see template above) via the get_serial or updating the file ONLY if the includefile has been changed. So i would need some kind of refreshonly mechanisms.

HBlock gravatar imageHBlock ( 2014-07-28 03:12:08 -0600 )edit

answered 2014-11-03 05:41:38 -0600

HBlock gravatar image

It's been a while and we've already found a solution for some time and i wanted to finally post it: We're creating the zonefile with puppetlabs-concat. We're having several concat-fragments for header information, body, etc. One fragment only contains the serial. The serial fragment refers to a local source:

  concat::fragment{"serial $file":
    target  => "$root_dir/$file",
    source  => "file:///var/lib/bind/serials/${file_without_dirs}_serial",
    order   => '02',

This file is written by a ruby script as part of an exec statement. The ruby script calculates the correct serial. The exec statement is - of course - refreshonly and triggered by any zonefile change, so if one of the concat fragments change, the serial is incremented: notify => Exec["/scripts/getserial.rb ${serial} >/var/lib/bind/serials/${filewithoutdirs}_serial"]

edit flag offensive delete link more

Your Answer

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

Add Answer

Question Tools



Asked: 2014-07-25 03:13:20 -0600

Seen: 2,284 times

Last updated: Nov 03 '14