add v1tarreader for images and use it for docker load

Signed-off-by: Avi Deitcher <avi@deitcher.net>
This commit is contained in:
Avi Deitcher 2021-05-18 13:05:28 +03:00
parent ebf570d045
commit f7ee51d931
6 changed files with 48 additions and 1 deletions

View File

@ -6,8 +6,10 @@ import (
"io"
"github.com/containerd/containerd/reference"
"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/mutate"
"github.com/google/go-containerregistry/pkg/v1/tarball"
lktspec "github.com/linuxkit/linuxkit/src/cmd/linuxkit/spec"
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
)
@ -70,6 +72,28 @@ func (c ImageSource) TarReader() (io.ReadCloser, error) {
return mutate.Extract(image), nil
}
// V1TarReader return an io.ReadCloser to read the image as a v1 tarball
func (c ImageSource) V1TarReader() (io.ReadCloser, error) {
imageName := c.ref.String()
refName, err := name.ParseReference(imageName)
if err != nil {
return nil, fmt.Errorf("error parsing image name: %v", err)
}
// get a reference to the image
image, err := c.provider.findImage(imageName, c.architecture)
if err != nil {
return nil, err
}
// convert the writer to a reader
r, w := io.Pipe()
go func() {
defer w.Close()
tarball.Write(refName, image, w)
}()
return r, nil
}
// Descriptor return the descriptor of the image.
func (c ImageSource) Descriptor() *v1.Descriptor {
return c.descriptor

View File

@ -88,6 +88,16 @@ func Export(container string) (io.ReadCloser, error) {
return responseBody, err
}
// Save save the provided image ref.
func Save(image string) (io.ReadCloser, error) {
log.Debugf("docker save: %s", image)
cli, err := Client()
if err != nil {
return nil, errors.New("could not initialize Docker API client")
}
return cli.ImageSave(context.Background(), []string{image})
}
// Rm remove the given container from docker.
func Rm(container string) error {
log.Debugf("docker rm: %s", container)

View File

@ -77,6 +77,11 @@ func (d ImageSource) TarReader() (io.ReadCloser, error) {
}, nil
}
// V1TarReader return an io.ReadCloser to read the save of the image
func (d ImageSource) V1TarReader() (io.ReadCloser, error) {
return Save(d.ref.String())
}
// Descriptor return the descriptor of the image.
func (d ImageSource) Descriptor() *v1.Descriptor {
return nil

View File

@ -289,7 +289,7 @@ func (p Pkg) Build(bos ...BuildOpt) error {
// if requested docker, load the image up
if bo.targetDocker {
cacheSource := c.NewSource(&ref, arch, desc)
reader, err := cacheSource.TarReader()
reader, err := cacheSource.V1TarReader()
if err != nil {
return fmt.Errorf("unable to get reader from cache: %v", err)
}

View File

@ -270,6 +270,9 @@ func (c cacheMockerSource) Config() (imagespec.ImageConfig, error) {
func (c cacheMockerSource) TarReader() (io.ReadCloser, error) {
return nil, errors.New("unsupported")
}
func (c cacheMockerSource) V1TarReader() (io.ReadCloser, error) {
return nil, errors.New("unsupported")
}
func (c cacheMockerSource) Descriptor() *registry.Descriptor {
return c.descriptor
}

View File

@ -10,7 +10,12 @@ import (
// ImageSource interface to an image. It can have its config read, and a its containers
// can be read via an io.ReadCloser tar stream.
type ImageSource interface {
// Config get the config for the image
Config() (imagespec.ImageConfig, error)
// TarReader get the flattened filesystem of the image as a tar stream/
TarReader() (io.ReadCloser, error)
// Descriptor get the v1.Descriptor of the image
Descriptor() *v1.Descriptor
// V1TarReader get the image as v1 tarball, also compatibel with `docker load`
V1TarReader() (io.ReadCloser, error)
}