update vendor

This commit is contained in:
Ettore Di Giacinto
2021-10-23 20:47:32 +02:00
parent 6a9f19941a
commit ab251fefce
889 changed files with 80636 additions and 20210 deletions

View File

@@ -23,13 +23,15 @@ import (
"io"
"io/ioutil"
"os"
"path"
"path/filepath"
"sync"
"github.com/google/go-containerregistry/internal/gzip"
"github.com/google/go-containerregistry/pkg/name"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/partial"
"github.com/google/go-containerregistry/pkg/v1/types"
"github.com/google/go-containerregistry/pkg/v1/v1util"
)
type image struct {
@@ -68,6 +70,22 @@ func ImageFromPath(path string, tag *name.Tag) (v1.Image, error) {
return Image(pathOpener(path), tag)
}
// LoadManifest load manifest
func LoadManifest(opener Opener) (Manifest, error) {
m, err := extractFileFromTar(opener, "manifest.json")
if err != nil {
return nil, err
}
defer m.Close()
var manifest Manifest
if err := json.NewDecoder(m).Decode(&manifest); err != nil {
return nil, err
}
return manifest, nil
}
// Image exposes an image from the tarball at the provided path.
func Image(opener Opener, tag *name.Tag) (v1.Image, error) {
img := &image{
@@ -148,7 +166,7 @@ func (i *image) areLayersCompressed() (bool, error) {
return false, err
}
defer blob.Close()
return v1util.IsGzipped(blob)
return gzip.Is(blob)
}
func (i *image) loadTarDescriptorAndConfig() error {
@@ -216,6 +234,10 @@ func extractFileFromTar(opener Opener, filePath string) (io.ReadCloser, error) {
return nil, err
}
if hdr.Name == filePath {
if hdr.Typeflag == tar.TypeSymlink || hdr.Typeflag == tar.TypeLink {
currentDir := filepath.Dir(filePath)
return extractFileFromTar(opener, path.Join(currentDir, hdr.Linkname))
}
close = false
return tarFile{
Reader: tf,

View File

@@ -20,51 +20,67 @@ import (
"io"
"io/ioutil"
"os"
"sync"
"github.com/containerd/stargz-snapshotter/estargz"
"github.com/google/go-containerregistry/internal/and"
gestargz "github.com/google/go-containerregistry/internal/estargz"
ggzip "github.com/google/go-containerregistry/internal/gzip"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/types"
"github.com/google/go-containerregistry/pkg/v1/v1util"
)
type layer struct {
digest v1.Hash
diffID v1.Hash
size int64
opener Opener
compressed bool
compression int
digest v1.Hash
diffID v1.Hash
size int64
compressedopener Opener
uncompressedopener Opener
compression int
annotations map[string]string
estgzopts []estargz.Option
}
// Descriptor implements partial.withDescriptor.
func (l *layer) Descriptor() (*v1.Descriptor, error) {
digest, err := l.Digest()
if err != nil {
return nil, err
}
return &v1.Descriptor{
Size: l.size,
Digest: digest,
Annotations: l.annotations,
MediaType: types.DockerLayer,
}, nil
}
// Digest implements v1.Layer
func (l *layer) Digest() (v1.Hash, error) {
return l.digest, nil
}
// DiffID implements v1.Layer
func (l *layer) DiffID() (v1.Hash, error) {
return l.diffID, nil
}
// Compressed implements v1.Layer
func (l *layer) Compressed() (io.ReadCloser, error) {
rc, err := l.opener()
if err == nil && !l.compressed {
return v1util.GzipReadCloserLevel(rc, l.compression), nil
}
return rc, err
return l.compressedopener()
}
// Uncompressed implements v1.Layer
func (l *layer) Uncompressed() (io.ReadCloser, error) {
rc, err := l.opener()
if err == nil && l.compressed {
return v1util.GunzipReadCloser(rc)
}
return rc, err
return l.uncompressedopener()
}
// Size implements v1.Layer
func (l *layer) Size() (int64, error) {
return l.size, nil
}
// MediaType implements v1.Layer
func (l *layer) MediaType() (types.MediaType, error) {
return types.DockerLayer, nil
}
@@ -72,13 +88,89 @@ func (l *layer) MediaType() (types.MediaType, error) {
// LayerOption applies options to layer
type LayerOption func(*layer)
// WithCompressionLevel sets the gzip compression. See `gzip.NewWriterLevel` for possible values.
// WithCompressionLevel is a functional option for overriding the default
// compression level used for compressing uncompressed tarballs.
func WithCompressionLevel(level int) LayerOption {
return func(l *layer) {
l.compression = level
}
}
// WithCompressedCaching is a functional option that overrides the
// logic for accessing the compressed bytes to memoize the result
// and avoid expensive repeated gzips.
func WithCompressedCaching(l *layer) {
var once sync.Once
var err error
buf := bytes.NewBuffer(nil)
og := l.compressedopener
l.compressedopener = func() (io.ReadCloser, error) {
once.Do(func() {
var rc io.ReadCloser
rc, err = og()
if err == nil {
defer rc.Close()
_, err = io.Copy(buf, rc)
}
})
if err != nil {
return nil, err
}
return ioutil.NopCloser(bytes.NewBuffer(buf.Bytes())), nil
}
}
// WithEstargzOptions is a functional option that allow the caller to pass
// through estargz.Options to the underlying compression layer. This is
// only meaningful when estargz is enabled.
func WithEstargzOptions(opts ...estargz.Option) LayerOption {
return func(l *layer) {
l.estgzopts = opts
}
}
// WithEstargz is a functional option that explicitly enables estargz support.
func WithEstargz(l *layer) {
oguncompressed := l.uncompressedopener
estargz := func() (io.ReadCloser, error) {
crc, err := oguncompressed()
if err != nil {
return nil, err
}
eopts := append(l.estgzopts, estargz.WithCompressionLevel(l.compression))
rc, h, err := gestargz.ReadCloser(crc, eopts...)
if err != nil {
return nil, err
}
l.annotations[estargz.TOCJSONDigestAnnotation] = h.String()
return &and.ReadCloser{
Reader: rc,
CloseFunc: func() error {
err := rc.Close()
if err != nil {
return err
}
// As an optimization, leverage the DiffID exposed by the estargz ReadCloser
l.diffID, err = v1.NewHash(rc.DiffID().String())
return err
},
}, nil
}
uncompressed := func() (io.ReadCloser, error) {
urc, err := estargz()
if err != nil {
return nil, err
}
return ggzip.UnzipReadCloser(urc)
}
l.compressedopener = estargz
l.uncompressedopener = uncompressed
}
// LayerFromFile returns a v1.Layer given a tarball
func LayerFromFile(path string, opts ...LayerOption) (v1.Layer, error) {
opener := func() (io.ReadCloser, error) {
@@ -87,7 +179,16 @@ func LayerFromFile(path string, opts ...LayerOption) (v1.Layer, error) {
return LayerFromOpener(opener, opts...)
}
// LayerFromOpener returns a v1.Layer given an Opener function
// LayerFromOpener returns a v1.Layer given an Opener function.
// The Opener may return either an uncompressed tarball (common),
// or a compressed tarball (uncommon).
//
// When using this in conjunction with something like remote.Write
// the uncompressed path may end up gzipping things multiple times:
// 1. Compute the layer SHA256
// 2. Upload the compressed layer.
// Since gzip can be expensive, we support an option to memoize the
// compression that can be passed here: tarball.WithCompressedCaching
func LayerFromOpener(opener Opener, opts ...LayerOption) (v1.Layer, error) {
rc, err := opener()
if err != nil {
@@ -95,27 +196,53 @@ func LayerFromOpener(opener Opener, opts ...LayerOption) (v1.Layer, error) {
}
defer rc.Close()
compressed, err := v1util.IsGzipped(rc)
compressed, err := ggzip.Is(rc)
if err != nil {
return nil, err
}
layer := &layer{
compressed: compressed,
compression: gzip.BestSpeed,
opener: opener,
annotations: make(map[string]string, 1),
}
if estgz := os.Getenv("GGCR_EXPERIMENT_ESTARGZ"); estgz == "1" {
opts = append([]LayerOption{WithEstargz}, opts...)
}
if compressed {
layer.compressedopener = opener
layer.uncompressedopener = func() (io.ReadCloser, error) {
urc, err := opener()
if err != nil {
return nil, err
}
return ggzip.UnzipReadCloser(urc)
}
} else {
layer.uncompressedopener = opener
layer.compressedopener = func() (io.ReadCloser, error) {
crc, err := opener()
if err != nil {
return nil, err
}
return ggzip.ReadCloserLevel(crc, layer.compression), nil
}
}
for _, opt := range opts {
opt(layer)
}
if layer.digest, layer.size, err = computeDigest(opener, compressed, layer.compression); err != nil {
if layer.digest, layer.size, err = computeDigest(layer.compressedopener); err != nil {
return nil, err
}
if layer.diffID, err = computeDiffID(opener, compressed); err != nil {
return nil, err
empty := v1.Hash{}
if layer.diffID == empty {
if layer.diffID, err = computeDiffID(layer.uncompressedopener); err != nil {
return nil, err
}
}
return layer, nil
@@ -133,38 +260,23 @@ func LayerFromReader(reader io.Reader, opts ...LayerOption) (v1.Layer, error) {
}, opts...)
}
func computeDigest(opener Opener, compressed bool, compression int) (v1.Hash, int64, error) {
func computeDigest(opener Opener) (v1.Hash, int64, error) {
rc, err := opener()
if err != nil {
return v1.Hash{}, 0, err
}
defer rc.Close()
if compressed {
return v1.SHA256(rc)
}
return v1.SHA256(v1util.GzipReadCloserLevel(ioutil.NopCloser(rc), compression))
return v1.SHA256(rc)
}
func computeDiffID(opener Opener, compressed bool) (v1.Hash, error) {
func computeDiffID(opener Opener) (v1.Hash, error) {
rc, err := opener()
if err != nil {
return v1.Hash{}, err
}
defer rc.Close()
if !compressed {
digest, _, err := v1.SHA256(rc)
return digest, err
}
reader, err := gzip.NewReader(rc)
if err != nil {
return v1.Hash{}, err
}
defer reader.Close()
diffID, _, err := v1.SHA256(reader)
return diffID, err
digest, _, err := v1.SHA256(rc)
return digest, err
}

View File

@@ -222,6 +222,10 @@ func writeImagesToTar(refToImage map[name.Reference]v1.Image, m []byte, size int
func calculateManifest(refToImage map[name.Reference]v1.Image) (m Manifest, err error) {
imageToTags := dedupRefToImage(refToImage)
if len(imageToTags) == 0 {
return nil, errors.New("set of images is empty")
}
for img, tags := range imageToTags {
cfgName, err := img.ConfigName()
if err != nil {
@@ -334,11 +338,22 @@ func dedupRefToImage(refToImage map[name.Reference]v1.Image) map[v1.Image][]stri
for ref, img := range refToImage {
if tag, ok := ref.(name.Tag); ok {
if tags, ok := imageToTags[img]; ok && tags != nil {
imageToTags[img] = append(tags, tag.String())
} else {
imageToTags[img] = []string{tag.String()}
if tags, ok := imageToTags[img]; !ok || tags == nil {
imageToTags[img] = []string{}
}
// Docker cannot load tarballs without an explicit tag:
// https://github.com/google/go-containerregistry/issues/890
//
// We can't use the fully qualified tag.Name() because of rules_docker:
// https://github.com/google/go-containerregistry/issues/527
//
// If the tag is "latest", but tag.String() doesn't end in ":latest",
// just append it. Kind of gross, but should work for now.
ts := tag.String()
if tag.Identifier() == name.DefaultTag && !strings.HasSuffix(ts, ":"+name.DefaultTag) {
ts = fmt.Sprintf("%s:%s", ts, name.DefaultTag)
}
imageToTags[img] = append(imageToTags[img], ts)
} else {
if _, ok := imageToTags[img]; !ok {
imageToTags[img] = nil