Playing with augeas for fun and profit
Contrary to what Wikipedia says, the Augeas I'm using isn't at all related to the 5th labour of Hercules. Rather, it's a configuration editing tool and Puppet resource type used primarily to alter and control config files.
After recently adding control of /root/.my.cnf to the manifests managing all my servers, I needed to look into something which could alter that configuration file without blowing away some of the other lines in there which weren't centrally managed - like the MySQL root password.
My /root/.my.cnf is structured as follows and I wanted to alter the port to 3306.
[client]
user=root
password=supersekretpassword
port=3306
socket=/var/run/mysqld/mysqld.sock
Augeas allows us to alter config from this file and rewrite it without clobbering any of the other details. Whilst there's already plenty of information about using Augeas on the documentation site and the puppet type reference page, there wasn't anything that immediately stood out to me when I had difficulty with the /root/.my.cnf file.
One of the key things to realise when dealing with Augeas is that it has preset configuration file types loaded into it. These preset config file styles are known as 'lenses' and each will only work with a set list of files at specific file locations. By default, the lens holding the information for MySQL config files (MySQL.lns) only acknowledges the existence of the following file locations:
- /etc/my.cnf
- /etc/mysql/conf.d/*.cnf
- /etc/mysql/my.cnf
Before we can make the augeas type alter the /root/.my.cnf file we have to register it with the MySQL.lns lens.
Understanding Augeas with augtool
From the command line, we can use augtool to investigate what Augeas is able to see and the files registered to each lens type. Using augtool is a great way to start understanding Augeas, the config tree and the ability to alter config files. To register our aforementioned /root/.my.cnf and alter the port number using augtool we may use the following steps.
# Load augtool without any files.
$ augtool --noload
# Add in the /root/.my.cnf file as a configuration
# file managed by the MySQL.lns lens and ensure
# we don't clobber any of the other include files by
# setting the include index as 1 greater than the last
# existing.
augtool> set /augeas/load/MySQL/incl[last()+1] "/root/.my.cnf"
# Finally load the files.
augtool> load
# Print the port directive from the [client]
# section in the /root/.my.cnf file
augtool> print /files/root/.my.cnf/target[ . = "client"]/port /files/root/.my.cnf/target/port = "3306"
# Set the port to 33306
augtool> set /files/root/.my.cnf/target[ . = "client"]/port 33306
# Save the changes back to /root/.my.cnf
augtool> save
Saved 1 file(s)
Implementing /root/.my.cnf changes with Augeas in Puppet
Once you start to understand how Augeas uses lenses for configuration file types and the way a configuration file becomes a tree, it becomes trivial to alter any config file in puppet with the augeas resource. The following snippet will ensure that, as above, the port directive in the [client] section of the /root/.my.cnf file is set to 33306. Without specifying the correct lens however, this won't work as Augeas doesn't register /root/.my.cnf to a lens by default so ignores it.
augeas {'/root/.my.cnf port change':
lens => 'MySQL.lns',
incl => '/root/.my.cnf',
changes => [
"set target[ . = 'client']/port 33306"
],
}