mirror of
https://github.com/containers/podman.git
synced 2025-06-06 15:00:40 +08:00
bump containers/image to v5.0.0, buildah to v1.11.4
Move to containers/image v5 and containers/buildah to v1.11.4. Replace an equality check with a type assertion when checking for a docker.ErrUnauthorizedForCredentials in `podman login`. Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
This commit is contained in:
26
vendor/github.com/containers/buildah/CHANGELOG.md
generated
vendored
26
vendor/github.com/containers/buildah/CHANGELOG.md
generated
vendored
@ -2,6 +2,32 @@
|
||||
|
||||
# Changelog
|
||||
|
||||
## v1.11.3 (2019-10-04)
|
||||
Update c/image to v4.0.1
|
||||
Bump github.com/spf13/pflag from 1.0.3 to 1.0.5
|
||||
Fix --build-args handling
|
||||
Bump github.com/spf13/cobra from 0.0.3 to 0.0.5
|
||||
Bump github.com/cyphar/filepath-securejoin from 0.2.1 to 0.2.2
|
||||
Bump github.com/onsi/ginkgo from 1.8.0 to 1.10.1
|
||||
Bump github.com/fsouza/go-dockerclient from 1.3.0 to 1.4.4
|
||||
Add support for retrieving context from stdin "-"
|
||||
Ensure bud remote context cleans up on error
|
||||
info: add cgroups2
|
||||
Bump github.com/seccomp/libseccomp-golang from 0.9.0 to 0.9.1
|
||||
Bump github.com/mattn/go-shellwords from 1.0.5 to 1.0.6
|
||||
Bump github.com/stretchr/testify from 1.3.0 to 1.4.0
|
||||
Bump github.com/opencontainers/selinux from 1.2.2 to 1.3.0
|
||||
Bump github.com/etcd-io/bbolt from 1.3.2 to 1.3.3
|
||||
Bump github.com/onsi/gomega from 1.5.0 to 1.7.0
|
||||
update c/storage to v1.13.4
|
||||
Print build 'STEP' line to stdout, not stderr
|
||||
Fix travis-ci on forks
|
||||
Vendor c/storage v1.13.3
|
||||
Use Containerfile by default
|
||||
Added tutorial on how to include Buildah as library
|
||||
util/util: Fix "configuraitno" -> "configuration" log typo
|
||||
Bump back to v1.12.0-dev
|
||||
|
||||
## v1.11.2 (2019-09-13)
|
||||
Add some cleanup code
|
||||
Move devices code to unit specific directory.
|
||||
|
22
vendor/github.com/containers/buildah/OWNERS
generated
vendored
Normal file
22
vendor/github.com/containers/buildah/OWNERS
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
approvers:
|
||||
- TomSweeneyRedHat
|
||||
- cevich
|
||||
- giuseppe
|
||||
- nalind
|
||||
- rhatdan
|
||||
- vrothberg
|
||||
reviewers:
|
||||
- QiWang19
|
||||
- TomSweeneyRedHat
|
||||
- baude
|
||||
- cevich
|
||||
- edsantiago
|
||||
- giuseppe
|
||||
- haircommander
|
||||
- jwhonce
|
||||
- mheon
|
||||
- mrunalp
|
||||
- nalind
|
||||
- rhatdan
|
||||
- umohnani8
|
||||
- vrothberg
|
4
vendor/github.com/containers/buildah/buildah.go
generated
vendored
4
vendor/github.com/containers/buildah/buildah.go
generated
vendored
@ -12,7 +12,7 @@ import (
|
||||
|
||||
"github.com/containers/buildah/docker"
|
||||
"github.com/containers/buildah/util"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/storage"
|
||||
"github.com/containers/storage/pkg/ioutils"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
@ -27,7 +27,7 @@ const (
|
||||
Package = "buildah"
|
||||
// Version for the Package. Bump version in contrib/rpm/buildah.spec
|
||||
// too.
|
||||
Version = "1.11.3"
|
||||
Version = "1.11.4"
|
||||
// The value we use to identify what type of information, currently a
|
||||
// serialized Builder structure, we are using as per-container state.
|
||||
// This should only be changed when we make incompatible changes to
|
||||
|
22
vendor/github.com/containers/buildah/changelog.txt
generated
vendored
22
vendor/github.com/containers/buildah/changelog.txt
generated
vendored
@ -1,3 +1,25 @@
|
||||
- Changelog for v1.11.4 (2019-10-28)
|
||||
* buildah: add a "manifest" command
|
||||
* manifests: add the module
|
||||
* pkg/supplemented: add a package for grouping images together
|
||||
* pkg/manifests: add a manifest list build/manipulation API
|
||||
* Update for ErrUnauthorizedForCredentials API change in containers/image
|
||||
* Update for manifest-lists API changes in containers/image
|
||||
* version: also note the version of containers/image
|
||||
* Move to containers/image v5.0.0
|
||||
* Enable --device directory as src device
|
||||
* Fix git build with branch specified
|
||||
* Bump github.com/openshift/imagebuilder from 1.1.0 to 1.1.1
|
||||
* Bump github.com/fsouza/go-dockerclient from 1.4.4 to 1.5.0
|
||||
* Add clarification to the Tutorial for new users
|
||||
* Silence "using cache" to ensure -q is fully quiet
|
||||
* Add OWNERS File to Buildah
|
||||
* Bump github.com/containers/storage from 1.13.4 to 1.13.5
|
||||
* Move runtime flag to bud from common
|
||||
* Commit: check for storage.ErrImageUnknown using errors.Cause()
|
||||
* Fix crash when invalid COPY --from flag is specified.
|
||||
* Bump back to v1.12.0-dev
|
||||
|
||||
- Changelog for v1.11.3 (2019-10-04)
|
||||
* Update c/image to v4.0.1
|
||||
* Bump github.com/spf13/pflag from 1.0.3 to 1.0.5
|
||||
|
20
vendor/github.com/containers/buildah/commit.go
generated
vendored
20
vendor/github.com/containers/buildah/commit.go
generated
vendored
@ -12,14 +12,14 @@ import (
|
||||
|
||||
"github.com/containers/buildah/pkg/blobcache"
|
||||
"github.com/containers/buildah/util"
|
||||
cp "github.com/containers/image/v4/copy"
|
||||
"github.com/containers/image/v4/docker"
|
||||
"github.com/containers/image/v4/docker/reference"
|
||||
"github.com/containers/image/v4/manifest"
|
||||
"github.com/containers/image/v4/signature"
|
||||
is "github.com/containers/image/v4/storage"
|
||||
"github.com/containers/image/v4/transports"
|
||||
"github.com/containers/image/v4/types"
|
||||
cp "github.com/containers/image/v5/copy"
|
||||
"github.com/containers/image/v5/docker"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/signature"
|
||||
is "github.com/containers/image/v5/storage"
|
||||
"github.com/containers/image/v5/transports"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/storage"
|
||||
"github.com/containers/storage/pkg/archive"
|
||||
"github.com/containers/storage/pkg/stringid"
|
||||
@ -96,7 +96,7 @@ type PushOptions struct {
|
||||
// github.com/containers/image/types SystemContext to hold credentials
|
||||
// and other authentication/authorization information.
|
||||
SystemContext *types.SystemContext
|
||||
// ManifestType is the format to use when saving the imge using the 'dir' transport
|
||||
// ManifestType is the format to use when saving the image using the 'dir' transport
|
||||
// possible options are oci, v2s1, and v2s2
|
||||
ManifestType string
|
||||
// BlobDirectory is the name of a directory in which we'll look for
|
||||
@ -309,7 +309,7 @@ func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options
|
||||
}
|
||||
|
||||
img, err := is.Transport.GetStoreImage(b.store, dest)
|
||||
if err != nil && err != storage.ErrImageUnknown {
|
||||
if err != nil && errors.Cause(err) != storage.ErrImageUnknown {
|
||||
return imgID, nil, "", errors.Wrapf(err, "error locating image %q in local storage", transports.ImageName(dest))
|
||||
}
|
||||
if err == nil {
|
||||
|
4
vendor/github.com/containers/buildah/common.go
generated
vendored
4
vendor/github.com/containers/buildah/common.go
generated
vendored
@ -6,8 +6,8 @@ import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/containers/buildah/pkg/unshare"
|
||||
cp "github.com/containers/image/v4/copy"
|
||||
"github.com/containers/image/v4/types"
|
||||
cp "github.com/containers/image/v5/copy"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/storage"
|
||||
)
|
||||
|
||||
|
6
vendor/github.com/containers/buildah/config.go
generated
vendored
6
vendor/github.com/containers/buildah/config.go
generated
vendored
@ -8,9 +8,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/containers/buildah/docker"
|
||||
"github.com/containers/image/v4/manifest"
|
||||
"github.com/containers/image/v4/transports"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/transports"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/storage/pkg/stringid"
|
||||
ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
|
2
vendor/github.com/containers/buildah/docker/types.go
generated
vendored
2
vendor/github.com/containers/buildah/docker/types.go
generated
vendored
@ -7,7 +7,7 @@ package docker
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/containers/image/v4/pkg/strslice"
|
||||
"github.com/containers/image/v5/pkg/strslice"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
)
|
||||
|
||||
|
10
vendor/github.com/containers/buildah/go.mod
generated
vendored
10
vendor/github.com/containers/buildah/go.mod
generated
vendored
@ -5,8 +5,8 @@ go 1.12
|
||||
require (
|
||||
github.com/blang/semver v3.5.0+incompatible // indirect
|
||||
github.com/containernetworking/cni v0.7.1
|
||||
github.com/containers/image/v4 v4.0.1
|
||||
github.com/containers/storage v1.13.4
|
||||
github.com/containers/image/v5 v5.0.0
|
||||
github.com/containers/storage v1.13.5
|
||||
github.com/cyphar/filepath-securejoin v0.2.2
|
||||
github.com/docker/distribution v2.7.1+incompatible
|
||||
github.com/docker/docker-credential-helpers v0.6.1 // indirect
|
||||
@ -14,7 +14,7 @@ require (
|
||||
github.com/docker/go-units v0.4.0
|
||||
github.com/docker/libnetwork v0.8.0-dev.2.0.20190625141545-5a177b73e316
|
||||
github.com/etcd-io/bbolt v1.3.3
|
||||
github.com/fsouza/go-dockerclient v1.4.4
|
||||
github.com/fsouza/go-dockerclient v1.5.0
|
||||
github.com/ghodss/yaml v1.0.0
|
||||
github.com/hashicorp/go-multierror v1.0.0
|
||||
github.com/imdario/mergo v0.3.6 // indirect
|
||||
@ -30,7 +30,7 @@ require (
|
||||
github.com/opencontainers/runtime-tools v0.9.0
|
||||
github.com/opencontainers/selinux v1.3.0
|
||||
github.com/openshift/api v3.9.1-0.20190810003144-27fb16909b15+incompatible
|
||||
github.com/openshift/imagebuilder v1.1.0
|
||||
github.com/openshift/imagebuilder v1.1.1
|
||||
github.com/pkg/errors v0.8.1
|
||||
github.com/seccomp/containers-golang v0.0.0-20180629143253-cdfdaa7543f4
|
||||
github.com/seccomp/libseccomp-golang v0.9.1
|
||||
@ -42,7 +42,7 @@ require (
|
||||
github.com/vishvananda/netlink v1.0.0 // indirect
|
||||
github.com/vishvananda/netns v0.0.0-20190625233234-7109fa855b0f // indirect
|
||||
github.com/xeipuuv/gojsonschema v1.1.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
|
||||
golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad
|
||||
golang.org/x/sys v0.0.0-20190902133755-9109b7679e13
|
||||
golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0 // indirect
|
||||
google.golang.org/grpc v1.24.0 // indirect
|
||||
|
29
vendor/github.com/containers/buildah/go.sum
generated
vendored
29
vendor/github.com/containers/buildah/go.sum
generated
vendored
@ -28,21 +28,23 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
|
||||
github.com/blang/semver v3.5.0+incompatible h1:CGxCgetQ64DKk7rdZ++Vfnb1+ogGNnB17OJKJXD2Cfs=
|
||||
github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/containerd/containerd v1.3.0 h1:xjvXQWABwS2uiv3TWgQt5Uth60Gu86LTGZXMJkjc7rY=
|
||||
github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||
github.com/containerd/continuity v0.0.0-20180216233310-d8fb8589b0e8/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
github.com/containerd/continuity v0.0.0-20181203112020-004b46473808 h1:4BX8f882bXEDKfWIf0wa8HRvpnBoPszJJXL+TVbBw4M=
|
||||
github.com/containerd/continuity v0.0.0-20181203112020-004b46473808/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
github.com/containernetworking/cni v0.7.1 h1:fE3r16wpSEyaqY4Z4oFrLMmIGfBYIKpPrHK31EJ9FzE=
|
||||
github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
|
||||
github.com/containers/image v3.0.2+incompatible h1:B1lqAE8MUPCrsBLE86J0gnXleeRq8zJnQryhiiGQNyE=
|
||||
github.com/containers/image v3.0.2+incompatible/go.mod h1:8Vtij257IWSanUQKe1tAeNOm2sRVkSqQTVQ1IlwI3+M=
|
||||
github.com/containers/image v4.0.0+incompatible h1:CfKbemfowbIg3nhq8rvtI+sdU9QbvODkiD+JLpOJMiQ=
|
||||
github.com/containers/image v4.0.0+incompatible/go.mod h1:Td6tqqQu0miIBO8mauyzsVqBbv5WhKSE4pH2ZwslVp0=
|
||||
github.com/containers/image/v4 v4.0.1 h1:idNGHChj0Pyv3vLrxul2oSVMZLeFqpoq3CjLeVgapSQ=
|
||||
github.com/containers/image/v4 v4.0.1/go.mod h1:0ASJH1YgJiX/eqFZObqepgsvIA4XjCgpyfwn9pDGafA=
|
||||
github.com/containers/image/v5 v5.0.0 h1:arnXgbt1ucsC/ndtSpiQY87rA0UjhF+/xQnPzqdBDn4=
|
||||
github.com/containers/image/v5 v5.0.0/go.mod h1:MgiLzCfIeo8lrHi+4Lb8HP+rh513sm0Mlk6RrhjFOLY=
|
||||
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b h1:Q8ePgVfHDplZ7U33NwHZkrVELsZP5fYj9pM5WBZB2GE=
|
||||
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY=
|
||||
github.com/containers/storage v1.13.4 h1:j0bBaJDKbUHtAW1MXPFnwXJtqcH+foWeuXK1YaBV5GA=
|
||||
github.com/containers/storage v1.13.4/go.mod h1:6D8nK2sU9V7nEmAraINRs88ZEscM5C5DK+8Npp27GeA=
|
||||
github.com/containers/storage v1.13.5 h1:/SUzGeOP2HDijpF7Yur21Ch6WTZC1BNeZF917CWcp5c=
|
||||
github.com/containers/storage v1.13.5/go.mod h1:HELz8Sn+UVbPaUZMI8RvIG9doD4y4z6Gtg4k7xdd2ZY=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
@ -60,6 +62,8 @@ github.com/docker/docker v0.0.0-20171019062838-86f080cff091/go.mod h1:eEKB0N0r5N
|
||||
github.com/docker/docker v0.0.0-20180522102801-da99009bbb11/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v1.4.2-0.20190710153559-aa8249ae1b8b h1:+Ga+YpCDpcY1fln6GI0fiiirpqHGcob5/Vk3oKNuGdU=
|
||||
github.com/docker/docker v1.4.2-0.20190710153559-aa8249ae1b8b/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v1.4.2-0.20190927142053-ada3c14355ce h1:H3csZuxZESJeeEiOxq4YXPNmLFbjl7u2qVBrAAGX/sA=
|
||||
github.com/docker/docker v1.4.2-0.20190927142053-ada3c14355ce/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker-credential-helpers v0.6.0/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
|
||||
github.com/docker/docker-credential-helpers v0.6.1 h1:Dq4iIfcM7cNtddhLVWe9h4QDjsi4OER3Z8voPu/I52g=
|
||||
github.com/docker/docker-credential-helpers v0.6.1/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
|
||||
@ -84,6 +88,8 @@ github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsouza/go-dockerclient v1.4.4 h1:Sd5nD4wdAgiPxvrbYUzT2ZZNmPk3z+GGnZ+frvw8z04=
|
||||
github.com/fsouza/go-dockerclient v1.4.4/go.mod h1:PrwszSL5fbmsESocROrOGq/NULMXRw+bajY0ltzD6MA=
|
||||
github.com/fsouza/go-dockerclient v1.5.0 h1:7OtayOe5HnoG+KWMHgyyPymwaodnB2IDYuVfseKyxbA=
|
||||
github.com/fsouza/go-dockerclient v1.5.0/go.mod h1:AqZZK/zFO3phxYxlTsAaeAMSdQ9mgHuhy+bjN034Qds=
|
||||
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/ghodss/yaml v0.0.0-20161207003320-04f313413ffd/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
@ -101,6 +107,7 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I=
|
||||
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
@ -190,16 +197,11 @@ github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lN
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
||||
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||
github.com/mtrmac/gpgme v0.0.0-20170102180018-b2432428689c h1:xa+eQWKuJ9MbB9FBL/eoNvDFvveAkz2LQoz8PzX7Q/4=
|
||||
github.com/mtrmac/gpgme v0.0.0-20170102180018-b2432428689c/go.mod h1:GhAqVMEWnTcW2dxoD/SO3n2enrgWl3y6Dnx4m59GvcA=
|
||||
github.com/mtrmac/image/v4 v4.0.0-20191001213151-121ffca6db69 h1:TVWS7od6UeGhdYqgXn/+EIDlulkGGV+r6FnjoxRJAl0=
|
||||
github.com/mtrmac/image/v4 v4.0.0-20191001213151-121ffca6db69/go.mod h1:0ASJH1YgJiX/eqFZObqepgsvIA4XjCgpyfwn9pDGafA=
|
||||
github.com/mtrmac/image/v4 v4.0.0-20191002203927-a64d9d2717f4 h1:AE5cilZfrGtAgMg5Ed4c2Y2KczlOsMVZAK055sSq+gc=
|
||||
github.com/mtrmac/image/v4 v4.0.0-20191002203927-a64d9d2717f4/go.mod h1:0ASJH1YgJiX/eqFZObqepgsvIA4XjCgpyfwn9pDGafA=
|
||||
github.com/mtrmac/image/v4 v4.0.0-20191003181245-f4c983e93262 h1:HMUEnWU3OPT09JRFQLn8VTp3GfdfiEhDMAEhkdX8QnA=
|
||||
github.com/mtrmac/image/v4 v4.0.0-20191003181245-f4c983e93262/go.mod h1:0ASJH1YgJiX/eqFZObqepgsvIA4XjCgpyfwn9pDGafA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
||||
@ -238,6 +240,8 @@ github.com/openshift/api v3.9.1-0.20190810003144-27fb16909b15+incompatible h1:s5
|
||||
github.com/openshift/api v3.9.1-0.20190810003144-27fb16909b15+incompatible/go.mod h1:dh9o4Fs58gpFXGSYfnVxGR9PnV53I8TW84pQaJDdGiY=
|
||||
github.com/openshift/imagebuilder v1.1.0 h1:oT704SkwMEzmIMU/+Uv1Wmvt+p10q3v2WuYMeFI18c4=
|
||||
github.com/openshift/imagebuilder v1.1.0/go.mod h1:9aJRczxCH0mvT6XQ+5STAQaPWz7OsWcU5/mRkt8IWeo=
|
||||
github.com/openshift/imagebuilder v1.1.1 h1:KAUR31p8UBJdfVO42azWgb+LeMAed2zaKQ19e0C0X2I=
|
||||
github.com/openshift/imagebuilder v1.1.1/go.mod h1:9aJRczxCH0mvT6XQ+5STAQaPWz7OsWcU5/mRkt8IWeo=
|
||||
github.com/ostreedev/ostree-go v0.0.0-20190702140239-759a8c1ac913 h1:TnbXhKzrTOyuvWrjI8W6pcoI9XPbLHFXCdN2dtUw7Rw=
|
||||
github.com/ostreedev/ostree-go v0.0.0-20190702140239-759a8c1ac913/go.mod h1:J6OG6YJVEWopen4avK3VNQSnALmmjvniMmni/YFYAwc=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
@ -299,8 +303,6 @@ github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG
|
||||
github.com/tchap/go-patricia v2.3.0+incompatible h1:GkY4dP3cEfEASBPPkWd+AmjYxhmDkqO9/zg7R0lSQRs=
|
||||
github.com/tchap/go-patricia v2.3.0+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
|
||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||
github.com/ulikunitz/xz v0.5.5 h1:pFrO0lVpTBXLpYw+pnLj6TbvHuyjXMfjGeCwSqCVwok=
|
||||
github.com/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
|
||||
github.com/ulikunitz/xz v0.5.6 h1:jGHAfXawEGZQ3blwU5wnWKQJvAraT7Ftq9EXjnXYgt8=
|
||||
github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
|
||||
github.com/vbatts/tar-split v0.11.1 h1:0Odu65rhcZ3JZaPHxl7tCI3V/C/Q9Zf82UFravl02dE=
|
||||
@ -329,6 +331,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90Pveol
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad h1:5E5raQxcv+6CZ11RrBYQe5WRbUIWpScjh0kvHZkZIrQ=
|
||||
golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@ -390,6 +394,7 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
|
12
vendor/github.com/containers/buildah/image.go
generated
vendored
12
vendor/github.com/containers/buildah/image.go
generated
vendored
@ -13,11 +13,11 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/containers/buildah/docker"
|
||||
"github.com/containers/image/v4/docker/reference"
|
||||
"github.com/containers/image/v4/image"
|
||||
"github.com/containers/image/v4/manifest"
|
||||
is "github.com/containers/image/v4/storage"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/image"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
is "github.com/containers/image/v5/storage"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/storage"
|
||||
"github.com/containers/storage/pkg/archive"
|
||||
"github.com/containers/storage/pkg/ioutils"
|
||||
@ -596,7 +596,7 @@ func (i *containerImageSource) GetManifest(ctx context.Context, instanceDigest *
|
||||
return i.manifest, i.manifestType, nil
|
||||
}
|
||||
|
||||
func (i *containerImageSource) LayerInfosForCopy(ctx context.Context) ([]types.BlobInfo, error) {
|
||||
func (i *containerImageSource) LayerInfosForCopy(ctx context.Context, instanceDigest *digest.Digest) ([]types.BlobInfo, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
4
vendor/github.com/containers/buildah/imagebuildah/build.go
generated
vendored
4
vendor/github.com/containers/buildah/imagebuildah/build.go
generated
vendored
@ -13,8 +13,8 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/containers/buildah"
|
||||
"github.com/containers/image/v4/docker/reference"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/storage"
|
||||
"github.com/containers/storage/pkg/archive"
|
||||
"github.com/opencontainers/runc/libcontainer/configs"
|
||||
|
10
vendor/github.com/containers/buildah/imagebuildah/executor.go
generated
vendored
10
vendor/github.com/containers/buildah/imagebuildah/executor.go
generated
vendored
@ -12,11 +12,11 @@ import (
|
||||
|
||||
"github.com/containers/buildah"
|
||||
"github.com/containers/buildah/util"
|
||||
"github.com/containers/image/v4/docker/reference"
|
||||
is "github.com/containers/image/v4/storage"
|
||||
"github.com/containers/image/v4/transports"
|
||||
"github.com/containers/image/v4/transports/alltransports"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
is "github.com/containers/image/v5/storage"
|
||||
"github.com/containers/image/v5/transports"
|
||||
"github.com/containers/image/v5/transports/alltransports"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/storage"
|
||||
"github.com/containers/storage/pkg/archive"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
|
23
vendor/github.com/containers/buildah/imagebuildah/stage_executor.go
generated
vendored
23
vendor/github.com/containers/buildah/imagebuildah/stage_executor.go
generated
vendored
@ -13,12 +13,12 @@ import (
|
||||
"github.com/containers/buildah"
|
||||
buildahdocker "github.com/containers/buildah/docker"
|
||||
"github.com/containers/buildah/util"
|
||||
cp "github.com/containers/image/v4/copy"
|
||||
"github.com/containers/image/v4/docker/reference"
|
||||
"github.com/containers/image/v4/manifest"
|
||||
is "github.com/containers/image/v4/storage"
|
||||
"github.com/containers/image/v4/transports"
|
||||
"github.com/containers/image/v4/types"
|
||||
cp "github.com/containers/image/v5/copy"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
is "github.com/containers/image/v5/storage"
|
||||
"github.com/containers/image/v5/transports"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/storage"
|
||||
"github.com/containers/storage/pkg/archive"
|
||||
securejoin "github.com/cyphar/filepath-securejoin"
|
||||
@ -759,6 +759,12 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b
|
||||
s.executor.log(commitMessage)
|
||||
}
|
||||
}
|
||||
logCacheHit := func(cacheID string) {
|
||||
if !s.executor.quiet {
|
||||
cacheHitMessage := "--> Using cache"
|
||||
fmt.Fprintf(s.executor.out, "%s %s\n", cacheHitMessage, cacheID)
|
||||
}
|
||||
}
|
||||
logImageID := func(imgID string) {
|
||||
if s.executor.iidfile == "" {
|
||||
fmt.Fprintf(s.executor.out, "%s\n", imgID)
|
||||
@ -816,6 +822,9 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b
|
||||
if strings.Contains(n, "--from") && (command == "COPY" || command == "ADD") {
|
||||
var mountPoint string
|
||||
arr := strings.Split(n, "=")
|
||||
if len(arr) != 2 {
|
||||
return "", nil, errors.Errorf("%s: invalid --from flag, should be --from=<name|index>", command)
|
||||
}
|
||||
otherStage, ok := s.executor.stages[arr[1]]
|
||||
if !ok {
|
||||
if mountPoint, err = s.getImageRootfs(ctx, stage, arr[1]); err != nil {
|
||||
@ -906,7 +915,7 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b
|
||||
}
|
||||
if cacheID != "" {
|
||||
// Note the cache hit.
|
||||
fmt.Fprintf(s.executor.out, "--> Using cache %s\n", cacheID)
|
||||
logCacheHit(cacheID)
|
||||
} else {
|
||||
// We're not going to find any more cache hits.
|
||||
checkForLayers = false
|
||||
|
11
vendor/github.com/containers/buildah/imagebuildah/util.go
generated
vendored
11
vendor/github.com/containers/buildah/imagebuildah/util.go
generated
vendored
@ -23,8 +23,15 @@ func cloneToDirectory(url, dir string) error {
|
||||
if !strings.HasPrefix(url, "git://") && !strings.HasSuffix(url, ".git") {
|
||||
url = "git://" + url
|
||||
}
|
||||
logrus.Debugf("cloning %q to %q", url, dir)
|
||||
cmd := exec.Command("git", "clone", url, dir)
|
||||
gitBranch := strings.Split(url, "#")
|
||||
var cmd *exec.Cmd
|
||||
if len(gitBranch) < 2 {
|
||||
logrus.Debugf("cloning %q to %q", url, dir)
|
||||
cmd = exec.Command("git", "clone", url, dir)
|
||||
} else {
|
||||
logrus.Debugf("cloning repo %q and branch %q to %q", gitBranch[0], gitBranch[1], dir)
|
||||
cmd = exec.Command("git", "clone", "-b", gitBranch[1], gitBranch[0], dir)
|
||||
}
|
||||
return cmd.Run()
|
||||
}
|
||||
|
||||
|
6
vendor/github.com/containers/buildah/import.go
generated
vendored
6
vendor/github.com/containers/buildah/import.go
generated
vendored
@ -5,9 +5,9 @@ import (
|
||||
|
||||
"github.com/containers/buildah/docker"
|
||||
"github.com/containers/buildah/util"
|
||||
"github.com/containers/image/v4/manifest"
|
||||
is "github.com/containers/image/v4/storage"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
is "github.com/containers/image/v5/storage"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/storage"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
|
12
vendor/github.com/containers/buildah/new.go
generated
vendored
12
vendor/github.com/containers/buildah/new.go
generated
vendored
@ -7,12 +7,12 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/containers/buildah/util"
|
||||
"github.com/containers/image/v4/manifest"
|
||||
"github.com/containers/image/v4/pkg/sysregistriesv2"
|
||||
is "github.com/containers/image/v4/storage"
|
||||
"github.com/containers/image/v4/transports"
|
||||
"github.com/containers/image/v4/transports/alltransports"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/pkg/sysregistriesv2"
|
||||
is "github.com/containers/image/v5/storage"
|
||||
"github.com/containers/image/v5/transports"
|
||||
"github.com/containers/image/v5/transports/alltransports"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/storage"
|
||||
"github.com/openshift/imagebuilder"
|
||||
"github.com/pkg/errors"
|
||||
|
28
vendor/github.com/containers/buildah/pkg/blobcache/blobcache.go
generated
vendored
28
vendor/github.com/containers/buildah/pkg/blobcache/blobcache.go
generated
vendored
@ -10,11 +10,11 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/containers/buildah/docker"
|
||||
"github.com/containers/image/v4/docker/reference"
|
||||
"github.com/containers/image/v4/image"
|
||||
"github.com/containers/image/v4/manifest"
|
||||
"github.com/containers/image/v4/transports"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/image"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/transports"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/storage/pkg/archive"
|
||||
"github.com/containers/storage/pkg/ioutils"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
@ -263,14 +263,14 @@ func (s *blobCacheSource) GetSignatures(ctx context.Context, instanceDigest *dig
|
||||
return s.source.GetSignatures(ctx, instanceDigest)
|
||||
}
|
||||
|
||||
func (s *blobCacheSource) LayerInfosForCopy(ctx context.Context) ([]types.BlobInfo, error) {
|
||||
signatures, err := s.source.GetSignatures(ctx, nil)
|
||||
func (s *blobCacheSource) LayerInfosForCopy(ctx context.Context, instanceDigest *digest.Digest) ([]types.BlobInfo, error) {
|
||||
signatures, err := s.source.GetSignatures(ctx, instanceDigest)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error checking if image %q has signatures", transports.ImageName(s.reference))
|
||||
}
|
||||
canReplaceBlobs := !(len(signatures) > 0 && len(signatures[0]) > 0)
|
||||
|
||||
infos, err := s.source.LayerInfosForCopy(ctx)
|
||||
infos, err := s.source.LayerInfosForCopy(ctx, instanceDigest)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error getting layer infos for copying image %q through cache", transports.ImageName(s.reference))
|
||||
}
|
||||
@ -515,7 +515,7 @@ func (d *blobCacheDestination) TryReusingBlob(ctx context.Context, info types.Bl
|
||||
return false, types.BlobInfo{}, nil
|
||||
}
|
||||
|
||||
func (d *blobCacheDestination) PutManifest(ctx context.Context, manifestBytes []byte) error {
|
||||
func (d *blobCacheDestination) PutManifest(ctx context.Context, manifestBytes []byte, instanceDigest *digest.Digest) error {
|
||||
manifestDigest, err := manifest.Digest(manifestBytes)
|
||||
if err != nil {
|
||||
logrus.Warnf("error digesting manifest %q: %v", string(manifestBytes), err)
|
||||
@ -525,13 +525,13 @@ func (d *blobCacheDestination) PutManifest(ctx context.Context, manifestBytes []
|
||||
logrus.Warnf("error saving manifest as %q: %v", filename, err)
|
||||
}
|
||||
}
|
||||
return d.destination.PutManifest(ctx, manifestBytes)
|
||||
return d.destination.PutManifest(ctx, manifestBytes, instanceDigest)
|
||||
}
|
||||
|
||||
func (d *blobCacheDestination) PutSignatures(ctx context.Context, signatures [][]byte) error {
|
||||
return d.destination.PutSignatures(ctx, signatures)
|
||||
func (d *blobCacheDestination) PutSignatures(ctx context.Context, signatures [][]byte, instanceDigest *digest.Digest) error {
|
||||
return d.destination.PutSignatures(ctx, signatures, instanceDigest)
|
||||
}
|
||||
|
||||
func (d *blobCacheDestination) Commit(ctx context.Context) error {
|
||||
return d.destination.Commit(ctx)
|
||||
func (d *blobCacheDestination) Commit(ctx context.Context, unparsedToplevel types.UnparsedImage) error {
|
||||
return d.destination.Commit(ctx, unparsedToplevel)
|
||||
}
|
||||
|
13
vendor/github.com/containers/buildah/pkg/cli/common.go
generated
vendored
13
vendor/github.com/containers/buildah/pkg/cli/common.go
generated
vendored
@ -8,6 +8,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/buildah"
|
||||
@ -95,6 +96,8 @@ type FromAndBudResults struct {
|
||||
Isolation string
|
||||
Memory string
|
||||
MemorySwap string
|
||||
OverrideArch string
|
||||
OverrideOS string
|
||||
SecurityOpt []string
|
||||
ShmSize string
|
||||
Ulimit []string
|
||||
@ -161,7 +164,7 @@ func GetBudFlags(flags *BudResults) pflag.FlagSet {
|
||||
fs.BoolVar(&flags.PullAlways, "pull-always", false, "pull the image, even if a version is present")
|
||||
fs.BoolVarP(&flags.Quiet, "quiet", "q", false, "refrain from announcing build instructions and image read/write progress")
|
||||
fs.BoolVar(&flags.Rm, "rm", true, "Remove intermediate containers after a successful build")
|
||||
fs.StringVar(&flags.Runtime, "runtime", util.Runtime(), "`path` to an alternate runtime. Use BUILDAH_RUNTIME environment variable to override.")
|
||||
// "runtime" definition moved to avoid name collision in podman build. Defined in cmd/buildah/bud.go.
|
||||
fs.StringSliceVar(&flags.RuntimeFlags, "runtime-flag", []string{}, "add global flags for the container runtime")
|
||||
fs.StringVar(&flags.SignaturePolicy, "signature-policy", "", "`pathname` of signature policy file (not usually used)")
|
||||
fs.BoolVar(&flags.Squash, "squash", false, "Squash newly built layers into a single new layer.")
|
||||
@ -194,6 +197,14 @@ func GetFromAndBudFlags(flags *FromAndBudResults, usernsResults *UserNSResults,
|
||||
fs.StringVar(&flags.Isolation, "isolation", DefaultIsolation(), "`type` of process isolation to use. Use BUILDAH_ISOLATION environment variable to override.")
|
||||
fs.StringVarP(&flags.Memory, "memory", "m", "", "memory limit (format: <number>[<unit>], where unit = b, k, m or g)")
|
||||
fs.StringVar(&flags.MemorySwap, "memory-swap", "", "swap limit equal to memory plus swap: '-1' to enable unlimited swap")
|
||||
fs.StringVar(&flags.OverrideOS, "override-os", runtime.GOOS, "prefer `OS` instead of the running OS when pulling images")
|
||||
if err := fs.MarkHidden("override-os"); err != nil {
|
||||
panic(fmt.Sprintf("error marking override-os as hidden: %v", err))
|
||||
}
|
||||
fs.StringVar(&flags.OverrideArch, "override-arch", runtime.GOARCH, "prefer `ARCH` instead of the architecture of the machine when pulling images")
|
||||
if err := fs.MarkHidden("override-arch"); err != nil {
|
||||
panic(fmt.Sprintf("error marking override-arch as hidden: %v", err))
|
||||
}
|
||||
fs.StringArrayVar(&flags.SecurityOpt, "security-opt", []string{}, "security options (default [])")
|
||||
fs.StringVar(&flags.ShmSize, "shm-size", "65536k", "size of '/dev/shm'. The format is `<number><unit>`.")
|
||||
fs.StringSliceVar(&flags.Ulimit, "ulimit", []string{}, "ulimit options (default [])")
|
||||
|
8
vendor/github.com/containers/buildah/pkg/parse/parse.go
generated
vendored
8
vendor/github.com/containers/buildah/pkg/parse/parse.go
generated
vendored
@ -14,7 +14,7 @@ import (
|
||||
"unicode"
|
||||
|
||||
"github.com/containers/buildah"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/storage/pkg/idtools"
|
||||
units "github.com/docker/go-units"
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
@ -583,6 +583,12 @@ func SystemContextFromOptions(c *cobra.Command) (*types.SystemContext, error) {
|
||||
ctx.RegistriesDirPath = regConfDir
|
||||
}
|
||||
ctx.DockerRegistryUserAgent = fmt.Sprintf("Buildah/%s", buildah.Version)
|
||||
if os, err := c.Flags().GetString("override-os"); err == nil {
|
||||
ctx.OSChoice = os
|
||||
}
|
||||
if arch, err := c.Flags().GetString("override-arch"); err == nil {
|
||||
ctx.ArchitectureChoice = arch
|
||||
}
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
|
38
vendor/github.com/containers/buildah/pkg/parse/parse_unix.go
generated
vendored
38
vendor/github.com/containers/buildah/pkg/parse/parse_unix.go
generated
vendored
@ -4,6 +4,8 @@ package parse
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/containers/buildah/pkg/unshare"
|
||||
"github.com/opencontainers/runc/libcontainer/configs"
|
||||
@ -24,18 +26,40 @@ func getDefaultProcessLimits() []string {
|
||||
return defaultLimits
|
||||
}
|
||||
|
||||
func DeviceFromPath(device string) (configs.Device, error) {
|
||||
func DeviceFromPath(device string) ([]configs.Device, error) {
|
||||
var devs []configs.Device
|
||||
src, dst, permissions, err := Device(device)
|
||||
if err != nil {
|
||||
return configs.Device{}, err
|
||||
return nil, err
|
||||
}
|
||||
if unshare.IsRootless() {
|
||||
return configs.Device{}, errors.Errorf("Renaming device %s to %s is not a supported in rootless containers", src, dst)
|
||||
return nil, errors.Errorf("Renaming device %s to %s is not a supported in rootless containers", src, dst)
|
||||
}
|
||||
dev, err := devices.DeviceFromPath(src, permissions)
|
||||
srcInfo, err := os.Stat(src)
|
||||
if err != nil {
|
||||
return configs.Device{}, errors.Wrapf(err, "%s is not a valid device", src)
|
||||
return nil, errors.Wrapf(err, "error getting info of source device %s", src)
|
||||
}
|
||||
dev.Path = dst
|
||||
return *dev, nil
|
||||
|
||||
if !srcInfo.IsDir() {
|
||||
|
||||
dev, err := devices.DeviceFromPath(src, permissions)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "%s is not a valid device", src)
|
||||
}
|
||||
dev.Path = dst
|
||||
devs = append(devs, *dev)
|
||||
return devs, nil
|
||||
}
|
||||
|
||||
// If source device is a directory
|
||||
srcDevices, err := devices.GetDevices(src)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error getting source devices from directory %s", src)
|
||||
}
|
||||
for _, d := range srcDevices {
|
||||
d.Path = filepath.Join(dst, filepath.Base(d.Path))
|
||||
d.Permissions = permissions
|
||||
devs = append(devs, *d)
|
||||
}
|
||||
return devs, nil
|
||||
}
|
||||
|
24
vendor/github.com/containers/buildah/pull.go
generated
vendored
24
vendor/github.com/containers/buildah/pull.go
generated
vendored
@ -8,18 +8,18 @@ import (
|
||||
|
||||
"github.com/containers/buildah/pkg/blobcache"
|
||||
"github.com/containers/buildah/util"
|
||||
cp "github.com/containers/image/v4/copy"
|
||||
"github.com/containers/image/v4/directory"
|
||||
"github.com/containers/image/v4/docker"
|
||||
dockerarchive "github.com/containers/image/v4/docker/archive"
|
||||
"github.com/containers/image/v4/docker/reference"
|
||||
tarfile "github.com/containers/image/v4/docker/tarfile"
|
||||
ociarchive "github.com/containers/image/v4/oci/archive"
|
||||
oci "github.com/containers/image/v4/oci/layout"
|
||||
"github.com/containers/image/v4/signature"
|
||||
is "github.com/containers/image/v4/storage"
|
||||
"github.com/containers/image/v4/transports"
|
||||
"github.com/containers/image/v4/types"
|
||||
cp "github.com/containers/image/v5/copy"
|
||||
"github.com/containers/image/v5/directory"
|
||||
"github.com/containers/image/v5/docker"
|
||||
dockerarchive "github.com/containers/image/v5/docker/archive"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
tarfile "github.com/containers/image/v5/docker/tarfile"
|
||||
ociarchive "github.com/containers/image/v5/oci/archive"
|
||||
oci "github.com/containers/image/v5/oci/layout"
|
||||
"github.com/containers/image/v5/signature"
|
||||
is "github.com/containers/image/v5/storage"
|
||||
"github.com/containers/image/v5/transports"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/storage"
|
||||
multierror "github.com/hashicorp/go-multierror"
|
||||
"github.com/pkg/errors"
|
||||
|
6
vendor/github.com/containers/buildah/util.go
generated
vendored
6
vendor/github.com/containers/buildah/util.go
generated
vendored
@ -8,9 +8,9 @@ import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/containers/buildah/util"
|
||||
"github.com/containers/image/v4/docker/reference"
|
||||
"github.com/containers/image/v4/pkg/sysregistriesv2"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/pkg/sysregistriesv2"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/storage"
|
||||
"github.com/containers/storage/pkg/archive"
|
||||
"github.com/containers/storage/pkg/chrootarchive"
|
||||
|
12
vendor/github.com/containers/buildah/util/util.go
generated
vendored
12
vendor/github.com/containers/buildah/util/util.go
generated
vendored
@ -10,12 +10,12 @@ import (
|
||||
"syscall"
|
||||
|
||||
"github.com/containers/buildah/pkg/cgroups"
|
||||
"github.com/containers/image/v4/docker/reference"
|
||||
"github.com/containers/image/v4/pkg/sysregistriesv2"
|
||||
"github.com/containers/image/v4/signature"
|
||||
is "github.com/containers/image/v4/storage"
|
||||
"github.com/containers/image/v4/transports"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/pkg/sysregistriesv2"
|
||||
"github.com/containers/image/v5/signature"
|
||||
is "github.com/containers/image/v5/storage"
|
||||
"github.com/containers/image/v5/transports"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/storage"
|
||||
"github.com/docker/distribution/registry/api/errcode"
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
|
94
vendor/github.com/containers/image/v4/image/docker_list.go
generated
vendored
94
vendor/github.com/containers/image/v4/image/docker_list.go
generated
vendored
@ -1,94 +0,0 @@
|
||||
package image
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
"github.com/containers/image/v4/manifest"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type platformSpec struct {
|
||||
Architecture string `json:"architecture"`
|
||||
OS string `json:"os"`
|
||||
OSVersion string `json:"os.version,omitempty"`
|
||||
OSFeatures []string `json:"os.features,omitempty"`
|
||||
Variant string `json:"variant,omitempty"`
|
||||
Features []string `json:"features,omitempty"` // removed in OCI
|
||||
}
|
||||
|
||||
// A manifestDescriptor references a platform-specific manifest.
|
||||
type manifestDescriptor struct {
|
||||
manifest.Schema2Descriptor
|
||||
Platform platformSpec `json:"platform"`
|
||||
}
|
||||
|
||||
type manifestList struct {
|
||||
SchemaVersion int `json:"schemaVersion"`
|
||||
MediaType string `json:"mediaType"`
|
||||
Manifests []manifestDescriptor `json:"manifests"`
|
||||
}
|
||||
|
||||
// chooseDigestFromManifestList parses blob as a schema2 manifest list,
|
||||
// and returns the digest of the image appropriate for the current environment.
|
||||
func chooseDigestFromManifestList(sys *types.SystemContext, blob []byte) (digest.Digest, error) {
|
||||
wantedArch := runtime.GOARCH
|
||||
if sys != nil && sys.ArchitectureChoice != "" {
|
||||
wantedArch = sys.ArchitectureChoice
|
||||
}
|
||||
wantedOS := runtime.GOOS
|
||||
if sys != nil && sys.OSChoice != "" {
|
||||
wantedOS = sys.OSChoice
|
||||
}
|
||||
|
||||
list := manifestList{}
|
||||
if err := json.Unmarshal(blob, &list); err != nil {
|
||||
return "", err
|
||||
}
|
||||
for _, d := range list.Manifests {
|
||||
if d.Platform.Architecture == wantedArch && d.Platform.OS == wantedOS {
|
||||
return d.Digest, nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("no image found in manifest list for architecture %s, OS %s", wantedArch, wantedOS)
|
||||
}
|
||||
|
||||
func manifestSchema2FromManifestList(ctx context.Context, sys *types.SystemContext, src types.ImageSource, manblob []byte) (genericManifest, error) {
|
||||
targetManifestDigest, err := chooseDigestFromManifestList(sys, manblob)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
manblob, mt, err := src.GetManifest(ctx, &targetManifestDigest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
matches, err := manifest.MatchesDigest(manblob, targetManifestDigest)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Error computing manifest digest")
|
||||
}
|
||||
if !matches {
|
||||
return nil, errors.Errorf("Manifest image does not match selected manifest digest %s", targetManifestDigest)
|
||||
}
|
||||
|
||||
return manifestInstanceFromBlob(ctx, sys, src, manblob, mt)
|
||||
}
|
||||
|
||||
// ChooseManifestInstanceFromManifestList returns a digest of a manifest appropriate
|
||||
// for the current system from the manifest available from src.
|
||||
func ChooseManifestInstanceFromManifestList(ctx context.Context, sys *types.SystemContext, src types.UnparsedImage) (digest.Digest, error) {
|
||||
// For now this only handles manifest.DockerV2ListMediaType; we can generalize it later,
|
||||
// probably along with manifest list editing.
|
||||
blob, mt, err := src.Manifest(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if mt != manifest.DockerV2ListMediaType {
|
||||
return "", fmt.Errorf("Internal error: Trying to select an image from a non-manifest-list manifest type %s", mt)
|
||||
}
|
||||
return chooseDigestFromManifestList(sys, blob)
|
||||
}
|
@ -13,15 +13,16 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/containers/image/v4/docker/reference"
|
||||
"github.com/containers/image/v4/image"
|
||||
"github.com/containers/image/v4/manifest"
|
||||
"github.com/containers/image/v4/pkg/blobinfocache"
|
||||
"github.com/containers/image/v4/pkg/compression"
|
||||
"github.com/containers/image/v4/signature"
|
||||
"github.com/containers/image/v4/transports"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/image"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/pkg/blobinfocache"
|
||||
"github.com/containers/image/v5/pkg/compression"
|
||||
"github.com/containers/image/v5/signature"
|
||||
"github.com/containers/image/v5/transports"
|
||||
"github.com/containers/image/v5/types"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vbauerster/mpb"
|
||||
@ -110,6 +111,37 @@ type imageCopier struct {
|
||||
canSubstituteBlobs bool
|
||||
}
|
||||
|
||||
const (
|
||||
// CopySystemImage is the default value which, when set in
|
||||
// Options.ImageListSelection, indicates that the caller expects only one
|
||||
// image to be copied, so if the source reference refers to a list of
|
||||
// images, one that matches the current system will be selected.
|
||||
CopySystemImage ImageListSelection = iota
|
||||
// CopyAllImages is a value which, when set in Options.ImageListSelection,
|
||||
// indicates that the caller expects to copy multiple images, and if
|
||||
// the source reference refers to a list, that the list and every image
|
||||
// to which it refers will be copied. If the source reference refers
|
||||
// to a list, the target reference can not accept lists, an error
|
||||
// should be returned.
|
||||
CopyAllImages
|
||||
// CopySpecificImages is a value which, when set in
|
||||
// Options.ImageListSelection, indicates that the caller expects the
|
||||
// source reference to be either a single image or a list of images,
|
||||
// and if the source reference is a list, wants only specific instances
|
||||
// from it copied (or none of them, if the list of instances to copy is
|
||||
// empty), along with the list itself. If the target reference can
|
||||
// only accept one image (i.e., it cannot accept lists), an error
|
||||
// should be returned.
|
||||
CopySpecificImages
|
||||
)
|
||||
|
||||
// ImageListSelection is one of CopySystemImage, CopyAllImages, or
|
||||
// CopySpecificImages, to control whether, when the source reference is a list,
|
||||
// copy.Image() copies only an image which matches the current runtime
|
||||
// environment, or all images which match the supplied reference, or only
|
||||
// specific images from the source reference.
|
||||
type ImageListSelection int
|
||||
|
||||
// Options allows supplying non-default configuration modifying the behavior of CopyImage.
|
||||
type Options struct {
|
||||
RemoveSignatures bool // Remove any pre-existing signatures. SignBy will still add a new signature.
|
||||
@ -121,12 +153,24 @@ type Options struct {
|
||||
Progress chan types.ProgressProperties // Reported to when ProgressInterval has arrived for a single artifact+offset.
|
||||
// manifest MIME type of image set by user. "" is default and means use the autodetection to the the manifest MIME type
|
||||
ForceManifestMIMEType string
|
||||
ImageListSelection ImageListSelection // set to either CopySystemImage (the default), CopyAllImages, or CopySpecificImages to control which instances we copy when the source reference is a list; ignored if the source reference is not a list
|
||||
Instances []digest.Digest // if ImageListSelection is CopySpecificImages, copy only these instances and the list itself
|
||||
}
|
||||
|
||||
// validateImageListSelection returns an error if the passed-in value is not one that we recognize as a valid ImageListSelection value
|
||||
func validateImageListSelection(selection ImageListSelection) error {
|
||||
switch selection {
|
||||
case CopySystemImage, CopyAllImages, CopySpecificImages:
|
||||
return nil
|
||||
default:
|
||||
return errors.Errorf("Invalid value for options.ImageListSelection: %d", selection)
|
||||
}
|
||||
}
|
||||
|
||||
// Image copies image from srcRef to destRef, using policyContext to validate
|
||||
// source image admissibility. It returns the manifest which was written to
|
||||
// the new copy of the image.
|
||||
func Image(ctx context.Context, policyContext *signature.PolicyContext, destRef, srcRef types.ImageReference, options *Options) (manifest []byte, retErr error) {
|
||||
func Image(ctx context.Context, policyContext *signature.PolicyContext, destRef, srcRef types.ImageReference, options *Options) (copiedManifest []byte, retErr error) {
|
||||
// NOTE this function uses an output parameter for the error return value.
|
||||
// Setting this and returning is the ideal way to return an error.
|
||||
//
|
||||
@ -136,6 +180,10 @@ func Image(ctx context.Context, policyContext *signature.PolicyContext, destRef,
|
||||
options = &Options{}
|
||||
}
|
||||
|
||||
if err := validateImageListSelection(options.ImageListSelection); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
reportWriter := ioutil.Discard
|
||||
|
||||
if options.ReportWriter != nil {
|
||||
@ -206,79 +254,278 @@ func Image(ctx context.Context, policyContext *signature.PolicyContext, destRef,
|
||||
}
|
||||
|
||||
if !multiImage {
|
||||
// The simple case: Just copy a single image.
|
||||
if manifest, err = c.copyOneImage(ctx, policyContext, options, unparsedToplevel); err != nil {
|
||||
// The simple case: just copy a single image.
|
||||
if copiedManifest, _, _, err = c.copyOneImage(ctx, policyContext, options, unparsedToplevel, unparsedToplevel, nil); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
// This is a manifest list. Choose a single image and copy it.
|
||||
// FIXME: Copy to destinations which support manifest lists, one image at a time.
|
||||
instanceDigest, err := image.ChooseManifestInstanceFromManifestList(ctx, options.SourceCtx, unparsedToplevel)
|
||||
} else if options.ImageListSelection == CopySystemImage {
|
||||
// This is a manifest list, and we weren't asked to copy multiple images. Choose a single image that
|
||||
// matches the current system to copy, and copy it.
|
||||
mfest, manifestType, err := unparsedToplevel.Manifest(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Error reading manifest for %s", transports.ImageName(srcRef))
|
||||
}
|
||||
manifestList, err := manifest.ListFromBlob(mfest, manifestType)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Error parsing primary manifest as list for %s", transports.ImageName(srcRef))
|
||||
}
|
||||
instanceDigest, err := manifestList.ChooseInstance(options.SourceCtx) // try to pick one that matches options.SourceCtx
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Error choosing an image from manifest list %s", transports.ImageName(srcRef))
|
||||
}
|
||||
logrus.Debugf("Source is a manifest list; copying (only) instance %s", instanceDigest)
|
||||
logrus.Debugf("Source is a manifest list; copying (only) instance %s for current system", instanceDigest)
|
||||
unparsedInstance := image.UnparsedInstance(rawSource, &instanceDigest)
|
||||
|
||||
if manifest, err = c.copyOneImage(ctx, policyContext, options, unparsedInstance); err != nil {
|
||||
if copiedManifest, _, _, err = c.copyOneImage(ctx, policyContext, options, unparsedToplevel, unparsedInstance, nil); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else { /* options.ImageListSelection == CopyAllImages or options.ImageListSelection == CopySpecificImages, */
|
||||
// If we were asked to copy multiple images and can't, that's an error.
|
||||
if !supportsMultipleImages(c.dest) {
|
||||
return nil, errors.Errorf("Error copying multiple images: destination transport %q does not support copying multiple images as a group", destRef.Transport().Name())
|
||||
}
|
||||
// Copy some or all of the images.
|
||||
switch options.ImageListSelection {
|
||||
case CopyAllImages:
|
||||
logrus.Debugf("Source is a manifest list; copying all instances")
|
||||
case CopySpecificImages:
|
||||
logrus.Debugf("Source is a manifest list; copying some instances")
|
||||
}
|
||||
if copiedManifest, _, err = c.copyMultipleImages(ctx, policyContext, options, unparsedToplevel); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if err := c.dest.Commit(ctx); err != nil {
|
||||
if err := c.dest.Commit(ctx, unparsedToplevel); err != nil {
|
||||
return nil, errors.Wrap(err, "Error committing the finished image")
|
||||
}
|
||||
|
||||
return manifest, nil
|
||||
return copiedManifest, nil
|
||||
}
|
||||
|
||||
// Image copies a single (on-manifest-list) image unparsedImage, using policyContext to validate
|
||||
// Checks if the destination supports accepting multiple images by checking if it can support
|
||||
// manifest types that are lists of other manifests.
|
||||
func supportsMultipleImages(dest types.ImageDestination) bool {
|
||||
mtypes := dest.SupportedManifestMIMETypes()
|
||||
if len(mtypes) == 0 {
|
||||
// Anything goes!
|
||||
return true
|
||||
}
|
||||
for _, mtype := range mtypes {
|
||||
if manifest.MIMETypeIsMultiImage(mtype) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// copyMultipleImages copies some or all of an image list's instances, using
|
||||
// policyContext to validate source image admissibility.
|
||||
func (c *copier) copyMultipleImages(ctx context.Context, policyContext *signature.PolicyContext, options *Options, unparsedToplevel *image.UnparsedImage) (copiedManifest []byte, copiedManifestType string, retErr error) {
|
||||
// Parse the list and get a copy of the original value after it's re-encoded.
|
||||
manifestList, manifestType, err := unparsedToplevel.Manifest(ctx)
|
||||
if err != nil {
|
||||
return nil, "", errors.Wrapf(err, "Error reading manifest list")
|
||||
}
|
||||
list, err := manifest.ListFromBlob(manifestList, manifestType)
|
||||
if err != nil {
|
||||
return nil, "", errors.Wrapf(err, "Error parsing manifest list %q", string(manifestList))
|
||||
}
|
||||
originalList := list.Clone()
|
||||
|
||||
// Read and/or clear the set of signatures for this list.
|
||||
var sigs [][]byte
|
||||
if options.RemoveSignatures {
|
||||
sigs = [][]byte{}
|
||||
} else {
|
||||
c.Printf("Getting image list signatures\n")
|
||||
s, err := c.rawSource.GetSignatures(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, "", errors.Wrap(err, "Error reading signatures")
|
||||
}
|
||||
sigs = s
|
||||
}
|
||||
if len(sigs) != 0 {
|
||||
c.Printf("Checking if image list destination supports signatures\n")
|
||||
if err := c.dest.SupportsSignatures(ctx); err != nil {
|
||||
return nil, "", errors.Wrap(err, "Can not copy signatures")
|
||||
}
|
||||
}
|
||||
|
||||
// Determine if we'll need to convert the manifest list to a different format.
|
||||
forceListMIMEType := options.ForceManifestMIMEType
|
||||
switch forceListMIMEType {
|
||||
case manifest.DockerV2Schema1MediaType, manifest.DockerV2Schema1SignedMediaType, manifest.DockerV2Schema2MediaType:
|
||||
forceListMIMEType = manifest.DockerV2ListMediaType
|
||||
case imgspecv1.MediaTypeImageManifest:
|
||||
forceListMIMEType = imgspecv1.MediaTypeImageIndex
|
||||
}
|
||||
selectedListType, err := c.determineListConversion(manifestType, c.dest.SupportedManifestMIMETypes(), forceListMIMEType)
|
||||
if err != nil {
|
||||
return nil, "", errors.Wrapf(err, "Error determining manifest list type to write to destination")
|
||||
}
|
||||
if selectedListType != list.MIMEType() {
|
||||
canModifyManifestList := (len(sigs) == 0)
|
||||
if !canModifyManifestList {
|
||||
return nil, "", errors.Errorf("Error: manifest list must be converted to type %q to be written to destination, but that would invalidate signatures", selectedListType)
|
||||
}
|
||||
}
|
||||
|
||||
// Copy each image, or just the ones we want to copy, in turn.
|
||||
instanceDigests := list.Instances()
|
||||
imagesToCopy := len(instanceDigests)
|
||||
if options.ImageListSelection == CopySpecificImages {
|
||||
imagesToCopy = len(options.Instances)
|
||||
}
|
||||
c.Printf("Copying %d of %d images in list\n", imagesToCopy, len(instanceDigests))
|
||||
updates := make([]manifest.ListUpdate, len(instanceDigests))
|
||||
instancesCopied := 0
|
||||
for i, instanceDigest := range instanceDigests {
|
||||
if options.ImageListSelection == CopySpecificImages {
|
||||
skip := true
|
||||
for _, instance := range options.Instances {
|
||||
if instance == instanceDigest {
|
||||
skip = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if skip {
|
||||
update, err := list.Instance(instanceDigest)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
logrus.Debugf("Skipping instance %s (%d/%d)", instanceDigest, i+1, len(instanceDigests))
|
||||
// Record the digest/size/type of the manifest that we didn't copy.
|
||||
updates[i] = update
|
||||
continue
|
||||
}
|
||||
}
|
||||
logrus.Debugf("Copying instance %s (%d/%d)", instanceDigest, i+1, len(instanceDigests))
|
||||
c.Printf("Copying image %s (%d/%d)\n", instanceDigest, instancesCopied+1, imagesToCopy)
|
||||
unparsedInstance := image.UnparsedInstance(c.rawSource, &instanceDigest)
|
||||
updatedManifest, updatedManifestType, updatedManifestDigest, err := c.copyOneImage(ctx, policyContext, options, unparsedToplevel, unparsedInstance, &instanceDigest)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
instancesCopied++
|
||||
// Record the result of a possible conversion here.
|
||||
update := manifest.ListUpdate{
|
||||
Digest: updatedManifestDigest,
|
||||
Size: int64(len(updatedManifest)),
|
||||
MediaType: updatedManifestType,
|
||||
}
|
||||
updates[i] = update
|
||||
}
|
||||
|
||||
// Now reset the digest/size/types of the manifests in the list to account for any conversions that we made.
|
||||
if err = list.UpdateInstances(updates); err != nil {
|
||||
return nil, "", errors.Wrapf(err, "Error updating manifest list")
|
||||
}
|
||||
|
||||
// Check if the updates meaningfully changed the list of images.
|
||||
listIsModified := false
|
||||
if !reflect.DeepEqual(list.Instances(), originalList.Instances()) {
|
||||
listIsModified = true
|
||||
}
|
||||
|
||||
// Perform the list conversion.
|
||||
if selectedListType != list.MIMEType() {
|
||||
list, err = list.ConvertToMIMEType(selectedListType)
|
||||
if err != nil {
|
||||
return nil, "", errors.Wrapf(err, "Error converting manifest list to list with MIME type %q", selectedListType)
|
||||
}
|
||||
}
|
||||
|
||||
// If we can't use the original value, but we have to change it, flag an error.
|
||||
if listIsModified {
|
||||
manifestList, err = list.Serialize()
|
||||
if err != nil {
|
||||
return nil, "", errors.Wrapf(err, "Error encoding updated manifest list (%q: %#v)", list.MIMEType(), list.Instances())
|
||||
}
|
||||
logrus.Debugf("Manifest list has been updated")
|
||||
}
|
||||
|
||||
// Save the manifest list.
|
||||
c.Printf("Writing manifest list to image destination\n")
|
||||
if err = c.dest.PutManifest(ctx, manifestList, nil); err != nil {
|
||||
return nil, "", errors.Wrapf(err, "Error writing manifest list %q", string(manifestList))
|
||||
}
|
||||
|
||||
// Sign the manifest list.
|
||||
if options.SignBy != "" {
|
||||
newSig, err := c.createSignature(manifestList, options.SignBy)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
sigs = append(sigs, newSig)
|
||||
}
|
||||
|
||||
c.Printf("Storing list signatures\n")
|
||||
if err := c.dest.PutSignatures(ctx, sigs, nil); err != nil {
|
||||
return nil, "", errors.Wrap(err, "Error writing signatures")
|
||||
}
|
||||
|
||||
return manifestList, selectedListType, nil
|
||||
}
|
||||
|
||||
// copyOneImage copies a single (non-manifest-list) image unparsedImage, using policyContext to validate
|
||||
// source image admissibility.
|
||||
func (c *copier) copyOneImage(ctx context.Context, policyContext *signature.PolicyContext, options *Options, unparsedImage *image.UnparsedImage) (manifestBytes []byte, retErr error) {
|
||||
func (c *copier) copyOneImage(ctx context.Context, policyContext *signature.PolicyContext, options *Options, unparsedToplevel, unparsedImage *image.UnparsedImage, targetInstance *digest.Digest) (retManifest []byte, retManifestType string, retManifestDigest digest.Digest, retErr error) {
|
||||
// The caller is handling manifest lists; this could happen only if a manifest list contains a manifest list.
|
||||
// Make sure we fail cleanly in such cases.
|
||||
multiImage, err := isMultiImage(ctx, unparsedImage)
|
||||
if err != nil {
|
||||
// FIXME FIXME: How to name a reference for the sub-image?
|
||||
return nil, errors.Wrapf(err, "Error determining manifest MIME type for %s", transports.ImageName(unparsedImage.Reference()))
|
||||
return nil, "", "", errors.Wrapf(err, "Error determining manifest MIME type for %s", transports.ImageName(unparsedImage.Reference()))
|
||||
}
|
||||
if multiImage {
|
||||
return nil, fmt.Errorf("Unexpectedly received a manifest list instead of a manifest for a single image")
|
||||
return nil, "", "", fmt.Errorf("Unexpectedly received a manifest list instead of a manifest for a single image")
|
||||
}
|
||||
|
||||
// Please keep this policy check BEFORE reading any other information about the image.
|
||||
// (the multiImage check above only matches the MIME type, which we have received anyway.
|
||||
// (The multiImage check above only matches the MIME type, which we have received anyway.
|
||||
// Actual parsing of anything should be deferred.)
|
||||
if allowed, err := policyContext.IsRunningImageAllowed(ctx, unparsedImage); !allowed || err != nil { // Be paranoid and fail if either return value indicates so.
|
||||
return nil, errors.Wrap(err, "Source image rejected")
|
||||
return nil, "", "", errors.Wrap(err, "Source image rejected")
|
||||
}
|
||||
src, err := image.FromUnparsedImage(ctx, options.SourceCtx, unparsedImage)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Error initializing image from source %s", transports.ImageName(c.rawSource.Reference()))
|
||||
return nil, "", "", errors.Wrapf(err, "Error initializing image from source %s", transports.ImageName(c.rawSource.Reference()))
|
||||
}
|
||||
|
||||
// If the destination is a digested reference, make a note of that, determine what digest value we're
|
||||
// expecting, and check that the source manifest matches it.
|
||||
// expecting, and check that the source manifest matches it. If the source manifest doesn't, but it's
|
||||
// one item from a manifest list that matches it, accept that as a match.
|
||||
destIsDigestedReference := false
|
||||
if named := c.dest.Reference().DockerReference(); named != nil {
|
||||
if digested, ok := named.(reference.Digested); ok {
|
||||
destIsDigestedReference = true
|
||||
sourceManifest, _, err := src.Manifest(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Error reading manifest from source image")
|
||||
return nil, "", "", errors.Wrapf(err, "Error reading manifest from source image")
|
||||
}
|
||||
matches, err := manifest.MatchesDigest(sourceManifest, digested.Digest())
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Error computing digest of source image's manifest")
|
||||
return nil, "", "", errors.Wrapf(err, "Error computing digest of source image's manifest")
|
||||
}
|
||||
if !matches {
|
||||
return nil, errors.New("Digest of source image's manifest would not match destination reference")
|
||||
manifestList, _, err := unparsedToplevel.Manifest(ctx)
|
||||
if err != nil {
|
||||
return nil, "", "", errors.Wrapf(err, "Error reading manifest from source image")
|
||||
}
|
||||
matches, err = manifest.MatchesDigest(manifestList, digested.Digest())
|
||||
if err != nil {
|
||||
return nil, "", "", errors.Wrapf(err, "Error computing digest of source image's manifest")
|
||||
}
|
||||
if !matches {
|
||||
return nil, "", "", errors.New("Digest of source image's manifest would not match destination reference")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := checkImageDestinationForCurrentRuntimeOS(ctx, options.DestinationCtx, src, c.dest); err != nil {
|
||||
return nil, err
|
||||
return nil, "", "", err
|
||||
}
|
||||
|
||||
var sigs [][]byte
|
||||
@ -288,14 +535,14 @@ func (c *copier) copyOneImage(ctx context.Context, policyContext *signature.Poli
|
||||
c.Printf("Getting image source signatures\n")
|
||||
s, err := src.Signatures(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Error reading signatures")
|
||||
return nil, "", "", errors.Wrap(err, "Error reading signatures")
|
||||
}
|
||||
sigs = s
|
||||
}
|
||||
if len(sigs) != 0 {
|
||||
c.Printf("Checking if image destination supports signatures\n")
|
||||
if err := c.dest.SupportsSignatures(ctx); err != nil {
|
||||
return nil, errors.Wrap(err, "Can not copy signatures")
|
||||
return nil, "", "", errors.Wrap(err, "Can not copy signatures")
|
||||
}
|
||||
}
|
||||
|
||||
@ -315,28 +562,29 @@ func (c *copier) copyOneImage(ctx context.Context, policyContext *signature.Poli
|
||||
ic.canSubstituteBlobs = ic.canModifyManifest && options.SignBy == ""
|
||||
|
||||
if err := ic.updateEmbeddedDockerReference(); err != nil {
|
||||
return nil, err
|
||||
return nil, "", "", err
|
||||
}
|
||||
|
||||
// We compute preferredManifestMIMEType only to show it in error messages.
|
||||
// Without having to add this context in an error message, we would be happy enough to know only that no conversion is needed.
|
||||
preferredManifestMIMEType, otherManifestMIMETypeCandidates, err := ic.determineManifestConversion(ctx, c.dest.SupportedManifestMIMETypes(), options.ForceManifestMIMEType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, "", "", err
|
||||
}
|
||||
|
||||
// If src.UpdatedImageNeedsLayerDiffIDs(ic.manifestUpdates) will be true, it needs to be true by the time we get here.
|
||||
ic.diffIDsAreNeeded = src.UpdatedImageNeedsLayerDiffIDs(*ic.manifestUpdates)
|
||||
|
||||
if err := ic.copyLayers(ctx); err != nil {
|
||||
return nil, err
|
||||
return nil, "", "", err
|
||||
}
|
||||
|
||||
// With docker/distribution registries we do not know whether the registry accepts schema2 or schema1 only;
|
||||
// and at least with the OpenShift registry "acceptschema2" option, there is no way to detect the support
|
||||
// without actually trying to upload something and getting a types.ManifestTypeRejectedError.
|
||||
// So, try the preferred manifest MIME type. If the process succeeds, fine…
|
||||
manifestBytes, err = ic.copyUpdatedConfigAndManifest(ctx)
|
||||
manifestBytes, retManifestDigest, err := ic.copyUpdatedConfigAndManifest(ctx, targetInstance)
|
||||
retManifestType = preferredManifestMIMEType
|
||||
if err != nil {
|
||||
logrus.Debugf("Writing manifest using preferred type %s failed: %v", preferredManifestMIMEType, err)
|
||||
// … if it fails, _and_ the failure is because the manifest is rejected, we may have other options.
|
||||
@ -344,14 +592,14 @@ func (c *copier) copyOneImage(ctx context.Context, policyContext *signature.Poli
|
||||
// We don’t have other options.
|
||||
// In principle the code below would handle this as well, but the resulting error message is fairly ugly.
|
||||
// Don’t bother the user with MIME types if we have no choice.
|
||||
return nil, err
|
||||
return nil, "", "", err
|
||||
}
|
||||
// If the original MIME type is acceptable, determineManifestConversion always uses it as preferredManifestMIMEType.
|
||||
// So if we are here, we will definitely be trying to convert the manifest.
|
||||
// With !ic.canModifyManifest, that would just be a string of repeated failures for the same reason,
|
||||
// so let’s bail out early and with a better error message.
|
||||
if !ic.canModifyManifest {
|
||||
return nil, errors.Wrap(err, "Writing manifest failed (and converting it is not possible)")
|
||||
return nil, "", "", errors.Wrap(err, "Writing manifest failed (and converting it is not possible)")
|
||||
}
|
||||
|
||||
// errs is a list of errors when trying various manifest types. Also serves as an "upload succeeded" flag when set to nil.
|
||||
@ -359,7 +607,7 @@ func (c *copier) copyOneImage(ctx context.Context, policyContext *signature.Poli
|
||||
for _, manifestMIMEType := range otherManifestMIMETypeCandidates {
|
||||
logrus.Debugf("Trying to use manifest type %s…", manifestMIMEType)
|
||||
ic.manifestUpdates.ManifestMIMEType = manifestMIMEType
|
||||
attemptedManifest, err := ic.copyUpdatedConfigAndManifest(ctx)
|
||||
attemptedManifest, attemptedManifestDigest, err := ic.copyUpdatedConfigAndManifest(ctx, targetInstance)
|
||||
if err != nil {
|
||||
logrus.Debugf("Upload of manifest type %s failed: %v", manifestMIMEType, err)
|
||||
errs = append(errs, fmt.Sprintf("%s(%v)", manifestMIMEType, err))
|
||||
@ -368,28 +616,30 @@ func (c *copier) copyOneImage(ctx context.Context, policyContext *signature.Poli
|
||||
|
||||
// We have successfully uploaded a manifest.
|
||||
manifestBytes = attemptedManifest
|
||||
retManifestDigest = attemptedManifestDigest
|
||||
retManifestType = manifestMIMEType
|
||||
errs = nil // Mark this as a success so that we don't abort below.
|
||||
break
|
||||
}
|
||||
if errs != nil {
|
||||
return nil, fmt.Errorf("Uploading manifest failed, attempted the following formats: %s", strings.Join(errs, ", "))
|
||||
return nil, "", "", fmt.Errorf("Uploading manifest failed, attempted the following formats: %s", strings.Join(errs, ", "))
|
||||
}
|
||||
}
|
||||
|
||||
if options.SignBy != "" {
|
||||
newSig, err := c.createSignature(manifestBytes, options.SignBy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, "", "", err
|
||||
}
|
||||
sigs = append(sigs, newSig)
|
||||
}
|
||||
|
||||
c.Printf("Storing signatures\n")
|
||||
if err := c.dest.PutSignatures(ctx, sigs); err != nil {
|
||||
return nil, errors.Wrap(err, "Error writing signatures")
|
||||
if err := c.dest.PutSignatures(ctx, sigs, targetInstance); err != nil {
|
||||
return nil, "", "", errors.Wrap(err, "Error writing signatures")
|
||||
}
|
||||
|
||||
return manifestBytes, nil
|
||||
return manifestBytes, retManifestType, retManifestDigest, nil
|
||||
}
|
||||
|
||||
// Printf writes a formatted string to c.reportWriter.
|
||||
@ -554,12 +804,13 @@ func layerDigestsDiffer(a, b []types.BlobInfo) bool {
|
||||
}
|
||||
|
||||
// copyUpdatedConfigAndManifest updates the image per ic.manifestUpdates, if necessary,
|
||||
// stores the resulting config and manifest to the destination, and returns the stored manifest.
|
||||
func (ic *imageCopier) copyUpdatedConfigAndManifest(ctx context.Context) ([]byte, error) {
|
||||
// stores the resulting config and manifest to the destination, and returns the stored manifest
|
||||
// and its digest.
|
||||
func (ic *imageCopier) copyUpdatedConfigAndManifest(ctx context.Context, instanceDigest *digest.Digest) ([]byte, digest.Digest, error) {
|
||||
pendingImage := ic.src
|
||||
if !reflect.DeepEqual(*ic.manifestUpdates, types.ManifestUpdateOptions{InformationOnly: ic.manifestUpdates.InformationOnly}) {
|
||||
if !ic.canModifyManifest {
|
||||
return nil, errors.Errorf("Internal error: copy needs an updated manifest but that was known to be forbidden")
|
||||
return nil, "", errors.Errorf("Internal error: copy needs an updated manifest but that was known to be forbidden")
|
||||
}
|
||||
if !ic.diffIDsAreNeeded && ic.src.UpdatedImageNeedsLayerDiffIDs(*ic.manifestUpdates) {
|
||||
// We have set ic.diffIDsAreNeeded based on the preferred MIME type returned by determineManifestConversion.
|
||||
@ -568,28 +819,35 @@ func (ic *imageCopier) copyUpdatedConfigAndManifest(ctx context.Context) ([]byte
|
||||
// when ic.c.dest.SupportedManifestMIMETypes() includes both s1 and s2, the upload using s1 failed, and we are now trying s2.
|
||||
// Supposedly s2-only registries do not exist or are extremely rare, so failing with this error message is good enough for now.
|
||||
// If handling such registries turns out to be necessary, we could compute ic.diffIDsAreNeeded based on the full list of manifest MIME type candidates.
|
||||
return nil, errors.Errorf("Can not convert image to %s, preparing DiffIDs for this case is not supported", ic.manifestUpdates.ManifestMIMEType)
|
||||
return nil, "", errors.Errorf("Can not convert image to %s, preparing DiffIDs for this case is not supported", ic.manifestUpdates.ManifestMIMEType)
|
||||
}
|
||||
pi, err := ic.src.UpdatedImage(ctx, *ic.manifestUpdates)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Error creating an updated image manifest")
|
||||
return nil, "", errors.Wrap(err, "Error creating an updated image manifest")
|
||||
}
|
||||
pendingImage = pi
|
||||
}
|
||||
manifest, _, err := pendingImage.Manifest(ctx)
|
||||
man, _, err := pendingImage.Manifest(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Error reading manifest")
|
||||
return nil, "", errors.Wrap(err, "Error reading manifest")
|
||||
}
|
||||
|
||||
if err := ic.c.copyConfig(ctx, pendingImage); err != nil {
|
||||
return nil, err
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
ic.c.Printf("Writing manifest to image destination\n")
|
||||
if err := ic.c.dest.PutManifest(ctx, manifest); err != nil {
|
||||
return nil, errors.Wrap(err, "Error writing manifest")
|
||||
manifestDigest, err := manifest.Digest(man)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return manifest, nil
|
||||
if instanceDigest != nil {
|
||||
instanceDigest = &manifestDigest
|
||||
}
|
||||
if err := ic.c.dest.PutManifest(ctx, man, instanceDigest); err != nil {
|
||||
return nil, "", errors.Wrap(err, "Error writing manifest")
|
||||
}
|
||||
return man, manifestDigest, nil
|
||||
}
|
||||
|
||||
// newProgressPool creates a *mpb.Progress and a cleanup function.
|
@ -4,8 +4,8 @@ import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/image/v4/manifest"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
@ -119,3 +119,36 @@ func isMultiImage(ctx context.Context, img types.UnparsedImage) (bool, error) {
|
||||
}
|
||||
return manifest.MIMETypeIsMultiImage(mt), nil
|
||||
}
|
||||
|
||||
// determineListConversion takes the current MIME type of a list of manifests,
|
||||
// the list of MIME types supported for a given destination, and a possible
|
||||
// forced value, and returns the MIME type to which we should convert the list
|
||||
// of manifests, whether we are converting to it or using it unmodified.
|
||||
func (c *copier) determineListConversion(currentListMIMEType string, destSupportedMIMETypes []string, forcedListMIMEType string) (string, error) {
|
||||
// If we're forcing it, we prefer the forced value over everything else.
|
||||
if forcedListMIMEType != "" {
|
||||
return forcedListMIMEType, nil
|
||||
}
|
||||
// If there's no list of supported types, then anything we support is expected to be supported.
|
||||
if len(destSupportedMIMETypes) == 0 {
|
||||
destSupportedMIMETypes = manifest.SupportedListMIMETypes
|
||||
}
|
||||
var selectedType string
|
||||
for i := range destSupportedMIMETypes {
|
||||
// The second priority is the first member of the list of acceptable types that is a list,
|
||||
// but keep going in case current type occurs later in the list.
|
||||
if selectedType == "" && manifest.MIMETypeIsMultiImage(destSupportedMIMETypes[i]) {
|
||||
selectedType = destSupportedMIMETypes[i]
|
||||
}
|
||||
// The first priority is the current type, if it's in the list, since that lets us avoid a
|
||||
// conversion that isn't strictly necessary.
|
||||
if destSupportedMIMETypes[i] == currentListMIMEType {
|
||||
selectedType = destSupportedMIMETypes[i]
|
||||
}
|
||||
}
|
||||
if selectedType == "" {
|
||||
return "", errors.Errorf("destination does not support any supported manifest list types (%v)", manifest.SupportedListMIMETypes)
|
||||
}
|
||||
// Done.
|
||||
return selectedType, nil
|
||||
}
|
@ -4,7 +4,7 @@ import (
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/types"
|
||||
)
|
||||
|
||||
// progressReader is a reader that reports its progress on an interval.
|
@ -1,8 +1,8 @@
|
||||
package copy
|
||||
|
||||
import (
|
||||
"github.com/containers/image/v4/signature"
|
||||
"github.com/containers/image/v4/transports"
|
||||
"github.com/containers/image/v5/signature"
|
||||
"github.com/containers/image/v5/transports"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
@ -199,16 +199,23 @@ func (d *dirImageDestination) TryReusingBlob(ctx context.Context, info types.Blo
|
||||
}
|
||||
|
||||
// PutManifest writes manifest to the destination.
|
||||
// If instanceDigest is not nil, it contains a digest of the specific manifest instance to write the manifest for (when
|
||||
// the primary manifest is a manifest list); this should always be nil if the primary manifest is not a manifest list.
|
||||
// It is expected but not enforced that the instanceDigest, when specified, matches the digest of `manifest` as generated
|
||||
// by `manifest.Digest()`.
|
||||
// FIXME? This should also receive a MIME type if known, to differentiate between schema versions.
|
||||
// If the destination is in principle available, refuses this manifest type (e.g. it does not recognize the schema),
|
||||
// but may accept a different manifest type, the returned error must be an ManifestTypeRejectedError.
|
||||
func (d *dirImageDestination) PutManifest(ctx context.Context, manifest []byte) error {
|
||||
return ioutil.WriteFile(d.ref.manifestPath(), manifest, 0644)
|
||||
func (d *dirImageDestination) PutManifest(ctx context.Context, manifest []byte, instanceDigest *digest.Digest) error {
|
||||
return ioutil.WriteFile(d.ref.manifestPath(instanceDigest), manifest, 0644)
|
||||
}
|
||||
|
||||
func (d *dirImageDestination) PutSignatures(ctx context.Context, signatures [][]byte) error {
|
||||
// PutSignatures writes a set of signatures to the destination.
|
||||
// If instanceDigest is not nil, it contains a digest of the specific manifest instance to write or overwrite the signatures for
|
||||
// (when the primary manifest is a manifest list); this should always be nil if the primary manifest is not a manifest list.
|
||||
func (d *dirImageDestination) PutSignatures(ctx context.Context, signatures [][]byte, instanceDigest *digest.Digest) error {
|
||||
for i, sig := range signatures {
|
||||
if err := ioutil.WriteFile(d.ref.signaturePath(i), sig, 0644); err != nil {
|
||||
if err := ioutil.WriteFile(d.ref.signaturePath(i, instanceDigest), sig, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -219,7 +226,7 @@ func (d *dirImageDestination) PutSignatures(ctx context.Context, signatures [][]
|
||||
// WARNING: This does not have any transactional semantics:
|
||||
// - Uploaded data MAY be visible to others before Commit() is called
|
||||
// - Uploaded data MAY be removed or MAY remain around if Close() is called without Commit() (i.e. rollback is allowed but not guaranteed)
|
||||
func (d *dirImageDestination) Commit(ctx context.Context) error {
|
||||
func (d *dirImageDestination) Commit(context.Context, types.UnparsedImage) error {
|
||||
return nil
|
||||
}
|
||||
|
@ -6,10 +6,9 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/containers/image/v4/manifest"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type dirImageSource struct {
|
||||
@ -38,10 +37,7 @@ func (s *dirImageSource) Close() error {
|
||||
// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve (when the primary manifest is a manifest list);
|
||||
// this never happens if the primary manifest is not a manifest list (e.g. if the source never returns manifest lists).
|
||||
func (s *dirImageSource) GetManifest(ctx context.Context, instanceDigest *digest.Digest) ([]byte, string, error) {
|
||||
if instanceDigest != nil {
|
||||
return nil, "", errors.Errorf(`Getting target manifest not supported by "dir:"`)
|
||||
}
|
||||
m, err := ioutil.ReadFile(s.ref.manifestPath())
|
||||
m, err := ioutil.ReadFile(s.ref.manifestPath(instanceDigest))
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
@ -73,12 +69,9 @@ func (s *dirImageSource) GetBlob(ctx context.Context, info types.BlobInfo, cache
|
||||
// (when the primary manifest is a manifest list); this never happens if the primary manifest is not a manifest list
|
||||
// (e.g. if the source never returns manifest lists).
|
||||
func (s *dirImageSource) GetSignatures(ctx context.Context, instanceDigest *digest.Digest) ([][]byte, error) {
|
||||
if instanceDigest != nil {
|
||||
return nil, errors.Errorf(`Manifests lists are not supported by "dir:"`)
|
||||
}
|
||||
signatures := [][]byte{}
|
||||
for i := 0; ; i++ {
|
||||
signature, err := ioutil.ReadFile(s.ref.signaturePath(i))
|
||||
signature, err := ioutil.ReadFile(s.ref.signaturePath(i, instanceDigest))
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
break
|
||||
@ -90,7 +83,14 @@ func (s *dirImageSource) GetSignatures(ctx context.Context, instanceDigest *dige
|
||||
return signatures, nil
|
||||
}
|
||||
|
||||
// LayerInfosForCopy() returns updated layer info that should be used when copying, in preference to values in the manifest, if specified.
|
||||
func (s *dirImageSource) LayerInfosForCopy(ctx context.Context) ([]types.BlobInfo, 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. If values are returned, they should be used when using GetBlob()
|
||||
// to read the image's layers.
|
||||
// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve BlobInfos for
|
||||
// (when the primary manifest is a manifest list); this never happens if the primary manifest is not a manifest list
|
||||
// (e.g. if the source never returns manifest lists).
|
||||
// The Digest field is guaranteed to be provided; Size may be -1.
|
||||
// WARNING: The list may contain duplicates, and they are semantically relevant.
|
||||
func (s *dirImageSource) LayerInfosForCopy(context.Context, *digest.Digest) ([]types.BlobInfo, error) {
|
||||
return nil, nil
|
||||
}
|
@ -6,11 +6,11 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/image/v4/directory/explicitfilepath"
|
||||
"github.com/containers/image/v4/docker/reference"
|
||||
"github.com/containers/image/v4/image"
|
||||
"github.com/containers/image/v4/transports"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/directory/explicitfilepath"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/image"
|
||||
"github.com/containers/image/v5/transports"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
@ -166,18 +166,24 @@ func (ref dirReference) DeleteImage(ctx context.Context, sys *types.SystemContex
|
||||
}
|
||||
|
||||
// manifestPath returns a path for the manifest within a directory using our conventions.
|
||||
func (ref dirReference) manifestPath() string {
|
||||
func (ref dirReference) manifestPath(instanceDigest *digest.Digest) string {
|
||||
if instanceDigest != nil {
|
||||
return filepath.Join(ref.path, instanceDigest.Encoded()+".manifest.json")
|
||||
}
|
||||
return filepath.Join(ref.path, "manifest.json")
|
||||
}
|
||||
|
||||
// layerPath returns a path for a layer tarball within a directory using our conventions.
|
||||
func (ref dirReference) layerPath(digest digest.Digest) string {
|
||||
// FIXME: Should we keep the digest identification?
|
||||
return filepath.Join(ref.path, digest.Hex())
|
||||
return filepath.Join(ref.path, digest.Encoded())
|
||||
}
|
||||
|
||||
// signaturePath returns a path for a signature within a directory using our conventions.
|
||||
func (ref dirReference) signaturePath(index int) string {
|
||||
func (ref dirReference) signaturePath(index int, instanceDigest *digest.Digest) string {
|
||||
if instanceDigest != nil {
|
||||
return filepath.Join(ref.path, fmt.Sprintf(instanceDigest.Encoded()+".signature-%d", index+1))
|
||||
}
|
||||
return filepath.Join(ref.path, fmt.Sprintf("signature-%d", index+1))
|
||||
}
|
||||
|
@ -5,8 +5,8 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/containers/image/v4/docker/tarfile"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/docker/tarfile"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@ -67,6 +67,6 @@ func (d *archiveImageDestination) Close() error {
|
||||
// WARNING: This does not have any transactional semantics:
|
||||
// - Uploaded data MAY be visible to others before Commit() is called
|
||||
// - Uploaded data MAY be removed or MAY remain around if Close() is called without Commit() (i.e. rollback is allowed but not guaranteed)
|
||||
func (d *archiveImageDestination) Commit(ctx context.Context) error {
|
||||
func (d *archiveImageDestination) Commit(ctx context.Context, unparsedToplevel types.UnparsedImage) error {
|
||||
return d.Destination.Commit(ctx)
|
||||
}
|
@ -2,8 +2,8 @@ package archive
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/containers/image/v4/docker/tarfile"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/docker/tarfile"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
@ -33,8 +33,3 @@ func newImageSource(ctx context.Context, ref archiveReference) (types.ImageSourc
|
||||
func (s *archiveImageSource) Reference() types.ImageReference {
|
||||
return s.ref
|
||||
}
|
||||
|
||||
// LayerInfosForCopy() returns updated layer info that should be used when reading, in preference to values in the manifest, if specified.
|
||||
func (s *archiveImageSource) LayerInfosForCopy(ctx context.Context) ([]types.BlobInfo, error) {
|
||||
return nil, nil
|
||||
}
|
@ -5,10 +5,10 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/image/v4/docker/reference"
|
||||
ctrImage "github.com/containers/image/v4/image"
|
||||
"github.com/containers/image/v4/transports"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
ctrImage "github.com/containers/image/v5/image"
|
||||
"github.com/containers/image/v5/transports"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
@ -1,8 +1,8 @@
|
||||
package docker
|
||||
|
||||
import (
|
||||
"github.com/containers/image/v4/docker/reference"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/types"
|
||||
)
|
||||
|
||||
// bicTransportScope returns a BICTransportScope appropriate for ref.
|
@ -4,7 +4,7 @@ import (
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/types"
|
||||
dockerclient "github.com/docker/docker/client"
|
||||
"github.com/docker/go-connections/tlsconfig"
|
||||
)
|
@ -4,9 +4,9 @@ import (
|
||||
"context"
|
||||
"io"
|
||||
|
||||
"github.com/containers/image/v4/docker/reference"
|
||||
"github.com/containers/image/v4/docker/tarfile"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/docker/tarfile"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
@ -124,7 +124,7 @@ func (d *daemonImageDestination) Reference() types.ImageReference {
|
||||
// WARNING: This does not have any transactional semantics:
|
||||
// - Uploaded data MAY be visible to others before Commit() is called
|
||||
// - Uploaded data MAY be removed or MAY remain around if Close() is called without Commit() (i.e. rollback is allowed but not guaranteed)
|
||||
func (d *daemonImageDestination) Commit(ctx context.Context) error {
|
||||
func (d *daemonImageDestination) Commit(ctx context.Context, unparsedToplevel types.UnparsedImage) error {
|
||||
logrus.Debugf("docker-daemon: Closing tar stream")
|
||||
if err := d.Destination.Commit(ctx); err != nil {
|
||||
return err
|
@ -3,8 +3,8 @@ package daemon
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/containers/image/v4/docker/tarfile"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/docker/tarfile"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@ -55,8 +55,3 @@ func newImageSource(ctx context.Context, sys *types.SystemContext, ref daemonRef
|
||||
func (s *daemonImageSource) Reference() types.ImageReference {
|
||||
return s.ref
|
||||
}
|
||||
|
||||
// LayerInfosForCopy() returns updated layer info that should be used when reading, in preference to values in the manifest, if specified.
|
||||
func (s *daemonImageSource) LayerInfosForCopy(ctx context.Context) ([]types.BlobInfo, error) {
|
||||
return nil, nil
|
||||
}
|
@ -4,11 +4,11 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/containers/image/v4/docker/policyconfiguration"
|
||||
"github.com/containers/image/v4/docker/reference"
|
||||
"github.com/containers/image/v4/image"
|
||||
"github.com/containers/image/v4/transports"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/docker/policyconfiguration"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/image"
|
||||
"github.com/containers/image/v5/transports"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
)
|
@ -16,12 +16,12 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/containers/image/v4/docker/reference"
|
||||
"github.com/containers/image/v4/pkg/docker/config"
|
||||
"github.com/containers/image/v4/pkg/sysregistriesv2"
|
||||
"github.com/containers/image/v4/pkg/tlsclientconfig"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/docker/distribution/registry/client"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/pkg/docker/config"
|
||||
"github.com/containers/image/v5/pkg/sysregistriesv2"
|
||||
"github.com/containers/image/v5/pkg/tlsclientconfig"
|
||||
"github.com/containers/image/v5/types"
|
||||
clientLib "github.com/docker/distribution/registry/client"
|
||||
"github.com/docker/go-connections/tlsconfig"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
@ -47,14 +47,7 @@ const (
|
||||
extensionSignatureTypeAtomic = "atomic" // extensionSignature.Type
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrV1NotSupported is returned when we're trying to talk to a
|
||||
// docker V1 registry.
|
||||
ErrV1NotSupported = errors.New("can't talk to a V1 docker registry")
|
||||
// ErrUnauthorizedForCredentials is returned when the status code returned is 401
|
||||
ErrUnauthorizedForCredentials = errors.New("unable to retrieve auth token: invalid username/password")
|
||||
systemPerHostCertDirPaths = [2]string{"/etc/containers/certs.d", "/etc/docker/certs.d"}
|
||||
)
|
||||
var systemPerHostCertDirPaths = [2]string{"/etc/containers/certs.d", "/etc/docker/certs.d"}
|
||||
|
||||
// extensionSignature and extensionSignatureList come from github.com/openshift/origin/pkg/dockerregistry/server/signaturedispatcher.go:
|
||||
// signature represents a Docker image signature.
|
||||
@ -284,14 +277,7 @@ func CheckAuth(ctx context.Context, sys *types.SystemContext, username, password
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
switch resp.StatusCode {
|
||||
case http.StatusOK:
|
||||
return nil
|
||||
case http.StatusUnauthorized:
|
||||
return ErrUnauthorizedForCredentials
|
||||
default:
|
||||
return errors.Errorf("error occured with status code %d (%s)", resp.StatusCode, http.StatusText(resp.StatusCode))
|
||||
}
|
||||
return httpResponseToError(resp)
|
||||
}
|
||||
|
||||
// SearchResult holds the information of each matching image
|
||||
@ -365,7 +351,7 @@ func SearchRegistry(ctx context.Context, sys *types.SystemContext, registry, ima
|
||||
} else {
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
logrus.Debugf("error getting search results from v1 endpoint %q, status code %d (%s)", registry, resp.StatusCode, http.StatusText(resp.StatusCode))
|
||||
logrus.Debugf("error getting search results from v1 endpoint %q: %v", registry, httpResponseToError(resp))
|
||||
} else {
|
||||
if err := json.NewDecoder(resp.Body).Decode(v1Res); err != nil {
|
||||
return nil, err
|
||||
@ -382,7 +368,7 @@ func SearchRegistry(ctx context.Context, sys *types.SystemContext, registry, ima
|
||||
} else {
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
logrus.Errorf("error getting search results from v2 endpoint %q, status code %d (%s)", registry, resp.StatusCode, http.StatusText(resp.StatusCode))
|
||||
logrus.Errorf("error getting search results from v2 endpoint %q: %v", registry, httpResponseToError(resp))
|
||||
} else {
|
||||
if err := json.NewDecoder(resp.Body).Decode(v2Res); err != nil {
|
||||
return nil, err
|
||||
@ -417,8 +403,78 @@ func (c *dockerClient) makeRequest(ctx context.Context, method, path string, hea
|
||||
// makeRequestToResolvedURL creates and executes a http.Request with the specified parameters, adding authentication and TLS options for the Docker client.
|
||||
// streamLen, if not -1, specifies the length of the data expected on stream.
|
||||
// makeRequest should generally be preferred.
|
||||
// In case of an http 429 status code in the response, it performs an exponential back off starting at 2 seconds for at most 5 iterations.
|
||||
// If the `Retry-After` header is set in the response, the specified value or date is
|
||||
// If the stream is non-nil, no back off will be performed.
|
||||
// TODO(runcom): too many arguments here, use a struct
|
||||
func (c *dockerClient) makeRequestToResolvedURL(ctx context.Context, method, url string, headers map[string][]string, stream io.Reader, streamLen int64, auth sendAuth, extraScope *authScope) (*http.Response, error) {
|
||||
var (
|
||||
res *http.Response
|
||||
err error
|
||||
delay int64
|
||||
)
|
||||
delay = 2
|
||||
const numIterations = 5
|
||||
const maxDelay = 60
|
||||
|
||||
// math.Min() only supports float64, so have an anonymous func to avoid
|
||||
// casting.
|
||||
min := func(a int64, b int64) int64 {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
nextDelay := func(r *http.Response, delay int64) int64 {
|
||||
after := res.Header.Get("Retry-After")
|
||||
if after == "" {
|
||||
return min(delay, maxDelay)
|
||||
}
|
||||
logrus.Debugf("detected 'Retry-After' header %q", after)
|
||||
// First check if we have a numerical value.
|
||||
if num, err := strconv.ParseInt(after, 10, 64); err == nil {
|
||||
return min(num, maxDelay)
|
||||
}
|
||||
// Secondly check if we have an http date.
|
||||
// If the delta between the date and now is positive, use it.
|
||||
// Otherwise, fall back to using the default exponential back off.
|
||||
if t, err := http.ParseTime(after); err == nil {
|
||||
delta := int64(t.Sub(time.Now()).Seconds())
|
||||
if delta > 0 {
|
||||
return min(delta, maxDelay)
|
||||
}
|
||||
logrus.Debugf("negative date: falling back to using %d seconds", delay)
|
||||
return min(delay, maxDelay)
|
||||
}
|
||||
// If the header contains bogus, fall back to using the default
|
||||
// exponential back off.
|
||||
logrus.Debugf("invalid format: falling back to using %d seconds", delay)
|
||||
return min(delay, maxDelay)
|
||||
}
|
||||
|
||||
for i := 0; i < numIterations; i++ {
|
||||
res, err = c.makeRequestToResolvedURLOnce(ctx, method, url, headers, stream, streamLen, auth, extraScope)
|
||||
if stream == nil && res != nil && res.StatusCode == http.StatusTooManyRequests {
|
||||
if i < numIterations-1 {
|
||||
logrus.Errorf("HEADER %v", res.Header)
|
||||
delay = nextDelay(res, delay) // compute next delay - does NOT exceed maxDelay
|
||||
logrus.Debugf("too many request to %s: sleeping for %d seconds before next attempt", url, delay)
|
||||
time.Sleep(time.Duration(delay) * time.Second)
|
||||
delay = delay * 2 // exponential back off
|
||||
}
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
return res, err
|
||||
}
|
||||
|
||||
// makeRequestToResolvedURLOnce creates and executes a http.Request with the specified parameters, adding authentication and TLS options for the Docker client.
|
||||
// streamLen, if not -1, specifies the length of the data expected on stream.
|
||||
// makeRequest should generally be preferred.
|
||||
// Note that no exponential back off is performed when receiving an http 429 status code.
|
||||
func (c *dockerClient) makeRequestToResolvedURLOnce(ctx context.Context, method, url string, headers map[string][]string, stream io.Reader, streamLen int64, auth sendAuth, extraScope *authScope) (*http.Response, error) {
|
||||
req, err := http.NewRequest(method, url, stream)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -533,9 +589,9 @@ func (c *dockerClient) getBearerToken(ctx context.Context, challenge challenge,
|
||||
defer res.Body.Close()
|
||||
switch res.StatusCode {
|
||||
case http.StatusUnauthorized:
|
||||
err := client.HandleErrorResponse(res)
|
||||
err := clientLib.HandleErrorResponse(res)
|
||||
logrus.Debugf("Server response when trying to obtain an access token: \n%q", err.Error())
|
||||
return nil, ErrUnauthorizedForCredentials
|
||||
return nil, ErrUnauthorizedForCredentials{Err: err}
|
||||
case http.StatusOK:
|
||||
break
|
||||
default:
|
||||
@ -571,7 +627,7 @@ func (c *dockerClient) detectPropertiesHelper(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 registry %s, response code %d (%s)", c.registry, resp.StatusCode, http.StatusText(resp.StatusCode))
|
||||
return httpResponseToError(resp)
|
||||
}
|
||||
c.challenges = parseAuthHeader(resp.Header)
|
||||
c.scheme = scheme
|
||||
@ -583,7 +639,7 @@ func (c *dockerClient) detectPropertiesHelper(ctx context.Context) error {
|
||||
err = ping("http")
|
||||
}
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "pinging docker registry returned")
|
||||
err = errors.Wrapf(err, "error pinging docker registry %s", c.registry)
|
||||
if c.sys != nil && c.sys.DockerDisableV1Ping {
|
||||
return err
|
||||
}
|
||||
@ -629,9 +685,11 @@ func (c *dockerClient) getExtensionsSignatures(ctx context.Context, ref dockerRe
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return nil, errors.Wrapf(client.HandleErrorResponse(res), "Error downloading signatures for %s in %s", manifestDigest, ref.ref.Name())
|
||||
return nil, errors.Wrapf(clientLib.HandleErrorResponse(res), "Error downloading signatures for %s in %s", manifestDigest, ref.ref.Name())
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
@ -4,13 +4,12 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/image/v4/docker/reference"
|
||||
"github.com/containers/image/v4/image"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/image"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@ -71,9 +70,8 @@ func GetRepositoryTags(ctx context.Context, sys *types.SystemContext, ref types.
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode != http.StatusOK {
|
||||
// print url also
|
||||
return nil, errors.Errorf("Invalid status code returned when fetching tags list %d (%s)", res.StatusCode, http.StatusText(res.StatusCode))
|
||||
if err := httpResponseToError(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tagsHolder struct {
|
@ -14,12 +14,12 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/image/v4/docker/reference"
|
||||
"github.com/containers/image/v4/manifest"
|
||||
"github.com/containers/image/v4/pkg/blobinfocache/none"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/pkg/blobinfocache/none"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/docker/distribution/registry/api/errcode"
|
||||
"github.com/docker/distribution/registry/api/v2"
|
||||
v2 "github.com/docker/distribution/registry/api/v2"
|
||||
"github.com/docker/distribution/registry/client"
|
||||
"github.com/opencontainers/go-digest"
|
||||
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
@ -61,6 +61,8 @@ func (d *dockerImageDestination) SupportedManifestMIMETypes() []string {
|
||||
return []string{
|
||||
imgspecv1.MediaTypeImageManifest,
|
||||
manifest.DockerV2Schema2MediaType,
|
||||
imgspecv1.MediaTypeImageIndex,
|
||||
manifest.DockerV2ListMediaType,
|
||||
manifest.DockerV2Schema1SignedMediaType,
|
||||
manifest.DockerV2Schema1MediaType,
|
||||
}
|
||||
@ -343,20 +345,47 @@ func (d *dockerImageDestination) TryReusingBlob(ctx context.Context, info types.
|
||||
}
|
||||
|
||||
// PutManifest writes manifest to the destination.
|
||||
// When the primary manifest is a manifest list, if instanceDigest is nil, we're saving the list
|
||||
// itself, else instanceDigest contains a digest of the specific manifest instance to overwrite the
|
||||
// manifest for; when the primary manifest is not a manifest list, instanceDigest should always be nil.
|
||||
// FIXME? This should also receive a MIME type if known, to differentiate between schema versions.
|
||||
// If the destination is in principle available, refuses this manifest type (e.g. it does not recognize the schema),
|
||||
// but may accept a different manifest type, the returned error must be an ManifestTypeRejectedError.
|
||||
func (d *dockerImageDestination) PutManifest(ctx context.Context, m []byte) error {
|
||||
digest, err := manifest.Digest(m)
|
||||
if err != nil {
|
||||
return err
|
||||
func (d *dockerImageDestination) PutManifest(ctx context.Context, m []byte, instanceDigest *digest.Digest) error {
|
||||
refTail := ""
|
||||
if instanceDigest != nil {
|
||||
// If the instanceDigest is provided, then use it as the refTail, because the reference,
|
||||
// whether it includes a tag or a digest, refers to the list as a whole, and not this
|
||||
// particular instance.
|
||||
refTail = instanceDigest.String()
|
||||
// Double-check that the manifest we've been given matches the digest we've been given.
|
||||
matches, err := manifest.MatchesDigest(m, *instanceDigest)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error digesting manifest in PutManifest")
|
||||
}
|
||||
if !matches {
|
||||
manifestDigest, merr := manifest.Digest(m)
|
||||
if merr != nil {
|
||||
return errors.Wrapf(err, "Attempted to PutManifest using an explicitly specified digest (%q) that didn't match the manifest's digest (%v attempting to compute it)", instanceDigest.String(), merr)
|
||||
}
|
||||
return errors.Errorf("Attempted to PutManifest using an explicitly specified digest (%q) that didn't match the manifest's digest (%q)", instanceDigest.String(), manifestDigest.String())
|
||||
}
|
||||
} else {
|
||||
// Compute the digest of the main manifest, or the list if it's a list, so that we
|
||||
// have a digest value to use if we're asked to save a signature for the manifest.
|
||||
digest, err := manifest.Digest(m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d.manifestDigest = digest
|
||||
// The refTail should be either a digest (which we expect to match the value we just
|
||||
// computed) or a tag name.
|
||||
refTail, err = d.ref.tagOrDigest()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
d.manifestDigest = digest
|
||||
|
||||
refTail, err := d.ref.tagOrDigest()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
path := fmt.Sprintf(manifestPath, reference.Path(d.ref.ref), refTail)
|
||||
|
||||
headers := map[string][]string{}
|
||||
@ -416,19 +445,30 @@ func isManifestInvalidError(err error) bool {
|
||||
}
|
||||
}
|
||||
|
||||
func (d *dockerImageDestination) PutSignatures(ctx context.Context, signatures [][]byte) error {
|
||||
// PutSignatures uploads a set of signatures to the relevant lookaside or API extension point.
|
||||
// If instanceDigest is not nil, it contains a digest of the specific manifest instance to upload the signatures for (when
|
||||
// the primary manifest is a manifest list); this should always be nil if the primary manifest is not a manifest list.
|
||||
func (d *dockerImageDestination) PutSignatures(ctx context.Context, signatures [][]byte, instanceDigest *digest.Digest) error {
|
||||
// Do not fail if we don’t really need to support signatures.
|
||||
if len(signatures) == 0 {
|
||||
return nil
|
||||
}
|
||||
if instanceDigest == nil {
|
||||
if d.manifestDigest.String() == "" {
|
||||
// This shouldn’t happen, ImageDestination users are required to call PutManifest before PutSignatures
|
||||
return errors.Errorf("Unknown manifest digest, can't add signatures")
|
||||
}
|
||||
instanceDigest = &d.manifestDigest
|
||||
}
|
||||
|
||||
if err := d.c.detectProperties(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
switch {
|
||||
case d.c.signatureBase != nil:
|
||||
return d.putSignaturesToLookaside(signatures)
|
||||
return d.putSignaturesToLookaside(signatures, instanceDigest)
|
||||
case d.c.supportsSignatures:
|
||||
return d.putSignaturesToAPIExtension(ctx, signatures)
|
||||
return d.putSignaturesToAPIExtension(ctx, signatures, instanceDigest)
|
||||
default:
|
||||
return errors.Errorf("X-Registry-Supports-Signatures extension not supported, and lookaside is not configured")
|
||||
}
|
||||
@ -436,7 +476,7 @@ func (d *dockerImageDestination) PutSignatures(ctx context.Context, signatures [
|
||||
|
||||
// putSignaturesToLookaside implements PutSignatures() from the lookaside location configured in s.c.signatureBase,
|
||||
// which is not nil.
|
||||
func (d *dockerImageDestination) putSignaturesToLookaside(signatures [][]byte) error {
|
||||
func (d *dockerImageDestination) putSignaturesToLookaside(signatures [][]byte, instanceDigest *digest.Digest) error {
|
||||
// FIXME? This overwrites files one at a time, definitely not atomic.
|
||||
// A failure when updating signatures with a reordered copy could lose some of them.
|
||||
|
||||
@ -445,14 +485,9 @@ func (d *dockerImageDestination) putSignaturesToLookaside(signatures [][]byte) e
|
||||
return nil
|
||||
}
|
||||
|
||||
if d.manifestDigest.String() == "" {
|
||||
// This shouldn’t happen, ImageDestination users are required to call PutManifest before PutSignatures
|
||||
return errors.Errorf("Unknown manifest digest, can't add signatures")
|
||||
}
|
||||
|
||||
// NOTE: Keep this in sync with docs/signature-protocols.md!
|
||||
for i, signature := range signatures {
|
||||
url := signatureStorageURL(d.c.signatureBase, d.manifestDigest, i)
|
||||
url := signatureStorageURL(d.c.signatureBase, *instanceDigest, i)
|
||||
if url == nil {
|
||||
return errors.Errorf("Internal error: signatureStorageURL with non-nil base returned nil")
|
||||
}
|
||||
@ -467,7 +502,7 @@ func (d *dockerImageDestination) putSignaturesToLookaside(signatures [][]byte) e
|
||||
// is enough for dockerImageSource to stop looking for other signatures, so that
|
||||
// is sufficient.
|
||||
for i := len(signatures); ; i++ {
|
||||
url := signatureStorageURL(d.c.signatureBase, d.manifestDigest, i)
|
||||
url := signatureStorageURL(d.c.signatureBase, *instanceDigest, i)
|
||||
if url == nil {
|
||||
return errors.Errorf("Internal error: signatureStorageURL with non-nil base returned nil")
|
||||
}
|
||||
@ -527,22 +562,17 @@ func (c *dockerClient) deleteOneSignature(url *url.URL) (missing bool, err error
|
||||
}
|
||||
|
||||
// putSignaturesToAPIExtension implements PutSignatures() using the X-Registry-Supports-Signatures API extension.
|
||||
func (d *dockerImageDestination) putSignaturesToAPIExtension(ctx context.Context, signatures [][]byte) error {
|
||||
func (d *dockerImageDestination) putSignaturesToAPIExtension(ctx context.Context, signatures [][]byte, instanceDigest *digest.Digest) error {
|
||||
// Skip dealing with the manifest digest, or reading the old state, if not necessary.
|
||||
if len(signatures) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if d.manifestDigest.String() == "" {
|
||||
// This shouldn’t happen, ImageDestination users are required to call PutManifest before PutSignatures
|
||||
return errors.Errorf("Unknown manifest digest, can't add signatures")
|
||||
}
|
||||
|
||||
// Because image signatures are a shared resource in Atomic Registry, the default upload
|
||||
// always adds signatures. Eventually we should also allow removing signatures,
|
||||
// but the X-Registry-Supports-Signatures API extension does not support that yet.
|
||||
|
||||
existingSignatures, err := d.c.getExtensionsSignatures(ctx, d.ref, d.manifestDigest)
|
||||
existingSignatures, err := d.c.getExtensionsSignatures(ctx, d.ref, *instanceDigest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -567,7 +597,7 @@ sigExists:
|
||||
if err != nil || n != 16 {
|
||||
return errors.Wrapf(err, "Error generating random signature len %d", n)
|
||||
}
|
||||
signatureName = fmt.Sprintf("%s@%032x", d.manifestDigest.String(), randBytes)
|
||||
signatureName = fmt.Sprintf("%s@%032x", instanceDigest.String(), randBytes)
|
||||
if _, ok := existingSigNames[signatureName]; !ok {
|
||||
break
|
||||
}
|
||||
@ -606,6 +636,6 @@ sigExists:
|
||||
// WARNING: This does not have any transactional semantics:
|
||||
// - Uploaded data MAY be visible to others before Commit() is called
|
||||
// - Uploaded data MAY be removed or MAY remain around if Close() is called without Commit() (i.e. rollback is allowed but not guaranteed)
|
||||
func (d *dockerImageDestination) Commit(ctx context.Context) error {
|
||||
func (d *dockerImageDestination) Commit(context.Context, types.UnparsedImage) error {
|
||||
return nil
|
||||
}
|
@ -11,10 +11,10 @@ import (
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/containers/image/v4/docker/reference"
|
||||
"github.com/containers/image/v4/manifest"
|
||||
"github.com/containers/image/v4/pkg/sysregistriesv2"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/pkg/sysregistriesv2"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/docker/distribution/registry/client"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
@ -103,8 +103,15 @@ func (s *dockerImageSource) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// LayerInfosForCopy() returns updated layer info that should be used when reading, in preference to values in the manifest, if specified.
|
||||
func (s *dockerImageSource) LayerInfosForCopy(ctx context.Context) ([]types.BlobInfo, 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. If values are returned, they should be used when using GetBlob()
|
||||
// to read the image's layers.
|
||||
// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve BlobInfos for
|
||||
// (when the primary manifest is a manifest list); this never happens if the primary manifest is not a manifest list
|
||||
// (e.g. if the source never returns manifest lists).
|
||||
// The Digest field is guaranteed to be provided; Size may be -1.
|
||||
// WARNING: The list may contain duplicates, and they are semantically relevant.
|
||||
func (s *dockerImageSource) LayerInfosForCopy(context.Context, *digest.Digest) ([]types.BlobInfo, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@ -232,9 +239,8 @@ func (s *dockerImageSource) GetBlob(ctx context.Context, info types.BlobInfo, ca
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if res.StatusCode != http.StatusOK {
|
||||
// print url also
|
||||
return nil, 0, errors.Errorf("Invalid status code returned when fetching blob %d (%s)", res.StatusCode, http.StatusText(res.StatusCode))
|
||||
if err := httpResponseToError(res); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
cache.RecordKnownLocation(s.ref.Transport(), bicTransportScope(s.ref), info.Digest, newBICLocationReference(s.ref))
|
||||
return res.Body, getBlobSize(res), nil
|
@ -5,10 +5,10 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/image/v4/docker/policyconfiguration"
|
||||
"github.com/containers/image/v4/docker/reference"
|
||||
"github.com/containers/image/v4/transports"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/docker/policyconfiguration"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/transports"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
43
vendor/github.com/containers/image/v5/docker/errors.go
generated
vendored
Normal file
43
vendor/github.com/containers/image/v5/docker/errors.go
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
package docker
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/docker/distribution/registry/client"
|
||||
perrors "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrV1NotSupported is returned when we're trying to talk to a
|
||||
// docker V1 registry.
|
||||
ErrV1NotSupported = errors.New("can't talk to a V1 docker registry")
|
||||
// ErrTooManyRequests is returned when the status code returned is 429
|
||||
ErrTooManyRequests = errors.New("too many request to registry")
|
||||
)
|
||||
|
||||
// ErrUnauthorizedForCredentials is returned when the status code returned is 401
|
||||
type ErrUnauthorizedForCredentials struct { // We only use a struct to allow a type assertion, without limiting the contents of the error otherwise.
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e ErrUnauthorizedForCredentials) Error() string {
|
||||
return fmt.Sprintf("unable to retrieve auth token: invalid username/password: %s", e.Err.Error())
|
||||
}
|
||||
|
||||
// httpResponseToError translates the https.Response into an error. It returns
|
||||
// nil if the response is not considered an error.
|
||||
func httpResponseToError(res *http.Response) error {
|
||||
switch res.StatusCode {
|
||||
case http.StatusOK:
|
||||
return nil
|
||||
case http.StatusTooManyRequests:
|
||||
return ErrTooManyRequests
|
||||
case http.StatusUnauthorized:
|
||||
err := client.HandleErrorResponse(res)
|
||||
return ErrUnauthorizedForCredentials{Err: err}
|
||||
default:
|
||||
return perrors.Errorf("invalid status code from registry %d (%s)", res.StatusCode, http.StatusText(res.StatusCode))
|
||||
}
|
||||
}
|
@ -9,8 +9,8 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/image/v4/docker/reference"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
@ -3,7 +3,7 @@ package policyconfiguration
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/containers/image/v4/docker/reference"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
@ -12,10 +12,10 @@ import (
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/containers/image/v4/docker/reference"
|
||||
"github.com/containers/image/v4/internal/tmpdir"
|
||||
"github.com/containers/image/v4/manifest"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/internal/tmpdir"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
@ -195,10 +195,15 @@ func (d *Destination) createRepositoriesFile(rootLayerID string) error {
|
||||
}
|
||||
|
||||
// PutManifest writes manifest to the destination.
|
||||
// The instanceDigest value is expected to always be nil, because this transport does not support manifest lists, so
|
||||
// there can be no secondary manifests.
|
||||
// FIXME? This should also receive a MIME type if known, to differentiate between schema versions.
|
||||
// If the destination is in principle available, refuses this manifest type (e.g. it does not recognize the schema),
|
||||
// but may accept a different manifest type, the returned error must be an ManifestTypeRejectedError.
|
||||
func (d *Destination) PutManifest(ctx context.Context, m []byte) error {
|
||||
func (d *Destination) PutManifest(ctx context.Context, m []byte, instanceDigest *digest.Digest) error {
|
||||
if instanceDigest != nil {
|
||||
return errors.New(`Manifest lists are not supported for docker tar files`)
|
||||
}
|
||||
// We do not bother with types.ManifestTypeRejectedError; our .SupportedManifestMIMETypes() above is already providing only one alternative,
|
||||
// so the caller trying a different manifest kind would be pointless.
|
||||
var man manifest.Schema2
|
||||
@ -390,10 +395,13 @@ func (d *Destination) sendFile(path string, expectedSize int64, stream io.Reader
|
||||
return nil
|
||||
}
|
||||
|
||||
// PutSignatures adds the given signatures to the docker tarfile (currently not
|
||||
// supported). MUST be called after PutManifest (signatures reference manifest
|
||||
// contents)
|
||||
func (d *Destination) PutSignatures(ctx context.Context, signatures [][]byte) error {
|
||||
// PutSignatures would add the given signatures to the docker tarfile (currently not supported).
|
||||
// The instanceDigest value is expected to always be nil, because this transport does not support manifest lists, so
|
||||
// there can be no secondary manifests. MUST be called after PutManifest (signatures reference manifest contents).
|
||||
func (d *Destination) PutSignatures(ctx context.Context, signatures [][]byte, instanceDigest *digest.Digest) error {
|
||||
if instanceDigest != nil {
|
||||
return errors.Errorf(`Manifest lists are not supported for docker tar files`)
|
||||
}
|
||||
if len(signatures) != 0 {
|
||||
return errors.Errorf("Storing signatures for docker tar files is not supported")
|
||||
}
|
@ -11,10 +11,10 @@ import (
|
||||
"path"
|
||||
"sync"
|
||||
|
||||
"github.com/containers/image/v4/internal/tmpdir"
|
||||
"github.com/containers/image/v4/manifest"
|
||||
"github.com/containers/image/v4/pkg/compression"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/internal/tmpdir"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/pkg/compression"
|
||||
"github.com/containers/image/v5/types"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
@ -349,10 +349,12 @@ func (s *Source) prepareLayerData(tarManifest *ManifestItem, parsedConfig *manif
|
||||
// It may use a remote (= slow) service.
|
||||
// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve (when the primary manifest is a manifest list);
|
||||
// this never happens if the primary manifest is not a manifest list (e.g. if the source never returns manifest lists).
|
||||
// This source implementation does not support manifest lists, so the passed-in instanceDigest should always be nil,
|
||||
// as the primary manifest can not be a list, so there can be no secondary instances.
|
||||
func (s *Source) GetManifest(ctx context.Context, instanceDigest *digest.Digest) ([]byte, string, error) {
|
||||
if instanceDigest != nil {
|
||||
// How did we even get here? GetManifest(ctx, nil) has returned a manifest.DockerV2Schema2MediaType.
|
||||
return nil, "", errors.Errorf(`Manifest lists are not supported by "docker-daemon:"`)
|
||||
return nil, "", errors.New(`Manifest lists are not supported by "docker-daemon:"`)
|
||||
}
|
||||
if s.generatedManifest == nil {
|
||||
if err := s.ensureCachedDataIsPresent(); err != nil {
|
||||
@ -466,9 +468,8 @@ func (s *Source) GetBlob(ctx context.Context, info types.BlobInfo, cache types.B
|
||||
}
|
||||
|
||||
// GetSignatures returns the image's signatures. It may use a remote (= slow) service.
|
||||
// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve signatures for
|
||||
// (when the primary manifest is a manifest list); this never happens if the primary manifest is not a manifest list
|
||||
// (e.g. if the source never returns manifest lists).
|
||||
// This source implementation does not support manifest lists, so the passed-in instanceDigest should always be nil,
|
||||
// as there can be no secondary manifests.
|
||||
func (s *Source) GetSignatures(ctx context.Context, instanceDigest *digest.Digest) ([][]byte, error) {
|
||||
if instanceDigest != nil {
|
||||
// How did we even get here? GetManifest(ctx, nil) has returned a manifest.DockerV2Schema2MediaType.
|
||||
@ -476,3 +477,14 @@ func (s *Source) GetSignatures(ctx context.Context, instanceDigest *digest.Diges
|
||||
}
|
||||
return [][]byte{}, nil
|
||||
}
|
||||
|
||||
// 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. If values are returned, they should be used when using GetBlob()
|
||||
// to read the image's layers.
|
||||
// This source implementation does not support manifest lists, so the passed-in instanceDigest should always be nil,
|
||||
// as the primary manifest can not be a list, so there can be no secondary manifests.
|
||||
// The Digest field is guaranteed to be provided; Size may be -1.
|
||||
// WARNING: The list may contain duplicates, and they are semantically relevant.
|
||||
func (s *Source) LayerInfosForCopy(context.Context, *digest.Digest) ([]types.BlobInfo, error) {
|
||||
return nil, nil
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
package tarfile
|
||||
|
||||
import (
|
||||
"github.com/containers/image/v4/manifest"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/opencontainers/go-digest"
|
||||
)
|
||||
|
34
vendor/github.com/containers/image/v5/image/docker_list.go
generated
vendored
Normal file
34
vendor/github.com/containers/image/v5/image/docker_list.go
generated
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
package image
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func manifestSchema2FromManifestList(ctx context.Context, sys *types.SystemContext, src types.ImageSource, manblob []byte) (genericManifest, error) {
|
||||
list, err := manifest.Schema2ListFromManifest(manblob)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Error parsing schema2 manifest list")
|
||||
}
|
||||
targetManifestDigest, err := list.ChooseInstance(sys)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Error choosing image instance")
|
||||
}
|
||||
manblob, mt, err := src.GetManifest(ctx, &targetManifestDigest)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Error loading manifest for target platform")
|
||||
}
|
||||
|
||||
matches, err := manifest.MatchesDigest(manblob, targetManifestDigest)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Error computing manifest digest")
|
||||
}
|
||||
if !matches {
|
||||
return nil, errors.Errorf("Image manifest does not match selected manifest digest %s", targetManifestDigest)
|
||||
}
|
||||
|
||||
return manifestInstanceFromBlob(ctx, sys, src, manblob, mt)
|
||||
}
|
@ -3,9 +3,9 @@ package image
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/containers/image/v4/docker/reference"
|
||||
"github.com/containers/image/v4/manifest"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/opencontainers/go-digest"
|
||||
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
@ -10,10 +10,10 @@ import (
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/image/v4/docker/reference"
|
||||
"github.com/containers/image/v4/manifest"
|
||||
"github.com/containers/image/v4/pkg/blobinfocache/none"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/pkg/blobinfocache/none"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/opencontainers/go-digest"
|
||||
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
@ -4,9 +4,9 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/containers/image/v4/docker/reference"
|
||||
"github.com/containers/image/v4/manifest"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/types"
|
||||
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
@ -58,6 +58,8 @@ func manifestInstanceFromBlob(ctx context.Context, sys *types.SystemContext, src
|
||||
return manifestSchema2FromManifest(src, manblob)
|
||||
case manifest.DockerV2ListMediaType:
|
||||
return manifestSchema2FromManifestList(ctx, sys, src, manblob)
|
||||
case imgspecv1.MediaTypeImageIndex:
|
||||
return manifestOCI1FromImageIndex(ctx, sys, src, manblob)
|
||||
default: // Note that this may not be reachable, manifest.NormalizedMIMEType has a default for unknown values.
|
||||
return nil, fmt.Errorf("Unimplemented manifest MIME type %s", mt)
|
||||
}
|
@ -3,9 +3,8 @@ package image
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/containers/image/v4/types"
|
||||
)
|
||||
|
||||
// memoryImage is a mostly-implementation of types.Image assembled from data
|
@ -6,10 +6,10 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/containers/image/v4/docker/reference"
|
||||
"github.com/containers/image/v4/manifest"
|
||||
"github.com/containers/image/v4/pkg/blobinfocache/none"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/pkg/blobinfocache/none"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/opencontainers/go-digest"
|
||||
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
34
vendor/github.com/containers/image/v5/image/oci_index.go
generated
vendored
Normal file
34
vendor/github.com/containers/image/v5/image/oci_index.go
generated
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
package image
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func manifestOCI1FromImageIndex(ctx context.Context, sys *types.SystemContext, src types.ImageSource, manblob []byte) (genericManifest, error) {
|
||||
index, err := manifest.OCI1IndexFromManifest(manblob)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Error parsing OCI1 index")
|
||||
}
|
||||
targetManifestDigest, err := index.ChooseInstance(sys)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Error choosing image instance")
|
||||
}
|
||||
manblob, mt, err := src.GetManifest(ctx, &targetManifestDigest)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Error loading manifest for target platform")
|
||||
}
|
||||
|
||||
matches, err := manifest.MatchesDigest(manblob, targetManifestDigest)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Error computing manifest digest")
|
||||
}
|
||||
if !matches {
|
||||
return nil, errors.Errorf("Image manifest does not match selected manifest digest %s", targetManifestDigest)
|
||||
}
|
||||
|
||||
return manifestInstanceFromBlob(ctx, sys, src, manblob, mt)
|
||||
}
|
@ -6,7 +6,7 @@ package image
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/types"
|
||||
)
|
||||
|
||||
// imageCloser implements types.ImageCloser, perhaps allowing simple users
|
||||
@ -100,5 +100,5 @@ func (i *sourcedImage) Manifest(ctx context.Context) ([]byte, string, error) {
|
||||
}
|
||||
|
||||
func (i *sourcedImage) LayerInfosForCopy(ctx context.Context) ([]types.BlobInfo, error) {
|
||||
return i.UnparsedImage.src.LayerInfosForCopy(ctx)
|
||||
return i.UnparsedImage.src.LayerInfosForCopy(ctx, i.UnparsedImage.instanceDigest)
|
||||
}
|
@ -3,9 +3,9 @@ package image
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/containers/image/v4/docker/reference"
|
||||
"github.com/containers/image/v4/manifest"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
)
|
@ -6,8 +6,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/containers/image/v4/docker/reference"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
@ -5,9 +5,9 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/containers/image/v4/pkg/compression"
|
||||
"github.com/containers/image/v4/pkg/strslice"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/pkg/compression"
|
||||
"github.com/containers/image/v5/pkg/strslice"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
216
vendor/github.com/containers/image/v5/manifest/docker_schema2_list.go
generated
vendored
Normal file
216
vendor/github.com/containers/image/v5/manifest/docker_schema2_list.go
generated
vendored
Normal file
@ -0,0 +1,216 @@
|
||||
package manifest
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/opencontainers/go-digest"
|
||||
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Schema2PlatformSpec describes the platform which a particular manifest is
|
||||
// specialized for.
|
||||
type Schema2PlatformSpec struct {
|
||||
Architecture string `json:"architecture"`
|
||||
OS string `json:"os"`
|
||||
OSVersion string `json:"os.version,omitempty"`
|
||||
OSFeatures []string `json:"os.features,omitempty"`
|
||||
Variant string `json:"variant,omitempty"`
|
||||
Features []string `json:"features,omitempty"` // removed in OCI
|
||||
}
|
||||
|
||||
// Schema2ManifestDescriptor references a platform-specific manifest.
|
||||
type Schema2ManifestDescriptor struct {
|
||||
Schema2Descriptor
|
||||
Platform Schema2PlatformSpec `json:"platform"`
|
||||
}
|
||||
|
||||
// Schema2List is a list of platform-specific manifests.
|
||||
type Schema2List struct {
|
||||
SchemaVersion int `json:"schemaVersion"`
|
||||
MediaType string `json:"mediaType"`
|
||||
Manifests []Schema2ManifestDescriptor `json:"manifests"`
|
||||
}
|
||||
|
||||
// MIMEType returns the MIME type of this particular manifest list.
|
||||
func (list *Schema2List) MIMEType() string {
|
||||
return list.MediaType
|
||||
}
|
||||
|
||||
// Instances returns a slice of digests of the manifests that this list knows of.
|
||||
func (list *Schema2List) Instances() []digest.Digest {
|
||||
results := make([]digest.Digest, len(list.Manifests))
|
||||
for i, m := range list.Manifests {
|
||||
results[i] = m.Digest
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
// Instance returns the ListUpdate of a particular instance in the list.
|
||||
func (list *Schema2List) Instance(instanceDigest digest.Digest) (ListUpdate, error) {
|
||||
for _, manifest := range list.Manifests {
|
||||
if manifest.Digest == instanceDigest {
|
||||
return ListUpdate{
|
||||
Digest: manifest.Digest,
|
||||
Size: manifest.Size,
|
||||
MediaType: manifest.MediaType,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
return ListUpdate{}, errors.Errorf("unable to find instance %s passed to Schema2List.Instances", instanceDigest)
|
||||
}
|
||||
|
||||
// UpdateInstances updates the sizes, digests, and media types of the manifests
|
||||
// which the list catalogs.
|
||||
func (list *Schema2List) UpdateInstances(updates []ListUpdate) error {
|
||||
if len(updates) != len(list.Manifests) {
|
||||
return errors.Errorf("incorrect number of update entries passed to Schema2List.UpdateInstances: expected %d, got %d", len(list.Manifests), len(updates))
|
||||
}
|
||||
for i := range updates {
|
||||
if err := updates[i].Digest.Validate(); err != nil {
|
||||
return errors.Wrapf(err, "update %d of %d passed to Schema2List.UpdateInstances contained an invalid digest", i+1, len(updates))
|
||||
}
|
||||
list.Manifests[i].Digest = updates[i].Digest
|
||||
if updates[i].Size < 0 {
|
||||
return errors.Errorf("update %d of %d passed to Schema2List.UpdateInstances had an invalid size (%d)", i+1, len(updates), updates[i].Size)
|
||||
}
|
||||
list.Manifests[i].Size = updates[i].Size
|
||||
if updates[i].MediaType == "" {
|
||||
return errors.Errorf("update %d of %d passed to Schema2List.UpdateInstances had no media type (was %q)", i+1, len(updates), list.Manifests[i].MediaType)
|
||||
}
|
||||
if err := SupportedSchema2MediaType(updates[i].MediaType); err != nil && SupportedOCI1MediaType(updates[i].MediaType) != nil {
|
||||
return errors.Wrapf(err, "update %d of %d passed to Schema2List.UpdateInstances had an unsupported media type (was %q): %q", i+1, len(updates), list.Manifests[i].MediaType, updates[i].MediaType)
|
||||
}
|
||||
list.Manifests[i].MediaType = updates[i].MediaType
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ChooseInstance parses blob as a schema2 manifest list, and returns the digest
|
||||
// of the image which is appropriate for the current environment.
|
||||
func (list *Schema2List) ChooseInstance(ctx *types.SystemContext) (digest.Digest, error) {
|
||||
wantedArch := runtime.GOARCH
|
||||
if ctx != nil && ctx.ArchitectureChoice != "" {
|
||||
wantedArch = ctx.ArchitectureChoice
|
||||
}
|
||||
wantedOS := runtime.GOOS
|
||||
if ctx != nil && ctx.OSChoice != "" {
|
||||
wantedOS = ctx.OSChoice
|
||||
}
|
||||
|
||||
for _, d := range list.Manifests {
|
||||
if d.Platform.Architecture == wantedArch && d.Platform.OS == wantedOS {
|
||||
return d.Digest, nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("no image found in manifest list for architecture %s, OS %s", wantedArch, wantedOS)
|
||||
}
|
||||
|
||||
// Serialize returns the list in a blob format.
|
||||
// NOTE: Serialize() does not in general reproduce the original blob if this object was loaded from one, even if no modifications were made!
|
||||
func (list *Schema2List) Serialize() ([]byte, error) {
|
||||
buf, err := json.Marshal(list)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error marshaling Schema2List %#v", list)
|
||||
}
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
// Schema2ListFromComponents creates a Schema2 manifest list instance from the
|
||||
// supplied data.
|
||||
func Schema2ListFromComponents(components []Schema2ManifestDescriptor) *Schema2List {
|
||||
list := Schema2List{
|
||||
SchemaVersion: 2,
|
||||
MediaType: DockerV2ListMediaType,
|
||||
Manifests: make([]Schema2ManifestDescriptor, len(components)),
|
||||
}
|
||||
for i, component := range components {
|
||||
m := Schema2ManifestDescriptor{
|
||||
Schema2Descriptor{
|
||||
MediaType: component.MediaType,
|
||||
Size: component.Size,
|
||||
Digest: component.Digest,
|
||||
URLs: dupStringSlice(component.URLs),
|
||||
},
|
||||
Schema2PlatformSpec{
|
||||
Architecture: component.Platform.Architecture,
|
||||
OS: component.Platform.OS,
|
||||
OSVersion: component.Platform.OSVersion,
|
||||
OSFeatures: dupStringSlice(component.Platform.OSFeatures),
|
||||
Variant: component.Platform.Variant,
|
||||
Features: dupStringSlice(component.Platform.Features),
|
||||
},
|
||||
}
|
||||
list.Manifests[i] = m
|
||||
}
|
||||
return &list
|
||||
}
|
||||
|
||||
// Schema2ListClone creates a deep copy of the passed-in list.
|
||||
func Schema2ListClone(list *Schema2List) *Schema2List {
|
||||
return Schema2ListFromComponents(list.Manifests)
|
||||
}
|
||||
|
||||
// ToOCI1Index returns the list encoded as an OCI1 index.
|
||||
func (list *Schema2List) ToOCI1Index() (*OCI1Index, error) {
|
||||
components := make([]imgspecv1.Descriptor, 0, len(list.Manifests))
|
||||
for _, manifest := range list.Manifests {
|
||||
converted := imgspecv1.Descriptor{
|
||||
MediaType: manifest.MediaType,
|
||||
Size: manifest.Size,
|
||||
Digest: manifest.Digest,
|
||||
URLs: dupStringSlice(manifest.URLs),
|
||||
Platform: &imgspecv1.Platform{
|
||||
OS: manifest.Platform.OS,
|
||||
Architecture: manifest.Platform.Architecture,
|
||||
OSFeatures: dupStringSlice(manifest.Platform.OSFeatures),
|
||||
OSVersion: manifest.Platform.OSVersion,
|
||||
Variant: manifest.Platform.Variant,
|
||||
},
|
||||
}
|
||||
components = append(components, converted)
|
||||
}
|
||||
oci := OCI1IndexFromComponents(components, nil)
|
||||
return oci, nil
|
||||
}
|
||||
|
||||
// ToSchema2List returns the list encoded as a Schema2 list.
|
||||
func (list *Schema2List) ToSchema2List() (*Schema2List, error) {
|
||||
return Schema2ListClone(list), nil
|
||||
}
|
||||
|
||||
// Schema2ListFromManifest creates a Schema2 manifest list instance from marshalled
|
||||
// JSON, presumably generated by encoding a Schema2 manifest list.
|
||||
func Schema2ListFromManifest(manifest []byte) (*Schema2List, error) {
|
||||
list := Schema2List{
|
||||
Manifests: []Schema2ManifestDescriptor{},
|
||||
}
|
||||
if err := json.Unmarshal(manifest, &list); err != nil {
|
||||
return nil, errors.Wrapf(err, "error unmarshaling Schema2List %q", string(manifest))
|
||||
}
|
||||
return &list, nil
|
||||
}
|
||||
|
||||
// Clone returns a deep copy of this list and its contents.
|
||||
func (list *Schema2List) Clone() List {
|
||||
return Schema2ListClone(list)
|
||||
}
|
||||
|
||||
// ConvertToMIMEType converts the passed-in manifest list to a manifest
|
||||
// list of the specified type.
|
||||
func (list *Schema2List) ConvertToMIMEType(manifestMIMEType string) (List, error) {
|
||||
switch normalized := NormalizedMIMEType(manifestMIMEType); normalized {
|
||||
case DockerV2ListMediaType:
|
||||
return list.Clone(), nil
|
||||
case imgspecv1.MediaTypeImageIndex:
|
||||
return list.ToOCI1Index()
|
||||
case DockerV2Schema1MediaType, DockerV2Schema1SignedMediaType, imgspecv1.MediaTypeImageManifest, DockerV2Schema2MediaType:
|
||||
return nil, fmt.Errorf("Can not convert manifest list to MIME type %q, which is not a list type", manifestMIMEType)
|
||||
default:
|
||||
// Note that this may not be reachable, NormalizedMIMEType has a default for unknown values.
|
||||
return nil, fmt.Errorf("Unimplemented manifest list MIME type %s", manifestMIMEType)
|
||||
}
|
||||
}
|
106
vendor/github.com/containers/image/v5/manifest/list.go
generated
vendored
Normal file
106
vendor/github.com/containers/image/v5/manifest/list.go
generated
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
package manifest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/containers/image/v5/types"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
var (
|
||||
// SupportedListMIMETypes is a list of the manifest list types that we know how to
|
||||
// read/manipulate/write.
|
||||
SupportedListMIMETypes = []string{
|
||||
DockerV2ListMediaType,
|
||||
imgspecv1.MediaTypeImageIndex,
|
||||
}
|
||||
)
|
||||
|
||||
// List is an interface for parsing, modifying lists of image manifests.
|
||||
// Callers can either use this abstract interface without understanding the details of the formats,
|
||||
// or instantiate a specific implementation (e.g. manifest.OCI1Index) and access the public members
|
||||
// directly.
|
||||
type List interface {
|
||||
// MIMEType returns the MIME type of this particular manifest list.
|
||||
MIMEType() string
|
||||
|
||||
// Instances returns a list of the manifests that this list knows of, other than its own.
|
||||
Instances() []digest.Digest
|
||||
|
||||
// Update information about the list's instances. The length of the passed-in slice must
|
||||
// match the length of the list of instances which the list already contains, and every field
|
||||
// must be specified.
|
||||
UpdateInstances([]ListUpdate) error
|
||||
|
||||
// Instance returns the size and MIME type of a particular instance in the list.
|
||||
Instance(digest.Digest) (ListUpdate, error)
|
||||
|
||||
// ChooseInstance selects which manifest is most appropriate for the platform described by the
|
||||
// SystemContext, or for the current platform if the SystemContext doesn't specify any details.
|
||||
ChooseInstance(ctx *types.SystemContext) (digest.Digest, error)
|
||||
|
||||
// Serialize returns the list in a blob format.
|
||||
// NOTE: Serialize() does not in general reproduce the original blob if this object was loaded
|
||||
// from, even if no modifications were made!
|
||||
Serialize() ([]byte, error)
|
||||
|
||||
// ConvertToMIMEType returns the list rebuilt to the specified MIME type, or an error.
|
||||
ConvertToMIMEType(mimeType string) (List, error)
|
||||
|
||||
// Clone returns a deep copy of this list and its contents.
|
||||
Clone() List
|
||||
}
|
||||
|
||||
// ListUpdate includes the fields which a List's UpdateInstances() method will modify.
|
||||
type ListUpdate struct {
|
||||
Digest digest.Digest
|
||||
Size int64
|
||||
MediaType string
|
||||
}
|
||||
|
||||
// dupStringSlice returns a deep copy of a slice of strings, or nil if the
|
||||
// source slice is empty.
|
||||
func dupStringSlice(list []string) []string {
|
||||
if len(list) == 0 {
|
||||
return nil
|
||||
}
|
||||
dup := make([]string, len(list))
|
||||
for i := range list {
|
||||
dup[i] = list[i]
|
||||
}
|
||||
return dup
|
||||
}
|
||||
|
||||
// dupStringStringMap returns a deep copy of a map[string]string, or nil if the
|
||||
// passed-in map is nil or has no keys.
|
||||
func dupStringStringMap(m map[string]string) map[string]string {
|
||||
if len(m) == 0 {
|
||||
return nil
|
||||
}
|
||||
result := make(map[string]string)
|
||||
for k, v := range m {
|
||||
result[k] = v
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// ListFromBlob parses a list of manifests.
|
||||
func ListFromBlob(manifest []byte, manifestMIMEType string) (List, error) {
|
||||
normalized := NormalizedMIMEType(manifestMIMEType)
|
||||
switch normalized {
|
||||
case DockerV2ListMediaType:
|
||||
return Schema2ListFromManifest(manifest)
|
||||
case imgspecv1.MediaTypeImageIndex:
|
||||
return OCI1IndexFromManifest(manifest)
|
||||
case DockerV2Schema1MediaType, DockerV2Schema1SignedMediaType, imgspecv1.MediaTypeImageManifest, DockerV2Schema2MediaType:
|
||||
return nil, fmt.Errorf("Treating single images as manifest lists is not implemented")
|
||||
}
|
||||
return nil, fmt.Errorf("Unimplemented manifest list MIME type %s (normalized as %s)", manifestMIMEType, normalized)
|
||||
}
|
||||
|
||||
// ConvertListToMIMEType converts the passed-in manifest list to a manifest
|
||||
// list of the specified type.
|
||||
func ConvertListToMIMEType(list List, manifestMIMEType string) (List, error) {
|
||||
return list.ConvertToMIMEType(manifestMIMEType)
|
||||
}
|
@ -4,7 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/libtrust"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
@ -52,6 +52,7 @@ var DefaultRequestedManifestMIMETypes = []string{
|
||||
DockerV2Schema1SignedMediaType,
|
||||
DockerV2Schema1MediaType,
|
||||
DockerV2ListMediaType,
|
||||
imgspecv1.MediaTypeImageIndex,
|
||||
}
|
||||
|
||||
// Manifest is an interface for parsing, modifying image manifests in isolation.
|
||||
@ -140,8 +141,11 @@ func GuessMIMEType(manifest []byte) string {
|
||||
if err := json.Unmarshal(manifest, &ociIndex); err != nil {
|
||||
return ""
|
||||
}
|
||||
if len(ociIndex.Manifests) != 0 && ociIndex.Manifests[0].MediaType == imgspecv1.MediaTypeImageManifest {
|
||||
return imgspecv1.MediaTypeImageIndex
|
||||
if len(ociIndex.Manifests) != 0 {
|
||||
if ociMan.Config.MediaType == "" {
|
||||
return imgspecv1.MediaTypeImageIndex
|
||||
}
|
||||
return ociMan.Config.MediaType
|
||||
}
|
||||
return DockerV2Schema2MediaType
|
||||
}
|
||||
@ -199,7 +203,7 @@ func AddDummyV2S1Signature(manifest []byte) ([]byte, error) {
|
||||
|
||||
// MIMETypeIsMultiImage returns true if mimeType is a list of images
|
||||
func MIMETypeIsMultiImage(mimeType string) bool {
|
||||
return mimeType == DockerV2ListMediaType
|
||||
return mimeType == DockerV2ListMediaType || mimeType == imgspecv1.MediaTypeImageIndex
|
||||
}
|
||||
|
||||
// NormalizedMIMEType returns the effective MIME type of a manifest MIME type returned by a server,
|
||||
@ -213,6 +217,7 @@ func NormalizedMIMEType(input string) string {
|
||||
return DockerV2Schema1SignedMediaType
|
||||
case DockerV2Schema1MediaType, DockerV2Schema1SignedMediaType,
|
||||
imgspecv1.MediaTypeImageManifest,
|
||||
imgspecv1.MediaTypeImageIndex,
|
||||
DockerV2Schema2MediaType,
|
||||
DockerV2ListMediaType:
|
||||
return input
|
||||
@ -232,18 +237,19 @@ func NormalizedMIMEType(input string) string {
|
||||
|
||||
// FromBlob returns a Manifest instance for the specified manifest blob and the corresponding MIME type
|
||||
func FromBlob(manblob []byte, mt string) (Manifest, error) {
|
||||
switch NormalizedMIMEType(mt) {
|
||||
nmt := NormalizedMIMEType(mt)
|
||||
switch nmt {
|
||||
case DockerV2Schema1MediaType, DockerV2Schema1SignedMediaType:
|
||||
return Schema1FromManifest(manblob)
|
||||
case imgspecv1.MediaTypeImageManifest:
|
||||
return OCI1FromManifest(manblob)
|
||||
case DockerV2Schema2MediaType:
|
||||
return Schema2FromManifest(manblob)
|
||||
case DockerV2ListMediaType:
|
||||
case DockerV2ListMediaType, imgspecv1.MediaTypeImageIndex:
|
||||
return nil, fmt.Errorf("Treating manifest lists as individual manifests is not implemented")
|
||||
default: // Note that this may not be reachable, NormalizedMIMEType has a default for unknown values.
|
||||
return nil, fmt.Errorf("Unimplemented manifest MIME type %s", mt)
|
||||
}
|
||||
// Note that this may not be reachable, NormalizedMIMEType has a default for unknown values.
|
||||
return nil, fmt.Errorf("Unimplemented manifest MIME type %s (normalized as %s)", mt, nmt)
|
||||
}
|
||||
|
||||
// layerInfosToStrings converts a list of layer infos, presumably obtained from a Manifest.LayerInfos()
|
@ -4,8 +4,8 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/containers/image/v4/pkg/compression"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/pkg/compression"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/opencontainers/image-spec/specs-go"
|
||||
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
221
vendor/github.com/containers/image/v5/manifest/oci_index.go
generated
vendored
Normal file
221
vendor/github.com/containers/image/v5/manifest/oci_index.go
generated
vendored
Normal file
@ -0,0 +1,221 @@
|
||||
package manifest
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/opencontainers/go-digest"
|
||||
imgspec "github.com/opencontainers/image-spec/specs-go"
|
||||
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// OCI1Index is just an alias for the OCI index type, but one which we can
|
||||
// provide methods for.
|
||||
type OCI1Index struct {
|
||||
imgspecv1.Index
|
||||
}
|
||||
|
||||
// MIMEType returns the MIME type of this particular manifest index.
|
||||
func (index *OCI1Index) MIMEType() string {
|
||||
return imgspecv1.MediaTypeImageIndex
|
||||
}
|
||||
|
||||
// Instances returns a slice of digests of the manifests that this index knows of.
|
||||
func (index *OCI1Index) Instances() []digest.Digest {
|
||||
results := make([]digest.Digest, len(index.Manifests))
|
||||
for i, m := range index.Manifests {
|
||||
results[i] = m.Digest
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
// Instance returns the ListUpdate of a particular instance in the index.
|
||||
func (index *OCI1Index) Instance(instanceDigest digest.Digest) (ListUpdate, error) {
|
||||
for _, manifest := range index.Manifests {
|
||||
if manifest.Digest == instanceDigest {
|
||||
return ListUpdate{
|
||||
Digest: manifest.Digest,
|
||||
Size: manifest.Size,
|
||||
MediaType: manifest.MediaType,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
return ListUpdate{}, errors.Errorf("unable to find instance %s in OCI1Index", instanceDigest)
|
||||
}
|
||||
|
||||
// UpdateInstances updates the sizes, digests, and media types of the manifests
|
||||
// which the list catalogs.
|
||||
func (index *OCI1Index) UpdateInstances(updates []ListUpdate) error {
|
||||
if len(updates) != len(index.Manifests) {
|
||||
return errors.Errorf("incorrect number of update entries passed to OCI1Index.UpdateInstances: expected %d, got %d", len(index.Manifests), len(updates))
|
||||
}
|
||||
for i := range updates {
|
||||
if err := updates[i].Digest.Validate(); err != nil {
|
||||
return errors.Wrapf(err, "update %d of %d passed to OCI1Index.UpdateInstances contained an invalid digest", i+1, len(updates))
|
||||
}
|
||||
index.Manifests[i].Digest = updates[i].Digest
|
||||
if updates[i].Size < 0 {
|
||||
return errors.Errorf("update %d of %d passed to OCI1Index.UpdateInstances had an invalid size (%d)", i+1, len(updates), updates[i].Size)
|
||||
}
|
||||
index.Manifests[i].Size = updates[i].Size
|
||||
if updates[i].MediaType == "" {
|
||||
return errors.Errorf("update %d of %d passed to OCI1Index.UpdateInstances had no media type (was %q)", i+1, len(updates), index.Manifests[i].MediaType)
|
||||
}
|
||||
if err := SupportedOCI1MediaType(updates[i].MediaType); err != nil && SupportedSchema2MediaType(updates[i].MediaType) != nil && updates[i].MediaType != imgspecv1.MediaTypeImageIndex {
|
||||
return errors.Wrapf(err, "update %d of %d passed to OCI1Index.UpdateInstances had an unsupported media type (was %q): %q", i+1, len(updates), index.Manifests[i].MediaType, updates[i].MediaType)
|
||||
}
|
||||
index.Manifests[i].MediaType = updates[i].MediaType
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ChooseInstance parses blob as an oci v1 manifest index, and returns the digest
|
||||
// of the image which is appropriate for the current environment.
|
||||
func (index *OCI1Index) ChooseInstance(ctx *types.SystemContext) (digest.Digest, error) {
|
||||
wantedArch := runtime.GOARCH
|
||||
if ctx != nil && ctx.ArchitectureChoice != "" {
|
||||
wantedArch = ctx.ArchitectureChoice
|
||||
}
|
||||
wantedOS := runtime.GOOS
|
||||
if ctx != nil && ctx.OSChoice != "" {
|
||||
wantedOS = ctx.OSChoice
|
||||
}
|
||||
|
||||
for _, d := range index.Manifests {
|
||||
if d.Platform != nil && d.Platform.Architecture == wantedArch && d.Platform.OS == wantedOS {
|
||||
return d.Digest, nil
|
||||
}
|
||||
}
|
||||
for _, d := range index.Manifests {
|
||||
if d.Platform == nil {
|
||||
return d.Digest, nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("no image found in image index for architecture %s, OS %s", wantedArch, wantedOS)
|
||||
}
|
||||
|
||||
// Serialize returns the index in a blob format.
|
||||
// NOTE: Serialize() does not in general reproduce the original blob if this object was loaded from one, even if no modifications were made!
|
||||
func (index *OCI1Index) Serialize() ([]byte, error) {
|
||||
buf, err := json.Marshal(index)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error marshaling OCI1Index %#v", index)
|
||||
}
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
// OCI1IndexFromComponents creates an OCI1 image index instance from the
|
||||
// supplied data.
|
||||
func OCI1IndexFromComponents(components []imgspecv1.Descriptor, annotations map[string]string) *OCI1Index {
|
||||
index := OCI1Index{
|
||||
imgspecv1.Index{
|
||||
Versioned: imgspec.Versioned{SchemaVersion: 2},
|
||||
Manifests: make([]imgspecv1.Descriptor, len(components)),
|
||||
Annotations: dupStringStringMap(annotations),
|
||||
},
|
||||
}
|
||||
for i, component := range components {
|
||||
var platform *imgspecv1.Platform
|
||||
if component.Platform != nil {
|
||||
platform = &imgspecv1.Platform{
|
||||
Architecture: component.Platform.Architecture,
|
||||
OS: component.Platform.OS,
|
||||
OSVersion: component.Platform.OSVersion,
|
||||
OSFeatures: dupStringSlice(component.Platform.OSFeatures),
|
||||
Variant: component.Platform.Variant,
|
||||
}
|
||||
}
|
||||
m := imgspecv1.Descriptor{
|
||||
MediaType: component.MediaType,
|
||||
Size: component.Size,
|
||||
Digest: component.Digest,
|
||||
URLs: dupStringSlice(component.URLs),
|
||||
Annotations: dupStringStringMap(component.Annotations),
|
||||
Platform: platform,
|
||||
}
|
||||
index.Manifests[i] = m
|
||||
}
|
||||
return &index
|
||||
}
|
||||
|
||||
// OCI1IndexClone creates a deep copy of the passed-in index.
|
||||
func OCI1IndexClone(index *OCI1Index) *OCI1Index {
|
||||
return OCI1IndexFromComponents(index.Manifests, index.Annotations)
|
||||
}
|
||||
|
||||
// ToOCI1Index returns the index encoded as an OCI1 index.
|
||||
func (index *OCI1Index) ToOCI1Index() (*OCI1Index, error) {
|
||||
return OCI1IndexClone(index), nil
|
||||
}
|
||||
|
||||
// ToSchema2List returns the index encoded as a Schema2 list.
|
||||
func (index *OCI1Index) ToSchema2List() (*Schema2List, error) {
|
||||
components := make([]Schema2ManifestDescriptor, 0, len(index.Manifests))
|
||||
for _, manifest := range index.Manifests {
|
||||
platform := manifest.Platform
|
||||
if platform == nil {
|
||||
platform = &imgspecv1.Platform{
|
||||
OS: runtime.GOOS,
|
||||
Architecture: runtime.GOARCH,
|
||||
}
|
||||
}
|
||||
converted := Schema2ManifestDescriptor{
|
||||
Schema2Descriptor{
|
||||
MediaType: manifest.MediaType,
|
||||
Size: manifest.Size,
|
||||
Digest: manifest.Digest,
|
||||
URLs: dupStringSlice(manifest.URLs),
|
||||
},
|
||||
Schema2PlatformSpec{
|
||||
OS: platform.OS,
|
||||
Architecture: platform.Architecture,
|
||||
OSFeatures: dupStringSlice(platform.OSFeatures),
|
||||
OSVersion: platform.OSVersion,
|
||||
Variant: platform.Variant,
|
||||
},
|
||||
}
|
||||
components = append(components, converted)
|
||||
}
|
||||
s2 := Schema2ListFromComponents(components)
|
||||
return s2, nil
|
||||
}
|
||||
|
||||
// OCI1IndexFromManifest creates an OCI1 manifest index instance from marshalled
|
||||
// JSON, presumably generated by encoding a OCI1 manifest index.
|
||||
func OCI1IndexFromManifest(manifest []byte) (*OCI1Index, error) {
|
||||
index := OCI1Index{
|
||||
Index: imgspecv1.Index{
|
||||
Versioned: imgspec.Versioned{SchemaVersion: 2},
|
||||
Manifests: []imgspecv1.Descriptor{},
|
||||
Annotations: make(map[string]string),
|
||||
},
|
||||
}
|
||||
if err := json.Unmarshal(manifest, &index); err != nil {
|
||||
return nil, errors.Wrapf(err, "error unmarshaling OCI1Index %q", string(manifest))
|
||||
}
|
||||
return &index, nil
|
||||
}
|
||||
|
||||
// Clone returns a deep copy of this list and its contents.
|
||||
func (index *OCI1Index) Clone() List {
|
||||
return OCI1IndexClone(index)
|
||||
}
|
||||
|
||||
// ConvertToMIMEType converts the passed-in image index to a manifest list of
|
||||
// the specified type.
|
||||
func (index *OCI1Index) ConvertToMIMEType(manifestMIMEType string) (List, error) {
|
||||
switch normalized := NormalizedMIMEType(manifestMIMEType); normalized {
|
||||
case DockerV2ListMediaType:
|
||||
return index.ToSchema2List()
|
||||
case imgspecv1.MediaTypeImageIndex:
|
||||
return index.Clone(), nil
|
||||
case DockerV2Schema1MediaType, DockerV2Schema1SignedMediaType, imgspecv1.MediaTypeImageManifest, DockerV2Schema2MediaType:
|
||||
return nil, fmt.Errorf("Can not convert image index to MIME type %q, which is not a list type", manifestMIMEType)
|
||||
default:
|
||||
// Note that this may not be reachable, NormalizedMIMEType has a default for unknown values.
|
||||
return nil, fmt.Errorf("Unimplemented manifest MIME type %s", manifestMIMEType)
|
||||
}
|
||||
}
|
@ -5,8 +5,9 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/storage/pkg/archive"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@ -105,19 +106,26 @@ func (d *ociArchiveImageDestination) TryReusingBlob(ctx context.Context, info ty
|
||||
return d.unpackedDest.TryReusingBlob(ctx, info, cache, canSubstitute)
|
||||
}
|
||||
|
||||
// PutManifest writes manifest to the destination
|
||||
func (d *ociArchiveImageDestination) PutManifest(ctx context.Context, m []byte) error {
|
||||
return d.unpackedDest.PutManifest(ctx, m)
|
||||
// PutManifest writes the manifest to the destination.
|
||||
// If instanceDigest is not nil, it contains a digest of the specific manifest instance to overwrite the manifest for (when
|
||||
// the primary manifest is a manifest list); this should always be nil if the primary manifest is not a manifest list.
|
||||
// It is expected but not enforced that the instanceDigest, when specified, matches the digest of `manifest` as generated
|
||||
// by `manifest.Digest()`.
|
||||
func (d *ociArchiveImageDestination) PutManifest(ctx context.Context, m []byte, instanceDigest *digest.Digest) error {
|
||||
return d.unpackedDest.PutManifest(ctx, m, instanceDigest)
|
||||
}
|
||||
|
||||
func (d *ociArchiveImageDestination) PutSignatures(ctx context.Context, signatures [][]byte) error {
|
||||
return d.unpackedDest.PutSignatures(ctx, signatures)
|
||||
// PutSignatures writes a set of signatures to the destination.
|
||||
// If instanceDigest is not nil, it contains a digest of the specific manifest instance to write or overwrite the signatures for
|
||||
// (when the primary manifest is a manifest list); this should always be nil if the primary manifest is not a manifest list.
|
||||
func (d *ociArchiveImageDestination) PutSignatures(ctx context.Context, signatures [][]byte, instanceDigest *digest.Digest) error {
|
||||
return d.unpackedDest.PutSignatures(ctx, signatures, instanceDigest)
|
||||
}
|
||||
|
||||
// Commit marks the process of storing the image as successful and asks for the image to be persisted
|
||||
// after the directory is made, it is tarred up into a file and the directory is deleted
|
||||
func (d *ociArchiveImageDestination) Commit(ctx context.Context) error {
|
||||
if err := d.unpackedDest.Commit(ctx); err != nil {
|
||||
func (d *ociArchiveImageDestination) Commit(ctx context.Context, unparsedToplevel types.UnparsedImage) error {
|
||||
if err := d.unpackedDest.Commit(ctx, unparsedToplevel); err != nil {
|
||||
return errors.Wrapf(err, "error storing image %q", d.ref.image)
|
||||
}
|
||||
|
@ -4,8 +4,8 @@ import (
|
||||
"context"
|
||||
"io"
|
||||
|
||||
ocilayout "github.com/containers/image/v4/oci/layout"
|
||||
"github.com/containers/image/v4/types"
|
||||
ocilayout "github.com/containers/image/v5/oci/layout"
|
||||
"github.com/containers/image/v5/types"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
@ -96,7 +96,14 @@ func (s *ociArchiveImageSource) GetSignatures(ctx context.Context, instanceDiges
|
||||
return s.unpackedSrc.GetSignatures(ctx, instanceDigest)
|
||||
}
|
||||
|
||||
// LayerInfosForCopy() returns updated layer info that should be used when reading, in preference to values in the manifest, if specified.
|
||||
func (s *ociArchiveImageSource) LayerInfosForCopy(ctx context.Context) ([]types.BlobInfo, error) {
|
||||
return nil, nil
|
||||
// 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. If values are returned, they should be used when using GetBlob()
|
||||
// to read the image's layers.
|
||||
// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve BlobInfos for
|
||||
// (when the primary manifest is a manifest list); this never happens if the primary manifest is not a manifest list
|
||||
// (e.g. if the source never returns manifest lists).
|
||||
// The Digest field is guaranteed to be provided; Size may be -1.
|
||||
// WARNING: The list may contain duplicates, and they are semantically relevant.
|
||||
func (s *ociArchiveImageSource) LayerInfosForCopy(ctx context.Context, instanceDigest *digest.Digest) ([]types.BlobInfo, error) {
|
||||
return s.unpackedSrc.LayerInfosForCopy(ctx, instanceDigest)
|
||||
}
|
@ -7,14 +7,14 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/image/v4/directory/explicitfilepath"
|
||||
"github.com/containers/image/v4/docker/reference"
|
||||
"github.com/containers/image/v4/image"
|
||||
"github.com/containers/image/v4/internal/tmpdir"
|
||||
"github.com/containers/image/v4/oci/internal"
|
||||
ocilayout "github.com/containers/image/v4/oci/layout"
|
||||
"github.com/containers/image/v4/transports"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/directory/explicitfilepath"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/image"
|
||||
"github.com/containers/image/v5/internal/tmpdir"
|
||||
"github.com/containers/image/v5/oci/internal"
|
||||
ocilayout "github.com/containers/image/v5/oci/layout"
|
||||
"github.com/containers/image/v5/transports"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/storage/pkg/archive"
|
||||
"github.com/pkg/errors"
|
||||
)
|
@ -9,8 +9,8 @@ import (
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
|
||||
"github.com/containers/image/v4/manifest"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/types"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
imgspec "github.com/opencontainers/image-spec/specs-go"
|
||||
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
@ -38,6 +38,7 @@ func newImageDestination(sys *types.SystemContext, ref ociReference) (types.Imag
|
||||
Versioned: imgspec.Versioned{
|
||||
SchemaVersion: 2,
|
||||
},
|
||||
Annotations: make(map[string]string),
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,6 +74,7 @@ func (d *ociImageDestination) Close() error {
|
||||
func (d *ociImageDestination) SupportedManifestMIMETypes() []string {
|
||||
return []string{
|
||||
imgspecv1.MediaTypeImageManifest,
|
||||
imgspecv1.MediaTypeImageIndex,
|
||||
}
|
||||
}
|
||||
|
||||
@ -205,20 +207,27 @@ func (d *ociImageDestination) TryReusingBlob(ctx context.Context, info types.Blo
|
||||
return true, types.BlobInfo{Digest: info.Digest, Size: finfo.Size()}, nil
|
||||
}
|
||||
|
||||
// PutManifest writes manifest to the destination.
|
||||
// PutManifest writes a manifest to the destination. Per our list of supported manifest MIME types,
|
||||
// this should be either an OCI manifest (possibly converted to this format by the caller) or index,
|
||||
// neither of which we'll need to modify further.
|
||||
// If instanceDigest is not nil, it contains a digest of the specific manifest instance to overwrite the manifest for (when
|
||||
// the primary manifest is a manifest list); this should always be nil if the primary manifest is not a manifest list.
|
||||
// It is expected but not enforced that the instanceDigest, when specified, matches the digest of `manifest` as generated
|
||||
// by `manifest.Digest()`.
|
||||
// FIXME? This should also receive a MIME type if known, to differentiate between schema versions.
|
||||
// If the destination is in principle available, refuses this manifest type (e.g. it does not recognize the schema),
|
||||
// but may accept a different manifest type, the returned error must be an ManifestTypeRejectedError.
|
||||
func (d *ociImageDestination) PutManifest(ctx context.Context, m []byte) error {
|
||||
digest, err := manifest.Digest(m)
|
||||
if err != nil {
|
||||
return err
|
||||
func (d *ociImageDestination) PutManifest(ctx context.Context, m []byte, instanceDigest *digest.Digest) error {
|
||||
var digest digest.Digest
|
||||
var err error
|
||||
if instanceDigest != nil {
|
||||
digest = *instanceDigest
|
||||
} else {
|
||||
digest, err = manifest.Digest(m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
desc := imgspecv1.Descriptor{}
|
||||
desc.Digest = digest
|
||||
// TODO(runcom): beaware and add support for OCI manifest list
|
||||
desc.MediaType = imgspecv1.MediaTypeImageManifest
|
||||
desc.Size = int64(len(m))
|
||||
|
||||
blobPath, err := d.ref.blobPath(digest, d.sharedBlobDir)
|
||||
if err != nil {
|
||||
@ -231,32 +240,59 @@ func (d *ociImageDestination) PutManifest(ctx context.Context, m []byte) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if instanceDigest != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// If we had platform information, we'd build an imgspecv1.Platform structure here.
|
||||
|
||||
// Start filling out the descriptor for this entry
|
||||
desc := imgspecv1.Descriptor{}
|
||||
desc.Digest = digest
|
||||
desc.Size = int64(len(m))
|
||||
if d.ref.image != "" {
|
||||
annotations := make(map[string]string)
|
||||
annotations["org.opencontainers.image.ref.name"] = d.ref.image
|
||||
desc.Annotations = annotations
|
||||
}
|
||||
desc.Platform = &imgspecv1.Platform{
|
||||
Architecture: runtime.GOARCH,
|
||||
OS: runtime.GOOS,
|
||||
desc.Annotations = make(map[string]string)
|
||||
desc.Annotations[imgspecv1.AnnotationRefName] = d.ref.image
|
||||
}
|
||||
|
||||
// If we knew the MIME type, we wouldn't have to guess here.
|
||||
desc.MediaType = manifest.GuessMIMEType(m)
|
||||
|
||||
d.addManifest(&desc)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *ociImageDestination) addManifest(desc *imgspecv1.Descriptor) {
|
||||
// If the new entry has a name, remove any conflicting names which we already have.
|
||||
if desc.Annotations != nil && desc.Annotations[imgspecv1.AnnotationRefName] != "" {
|
||||
// The name is being set on a new entry, so remove any older ones that had the same name.
|
||||
// We might be storing an index and all of its component images, and we'll want to attach
|
||||
// the name to the last one, which is the index.
|
||||
for i, manifest := range d.index.Manifests {
|
||||
if manifest.Annotations[imgspecv1.AnnotationRefName] == desc.Annotations[imgspecv1.AnnotationRefName] {
|
||||
delete(d.index.Manifests[i].Annotations, imgspecv1.AnnotationRefName)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
// If it has the same digest as another entry in the index, we already overwrote the file,
|
||||
// so just pick up the other information.
|
||||
for i, manifest := range d.index.Manifests {
|
||||
if manifest.Annotations["org.opencontainers.image.ref.name"] == desc.Annotations["org.opencontainers.image.ref.name"] {
|
||||
// TODO Should there first be a cleanup based on the descriptor we are going to replace?
|
||||
if manifest.Digest == desc.Digest {
|
||||
// Replace it completely.
|
||||
d.index.Manifests[i] = *desc
|
||||
return
|
||||
}
|
||||
}
|
||||
// It's a new entry to be added to the index.
|
||||
d.index.Manifests = append(d.index.Manifests, *desc)
|
||||
}
|
||||
|
||||
func (d *ociImageDestination) PutSignatures(ctx context.Context, signatures [][]byte) error {
|
||||
// PutSignatures would add the given signatures to the oci layout (currently not supported).
|
||||
// If instanceDigest is not nil, it contains a digest of the specific manifest instance to write or overwrite the signatures for
|
||||
// (when the primary manifest is a manifest list); this should always be nil if the primary manifest is not a manifest list.
|
||||
func (d *ociImageDestination) PutSignatures(ctx context.Context, signatures [][]byte, instanceDigest *digest.Digest) error {
|
||||
if len(signatures) != 0 {
|
||||
return errors.Errorf("Pushing signatures for OCI images is not supported")
|
||||
}
|
||||
@ -267,7 +303,7 @@ func (d *ociImageDestination) PutSignatures(ctx context.Context, signatures [][]
|
||||
// WARNING: This does not have any transactional semantics:
|
||||
// - Uploaded data MAY be visible to others before Commit() is called
|
||||
// - Uploaded data MAY be removed or MAY remain around if Close() is called without Commit() (i.e. rollback is allowed but not guaranteed)
|
||||
func (d *ociImageDestination) Commit(ctx context.Context) error {
|
||||
func (d *ociImageDestination) Commit(context.Context, types.UnparsedImage) error {
|
||||
if err := ioutil.WriteFile(d.ref.ociLayoutPath(), []byte(`{"imageLayoutVersion": "1.0.0"}`), 0644); err != nil {
|
||||
return err
|
||||
}
|
@ -8,8 +8,9 @@ import (
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/containers/image/v4/pkg/tlsclientconfig"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/pkg/tlsclientconfig"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/docker/go-connections/tlsconfig"
|
||||
"github.com/opencontainers/go-digest"
|
||||
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
@ -18,6 +19,7 @@ import (
|
||||
|
||||
type ociImageSource struct {
|
||||
ref ociReference
|
||||
index *imgspecv1.Index
|
||||
descriptor imgspecv1.Descriptor
|
||||
client *http.Client
|
||||
sharedBlobDir string
|
||||
@ -41,7 +43,11 @@ func newImageSource(sys *types.SystemContext, ref ociReference) (types.ImageSour
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
d := &ociImageSource{ref: ref, descriptor: descriptor, client: client}
|
||||
index, err := ref.getIndex()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
d := &ociImageSource{ref: ref, index: index, descriptor: descriptor, client: client}
|
||||
if sys != nil {
|
||||
// TODO(jonboulle): check dir existence?
|
||||
d.sharedBlobDir = sys.OCISharedBlobDirPath
|
||||
@ -66,28 +72,33 @@ func (s *ociImageSource) Close() error {
|
||||
func (s *ociImageSource) GetManifest(ctx context.Context, instanceDigest *digest.Digest) ([]byte, string, error) {
|
||||
var dig digest.Digest
|
||||
var mimeType string
|
||||
var err error
|
||||
|
||||
if instanceDigest == nil {
|
||||
dig = digest.Digest(s.descriptor.Digest)
|
||||
mimeType = s.descriptor.MediaType
|
||||
} else {
|
||||
dig = *instanceDigest
|
||||
// XXX: instanceDigest means that we don't immediately have the context of what
|
||||
// mediaType the manifest has. In OCI this means that we don't know
|
||||
// what reference it came from, so we just *assume* that its
|
||||
// MediaTypeImageManifest.
|
||||
// FIXME: We should actually be able to look up the manifest in the index,
|
||||
// and see the MIME type there.
|
||||
mimeType = imgspecv1.MediaTypeImageManifest
|
||||
for _, md := range s.index.Manifests {
|
||||
if md.Digest == dig {
|
||||
mimeType = md.MediaType
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
manifestPath, err := s.ref.blobPath(dig, s.sharedBlobDir)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
m, err := ioutil.ReadFile(manifestPath)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
if mimeType == "" {
|
||||
mimeType = manifest.GuessMIMEType(m)
|
||||
}
|
||||
|
||||
return m, mimeType, nil
|
||||
}
|
||||
@ -157,8 +168,15 @@ func (s *ociImageSource) getExternalBlob(ctx context.Context, urls []string) (io
|
||||
return nil, 0, errWrap
|
||||
}
|
||||
|
||||
// LayerInfosForCopy() returns updated layer info that should be used when reading, in preference to values in the manifest, if specified.
|
||||
func (s *ociImageSource) LayerInfosForCopy(ctx context.Context) ([]types.BlobInfo, 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. If values are returned, they should be used when using GetBlob()
|
||||
// to read the image's layers.
|
||||
// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve BlobInfos for
|
||||
// (when the primary manifest is a manifest list); this never happens if the primary manifest is not a manifest list
|
||||
// (e.g. if the source never returns manifest lists).
|
||||
// The Digest field is guaranteed to be provided; Size may be -1.
|
||||
// WARNING: The list may contain duplicates, and they are semantically relevant.
|
||||
func (s *ociImageSource) LayerInfosForCopy(context.Context, *digest.Digest) ([]types.BlobInfo, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
@ -8,12 +8,12 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/image/v4/directory/explicitfilepath"
|
||||
"github.com/containers/image/v4/docker/reference"
|
||||
"github.com/containers/image/v4/image"
|
||||
"github.com/containers/image/v4/oci/internal"
|
||||
"github.com/containers/image/v4/transports"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/directory/explicitfilepath"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/image"
|
||||
"github.com/containers/image/v5/oci/internal"
|
||||
"github.com/containers/image/v5/transports"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/opencontainers/go-digest"
|
||||
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
@ -195,10 +195,10 @@ func (ref ociReference) getManifestDescriptor() (imgspecv1.Descriptor, error) {
|
||||
} else {
|
||||
// if image specified, look through all manifests for a match
|
||||
for _, md := range index.Manifests {
|
||||
if md.MediaType != imgspecv1.MediaTypeImageManifest {
|
||||
if md.MediaType != imgspecv1.MediaTypeImageManifest && md.MediaType != imgspecv1.MediaTypeImageIndex {
|
||||
continue
|
||||
}
|
||||
refName, ok := md.Annotations["org.opencontainers.image.ref.name"]
|
||||
refName, ok := md.Annotations[imgspecv1.AnnotationRefName]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
@ -12,11 +12,11 @@ import (
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/image/v4/docker"
|
||||
"github.com/containers/image/v4/docker/reference"
|
||||
"github.com/containers/image/v4/manifest"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v4/version"
|
||||
"github.com/containers/image/v5/docker"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/image/v5/version"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
@ -231,16 +231,16 @@ func (s *openshiftImageSource) GetBlob(ctx context.Context, info types.BlobInfo,
|
||||
// (when the primary manifest is a manifest list); this never happens if the primary manifest is not a manifest list
|
||||
// (e.g. if the source never returns manifest lists).
|
||||
func (s *openshiftImageSource) GetSignatures(ctx context.Context, instanceDigest *digest.Digest) ([][]byte, error) {
|
||||
var imageName string
|
||||
var imageStreamImageName string
|
||||
if instanceDigest == nil {
|
||||
if err := s.ensureImageIsResolved(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
imageName = s.imageStreamImageName
|
||||
imageStreamImageName = s.imageStreamImageName
|
||||
} else {
|
||||
imageName = instanceDigest.String()
|
||||
imageStreamImageName = instanceDigest.String()
|
||||
}
|
||||
image, err := s.client.getImage(ctx, imageName)
|
||||
image, err := s.client.getImage(ctx, imageStreamImageName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -253,8 +253,15 @@ func (s *openshiftImageSource) GetSignatures(ctx context.Context, instanceDigest
|
||||
return sigs, nil
|
||||
}
|
||||
|
||||
// LayerInfosForCopy() returns updated layer info that should be used when reading, in preference to values in the manifest, if specified.
|
||||
func (s *openshiftImageSource) LayerInfosForCopy(ctx context.Context) ([]types.BlobInfo, 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. If values are returned, they should be used when using GetBlob()
|
||||
// to read the image's layers.
|
||||
// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve BlobInfos for
|
||||
// (when the primary manifest is a manifest list); this never happens if the primary manifest is not a manifest list
|
||||
// (e.g. if the source never returns manifest lists).
|
||||
// The Digest field is guaranteed to be provided; Size may be -1.
|
||||
// WARNING: The list may contain duplicates, and they are semantically relevant.
|
||||
func (s *openshiftImageSource) LayerInfosForCopy(ctx context.Context, instanceDigest *digest.Digest) ([]types.BlobInfo, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@ -414,20 +421,28 @@ func (d *openshiftImageDestination) TryReusingBlob(ctx context.Context, info typ
|
||||
// FIXME? This should also receive a MIME type if known, to differentiate between schema versions.
|
||||
// If the destination is in principle available, refuses this manifest type (e.g. it does not recognize the schema),
|
||||
// but may accept a different manifest type, the returned error must be an ManifestTypeRejectedError.
|
||||
func (d *openshiftImageDestination) PutManifest(ctx context.Context, m []byte) error {
|
||||
manifestDigest, err := manifest.Digest(m)
|
||||
if err != nil {
|
||||
return err
|
||||
func (d *openshiftImageDestination) PutManifest(ctx context.Context, m []byte, instanceDigest *digest.Digest) error {
|
||||
if instanceDigest == nil {
|
||||
manifestDigest, err := manifest.Digest(m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d.imageStreamImageName = manifestDigest.String()
|
||||
}
|
||||
d.imageStreamImageName = manifestDigest.String()
|
||||
|
||||
return d.docker.PutManifest(ctx, m)
|
||||
return d.docker.PutManifest(ctx, m, instanceDigest)
|
||||
}
|
||||
|
||||
func (d *openshiftImageDestination) PutSignatures(ctx context.Context, signatures [][]byte) error {
|
||||
if d.imageStreamImageName == "" {
|
||||
return errors.Errorf("Internal error: Unknown manifest digest, can't add signatures")
|
||||
func (d *openshiftImageDestination) PutSignatures(ctx context.Context, signatures [][]byte, instanceDigest *digest.Digest) error {
|
||||
var imageStreamName string
|
||||
if instanceDigest == nil {
|
||||
if d.imageStreamImageName == "" {
|
||||
return errors.Errorf("Internal error: Unknown manifest digest, can't add signatures")
|
||||
}
|
||||
imageStreamName = d.imageStreamImageName
|
||||
} else {
|
||||
imageStreamName = instanceDigest.String()
|
||||
}
|
||||
|
||||
// Because image signatures are a shared resource in Atomic Registry, the default upload
|
||||
// always adds signatures. Eventually we should also allow removing signatures.
|
||||
|
||||
@ -435,7 +450,7 @@ func (d *openshiftImageDestination) PutSignatures(ctx context.Context, signature
|
||||
return nil // No need to even read the old state.
|
||||
}
|
||||
|
||||
image, err := d.client.getImage(ctx, d.imageStreamImageName)
|
||||
image, err := d.client.getImage(ctx, imageStreamName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -460,7 +475,7 @@ sigExists:
|
||||
if err != nil || n != 16 {
|
||||
return errors.Wrapf(err, "Error generating random signature len %d", n)
|
||||
}
|
||||
signatureName = fmt.Sprintf("%s@%032x", d.imageStreamImageName, randBytes)
|
||||
signatureName = fmt.Sprintf("%s@%032x", imageStreamName, randBytes)
|
||||
if _, ok := existingSigNames[signatureName]; !ok {
|
||||
break
|
||||
}
|
||||
@ -489,8 +504,8 @@ sigExists:
|
||||
// WARNING: This does not have any transactional semantics:
|
||||
// - Uploaded data MAY be visible to others before Commit() is called
|
||||
// - Uploaded data MAY be removed or MAY remain around if Close() is called without Commit() (i.e. rollback is allowed but not guaranteed)
|
||||
func (d *openshiftImageDestination) Commit(ctx context.Context) error {
|
||||
return d.docker.Commit(ctx)
|
||||
func (d *openshiftImageDestination) Commit(ctx context.Context, unparsedToplevel types.UnparsedImage) error {
|
||||
return d.docker.Commit(ctx, unparsedToplevel)
|
||||
}
|
||||
|
||||
// These structs are subsets of github.com/openshift/origin/pkg/image/api/v1 and its dependencies.
|
@ -6,11 +6,11 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/image/v4/docker/policyconfiguration"
|
||||
"github.com/containers/image/v4/docker/reference"
|
||||
genericImage "github.com/containers/image/v4/image"
|
||||
"github.com/containers/image/v4/transports"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/docker/policyconfiguration"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
genericImage "github.com/containers/image/v5/image"
|
||||
"github.com/containers/image/v5/transports"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
@ -20,8 +20,8 @@ import (
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/containers/image/v4/manifest"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/storage/pkg/archive"
|
||||
"github.com/klauspost/pgzip"
|
||||
"github.com/opencontainers/go-digest"
|
||||
@ -376,10 +376,16 @@ func (d *ostreeImageDestination) TryReusingBlob(ctx context.Context, info types.
|
||||
}
|
||||
|
||||
// PutManifest writes manifest to the destination.
|
||||
// The instanceDigest value is expected to always be nil, because this transport does not support manifest lists, so
|
||||
// there can be no secondary manifests.
|
||||
// FIXME? This should also receive a MIME type if known, to differentiate between schema versions.
|
||||
// If the destination is in principle available, refuses this manifest type (e.g. it does not recognize the schema),
|
||||
// but may accept a different manifest type, the returned error must be an ManifestTypeRejectedError.
|
||||
func (d *ostreeImageDestination) PutManifest(ctx context.Context, manifestBlob []byte) error {
|
||||
func (d *ostreeImageDestination) PutManifest(ctx context.Context, manifestBlob []byte, instanceDigest *digest.Digest) error {
|
||||
if instanceDigest != nil {
|
||||
return errors.New(`Manifest lists are not supported by "ostree:"`)
|
||||
}
|
||||
|
||||
d.manifest = string(manifestBlob)
|
||||
|
||||
if err := json.Unmarshal(manifestBlob, &d.schema); err != nil {
|
||||
@ -400,7 +406,14 @@ func (d *ostreeImageDestination) PutManifest(ctx context.Context, manifestBlob [
|
||||
return ioutil.WriteFile(manifestPath, manifestBlob, 0644)
|
||||
}
|
||||
|
||||
func (d *ostreeImageDestination) PutSignatures(ctx context.Context, signatures [][]byte) error {
|
||||
// PutSignatures writes signatures to the destination.
|
||||
// The instanceDigest value is expected to always be nil, because this transport does not support manifest lists, so
|
||||
// there can be no secondary manifests.
|
||||
func (d *ostreeImageDestination) PutSignatures(ctx context.Context, signatures [][]byte, instanceDigest *digest.Digest) error {
|
||||
if instanceDigest != nil {
|
||||
return errors.New(`Manifest lists are not supported by "ostree:"`)
|
||||
}
|
||||
|
||||
path := filepath.Join(d.tmpDirPath, d.ref.signaturePath(0))
|
||||
if err := ensureParentDirectoryExists(path); err != nil {
|
||||
return err
|
||||
@ -416,7 +429,7 @@ func (d *ostreeImageDestination) PutSignatures(ctx context.Context, signatures [
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *ostreeImageDestination) Commit(ctx context.Context) error {
|
||||
func (d *ostreeImageDestination) Commit(context.Context, types.UnparsedImage) error {
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
@ -13,8 +13,8 @@ import (
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"github.com/containers/image/v4/manifest"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/storage/pkg/ioutils"
|
||||
"github.com/klauspost/pgzip"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
@ -98,9 +98,11 @@ func (s *ostreeImageSource) getTarSplitData(blob string) ([]byte, error) {
|
||||
|
||||
// GetManifest returns the image's manifest along with its MIME type (which may be empty when it can't be determined but the manifest is available).
|
||||
// It may use a remote (= slow) service.
|
||||
// This source implementation does not support manifest lists, so the passed-in instanceDigest should always be nil,
|
||||
// as the primary manifest can not be a list, so there can be non-default instances.
|
||||
func (s *ostreeImageSource) GetManifest(ctx context.Context, instanceDigest *digest.Digest) ([]byte, string, error) {
|
||||
if instanceDigest != nil {
|
||||
return nil, "", errors.Errorf(`Manifest lists are not supported by "ostree:"`)
|
||||
return nil, "", errors.New(`Manifest lists are not supported by "ostree:"`)
|
||||
}
|
||||
if s.repo == nil {
|
||||
repo, err := openRepo(s.ref.repo)
|
||||
@ -275,7 +277,7 @@ func (s *ostreeImageSource) GetBlob(ctx context.Context, info types.BlobInfo, ca
|
||||
|
||||
// Ensure s.compressed is initialized. It is build by LayerInfosForCopy.
|
||||
if s.compressed == nil {
|
||||
_, err := s.LayerInfosForCopy(ctx)
|
||||
_, err := s.LayerInfosForCopy(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, -1, err
|
||||
}
|
||||
@ -337,9 +339,12 @@ func (s *ostreeImageSource) GetBlob(ctx context.Context, info types.BlobInfo, ca
|
||||
return rc, layerSize, nil
|
||||
}
|
||||
|
||||
// GetSignatures returns the image's signatures. It may use a remote (= slow) service.
|
||||
// This source implementation does not support manifest lists, so the passed-in instanceDigest should always be nil,
|
||||
// as there can be no secondary manifests.
|
||||
func (s *ostreeImageSource) GetSignatures(ctx context.Context, instanceDigest *digest.Digest) ([][]byte, error) {
|
||||
if instanceDigest != nil {
|
||||
return nil, errors.New("manifest lists are not supported by this transport")
|
||||
return nil, errors.New(`Manifest lists are not supported by "ostree:"`)
|
||||
}
|
||||
lenSignatures, err := s.getLenSignatures()
|
||||
if err != nil {
|
||||
@ -372,9 +377,18 @@ func (s *ostreeImageSource) GetSignatures(ctx context.Context, instanceDigest *d
|
||||
return signatures, nil
|
||||
}
|
||||
|
||||
// LayerInfosForCopy() returns the list of layer blobs that make up the root filesystem of
|
||||
// the image, after they've been decompressed.
|
||||
func (s *ostreeImageSource) LayerInfosForCopy(ctx context.Context) ([]types.BlobInfo, 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. If values are returned, they should be used when using GetBlob()
|
||||
// to read the image's layers.
|
||||
// This source implementation does not support manifest lists, so the passed-in instanceDigest should always be nil,
|
||||
// as the primary manifest can not be a list, so there can be secondary manifests.
|
||||
// The Digest field is guaranteed to be provided; Size may be -1.
|
||||
// WARNING: The list may contain duplicates, and they are semantically relevant.
|
||||
func (s *ostreeImageSource) LayerInfosForCopy(ctx context.Context, instanceDigest *digest.Digest) ([]types.BlobInfo, error) {
|
||||
if instanceDigest != nil {
|
||||
return nil, errors.New(`Manifest lists are not supported by "ostree:"`)
|
||||
}
|
||||
|
||||
updatedBlobInfos := []types.BlobInfo{}
|
||||
manifestBlob, manifestType, err := s.GetManifest(ctx, nil)
|
||||
if err != nil {
|
@ -11,11 +11,11 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/image/v4/directory/explicitfilepath"
|
||||
"github.com/containers/image/v4/docker/reference"
|
||||
"github.com/containers/image/v4/image"
|
||||
"github.com/containers/image/v4/transports"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/directory/explicitfilepath"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/image"
|
||||
"github.com/containers/image/v5/transports"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
@ -7,8 +7,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/containers/image/v4/pkg/blobinfocache/internal/prioritize"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/pkg/blobinfocache/internal/prioritize"
|
||||
"github.com/containers/image/v5/types"
|
||||
bolt "github.com/etcd-io/bbolt"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/sirupsen/logrus"
|
@ -6,9 +6,9 @@ import (
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
|
||||
"github.com/containers/image/v4/pkg/blobinfocache/boltdb"
|
||||
"github.com/containers/image/v4/pkg/blobinfocache/memory"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/pkg/blobinfocache/boltdb"
|
||||
"github.com/containers/image/v5/pkg/blobinfocache/memory"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/opencontainers/go-digest"
|
||||
)
|
||||
|
@ -5,8 +5,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/containers/image/v4/pkg/blobinfocache/internal/prioritize"
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/pkg/blobinfocache/internal/prioritize"
|
||||
"github.com/containers/image/v5/types"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
@ -2,7 +2,7 @@
|
||||
package none
|
||||
|
||||
import (
|
||||
"github.com/containers/image/v4/types"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/opencontainers/go-digest"
|
||||
)
|
||||
|
@ -7,8 +7,8 @@ import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/containers/image/v4/pkg/compression/internal"
|
||||
"github.com/containers/image/v4/pkg/compression/types"
|
||||
"github.com/containers/image/v5/pkg/compression/internal"
|
||||
"github.com/containers/image/v5/pkg/compression/types"
|
||||
"github.com/klauspost/pgzip"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user