Big Bubbles (no troubles)

What sucks, who sucks and you suck

Using Augeas With Puppet

‘Augeas is a configuration editing tool.’

My take: Augeas is what the Puppet crew integrated after years of various people saying that editing files in place was the Wrong Way to do things and hence the EditFiles facility in Cfengine was Evil.

Sometimes, in this imperfect real world, you have to edit a file in place.

Augeas can best be thought of as plugging the gaps in Puppet’s capabilities where an object-specific resource type (such as the host resource to manipulate /etc/hosts entries) is not yet available. In these cases, you can use an augeas resource to modify the relevant file.

Use augtool to test and verify your Augeas changes. (When using EPEL RPMs, you will need to install the augeas package as it is not a dependency for puppet.)

Basic example: $ augtool -n augtool> ls /files/etc # list augeas-manageable files under /etc augtool> print /files/etc/hosts # show tree layout of hosts file (Use -n so that any changes will be saved to a new file called filename.augnew.) Augeas commands can also be held in a file and submitted to augtool with the -f flag.

Augtool is useful to interactively examine and formulate programmatic changes to files; print the tree of the relevant file and determine where and how to make the required edits. Note that the commands are sometimes not directly translatable to Puppet augeas resources.

For example, enabling password history on RHEL with augtool: augtool> set /files/etc/pam.d/system-auth/10/argument[last()+1] “remember=6” augtool> save

Same thing in Puppet: augeas { ‘passwd-history’: context => ‘/files/etc/pam.d/system-auth’, changes => [“set [module =~ regexp(‘.pam_unix.so’)][type = ‘password’]/argument[last()+1] remember=6”], onlyif => “match [module =~ regexp(‘.pam_unix.so’)][type = ‘password’][argument = ‘remember=6’] size == 0”, } In Puppet, we have to add an onlyif parameter to check for the existence of the relevant argument and prevent Puppet repeatedly adding it on successive runs. Also, we imply the location of the required line relative to existing ones rather than explicitly stating the branch of the file tree. (The regexp is used because the exact format of ‘pam_unix.so’ can vary depending on distro release; some versions specify an explicit path to the library.)

Enabling pam_tally on RHEL with augtool: augtool> ins 01 after /files/etc/pam.d/system-auth/*[module=’pam_unix.so’][type=’account’][last()] augtool> set /files/etc/pam.d/system-auth/01/type account augtool> set /files/etc/pam.d/system-auth/01/control required augtool> set /files/etc/pam.d/system-auth/01/module ‘pam_tally.so’ augtool> save

Same thing in Puppet: augeas { ‘pam_tally_auth’: context => ‘/files/etc/pam.d/system-auth’, changes => [“ins 01 after [module =~ regexp(‘.pam_unix.so’)][type = ‘account’][last()]”, ‘set 01/type account’, ‘set 01/control required’, ‘set 01/module pam_tally.so’, ], onlyif => “match [module =~ regexp(‘.pam_tally.so’)][type = ‘account’][control = ‘required’] size == 0”, } Here we use the onlyif parameter to check that line does not already exist (empty size in tree). Yes, the quoting can be tricky. (You will also need to add a pam_tally.so auth line.)

If Augeas doesn’t recognise a particular file but its format corresponds to one of the supplied lenses, you can explicitly specify the compatible lens to augtool. For example, augeas doesn’t currently handle the audispd plugin file format, but it corresponds closely to a normal ‘ini’ file except that it doesn’t use [section]s. The PHP lens accepts ini files in which parameters can be defined outside of sections (i.e. as is the case for php.ini), so we can co-opt that: $ augtool -n –noautoload set /augeas/load/IniFile/lens PHP.lns set /augeas/load/IniFile/incl /etc/audisp/plugins.d/syslog.conf load print /files/etc/audisp/plugins.d/syslog.conf print /augeas//error # show parse errors if previous result empty set /files/etc/audisp/plugins.d/syslog.conf/.anon/active yes save (Note that the unknown/missing section is referred to as ‘.anon’.)

In Puppet, you specify the lens parameter to the augeas resource: augeas { ‘audisp-syslog’: context => ‘/files/etc/audisp/plugins.d/syslog.conf’, incl => ‘/etc/audisp/plugins.d/syslog.conf’, changes => [ ‘set .anon/active yes’ ], lens => ‘PHP.lns’, }

More info? The Puppet wiki has an excellent tutorial page with practical examples. Failing that, Google the Augeas fora and see if someone else has had the same question. If you really, really like the Augeas approach, have a look at the alternative Augeas-based providers for Puppet (hat tip to @raphink).

Other bubbles

  • I have various gists containing further Augeas examples.
  • The Aqueduct project also has some good examples of Augeas use in its Puppet manifests.