package Tapper::CLI::Precondition;
our $AUTHORITY = 'cpan:TAPPER';
$Tapper::CLI::Precondition::VERSION = '5.0.4';
use 5.010;
use warnings;
use strict;
use feature qw/ say /;
use English qw/ -no_match_vars /;
# list limit default value
my $i_limit_default = 50;
sub b_print_single_precondition {
my ( $or_precondition, $hr_options ) = @_;
my %h_print_elements = (
'Id' => [ 1, $or_precondition->id, ],
'Shortname' => [ 2, $or_precondition->shortname, ],
'Precondition' => [ 3, $or_precondition->precondition, ],
'Timeout' => [ 4, $or_precondition->timeout || q##, ],
);
if ( $hr_options->{nonewlines} ) {
$h_print_elements{Precondition}[1] =~ s/\n/\\n/mg;
}
if ( $hr_options->{quotevalues} ) {
require Data::Dumper;
for my $s_key ( keys %h_print_elements ) {
$h_print_elements{$s_key}[1] =
Data::Dumper
->new([$h_print_elements{$s_key}[1]])
->Terse(1)
->Indent(0)
->Dump
;
}
}
print "\n";
my $i_key_length = 0;
for my $s_key ( keys %h_print_elements ) {
if ( length $s_key > $i_key_length ) {
$i_key_length = length $s_key;
}
}
for my $s_key (
sort {
$h_print_elements{$a}[0] <=> $h_print_elements{$b}[0]
} keys %h_print_elements
) {
printf ' %' . $i_key_length . "s: %s\n", $s_key, $h_print_elements{$s_key}[1];
}
return 1;
}
sub b_print_preconditions {
my ( $or_preconditions, $hr_options ) = @_;
if ( $or_preconditions->isa('DBIx::Class::ResultSet') ) {
for my $or_precondition ( $or_preconditions->all ) {
b_print_single_precondition(
$or_precondition,
$hr_options,
);
}
}
else {
b_print_single_precondition(
$or_preconditions,
$hr_options,
);
}
print "\n";
return 1;
}
sub ar_get_list_parameters {
return [
[ 'id|i=i@' , 'list particular preconditions by id', 'Can be given multiple times.', ],
[ 'testrun|t=i@' , 'list particular preconditions by testrun id', 'Can be given multiple times.', ],
[ 'limit|l=i' , "limit the number of testruns (default = $i_limit_default). A value smaller than 1 deactivates the limit.", ],
[ 'verbose|v' , 'print all output, without only print ids', ],
[ 'nonewlines|n' , 'no newslines in precondition ( available in verbose mode )', ],
[ 'quotevalues|q' , 'quote every value ( available in verbose mode )', ],
[ 'help|?' , 'Print this help message and exit.', ],
];
}
sub b_list {
my ( $or_app_rad ) = @_;
my $or_querylog;
require Tapper::Model;
my $or_schema = Tapper::Model::model('TestrunDB');
if ( $ENV{DEBUG} ) {
require DBIx::Class::QueryLog;
$or_querylog = DBIx::Class::QueryLog->new();
$or_schema->storage->debugobj( $or_querylog );
$or_schema->storage->debug( 1 );
}
my $ar_parameters = ar_get_list_parameters();
$or_app_rad->getopt( map { $_->[0] } @{$ar_parameters} );
my %h_options = %{$or_app_rad->options};
if ( $h_options{help} ) {
say {*STDERR} "Usage: $PROGRAM_NAME precondition-list [options]";
require Tapper::CLI::Base;
Tapper::CLI::Base::b_print_help( $ar_parameters );
return;
}
my $hr_search;
my $hr_search_options = {
order_by => { -desc => 'me.id' },
};
if ( exists $h_options{limit} ) {
if ( $h_options{limit} > 0 ) {
$hr_search_options->{rows} = $h_options{limit};
}
}
else {
$hr_search_options->{rows} = $i_limit_default;
}
if ( my $ar_precondition_ids = $h_options{id} ) {
if ( $h_options{testrun} ) {
die "error: filter 'testrun' doesn't make sense with filter 'id'\n";
}
# filter 'id' doesn't make sense without verbose
$h_options{verbose} = 1;
$hr_search = { 'me.id' => $ar_precondition_ids }
}
elsif ( my $ar_testrun_ids = $h_options{testrun} ) {
$hr_search = { 'testrun_precondition.testrun_id' => $ar_testrun_ids };
$hr_search_options->{'join'} = 'testrun_precondition';
}
my $or_precondition_rs =
$or_schema
->resultset('Precondition')
->search( $hr_search, $hr_search_options )
;
if ( $h_options{verbose} ) {
b_print_preconditions( $or_precondition_rs, \%h_options, );
}
else {
for my $i_precondition_id ( $or_precondition_rs->get_column('id')->all ) {
say $i_precondition_id;
}
}
if ( $ENV{DEBUG} ) {
require DBIx::Class::QueryLog::Analyzer;
my $or_analyzer = DBIx::Class::QueryLog::Analyzer->new({
querylog => $or_querylog,
});
require Data::Dumper;
say {*STDERR} "Query count: " . scalar( @{$or_analyzer->get_sorted_queries} );
say {*STDERR} Data::Dumper::Dumper([
$or_analyzer->get_sorted_queries
]);
}
return;
}
sub ar_get_delete_parameters {
return [
[ 'id|i=i@' , 'delete particular preconditions', 'Can be given multiple times.', ],
[ 'force|f' , 'really execute the command', ],
[ 'verbose|v' , 'print all output, without only print ids', ],
[ 'help|?' , 'Print this help message and exit.', ],
];
}
sub b_delete {
my ( $or_app_rad ) = @_;
my $ar_parameters = ar_get_delete_parameters();
$or_app_rad->getopt( map { $_->[0] } @{$ar_parameters} );
my $hr_options = $or_app_rad->options;
if ( $hr_options->{help} ) {
say {*STDERR} "Usage: $PROGRAM_NAME precondition-delete [options]";
require Tapper::CLI::Base;
Tapper::CLI::Base::b_print_help( $ar_parameters );
return;
}
if (! $hr_options->{id} ) {
die "error: required parameter 'id' is missing\n";
}
if (! $hr_options->{force} ) {
say {*STDERR} "info: Skip deleting preconditions unless --force is used.";
return;
}
require Tapper::Cmd::Precondition;
my $or_cmd = Tapper::Cmd::Precondition->new();
foreach my $i_precondition_id ( @{$hr_options->{id}} ){
if ( my $s_error = $or_cmd->del( $i_precondition_id ) ) {
die "$s_error\n";
}
elsif ( $hr_options->{verbose} ) {
say "info: precondition deleted $i_precondition_id";
}
}
return;
}
sub s_read_condition_file {
my ( $s_condition_file ) = @_;
my $s_condition;
if ( $s_condition_file ) {
require File::Slurp;
$s_condition = File::Slurp::read_file(
# read from file or STDIN if filename == '-'
$s_condition_file eq q#-# ? \*STDIN : $s_condition_file
);
}
else {
die "error: missing parameter 'condition file'\n";
}
return $s_condition;
}
sub ar_get_precondition_parameters {
my ( $s_command ) = @_;
return [
(
$s_command eq 'precondition-update'
? ( [ 'id|i=s', 'the precondition id to change', ] )
: ()
),
[ 'shortname|s=s' , 'shortname', ],
[ 'timeout|t=s' , 'stop trying to fullfill this precondition after timeout second', ],
[ 'condition|c=s' , 'condition description in YAML format (see Spec)', ],
[ 'condition_file|f=s' , 'filename from where to read condition, use - to read from STDIN' ],
[ 'verbose|v' , 'some more informational output', ],
[ 'help|?' , 'print this help message and exit.', ],
];
}
sub hr_init_precondition_commands {
my ( $or_app_rad, $s_command ) = @_;
my $ar_parameters = ar_get_precondition_parameters( $s_command );
$or_app_rad->getopt( map { $_->[0] } @{$ar_parameters} );
my $hr_options = $or_app_rad->options;
if ( $hr_options->{help} ) {
say {*STDERR} "Usage: $PROGRAM_NAME $s_command [options]";
require Tapper::CLI::Base;
Tapper::CLI::Base::b_print_help( $ar_parameters );
return;
}
if ( !$hr_options->{condition} && !$hr_options->{condition_file} ) {
die "error: missing parameter --condition or --condition_file\n";
}
elsif ( $hr_options->{condition} && $hr_options->{condition_file} ) {
die "error: only one of --condition or --condition_file allowed\n";
}
my $s_condition = $hr_options->{condition};
my $s_condition_file = $hr_options->{condition_file};
if (! $s_condition ) {
$s_condition = s_read_condition_file( $s_condition_file );
}
if ( $s_condition !~ /\n$/ ) {
$s_condition .= "\n";
}
if ( my @a_elements = grep { $hr_options->{$_} } qw/ shortname timeout / ) {
require YAML::Syck;
my @a_yaml = YAML::Syck::Load( $s_condition );
for my $hr_yaml ( @a_yaml ) {
@{$hr_yaml}{@a_elements} = @{$hr_options}{@a_elements};
}
$s_condition = YAML::Syck::Dump( @a_yaml );
}
return {
condition => $s_condition,
options => $hr_options,
};
}
sub b_new {
my ( $or_app_rad ) = @_;
my $hr_precond_data = hr_init_precondition_commands(
$or_app_rad, 'precondition-new',
);
require Tapper::Model;
require Tapper::Cmd::Precondition;
if ( my @a_precondition_ids = Tapper::Cmd::Precondition->new->add( $hr_precond_data->{condition} ) ) {
if ( $hr_precond_data->{options}{verbose} ) {
foreach my $i_precondition_id ( @a_precondition_ids ) {
b_print_single_precondition(
Tapper::Model::model('TestrunDB')
->resultset('Precondition')
->search({ id => $i_precondition_id }, { rows => 1 })
->first
);
}
}
else {
print map { $_, "\n" } @a_precondition_ids;
}
}
return;
}
sub b_update {
my ( $or_app_rad ) = @_;
my $hr_precond_data = hr_init_precondition_commands(
$or_app_rad, 'precondition-update',
);
if (! $hr_precond_data->{options}{id} ) {
die "error: Missing required parameter 'id'\n";
}
require Tapper::Model;
require Tapper::Cmd::Precondition;
my $or_cmd = Tapper::Cmd::Precondition->new();
if (
$or_cmd->update(
$hr_precond_data->{options}{id},
$hr_precond_data->{condition},
)
) {
if ( $hr_precond_data->{options}{verbose} ) {
b_print_single_precondition(
Tapper::Model::model('TestrunDB')
->resultset('Precondition')
->find( $hr_precond_data->{options}{id} )
);
}
else {
say $hr_precond_data->{options}{id};
}
}
else {
die "error: cannot update precondition\n";
}
return;
}
sub setup {
my ( $or_apprad ) = @_;
$or_apprad->register( 'precondition-list' , \&b_list , 'List preconditions' , );
$or_apprad->register( 'precondition-new' , \&b_new , 'Create preconditions', );
$or_apprad->register( 'precondition-update', \&b_update, 'Update preconditions', );
$or_apprad->register( 'precondition-delete', \&b_delete, 'Delete preconditions', );
if ( $or_apprad->can('group_commands') ) {
$or_apprad->group_commands(
'Testrun commands',
'precondition-list',
'precondition-new',
'precondition-update',
'precondition-delete',
);
}
return;
}
1; # End of Tapper::CLI
__END__
=pod
=encoding UTF-8
=head1 NAME
Tapper::CLI::Precondition
=head1 SYNOPSIS
This module is part of the Tapper::CLI framework. It is supposed to be
used together with App::Rad. All following functions expect their
arguments as $c->options->{$arg} unless otherwise stated.
use App::Rad;
use Tapper::CLI::Test;
Tapper::CLI::Test::setup($c);
App::Rad->run();
=head1 NAME
Tapper::CLI::Test - Tapper - precondition related commands for the tapper CLI
=head1 FUNCTIONS
=head2 b_print_single_precondition
print a single precondition ( verbose )
=head2 b_print_preconditions
print preconditions
=head2 b_list
get "list precondition" parameters
=head2 b_list
list preconditions from database
=head2 ar_get_delete_parameters
get "delete precondition" parameters
=head2 b_delete
delete a precondition from database
=head2 s_read_condition_file
read a condition file and return it as strings
=head2 ar_get_precondition_parameters
get parameters and descriptions for command "precondition-new" and "precondition-update"
=head2 b_new
run some initial checks and commands for "new" and "update" command
=head2 b_new
create new preconditions
=head2 b_update
update a existing precondition
=head2 setup
Initialize the testplan functions for tapper CLI
=head1 AUTHOR
AMD OSRC Tapper Team <tapper@amd64.org>
=head1 COPYRIGHT AND LICENSE
This software is Copyright (c) 2016 by Advanced Micro Devices, Inc..
This is free software, licensed under:
The (two-clause) FreeBSD License
=cut