File Coverage

blib/lib/Tapper/CLI/Testrun.pm
Criterion Covered Total %
statement 14 399 3.5
branch 0 176 0.0
condition 0 52 0.0
subroutine 5 24 20.8
pod 19 19 100.0
total 38 670 5.6


line stmt bran cond sub pod time code
1             package Tapper::CLI::Testrun;
2             our $AUTHORITY = 'cpan:TAPPER';
3             $Tapper::CLI::Testrun::VERSION = '5.0.6';
4              
5 1     1   968 use 5.010;
  1         3  
6 1     1   6 use warnings;
  1         1  
  1         24  
7 1     1   6 use strict;
  1         2  
  1         22  
8 1     1   5 use feature qw/ say /;
  1         2  
  1         133  
9 1     1   7 use English qw/ -no_match_vars /;
  1         2  
  1         15  
10              
11             # list limit default value
12             my $i_limit_default = 50;
13              
14              
15             sub b_print_single_testrun {
16              
17 0     0 1   my ( $or_testrun ) = @_;
18              
19 0           print "\n";
20 0           printf "%17s: %s\n", 'Id' , $or_testrun->id;
21 0           printf "%17s: %s\n", 'Topic', $or_testrun->topic_name;
22              
23 0 0         if ( $or_testrun->shortname ) {
24 0           printf "%17s: %s\n", 'Shortname', $or_testrun->shortname;
25             }
26 0 0         if ( $or_testrun->testrun_scheduling ) {
27              
28 0           require Tapper::Cmd::Testrun;
29 0           my $or_cmd = Tapper::Cmd::Testrun->new();
30 0           my $hr_testrun_details = $or_cmd->status($or_testrun->id);
31 0           printf "%17s: %s\n", 'State', $hr_testrun_details->{status};
32 0           printf "%17s: %s\n", 'Queue', $or_testrun->testrun_scheduling->queue->name;
33              
34 0 0         if ( $or_testrun->testrun_scheduling->status eq 'schedule' ) {
35 0 0         if ( $or_testrun->testrun_scheduling->requested_hosts->count ) {
36 0           printf "%17s: %s\n", q#Requested Host's#, join ",", $or_testrun->testrun_scheduling->requested_hosts->related_resultset('host')->get_column('name')->all;
37             }
38             }
39             else {
40 0 0 0       if (
41             $or_testrun->testrun_scheduling->host &&
42             $or_testrun->testrun_scheduling->host->name
43             ) {
44 0           printf "%17s: %s\n", 'Used Host', $or_testrun->testrun_scheduling->host->name;
45             }
46             }
47              
48 0 0         printf "%17s: %s\n", 'Auto rerun', $or_testrun->testrun_scheduling->auto_rerun ? 'yes' : 'no';
49              
50             }
51             else {
52 0           printf "%17s: %s\n", q##, 'Old testrun without scheduling information';
53             }
54              
55 0 0         if ( $or_testrun->notes ) {
56 0           printf "%17s: %s\n", 'Notes', $or_testrun->notes;
57             }
58              
59 0           printf "%17s: ", q#Precondition Id's#;
60 0 0         if ( my @a_preconditions = $or_testrun->ordered_preconditions ) {
61 0           say join ", ", map {$_->id} @a_preconditions;
  0            
62             }
63             else {
64 0           say 'None';
65             }
66              
67 0           return 1;
68              
69             }
70              
71              
72             sub b_print_testruns {
73              
74 0     0 1   my ( $or_testruns ) = @_;
75              
76 0 0         if ( $or_testruns->isa('DBIx::Class::ResultSet') ) {
77 0           for my $or_testrun ( $or_testruns->all ) {
78 0           b_print_single_testrun( $or_testrun );
79             }
80             }
81             else {
82 0           b_print_single_testrun( $or_testruns );
83             }
84 0           print "\n";
85              
86 0           return 1;
87              
88             }
89              
90              
91             sub ar_get_list_testrun_parameters {
92             return [
93 0     0 1   [ 'id|i=i@' , 'list particular testruns', 'Can be given multiple times.', ],
94             [ 'finished|f', 'list finished testruns, OR combined with other state filters', ],
95             [ 'running|r' , 'list running testruns, OR combined with other state filters', ],
96             [ 'schedule|s', 'list scheduled testruns, OR combined with other state filters', ],
97             [ 'prepare|p' , 'list testruns not yet in any scheduling queue, OR combined with other state filters', ],
98             [ 'queue|q=s@', 'list testruns assigned to this queue, OR combined with other queues, AND combined with other filters', ],
99             [ 'host|h=s@' , 'list testruns assigned to this queue, OR combined with other hosts, AND combined with other filters', ],
100             [ 'limit|l=i' , "limit the number of testruns (default = $i_limit_default). A value smaller than 1 deactivates the limit.", ],
101             [ 'verbose|v' , 'print all output, without only print ids', ],
102             [ 'help|?' , 'Print this help message and exit.', ],
103             ];
104             }
105              
106              
107             sub ar_get_rerun_testrun_parameters {
108             return [
109 0     0 1   [ 'id|i=i@' , 'rerun particular testruns', 'Can be given multiple times.', ],
110             [ 'notes|n=s' , 'add a description for new testruns', ],
111             [ 'verbose|v' , 'print all output, without only print ids', ],
112             [ 'help|?' , 'Print this help message and exit.', ],
113             ];
114             }
115              
116              
117             sub ar_get_delete_testrun_parameters {
118             return [
119 0     0 1   [ 'id|i=i@' , 'delete particular testruns', 'Can be given multiple times.', ],
120             [ 'force|f' , 'really execute the command', ],
121             [ 'verbose|v', 'print all output, without only print ids', ],
122             [ 'help|?' , 'Print this help message and exit.', ],
123             ];
124             }
125              
126              
127             sub ar_get_create_testrun_parameters {
128             return [
129             [
130 0     0 1   'macroprecond|m=s',
131             'use this macro precondition file',
132             ],[
133             'precondition|p=i@',
134             'assigned precondition ids',
135             ],[
136             'owner|o=s',
137             'default=$USER; user login name',
138             ],[
139             'topic|t=s',
140             'default=Misc; one of: Kernel, Xen, KVM, Hardware, Distribution, Benchmark, Software, Misc',
141             ],[
142             'queue|q=s',
143             'default=AdHoc',
144             ],[
145             'notes|n=s',
146             'notes',
147             ],[
148             'rerun_on_error=i',
149             'retry this testrun this many times if an error occurs',
150             ],[
151             'shortname|s=s',
152             'shortname',
153             ],[
154             'earliest|e=s',
155             q#default=now; don't start testrun before this time (format: YYYY-MM-DD hh:mm:ss or now)#,
156             ],[
157             'requested_host|rh=s@',
158             'String; name one possible host for this testrequest;',
159             'multiple requested hosts are OR evaluated, i.e. each is appropriate',
160             ],[
161             'requested_feature|rf=s@',
162             'description of one requested feature of a matching host for this testrequest;',
163             'multiple requested features are AND evaluated, i.e. each must fit;',
164             'not evaluated if a matching requested host is found already',
165             ],[
166             'notify:s',
167             q#create a notification for when the testrun is finished, possibly with filter for 'fail' or 'success'#,
168             ],[
169             'wait_after_tests',
170             'default=0; wait after testrun for human investigation',
171             ],[
172             'verbose|v',
173             'some more informational output',
174             ],[
175             'dryrun',
176             'default=0; only print the preconditions to stdout and then exit',
177             ],[
178             'auto_rerun',
179             'default=0; put this testrun into db again when it is chosen by scheduler',
180             ],[
181             'priority',
182             'This is a very important testrun that should bypass scheduling and not wait for others',
183             ],[
184             'D=s%',
185             'Define a key=value pair used in macro preconditions',
186             ],[
187             'help|?',
188             'Print this help message and exit',
189             ],
190             ];
191             }
192              
193              
194             sub create_macro_preconditions {
195              
196 0     0 1   my ( $hr_options ) = @_;
197              
198 0           my $hr_d = $hr_options->{D}; # options are auto-down-cased
199 0           my $b_dryrun = $hr_options->{dryrun};
200 0           my $s_ttapplied = $hr_options->{macroprecond_evaluated};
201              
202 0 0         if ($b_dryrun) {
203 0           print $s_ttapplied;
204 0           exit 0;
205             }
206              
207 0           require Tapper::Cmd::Precondition;
208 0           return Tapper::Cmd::Precondition->new->add( $s_ttapplied );
209              
210             }
211              
212              
213             sub s_create_testrun_parameter_check {
214              
215 0     0 1   my ( $hr_options ) = @_;
216              
217 0 0 0       if ( !$hr_options->{precondition} && !$hr_options->{macroprecond} ) {
218 0           return q#At least one of "precondition" or "macroprecond" is required#;
219             }
220 0 0 0       if ( exists $hr_options->{rerun_on_error} && $hr_options->{rerun_on_error} !~ /^\d+$/ ) {
221 0           return "value for rerun_on_error ($hr_options->{rerun_on_error}) is not an integer value";
222             }
223 0 0         if ( $hr_options->{earliest} ) {
224 0           require DateTime::Format::Natural;
225 0           my $or_parser = DateTime::Format::Natural->new;
226 0           $hr_options->{earliest} = $or_parser->parse_datetime( $hr_options->{earliest} );
227 0 0         if ( $or_parser->success ) {
228 0 0         if ( $hr_options->{verbose} ) {
229 0           say $hr_options->{earliest}->strftime('%d.%m.%Y %T');
230             }
231             }
232             else {
233 0           return $or_parser->error;
234             }
235             }
236              
237 0           require Tapper::Model;
238 0 0         if ( $hr_options->{requested_host} ) {
239 0           for my $i_counter ( 0..$#{$hr_options->{requested_host}} ) {
  0            
240 0 0         if (
241             my $or_host =
242             Tapper::Model::model('TestrunDB')
243             ->resultset('Host')
244             ->search(
245             { name => $hr_options->{requested_host}[$i_counter] },
246             { rows => 1 },
247             )
248             ->first
249             ) {
250 0           $hr_options->{requested_host}[$i_counter] = $or_host->id;
251             }
252             else {
253 0           die "Host '$hr_options->{requested_host}[$i_counter]' does not exist\n";
254             }
255             }
256             }
257 0 0         if ( $hr_options->{notify} ) {
258 0           $hr_options->{notify} = lc $hr_options->{notify};
259 0 0         if (! grep { $hr_options->{notify} eq $_ } qw/ pass fail / ) {
  0            
260 0           die "invalid value for 'notify': valid values 'pass', 'fail'\n";
261             }
262             }
263              
264 0           require File::Slurp;
265 0 0         if ( $hr_options->{macroprecond} ) {
266 0 0         if ( -e $hr_options->{macroprecond} ) {
267              
268 0           require Tapper::Cmd;
269 0           my $or_cmd = Tapper::Cmd->new;
270 0           my $s_mpc_file = $hr_options->{macroprecond};
271 0           my $hr_d = $hr_options->{D};
272              
273 0           $hr_options->{macroprecond_evaluated} = $or_cmd->apply_macro($s_mpc_file, $hr_d);
274 0 0         if ( (my $s_required) = $hr_options->{macroprecond_evaluated} =~/^# (?:tapper[_-])?mandatory[_-]fields:\s*(.+)/m ) {
275 0           my $re_delim = qr/,+\s*/;
276 0           foreach my $s_field ( split $re_delim, $s_required ) {
277 0           $s_field =~ s/\s+//g;
278 0           my ( $s_name, undef ) = split /\./, $s_field;
279 0 0         if (! $hr_options->{D}{$s_name} ) {
280 0           die "Expected macro field '$s_name' missing.\n";
281             }
282             }
283             }
284              
285             }
286              
287             }
288              
289 0           return;
290              
291             }
292              
293              
294             sub b_create_testrun {
295              
296 0     0 1   my ( $or_app_rad ) = @_;
297              
298 0           my $ar_parameters = ar_get_create_testrun_parameters();
299 0           $or_app_rad->getopt( map { $_->[0] } @{$ar_parameters} );
  0            
  0            
300 0           my $hr_options = $or_app_rad->options;
301              
302 0 0         if ( $hr_options->{help} ) {
303 0           say {*STDERR} "Usage: $PROGRAM_NAME testrun-new [options]";
  0            
304 0           require Tapper::CLI::Base;
305 0           Tapper::CLI::Base::b_print_help( $ar_parameters );
306 0           return;
307             }
308              
309 0 0         if ( my $s_error = s_create_testrun_parameter_check( $hr_options ) ) {
310 0           die 'error: ' . $s_error . "\n";
311             }
312              
313 0           my @a_ids;
314 0 0         if ( $hr_options->{macroprecond} ) {
315 0           @a_ids = create_macro_preconditions( $hr_options );
316             }
317 0 0         if ( $hr_options->{precondition} ) {
318 0           push @a_ids, @{$hr_options->{precondition}};
  0            
319             }
320              
321 0 0         if (! @a_ids ) {
322 0           die "error: No valid preconditions given\n";
323             }
324              
325 0           require DateTime;
326             my $hr_testrun = {
327             wait_after_tests => $hr_options->{wait_after_tests},
328             priority => $hr_options->{priority} || 0,
329             auto_rerun => $hr_options->{auto_rerun} || 0,
330             earliest => $hr_options->{earliest} || DateTime->now,
331             notes => $hr_options->{notes} || q##,
332             owner => $hr_options->{owner} || $ENV{USER},
333             queue => $hr_options->{queue} || 'AdHoc',
334             rerun_on_error => $hr_options->{rerun_on_error} ? int( $hr_options->{rerun_on_error} ) || 0 : 0,
335             shortname => $hr_options->{shortname} || q##,
336 0 0 0       topic => $hr_options->{topic} || 'Misc',
      0        
      0        
      0        
      0        
      0        
      0        
      0        
      0        
337             };
338              
339 0 0         if ( exists $hr_options->{notify} ) {
340 0           $hr_testrun->{notify} = $hr_options->{notify};
341             }
342              
343 0           require Tapper::Cmd::Testrun;
344 0           my $or_cmd = Tapper::Cmd::Testrun->new();
345 0           my ( $i_testrun_id, $s_error ) = $or_cmd->add( $hr_testrun );
346              
347 0 0         if ( $i_testrun_id ) {
348 0 0         if ( $s_error ) {
349 0           say {*STDERR} "warning: $s_error";
  0            
350             }
351             }
352             else {
353 0 0         if ( $s_error ) {
354 0           die "error: Can't create new testrun\n$s_error\n";
355             }
356             else {
357 0           die "error: Can't create new testrun because of an unknown error\n";
358             }
359             }
360              
361 0           require Tapper::Model;
362 0           my $or_testrun_search =
363             Tapper::Model::model('TestrunDB')
364             ->resultset('Testrun')
365             ->find( $i_testrun_id )
366             ;
367              
368 0 0         if ( my $retval = $or_cmd->assign_preconditions( $i_testrun_id, @a_ids ) ) {
369 0           $or_testrun_search->delete();
370 0           die $retval . "\n";
371             }
372              
373 0           require Tapper::Cmd::Requested;
374              
375 0           my $or_cmd_req;
376 0 0         if ( $hr_options->{requested_host} ) {
377 0           $or_cmd_req = Tapper::Cmd::Requested->new;
378 0           foreach my $s_host ( @{$hr_options->{requested_host}} ) {
  0            
379 0 0         if (! $or_cmd_req->add_host( $i_testrun_id, $s_host, ) ) {
380 0           die "error: adding host failed\n";
381             }
382             }
383             }
384              
385 0 0         if ( $hr_options->{requested_feature} ) {
386 0   0       $or_cmd_req ||= Tapper::Cmd::Requested->new;
387 0           foreach my $s_feature ( @{$hr_options->{requested_feature}} ) {
  0            
388 0 0         if (! $or_cmd_req->add_feature( $i_testrun_id, $s_feature ) ) {
389 0           die "error: adding feature failed\n";
390             }
391             }
392             }
393              
394 0           require DateTime;
395 0           $or_testrun_search->testrun_scheduling->updated_at( DateTime->now->strftime('%F %T') );
396 0           $or_testrun_search->testrun_scheduling->status('schedule');
397 0           $or_testrun_search->testrun_scheduling->update;
398              
399 0 0         if ( $hr_options->{verbose} ) {
400 0           say $or_testrun_search->to_string;
401             }
402             else {
403 0 0         if ( $ENV{TAPPER_WITH_WEB} ) {
404 0           my $s_webserver = Tapper::Config->subconfig->{webserver};
405 0           say "http://$s_webserver/tapper/testrun/id/$i_testrun_id";
406             }
407             else {
408 0           say $i_testrun_id;
409             }
410             }
411              
412 0           return;
413              
414             }
415              
416              
417             sub b_delete {
418              
419 0     0 1   my ( $or_app_rad ) = @_;
420              
421 0           my $ar_parameters = ar_get_delete_testrun_parameters();
422 0           $or_app_rad->getopt( map { $_->[0] } @{$ar_parameters} );
  0            
  0            
423 0           my $hr_options = $or_app_rad->options;
424              
425 0 0         if ( $hr_options->{help} ) {
426 0           say {*STDERR} "Usage: $PROGRAM_NAME testrun-delete [options]";
  0            
427 0           require Tapper::CLI::Base;
428 0           Tapper::CLI::Base::b_print_help( $ar_parameters );
429 0           return;
430             }
431              
432 0 0         if (! $hr_options->{force} ) {
433 0           say {*STDERR} "info: Skip all testruns. Use --force.";
  0            
434 0           return;
435             }
436              
437 0           require Tapper::Cmd::Testrun;
438 0           my $or_cmd = Tapper::Cmd::Testrun->new();
439 0           for my $i_testrun_id ( @{$hr_options->{id}} ){
  0            
440 0 0         if ( my $s_error = $or_cmd->del( $i_testrun_id ) ) {
441 0           die "error: Can not delete testrun $i_testrun_id: $s_error\n";
442             }
443 0 0         if ( $hr_options->{verbose} ) {
444 0           say "info: deleted testrun $i_testrun_id\n";
445             }
446             }
447              
448 0           return;
449              
450             }
451              
452              
453             sub b_rerun {
454              
455 0     0 1   my ( $or_app_rad ) = @_;
456              
457 0           my $ar_parameters = ar_get_rerun_testrun_parameters();
458 0           $or_app_rad->getopt( map { $_->[0] } @{$ar_parameters} );
  0            
  0            
459 0           my $hr_options = $or_app_rad->options;
460              
461 0 0         if ( $hr_options->{help} ) {
462 0           say {*STDERR} "Usage: $PROGRAM_NAME testrun-rerun [options]";
  0            
463 0           require Tapper::CLI::Base;
464 0           Tapper::CLI::Base::b_print_help( $ar_parameters );
465 0           return;
466             }
467              
468 0           require Tapper::Cmd::Testrun;
469 0           my $or_testrun = Tapper::Cmd::Testrun->new();
470              
471 0 0         if ( my $ar_testrun_ids = $hr_options->{id} ) {
472 0           for my $i_testrun_id ( @{$ar_testrun_ids} ) {
  0            
473 0 0         if ( my $i_new_testrun_id = $or_testrun->rerun( $i_testrun_id, $hr_options ) ) {
474 0 0         if ( $hr_options->{verbose} ) {
475 0           my $or_new_testrun = Tapper::Model::model->resultset('TestRun')->find($i_new_testrun_id);
476 0           b_print_testruns( $or_new_testrun );
477 0           say 'info: original id: ', $i_testrun_id;
478             }
479             else {
480 0           say $i_new_testrun_id;
481             }
482             }
483             else {
484 0           die "error: Can't restart testrun $i_testrun_id\n";
485             }
486             }
487 0           return;
488             }
489             else {
490 0           die "error: missing required parameter id\n";
491             }
492              
493             }
494              
495              
496             sub ar_get_queue_ids {
497              
498 0     0 1   my ( $or_schema, $ar_queue_names ) = @_;
499              
500 0           my @a_check_queues;
501 0           foreach my $s_queue ( @{$ar_queue_names} ) {
  0            
502 0 0         if (
503             my $or_queue_rs =
504             $or_schema
505             ->resultset('Queue')
506             ->search({
507             name => $s_queue,
508             },{
509             'select' => [ 'id' ],
510             })
511             ) {
512 0           push @a_check_queues, $or_queue_rs->get_column('id')->all
513             }
514             else {
515 0           die "error: No such queue: $s_queue\n";
516             }
517             }
518              
519 0 0         if ( @a_check_queues ) {
520 0           return @a_check_queues;
521             }
522 0           return;
523              
524             }
525              
526              
527             sub ar_get_host_ids {
528              
529 0     0 1   my ( $or_schema, $ar_host_names ) = @_;
530              
531 0           my @a_check_hosts = ();
532 0           foreach my $s_host ( @{$ar_host_names} ) {
  0            
533 0 0         if (
534             my $or_host_rs =
535             $or_schema
536             ->resultset('Host')
537             ->search({
538             name => $s_host
539             },{
540             'select' => [ 'id' ],
541             })
542             ) {
543 0           push @a_check_hosts, $or_host_rs->get_column('id')->all;
544             }
545             else {
546 0           die "error: No such host: $s_host\n";
547             }
548             }
549              
550 0 0         if ( @a_check_hosts ) {
551 0           return @a_check_hosts;
552             }
553 0           return;
554              
555             }
556              
557              
558             sub b_list_testrun {
559              
560 0     0 1   my ( $or_app_rad ) = @_;
561              
562 0           my $or_querylog;
563              
564 0           require Tapper::Model;
565 0           my $or_schema = Tapper::Model::model('TestrunDB');
566              
567 0 0         if ( $ENV{DEBUG} ) {
568 0           require DBIx::Class::QueryLog;
569 0           $or_querylog = DBIx::Class::QueryLog->new();
570 0           $or_schema->storage->debugobj( $or_querylog );
571 0           $or_schema->storage->debug( 1 );
572             }
573              
574 0           my $ar_parameters = ar_get_list_testrun_parameters();
575 0           $or_app_rad->getopt( map { $_->[0] } @{$ar_parameters} );
  0            
  0            
576 0           my %h_options = %{$or_app_rad->options};
  0            
577              
578 0 0         if ( $h_options{help} ) {
579 0           say {*STDERR} "Usage: $PROGRAM_NAME testrun-rerun [options]";
  0            
580 0           require Tapper::CLI::Base;
581 0           Tapper::CLI::Base::b_print_help( $ar_parameters );
582 0           return;
583             }
584              
585             my @a_given_options = grep {
586 0           $h_options{$_}
  0            
587             } qw/ finished running schedule prepare queue host /;
588              
589 0           my $hr_search = {};
590 0           my @a_check_queues = ();
591              
592 0 0         if ( my $i_testrun_id = $h_options{id} ) {
    0          
593              
594 0 0         if ( @a_given_options ) {
595 0           print {*STDERR} "error: other filters doesn't make sense with filter 'id'\n";
  0            
596             }
597              
598             # filter 'id' doesn't make sense without verbose
599 0           $h_options{verbose} = 1;
600              
601 0           $hr_search = { 'me.id' => $i_testrun_id }
602              
603             }
604             elsif ( @a_given_options ) {
605              
606 0 0         if ( my @a_state_selection = grep { $h_options{$_} } qw/ finished running schedule prepare / ) {
  0            
607 0   0       $hr_search->{'testrun_scheduling.status'} ||= \@a_state_selection;
608             }
609              
610 0 0         if ( my $ar_queue_ids = ar_get_queue_ids( $or_schema, $h_options{queue} ) ) {
611 0           $hr_search->{'testrun_scheduling.queue_id'} = { -in => $ar_queue_ids };
612             }
613              
614 0 0         if ( my $ar_host_ids = ar_get_queue_ids( $or_schema, $h_options{host} ) ) {
615             $hr_search->{-or} = [
616 0           -and => [
617             -not => { 'testrun_scheduling.status' => 'schedule', },
618             'testrun_scheduling.host_id' => { -in => $ar_host_ids, },
619             ],
620             -and => [
621             'testrun_scheduling.status' => 'schedule',
622             'requested_hosts.host_id' => { -in => $ar_host_ids, },
623             ],
624             ];
625             }
626              
627             }
628              
629 0           my $hr_search_options = {
630             order_by => { -desc => 'me.id' }
631             };
632              
633 0 0         if ( exists $h_options{limit} ) {
634 0 0         if ( $h_options{limit} > 0 ) {
635 0           $hr_search_options->{rows} = $h_options{limit};
636             }
637             }
638             else {
639 0           $hr_search_options->{rows} = $i_limit_default;
640             }
641 0 0         if ( $h_options{verbose} ) {
642 0           $hr_search_options->{'prefetch'} = [
643             {
644             'testrun_scheduling' => [
645             'queue',
646             {
647             'requested_hosts' => 'host',
648             },
649             ],
650             },
651             {
652             'testrun_scheduling' => 'host',
653             },
654             ];
655             }
656             else {
657 0           $hr_search_options->{'join'} = 'testrun_scheduling';
658 0           $hr_search_options->{'select'} = ['id'];
659             }
660              
661 0           my $or_testrun_rs =
662             $or_schema
663             ->resultset('Testrun')
664             ->search( $hr_search, $hr_search_options )
665             ;
666              
667 0 0         if ( $h_options{verbose} ) {
668 0           Tapper::CLI::Testrun::b_print_testruns( $or_testrun_rs );
669             }
670             else {
671 0           foreach my $i_testrun_id ( $or_testrun_rs->get_column('id')->all ) {
672 0           say $i_testrun_id;
673             }
674             }
675              
676 0 0         if ( $ENV{DEBUG} ) {
677              
678 0           require DBIx::Class::QueryLog::Analyzer;
679 0           my $or_analyzer = DBIx::Class::QueryLog::Analyzer->new({
680             querylog => $or_querylog,
681             });
682              
683 0           require Data::Dumper;
684 0           say {*STDERR} "Query count: " . scalar( @{$or_analyzer->get_sorted_queries} );
  0            
  0            
685 0           say {*STDERR} Data::Dumper::Dumper([
  0            
686             $or_analyzer->get_sorted_queries
687             ]);
688              
689             }
690              
691 0           return;
692              
693             }
694              
695              
696             sub testrun_update
697             {
698 0     0 1   my ($c) = @_;
699 0           $c->getopt( 'id=i@','status=s', 'topic=s', 'auto-rerun!','help|?', 'verbose|v' );
700 0 0 0       if ( $c->options->{help} or not $c->options->{id}) {
701 0 0         say STDERR "Please set at least one testrun id with --id!" unless @{$c->options->{id} || []};
  0 0          
702 0 0 0       say STDERR "Please set an update action" unless ($c->options->{state} or defined $c->options->{"auto-rerun"});
703 0           say STDERR "$PROGRAM_NAME testrun-update --id=s@ --status=s --auto_rerun --no-auto-rerun --verbose|v [--help|?]";
704 0           say STDERR " --id Id of the testrun to update, can be given multiple times";
705 0           say STDERR " --topic one of: Kernel, Xen, KVM, Hardware, Distribution, Benchmark, Software, Misc";
706 0           say STDERR " --status Set testrun to given status, can be one of 'prepare', 'schedule', 'finished'.";
707 0           say STDERR " --auto-rerun Activate auto-rerun on testrun. ";
708 0           say STDERR " --no-auto-rerun Activate auto-rerun on testrun";
709 0           say STDERR " --verbose|v Print new state of testrun (will only print id of updated testruns without)";
710 0           say STDERR " --help|? Print this help message and exit";
711 0           return;
712             }
713              
714 0           require Tapper::Model;
715             ID:
716 0           foreach my $testrun_id (@{$c->options->{id}}) {
  0            
717 0           my $testrun = Tapper::Model::model('TestrunDB')->resultset('Testrun')->find($testrun_id);
718 0 0         if (not $testrun) {
719 0           say STDERR "Testrun with id $testrun_id not found. Skipping!";
720 0           next ID;
721             }
722              
723 0 0         if ( $c->options->{topic} ) {
724             $testrun->update_content({
725             topic => $c->options->{topic},
726 0           });
727             }
728              
729 0 0 0       if (not ($testrun->testrun_scheduling->status eq 'prepare' or
730             $testrun->testrun_scheduling->status eq 'schedule')
731             )
732             {
733 0           say STDERR "Can only update testruns in state 'schedule' and 'finished'. Updating testruns in other states will break something. Please consider tapper testrun-rerun";
734 0           next ID;
735             }
736              
737 0 0         if ($c->options->{status}) {
738 0           $testrun->testrun_scheduling->status($c->options->{status});
739 0           $testrun->testrun_scheduling->update;
740             }
741 0 0         if (defined($c->options->{"auto-rerun"})) {
742 0           $testrun->testrun_scheduling->auto_rerun($c->options->{"auto-rerun"});
743 0           $testrun->testrun_scheduling->update;
744             }
745 0 0         if ($c->options->{verbose}) {
746 0           b_print_testruns($testrun);
747             } else {
748 0           say $testrun_id;
749             }
750             }
751              
752             }
753              
754              
755             sub b_cancel
756             {
757              
758 0     0 1   my ($c) = @_;
759 0           $c->getopt( 'id=i@','comment=s','help|?', 'verbose|v' );
760 0 0 0       if ( $c->options->{help} or not $c->options->{id}) {
761 0 0         say STDERR "Please set at least one testrun id with --id!" unless @{$c->options->{id} || []};
  0 0          
762 0           say STDERR "$PROGRAM_NAME testrun-cancel --id=i@ [--comment=s] [--verbose|v] [--help|?]";
763 0           say STDERR " --id Id of the testrun to cancel, can be given multiple times";
764 0           say STDERR " --comment A comment why the testrun(s) were cancelled";
765 0           say STDERR " --verbose|v Tell user what we just did (without -v only the testrun id will be printed in the success case)";
766 0           say STDERR " --help|? Print this help message and exit";
767 0           return;
768             }
769              
770 0           require Tapper::Cmd::Testrun;
771 0           my $cmd = Tapper::Cmd::Testrun->new();
772 0           foreach my $id (@{$c->options->{id}}) {
  0            
773 0           my $retval = $cmd->cancel($id, $c->options->{comment});
774 0 0         warn $retval if $retval;
775             }
776 0           return;
777             }
778              
779              
780              
781             sub b_pause
782             {
783              
784 0     0 1   my ($c) = @_;
785 0           $c->getopt( 'id=i@','help|?', 'verbose|v' );
786 0 0 0       if ( $c->options->{help} or not $c->options->{id}) {
787 0 0         say STDERR "Please set at least one testrun id with --id!" unless @{$c->options->{id} || []};
  0 0          
788 0           say STDERR "$PROGRAM_NAME testrun-pause --id=i@ [--verbose|v] [--help|?]";
789 0           say STDERR " --id Id of the testrun to pause, can be given multiple times";
790 0           say STDERR " --help|? Print this help message and exit";
791 0           return;
792             }
793              
794 0           require Tapper::Cmd::Testrun;
795 0           my $cmd = Tapper::Cmd::Testrun->new();
796 0           foreach my $id (@{$c->options->{id}}) {
  0            
797 0           my $retval = $cmd->pause($id);
798 0 0         say $id if $retval;
799             }
800 0           return;
801             }
802              
803              
804              
805             sub b_continue
806             {
807              
808 0     0 1   my ($c) = @_;
809 0           $c->getopt( 'id=i@','help|?', 'verbose|v' );
810 0 0 0       if ( $c->options->{help} or not $c->options->{id}) {
811 0 0         say STDERR "Please set at least one testrun id with --id!" unless @{$c->options->{id} || []};
  0 0          
812 0           say STDERR "$PROGRAM_NAME testrun-continue --id=i@ [--verbose|v] [--help|?]";
813 0           say STDERR " --id Id of the testrun to continue, can be given multiple times";
814 0           say STDERR " --help|? Print this help message and exit";
815 0           return;
816             }
817              
818 0           require Tapper::Cmd::Testrun;
819 0           my $cmd = Tapper::Cmd::Testrun->new();
820 0           foreach my $id (@{$c->options->{id}}) {
  0            
821 0           my $retval = $cmd->continue($id);
822 0 0         say $id if $retval;
823             }
824 0           return;
825             }
826              
827              
828              
829             sub setup {
830              
831 0     0 1   my ( $or_apprad ) = @_;
832              
833 0           $or_apprad->register( 'testrun-list' , \&b_list_testrun , 'Show all testruns matching a given condition', );
834 0           $or_apprad->register( 'testrun-update' , \&testrun_update , 'Update an existing testrun', );
835 0           $or_apprad->register( 'testrun-rerun' , \&b_rerun , 'Rerun an existing testrun with the same preconditions', );
836 0           $or_apprad->register( 'testrun-delete' , \&b_delete , 'Delete a testrun', );
837 0           $or_apprad->register( 'testrun-pause' , \&b_pause , 'Pause a not-yet-running testrun', );
838 0           $or_apprad->register( 'testrun-continue',\&b_continue , 'Continue a paused testrun', );
839 0           $or_apprad->register( 'testrun-cancel' , \&b_cancel , 'Cancel a running testrun', );
840 0           $or_apprad->register( 'testrun-new' , \&b_create_testrun , 'Create a testrun', );
841              
842 0 0         if ( $or_apprad->can('group_commands') ) {
843 0           $or_apprad->group_commands(
844             'Testrun commands',
845             'testrun-list',
846             'testrun-new',
847             'testrun-update',
848             'testrun-rerun',
849             'testrun-delete',
850             'testrun-pause',
851             'testrun-continue',
852             'testrun-cancel',
853             );
854             }
855              
856 0           return;
857              
858             }
859              
860             1; # End of Tapper::CLI
861              
862             __END__
863              
864             =pod
865              
866             =encoding UTF-8
867              
868             =head1 NAME
869              
870             Tapper::CLI::Testrun
871              
872             =head1 SYNOPSIS
873              
874             This module is part of the Tapper::CLI framework. It is supposed to be
875             used together with App::Rad. All following functions expect their
876             arguments as $c->options->{$arg} unless otherwise stated.
877              
878             use App::Rad;
879             use Tapper::CLI::Testrun;
880             Tapper::CLI::Testrun::setup($c);
881             App::Rad->run();
882              
883             =head1 NAME
884              
885             Tapper::CLI::Testrun - Tapper - testrun related commands for the tapper CLI
886              
887             =head1 FUNCTIONS
888              
889             =head2 b_print_single_testrun
890              
891             print column data for a single testrun row to STDOUT
892              
893             =head2 b_print_testruns
894              
895             print column data for resultset to STDOUT
896              
897             =head2 ar_get_list_testrun_parameters
898              
899             return list testrun parameters and descriptions
900              
901             =head2 ar_get_rerun_testrun_parameters
902              
903             return rerun testrun parameters and descriptions
904              
905             =head2 ar_get_delete_testrun_parameters
906              
907             return delete testrun parameters and descriptions
908              
909             =head2 ar_get_create_testrun_parameters
910              
911             return create testrun parameters and descriptions
912              
913             =head2 create_macro_preconditions
914              
915             Process a macroprecondition. This includes substitions using
916             Template::Toolkit, separating the individual preconditions that are part of
917             the macroprecondition and putting them into the database. Parameters fit the
918             App::Cmd::Command API.
919              
920             @param hashref - hash containing options
921             @param hashref - hash containing arguments
922              
923             @returnlist array containing precondition ids
924              
925             =head2 s_create_testrun_parameter_check
926              
927             check command line parameters for create testrun and return error if exists
928              
929             =head2 b_create_testrun
930              
931             create a testrun
932              
933             =head2 b_delete
934              
935             delete a testrun
936              
937             =head2 b_rerun
938              
939             rerun an existing testrun
940              
941             =head2 ar_get_queue_ids
942              
943             return an array reference of queue_ids for a an array reference of queue_names
944              
945             =head2 ar_get_host_ids
946              
947             return an array reference of host_ids for a an array reference of host_names
948              
949             =head2 b_list_testrun
950              
951             list existing restuns
952              
953             =head2 testrun_update
954              
955             Update values of an existing testrun.
956              
957             =head2 b_cancel
958              
959             Cancel a running testrun. If the given testrun is currently not running,
960             the function does the obvious right thing and also warns the user.
961              
962             =head2 b_pause
963              
964             Pause a not-yet-running testrun.
965              
966             =head2 b_continue
967              
968             Continue a paused testrun.
969              
970             =head2 setup
971              
972             Initialize the testplan functions for tapper CLI
973              
974             =head1 AUTHOR
975              
976             AMD OSRC Tapper Team <tapper@amd64.org>
977              
978             =head1 COPYRIGHT AND LICENSE
979              
980             This software is Copyright (c) 2020 by Advanced Micro Devices, Inc..
981              
982             This is free software, licensed under:
983              
984             The (two-clause) FreeBSD License
985              
986             =cut