summaryrefslogtreecommitdiff
path: root/vendor
diff options
context:
space:
mode:
Diffstat (limited to 'vendor')
-rw-r--r--vendor/github.com/containers/image/copy/copy.go3
-rw-r--r--vendor/github.com/containers/image/directory/directory_dest.go7
-rw-r--r--vendor/github.com/containers/image/docker/docker_client.go8
-rw-r--r--vendor/github.com/containers/image/docker/docker_image_dest.go7
-rw-r--r--vendor/github.com/containers/image/docker/tarfile/dest.go7
-rw-r--r--vendor/github.com/containers/image/oci/archive/oci_dest.go7
-rw-r--r--vendor/github.com/containers/image/oci/layout/oci_dest.go7
-rw-r--r--vendor/github.com/containers/image/oci/layout/oci_transport.go12
-rw-r--r--vendor/github.com/containers/image/openshift/openshift.go7
-rw-r--r--vendor/github.com/containers/image/ostree/ostree_dest.go11
-rw-r--r--vendor/github.com/containers/image/storage/storage_image.go26
-rw-r--r--vendor/github.com/containers/image/storage/storage_reference.go139
-rw-r--r--vendor/github.com/containers/image/storage/storage_transport.go190
-rw-r--r--vendor/github.com/containers/image/types/types.go5
-rw-r--r--vendor/github.com/containers/image/vendor.conf2
15 files changed, 213 insertions, 225 deletions
diff --git a/vendor/github.com/containers/image/copy/copy.go b/vendor/github.com/containers/image/copy/copy.go
index 65c3853be..6714a91f2 100644
--- a/vendor/github.com/containers/image/copy/copy.go
+++ b/vendor/github.com/containers/image/copy/copy.go
@@ -347,6 +347,9 @@ func checkImageDestinationForCurrentRuntimeOS(ctx context.Context, sys *types.Sy
// updateEmbeddedDockerReference handles the Docker reference embedded in Docker schema1 manifests.
func (ic *imageCopier) updateEmbeddedDockerReference() error {
+ if ic.c.dest.IgnoresEmbeddedDockerReference() {
+ return nil // Destination would prefer us not to update the embedded reference.
+ }
destRef := ic.c.dest.Reference().DockerReference()
if destRef == nil {
return nil // Destination does not care about Docker references
diff --git a/vendor/github.com/containers/image/directory/directory_dest.go b/vendor/github.com/containers/image/directory/directory_dest.go
index a38d7d5cf..d888931fe 100644
--- a/vendor/github.com/containers/image/directory/directory_dest.go
+++ b/vendor/github.com/containers/image/directory/directory_dest.go
@@ -117,6 +117,13 @@ func (d *dirImageDestination) MustMatchRuntimeOS() bool {
return false
}
+// IgnoresEmbeddedDockerReference returns true iff the destination does not care about Image.EmbeddedDockerReferenceConflicts(),
+// and would prefer to receive an unmodified manifest instead of one modified for the destination.
+// Does not make a difference if Reference().DockerReference() is nil.
+func (d *dirImageDestination) IgnoresEmbeddedDockerReference() bool {
+ return false // N/A, DockerReference() returns nil.
+}
+
// PutBlob writes contents of stream and returns data representing the result (with all data filled in).
// inputInfo.Digest can be optionally provided if known; it is not mandatory for the implementation to verify it.
// inputInfo.Size is the expected length of stream, if known.
diff --git a/vendor/github.com/containers/image/docker/docker_client.go b/vendor/github.com/containers/image/docker/docker_client.go
index 4a1d42149..0a6dd9b80 100644
--- a/vendor/github.com/containers/image/docker/docker_client.go
+++ b/vendor/github.com/containers/image/docker/docker_client.go
@@ -280,13 +280,19 @@ func SearchRegistry(ctx context.Context, sys *types.SystemContext, registry, ima
v2Res := &V2Results{}
v1Res := &V1Results{}
+ // Get credentials from authfile for the underlying hostname
+ username, password, err := config.GetAuthentication(sys, registry)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error getting username and password")
+ }
+
// The /v2/_catalog endpoint has been disabled for docker.io therefore the call made to that endpoint will fail
// So using the v1 hostname for docker.io for simplicity of implementation and the fact that it returns search results
if registry == dockerHostname {
registry = dockerV1Hostname
}
- client, err := newDockerClientWithDetails(sys, registry, "", "", "", nil, "")
+ client, err := newDockerClientWithDetails(sys, registry, username, password, "", nil, "")
if err != nil {
return nil, errors.Wrapf(err, "error creating new docker client")
}
diff --git a/vendor/github.com/containers/image/docker/docker_image_dest.go b/vendor/github.com/containers/image/docker/docker_image_dest.go
index 782a048ce..85d568995 100644
--- a/vendor/github.com/containers/image/docker/docker_image_dest.go
+++ b/vendor/github.com/containers/image/docker/docker_image_dest.go
@@ -95,6 +95,13 @@ func (d *dockerImageDestination) MustMatchRuntimeOS() bool {
return false
}
+// IgnoresEmbeddedDockerReference returns true iff the destination does not care about Image.EmbeddedDockerReferenceConflicts(),
+// and would prefer to receive an unmodified manifest instead of one modified for the destination.
+// Does not make a difference if Reference().DockerReference() is nil.
+func (d *dockerImageDestination) IgnoresEmbeddedDockerReference() bool {
+ return false // We do want the manifest updated; older registry versions refuse manifests if the embedded reference does not match.
+}
+
// sizeCounter is an io.Writer which only counts the total size of its input.
type sizeCounter struct{ size int64 }
diff --git a/vendor/github.com/containers/image/docker/tarfile/dest.go b/vendor/github.com/containers/image/docker/tarfile/dest.go
index b6791af95..d6510ccf1 100644
--- a/vendor/github.com/containers/image/docker/tarfile/dest.go
+++ b/vendor/github.com/containers/image/docker/tarfile/dest.go
@@ -75,6 +75,13 @@ func (d *Destination) MustMatchRuntimeOS() bool {
return false
}
+// IgnoresEmbeddedDockerReference returns true iff the destination does not care about Image.EmbeddedDockerReferenceConflicts(),
+// and would prefer to receive an unmodified manifest instead of one modified for the destination.
+// Does not make a difference if Reference().DockerReference() is nil.
+func (d *Destination) IgnoresEmbeddedDockerReference() bool {
+ return false // N/A, we only accept schema2 images where EmbeddedDockerReferenceConflicts() is always false.
+}
+
// PutBlob writes contents of stream and returns data representing the result (with all data filled in).
// inputInfo.Digest can be optionally provided if known; it is not mandatory for the implementation to verify it.
// inputInfo.Size is the expected length of stream, if known.
diff --git a/vendor/github.com/containers/image/oci/archive/oci_dest.go b/vendor/github.com/containers/image/oci/archive/oci_dest.go
index 432b310b4..93f3f80f9 100644
--- a/vendor/github.com/containers/image/oci/archive/oci_dest.go
+++ b/vendor/github.com/containers/image/oci/archive/oci_dest.go
@@ -70,6 +70,13 @@ func (d *ociArchiveImageDestination) MustMatchRuntimeOS() bool {
return d.unpackedDest.MustMatchRuntimeOS()
}
+// IgnoresEmbeddedDockerReference returns true iff the destination does not care about Image.EmbeddedDockerReferenceConflicts(),
+// and would prefer to receive an unmodified manifest instead of one modified for the destination.
+// Does not make a difference if Reference().DockerReference() is nil.
+func (d *ociArchiveImageDestination) IgnoresEmbeddedDockerReference() bool {
+ return d.unpackedDest.IgnoresEmbeddedDockerReference()
+}
+
// PutBlob writes contents of stream and returns data representing the result (with all data filled in).
// inputInfo.Digest can be optionally provided if known; it is not mandatory for the implementation to verify it.
// inputInfo.Size is the expected length of stream, if known.
diff --git a/vendor/github.com/containers/image/oci/layout/oci_dest.go b/vendor/github.com/containers/image/oci/layout/oci_dest.go
index a1e27b5d5..0a0cad15e 100644
--- a/vendor/github.com/containers/image/oci/layout/oci_dest.go
+++ b/vendor/github.com/containers/image/oci/layout/oci_dest.go
@@ -95,6 +95,13 @@ func (d *ociImageDestination) MustMatchRuntimeOS() bool {
return false
}
+// IgnoresEmbeddedDockerReference returns true iff the destination does not care about Image.EmbeddedDockerReferenceConflicts(),
+// and would prefer to receive an unmodified manifest instead of one modified for the destination.
+// Does not make a difference if Reference().DockerReference() is nil.
+func (d *ociImageDestination) IgnoresEmbeddedDockerReference() bool {
+ return false // N/A, DockerReference() returns nil.
+}
+
// PutBlob writes contents of stream and returns data representing the result (with all data filled in).
// inputInfo.Digest can be optionally provided if known; it is not mandatory for the implementation to verify it.
// inputInfo.Size is the expected length of stream, if known.
diff --git a/vendor/github.com/containers/image/oci/layout/oci_transport.go b/vendor/github.com/containers/image/oci/layout/oci_transport.go
index 857c80818..4e5cecff2 100644
--- a/vendor/github.com/containers/image/oci/layout/oci_transport.go
+++ b/vendor/github.com/containers/image/oci/layout/oci_transport.go
@@ -23,8 +23,14 @@ func init() {
transports.Register(Transport)
}
-// Transport is an ImageTransport for OCI directories.
-var Transport = ociTransport{}
+var (
+ // Transport is an ImageTransport for OCI directories.
+ Transport = ociTransport{}
+
+ // ErrMoreThanOneImage is an error returned when the manifest includes
+ // more than one image and the user should choose which one to use.
+ ErrMoreThanOneImage = errors.New("more than one image in oci, choose an image")
+)
type ociTransport struct{}
@@ -184,7 +190,7 @@ func (ref ociReference) getManifestDescriptor() (imgspecv1.Descriptor, error) {
d = &index.Manifests[0]
} else {
// ask user to choose image when more than one image in the oci directory
- return imgspecv1.Descriptor{}, errors.Wrapf(err, "more than one image in oci, choose an image")
+ return imgspecv1.Descriptor{}, ErrMoreThanOneImage
}
} else {
// if image specified, look through all manifests for a match
diff --git a/vendor/github.com/containers/image/openshift/openshift.go b/vendor/github.com/containers/image/openshift/openshift.go
index 3504d8ce1..2cadb0ce2 100644
--- a/vendor/github.com/containers/image/openshift/openshift.go
+++ b/vendor/github.com/containers/image/openshift/openshift.go
@@ -369,6 +369,13 @@ func (d *openshiftImageDestination) MustMatchRuntimeOS() bool {
return false
}
+// IgnoresEmbeddedDockerReference returns true iff the destination does not care about Image.EmbeddedDockerReferenceConflicts(),
+// and would prefer to receive an unmodified manifest instead of one modified for the destination.
+// Does not make a difference if Reference().DockerReference() is nil.
+func (d *openshiftImageDestination) IgnoresEmbeddedDockerReference() bool {
+ return d.docker.IgnoresEmbeddedDockerReference()
+}
+
// PutBlob writes contents of stream and returns data representing the result (with all data filled in).
// inputInfo.Digest can be optionally provided if known; it is not mandatory for the implementation to verify it.
// inputInfo.Size is the expected length of stream, if known.
diff --git a/vendor/github.com/containers/image/ostree/ostree_dest.go b/vendor/github.com/containers/image/ostree/ostree_dest.go
index 2e0d7fcff..0ae30f1f4 100644
--- a/vendor/github.com/containers/image/ostree/ostree_dest.go
+++ b/vendor/github.com/containers/image/ostree/ostree_dest.go
@@ -14,6 +14,7 @@ import (
"os"
"os/exec"
"path/filepath"
+ "runtime"
"strconv"
"strings"
"syscall"
@@ -124,6 +125,13 @@ func (d *ostreeImageDestination) MustMatchRuntimeOS() bool {
return true
}
+// IgnoresEmbeddedDockerReference returns true iff the destination does not care about Image.EmbeddedDockerReferenceConflicts(),
+// and would prefer to receive an unmodified manifest instead of one modified for the destination.
+// Does not make a difference if Reference().DockerReference() is nil.
+func (d *ostreeImageDestination) IgnoresEmbeddedDockerReference() bool {
+ return false // N/A, DockerReference() returns nil.
+}
+
func (d *ostreeImageDestination) PutBlob(ctx context.Context, stream io.Reader, inputInfo types.BlobInfo, isConfig bool) (types.BlobInfo, error) {
tmpDir, err := ioutil.TempDir(d.tmpDirPath, "blob")
if err != nil {
@@ -394,6 +402,9 @@ func (d *ostreeImageDestination) PutSignatures(ctx context.Context, signatures [
}
func (d *ostreeImageDestination) Commit(ctx context.Context) error {
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
repo, err := otbuiltin.OpenRepo(d.ref.repo)
if err != nil {
return err
diff --git a/vendor/github.com/containers/image/storage/storage_image.go b/vendor/github.com/containers/image/storage/storage_image.go
index b43caf1a0..a6da88e71 100644
--- a/vendor/github.com/containers/image/storage/storage_image.go
+++ b/vendor/github.com/containers/image/storage/storage_image.go
@@ -50,8 +50,7 @@ type storageImageSource struct {
}
type storageImageDestination struct {
- imageRef storageReference // The reference we'll use to name the image
- publicRef storageReference // The reference we return when asked about the name we'll give to the image
+ imageRef storageReference
directory string // Temporary directory where we store blobs until Commit() time
nextTempFileID int32 // A counter that we use for computing filenames to assign to blobs
manifest []byte // Manifest contents, temporary
@@ -243,15 +242,8 @@ func newImageDestination(imageRef storageReference) (*storageImageDestination, e
if err != nil {
return nil, errors.Wrapf(err, "error creating a temporary directory")
}
- // Break reading of the reference we're writing, so that copy.Image() won't try to rewrite
- // schema1 image manifests to remove embedded references, since that changes the manifest's
- // digest, and that makes the image unusable if we subsequently try to access it using a
- // reference that mentions the no-longer-correct digest.
- publicRef := imageRef
- publicRef.name = nil
image := &storageImageDestination{
imageRef: imageRef,
- publicRef: publicRef,
directory: directory,
blobDiffIDs: make(map[digest.Digest]digest.Digest),
fileSizes: make(map[digest.Digest]int64),
@@ -261,11 +253,10 @@ func newImageDestination(imageRef storageReference) (*storageImageDestination, e
return image, nil
}
-// Reference returns a mostly-usable image reference that can't return a DockerReference, to
-// avoid triggering logic in copy.Image() that rewrites schema 1 image manifests in order to
-// remove image names that they contain which don't match the value we're using.
+// Reference returns the reference used to set up this destination. Note that this should directly correspond to user's intent,
+// e.g. it should use the public hostname instead of the result of resolving CNAMEs or following redirects.
func (s storageImageDestination) Reference() types.ImageReference {
- return s.publicRef
+ return s.imageRef
}
// Close cleans up the temporary directory.
@@ -613,7 +604,7 @@ func (s *storageImageDestination) Commit(ctx context.Context) error {
if name := s.imageRef.DockerReference(); len(oldNames) > 0 || name != nil {
names := []string{}
if name != nil {
- names = append(names, verboseName(name))
+ names = append(names, name.String())
}
if len(oldNames) > 0 {
names = append(names, oldNames...)
@@ -703,6 +694,13 @@ func (s *storageImageDestination) MustMatchRuntimeOS() bool {
return true
}
+// IgnoresEmbeddedDockerReference returns true iff the destination does not care about Image.EmbeddedDockerReferenceConflicts(),
+// and would prefer to receive an unmodified manifest instead of one modified for the destination.
+// Does not make a difference if Reference().DockerReference() is nil.
+func (s *storageImageDestination) IgnoresEmbeddedDockerReference() bool {
+ return true // Yes, we want the unmodified manifest
+}
+
// PutSignatures records the image's signatures for committing as a single data blob.
func (s *storageImageDestination) PutSignatures(ctx context.Context, signatures [][]byte) error {
sizes := []int{}
diff --git a/vendor/github.com/containers/image/storage/storage_reference.go b/vendor/github.com/containers/image/storage/storage_reference.go
index 532716941..73306b972 100644
--- a/vendor/github.com/containers/image/storage/storage_reference.go
+++ b/vendor/github.com/containers/image/storage/storage_reference.go
@@ -9,7 +9,6 @@ import (
"github.com/containers/image/docker/reference"
"github.com/containers/image/types"
"github.com/containers/storage"
- digest "github.com/opencontainers/go-digest"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -17,55 +16,65 @@ import (
// A storageReference holds an arbitrary name and/or an ID, which is a 32-byte
// value hex-encoded into a 64-character string, and a reference to a Store
// where an image is, or would be, kept.
+// Either "named" or "id" must be set.
type storageReference struct {
transport storageTransport
- reference string
+ named reference.Named // may include a tag and/or a digest
id string
- name reference.Named
- tag string
- digest digest.Digest
}
-func newReference(transport storageTransport, reference, id string, name reference.Named, tag string, digest digest.Digest) *storageReference {
+func newReference(transport storageTransport, named reference.Named, id string) (*storageReference, error) {
+ if named == nil && id == "" {
+ return nil, ErrInvalidReference
+ }
// We take a copy of the transport, which contains a pointer to the
// store that it used for resolving this reference, so that the
// transport that we'll return from Transport() won't be affected by
// further calls to the original transport's SetStore() method.
return &storageReference{
transport: transport,
- reference: reference,
+ named: named,
id: id,
- name: name,
- tag: tag,
- digest: digest,
+ }, nil
+}
+
+// imageMatchesRepo returns true iff image.Names contains an element with the same repo as ref
+func imageMatchesRepo(image *storage.Image, ref reference.Named) bool {
+ repo := ref.Name()
+ for _, name := range image.Names {
+ if named, err := reference.ParseNormalizedNamed(name); err == nil {
+ if named.Name() == repo {
+ return true
+ }
+ }
}
+ return false
}
// Resolve the reference's name to an image ID in the store, if there's already
// one present with the same name or ID, and return the image.
func (s *storageReference) resolveImage() (*storage.Image, error) {
+ var loadedImage *storage.Image
if s.id == "" {
// Look for an image that has the expanded reference name as an explicit Name value.
- image, err := s.transport.store.Image(s.reference)
+ image, err := s.transport.store.Image(s.named.String())
if image != nil && err == nil {
+ loadedImage = image
s.id = image.ID
}
}
- if s.id == "" && s.name != nil && s.digest != "" {
- // Look for an image with the specified digest that has the same name,
- // though possibly with a different tag or digest, as a Name value, so
- // that the canonical reference can be implicitly resolved to the image.
- images, err := s.transport.store.ImagesByDigest(s.digest)
- if images != nil && err == nil {
- repo := reference.FamiliarName(reference.TrimNamed(s.name))
- search:
- for _, image := range images {
- for _, name := range image.Names {
- if named, err := reference.ParseNormalizedNamed(name); err == nil {
- if reference.FamiliarName(reference.TrimNamed(named)) == repo {
- s.id = image.ID
- break search
- }
+ if s.id == "" && s.named != nil {
+ if digested, ok := s.named.(reference.Digested); ok {
+ // Look for an image with the specified digest that has the same name,
+ // though possibly with a different tag or digest, as a Name value, so
+ // that the canonical reference can be implicitly resolved to the image.
+ images, err := s.transport.store.ImagesByDigest(digested.Digest())
+ if images != nil && err == nil {
+ for _, image := range images {
+ if imageMatchesRepo(image, s.named) {
+ loadedImage = image
+ s.id = image.ID
+ break
}
}
}
@@ -75,27 +84,20 @@ func (s *storageReference) resolveImage() (*storage.Image, error) {
logrus.Debugf("reference %q does not resolve to an image ID", s.StringWithinTransport())
return nil, errors.Wrapf(ErrNoSuchImage, "reference %q does not resolve to an image ID", s.StringWithinTransport())
}
- img, err := s.transport.store.Image(s.id)
- if err != nil {
- return nil, errors.Wrapf(err, "error reading image %q", s.id)
- }
- if s.name != nil {
- repo := reference.FamiliarName(reference.TrimNamed(s.name))
- nameMatch := false
- for _, name := range img.Names {
- if named, err := reference.ParseNormalizedNamed(name); err == nil {
- if reference.FamiliarName(reference.TrimNamed(named)) == repo {
- nameMatch = true
- break
- }
- }
+ if loadedImage == nil {
+ img, err := s.transport.store.Image(s.id)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error reading image %q", s.id)
}
- if !nameMatch {
+ loadedImage = img
+ }
+ if s.named != nil {
+ if !imageMatchesRepo(loadedImage, s.named) {
logrus.Errorf("no image matching reference %q found", s.StringWithinTransport())
return nil, ErrNoSuchImage
}
}
- return img, nil
+ return loadedImage, nil
}
// Return a Transport object that defaults to using the same store that we used
@@ -110,20 +112,7 @@ func (s storageReference) Transport() types.ImageTransport {
// Return a name with a tag or digest, if we have either, else return it bare.
func (s storageReference) DockerReference() reference.Named {
- if s.name == nil {
- return nil
- }
- if s.tag != "" {
- if namedTagged, err := reference.WithTag(s.name, s.tag); err == nil {
- return namedTagged
- }
- }
- if s.digest != "" {
- if canonical, err := reference.WithDigest(s.name, s.digest); err == nil {
- return canonical
- }
- }
- return s.name
+ return s.named
}
// Return a name with a tag, prefixed with the graph root and driver name, to
@@ -135,25 +124,25 @@ func (s storageReference) StringWithinTransport() string {
if len(options) > 0 {
optionsList = ":" + strings.Join(options, ",")
}
- storeSpec := "[" + s.transport.store.GraphDriverName() + "@" + s.transport.store.GraphRoot() + "+" + s.transport.store.RunRoot() + optionsList + "]"
- if s.reference == "" {
- return storeSpec + "@" + s.id
+ res := "[" + s.transport.store.GraphDriverName() + "@" + s.transport.store.GraphRoot() + "+" + s.transport.store.RunRoot() + optionsList + "]"
+ if s.named != nil {
+ res = res + s.named.String()
}
- if s.id == "" {
- return storeSpec + s.reference
+ if s.id != "" {
+ res = res + "@" + s.id
}
- return storeSpec + s.reference + "@" + s.id
+ return res
}
func (s storageReference) PolicyConfigurationIdentity() string {
- storeSpec := "[" + s.transport.store.GraphDriverName() + "@" + s.transport.store.GraphRoot() + "]"
- if s.name == nil {
- return storeSpec + "@" + s.id
+ res := "[" + s.transport.store.GraphDriverName() + "@" + s.transport.store.GraphRoot() + "]"
+ if s.named != nil {
+ res = res + s.named.String()
}
- if s.id == "" {
- return storeSpec + s.reference
+ if s.id != "" {
+ res = res + "@" + s.id
}
- return storeSpec + s.reference + "@" + s.id
+ return res
}
// Also accept policy that's tied to the combination of the graph root and
@@ -164,9 +153,17 @@ func (s storageReference) PolicyConfigurationNamespaces() []string {
storeSpec := "[" + s.transport.store.GraphDriverName() + "@" + s.transport.store.GraphRoot() + "]"
driverlessStoreSpec := "[" + s.transport.store.GraphRoot() + "]"
namespaces := []string{}
- if s.name != nil {
- name := reference.TrimNamed(s.name)
- components := strings.Split(name.String(), "/")
+ if s.named != nil {
+ if s.id != "" {
+ // The reference without the ID is also a valid namespace.
+ namespaces = append(namespaces, storeSpec+s.named.String())
+ }
+ tagged, isTagged := s.named.(reference.Tagged)
+ _, isDigested := s.named.(reference.Digested)
+ if isTagged && isDigested { // s.named is "name:tag@digest"; add a "name:tag" parent namespace.
+ namespaces = append(namespaces, storeSpec+s.named.Name()+":"+tagged.Tag())
+ }
+ components := strings.Split(s.named.Name(), "/")
for len(components) > 0 {
namespaces = append(namespaces, storeSpec+strings.Join(components, "/"))
components = components[:len(components)-1]
diff --git a/vendor/github.com/containers/image/storage/storage_transport.go b/vendor/github.com/containers/image/storage/storage_transport.go
index f6ebcdc4a..8886f9250 100644
--- a/vendor/github.com/containers/image/storage/storage_transport.go
+++ b/vendor/github.com/containers/image/storage/storage_transport.go
@@ -3,6 +3,7 @@
package storage
import (
+ "fmt"
"path/filepath"
"strings"
@@ -105,7 +106,6 @@ func (s *storageTransport) DefaultGIDMap() []idtools.IDMap {
// ParseStoreReference takes a name or an ID, tries to figure out which it is
// relative to the given store, and returns it in a reference object.
func (s storageTransport) ParseStoreReference(store storage.Store, ref string) (*storageReference, error) {
- var name reference.Named
if ref == "" {
return nil, errors.Wrapf(ErrInvalidReference, "%q is an empty reference")
}
@@ -118,66 +118,36 @@ func (s storageTransport) ParseStoreReference(store storage.Store, ref string) (
ref = ref[closeIndex+1:]
}
- // The last segment, if there's more than one, is either a digest from a reference, or an image ID.
+ // The reference may end with an image ID. Image IDs and digests use the same "@" separator;
+ // here we only peel away an image ID, and leave digests alone.
split := strings.LastIndex(ref, "@")
- idOrDigest := ""
- if split != -1 {
- // Peel off that last bit so that we can work on the rest.
- idOrDigest = ref[split+1:]
- if idOrDigest == "" {
- return nil, errors.Wrapf(ErrInvalidReference, "%q does not look like a digest or image ID", idOrDigest)
- }
- ref = ref[:split]
- }
-
- // The middle segment (now the last segment), if there is one, is a digest.
- split = strings.LastIndex(ref, "@")
- sum := digest.Digest("")
- if split != -1 {
- sum = digest.Digest(ref[split+1:])
- if sum == "" {
- return nil, errors.Wrapf(ErrInvalidReference, "%q does not look like an image digest", sum)
- }
- ref = ref[:split]
- }
-
- // If we have something that unambiguously should be a digest, validate it, and then the third part,
- // if we have one, as an ID.
id := ""
- if sum != "" {
- if idSum, err := digest.Parse("sha256:" + idOrDigest); err != nil || idSum.Validate() != nil {
- return nil, errors.Wrapf(ErrInvalidReference, "%q does not look like an image ID", idOrDigest)
- }
- if err := sum.Validate(); err != nil {
- return nil, errors.Wrapf(ErrInvalidReference, "%q does not look like an image digest", sum)
- }
- id = idOrDigest
- if img, err := store.Image(idOrDigest); err == nil && img != nil && len(idOrDigest) >= minimumTruncatedIDLength && strings.HasPrefix(img.ID, idOrDigest) {
- // The ID is a truncated version of the ID of an image that's present in local storage,
- // so we might as well use the expanded value.
- id = img.ID
+ if split != -1 {
+ possibleID := ref[split+1:]
+ if possibleID == "" {
+ return nil, errors.Wrapf(ErrInvalidReference, "empty trailing digest or ID in %q", ref)
}
- } else if idOrDigest != "" {
- // There was no middle portion, so the final portion could be either a digest or an ID.
- if idSum, err := digest.Parse("sha256:" + idOrDigest); err == nil && idSum.Validate() == nil {
- // It's an ID.
- id = idOrDigest
- } else if idSum, err := digest.Parse(idOrDigest); err == nil && idSum.Validate() == nil {
- // It's a digest.
- sum = idSum
- } else if img, err := store.Image(idOrDigest); err == nil && img != nil && len(idOrDigest) >= minimumTruncatedIDLength && strings.HasPrefix(img.ID, idOrDigest) {
- // It's a truncated version of the ID of an image that's present in local storage,
- // and we may need the expanded value.
- id = img.ID
- } else {
- return nil, errors.Wrapf(ErrInvalidReference, "%q does not look like a digest or image ID", idOrDigest)
+ // If it looks like a digest, leave it alone for now.
+ if _, err := digest.Parse(possibleID); err != nil {
+ // Otherwise…
+ if idSum, err := digest.Parse("sha256:" + possibleID); err == nil && idSum.Validate() == nil {
+ id = possibleID // … it is a full ID
+ } else if img, err := store.Image(possibleID); err == nil && img != nil && len(possibleID) >= minimumTruncatedIDLength && strings.HasPrefix(img.ID, possibleID) {
+ // … it is a truncated version of the ID of an image that's present in local storage,
+ // so we might as well use the expanded value.
+ id = img.ID
+ } else {
+ return nil, errors.Wrapf(ErrInvalidReference, "%q does not look like an image ID or digest", possibleID)
+ }
+ // We have recognized an image ID; peel it off.
+ ref = ref[:split]
}
}
- // If we only had one portion, then _maybe_ it's a truncated image ID. Only check on that if it's
+ // If we only have one @-delimited portion, then _maybe_ it's a truncated image ID. Only check on that if it's
// at least of what we guess is a reasonable minimum length, because we don't want a really short value
// like "a" matching an image by ID prefix when the input was actually meant to specify an image name.
- if len(ref) >= minimumTruncatedIDLength && sum == "" && id == "" {
+ if id == "" && len(ref) >= minimumTruncatedIDLength && !strings.ContainsAny(ref, "@:") {
if img, err := store.Image(ref); err == nil && img != nil && strings.HasPrefix(img.ID, ref) {
// It's a truncated version of the ID of an image that's present in local storage;
// we need to expand it.
@@ -186,53 +156,24 @@ func (s storageTransport) ParseStoreReference(store storage.Store, ref string) (
}
}
- // The initial portion is probably a name, possibly with a tag.
+ var named reference.Named
+ // Unless we have an un-named "ID" or "@ID" reference (where ID might only have been a prefix), which has been
+ // completely parsed above, the initial portion should be a name, possibly with a tag and/or a digest..
if ref != "" {
var err error
- if name, err = reference.ParseNormalizedNamed(ref); err != nil {
+ named, err = reference.ParseNormalizedNamed(ref)
+ if err != nil {
return nil, errors.Wrapf(err, "error parsing named reference %q", ref)
}
- }
- if name == nil && sum == "" && id == "" {
- return nil, errors.Errorf("error parsing reference")
+ named = reference.TagNameOnly(named)
}
- // Construct a copy of the store spec.
- optionsList := ""
- options := store.GraphOptions()
- if len(options) > 0 {
- optionsList = ":" + strings.Join(options, ",")
- }
- storeSpec := "[" + store.GraphDriverName() + "@" + store.GraphRoot() + "+" + store.RunRoot() + optionsList + "]"
-
- // Convert the name back into a reference string, if we got a name.
- refname := ""
- tag := ""
- if name != nil {
- if sum.Validate() == nil {
- canonical, err := reference.WithDigest(name, sum)
- if err != nil {
- return nil, errors.Wrapf(err, "error mixing name %q with digest %q", name, sum)
- }
- refname = verboseName(canonical)
- } else {
- name = reference.TagNameOnly(name)
- tagged, ok := name.(reference.Tagged)
- if !ok {
- return nil, errors.Errorf("error parsing possibly-tagless name %q", ref)
- }
- refname = verboseName(name)
- tag = tagged.Tag()
- }
- }
- if refname == "" {
- logrus.Debugf("parsed reference to id into %q", storeSpec+"@"+id)
- } else if id == "" {
- logrus.Debugf("parsed reference to refname into %q", storeSpec+refname)
- } else {
- logrus.Debugf("parsed reference to refname@id into %q", storeSpec+refname+"@"+id)
+ result, err := newReference(storageTransport{store: store, defaultUIDMap: s.defaultUIDMap, defaultGIDMap: s.defaultGIDMap}, named, id)
+ if err != nil {
+ return nil, err
}
- return newReference(storageTransport{store: store, defaultUIDMap: s.defaultUIDMap, defaultGIDMap: s.defaultGIDMap}, refname, id, name, tag, sum), nil
+ logrus.Debugf("parsed reference into %q", result.StringWithinTransport())
+ return result, nil
}
func (s *storageTransport) GetStore() (storage.Store, error) {
@@ -252,7 +193,7 @@ func (s *storageTransport) GetStore() (storage.Store, error) {
}
// ParseReference takes a name and a tag or digest and/or ID
-// ("_name_"/"@_id_"/"_name_:_tag_"/"_name_:_tag_@_id_"/"_name_@_digest_"/"_name_@_digest_@_id_"),
+// ("_name_"/"@_id_"/"_name_:_tag_"/"_name_:_tag_@_id_"/"_name_@_digest_"/"_name_@_digest_@_id_"/"_name_:_tag_@_digest_"/"_name_:_tag_@_digest_@_id_"),
// possibly prefixed with a store specifier in the form "[_graphroot_]" or
// "[_driver_@_graphroot_]" or "[_driver_@_graphroot_+_runroot_]" or
// "[_driver_@_graphroot_:_options_]" or "[_driver_@_graphroot_+_runroot_:_options_]",
@@ -338,7 +279,7 @@ func (s *storageTransport) ParseReference(reference string) (types.ImageReferenc
func (s storageTransport) GetStoreImage(store storage.Store, ref types.ImageReference) (*storage.Image, error) {
dref := ref.DockerReference()
if dref != nil {
- if img, err := store.Image(verboseName(dref)); err == nil {
+ if img, err := store.Image(dref.String()); err == nil {
return img, nil
}
}
@@ -399,52 +340,29 @@ func (s storageTransport) ValidatePolicyConfigurationScope(scope string) error {
if scope == "" {
return nil
}
- // But if there is anything left, it has to be a name, with or without
- // a tag, with or without an ID, since we don't return namespace values
- // that are just bare IDs.
- scopeInfo := strings.SplitN(scope, "@", 2)
- if len(scopeInfo) == 1 && scopeInfo[0] != "" {
- _, err := reference.ParseNormalizedNamed(scopeInfo[0])
- if err != nil {
- return err
+
+ fields := strings.SplitN(scope, "@", 3)
+ switch len(fields) {
+ case 1: // name only
+ case 2: // name:tag@ID or name[:tag]@digest
+ if _, idErr := digest.Parse("sha256:" + fields[1]); idErr != nil {
+ if _, digestErr := digest.Parse(fields[1]); digestErr != nil {
+ return fmt.Errorf("%v is neither a valid digest(%s) nor a valid ID(%s)", fields[1], digestErr.Error(), idErr.Error())
+ }
}
- } else if len(scopeInfo) == 2 && scopeInfo[0] != "" && scopeInfo[1] != "" {
- _, err := reference.ParseNormalizedNamed(scopeInfo[0])
- if err != nil {
+ case 3: // name[:tag]@digest@ID
+ if _, err := digest.Parse(fields[1]); err != nil {
return err
}
- _, err = digest.Parse("sha256:" + scopeInfo[1])
- if err != nil {
+ if _, err := digest.Parse("sha256:" + fields[2]); err != nil {
return err
}
- } else {
- return ErrInvalidReference
+ default: // Coverage: This should never happen
+ return errors.New("Internal error: unexpected number of fields form strings.SplitN")
}
+ // As for field[0], if it is non-empty at all:
+ // FIXME? We could be verifying the various character set and length restrictions
+ // from docker/distribution/reference.regexp.go, but other than that there
+ // are few semantically invalid strings.
return nil
}
-
-func verboseName(r reference.Reference) string {
- if r == nil {
- return ""
- }
- named, isNamed := r.(reference.Named)
- digested, isDigested := r.(reference.Digested)
- tagged, isTagged := r.(reference.Tagged)
- name := ""
- tag := ""
- sum := ""
- if isNamed {
- name = (reference.TrimNamed(named)).String()
- }
- if isTagged {
- if tagged.Tag() != "" {
- tag = ":" + tagged.Tag()
- }
- }
- if isDigested {
- if digested.Digest().Validate() == nil {
- sum = "@" + digested.Digest().String()
- }
- }
- return name + tag + sum
-}
diff --git a/vendor/github.com/containers/image/types/types.go b/vendor/github.com/containers/image/types/types.go
index 2823a05c0..3ec77e0d1 100644
--- a/vendor/github.com/containers/image/types/types.go
+++ b/vendor/github.com/containers/image/types/types.go
@@ -174,6 +174,11 @@ type ImageDestination interface {
AcceptsForeignLayerURLs() bool
// MustMatchRuntimeOS returns true iff the destination can store only images targeted for the current runtime OS. False otherwise.
MustMatchRuntimeOS() bool
+ // IgnoresEmbeddedDockerReference() returns true iff the destination does not care about Image.EmbeddedDockerReferenceConflicts(),
+ // and would prefer to receive an unmodified manifest instead of one modified for the destination.
+ // Does not make a difference if Reference().DockerReference() is nil.
+ IgnoresEmbeddedDockerReference() bool
+
// PutBlob writes contents of stream and returns data representing the result.
// inputInfo.Digest can be optionally provided if known; it is not mandatory for the implementation to verify it.
// inputInfo.Size is the expected length of stream, if known.
diff --git a/vendor/github.com/containers/image/vendor.conf b/vendor/github.com/containers/image/vendor.conf
index 123bde98a..a84ab18b3 100644
--- a/vendor/github.com/containers/image/vendor.conf
+++ b/vendor/github.com/containers/image/vendor.conf
@@ -40,3 +40,5 @@ github.com/ostreedev/ostree-go aeb02c6b6aa2889db3ef62f7855650755befd460
github.com/gogo/protobuf fcdc5011193ff531a548e9b0301828d5a5b97fd8
github.com/pquerna/ffjson master
github.com/syndtr/gocapability master
+github.com/Microsoft/go-winio ab35fc04b6365e8fcb18e6e9e41ea4a02b10b175
+github.com/Microsoft/hcsshim eca7177590cdcbd25bbc5df27e3b693a54b53a6a