2021-04-28 22:24:24 +00:00
use strict ;
2021-08-19 20:36:43 +00:00
use warnings ;
2021-04-28 22:24:24 +00:00
use Setup ;
2021-10-20 02:53:39 +00:00
use JSON::MaybeXS ;
2021-04-28 22:24:24 +00:00
use File::Copy ;
2013-06-17 16:34:21 +00:00
2021-04-28 22:24:24 +00:00
my % ctx = test_init (
hydra_config = > q |
# No caching for PathInput plugin, otherwise we get wrong values
# (as it has a 30s window where no changes to the file are considered).
path_input_cache_validity_seconds = 0
|
) ;
my $ jobsetdir = $ ctx { tmpdir } . '/jobset' ;
mkdir ( $ jobsetdir ) ;
copy ( $ ctx { jobsdir } . '/api-test.nix' , "$jobsetdir/default.nix" ) ;
require Hydra::Schema ;
use HTTP::Request::Common ;
use Test2::V0 ;
require Catalyst::Test ;
Catalyst::Test - > import ( 'Hydra' ) ;
my $ db = Hydra::Model::DB - > new ;
hydra_setup ( $ db ) ;
{
my $ user = $ db - > resultset ( 'Users' ) - > find ( { username = > 'root' } ) ;
$ user - > setPassword ( 'foobar' ) ;
$ user - > userroles - > update_or_create ( { role = > 'admin' } ) ;
}
my $ cookie = "" ;
2013-06-17 16:34:21 +00:00
sub request_json {
my ( $ opts ) = @ _ ;
my $ req = HTTP::Request - > new ;
$ req - > method ( $ opts - > { method } or "GET" ) ;
2021-04-28 22:24:24 +00:00
$ req - > uri ( "http://localhost$opts->{uri}" ) ;
2013-06-17 16:34:21 +00:00
$ req - > header ( Accept = > "application/json" ) ;
2021-04-28 22:24:24 +00:00
$ req - > header ( Content_Type = > "application/json" ) ;
2022-01-10 15:38:48 +00:00
$ req - > header ( Origin = > "http://localhost/" ) if ( $ opts - > { method } // "" ) eq "POST" ;
2021-04-28 22:24:24 +00:00
$ req - > header ( Cookie = > $ cookie ) ;
2013-06-17 16:34:21 +00:00
$ req - > content ( encode_json ( $ opts - > { data } ) ) if defined $ opts - > { data } ;
2021-04-28 22:24:24 +00:00
my $ res = request ( $ req ) ;
2013-06-17 16:34:21 +00:00
return $ res ;
}
2021-04-28 23:41:49 +00:00
subtest "login" = > sub {
subtest "bad password" = > sub {
my $ result = request_json ( { uri = > "/login" , method = > "POST" , data = > { username = > "root" , password = > "wrong" } } ) ;
is ( $ result - > code ( ) , 403 , "Incorrect password rejected." ) ;
} ;
2013-11-06 15:10:47 +00:00
2021-04-28 23:41:49 +00:00
my $ result = request_json ( { uri = > "/login" , method = > "POST" , data = > { username = > "root" , password = > "foobar" } } ) ;
2013-06-17 16:34:21 +00:00
2021-04-28 23:41:49 +00:00
my $ user = decode_json ( $ result - > content ( ) ) ;
2013-06-17 16:34:21 +00:00
2021-04-28 23:41:49 +00:00
is ( $ user - > { username } , "root" , "The root user is named root" ) ;
is ( $ user - > { userroles } - > [ 0 ] , "admin" , "The root user is an admin" ) ;
$ cookie = $ result - > header ( "set-cookie" ) ;
2013-06-17 16:34:21 +00:00
2021-04-28 23:41:49 +00:00
$ user = decode_json ( request_json ( { uri = > "/current-user" } ) - > content ( ) ) ;
is ( $ user - > { username } , "root" , "The current user is named root" ) ;
is ( $ user - > { userroles } - > [ 0 ] , "admin" , "The current user is an admin" ) ;
} ;
2013-10-16 20:48:03 +00:00
2021-04-28 23:41:49 +00:00
subtest "projects" = > sub {
is ( request_json ( { uri = > '/project/sample' } ) - > code ( ) , 404 , "Non-existent projects don't exist" ) ;
2013-06-17 16:34:21 +00:00
2021-04-28 23:41:49 +00:00
my $ result = request_json ( { uri = > '/project/sample' , method = > 'PUT' , data = > { displayname = > "Sample" , enabled = > "1" , visible = > "1" , } } ) ;
is ( $ result - > code ( ) , 201 , "PUTting a new project creates it" ) ;
2013-06-17 16:34:21 +00:00
2021-04-28 23:41:49 +00:00
my $ project = decode_json ( request_json ( { uri = > '/project/sample' } ) - > content ( ) ) ;
2013-06-17 16:34:21 +00:00
2021-04-28 23:41:49 +00:00
ok ( ( not @ { $ project - > { jobsets } } ) , "A new project has no jobsets" ) ;
} ;
2013-06-17 16:34:21 +00:00
2021-04-28 23:41:49 +00:00
subtest "jobsets" = > sub {
2021-04-28 19:41:05 +00:00
my $ result = request_json ( { uri = > '/jobset/sample/default' , method = > 'PUT' , data = > { nixexprpath = > "default.nix" , nixexprinput = > "my-src" , inputs = > { "my-src" = > { type = > "path" , value = > $ jobsetdir } } , enabled = > "1" , visible = > "1" , checkinterval = > "3600" } } ) ;
2021-04-28 23:41:49 +00:00
is ( $ result - > code ( ) , 201 , "PUTting a new jobset creates it" ) ;
2013-06-17 16:34:21 +00:00
2021-04-28 23:41:49 +00:00
my $ jobset = decode_json ( request_json ( { uri = > '/jobset/sample/default' } ) - > content ( ) ) ;
2013-06-17 16:34:21 +00:00
2021-04-28 19:41:05 +00:00
ok ( exists $ jobset - > { inputs } - > { "my-src" } , "The new jobset has a 'my-src' input" ) ;
2013-10-24 15:01:17 +00:00
2021-04-28 19:41:05 +00:00
is ( $ jobset - > { inputs } - > { "my-src" } - > { value } , $ jobsetdir , "The 'my-src' input is in $jobsetdir" ) ;
2021-04-28 23:41:49 +00:00
} ;
2021-04-28 22:24:24 +00:00
2021-04-28 23:41:49 +00:00
subtest "evaluation" = > sub {
subtest "initial evaluaton" = > sub {
ok ( evalSucceeds ( $ db - > resultset ( 'Jobsets' ) - > find ( { name = > 'default' } ) ) , "Evaluating should exit with return code 0" ) ;
2013-10-24 15:01:17 +00:00
2021-04-28 23:41:49 +00:00
my $ result = request_json ( { uri = > '/jobset/sample/default/evals' } ) ;
is ( $ result - > code ( ) , 200 , "Can get evals of a jobset" ) ;
my $ evals = decode_json ( $ result - > content ( ) ) - > { evals } ;
my $ eval = $ evals - > [ 0 ] ;
is ( $ eval - > { hasnewbuilds } , 1 , "The first eval of a jobset has new builds" ) ;
} ;
2013-06-17 16:34:21 +00:00
2021-04-28 23:41:49 +00:00
subtest "second evaluation" = > sub {
open ( my $ fh , ">>" , "${jobsetdir}/default.nix" ) or die "didn't open?" ;
say $ fh "\n" ;
close $ fh ;
ok ( evalSucceeds ( $ db - > resultset ( 'Jobsets' ) - > find ( { name = > 'default' } ) ) , "Evaluating should exit with return code 0" ) ;
2021-04-28 22:24:24 +00:00
2021-04-28 23:41:49 +00:00
my $ evals = decode_json ( request_json ( { uri = > '/jobset/sample/default/evals' } ) - > content ( ) ) - > { evals } ;
is ( scalar ( @$ evals ) , 2 , "Changing a jobset source creates the second evaluation" ) ;
isnt ( $ evals - > [ 0 ] - > { jobsetevalinputs } - > { "my-src" } - > { revision } , $ evals - > [ 1 ] - > { jobsetevalinputs } - > { "my-src" } - > { revision } , "Changing a jobset source changes its revision" ) ;
2021-04-28 22:24:24 +00:00
2021-04-28 23:41:49 +00:00
my $ build = decode_json ( request_json ( { uri = > "/build/" . $ evals - > [ 0 ] - > { builds } - > [ 0 ] } ) - > content ( ) ) ;
is ( $ build - > { job } , "job" , "The build's job name is job" ) ;
is ( $ build - > { finished } , 0 , "The build isn't finished yet" ) ;
ok ( $ build - > { buildoutputs } - > { out } - > { path } =~ /\/nix\/store\/[a-zA-Z0-9]{32}-job$/ , "The build's outpath is in the Nix store and named 'job'" ) ;
2013-10-24 19:38:20 +00:00
2021-04-28 23:41:49 +00:00
subtest "search" = > sub {
my $ search_project = decode_json ( request_json ( { uri = > "/search/?query=sample" } ) - > content ( ) ) ;
is ( $ search_project - > { projects } [ 0 ] - > { name } , "sample" , "Search for project 'sample' works" ) ;
Add json output for the search API endpoint
This commit also add a test of this feature.
Note the search JSON output doesn't contain any jobs because they can
not be exported to JSON yet.
The JSON output on a search query matching a build looks like:
```
{
"builds": [
{
"buildoutputs": {
"out": {
"path": "/nix/store/wdag3pznrvqk01byk989irg7rq3q2a2c-job"
}
},
"finished": 0,
"releasename": null,
"starttime": null,
"project": "sample",
"buildproducts": {},
"timestamp": 1541007629,
"buildstatus": null,
"nixname": "job",
"drvpath": "/nix/store/n9zqndn7j7nyr6gg3bmxvw26cfmdwv2n-job.drv",
"job": "job",
"id": 1,
"stoptime": null,
"priority": 100,
"system": "x86_64-linux",
"jobsetevals": [
1
],
"jobset": "default",
"buildmetrics": {}
}
],
"projects": [],
"jobsets": [],
"buildsdrv": []
}
```
2018-10-31 17:46:33 +00:00
2021-04-28 23:41:49 +00:00
my $ search_build = decode_json ( request_json ( { uri = > "/search/?query=" . $ build - > { buildoutputs } - > { out } - > { path } } ) - > content ( ) ) ;
is ( $ search_build - > { builds } [ 0 ] - > { buildoutputs } - > { out } - > { path } , $ build - > { buildoutputs } - > { out } - > { path } , "Search for builds work" ) ;
} ;
} ;
} ;
Add json output for the search API endpoint
This commit also add a test of this feature.
Note the search JSON output doesn't contain any jobs because they can
not be exported to JSON yet.
The JSON output on a search query matching a build looks like:
```
{
"builds": [
{
"buildoutputs": {
"out": {
"path": "/nix/store/wdag3pznrvqk01byk989irg7rq3q2a2c-job"
}
},
"finished": 0,
"releasename": null,
"starttime": null,
"project": "sample",
"buildproducts": {},
"timestamp": 1541007629,
"buildstatus": null,
"nixname": "job",
"drvpath": "/nix/store/n9zqndn7j7nyr6gg3bmxvw26cfmdwv2n-job.drv",
"job": "job",
"id": 1,
"stoptime": null,
"priority": 100,
"system": "x86_64-linux",
"jobsetevals": [
1
],
"jobset": "default",
"buildmetrics": {}
}
],
"projects": [],
"jobsets": [],
"buildsdrv": []
}
```
2018-10-31 17:46:33 +00:00
2021-04-30 17:42:38 +00:00
subtest "delete project" = > sub {
subtest "with evaluations and builds" = > sub {
my $ result = request_json ( { uri = > "/project/sample" , method = > "DELETE" } ) ;
is ( $ result - > code ( ) , 200 , "DELETEing a project with evaluations and builds succeeds" ) ;
} ;
subtest "without evaluations and builds" = > sub {
my $ project = request_json ( { uri = > '/project/sample2' , method = > 'PUT' , data = > { displayname = > "Sample2" , enabled = > "1" , visible = > "1" , } } ) ;
is ( $ project - > code ( ) , 201 , "PUTting a new project creates it" ) ;
my $ jobset = request_json ( { uri = > '/jobset/sample2/default2' , method = > 'PUT' , data = > { type = > "1" , flake = > "github:nixos/nix" , enabled = > "1" , visible = > "1" , checkinterval = > "0" } } ) ;
is ( $ jobset - > code ( ) , 201 , "PUTting a new jobset creates it" ) ;
my $ delete = request_json ( { uri = > "/project/sample2" , method = > "DELETE" } ) ;
is ( $ delete - > code ( ) , 200 , "DELETEing a jobset with no evaluations and builds succeeds" ) ;
} ;
} ;
2021-04-28 23:41:49 +00:00
done_testing ;