Changeset 3701 for lang/perl/Archer

Show
Ignore:
Timestamp:
12/28/07 11:23:42 (11 months ago)
Author:
tokuhirom
Message:

r3654@mnk (orig r304): tokuhiro | 2007-03-05 21:15:30 -0800
apply franck's patch.


Files:
1 modified

Legend:

Unmodified
Added
Removed
  • lang/perl/Archer/lib/Archer/Shell.pm

    r3698 r3701  
    2020    my $HISTSIZE = 256; 
    2121 
    22         # this won't work with Term::ReadLine::Perl 
    23         # If there is Term::ReadLine::Gnu, be sure to do : export "PERL_RL=Gnu o=0" 
    24         eval { $term->stifle_history($HISTSIZE);}; 
    25          
    26         if (@!){ 
    27                 $self->{context}->log('debug' => "You will need Term::ReadLine::Gnu"); 
    28         }else{ 
    29         if (-f $HISTFILE) { 
    30                 $term->ReadHistory($HISTFILE) or $self->{context}->log('warn' => "cannot read history file: $!"); 
    31         } 
    32         } 
    33  
    34     while ( defined( my $line = $term->readline('archer> ') )) { 
     22   # this won't work with Term::ReadLine::Perl 
     23   # If there is Term::ReadLine::Gnu, be sure to do : export "PERL_RL=Gnu o=0" 
     24    eval { $term->stifle_history( $HISTSIZE ); }; 
     25 
     26    if ( @! ) { 
     27        $self->{ context }->log( 'debug' => "You will need Term::ReadLine::Gnu" ); 
     28    } else { 
     29        if ( -f $HISTFILE ) { 
     30            $term->ReadHistory( $HISTFILE ) 
     31                or $self->{ context }->log( 'warn' => "cannot read history file: $!" ); 
     32        } 
     33    } 
     34 
     35    while ( defined( my $line = $term->readline( 'archer> ' ) ) ) { 
    3536        next if $line =~ /^\s*$/; 
    36         $self->catch_run($line); 
     37        $self->catch_run( $line ); 
    3738    } 
    3839 
    3940    print "\n"; 
    4041 
    41         eval {$term->WriteHistory($HISTFILE);}; 
    42         if (@!){ 
    43                 $self->{context}->log('debug' => "perlsh: cannot write history file: $!"); 
    44         } 
     42    eval { $term->WriteHistory( $HISTFILE ); }; 
     43    if ( @! ) { 
     44        $self->{context}->log( 'debug' => "perlsh: cannot write history file: $!" ); 
     45    } 
    4546 
    4647} 
    4748 
    4849sub catch_run { 
    49     my ($self, $cmd) = @_; 
    50  
    51     my $parallel = $self->{context}->{config}->{global}->{parallel} 
     50    my ( $self, $cmd ) = @_; 
     51 
     52    $self->{ parallel } 
     53        = $self->{ context }->{ config }->{ global }->{ parallel } 
    5254        || 'Archer::Parallel::ForkManager'; 
    53     $parallel->use or die $@; 
    54  
    55     my $manager = $parallel->new; 
    56     $manager->run({ 
    57         elems => $self->{servers}, 
    58         callback => sub { 
    59             my $server = shift; 
    60             $self->callback($server, $cmd); 
    61         }, 
    62         num => $self->{context}->{parallel_num}, 
    63     }); 
     55    $self->{ parallel }->use or die $@; 
     56 
     57    if ( $cmd =~ /^on/ ) { 
     58        if ( $cmd =~ /^on\s(.*)\sdo\s(.*)$/ ) { 
     59            $self->process_host( $1, $2 ); 
     60        } else { 
     61            print "[WARNING] error in your syntax, see help\n"; 
     62        } 
     63    } elsif ( $cmd =~ /^with/ ) { 
     64        if ( $cmd =~ /^with\s(.*)\sdo\s(.*)$/ ) { 
     65            $self->process_role( $1, $2 ); 
     66        } else { 
     67            print "[WARNING] error in your syntax, see help\n"; 
     68        } 
     69    } elsif ( $cmd =~ /^help/ ) { 
     70        $self->help(); 
     71    } elsif ( $cmd =~ /^(quit|exit)/ ) { 
     72        print "bye bye\n"; 
     73        exit; 
     74    } elsif ( $cmd =~ /^!/ ) { 
     75        if ( $cmd =~ /^!(\w+)\s?(on|with)?\s?(.*)?$/ ) { 
     76            my $task     = $1; 
     77            my $action   = $2; 
     78            my $machines = $3; 
     79            if (    defined $action 
     80                 && defined $machines 
     81                 && length( $machines ) < 1 ) 
     82            { 
     83                return print "[WARNING] error in your syntax, see help\n"; 
     84            } 
     85            my $executed = 0; 
     86            for 
     87                my $plugin ( @{ $self->{ config }->{ tasks }->{ process } } ) 
     88            { 
     89                next if $plugin->{ name } ne $task; 
     90                $executed = 1; 
     91                if ( defined $action ) { 
     92                    if ( $action eq "on" ) { 
     93                        my @hosts = split " ", $machines; 
     94                        for my $host ( @hosts ) { 
     95                            $self->process_task( $plugin, $host ); 
     96                        } 
     97                    } else { 
     98                        my @roles = split " ", $machines; 
     99                        for my $role ( @roles ) { 
     100                            for my $host ( 
     101                                          @{ $self->{ servers }->{ $role } } ) 
     102                            { 
     103                                $self->process_task( $plugin, $host ); 
     104                            } 
     105                        } 
     106                    } 
     107                } else { 
     108                    for my $host ( 
     109                                   @{  $self->{ servers } 
     110                                           ->{ $plugin->{ config }->{ role } } 
     111                                   } ) 
     112                    { 
     113                        $self->process_task( $plugin, $host ); 
     114                    } 
     115                } 
     116            } 
     117            if ( $executed == 0 ) { 
     118                print "[WARNING] unable to find the requested task: $task\n"; 
     119            } 
     120        } else { 
     121            print "[WARNING] error in your syntax\n"; 
     122        } 
     123    } else { 
     124        $self->process_command( $cmd ); 
     125    } 
     126} 
     127 
     128sub process_host { 
     129    my ( $self, $hosts, $cmd ) = @_; 
     130 
     131    my @hosts = split /\s/, $hosts; 
     132 
     133    # check if hosts are in our config. 
     134    for my $host ( @hosts ) { 
     135        for my $role ( keys %{ $self->{ servers } } ) { 
     136            @hosts = grep ( /$host/, @{ $self->{ servers }->{ $role } } ); 
     137        } 
     138    } 
     139 
     140    if ( @hosts ) { 
     141        $self->process_command( $cmd, \@hosts ); 
     142    } 
     143} 
     144 
     145sub process_role { 
     146    my ( $self, $roles, $cmd ) = @_; 
     147 
     148    my @roles      = split /\s/, $roles; 
     149    my @hosts      = (); 
     150    my @inexistant = (); 
     151    for my $role ( @roles ) { 
     152        if ( !defined $self->{ servers }->{ $role } ) { 
     153            push( @inexistant, $role ); 
     154            next; 
     155        } 
     156        for my $host ( @{ $self->{ servers }->{ $role } } ) { 
     157            push @hosts, $host; 
     158        } 
     159    } 
     160    if ( @inexistant ) { 
     161        print "[WARNING] inexisting role(s) for " 
     162            . join( ' ', @inexistant ) . "\n"; 
     163    } 
     164    $self->process_command( $cmd, \@hosts ); 
     165} 
     166 
     167sub process_command { 
     168    my ( $self, $cmd, $hosts ) = @_; 
     169    my $manager = $self->{parallel}->new; 
     170 
     171    if ( !$hosts ) { 
     172        for my $role ( 
     173            keys 
     174            %{ $self->{config}->{projects}->{ $self->{context}->{project} } } 
     175            ) 
     176        { 
     177            for my $host ( 
     178                @{  $self->{config}->{projects} 
     179                        ->{ $self->{context}->{project} }->{$role} 
     180                } 
     181                ) 
     182            { 
     183                push @{$hosts}, $host; 
     184            } 
     185        } 
     186    } 
     187 
     188    $manager->run( 
     189        {   elems    => $hosts, 
     190            callback => sub { 
     191                my $server = shift; 
     192                $self->callback( $server, $cmd ); 
     193            }, 
     194            num => $self->{context}->{parallel_num}, 
     195        } 
     196    ); 
     197} 
     198 
     199sub process_task { 
     200    my ( $self, $plugin, $host ) = @_; 
     201    my $class = "Archer::Plugin::$plugin->{module}"; 
     202    $class->use or die $@; 
     203    $class->new( { config  => $plugin->{ config }, 
     204                   project => $self->{ context }->{ project }, 
     205                   server  => $host 
     206                 } )->run( $self->{ context } ); 
    64207} 
    65208 
     
    76219} 
    77220 
     221sub help { 
     222    my ( $self ) = @_; 
     223    my $help = <<HELP; 
     224 To quit, just type quit, exit, or press ctrl-D.  
     225 This shell is still experimental. 
     226 
     227 execute a command on all servers, just type it directly, like: 
     228 
     229archer> ping 
     230 
     231 To execute a command on a specific set of servers, specify an 'on' clause. 
     232 Note that if you specify more than one host name, they must be  
     233 space-delimited. 
     234 
     235archer> on app1.foo.com app2.foo.com do ping 
     236 
     237 To execute a command on all servers matching a set of roles: 
     238 
     239archer> with web db do ping 
     240 
     241 To execute an Archer task, prefix the name with a bang, by default it 
     242 will be executed only on the role applyed to this task. 
     243 
     244archer> !restart 
     245 
     246 To execute an Archer task on a specific set of servers: 
     247 
     248archer> !restart on app1.foo.com app2.foo.com 
     249 
     250 To execute an Archer task on all servers matching a set of roles: 
     251 
     252archer> !restart with web db 
     253 
     254HELP 
     255    print $help; 
     256} 
     257 
    782581; 
    79259__END__