Skip to content

Commit

Permalink
feat(daemon): lazy image saving (#1121)
Browse files Browse the repository at this point in the history
* feat(daemon): tarball lazy loading

* fix tests

* fix: replace LayerByDigest with LayerByDiffID

* test: add validate.Image
  • Loading branch information
knqyf263 committed Sep 19, 2021
1 parent 0e8b581 commit f0983da
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 4 deletions.
102 changes: 101 additions & 1 deletion pkg/v1/daemon/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,15 @@ import (
"github.com/google/go-containerregistry/pkg/name"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/tarball"
"github.com/google/go-containerregistry/pkg/v1/types"
)

type image struct {
ref name.Reference
opener *imageOpener
tarballImage v1.Image
}

type imageOpener struct {
ref name.Reference
ctx context.Context
Expand Down Expand Up @@ -85,5 +92,98 @@ func Image(ref name.Reference, options ...Option) (v1.Image, error) {
ctx: o.ctx,
}

return tarball.Image(i.opener(), nil)
return &image{
ref: ref,
opener: i,
}, nil
}

func (i *image) initialize() error {
// Don't re-initialize tarball if already initialized.
if i.tarballImage == nil {
var err error
i.tarballImage, err = tarball.Image(i.opener.opener(), nil)
if err != nil {
return err
}
}
return nil
}

func (i *image) Layers() ([]v1.Layer, error) {
if err := i.initialize(); err != nil {
return nil, err
}
return i.tarballImage.Layers()
}

func (i image) MediaType() (types.MediaType, error) {
if err := i.initialize(); err != nil {
return "", err
}
return i.tarballImage.MediaType()
}

func (i *image) Size() (int64, error) {
if err := i.initialize(); err != nil {
return 0, err
}
return i.tarballImage.Size()
}

func (i *image) ConfigName() (v1.Hash, error) {
res, _, err := i.opener.client.ImageInspectWithRaw(i.opener.ctx, i.ref.String())
if err != nil {
return v1.Hash{}, err
}
return v1.NewHash(res.ID)
}

func (i image) ConfigFile() (*v1.ConfigFile, error) {
if err := i.initialize(); err != nil {
return nil, err
}
return i.tarballImage.ConfigFile()
}

func (i image) RawConfigFile() ([]byte, error) {
if err := i.initialize(); err != nil {
return nil, err
}
return i.tarballImage.RawConfigFile()
}

func (i image) Digest() (v1.Hash, error) {
if err := i.initialize(); err != nil {
return v1.Hash{}, err
}
return i.tarballImage.Digest()
}

func (i image) Manifest() (*v1.Manifest, error) {
if err := i.initialize(); err != nil {
return nil, err
}
return i.tarballImage.Manifest()
}

func (i image) RawManifest() ([]byte, error) {
if err := i.initialize(); err != nil {
return nil, err
}
return i.tarballImage.RawManifest()
}

func (i image) LayerByDigest(h v1.Hash) (v1.Layer, error) {
if err := i.initialize(); err != nil {
return nil, err
}
return i.tarballImage.LayerByDigest(h)
}

func (i image) LayerByDiffID(h v1.Hash) (v1.Layer, error) {
if err := i.initialize(); err != nil {
return nil, err
}
return i.tarballImage.LayerByDiffID(h)
}
27 changes: 24 additions & 3 deletions pkg/v1/daemon/image_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@ import (
"strings"
"testing"

"github.com/docker/docker/api/types"
"github.com/google/go-containerregistry/internal/compare"
"github.com/google/go-containerregistry/pkg/name"

"github.com/google/go-containerregistry/pkg/v1/tarball"
"github.com/google/go-containerregistry/pkg/v1/validate"
)

var imagePath = "../tarball/testdata/test_image_1.tar"
Expand Down Expand Up @@ -62,6 +63,12 @@ func (m *MockClient) ImageSave(_ context.Context, _ []string) (io.ReadCloser, er
return m.saveBody, m.saveErr
}

func (m *MockClient) ImageInspectWithRaw(context.Context, string) (types.ImageInspect, []byte, error) {
return types.ImageInspect{
ID: "sha256:6e0b05049ed9c17d02e1a55e80d6599dbfcce7f4f4b022e3c673e685789c470e",
}, nil, nil
}

func TestImage(t *testing.T) {
for _, tc := range []struct {
name string
Expand Down Expand Up @@ -114,8 +121,22 @@ func TestImage(t *testing.T) {
}
return
}
if err := compare.Images(img, dmn); err != nil {
t.Errorf("compare.Images: %v", err)
err = compare.Images(img, dmn)
if err != nil {
if tc.wantErr == "" {
t.Errorf("compare.Images: %v", err)
} else if !strings.Contains(err.Error(), tc.wantErr) {
t.Errorf("wanted %s to contain %s", err.Error(), tc.wantErr)
}
}

err = validate.Image(dmn)
if err != nil {
if tc.wantErr == "" {
t.Errorf("validate.Image: %v", err)
} else if !strings.Contains(err.Error(), tc.wantErr) {
t.Errorf("wanted %s to contain %s", err.Error(), tc.wantErr)
}
}
}

Expand Down
1 change: 1 addition & 0 deletions pkg/v1/daemon/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,5 @@ type Client interface {
ImageSave(context.Context, []string) (io.ReadCloser, error)
ImageLoad(context.Context, io.Reader, bool) (types.ImageLoadResponse, error)
ImageTag(context.Context, string, string) error
ImageInspectWithRaw(context.Context, string) (types.ImageInspect, []byte, error)
}

0 comments on commit f0983da

Please sign in to comment.