augeas

Bindings to the Augeas configuration API.

  1. augeas
  2. Overview
  3. Requirements
  4. Error reporting
  5. Interface
  6. Bugs and limitations
  7. About this egg
    1. Author
    2. Acknowledgements
    3. Version history
    4. Repository
    5. License

Overview

This egg provides an interface to the Augeas configuration API. From the Augeas web page:

For a short tutorial on Augeas, see the Augeas quick tour.

For information on the XPath expressions accepted by Augeas, see the Augeas path expression docs.

Requirements

pkg-config is required to obtain the proper compilation flags for libxml2, which Augeas depends on (even though we do not use it!) Both augeas and libxml2 must be visible to pkg-config, which should normally be the case.

Error reporting

All API calls raise errors of type (exn augeas errcode), where errcode is one of the symbols:

nomem Out of memory
internal Internal error (bug)
pathx Invalid path expression
nomatch No match for path expression
mmatch Too many matches for path expression
syntax Syntax error in lens file
nolens Lens lookup failed
mxfm Multiple transforms
nospan No span for this node
mvdesc Cannot move node into its descendant
cmdrun Failed to execute command
badarg Invalid argument in function call
label Invalid label

Under the augeas condition are properties containing the integer error code, message, minor message elaborating on the main message (may be #f), and any details (may be #f). For example:

#;3> (aug-get a "/files/etc/hosts/alias[")
Error: (aug-get) Invalid path expression: "/files/etc/hosts/alias["

#;3> ,exn
condition: (exn augeas pathx)
 exn
	location: aug-get
	message: "Invalid path expression"
	arguments: ("/files/etc/hosts/alias[")
 augeas
	code: 3
	message: "Invalid path expression"
	minor-message: "illegal string literal"
	details: "/files/etc/hosts/alias[|=|"
 pathx

#;4> ((condition-property-accessor 'augeas 'minor-message) #3)
"illegal string literal"

Interface

[procedure] (aug-init #!key root loadpath (flags '()))

Initializes the Augeas library and returns an opaque augeus record object which you pass to the other API calls.

On failure, raises an error. Unlike the other API calls, this is currently a generic exception, not an (exn augeas ...).

Optional keywords:

root
A string representing the filesystem root. If omitted or #f, uses the environment variable AUGEAS_ROOT, or failing that, "/".
loadpath
A colon-separated list of directories to search for modules. May be omitted or #f. This is in addition to the standard load path and the env var AUGEAS_LENS_LIB.
flags
A list of flags (see below).

Flags is a list containing at most one of the save- flags:

save-overwrite Overwrite the original file (the default behavior)
save-backup Copy the original file to file.augsave, then overwrite the original file
save-newfile Save changes into file.augnew; do not overwrite original file
save-noop Make save a no-op process, just record what would have changed into /augeas/events/saved

and any of these flags:

type-check Typecheck lenses; very expensive
no-stdinc Do not search the builtin default directories for modules
no-load Do not load the tree of files
no-module-autoload Do not autoload modules from the search path
enable-span Load span positions for nodes; required if using aug-span

Examples:

;; Init Augeas and load all recognized files from "/",
;; along with all available modules (lenses).
(define a (aug-init))

;; Init Augeas and load all recognized files from ./root, 
;; along with all available lenses.
(define a (aug-init root: "./root"))

;; Extremely quick startup, but you have to set up /augeas/load/* manually
;; (see the Augeas docs).  Will copy original file with .augsave extension
;; before modifying it.  Uses / as the root, assuming AUGEAS_ROOT is not set.
(define a (aug-init flags: '(save-backup no-load no-module-autoload)))
[procedure] (aug-close a)

Closes augeas handle and relinquishes any resources. It is safe to call this multiple times. However, once the handle is closed, passing it to any other API call will raise an error.

[procedure] (aug-get a path)

Get the string value of the node at PATH. If the node exists but has no value, it returns #f. If the node does not exist, it also returns #f.

Raises an error if there is more than one node matching PATH, or if PATH is not a legal path expression.

(aug-get a "/files/etc/hosts/1/ipaddr")
 ;=> "127.0.0.1"
(aug-get a "/files/etc/hosts/1/foo")
 ;=> #f
[procedure] (aug-exists? a path)

Returns a boolean indicating whether a node exists at PATH. Unlike get, this can distinguish between nodes with value #f and non-existent nodes.

[procedure] (aug-set! a path val)

Sets the value associated with PATH to VALUE (a string). The node is created a PATH if it does not exist; otherwise its value is updated. Raises an error if PATH matches more than one node.

(aug-set! a "/files/etc/hosts/1/ipaddr" "33.34.35.36")
[procedure] (aug-set-multiple! a base sub value)

Sets the value of multiple nodes in one operation. Finds or creates a node matching SUB by interpreting SUB as a path expression relative to each node matching BASE. SUB may be #f, in which case all the nodes matching BASE will be modified.

Returns the integer number of modified nodes on success, or raises an error on failure.

Example:

;; Add node test="foo" to all host entries that are not comments.
(aug-match a "/files/etc/hosts/*[label() != '#comment']")
 ;=> ("/files/etc/hosts/1" "/files/etc/hosts/2")
(aug-print a "/files/etc/hosts/*/test")
(aug-set-multiple! a "/files/etc/hosts/*[label() != '#comment']"
                     "test" "foo")
(aug-print a "/files/etc/hosts/*/test")
 ;; /files/etc/hosts/1/test = "foo"
 ;; /files/etc/hosts/2/test = "foo"
[procedure] (aug-remove! a path)

Remove all nodes that match PATH, along with all their children. Returns the number of entries removed, or raises an error on failure.

[procedure] (aug-move! a src dst)

Move the node SRC to DST. SRC must match exactly one node in the tree. DST must either match exactly one node in the tree, or may not exist yet. If DST exists already, it and all its descendants are deleted. If DST does not exist yet, it and all its missing ancestors are created.

Note that the node SRC always becomes the node DST: when you move /a/b to /x, the node /a/b is now called /x, no matter whether /x existed initially or not.

Returns an unspecified value on success; raises an error if the move fails.

[procedure] (aug-match a path)
[procedure] (aug-match-count a path)

aug-match returns a list of all single node paths matching the XPath expression PATH.

aug-match-count is like aug-match but returns the number of matches. This is more efficient than (length (aug-match ...)).

For information on the XPath expressions accepted by Augeas, see the Augeas path expression docs.

Example:

(aug-match a "/files/etc/hosts/*/ipaddr")
 ;=> ("/files/etc/hosts/1/ipaddr" "/files/etc/hosts/2/ipaddr")
[procedure] (aug-insert! a path label #!optional before?)

Creates a new sibling LABEL for PATH by inserting into the tree just before PATH if before? is #t, or just after PATH if before? is #f (the default). The new node's value is null.

PATH must match exactly one existing node in the tree, and LABEL must be a label, i.e. not contain a /, * or end with a bracketed index [N].

Returns an unspecified value on success; raises an error if the insertion fails.

Unfortunately, there is no way to set the value at the same time, nor to capture the inserted node into a variable.

Example:

(aug-print a "/files/etc/hosts/1/alias")
 ;; /files/etc/hosts/1/alias[1] = "localhost"
 ;; /files/etc/hosts/1/alias[2] = "galia.watzmann.net"
 ;; /files/etc/hosts/1/alias[3] = "galia"
(aug-insert! a "/files/etc/hosts/1/alias[2]" "alias" #t)
(aug-insert! a "/files/etc/hosts/1/alias[3]" "alias")
(aug-print a "/files/etc/hosts/1/alias")
 ;; /files/etc/hosts/1/alias[1] = "localhost"
 ;; /files/etc/hosts/1/alias[2]
 ;; /files/etc/hosts/1/alias[3] = "galia.watzmann.net"
 ;; /files/etc/hosts/1/alias[4]
 ;; /files/etc/hosts/1/alias[5] = "galia"
[procedure] (aug-load! a)

Loads files into the tree. This is done by default in aug-init unless you provide it the no-load flag.

Raises an error on failure, or returns an unspecified value on success. Note that "success" includes the case where some files could not be loaded due to parse error etc. Details of such files can be found in the nodeset /augeas//error.

Which files to load and what lenses to use on them is specified under /augeas/load in the tree; each entry /augeas/load/NAME specifies a transform, by having itself exactly one child lens and any number of children labelled incl and excl. The value of NAME has no meaning.

The lens grandchild of /augeas/load specifies which lens to use, and can either be the fully qualified name of a lens Module.lens or @Module. The latter form means that the lens from the transform marked for autoloading in MODULE should be used.

The 'incl' and 'excl' grandchildren of /augeas/load indicate which files to transform. Their value are used as glob patterns. Any file that matches at least one 'incl' pattern and no 'excl' pattern is transformed. The order of 'incl' and 'excl' entries is irrelevant.

When aug-load! is first called, it populates /augeas/load with the transforms marked for autoloading in all the modules it finds. Before loading any files, aug-load! will remove everything underneath /augeas/files (file metadata) and /files (file data), regardless of whether any entries have been modified or not.

Note: despite the fact that file metadata under /augeas/files is cleared on load, a previously-loaded file will only be reloaded if its data in /files has been modified in memory, or if its modification time on disk (mtime) has changed. The mtime has a granularity of one second. Therefore, if the file changes within one second after it was loaded or saved, it won't be re-read. If necessary, you can force a reload by clearing the mtime with something similar to:

(aug-set! a "/augeas/files/etc/hosts/mtime" #f)
[procedure] (aug-save! a #!optional mode)

Writes all pending changes to disk. Raises an error on failure, returns an unspecified value on success.

The optional save mode may be any of:

#f or omitted Use the save mode passed to aug-init!
overwrite Overwrite the original file
backup Copy the original file to file.augsave, then overwrite the original file
newfile Save changes into file.augnew; do not overwrite original file
noop Make save a no-op process, just record what would have changed into /augeas/events/saved
[procedure] (aug-defvar a name expr)

Defines a variable NAME whose value is the result of evaluating EXPR. If a variable NAME already exists, its name will be replaced with the result of evaluating EXPR. Context will not be applied to EXPR.

If EXPR is NULL, the variable NAME will be removed if it is defined.

Path variables can be used in path expressions later on by prefixing them with $.

On success, returns 0 if EXPR evaluates to anything other than a nodeset, or the number of nodes if EXPR evaluates to a nodeset. On failure, raises an error.

Example:

(aug-defvar a "hosts" "/files/etc/hosts")    ;=> 1
(aug-get a "$hosts/1/ipaddr")                ;=> "127.0.0.1"
(aug-defvar a "hosts" #f)                    ;=> 0
(aug-get a "$hosts/1/ipaddr")                ;=> undefined variable (exn augeas pathx)
[procedure] (aug-defnode a name expr value)

If the node at EXPR does not exist, creates a node at EXPR with value VALUE, storing the node in variable NAME. This is like using defvar followed by aug-set!.

If the node or nodes at EXPR do exist, stores the corresponding nodeset in variable NAME. The node values are not modified and VALUE is ignored.

Returns two values: the integer number of nodes in the nodeset, and a boolean indicating whether a node was created or not.

A typical use is with the XPath predicate [last()+1] to append a node to a list of nodes that all have the same name, and keep a reference to the new node.

Example:

;; First create a new node with a value and assign it to a variable;
;; then assign the same node to a second variable (value is ignored).
(aug-defnode a "myalias" "/files/etc/hosts/1/alias[last()+1]" "crichton")
 ;=> values: 1 #t
(aug-defnode a "myalias1" "/files/etc/hosts/1/alias[last()]" "crichton2")
 ;=> values: 1 #f
(aug-get a "$myalias") 
 ;=> "crichton"
(aug-get a "$myalias1")
 ;=> "crichton"
[procedure] (aug-print a path #!optional (port (current-output-port)))

Print each node matching PATH and its descendants to PORT. Limitation: PORT must be a stream port (such as a file or terminal); you can't write to a string port.

Example:

(aug-print a "/files/etc/hosts/1")
 ;; /files/etc/hosts/1
 ;; /files/etc/hosts/1/ipaddr = "127.0.0.1"
 ;; /files/etc/hosts/1/canonical = "localhost.localdomain"
 ;; /files/etc/hosts/1/alias[1] = "localhost"

Bugs and limitations

About this egg

Author

Jim Ursetto

Acknowledgements

Some documentation is cribbed from the Augeas API docs.

Version history

0.1
Initial release

Repository

https://github.com/ursetto/augeas

License

Copyright (c) 2012, Ursetto Consulting, Inc. MIT license.