dep update go-containerregistry

This commit is contained in:
Jon Johnson
2018-06-03 00:59:34 +00:00
parent 3d750de048
commit 8b0a1a7689
107 changed files with 367 additions and 9964 deletions
@@ -21,7 +21,7 @@ import (
"os/exec"
"strings"
"github.com/google/go-containerregistry/name"
"github.com/google/go-containerregistry/pkg/name"
)
// magicNotFoundMessage is the string that the CLI special cases to mean
@@ -72,17 +72,19 @@ func (h *helper) Authorization() (string, error) {
var out bytes.Buffer
cmd.Stdout = &out
if err := h.r.Run(cmd); err != nil {
return "", err
}
output := out.String()
err := h.r.Run(cmd)
// If we see this specific message, it means the domain wasn't found
// and we should fall back on anonymous auth.
output := out.String()
if output == magicNotFoundMessage {
return Anonymous.Authorization()
}
if err != nil {
return "", err
}
// Any other output should be parsed as JSON and the Username / Secret
// fields used for Basic authentication.
ho := helperOutput{}
@@ -24,7 +24,7 @@ import (
"path"
"runtime"
"github.com/google/go-containerregistry/name"
"github.com/google/go-containerregistry/pkg/name"
)
// Keychain is an interface for resolving an image reference to a credential.
@@ -15,7 +15,7 @@
package empty
import (
"github.com/google/go-containerregistry/v1/random"
"github.com/google/go-containerregistry/pkg/v1/random"
)
// Image is a singleton empty image, think: FROM scratch.
@@ -15,7 +15,7 @@
package v1
import (
"github.com/google/go-containerregistry/v1/types"
"github.com/google/go-containerregistry/pkg/v1/types"
)
// Image defines the interface for interacting with an OCI v1 image.
@@ -18,7 +18,7 @@ import (
"encoding/json"
"io"
"github.com/google/go-containerregistry/v1/types"
"github.com/google/go-containerregistry/pkg/v1/types"
)
// Manifest represents the OCI image manifest in a structured way.
@@ -16,6 +16,7 @@ package mutate
import (
"archive/tar"
"bytes"
"encoding/json"
"errors"
"fmt"
@@ -23,9 +24,9 @@ import (
"path/filepath"
"strings"
"github.com/google/go-containerregistry/v1"
"github.com/google/go-containerregistry/v1/partial"
"github.com/google/go-containerregistry/v1/types"
"github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/partial"
"github.com/google/go-containerregistry/pkg/v1/types"
)
const whiteoutPrefix = ".wh."
@@ -110,10 +111,17 @@ func Append(base v1.Image, adds ...Addendum) (v1.Image, error) {
image.configFile.RootFS.DiffIDs = diffIDs
image.configFile.History = history
image.manifest.Layers = manifestLayers
image.manifest.Config.Digest, err = image.ConfigName()
rcfg, err := image.RawConfigFile()
if err != nil {
return nil, err
}
d, sz, err := v1.SHA256(bytes.NewBuffer(rcfg))
if err != nil {
return nil, err
}
image.manifest.Config.Digest = d
image.manifest.Config.Size = sz
return image, nil
}
@@ -136,9 +144,44 @@ func Config(base v1.Image, cfg v1.Config) (v1.Image, error) {
Image: base,
manifest: m.DeepCopy(),
configFile: cf.DeepCopy(),
diffIDMap: make(map[v1.Hash]v1.Layer),
digestMap: make(map[v1.Hash]v1.Layer),
}
rcfg, err := image.RawConfigFile()
if err != nil {
return nil, err
}
d, sz, err := v1.SHA256(bytes.NewBuffer(rcfg))
if err != nil {
return nil, err
}
image.manifest.Config.Digest = d
image.manifest.Config.Size = sz
return image, nil
}
// Created mutates the provided v1.Image to have the provided v1.Time
func CreatedAt(base v1.Image, created v1.Time) (v1.Image, error) {
m, err := base.Manifest()
if err != nil {
return nil, err
}
cf, err := base.ConfigFile()
if err != nil {
return nil, err
}
cfg := cf.DeepCopy()
cfg.Created = created
image := &image{
Image: base,
manifest: m.DeepCopy(),
configFile: cfg,
digestMap: make(map[v1.Hash]v1.Layer),
}
image.manifest.Config.Digest, err = image.ConfigName()
if err != nil {
return nil, err
@@ -17,8 +17,8 @@ package mutate
import (
"fmt"
"github.com/google/go-containerregistry/v1"
"github.com/google/go-containerregistry/v1/empty"
"github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/empty"
)
type RebaseOptions struct {
@@ -17,8 +17,8 @@ package partial
import (
"io"
"github.com/google/go-containerregistry/v1"
"github.com/google/go-containerregistry/v1/v1util"
"github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/v1util"
)
// CompressedLayer represents the bare minimum interface a natively
@@ -50,6 +50,11 @@ func (ule *compressedLayerExtender) Uncompressed() (io.ReadCloser, error) {
// DiffID implements v1.Layer
func (ule *compressedLayerExtender) DiffID() (v1.Hash, error) {
// If our nested CompressedLayer implements DiffID,
// then delegate to it instead.
if wdi, ok := ule.CompressedLayer.(WithDiffID); ok {
return wdi.DiffID()
}
r, err := ule.Uncompressed()
if err != nil {
return v1.Hash{}, err
@@ -15,7 +15,7 @@
package partial
import (
"github.com/google/go-containerregistry/v1/types"
"github.com/google/go-containerregistry/pkg/v1/types"
)
// imageCore is the core set of properties without which we cannot build a v1.Image
@@ -19,9 +19,9 @@ import (
"io"
"sync"
"github.com/google/go-containerregistry/v1"
"github.com/google/go-containerregistry/v1/types"
"github.com/google/go-containerregistry/v1/v1util"
"github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/types"
"github.com/google/go-containerregistry/pkg/v1/v1util"
)
// UncompressedLayer represents the bare minimum interface a natively
@@ -20,8 +20,8 @@ import (
"fmt"
"io"
"github.com/google/go-containerregistry/v1"
"github.com/google/go-containerregistry/v1/v1util"
"github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/v1util"
)
// WithRawConfigFile defines the subset of v1.Image used by these helper methods
@@ -285,3 +285,8 @@ func UncompressedBlob(b WithBlob, h v1.Hash) (io.ReadCloser, error) {
}
return v1util.GunzipReadCloser(rc)
}
// WithDiffID defines the subset of v1.Layer for exposing the DiffID method.
type WithDiffID interface {
DiffID() (v1.Hash, error)
}
@@ -22,10 +22,10 @@ import (
"io"
"time"
"github.com/google/go-containerregistry/v1"
"github.com/google/go-containerregistry/v1/partial"
"github.com/google/go-containerregistry/v1/types"
"github.com/google/go-containerregistry/v1/v1util"
"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"
)
// uncompressedLayer implements partial.UncompressedLayer from raw bytes.
@@ -20,9 +20,9 @@ import (
"net/http"
"net/url"
"github.com/google/go-containerregistry/authn"
"github.com/google/go-containerregistry/name"
"github.com/google/go-containerregistry/v1/remote/transport"
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1/remote/transport"
)
// DeleteOptions are used to expose optional information to guide or
@@ -23,13 +23,13 @@ import (
"net/url"
"sync"
"github.com/google/go-containerregistry/authn"
"github.com/google/go-containerregistry/name"
"github.com/google/go-containerregistry/v1"
"github.com/google/go-containerregistry/v1/partial"
"github.com/google/go-containerregistry/v1/remote/transport"
"github.com/google/go-containerregistry/v1/types"
"github.com/google/go-containerregistry/v1/v1util"
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/partial"
"github.com/google/go-containerregistry/pkg/v1/remote/transport"
"github.com/google/go-containerregistry/pkg/v1/types"
"github.com/google/go-containerregistry/pkg/v1/v1util"
)
// remoteImage accesses an image from a remote registry
@@ -51,10 +51,19 @@ func Image(ref name.Reference, auth authn.Authenticator, t http.RoundTripper) (v
if err != nil {
return nil, err
}
return partial.CompressedToImage(&remoteImage{
img, err := partial.CompressedToImage(&remoteImage{
ref: ref,
client: &http.Client{Transport: tr},
})
if err != nil {
return nil, err
}
// Wrap the v1.Layers returned by this v1.Image in a hint for downstream
// remote.Write calls to facilitate cross-repo "mounting".
return &mountableImage{
Image: img,
Repository: ref.Context(),
}, nil
}
func (r *remoteImage) url(resource, identifier string) url.URL {
@@ -191,6 +200,17 @@ func (rl *remoteLayer) Size() (int64, error) {
return partial.BlobSize(rl, rl.digest)
}
// ConfigFile implements partial.WithManifestAndConfigFile so that we can use partial.BlobToDiffID below.
func (rl *remoteLayer) ConfigFile() (*v1.ConfigFile, error) {
return partial.ConfigFile(rl.ri)
}
// DiffID implements partial.WithDiffID so that we don't recompute a DiffID that we already have
// available in our ConfigFile.
func (rl *remoteLayer) DiffID() (v1.Hash, error) {
return partial.BlobToDiffID(rl, rl.digest)
}
// LayerByDigest implements partial.CompressedLayer
func (r *remoteImage) LayerByDigest(h v1.Hash) (partial.CompressedLayer, error) {
return &remoteLayer{
@@ -20,9 +20,9 @@ import (
"net/http"
"net/url"
"github.com/google/go-containerregistry/authn"
"github.com/google/go-containerregistry/name"
"github.com/google/go-containerregistry/v1/remote/transport"
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1/remote/transport"
)
type Tags struct {
+77
View File
@@ -0,0 +1,77 @@
// Copyright 2018 Google LLC All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package remote
import (
"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1"
)
// MountableLayer wraps a v1.Layer in a shim that enables the layer to be
// "mounted" when published to another registry.
type MountableLayer struct {
v1.Layer
Repository name.Repository
}
// mountableImage wraps the v1.Layer references returned by the embedded v1.Image
// in MountableLayer's so that remote.Write might attempt to mount them from their
// source repository.
type mountableImage struct {
v1.Image
Repository name.Repository
}
// Layers implements v1.Image
func (mi *mountableImage) Layers() ([]v1.Layer, error) {
ls, err := mi.Image.Layers()
if err != nil {
return nil, err
}
mls := make([]v1.Layer, 0, len(ls))
for _, l := range ls {
mls = append(mls, &MountableLayer{
Layer: l,
Repository: mi.Repository,
})
}
return mls, nil
}
// LayerByDigest implements v1.Image
func (mi *mountableImage) LayerByDigest(d v1.Hash) (v1.Layer, error) {
l, err := mi.Image.LayerByDigest(d)
if err != nil {
return nil, err
}
return &MountableLayer{
Layer: l,
Repository: mi.Repository,
}, nil
}
// LayerByDiffID implements v1.Image
func (mi *mountableImage) LayerByDiffID(d v1.Hash) (v1.Layer, error) {
l, err := mi.Image.LayerByDiffID(d)
if err != nil {
return nil, err
}
return &MountableLayer{
Layer: l,
Repository: mi.Repository,
}, nil
}
@@ -17,7 +17,7 @@ package transport
import (
"net/http"
"github.com/google/go-containerregistry/authn"
"github.com/google/go-containerregistry/pkg/authn"
)
type basicTransport struct {
@@ -22,8 +22,8 @@ import (
"net/http"
"net/url"
"github.com/google/go-containerregistry/authn"
"github.com/google/go-containerregistry/name"
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/name"
)
type bearerTransport struct {
@@ -19,15 +19,15 @@ import (
"net/http"
"strings"
"github.com/google/go-containerregistry/name"
"github.com/google/go-containerregistry/pkg/name"
)
type challenge string
const (
anonymous challenge = "Anonymous"
basic challenge = "Basic"
bearer challenge = "Bearer"
anonymous challenge = "anonymous"
basic challenge = "basic"
bearer challenge = "bearer"
)
type pingResp struct {
@@ -38,6 +38,10 @@ type pingResp struct {
parameters map[string]string
}
func (c challenge) Canonical() challenge {
return challenge(strings.ToLower(string(c)))
}
func parseChallenge(suffix string) map[string]string {
kv := make(map[string]string)
for _, token := range strings.Split(suffix, ",") {
@@ -75,13 +79,13 @@ func ping(reg name.Registry, t http.RoundTripper) (*pingResp, error) {
if parts := strings.SplitN(wac, " ", 2); len(parts) == 2 {
// If there are two parts, then parse the challenge parameters.
return &pingResp{
challenge: challenge(strings.Title(parts[0])),
challenge: challenge(parts[0]).Canonical(),
parameters: parseChallenge(parts[1]),
}, nil
}
// Otherwise, just return the challenge without parameters.
return &pingResp{
challenge: challenge(strings.Title(wac)),
challenge: challenge(wac).Canonical(),
}, nil
default:
return nil, fmt.Errorf("unrecognized HTTP status: %v", resp.Status)
@@ -18,7 +18,7 @@ import (
"regexp"
"strings"
"github.com/google/go-containerregistry/name"
"github.com/google/go-containerregistry/pkg/name"
)
// Detect more complex forms of local references.
@@ -18,8 +18,8 @@ import (
"fmt"
"net/http"
"github.com/google/go-containerregistry/authn"
"github.com/google/go-containerregistry/name"
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/name"
)
const (
@@ -49,7 +49,7 @@ func New(reg name.Registry, auth authn.Authenticator, t http.RoundTripper, scope
return nil, err
}
switch pr.challenge {
switch pr.challenge.Canonical() {
case anonymous:
return t, nil
case basic:
@@ -22,17 +22,15 @@ import (
"net/http"
"net/url"
"github.com/google/go-containerregistry/authn"
"github.com/google/go-containerregistry/name"
"github.com/google/go-containerregistry/v1"
"github.com/google/go-containerregistry/v1/remote/transport"
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/remote/transport"
)
// WriteOptions are used to expose optional information to guide or
// control the image write.
type WriteOptions struct {
// The set of paths from which to attempt to mount blobs.
MountPaths []name.Repository
// TODO(mattmoor): Expose "threads" to limit parallelism?
}
@@ -40,9 +38,15 @@ type WriteOptions struct {
func Write(ref name.Reference, img v1.Image, auth authn.Authenticator, t http.RoundTripper,
wo WriteOptions) error {
ls, err := img.Layers()
if err != nil {
return err
}
scopes := []string{ref.Scope(transport.PushScope)}
for _, mp := range wo.MountPaths {
scopes = append(scopes, mp.Scope(transport.PullScope))
for _, l := range ls {
if ml, ok := l.(*MountableLayer); ok {
scopes = append(scopes, ml.Repository.Scope(transport.PullScope))
}
}
tr, err := transport.New(ref.Context().Registry, auth, t, scopes)
@@ -132,16 +136,16 @@ func (w *writer) initiateUpload(h v1.Hash) (location string, mounted bool, err e
uv := url.Values{
"mount": []string{h.String()},
}
var from []string
for _, m := range w.options.MountPaths {
from = append(from, m.RepositoryStr())
l, err := w.img.LayerByDigest(h)
if err != nil {
return "", false, err
}
// We currently avoid HEAD because it's semi-redundant with the mount that is part
// of initiating the blob upload. GCR will perform an existence check on the initiation
// if "mount" is specified, even if no "from" sources are specified. If this turns out
// to not be broadly applicable then we should replace mounts without "from"s with a HEAD.
if len(from) > 0 {
uv["from"] = from
if ml, ok := l.(*MountableLayer); ok {
uv["from"] = []string{ml.Repository.RepositoryStr()}
}
u.RawQuery = uv.Encode()
@@ -286,7 +290,7 @@ func (w *writer) commitImage() error {
}
// The image was successfully pushed!
fmt.Printf("%v: digest: %v size: %d\n", w.ref, digest, len(raw))
log.Printf("%v: digest: %v size: %d", w.ref, digest, len(raw))
return nil
}
@@ -25,11 +25,11 @@ import (
"os"
"sync"
"github.com/google/go-containerregistry/name"
"github.com/google/go-containerregistry/v1"
"github.com/google/go-containerregistry/v1/partial"
"github.com/google/go-containerregistry/v1/types"
"github.com/google/go-containerregistry/v1/v1util"
"github.com/google/go-containerregistry/pkg/name"
"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 {
@@ -298,7 +298,7 @@ type compressedLayerFromTarball struct {
filePath string
}
// DiffID implements partial.CompressedLayer
// Digest implements partial.CompressedLayer
func (clft *compressedLayerFromTarball) Digest() (v1.Hash, error) {
return clft.digest, nil
}
@@ -20,8 +20,8 @@ import (
"io/ioutil"
"os"
"github.com/google/go-containerregistry/v1"
"github.com/google/go-containerregistry/v1/v1util"
"github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/v1util"
)
type layer struct {
@@ -22,8 +22,8 @@ import (
"io"
"os"
"github.com/google/go-containerregistry/name"
"github.com/google/go-containerregistry/v1"
"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1"
)
// WriteOptions are used to expose optional information to guide or
@@ -20,7 +20,7 @@ import (
"hash"
"io"
"github.com/google/go-containerregistry/v1"
"github.com/google/go-containerregistry/pkg/v1"
)
type verifyReader struct {
@@ -24,14 +24,23 @@ var gzipMagicHeader = []byte{'\x1f', '\x8b'}
// GzipReadCloser reads uncompressed input data from the io.ReadCloser and
// returns an io.ReadCloser from which compressed data may be read.
// This uses gzip.BestSpeed for the compression level.
func GzipReadCloser(r io.ReadCloser) (io.ReadCloser, error) {
return GzipReadCloserLevel(r, gzip.BestSpeed)
}
// GzipReadCloserLevel reads uncompressed input data from the io.ReadCloser and
// returns an io.ReadCloser from which compressed data may be read.
// Refer to compress/gzip for the level:
// https://golang.org/pkg/compress/gzip/#pkg-constants
func GzipReadCloserLevel(r io.ReadCloser, level int) (io.ReadCloser, error) {
pr, pw := io.Pipe()
go func() {
defer pw.Close()
defer r.Close()
gw, _ := gzip.NewWriterLevel(pw, gzip.BestCompression)
gw, _ := gzip.NewWriterLevel(pw, level)
defer gw.Close()
_, err := io.Copy(gw, r)