506 lines
14 KiB
Go
506 lines
14 KiB
Go
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"
|
|
distro_mock "github.com/osbuild/osbuild-composer/internal/mocks/distro"
|
|
rpmmd_mock "github.com/osbuild/osbuild-composer/internal/mocks/rpmmd"
|
|
"github.com/osbuild/osbuild-composer/internal/test"
|
|
"github.com/osbuild/osbuild-composer/internal/worker"
|
|
)
|
|
|
|
func newV2Server(t *testing.T, dir string) (*v2.Server, *worker.Server) {
|
|
rpmFixture := rpmmd_mock.BaseFixture(dir)
|
|
rpm := rpmmd_mock.NewRPMMDMock(rpmFixture)
|
|
require.NotNil(t, rpm)
|
|
|
|
distros, err := distro_mock.NewDefaultRegistry()
|
|
require.NoError(t, err)
|
|
require.NotNil(t, distros)
|
|
|
|
v2Server := v2.NewServer(rpmFixture.Workers, rpm, distros, "image-builder.service")
|
|
require.NotNil(t, v2Server)
|
|
|
|
return v2Server, rpmFixture.Workers
|
|
}
|
|
|
|
func TestUnknownRoute(t *testing.T) {
|
|
dir, err := ioutil.TempDir("", "osbuild-composer-test-api-v2-")
|
|
require.NoError(t, err)
|
|
defer os.RemoveAll(dir)
|
|
srv, _ := newV2Server(t, dir)
|
|
|
|
test.TestRoute(t, srv.Handler("/api/composer/v2"), false, "GET", "/api/composer/v2/badroute", ``, http.StatusNotFound, `
|
|
{
|
|
"href": "/api/composer/v2/errors/21",
|
|
"id": "21",
|
|
"kind": "Error",
|
|
"code": "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, _ := newV2Server(t, dir)
|
|
|
|
test.TestRoute(t, srv.Handler("/api/composer/v2"), false, "GET", "/api/composer/v2/errors/4", ``, http.StatusOK, `
|
|
{
|
|
"href": "/api/composer/v2/errors/4",
|
|
"id": "4",
|
|
"kind": "Error",
|
|
"code": "COMPOSER-4",
|
|
"reason": "Unsupported distribution"
|
|
}`, "operation_id")
|
|
|
|
test.TestRoute(t, srv.Handler("/api/composer/v2"), false, "GET", "/api/composer/v2/errors/3000", ``, http.StatusNotFound, `
|
|
{
|
|
"href": "/api/composer/v2/errors/17",
|
|
"id": "17",
|
|
"kind": "Error",
|
|
"code": "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, _ := newV2Server(t, dir)
|
|
|
|
test.TestRoute(t, srv.Handler("/api/composer/v2"), false, "GET", "/api/composer/v2/errors?page=3&size=1", ``, http.StatusOK, `
|
|
{
|
|
"kind": "ErrorList",
|
|
"page": 3,
|
|
"size": 1,
|
|
"items": [{
|
|
"href": "/api/composer/v2/errors/4",
|
|
"id": "4",
|
|
"kind": "Error",
|
|
"code": "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, _ := newV2Server(t, dir)
|
|
|
|
// unsupported distribution
|
|
test.TestRoute(t, srv.Handler("/api/composer/v2"), false, "POST", "/api/composer/v2/compose", fmt.Sprintf(`
|
|
{
|
|
"distribution": "unsupported_distro",
|
|
"image_requests":[{
|
|
"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/composer/v2/errors/4",
|
|
"id": "4",
|
|
"kind": "Error",
|
|
"code": "COMPOSER-4",
|
|
"reason": "Unsupported distribution"
|
|
}`, "operation_id")
|
|
|
|
// unsupported architecture
|
|
test.TestRoute(t, srv.Handler("/api/composer/v2"), false, "POST", "/api/composer/v2/compose", fmt.Sprintf(`
|
|
{
|
|
"distribution": "%s",
|
|
"image_requests":[{
|
|
"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/composer/v2/errors/5",
|
|
"id": "5",
|
|
"kind": "Error",
|
|
"code": "COMPOSER-5",
|
|
"reason": "Unsupported architecture"
|
|
}`, "operation_id")
|
|
|
|
// unsupported imagetype
|
|
test.TestRoute(t, srv.Handler("/api/composer/v2"), false, "POST", "/api/composer/v2/compose", fmt.Sprintf(`
|
|
{
|
|
"distribution": "%s",
|
|
"image_requests":[{
|
|
"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/composer/v2/errors/6",
|
|
"id": "6",
|
|
"kind": "Error",
|
|
"code": "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/composer/v2"), false, "GET", "/api/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/composer/v2/errors/22",
|
|
// "id": "22",
|
|
// "kind": "Error",
|
|
// "code": "COMPOSER-22",
|
|
// "reason": "Requested method isn't supported for resource"
|
|
// }`, "operation_id")
|
|
|
|
test.TestRoute(t, srv.Handler("/api/composer/v2"), false, "POST", "/api/composer/v2/compose", fmt.Sprintf(`
|
|
{
|
|
"distribution": "%s",
|
|
"image_requests":[{
|
|
"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/composer/v2/compose",
|
|
"kind": "ComposeId"
|
|
}`, "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 := newV2Server(t, dir)
|
|
|
|
test.TestRoute(t, srv.Handler("/api/composer/v2"), false, "POST", "/api/composer/v2/compose", fmt.Sprintf(`
|
|
{
|
|
"distribution": "%s",
|
|
"image_requests":[{
|
|
"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/composer/v2/compose",
|
|
"kind": "ComposeId"
|
|
}`, "id")
|
|
|
|
jobId, token, jobType, _, _, err := wrksrv.RequestJob(context.Background(), test_distro.TestArch3Name, []string{"osbuild"})
|
|
require.NoError(t, err)
|
|
require.Equal(t, "osbuild", jobType)
|
|
|
|
test.TestRoute(t, srv.Handler("/api/composer/v2"), false, "GET", fmt.Sprintf("/api/composer/v2/compose/%v", jobId), ``, http.StatusOK, fmt.Sprintf(`
|
|
{
|
|
"href": "/api/composer/v2/compose/%v",
|
|
"kind": "ComposeStatus",
|
|
"id": "%v",
|
|
"image_status": {"status": "building"}
|
|
}`, jobId, jobId))
|
|
|
|
// todo make it an osbuildjobresult
|
|
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/composer/v2"), false, "GET", fmt.Sprintf("/api/composer/v2/compose/%v", jobId), ``, http.StatusOK, fmt.Sprintf(`
|
|
{
|
|
"href": "/api/composer/v2/compose/%v",
|
|
"kind": "ComposeStatus",
|
|
"id": "%v",
|
|
"image_status": {"status": "success"}
|
|
}`, jobId, jobId))
|
|
|
|
test.TestRoute(t, srv.Handler("/api/composer/v2"), false, "GET", fmt.Sprintf("/api/composer/v2/compose/%v/metadata", jobId), ``, http.StatusInternalServerError, `
|
|
{
|
|
"href": "/api/composer/v2/errors/1012",
|
|
"id": "1012",
|
|
"kind": "Error",
|
|
"code": "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 := newV2Server(t, dir)
|
|
|
|
test.TestRoute(t, srv.Handler("/api/composer/v2"), false, "POST", "/api/composer/v2/compose", fmt.Sprintf(`
|
|
{
|
|
"distribution": "%s",
|
|
"image_requests":[{
|
|
"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/composer/v2/compose",
|
|
"kind": "ComposeId"
|
|
}`, "id")
|
|
|
|
jobId, token, jobType, _, _, err := wrksrv.RequestJob(context.Background(), test_distro.TestArch3Name, []string{"osbuild"})
|
|
require.NoError(t, err)
|
|
require.Equal(t, "osbuild", jobType)
|
|
|
|
test.TestRoute(t, srv.Handler("/api/composer/v2"), false, "GET", fmt.Sprintf("/api/composer/v2/compose/%v", jobId), ``, http.StatusOK, fmt.Sprintf(`
|
|
{
|
|
"href": "/api/composer/v2/compose/%v",
|
|
"kind": "ComposeStatus",
|
|
"id": "%v",
|
|
"image_status": {"status": "building"}
|
|
}`, jobId, jobId))
|
|
|
|
err = wrksrv.FinishJob(token, nil)
|
|
require.NoError(t, err)
|
|
test.TestRoute(t, srv.Handler("/api/composer/v2"), false, "GET", fmt.Sprintf("/api/composer/v2/compose/%v", jobId), ``, http.StatusOK, fmt.Sprintf(`
|
|
{
|
|
"href": "/api/composer/v2/compose/%v",
|
|
"kind": "ComposeStatus",
|
|
"id": "%v",
|
|
"image_status": {"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, _ := newV2Server(t, dir)
|
|
|
|
test.TestRoute(t, srv.Handler("/api/composer/v2"), false, "POST", "/api/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"
|
|
}]
|
|
},
|
|
"image_requests":[{
|
|
"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/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, _ := newV2Server(t, dir)
|
|
|
|
test.TestRoute(t, srv.Handler("/api/composer/v2"), false, "POST", "/api/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",
|
|
"snapshot_name": "name",
|
|
"share_with_accounts": ["123456789012","234567890123"]
|
|
}
|
|
}]
|
|
}`, test_distro.TestDistroName, test_distro.TestArch3Name, string(v2.ImageTypes_aws)), http.StatusCreated, `
|
|
{
|
|
"href": "/api/composer/v2/compose",
|
|
"kind": "ComposeId"
|
|
}`, "id")
|
|
test.TestRoute(t, srv.Handler("/api/composer/v2"), false, "POST", "/api/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, string(v2.ImageTypes_aws)), http.StatusCreated, `
|
|
{
|
|
"href": "/api/composer/v2/compose",
|
|
"kind": "ComposeId"
|
|
}`, "id")
|
|
test.TestRoute(t, srv.Handler("/api/composer/v2"), false, "POST", "/api/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, string(v2.ImageTypes_edge_commit)), http.StatusCreated, `
|
|
{
|
|
"href": "/api/composer/v2/compose",
|
|
"kind": "ComposeId"
|
|
}`, "id")
|
|
test.TestRoute(t, srv.Handler("/api/composer/v2"), false, "POST", "/api/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, string(v2.ImageTypes_edge_installer)), http.StatusCreated, `
|
|
{
|
|
"href": "/api/composer/v2/compose",
|
|
"kind": "ComposeId"
|
|
}`, "id")
|
|
test.TestRoute(t, srv.Handler("/api/composer/v2"), false, "POST", "/api/composer/v2/compose", fmt.Sprintf(`
|
|
{
|
|
"distribution": "%s",
|
|
"image_requests":[{
|
|
"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.ImageTypes_azure)), http.StatusCreated, `
|
|
{
|
|
"href": "/api/composer/v2/compose",
|
|
"kind": "ComposeId"
|
|
}`, "id")
|
|
test.TestRoute(t, srv.Handler("/api/composer/v2"), false, "POST", "/api/composer/v2/compose", fmt.Sprintf(`
|
|
{
|
|
"distribution": "%s",
|
|
"image_requests":[{
|
|
"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.ImageTypes_gcp)), http.StatusCreated, `
|
|
{
|
|
"href": "/api/composer/v2/compose",
|
|
"kind": "ComposeId"
|
|
}`, "id")
|
|
}
|