Augeas is a configuration editing tool. It parses configuration files in their native formats and transforms them into a tree. Configuration changes are made by manipulating this tree and saving it back into native config files.
Configuration files support is provided by “lenses”. The default lenses are provided in augeas-lib package
$ rpm -ql pe-augeas-libs | grep lenses
/opt/puppet/share/augeas/lenses/dist
/opt/puppet/share/augeas/lenses/dist/aliases.aug
…
If your configuration is not listed, you can write your own lenses definition file.
Language bindings are available:
Ruby, Python, OCaml, Perl, Haskell, PHP, Lua, and Java
Augeas has two main directories:
- augeas: augeas configuration directory. e.g control loading lenses
- files: user data directory tree. e.g /etc/hosts is mapped to /files/etc/hosts
$augtool
augtool> ls /
augeas/ = (none)
files/ = (none)
Sample hosts file to be tested
$cat /etc/hosts
# comment test1
# comment test2
172.16.1.11 web1 web1.example.com server1.example.com
#######Augeas translate above hosts file to
augtool> print /files/etc/hosts
/files/etc/hosts
/files/etc/hosts/#comment[1] = "comment test1"
/files/etc/hosts/#comment[2] = "comment test2"
/files/etc/hosts/1
/files/etc/hosts/1/ipaddr = "172.16.1.11"
/files/etc/hosts/1/canonical = "web1"
/files/etc/hosts/1/alias[1] = "web1.example.com"
/files/etc/hosts/1/alias[2] = "server1.example.com"
Adding a new comment
augtool> set /files/etc/hosts/#comment[last()+1] "comment test3"
augtool> print /files/etc/hosts/
/files/etc/hosts
/files/etc/hosts/#comment[1] = "comment test1"
/files/etc/hosts/#comment[2] = "comment test2"
/files/etc/hosts/1
/files/etc/hosts/1/ipaddr = "172.16.1.11"
/files/etc/hosts/1/canonical = "web1"
/files/etc/hosts/1/alias[1] = "web1.example.com"
/files/etc/hosts/1/alias[2] = "server1.example.com"
/files/etc/hosts/#comment[3] = "comment test3"
########New comment will be added to last line.
########If you want to append it next to #comment[2], use insert
augtool> ins #comment after /files/etc/hosts/#comment[last()]
augtool>
augtool> set /files/etc/hosts/#comment[last()] "comment test3"
augtool> print /files/etc/hosts
/files/etc/hosts
/files/etc/hosts/#comment[1] = "comment test1"
/files/etc/hosts/#comment[2] = "comment test2"
/files/etc/hosts/#comment[3] = "comment test3"
/files/etc/hosts/1
/files/etc/hosts/1/ipaddr = "172.16.1.11"
/files/etc/hosts/1/canonical = "web1"
/files/etc/hosts/1/alias[1] = "web1.example.com"
/files/etc/hosts/1/alias[2] = "server1.example.com"
Adding a host entry.
You can’t use last() to auto increase it from hosts/1 to hosts/2, because “1” or “2” is label name not an index number like #comment[1]/#comment[2].
The trick is to use “01,02,03” etc.
augtool> set /files/etc/hosts/01/ipaddr 172.16.1.12
augtool>set /files/etc/hosts/01/canonical web2
##at this point, it is hosts/01 added
augtool> print /files/etc/hosts
/files/etc/hosts
/files/etc/hosts/#comment[1] = "comment test1"
/files/etc/hosts/#comment[2] = "comment test2"
/files/etc/hosts/#comment[3] = "coment test3"
/files/etc/hosts/1
/files/etc/hosts/1/ipaddr = "172.16.1.11"
/files/etc/hosts/1/canonical = "web1"
/files/etc/hosts/1/alias[1] = "web1.example.com"
/files/etc/hosts/1/alias[2] = "server1.example.com"
/files/etc/hosts/01
/files/etc/hosts/01/ipaddr = "172.16.1.12"
/files/etc/hosts/01/canonical = "web2"
####after save and load, hosts/2 is added
augtool> save
Saved 1 file(s)
augtool> load
augtool> print /files/etc/hosts
/files/etc/hosts
/files/etc/hosts/#comment[1] = "comment test1"
/files/etc/hosts/#comment[2] = "comment test2"
/files/etc/hosts/#comment[3] = "coment test3"
/files/etc/hosts/1
/files/etc/hosts/1/ipaddr = "172.16.1.11"
/files/etc/hosts/1/canonical = "web1"
/files/etc/hosts/1/alias[1] = "web1.example.com"
/files/etc/hosts/1/alias[2] = "server1.example.com"
/files/etc/hosts/2
/files/etc/hosts/2/ipaddr = "172.16.1.12"
/files/etc/hosts/2/canonical = "web2"
Change an entry by referencing to itself
Change the comment “comment test1” to “newcomment test1”
#Change the comment “comment test1” to “newcomment test1”
augtool> /set files/etc/hosts/#comment[.='comment test1'] 'newcomment test1'
augtool> print /files/etc/hosts/#comment
/files/etc/hosts/#comment[1] = "newcomment test1"
/files/etc/hosts/#comment[2] = "comment test2"
/files/etc/hosts/#comment[3] = "comment test3
#Change any comment starting with comment to ‘oldcomment’ by regex match
augtool>setm /files/etc/hosts #comment[.=~regexp('comment.*')] 'oldcomment'
augtool> print /files/etc/hosts/#comment
/files/etc/hosts/#comment[1] = "newcomment test1"
/files/etc/hosts/#comment[2] = "oldcomment"
/files/etc/hosts/#comment[3] = "oldcomment"
#Usually, regex match is used to delete entries. e.g delete comment test[23]
augtool> print /files/etc/hosts/#comment
/files/etc/hosts/#comment[1] = "comment test1"
/files/etc/hosts/#comment[2] = "comment test2"
/files/etc/hosts/#comment[3] = "comment test3"
augtool> rm /files/etc/hosts/#comment[.=~regexp('comment test[23]')]
rm : /files/etc/hosts/#comment[.=~regexp('comment test[23]')] 2
augtool> print /files/etc/hosts/#comment
/files/etc/hosts/#comment = "comment test1"
augtool>
Change an entry by referencing to relative nodes
e.g change ip of a host ‘web1’ to 172.16.11.11
augtool> print /files/etc/hosts/1
/files/etc/hosts/1
/files/etc/hosts/1/ipaddr = "172.16.1.11"
/files/etc/hosts/1/canonical = "web1"
/files/etc/hosts/1/alias[1] = "web1.example.com"
/files/etc/hosts/1/alias[2] = "server1.example.com"
augtool> set /files/etc/hosts/*/ipaddr[../canonical = 'web1'] 172.16.11.11
augtool> print /files/etc/hosts/1
/files/etc/hosts/1
/files/etc/hosts/1/ipaddr = "172.16.11.11"
/files/etc/hosts/1/canonical = "web1"
/files/etc/hosts/1/alias[1] = "web1.example.com"
/files/etc/hosts/1/alias[2] = "server1.example.com"
#multiple conditions can be joined together
augtool> match /files/etc/hosts/*/ipaddr[../canonical = 'web1' and ../alias = 'server1.example.com']
/files/etc/hosts/1/ipaddr = 172.16.11.11
augtool> match /files/etc/hosts/*[canonical = 'web1' and alias = 'server1.example.com']
/files/etc/hosts/1 = (none)
Comment or uncomment a line
Comment or uncomment is difficult for Augeas to implement, it can only be achieved by inserting a new line after the comment line then removing the old line.
You can extend Augeas to include ‘comment’ and ‘uncomment’ functions. The following code is an example for puppet.
##Define a function
define augeasnew ($file,$line){
$exp=regsubst($line[0], '^(un)?comment *(.*)' , '\2')
case $line[0] {
/^uncomment/: {
exec {"/bin/sed -i -e '/${exp}/s/#//g' $file":
onlyif => "/bin/grep '${exp}' ${file} | /bin/grep '#' ",}
}
/^comment/: {
exec {"/bin/sed -i -e '/${exp}/ s/^/#/' $file":
onlyif => "/bin/grep '${exp}' ${file} | /bin/grep -v '#' ",}
}
default: {
augeas {'augeas-chg-any':
context => "/files/${file}",
changes => $line, }
}
}
}
##execute the function
augeasnew {'chg-hosts-file':
file => '/etc/hosts',
#Mulitple Augeas commands can be stored in an array
#However,none-Augeas command (uncomment or comment) can only be stored in first element of an array.
#line => ["set 1/ipaddr '10.1.1.1'" , "set 2/ipaddr '10.1.1.2'",],
line => ["comment c line1",],
}
Troubleshooting.
You can check /augeas//error for detailed errors, for example, Augeas can’t load /etc/sudoers
augtool> print /augeas//error
/augeas/files/etc/sudoers/error = "parse_failed"
/augeas/files/etc/sudoers/error/pos = "1998"
/augeas/files/etc/sudoers/error/line = "62"
/augeas/files/etc/sudoers/error/char = "0"
/augeas/files/etc/sudoers/error/lens = "/opt/puppet/share/augeas/lenses/dist/sudoers.aug:478.10-.57:"
/augeas/files/etc/sudoers/error/message = "Iterated lens matched less than it should"
In this case, error is encountered in line 62.
$sed -n '62p' /etc/sudoers
Defaults !visiblepw
#You can upgrade Augeas or comment out the line to resolve the issue
Reference:
http://augeas.net/tour.html
http://augeas.net/page/Path_expressions
http://docs.puppetlabs.com/references/2.6.8/function.html
http://docs.puppetlabs.com/guides/language_guide.html