diff options
18 files changed, 112 insertions, 127 deletions
diff --git a/vendor.conf b/vendor.conf index 25d6f782b..7c9c96936 100644 --- a/vendor.conf +++ b/vendor.conf @@ -1,6 +1,6 @@ # github.com/sirupsen/logrus v1.0.0 -github.com/containers/image b129a8413fd1e8c53379acbbacfc7b667070ae50 +github.com/containers/image b327f751c16e4a189fdcde4ea36be67cc964c605 github.com/docker/docker-credential-helpers d68f9aeca33f5fd3f08eeae5e9d175edf4e731d1 github.com/ostreedev/ostree-go master github.com/containers/storage 1e5ce40cdb84ab66e26186435b1273e04b879fef diff --git a/vendor/github.com/containers/image/docker/docker_client.go b/vendor/github.com/containers/image/docker/docker_client.go index ff1af8f65..47b3e4690 100644 --- a/vendor/github.com/containers/image/docker/docker_client.go +++ b/vendor/github.com/containers/image/docker/docker_client.go @@ -495,7 +495,7 @@ func (c *dockerClient) detectProperties(ctx context.Context) error { defer resp.Body.Close() logrus.Debugf("Ping %s status %d", url, resp.StatusCode) if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusUnauthorized { - return errors.Errorf("error pinging repository, response code %d", resp.StatusCode) + return errors.Errorf("error pinging registry %s, response code %d", c.registry, resp.StatusCode) } c.challenges = parseAuthHeader(resp.Header) c.scheme = scheme @@ -547,7 +547,7 @@ func (c *dockerClient) getExtensionsSignatures(ctx context.Context, ref dockerRe } defer res.Body.Close() if res.StatusCode != http.StatusOK { - return nil, client.HandleErrorResponse(res) + return nil, errors.Wrapf(client.HandleErrorResponse(res), "Error downloading signatures for %s in %s", manifestDigest, ref.ref.Name()) } body, err := ioutil.ReadAll(res.Body) if err != nil { 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 2f3b6c2c3..2cf81844c 100644 --- a/vendor/github.com/containers/image/docker/docker_image_dest.go +++ b/vendor/github.com/containers/image/docker/docker_image_dest.go @@ -131,7 +131,7 @@ func (d *dockerImageDestination) PutBlob(stream io.Reader, inputInfo types.BlobI defer res.Body.Close() if res.StatusCode != http.StatusAccepted { logrus.Debugf("Error initiating layer upload, response %#v", *res) - return types.BlobInfo{}, errors.Wrapf(client.HandleErrorResponse(res), "Error initiating layer upload to %s", uploadPath) + return types.BlobInfo{}, errors.Wrapf(client.HandleErrorResponse(res), "Error initiating layer upload to %s in %s", uploadPath, d.c.registry) } uploadLocation, err := res.Location() if err != nil { @@ -196,7 +196,7 @@ func (d *dockerImageDestination) HasBlob(info types.BlobInfo) (bool, int64, erro return true, getBlobSize(res), nil case http.StatusUnauthorized: logrus.Debugf("... not authorized") - return false, -1, client.HandleErrorResponse(res) + return false, -1, errors.Wrapf(client.HandleErrorResponse(res), "Error checking whether a blob %s exists in %s", info.Digest, d.ref.ref.Name()) case http.StatusNotFound: logrus.Debugf("... not present") return false, -1, nil @@ -237,7 +237,7 @@ func (d *dockerImageDestination) PutManifest(m []byte) error { } defer res.Body.Close() if !successStatus(res.StatusCode) { - err = errors.Wrapf(client.HandleErrorResponse(res), "Error uploading manifest to %s", path) + err = errors.Wrapf(client.HandleErrorResponse(res), "Error uploading manifest %s to %s", refTail, d.ref.ref.Name()) if isManifestInvalidError(errors.Cause(err)) { err = types.ManifestTypeRejectedError{Err: err} } @@ -447,7 +447,7 @@ sigExists: logrus.Debugf("Error body %s", string(body)) } logrus.Debugf("Error uploading signature, status %d, %#v", res.StatusCode, res) - return errors.Wrapf(client.HandleErrorResponse(res), "Error uploading signature to %s", path) + return errors.Wrapf(client.HandleErrorResponse(res), "Error uploading signature to %s in %s", path, d.c.registry) } } diff --git a/vendor/github.com/containers/image/docker/docker_image_src.go b/vendor/github.com/containers/image/docker/docker_image_src.go index 6c208b278..7b96e95e8 100644 --- a/vendor/github.com/containers/image/docker/docker_image_src.go +++ b/vendor/github.com/containers/image/docker/docker_image_src.go @@ -95,7 +95,7 @@ func (s *dockerImageSource) fetchManifest(ctx context.Context, tagOrDigest strin } defer res.Body.Close() if res.StatusCode != http.StatusOK { - return nil, "", client.HandleErrorResponse(res) + return nil, "", errors.Wrapf(client.HandleErrorResponse(res), "Error reading manifest %s in %s", tagOrDigest, s.ref.ref.Name()) } manblob, err := ioutil.ReadAll(res.Body) if err != nil { diff --git a/vendor/github.com/containers/image/image/docker_schema1.go b/vendor/github.com/containers/image/image/docker_schema1.go index c486a2c34..f7dc90a3f 100644 --- a/vendor/github.com/containers/image/image/docker_schema1.go +++ b/vendor/github.com/containers/image/image/docker_schema1.go @@ -87,7 +87,8 @@ func (m *manifestSchema1) EmbeddedDockerReferenceConflicts(ref reference.Named) return m.m.Name != name || m.m.Tag != tag } -func (m *manifestSchema1) imageInspectInfo() (*types.ImageInspectInfo, error) { +// Inspect returns various information for (skopeo inspect) parsed from the manifest and configuration. +func (m *manifestSchema1) Inspect() (*types.ImageInspectInfo, error) { return m.m.Inspect(nil) } @@ -187,7 +188,7 @@ func (m *manifestSchema1) convertToManifestSchema2(uploadedLayerInfos []types.Bl diffIDs = append(diffIDs, d) } } - configJSON, err := m.m.ToSchema2(diffIDs) + configJSON, err := m.m.ToSchema2Config(diffIDs) if err != nil { return nil, err } diff --git a/vendor/github.com/containers/image/image/docker_schema2.go b/vendor/github.com/containers/image/image/docker_schema2.go index b43bc17cf..ef6cef440 100644 --- a/vendor/github.com/containers/image/image/docker_schema2.go +++ b/vendor/github.com/containers/image/image/docker_schema2.go @@ -130,7 +130,8 @@ func (m *manifestSchema2) EmbeddedDockerReferenceConflicts(ref reference.Named) return false } -func (m *manifestSchema2) imageInspectInfo() (*types.ImageInspectInfo, error) { +// Inspect returns various information for (skopeo inspect) parsed from the manifest and configuration. +func (m *manifestSchema2) Inspect() (*types.ImageInspectInfo, error) { getter := func(info types.BlobInfo) ([]byte, error) { if info.Digest != m.ConfigInfo().Digest { // Shouldn't ever happen diff --git a/vendor/github.com/containers/image/image/manifest.go b/vendor/github.com/containers/image/image/manifest.go index cdd4233f7..4f7d6248f 100644 --- a/vendor/github.com/containers/image/image/manifest.go +++ b/vendor/github.com/containers/image/image/manifest.go @@ -34,7 +34,8 @@ type genericManifest interface { // It returns false if the manifest does not embed a Docker reference. // (This embedding unfortunately happens for Docker schema1, please do not add support for this in any new formats.) EmbeddedDockerReferenceConflicts(ref reference.Named) bool - imageInspectInfo() (*types.ImageInspectInfo, error) // To be called by inspectManifest + // Inspect returns various information for (skopeo inspect) parsed from the manifest and configuration. + Inspect() (*types.ImageInspectInfo, error) // UpdatedImageNeedsLayerDiffIDs returns true iff UpdatedImage(options) needs InformationOnly.LayerDiffIDs. // This is a horribly specific interface, but computing InformationOnly.LayerDiffIDs can be very expensive to compute // (most importantly it forces us to download the full layers even if they are already present at the destination). @@ -60,8 +61,3 @@ func manifestInstanceFromBlob(ctx *types.SystemContext, src types.ImageSource, m return nil, fmt.Errorf("Unimplemented manifest MIME type %s", mt) } } - -// inspectManifest is an implementation of types.Image.Inspect -func inspectManifest(m genericManifest) (*types.ImageInspectInfo, error) { - return m.imageInspectInfo() -} diff --git a/vendor/github.com/containers/image/image/memory.go b/vendor/github.com/containers/image/image/memory.go index 8671c2490..42b287994 100644 --- a/vendor/github.com/containers/image/image/memory.go +++ b/vendor/github.com/containers/image/image/memory.go @@ -57,11 +57,6 @@ func (i *memoryImage) Signatures(ctx context.Context) ([][]byte, error) { return nil, errors.New("Internal error: Image.Signatures() is not supported for images modified in memory") } -// Inspect returns various information for (skopeo inspect) parsed from the manifest and configuration. -func (i *memoryImage) Inspect() (*types.ImageInspectInfo, error) { - return inspectManifest(i.genericManifest) -} - // LayerInfosForCopy returns an updated set of layer blob information which may not match the manifest. // The Digest field is guaranteed to be provided; Size may be -1. // WARNING: The list may contain duplicates, and they are semantically relevant. diff --git a/vendor/github.com/containers/image/image/oci.go b/vendor/github.com/containers/image/image/oci.go index e7780c5a6..8569dd0b1 100644 --- a/vendor/github.com/containers/image/image/oci.go +++ b/vendor/github.com/containers/image/image/oci.go @@ -110,7 +110,8 @@ func (m *manifestOCI1) EmbeddedDockerReferenceConflicts(ref reference.Named) boo return false } -func (m *manifestOCI1) imageInspectInfo() (*types.ImageInspectInfo, error) { +// Inspect returns various information for (skopeo inspect) parsed from the manifest and configuration. +func (m *manifestOCI1) Inspect() (*types.ImageInspectInfo, error) { getter := func(info types.BlobInfo) ([]byte, error) { if info.Digest != m.ConfigInfo().Digest { // Shouldn't ever happen diff --git a/vendor/github.com/containers/image/image/sourced.go b/vendor/github.com/containers/image/image/sourced.go index 4a0dd88fd..84fea26e7 100644 --- a/vendor/github.com/containers/image/image/sourced.go +++ b/vendor/github.com/containers/image/image/sourced.go @@ -97,10 +97,6 @@ func (i *sourcedImage) Manifest() ([]byte, string, error) { return i.manifestBlob, i.manifestMIMEType, nil } -func (i *sourcedImage) Inspect() (*types.ImageInspectInfo, error) { - return inspectManifest(i.genericManifest) -} - func (i *sourcedImage) LayerInfosForCopy() ([]types.BlobInfo, error) { - return i.UnparsedImage.LayerInfosForCopy() + return i.UnparsedImage.src.LayerInfosForCopy() } diff --git a/vendor/github.com/containers/image/image/unparsed.go b/vendor/github.com/containers/image/image/unparsed.go index 7a3288fff..0a8f78b66 100644 --- a/vendor/github.com/containers/image/image/unparsed.go +++ b/vendor/github.com/containers/image/image/unparsed.go @@ -93,10 +93,3 @@ func (i *UnparsedImage) Signatures(ctx context.Context) ([][]byte, error) { } return i.cachedSignatures, nil } - -// LayerInfosForCopy returns an updated set of layer blob information which may not match the manifest. -// The Digest field is guaranteed to be provided; Size may be -1. -// WARNING: The list may contain duplicates, and they are semantically relevant. -func (i *UnparsedImage) LayerInfosForCopy() ([]types.BlobInfo, error) { - return i.src.LayerInfosForCopy() -} diff --git a/vendor/github.com/containers/image/manifest/docker_schema1.go b/vendor/github.com/containers/image/manifest/docker_schema1.go index b1c1cfe9f..42751cec1 100644 --- a/vendor/github.com/containers/image/manifest/docker_schema1.go +++ b/vendor/github.com/containers/image/manifest/docker_schema1.go @@ -116,6 +116,7 @@ func (m *Schema1) UpdateLayerInfos(layerInfos []types.BlobInfo) error { if len(m.FSLayers) != len(layerInfos) { return errors.Errorf("Error preparing updated manifest: layer count changed from %d to %d", len(m.FSLayers), len(layerInfos)) } + m.FSLayers = make([]Schema1FSLayers, len(layerInfos)) for i, info := range layerInfos { // (docker push) sets up m.History.V1Compatibility->{Id,Parent} based on values of info.Digest, // but (docker pull) ignores them in favor of computing DiffIDs from uncompressed data, except verifying the child->parent links and uniqueness. @@ -202,44 +203,39 @@ func (m *Schema1) Inspect(_ func(types.BlobInfo) ([]byte, error)) (*types.ImageI if err := json.Unmarshal([]byte(m.History[0].V1Compatibility), s1); err != nil { return nil, err } - return &types.ImageInspectInfo{ + i := &types.ImageInspectInfo{ Tag: m.Tag, - Created: s1.Created, + Created: &s1.Created, DockerVersion: s1.DockerVersion, - Labels: make(map[string]string), Architecture: s1.Architecture, Os: s1.OS, Layers: LayerInfosToStrings(m.LayerInfos()), - }, nil + } + if s1.Config != nil { + i.Labels = s1.Config.Labels + } + return i, nil } -// ToSchema2 builds a schema2-style configuration blob using the supplied diffIDs. -func (m *Schema1) ToSchema2(diffIDs []digest.Digest) ([]byte, error) { +// ToSchema2Config builds a schema2-style configuration blob using the supplied diffIDs. +func (m *Schema1) ToSchema2Config(diffIDs []digest.Digest) ([]byte, error) { // Convert the schema 1 compat info into a schema 2 config, constructing some of the fields // that aren't directly comparable using info from the manifest. if len(m.History) == 0 { return nil, errors.New("image has no layers") } - s2 := struct { - Schema2Image - ID string `json:"id,omitempty"` - Parent string `json:"parent,omitempty"` - ParentID string `json:"parent_id,omitempty"` - LayerID string `json:"layer_id,omitempty"` - ThrowAway bool `json:"throwaway,omitempty"` - Size int64 `json:",omitempty"` - }{} + s1 := Schema2V1Image{} config := []byte(m.History[0].V1Compatibility) - err := json.Unmarshal(config, &s2) + err := json.Unmarshal(config, &s1) if err != nil { return nil, errors.Wrapf(err, "error decoding configuration") } // Images created with versions prior to 1.8.3 require us to re-encode the encoded object, // adding some fields that aren't "omitempty". - if s2.DockerVersion != "" && versions.LessThan(s2.DockerVersion, "1.8.3") { - config, err = json.Marshal(&s2) + if s1.DockerVersion != "" && versions.LessThan(s1.DockerVersion, "1.8.3") { + config, err = json.Marshal(&s1) if err != nil { - return nil, errors.Wrapf(err, "error re-encoding compat image config %#v", s2) + return nil, errors.Wrapf(err, "error re-encoding compat image config %#v", s1) } } // Build the history. @@ -270,7 +266,7 @@ func (m *Schema1) ToSchema2(diffIDs []digest.Digest) ([]byte, error) { raw := make(map[string]*json.RawMessage) err = json.Unmarshal(config, &raw) if err != nil { - return nil, errors.Wrapf(err, "error re-decoding compat image config %#v: %v", s2) + return nil, errors.Wrapf(err, "error re-decoding compat image config %#v: %v", s1) } // Drop some fields. delete(raw, "id") @@ -295,14 +291,14 @@ func (m *Schema1) ToSchema2(diffIDs []digest.Digest) ([]byte, error) { // Encode the result. config, err = json.Marshal(raw) if err != nil { - return nil, errors.Errorf("error re-encoding compat image config %#v: %v", s2, err) + return nil, errors.Errorf("error re-encoding compat image config %#v: %v", s1, err) } return config, nil } // ImageID computes an ID which can uniquely identify this image by its contents. func (m *Schema1) ImageID(diffIDs []digest.Digest) (string, error) { - image, err := m.ToSchema2(diffIDs) + image, err := m.ToSchema2Config(diffIDs) if err != nil { return "", err } diff --git a/vendor/github.com/containers/image/manifest/docker_schema2.go b/vendor/github.com/containers/image/manifest/docker_schema2.go index ef82ffc24..ef176271d 100644 --- a/vendor/github.com/containers/image/manifest/docker_schema2.go +++ b/vendor/github.com/containers/image/manifest/docker_schema2.go @@ -142,13 +142,6 @@ type Schema2Image struct { History []Schema2History `json:"history,omitempty"` OSVersion string `json:"os.version,omitempty"` OSFeatures []string `json:"os.features,omitempty"` - - // rawJSON caches the immutable JSON associated with this image. - rawJSON []byte - - // computedID is the ID computed from the hash of the image config. - // Not to be confused with the legacy V1 ID in V1Image. - computedID digest.Digest } // Schema2FromManifest creates a Schema2 manifest instance from a manifest blob. @@ -230,7 +223,7 @@ func (m *Schema2) Inspect(configGetter func(types.BlobInfo) ([]byte, error)) (*t } i := &types.ImageInspectInfo{ Tag: "", - Created: s2.Created, + Created: &s2.Created, DockerVersion: s2.DockerVersion, Architecture: s2.Architecture, Os: s2.OS, diff --git a/vendor/github.com/containers/image/manifest/oci.go b/vendor/github.com/containers/image/manifest/oci.go index 0ffb35b74..8cdc3e5b9 100644 --- a/vendor/github.com/containers/image/manifest/oci.go +++ b/vendor/github.com/containers/image/manifest/oci.go @@ -2,7 +2,6 @@ package manifest import ( "encoding/json" - "time" "github.com/containers/image/types" "github.com/opencontainers/go-digest" @@ -95,13 +94,9 @@ func (m *OCI1) Inspect(configGetter func(types.BlobInfo) ([]byte, error)) (*type } d1 := &Schema2V1Image{} json.Unmarshal(config, d1) - created := time.Time{} - if v1.Created != nil { - created = *v1.Created - } i := &types.ImageInspectInfo{ Tag: "", - Created: created, + Created: v1.Created, DockerVersion: d1.DockerVersion, Labels: v1.Config.Labels, Architecture: v1.Architecture, diff --git a/vendor/github.com/containers/image/pkg/docker/config/config.go b/vendor/github.com/containers/image/pkg/docker/config/config.go index fd0ae7d84..817930f41 100644 --- a/vendor/github.com/containers/image/pkg/docker/config/config.go +++ b/vendor/github.com/containers/image/pkg/docker/config/config.go @@ -27,7 +27,7 @@ type dockerConfigFile struct { } const ( - defaultPath = "/run/user" + defaultPath = "/run" authCfg = "containers" authCfgFileName = "auth.json" dockerCfg = ".docker" @@ -64,7 +64,11 @@ func GetAuthentication(ctx *types.SystemContext, registry string) (string, strin } dockerLegacyPath := filepath.Join(homedir.Get(), dockerLegacyCfg) - paths := [3]string{getPathToAuth(ctx), filepath.Join(homedir.Get(), dockerCfg, dockerCfgFileName), dockerLegacyPath} + pathToAuth, err := getPathToAuth(ctx) + if err != nil { + return "", "", err + } + paths := [3]string{pathToAuth, filepath.Join(homedir.Get(), dockerCfg, dockerCfgFileName), dockerLegacyPath} for _, path := range paths { legacyFormat := path == dockerLegacyPath @@ -82,13 +86,16 @@ func GetAuthentication(ctx *types.SystemContext, registry string) (string, strin // GetUserLoggedIn returns the username logged in to registry from either // auth.json or XDG_RUNTIME_DIR // Used to tell the user if someone is logged in to the registry when logging in -func GetUserLoggedIn(ctx *types.SystemContext, registry string) string { - path := getPathToAuth(ctx) +func GetUserLoggedIn(ctx *types.SystemContext, registry string) (string, error) { + path, err := getPathToAuth(ctx) + if err != nil { + return "", err + } username, _, _ := findAuthentication(registry, path, false) if username != "" { - return username + return username, nil } - return "" + return "", nil } // RemoveAuthentication deletes the credentials stored in auth.json @@ -123,20 +130,30 @@ func RemoveAllAuthentication(ctx *types.SystemContext) error { // The path can be overriden by the user if the overwrite-path flag is set // If the flag is not set and XDG_RUNTIME_DIR is ser, the auth.json file is saved in XDG_RUNTIME_DIR/containers // Otherwise, the auth.json file is stored in /run/user/UID/containers -func getPathToAuth(ctx *types.SystemContext) string { +func getPathToAuth(ctx *types.SystemContext) (string, error) { if ctx != nil { if ctx.AuthFilePath != "" { - return ctx.AuthFilePath + return ctx.AuthFilePath, nil } if ctx.RootForImplicitAbsolutePaths != "" { - return filepath.Join(ctx.RootForImplicitAbsolutePaths, defaultPath, strconv.Itoa(os.Getuid()), authCfg, authCfgFileName) + return filepath.Join(ctx.RootForImplicitAbsolutePaths, defaultPath, strconv.Itoa(os.Getuid()), authCfg, authCfgFileName), nil } } + runtimeDir := os.Getenv("XDG_RUNTIME_DIR") - if runtimeDir == "" { - runtimeDir = filepath.Join(defaultPath, strconv.Itoa(os.Getuid())) + if runtimeDir != "" { + _, err := os.Stat(runtimeDir) + if os.IsNotExist(err) { + // This means the user set the XDG_RUNTIME_DIR variable and either forgot to create the directory + // or made a typo while setting the environment variable + // so we log the error and return an empty string as the path + return "", errors.Wrapf(err, "%q directory set by $XDG_RUNTIME_DIR does not exist. Either create the directory or unset $XDG_RUNTIME_DIR.", runtimeDir) + } + runtimeDir = filepath.Join(runtimeDir, authCfg) + } else { + runtimeDir = filepath.Join(defaultPath, authCfg, strconv.Itoa(os.Getuid())) } - return filepath.Join(runtimeDir, authCfg, authCfgFileName) + return filepath.Join(runtimeDir, authCfgFileName), nil } // readJSONFile unmarshals the authentications stored in the auth.json file and returns it @@ -167,10 +184,14 @@ func readJSONFile(path string, legacyFormat bool) (dockerConfigFile, error) { // modifyJSON writes to auth.json if the dockerConfigFile has been updated func modifyJSON(ctx *types.SystemContext, editor func(auths *dockerConfigFile) (bool, error)) error { - path := getPathToAuth(ctx) + path, err := getPathToAuth(ctx) + if err != nil { + return err + } + dir := filepath.Dir(path) if _, err := os.Stat(dir); os.IsNotExist(err) { - if err = os.Mkdir(dir, 0700); err != nil { + if err = os.MkdirAll(dir, 0700); err != nil { return errors.Wrapf(err, "error creating directory %q", dir) } } diff --git a/vendor/github.com/containers/image/pkg/sysregistries/system_registries.go b/vendor/github.com/containers/image/pkg/sysregistries/system_registries.go index e5564a2a2..6d2f7544d 100644 --- a/vendor/github.com/containers/image/pkg/sysregistries/system_registries.go +++ b/vendor/github.com/containers/image/pkg/sysregistries/system_registries.go @@ -1,6 +1,8 @@ package sysregistries import ( + "strings" + "github.com/BurntSushi/toml" "github.com/containers/image/types" "io/ioutil" @@ -29,6 +31,14 @@ type tomlConfig struct { } `toml:"registries"` } +// normalizeRegistries removes a trailing slash from registries, which is a +// common pitfall when configuring registries (e.g., "docker.io/library/). +func normalizeRegistries(regs *registries) { + for i := range regs.Registries { + regs.Registries[i] = strings.TrimSuffix(regs.Registries[i], "/") + } +} + // Reads the global registry file from the filesystem. Returns // a byte array func readRegistryConf(ctx *types.SystemContext) ([]byte, error) { @@ -58,6 +68,9 @@ func loadRegistryConf(ctx *types.SystemContext) (*tomlConfig, error) { } err = toml.Unmarshal(configBytes, &config) + normalizeRegistries(&config.Registries.Search) + normalizeRegistries(&config.Registries.Insecure) + normalizeRegistries(&config.Registries.Block) return config, err } diff --git a/vendor/github.com/containers/image/storage/storage_image.go b/vendor/github.com/containers/image/storage/storage_image.go index d263d0126..a2babc9ea 100644 --- a/vendor/github.com/containers/image/storage/storage_image.go +++ b/vendor/github.com/containers/image/storage/storage_image.go @@ -44,15 +44,13 @@ var ( type storageImageSource struct { imageRef storageReference - ID string + image *storage.Image layerPosition map[digest.Digest]int // Where we are in reading a blob's layers cachedManifest []byte // A cached copy of the manifest, if already known, or nil SignatureSizes []int `json:"signature-sizes,omitempty"` // List of sizes of each signature slice } type storageImageDestination struct { - image types.ImageCloser - systemContext *types.SystemContext 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 directory string // Temporary directory where we store blobs until Commit() time @@ -81,7 +79,7 @@ func newImageSource(imageRef storageReference) (*storageImageSource, error) { // Build the reader object. image := &storageImageSource{ imageRef: imageRef, - ID: img.ID, + image: img, layerPosition: make(map[digest.Digest]int), SignatureSizes: []int{}, } @@ -124,7 +122,7 @@ func (s *storageImageSource) getBlobAndLayerID(info types.BlobInfo) (rc io.ReadC layers, err := s.imageRef.transport.store.LayersByUncompressedDigest(info.Digest) // If it's not a layer, then it must be a data item. if len(layers) == 0 { - b, err := s.imageRef.transport.store.ImageBigData(s.ID, info.Digest.String()) + b, err := s.imageRef.transport.store.ImageBigData(s.image.ID, info.Digest.String()) if err != nil { return nil, -1, "", err } @@ -166,7 +164,7 @@ func (s *storageImageSource) GetManifest(instanceDigest *digest.Digest) (manifes } if len(s.cachedManifest) == 0 { // We stored the manifest as an item named after storage.ImageDigestBigDataKey. - cachedBlob, err := s.imageRef.transport.store.ImageBigData(s.ID, storage.ImageDigestBigDataKey) + cachedBlob, err := s.imageRef.transport.store.ImageBigData(s.image.ID, storage.ImageDigestBigDataKey) if err != nil { return nil, "", err } @@ -178,15 +176,10 @@ func (s *storageImageSource) GetManifest(instanceDigest *digest.Digest) (manifes // LayerInfosForCopy() returns the list of layer blobs that make up the root filesystem of // the image, after they've been decompressed. func (s *storageImageSource) LayerInfosForCopy() ([]types.BlobInfo, error) { - simg, err := s.imageRef.transport.store.Image(s.ID) - if err != nil { - return nil, errors.Wrapf(err, "error reading image %q", s.ID) - } updatedBlobInfos := []types.BlobInfo{} - layerID := simg.TopLayer _, manifestType, err := s.GetManifest(nil) if err != nil { - return nil, errors.Wrapf(err, "error reading image manifest for %q", s.ID) + return nil, errors.Wrapf(err, "error reading image manifest for %q", s.image.ID) } uncompressedLayerType := "" switch manifestType { @@ -196,10 +189,11 @@ func (s *storageImageSource) LayerInfosForCopy() ([]types.BlobInfo, error) { // This is actually a compressed type, but there's no uncompressed type defined uncompressedLayerType = manifest.DockerV2Schema2LayerMediaType } + layerID := s.image.TopLayer for layerID != "" { layer, err := s.imageRef.transport.store.Layer(layerID) if err != nil { - return nil, errors.Wrapf(err, "error reading layer %q in image %q", layerID, s.ID) + return nil, errors.Wrapf(err, "error reading layer %q in image %q", layerID, s.image.ID) } if layer.UncompressedDigest == "" { return nil, errors.Errorf("uncompressed digest for layer %q is unknown", layerID) @@ -227,9 +221,9 @@ func (s *storageImageSource) GetSignatures(ctx context.Context, instanceDigest * sigslice := [][]byte{} signature := []byte{} if len(s.SignatureSizes) > 0 { - signatureBlob, err := s.imageRef.transport.store.ImageBigData(s.ID, "signatures") + signatureBlob, err := s.imageRef.transport.store.ImageBigData(s.image.ID, "signatures") if err != nil { - return nil, errors.Wrapf(err, "error looking up signatures data for image %q", s.ID) + return nil, errors.Wrapf(err, "error looking up signatures data for image %q", s.image.ID) } signature = signatureBlob } @@ -257,7 +251,6 @@ func newImageDestination(ctx *types.SystemContext, imageRef storageReference) (* publicRef := imageRef publicRef.name = nil image := &storageImageDestination{ - systemContext: ctx, imageRef: imageRef, publicRef: publicRef, directory: directory, @@ -412,17 +405,11 @@ func (s *storageImageDestination) computeID(m manifest.Manifest) string { // fill in the DiffIDs. It's expected (but not enforced by us) that the number of // diffIDs corresponds to the number of non-EmptyLayer entries in the history. var diffIDs []digest.Digest - switch m.(type) { + switch m := m.(type) { case *manifest.Schema1: // Build a list of the diffIDs we've generated for the non-throwaway FS layers, // in reverse of the order in which they were originally listed. - s1, ok := m.(*manifest.Schema1) - if !ok { - // Shouldn't happen - logrus.Debugf("internal error reading schema 1 manifest") - return "" - } - for i, history := range s1.History { + for i, history := range m.History { compat := manifest.Schema1V1Compatibility{} if err := json.Unmarshal([]byte(history.V1Compatibility), &compat); err != nil { logrus.Debugf("internal error reading schema 1 history: %v", err) @@ -431,7 +418,7 @@ func (s *storageImageDestination) computeID(m manifest.Manifest) string { if compat.ThrowAway { continue } - blobSum := s1.FSLayers[i].BlobSum + blobSum := m.FSLayers[i].BlobSum diffID, ok := s.blobDiffIDs[blobSum] if !ok { logrus.Infof("error looking up diffID for layer %q", blobSum.String()) @@ -442,6 +429,8 @@ func (s *storageImageDestination) computeID(m manifest.Manifest) string { case *manifest.Schema2, *manifest.OCI1: // We know the ID calculation for these formats doesn't actually use the diffIDs, // so we don't need to populate the diffID list. + default: + return "" } id, err := m.ImageID(diffIDs) if err != nil { @@ -566,9 +555,9 @@ func (s *storageImageDestination) Commit() error { // If one of those blobs was a configuration blob, then we can try to dig out the date when the image // was originally created, in case we're just copying it. If not, no harm done. options := &storage.ImageOptions{} - if inspect, err := man.Inspect(s.getConfigBlob); err == nil { + if inspect, err := man.Inspect(s.getConfigBlob); err == nil && inspect.Created != nil { logrus.Debugf("setting image creation date to %s", inspect.Created) - options.CreationDate = inspect.Created + options.CreationDate = *inspect.Created } if manifestDigest, err := manifest.Digest(s.manifest); err == nil { options.Digest = manifestDigest @@ -735,14 +724,14 @@ func (s *storageImageDestination) PutSignatures(signatures [][]byte) error { func (s *storageImageSource) getSize() (int64, error) { var sum int64 // Size up the data blobs. - dataNames, err := s.imageRef.transport.store.ListImageBigData(s.ID) + dataNames, err := s.imageRef.transport.store.ListImageBigData(s.image.ID) if err != nil { - return -1, errors.Wrapf(err, "error reading image %q", s.ID) + return -1, errors.Wrapf(err, "error reading image %q", s.image.ID) } for _, dataName := range dataNames { - bigSize, err := s.imageRef.transport.store.ImageBigDataSize(s.ID, dataName) + bigSize, err := s.imageRef.transport.store.ImageBigDataSize(s.image.ID, dataName) if err != nil { - return -1, errors.Wrapf(err, "error reading data blob size %q for %q", dataName, s.ID) + return -1, errors.Wrapf(err, "error reading data blob size %q for %q", dataName, s.image.ID) } sum += bigSize } @@ -750,13 +739,8 @@ func (s *storageImageSource) getSize() (int64, error) { for _, sigSize := range s.SignatureSizes { sum += int64(sigSize) } - // Prepare to walk the layer list. - img, err := s.imageRef.transport.store.Image(s.ID) - if err != nil { - return -1, errors.Wrapf(err, "error reading image info %q", s.ID) - } // Walk the layer list. - layerID := img.TopLayer + layerID := s.image.TopLayer for layerID != "" { layer, err := s.imageRef.transport.store.Layer(layerID) if err != nil { diff --git a/vendor/github.com/containers/image/types/types.go b/vendor/github.com/containers/image/types/types.go index d1e33e0c8..88dcc8a29 100644 --- a/vendor/github.com/containers/image/types/types.go +++ b/vendor/github.com/containers/image/types/types.go @@ -215,10 +215,6 @@ type UnparsedImage interface { Manifest() ([]byte, string, error) // Signatures is like ImageSource.GetSignatures, but the result is cached; it is OK to call this however often you need. Signatures(ctx context.Context) ([][]byte, error) - // LayerInfosForCopy returns either nil (meaning the values in the manifest are fine), or updated values for the layer blobsums that are listed in the image's manifest. - // The Digest field is guaranteed to be provided, Size may be -1 and MediaType may be optionally provided. - // WARNING: The list may contain duplicates, and they are semantically relevant. - LayerInfosForCopy() ([]BlobInfo, error) } // Image is the primary API for inspecting properties of images. @@ -242,6 +238,10 @@ type Image interface { // The Digest field is guaranteed to be provided, Size may be -1 and MediaType may be optionally provided. // WARNING: The list may contain duplicates, and they are semantically relevant. LayerInfos() []BlobInfo + // LayerInfosForCopy returns either nil (meaning the values in the manifest are fine), or updated values for the layer blobsums that are listed in the image's manifest. + // The Digest field is guaranteed to be provided, Size may be -1 and MediaType may be optionally provided. + // WARNING: The list may contain duplicates, and they are semantically relevant. + LayerInfosForCopy() ([]BlobInfo, error) // EmbeddedDockerReferenceConflicts whether a Docker reference embedded in the manifest, if any, conflicts with destination ref. // It returns false if the manifest does not embed a Docker reference. // (This embedding unfortunately happens for Docker schema1, please do not add support for this in any new formats.) @@ -292,7 +292,7 @@ type ManifestUpdateInformation struct { // for other manifest types. type ImageInspectInfo struct { Tag string - Created time.Time + Created *time.Time DockerVersion string Labels map[string]string Architecture string |