Use tarball.LayerFromOpener

tarball.LayerFromReader slurps the whole src in memory. The payoff is
that we might read the file multiple time as internally it's called
multiple times.
This commit is contained in:
Ettore Di Giacinto 2021-11-22 11:27:46 +01:00
parent 80412e2e5d
commit 44e66cc729
3 changed files with 18 additions and 36 deletions

View File

@ -28,7 +28,6 @@ import (
fileHelper "github.com/mudler/luet/pkg/helpers/file" fileHelper "github.com/mudler/luet/pkg/helpers/file"
"github.com/pkg/errors" "github.com/pkg/errors"
containerdCompression "github.com/containerd/containerd/archive/compression"
"github.com/mudler/luet/cmd/util" "github.com/mudler/luet/cmd/util"
"github.com/mudler/luet/pkg/helpers/docker" "github.com/mudler/luet/pkg/helpers/docker"
@ -36,16 +35,6 @@ import (
) )
func pack(ctx *luettypes.Context, p, dst, imageName, arch, OS string) error { func pack(ctx *luettypes.Context, p, dst, imageName, arch, OS string) error {
archiveFile, err := os.Open(p)
if err != nil {
return errors.Wrap(err, "Cannot open "+p)
}
defer archiveFile.Close()
decompressed, err := containerdCompression.DecompressStream(archiveFile)
if err != nil {
return errors.Wrap(err, "Cannot open "+p)
}
tempimage, err := ctx.Config.GetSystem().TempFile("tempimage") tempimage, err := ctx.Config.GetSystem().TempFile("tempimage")
if err != nil { if err != nil {
@ -53,7 +42,7 @@ func pack(ctx *luettypes.Context, p, dst, imageName, arch, OS string) error {
} }
defer os.RemoveAll(tempimage.Name()) // clean up defer os.RemoveAll(tempimage.Name()) // clean up
if err := image.CreateTarReader(decompressed, tempimage.Name(), imageName, arch, OS); err != nil { if err := image.CreateTar(p, tempimage.Name(), imageName, arch, OS); err != nil {
return errors.Wrap(err, "could not create image from tar") return errors.Wrap(err, "could not create image from tar")
} }

View File

@ -19,6 +19,7 @@ import (
"io" "io"
"os" "os"
containerdCompression "github.com/containerd/containerd/archive/compression"
"github.com/google/go-containerregistry/pkg/name" "github.com/google/go-containerregistry/pkg/name"
v1 "github.com/google/go-containerregistry/pkg/v1" v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/empty" "github.com/google/go-containerregistry/pkg/v1/empty"
@ -27,13 +28,13 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
) )
func imageFromTar(imagename, architecture, OS string, r io.Reader) (name.Reference, v1.Image, error) { func imageFromTar(imagename, architecture, OS string, opener func() (io.ReadCloser, error)) (name.Reference, v1.Image, error) {
newRef, err := name.ParseReference(imagename) newRef, err := name.ParseReference(imagename)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
layer, err := tarball.LayerFromReader(r) layer, err := tarball.LayerFromOpener(opener)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -67,28 +68,30 @@ func imageFromTar(imagename, architecture, OS string, r io.Reader) (name.Referen
// CreateTar a imagetarball from a standard tarball // CreateTar a imagetarball from a standard tarball
func CreateTar(srctar, dstimageTar, imagename, architecture, OS string) error { func CreateTar(srctar, dstimageTar, imagename, architecture, OS string) error {
f, err := os.Open(srctar)
if err != nil {
return errors.Wrap(err, "Cannot open "+srctar)
}
defer f.Close()
return CreateTarReader(f, dstimageTar, imagename, architecture, OS)
}
// CreateTarReader a imagetarball from a standard tarball
func CreateTarReader(r io.Reader, dstimageTar, imagename, architecture, OS string) error {
dstFile, err := os.Create(dstimageTar) dstFile, err := os.Create(dstimageTar)
if err != nil { if err != nil {
return errors.Wrap(err, "Cannot create "+dstimageTar) return errors.Wrap(err, "Cannot create "+dstimageTar)
} }
defer dstFile.Close() defer dstFile.Close()
newRef, img, err := imageFromTar(imagename, architecture, OS, r) newRef, img, err := imageFromTar(imagename, architecture, OS, func() (io.ReadCloser, error) {
f, err := os.Open(srctar)
if err != nil {
return nil, errors.Wrap(err, "Cannot open "+srctar)
}
decompressed, err := containerdCompression.DecompressStream(f)
if err != nil {
return nil, errors.Wrap(err, "Cannot open "+srctar)
}
return decompressed, nil
})
if err != nil { if err != nil {
return err return err
} }
// NOTE: We might also stream that back to the daemon with daemon.Write(tag, img) // NOTE: We might also stream that back to the daemon with daemon.Write(tag, img)
return tarball.Write(newRef, img, dstFile) return tarball.Write(newRef, img, dstFile)
} }

View File

@ -211,16 +211,6 @@ type ImageBuilder interface {
// GenerateFinalImage takes an artifact and builds a Docker image with its content // GenerateFinalImage takes an artifact and builds a Docker image with its content
func (a *PackageArtifact) GenerateFinalImage(ctx *types.Context, imageName string, b ImageBuilder, keepPerms bool) error { func (a *PackageArtifact) GenerateFinalImage(ctx *types.Context, imageName string, b ImageBuilder, keepPerms bool) error {
archiveFile, err := os.Open(a.Path)
if err != nil {
return errors.Wrap(err, "Cannot open "+a.Path)
}
defer archiveFile.Close()
decompressed, err := containerdCompression.DecompressStream(archiveFile)
if err != nil {
return errors.Wrap(err, "Cannot open "+a.Path)
}
tempimage, err := ctx.Config.GetSystem().TempFile("tempimage") tempimage, err := ctx.Config.GetSystem().TempFile("tempimage")
if err != nil { if err != nil {
@ -228,7 +218,7 @@ func (a *PackageArtifact) GenerateFinalImage(ctx *types.Context, imageName strin
} }
defer os.RemoveAll(tempimage.Name()) // clean up defer os.RemoveAll(tempimage.Name()) // clean up
if err := image.CreateTarReader(decompressed, tempimage.Name(), imageName, runtime.GOARCH, runtime.GOOS); err != nil { if err := image.CreateTar(a.Path, tempimage.Name(), imageName, runtime.GOARCH, runtime.GOOS); err != nil {
return errors.Wrap(err, "could not create image from tar") return errors.Wrap(err, "could not create image from tar")
} }