Rex
view release on metacpan or search on metacpan
lib/Rex/Task.pm view on Meta::CPAN
=head1 SYNOPSIS
use Rex::Task;
# create a new task
my $task = Rex::Task->new( name => 'testtask' );
$task->set_server('remoteserver');
$task->set_code( sub { say 'Hello'; } );
$task->modify( 'no_ssh', 1 );
# retrieve an existing task
use Rex::TaskList;
my $existing_task = Rex::TaskList->create->get_task('my_task');
=head1 METHODS
=cut
package Rex::Task;
use v5.14.4;
use warnings;
use Data::Dumper;
use Time::HiRes qw(time);
our $VERSION = '1.16.1'; # VERSION
use Rex::Logger;
use Rex::TaskList;
use Rex::Interface::Connection;
use Rex::Interface::Executor;
use Rex::Group::Entry::Server;
use Rex::Profiler;
use Rex::Hardware;
use Rex::Interface::Cache;
use Rex::Report;
use Rex::Helper::Run;
use Rex::Helper::Path;
use Rex::Notify;
use Carp;
require Rex::Commands;
require Rex::Args;
=head2 new
This is the constructor.
$task = Rex::Task->new(
func => sub { some_code_here },
server => [ @server ],
desc => $description,
no_ssh => $no_ssh,
hidden => $hidden,
auth => {
user => $user,
password => $password,
private_key => $private_key,
public_key => $public_key,
},
before => [sub {}, sub {}, ...],
after => [sub {}, sub {}, ...],
around => [sub {}, sub {}, ...],
before_task_start => [sub {}, sub {}, ...],
after_task_finished => [sub {}, sub {}, ...],
name => $task_name,
executor => Rex::Interface::Executor->create,
opts => {key1 => val1, key2 => val2, ...},
args => [arg1, arg2, ...],
);
=cut
sub new {
my $that = shift;
my $proto = ref($that) || $that;
my $self = {@_};
bless( $self, $proto );
if ( !exists $self->{name} ) {
die("You have to define a task name.");
}
$self->{no_ssh} ||= 0;
$self->{func} ||= sub { };
$self->{executor} ||= Rex::Interface::Executor->create;
$self->{opts} ||= {};
$self->{args} ||= [];
$self->{connection} = undef;
# set to true as default
if ( !exists $self->{exit_on_connect_fail} ) {
$self->{exit_on_connect_fail} = 1;
}
return $self;
}
=head2 connection
Returns the current connection object.
=cut
sub connection {
my ($self) = @_;
if ( !exists $self->{connection} || !$self->{connection} ) {
$self->{connection} =
Rex::Interface::Connection->create( $self->get_connection_type );
}
$self->{connection};
}
sub set_connection {
my ( $self, $conn ) = @_;
$self->{connection} = $conn;
}
=head2 executor
Returns the current executor object.
=cut
sub executor {
my ($self) = @_;
$self->{executor}->set_task($self);
return $self->{executor};
}
=head2 hidden
Returns true if the task is hidden. (Should not be displayed on ,,rex -T''.)
=cut
sub hidden {
my ($self) = @_;
return $self->{hidden};
}
=head2 server
Returns the servers on which the task should be executed as an ArrayRef.
=cut
sub server {
my ($self) = @_;
my @server = @{ $self->{server} };
my @ret = ();
if ( ref( $server[-1] ) eq "HASH" ) {
Rex::deprecated(
undef, "0.40",
"Defining extra credentials within the task creation is deprecated.",
"Please use set auth => task => 'taskname' instead."
);
# use extra defined credentials
my $data = pop(@server);
$self->set_auth( "user", $data->{'user'} );
$self->set_auth( "password", $data->{'password'} );
if ( exists $data->{"private_key"} ) {
$self->set_auth( "private_key", $data->{"private_key"} );
$self->set_auth( "public_key", $data->{"public_key"} );
}
}
if ( ref( $self->{server} ) eq "ARRAY"
&& scalar( @{ $self->{server} } ) > 0 )
{
for my $srv ( @{ $self->{server} } ) {
if ( ref($srv) eq "CODE" ) {
push( @ret, &$srv() );
}
else {
if ( ref $srv && $srv->isa("Rex::Group::Entry::Server") ) {
push( @ret, $srv->get_servers );
}
else {
push( @ret, $srv );
}
}
}
}
elsif ( ref( $self->{server} ) eq "CODE" ) {
push( @ret, &{ $self->{server} }() );
}
else {
push( @ret, Rex::Group::Entry::Server->new( name => "<local>" ) );
}
return [@ret];
}
=head2 set_server(@server)
With this method you can set new servers on which the task should be executed on.
=cut
sub set_server {
my ( $self, @server ) = @_;
$self->{server} = \@server;
}
=head2 delete_server
Delete every server registered to the task.
=cut
sub delete_server {
my ($self) = @_;
delete $self->{current_server};
delete $self->{server};
$self->rethink_connection;
}
=head2 current_server
Returns the current server on which the tasks gets executed right now.
=cut
lib/Rex/Task.pm view on Meta::CPAN
sub parallelism {
my ($self) = @_;
return $self->{parallelism};
}
=head2 set_parallelism($count)
Set the parallelism of the task.
=cut
sub set_parallelism {
my ( $self, $para ) = @_;
$self->{parallelism} = $para;
}
=head2 connect($server)
Initiate the connection to $server.
=cut
sub connect {
my ( $self, $server, %override ) = @_;
if ( !ref $server ) {
$server = Rex::Group::Entry::Server->new( name => $server );
}
$self->{current_server} = $server;
$self->run_hook( \$server, "before" );
# need to be called, in case of a run_task task call.
# see #788
$self->rethink_connection;
my $user = $self->user;
#print Dumper($self);
my $auth = $self->merge_auth($server);
if ( exists $override{auth} ) {
$auth = $override{auth};
$user = $auth->{user};
}
my $rex_int_conf = Rex::Commands::get("rex_internals");
Rex::Logger::debug( Dumper($rex_int_conf) );
Rex::Logger::debug("Auth-Information inside Task:");
for my $key ( keys %{$auth} ) {
my $data = $auth->{$key};
$data = Rex::Logger::masq( "%s", $data ) if $key eq 'password';
$data = Rex::Logger::masq( "%s", $data ) if $key eq 'sudo_password';
$data ||= "";
Rex::Logger::debug("$key => [[$data]]");
}
$auth->{public_key} = resolv_path( $auth->{public_key}, 1 )
if ( $auth->{public_key} );
$auth->{private_key} = resolv_path( $auth->{private_key}, 1 )
if ( $auth->{private_key} );
my $profiler = Rex::Profiler->new;
# task specific auth rules over all
my %connect_hash = %{$auth};
$connect_hash{server} = $server;
# need to get rid of this
Rex::push_connection(
{
conn => $self->connection,
ssh => $self->connection->get_connection_object,
server => $server,
cache => Rex::Interface::Cache->create(),
task => [],
profiler => $profiler,
reporter => Rex::Report->create( Rex::Config->get_report_type ),
notify => Rex::Notify->new(),
}
);
push @{ Rex::get_current_connection()->{task} }, $self;
$profiler->start("connect");
eval {
$self->connection->connect(%connect_hash);
1;
} or do {
if ( !defined Rex::Config->get_fallback_auth ) {
croak $@;
}
};
$profiler->end("connect");
if ( !$self->connection->is_connected ) {
Rex::pop_connection();
croak("Couldn't connect to $server.");
}
elsif ( !$self->connection->is_authenticated ) {
Rex::pop_connection();
my $message =
"Couldn't authenticate against $server. It may be caused by one or more of:\n";
$message .= " - wrong username, password, key or passphrase\n";
$message .= " - changed remote host key\n";
$message .= " - root is not permitted to login over SSH\n"
if ( $connect_hash{user} eq 'root' );
if ( !exists $override{auth} ) {
my $fallback_auth = Rex::Config->get_fallback_auth;
if ( ref $fallback_auth eq "ARRAY" ) {
my $ret_eval;
for my $fallback_a ( @{$fallback_auth} ) {
$ret_eval = eval { $self->connect( $server, auth => $fallback_a ); };
}
return $ret_eval if $ret_eval;
}
}
croak($message);
( run in 0.561 second using v1.01-cache-2.11-cpan-524268b4103 )