summaryrefslogtreecommitdiff
path: root/daemon/images/store_test.go
blob: 2732162e7745aec3f5d456769de534840547ff01 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package images

import (
	"context"
	"os"
	"path/filepath"
	"testing"

	"github.com/containerd/containerd/content"
	"github.com/containerd/containerd/content/local"
	cerrdefs "github.com/containerd/containerd/errdefs"
	"github.com/containerd/containerd/leases"
	"github.com/containerd/containerd/metadata"
	"github.com/containerd/containerd/namespaces"
	"github.com/docker/docker/image"
	"github.com/opencontainers/go-digest"
	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
	"go.etcd.io/bbolt"
	"gotest.tools/v3/assert"
	is "gotest.tools/v3/assert/cmp"
)

func setupTestStores(t *testing.T) (context.Context, content.Store, *imageStoreWithLease, func(t *testing.T)) {
	dir, err := os.MkdirTemp("", t.Name())
	assert.NilError(t, err)

	backend, err := image.NewFSStoreBackend(filepath.Join(dir, "images"))
	assert.NilError(t, err)
	is, err := image.NewImageStore(backend, nil)
	assert.NilError(t, err)

	db, err := bbolt.Open(filepath.Join(dir, "metadata.db"), 0600, nil)
	assert.NilError(t, err)

	cs, err := local.NewStore(filepath.Join(dir, "content"))
	assert.NilError(t, err)
	mdb := metadata.NewDB(db, cs, nil)

	cleanup := func(t *testing.T) {
		assert.Check(t, db.Close())
		assert.Check(t, os.RemoveAll(dir))
	}
	ctx := namespaces.WithNamespace(context.Background(), t.Name())
	images := &imageStoreWithLease{Store: is, ns: t.Name(), leases: metadata.NewLeaseManager(mdb)}

	return ctx, cs, images, cleanup
}

func TestImageDelete(t *testing.T) {
	ctx, _, images, cleanup := setupTestStores(t)
	defer cleanup(t)

	t.Run("no lease", func(t *testing.T) {
		id, err := images.Create([]byte(`{"rootFS": {}}`))
		assert.NilError(t, err)
		defer images.Delete(id)

		ls, err := images.leases.List(ctx)
		assert.NilError(t, err)
		assert.Equal(t, len(ls), 0, ls)

		_, err = images.Delete(id)
		assert.NilError(t, err, "should not error when there is no lease")
	})

	t.Run("lease exists", func(t *testing.T) {
		id, err := images.Create([]byte(`{"rootFS": {}}`))
		assert.NilError(t, err)
		defer images.Delete(id)

		leaseID := imageKey(id.String())
		_, err = images.leases.Create(ctx, leases.WithID(leaseID))
		assert.NilError(t, err)
		defer images.leases.Delete(ctx, leases.Lease{ID: leaseID})

		ls, err := images.leases.List(ctx)
		assert.NilError(t, err)
		assert.Check(t, is.Equal(len(ls), 1), ls)

		_, err = images.Delete(id)
		assert.NilError(t, err)

		ls, err = images.leases.List(ctx)
		assert.NilError(t, err)
		assert.Check(t, is.Equal(len(ls), 0), ls)
	})
}

func TestContentStoreForPull(t *testing.T) {
	ctx, cs, imgStore, cleanup := setupTestStores(t)
	defer cleanup(t)

	csP := &contentStoreForPull{
		ContentStore: cs,
		leases:       imgStore.leases,
	}

	data := []byte(`{}`)
	desc := ocispec.Descriptor{
		Digest: digest.Canonical.FromBytes(data),
		Size:   int64(len(data)),
	}

	w, err := csP.Writer(ctx, content.WithRef(t.Name()), content.WithDescriptor(desc))
	assert.NilError(t, err)

	_, err = w.Write(data)
	assert.NilError(t, err)
	defer w.Close()

	err = w.Commit(ctx, desc.Size, desc.Digest)
	assert.NilError(t, err)

	assert.Equal(t, len(csP.digested), 1)
	assert.Check(t, is.Equal(csP.digested[0], desc.Digest))

	// Test already exists
	csP.digested = nil
	_, err = csP.Writer(ctx, content.WithRef(t.Name()), content.WithDescriptor(desc))
	assert.Check(t, cerrdefs.IsAlreadyExists(err))
	assert.Equal(t, len(csP.digested), 1)
	assert.Check(t, is.Equal(csP.digested[0], desc.Digest))
}