File Coverage

lib/Rex/Task.pm
Criterion Covered Total %
statement 286 359 79.6
branch 82 124 66.1
condition 50 70 71.4
subroutine 58 68 85.2
pod 48 50 96.0
total 524 671 78.0


line stmt bran cond sub pod time code
1             #
2             # (c) Jan Gehring
3             #
4              
5             =head1 NAME
6              
7             Rex::Task - The Task Object
8              
9             =head1 DESCRIPTION
10              
11             The Task Object. Typically you only need this class if you want to manipulate tasks after their initial creation.
12              
13             =head1 SYNOPSIS
14              
15             use Rex::Task;
16              
17             # create a new task
18             my $task = Rex::Task->new( name => 'testtask' );
19             $task->set_server('remoteserver');
20             $task->set_code( sub { say 'Hello'; } );
21             $task->modify( 'no_ssh', 1 );
22              
23             # retrieve an existing task
24             use Rex::TaskList;
25              
26             my $existing_task = Rex::TaskList->create->get_task('my_task');
27              
28             =head1 METHODS
29              
30             =cut
31              
32             package Rex::Task;
33              
34 56     56   69689 use v5.12.5;
  56         319  
35 56     56   417 use warnings;
  56         167  
  56         1527  
36 56     56   994 use Data::Dumper;
  56         7376  
  56         2655  
37 56     56   933 use Time::HiRes qw(time);
  56         1764  
  56         736  
38              
39             our $VERSION = '1.14.2.3'; # TRIAL VERSION
40              
41 56     56   9092 use Rex::Logger;
  56         267  
  56         449  
42 56     56   1857 use Rex::TaskList;
  56         189  
  56         507  
43 56     56   2395 use Rex::Interface::Connection;
  56         193  
  56         754  
44 56     56   1514 use Rex::Interface::Executor;
  56         192  
  56         591  
45 56     56   2442 use Rex::Group::Entry::Server;
  56         149  
  56         1401  
46 56     56   2355 use Rex::Profiler;
  56         159  
  56         686  
47 56     56   1733 use Rex::Hardware;
  56         131  
  56         554  
48 56     56   1706 use Rex::Interface::Cache;
  56         153  
  56         575  
49 56     56   1409 use Rex::Report;
  56         161  
  56         481  
50 56     56   1283 use Rex::Helper::Run;
  56         146  
  56         4039  
51 56     56   387 use Rex::Helper::Path;
  56         149  
  56         3864  
52 56     56   404 use Rex::Notify;
  56         134  
  56         522  
53 56     56   1530 use Carp;
  56         190  
  56         236842  
54              
55             require Rex::Commands;
56              
57             require Rex::Args;
58              
59             =head2 new
60              
61             This is the constructor.
62              
63             $task = Rex::Task->new(
64             func => sub { some_code_here },
65             server => [ @server ],
66             desc => $description,
67             no_ssh => $no_ssh,
68             hidden => $hidden,
69             auth => {
70             user => $user,
71             password => $password,
72             private_key => $private_key,
73             public_key => $public_key,
74             },
75             before => [sub {}, sub {}, ...],
76             after => [sub {}, sub {}, ...],
77             around => [sub {}, sub {}, ...],
78             before_task_start => [sub {}, sub {}, ...],
79             after_task_finished => [sub {}, sub {}, ...],
80             name => $task_name,
81             executor => Rex::Interface::Executor->create,
82             opts => {key1 => val1, key2 => val2, ...},
83             args => [arg1, arg2, ...],
84             );
85              
86             =cut
87              
88             sub new {
89 245     245 1 23300 my $that = shift;
90 245   33     1760 my $proto = ref($that) || $that;
91 245         2043 my $self = {@_};
92              
93 245         911 bless( $self, $proto );
94              
95 245 50       1227 if ( !exists $self->{name} ) {
96 0         0 die("You have to define a task name.");
97             }
98              
99 245   100     1815 $self->{no_ssh} ||= 0;
100 245   100 0   839 $self->{func} ||= sub { };
101 245   66     1183 $self->{executor} ||= Rex::Interface::Executor->create;
102 245   100     1568 $self->{opts} ||= {};
103 245   100     1134 $self->{args} ||= [];
104              
105 245         750 $self->{connection} = undef;
106              
107             # set to true as default
108 245 100       727 if ( !exists $self->{exit_on_connect_fail} ) {
109 33         265 $self->{exit_on_connect_fail} = 1;
110             }
111              
112 245         2204 return $self;
113             }
114              
115             =head2 connection
116              
117             Returns the current connection object.
118              
119             =cut
120              
121             sub connection {
122 260     260 1 669 my ($self) = @_;
123 260 100 100     1754 if ( !exists $self->{connection} || !$self->{connection} ) {
124             $self->{connection} =
125 40         544 Rex::Interface::Connection->create( $self->get_connection_type );
126             }
127              
128 260         1809 $self->{connection};
129             }
130              
131             sub set_connection {
132 7     7 0 34 my ( $self, $conn ) = @_;
133 7         26 $self->{connection} = $conn;
134             }
135              
136             =head2 executor
137              
138             Returns the current executor object.
139              
140             =cut
141              
142             sub executor {
143 54     54 1 284 my ($self) = @_;
144 54         2910 $self->{executor}->set_task($self);
145 54         825 return $self->{executor};
146             }
147              
148             =head2 hidden
149              
150             Returns true if the task is hidden. (Should not be displayed on ,,rex -T''.)
151              
152             =cut
153              
154             sub hidden {
155 60     60 1 113 my ($self) = @_;
156 60         248 return $self->{hidden};
157             }
158              
159             =head2 server
160              
161             Returns the servers on which the task should be executed as an ArrayRef.
162              
163             =cut
164              
165             sub server {
166 292     292 1 3073 my ($self) = @_;
167              
168 292         559 my @server = @{ $self->{server} };
  292         1026  
169 292         592 my @ret = ();
170              
171 292 50       1107 if ( ref( $server[-1] ) eq "HASH" ) {
172 0         0 Rex::deprecated(
173             undef, "0.40",
174             "Defining extra credentials within the task creation is deprecated.",
175             "Please use set auth => task => 'taskname' instead."
176             );
177              
178             # use extra defined credentials
179 0         0 my $data = pop(@server);
180 0         0 $self->set_auth( "user", $data->{'user'} );
181 0         0 $self->set_auth( "password", $data->{'password'} );
182              
183 0 0       0 if ( exists $data->{"private_key"} ) {
184 0         0 $self->set_auth( "private_key", $data->{"private_key"} );
185 0         0 $self->set_auth( "public_key", $data->{"public_key"} );
186             }
187             }
188              
189 292 100 66     1815 if ( ref( $self->{server} ) eq "ARRAY"
    50          
190 292         2052 && scalar( @{ $self->{server} } ) > 0 )
191             {
192 18         36 for my $srv ( @{ $self->{server} } ) {
  18         51  
193 30 100       78 if ( ref($srv) eq "CODE" ) {
194 1         5 push( @ret, &$srv() );
195             }
196             else {
197 29 100 66     185 if ( ref $srv && $srv->isa("Rex::Group::Entry::Server") ) {
198 28         86 push( @ret, $srv->get_servers );
199             }
200             else {
201 1         4 push( @ret, $srv );
202             }
203             }
204             }
205             }
206             elsif ( ref( $self->{server} ) eq "CODE" ) {
207 0         0 push( @ret, &{ $self->{server} }() );
  0         0  
208             }
209             else {
210 274         3870 push( @ret, Rex::Group::Entry::Server->new( name => "" ) );
211             }
212              
213 292         1404 return [@ret];
214             }
215              
216             =head2 set_server(@server)
217              
218             With this method you can set new servers on which the task should be executed on.
219              
220             =cut
221              
222             sub set_server {
223 1     1 1 5 my ( $self, @server ) = @_;
224 1         5 $self->{server} = \@server;
225             }
226              
227             =head2 delete_server
228              
229             Delete every server registered to the task.
230              
231             =cut
232              
233             sub delete_server {
234 1     1 1 3 my ($self) = @_;
235 1         9 delete $self->{current_server};
236 1         5 delete $self->{server};
237 1         5 $self->rethink_connection;
238             }
239              
240             =head2 current_server
241              
242             Returns the current server on which the tasks gets executed right now.
243              
244             =cut
245              
246             sub current_server {
247 2     2 1 3 my ($self) = @_;
248             return $self->{current_server}
249 2   66     20 || Rex::Group::Entry::Server->new( name => "" );
250             }
251              
252             =head2 desc
253              
254             Returns the description of a task.
255              
256             =cut
257              
258             sub desc {
259 2     2 1 5 my ($self) = @_;
260 2         11 return $self->{desc};
261             }
262              
263             =head2 set_desc($description)
264              
265             Set the description of a task.
266              
267             =cut
268              
269             sub set_desc {
270 1     1 1 4 my ( $self, $desc ) = @_;
271 1         3 $self->{desc} = $desc;
272             }
273              
274             =head2 is_remote
275              
276             Returns true (1) if the task will be executed remotely.
277              
278             =cut
279              
280             sub is_remote {
281 142     142 1 1447 my ($self) = @_;
282 142 100       491 if ( exists $self->{current_server} ) {
283 118 100       496 if ( $self->{current_server} ne '' ) {
284 14         75 return 1;
285             }
286             }
287             else {
288 24 100 100     111 if ( exists $self->{server} && scalar( @{ $self->{server} } ) > 0 ) {
  17         64  
289 14         48 return 1;
290             }
291             }
292              
293 114         1585 return 0;
294             }
295              
296             =head2 is_local
297              
298             Returns true (1) if the task gets executed on the local host.
299              
300             =cut
301              
302             sub is_local {
303 5     5 1 17 my ($self) = @_;
304 5 100       13 return $self->is_remote() == 0 ? 1 : 0;
305             }
306              
307             =head2 is_http
308              
309             Returns true (1) if the task gets executed over http protocol.
310              
311             =cut
312              
313             sub is_http {
314 46     46 1 223 my ($self) = @_;
315             return ( $self->{"connection_type"}
316 46   66     1095 && lc( $self->{"connection_type"} ) eq "http" );
317             }
318              
319             =head2 is_https
320              
321             Returns true (1) if the task gets executed over https protocol.
322              
323             =cut
324              
325             sub is_https {
326 46     46 1 180 my ($self) = @_;
327             return ( $self->{"connection_type"}
328 46   66     894 && lc( $self->{"connection_type"} ) eq "https" );
329             }
330              
331             =head2 is_openssh
332              
333             Returns true (1) if the task gets executed with openssh.
334              
335             =cut
336              
337             sub is_openssh {
338 10     10 1 19 my ($self) = @_;
339             return ( $self->{"connection_type"}
340 10   66     56 && lc( $self->{"connection_type"} ) eq "openssh" );
341             }
342              
343             =head2 want_connect
344              
345             Returns true (1) if the task will establish a connection to a remote system.
346              
347             =cut
348              
349             sub want_connect {
350 14     14 1 815 my ($self) = @_;
351 14 100       76 return $self->{no_ssh} == 0 ? 1 : 0;
352             }
353              
354             =head2 get_connection_type
355              
356             This method tries to guess the right connection type for the task and returns it.
357              
358             Current return values are below:
359              
360             =over 4
361              
362             =item * SSH: connect to the remote server using Net::SSH2
363              
364             =item * OpenSSH: connect to the remote server using Net::OpenSSH
365              
366             =item * Local: runs locally (without any connections)
367              
368             =item * HTTP: uses experimental HTTP connection
369              
370             =item * HTTPS: uses experimental HTTPS connection
371              
372             =item * Fake: populate the connection properties, but do not connect
373              
374             So you can use this type to iterate over a list of remote hosts, but don't let rex build a connection. For example if you want to use Sys::Virt or other modules.
375              
376             =back
377              
378             =cut
379              
380             sub get_connection_type {
381 46     46 1 692 my ($self) = @_;
382              
383 46 50 100     345 if ( $self->is_http ) {
    50 66        
    50 100        
    100          
    100          
384 0         0 return "HTTP";
385             }
386             elsif ( $self->is_https ) {
387 0         0 return "HTTPS";
388             }
389             elsif ( $self->is_remote && $self->is_openssh && $self->want_connect ) {
390 0         0 return "OpenSSH";
391             }
392             elsif ( $self->is_remote && $self->want_connect ) {
393 5         39 return Rex::Config->get_connection_type();
394             }
395             elsif ( $self->is_remote ) {
396 5         49 return "Fake";
397             }
398             else {
399 36         1064 return "Local";
400             }
401             }
402              
403             =head2 modify($key, $value)
404              
405             With this method you can modify values of the task.
406              
407             =cut
408              
409             sub modify {
410 90     90 1 323 my ( $self, $key, $value ) = @_;
411              
412 90 100       364 if ( ref( $self->{$key} ) eq "ARRAY" ) {
413 87         153 push( @{ $self->{$key} }, $value );
  87         224  
414             }
415             else {
416 3         7 $self->{$key} = $value;
417             }
418              
419 90         216 $self->rethink_connection;
420             }
421              
422             =head2 rethink_connection
423              
424             Deletes current connection object.
425              
426             =cut
427              
428             sub rethink_connection {
429 128     128 1 345 my ($self) = @_;
430 128         572 delete $self->{connection};
431             }
432              
433             =head2 user
434              
435             Returns the username the task will use.
436              
437             =cut
438              
439             sub user {
440 39     39 1 152 my ($self) = @_;
441 39 50 33     814 if ( exists $self->{auth} && $self->{auth}->{user} ) {
442 39         281 return $self->{auth}->{user};
443             }
444             }
445              
446             =head2 set_user($user)
447              
448             Set the username of a task.
449              
450             =cut
451              
452             sub set_user {
453 1     1 1 4 my ( $self, $user ) = @_;
454 1         5 $self->{auth}->{user} = $user;
455             }
456              
457             =head2 password
458              
459             Returns the password that will be used.
460              
461             =cut
462              
463             sub password {
464 2     2 1 5 my ($self) = @_;
465 2 50 33     14 if ( exists $self->{auth} && $self->{auth}->{password} ) {
466 2         8 return $self->{auth}->{password};
467             }
468             }
469              
470             =head2 set_password($password)
471              
472             Set the password of the task.
473              
474             =cut
475              
476             sub set_password {
477 1     1 1 4 my ( $self, $password ) = @_;
478 1         4 $self->{auth}->{password} = $password;
479             }
480              
481             =head2 name
482              
483             Returns the name of the task.
484              
485             =cut
486              
487             sub name {
488 250     250 1 1584 my ($self) = @_;
489 250         4576 return $self->{name};
490             }
491              
492             =head2 code
493              
494             Returns the code of the task.
495              
496             =cut
497              
498             sub code {
499 54     54 1 278 my ($self) = @_;
500 54         427 return $self->{func};
501             }
502              
503             =head2 set_code(\&code_ref)
504              
505             Set the code of the task.
506              
507             =cut
508              
509             sub set_code {
510 1     1 1 3 my ( $self, $code ) = @_;
511 1         7 $self->{func} = $code;
512             }
513              
514             =head2 run_hook($server, $hook)
515              
516             This method is used internally to execute the specified hooks.
517              
518             =cut
519              
520             sub run_hook {
521 136     136 1 1143 my ( $self, $server, $hook, @more_args ) = @_;
522 136         440 my $old_server;
523              
524 136         349 for my $code ( @{ $self->{$hook} } ) {
  136         1203  
525 24 100       127 if ( $hook eq "after" ) { # special case for after hooks
526             $code->(
527             $$server,
528 6   50     47 ( $self->{"__was_authenticated"} || 0 ),
529             { $self->get_opts }, @more_args
530             );
531             }
532             else {
533 18 50       81 $old_server = $$server if $server;
534 18         119 $code->( $$server, $server, { $self->get_opts }, @more_args );
535 18 100 66     218 if ( $old_server && $old_server ne $$server ) {
536 2         15 $self->{current_server} = $$server;
537             }
538             }
539             }
540             }
541              
542             =head2 set_auth($key, $value)
543              
544             Set the authentication of the task.
545              
546             $task->set_auth("user", "foo");
547             $task->set_auth("password", "bar");
548              
549             =cut
550              
551             sub set_auth {
552 4     4 1 18 my ( $self, $key, $value ) = @_;
553              
554 4 100       17 if ( scalar(@_) > 3 ) {
555 2         6 my $_d = shift;
556 2         14 $self->{auth} = {@_};
557             }
558             else {
559 2         11 $self->{auth}->{$key} = $value;
560             }
561             }
562              
563             =head2 merge_auth($server)
564              
565             Merges the authentication information from $server into the task.
566             Tasks authentication information have precedence.
567              
568             =cut
569              
570             sub merge_auth {
571 88     88 1 85792 my ( $self, $server ) = @_;
572              
573             # merge auth hashs
574             # task auth as precedence
575 88         956 my %auth = $server->merge_auth( $self->{auth} );
576              
577 88         659 return \%auth;
578             }
579              
580             =head2 get_sudo_password
581              
582             Returns the sudo password.
583              
584             =cut
585              
586             sub get_sudo_password {
587 0     0 1 0 my ($self) = @_;
588              
589 0         0 my $server = $self->connection->server;
590 0         0 my %auth = $server->merge_auth( $self->{auth} );
591              
592 0         0 return $auth{sudo_password};
593             }
594              
595             =head2 parallelism
596              
597             Get the parallelism count of a task.
598              
599             =cut
600              
601             sub parallelism {
602 138     138 1 798 my ($self) = @_;
603 138         3984 return $self->{parallelism};
604             }
605              
606             =head2 set_parallelism($count)
607              
608             Set the parallelism of the task.
609              
610             =cut
611              
612             sub set_parallelism {
613 0     0 1 0 my ( $self, $para ) = @_;
614 0         0 $self->{parallelism} = $para;
615             }
616              
617             =head2 connect($server)
618              
619             Initiate the connection to $server.
620              
621             =cut
622              
623             sub connect {
624 37     37 1 406 my ( $self, $server, %override ) = @_;
625              
626 37 100       361 if ( !ref $server ) {
627 1         11 $server = Rex::Group::Entry::Server->new( name => $server );
628             }
629 37         368 $self->{current_server} = $server;
630              
631 37         523 $self->run_hook( \$server, "before" );
632              
633             # need to be called, in case of a run_task task call.
634             # see #788
635 37         522 $self->rethink_connection;
636              
637 37         262 my $user = $self->user;
638              
639             #print Dumper($self);
640 37         342 my $auth = $self->merge_auth($server);
641              
642 37 50       278 if ( exists $override{auth} ) {
643 0         0 $auth = $override{auth};
644 0         0 $user = $auth->{user};
645             }
646              
647 37         1077 my $rex_int_conf = Rex::Commands::get("rex_internals");
648 37         988 Rex::Logger::debug( Dumper($rex_int_conf) );
649 37         257 Rex::Logger::debug("Auth-Information inside Task:");
650 37         109 for my $key ( keys %{$auth} ) {
  37         391  
651 296         586 my $data = $auth->{$key};
652 296 100       828 $data = Rex::Logger::masq( "%s", $data ) if $key eq 'password';
653 296 100       780 $data = Rex::Logger::masq( "%s", $data ) if $key eq 'sudo_password';
654 296   100     1289 $data ||= "";
655              
656 296         950 Rex::Logger::debug("$key => [[$data]]");
657             }
658              
659             $auth->{public_key} = resolv_path( $auth->{public_key}, 1 )
660 37 50       210 if ( $auth->{public_key} );
661             $auth->{private_key} = resolv_path( $auth->{private_key}, 1 )
662 37 50       171 if ( $auth->{private_key} );
663              
664 37         858 my $profiler = Rex::Profiler->new;
665              
666             # task specific auth rules over all
667 37         145 my %connect_hash = %{$auth};
  37         363  
668 37         280 $connect_hash{server} = $server;
669              
670             # need to get rid of this
671 37         453 Rex::push_connection(
672             {
673             conn => $self->connection,
674             ssh => $self->connection->get_connection_object,
675             server => $server,
676             cache => Rex::Interface::Cache->create(),
677             task => [],
678             profiler => $profiler,
679             reporter => Rex::Report->create( Rex::Config->get_report_type ),
680             notify => Rex::Notify->new(),
681             }
682             );
683              
684 37         151 push @{ Rex::get_current_connection()->{task} }, $self;
  37         269  
685              
686 37         350 $profiler->start("connect");
687             eval {
688 37         178 $self->connection->connect(%connect_hash);
689 37         246 1;
690 37 50       139 } or do {
691 0 0       0 if ( !defined Rex::Config->get_fallback_auth ) {
692 0         0 croak $@;
693             }
694             };
695 37         322 $profiler->end("connect");
696              
697 37 50       188 if ( !$self->connection->is_connected ) {
    50          
698 0         0 Rex::pop_connection();
699 0         0 croak("Couldn't connect to $server.");
700             }
701             elsif ( !$self->connection->is_authenticated ) {
702 0         0 Rex::pop_connection();
703 0         0 my $message =
704             "Couldn't authenticate against $server. It may be caused by one or more of:\n";
705 0         0 $message .= " - wrong username, password, key or passphrase\n";
706 0         0 $message .= " - changed remote host key\n";
707             $message .= " - root is not permitted to login over SSH\n"
708 0 0       0 if ( $connect_hash{user} eq 'root' );
709              
710 0 0       0 if ( !exists $override{auth} ) {
711 0         0 my $fallback_auth = Rex::Config->get_fallback_auth;
712 0 0       0 if ( ref $fallback_auth eq "ARRAY" ) {
713 0         0 my $ret_eval;
714 0         0 for my $fallback_a ( @{$fallback_auth} ) {
  0         0  
715 0         0 $ret_eval = eval { $self->connect( $server, auth => $fallback_a ); };
  0         0  
716             }
717              
718 0 0       0 return $ret_eval if $ret_eval;
719             }
720             }
721              
722 0         0 croak($message);
723             }
724             else {
725 37 50       150 Rex::Logger::debug("Successfully authenticated on $server.")
726             if ( $self->connection->get_connection_type ne "Local" );
727 37         402 $self->{"__was_authenticated"} = 1;
728             }
729              
730 37         290 $self->run_hook( \$server, "around" );
731              
732 37         278 return 1;
733             }
734              
735             =head2 disconnect
736              
737             Disconnect from the current connection.
738              
739             =cut
740              
741             sub disconnect {
742 29     29 1 218 my ( $self, $server ) = @_;
743              
744 29         444 $self->run_hook( \$server, "around", 1 );
745 29         349 $self->connection->disconnect;
746              
747 29         216 my %args = Rex::Args->getopts;
748              
749 29 50 33     286 if ( defined $args{'d'} && $args{'d'} > 2 ) {
750 0         0 Rex::Commands::profiler()->report;
751             }
752              
753 29         332 delete $self->{connection};
754              
755 29         122 pop @{ Rex::get_current_connection()->{task} };
  29         2103  
756              
757             # need to get rid of this
758 29         311 Rex::pop_connection();
759              
760 29         1158 $self->run_hook( \$server, "after" );
761             }
762              
763             =head2 get_data
764              
765             Dump task data.
766              
767             =cut
768              
769             sub get_data {
770 33     33 1 259 my ($self) = @_;
771              
772             return {
773             func => $self->{func},
774             server => $self->{server},
775             desc => $self->{desc},
776             no_ssh => $self->{no_ssh},
777             hidden => $self->{hidden},
778             auth => $self->{auth},
779             before => $self->{before},
780             after => $self->{after},
781             around => $self->{around},
782             name => $self->{name},
783             executor => $self->{executor},
784             connection_type => $self->{connection_type},
785             opts => $self->{opts},
786             args => $self->{args},
787 33         5190 };
788             }
789              
790             =head2 run($server, %options)
791              
792             Run the task on C<$server>, with C<%options>.
793              
794             =cut
795              
796             sub run {
797 54 50   54 1 553 return pre_40_run(@_) unless ref $_[0];
798              
799 54         1073 my ( $self, $server, %options ) = @_;
800              
801 54   50     994 $options{opts} ||= { $self->get_opts };
802 54   100     606 $options{args} ||= [ $self->get_args ];
803 54   66     525 $options{params} ||= $options{opts};
804              
805 54 100       421 if ( !ref $server ) {
806 22         314 $server = Rex::Group::Entry::Server->new( name => $server );
807             }
808              
809 54 50       349 if ( !$_[1] ) {
810              
811             # run is called without any server.
812             # so just connect to any servers.
813 0         0 return Rex::TaskList->create()->run( $self, %options );
814             }
815              
816             # this is a method call
817             # so run the task
818              
819             # TODO: refactor complete task calling
820             # direct call with function and normal task call
821              
822 54         283 my ( $in_transaction, $start_time );
823              
824 54         837 $start_time = time;
825              
826 54 100       505 if ( $server ne "" ) {
827              
828             # this is _not_ a task call via function syntax.
829              
830 36         270 $in_transaction = $options{in_transaction};
831              
832 36         130 eval { $self->connect($server) };
  36         569  
833 36 50       224 if ($@) {
834 0         0 my $error = $@;
835 0         0 $self->{"__was_authenticated"} = 0;
836 0         0 $self->run_hook( \$server, "after" );
837 0         0 die $error;
838             }
839              
840 36 50       913 if ( Rex::Args->is_opt("c") ) {
841              
842             # get and cache all os info
843 0 0       0 if ( !Rex::get_cache()->load() ) {
844 0         0 Rex::Logger::debug("No cache found, need to collect new data.");
845 0         0 $server->gather_information;
846             }
847             }
848              
849 36 50       458 if ( !$server->test_perl ) {
850 0         0 Rex::Logger::info(
851             "There is no perl interpreter found on this system. "
852             . "Some commands may not work. Sudo won't work.",
853             "warn"
854             );
855 0         0 sleep 3;
856             }
857              
858             }
859             else {
860             # we need to push the connection information of the last task onto this task object
861             # if we don't do this, the task doesn't have any information of the current connection when called like a function.
862             # See: #1091
863             $self->set_connection(
864             Rex::get_current_connection()->{task}->[-1]->connection )
865 18 100       101 if Rex::get_current_connection()->{task}->[-1];
866 18         37 push @{ Rex::get_current_connection()->{task} }, $self;
  18         65  
867             }
868              
869             # execute code
870 54         609 my @ret;
871 54         402 my $wantarray = wantarray;
872              
873             eval {
874 40         1431 $self->set_opts( %{ $options{params} } )
875 54 100       511 if ref $options{params} eq "HASH";
876 54 100       397 if ($wantarray) {
877 1         5 @ret = $self->executor->exec( $options{params}, $options{args} );
878             }
879             else {
880 53         692 $ret[0] = $self->executor->exec( $options{params}, $options{args} );
881             }
882 47         327 my $notify = Rex::get_current_connection()->{notify};
883 47         718 $notify->run_postponed();
884 54 50       199 } or do {
885 54 100       383 if ($@) {
886 7         37 my $error = $@;
887              
888             Rex::get_current_connection()->{reporter}
889 7         91 ->report_resource_failed( message => $error );
890              
891             Rex::get_current_connection()->{reporter}->report_task_execution(
892 7         59 failed => 1,
893             start_time => $start_time,
894             end_time => time,
895             message => $error,
896             );
897              
898 7         27 Rex::get_current_connection()->{reporter}->write_report();
899              
900 7         78 pop @{ Rex::get_current_connection()->{task} };
  7         37  
901 7         199 die($error);
902             }
903             };
904              
905 47 100       774 if ( $server ne "" ) {
906 29 50       471 if ( Rex::Args->is_opt("c") ) {
907              
908             # get and cache all os info
909 0         0 Rex::get_cache()->save();
910             }
911              
912             Rex::get_current_connection()->{reporter}->report_task_execution(
913 29         218 failed => 0,
914             start_time => $start_time,
915             end_time => time,
916             );
917              
918 29         214 Rex::get_current_connection()->{reporter}->write_report();
919              
920 29 100       174 if ($in_transaction) {
921 1         15 $self->run_hook( \$server, "around", 1 );
922 1         6 $self->run_hook( \$server, "after" );
923             }
924             else {
925 28         508 $self->disconnect($server);
926             }
927             }
928             else {
929 18         55 pop @{ Rex::get_current_connection()->{task} };
  18         83  
930             }
931              
932 47 100       301 if ($wantarray) {
933 1         9 return @ret;
934             }
935             else {
936 46         2092 return $ret[0];
937             }
938             }
939              
940             sub pre_40_run {
941 0     0 0 0 my ( $class, $task_name, $server_overwrite, $params ) = @_;
942              
943             # static calls to this method are deprecated
944 0         0 Rex::deprecated( "Rex::Task->run()", "0.40" );
945              
946 0         0 my $tasklist = Rex::TaskList->create;
947 0         0 my $task = $tasklist->get_task($task_name);
948              
949 0 0       0 $task->set_server($server_overwrite) if $server_overwrite;
950 0         0 $tasklist->run( $task, params => $params );
951             }
952              
953             =head2 modify_task($task, $key => $value)
954              
955             Modify C<$task>, by setting C<$key> to C<$value>.
956              
957             =cut
958              
959             sub modify_task {
960 0     0 1 0 my $class = shift;
961 0         0 my $task = shift;
962 0         0 my $key = shift;
963 0         0 my $value = shift;
964              
965 0         0 Rex::TaskList->create()->get_task($task)->modify( $key => $value );
966             }
967              
968             =head2 is_task
969              
970             Returns true(1) if the passed object is a task.
971              
972             =cut
973              
974             sub is_task {
975 0     0 1 0 my ( $class, $task ) = @_;
976 0         0 return Rex::TaskList->create()->is_task($task);
977             }
978              
979             =head2 get_tasks
980              
981             Returns list of tasks.
982              
983             =cut
984              
985             sub get_tasks {
986 0     0 1 0 my ( $class, @tmp ) = @_;
987 0         0 return Rex::TaskList->create()->get_tasks(@tmp);
988             }
989              
990             =head2 get_desc
991              
992             Returns description of task.
993              
994             =cut
995              
996             sub get_desc {
997 0     0 1 0 my ( $class, @tmp ) = @_;
998 0         0 return Rex::TaskList->create()->get_desc(@tmp);
999             }
1000              
1001             =head2 exit_on_connect_fail
1002              
1003             Returns true if rex should exit on connect failure.
1004              
1005             =cut
1006              
1007             sub exit_on_connect_fail {
1008 0     0 1 0 my ($self) = @_;
1009 0         0 return $self->{exit_on_connect_fail};
1010             }
1011              
1012             =head2 set_exit_on_connect_fail
1013              
1014             Sets if rex should exit on connect failure.
1015              
1016             =cut
1017              
1018             sub set_exit_on_connect_fail {
1019 0     0 1 0 my ( $self, $exit ) = @_;
1020 0         0 $self->{exit_on_connect_fail} = $exit;
1021             }
1022              
1023             =head2 get_args
1024              
1025             Returns arguments of task.
1026              
1027             =cut
1028              
1029             sub get_args {
1030 65     65 1 247 my ($self) = @_;
1031 65 50       147 @{ $self->{args} || [] };
  65         616  
1032             }
1033              
1034             =head2 get_opts
1035              
1036             Returns options of task.
1037              
1038             =cut
1039              
1040             sub get_opts {
1041 137     137 1 11613 my ($self) = @_;
1042 137 50       331 %{ $self->{opts} || {} };
  137         2771  
1043             }
1044              
1045             =head2 set_args
1046              
1047             Sets arguments for task.
1048              
1049             =cut
1050              
1051             sub set_args {
1052 101     101 1 268 my ( $self, @args ) = @_;
1053 101         463 $self->{args} = \@args;
1054             }
1055              
1056             =head2 set_opt
1057              
1058             Sets an option for task.
1059              
1060             =cut
1061              
1062             sub set_opt {
1063 6     6 1 43 my ( $self, $key, $value ) = @_;
1064 6         47 $self->{opts}->{$key} = $value;
1065             }
1066              
1067             =head2 set_opts
1068              
1069             Sets options for task.
1070              
1071             =cut
1072              
1073             sub set_opts {
1074 141     141 1 1050 my ( $self, %opts ) = @_;
1075 141         1086 $self->{opts} = \%opts;
1076             }
1077              
1078             =head2 clone
1079              
1080             Clones a task.
1081              
1082             =cut
1083              
1084             sub clone {
1085 32     32 1 165 my $self = shift;
1086 32         131 return Rex::Task->new( %{ $self->get_data } );
  32         676  
1087             }
1088              
1089             1;