# Copyright (c) 2008-2009 Dominique Dumont. # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser Public License as # published by the Free Software Foundation; either version 2.1 of # the License, or (at your option) any later version. # # Config-Model is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser Public License for more details. # # You should have received a copy of the GNU Lesser Public License # along with Config-Model; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA package Config::Augeas; use strict; use warnings; use Carp; use IO::File ; our $VERSION = '0.501'; require XSLoader; XSLoader::load('Config::Augeas', $VERSION); =head1 NAME Config::Augeas - Edit configuration files through Augeas C library =head1 SYNOPSIS use Config::Augeas; my $aug = Config::Augeas->new( root => $aug_root ) ; my $ret = $aug->get("/files/etc/hosts/1/ipaddr") ; $aug->set("/files/etc/hosts/2/ipaddr","192.168.0.1") ; my @a = $aug->match("/files/etc/hosts/") ; my $nb = $aug->count_match("/files/etc/hosts/") ; $aug->save ; =head1 DESCRIPTION =for comment Description snatched from Augeas README Augeas is a library and command line tool that focuses on the most basic problem in handling Linux configurations programmatically: editing actual configuration files in a controlled manner. To that end, Augeas exposes a tree of all configuration settings (well, all the ones it knows about) and a simple local API for manipulating the tree. Augeas then modifies underlying configuration files according to the changes that have been made to the tree; it does as little modeling of configurations as possible, and focuses exclusively on transforming the tree-oriented syntax of its public API to the myriad syntaxes of individual configuration files. This module provides an object oriented Perl interface for Augeas configuration edition library with a more "perlish" API than Augeas C counterpart. =head1 Constructor =head1 new ( ... ) Creates a new Config::Augeas object. Optional parameters are: =over =item loadpath a colon-spearated list of directories that lenses should be searched in. This is in addition to the standard load path and the directories in specified C environment variable. =item root Use C as the filesystem root. If not specified, use the value of the environment variable C. If that doesn't exist either, use "C". =item save => backup | newfile | noop Specify how to save the configuration file. Either create a newfile (with extension C<.augnew>, and do not overwrite the original file) or move the original file into a backup file (C<.augsave> extension). C make saves a no-op process, just record what would have changed =item type_check => 1 Typecheck lenses; since it can be very expensive it is not done by default. =item no_std_inc Do not use the builtin load path for modules =item no_load Do not load the tree from AUG_INIT =back =cut sub new { my $type = shift ; my $self = {} ; my %args = @_ ; my $flags = 0 ; my $loadpath = delete $args{loadpath} || ''; my $root = delete $args{root} || ''; my $save = delete $args{save} || ''; if ($save eq 'backup') { $flags ||= &AUG_SAVE_BACKUP } elsif ($save eq 'newfile') { $flags ||= &AUG_SAVE_NEWFILE } elsif ($save =~ 'noop') { $flags ||= &AUG_SAVE_NOOP } elsif ($save) { croak __PACKAGE__," new: unexpected save value: $save. ", "Expected backup or newfile"; } $flags ||= &AUG_TYPE_CHECK if ( delete $args{type_check} || 0 ); $flags ||= &AUG_NO_STDINC if ( delete $args{no_std_inc} || 0 ) ; $flags ||= &AUG_NO_LOAD if ( delete $args{no_load} || 0 ) ; croak __PACKAGE__," new: unexpected parameters: ", join (' ',keys %args) if %args ; $self->{aug_c} = Config::Augeas::init($root,$loadpath,$flags) ; bless $self,$type ; return $self } =head1 Methods =head2 defvar( name, [ expr ]) Define a variable C whose value is the result of evaluating C. If a variable C already exists, its name will be replaced with the result of evaluating C. If C is omitted, the variable C will be removed if it is defined. Path variables can be used in path expressions later on by prefixing them with '$'. Returns -1 on error; on success, returns 0 if C evaluates to anything other than a nodeset, and the number of nodes if C evaluates to a nodeset =cut sub defvar { my $self = shift ; my $name = shift || croak __PACKAGE__," defvar: undefined name"; my $expr = shift || 0 ; return $self->{aug_c} -> defvar($name, $expr) ; } =head2 defnode ( name, expr, value ) Define a variable C whose value is the result of evaluating C, which must evaluate to a nodeset. If a variable C already exists, its name will be replaced with the result of evaluating C. If C evaluates to an empty nodeset, a node is created, equivalent to calling C and C will be the nodeset containing that single node. Returns undef on error Returns an array containing: =over =item * the number of nodes in the nodeset =item * 1 if a node was created, and 0 if it already existed. =back =cut sub defnode { my $self = shift ; my $name = shift || croak __PACKAGE__," defnode: undefined name"; my $expr = shift || croak __PACKAGE__," defnode: undefined expr"; my $value = shift || croak __PACKAGE__," defnode: undefined value"; return ($self->{aug_c} -> defnode($name, $expr, $value)) ; } =head2 get( path ) Lookup the value associated with C. Returns the value associated with C if C matches exactly one node. If PATH matches no nodes or more than one node, returns undef. =cut sub get { my $self = shift ; my $path = shift || croak __PACKAGE__," get: undefined path"; return $self->{aug_c} -> get($path) ; } =head2 set ( path, value ) Set the value associated with C to C. C is copied into Augeas internal data structure. Intermediate entries are created if they don't exist. Return 1 on success, 0 on error. It is an error if more than one node matches C. =cut sub set { my $self = shift ; my $path = shift || croak __PACKAGE__," set: undefined path"; my $value = shift ; croak __PACKAGE__," set: undefined value" unless defined $value; my $result ; my $ret = $self->{aug_c} -> set($path,$value) ; return 1 if $ret == 0; $self -> print('/augeas') ; croak __PACKAGE__," set: error with path $path"; } =head2 insert ( label, before | after , path ) Create a new sibling C