Repository: osbuild/osbuild-composer
Pull request #1158 (2021-01-11 17:18:16)

jobqueue: remove testjobqueue
testjobqueue did not implement the JobQueue interface correctly (noted
in its package comment), making it impossible to write tests for
JobQueue itself.

Replace its use everywhere with fsjobqueue operating on a temporary
directory.

larskarlitski: Update to remove `t.TempDir()`.
larskarlitski: As far as I can see, only openstack-boot tests failed due to PSI issues. @ondrejbudai could you please confirm?
ondrejbudai: Yeah, this change doesn't interfere with OpenStack in any way. :/

Patch:
diff --git a/internal/mocks/rpmmd/fixtures.go b/internal/mocks/rpmmd/fixtures.go
index edd07e993..9f1fc2bc9 100644
--- a/internal/mocks/rpmmd/fixtures.go
+++ b/internal/mocks/rpmmd/fixtures.go
@@ -5,14 +5,14 @@ import (
 	"sort"
 	"time"
 
-	"github.com/osbuild/osbuild-composer/internal/jobqueue/testjobqueue"
+	"github.com/osbuild/osbuild-composer/internal/jobqueue/fsjobqueue"
 	"github.com/osbuild/osbuild-composer/internal/worker"
 
 	"github.com/osbuild/osbuild-composer/internal/rpmmd"
 	"github.com/osbuild/osbuild-composer/internal/store"
 )
 
-type FixtureGenerator func() Fixture
+type FixtureGenerator func(tmpdir string) Fixture
 
 func generatePackageList() rpmmd.PackageList {
 	baseTime, err := time.Parse(time.RFC3339, "2006-01-02T15:04:05Z")
@@ -52,8 +52,12 @@ func generatePackageList() rpmmd.PackageList {
 	return packageList
 }
 
-func createBaseWorkersFixture() *worker.Server {
-	return worker.NewServer(nil, testjobqueue.New(), "")
+func createBaseWorkersFixture(tmpdir string) *worker.Server {
+	q, err := fsjobqueue.New(tmpdir)
+	if err != nil {
+		panic(err)
+	}
+	return worker.NewServer(nil, q, "")
 }
 
 func createBaseDepsolveFixture() []rpmmd.PackageSpec {
@@ -82,7 +86,7 @@ func createBaseDepsolveFixture() []rpmmd.PackageSpec {
 	}
 }
 
-func BaseFixture() Fixture {
+func BaseFixture(tmpdir string) Fixture {
 	return Fixture{
 		fetchPackageList{
 			generatePackageList(),
@@ -95,11 +99,11 @@ func BaseFixture() Fixture {
 			nil,
 		},
 		store.FixtureBase(),
-		createBaseWorkersFixture(),
+		createBaseWorkersFixture(tmpdir),
 	}
 }
 
-func NoComposesFixture() Fixture {
+func NoComposesFixture(tmpdir string) Fixture {
 	return Fixture{
 		fetchPackageList{
 			generatePackageList(),
@@ -112,11 +116,11 @@ func NoComposesFixture() Fixture {
 			nil,
 		},
 		store.FixtureEmpty(),
-		createBaseWorkersFixture(),
+		createBaseWorkersFixture(tmpdir),
 	}
 }
 
-func NonExistingPackage() Fixture {
+func NonExistingPackage(tmpdir string) Fixture {
 	return Fixture{
 		fetchPackageList{
 			generatePackageList(),
@@ -132,11 +136,11 @@ func NonExistingPackage() Fixture {
 			},
 		},
 		store.FixtureBase(),
-		createBaseWorkersFixture(),
+		createBaseWorkersFixture(tmpdir),
 	}
 }
 
-func BadDepsolve() Fixture {
+func BadDepsolve(tmpdir string) Fixture {
 	return Fixture{
 		fetchPackageList{
 			generatePackageList(),
@@ -152,11 +156,11 @@ func BadDepsolve() Fixture {
 			},
 		},
 		store.FixtureBase(),
-		createBaseWorkersFixture(),
+		createBaseWorkersFixture(tmpdir),
 	}
 }
 
-func BadFetch() Fixture {
+func BadFetch(tmpdir string) Fixture {
 	return Fixture{
 		fetchPackageList{
 			ret:       nil,
@@ -175,6 +179,6 @@ func BadFetch() Fixture {
 			},
 		},
 		store.FixtureBase(),
-		createBaseWorkersFixture(),
+		createBaseWorkersFixture(tmpdir),
 	}
 }


Test patch:
diff --git a/internal/client/unit_test.go b/internal/client/unit_test.go
index 90d6a89a8..2b947bd12 100644
--- a/internal/client/unit_test.go
+++ b/internal/client/unit_test.go
@@ -11,6 +11,7 @@ import (
 	"net"
 	"net/http"
 	"os"
+	"path"
 	"testing"
 
 	"github.com/osbuild/osbuild-composer/internal/distro/fedoratest"
@@ -37,7 +38,11 @@ func executeTests(m *testing.M) int {
 	}
 
 	// Create a mock API server listening on the temporary socket
-	fixture := rpmmd_mock.BaseFixture()
+	err = os.Mkdir(path.Join(tmpdir, "/jobs"), 0755)
+	if err != nil {
+		panic(err)
+	}
+	fixture := rpmmd_mock.BaseFixture(path.Join(tmpdir, "/jobs"))
 	rpm := rpmmd_mock.NewRPMMDMock(fixture)
 	distro := fedoratest.New()
 	arch, err := distro.GetArch("x86_64")
diff --git a/internal/jobqueue/testjobqueue/testjobqueue.go b/internal/jobqueue/testjobqueue/testjobqueue.go
deleted file mode 100644
index 25d8ba323..000000000
--- a/internal/jobqueue/testjobqueue/testjobqueue.go
+++ /dev/null
@@ -1,175 +0,0 @@
-// Package testjobqueue implements jobqueue interface. It is meant for testing,
-// and as such doesn't implement two invariants of jobqueue: it is not safe for
-// concurrent access and `Dequeue()` doesn't wait for new jobs to appear.
-package testjobqueue
-
-import (
-	"context"
-	"encoding/json"
-	"errors"
-	"fmt"
-	"time"
-
-	"github.com/google/uuid"
-	"github.com/osbuild/osbuild-composer/internal/jobqueue"
-)
-
-type testJobQueue struct {
-	jobs map[uuid.UUID]*job
-
-	pending map[string][]uuid.UUID
-
-	// Maps job ids to the jobs that depend on it
-	dependants map[uuid.UUID][]uuid.UUID
-}
-
-type job struct {
-	Id           uuid.UUID
-	Type         string
-	Args         json.RawMessage
-	Dependencies []uuid.UUID
-	Result       json.RawMessage
-	QueuedAt     time.Time
-	StartedAt    time.Time
-	FinishedAt   time.Time
-	Canceled     bool
-}
-
-func New() *testJobQueue {
-	return &testJobQueue{
-		jobs:       make(map[uuid.UUID]*job),
-		pending:    make(map[string][]uuid.UUID),
-		dependants: make(map[uuid.UUID][]uuid.UUID),
-	}
-}
-
-func (q *testJobQueue) Enqueue(jobType string, args interface{}, dependencies []uuid.UUID) (uuid.UUID, error) {
-	var j = job{
-		Id:           uuid.New(),
-		Type:         jobType,
-		Dependencies: dependencies,
-		QueuedAt:     time.Now(),
-	}
-
-	var err error
-	j.Args, err = json.Marshal(args)
-	if err != nil {
-		return uuid.Nil, err
-	}
-
-	q.jobs[j.Id] = &j
-
-	// Verify dependencies and check how many of them are already finished.
-	finished, err := q.countFinishedJobs(j.Dependencies)
-	if err != nil {
-		return uuid.Nil, err
-	}
-
-	// If all dependencies have finished, or there are none, queue the job.
-	// Otherwise, update dependants so that this check is done again when
-	// FinishJob() is called for a dependency.
-	if finished == len(j.Dependencies) {
-		q.pending[j.Type] = append(q.pending[j.Type], j.Id)
-	} else {
-		for _, id := range j.Dependencies {
-			q.dependants[id] = append(q.dependants[id], j.Id)
-		}
-	}
-
-	return j.Id, nil
-}
-
-func (q *testJobQueue) Dequeue(ctx context.Context, jobTypes []string) (uuid.UUID, []uuid.UUID, string, json.RawMessage, error) {
-	for _, t := range jobTypes {
-		if len(q.pending[t]) == 0 {
-			continue
-		}
-
-		id := q.pending[t][0]
-		q.pending[t] = q.pending[t][1:]
-
-		j := q.jobs[id]
-
-		j.StartedAt = time.Now()
-		return j.Id, j.Dependencies, j.Type, j.Args, nil
-	}
-
-	return uuid.Nil, nil, "", nil, errors.New("no job available")
-}
-
-func (q *testJobQueue) FinishJob(id uuid.UUID, result interface{}) error {
-	j, exists := q.jobs[id]
-	if !exists {
-		return jobqueue.ErrNotExist
-	}
-
-	if j.StartedAt.IsZero() || !j.FinishedAt.IsZero() {
-		return jobqueue.ErrNotRunning
-	}
-
-	var err error
-	j.Result, err = json.Marshal(result)
-	if err != nil {
-		return fmt.Errorf("error marshaling result: %v", err)
-	}
-
-	j.FinishedAt = time.Now()
-
-	for _, depid := range q.dependants[id] {
-		dep := q.jobs[depid]
-		n, err := q.countFinishedJobs(dep.Dependencies)
-		if err != nil {
-			return err
-		}
-		if n == len(dep.Dependencies) {
-			q.pending[dep.Type] = append(q.pending[dep.Type], dep.Id)
-		}
-	}
-	delete(q.dependants, id)
-
-	return nil
-}
-
-func (q *testJobQueue) CancelJob(id uuid.UUID) error {
-	j, exists := q.jobs[id]
-	if !exists {
-		return jobqueue.ErrNotExist
-	}
-
-	j.Canceled = true
-
-	return nil
-}
-
-func (q *testJobQueue) JobStatus(id uuid.UUID) (result json.RawMessage, queued, started, finished time.Time, canceled bool, deps []uuid.UUID, err error) {
-	j, exists := q.jobs[id]
-	if !exists {
-		err = jobqueue.ErrNotExist
-		return
-	}
-
-	result = j.Result
-	queued = j.QueuedAt
-	started = j.StartedAt
-	finished = j.FinishedAt
-	canceled = j.Canceled
-	deps = j.Dependencies
-
-	return
-}
-
-// Returns the number of finished jobs in `ids`.
-func (q *testJobQueue) countFinishedJobs(ids []uuid.UUID) (int, error) {
-	n := 0
-	for _, id := range ids {
-		j, exists := q.jobs[id]
-		if !exists {
-			return 0, jobqueue.ErrNotExist
-		}
-		if j.Result != nil {
-			n += 1
-		}
-	}
-
-	return n, nil
-}
diff --git a/internal/kojiapi/server_test.go b/internal/kojiapi/server_test.go
index 76c1bf99d..1f5ac9c07 100644
--- a/internal/kojiapi/server_test.go
+++ b/internal/kojiapi/server_test.go
@@ -12,7 +12,6 @@ import (
 	"sync"
 	"testing"
 
-	"github.com/osbuild/osbuild-composer/internal/jobqueue/fsjobqueue"
 	"github.com/osbuild/osbuild-composer/internal/kojiapi"
 	"github.com/osbuild/osbuild-composer/internal/kojiapi/api"
 	distro_mock "github.com/osbuild/osbuild-composer/internal/mocks/distro"
@@ -24,7 +23,7 @@ import (
 )
 
 func newTestKojiServer(t *testing.T, dir string) (*kojiapi.Server, *worker.Server) {
-	rpm_fixture := rpmmd_mock.BaseFixture()
+	rpm_fixture := rpmmd_mock.BaseFixture(dir)
 	rpm := rpmmd_mock.NewRPMMDMock(rpm_fixture)
 	require.NotNil(t, rpm)
 
@@ -32,16 +31,10 @@ func newTestKojiServer(t *testing.T, dir string) (*kojiapi.Server, *worker.Serve
 	require.NoError(t, err)
 	require.NotNil(t, distros)
 
-	queue, err := fsjobqueue.New(dir)
-	require.NoError(t, err)
-
-	workerServer := worker.NewServer(nil, queue, "")
-	require.NotNil(t, workerServer)
-
-	kojiServer := kojiapi.NewServer(nil, workerServer, rpm, distros)
+	kojiServer := kojiapi.NewServer(nil, rpm_fixture.Workers, rpm, distros)
 	require.NotNil(t, kojiServer)
 
-	return kojiServer, workerServer
+	return kojiServer, rpm_fixture.Workers
 }
 
 func TestStatus(t *testing.T) {
diff --git a/internal/weldr/api_test.go b/internal/weldr/api_test.go
index 86bd19470..9f32dec3e 100644
--- a/internal/weldr/api_test.go
+++ b/internal/weldr/api_test.go
@@ -4,6 +4,7 @@ import (
 	"archive/tar"
 	"bytes"
 	"io"
+	"io/ioutil"
 	"math/rand"
 	"net/http"
 	"net/http/httptest"
@@ -27,8 +28,8 @@ import (
 	"github.com/stretchr/testify/require"
 )
 
-func createWeldrAPI(fixtureGenerator rpmmd_mock.FixtureGenerator) (*API, *store.Store) {
-	fixture := fixtureGenerator()
+func createWeldrAPI(tempdir string, fixtureGenerator rpmmd_mock.FixtureGenerator) (*API, *store.Store) {
+	fixture := fixtureGenerator(tempdir)
 	rpm := rpmmd_mock.NewRPMMDMock(fixture)
 	repos := []rpmmd.RepoConfig{{Name: "test-id", BaseURL: "http://example.com/test/os/x86_64", CheckGPG: true}}
 	d := test_distro.New()
@@ -61,8 +62,12 @@ func TestBasic(t *testing.T) {
 		{"/api/v0/blueprints/info/foo", http.StatusOK, `{"blueprints":[],"changes":[],"errors":[{"id":"UnknownBlueprint","msg":"foo: "}]}`},
 	}
 
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	for _, c := range cases {
-		api, _ := createWeldrAPI(rpmmd_mock.BaseFixture)
+		api, _ := createWeldrAPI(tempdir, rpmmd_mock.BaseFixture)
 		test.TestRoute(t, api, true, "GET", c.Path, ``, c.ExpectedStatus, c.ExpectedJSON)
 	}
 }
@@ -82,13 +87,21 @@ func TestBlueprintsNew(t *testing.T) {
 		{"POST", "/api/v0/blueprints/new", ``, http.StatusBadRequest, `{"status":false,"errors":[{"id":"BlueprintsError","msg":"Missing blueprint"}]}`},
 	}
 
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	for _, c := range cases {
-		api, _ := createWeldrAPI(rpmmd_mock.BaseFixture)
+		api, _ := createWeldrAPI(tempdir, rpmmd_mock.BaseFixture)
 		test.TestRoute(t, api, true, c.Method, c.Path, c.Body, c.ExpectedStatus, c.ExpectedJSON)
 	}
 }
 
 func TestBlueprintsNewToml(t *testing.T) {
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	blueprint := `
 name = "test"
 description = "Test"
@@ -102,7 +115,7 @@ version = "2.4.*"`
 	req.Header.Set("Content-Type", "text/x-toml")
 	recorder := httptest.NewRecorder()
 
-	api, _ := createWeldrAPI(rpmmd_mock.BaseFixture)
+	api, _ := createWeldrAPI(tempdir, rpmmd_mock.BaseFixture)
 	api.ServeHTTP(recorder, req)
 
 	r := recorder.Result()
@@ -110,11 +123,15 @@ version = "2.4.*"`
 }
 
 func TestBlueprintsEmptyToml(t *testing.T) {
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	req := httptest.NewRequest("POST", "/api/v0/blueprints/new", bytes.NewReader(nil))
 	req.Header.Set("Content-Type", "text/x-toml")
 	recorder := httptest.NewRecorder()
 
-	api, _ := createWeldrAPI(rpmmd_mock.BaseFixture)
+	api, _ := createWeldrAPI(tempdir, rpmmd_mock.BaseFixture)
 	api.ServeHTTP(recorder, req)
 
 	r := recorder.Result()
@@ -122,6 +139,10 @@ func TestBlueprintsEmptyToml(t *testing.T) {
 }
 
 func TestBlueprintsInvalidToml(t *testing.T) {
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	blueprint := `
 name = "test"
 description = "Test"
@@ -135,7 +156,7 @@ version = "2.4.*"`
 	req.Header.Set("Content-Type", "text/x-toml")
 	recorder := httptest.NewRecorder()
 
-	api, _ := createWeldrAPI(rpmmd_mock.BaseFixture)
+	api, _ := createWeldrAPI(tempdir, rpmmd_mock.BaseFixture)
 	api.ServeHTTP(recorder, req)
 
 	r := recorder.Result()
@@ -155,13 +176,21 @@ func TestBlueprintsWorkspaceJSON(t *testing.T) {
 		{"POST", "/api/v0/blueprints/workspace", ``, http.StatusBadRequest, `{"status":false,"errors":[{"id":"BlueprintsError","msg":"Missing blueprint"}]}`},
 	}
 
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	for _, c := range cases {
-		api, _ := createWeldrAPI(rpmmd_mock.BaseFixture)
+		api, _ := createWeldrAPI(tempdir, rpmmd_mock.BaseFixture)
 		test.TestRoute(t, api, true, c.Method, c.Path, c.Body, c.ExpectedStatus, c.ExpectedJSON)
 	}
 }
 
 func TestBlueprintsWorkspaceTOML(t *testing.T) {
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	blueprint := `
 name = "test"
 description = "Test"
@@ -175,7 +204,7 @@ version = "2.4.*"`
 	req.Header.Set("Content-Type", "text/x-toml")
 	recorder := httptest.NewRecorder()
 
-	api, _ := createWeldrAPI(rpmmd_mock.BaseFixture)
+	api, _ := createWeldrAPI(tempdir, rpmmd_mock.BaseFixture)
 	api.ServeHTTP(recorder, req)
 
 	r := recorder.Result()
@@ -183,11 +212,15 @@ version = "2.4.*"`
 }
 
 func TestBlueprintsWorkspaceEmptyTOML(t *testing.T) {
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	req := httptest.NewRequest("POST", "/api/v0/blueprints/workspace", bytes.NewReader(nil))
 	req.Header.Set("Content-Type", "text/x-toml")
 	recorder := httptest.NewRecorder()
 
-	api, _ := createWeldrAPI(rpmmd_mock.BaseFixture)
+	api, _ := createWeldrAPI(tempdir, rpmmd_mock.BaseFixture)
 	api.ServeHTTP(recorder, req)
 
 	r := recorder.Result()
@@ -195,6 +228,10 @@ func TestBlueprintsWorkspaceEmptyTOML(t *testing.T) {
 }
 
 func TestBlueprintsWorkspaceInvalidTOML(t *testing.T) {
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	blueprint := `
 name = "test"
 description = "Test"
@@ -208,7 +245,7 @@ version = "2.4.*"`
 	req.Header.Set("Content-Type", "text/x-toml")
 	recorder := httptest.NewRecorder()
 
-	api, _ := createWeldrAPI(rpmmd_mock.BaseFixture)
+	api, _ := createWeldrAPI(tempdir, rpmmd_mock.BaseFixture)
 	api.ServeHTTP(recorder, req)
 
 	r := recorder.Result()
@@ -230,8 +267,12 @@ func TestBlueprintsInfo(t *testing.T) {
 		{"GET", "/api/v0/blueprints/info/test3-non", ``, http.StatusOK, `{"blueprints":[],"changes":[],"errors":[{"id":"UnknownBlueprint","msg":"test3-non: "}]}`},
 	}
 
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	for _, c := range cases {
-		api, _ := createWeldrAPI(rpmmd_mock.BaseFixture)
+		api, _ := createWeldrAPI(tempdir, rpmmd_mock.BaseFixture)
 		test.SendHTTP(api, true, "POST", "/api/v0/blueprints/new", `{"name":"test1","description":"Test","packages":[{"name":"httpd","version":"2.4.*"}],"version":"0.0.0"}`)
 		test.SendHTTP(api, true, "POST", "/api/v0/blueprints/new", `{"name":"test2","description":"Test","packages":[{"name":"httpd","version":"2.4.*"}],"version":"0.0.0"}`)
 		test.SendHTTP(api, true, "POST", "/api/v0/blueprints/workspace", `{"name":"test2","description":"Test","packages":[{"name":"systemd","version":"123"}],"version":"0.0.0"}`)
@@ -242,7 +283,11 @@ func TestBlueprintsInfo(t *testing.T) {
 }
 
 func TestBlueprintsInfoToml(t *testing.T) {
-	api, _ := createWeldrAPI(rpmmd_mock.BaseFixture)
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
+	api, _ := createWeldrAPI(tempdir, rpmmd_mock.BaseFixture)
 	test.SendHTTP(api, true, "POST", "/api/v0/blueprints/new", `{"name":"test1","description":"Test","packages":[{"name":"httpd","version":"2.4.*"}],"version":"0.0.0"}`)
 
 	req := httptest.NewRequest("GET", "/api/v0/blueprints/info/test1?format=toml", nil)
@@ -253,7 +298,7 @@ func TestBlueprintsInfoToml(t *testing.T) {
 	require.Equal(t, http.StatusOK, resp.StatusCode)
 
 	var got blueprint.Blueprint
-	_, err := toml.DecodeReader(resp.Body, &got)
+	_, err = toml.DecodeReader(resp.Body, &got)
 	require.NoErrorf(t, err, "error decoding toml file")
 
 	expected := blueprint.Blueprint{
@@ -272,7 +317,11 @@ func TestBlueprintsInfoToml(t *testing.T) {
 }
 
 func TestNonExistentBlueprintsInfoToml(t *testing.T) {
-	api, _ := createWeldrAPI(rpmmd_mock.BaseFixture)
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
+	api, _ := createWeldrAPI(tempdir, rpmmd_mock.BaseFixture)
 	req := httptest.NewRequest("GET", "/api/v0/blueprints/info/test3-non?format=toml", nil)
 	recorder := httptest.NewRecorder()
 	api.ServeHTTP(recorder, req)
@@ -337,8 +386,12 @@ func TestBlueprintsFreeze(t *testing.T) {
 			{rpmmd_mock.BaseFixture, "/api/v0/blueprints/freeze/test,test2", http.StatusOK, `{"blueprints":[{"blueprint":{"name":"test","description":"Test","version":"0.0.1","packages":[{"name":"dep-package1","version":"1.33-2.fc30.x86_64"},{"name":"dep-package3","version":"7:3.0.3-1.fc30.x86_64"}],"modules":[{"name":"dep-package2","version":"2.9-1.fc30.x86_64"}],"groups":[]}},{"blueprint":{"name":"test2","description":"Test","version":"0.0.0","packages":[{"name":"dep-package1","version":"1.33-2.fc30.x86_64"},{"name":"dep-package3","version":"7:3.0.3-1.fc30.x86_64"}],"modules":[{"name":"dep-package2","version":"2.9-1.fc30.x86_64"}],"groups":[]}}],"errors":[]}`},
 		}
 
+		tempdir, err := ioutil.TempDir("", "weldr-tests-")
+		require.NoError(t, err)
+		defer os.RemoveAll(tempdir)
+
 		for _, c := range cases {
-			api, _ := createWeldrAPI(c.Fixture)
+			api, _ := createWeldrAPI(tempdir, c.Fixture)
 			test.SendHTTP(api, false, "POST", "/api/v0/blueprints/new", `{"name":"test","description":"Test","packages":[{"name":"dep-package1","version":"*"},{"name":"dep-package3","version":"*"}], "modules":[{"name":"dep-package2","version":"*"}],"version":"0.0.0"}`)
 			test.SendHTTP(api, false, "POST", "/api/v0/blueprints/new", `{"name":"test2","description":"Test","packages":[{"name":"dep-package1","version":"*"},{"name":"dep-package3","version":"*"}], "modules":[{"name":"dep-package2","version":"*"}],"version":"0.0.0"}`)
 			test.TestRoute(t, api, false, "GET", c.Path, ``, c.ExpectedStatus, c.ExpectedJSON)
@@ -356,8 +409,12 @@ func TestBlueprintsFreeze(t *testing.T) {
 			{rpmmd_mock.BaseFixture, "/api/v0/blueprints/freeze/missing?format=toml", http.StatusOK, ""},
 		}
 
+		tempdir, err := ioutil.TempDir("", "weldr-tests-")
+		require.NoError(t, err)
+		defer os.RemoveAll(tempdir)
+
 		for _, c := range cases {
-			api, _ := createWeldrAPI(c.Fixture)
+			api, _ := createWeldrAPI(tempdir, c.Fixture)
 			test.SendHTTP(api, false, "POST", "/api/v0/blueprints/new", `{"name":"test","description":"Test","packages":[{"name":"dep-package1","version":"*"},{"name":"dep-package3","version":"*"}], "modules":[{"name":"dep-package2","version":"*"}],"version":"0.0.0"}`)
 			test.TestTOMLRoute(t, api, false, "GET", c.Path, ``, c.ExpectedStatus, c.ExpectedTOML)
 		}
@@ -373,8 +430,12 @@ func TestBlueprintsFreeze(t *testing.T) {
 			{rpmmd_mock.BaseFixture, "/api/v0/blueprints/freeze/test,test2?format=toml", http.StatusBadRequest, "{\"status\":false,\"errors\":[{\"id\":\"HTTPError\",\"msg\":\"toml format only supported when requesting one blueprint\"}]}"},
 		}
 
+		tempdir, err := ioutil.TempDir("", "weldr-tests-")
+		require.NoError(t, err)
+		defer os.RemoveAll(tempdir)
+
 		for _, c := range cases {
-			api, _ := createWeldrAPI(c.Fixture)
+			api, _ := createWeldrAPI(tempdir, c.Fixture)
 			test.SendHTTP(api, false, "POST", "/api/v0/blueprints/new", `{"name":"test","description":"Test","packages":[{"name":"dep-package1","version":"*"},{"name":"dep-package3","version":"*"}], "modules":[{"name":"dep-package2","version":"*"}],"version":"0.0.0"}`)
 			test.SendHTTP(api, false, "POST", "/api/v0/blueprints/new", `{"name":"test2","description":"Test","packages":[{"name":"dep-package1","version":"*"},{"name":"dep-package3","version":"*"}], "modules":[{"name":"dep-package2","version":"*"}],"version":"0.0.0"}`)
 			test.TestRoute(t, api, false, "GET", c.Path, ``, c.ExpectedStatus, c.ExpectedJSON)
@@ -393,8 +454,12 @@ func TestBlueprintsDiff(t *testing.T) {
 		{"GET", "/api/v0/blueprints/diff/test/NEWEST/WORKSPACE", ``, http.StatusOK, `{"diff":[{"new":{"Package":{"name":"systemd","version":"123"}},"old":null},{"new":null,"old":{"Package":{"name":"httpd","version":"2.4.*"}}}]}`},
 	}
 
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	for _, c := range cases {
-		api, _ := createWeldrAPI(rpmmd_mock.BaseFixture)
+		api, _ := createWeldrAPI(tempdir, rpmmd_mock.BaseFixture)
 		test.SendHTTP(api, true, "POST", "/api/v0/blueprints/new", `{"name":"test","description":"Test","packages":[{"name":"httpd","version":"2.4.*"}],"version":"0.0.0"}`)
 		test.SendHTTP(api, true, "POST", "/api/v0/blueprints/workspace", `{"name":"test","description":"Test","packages":[{"name":"systemd","version":"123"}],"version":"0.0.0"}`)
 		test.TestRoute(t, api, true, c.Method, c.Path, c.Body, c.ExpectedStatus, c.ExpectedJSON)
@@ -414,8 +479,12 @@ func TestBlueprintsDelete(t *testing.T) {
 		{"DELETE", "/api/v0/blueprints/delete/test3-non", ``, http.StatusBadRequest, `{"status":false,"errors":[{"id":"BlueprintsError","msg":"Unknown blueprint: test3-non"}]}`},
 	}
 
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	for _, c := range cases {
-		api, _ := createWeldrAPI(rpmmd_mock.BaseFixture)
+		api, _ := createWeldrAPI(tempdir, rpmmd_mock.BaseFixture)
 		test.SendHTTP(api, true, "POST", "/api/v0/blueprints/new", `{"name":"test","description":"Test","packages":[{"name":"httpd","version":"2.4.*"}],"version":"0.0.0"}`)
 		test.TestRoute(t, api, true, c.Method, c.Path, c.Body, c.ExpectedStatus, c.ExpectedJSON)
 		test.SendHTTP(api, true, "DELETE", "/api/v0/blueprints/delete/test", ``)
@@ -423,7 +492,11 @@ func TestBlueprintsDelete(t *testing.T) {
 }
 
 func TestBlueprintsChanges(t *testing.T) {
-	api, _ := createWeldrAPI(rpmmd_mock.BaseFixture)
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
+	api, _ := createWeldrAPI(tempdir, rpmmd_mock.BaseFixture)
 	rand.Seed(time.Now().UnixNano())
 	id := strconv.Itoa(rand.Int())
 	ignoreFields := []string{"commit", "timestamp"}
@@ -448,8 +521,12 @@ func TestBlueprintsDepsolve(t *testing.T) {
 		{rpmmd_mock.BadDepsolve, http.StatusOK, `{"blueprints":[{"blueprint":{"name":"test","description":"Test","version":"0.0.1","packages":[{"name":"dep-package1","version":"*"}],"groups":[],"modules":[{"name":"dep-package3","version":"*"}]},"dependencies":[]}],"errors":[{"id":"BlueprintsError","msg":"test: DNF error occured: DepsolveError: There was a problem depsolving ['go2rpm']: \n Problem: conflicting requests\n  - nothing provides askalono-cli needed by go2rpm-1-4.fc31.noarch"}]}`},
 	}
 
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	for _, c := range cases {
-		api, _ := createWeldrAPI(c.Fixture)
+		api, _ := createWeldrAPI(tempdir, c.Fixture)
 		test.SendHTTP(api, false, "POST", "/api/v0/blueprints/new", `{"name":"test","description":"Test","packages":[{"name":"dep-package1","version":"*"}],"modules":[{"name":"dep-package3","version":"*"}],"version":"0.0.0"}`)
 		test.TestRoute(t, api, false, "GET", "/api/v0/blueprints/depsolve/test", ``, c.ExpectedStatus, c.ExpectedJSON)
 		test.SendHTTP(api, false, "DELETE", "/api/v0/blueprints/delete/test", ``)
@@ -524,8 +601,12 @@ func TestCompose(t *testing.T) {
 		{false, "POST", "/api/v1/compose", `{"blueprint_name": "test","compose_type":"qcow2","branch":"master","upload":{"image_name":"test_upload","provider":"aws","settings":{"region":"frankfurt","accessKeyID":"accesskey","secretAccessKey":"secretkey","bucket":"clay","key":"imagekey"}}}`, http.StatusOK, `{"status": true}`, expectedComposeLocalAndAws, []string{"build_id"}},
 	}
 
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	for _, c := range cases {
-		api, s := createWeldrAPI(rpmmd_mock.NoComposesFixture)
+		api, s := createWeldrAPI(tempdir, rpmmd_mock.NoComposesFixture)
 		test.TestRoute(t, api, c.External, c.Method, c.Path, c.Body, c.ExpectedStatus, c.ExpectedJSON, c.IgnoreFields...)
 
 		if c.ExpectedStatus != http.StatusOK {
@@ -568,8 +649,12 @@ func TestComposeDelete(t *testing.T) {
 		{"/api/v0/compose/delete/30000000-0000-0000-0000-000000000003,42000000-0000-0000-0000-000000000000", `{"uuids":[{"uuid":"30000000-0000-0000-0000-000000000003","status":true}],"errors":[{"id":"UnknownUUID","msg":"compose 42000000-0000-0000-0000-000000000000 doesn't exist"}]}`, []string{"30000000-0000-0000-0000-000000000000", "30000000-0000-0000-0000-000000000001", "30000000-0000-0000-0000-000000000002"}},
 	}
 
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	for _, c := range cases {
-		api, s := createWeldrAPI(rpmmd_mock.BaseFixture)
+		api, s := createWeldrAPI(tempdir, rpmmd_mock.BaseFixture)
 		test.TestRoute(t, api, false, "DELETE", c.Path, "", http.StatusOK, c.ExpectedJSON)
 
 		idsInStore := []string{}
@@ -603,8 +688,12 @@ func TestComposeStatus(t *testing.T) {
 		t.Skip("This test is for internal testing only")
 	}
 
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	for _, c := range cases {
-		api, _ := createWeldrAPI(rpmmd_mock.BaseFixture)
+		api, _ := createWeldrAPI(tempdir, rpmmd_mock.BaseFixture)
 		test.TestRoute(t, api, false, c.Method, c.Path, c.Body, c.ExpectedStatus, c.ExpectedJSON, "id", "job_created", "job_started")
 	}
 }
@@ -628,8 +717,12 @@ func TestComposeInfo(t *testing.T) {
 		t.Skip("This test is for internal testing only")
 	}
 
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	for _, c := range cases {
-		api, _ := createWeldrAPI(rpmmd_mock.BaseFixture)
+		api, _ := createWeldrAPI(tempdir, rpmmd_mock.BaseFixture)
 		test.TestRoute(t, api, false, c.Method, c.Path, c.Body, c.ExpectedStatus, c.ExpectedJSON)
 	}
 }
@@ -654,8 +747,12 @@ func TestComposeLogs(t *testing.T) {
 		{"/api/v1/compose/results/30000000-0000-0000-0000-000000000002", "attachment; filename=30000000-0000-0000-0000-000000000002.tar", "application/x-tar", "30000000-0000-0000-0000-000000000002.json", "{\"sources\":{},\"pipeline\":{}}"},
 	}
 
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	for _, c := range successCases {
-		api, _ := createWeldrAPI(rpmmd_mock.BaseFixture)
+		api, _ := createWeldrAPI(tempdir, rpmmd_mock.BaseFixture)
 
 		response := test.SendHTTP(api, false, "GET", c.Path, "")
 		require.Equalf(t, http.StatusOK, response.StatusCode, "%s: unexpected status code", c.Path)
@@ -694,7 +791,7 @@ func TestComposeLogs(t *testing.T) {
 	}
 
 	for _, c := range failureCases {
-		api, _ := createWeldrAPI(rpmmd_mock.BaseFixture)
+		api, _ := createWeldrAPI(tempdir, rpmmd_mock.BaseFixture)
 		test.TestRoute(t, api, false, "GET", c.Path, "", http.StatusBadRequest, c.ExpectedJSON)
 	}
 }
@@ -719,8 +816,12 @@ func TestComposeLog(t *testing.T) {
 		t.Skip("This test is for internal testing only")
 	}
 
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	for _, c := range cases {
-		api, _ := createWeldrAPI(rpmmd_mock.BaseFixture)
+		api, _ := createWeldrAPI(tempdir, rpmmd_mock.BaseFixture)
 		test.TestNonJsonRoute(t, api, false, "GET", c.Path, "", c.ExpectedStatus, c.ExpectedResponse)
 	}
 }
@@ -743,8 +844,12 @@ func TestComposeQueue(t *testing.T) {
 		t.Skip("This test is for internal testing only")
 	}
 
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	for _, c := range cases {
-		api, _ := createWeldrAPI(c.Fixture)
+		api, _ := createWeldrAPI(tempdir, c.Fixture)
 		test.TestRoute(t, api, false, c.Method, c.Path, c.Body, c.ExpectedStatus, c.ExpectedJSON, "id", "job_created", "job_started")
 	}
 }
@@ -767,8 +872,12 @@ func TestComposeFinished(t *testing.T) {
 		t.Skip("This test is for internal testing only")
 	}
 
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	for _, c := range cases {
-		api, _ := createWeldrAPI(c.Fixture)
+		api, _ := createWeldrAPI(tempdir, c.Fixture)
 		test.TestRoute(t, api, false, c.Method, c.Path, c.Body, c.ExpectedStatus, c.ExpectedJSON, "id", "job_created", "job_started")
 	}
 }
@@ -791,8 +900,12 @@ func TestComposeFailed(t *testing.T) {
 		t.Skip("This test is for internal testing only")
 	}
 
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	for _, c := range cases {
-		api, _ := createWeldrAPI(c.Fixture)
+		api, _ := createWeldrAPI(tempdir, c.Fixture)
 		test.TestRoute(t, api, false, c.Method, c.Path, c.Body, c.ExpectedStatus, c.ExpectedJSON, "id", "job_created", "job_started")
 	}
 }
@@ -814,14 +927,22 @@ func TestSourcesNew(t *testing.T) {
 		{"POST", "/api/v0/projects/source/new", `{"name": "fish", "url": "https://download.opensuse.org/repositories/shells:/fish:/release:/3/Fedora_29/","check_ssl": false,"check_gpg": false}`, http.StatusBadRequest, `{"errors": [{"id": "ProjectsError","msg": "Problem parsing POST body: 'type' field is missing from request"}],"status":false}`},
 	}
 
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	for _, c := range cases {
-		api, _ := createWeldrAPI(rpmmd_mock.BaseFixture)
+		api, _ := createWeldrAPI(tempdir, rpmmd_mock.BaseFixture)
 		test.TestRoute(t, api, true, c.Method, c.Path, c.Body, c.ExpectedStatus, c.ExpectedJSON)
 		test.SendHTTP(api, true, "DELETE", "/api/v0/projects/source/delete/fish", ``)
 	}
 }
 
 func TestSourcesNewToml(t *testing.T) {
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	source := `
 name = "fish"
 url = "https://download.opensuse.org/repositories/shells:/fish:/release:/3/Fedora_29/"
@@ -833,7 +954,7 @@ check_gpg = false
 	req.Header.Set("Content-Type", "text/x-toml")
 	recorder := httptest.NewRecorder()
 
-	api, _ := createWeldrAPI(rpmmd_mock.BaseFixture)
+	api, _ := createWeldrAPI(tempdir, rpmmd_mock.BaseFixture)
 	api.ServeHTTP(recorder, req)
 
 	r := recorder.Result()
@@ -844,6 +965,10 @@ check_gpg = false
 
 // Empty TOML, and invalid TOML should return an error
 func TestSourcesNewWrongToml(t *testing.T) {
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	sources := []string{``, `
 [fish]
 name = "fish"
@@ -857,7 +982,7 @@ check_gpg = false
 		req.Header.Set("Content-Type", "text/x-toml")
 		recorder := httptest.NewRecorder()
 
-		api, _ := createWeldrAPI(rpmmd_mock.BaseFixture)
+		api, _ := createWeldrAPI(tempdir, rpmmd_mock.BaseFixture)
 		api.ServeHTTP(recorder, req)
 
 		r := recorder.Result()
@@ -866,9 +991,13 @@ check_gpg = false
 }
 
 func TestSourcesInfo(t *testing.T) {
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	sourceStr := `{"name":"fish","type":"yum-baseurl","url":"https://download.opensuse.org/repositories/shells:/fish:/release:/3/Fedora_29/","check_gpg":false,"check_ssl":false,"system":false}`
 
-	api, _ := createWeldrAPI(rpmmd_mock.BaseFixture)
+	api, _ := createWeldrAPI(tempdir, rpmmd_mock.BaseFixture)
 	test.SendHTTP(api, true, "POST", "/api/v0/projects/source/new", sourceStr)
 	test.TestRoute(t, api, true, "GET", "/api/v0/projects/source/info/fish", ``, 200, `{"sources":{"fish":`+sourceStr+`},"errors":[]}`)
 	test.TestRoute(t, api, true, "GET", "/api/v0/projects/source/info/fish?format=json", ``, 200, `{"sources":{"fish":`+sourceStr+`},"errors":[]}`)
@@ -876,9 +1005,13 @@ func TestSourcesInfo(t *testing.T) {
 }
 
 func TestSourcesInfoToml(t *testing.T) {
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	sourceStr := `{"name":"fish","type":"yum-baseurl","url":"https://download.opensuse.org/repositories/shells:/fish:/release:/3/Fedora_29/","check_gpg":false,"check_ssl":false,"system":false}`
 
-	api, _ := createWeldrAPI(rpmmd_mock.BaseFixture)
+	api, _ := createWeldrAPI(tempdir, rpmmd_mock.BaseFixture)
 	test.SendHTTP(api, true, "POST", "/api/v0/projects/source/new", sourceStr)
 
 	req := httptest.NewRequest("GET", "/api/v0/projects/source/info/fish?format=toml", nil)
@@ -887,7 +1020,7 @@ func TestSourcesInfoToml(t *testing.T) {
 	resp := recorder.Result()
 
 	var sources map[string]store.SourceConfig
-	_, err := toml.DecodeReader(resp.Body, &sources)
+	_, err = toml.DecodeReader(resp.Body, &sources)
 	require.NoErrorf(t, err, "error decoding toml file")
 
 	expected := map[string]store.SourceConfig{
@@ -913,8 +1046,12 @@ func TestSourcesDelete(t *testing.T) {
 		{"DELETE", "/api/v0/projects/source/delete/fish", ``, http.StatusOK, `{"status":true}`},
 	}
 
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	for _, c := range cases {
-		api, _ := createWeldrAPI(rpmmd_mock.BaseFixture)
+		api, _ := createWeldrAPI(tempdir, rpmmd_mock.BaseFixture)
 		test.SendHTTP(api, true, "POST", "/api/v0/projects/source/new", `{"name": "fish","url": "https://download.opensuse.org/repositories/shells:/fish:/release:/3/Fedora_29/","type": "yum-baseurl","check_ssl": false,"check_gpg": false}`)
 		test.TestRoute(t, api, true, c.Method, c.Path, c.Body, c.ExpectedStatus, c.ExpectedJSON)
 		test.SendHTTP(api, true, "DELETE", "/api/v0/projects/source/delete/fish", ``)
@@ -933,8 +1070,12 @@ func TestProjectsDepsolve(t *testing.T) {
 		{rpmmd_mock.BadDepsolve, "/api/v0/projects/depsolve/go2rpm", http.StatusBadRequest, `{"status":false,"errors":[{"id":"PROJECTS_ERROR","msg":"BadRequest: DNF error occured: DepsolveError: There was a problem depsolving ['go2rpm']: \n Problem: conflicting requests\n  - nothing provides askalono-cli needed by go2rpm-1-4.fc31.noarch"}]}`},
 	}
 
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	for _, c := range cases {
-		api, _ := createWeldrAPI(c.Fixture)
+		api, _ := createWeldrAPI(tempdir, c.Fixture)
 		test.TestRoute(t, api, true, "GET", c.Path, ``, c.ExpectedStatus, c.ExpectedJSON)
 	}
 }
@@ -954,8 +1095,12 @@ func TestProjectsInfo(t *testing.T) {
 		{rpmmd_mock.BadFetch, "/api/v0/projects/info/package2*,package16", http.StatusBadRequest, `{"status":false,"errors":[{"id":"ModulesError","msg":"msg: DNF error occured: FetchError: There was a problem when fetching packages."}]}`},
 	}
 
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	for _, c := range cases {
-		api, _ := createWeldrAPI(c.Fixture)
+		api, _ := createWeldrAPI(tempdir, c.Fixture)
 		test.TestRoute(t, api, true, "GET", c.Path, ``, c.ExpectedStatus, c.ExpectedJSON)
 	}
 }
@@ -976,8 +1121,12 @@ func TestModulesInfo(t *testing.T) {
 		{rpmmd_mock.BadFetch, "/api/v0/modules/info/package2*,package16", http.StatusBadRequest, `{"status":false,"errors":[{"id":"ModulesError","msg":"msg: DNF error occured: FetchError: There was a problem when fetching packages."}]}`},
 	}
 
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	for _, c := range cases {
-		api, _ := createWeldrAPI(c.Fixture)
+		api, _ := createWeldrAPI(tempdir, c.Fixture)
 		test.TestRoute(t, api, true, "GET", c.Path, ``, c.ExpectedStatus, c.ExpectedJSON)
 	}
 }
@@ -995,8 +1144,12 @@ func TestProjectsList(t *testing.T) {
 		{rpmmd_mock.BaseFixture, "/api/v0/projects/list?offset=1&limit=1", http.StatusOK, `{"total":22,"offset":1,"limit":1,"projects":[{"name":"package1","summary":"pkg1 sum","description":"pkg1 desc","homepage":"https://pkg1.example.com","upstream_vcs":"UPSTREAM_VCS","builds":[{"arch":"x86_64","build_time":"2006-02-02T15:04:05","epoch":0,"release":"1.fc30","changelog":"CHANGELOG_NEEDED","build_config_ref":"BUILD_CONFIG_REF","build_env_ref":"BUILD_ENV_REF","metadata":{},"source":{"license":"MIT","version":"1.0","source_ref":"SOURCE_REF","metadata":{}}},{"arch":"x86_64","build_time":"2006-02-03T15:04:05","epoch":0,"release":"1.fc30","changelog":"CHANGELOG_NEEDED","build_config_ref":"BUILD_CONFIG_REF","build_env_ref":"BUILD_ENV_REF","metadata":{},"source":{"license":"MIT","version":"1.1","source_ref":"SOURCE_REF","metadata":{}}}]}]}`},
 	}
 
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	for _, c := range cases {
-		api, _ := createWeldrAPI(c.Fixture)
+		api, _ := createWeldrAPI(tempdir, c.Fixture)
 		test.TestRoute(t, api, true, "GET", c.Path, ``, c.ExpectedStatus, c.ExpectedJSON)
 	}
 }
@@ -1017,8 +1170,12 @@ func TestModulesList(t *testing.T) {
 		{rpmmd_mock.BaseFixture, "/api/v0/modules/list/*", http.StatusOK, `{"total":22,"offset":0,"limit":20,"modules":[{"name":"package0","group_type":"rpm"},{"name":"package1","group_type":"rpm"},{"name":"package10","group_type":"rpm"},{"name":"package11","group_type":"rpm"},{"name":"package12","group_type":"rpm"},{"name":"package13","group_type":"rpm"},{"name":"package14","group_type":"rpm"},{"name":"package15","group_type":"rpm"},{"name":"package16","group_type":"rpm"},{"name":"package17","group_type":"rpm"},{"name":"package18","group_type":"rpm"},{"name":"package19","group_type":"rpm"},{"name":"package2","group_type":"rpm"},{"name":"package20","group_type":"rpm"},{"name":"package21","group_type":"rpm"},{"name":"package3","group_type":"rpm"},{"name":"package4","group_type":"rpm"},{"name":"package5","group_type":"rpm"},{"name":"package6","group_type":"rpm"},{"name":"package7","group_type":"rpm"}]}`},
 	}
 
+	tempdir, err := ioutil.TempDir("", "weldr-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	for _, c := range cases {
-		api, _ := createWeldrAPI(c.Fixture)
+		api, _ := createWeldrAPI(tempdir, c.Fixture)
 		test.TestRoute(t, api, true, "GET", c.Path, ``, c.ExpectedStatus, c.ExpectedJSON)
 	}
 }
diff --git a/internal/worker/server_test.go b/internal/worker/server_test.go
index 277bd4d85..7a34eb1dd 100644
--- a/internal/worker/server_test.go
+++ b/internal/worker/server_test.go
@@ -3,21 +3,35 @@ package worker_test
 import (
 	"context"
 	"fmt"
+	"io/ioutil"
 	"net/http"
+	"os"
 	"testing"
 
 	"github.com/stretchr/testify/require"
 
 	"github.com/osbuild/osbuild-composer/internal/distro"
 	"github.com/osbuild/osbuild-composer/internal/distro/fedoratest"
-	"github.com/osbuild/osbuild-composer/internal/jobqueue/testjobqueue"
+	"github.com/osbuild/osbuild-composer/internal/jobqueue/fsjobqueue"
 	"github.com/osbuild/osbuild-composer/internal/test"
 	"github.com/osbuild/osbuild-composer/internal/worker"
 )
 
+func newTestServer(t *testing.T, tempdir string) *worker.Server {
+	q, err := fsjobqueue.New(tempdir)
+	if err != nil {
+		t.Fatalf("error creating fsjobqueue: %v", err)
+	}
+	return worker.NewServer(nil, q, "")
+}
+
 // Ensure that the status request returns OK.
 func TestStatus(t *testing.T) {
-	server := worker.NewServer(nil, testjobqueue.New(), "")
+	tempdir, err := ioutil.TempDir("", "worker-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
+	server := newTestServer(t, tempdir)
 	handler := server.Handler()
 	test.TestRoute(t, handler, false, "GET", "/api/worker/v1/status", ``, http.StatusOK, `{"status":"OK"}`, "message")
 }
@@ -43,14 +57,22 @@ func TestErrors(t *testing.T) {
 		{"PATCH", "/api/worker/v1/jobs/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", `{"status":"FINISHED"}`, http.StatusNotFound},
 	}
 
+	tempdir, err := ioutil.TempDir("", "worker-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	for _, c := range cases {
-		server := worker.NewServer(nil, testjobqueue.New(), "")
+		server := newTestServer(t, tempdir)
 		handler := server.Handler()
 		test.TestRoute(t, handler, false, c.Method, c.Path, c.Body, c.ExpectedStatus, "{}", "message")
 	}
 }
 
 func TestCreate(t *testing.T) {
+	tempdir, err := ioutil.TempDir("", "worker-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	distroStruct := fedoratest.New()
 	arch, err := distroStruct.GetArch("x86_64")
 	if err != nil {
@@ -64,7 +86,7 @@ func TestCreate(t *testing.T) {
 	if err != nil {
 		t.Fatalf("error creating osbuild manifest")
 	}
-	server := worker.NewServer(nil, testjobqueue.New(), "")
+	server := newTestServer(t, tempdir)
 	handler := server.Handler()
 
 	_, err = server.EnqueueOSBuild(arch.Name(), &worker.OSBuildJob{Manifest: manifest})
@@ -75,6 +97,10 @@ func TestCreate(t *testing.T) {
 }
 
 func TestCancel(t *testing.T) {
+	tempdir, err := ioutil.TempDir("", "worker-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	distroStruct := fedoratest.New()
 	arch, err := distroStruct.GetArch("x86_64")
 	if err != nil {
@@ -88,7 +114,7 @@ func TestCancel(t *testing.T) {
 	if err != nil {
 		t.Fatalf("error creating osbuild manifest")
 	}
-	server := worker.NewServer(nil, testjobqueue.New(), "")
+	server := newTestServer(t, tempdir)
 	handler := server.Handler()
 
 	jobId, err := server.EnqueueOSBuild(arch.Name(), &worker.OSBuildJob{Manifest: manifest})
@@ -112,6 +138,10 @@ func TestCancel(t *testing.T) {
 }
 
 func TestUpdate(t *testing.T) {
+	tempdir, err := ioutil.TempDir("", "worker-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	distroStruct := fedoratest.New()
 	arch, err := distroStruct.GetArch("x86_64")
 	if err != nil {
@@ -125,7 +155,7 @@ func TestUpdate(t *testing.T) {
 	if err != nil {
 		t.Fatalf("error creating osbuild manifest")
 	}
-	server := worker.NewServer(nil, testjobqueue.New(), "")
+	server := newTestServer(t, tempdir)
 	handler := server.Handler()
 
 	jobId, err := server.EnqueueOSBuild(arch.Name(), &worker.OSBuildJob{Manifest: manifest})
@@ -143,6 +173,10 @@ func TestUpdate(t *testing.T) {
 }
 
 func TestUpload(t *testing.T) {
+	tempdir, err := ioutil.TempDir("", "worker-tests-")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempdir)
+
 	distroStruct := fedoratest.New()
 	arch, err := distroStruct.GetArch("x86_64")
 	if err != nil {
@@ -156,7 +190,7 @@ func TestUpload(t *testing.T) {
 	if err != nil {
 		t.Fatalf("error creating osbuild manifest")
 	}
-	server := worker.NewServer(nil, testjobqueue.New(), "")
+	server := newTestServer(t, tempdir)
 	handler := server.Handler()
 
 	jobID, err := server.EnqueueOSBuild(arch.Name(), &worker.OSBuildJob{Manifest: manifest})