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   70221 use v5.12.5;
  56         255  
35 56     56   313 use warnings;
  56         179  
  56         1416  
36 56     56   1110 use Data::Dumper;
  56         7860  
  56         2741  
37 56     56   945 use Time::HiRes qw(time);
  56         1793  
  56         729  
38              
39             our $VERSION = '1.14.2.2'; # TRIAL VERSION
40              
41 56     56   9005 use Rex::Logger;
  56         119  
  56         398  
42 56     56   1801 use Rex::TaskList;
  56         171  
  56         464  
43 56     56   2257 use Rex::Interface::Connection;
  56         115  
  56         674  
44 56     56   1406 use Rex::Interface::Executor;
  56         164  
  56         670  
45 56     56   2522 use Rex::Group::Entry::Server;
  56         144  
  56         1365  
46 56     56   2463 use Rex::Profiler;
  56         191  
  56         680  
47 56     56   1799 use Rex::Hardware;
  56         157  
  56         499  
48 56     56   1620 use Rex::Interface::Cache;
  56         129  
  56         595  
49 56     56   1417 use Rex::Report;
  56         121  
  56         442  
50 56     56   1271 use Rex::Helper::Run;
  56         142  
  56         4502  
51 56     56   424 use Rex::Helper::Path;
  56         210  
  56         3872  
52 56     56   418 use Rex::Notify;
  56         232  
  56         660  
53 56     56   1356 use Carp;
  56         160  
  56         241501  
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 2517 my $that = shift;
90 245   33     1692 my $proto = ref($that) || $that;
91 245         2009 my $self = {@_};
92              
93 245         1027 bless( $self, $proto );
94              
95 245 50       1321 if ( !exists $self->{name} ) {
96 0         0 die("You have to define a task name.");
97             }
98              
99 245   100     1530 $self->{no_ssh} ||= 0;
100 245   100 0   805 $self->{func} ||= sub { };
101 245   66     1225 $self->{executor} ||= Rex::Interface::Executor->create;
102 245   100     1643 $self->{opts} ||= {};
103 245   100     1162 $self->{args} ||= [];
104              
105 245         840 $self->{connection} = undef;
106              
107             # set to true as default
108 245 100       729 if ( !exists $self->{exit_on_connect_fail} ) {
109 33         244 $self->{exit_on_connect_fail} = 1;
110             }
111              
112 245         2086 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 605 my ($self) = @_;
123 260 100 100     1727 if ( !exists $self->{connection} || !$self->{connection} ) {
124             $self->{connection} =
125 40         435 Rex::Interface::Connection->create( $self->get_connection_type );
126             }
127              
128 260         1918 $self->{connection};
129             }
130              
131             sub set_connection {
132 7     7 0 26 my ( $self, $conn ) = @_;
133 7         22 $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 373 my ($self) = @_;
144 54         2953 $self->{executor}->set_task($self);
145 54         881 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 105 my ($self) = @_;
156 60         255 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 2936 my ($self) = @_;
167              
168 292         584 my @server = @{ $self->{server} };
  292         1402  
169 292         963 my @ret = ();
170              
171 292 50       1243 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     1905 if ( ref( $self->{server} ) eq "ARRAY"
    50          
190 292         2270 && scalar( @{ $self->{server} } ) > 0 )
191             {
192 18         35 for my $srv ( @{ $self->{server} } ) {
  18         50  
193 30 100       69 if ( ref($srv) eq "CODE" ) {
194 1         4 push( @ret, &$srv() );
195             }
196             else {
197 29 100 66     152 if ( ref $srv && $srv->isa("Rex::Group::Entry::Server") ) {
198 28         84 push( @ret, $srv->get_servers );
199             }
200             else {
201 1         3 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         4195 push( @ret, Rex::Group::Entry::Server->new( name => "" ) );
211             }
212              
213 292         1374 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 4 my ( $self, @server ) = @_;
224 1         6 $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 6 my ($self) = @_;
235 1         7 delete $self->{current_server};
236 1         10 delete $self->{server};
237 1         12 $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 6 my ($self) = @_;
248             return $self->{current_server}
249 2   66     27 || 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 6 my ($self) = @_;
260 2         9 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 7 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 1847 my ($self) = @_;
282 142 100       411 if ( exists $self->{current_server} ) {
283 118 100       430 if ( $self->{current_server} ne '' ) {
284 14         89 return 1;
285             }
286             }
287             else {
288 24 100 100     72 if ( exists $self->{server} && scalar( @{ $self->{server} } ) > 0 ) {
  17         57  
289 14         68 return 1;
290             }
291             }
292              
293 114         1300 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 18 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 213 my ($self) = @_;
315             return ( $self->{"connection_type"}
316 46   66     1046 && 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 174 my ($self) = @_;
327             return ( $self->{"connection_type"}
328 46   66     1059 && 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 18 my ($self) = @_;
339             return ( $self->{"connection_type"}
340 10   66     59 && 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 1159 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 924 my ($self) = @_;
382              
383 46 50 100     414 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         37 return Rex::Config->get_connection_type();
394             }
395             elsif ( $self->is_remote ) {
396 5         77 return "Fake";
397             }
398             else {
399 36         1037 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 218 my ( $self, $key, $value ) = @_;
411              
412 90 100       287 if ( ref( $self->{$key} ) eq "ARRAY" ) {
413 87         157 push( @{ $self->{$key} }, $value );
  87         196  
414             }
415             else {
416 3         10 $self->{$key} = $value;
417             }
418              
419 90         229 $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 332 my ($self) = @_;
430 128         620 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 167 my ($self) = @_;
441 39 50 33     878 if ( exists $self->{auth} && $self->{auth}->{user} ) {
442 39         338 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         6 $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 16 my ($self) = @_;
465 2 50 33     13 if ( exists $self->{auth} && $self->{auth}->{password} ) {
466 2         11 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 1685 my ($self) = @_;
489 250         4803 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 286 my ($self) = @_;
500 54         466 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 5 my ( $self, $code ) = @_;
511 1         8 $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 1299 my ( $self, $server, $hook, @more_args ) = @_;
522 136         447 my $old_server;
523              
524 136         395 for my $code ( @{ $self->{$hook} } ) {
  136         1302  
525 24 100       127 if ( $hook eq "after" ) { # special case for after hooks
526             $code->(
527             $$server,
528 6   50     49 ( $self->{"__was_authenticated"} || 0 ),
529             { $self->get_opts }, @more_args
530             );
531             }
532             else {
533 18 50       93 $old_server = $$server if $server;
534 18         78 $code->( $$server, $server, { $self->get_opts }, @more_args );
535 18 100 66     159 if ( $old_server && $old_server ne $$server ) {
536 2         16 $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 20 my ( $self, $key, $value ) = @_;
553              
554 4 100       18 if ( scalar(@_) > 3 ) {
555 2         4 my $_d = shift;
556 2         13 $self->{auth} = {@_};
557             }
558             else {
559 2         8 $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 98056 my ( $self, $server ) = @_;
572              
573             # merge auth hashs
574             # task auth as precedence
575 88         1130 my %auth = $server->merge_auth( $self->{auth} );
576              
577 88         803 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 822 my ($self) = @_;
603 138         3890 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 523 my ( $self, $server, %override ) = @_;
625              
626 37 100       333 if ( !ref $server ) {
627 1         13 $server = Rex::Group::Entry::Server->new( name => $server );
628             }
629 37         341 $self->{current_server} = $server;
630              
631 37         527 $self->run_hook( \$server, "before" );
632              
633             # need to be called, in case of a run_task task call.
634             # see #788
635 37         559 $self->rethink_connection;
636              
637 37         273 my $user = $self->user;
638              
639             #print Dumper($self);
640 37         531 my $auth = $self->merge_auth($server);
641              
642 37 50       306 if ( exists $override{auth} ) {
643 0         0 $auth = $override{auth};
644 0         0 $user = $auth->{user};
645             }
646              
647 37         1095 my $rex_int_conf = Rex::Commands::get("rex_internals");
648 37         1052 Rex::Logger::debug( Dumper($rex_int_conf) );
649 37         366 Rex::Logger::debug("Auth-Information inside Task:");
650 37         144 for my $key ( keys %{$auth} ) {
  37         362  
651 296         617 my $data = $auth->{$key};
652 296 100       753 $data = Rex::Logger::masq( "%s", $data ) if $key eq 'password';
653 296 100       910 $data = Rex::Logger::masq( "%s", $data ) if $key eq 'sudo_password';
654 296   100     1276 $data ||= "";
655              
656 296         975 Rex::Logger::debug("$key => [[$data]]");
657             }
658              
659             $auth->{public_key} = resolv_path( $auth->{public_key}, 1 )
660 37 50       289 if ( $auth->{public_key} );
661             $auth->{private_key} = resolv_path( $auth->{private_key}, 1 )
662 37 50       196 if ( $auth->{private_key} );
663              
664 37         1022 my $profiler = Rex::Profiler->new;
665              
666             # task specific auth rules over all
667 37         190 my %connect_hash = %{$auth};
  37         369  
668 37         202 $connect_hash{server} = $server;
669              
670             # need to get rid of this
671 37         340 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         130 push @{ Rex::get_current_connection()->{task} }, $self;
  37         197  
685              
686 37         385 $profiler->start("connect");
687             eval {
688 37         175 $self->connection->connect(%connect_hash);
689 37         191 1;
690 37 50       168 } or do {
691 0 0       0 if ( !defined Rex::Config->get_fallback_auth ) {
692 0         0 croak $@;
693             }
694             };
695 37         272 $profiler->end("connect");
696              
697 37 50       187 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       154 Rex::Logger::debug("Successfully authenticated on $server.")
726             if ( $self->connection->get_connection_type ne "Local" );
727 37         407 $self->{"__was_authenticated"} = 1;
728             }
729              
730 37         256 $self->run_hook( \$server, "around" );
731              
732 37         270 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 185 my ( $self, $server ) = @_;
743              
744 29         563 $self->run_hook( \$server, "around", 1 );
745 29         327 $self->connection->disconnect;
746              
747 29         211 my %args = Rex::Args->getopts;
748              
749 29 50 33     302 if ( defined $args{'d'} && $args{'d'} > 2 ) {
750 0         0 Rex::Commands::profiler()->report;
751             }
752              
753 29         253 delete $self->{connection};
754              
755 29         147 pop @{ Rex::get_current_connection()->{task} };
  29         248  
756              
757             # need to get rid of this
758 29         354 Rex::pop_connection();
759              
760 29         238 $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 274 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         5541 };
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 497 return pre_40_run(@_) unless ref $_[0];
798              
799 54         1020 my ( $self, $server, %options ) = @_;
800              
801 54   50     1035 $options{opts} ||= { $self->get_opts };
802 54   100     815 $options{args} ||= [ $self->get_args ];
803 54   66     635 $options{params} ||= $options{opts};
804              
805 54 100       502 if ( !ref $server ) {
806 22         280 $server = Rex::Group::Entry::Server->new( name => $server );
807             }
808              
809 54 50       424 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         197 my ( $in_transaction, $start_time );
823              
824 54         712 $start_time = time;
825              
826 54 100       573 if ( $server ne "" ) {
827              
828             # this is _not_ a task call via function syntax.
829              
830 36         155 $in_transaction = $options{in_transaction};
831              
832 36         147 eval { $self->connect($server) };
  36         2346  
833 36 50       246 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       887 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       475 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       122 if Rex::get_current_connection()->{task}->[-1];
866 18         40 push @{ Rex::get_current_connection()->{task} }, $self;
  18         47  
867             }
868              
869             # execute code
870 54         1084 my @ret;
871 54         361 my $wantarray = wantarray;
872              
873             eval {
874 40         1431 $self->set_opts( %{ $options{params} } )
875 54 100       578 if ref $options{params} eq "HASH";
876 54 100       467 if ($wantarray) {
877 1         15 @ret = $self->executor->exec( $options{params}, $options{args} );
878             }
879             else {
880 53         858 $ret[0] = $self->executor->exec( $options{params}, $options{args} );
881             }
882 47         675 my $notify = Rex::get_current_connection()->{notify};
883 47         907 $notify->run_postponed();
884 54 50       352 } or do {
885 54 100       469 if ($@) {
886 7         36 my $error = $@;
887              
888             Rex::get_current_connection()->{reporter}
889 7         38 ->report_resource_failed( message => $error );
890              
891             Rex::get_current_connection()->{reporter}->report_task_execution(
892 7         56 failed => 1,
893             start_time => $start_time,
894             end_time => time,
895             message => $error,
896             );
897              
898 7         33 Rex::get_current_connection()->{reporter}->write_report();
899              
900 7         21 pop @{ Rex::get_current_connection()->{task} };
  7         51  
901 7         209 die($error);
902             }
903             };
904              
905 47 100       1057 if ( $server ne "" ) {
906 29 50       412 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         331 failed => 0,
914             start_time => $start_time,
915             end_time => time,
916             );
917              
918 29         203 Rex::get_current_connection()->{reporter}->write_report();
919              
920 29 100       221 if ($in_transaction) {
921 1         9 $self->run_hook( \$server, "around", 1 );
922 1         9 $self->run_hook( \$server, "after" );
923             }
924             else {
925 28         403 $self->disconnect($server);
926             }
927             }
928             else {
929 18         51 pop @{ Rex::get_current_connection()->{task} };
  18         93  
930             }
931              
932 47 100       319 if ($wantarray) {
933 1         9 return @ret;
934             }
935             else {
936 46         2166 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       149 @{ $self->{args} || [] };
  65         681  
1032             }
1033              
1034             =head2 get_opts
1035              
1036             Returns options of task.
1037              
1038             =cut
1039              
1040             sub get_opts {
1041 137     137 1 12463 my ($self) = @_;
1042 137 50       299 %{ $self->{opts} || {} };
  137         2973  
1043             }
1044              
1045             =head2 set_args
1046              
1047             Sets arguments for task.
1048              
1049             =cut
1050              
1051             sub set_args {
1052 101     101 1 202 my ( $self, @args ) = @_;
1053 101         336 $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 41 my ( $self, $key, $value ) = @_;
1064 6         44 $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 1073 my ( $self, %opts ) = @_;
1075 141         1016 $self->{opts} = \%opts;
1076             }
1077              
1078             =head2 clone
1079              
1080             Clones a task.
1081              
1082             =cut
1083              
1084             sub clone {
1085 32     32 1 188 my $self = shift;
1086 32         199 return Rex::Task->new( %{ $self->get_data } );
  32         761  
1087             }
1088              
1089             1;