Skip to content

Commit

Permalink
Rewrite IBS embargo feature to rely on SMASH
Browse files Browse the repository at this point in the history
  • Loading branch information
kraih committed Oct 25, 2024
1 parent 63c61ab commit ee06b42
Show file tree
Hide file tree
Showing 4 changed files with 215 additions and 231 deletions.
5 changes: 3 additions & 2 deletions cavil.conf
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@
password => 'OBS_PASSWORD'
},
'api.suse.de' => {
user => 'IBS_USER',
ssh_key => 'SSH_PRIVATE_KEY_PATH'
user => 'IBS_USER',
ssh_key => 'SSH_PRIVATE_KEY_PATH',
embargoed_bugs => 'https://smash.suse.de/api/embargoed-bugs/'
}
},

Expand Down
90 changes: 60 additions & 30 deletions lib/Cavil/OBS.pm
Original file line number Diff line number Diff line change
Expand Up @@ -40,26 +40,53 @@ has ua => sub {
};

sub check_for_embargo ($self, $api, $request) {
my $url = _url($api, 'request', $request);
my $res = $self->_get($url);
my $bugrefs = $self->get_bugrefs_for_request($api, $request);
my $embargoed_bugrefs = $self->get_embargoed_bugrefs($api);

my %enbargoed = map { $_ => 1 } @$embargoed_bugrefs;
for my $bugref (@$bugrefs) {
return 1 if $enbargoed{$bugref};
}

return 0;
}

sub get_bugrefs_for_request ($self, $api, $request) {
my $url = _url($api, 'request', $request)
->query({cmd => 'diff', view => 'xml', withissues => 1, withdescriptionissues => 1});
my $res = $self->_request($url, 'POST');
croak "$url: " . $res->code unless $res->is_success;

for my $project ($res->dom->find('action [project]')->map('attr', 'project')->uniq->each) {
my $url = _url($api, 'source', $project, '_attribute');
my $res = $self->_get($url);
my $code = $res->code;
next if $code == 404;
my $dom = $res->dom;
my $bugrefs = {};
for my $issue ($dom->find('issues > issue[label]')->each) {
my $label = $issue->{label};
$bugrefs->{$label}++;

# Labels in SMASH and IBS can be inconsistent with "bnc#" and "bsc#" (so we generate both)
$bugrefs->{"bnc#$1"}++ if $label =~ /^bsc#(\d+)$/;
}

# Looks like OBS has repo types that do not support attributes yet and produces a bad 400 response in such cases
# (501 is supposed to treplace it in the future)
next if $code == 400 && $res->dom->at('status[code=remote_project]');
next if $code == 501;
return [sort keys %$bugrefs];
}

croak "$url: " . $res->code unless $res->is_success;
return 1 if $res->dom->at('attributes attribute[name=EmbargoDate]');
sub get_embargoed_bugrefs ($self, $api) {
my $ua = $self->ua;

my $host = _url($api)->host;
die "Missing configuration for OBS instance: $host" unless my $config = $self->config->{$host};
return [] unless my $embargoed_bugs = $config->{embargoed_bugs};

my $bugs = $ua->get($embargoed_bugs)->result->json;
my $bugrefs = {};
for my $bug (@$bugs) {
$bugrefs->{$bug->{bug}{name}}++;
for my $cve (@{$bug->{cves}}) {
$bugrefs->{$cve->{name}}++;
}
}

return 0;
return [sort keys %$bugrefs];
}

sub download_source ($self, $api, $project, $pkg, $dir, $options = {}) {
Expand All @@ -68,7 +95,7 @@ sub download_source ($self, $api, $project, $pkg, $dir, $options = {}) {
# List files
my $url = _url($api, 'source', $project, $pkg)->query(expand => 1);
$url->query([rev => $options->{rev}]) if defined $options->{rev};
my $res = $self->_get($url);
my $res = $self->_request($url);
croak "$url: " . $res->code unless $res->is_success;
my $dom = $res->dom;
my $srcmd5 = $dom->at('directory')->{srcmd5};
Expand All @@ -82,7 +109,7 @@ sub download_source ($self, $api, $project, $pkg, $dir, $options = {}) {

my $url = _url($api, 'source', $project, $pkg, $file->{name});
$url->query([expand => 1, rev => $srcmd5]);
my $res = $self->_get($url);
my $res = $self->_request($url);
croak "$url: " . $res->code unless $res->is_success;
my $target = $dir->child($file->{name});
$res->content->asset->move_to($target);
Expand All @@ -94,7 +121,7 @@ sub download_source ($self, $api, $project, $pkg, $dir, $options = {}) {
sub package_info ($self, $api, $project, $pkg, $options = {}) {
my $url = _url($api, 'source', $project, $pkg)->query(view => 'info');
$url->query([rev => $options->{rev}]) if defined $options->{rev};
my $res = $self->_get($url);
my $res = $self->_request($url);
croak "$url: " . $res->code unless $res->is_success;

my $source = $res->dom->at('sourceinfo');
Expand All @@ -111,7 +138,7 @@ sub _find_link_target ($self, $api, $project, $pkg, $lrev) {
my $query = {expand => 1};
$query->{rev} = $lrev if defined $lrev;
$url->query($query);
my $res = $self->_get($url);
my $res = $self->_request($url);
return undef unless $res->is_success;

# Check if we're on track
Expand All @@ -126,7 +153,7 @@ sub _find_link_target ($self, $api, $project, $pkg, $lrev) {
}
}
$url = _url($api, 'source', $project, $pkg, '_meta');
$res = $self->_get($url);
$res = $self->_request($url);

# This is severe as we already checked the sources
croak "$url: " . $res->code unless $res->is_success;
Expand All @@ -136,7 +163,13 @@ sub _find_link_target ($self, $api, $project, $pkg, $lrev) {
return {%linfo, package => $rn->text};
}

sub _get ($self, $url) {
sub _md5 ($file) {
my $md5 = Digest::MD5->new;
$md5->addfile(path($file)->open('r'));
return $md5->hexdigest;
}

sub _request ($self, $url, $method = 'GET') {
my $ua = $self->ua;

my $host = $url->host;
Expand All @@ -146,27 +179,24 @@ sub _get ($self, $url) {
# "api.suse.de" needs ssh authentication
my $tx;
if (my $ssh_key = $config->{ssh_key}) {
$tx = $ua->get($url);
$tx = $ua->start($ua->build_tx($method => $url));
my $res = $tx->res;
$tx = $ua->get($url, {Authorization => obs_ssh_auth($res->headers->www_authenticate, $user, $ssh_key)})
if $res->code == 401;
$tx = $ua->start(
$ua->build_tx(
$method => $url => {Authorization => obs_ssh_auth($res->headers->www_authenticate, $user, $ssh_key)}
)
) if $res->code == 401;
}

# All other instances should use basic authentication
else {
die "Missing password for OBS instance: $host" unless my $password = $config->{password};
$tx = $ua->get($url->userinfo("$user:$password"));
$tx = $ua->start($ua->build_tx($method => $url->userinfo("$user:$password")));
}

return $tx->result;
}

sub _md5 ($file) {
my $md5 = Digest::MD5->new;
$md5->addfile(path($file)->open('r'));
return $md5->hexdigest;
}

sub _url ($api, @path) {
my $url = Mojo::URL->new($api);
my $path = $url->path->leading_slash(1);
Expand Down
37 changes: 23 additions & 14 deletions t/embargo.t
Original file line number Diff line number Diff line change
Expand Up @@ -84,23 +84,30 @@ get("/source/:project/perl-Mojolicious.SUSE_SLE-15-SP2_Update//$_" => [project =
{data => path(__FILE__)->sibling('legal-bot', 'perl-Mojolicious', 'c7cfdab0e71b0bebfdf8b2dc3badfecd', $_)->slurp})
for @files;

get '/request/4321' => {text => <<'EOF'};
<request id="4321" creator="test2">
<action type="maintenance_release">
<source project="SUSE:Maintenance:4321" package="perl-Mojolicious.SUSE_SLE-15-SP2_Update"
rev="961b20692bc317a3c6ab3166312425da"/>
<target project="SUSE:SLE-15-SP2:Update" package="perl-Mojolicious.33127"/>
post '/request/4321' => (query => {cmd => 'diff', view => 'xml', withissues => 1, withdescriptionissues => 1}) =>
{status => 200, text => <<'EOF'};
<request id="4321" actions="0">
<action type="maintenance_incident">
<sourcediff key="08943b6f0b415b013042f01b23fabdd">
<issues>
<issue state="added" tracker="bnc" name="1196706" label="bsc#1196706" url="https://bugzilla.suse.com/show_bug.cgi?id=1196706"/>
</issues>
</sourcediff>
</action>
<description>requesting release</description>
</request>
EOF

get '/source/:project/_attribute' => [project => 'SUSE:Maintenance:4321'] => {text => <<'EOF'};
<attributes>
<attribute name="EmbargoDate" namespace="OBS">
<value>2024-03-27 07:00 UTC</value>
</attribute>
</attributes>
get '/api/embargoed-bugs' => {format => 'json', text => <<'EOF'};
[
{
"bug": {
"name": "bnc#1196706",
"url": "https://bugzilla.suse.com/show_bug.cgi?id=1196706",
"source": "SUSE Bugzilla"
},
"cves": []
}
]
EOF

get '/*whatever' => {whatever => ''} => {text => '', status => 404};
Expand All @@ -113,7 +120,8 @@ my $dir = $cavil_test->checkout_dir;
# Connect mock web service
my $mock_app = app;
my $api = 'http://127.0.0.1:' . $t->app->obs->ua->server->app($mock_app)->url->port;
$t->app->obs->config({'127.0.0.1' => {user => 'test', password => 'testing'}});
$t->app->obs->config(
{'127.0.0.1' => {user => 'test', password => 'testing', embargoed_bugs => "$api/api/embargoed-bugs"}});

subtest 'Embargoed package does not existy yet' => sub {
$t->get_ok('/package/3' => {Authorization => 'Token test_token'})->status_is(404)->content_like(qr/No such package/);
Expand Down Expand Up @@ -144,6 +152,7 @@ subtest 'Embargoed packages' => sub {
return unless $task eq 'obs_import';
$job->app->obs(Cavil::OBS->new(config => $job->app->obs->config));
my $api = 'http://127.0.0.1:' . $job->app->obs->ua->server->app($mock_app)->url->port;
$job->app->obs->config->{'127.0.0.1'}{embargoed_bugs} = "$api/api/embargoed-bugs";
$job->args->[1]{api} = $api;
}
);
Expand Down
Loading

0 comments on commit ee06b42

Please sign in to comment.