Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix image pull after a failure #1916

Merged
merged 1 commit into from
Dec 14, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion content/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
40 changes: 40 additions & 0 deletions content/local/store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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())
}
4 changes: 4 additions & 0 deletions content/local/writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package local

import (
"context"
"io"
"os"
"path/filepath"
"runtime"
Expand Down Expand Up @@ -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)
}