Net::LDAP::Batch - perform a batch of LDAP actions


Net-LDAP-Batch documentation Contained in the Net-LDAP-Batch distribution.

Index


Code Index:

NAME

Top

Net::LDAP::Batch - perform a batch of LDAP actions

SYNOPSIS

Top

 use Net::LDAP::Batch;

 my $BaseDN = 'ou=People,dc=MyDomain';
 my $ldap   = make_and_bind_Net_LDAP_object();  # you write this

 my $batch = Net::LDAP::Batch->new( ldap => $ldap );
 $batch->add_actions(
    add => [
        {
            dn      => "cn=MyGroup,ou=Group,$BaseDN",
            attr    => [
                objectClass => [ 'top', 'posixGroup' ],
                cn          => 'MyGroup',
                gidNumber   => '1234'
            ]
        }
    ],
    delete => [
        {
            search  => [
                base    => "ou=Group,$BaseDN",
                scope   => 'sub',
                filter  => "(cn=MyOldGroup)"
            ]
        }
    ],
    update => [
        {
            search  => [
                base    => "ou=Group,$BaseDN",
                scope   => 'sub',
                filter  => "(cn=OtherGroup)"
            ],
            replace => { gidNumber => '5678' },
            delete  => { foo => [ 'bar' ] },
        }
    ]
 );

 $batch->do or die $batch->error;

DESCRIPTION

Top

Net::LDAP::Batch performs a series of actions against a LDAP server. If any of the actions fails, then all the actions in the batch are reverted.

Be advised: This is not a true ACID-compliant transaction feature, since no locking is performed. Instead it is simply a way to execute a series of actions without having to worry about checking return values, or error codes, or un-doing the changes should any of them fail. Of course, since no ACID compliance is claimed, anything could (and likely will) happen if there is more than one client attempting to make changes on the same server at the same time. You have been warned.

METHODS

Top

new

Create a batch instance.

You must pass in a valid Net::LDAP object that has already been bound to the server with whatever credentials are necessary to complete the actions you will specify.

You may optionally pass in an array ref of actions. See also the add_actions() method.

actions

Get the array ref of Net::LDAP::Batch::Action objects in the batch. To set the array, use add_actions().

add_actions( actions )

Set the array of actions to be executed. actions may be either an array or array ref, and may either be key/value pairs as in the SYNOPSIS or Net::LDAP::Batch::Action objects. You may not mix the two types of values.

Returns the total number of actions in batch.

clear_actions

Sets the number of actions to zero. Returns the former contents of actions().

do

Perform the actions and rollback() if any are fatal. Same thing as calling:

 eval { $batch->execute };
 if ($@) {
     warn "batch failed: $@";
     $batch->rollback;  # could be fatal
 }

The code above is nearly verbatim what do() actually does.

execute

Calls execute() method on each action.

rollback

Calls rollback() method on each action.

AUTHOR

Top

Peter Karman, <karman at cpan.org>

BUGS

Top

Please report any bugs or feature requests to bug-net-ldap-batch at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Net-LDAP-Batch. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

SUPPORT

Top

You can find documentation for this module with the perldoc command.

    perldoc Net::LDAP::Batch

You can also look for information at:

* AnnoCPAN: Annotated CPAN documentation

http://annocpan.org/dist/Net-LDAP-Batch

* CPAN Ratings

http://cpanratings.perl.org/d/Net-LDAP-Batch

* RT: CPAN's request tracker

http://rt.cpan.org/NoAuth/Bugs.html?Dist=Net-LDAP-Batch

* Search CPAN

http://search.cpan.org/dist/Net-LDAP-Batch

ACKNOWLEDGEMENTS

Top

The Minnesota Supercomputing Institute http://www.msi.umn.edu/ sponsored the development of this software.

COPYRIGHT

Top

SEE ALSO

Top

Net::LDAP


Net-LDAP-Batch documentation Contained in the Net-LDAP-Batch distribution.
package Net::LDAP::Batch;
use strict;
use warnings;
use Carp;
use Data::Dump qw( dump );
use base qw( Class::Accessor::Fast );
__PACKAGE__->mk_accessors(qw( ldap debug ));
__PACKAGE__->mk_ro_accessors(qw( actions error ));
use Net::LDAP::Batch::Action::Add;
use Net::LDAP::Batch::Action::Update;
use Net::LDAP::Batch::Action::Delete;
use Scalar::Util qw( blessed );

our $VERSION = '0.02';

sub new {
    my $class = shift;
    my $opts  = ref( $_[0] ) ? $_[0] : {@_};
    my $self  = $class->SUPER::new($opts);
    $self->_setup;
    return $self;
}

sub _setup {
    my $self = shift;
    if ( $self->{actions} ) {
        my $actions = $self->clear_actions;
        $self->add_actions($actions);
    }
    $self->debug( $ENV{PERL_DEBUG} ) unless defined $self->debug;
}

my %action_classes = (
    'add'    => 'Net::LDAP::Batch::Action::Add',
    'update' => 'Net::LDAP::Batch::Action::Update',
    'delete' => 'Net::LDAP::Batch::Action::Delete',
);

sub add_actions {
    my $self = shift;
    my @arg;
    if ( @_ == 1 && ref( $_[0] ) eq 'ARRAY' ) {
        @arg = @{ $_[0] };
    }
    else {
        @arg = @_;
    }

    if ( blessed( $arg[0] ) && $arg[0]->isa('Net::LDAP::Batch::Action') ) {
        push( @{ $self->{actions} }, @arg );
    }
    else {
        if ( @arg % 2 ) {
            croak "uneven number of action key/value pairs";
        }
        while ( scalar(@arg) ) {
            my $what = shift(@arg);
            my $todo = shift(@arg);
            if ( !exists $action_classes{$what} ) {
                croak "unsupported action: $what";
            }
            my $class = $action_classes{$what};
            my @todo;
            if ( ref($todo) eq 'ARRAY' ) {
                @todo = @$todo;
            }
            else {
                @todo = ($todo);
            }
            for my $params (@todo) {
                $params->{ldap}  = $self->ldap;
                $params->{debug} = $self->debug;
                push( @{ $self->{actions} }, $class->new($params) );
            }
        }
    }
    return scalar( @{ $self->{actions} } );
}

sub clear_actions {
    my $self    = shift;
    my $actions = $self->{actions};
    $self->{actions} = [];
    return $actions;
}

sub do {
    my $self = shift;
    eval { $self->execute };
    if ($@) {
        $self->{error} = $@;
        $self->rollback;
        return 0;
    }
    return 1;
}

sub execute {
    my $self = shift;
    if ( !$self->actions or !scalar( @{ $self->actions } ) ) {
        croak "no actions to execute";
    }
    for my $action ( @{ $self->actions } ) {
        warn "executing $action\n" if $self->debug;
        $action->execute;
    }
    return 1;
}

sub rollback {
    my $self = shift;
    if ( !$self->actions or !scalar( @{ $self->actions } ) ) {
        croak "no actions to rollback";
    }
    for my $action ( reverse @{ $self->actions } ) {
        next unless $action->complete;
        warn "rolling back $action\n" if $self->debug;
        $action->rollback;
    }
    return 1;
}

1;

__END__