2017-05-27 06:12:13 +00:00
|
|
|
package cache
|
2017-05-26 00:16:32 +00:00
|
|
|
|
|
|
|
import (
|
2017-05-26 18:56:12 +00:00
|
|
|
"context"
|
2017-07-14 18:59:31 +00:00
|
|
|
"fmt"
|
2017-05-26 00:16:32 +00:00
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
2017-05-26 17:20:41 +00:00
|
|
|
"path/filepath"
|
2017-05-26 00:16:32 +00:00
|
|
|
"testing"
|
|
|
|
|
2017-06-13 23:01:47 +00:00
|
|
|
"github.com/containerd/containerd/namespaces"
|
2017-12-05 07:34:25 +00:00
|
|
|
"github.com/containerd/containerd/snapshots/naive"
|
2017-07-05 02:00:27 +00:00
|
|
|
"github.com/moby/buildkit/cache/metadata"
|
2017-07-25 22:14:46 +00:00
|
|
|
"github.com/moby/buildkit/client"
|
2017-06-22 20:15:46 +00:00
|
|
|
"github.com/moby/buildkit/snapshot"
|
2017-05-26 17:59:33 +00:00
|
|
|
"github.com/pkg/errors"
|
2017-07-14 18:59:31 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
2017-05-26 00:16:32 +00:00
|
|
|
)
|
|
|
|
|
2017-05-27 06:12:13 +00:00
|
|
|
func TestManager(t *testing.T) {
|
2017-06-13 23:01:47 +00:00
|
|
|
ctx := namespaces.WithNamespace(context.Background(), "buildkit-test")
|
|
|
|
|
2017-05-26 00:16:32 +00:00
|
|
|
tmpdir, err := ioutil.TempDir("", "cachemanager")
|
2017-07-14 18:59:31 +00:00
|
|
|
require.NoError(t, err)
|
2017-05-26 00:16:32 +00:00
|
|
|
defer os.RemoveAll(tmpdir)
|
|
|
|
|
2017-11-06 09:44:23 +00:00
|
|
|
snapshotter, err := naive.NewSnapshotter(filepath.Join(tmpdir, "snapshots"))
|
|
|
|
require.NoError(t, err)
|
|
|
|
cm := getCacheManager(t, tmpdir, snapshotter)
|
2017-05-26 00:16:32 +00:00
|
|
|
|
2017-06-13 23:01:47 +00:00
|
|
|
_, err = cm.Get(ctx, "foobar")
|
2017-07-14 18:59:31 +00:00
|
|
|
require.Error(t, err)
|
2017-05-26 00:34:59 +00:00
|
|
|
|
2017-11-17 02:09:35 +00:00
|
|
|
checkDiskUsage(ctx, t, cm, 0, 0)
|
2017-05-26 21:17:38 +00:00
|
|
|
|
2017-07-20 22:55:24 +00:00
|
|
|
active, err := cm.New(ctx, nil, CachePolicyRetain)
|
2017-07-14 18:59:31 +00:00
|
|
|
require.NoError(t, err)
|
2017-05-26 17:20:41 +00:00
|
|
|
|
2017-07-18 06:08:22 +00:00
|
|
|
m, err := active.Mount(ctx, false)
|
2017-07-14 18:59:31 +00:00
|
|
|
require.NoError(t, err)
|
2017-05-26 17:20:41 +00:00
|
|
|
|
|
|
|
lm := snapshot.LocalMounter(m)
|
|
|
|
target, err := lm.Mount()
|
2017-07-14 18:59:31 +00:00
|
|
|
require.NoError(t, err)
|
2017-05-26 17:20:41 +00:00
|
|
|
|
|
|
|
fi, err := os.Stat(target)
|
2017-07-14 18:59:31 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, fi.IsDir(), true)
|
2017-05-26 17:20:41 +00:00
|
|
|
|
|
|
|
err = lm.Unmount()
|
2017-07-14 18:59:31 +00:00
|
|
|
require.NoError(t, err)
|
2017-05-26 17:20:41 +00:00
|
|
|
|
2017-06-13 23:01:47 +00:00
|
|
|
_, err = cm.GetMutable(ctx, active.ID())
|
2017-07-14 18:59:31 +00:00
|
|
|
require.Error(t, err)
|
|
|
|
require.Equal(t, errLocked, errors.Cause(err))
|
2017-05-26 17:59:33 +00:00
|
|
|
|
2017-11-17 02:09:35 +00:00
|
|
|
checkDiskUsage(ctx, t, cm, 1, 0)
|
2017-05-26 21:17:38 +00:00
|
|
|
|
2017-07-14 18:59:31 +00:00
|
|
|
snap, err := active.Commit(ctx)
|
|
|
|
require.NoError(t, err)
|
2017-05-26 17:59:33 +00:00
|
|
|
|
2017-11-17 02:09:35 +00:00
|
|
|
checkDiskUsage(ctx, t, cm, 1, 0)
|
2017-05-26 21:17:38 +00:00
|
|
|
|
2017-06-13 23:01:47 +00:00
|
|
|
_, err = cm.GetMutable(ctx, active.ID())
|
2017-07-14 18:59:31 +00:00
|
|
|
require.Error(t, err)
|
|
|
|
require.Equal(t, errLocked, errors.Cause(err))
|
2017-05-26 18:56:12 +00:00
|
|
|
|
2017-06-13 23:01:47 +00:00
|
|
|
err = snap.Release(ctx)
|
2017-07-14 18:59:31 +00:00
|
|
|
require.NoError(t, err)
|
2017-05-26 18:56:12 +00:00
|
|
|
|
2017-11-17 02:09:35 +00:00
|
|
|
checkDiskUsage(ctx, t, cm, 0, 1)
|
2017-05-26 21:17:38 +00:00
|
|
|
|
2017-06-13 23:01:47 +00:00
|
|
|
active, err = cm.GetMutable(ctx, active.ID())
|
2017-07-14 18:59:31 +00:00
|
|
|
require.NoError(t, err)
|
2017-05-26 18:56:12 +00:00
|
|
|
|
2017-11-17 02:09:35 +00:00
|
|
|
checkDiskUsage(ctx, t, cm, 1, 0)
|
2017-05-26 21:17:38 +00:00
|
|
|
|
2017-07-14 18:59:31 +00:00
|
|
|
snap, err = active.Commit(ctx)
|
|
|
|
require.NoError(t, err)
|
2017-05-26 17:59:33 +00:00
|
|
|
|
2017-11-17 02:09:35 +00:00
|
|
|
checkDiskUsage(ctx, t, cm, 1, 0)
|
2017-05-26 21:17:38 +00:00
|
|
|
|
2017-07-14 18:59:31 +00:00
|
|
|
err = snap.Finalize(ctx)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2017-06-13 23:01:47 +00:00
|
|
|
err = snap.Release(ctx)
|
2017-07-14 18:59:31 +00:00
|
|
|
require.NoError(t, err)
|
2017-05-26 17:59:33 +00:00
|
|
|
|
2017-06-13 23:01:47 +00:00
|
|
|
_, err = cm.GetMutable(ctx, active.ID())
|
2017-07-14 18:59:31 +00:00
|
|
|
require.Error(t, err)
|
|
|
|
require.Equal(t, errNotFound, errors.Cause(err))
|
2017-05-26 18:56:12 +00:00
|
|
|
|
2017-06-13 23:01:47 +00:00
|
|
|
_, err = cm.GetMutable(ctx, snap.ID())
|
2017-07-14 18:59:31 +00:00
|
|
|
require.Error(t, err)
|
|
|
|
require.Equal(t, errInvalid, errors.Cause(err))
|
2017-05-26 18:56:12 +00:00
|
|
|
|
2017-06-13 23:01:47 +00:00
|
|
|
snap, err = cm.Get(ctx, snap.ID())
|
2017-07-14 18:59:31 +00:00
|
|
|
require.NoError(t, err)
|
2017-05-26 18:56:12 +00:00
|
|
|
|
2017-06-13 23:01:47 +00:00
|
|
|
snap2, err := cm.Get(ctx, snap.ID())
|
2017-07-14 18:59:31 +00:00
|
|
|
require.NoError(t, err)
|
2017-05-26 18:56:12 +00:00
|
|
|
|
2017-11-17 02:09:35 +00:00
|
|
|
checkDiskUsage(ctx, t, cm, 1, 0)
|
2017-05-26 21:17:38 +00:00
|
|
|
|
2017-06-13 23:01:47 +00:00
|
|
|
err = snap.Release(ctx)
|
2017-07-14 18:59:31 +00:00
|
|
|
require.NoError(t, err)
|
2017-05-26 18:56:12 +00:00
|
|
|
|
2017-07-20 22:55:24 +00:00
|
|
|
active2, err := cm.New(ctx, snap2, CachePolicyRetain)
|
2017-07-14 18:59:31 +00:00
|
|
|
require.NoError(t, err)
|
2017-05-26 20:45:01 +00:00
|
|
|
|
2017-11-17 02:09:35 +00:00
|
|
|
checkDiskUsage(ctx, t, cm, 2, 0)
|
2017-05-26 21:17:38 +00:00
|
|
|
|
2017-07-14 18:59:31 +00:00
|
|
|
snap3, err := active2.Commit(ctx)
|
|
|
|
require.NoError(t, err)
|
2017-05-26 20:45:01 +00:00
|
|
|
|
2017-06-13 23:01:47 +00:00
|
|
|
err = snap2.Release(ctx)
|
2017-07-14 18:59:31 +00:00
|
|
|
require.NoError(t, err)
|
2017-05-26 20:45:01 +00:00
|
|
|
|
2017-11-17 02:09:35 +00:00
|
|
|
checkDiskUsage(ctx, t, cm, 2, 0)
|
2017-05-26 21:17:38 +00:00
|
|
|
|
2017-06-13 23:01:47 +00:00
|
|
|
err = snap3.Release(ctx)
|
2017-07-14 18:59:31 +00:00
|
|
|
require.NoError(t, err)
|
2017-05-26 17:59:33 +00:00
|
|
|
|
2017-11-17 02:09:35 +00:00
|
|
|
checkDiskUsage(ctx, t, cm, 0, 2)
|
2017-05-26 21:17:38 +00:00
|
|
|
|
2017-05-26 00:16:32 +00:00
|
|
|
err = cm.Close()
|
2017-07-14 18:59:31 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestLazyCommit(t *testing.T) {
|
|
|
|
ctx := namespaces.WithNamespace(context.Background(), "buildkit-test")
|
|
|
|
|
|
|
|
tmpdir, err := ioutil.TempDir("", "cachemanager")
|
|
|
|
require.NoError(t, err)
|
|
|
|
defer os.RemoveAll(tmpdir)
|
|
|
|
|
2017-11-06 09:44:23 +00:00
|
|
|
snapshotter, err := naive.NewSnapshotter(filepath.Join(tmpdir, "snapshots"))
|
|
|
|
require.NoError(t, err)
|
|
|
|
cm := getCacheManager(t, tmpdir, snapshotter)
|
2017-07-14 18:59:31 +00:00
|
|
|
|
2017-07-20 22:55:24 +00:00
|
|
|
active, err := cm.New(ctx, nil, CachePolicyRetain)
|
2017-07-14 18:59:31 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// after commit mutable is locked
|
|
|
|
snap, err := active.Commit(ctx)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
_, err = cm.GetMutable(ctx, active.ID())
|
|
|
|
require.Error(t, err)
|
|
|
|
require.Equal(t, errLocked, errors.Cause(err))
|
|
|
|
|
|
|
|
// immutable refs still work
|
|
|
|
snap2, err := cm.Get(ctx, snap.ID())
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, snap.ID(), snap2.ID())
|
|
|
|
|
|
|
|
err = snap.Release(ctx)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
err = snap2.Release(ctx)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// immutable work after final release as well
|
|
|
|
snap, err = cm.Get(ctx, snap.ID())
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, snap.ID(), snap2.ID())
|
2017-07-19 23:39:32 +00:00
|
|
|
|
|
|
|
// active can't be get while immutable is held
|
|
|
|
_, err = cm.GetMutable(ctx, active.ID())
|
|
|
|
require.Error(t, err)
|
|
|
|
require.Equal(t, errLocked, errors.Cause(err))
|
|
|
|
|
2017-07-14 18:59:31 +00:00
|
|
|
err = snap.Release(ctx)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// after release mutable becomes available again
|
|
|
|
active2, err := cm.GetMutable(ctx, active.ID())
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, active2.ID(), active.ID())
|
|
|
|
|
|
|
|
// because ref was took mutable old immutable are cleared
|
|
|
|
_, err = cm.Get(ctx, snap.ID())
|
|
|
|
require.Error(t, err)
|
|
|
|
require.Equal(t, errNotFound, errors.Cause(err))
|
|
|
|
|
|
|
|
snap, err = active2.Commit(ctx)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// this time finalize commit
|
|
|
|
err = snap.Finalize(ctx)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
err = snap.Release(ctx)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// mutable is gone after finalize
|
|
|
|
_, err = cm.GetMutable(ctx, active2.ID())
|
|
|
|
require.Error(t, err)
|
|
|
|
require.Equal(t, errNotFound, errors.Cause(err))
|
|
|
|
|
|
|
|
// immutable still works
|
|
|
|
snap2, err = cm.Get(ctx, snap.ID())
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, snap.ID(), snap2.ID())
|
|
|
|
|
|
|
|
err = snap2.Release(ctx)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// test restarting after commit
|
2017-07-20 22:55:24 +00:00
|
|
|
active, err = cm.New(ctx, nil, CachePolicyRetain)
|
2017-07-14 18:59:31 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// after commit mutable is locked
|
|
|
|
snap, err = active.Commit(ctx)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
err = cm.Close()
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2017-11-06 09:44:23 +00:00
|
|
|
// we can't close snapshotter and open it twice (especially, its internal boltdb store)
|
|
|
|
cm = getCacheManager(t, tmpdir, snapshotter)
|
2017-07-14 18:59:31 +00:00
|
|
|
|
|
|
|
snap2, err = cm.Get(ctx, snap.ID())
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
err = snap2.Release(ctx)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
active, err = cm.GetMutable(ctx, active.ID())
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
_, err = cm.Get(ctx, snap.ID())
|
|
|
|
require.Error(t, err)
|
|
|
|
require.Equal(t, errNotFound, errors.Cause(err))
|
|
|
|
|
|
|
|
snap, err = active.Commit(ctx)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
err = cm.Close()
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2017-11-06 09:44:23 +00:00
|
|
|
cm = getCacheManager(t, tmpdir, snapshotter)
|
2017-07-14 18:59:31 +00:00
|
|
|
|
|
|
|
snap2, err = cm.Get(ctx, snap.ID())
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
err = snap2.Finalize(ctx)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
err = snap2.Release(ctx)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
active, err = cm.GetMutable(ctx, active.ID())
|
|
|
|
require.Error(t, err)
|
|
|
|
require.Equal(t, errNotFound, errors.Cause(err))
|
|
|
|
}
|
|
|
|
|
2017-11-06 09:44:23 +00:00
|
|
|
func getCacheManager(t *testing.T, tmpdir string, snapshotter snapshot.Snapshotter) Manager {
|
2017-07-14 18:59:31 +00:00
|
|
|
md, err := metadata.NewStore(filepath.Join(tmpdir, "metadata.db"))
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
cm, err := NewManager(ManagerOpt{
|
|
|
|
Snapshotter: snapshotter,
|
|
|
|
MetadataStore: md,
|
|
|
|
})
|
|
|
|
require.NoError(t, err, fmt.Sprintf("error: %+v", err))
|
|
|
|
return cm
|
2017-05-26 00:16:32 +00:00
|
|
|
}
|
2017-05-26 21:17:38 +00:00
|
|
|
|
2017-11-17 02:09:35 +00:00
|
|
|
func checkDiskUsage(ctx context.Context, t *testing.T, cm Manager, inuse, unused int) {
|
2017-07-25 22:14:46 +00:00
|
|
|
du, err := cm.DiskUsage(ctx, client.DiskUsageInfo{})
|
2017-07-14 18:59:31 +00:00
|
|
|
require.NoError(t, err)
|
2017-05-26 21:17:38 +00:00
|
|
|
var inuseActual, unusedActual int
|
|
|
|
for _, r := range du {
|
|
|
|
if r.InUse {
|
|
|
|
inuseActual++
|
|
|
|
} else {
|
|
|
|
unusedActual++
|
|
|
|
}
|
|
|
|
}
|
2017-07-14 18:59:31 +00:00
|
|
|
require.Equal(t, inuse, inuseActual)
|
|
|
|
require.Equal(t, unused, unusedActual)
|
2017-05-26 21:17:38 +00:00
|
|
|
}
|