Repository: osbuild/osbuild-composer (go)

Issue:
Local target only supports uploading one file
https://github.com/osbuild/osbuild-composer/pull/347 changes the local upload target to only upload a single file from the result directory. That's a bit smelly (we ought to know the name) and will not work for pipelines that have multiple outputs (if we ever have those).

I see a few options of fixing that:
1. Include the filename(s) to upload in the UploadTarget that's passed to the job.
2. Base the filename on the compose id (this only works for one and might be a layer violation: `distro` package doesn't necessarily know the compose id yet)
3. Upload all files

Curious to hear your thoughts.

Pull request description:
Specify image filenames in upload targets
Drop any assumptions about the name or number of output files that osbuild produces from the worker.

Inspired by #370, fixes #348.

Patch:
diff --git a/cmd/osbuild-composer/main.go b/cmd/osbuild-composer/main.go
index 1083e5d44..5e4b39c96 100644
--- a/cmd/osbuild-composer/main.go
+++ b/cmd/osbuild-composer/main.go
@@ -104,7 +104,7 @@ func main() {
 		logger = log.New(os.Stdout, "", 0)
 	}
 
-	store := store.New(&stateDir, *distros)
+	store := store.New(&stateDir)
 
 	jobAPI := jobqueue.New(logger, store)
 	weldrAPI := weldr.New(rpm, common.CurrentArch(), distribution, repoMap[common.CurrentArch()], logger, store)
diff --git a/internal/compose/compose.go b/internal/compose/compose.go
index 899800830..cec457e73 100644
--- a/internal/compose/compose.go
+++ b/internal/compose/compose.go
@@ -60,14 +60,15 @@ func (ib *ImageBuild) DeepCopy() ImageBuild {
 	}
 }
 
-func (ib *ImageBuild) HasLocalTarget() bool {
+func (ib *ImageBuild) GetLocalTargetOptions() *target.LocalTargetOptions {
 	for _, t := range ib.Targets {
-		if _, ok := t.Options.(*target.LocalTargetOptions); ok {
-			return true
+		switch options := t.Options.(type) {
+		case *target.LocalTargetOptions:
+			return options
 		}
 	}
 
-	return false
+	return nil
 }
 
 // A Compose represent the task of building a set of images from a single blueprint.
diff --git a/internal/jobqueue/job.go b/internal/jobqueue/job.go
index 06f7d5bbc..49c31e7c5 100644
--- a/internal/jobqueue/job.go
+++ b/internal/jobqueue/job.go
@@ -97,23 +97,7 @@ func (job *Job) Run(uploader LocalTargetUploader) (*common.ComposeResult, error)
 	for _, t := range job.Targets {
 		switch options := t.Options.(type) {
 		case *target.LocalTargetOptions:
-			outputDir := path.Join(tmpStore, "refs", result.OutputID)
-
-			files, err := ioutil.ReadDir(outputDir)
-			if err != nil {
-				r = append(r, err)
-				continue
-			}
-
-			// TODO osbuild pipelines can have multiple outputs. All the pipelines we
-			// are currently generating have exactly one, but we should support
-			// uploading all results in the future.
-			if len(files) != 1 {
-				r = append(r, fmt.Errorf("expected exactly one resulting image file"))
-				continue
-			}
-
-			f, err := os.Open(path.Join(outputDir, files[0].Name()))
+			f, err := os.Open(path.Join(tmpStore, "refs", result.OutputID, options.Filename))
 			if err != nil {
 				r = append(r, err)
 				continue
@@ -137,7 +121,7 @@ func (job *Job) Run(uploader LocalTargetUploader) (*common.ComposeResult, error)
 				options.Key = job.ID.String()
 			}
 
-			_, err = a.Upload(tmpStore+"/refs/"+result.OutputID+"/image.raw.xz", options.Bucket, options.Key)
+			_, err = a.Upload(path.Join(tmpStore, "refs", result.OutputID, options.Filename), options.Bucket, options.Key)
 			if err != nil {
 				r = append(r, err)
 				continue
diff --git a/internal/mocks/rpmmd/fixtures.go b/internal/mocks/rpmmd/fixtures.go
index a54603d25..e34ebee37 100644
--- a/internal/mocks/rpmmd/fixtures.go
+++ b/internal/mocks/rpmmd/fixtures.go
@@ -2,12 +2,12 @@ package rpmmd_mock
 
 import (
 	"fmt"
-	"github.com/osbuild/osbuild-composer/internal/common"
-	"github.com/osbuild/osbuild-composer/internal/compose"
-	distro_mock "github.com/osbuild/osbuild-composer/internal/mocks/distro"
 	"sort"
 	"time"
 
+	"github.com/osbuild/osbuild-composer/internal/common"
+	"github.com/osbuild/osbuild-composer/internal/compose"
+
 	"github.com/google/uuid"
 	"github.com/osbuild/osbuild-composer/internal/blueprint"
 	"github.com/osbuild/osbuild-composer/internal/rpmmd"
@@ -92,8 +92,7 @@ func createBaseStoreFixture() *store.Store {
 		},
 	}
 
-	r, _ := distro_mock.NewDefaultRegistry()
-	s := store.New(nil, *r)
+	s := store.New(nil)
 
 	s.Blueprints[bName] = b
 	s.Composes = map[uuid.UUID]compose.Compose{
@@ -188,8 +187,7 @@ func createStoreWithoutComposesFixture() *store.Store {
 		Customizations: nil,
 	}
 
-	r, _ := distro_mock.NewDefaultRegistry()
-	s := store.New(nil, *r)
+	s := store.New(nil)
 
 	s.Blueprints[bName] = b
 
diff --git a/internal/store/store.go b/internal/store/store.go
index eee084677..98539575d 100644
--- a/internal/store/store.go
+++ b/internal/store/store.go
@@ -42,11 +42,10 @@ type Store struct {
 	BlueprintsChanges map[string]map[string]blueprint.Change `json:"changes"`
 	BlueprintsCommits map[string][]string                    `json:"commits"`
 
-	mu             sync.RWMutex // protects all fields
-	pendingJobs    chan Job
-	stateChannel   chan []byte
-	distroRegistry distro.Registry
-	stateDir       *string
+	mu           sync.RWMutex // protects all fields
+	pendingJobs  chan Job
+	stateChannel chan []byte
+	stateDir     *string
 }
 
 // A Job contains the information about a compose a worker needs to process it.
@@ -107,7 +106,7 @@ func (e *NoLocalTargetError) Error() string {
 	return e.message
 }
 
-func New(stateDir *string, distroRegistryArg distro.Registry) *Store {
+func New(stateDir *string) *Store {
 	var s Store
 
 	if stateDir != nil {
@@ -141,7 +140,6 @@ func New(stateDir *string, distroRegistryArg distro.Registry) *Store {
 	}
 
 	s.pendingJobs = make(chan Job, 200)
-	s.distroRegistry = distroRegistryArg
 	s.stateDir = stateDir
 
 	if s.Blueprints == nil {
@@ -531,28 +529,12 @@ func (s *Store) GetImageBuildImage(composeId uuid.UUID, imageBuildId int) (io.Re
 		return nil, 0, &NotFoundError{"compose does not exist"}
 	}
 
-	imageBuild := c.ImageBuilds[imageBuildId]
-	if !imageBuild.HasLocalTarget() {
+	localTargetOptions := c.ImageBuilds[imageBuildId].GetLocalTargetOptions()
+	if localTargetOptions == nil {
 		return nil, 0, &NoLocalTargetError{"compose does not have local target"}
 	}
 
-	name, ok := imageBuild.Distro.ToString()
-	if !ok {
-		panic("distro name was validated earlier")
-	}
-
-	distro := s.distroRegistry.GetDistro(name)
-	if distro == nil {
-		panic("distro was validated earlier")
-	}
-
-	compatString, _ := imageBuild.ImageType.ToCompatString()
-	filename, _, err := distro.FilenameFromType(compatString)
-	if err != nil {
-		panic(err)
-	}
-
-	path := fmt.Sprintf("%s/%s", s.getImageBuildDirectory(composeId, imageBuildId), filename)
+	path := fmt.Sprintf("%s/%s", s.getImageBuildDirectory(composeId, imageBuildId), localTargetOptions.Filename)
 
 	f, err := os.Open(path)
 
@@ -595,8 +577,15 @@ func (s *Store) PushCompose(distro distro.Distro, composeID uuid.UUID, bp *bluep
 			return fmt.Errorf("cannot create output directory for job %v: %#v", composeID, err)
 		}
 
+		filename, _, err := distro.FilenameFromType(composeType)
+		if err != nil {
+			return fmt.Errorf("cannot query filename from image type %s: %#v", composeType, err)
+		}
+
 		targets = append(targets, target.NewLocalTarget(
-			&target.LocalTargetOptions{},
+			&target.LocalTargetOptions{
+				Filename: filename,
+			},
 		))
 	}
 
@@ -769,29 +758,12 @@ func (s *Store) AddImageToImageUpload(composeID uuid.UUID, imageBuildID int, rea
 		return &NotFoundError{"compose does not exist"}
 	}
 
-	imageBuild := currentCompose.ImageBuilds[imageBuildID]
-	if !imageBuild.HasLocalTarget() {
+	localTargetOptions := currentCompose.ImageBuilds[imageBuildID].GetLocalTargetOptions()
+	if localTargetOptions == nil {
 		return &NoLocalTargetError{fmt.Sprintf("image upload requested for compse %s and image build %d but it has no local target", composeID.String(), imageBuildID)}
 	}
 
-	name, ok := imageBuild.Distro.ToString()
-	if !ok {
-		panic("distro name was validated earlier")
-	}
-
-	distro := s.distroRegistry.GetDistro(name)
-	if distro == nil {
-		panic("distro was validated earlier")
-	}
-
-	imageType, _ := imageBuild.ImageType.ToCompatString()
-	filename, _, err := distro.FilenameFromType(imageType)
-
-	if err != nil {
-		return &InvalidRequestError{err.Error()}
-	}
-
-	path := fmt.Sprintf("%s/%s", s.getImageBuildDirectory(composeID, imageBuildID), filename)
+	path := fmt.Sprintf("%s/%s", s.getImageBuildDirectory(composeID, imageBuildID), localTargetOptions.Filename)
 	f, err := os.Create(path)
 
 	if err != nil {
diff --git a/internal/target/aws_target.go b/internal/target/aws_target.go
index d54172afa..3ff41f461 100644
--- a/internal/target/aws_target.go
+++ b/internal/target/aws_target.go
@@ -1,6 +1,7 @@
 package target
 
 type AWSTargetOptions struct {
+	Filename        string `json:"filename"`
 	Region          string `json:"region"`
 	AccessKeyID     string `json:"accessKeyID"`
 	SecretAccessKey string `json:"secretAccessKey"`
diff --git a/internal/target/azure_target.go b/internal/target/azure_target.go
index 9b9a2e2fd..09c32c651 100644
--- a/internal/target/azure_target.go
+++ b/internal/target/azure_target.go
@@ -1,6 +1,7 @@
 package target
 
 type AzureTargetOptions struct {
+	Filename  string `json:"filename"`
 	Account   string `json:"account"`
 	AccessKey string `json:"accessKey"`
 	Container string `json:"container"`
diff --git a/internal/target/local_target.go b/internal/target/local_target.go
index eb2fa9dbc..48f25ccb2 100644
--- a/internal/target/local_target.go
+++ b/internal/target/local_target.go
@@ -1,6 +1,7 @@
 package target
 
 type LocalTargetOptions struct {
+	Filename string `json:"filename"`
 }
 
 func (LocalTargetOptions) isTargetOptions() {}
diff --git a/internal/weldr/api.go b/internal/weldr/api.go
index 2db121ea3..9a317a03b 100644
--- a/internal/weldr/api.go
+++ b/internal/weldr/api.go
@@ -1360,7 +1360,7 @@ func (api *API) composeHandler(writer http.ResponseWriter, request *http.Request
 		ComposeType   string         `json:"compose_type"`
 		Size          uint64         `json:"size"`
 		Branch        string         `json:"branch"`
-		Upload        *UploadRequest `json:"upload"`
+		Upload        *uploadRequest `json:"upload"`
 	}
 	type ComposeReply struct {
 		BuildID uuid.UUID `json:"build_id"`
@@ -1396,8 +1396,7 @@ func (api *API) composeHandler(writer http.ResponseWriter, request *http.Request
 
 	var uploadTarget *target.Target
 	if isRequestVersionAtLeast(params, 1) && cr.Upload != nil {
-		uploadTarget, err = UploadRequestToTarget(*cr.Upload)
-
+		uploadTarget, err = uploadRequestToTarget(*cr.Upload, api.distro, cr.ComposeType)
 		if err != nil {
 			errors := responseError{
 				ID:  "UploadError",
@@ -1661,7 +1660,7 @@ func (api *API) composeInfoHandler(writer http.ResponseWriter, request *http.Req
 		ComposeType string               `json:"compose_type"`
 		QueueStatus string               `json:"queue_status"`
 		ImageSize   uint64               `json:"image_size"`
-		Uploads     []UploadResponse     `json:"uploads,omitempty"`
+		Uploads     []uploadResponse     `json:"uploads,omitempty"`
 	}
 
 	reply.ID = id
@@ -1676,7 +1675,7 @@ func (api *API) composeInfoHandler(writer http.ResponseWriter, request *http.Req
 	reply.ImageSize = compose.ImageBuilds[0].Size
 
 	if isRequestVersionAtLeast(params, 1) {
-		reply.Uploads = TargetsToUploadResponses(compose.ImageBuilds[0].Targets)
+		reply.Uploads = targetsToUploadResponses(compose.ImageBuilds[0].Targets)
 	}
 
 	err = json.NewEncoder(writer).Encode(reply)
diff --git a/internal/weldr/compose.go b/internal/weldr/compose.go
index 1ca058a4e..c980c812a 100644
--- a/internal/weldr/compose.go
+++ b/internal/weldr/compose.go
@@ -1,10 +1,11 @@
 package weldr
 
 import (
+	"sort"
+
 	"github.com/google/uuid"
 	"github.com/osbuild/osbuild-composer/internal/common"
 	"github.com/osbuild/osbuild-composer/internal/compose"
-	"sort"
 )
 
 type ComposeEntry struct {
@@ -17,7 +18,7 @@ type ComposeEntry struct {
 	JobCreated  float64                `json:"job_created"`
 	JobStarted  float64                `json:"job_started,omitempty"`
 	JobFinished float64                `json:"job_finished,omitempty"`
-	Uploads     []UploadResponse       `json:"uploads,omitempty"`
+	Uploads     []uploadResponse       `json:"uploads,omitempty"`
 }
 
 func composeToComposeEntry(id uuid.UUID, compose compose.Compose, includeUploads bool) *ComposeEntry {
@@ -30,7 +31,7 @@ func composeToComposeEntry(id uuid.UUID, compose compose.Compose, includeUploads
 	composeEntry.QueueStatus = compose.ImageBuilds[0].QueueStatus
 
 	if includeUploads {
-		composeEntry.Uploads = TargetsToUploadResponses(compose.ImageBuilds[0].Targets)
+		composeEntry.Uploads = targetsToUploadResponses(compose.ImageBuilds[0].Targets)
 	}
 
 	switch compose.ImageBuilds[0].QueueStatus {
diff --git a/internal/weldr/upload.go b/internal/weldr/upload.go
index 6c3c31b7b..5e9029d6b 100644
--- a/internal/weldr/upload.go
+++ b/internal/weldr/upload.go
@@ -3,109 +3,154 @@ package weldr
 import (
 	"encoding/json"
 	"errors"
-	"github.com/osbuild/osbuild-composer/internal/common"
 	"time"
 
+	"github.com/osbuild/osbuild-composer/internal/common"
+	"github.com/osbuild/osbuild-composer/internal/distro"
+
 	"github.com/google/uuid"
 	"github.com/osbuild/osbuild-composer/internal/target"
 )
 
-type UploadResponse struct {
+type uploadResponse struct {
 	Uuid         uuid.UUID              `json:"uuid"`
 	Status       common.ImageBuildState `json:"status"`
 	ProviderName string                 `json:"provider_name"`
 	ImageName    string                 `json:"image_name"`
 	CreationTime float64                `json:"creation_time"`
-	Settings     target.TargetOptions   `json:"settings"`
+	Settings     uploadSettings         `json:"settings"`
 }
 
-type UploadRequest struct {
-	Provider  string               `json:"provider"`
-	ImageName string               `json:"image_name"`
-	Settings  target.TargetOptions `json:"settings"`
+type uploadSettings interface {
+	isUploadSettings()
 }
 
-type rawUploadRequest struct {
-	Provider  string          `json:"provider"`
-	ImageName string          `json:"image_name"`
-	Settings  json.RawMessage `json:"settings"`
+type awsUploadSettings struct {
+	Region          string `json:"region"`
+	AccessKeyID     string `json:"accessKeyID"`
+	SecretAccessKey string `json:"secretAccessKey"`
+	Bucket          string `json:"bucket"`
+	Key             string `json:"key"`
 }
 
-func (u *UploadRequest) UnmarshalJSON(data []byte) error {
-	var rawUpload rawUploadRequest
-	err := json.Unmarshal(data, &rawUpload)
-	if err != nil {
-		return err
-	}
-
-	// we need to convert provider name to target name to use the unmarshaller
-	targetName := providerNameToTargetNameMap[rawUpload.Provider]
-	options, err := target.UnmarshalTargetOptions(targetName, rawUpload.Settings)
-
-	u.Provider = rawUpload.Provider
-	u.ImageName = rawUpload.ImageName
-	u.Settings = options
+func (awsUploadSettings) isUploadSettings() {}
 
-	return err
+type azureUploadSettings struct {
+	Account   string `json:"account"`
+	AccessKey string `json:"accessKey"`
+	Container string `json:"container"`
 }
 
-var targetNameToProviderNameMap = map[string]string{
-	"org.osbuild.aws":   "aws",
-	"org.osbuild.azure": "azure",
+func (azureUploadSettings) isUploadSettings() {}
+
+type uploadRequest struct {
+	Provider  string         `json:"provider"`
+	ImageName string         `json:"image_name"`
+	Settings  uploadSettings `json:"settings"`
 }
 
-var providerNameToTargetNameMap = map[string]string{
-	"aws":   "org.osbuild.aws",
-	"azure": "org.osbuild.azure",
+type rawUploadRequest struct {
+	Provider  string          `json:"provider"`
+	ImageName string          `json:"image_name"`
+	Settings  json.RawMessage `json:"settings"`
 }
 
-func targetToUploadResponse(t *target.Target) UploadResponse {
-	var u UploadResponse
+func (u *uploadRequest) UnmarshalJSON(data []byte) error {
+	var rawUploadRequest rawUploadRequest
+	err := json.Unmarshal(data, &rawUploadRequest)
+	if err != nil {
+		return err
+	}
 
-	providerName, providerExist := targetNameToProviderNameMap[t.Name]
-	if !providerExist {
-		panic("target name " + t.Name + " is not defined in conversion map!")
+	var settings uploadSettings
+	switch rawUploadRequest.Provider {
+	case "azure":
+		settings = new(azureUploadSettings)
+	case "aws":
+		settings = new(awsUploadSettings)
+	default:
+		return errors.New("unexpected provider name")
+	}
+	err = json.Unmarshal(rawUploadRequest.Settings, settings)
+	if err != nil {
+		return err
 	}
 
-	u.CreationTime = float64(t.Created.UnixNano()) / 1000000000
-	u.ImageName = t.ImageName
-	u.ProviderName = providerName
-	u.Status = t.Status
-	u.Uuid = t.Uuid
-	u.Settings = t.Options
+	u.Provider = rawUploadRequest.Provider
+	u.ImageName = rawUploadRequest.ImageName
+	u.Settings = settings
 
-	return u
+	return err
 }
 
-func TargetsToUploadResponses(targets []*target.Target) []UploadResponse {
-	var uploads []UploadResponse
+func targetsToUploadResponses(targets []*target.Target) []uploadResponse {
+	var uploads []uploadResponse
 	for _, t := range targets {
-		if t.Name == "org.osbuild.local" {
-			continue
+		upload := uploadResponse{
+			Uuid:         t.Uuid,
+			Status:       t.Status,
+			ImageName:    t.ImageName,
+			CreationTime: float64(t.Created.UnixNano()) / 1000000000,
 		}
 
-		upload := targetToUploadResponse(t)
-
-		uploads = append(uploads, upload)
+		switch options := t.Options.(type) {
+		case *target.AWSTargetOptions:
+			upload.ProviderName = "aws"
+			upload.Settings = &awsUploadSettings{
+				Region:          options.Region,
+				AccessKeyID:     options.AccessKeyID,
+				SecretAccessKey: options.SecretAccessKey,
+				Bucket:          options.Bucket,
+				Key:             options.Key,
+			}
+			uploads = append(uploads, upload)
+		case *target.AzureTargetOptions:
+			upload.ProviderName = "azure"
+			upload.Settings = &azureUploadSettings{
+				Account:   options.Account,
+				AccessKey: options.AccessKey,
+				Container: options.Container,
+			}
+			uploads = append(uploads, upload)
+		}
 	}
 
 	return uploads
 }
 
-func UploadRequestToTarget(u UploadRequest) (*target.Target, error) {
+func uploadRequestToTarget(u uploadRequest, d distro.Distro, imageType string) (*target.Target, error) {
 	var t target.Target
-	targetName, targetExist := providerNameToTargetNameMap[u.Provider]
 
-	if !targetExist {
-		return nil, errors.New("Unknown provider name " + u.Provider)
+	filename, _, err := d.FilenameFromType(imageType)
+	if err != nil {
+		return nil, err
 	}
 
 	t.Uuid = uuid.New()
 	t.ImageName = u.ImageName
-	t.Options = u.Settings
-	t.Name = targetName
 	t.Status = common.IBWaiting
 	t.Created = time.Now()
 
+	switch options := u.Settings.(type) {
+	case *awsUploadSettings:
+		t.Name = "org.osbuild.aws"
+		t.Options = &target.AWSTargetOptions{
+			Filename:        filename,
+			Region:          options.Region,
+			AccessKeyID:     options.AccessKeyID,
+			SecretAccessKey: options.SecretAccessKey,
+			Bucket:          options.Bucket,
+			Key:             options.Key,
+		}
+	case *azureUploadSettings:
+		t.Name = "org.osbuild.azure"
+		t.Options = &target.AzureTargetOptions{
+			Filename:  filename,
+			Account:   options.Account,
+			AccessKey: options.AccessKey,
+			Container: options.Container,
+		}
+	}
+
 	return &t, nil
 }


Test patch:
diff --git a/internal/jobqueue/api_test.go b/internal/jobqueue/api_test.go
index 78ea7df38..be86055c5 100644
--- a/internal/jobqueue/api_test.go
+++ b/internal/jobqueue/api_test.go
@@ -4,8 +4,6 @@ import (
 	"net/http"
 	"testing"
 
-	distro_mock "github.com/osbuild/osbuild-composer/internal/mocks/distro"
-
 	"github.com/osbuild/osbuild-composer/internal/blueprint"
 	test_distro "github.com/osbuild/osbuild-composer/internal/distro/fedoratest"
 	"github.com/osbuild/osbuild-composer/internal/jobqueue"
@@ -34,11 +32,7 @@ func TestBasic(t *testing.T) {
 	}
 
 	for _, c := range cases {
-		registry, err := distro_mock.NewDefaultRegistry()
-		if err != nil {
-			t.Fatal(err)
-		}
-		api := jobqueue.New(nil, store.New(nil, *registry))
+		api := jobqueue.New(nil, store.New(nil))
 
 		test.TestNonJsonRoute(t, api, false, c.Method, c.Path, c.Body, c.ExpectedStatus, c.ExpectedResponse)
 	}
@@ -47,14 +41,10 @@ func TestBasic(t *testing.T) {
 func TestCreate(t *testing.T) {
 	id, _ := uuid.Parse("ffffffff-ffff-ffff-ffff-ffffffffffff")
 	distroStruct := test_distro.New()
-	registry, err := distro_mock.NewDefaultRegistry()
-	if err != nil {
-		t.Fatal(err)
-	}
-	store := store.New(nil, *registry)
+	store := store.New(nil)
 	api := jobqueue.New(nil, store)
 
-	err = store.PushCompose(distroStruct, id, &blueprint.Blueprint{}, nil, nil, nil, "x86_64", "qcow2", 0, nil)
+	err := store.PushCompose(distroStruct, id, &blueprint.Blueprint{}, nil, nil, nil, "x86_64", "qcow2", 0, nil)
 	if err != nil {
 		t.Fatalf("error pushing compose: %v", err)
 	}
@@ -66,11 +56,7 @@ func TestCreate(t *testing.T) {
 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, err := distro_mock.NewDefaultRegistry()
-	if err != nil {
-		t.Fatal(err)
-	}
-	store := store.New(nil, *registry)
+	store := store.New(nil)
 	api := jobqueue.New(nil, store)
 
 	if from != "VOID" {
diff --git a/internal/rcm/api_test.go b/internal/rcm/api_test.go
index 95fe1c21e..f5c4fb2bc 100644
--- a/internal/rcm/api_test.go
+++ b/internal/rcm/api_test.go
@@ -3,12 +3,13 @@ package rcm_test
 import (
 	"bytes"
 	"encoding/json"
-	"github.com/google/uuid"
 	"net/http"
 	"net/http/httptest"
 	"regexp"
 	"testing"
 
+	"github.com/google/uuid"
+
 	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/rcm"
@@ -52,7 +53,7 @@ func TestBasicRcmAPI(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	api := rcm.New(nil, store.New(nil, *registry), rpmmd_mock.NewRPMMDMock(rpmmd_mock.BaseFixture()), registry)
+	api := rcm.New(nil, store.New(nil), rpmmd_mock.NewRPMMDMock(rpmmd_mock.BaseFixture()), registry)
 
 	for _, c := range cases {
 		resp := internalRequest(api, c.Method, c.Path, c.Body, c.ContentType)
@@ -78,7 +79,7 @@ func TestSubmitCompose(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	api := rcm.New(nil, store.New(nil, *registry), rpmmd_mock.NewRPMMDMock(rpmmd_mock.BaseFixture()), registry)
+	api := rcm.New(nil, store.New(nil), rpmmd_mock.NewRPMMDMock(rpmmd_mock.BaseFixture()), registry)
 
 	var submit_reply struct {
 		UUID uuid.UUID `json:"compose_id"`
diff --git a/internal/weldr/api_test.go b/internal/weldr/api_test.go
index 163706010..d6b8ad7ca 100644
--- a/internal/weldr/api_test.go
+++ b/internal/weldr/api_test.go
@@ -495,6 +495,7 @@ func TestCompose(t *testing.T) {
 						Status:    common.IBWaiting,
 						ImageName: "test_upload",
 						Options: &target.AWSTargetOptions{
+							Filename:        "test.img",
 							Region:          "frankfurt",
 							AccessKeyID:     "accesskey",
 							SecretAccessKey: "secretkey",