#!/usr/bin/perl

# Copyright (C) 2014-2020 SUSE LLC
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, see <http://www.gnu.org/licenses/>.

=head1 SYNOPSIS

client [OPTIONS] PATH

=head1 OPTIONS

=over 4

=item B<--host> HOST

Connect to specified host, defaults to localhost

=item B<--params> FILE

Load get/post parameters from a json file. For example

{
   "FLAVOR" : "DVD",
   "BUILD" : "42",
   "ARCH" : "i586",
   "DISTRI" : "opensuse",
   "VERSION" : "26",
}

=item B<--apibase>

Set API base URL component, default: '/api/v1'

=item B<--json-output>

Output JSON instead of Perl structures.

=item B<--yaml-output>

Output YAML instead of Perl structures.

=item B<accept> (json|yaml)

Send Accept header to explicitly tell the API what format is accepted

Note that currently only one endpoint (job_templates_scheduling) is able
to return YAML, and it's deprecated.

By default, C<Accept: */*> is sent.

=item B<--verbose, -v>

Be verbose in output.

=item B<--apikey> KEY, B<--apisecret> SECRET

Specify api key and secret to use, overrides use of config file ~/.config/openqa/client.conf

=item B<--json-data>

Send JSON data; expected by certain routes

For example:
jobs/639172 put --json-data '{"group_id": 1}'

=item B<--form>

Send form data (application/x-www-form-urlencoded) instead of appending supplied parameters
as URL query; expected by certain routes

This is for instance used to post job templates, e.g.:

job_templates_scheduling/1 post --form schema=JobTemplates-01.yaml preview=0 template="$(cat foo.yaml)"

To create nested forms use dotted syntax, e.g.:

jobs/1/artefact post --form file.file=bar file.filename=bar.log

=item B<--help, -h>

print help

=head2 Archive mode

=item B<--archive, -a> DIRECTORY

Archive mode: Download assets and test results from a job to DIRECTORY.

=item B<--with-thumbnails>

Archive mode: Include thumbnails

=item B<--asset-size-limit> LIMIT

Archive mode: Download assets that do not exceed the specified limit in bytes
The default limit is 200 MB.

=head1 SYNOPSIS

Interact with the openQA API by specified route entry points and optionally
operations, defaults to the 'get' operation, i.e. just reading out the data
without changing it. See the help on the openQA instance you want to access
for available API routes.

Common top level entry points: jobs, workers, isos.

=item client --host openqa.example.com jobs

List all jobs. Caution: this will take a very long time or even timeout on big
productive instances.

=item client --host openqa.example.com jobs groupid=135 distri=caasp version=3.0 latest=1

List all jobs matching the specified search criteria.

=item client --host openqa.example.com jobs/overview groupid=135 distri=caasp version=3.0

List the latest jobs for the latest build in the given scenario.
In contrast to the route above, this will limit the results to the latest build in the same
way the test result overview in the web UI does.

=item client --host openqa.example.com jobs/1

Show details of job nr. B<1>.

=item client --host openqa.example.com jobs/1 delete

Delete job nr. B<1> (permissions read from config file).

=item client --host openqa.example.com isos post ISO=bar.iso DISTRI=my-distri FLAVOR=my-flavor ARCH=my-arch VERSION=42 BUILD=1234

Trigger jobs on iso B<bar.iso> matching test suite B<blah>.

=item client --archive /path/to/directory --asset-size-limit 1048576000 --with-thumbnails --host openqa.opensuse.org jobs/42

Download all assets and test logs and images from job B<42> with asset limit of B<1GB> to B</path/to/directory>.

=cut

use strict;
use warnings;
use FindBin;
BEGIN { unshift @INC, "$FindBin::RealBin/../lib" }

use OpenQA::Script::Client;
use Getopt::Long;
Getopt::Long::Configure("no_ignore_case");

my %options;

sub usage($) {
    my $r = shift;
    eval { require Pod::Usage; Pod::Usage::pod2usage($r); };
    die "cannot display help, install perl(Pod::Usage)\n" if $@;
}

GetOptions(
    \%options,            'host=s',          'apibase=s',   'json-output',
    'verbose|v',          'apikey:s',        'apisecret:s', 'params=s',
    'form',               'json-data:s',     'help|h|?',    'archive|a:s',
    'asset-size-limit:i', 'with-thumbnails', 'accept=s',    'yaml-output',
) or usage(1);

usage(0) if $options{help};
usage(1) unless @ARGV;

if ($options{form} && $options{'json-data'}) {
    print STDERR "ERROR: The options --form and --json-data can not be combined.\n";
    exit(2);
}

my $ret = run(\%options, @ARGV);
exit(defined $ret ? 0 : 1);

1;
