package v2_test import ( "context" "encoding/json" "fmt" "io/ioutil" "net/http" "os" "testing" "github.com/stretchr/testify/require" v2 "github.com/osbuild/osbuild-composer/internal/cloudapi/v2" "github.com/osbuild/osbuild-composer/internal/distro/test_distro" "github.com/osbuild/osbuild-composer/internal/jobqueue" "github.com/osbuild/osbuild-composer/internal/jobqueue/fsjobqueue" distro_mock "github.com/osbuild/osbuild-composer/internal/mocks/distro" "github.com/osbuild/osbuild-composer/internal/ostree/mock_ostree_repo" "github.com/osbuild/osbuild-composer/internal/rpmmd" "github.com/osbuild/osbuild-composer/internal/test" "github.com/osbuild/osbuild-composer/internal/worker" "github.com/osbuild/osbuild-composer/internal/worker/clienterrors" ) func newV2Server(t *testing.T, dir string, depsolveChannels []string, enableJWT bool) (*v2.Server, *worker.Server, jobqueue.JobQueue, context.CancelFunc) { q, err := fsjobqueue.New(dir) require.NoError(t, err) workerServer := worker.NewServer(nil, q, worker.Config{BasePath: "/api/worker/v1", JWTEnabled: enableJWT, TenantProviderFields: []string{"rh-org-id", "account_id"}}) distros, err := distro_mock.NewDefaultRegistry() require.NoError(t, err) require.NotNil(t, distros) config := v2.ServerConfig{ AWSBucket: "image-builder.service", JWTEnabled: enableJWT, TenantProviderFields: []string{"rh-org-id", "account_id"}, } v2Server := v2.NewServer(workerServer, distros, config) require.NotNil(t, v2Server) // start a routine which just completes depsolve jobs depsolveContext, cancel := context.WithCancel(context.Background()) go func() { for { _, token, _, _, _, err := workerServer.RequestJob(context.Background(), test_distro.TestDistroName, []string{"depsolve"}, depsolveChannels) if err != nil { continue } rawMsg, err := json.Marshal(&worker.DepsolveJobResult{PackageSpecs: map[string][]rpmmd.PackageSpec{"build": []rpmmd.PackageSpec{rpmmd.PackageSpec{Name: "pkg1"}}}, Error: "", ErrorType: worker.ErrorType("")}) require.NoError(t, err) err = workerServer.FinishJob(token, rawMsg) if err != nil { return } select { case <-depsolveContext.Done(): return default: continue } } }() return v2Server, workerServer, q, cancel } func TestUnknownRoute(t *testing.T) { dir, err := ioutil.TempDir("", "osbuild-composer-test-api-v2-") require.NoError(t, err) defer os.RemoveAll(dir) srv, _, _, cancel := newV2Server(t, dir, []string{""}, false) defer cancel() test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "GET", "/api/image-builder-composer/v2/badroute", ``, http.StatusNotFound, ` { "href": "/api/image-builder-composer/v2/errors/21", "id": "21", "kind": "Error", "code": "IMAGE-BUILDER-COMPOSER-21", "reason": "Requested resource doesn't exist" }`, "operation_id") } func TestGetError(t *testing.T) { dir, err := ioutil.TempDir("", "osbuild-composer-test-api-v2-") require.NoError(t, err) defer os.RemoveAll(dir) srv, _, _, cancel := newV2Server(t, dir, []string{""}, false) defer cancel() test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "GET", "/api/image-builder-composer/v2/errors/4", ``, http.StatusOK, ` { "href": "/api/image-builder-composer/v2/errors/4", "id": "4", "kind": "Error", "code": "IMAGE-BUILDER-COMPOSER-4", "reason": "Unsupported distribution" }`, "operation_id") test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "GET", "/api/image-builder-composer/v2/errors/3000", ``, http.StatusNotFound, ` { "href": "/api/image-builder-composer/v2/errors/17", "id": "17", "kind": "Error", "code": "IMAGE-BUILDER-COMPOSER-17", "reason": "Error with given id not found" }`, "operation_id") } func TestGetErrorList(t *testing.T) { dir, err := ioutil.TempDir("", "osbuild-composer-test-api-v2-") require.NoError(t, err) defer os.RemoveAll(dir) srv, _, _, cancel := newV2Server(t, dir, []string{""}, false) defer cancel() test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "GET", "/api/image-builder-composer/v2/errors?page=3&size=1", ``, http.StatusOK, ` { "kind": "ErrorList", "page": 3, "size": 1, "items": [{ "href": "/api/image-builder-composer/v2/errors/4", "id": "4", "kind": "Error", "code": "IMAGE-BUILDER-COMPOSER-4", "reason": "Unsupported distribution" }] }`, "operation_id", "total") } func TestCompose(t *testing.T) { dir, err := ioutil.TempDir("", "osbuild-composer-test-api-v2-") require.NoError(t, err) defer os.RemoveAll(dir) srv, _, _, cancel := newV2Server(t, dir, []string{""}, false) defer cancel() // create two ostree repos, one to serve the default test_distro ref (for fallback tests) and one to serve a custom ref ostreeRepoDefault := mock_ostree_repo.Setup(test_distro.New().OSTreeRef()) defer ostreeRepoDefault.TearDown() ostreeRepoOther := mock_ostree_repo.Setup("some/other/ref") defer ostreeRepoOther.TearDown() // unsupported distribution test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "POST", "/api/image-builder-composer/v2/compose", fmt.Sprintf(` { "distribution": "unsupported_distro", "image_request":{ "architecture": "%s", "image_type": "aws.ec2", "repositories": [{ "baseurl": "somerepo.org", "rhsm": false }], "upload_options": { "region": "eu-central-1", "share_with_accounts": ["123456789012"] } } }`, test_distro.TestArch3Name), http.StatusBadRequest, ` { "href": "/api/image-builder-composer/v2/errors/4", "id": "4", "kind": "Error", "code": "IMAGE-BUILDER-COMPOSER-4", "reason": "Unsupported distribution" }`, "operation_id") // unsupported architecture test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "POST", "/api/image-builder-composer/v2/compose", fmt.Sprintf(` { "distribution": "%s", "image_request":{ "architecture": "unsupported_arch", "image_type": "aws", "repositories": [{ "baseurl": "somerepo.org", "rhsm": false }], "upload_options": { "region": "eu-central-1" } } }`, test_distro.TestDistroName), http.StatusBadRequest, ` { "href": "/api/image-builder-composer/v2/errors/5", "id": "5", "kind": "Error", "code": "IMAGE-BUILDER-COMPOSER-5", "reason": "Unsupported architecture" }`, "operation_id") // unsupported imagetype test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "POST", "/api/image-builder-composer/v2/compose", fmt.Sprintf(` { "distribution": "%s", "image_request":{ "architecture": "%s", "image_type": "unsupported_image_type", "repositories": [{ "baseurl": "somerepo.org", "rhsm": false }], "upload_options": { "region": "eu-central-1" } } }`, test_distro.TestDistroName, test_distro.TestArch3Name), http.StatusBadRequest, ` { "href": "/api/image-builder-composer/v2/errors/6", "id": "6", "kind": "Error", "code": "IMAGE-BUILDER-COMPOSER-6", "reason": "Unsupported image type" }`, "operation_id") // Returns 404, but should be 405; see https://github.com/labstack/echo/issues/1981 // test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "GET", "/api/image-builder-composer/v2/compose", fmt.Sprintf(` // { // "distribution": "%s", // "image_requests":[{ // "architecture": "%s", // "image_type": "%s", // "repositories": [{ // "baseurl": "somerepo.org", // "rhsm": false // }], // "upload_options": { // "region": "eu-central-1" // } // }] // }`, test_distro.TestDistroName, test_distro.TestArch3Name, test_distro.TestImageTypeName), http.StatusMethodNotAllowed, ` // { // "href": "/api/image-builder-composer/v2/errors/22", // "id": "22", // "kind": "Error", // "code": "IMAGE-BUILDER-COMPOSER-22", // "reason": "Requested method isn't supported for resource" // }`, "operation_id") test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "POST", "/api/image-builder-composer/v2/compose", fmt.Sprintf(` { "distribution": "%s", "image_request":{ "architecture": "%s", "image_type": "aws", "repositories": [{ "baseurl": "somerepo.org", "rhsm": false }], "upload_options": { "region": "eu-central-1" } } }`, test_distro.TestDistroName, test_distro.TestArch3Name), http.StatusCreated, ` { "href": "/api/image-builder-composer/v2/compose", "kind": "ComposeId" }`, "id") test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "POST", "/api/image-builder-composer/v2/compose", fmt.Sprintf(` { "distribution": "%s", "koji":{ "name": "name", "version": "version", "release": "release", "server": "https://koji.example.com", "task_id": 42 }, "image_request":{ "architecture": "%s", "image_type": "aws", "repositories": [{ "baseurl": "somerepo.org", "rhsm": false }] } }`, test_distro.TestDistroName, test_distro.TestArch3Name), http.StatusCreated, ` { "href": "/api/image-builder-composer/v2/compose", "kind": "ComposeId" }`, "id") // ostree parameters (success) // ref only test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "POST", "/api/image-builder-composer/v2/compose", fmt.Sprintf(` { "distribution": "%s", "image_request":{ "architecture": "%s", "image_type": "edge-commit", "repositories": [{ "baseurl": "somerepo.org", "rhsm": false }], "upload_options": { "region": "eu-central-1" }, "ostree": { "ref": "rhel/10/x86_64/edge" } } }`, test_distro.TestDistroName, test_distro.TestArch3Name), http.StatusCreated, ` { "href": "/api/image-builder-composer/v2/compose", "kind": "ComposeId" }`, "id") // url only (must use ostreeRepoDefault for default ref) test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "POST", "/api/image-builder-composer/v2/compose", fmt.Sprintf(` { "distribution": "%s", "image_request":{ "architecture": "%s", "image_type": "edge-commit", "repositories": [{ "baseurl": "somerepo.org", "rhsm": false }], "upload_options": { "region": "eu-central-1" }, "ostree": { "url": "%s" } } }`, test_distro.TestDistroName, test_distro.TestArch3Name, ostreeRepoDefault.Server.URL), http.StatusCreated, ` { "href": "/api/image-builder-composer/v2/compose", "kind": "ComposeId" }`, "id") // ref + url test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "POST", "/api/image-builder-composer/v2/compose", fmt.Sprintf(` { "distribution": "%s", "image_request":{ "architecture": "%s", "image_type": "edge-commit", "repositories": [{ "baseurl": "somerepo.org", "rhsm": false }], "upload_options": { "region": "eu-central-1" }, "ostree": { "ref": "%s", "url": "%s" } } }`, test_distro.TestDistroName, test_distro.TestArch3Name, ostreeRepoDefault.OSTreeRef, ostreeRepoDefault.Server.URL), http.StatusCreated, ` { "href": "/api/image-builder-composer/v2/compose", "kind": "ComposeId" }`, "id") // parent + url test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "POST", "/api/image-builder-composer/v2/compose", fmt.Sprintf(` { "distribution": "%s", "image_request":{ "architecture": "%s", "image_type": "edge-commit", "repositories": [{ "baseurl": "somerepo.org", "rhsm": false }], "upload_options": { "region": "eu-central-1" }, "ostree": { "parent": "%s", "url": "%s" } } }`, test_distro.TestDistroName, test_distro.TestArch3Name, ostreeRepoDefault.OSTreeRef, ostreeRepoDefault.Server.URL), http.StatusCreated, ` { "href": "/api/image-builder-composer/v2/compose", "kind": "ComposeId" }`, "id") // ref + parent + url test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "POST", "/api/image-builder-composer/v2/compose", fmt.Sprintf(` { "distribution": "%s", "image_request":{ "architecture": "%s", "image_type": "edge-commit", "repositories": [{ "baseurl": "somerepo.org", "rhsm": false }], "upload_options": { "region": "eu-central-1" }, "ostree": { "parent": "%s", "url": "%s", "ref": "a/new/ref" } } }`, test_distro.TestDistroName, test_distro.TestArch3Name, ostreeRepoOther.OSTreeRef, ostreeRepoOther.Server.URL), http.StatusCreated, ` { "href": "/api/image-builder-composer/v2/compose", "kind": "ComposeId" }`, "id") // ostree errors // bad url test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "POST", "/api/image-builder-composer/v2/compose", fmt.Sprintf(` { "distribution": "%s", "image_request":{ "architecture": "%s", "image_type": "edge-commit", "repositories": [{ "baseurl": "somerepo.org", "rhsm": false }], "upload_options": { "region": "eu-central-1" }, "ostree": { "ref": "rhel/10/x86_64/edge", "url": "not-a-URL" } } }`, test_distro.TestDistroName, test_distro.TestArch3Name), http.StatusBadRequest, ` { "href": "/api/image-builder-composer/v2/errors/10", "id": "10", "kind": "Error", "code": "IMAGE-BUILDER-COMPOSER-10", "reason": "Error resolving OSTree repo" }`, "operation_id") // bad ref test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "POST", "/api/image-builder-composer/v2/compose", fmt.Sprintf(` { "distribution": "%s", "image_request":{ "architecture": "%s", "image_type": "edge-commit", "repositories": [{ "baseurl": "somerepo.org", "rhsm": false }], "upload_options": { "region": "eu-central-1" }, "ostree": { "ref": "/bad/ref" } } }`, test_distro.TestDistroName, test_distro.TestArch3Name), http.StatusBadRequest, ` { "href": "/api/image-builder-composer/v2/errors/9", "id": "9", "kind": "Error", "code": "IMAGE-BUILDER-COMPOSER-9", "reason": "Invalid OSTree ref" }`, "operation_id") // bad parent ref test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "POST", "/api/image-builder-composer/v2/compose", fmt.Sprintf(` { "distribution": "%s", "image_request":{ "architecture": "%s", "image_type": "edge-commit", "repositories": [{ "baseurl": "somerepo.org", "rhsm": false }], "upload_options": { "region": "eu-central-1" }, "ostree": { "ref": "%s", "url": "%s", "parent": "/bad/ref/number/2" } } }`, test_distro.TestDistroName, test_distro.TestArch3Name, ostreeRepoDefault.OSTreeRef, ostreeRepoDefault.Server.URL), http.StatusBadRequest, ` { "href": "/api/image-builder-composer/v2/errors/9", "id": "9", "kind": "Error", "code": "IMAGE-BUILDER-COMPOSER-9", "reason": "Invalid OSTree ref" }`, "operation_id") // incorrect ref for URL test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "POST", "/api/image-builder-composer/v2/compose", fmt.Sprintf(` { "distribution": "%s", "image_request":{ "architecture": "%s", "image_type": "edge-commit", "repositories": [{ "baseurl": "somerepo.org", "rhsm": false }], "upload_options": { "region": "eu-central-1" }, "ostree": { "url": "%s", "parent": "incorrect/ref" } } }`, test_distro.TestDistroName, test_distro.TestArch3Name, ostreeRepoOther.Server.URL), http.StatusBadRequest, ` { "href": "/api/image-builder-composer/v2/errors/10", "id": "10", "kind": "Error", "code": "IMAGE-BUILDER-COMPOSER-10", "reason": "Error resolving OSTree repo" }`, "operation_id") // parent ref without URL test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "POST", "/api/image-builder-composer/v2/compose", fmt.Sprintf(` { "distribution": "%s", "image_request":{ "architecture": "%s", "image_type": "edge-commit", "repositories": [{ "baseurl": "somerepo.org", "rhsm": false }], "upload_options": { "region": "eu-central-1" }, "ostree": { "parent": "some/ref" } } }`, test_distro.TestDistroName, test_distro.TestArch3Name), http.StatusBadRequest, ` { "href": "/api/image-builder-composer/v2/errors/27", "id": "27", "kind": "Error", "code": "IMAGE-BUILDER-COMPOSER-27", "reason": "Invalid OSTree parameters or parameter combination" }`, "operation_id") } func TestComposeStatusSuccess(t *testing.T) { dir, err := ioutil.TempDir("", "osbuild-composer-test-api-v2-") require.NoError(t, err) defer os.RemoveAll(dir) srv, wrksrv, _, cancel := newV2Server(t, dir, []string{""}, false) defer cancel() test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "POST", "/api/image-builder-composer/v2/compose", fmt.Sprintf(` { "distribution": "%s", "image_request":{ "architecture": "%s", "image_type": "aws", "repositories": [{ "baseurl": "somerepo.org", "rhsm": false }], "upload_options": { "region": "eu-central-1" } } }`, test_distro.TestDistroName, test_distro.TestArch3Name), http.StatusCreated, ` { "href": "/api/image-builder-composer/v2/compose", "kind": "ComposeId" }`, "id") jobId, token, jobType, args, dynArgs, err := wrksrv.RequestJob(context.Background(), test_distro.TestArch3Name, []string{"osbuild"}, []string{""}) require.NoError(t, err) require.Equal(t, "osbuild", jobType) var osbuildJob worker.OSBuildJob err = json.Unmarshal(args, &osbuildJob) require.NoError(t, err) require.Equal(t, 0, len(osbuildJob.Manifest)) require.NotEqual(t, 0, len(dynArgs[0])) test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "GET", fmt.Sprintf("/api/image-builder-composer/v2/composes/%v", jobId), ``, http.StatusOK, fmt.Sprintf(` { "href": "/api/image-builder-composer/v2/composes/%v", "kind": "ComposeStatus", "id": "%v", "image_status": {"status": "building"}, "status": "pending" }`, jobId, jobId)) res, err := json.Marshal(&worker.OSBuildJobResult{ Success: true, }) require.NoError(t, err) err = wrksrv.FinishJob(token, res) require.NoError(t, err) test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "GET", fmt.Sprintf("/api/image-builder-composer/v2/composes/%v", jobId), ``, http.StatusOK, fmt.Sprintf(` { "href": "/api/image-builder-composer/v2/composes/%v", "kind": "ComposeStatus", "id": "%v", "image_status": {"status": "success"}, "status": "success" }`, jobId, jobId)) test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "GET", fmt.Sprintf("/api/image-builder-composer/v2/composes/%v/metadata", jobId), ``, http.StatusInternalServerError, ` { "href": "/api/image-builder-composer/v2/errors/1012", "id": "1012", "kind": "Error", "code": "IMAGE-BUILDER-COMPOSER-1012", "reason": "OSBuildJobResult does not have expected fields set" }`, "operation_id") } func TestComposeStatusFailure(t *testing.T) { dir, err := ioutil.TempDir("", "osbuild-composer-test-api-v2-") require.NoError(t, err) defer os.RemoveAll(dir) srv, wrksrv, _, cancel := newV2Server(t, dir, []string{""}, false) defer cancel() test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "POST", "/api/image-builder-composer/v2/compose", fmt.Sprintf(` { "distribution": "%s", "image_request":{ "architecture": "%s", "image_type": "aws", "repositories": [{ "baseurl": "somerepo.org", "rhsm": false }], "upload_options": { "region": "eu-central-1" } } }`, test_distro.TestDistroName, test_distro.TestArch3Name), http.StatusCreated, ` { "href": "/api/image-builder-composer/v2/compose", "kind": "ComposeId" }`, "id") jobId, token, jobType, _, _, err := wrksrv.RequestJob(context.Background(), test_distro.TestArch3Name, []string{"osbuild"}, []string{""}) require.NoError(t, err) require.Equal(t, "osbuild", jobType) test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "GET", fmt.Sprintf("/api/image-builder-composer/v2/composes/%v", jobId), ``, http.StatusOK, fmt.Sprintf(` { "href": "/api/image-builder-composer/v2/composes/%v", "kind": "ComposeStatus", "id": "%v", "image_status": {"status": "building"}, "status": "pending" }`, jobId, jobId)) err = wrksrv.FinishJob(token, nil) require.NoError(t, err) test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "GET", fmt.Sprintf("/api/image-builder-composer/v2/composes/%v", jobId), ``, http.StatusOK, fmt.Sprintf(` { "href": "/api/image-builder-composer/v2/composes/%v", "kind": "ComposeStatus", "id": "%v", "image_status": {"status": "failure"}, "status": "failure" }`, jobId, jobId)) } func TestComposeLegacyError(t *testing.T) { dir, err := ioutil.TempDir("", "osbuild-composer-test-api-v2-") require.NoError(t, err) defer os.RemoveAll(dir) srv, wrksrv, _, cancel := newV2Server(t, dir, []string{""}, false) defer cancel() test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "POST", "/api/image-builder-composer/v2/compose", fmt.Sprintf(` { "distribution": "%s", "image_request":{ "architecture": "%s", "image_type": "aws", "repositories": [{ "baseurl": "somerepo.org", "rhsm": false }], "upload_options": { "region": "eu-central-1" } } }`, test_distro.TestDistroName, test_distro.TestArch3Name), http.StatusCreated, ` { "href": "/api/image-builder-composer/v2/compose", "kind": "ComposeId" }`, "id") jobId, token, jobType, _, _, err := wrksrv.RequestJob(context.Background(), test_distro.TestArch3Name, []string{"osbuild"}, []string{""}) require.NoError(t, err) require.Equal(t, "osbuild", jobType) test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "GET", fmt.Sprintf("/api/image-builder-composer/v2/composes/%v", jobId), ``, http.StatusOK, fmt.Sprintf(` { "href": "/api/image-builder-composer/v2/composes/%v", "kind": "ComposeStatus", "id": "%v", "image_status": {"status": "building"}, "status": "pending" }`, jobId, jobId)) jobResult, err := json.Marshal(worker.OSBuildJobResult{TargetErrors: []string{"Osbuild failed"}}) require.NoError(t, err) err = wrksrv.FinishJob(token, jobResult) require.NoError(t, err) test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "GET", fmt.Sprintf("/api/image-builder-composer/v2/composes/%v", jobId), ``, http.StatusOK, fmt.Sprintf(` { "href": "/api/image-builder-composer/v2/composes/%v", "kind": "ComposeStatus", "id": "%v", "image_status": {"status": "failure"}, "status": "failure" }`, jobId, jobId)) } func TestComposeJobError(t *testing.T) { dir, err := ioutil.TempDir("", "osbuild-composer-test-api-v2-") require.NoError(t, err) defer os.RemoveAll(dir) srv, wrksrv, _, cancel := newV2Server(t, dir, []string{""}, false) defer cancel() test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "POST", "/api/image-builder-composer/v2/compose", fmt.Sprintf(` { "distribution": "%s", "image_request":{ "architecture": "%s", "image_type": "aws", "repositories": [{ "baseurl": "somerepo.org", "rhsm": false }], "upload_options": { "region": "eu-central-1" } } }`, test_distro.TestDistroName, test_distro.TestArch3Name), http.StatusCreated, ` { "href": "/api/image-builder-composer/v2/compose", "kind": "ComposeId" }`, "id") jobId, token, jobType, _, _, err := wrksrv.RequestJob(context.Background(), test_distro.TestArch3Name, []string{"osbuild"}, []string{""}) require.NoError(t, err) require.Equal(t, "osbuild", jobType) test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "GET", fmt.Sprintf("/api/image-builder-composer/v2/composes/%v", jobId), ``, http.StatusOK, fmt.Sprintf(` { "href": "/api/image-builder-composer/v2/composes/%v", "kind": "ComposeStatus", "id": "%v", "image_status": {"status": "building"}, "status": "pending" }`, jobId, jobId)) jobErr := worker.JobResult{ JobError: clienterrors.WorkerClientError(clienterrors.ErrorBuildJob, "Error building image"), } jobResult, err := json.Marshal(worker.OSBuildJobResult{JobResult: jobErr}) require.NoError(t, err) err = wrksrv.FinishJob(token, jobResult) require.NoError(t, err) test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "GET", fmt.Sprintf("/api/image-builder-composer/v2/composes/%v", jobId), ``, http.StatusOK, fmt.Sprintf(` { "href": "/api/image-builder-composer/v2/composes/%v", "kind": "ComposeStatus", "id": "%v", "image_status": {"status": "failure"}, "status": "failure" }`, jobId, jobId)) } func TestComposeCustomizations(t *testing.T) { dir, err := ioutil.TempDir("", "osbuild-composer-test-api-v2-") require.NoError(t, err) defer os.RemoveAll(dir) srv, _, _, cancel := newV2Server(t, dir, []string{""}, false) defer cancel() test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "POST", "/api/image-builder-composer/v2/compose", fmt.Sprintf(` { "distribution": "%s", "customizations": { "subscription": { "organization": "2040324", "activation_key": "my-secret-key", "server_url": "subscription.rhsm.redhat.com", "base_url": "http://cdn.redhat.com/", "insights": true }, "packages": [ "pkg1", "pkg2" ], "users": [{ "name": "user1", "groups": [ "wheel" ], "key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINrGKErMYi+MMUwuHaRAJmRLoIzRf2qD2dD5z0BTx/6x" }], "payload_repositories": [{ "baseurl": "some-custom-repo.org", "check_gpg": false, "ignore_ssl": false, "gpg_key": "some-gpg-key" }] }, "image_request":{ "architecture": "%s", "image_type": "aws", "repositories": [{ "baseurl": "somerepo.org", "rhsm": false }], "upload_options": { "region": "eu-central-1" } } }`, test_distro.TestDistroName, test_distro.TestArch3Name), http.StatusCreated, ` { "href": "/api/image-builder-composer/v2/compose", "kind": "ComposeId" }`, "id") } func TestImageTypes(t *testing.T) { dir, err := ioutil.TempDir("", "osbuild-composer-test-api-v2-") require.NoError(t, err) defer os.RemoveAll(dir) srv, _, _, cancel := newV2Server(t, dir, []string{""}, false) defer cancel() test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "POST", "/api/image-builder-composer/v2/compose", fmt.Sprintf(` { "distribution": "%s", "image_request":{ "architecture": "%s", "image_type": "%s", "repositories": [{ "baseurl": "somerepo.org", "rhsm": false }], "upload_options": { "region": "eu-central-1", "snapshot_name": "name", "share_with_accounts": ["123456789012","234567890123"] } } }`, test_distro.TestDistroName, test_distro.TestArch3Name, string(v2.ImageTypesAws)), http.StatusCreated, ` { "href": "/api/image-builder-composer/v2/compose", "kind": "ComposeId" }`, "id") test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "POST", "/api/image-builder-composer/v2/compose", fmt.Sprintf(` { "distribution": "%s", "image_request":{ "architecture": "%s", "image_type": "%s", "repositories": [{ "baseurl": "somerepo.org", "rhsm": false }], "upload_options": { "region": "eu-central-1" } } }`, test_distro.TestDistroName, test_distro.TestArch3Name, string(v2.ImageTypesAws)), http.StatusCreated, ` { "href": "/api/image-builder-composer/v2/compose", "kind": "ComposeId" }`, "id") test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "POST", "/api/image-builder-composer/v2/compose", fmt.Sprintf(` { "distribution": "%s", "image_request":{ "architecture": "%s", "image_type": "%s", "repositories": [{ "baseurl": "somerepo.org", "rhsm": false }], "upload_options": { "region": "eu-central-1" } } }`, test_distro.TestDistroName, test_distro.TestArch3Name, string(v2.ImageTypesEdgeCommit)), http.StatusCreated, ` { "href": "/api/image-builder-composer/v2/compose", "kind": "ComposeId" }`, "id") test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "POST", "/api/image-builder-composer/v2/compose", fmt.Sprintf(` { "distribution": "%s", "image_request":{ "architecture": "%s", "image_type": "%s", "repositories": [{ "baseurl": "somerepo.org", "rhsm": false }], "upload_options": { "region": "eu-central-1" } } }`, test_distro.TestDistroName, test_distro.TestArch3Name, string(v2.ImageTypesEdgeInstaller)), http.StatusCreated, ` { "href": "/api/image-builder-composer/v2/compose", "kind": "ComposeId" }`, "id") test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "POST", "/api/image-builder-composer/v2/compose", fmt.Sprintf(` { "distribution": "%s", "image_request":{ "architecture": "%s", "image_type": "%s", "repositories": [{ "baseurl": "somerepo.org", "rhsm": false }], "upload_options": { "subscription_id": "4e5d8b2c-ab24-4413-90c5-612306e809e2", "tenant_id": "5c7ef5b6-1c3f-4da0-a622-0b060239d7d7", "resource_group": "ToucanResourceGroup", "location": "westeurope" } } }`, test_distro.TestDistroName, test_distro.TestArch3Name, string(v2.ImageTypesAzure)), http.StatusCreated, ` { "href": "/api/image-builder-composer/v2/compose", "kind": "ComposeId" }`, "id") test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "POST", "/api/image-builder-composer/v2/compose", fmt.Sprintf(` { "distribution": "%s", "image_request":{ "architecture": "%s", "image_type": "%s", "repositories": [{ "baseurl": "somerepo.org", "rhsm": false }], "upload_options": { "region": "eu", "bucket": "some-eu-bucket", "share_with_accounts": ["user:alice@example.com"] } } }`, test_distro.TestDistroName, test_distro.TestArch3Name, string(v2.ImageTypesGcp)), http.StatusCreated, ` { "href": "/api/image-builder-composer/v2/compose", "kind": "ComposeId" }`, "id") test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "POST", "/api/image-builder-composer/v2/compose", fmt.Sprintf(` { "distribution": "%s", "image_request":{ "architecture": "%s", "image_type": "%s", "repositories": [{ "baseurl": "somerepo.org", "rhsm": false }], "upload_options": { "region": "eu-central-1" } } }`, test_distro.TestDistroName, test_distro.TestArch3Name, string(v2.ImageTypesImageInstaller)), http.StatusCreated, ` { "href": "/api/image-builder-composer/v2/compose", "kind": "ComposeId" }`, "id") test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "POST", "/api/image-builder-composer/v2/compose", fmt.Sprintf(` { "distribution": "%s", "image_request":{ "architecture": "%s", "image_type": "%s", "repositories": [{ "baseurl": "somerepo.org", "rhsm": false }], "upload_options": { "region": "eu-central-1" } } }`, test_distro.TestDistroName, test_distro.TestArch3Name, string(v2.ImageTypesGuestImage)), http.StatusCreated, ` { "href": "/api/image-builder-composer/v2/compose", "kind": "ComposeId" }`, "id") test.TestRoute(t, srv.Handler("/api/image-builder-composer/v2"), false, "POST", "/api/image-builder-composer/v2/compose", fmt.Sprintf(` { "distribution": "%s", "image_request":{ "architecture": "%s", "image_type": "%s", "repositories": [{ "baseurl": "somerepo.org", "rhsm": false }], "upload_options": { "region": "eu-central-1" } } }`, test_distro.TestDistroName, test_distro.TestArch3Name, string(v2.ImageTypesVsphere)), http.StatusCreated, ` { "href": "/api/image-builder-composer/v2/compose", "kind": "ComposeId" }`, "id") }