Imho it makes more sense from REST perspective. Also, in the future there will be ROUTE for uploading image to image build. As it's not a good idea transport file inside JSON, all the parameters (compose id and image build id) need to be inside the URL. Therefore for the sake of consistency, all these routes should have compose id and image build id in the URL. There is another solution to embedding multiple values inside http body which allows file transport - multipart/form-data. I think using form-data is worth when doing more complex stuff, for our usecase transporting all the metadata in the URL is more appropriate solution.
115 lines
5.4 KiB
Go
115 lines
5.4 KiB
Go
package jobqueue_test
|
|
|
|
import (
|
|
"net/http"
|
|
"testing"
|
|
|
|
"github.com/osbuild/osbuild-composer/internal/blueprint"
|
|
"github.com/osbuild/osbuild-composer/internal/distro"
|
|
test_distro "github.com/osbuild/osbuild-composer/internal/distro/fedoratest"
|
|
"github.com/osbuild/osbuild-composer/internal/jobqueue"
|
|
"github.com/osbuild/osbuild-composer/internal/store"
|
|
"github.com/osbuild/osbuild-composer/internal/test"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
func TestBasic(t *testing.T) {
|
|
var cases = []struct {
|
|
Method string
|
|
Path string
|
|
Body string
|
|
ExpectedStatus int
|
|
ExpectedResponse string
|
|
}{
|
|
// Create job with invalid body
|
|
{"POST", "/job-queue/v1/jobs", ``, http.StatusBadRequest, `invalid request: EOF`},
|
|
// Update job with invalid ID
|
|
{"PATCH", "/job-queue/v1/jobs/foo/builds/0", `{"status":"RUNNING"}`, http.StatusBadRequest, `invalid compose id: invalid UUID length: 3`},
|
|
// Update job that does not exist, with invalid body
|
|
{"PATCH", "/job-queue/v1/jobs/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa/builds/0", ``, http.StatusBadRequest, `invalid status: EOF`},
|
|
// Update job that does not exist
|
|
{"PATCH", "/job-queue/v1/jobs/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa/builds/0", `{"status":"RUNNING"}`, http.StatusNotFound, `compose does not exist`},
|
|
}
|
|
|
|
for _, c := range cases {
|
|
distroStruct := test_distro.New()
|
|
registry := distro.NewRegistry([]string{"."})
|
|
api := jobqueue.New(nil, store.New(nil, distroStruct, *registry))
|
|
|
|
test.TestNonJsonRoute(t, api, false, c.Method, c.Path, c.Body, c.ExpectedStatus, c.ExpectedResponse)
|
|
}
|
|
}
|
|
|
|
func TestCreate(t *testing.T) {
|
|
id, _ := uuid.Parse("ffffffff-ffff-ffff-ffff-ffffffffffff")
|
|
distroStruct := test_distro.New()
|
|
registry := distro.NewRegistry([]string{"."})
|
|
store := store.New(nil, distroStruct, *registry)
|
|
api := jobqueue.New(nil, store)
|
|
|
|
err := store.PushCompose(id, &blueprint.Blueprint{}, map[string]string{"test-repo": "test:foo"}, "x86_64", "qcow2", 0, nil)
|
|
if err != nil {
|
|
t.Fatalf("error pushing compose: %v", err)
|
|
}
|
|
|
|
test.TestRoute(t, api, false, "POST", "/job-queue/v1/jobs", `{}`, http.StatusCreated,
|
|
`{"distro":"fedora-30","id":"ffffffff-ffff-ffff-ffff-ffffffffffff","image_build_id":0,"output_type":"qcow2","pipeline":{},"targets":[]}`, "created", "uuid")
|
|
}
|
|
|
|
func testUpdateTransition(t *testing.T, from, to string, expectedStatus int, expectedResponse string) {
|
|
id, _ := uuid.Parse("ffffffff-ffff-ffff-ffff-ffffffffffff")
|
|
distroStruct := test_distro.New()
|
|
registry := distro.NewRegistry([]string{"."})
|
|
store := store.New(nil, distroStruct, *registry)
|
|
api := jobqueue.New(nil, store)
|
|
|
|
if from != "VOID" {
|
|
err := store.PushCompose(id, &blueprint.Blueprint{}, map[string]string{"test": "test:foo"}, "x86_64", "qcow2", 0, nil)
|
|
if err != nil {
|
|
t.Fatalf("error pushing compose: %v", err)
|
|
}
|
|
if from != "WAITING" {
|
|
test.SendHTTP(api, false, "POST", "/job-queue/v1/jobs", `{}`)
|
|
if from != "RUNNING" {
|
|
test.SendHTTP(api, false, "PATCH", "/job-queue/v1/jobs/ffffffff-ffff-ffff-ffff-ffffffffffff/builds/0", `{"status":"`+from+`"}`)
|
|
}
|
|
}
|
|
}
|
|
|
|
test.TestNonJsonRoute(t, api, false, "PATCH", "/job-queue/v1/jobs/ffffffff-ffff-ffff-ffff-ffffffffffff/builds/0", `{"status":"`+to+`"}`, expectedStatus, expectedResponse)
|
|
}
|
|
|
|
func TestUpdate(t *testing.T) {
|
|
var cases = []struct {
|
|
From string
|
|
To string
|
|
ExpectedStatus int
|
|
ExpectedResponse string
|
|
}{
|
|
{"VOID", "WAITING", http.StatusNotFound, "compose does not exist"},
|
|
{"VOID", "RUNNING", http.StatusNotFound, "compose does not exist"},
|
|
{"VOID", "FINISHED", http.StatusNotFound, "compose does not exist"},
|
|
{"VOID", "FAILED", http.StatusNotFound, "compose does not exist"},
|
|
{"WAITING", "WAITING", http.StatusNotFound, "compose has not been popped"},
|
|
{"WAITING", "RUNNING", http.StatusNotFound, "compose has not been popped"},
|
|
{"WAITING", "FINISHED", http.StatusNotFound, "compose has not been popped"},
|
|
{"WAITING", "FAILED", http.StatusNotFound, "compose has not been popped"},
|
|
{"RUNNING", "WAITING", http.StatusBadRequest, "invalid state transition: image build cannot be moved into waiting state"},
|
|
{"RUNNING", "RUNNING", http.StatusOK, ""},
|
|
{"RUNNING", "FINISHED", http.StatusOK, ""},
|
|
{"RUNNING", "FAILED", http.StatusOK, ""},
|
|
{"FINISHED", "WAITING", http.StatusBadRequest, "invalid state transition: image build cannot be moved into waiting state"},
|
|
{"FINISHED", "RUNNING", http.StatusBadRequest, "invalid state transition: only waiting image build can be transitioned into running state"},
|
|
{"FINISHED", "FINISHED", http.StatusBadRequest, "invalid state transition: only running image build can be transitioned into finished or failed state"},
|
|
{"FINISHED", "FAILED", http.StatusBadRequest, "invalid state transition: only running image build can be transitioned into finished or failed state"},
|
|
{"FAILED", "WAITING", http.StatusBadRequest, "invalid state transition: image build cannot be moved into waiting state"},
|
|
{"FAILED", "RUNNING", http.StatusBadRequest, "invalid state transition: only waiting image build can be transitioned into running state"},
|
|
{"FAILED", "FINISHED", http.StatusBadRequest, "invalid state transition: only running image build can be transitioned into finished or failed state"},
|
|
{"FAILED", "FAILED", http.StatusBadRequest, "invalid state transition: only running image build can be transitioned into finished or failed state"},
|
|
}
|
|
|
|
for _, c := range cases {
|
|
testUpdateTransition(t, c.From, c.To, c.ExpectedStatus, c.ExpectedResponse)
|
|
}
|
|
}
|