Using Puppet with Augeas
Augeas is a lovely tool that treats config files (well, anything really, but it’s mostly about config files) as trees of values. You then modify the tree as you like, and write the file back.
This is basically the solution to the problem of dealing with upstream configuration changes combined with local modifications: you can allow the upstream changes through and then apply changes with Augeas to the new version.
Assuming you want to work with Augeas, this is a description of how to perform Augeas changes using Puppet. You’ll need Puppet >= 0.24.7 for this. The basic usage is [[Type_Reference#augeas|Type Reference]] .
The somewhat more important, and unfortunately complicated, part is figuring out what the tree for a file looks like so you can manipulate it properly. The definition that Augeas uses to turn a file into a tree is called a lens, and understanding the trees is more difficult than it should be, because many lenses are not documented sufficiently, or at all. The documentation for those that are has its own surprisingly hard to find page on the Augeas site. You can see what lenses are available by looking in /usr/share/augeas/lenses/ (or /usr/local/share/augeas/lenses/ , or possibly somewhere else, depending on your setup).
You can also see which files Augeas has successfully parsed by entering “ls /files/” in augtool and drilling down from there. If a file hasn’t been properly parsed by Augeas, it simply won’t show up. This could mean that the file has a syntax error, or it could imply a failure in the lense itself.
Here’s an example of how to determine the tree structure of a file, in this case /etc/exports.
The easiest thing to do is to set up the file with some examples (I pulled examples from the bottom of “man 5 exports”) and see what they look like:
$ augtool
augtool> ls /files/etc/exports/
comment[1] = /etc/exports: the access control list for filesystems which may be exported
comment[2] = to NFS clients. See exports(5).
comment[3] = sample /etc/exports file
dir[1]/ = /
dir[2]/ = /projects
dir[3]/ = /usr
dir[4]/ = /home/joe
From here you can investigate the structure, like so:
augtool> ls /files/etc/exports/dir[1]
client[1]/ = master
client[2]/ = trusty
The corresponding line in the file is:
/ master(rw) trusty(rw,no_root_squash)
Digging further:
augtool> ls /files/etc/exports/dir[1]/client[1]
option = rw
So, if you want to add a new entry, you’d do something like this:
augtool> set /files/etc/exports/dir[last()+1] /foo
augtool> set /files/etc/exports/dir[last()]/client weeble
augtool> set /files/etc/exports/dir[last()]/client/option[1] ro
augtool> set /files/etc/exports/dir[last()]/client/option[2] all_squash
augtool> save
Saved 1 file(s)
Which creates the line:
/foo weeble(ro,all_squash)
Now that you’ve played around in augtool, you can make changes using Puppet:
augeas{ "export foo" :
context => "/files/etc/exports",
changes => [
"set dir[last()+1] /foo",
"set dir[last()]/client weeble",
"set dir[last()]/client/option[1] ro",
"set dir[last()]/client/option[2] all_squash",
],
}
This adds the line described above.