File Coverage

lib/Rex/Commands.pm
Criterion Covered Total %
statement 302 475 63.5
branch 100 190 52.6
condition 46 117 39.3
subroutine 58 85 68.2
pod 50 60 83.3
total 556 927 59.9


line stmt bran cond sub pod time code
1              
2             # (c) Jan Gehring
3             #
4              
5             =head1 NAME
6              
7             Rex::Commands - All the basic commands
8              
9             =head1 DESCRIPTION
10              
11             This module is the core commands module.
12              
13             =head1 SYNOPSIS
14              
15             desc "Task description";
16              
17             task "taskname", sub { ... };
18             task "taskname", "server1", ..., "server20", sub { ... };
19              
20             group "group" => "server1", "server2", ...;
21              
22             user "user";
23              
24             password "password";
25              
26             environment live => sub {
27             user "root";
28             password "foobar";
29             pass_auth;
30             group frontend => "www01", "www02";
31             };
32              
33              
34              
35             =head1 COMMANDLIST
36              
37             =over 4
38              
39             =item * Augeas config file management library L
40              
41             =item * Cloud Management L
42              
43             =item * Cron Management L
44              
45             =item * Database Commands L
46              
47             =item * SCP Up- and Download L, L
48              
49             =item * File Manipulation L
50              
51             =item * Filesystem Manipulation L
52              
53             =item * Information Gathering L
54              
55             =item * Manipulation of /etc/hosts L
56              
57             =item * Get an inventory of your Hardware L
58              
59             =item * Manage your iptables rules L
60              
61             =item * Kernel Commands L
62              
63             =item * LVM Commands L
64              
65             =item * MD5 checksums L
66              
67             =item * Network commands L
68              
69             =item * Notify resources to execute L
70              
71             =item * Package Commands L
72              
73             =item * Partition your storage device(s) L
74              
75             =item * Configure packages (via debconf) L
76              
77             =item * Process Management L
78              
79             =item * Rsync Files L
80              
81             =item * Run Remote Commands L
82              
83             =item * Source control via Subversion/Git L
84              
85             =item * Manage System Services (sysvinit) L
86              
87             =item * Simple TCP/alive checks L
88              
89             =item * Sync directories L
90              
91             =item * Sysctl Commands L
92              
93             =item * Live Tail files L
94              
95             =item * Upload local file to remote server L
96              
97             =item * Manage user and group accounts L
98              
99             =item * Manage your virtual environments L
100              
101             =back
102              
103             =head1 EXPORTED FUNCTIONS
104              
105             =cut
106              
107             package Rex::Commands;
108              
109 102     102   2022466 use v5.12.5;
  102         615  
110 102     102   916 use warnings;
  102         201  
  102         5630  
111              
112             our $VERSION = '1.14.2.2'; # TRIAL VERSION
113              
114             require Rex::Exporter;
115 102     102   19809 use Rex::TaskList;
  102         404  
  102         1190  
116 102     102   3061 use Rex::Logger;
  102         214  
  102         577  
117 102     102   2347 use Rex::Config;
  102         2681  
  102         750  
118 102     102   26169 use Rex::Profiler;
  102         10463  
  102         1277  
119 102     102   28799 use Rex::Report;
  102         241  
  102         2055  
120 102     102   34378 use Rex;
  102         246  
  102         642  
121 102     102   1167 use Rex::Helper::Misc;
  102         258  
  102         2114  
122 102     102   3368 use Rex::RunList;
  102         256  
  102         1033  
123 102     102   2890 use Symbol;
  102         1467  
  102         11084  
124              
125 102     102   1584 use Carp;
  102         199  
  102         6311  
126              
127             use vars
128 102     102   577 qw(@EXPORT $current_desc $global_no_ssh $environments $dont_register_tasks $profiler %auth_late);
  102         171  
  102         9066  
129 102     102   727 use base qw(Rex::Exporter);
  102         6456  
  102         11309  
130              
131             @EXPORT = qw(task desc group
132             user password port sudo_password public_key private_key pass_auth key_auth krb5_auth no_ssh
133             get_random batch timeout max_connect_retries parallelism proxy_command
134             do_task run_task run_batch needs
135             exit
136             evaluate_hostname
137             logging
138             include
139             say
140             environment
141             LOCAL
142             path
143             set
144             get
145             before after around before_task_start after_task_finished
146             logformat log_format
147             sayformat say_format
148             connection
149             auth
150             FALSE TRUE
151             set_distributor
152             set_executor_for
153             template_function
154             report
155             make
156             source_global_profile
157             last_command_output
158             case
159             inspect
160             tmp_dir
161             cache
162             );
163              
164             our $REGISTER_SUB_HASH_PARAMETER = 0;
165              
166             =head2 no_ssh([$task])
167              
168             Disable ssh for all tasks or a specified task.
169              
170             If you want to disable ssh connection for your complete tasks (for example if you only want to use libVirt) put this in the main section of your Rexfile.
171              
172             no_ssh;
173              
174             If you want to disable ssh connection for a given task, put I in front of the task definition.
175              
176             no_ssh task "mytask", "myserver", sub {
177             say "Do something without a ssh connection";
178             };
179              
180             =cut
181              
182             sub no_ssh {
183 1 50   1 1 4 if (@_) {
184 1         3 $_[0]->( no_ssh => 1 );
185             }
186             else {
187 0         0 $global_no_ssh = 1;
188             }
189             }
190              
191             =head2 task($name [, @servers], $funcref)
192              
193             This function will create a new task.
194              
195             =over 4
196              
197             =item Create a local task (a server independent task)
198              
199             task "mytask", sub {
200             say "Do something";
201             };
202              
203             If you call this task with (R)?ex it will run on your local machine. You can explicit run this task on other machines if you specify the I<-H> command line parameter.
204              
205             =item Create a server bound task.
206              
207             task "mytask", "server1", sub {
208             say "Do something";
209             };
210              
211             You can also specify more than one server.
212              
213             task "mytask", "server1", "server2", "server3", sub {
214             say "Do something";
215             };
216              
217             Or you can use some expressions to define more than one server.
218              
219             task "mytask", "server[1..3]", sub {
220             say "Do something";
221             };
222              
223             If you want, you can overwrite the servers with the I<-H> command line parameter.
224              
225             =item Create a group bound task.
226              
227             You can define server groups with the I function.
228              
229             group "allserver" => "server[1..3]", "workstation[1..10]";
230              
231             task "mytask", group => "allserver", sub {
232             say "Do something";
233             };
234              
235             =back
236              
237             =cut
238              
239             sub task {
240 372     372 1 7797 my ( $class, $file, @tmp ) = caller;
241 372         1287 my @_ARGS = @_;
242              
243 372 100       1288 if ( !@_ ) {
244 159 50       532 if ( my $t = Rex::get_current_connection ) {
245 159         1579 return $t->{task}->[-1];
246             }
247 0         0 return;
248             }
249              
250             # for things like
251             # no_ssh task ...
252 213 100       643 if (wantarray) {
253             return sub {
254 1     1   4 my %option = @_;
255              
256 1         4 $option{class} = $class;
257 1         2 $option{file} = $file;
258 1         2 $option{tmp} = \@tmp;
259              
260 1         3 task( @_ARGS, \%option );
261 1         20 };
262             }
263              
264 212 100       786 if ( ref( $_ARGS[-1] ) eq "HASH" ) {
265 2 100       9 if ( $_ARGS[-1]->{class} ) {
266 1         2 $class = $_ARGS[-1]->{class};
267             }
268              
269 2 100       15 if ( $_ARGS[-1]->{file} ) {
270 1         5 $file = $_ARGS[-1]->{file};
271             }
272              
273 2 100       8 if ( $_ARGS[-1]->{tmp} ) {
274 1         3 @tmp = @{ $_ARGS[-1]->{tmp} };
  1         3  
275             }
276             }
277              
278 212         483 my $task_name = shift;
279 212         432 my $task_name_save = $task_name;
280              
281 212 0 33     1514 if ( $task_name !~ m/^[a-zA-Z_][a-zA-Z0-9_]*$/
282             && !Rex::Config->get_disable_taskname_warning() )
283             {
284 0         0 Rex::Logger::info(
285             "Please use only the following characters for task names:", "warn" );
286 0         0 Rex::Logger::info( " A-Z, a-z, 0-9 and _", "warn" );
287 0         0 Rex::Logger::info( "Also the task should start with A-Z or a-z", "warn" );
288 0         0 Rex::Logger::info(
289             "You can disable this warning by setting feature flag: disable_taskname_warning",
290             "warn"
291             );
292             }
293              
294 212         510 my $options = {};
295              
296 212 100       771 if ( ref( $_[-1] ) eq "HASH" ) {
297 2         6 $options = pop;
298             }
299              
300 212 50       612 if ($global_no_ssh) {
301 0         0 $options->{"no_ssh"} = 1;
302             }
303              
304 212 100 100     902 if ( $class ne "main" && $class ne "Rex::CLI" ) {
305 32         120 $task_name = $class . ":" . $task_name;
306             }
307              
308 212         662 $task_name =~ s/^Rex:://;
309 212         514 $task_name =~ s/::/:/g;
310              
311 212 100       598 if ($current_desc) {
312 69         176 push( @_, $current_desc );
313 69         161 $current_desc = "";
314             }
315             else {
316 143         401 push( @_, "" );
317             }
318              
319 212   100     1532 $options->{'dont_register'} ||= $dont_register_tasks;
320 212         1532 my $task_o = Rex::TaskList->create()->create_task( $task_name, @_, $options );
321              
322 212 100 66     4044 if (!$class->can($task_name_save)
323             && $task_name_save =~ m/^[a-zA-Z_][a-zA-Z0-9_]+$/ )
324             {
325 188         1145 Rex::Logger::debug("Registering task: $task_name");
326 188         482 my $code = $_[-2];
327 188         841 my $ref_to_task = qualify_to_ref( $task_name_save, $class );
328 188         621 *{$ref_to_task} = sub {
329 12     12   2042 Rex::Logger::info("Running task $task_name on current connection");
330 12         28 my $param;
331              
332 12 100 66     179 if ( scalar @_ == 1 && ref $_[0] eq "HASH" ) {
    50 33        
333 4         18 $param = $_[0];
334             }
335             elsif ( $REGISTER_SUB_HASH_PARAMETER && scalar @_ % 2 == 0 ) {
336 0         0 $param = {@_};
337             }
338             else {
339 8         24 $param = \@_;
340             }
341              
342 12         104 $task_o->run( "", params => $param );
343 188         5713 };
344             }
345              
346 212   66     1461 $options->{'dont_register'} ||= $dont_register_tasks;
347 212         1200 return $task_o;
348             }
349              
350             =head2 desc($description)
351              
352             Set the description of the task, batch, or environment following it.
353              
354             desc 'This is the description of the following task';
355             task 'mytask', sub {
356             say 'Do something';
357             };
358              
359             desc 'This is the description of the following batch';
360             batch mybatch => 'task1', 'task2', 'task3';
361              
362             desc 'This is the description of the following environment';
363             environment production => sub {
364             ...
365             };
366              
367             =cut
368              
369             sub desc {
370 69     69 1 2284 $current_desc = shift;
371             }
372              
373             =head2 group($name, @servers)
374              
375             With this function you can group servers, so that you don't need to write too much ;-)
376              
377             group "servergroup", "www1", "www2", "www3", "memcache01", "memcache02", "memcache03";
378              
379             Or with the expression syntax:
380              
381             group "servergroup", "www[1..3]", "memcache[01..03]";
382              
383             If the C feature flag is enabled, you can also specify server options after a server name with a hash reference:
384              
385             use Rex -feature => ['use_server_auth'];
386              
387             group "servergroup", "www1" => { user => "other" }, "www2";
388              
389             These expressions are allowed:
390              
391             =over 4
392              
393             =item * \d+..\d+ (range)
394              
395             The first number is the start and the second number is the
396             end for numbering the servers.
397              
398             group "name", "www[1..3]"; # www1, www2, www3
399              
400             =item * \d+..\d+/\d+ (range with step)
401              
402             Just like the range notation, but with an additional "step" defined.
403             If step is omitted, it defaults to 1 (i.e. it behaves like a simple range expression).
404              
405             group "name", "www[1..5/2]"; # www1, www3, www5
406             group "name", "www[111..133/11]"; # www111, www122, www133
407              
408             =item * \d+,\d+,\d+ (list)
409              
410             With this variant you can define fixed values.
411              
412             group "name", "www[1,3,7,01]"; # www1, www3, www7, www01
413              
414             =item * Mixed list, range and range with step
415              
416             You can mix the three variants above
417              
418             www[1..3,5,9..21/3]; # www1, www2, www3, www5, www9, www12, www15, www18, www21
419              
420             =back
421              
422             =cut
423              
424             sub group {
425 16     16 1 2757 my @params = @_;
426              
427 16 50 66     92 if (
    0 33        
    0 0        
    50          
428             scalar @params <= 7
429             && (
430 45         137 defined $params[1] ? ( grep { $params[1] eq $_ } qw/ensure system gid/ )
431             : 0
432             )
433             && (
434 0         0 defined $params[3] ? ( grep { $params[3] eq $_ } qw/ensure system gid/ )
435             : 1
436             )
437             && (
438 0         0 defined $params[5] ? ( grep { $params[5] eq $_ } qw/ensure system gid/ )
439             : 1
440             )
441             )
442             {
443             # call create_group
444 0         0 Rex::Commands::User::group_resource(@params);
445             }
446             else {
447 16         91 Rex::Group->create_group(@params);
448             }
449             }
450              
451             # Register set-handler for group
452             Rex::Config->register_set_handler(
453             group => sub {
454             Rex::Commands::group(@_);
455             }
456             );
457              
458             =head2 batch($name, @tasks)
459              
460             With the batch function you can call tasks in a batch.
461              
462             batch "name", "task1", "task2", "task3";
463              
464             And call it with the I<-b> console parameter. I
465              
466             =cut
467              
468             sub batch {
469 1 50   1 1 8 if ($current_desc) {
470 0         0 push( @_, $current_desc );
471 0         0 $current_desc = "";
472             }
473             else {
474 1         3 push( @_, "" );
475             }
476              
477 1         10 Rex::Batch->create_batch(@_);
478             }
479              
480             =head2 user($user)
481              
482             Set the user for the ssh connection.
483              
484             =cut
485              
486             sub user {
487 8     8 1 3137 Rex::Config->set_user(@_);
488             }
489              
490             =head2 password($password)
491              
492             Set the password for the ssh connection (or for the private key file).
493              
494             =cut
495              
496             sub password {
497 8     8 1 56 Rex::Config->set_password(@_);
498             }
499              
500             =head2 auth(for => $entity, %data)
501              
502             With this command you can set or modify authentication parameters for tasks and groups. (Please note this is different than setting authentication details for the members of a host group. If you are looking for that, please check out the L command.)
503              
504             If you want to set special login information for a group you have to enable at least the C<0.31> feature flag, and ensure the C is declared before the C command.
505              
506             Command line options to set locality or authentication details are still taking precedence, and may override these settings.
507              
508             # auth for groups
509              
510             use Rex -feature => ['0.31']; # activate setting auth for a group
511              
512             group frontends => "web[01..10]";
513             group backends => "be[01..05]";
514              
515             auth for => "frontends" =>
516             user => "root",
517             password => "foobar";
518              
519             auth for => "backends" =>
520             user => "admin",
521             private_key => "/path/to/id_rsa",
522             public_key => "/path/to/id_rsa.pub",
523             sudo => TRUE;
524              
525             # auth for tasks
526              
527             task "prepare", group => ["frontends", "backends"], sub {
528             # do something
529             };
530              
531             auth for => "prepare" =>
532             user => "root";
533              
534             # auth for multiple tasks with regular expression
535              
536             task "step_1", sub {
537             # do something
538             };
539              
540             task "step_2", sub {
541             # do something
542             };
543              
544             auth for => qr/step/ =>
545             user => $user,
546             password => $password;
547              
548             # fallback auth
549             auth fallback => {
550             user => "fallback_user1",
551             password => "fallback_pw1",
552             public_key => "",
553             private_key => "",
554             }, {
555             user => "fallback_user2",
556             password => "fallback_pw2",
557             public_key => "keys/public.key",
558             private_key => "keys/private.key",
559             sudo => TRUE,
560             };
561              
562             =cut
563              
564             sub auth {
565              
566 6 50 33 6 1 7436 if ( !ref $_[0] && $_[0] eq "fallback" ) {
567              
568             # set fallback authentication
569 0         0 shift;
570              
571 0         0 Rex::Config->set_fallback_auth(@_);
572 0         0 return 1;
573             }
574              
575 6         47 my ( $_d, $entity, %data ) = @_;
576              
577 6         37 my $group = Rex::Group->get_group_object($entity);
578 6 100       23 if ( !$group ) {
579 3         19 Rex::Logger::debug("No group $entity found, looking for a task.");
580 3 50       20 if ( ref($entity) eq "Regexp" ) {
581 0         0 my @tasks = Rex::TaskList->create()->get_tasks;
582 0         0 my @selected_tasks = grep { m/$entity/ } @tasks;
  0         0  
583 0         0 for my $t (@selected_tasks) {
584 0         0 auth( $_d, $t, %data );
585             }
586 0         0 return;
587             }
588             else {
589 3         17 $group = Rex::TaskList->create()->get_task($entity);
590             }
591             }
592              
593 6 100       21 if ( !$group ) {
594 1         8 Rex::Logger::info(
595             "Group or Task $entity not found. Assuming late-binding for task.");
596 1         4 $auth_late{$entity} = \%data;
597 1         4 return;
598             }
599              
600 5 100       42 if ( ref($group) eq "Rex::Group" ) {
601 3         11 Rex::Logger::debug("=================================================");
602 3         12 Rex::Logger::debug("You're setting special login credentials for a Group.");
603 3         9 Rex::Logger::debug(
604             "Please remember that the default auth information/task auth information has precedence."
605             );
606 3         26 Rex::Logger::debug(
607             "If you want to overwrite this behaviour please use ,,use Rex -feature => 0.31;'' in your Rexfile."
608             );
609 3         7 Rex::Logger::debug("=================================================");
610             }
611              
612 5 50       18 if ( exists $data{pass_auth} ) {
613 0         0 $data{auth_type} = "pass";
614             }
615 5 50       15 if ( exists $data{key_auth} ) {
616 0         0 $data{auth_type} = "key";
617             }
618 5 50       18 if ( exists $data{krb5_auth} ) {
619 0         0 $data{auth_type} = "krb5";
620             }
621              
622 5         39 Rex::Logger::debug( "Setting auth info for " . ref($group) . " $entity" );
623 5         35 $group->set_auth(%data);
624             }
625              
626             =head2 port($port)
627              
628             Set the port where the ssh server is listening.
629              
630             =cut
631              
632             sub port {
633 0     0 1 0 Rex::Config->set_port(@_);
634             }
635              
636             =head2 sudo_password($password)
637              
638             Set the password for the sudo command.
639              
640             =cut
641              
642             sub sudo_password {
643 1     1 1 7 Rex::Config->set_sudo_password(@_);
644             }
645              
646             =head2 timeout($seconds)
647              
648             Set the timeout for the ssh connection and other network related stuff.
649              
650             =cut
651              
652             sub timeout {
653 7     7 1 160 Rex::Config->set_timeout(@_);
654             }
655              
656             =head2 max_connect_retries($count)
657              
658             Set the maximum number of connection retries.
659              
660             =cut
661              
662             sub max_connect_retries {
663 1     1 1 8 Rex::Config->set_max_connect_fails(@_);
664             }
665              
666             =head2 get_random($count, @chars)
667              
668             Returns a random string of $count characters on the basis of @chars.
669              
670             my $rnd = get_random(8, 'a' .. 'z');
671              
672             =cut
673              
674             sub get_random {
675 917     917 1 13539 return Rex::Helper::Misc::get_random(@_);
676             }
677              
678             =head2 do_task($task)
679              
680             Call $task from another task. It will establish a new connection to the server defined in $task and then execute $task there.
681              
682             task "task1", "server1", sub {
683             say "Running on server1";
684             do_task "task2";
685             };
686              
687             task "task2", "server2", sub {
688             say "Running on server2";
689             };
690              
691             You may also use an arrayRef for $task if you want to call multiple tasks.
692              
693             do_task [ qw/task1 task2 task3/ ];
694              
695             =cut
696              
697             sub do_task {
698 5     5 1 1992 my $task = shift;
699 5         11 my $params = shift;
700              
701             # only get all parameters if task_chaining_cmdline_args (or feature flag >= 1.4)
702             # is not active.
703             # since 1.4 every task can have its own arguments.
704 5 50       61 if ( !Rex::Config->get_task_chaining_cmdline_args ) {
705 5   50     112 $params ||= { Rex::Args->get };
706             }
707              
708             # default is an empty hash
709 5   50     20 $params ||= {};
710              
711 5 100       33 if ( ref($task) eq "ARRAY" ) {
712 1         2 for my $t ( @{$task} ) {
  1         4  
713 1 50       4 Rex::TaskList->create()->get_task($t) || die "Task $t not found.";
714 0         0 Rex::TaskList->run( $t, params => $params );
715             }
716             }
717             else {
718 4 100       28 Rex::TaskList->create()->get_task($task) || die "Task $task not found.";
719 3         52 return Rex::TaskList->run( $task, params => $params );
720             }
721             }
722              
723             =head2 run_task($task_name, %option)
724              
725             Run a task on a given host.
726              
727             my $return = run_task "taskname", on => "192.168.3.56";
728              
729             Do something on server5 if memory is less than 100 MB free on server3.
730              
731             task "prepare", "server5", sub {
732             my $free_mem = run_task "get_free_mem", on => "server3";
733             if($free_mem < 100) {
734             say "Less than 100 MB free mem on server3";
735             # create a new server instance on server5 to unload server3
736             }
737             };
738              
739             task "get_free_mem", sub {
740             return memory->{free};
741             };
742              
743             If called without a hostname the task is run localy.
744              
745             # this task will run on server5
746             task "prepare", "server5", sub {
747             # this will call task check_something. but this task will run on localhost.
748             my $check = run_task "check_something";
749             }
750              
751             task "check_something", "server4", sub {
752             return "foo";
753             };
754              
755             If you want to add custom parameters for the task you can do it this way.
756              
757             task "prepare", "server5", sub {
758             run_task "check_something", on => "foo", params => { param1 => "value1", param2 => "value2" };
759             };
760              
761             =cut
762              
763             sub run_task {
764 0     0 1 0 my ( $task_name, %option ) = @_;
765              
766 0         0 my $task = Rex::TaskList->create()->get_task($task_name);
767 0 0       0 if ( !$task ) {
768 0         0 croak("No task named '$task_name' found.");
769             }
770              
771 0 0       0 if ( exists $option{on} ) {
772 0 0       0 if ( exists $option{params} ) {
773 0         0 $task->run( $option{on}, params => $option{params} );
774             }
775             else {
776 0         0 $task->run( $option{on} );
777             }
778             }
779             else {
780 0 0       0 if ( exists $option{params} ) {
781 0         0 $task->run( "", params => $option{params} );
782             }
783             else {
784 0         0 $task->run("");
785             }
786             }
787              
788             }
789              
790             =head2 run_batch($batch_name, %option)
791              
792             Run a batch on a given host.
793              
794             my @return = run_batch "batchname", on => "192.168.3.56";
795              
796             It calls internally run_task, and passes it any option given.
797              
798             =cut
799              
800             sub run_batch {
801 0     0 1 0 my ( $batch_name, %option ) = @_;
802              
803 0         0 my @tasks = Rex::Batch->get_batch($batch_name);
804 0         0 my @results;
805 0         0 for my $task (@tasks) {
806 0         0 my $return = run_task $task, %option;
807 0         0 push @results, $return;
808             }
809              
810 0         0 return @results;
811             }
812              
813             =head2 public_key($key)
814              
815             Set the public key.
816              
817             =cut
818              
819             sub public_key {
820 7     7 1 45 Rex::Config->set_public_key(@_);
821             }
822              
823             =head2 private_key($key)
824              
825             Set the private key.
826              
827             =cut
828              
829             sub private_key {
830 7     7 1 70 Rex::Config->set_private_key(@_);
831             }
832              
833             =head2 pass_auth
834              
835             If you want to use password authentication, then you need to call I.
836              
837             user "root";
838             password "root";
839              
840             pass_auth;
841              
842             =cut
843              
844             sub pass_auth {
845 3 50   3 1 3111 if (wantarray) { return "pass"; }
  0         0  
846 3         31 Rex::Config->set_password_auth(1);
847             }
848              
849             =head2 key_auth
850              
851             If you want to use pubkey authentication, then you need to call I.
852              
853             user "bob";
854             private_key "/home/bob/.ssh/id_rsa"; # passphrase-less key
855             public_key "/home/bob/.ssh/id_rsa.pub";
856              
857             key_auth;
858              
859             =cut
860              
861             sub key_auth {
862 1 50   1 1 22 if (wantarray) { return "key"; }
  0         0  
863 1         7 Rex::Config->set_key_auth(1);
864             }
865              
866             =head2 krb5_auth
867              
868             If you want to use kerberos authentication, then you need to call I.
869             This authentication mechanism is only available if you use Net::OpenSSH.
870              
871             set connection => "OpenSSH";
872             user "root";
873             krb5_auth;
874              
875             =cut
876              
877             sub krb5_auth {
878 0 0   0 1 0 if (wantarray) { return "krb5"; }
  0         0  
879 0         0 Rex::Config->set_krb5_auth(1);
880             }
881              
882             =head2 parallelism($count)
883              
884             Will execute the tasks in parallel on the given servers. $count is the thread count to be used:
885              
886             parallelism '2'; # set parallelism to 2
887              
888             Alternatively, the following notation can be used to set thread count more dynamically:
889              
890             parallelism 'max'; # set parallelism to the number of servers a task is asked to run on
891             parallelism 'max/3'; # set parallelism to 1/3 of the number of servers
892             parallelism 'max 10%'; # set parallelism to 10% of the number of servers
893              
894             If an unrecognized value is passed, or the calculated thread count would be less than 1, Rex falls back to use a single thread.
895              
896             =cut
897              
898             sub parallelism {
899 2     2 1 14 Rex::Config->set_parallelism( $_[0] );
900             }
901              
902             =head2 proxy_command($cmd)
903              
904             Set a proxy command to use for the connection. This is only possible with OpenSSH connection method.
905              
906             set connection => "OpenSSH";
907             proxy_command "ssh user@jumphost nc %h %p 2>/dev/null";
908              
909             =cut
910              
911             sub proxy_command {
912 0     0 1 0 Rex::Config->set_proxy_command( $_[0] );
913             }
914              
915             =head2 set_distributor($distributor)
916              
917             This sets the task distribution module. Default is "Base".
918              
919             Possible values are: Base, Gearman, Parallel_ForkManager
920              
921             =cut
922              
923             sub set_distributor {
924 0     0 1 0 Rex::Config->set_distributor( $_[0] );
925             }
926              
927             =head2 template_function(sub { ... })
928              
929             This function sets the template processing function. So it is possible to change the template engine. For example to Template::Toolkit.
930              
931             =cut
932              
933             sub template_function {
934 0     0 1 0 Rex::Config->set_template_function( $_[0] );
935             }
936              
937             =head2 logging
938              
939             With this function you can define the logging behaviour of (R)?ex.
940              
941             =over 4
942              
943             =item Logging to a file
944              
945             logging to_file => "rex.log";
946              
947             =item Logging to syslog
948              
949             logging to_syslog => $facility;
950              
951             =back
952              
953             =cut
954              
955             sub logging {
956 0     0 1 0 my $args;
957              
958 0 0 0     0 if ( $_[0] eq "-nolog" || $_[0] eq "nolog" ) {
959 0 0       0 $Rex::Logger::silent = 1 unless $Rex::Logger::debug;
960 0         0 return;
961             }
962             else {
963 0         0 $args = {@_};
964             }
965              
966 0 0       0 if ( exists $args->{'to_file'} ) {
    0          
967 0         0 Rex::Config->set_log_filename( $args->{'to_file'} );
968             }
969             elsif ( exists $args->{'to_syslog'} ) {
970 0         0 Rex::Config->set_log_facility( $args->{'to_syslog'} );
971             }
972             else {
973 0         0 Rex::Config->set_log_filename('rex.log');
974             }
975             }
976              
977             =head2 needs($package [, @tasks])
978              
979             With I you can define dependencies between tasks. The "needed" tasks will be called with the same server configuration as the calling task.
980              
981             I will not execute before, around and after hooks.
982              
983             =over 4
984              
985             =item Depend on all tasks in a given package.
986              
987             Depend on all tasks in the package MyPkg. All tasks will be called with the server I.
988              
989             task "mytask", "server1", sub {
990             needs MyPkg;
991             };
992              
993             =item Depend on a single task in a given package.
994              
995             Depend on the I task in the package MyPkg. The I task will be called with the server I.
996              
997             task "mytask", "server1", sub {
998             needs MyPkg "uname";
999             };
1000              
1001             =item To call tasks defined in the Rexfile from within a module
1002              
1003             task "mytask", "server1", sub {
1004             needs main "uname";
1005             };
1006              
1007              
1008             =back
1009              
1010             =cut
1011              
1012             sub needs {
1013 5     5 1 207 my ( $self, @args ) = @_;
1014              
1015             # if no namespace is given, use the current one
1016 5 50       922 if ( ref($self) eq "ARRAY" ) {
1017 0         0 @args = @{$self};
  0         0  
1018 0         0 ($self) = caller;
1019             }
1020              
1021 5 50       46 if ( $self eq "main" ) {
1022 0         0 $self = ""; # Tasks in main namespace are really registered in Rex::CLI
1023             }
1024              
1025 5         229 my $tl = Rex::TaskList->create();
1026 5         22 my @maybe_tasks_to_run;
1027 5 50       20 if ($self) {
1028 5         439 @maybe_tasks_to_run = $tl->get_all_tasks(qr{^\Q$self\E:[A-Za-z0-9_\-]+$});
1029             }
1030             else {
1031 0         0 @maybe_tasks_to_run = $tl->get_all_tasks(qr{^[A-Za-z0-9_\-]+$});
1032             }
1033              
1034 5 100 100     64 if ( !@args && !@maybe_tasks_to_run ) {
1035 1         4 @args = ($self);
1036 1         5 ($self) = caller;
1037 1 50       31 $self = "" if ( $self =~ m/^(Rex::CLI|main)$/ );
1038             }
1039              
1040 5 50       31 if ( ref( $args[0] ) eq "ARRAY" ) {
1041 0         0 @args = @{ $args[0] };
  0         0  
1042             }
1043              
1044 5         34 Rex::Logger::debug("need to call tasks from $self");
1045              
1046 5         74 $self =~ s/^Rex:://g;
1047 5         31 $self =~ s/::/:/g;
1048              
1049 5         16 my @tasks_to_run;
1050 5 100       24 if ($self) {
1051 4         137 @tasks_to_run = $tl->get_all_tasks(qr{^\Q$self\E:[A-Za-z0-9_\-]+$});
1052             }
1053             else {
1054 1         6 @tasks_to_run = $tl->get_all_tasks(qr{^[A-Za-z0-9_\-]+$});
1055             }
1056              
1057 5         188 my $run_list = Rex::RunList->instance;
1058 5         64 my $current_task = $run_list->current_task;
1059 5         47 my %task_opts = $current_task->get_opts;
1060 5         45 my @task_args = $current_task->get_args;
1061              
1062 5 100       21 if ($self) {
1063 4         11 my $suffix = $self;
1064 4         12 $suffix =~ s/::/:/g;
1065 4         20 @args = map { "$suffix:$_" } @args;
  3         22  
1066             }
1067              
1068 5         62 for my $task (@tasks_to_run) {
1069 12         63 my $task_o = $tl->get_task($task);
1070 12         40 my $task_name = $task_o->name;
1071 12         39 my $suffix = $self . ":";
1072 12 100 100     306 if ( @args && grep ( /^\Q$task_name\E$/, @args ) ) {
    100          
1073 4         108 Rex::Logger::debug( "Calling " . $task_o->name );
1074 4         94 $task_o->run( "", params => \@task_args, args => \%task_opts );
1075             }
1076             elsif ( !@args ) {
1077 2         6 Rex::Logger::debug( "Calling " . $task_o->name );
1078 2         25 $task_o->run( "", params => \@task_args, args => \%task_opts );
1079             }
1080             }
1081              
1082             }
1083              
1084             # register needs in main namespace
1085             _register_needs_in_main_namespace();
1086              
1087             sub _register_needs_in_main_namespace {
1088 102     102   630 my ($caller_pkg) = caller(1);
1089              
1090 102 50       498 if ( !$caller_pkg ) {
1091 0         0 ($caller_pkg) = caller(0);
1092             }
1093              
1094 102 100 100     936 if ( $caller_pkg && ( $caller_pkg eq "Rex::CLI" || $caller_pkg eq "main" ) ) {
      66        
1095 56         285 my $ref_to_needs = qualify_to_ref( 'needs', 'main' );
1096 56         1919 *{$ref_to_needs} = \&needs;
  56         189  
1097             }
1098             }
1099              
1100             =head2 include Module::Name
1101              
1102             Include a module without registering its tasks.
1103              
1104             include qw/
1105             Module::One
1106             Module::Two
1107             /;
1108              
1109             =cut
1110              
1111             sub include {
1112 1     1 1 14 my (@mods) = @_;
1113              
1114 1         2 my $old_val = $dont_register_tasks;
1115 1         4 $dont_register_tasks = 1;
1116 1         4 for my $mod (@mods) {
1117 1         79 eval "require $mod";
1118 1 50       19 if ($@) { die $@; }
  0         0  
1119             }
1120 1         4 $dont_register_tasks = $old_val;
1121             }
1122              
1123             =head2 environment($name => $code)
1124              
1125             Define an environment. With environments one can use the same task for different hosts. For example if you want to use the same task on your integration-, test- and production servers.
1126              
1127             # define default user/password
1128             user "root";
1129             password "foobar";
1130             pass_auth;
1131              
1132             # define default frontend group containing only testwww01.
1133             group frontend => "testwww01";
1134              
1135             # define live environment, with different user/password
1136             # and a frontend server group containing www01, www02 and www03.
1137             environment live => sub {
1138             user "root";
1139             password "livefoo";
1140             pass_auth;
1141              
1142             group frontend => "www01", "www02", "www03";
1143             };
1144              
1145             # define stage environment with default user and password. but with
1146             # a own frontend group containing only stagewww01.
1147             environment stage => sub {
1148             group frontend => "stagewww01";
1149             };
1150              
1151             task "prepare", group => "frontend", sub {
1152             say run "hostname";
1153             };
1154              
1155             Calling this task I will execute on testwww01.
1156             Calling this task with I will execute on www01, www02, www03.
1157             Calling this task I will execute on stagewww01.
1158              
1159             You can call the function within a task to get the current environment.
1160              
1161             task "prepare", group => "frontend", sub {
1162             if(environment() eq "dev") {
1163             say "i'm in the dev environment";
1164             }
1165             };
1166              
1167             If no I<-E> option is passed on the command line, the default environment
1168             (named 'default') will be used.
1169              
1170             =cut
1171              
1172             sub environment {
1173 225 50   225 1 776 if (@_) {
1174 0         0 my ( $name, $code ) = @_;
1175 0   0     0 $environments->{$name} = {
1176             code => $code,
1177             description => $current_desc || '',
1178             name => $name,
1179             };
1180 0         0 $current_desc = "";
1181              
1182 0 0       0 if ( Rex::Config->get_environment eq $name ) {
1183 0         0 &$code();
1184             }
1185              
1186 0         0 return 1;
1187             }
1188             else {
1189 225   50     1736 return Rex::Config->get_environment || "default";
1190             }
1191             }
1192              
1193             =head2 LOCAL(&)
1194              
1195             With the LOCAL function you can do local commands within a task that is defined to work on remote servers.
1196              
1197             task "mytask", "server1", "server2", sub {
1198             # this will call 'uptime' on the servers 'server1' and 'server2'
1199             say run "uptime";
1200              
1201             # this will call 'uptime' on the local machine.
1202             LOCAL {
1203             say run "uptime";
1204             };
1205             };
1206              
1207             =cut
1208              
1209             sub LOCAL (&) {
1210 3     3 1 23 my $cur_conn = Rex::get_current_connection();
1211 3         100 my $local_connect = Rex::Interface::Connection->create("Local");
1212              
1213 3         18 my $old_global_sudo = $Rex::GLOBAL_SUDO;
1214 3         33 $Rex::GLOBAL_SUDO = 0;
1215              
1216             Rex::push_connection(
1217             {
1218             conn => $local_connect,
1219             ssh => 0,
1220             server => $cur_conn->{server},
1221 3         78 cache => Rex::Interface::Cache->create(),
1222             task => [ task() ],
1223             reporter => Rex::Report->create( Rex::Config->get_report_type ),
1224             notify => Rex::Notify->new(),
1225             }
1226             );
1227              
1228 3         15 my $ret = $_[0]->();
1229              
1230 3         91 Rex::pop_connection();
1231              
1232 3         37 $Rex::GLOBAL_SUDO = $old_global_sudo;
1233              
1234 3         371 return $ret;
1235             }
1236              
1237             =head2 path(@path)
1238              
1239             Set the execution path for all commands.
1240              
1241             path "/bin", "/sbin", "/usr/bin", "/usr/sbin", "/usr/pkg/bin", "/usr/pkg/sbin";
1242              
1243             It's a convenience wrapper for the L configuration option.
1244              
1245             =cut
1246              
1247             sub path {
1248 1     1 1 8 Rex::Config->set_path( [@_] );
1249             }
1250              
1251             =head2 set($key, $value)
1252              
1253             Set a configuration parameter. These variables can be used in templates as well.
1254              
1255             set database => "db01";
1256              
1257             task "prepare", sub {
1258             my $db = get "database";
1259             };
1260              
1261             Or in a template
1262              
1263             DB: <%= $::database %>
1264              
1265             The following list of configuration parameters are Rex specific:
1266              
1267             =over
1268              
1269             =back
1270              
1271              
1272             =cut
1273              
1274             sub set {
1275 125     125 1 47035 my ( $key, @value ) = @_;
1276 125         923 Rex::Config->set( $key, @value );
1277             }
1278              
1279             =head2 get($key, $value)
1280              
1281             Get a configuration parameter.
1282              
1283             set database => "db01";
1284              
1285             task "prepare", sub {
1286             my $db = get "database";
1287             };
1288              
1289             Or in a template
1290              
1291             DB: <%= $::database %>
1292              
1293             =cut
1294              
1295             sub get {
1296 114     114 1 605 my ($key) = @_;
1297              
1298 114 100       593 if ( ref($key) eq "Rex::Value" ) {
1299 18         79 return $key->value;
1300             }
1301              
1302 96         1227 return Rex::Config->get($key);
1303             }
1304              
1305             =head2 before($task => sub {})
1306              
1307             Run code before executing the specified task.
1308              
1309             The task name is a regular expression to find all tasks with a matching name. The special task name C<'ALL'> can also be used to run code before all tasks.
1310              
1311             If called repeatedly, each sub will be appended to a list of 'before' functions.
1312              
1313             In this hook you can overwrite the server to which the task will connect to. The second argument is a reference to the
1314             server object that will be used for the connection.
1315              
1316             Please note, this must come after the definition of the specified task.
1317              
1318             before mytask => sub {
1319             my ($server, $server_ref, $cli_args) = @_;
1320             run "vzctl start vm$server";
1321             };
1322              
1323             =cut
1324              
1325             sub before {
1326 43     43 1 494 my ( $task, $code ) = @_;
1327              
1328 43 100       134 if ( $task eq "ALL" ) {
1329 7         48 $task = qr{.*};
1330             }
1331              
1332 43         143 my ( $package, $file, $line ) = caller;
1333 43         185 Rex::TaskList->create()
1334             ->modify( 'before', $task, $code, $package, $file, $line );
1335             }
1336              
1337             =head2 after($task => sub {})
1338              
1339             Run code after executing the specified task.
1340              
1341             The task name is a regular expression to find all tasks with a matching name. The special task name C<'ALL'> can be used to run code after all tasks.
1342              
1343             If called repeatedly, each sub will be appended to a list of 'after' functions.
1344              
1345             Please note, this must come after the definition of the specified task.
1346              
1347             after mytask => sub {
1348             my ($server, $failed, $cli_args) = @_;
1349             if($failed) { say "Connection to $server failed."; }
1350              
1351             run "vzctl stop vm$server";
1352             };
1353              
1354             =cut
1355              
1356             sub after {
1357 12     12 1 120 my ( $task, $code ) = @_;
1358              
1359 12 100       52 if ( $task eq "ALL" ) {
1360 6         34 $task = qr{.*};
1361             }
1362              
1363 12         44 my ( $package, $file, $line ) = caller;
1364              
1365 12         108 Rex::TaskList->create()
1366             ->modify( 'after', $task, $code, $package, $file, $line );
1367             }
1368              
1369             =head2 around($task => sub {})
1370              
1371             Run code around the specified task (that is both before and after executing it).
1372              
1373             The task name is a regular expression to find all tasks with a matching name. The special task name C<'ALL'> can be used to run code around all tasks.
1374              
1375             If called repeatedly, each sub will be appended to a list of 'around' functions.
1376              
1377             In this hook you can overwrite the server to which the task will connect to. The second argument is a reference to the
1378             server object that will be used for the connection.
1379              
1380             Please note, this must come after the definition of the specified task.
1381              
1382             around mytask => sub {
1383             my ($server, $server_ref, $cli_args, $position) = @_;
1384              
1385             unless($position) {
1386             say "Before Task\n";
1387             }
1388             else {
1389             say "After Task\n";
1390             }
1391             };
1392              
1393             =cut
1394              
1395             sub around {
1396 0     0 1 0 my ( $task, $code ) = @_;
1397              
1398 0 0       0 if ( $task eq "ALL" ) {
1399 0         0 $task = qr{.*};
1400             }
1401              
1402 0         0 my ( $package, $file, $line ) = caller;
1403              
1404 0         0 Rex::TaskList->create()
1405             ->modify( 'around', $task, $code, $package, $file, $line );
1406             }
1407              
1408             =head2 before_task_start($task => sub {})
1409              
1410             Run code before executing the specified task. This gets executed only once for a task.
1411              
1412             The task name is a regular expression to find all tasks with a matching name. The special task name C<'ALL'> can be used to run code before all tasks.
1413              
1414             If called repeatedly, each sub will be appended to a list of 'before_task_start' functions.
1415              
1416             Please note, this must come after the definition of the specified task.
1417              
1418             before_task_start mytask => sub {
1419             # do some things
1420             };
1421              
1422             =cut
1423              
1424             sub before_task_start {
1425 16     16 1 198 my ( $task, $code ) = @_;
1426              
1427 16 100       59 if ( $task eq "ALL" ) {
1428 6         64 $task = qr{.*};
1429             }
1430              
1431 16         71 my ( $package, $file, $line ) = caller;
1432 16         112 Rex::TaskList->create()
1433             ->modify( 'before_task_start', $task, $code, $package, $file, $line );
1434             }
1435              
1436             =head2 after_task_finished($task => sub {})
1437              
1438             Run code after the task is finished (and after the ssh connection is terminated). This gets executed only once for a task.
1439              
1440             The task name is a regular expression to find all tasks with a matching name. The special task name C<'ALL'> can be used to run code after all tasks.
1441              
1442             If called repeatedly, each sub will be appended to a list of 'after_task_finished' functions.
1443              
1444             Please note, this must come after the definition of the specified task.
1445              
1446             after_task_finished mytask => sub {
1447             # do some things
1448             };
1449              
1450             =cut
1451              
1452             sub after_task_finished {
1453 14     14 1 201 my ( $task, $code ) = @_;
1454              
1455 14 100       66 if ( $task eq "ALL" ) {
1456 6         26 $task = qr{.*};
1457             }
1458              
1459 14         49 my ( $package, $file, $line ) = caller;
1460 14         54 Rex::TaskList->create()
1461             ->modify( 'after_task_finished', $task, $code, $package, $file, $line );
1462             }
1463              
1464             =head2 logformat($format)
1465              
1466             You can define the logging format with the following parameters.
1467              
1468             %D - Appends the current date yyyy-mm-dd HH:mm:ss
1469              
1470             %h - The target host
1471              
1472             %p - The pid of the running process
1473              
1474             %l - Loglevel (INFO or DEBUG)
1475              
1476             %s - The Logstring
1477              
1478             Default is: [%D] %l - %s
1479              
1480             =cut
1481              
1482             sub logformat {
1483 0     0 1 0 my ($format) = @_;
1484 0         0 $Rex::Logger::format = $format;
1485             }
1486              
1487 0     0 0 0 sub log_format { logformat(@_); }
1488              
1489             =head2 connection
1490              
1491             This function returns the current connection object.
1492              
1493             task "foo", group => "baz", sub {
1494             say "Current Server: " . connection->server;
1495             };
1496              
1497             =cut
1498              
1499             sub connection {
1500 179     179 1 584 return Rex::get_current_connection()->{conn};
1501             }
1502              
1503             =head2 cache
1504              
1505             This function returns the current cache object.
1506              
1507             =cut
1508              
1509             sub cache {
1510 0     0 1 0 my ($type) = @_;
1511              
1512 0 0       0 if ( !$type ) {
1513 0         0 return Rex::get_cache();
1514             }
1515              
1516 0         0 Rex::Config->set_cache_type($type);
1517             }
1518              
1519             =head2 profiler
1520              
1521             Returns the profiler object for the current connection.
1522              
1523             =cut
1524              
1525             sub profiler {
1526 2472     2472 1 28001 my $c_profiler = Rex::get_current_connection()->{"profiler"};
1527 2472 100       8786 unless ($c_profiler) {
1528 2380   66     9712 $c_profiler = $profiler || Rex::Profiler->new;
1529 2380         10030 $profiler = $c_profiler;
1530             }
1531              
1532 2472         46155 return $c_profiler;
1533             }
1534              
1535             =head2 report($switch, $type)
1536              
1537             This function will initialize the reporting.
1538              
1539             report -on => "YAML";
1540              
1541             =cut
1542              
1543             sub report {
1544 1     1 1 16 my ( $str, $type ) = @_;
1545              
1546 1   50     5 $type ||= "Base";
1547 1         22 Rex::Config->set_report_type($type);
1548              
1549 1 50 33     58 if ( $str && ( $str eq "-on" || $str eq "on" ) ) {
    0 33        
      0        
      0        
1550 1         8 Rex::Config->set_do_reporting(1);
1551 1         3 return;
1552             }
1553             elsif ( $str && ( $str eq "-off" || $str eq "off" ) ) {
1554 0         0 Rex::Config->set_do_reporting(0);
1555 0         0 return;
1556             }
1557              
1558 0         0 return Rex::get_current_connection()->{reporter};
1559             }
1560              
1561             =head2 source_global_profile(0|1)
1562              
1563             If this option is set, every run() command will first source /etc/profile before getting executed.
1564              
1565             =cut
1566              
1567             sub source_global_profile {
1568 0     0 1 0 my ($source) = @_;
1569 0         0 Rex::Config->set_source_global_profile($source);
1570             }
1571              
1572             =head2 last_command_output
1573              
1574             This function returns the output of the last "run" command.
1575              
1576             On a debian system this example will return the output of I.
1577              
1578             task "mytask", "myserver", sub {
1579             install "foobar";
1580             say last_command_output();
1581             };
1582              
1583             =cut
1584              
1585             sub last_command_output {
1586 2     2 1 51 return $Rex::Commands::Run::LAST_OUTPUT->[0];
1587             }
1588              
1589             =head2 case($compare, $option)
1590              
1591             This is a function to compare a string with some given options.
1592              
1593             task "mytask", "myserver", sub {
1594             my $ntp_service = case operating_system, {
1595             Debian => "ntp",
1596             default => "ntpd",
1597             };
1598              
1599             my $ntp_service = case operating_system, {
1600             qr{debian}i => "ntp",
1601             default => "ntpd",
1602             };
1603              
1604             my $ntp_service = case operating_system, {
1605             qr{debian}i => "ntp",
1606             default => sub { return "foo"; },
1607             };
1608             };
1609              
1610             =cut
1611              
1612             sub case {
1613 8     8 1 3625 my ( $compare, $option ) = @_;
1614              
1615 8         17 my $to_return = undef;
1616              
1617 8 100       23 if ( exists $option->{$compare} ) {
1618 2         5 $to_return = $option->{$compare};
1619             }
1620             else {
1621 6         10 for my $key ( keys %{$option} ) {
  6         22  
1622 11 100       137 if ( $compare =~ $key ) {
1623 2         5 $to_return = $option->{$key};
1624 2         5 last;
1625             }
1626             }
1627             }
1628              
1629 8 100 100     47 if ( exists $option->{default} && !$to_return ) {
1630 3         8 $to_return = $option->{default};
1631             }
1632              
1633 8 100       40 if ( ref $to_return eq "CODE" ) {
1634 3         7 $to_return = &$to_return();
1635             }
1636              
1637 8         33 return $to_return;
1638             }
1639              
1640             =head2 set_executor_for($type, $executor)
1641              
1642             Set the executor for a special type. This is primary used for the upload_and_run helper function.
1643              
1644             set_executor_for perl => "/opt/local/bin/perl";
1645              
1646             =cut
1647              
1648             sub set_executor_for {
1649 0     0 1 0 Rex::Config->set_executor_for(@_);
1650             }
1651              
1652             =head2 tmp_dir($tmp_dir)
1653              
1654             Set the tmp directory on the remote host to store temporary files.
1655              
1656             =cut
1657              
1658             sub tmp_dir {
1659 0     0 1 0 Rex::Config->set_tmp_dir(@_);
1660             }
1661              
1662             =head2 inspect($varRef)
1663              
1664             This function dumps the contents of a variable to STDOUT.
1665              
1666             task "mytask", "myserver", sub {
1667             my $myvar = {
1668             name => "foo",
1669             sys => "bar",
1670             };
1671              
1672             inspect $myvar;
1673             };
1674              
1675             =cut
1676              
1677             my $depth = 0;
1678              
1679             sub _dump_hash {
1680 0     0   0 my ( $hash, $option ) = @_;
1681              
1682 0 0 0     0 unless ( $depth == 0 && exists $option->{no_root} && $option->{no_root} ) {
      0        
1683 0         0 print "{\n";
1684             }
1685 0         0 $depth++;
1686              
1687 0         0 for my $key ( keys %{$hash} ) {
  0         0  
1688 0         0 _print_indent($option);
1689 0 0       0 if ( exists $option->{prepend_key} ) { print $option->{prepend_key}; }
  0         0  
1690             print "$key"
1691 0 0       0 . ( exists $option->{key_value_sep} ? $option->{key_value_sep} : " => " );
1692 0         0 _dump_var( $hash->{$key} );
1693             }
1694              
1695 0         0 $depth--;
1696 0         0 _print_indent($option);
1697              
1698 0 0 0     0 unless ( $depth == 0 && exists $option->{no_root} && $option->{no_root} ) {
      0        
1699 0         0 print "}\n";
1700             }
1701             }
1702              
1703             sub _dump_array {
1704 0     0   0 my ( $array, $option ) = @_;
1705              
1706 0 0 0     0 unless ( $depth == 0 && exists $option->{no_root} && $option->{no_root} ) {
      0        
1707 0         0 print "[\n";
1708             }
1709 0         0 $depth++;
1710              
1711 0         0 for my $itm ( @{$array} ) {
  0         0  
1712 0         0 _print_indent($option);
1713 0         0 _dump_var($itm);
1714             }
1715              
1716 0         0 $depth--;
1717 0         0 _print_indent($option);
1718              
1719 0 0 0     0 unless ( $depth == 0 && exists $option->{no_root} && $option->{no_root} ) {
      0        
1720 0         0 print "]\n";
1721             }
1722             }
1723              
1724             sub _print_indent {
1725 0     0   0 my ($option) = @_;
1726 0 0 0     0 unless ( $depth == 1 && exists $option->{no_root} && $option->{no_root} ) {
      0        
1727 0         0 print " " x $depth;
1728             }
1729             }
1730              
1731             sub _dump_var {
1732 0     0   0 my ( $var, $option ) = @_;
1733              
1734 0 0       0 if ( ref $var eq "HASH" ) {
    0          
1735 0         0 _dump_hash( $var, $option );
1736             }
1737             elsif ( ref $var eq "ARRAY" ) {
1738 0         0 _dump_array( $var, $option );
1739             }
1740             else {
1741 0 0       0 if ( defined $var ) {
1742 0         0 $var =~ s/\n/\\n/gms;
1743 0         0 $var =~ s/\r/\\r/gms;
1744 0         0 $var =~ s/'/\\'/gms;
1745              
1746 0         0 print "'$var'\n";
1747             }
1748             else {
1749 0         0 print "no value\n";
1750             }
1751             }
1752             }
1753              
1754             sub inspect {
1755 0     0 1 0 _dump_var(@_);
1756             }
1757              
1758             ######### private functions
1759              
1760             sub evaluate_hostname {
1761 47     47 0 10188 my $str = shift;
1762 47 50       126 return unless $str;
1763              
1764             # e.g. server[0..4/2].domain.com
1765 47         303 my ( $start, $rule, $end ) = $str =~ m{
1766             ^
1767             ([0-9\.\w\-:]*) # prefix (e.g. server)
1768             \[ # rule -> 0..4 | 0..4/2 | 0,2,4
1769             (
1770             (?: \d+ \.\. \d+ # range-rule e.g. 0..4
1771             (?:\/ \d+ )? # step for range-rule
1772             ) |
1773             (?:
1774             (?:
1775             \d+ (?:,\s*)?
1776             ) |
1777             (?: \d+ \.\. \d+
1778             (?: \/ \d+ )?
1779             (?:,\s*)?
1780             )
1781             )+ # list
1782             )
1783             \] # end of rule
1784             ([0-9\w\.\-:]+)? # suffix (e.g. .domain.com)
1785             $
1786             }xms;
1787              
1788 47 100       119 if ( !defined $rule ) {
1789 25         74 return $str;
1790             }
1791              
1792 22         48 my @ret;
1793 22 100       97 if ( $rule =~ m/,/ ) {
    100          
1794 5         19 @ret = _evaluate_hostname_list( $start, $rule, $end );
1795             }
1796             elsif ( $rule =~ m/[.]{2}/msx ) {
1797 16         54 @ret = _evaluate_hostname_range( $start, $rule, $end );
1798             }
1799             else {
1800 1         18 croak('Invalid hostgroup expression');
1801             }
1802              
1803 21         82 return @ret;
1804             }
1805              
1806             sub _evaluate_hostname_range {
1807 24     24   54 my ( $start, $rule, $end ) = @_;
1808              
1809 24         135 my ( $from, $to, $step ) = $rule =~ m{(\d+) \.\. (\d+) (?:/(\d+))?}xms;
1810              
1811 24   100     96 $end ||= '';
1812 24   100     99 $step ||= 1;
1813              
1814 24         37 my $strict_length = 0;
1815 24 100       73 if ( length $from == length $to ) {
1816 21         36 $strict_length = length $to;
1817             }
1818              
1819 24         39 my @ret = ();
1820 24         78 for ( ; $from <= $to ; $from += $step ) {
1821 111         210 my $format = "%0" . $strict_length . "i";
1822 111         412 push @ret, $start . sprintf( $format, $from ) . $end;
1823             }
1824              
1825 24         107 return @ret;
1826             }
1827              
1828             sub _evaluate_hostname_list {
1829 5     5   14 my ( $start, $rule, $end ) = @_;
1830              
1831 5         28 my @values = split /,\s*/, $rule;
1832              
1833 5   100     20 $end ||= '';
1834              
1835 5         9 my @ret;
1836 5         21 for my $value (@values) {
1837 13 100       55 if ( $value =~ m{\d+\.\.\d+(?:/\d+)?} ) {
1838 8         24 push @ret, _evaluate_hostname_range( $start, $value, $end );
1839             }
1840             else {
1841 5         11 push @ret, "$start$value$end";
1842             }
1843             }
1844              
1845 5         22 return @ret;
1846             }
1847              
1848             sub exit {
1849 0     0 0 0 Rex::Logger::info("Exiting Rex...");
1850 0         0 Rex::Logger::info("Cleaning up...");
1851              
1852 0         0 Rex::global_sudo(0);
1853 0 0       0 unlink("$::rexfile.lock") if ($::rexfile);
1854 0   0     0 CORE::exit( $_[0] || 0 );
1855             }
1856              
1857             sub get_environment {
1858 0     0 0 0 my ( $class, $env ) = @_;
1859              
1860 0 0       0 if ( exists $environments->{$env} ) {
1861 0         0 return $environments->{$env};
1862             }
1863             }
1864              
1865             sub get_environments {
1866 39     39 0 140 my $class = shift;
1867              
1868 39         107 my @ret = sort { $a cmp $b } keys %{$environments};
  0         0  
  39         311  
1869 39         133 return @ret;
1870             }
1871              
1872             =head2 sayformat($format)
1873              
1874             You can define the format of the say() function.
1875              
1876             %D - The current date yyyy-mm-dd HH:mm:ss
1877              
1878             %h - The target host
1879              
1880             %p - The pid of the running process
1881              
1882             %s - The Logstring
1883              
1884             You can also define the following values:
1885              
1886             default - the default behaviour.
1887              
1888             asis - will print every single parameter in its own line. This is useful if you want to print the output of a command.
1889              
1890             =cut
1891              
1892             sub sayformat {
1893 0     0 1 0 my ($format) = @_;
1894 0         0 Rex::Config->set_say_format($format);
1895             }
1896              
1897 0     0 0 0 sub say_format { sayformat(@_); }
1898              
1899             sub say {
1900 0     0 0 0 my (@data) = @_;
1901              
1902 0 0       0 return unless defined $_[0];
1903              
1904 0         0 my $format = Rex::Config->get_say_format;
1905 0 0 0     0 if ( !defined $format || $format eq "default" ) {
1906 0         0 print @_, "\n";
1907 0         0 return;
1908             }
1909              
1910 0 0       0 if ( $format eq "asis" ) {
1911 0         0 print join( "\n", @_ );
1912 0         0 return;
1913             }
1914              
1915 0         0 for my $line (@data) {
1916 0         0 print _format_string( $format, $line ) . "\n";
1917             }
1918              
1919             }
1920              
1921             # %D - Date
1922             # %h - Host
1923             # %s - Logstring
1924             sub _format_string {
1925 0     0   0 my ( $format, $line ) = @_;
1926              
1927 0         0 my $date = _get_timestamp();
1928             my $host =
1929             Rex::get_current_connection()
1930             ? Rex::get_current_connection()->{conn}->server
1931 0 0       0 : "";
1932 0         0 my $pid = $$;
1933              
1934 0         0 $format =~ s/\%D/$date/gms;
1935 0         0 $format =~ s/\%h/$host/gms;
1936 0         0 $format =~ s/\%s/$line/gms;
1937 0         0 $format =~ s/\%p/$pid/gms;
1938              
1939 0         0 return $format;
1940             }
1941              
1942             sub _get_timestamp {
1943 0     0   0 my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) =
1944             localtime(time);
1945 0         0 $mon++;
1946 0         0 $year += 1900;
1947              
1948             return
1949 0         0 "$year-"
1950             . sprintf( "%02i", $mon ) . "-"
1951             . sprintf( "%02i", $mday ) . " "
1952             . sprintf( "%02i", $hour ) . ":"
1953             . sprintf( "%02i", $min ) . ":"
1954             . sprintf( "%02i", $sec );
1955             }
1956              
1957             sub TRUE {
1958 32     32 0 684 return 1;
1959             }
1960              
1961             sub FALSE {
1962 8     8 0 6152 return 0;
1963             }
1964              
1965             sub make(&) {
1966 1     1 0 11 return $_[0];
1967             }
1968              
1969             1;