Fix image pull after a failure
When resuming from a failed pull writer.Truncate() was not seeking to the proper position in the file. This caused writes to happen after the previously written content, instead of at the start of the file. Signed-off-by: Daniel Nephin <dnephin@gmail.com>
This commit is contained in:
parent
03bc5e974d
commit
9184908075
@ -77,7 +77,7 @@ func Copy(ctx context.Context, cw Writer, r io.Reader, size int64, expected dige
|
||||
r, err = seekReader(r, ws.Offset, size)
|
||||
if err != nil {
|
||||
if !isUnseekable(err) {
|
||||
return errors.Wrapf(err, "unabled to resume write to %v", ws.Ref)
|
||||
return errors.Wrapf(err, "unable to resume write to %v", ws.Ref)
|
||||
}
|
||||
|
||||
// reader is unseekable, try to move the writer back to the start.
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
"github.com/containerd/containerd/content/testsuite"
|
||||
"github.com/containerd/containerd/testutil"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type memoryLabelStore struct {
|
||||
@ -335,3 +336,42 @@ func checkWrite(ctx context.Context, t checker, cs content.Store, dgst digest.Di
|
||||
|
||||
return dgst
|
||||
}
|
||||
|
||||
func TestWriterTruncateRecoversFromIncompleteWrite(t *testing.T) {
|
||||
tmpdir, err := ioutil.TempDir("", "test-local-content-store-recover")
|
||||
require.NoError(t, err)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
cs, err := NewStore(tmpdir)
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
ref := "ref"
|
||||
content := []byte("this is the content")
|
||||
total := int64(len(content))
|
||||
setupIncompleteWrite(ctx, t, cs, ref, total)
|
||||
|
||||
writer, err := cs.Writer(ctx, ref, total, "")
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, writer.Truncate(0))
|
||||
|
||||
_, err = writer.Write(content)
|
||||
require.NoError(t, err)
|
||||
|
||||
dgst := digest.FromBytes(content)
|
||||
err = writer.Commit(ctx, total, dgst)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func setupIncompleteWrite(ctx context.Context, t *testing.T, cs content.Store, ref string, total int64) {
|
||||
writer, err := cs.Writer(ctx, ref, total, "")
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = writer.Write([]byte("bad data"))
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, writer.Close())
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package local
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
@ -167,5 +168,8 @@ func (w *writer) Truncate(size int64) error {
|
||||
}
|
||||
w.offset = 0
|
||||
w.digester.Hash().Reset()
|
||||
if _, err := w.fp.Seek(0, io.SeekStart); err != nil {
|
||||
return err
|
||||
}
|
||||
return w.fp.Truncate(0)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user