mirror of
https://github.com/containers/skopeo.git
synced 2025-09-21 09:57:19 +00:00
Update c/image with https://github.com/containers/image/pull/1944
... to update github.com/opencontainers/image-spec to v1.1.0-rc3. Signed-off-by: Miloslav Trmač <mitr@redhat.com>
This commit is contained in:
4
vendor/github.com/containers/image/v5/copy/blob.go
generated
vendored
4
vendor/github.com/containers/image/v5/copy/blob.go
generated
vendored
@@ -43,7 +43,7 @@ func (ic *imageCopier) copyBlobFromStream(ctx context.Context, srcReader io.Read
|
||||
stream.reader = bar.ProxyReader(stream.reader)
|
||||
|
||||
// === Decrypt the stream, if required.
|
||||
decryptionStep, err := ic.c.blobPipelineDecryptionStep(&stream, srcInfo)
|
||||
decryptionStep, err := ic.blobPipelineDecryptionStep(&stream, srcInfo)
|
||||
if err != nil {
|
||||
return types.BlobInfo{}, err
|
||||
}
|
||||
@@ -78,7 +78,7 @@ func (ic *imageCopier) copyBlobFromStream(ctx context.Context, srcReader io.Read
|
||||
// Before relaxing this, see the original pull request’s review if there are other reasons to reject this.
|
||||
return types.BlobInfo{}, errors.New("Unable to support both decryption and encryption in the same copy")
|
||||
}
|
||||
encryptionStep, err := ic.c.blobPipelineEncryptionStep(&stream, toEncrypt, srcInfo, decryptionStep)
|
||||
encryptionStep, err := ic.blobPipelineEncryptionStep(&stream, toEncrypt, srcInfo, decryptionStep)
|
||||
if err != nil {
|
||||
return types.BlobInfo{}, err
|
||||
}
|
||||
|
92
vendor/github.com/containers/image/v5/copy/encryption.go
generated
vendored
92
vendor/github.com/containers/image/v5/copy/encryption.go
generated
vendored
@@ -33,28 +33,33 @@ type bpDecryptionStepData struct {
|
||||
// blobPipelineDecryptionStep updates *stream to decrypt if, it necessary.
|
||||
// srcInfo is only used for error messages.
|
||||
// Returns data for other steps; the caller should eventually use updateCryptoOperation.
|
||||
func (c *copier) blobPipelineDecryptionStep(stream *sourceStream, srcInfo types.BlobInfo) (*bpDecryptionStepData, error) {
|
||||
if isOciEncrypted(stream.info.MediaType) && c.ociDecryptConfig != nil {
|
||||
desc := imgspecv1.Descriptor{
|
||||
Annotations: stream.info.Annotations,
|
||||
}
|
||||
reader, decryptedDigest, err := ocicrypt.DecryptLayer(c.ociDecryptConfig, stream.reader, desc, false)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("decrypting layer %s: %w", srcInfo.Digest, err)
|
||||
}
|
||||
|
||||
stream.reader = reader
|
||||
stream.info.Digest = decryptedDigest
|
||||
stream.info.Size = -1
|
||||
maps.DeleteFunc(stream.info.Annotations, func(k string, _ string) bool {
|
||||
return strings.HasPrefix(k, "org.opencontainers.image.enc")
|
||||
})
|
||||
func (ic *imageCopier) blobPipelineDecryptionStep(stream *sourceStream, srcInfo types.BlobInfo) (*bpDecryptionStepData, error) {
|
||||
if !isOciEncrypted(stream.info.MediaType) || ic.c.ociDecryptConfig == nil {
|
||||
return &bpDecryptionStepData{
|
||||
decrypting: true,
|
||||
decrypting: false,
|
||||
}, nil
|
||||
}
|
||||
|
||||
if ic.cannotModifyManifestReason != "" {
|
||||
return nil, fmt.Errorf("layer %s should be decrypted, but we can’t modify the manifest: %s", srcInfo.Digest, ic.cannotModifyManifestReason)
|
||||
}
|
||||
|
||||
desc := imgspecv1.Descriptor{
|
||||
Annotations: stream.info.Annotations,
|
||||
}
|
||||
reader, decryptedDigest, err := ocicrypt.DecryptLayer(ic.c.ociDecryptConfig, stream.reader, desc, false)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("decrypting layer %s: %w", srcInfo.Digest, err)
|
||||
}
|
||||
|
||||
stream.reader = reader
|
||||
stream.info.Digest = decryptedDigest
|
||||
stream.info.Size = -1
|
||||
maps.DeleteFunc(stream.info.Annotations, func(k string, _ string) bool {
|
||||
return strings.HasPrefix(k, "org.opencontainers.image.enc")
|
||||
})
|
||||
return &bpDecryptionStepData{
|
||||
decrypting: false,
|
||||
decrypting: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -74,34 +79,39 @@ type bpEncryptionStepData struct {
|
||||
// blobPipelineEncryptionStep updates *stream to encrypt if, it required by toEncrypt.
|
||||
// srcInfo is primarily used for error messages.
|
||||
// Returns data for other steps; the caller should eventually call updateCryptoOperationAndAnnotations.
|
||||
func (c *copier) blobPipelineEncryptionStep(stream *sourceStream, toEncrypt bool, srcInfo types.BlobInfo,
|
||||
func (ic *imageCopier) blobPipelineEncryptionStep(stream *sourceStream, toEncrypt bool, srcInfo types.BlobInfo,
|
||||
decryptionStep *bpDecryptionStepData) (*bpEncryptionStepData, error) {
|
||||
if toEncrypt && !isOciEncrypted(srcInfo.MediaType) && c.ociEncryptConfig != nil {
|
||||
var annotations map[string]string
|
||||
if !decryptionStep.decrypting {
|
||||
annotations = srcInfo.Annotations
|
||||
}
|
||||
desc := imgspecv1.Descriptor{
|
||||
MediaType: srcInfo.MediaType,
|
||||
Digest: srcInfo.Digest,
|
||||
Size: srcInfo.Size,
|
||||
Annotations: annotations,
|
||||
}
|
||||
reader, finalizer, err := ocicrypt.EncryptLayer(c.ociEncryptConfig, stream.reader, desc)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("encrypting blob %s: %w", srcInfo.Digest, err)
|
||||
}
|
||||
|
||||
stream.reader = reader
|
||||
stream.info.Digest = ""
|
||||
stream.info.Size = -1
|
||||
if !toEncrypt || isOciEncrypted(srcInfo.MediaType) || ic.c.ociEncryptConfig == nil {
|
||||
return &bpEncryptionStepData{
|
||||
encrypting: true,
|
||||
finalizer: finalizer,
|
||||
encrypting: false,
|
||||
}, nil
|
||||
}
|
||||
|
||||
if ic.cannotModifyManifestReason != "" {
|
||||
return nil, fmt.Errorf("layer %s should be encrypted, but we can’t modify the manifest: %s", srcInfo.Digest, ic.cannotModifyManifestReason)
|
||||
}
|
||||
|
||||
var annotations map[string]string
|
||||
if !decryptionStep.decrypting {
|
||||
annotations = srcInfo.Annotations
|
||||
}
|
||||
desc := imgspecv1.Descriptor{
|
||||
MediaType: srcInfo.MediaType,
|
||||
Digest: srcInfo.Digest,
|
||||
Size: srcInfo.Size,
|
||||
Annotations: annotations,
|
||||
}
|
||||
reader, finalizer, err := ocicrypt.EncryptLayer(ic.c.ociEncryptConfig, stream.reader, desc)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("encrypting blob %s: %w", srcInfo.Digest, err)
|
||||
}
|
||||
|
||||
stream.reader = reader
|
||||
stream.info.Digest = ""
|
||||
stream.info.Size = -1
|
||||
return &bpEncryptionStepData{
|
||||
encrypting: false,
|
||||
encrypting: true,
|
||||
finalizer: finalizer,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
44
vendor/github.com/containers/image/v5/copy/manifest.go
generated
vendored
44
vendor/github.com/containers/image/v5/copy/manifest.go
generated
vendored
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/containers/image/v5/internal/set"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/types"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
@@ -18,6 +19,9 @@ import (
|
||||
// Include v2s1 signed but not v2s1 unsigned, because docker/distribution requires a signature even if the unsigned MIME type is used.
|
||||
var preferredManifestMIMETypes = []string{manifest.DockerV2Schema2MediaType, manifest.DockerV2Schema1SignedMediaType}
|
||||
|
||||
// ociEncryptionMIMETypes lists manifest MIME types that are known to support OCI encryption.
|
||||
var ociEncryptionMIMETypes = []string{v1.MediaTypeImageManifest}
|
||||
|
||||
// orderedSet is a list of strings (MIME types or platform descriptors in our case), with each string appearing at most once.
|
||||
type orderedSet struct {
|
||||
list []string
|
||||
@@ -76,11 +80,14 @@ func determineManifestConversion(in determineManifestConversionInputs) (manifest
|
||||
destSupportedManifestMIMETypes = []string{in.forceManifestMIMEType}
|
||||
}
|
||||
|
||||
if len(destSupportedManifestMIMETypes) == 0 && (!in.requiresOCIEncryption || manifest.MIMETypeSupportsEncryption(srcType)) {
|
||||
return manifestConversionPlan{ // Anything goes; just use the original as is, do not try any conversions.
|
||||
preferredMIMEType: srcType,
|
||||
otherMIMETypeCandidates: []string{},
|
||||
}, nil
|
||||
if len(destSupportedManifestMIMETypes) == 0 {
|
||||
if !in.requiresOCIEncryption || manifest.MIMETypeSupportsEncryption(srcType) {
|
||||
return manifestConversionPlan{ // Anything goes; just use the original as is, do not try any conversions.
|
||||
preferredMIMEType: srcType,
|
||||
otherMIMETypeCandidates: []string{},
|
||||
}, nil
|
||||
}
|
||||
destSupportedManifestMIMETypes = ociEncryptionMIMETypes
|
||||
}
|
||||
supportedByDest := set.New[string]()
|
||||
for _, t := range destSupportedManifestMIMETypes {
|
||||
@@ -88,6 +95,27 @@ func determineManifestConversion(in determineManifestConversionInputs) (manifest
|
||||
supportedByDest.Add(t)
|
||||
}
|
||||
}
|
||||
if supportedByDest.Empty() {
|
||||
if len(destSupportedManifestMIMETypes) == 0 { // Coverage: This should never happen, empty values were replaced by ociEncryptionMIMETypes
|
||||
return manifestConversionPlan{}, errors.New("internal error: destSupportedManifestMIMETypes is empty")
|
||||
}
|
||||
// We know, and have verified, that destSupportedManifestMIMETypes is not empty, so encryption must have been involved.
|
||||
if !in.requiresOCIEncryption { // Coverage: This should never happen, destSupportedManifestMIMETypes was not empty, so we should have filtered for encryption.
|
||||
return manifestConversionPlan{}, errors.New("internal error: supportedByDest is empty but destSupportedManifestMIMETypes is not, and not encrypting")
|
||||
}
|
||||
// destSupportedManifestMIMETypes has three possible origins:
|
||||
if in.forceManifestMIMEType != "" { // 1. forceManifestType specified
|
||||
return manifestConversionPlan{}, fmt.Errorf("encryption required together with format %s, which does not support encryption",
|
||||
in.forceManifestMIMEType)
|
||||
}
|
||||
if len(in.destSupportedManifestMIMETypes) == 0 { // 2. destination accepts anything and we have chosen ociEncryptionMIMETypes
|
||||
// Coverage: This should never happen, ociEncryptionMIMETypes all support encryption
|
||||
return manifestConversionPlan{}, errors.New("internal error: in.destSupportedManifestMIMETypes is empty but supportedByDest is empty as well")
|
||||
}
|
||||
// 3. destination does not support encryption.
|
||||
return manifestConversionPlan{}, fmt.Errorf("encryption required but the destination only supports MIME types [%s], none of which support encryption",
|
||||
strings.Join(destSupportedManifestMIMETypes, ", "))
|
||||
}
|
||||
|
||||
// destSupportedManifestMIMETypes is a static guess; a particular registry may still only support a subset of the types.
|
||||
// So, build a list of types to try in order of decreasing preference.
|
||||
@@ -122,11 +150,13 @@ func determineManifestConversion(in determineManifestConversionInputs) (manifest
|
||||
|
||||
// Finally, try anything else the destination supports.
|
||||
for _, t := range destSupportedManifestMIMETypes {
|
||||
prioritizedTypes.append(t)
|
||||
if supportedByDest.Contains(t) {
|
||||
prioritizedTypes.append(t)
|
||||
}
|
||||
}
|
||||
|
||||
logrus.Debugf("Manifest has MIME type %s, ordered candidate list [%s]", srcType, strings.Join(prioritizedTypes.list, ", "))
|
||||
if len(prioritizedTypes.list) == 0 { // Coverage: destSupportedManifestMIMETypes is not empty (or we would have exited in the “Anything goes” case above), so this should never happen.
|
||||
if len(prioritizedTypes.list) == 0 { // Coverage: destSupportedManifestMIMETypes and supportedByDest, which is a subset, is not empty (or we would have exited above), so this should never happen.
|
||||
return manifestConversionPlan{}, errors.New("Internal error: no candidate MIME types")
|
||||
}
|
||||
res := manifestConversionPlan{
|
||||
|
52
vendor/github.com/containers/image/v5/docker/daemon/client.go
generated
vendored
52
vendor/github.com/containers/image/v5/docker/daemon/client.go
generated
vendored
@@ -21,33 +21,49 @@ func newDockerClient(sys *types.SystemContext) (*dockerclient.Client, error) {
|
||||
host = sys.DockerDaemonHost
|
||||
}
|
||||
|
||||
// Sadly, unix:// sockets don't work transparently with dockerclient.NewClient.
|
||||
// They work fine with a nil httpClient; with a non-nil httpClient, the transport’s
|
||||
// TLSClientConfig must be nil (or the client will try using HTTPS over the PF_UNIX socket
|
||||
// regardless of the values in the *tls.Config), and we would have to call sockets.ConfigureTransport.
|
||||
opts := []dockerclient.Opt{
|
||||
dockerclient.WithHost(host),
|
||||
dockerclient.WithVersion(defaultAPIVersion),
|
||||
}
|
||||
|
||||
// We conditionalize building the TLS configuration only to TLS sockets:
|
||||
//
|
||||
// We don't really want to configure anything for unix:// sockets, so just pass a nil *http.Client.
|
||||
// The dockerclient.Client implementation differentiates between
|
||||
// - Client.proto, which is ~how the connection is establishe (IP / AF_UNIX/Windows)
|
||||
// - Client.scheme, which is what is sent over the connection (HTTP with/without TLS).
|
||||
//
|
||||
// Similarly, if we want to communicate over plain HTTP on a TCP socket, we also need to set
|
||||
// TLSClientConfig to nil. This can be achieved by using the form `http://`
|
||||
// Only Client.proto is set from the URL in dockerclient.WithHost(),
|
||||
// Client.scheme is detected based on a http.Client.TLSClientConfig presence;
|
||||
// dockerclient.WithHTTPClient with a client that has TLSClientConfig set
|
||||
// will, by default, trigger an attempt to use TLS.
|
||||
//
|
||||
// So, don’t use WithHTTPClient for unix:// sockets at all.
|
||||
//
|
||||
// Similarly, if we want to communicate over plain HTTP on a TCP socket (http://),
|
||||
// we also should not set TLSClientConfig. We continue to use WithHTTPClient
|
||||
// with our slightly non-default settings to avoid a behavior change on updates of c/image.
|
||||
//
|
||||
// Alternatively we could use dockerclient.WithScheme to drive the TLS/non-TLS logic
|
||||
// explicitly, but we would still want to set WithHTTPClient (differently) for https:// and http:// ;
|
||||
// so that would not be any simpler.
|
||||
serverURL, err := dockerclient.ParseHostURL(host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var httpClient *http.Client
|
||||
if serverURL.Scheme != "unix" {
|
||||
if serverURL.Scheme == "http" {
|
||||
httpClient = httpConfig()
|
||||
} else {
|
||||
hc, err := tlsConfig(sys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
httpClient = hc
|
||||
switch serverURL.Scheme {
|
||||
case "unix": // Nothing
|
||||
case "http":
|
||||
hc := httpConfig()
|
||||
opts = append(opts, dockerclient.WithHTTPClient(hc))
|
||||
default:
|
||||
hc, err := tlsConfig(sys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
opts = append(opts, dockerclient.WithHTTPClient(hc))
|
||||
}
|
||||
|
||||
return dockerclient.NewClient(host, defaultAPIVersion, httpClient, nil)
|
||||
return dockerclient.NewClientWithOpts(opts...)
|
||||
}
|
||||
|
||||
func tlsConfig(sys *types.SystemContext) (*http.Client, error) {
|
||||
|
4
vendor/github.com/containers/image/v5/internal/image/docker_schema2.go
generated
vendored
4
vendor/github.com/containers/image/v5/internal/image/docker_schema2.go
generated
vendored
@@ -226,9 +226,9 @@ func (m *manifestSchema2) convertToManifestOCI1(ctx context.Context, _ *types.Ma
|
||||
layers[idx] = oci1DescriptorFromSchema2Descriptor(m.m.LayersDescriptors[idx])
|
||||
switch m.m.LayersDescriptors[idx].MediaType {
|
||||
case manifest.DockerV2Schema2ForeignLayerMediaType:
|
||||
layers[idx].MediaType = imgspecv1.MediaTypeImageLayerNonDistributable
|
||||
layers[idx].MediaType = imgspecv1.MediaTypeImageLayerNonDistributable //nolint:staticcheck // NonDistributable layers are deprecated, but we want to continue to support manipulating pre-existing images.
|
||||
case manifest.DockerV2Schema2ForeignLayerMediaTypeGzip:
|
||||
layers[idx].MediaType = imgspecv1.MediaTypeImageLayerNonDistributableGzip
|
||||
layers[idx].MediaType = imgspecv1.MediaTypeImageLayerNonDistributableGzip //nolint:staticcheck // NonDistributable layers are deprecated, but we want to continue to support manipulating pre-existing images.
|
||||
case manifest.DockerV2SchemaLayerMediaTypeUncompressed:
|
||||
layers[idx].MediaType = imgspecv1.MediaTypeImageLayer
|
||||
case manifest.DockerV2Schema2LayerMediaType:
|
||||
|
6
vendor/github.com/containers/image/v5/internal/image/oci.go
generated
vendored
6
vendor/github.com/containers/image/v5/internal/image/oci.go
generated
vendored
@@ -215,11 +215,11 @@ func (m *manifestOCI1) convertToManifestSchema2(_ context.Context, _ *types.Mani
|
||||
for idx := range layers {
|
||||
layers[idx] = schema2DescriptorFromOCI1Descriptor(m.m.Layers[idx])
|
||||
switch layers[idx].MediaType {
|
||||
case imgspecv1.MediaTypeImageLayerNonDistributable:
|
||||
case imgspecv1.MediaTypeImageLayerNonDistributable: //nolint:staticcheck // NonDistributable layers are deprecated, but we want to continue to support manipulating pre-existing images.
|
||||
layers[idx].MediaType = manifest.DockerV2Schema2ForeignLayerMediaType
|
||||
case imgspecv1.MediaTypeImageLayerNonDistributableGzip:
|
||||
case imgspecv1.MediaTypeImageLayerNonDistributableGzip: //nolint:staticcheck // NonDistributable layers are deprecated, but we want to continue to support manipulating pre-existing images.
|
||||
layers[idx].MediaType = manifest.DockerV2Schema2ForeignLayerMediaTypeGzip
|
||||
case imgspecv1.MediaTypeImageLayerNonDistributableZstd:
|
||||
case imgspecv1.MediaTypeImageLayerNonDistributableZstd: //nolint:staticcheck // NonDistributable layers are deprecated, but we want to continue to support manipulating pre-existing images.
|
||||
return nil, fmt.Errorf("Error during manifest conversion: %q: zstd compression is not supported for docker images", layers[idx].MediaType)
|
||||
case imgspecv1.MediaTypeImageLayer:
|
||||
layers[idx].MediaType = manifest.DockerV2SchemaLayerMediaTypeUncompressed
|
||||
|
16
vendor/github.com/containers/image/v5/manifest/oci.go
generated
vendored
16
vendor/github.com/containers/image/v5/manifest/oci.go
generated
vendored
@@ -42,7 +42,12 @@ type OCI1 struct {
|
||||
// useful for validation anyway.
|
||||
func SupportedOCI1MediaType(m string) error {
|
||||
switch m {
|
||||
case imgspecv1.MediaTypeDescriptor, imgspecv1.MediaTypeImageConfig, imgspecv1.MediaTypeImageLayer, imgspecv1.MediaTypeImageLayerGzip, imgspecv1.MediaTypeImageLayerNonDistributable, imgspecv1.MediaTypeImageLayerNonDistributableGzip, imgspecv1.MediaTypeImageLayerNonDistributableZstd, imgspecv1.MediaTypeImageLayerZstd, imgspecv1.MediaTypeImageManifest, imgspecv1.MediaTypeLayoutHeader, ociencspec.MediaTypeLayerEnc, ociencspec.MediaTypeLayerGzipEnc:
|
||||
case imgspecv1.MediaTypeDescriptor, imgspecv1.MediaTypeImageConfig,
|
||||
imgspecv1.MediaTypeImageLayer, imgspecv1.MediaTypeImageLayerGzip, imgspecv1.MediaTypeImageLayerZstd,
|
||||
imgspecv1.MediaTypeImageLayerNonDistributable, imgspecv1.MediaTypeImageLayerNonDistributableGzip, imgspecv1.MediaTypeImageLayerNonDistributableZstd, //nolint:staticcheck // NonDistributable layers are deprecated, but we want to continue to support manipulating pre-existing images.
|
||||
imgspecv1.MediaTypeImageManifest,
|
||||
imgspecv1.MediaTypeLayoutHeader,
|
||||
ociencspec.MediaTypeLayerEnc, ociencspec.MediaTypeLayerGzipEnc:
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("unsupported OCIv1 media type: %q", m)
|
||||
@@ -102,9 +107,9 @@ func (m *OCI1) LayerInfos() []LayerInfo {
|
||||
|
||||
var oci1CompressionMIMETypeSets = []compressionMIMETypeSet{
|
||||
{
|
||||
mtsUncompressed: imgspecv1.MediaTypeImageLayerNonDistributable,
|
||||
compressiontypes.GzipAlgorithmName: imgspecv1.MediaTypeImageLayerNonDistributableGzip,
|
||||
compressiontypes.ZstdAlgorithmName: imgspecv1.MediaTypeImageLayerNonDistributableZstd,
|
||||
mtsUncompressed: imgspecv1.MediaTypeImageLayerNonDistributable, //nolint:staticcheck // NonDistributable layers are deprecated, but we want to continue to support manipulating pre-existing images.
|
||||
compressiontypes.GzipAlgorithmName: imgspecv1.MediaTypeImageLayerNonDistributableGzip, //nolint:staticcheck // NonDistributable layers are deprecated, but we want to continue to support manipulating pre-existing images.
|
||||
compressiontypes.ZstdAlgorithmName: imgspecv1.MediaTypeImageLayerNonDistributableZstd, //nolint:staticcheck // NonDistributable layers are deprecated, but we want to continue to support manipulating pre-existing images.
|
||||
},
|
||||
{
|
||||
mtsUncompressed: imgspecv1.MediaTypeImageLayer,
|
||||
@@ -166,7 +171,8 @@ func getEncryptedMediaType(mediatype string) (string, error) {
|
||||
}
|
||||
unsuffixedMediatype := strings.Split(mediatype, "+")[0]
|
||||
switch unsuffixedMediatype {
|
||||
case DockerV2Schema2LayerMediaType, imgspecv1.MediaTypeImageLayer, imgspecv1.MediaTypeImageLayerNonDistributable:
|
||||
case DockerV2Schema2LayerMediaType, imgspecv1.MediaTypeImageLayer,
|
||||
imgspecv1.MediaTypeImageLayerNonDistributable: //nolint:staticcheck // NonDistributable layers are deprecated, but we want to continue to support manipulating pre-existing images.
|
||||
return mediatype + "+encrypted", nil
|
||||
}
|
||||
|
||||
|
12
vendor/github.com/containers/image/v5/oci/layout/oci_transport.go
generated
vendored
12
vendor/github.com/containers/image/v5/oci/layout/oci_transport.go
generated
vendored
@@ -188,14 +188,18 @@ func (ref ociReference) getManifestDescriptor() (imgspecv1.Descriptor, error) {
|
||||
return index.Manifests[0], nil
|
||||
} else {
|
||||
// if image specified, look through all manifests for a match
|
||||
var unsupportedMIMETypes []string
|
||||
for _, md := range index.Manifests {
|
||||
if md.MediaType != imgspecv1.MediaTypeImageManifest && md.MediaType != imgspecv1.MediaTypeImageIndex {
|
||||
continue
|
||||
}
|
||||
if refName, ok := md.Annotations[imgspecv1.AnnotationRefName]; ok && refName == ref.image {
|
||||
return md, nil
|
||||
if md.MediaType == imgspecv1.MediaTypeImageManifest || md.MediaType == imgspecv1.MediaTypeImageIndex {
|
||||
return md, nil
|
||||
}
|
||||
unsupportedMIMETypes = append(unsupportedMIMETypes, md.MediaType)
|
||||
}
|
||||
}
|
||||
if len(unsupportedMIMETypes) != 0 {
|
||||
return imgspecv1.Descriptor{}, fmt.Errorf("reference %q matches unsupported manifest MIME types %q", ref.image, unsupportedMIMETypes)
|
||||
}
|
||||
}
|
||||
return imgspecv1.Descriptor{}, ImageNotFoundError{ref}
|
||||
}
|
||||
|
10
vendor/github.com/containers/image/v5/sif/src.go
generated
vendored
10
vendor/github.com/containers/image/v5/sif/src.go
generated
vendored
@@ -96,9 +96,11 @@ func newImageSource(ctx context.Context, sys *types.SystemContext, ref sifRefere
|
||||
|
||||
created := sifImg.ModifiedAt()
|
||||
config := imgspecv1.Image{
|
||||
Created: &created,
|
||||
Architecture: sifImg.PrimaryArch(),
|
||||
OS: "linux",
|
||||
Created: &created,
|
||||
Platform: imgspecv1.Platform{
|
||||
Architecture: sifImg.PrimaryArch(),
|
||||
OS: "linux",
|
||||
},
|
||||
Config: imgspecv1.ImageConfig{
|
||||
Cmd: commandLine,
|
||||
},
|
||||
@@ -180,7 +182,7 @@ func (s *sifImageSource) Close() error {
|
||||
func (s *sifImageSource) GetBlob(ctx context.Context, info types.BlobInfo, cache types.BlobInfoCache) (io.ReadCloser, int64, error) {
|
||||
switch info.Digest {
|
||||
case s.configDigest:
|
||||
return io.NopCloser(bytes.NewBuffer(s.config)), int64(len(s.config)), nil
|
||||
return io.NopCloser(bytes.NewReader(s.config)), int64(len(s.config)), nil
|
||||
case s.layerDigest:
|
||||
reader, err := os.Open(s.layerFile)
|
||||
if err != nil {
|
||||
|
161
vendor/github.com/containers/image/v5/tarball/tarball_src.go
generated
vendored
161
vendor/github.com/containers/image/v5/tarball/tarball_src.go
generated
vendored
@@ -19,7 +19,6 @@ import (
|
||||
imgspecs "github.com/opencontainers/image-spec/specs-go"
|
||||
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"golang.org/x/exp/maps"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
type tarballImageSource struct {
|
||||
@@ -29,42 +28,46 @@ type tarballImageSource struct {
|
||||
impl.DoesNotAffectLayerInfosForCopy
|
||||
stubs.NoGetBlobAtInitialize
|
||||
|
||||
reference tarballReference
|
||||
filenames []string
|
||||
diffIDs []digest.Digest
|
||||
diffSizes []int64
|
||||
blobIDs []digest.Digest
|
||||
blobSizes []int64
|
||||
blobTypes []string
|
||||
config []byte
|
||||
configID digest.Digest
|
||||
configSize int64
|
||||
manifest []byte
|
||||
reference tarballReference
|
||||
blobs map[digest.Digest]tarballBlob
|
||||
manifest []byte
|
||||
}
|
||||
|
||||
// tarballBlob is a blob that tarballImagSource can return by GetBlob.
|
||||
type tarballBlob struct {
|
||||
contents []byte // or nil to read from filename below
|
||||
filename string // valid if contents == nil
|
||||
size int64
|
||||
}
|
||||
|
||||
func (r *tarballReference) NewImageSource(ctx context.Context, sys *types.SystemContext) (types.ImageSource, error) {
|
||||
// Gather up the digests, sizes, and date information for all of the files.
|
||||
filenames := []string{}
|
||||
// Pick up the layer comment from the configuration's history list, if one is set.
|
||||
comment := "imported from tarball"
|
||||
if len(r.config.History) > 0 && r.config.History[0].Comment != "" {
|
||||
comment = r.config.History[0].Comment
|
||||
}
|
||||
|
||||
// Gather up the digests, sizes, and history information for all of the files.
|
||||
blobs := map[digest.Digest]tarballBlob{}
|
||||
diffIDs := []digest.Digest{}
|
||||
diffSizes := []int64{}
|
||||
blobIDs := []digest.Digest{}
|
||||
blobSizes := []int64{}
|
||||
blobTimes := []time.Time{}
|
||||
blobTypes := []string{}
|
||||
created := time.Time{}
|
||||
history := []imgspecv1.History{}
|
||||
layerDescriptors := []imgspecv1.Descriptor{}
|
||||
for _, filename := range r.filenames {
|
||||
var file *os.File
|
||||
var err error
|
||||
var blobSize int64
|
||||
var blobTime time.Time
|
||||
var reader io.Reader
|
||||
var blobTime time.Time
|
||||
var blob tarballBlob
|
||||
if filename == "-" {
|
||||
blobSize = int64(len(r.stdin))
|
||||
blobTime = time.Now()
|
||||
reader = bytes.NewReader(r.stdin)
|
||||
blobTime = time.Now()
|
||||
blob = tarballBlob{
|
||||
contents: r.stdin,
|
||||
size: int64(len(r.stdin)),
|
||||
}
|
||||
} else {
|
||||
file, err = os.Open(filename)
|
||||
file, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error opening %q for reading: %w", filename, err)
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
reader = file
|
||||
@@ -72,8 +75,11 @@ func (r *tarballReference) NewImageSource(ctx context.Context, sys *types.System
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error reading size of %q: %w", filename, err)
|
||||
}
|
||||
blobSize = fileinfo.Size()
|
||||
blobTime = fileinfo.ModTime()
|
||||
blob = tarballBlob{
|
||||
filename: filename,
|
||||
size: fileinfo.Size(),
|
||||
}
|
||||
}
|
||||
|
||||
// Default to assuming the layer is compressed.
|
||||
@@ -96,8 +102,7 @@ func (r *tarballReference) NewImageSource(ctx context.Context, sys *types.System
|
||||
uncompressed = nil
|
||||
}
|
||||
// TODO: This can take quite some time, and should ideally be cancellable using ctx.Done().
|
||||
n, err := io.Copy(io.Discard, reader)
|
||||
if err != nil {
|
||||
if _, err := io.Copy(io.Discard, reader); err != nil {
|
||||
return nil, fmt.Errorf("error reading %q: %v", filename, err)
|
||||
}
|
||||
if uncompressed != nil {
|
||||
@@ -105,38 +110,26 @@ func (r *tarballReference) NewImageSource(ctx context.Context, sys *types.System
|
||||
}
|
||||
|
||||
// Grab our uncompressed and possibly-compressed digests and sizes.
|
||||
filenames = append(filenames, filename)
|
||||
diffIDs = append(diffIDs, diffIDdigester.Digest())
|
||||
diffSizes = append(diffSizes, n)
|
||||
blobIDs = append(blobIDs, blobIDdigester.Digest())
|
||||
blobSizes = append(blobSizes, blobSize)
|
||||
blobTimes = append(blobTimes, blobTime)
|
||||
blobTypes = append(blobTypes, layerType)
|
||||
}
|
||||
diffID := diffIDdigester.Digest()
|
||||
blobID := blobIDdigester.Digest()
|
||||
diffIDs = append(diffIDs, diffID)
|
||||
blobs[blobID] = blob
|
||||
|
||||
// Build the rootfs and history for the configuration blob.
|
||||
rootfs := imgspecv1.RootFS{
|
||||
Type: "layers",
|
||||
DiffIDs: diffIDs,
|
||||
}
|
||||
created := time.Time{}
|
||||
history := []imgspecv1.History{}
|
||||
// Pick up the layer comment from the configuration's history list, if one is set.
|
||||
comment := "imported from tarball"
|
||||
if len(r.config.History) > 0 && r.config.History[0].Comment != "" {
|
||||
comment = r.config.History[0].Comment
|
||||
}
|
||||
for i := range diffIDs {
|
||||
createdBy := fmt.Sprintf("/bin/sh -c #(nop) ADD file:%s in %c", diffIDs[i].Hex(), os.PathSeparator)
|
||||
history = append(history, imgspecv1.History{
|
||||
Created: &blobTimes[i],
|
||||
CreatedBy: createdBy,
|
||||
Created: &blobTime,
|
||||
CreatedBy: fmt.Sprintf("/bin/sh -c #(nop) ADD file:%s in %c", diffID.Hex(), os.PathSeparator),
|
||||
Comment: comment,
|
||||
})
|
||||
// Use the mtime of the most recently modified file as the image's creation time.
|
||||
if created.Before(blobTimes[i]) {
|
||||
created = blobTimes[i]
|
||||
if created.Before(blobTime) {
|
||||
created = blobTime
|
||||
}
|
||||
|
||||
layerDescriptors = append(layerDescriptors, imgspecv1.Descriptor{
|
||||
Digest: blobID,
|
||||
Size: blob.size,
|
||||
MediaType: layerType,
|
||||
})
|
||||
}
|
||||
|
||||
// Pick up other defaults from the config in the reference.
|
||||
@@ -150,7 +143,10 @@ func (r *tarballReference) NewImageSource(ctx context.Context, sys *types.System
|
||||
if config.OS == "" {
|
||||
config.OS = runtime.GOOS
|
||||
}
|
||||
config.RootFS = rootfs
|
||||
config.RootFS = imgspecv1.RootFS{
|
||||
Type: "layers",
|
||||
DiffIDs: diffIDs,
|
||||
}
|
||||
config.History = history
|
||||
|
||||
// Encode and digest the image configuration blob.
|
||||
@@ -159,24 +155,19 @@ func (r *tarballReference) NewImageSource(ctx context.Context, sys *types.System
|
||||
return nil, fmt.Errorf("error generating configuration blob for %q: %v", strings.Join(r.filenames, separator), err)
|
||||
}
|
||||
configID := digest.Canonical.FromBytes(configBytes)
|
||||
configSize := int64(len(configBytes))
|
||||
|
||||
// Populate a manifest with the configuration blob and the file as the single layer.
|
||||
layerDescriptors := []imgspecv1.Descriptor{}
|
||||
for i := range blobIDs {
|
||||
layerDescriptors = append(layerDescriptors, imgspecv1.Descriptor{
|
||||
Digest: blobIDs[i],
|
||||
Size: blobSizes[i],
|
||||
MediaType: blobTypes[i],
|
||||
})
|
||||
blobs[configID] = tarballBlob{
|
||||
contents: configBytes,
|
||||
size: int64(len(configBytes)),
|
||||
}
|
||||
|
||||
// Populate a manifest with the configuration blob and the layers.
|
||||
manifest := imgspecv1.Manifest{
|
||||
Versioned: imgspecs.Versioned{
|
||||
SchemaVersion: 2,
|
||||
},
|
||||
Config: imgspecv1.Descriptor{
|
||||
Digest: configID,
|
||||
Size: configSize,
|
||||
Size: int64(len(configBytes)),
|
||||
MediaType: imgspecv1.MediaTypeImageConfig,
|
||||
},
|
||||
Layers: layerDescriptors,
|
||||
@@ -196,17 +187,9 @@ func (r *tarballReference) NewImageSource(ctx context.Context, sys *types.System
|
||||
}),
|
||||
NoGetBlobAtInitialize: stubs.NoGetBlobAt(r),
|
||||
|
||||
reference: *r,
|
||||
filenames: filenames,
|
||||
diffIDs: diffIDs,
|
||||
diffSizes: diffSizes,
|
||||
blobIDs: blobIDs,
|
||||
blobSizes: blobSizes,
|
||||
blobTypes: blobTypes,
|
||||
config: configBytes,
|
||||
configID: configID,
|
||||
configSize: configSize,
|
||||
manifest: manifestBytes,
|
||||
reference: *r,
|
||||
blobs: blobs,
|
||||
manifest: manifestBytes,
|
||||
}
|
||||
src.Compat = impl.AddCompat(src)
|
||||
|
||||
@@ -221,24 +204,18 @@ func (is *tarballImageSource) Close() error {
|
||||
// The Digest field in BlobInfo is guaranteed to be provided, Size may be -1 and MediaType may be optionally provided.
|
||||
// May update BlobInfoCache, preferably after it knows for certain that a blob truly exists at a specific location.
|
||||
func (is *tarballImageSource) GetBlob(ctx context.Context, blobinfo types.BlobInfo, cache types.BlobInfoCache) (io.ReadCloser, int64, error) {
|
||||
// We should only be asked about things in the manifest. Maybe the configuration blob.
|
||||
if blobinfo.Digest == is.configID {
|
||||
return io.NopCloser(bytes.NewBuffer(is.config)), is.configSize, nil
|
||||
}
|
||||
// Maybe one of the layer blobs.
|
||||
i := slices.Index(is.blobIDs, blobinfo.Digest)
|
||||
if i == -1 {
|
||||
blob, ok := is.blobs[blobinfo.Digest]
|
||||
if !ok {
|
||||
return nil, -1, fmt.Errorf("no blob with digest %q found", blobinfo.Digest.String())
|
||||
}
|
||||
// We want to read that layer: open the file or memory block and hand it back.
|
||||
if is.filenames[i] == "-" {
|
||||
return io.NopCloser(bytes.NewBuffer(is.reference.stdin)), int64(len(is.reference.stdin)), nil
|
||||
if blob.contents != nil {
|
||||
return io.NopCloser(bytes.NewReader(blob.contents)), int64(len(blob.contents)), nil
|
||||
}
|
||||
reader, err := os.Open(is.filenames[i])
|
||||
reader, err := os.Open(blob.filename)
|
||||
if err != nil {
|
||||
return nil, -1, fmt.Errorf("error opening %q: %v", is.filenames[i], err)
|
||||
return nil, -1, err
|
||||
}
|
||||
return reader, is.blobSizes[i], nil
|
||||
return reader, blob.size, nil
|
||||
}
|
||||
|
||||
// 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).
|
||||
|
4
vendor/github.com/containers/image/v5/version/version.go
generated
vendored
4
vendor/github.com/containers/image/v5/version/version.go
generated
vendored
@@ -8,10 +8,10 @@ const (
|
||||
// VersionMinor is for functionality in a backwards-compatible manner
|
||||
VersionMinor = 25
|
||||
// VersionPatch is for backwards-compatible bug fixes
|
||||
VersionPatch = 0
|
||||
VersionPatch = 1
|
||||
|
||||
// VersionDev indicates development branch. Releases will be empty string.
|
||||
VersionDev = ""
|
||||
VersionDev = "-dev"
|
||||
)
|
||||
|
||||
// Version is the specification version that the package types support.
|
||||
|
Reference in New Issue
Block a user