Skip to content

Commit

Permalink
Add repeat parameter to clone a job multiple times
Browse files Browse the repository at this point in the history
to better support statistical investigation, we want to provide an
immediate way to clone a job multiple times. Till now it has been done
with a for loop similar to

for i in {01..50}; do openqa-clone-job … TEST+=-$i; done

But we can avoid the API overhead of copying the same parameters and
assets again and again from the original job, simply by cloning it once and
posting the new job(s) N times. TEST name is automatically numbered, so the
user is not forced to remember any shell syntax.

As the default is --repeat=1, the API remains compatible with any shell
script using the openqa-clone-job program.
  • Loading branch information
ilmanzo committed Oct 17, 2023
1 parent f46075b commit 13bfa84
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 3 deletions.
19 changes: 19 additions & 0 deletions docs/UsersGuide.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -1113,6 +1113,25 @@ timeouts by performing the task in background.
This is recommended on big instances but means that the results (and
possible errors) need to be polled via `openqa-cli api isos/$scheduled_product_id`.


===== Statistical investigation =====
In case issues appear sporadically and are therefore hard to reproduce it can
help to trigger many more jobs on a production instance to gather more data
first, for example the failure ratio.

Example of triggering 50 jobs in a development group so that the result of
passed/failed jobs is counted by openQA itself on the corresponding overview page:
[source,sh]
--------------------------------------------------------------------------------
openqa-clone-job --skip-chained-deps --repeat=50 --within-instance \
https://openqa.opensuse.org 123456 BUILD=poo32242_investigation \
_GROUP="Test Development:openSUSE Tumbleweed"
--------------------------------------------------------------------------------

To get an overview about the fail ratio and confidence interval of sporadically
failing applications you can also use a script like
https://github.com/okurz/scripts/blob/master/count_fail_ratio[this].

[id="scenarios_yaml"]
===== Defining test scenarios in YAML =====
Instead of relying on the tables for machines, mediums/products, test suites and
Expand Down
24 changes: 22 additions & 2 deletions lib/OpenQA/Script/CloneJob.pm
Original file line number Diff line number Diff line change
Expand Up @@ -226,11 +226,31 @@ sub handle_tx ($tx, $url_handler, $options, $jobs) {
}
}

# append a formatted "-NN" to the TEST parameter
sub append_idx_to_test_name ($n, $post_params) {
foreach my $job_key (keys %$post_params) {
my $job = $post_params->{$job_key};
my $test_name = $job->{TEST};
if ($n == 1) {
$test_name .= '-1'; # just append at the first time
}
else {
# from the second onwards, replace with the number
$test_name =~ s/-\d+$/\-$n/;
}
$job->{TEST} = $test_name;
}
}

sub clone_jobs ($jobid, $options) {
my $url_handler = create_url_handler($options);
my $repeat = delete $options->{repeat} || 1;
clone_job($jobid, $url_handler, $options, my $post_params = {}, my $jobs = {});
my $tx = post_jobs($post_params, $url_handler, $options);
handle_tx($tx, $url_handler, $options, $jobs) if $tx;
for my $counter (1 .. $repeat) {
append_idx_to_test_name($counter, $post_params) if $repeat > 1;
my $tx = post_jobs($post_params, $url_handler, $options);
handle_tx($tx, $url_handler, $options, $jobs) if $tx;
}
}

sub clone_job ($jobid, $url_handler, $options, $post_params = {}, $jobs = {}, $depth = 1, $relation = '') {
Expand Down
9 changes: 8 additions & 1 deletion script/openqa-clone-job
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ are cloned. Use C<0> to denote infinity.
A shortcut for C<--skip-download --from HOST --host HOST> to clone a job within
a local or remote instance.
=item B<--repeat> N
Do the same clone operation N times.
=item B<--show-progress>
Displays a progress bar when downloading assets.
Expand Down Expand Up @@ -175,6 +179,7 @@ use FindBin;
use lib "$FindBin::RealBin/../lib";
use OpenQA::Script::CloneJob;
use OpenQA::Utils 'assetdir';
use Scalar::Util qw(looks_like_number);

my %options;
my $jobid;
Expand All @@ -190,7 +195,7 @@ sub parse_options () {
"apikey:s", "apisecret:s", "verbose|v", "json-output|j",
"skip-deps", "skip-chained-deps", "skip-download", "parental-inheritance",
"help|h", "show-progress", "within-instance|w=s", "clone-children",
"max-depth:i", "ignore-missing-assets", "export-command",
"max-depth:i", "repeat|r:i", "ignore-missing-assets", "export-command",
) or usage(1);
usage(0) if $options{help};
usage(1) if $options{help} || ($options{'within-instance'} && $options{from});
Expand All @@ -207,6 +212,8 @@ sub parse_options () {
die "missing job reference, see --help for usage\n" unless $jobid;
($options{'from'}, $jobid) = split_jobid($jobid) unless $options{'from'};
usage(1) unless ($jobid && $options{'from'});
my $repeat = $options{'repeat'} //= 1;
die "invalid repeat count, should be greater than or equal to 1\n" if !looks_like_number($repeat) || $repeat < 1;
$options{'dir'} ||= assetdir();
$options{'host'} ||= 'localhost';
$options{'args'} = \@ARGV;
Expand Down
20 changes: 20 additions & 0 deletions t/35-script_clone_job.t
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,26 @@ subtest 'export command' => sub {
combined_like { clone_jobs(42, \%options) } $expected_cmd, 'openqa-cli command printed';
};

subtest 'cloning with repeat count' => sub {
my $ua_mock = Test::MockModule->new('Mojo::UserAgent');
my $clone_mock = Test::MockModule->new('OpenQA::Script::CloneJob');
my @post_args;
my $tx_handled = 0;
$ua_mock->redefine(post => sub { push @post_args, [@_] });
$clone_mock->redefine(handle_tx => sub ($tx, $url_handler, $options, $jobs) { $tx_handled = 1 });
my %fake_jobs = (42 => {id => 42, name => 'myjob', settings => {TEST => 'myjob'}, children => {Parallel => [42]}});
$clone_mock->redefine(clone_job_get_job => sub ($job_id, @args) { $fake_jobs{$job_id} });
my %options = (host => 'foo', from => 'bar', repeat => 42, apikey => 'bar', apisecret => 'bar');
OpenQA::Script::CloneJob::clone_jobs(42, \%options);
is $options{repeat}, undef, 'repeat count has been removed from options';
subtest 'post args' => sub {
is scalar @post_args, 42, 'exactly 42 post calls made';
# check Nth test name ends with -N
is $post_args[0]->[3]->{'TEST:42'}, 'myjob-1', 'first index has been appended to test name';
is $post_args[41]->[3]->{'TEST:42'}, 'myjob-42', 'last index has been appended to test name';
} or diag explain \@post_args;
};

subtest 'overall cloning with parallel and chained dependencies' => sub {
# do not actually post any jobs, assume jobs can be cloned (clone ID = original ID + 100)
my $ua_mock = Test::MockModule->new('Mojo::UserAgent');
Expand Down

0 comments on commit 13bfa84

Please sign in to comment.