mirror of https://github.com/containers/podman.git
Bump c/storage to v1.57.1, c/image v5.34.0, c/common v0.62.0
If not already bumped, this will bump: c/storage v1.57.1 c/image v5.34.0 c/common v0.62.0 in preparation for Podman v5.4 and beyond. Buildah will be vendored in a separate PR. Signed-off-by: tomsweeneyredhat <tsweeney@redhat.com>
This commit is contained in:
parent
b06d78651a
commit
211d3ea3cf
6
go.mod
6
go.mod
|
@ -14,14 +14,14 @@ require (
|
|||
github.com/checkpoint-restore/go-criu/v7 v7.2.0
|
||||
github.com/containernetworking/plugins v1.5.1
|
||||
github.com/containers/buildah v1.38.1-0.20250125114111-92015b7f4301
|
||||
github.com/containers/common v0.61.1-0.20250124131345-fa339b6b6eda
|
||||
github.com/containers/common v0.62.0
|
||||
github.com/containers/conmon v2.0.20+incompatible
|
||||
github.com/containers/gvisor-tap-vsock v0.8.2
|
||||
github.com/containers/image/v5 v5.33.2-0.20250122233652-b5c6aff95ca7
|
||||
github.com/containers/image/v5 v5.34.0
|
||||
github.com/containers/libhvee v0.9.0
|
||||
github.com/containers/ocicrypt v1.2.1
|
||||
github.com/containers/psgo v1.9.0
|
||||
github.com/containers/storage v1.56.2-0.20250123125217-80d3c0e77d29
|
||||
github.com/containers/storage v1.57.1
|
||||
github.com/containers/winquit v1.1.0
|
||||
github.com/coreos/go-systemd/v22 v22.5.1-0.20231103132048-7d375ecc2b09
|
||||
github.com/crc-org/crc/v2 v2.45.0
|
||||
|
|
12
go.sum
12
go.sum
|
@ -78,14 +78,14 @@ github.com/containernetworking/plugins v1.5.1 h1:T5ji+LPYjjgW0QM+KyrigZbLsZ8jaX+
|
|||
github.com/containernetworking/plugins v1.5.1/go.mod h1:MIQfgMayGuHYs0XdNudf31cLLAC+i242hNm6KuDGqCM=
|
||||
github.com/containers/buildah v1.38.1-0.20250125114111-92015b7f4301 h1:eqHczpfbWOjyvQAkuCmzsZPds657cPXxXniXLcKFHdQ=
|
||||
github.com/containers/buildah v1.38.1-0.20250125114111-92015b7f4301/go.mod h1:UOhJzUS2A0uyZR/TygObcg2Og+nJ02pwMfVhIQBRIN8=
|
||||
github.com/containers/common v0.61.1-0.20250124131345-fa339b6b6eda h1:ltztaW234A8UvR3xz0hY4eD8ABo3B6gd3kGKVHPqGuE=
|
||||
github.com/containers/common v0.61.1-0.20250124131345-fa339b6b6eda/go.mod h1:mWhwkYaWR5bXeOwq3ruzdmH9gaT2pex00C6pd4VXuvM=
|
||||
github.com/containers/common v0.62.0 h1:Sl9WE5h7Y/F3bejrMAA4teP1EcY9ygqJmW4iwSloZ10=
|
||||
github.com/containers/common v0.62.0/go.mod h1:Yec+z8mrSq4rydHofrnDCBqAcNA/BGrSg1kfFUL6F6s=
|
||||
github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg=
|
||||
github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
|
||||
github.com/containers/gvisor-tap-vsock v0.8.2 h1:uQMBCCHlIIj62fPjbvgm6AL5EzsP6TP5eviByOJEsOg=
|
||||
github.com/containers/gvisor-tap-vsock v0.8.2/go.mod h1:EMRe2o63ddq2zxcP0hTysmxCf/5JlaNEg8/gpzP0ox4=
|
||||
github.com/containers/image/v5 v5.33.2-0.20250122233652-b5c6aff95ca7 h1:dTKluTTlijEdQmTZPK1wTX39qXb4F93/GPHhq+vlC3U=
|
||||
github.com/containers/image/v5 v5.33.2-0.20250122233652-b5c6aff95ca7/go.mod h1:NyH4/AlLW8cvPgtwbCMzz71dr9SOh8/WP9ua5c9Akc8=
|
||||
github.com/containers/image/v5 v5.34.0 h1:HPqQaDUsox/3mC1pbOyLAIQEp0JhQqiUZ+6JiFIZLDI=
|
||||
github.com/containers/image/v5 v5.34.0/go.mod h1:/WnvUSEfdqC/ahMRd4YJDBLrpYWkGl018rB77iB3FDo=
|
||||
github.com/containers/libhvee v0.9.0 h1:5UxJMka1lDfxTeITA25Pd8QVVttJAG43eQS1Getw1tc=
|
||||
github.com/containers/libhvee v0.9.0/go.mod h1:p44VJd8jMIx3SRN1eM6PxfCEwXQE0lJ0dQppCAlzjPQ=
|
||||
github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 h1:Qzk5C6cYglewc+UyGf6lc8Mj2UaPTHy/iF2De0/77CA=
|
||||
|
@ -96,8 +96,8 @@ github.com/containers/ocicrypt v1.2.1 h1:0qIOTT9DoYwcKmxSt8QJt+VzMY18onl9jUXsxpV
|
|||
github.com/containers/ocicrypt v1.2.1/go.mod h1:aD0AAqfMp0MtwqWgHM1bUwe1anx0VazI108CRrSKINQ=
|
||||
github.com/containers/psgo v1.9.0 h1:eJ74jzSaCHnWt26OlKZROSyUyRcGDf+gYBdXnxrMW4g=
|
||||
github.com/containers/psgo v1.9.0/go.mod h1:0YoluUm43Mz2UnBIh1P+6V6NWcbpTL5uRtXyOcH0B5A=
|
||||
github.com/containers/storage v1.56.2-0.20250123125217-80d3c0e77d29 h1:3L1QCfh72xytLizQeswDaKcB5ajq54DuFRcAy/C3P3c=
|
||||
github.com/containers/storage v1.56.2-0.20250123125217-80d3c0e77d29/go.mod h1:i/Hb4lu7YgFr9G0K6BMjqW0BLJO1sFsnWQwj2UoWCUM=
|
||||
github.com/containers/storage v1.57.1 h1:hKPoFsuBcB3qTzBxa4IFpZMRzUuL5Xhv/BE44W0XHx8=
|
||||
github.com/containers/storage v1.57.1/go.mod h1:i/Hb4lu7YgFr9G0K6BMjqW0BLJO1sFsnWQwj2UoWCUM=
|
||||
github.com/containers/winquit v1.1.0 h1:jArun04BNDQvt2W0Y78kh9TazN2EIEMG5Im6/JY7+pE=
|
||||
github.com/containers/winquit v1.1.0/go.mod h1:PsPeZlnbkmGGIToMPHF1zhWjBUkd8aHjMOr/vFcPxw8=
|
||||
github.com/coreos/go-oidc/v3 v3.12.0 h1:sJk+8G2qq94rDI6ehZ71Bol3oUHy63qNYmkiSjrc/Jo=
|
||||
|
|
|
@ -86,7 +86,7 @@ func (n *cniNetwork) networkCreate(newNetwork *types.Network, defaultNet bool) (
|
|||
switch newNetwork.Driver {
|
||||
case types.BridgeNetworkDriver:
|
||||
internalutil.MapDockerBridgeDriverOptions(newNetwork)
|
||||
err = internalutil.CreateBridge(n, newNetwork, usedNetworks, n.defaultsubnetPools)
|
||||
err = internalutil.CreateBridge(n, newNetwork, usedNetworks, n.defaultsubnetPools, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
9
vendor/github.com/containers/common/libnetwork/internal/rootlessnetns/netns_linux.go
generated
vendored
9
vendor/github.com/containers/common/libnetwork/internal/rootlessnetns/netns_linux.go
generated
vendored
|
@ -135,6 +135,15 @@ func (n *Netns) getOrCreateNetns() (ns.NetNS, bool, error) {
|
|||
}
|
||||
// In case of errors continue and setup the network cmd again.
|
||||
} else {
|
||||
// Special case, the file might exist already but is not a valid netns.
|
||||
// One reason could be that a previous setup was killed between creating
|
||||
// the file and mounting it. Or if the file is not on tmpfs (deleted on boot)
|
||||
// you might run into it as well: https://github.com/containers/podman/issues/25144
|
||||
// We have to do this because NewNSAtPath fails with EEXIST otherwise
|
||||
if errors.As(err, &ns.NSPathNotNSErr{}) {
|
||||
// We don't care if this fails, NewNSAtPath() should return the real error.
|
||||
_ = os.Remove(nsPath)
|
||||
}
|
||||
logrus.Debugf("Creating rootless network namespace at %q", nsPath)
|
||||
// We have to create the netns dir again here because it is possible
|
||||
// that cleanup() removed it.
|
||||
|
|
|
@ -10,11 +10,13 @@ import (
|
|||
"github.com/containers/common/pkg/config"
|
||||
)
|
||||
|
||||
func CreateBridge(n NetUtil, network *types.Network, usedNetworks []*net.IPNet, subnetPools []config.SubnetPool) error {
|
||||
func CreateBridge(n NetUtil, network *types.Network, usedNetworks []*net.IPNet, subnetPools []config.SubnetPool, checkBridgeConflict bool) error {
|
||||
if network.NetworkInterface != "" {
|
||||
bridges := GetBridgeInterfaceNames(n)
|
||||
if slices.Contains(bridges, network.NetworkInterface) {
|
||||
return fmt.Errorf("bridge name %s already in use", network.NetworkInterface)
|
||||
if checkBridgeConflict {
|
||||
bridges := GetBridgeInterfaceNames(n)
|
||||
if slices.Contains(bridges, network.NetworkInterface) {
|
||||
return fmt.Errorf("bridge name %s already in use", network.NetworkInterface)
|
||||
}
|
||||
}
|
||||
if !types.NameRegex.MatchString(network.NetworkInterface) {
|
||||
return fmt.Errorf("bridge name %s invalid: %w", network.NetworkInterface, types.RegexError)
|
||||
|
|
|
@ -169,11 +169,9 @@ func (n *netavarkNetwork) networkCreate(newNetwork *types.Network, defaultNet bo
|
|||
switch newNetwork.Driver {
|
||||
case types.BridgeNetworkDriver:
|
||||
internalutil.MapDockerBridgeDriverOptions(newNetwork)
|
||||
err = internalutil.CreateBridge(n, newNetwork, usedNetworks, n.defaultsubnetPools)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// validate the given options, we do not need them but just check to make sure they are valid
|
||||
|
||||
var vlan int
|
||||
// validate the given options,
|
||||
for key, value := range newNetwork.Options {
|
||||
switch key {
|
||||
case types.MTUOption:
|
||||
|
@ -183,7 +181,7 @@ func (n *netavarkNetwork) networkCreate(newNetwork *types.Network, defaultNet bo
|
|||
}
|
||||
|
||||
case types.VLANOption:
|
||||
_, err = internalutil.ParseVlan(value)
|
||||
vlan, err = internalutil.ParseVlan(value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -218,6 +216,17 @@ func (n *netavarkNetwork) networkCreate(newNetwork *types.Network, defaultNet bo
|
|||
return nil, fmt.Errorf("unsupported bridge network option %s", key)
|
||||
}
|
||||
}
|
||||
|
||||
// If there is no vlan there should be no other config with the same bridge.
|
||||
// However with vlan we want to allow that so that you can have different
|
||||
// configs on the same bridge but different vlans
|
||||
// https://github.com/containers/common/issues/2095
|
||||
checkBridgeConflict := vlan == 0
|
||||
err = internalutil.CreateBridge(n, newNetwork, usedNetworks, n.defaultsubnetPools, checkBridgeConflict)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
case types.MacVLANNetworkDriver, types.IPVLANNetworkDriver:
|
||||
err = createIpvlanOrMacvlan(newNetwork)
|
||||
if err != nil {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package version
|
||||
|
||||
// Version is the version of the build.
|
||||
const Version = "0.62.0-dev"
|
||||
const Version = "0.62.0"
|
||||
|
|
|
@ -3,6 +3,7 @@ package docker
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
|
@ -129,6 +130,11 @@ func loadAndMergeConfig(dirPath string) (*registryConfiguration, error) {
|
|||
configPath := filepath.Join(dirPath, configName)
|
||||
configBytes, err := os.ReadFile(configPath)
|
||||
if err != nil {
|
||||
if errors.Is(err, fs.ErrNotExist) {
|
||||
// file must have been removed between the directory listing
|
||||
// and the open call, ignore that as it is a expected race
|
||||
continue
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
6
vendor/github.com/containers/image/v5/pkg/sysregistriesv2/system_registries_v2.go
generated
vendored
6
vendor/github.com/containers/image/v5/pkg/sysregistriesv2/system_registries_v2.go
generated
vendored
|
@ -1,6 +1,7 @@
|
|||
package sysregistriesv2
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
|
@ -744,6 +745,11 @@ func tryUpdatingCache(ctx *types.SystemContext, wrapper configWrapper) (*parsedC
|
|||
// Enforce v2 format for drop-in-configs.
|
||||
dropIn, err := loadConfigFile(path, true)
|
||||
if err != nil {
|
||||
if errors.Is(err, fs.ErrNotExist) {
|
||||
// file must have been removed between the directory listing
|
||||
// and the open call, ignore that as it is a expected race
|
||||
continue
|
||||
}
|
||||
return nil, fmt.Errorf("loading drop-in registries configuration %q: %w", path, err)
|
||||
}
|
||||
config.updateWithConfigurationFrom(dropIn)
|
||||
|
|
|
@ -3,6 +3,7 @@ package tlsclientconfig
|
|||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
|
@ -36,12 +37,9 @@ func SetupCertificates(dir string, tlsc *tls.Config) error {
|
|||
logrus.Debugf(" crt: %s", fullPath)
|
||||
data, err := os.ReadFile(fullPath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
// Dangling symbolic link?
|
||||
// Race with someone who deleted the
|
||||
// file after we read the directory's
|
||||
// list of contents?
|
||||
logrus.Warnf("error reading certificate %q: %v", fullPath, err)
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
// file must have been removed between the directory listing
|
||||
// and the open call, ignore that as it is a expected race
|
||||
continue
|
||||
}
|
||||
return err
|
||||
|
|
|
@ -8,10 +8,10 @@ const (
|
|||
// VersionMinor is for functionality in a backwards-compatible manner
|
||||
VersionMinor = 34
|
||||
// VersionPatch is for backwards-compatible bug fixes
|
||||
VersionPatch = 1
|
||||
VersionPatch = 0
|
||||
|
||||
// VersionDev indicates development branch. Releases will be empty string.
|
||||
VersionDev = "-dev"
|
||||
VersionDev = ""
|
||||
)
|
||||
|
||||
// Version is the specification version that the package types support.
|
||||
|
|
|
@ -1 +1 @@
|
|||
1.57.0-dev
|
||||
1.57.1
|
||||
|
|
|
@ -23,7 +23,7 @@ import (
|
|||
const (
|
||||
// maxTocSize is the maximum size of a blob that we will attempt to process.
|
||||
// It is used to prevent DoS attacks from layers that embed a very large TOC file.
|
||||
maxTocSize = (1 << 20) * 50
|
||||
maxTocSize = (1 << 20) * 150
|
||||
)
|
||||
|
||||
var typesToTar = map[string]byte{
|
||||
|
@ -44,6 +44,8 @@ func typeToTarType(t string) (byte, error) {
|
|||
return r, nil
|
||||
}
|
||||
|
||||
// readEstargzChunkedManifest reads the estargz manifest from the seekable stream blobStream.
|
||||
// It may return an error matching ErrFallbackToOrdinaryLayerDownload / errFallbackCanConvert.
|
||||
func readEstargzChunkedManifest(blobStream ImageSourceSeekable, blobSize int64, tocDigest digest.Digest) ([]byte, int64, error) {
|
||||
// information on the format here https://github.com/containerd/stargz-snapshotter/blob/main/docs/stargz-estargz.md
|
||||
footerSize := int64(51)
|
||||
|
@ -54,6 +56,10 @@ func readEstargzChunkedManifest(blobStream ImageSourceSeekable, blobSize int64,
|
|||
footer := make([]byte, footerSize)
|
||||
streamsOrErrors, err := getBlobAt(blobStream, ImageSourceChunk{Offset: uint64(blobSize - footerSize), Length: uint64(footerSize)})
|
||||
if err != nil {
|
||||
var badRequestErr ErrBadRequest
|
||||
if errors.As(err, &badRequestErr) {
|
||||
err = errFallbackCanConvert{newErrFallbackToOrdinaryLayerDownload(err)}
|
||||
}
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
|
@ -84,11 +90,16 @@ func readEstargzChunkedManifest(blobStream ImageSourceSeekable, blobSize int64,
|
|||
size := int64(blobSize - footerSize - tocOffset)
|
||||
// set a reasonable limit
|
||||
if size > maxTocSize {
|
||||
return nil, 0, errors.New("manifest too big")
|
||||
// Not errFallbackCanConvert: we would still use too much memory.
|
||||
return nil, 0, newErrFallbackToOrdinaryLayerDownload(fmt.Errorf("estargz manifest too big to process in memory (%d bytes)", size))
|
||||
}
|
||||
|
||||
streamsOrErrors, err = getBlobAt(blobStream, ImageSourceChunk{Offset: uint64(tocOffset), Length: uint64(size)})
|
||||
if err != nil {
|
||||
var badRequestErr ErrBadRequest
|
||||
if errors.As(err, &badRequestErr) {
|
||||
err = errFallbackCanConvert{newErrFallbackToOrdinaryLayerDownload(err)}
|
||||
}
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
|
@ -148,6 +159,7 @@ func readEstargzChunkedManifest(blobStream ImageSourceSeekable, blobSize int64,
|
|||
|
||||
// readZstdChunkedManifest reads the zstd:chunked manifest from the seekable stream blobStream.
|
||||
// Returns (manifest blob, parsed manifest, tar-split blob or nil, manifest offset).
|
||||
// It may return an error matching ErrFallbackToOrdinaryLayerDownload / errFallbackCanConvert.
|
||||
func readZstdChunkedManifest(blobStream ImageSourceSeekable, tocDigest digest.Digest, annotations map[string]string) (_ []byte, _ *minimal.TOC, _ []byte, _ int64, retErr error) {
|
||||
offsetMetadata := annotations[minimal.ManifestInfoKey]
|
||||
if offsetMetadata == "" {
|
||||
|
@ -173,10 +185,12 @@ func readZstdChunkedManifest(blobStream ImageSourceSeekable, tocDigest digest.Di
|
|||
|
||||
// set a reasonable limit
|
||||
if manifestChunk.Length > maxTocSize {
|
||||
return nil, nil, nil, 0, errors.New("manifest too big")
|
||||
// Not errFallbackCanConvert: we would still use too much memory.
|
||||
return nil, nil, nil, 0, newErrFallbackToOrdinaryLayerDownload(fmt.Errorf("zstd:chunked manifest too big to process in memory (%d bytes compressed)", manifestChunk.Length))
|
||||
}
|
||||
if manifestLengthUncompressed > maxTocSize {
|
||||
return nil, nil, nil, 0, errors.New("manifest too big")
|
||||
// Not errFallbackCanConvert: we would still use too much memory.
|
||||
return nil, nil, nil, 0, newErrFallbackToOrdinaryLayerDownload(fmt.Errorf("zstd:chunked manifest too big to process in memory (%d bytes uncompressed)", manifestLengthUncompressed))
|
||||
}
|
||||
|
||||
chunks := []ImageSourceChunk{manifestChunk}
|
||||
|
@ -186,6 +200,10 @@ func readZstdChunkedManifest(blobStream ImageSourceSeekable, tocDigest digest.Di
|
|||
|
||||
streamsOrErrors, err := getBlobAt(blobStream, chunks...)
|
||||
if err != nil {
|
||||
var badRequestErr ErrBadRequest
|
||||
if errors.As(err, &badRequestErr) {
|
||||
err = errFallbackCanConvert{newErrFallbackToOrdinaryLayerDownload(err)}
|
||||
}
|
||||
return nil, nil, nil, 0, err
|
||||
}
|
||||
|
||||
|
|
|
@ -62,46 +62,53 @@ const (
|
|||
type compressedFileType int
|
||||
|
||||
type chunkedDiffer struct {
|
||||
// Initial parameters, used throughout and never modified
|
||||
// ==========
|
||||
pullOptions pullOptions
|
||||
stream ImageSourceSeekable
|
||||
manifest []byte
|
||||
toc *minimal.TOC // The parsed contents of manifest, or nil if not yet available
|
||||
tarSplit []byte
|
||||
layersCache *layersCache
|
||||
tocOffset int64
|
||||
fileType compressedFileType
|
||||
|
||||
copyBuffer []byte
|
||||
|
||||
gzipReader *pgzip.Reader
|
||||
zstdReader *zstd.Decoder
|
||||
rawReader io.Reader
|
||||
|
||||
// tocDigest is the digest of the TOC document when the layer
|
||||
// is partially pulled.
|
||||
tocDigest digest.Digest
|
||||
// blobDigest is the digest of the whole compressed layer. It is used if
|
||||
// convertToZstdChunked to validate a layer when it is converted since there
|
||||
// is no TOC referenced by the manifest.
|
||||
blobDigest digest.Digest
|
||||
blobSize int64
|
||||
|
||||
// Input format
|
||||
// ==========
|
||||
fileType compressedFileType
|
||||
// convertedToZstdChunked is set to true if the layer needs to
|
||||
// be converted to the zstd:chunked format before it can be
|
||||
// handled.
|
||||
convertToZstdChunked bool
|
||||
|
||||
// Chunked metadata
|
||||
// This is usually set in GetDiffer, but if convertToZstdChunked, it is only computed in chunkedDiffer.ApplyDiff
|
||||
// ==========
|
||||
// tocDigest is the digest of the TOC document when the layer
|
||||
// is partially pulled, or "" if not relevant to consumers.
|
||||
tocDigest digest.Digest
|
||||
tocOffset int64
|
||||
manifest []byte
|
||||
toc *minimal.TOC // The parsed contents of manifest, or nil if not yet available
|
||||
tarSplit []byte
|
||||
uncompressedTarSize int64 // -1 if unknown
|
||||
// skipValidation is set to true if the individual files in
|
||||
// the layer are trusted and should not be validated.
|
||||
skipValidation bool
|
||||
|
||||
// blobDigest is the digest of the whole compressed layer. It is used if
|
||||
// convertToZstdChunked to validate a layer when it is converted since there
|
||||
// is no TOC referenced by the manifest.
|
||||
blobDigest digest.Digest
|
||||
|
||||
blobSize int64
|
||||
uncompressedTarSize int64 // -1 if unknown
|
||||
|
||||
pullOptions pullOptions
|
||||
|
||||
useFsVerity graphdriver.DifferFsVerity
|
||||
// Long-term caches
|
||||
// This is set in GetDiffer, when the caller must not hold any storage locks, and later consumed in .ApplyDiff()
|
||||
// ==========
|
||||
layersCache *layersCache
|
||||
copyBuffer []byte
|
||||
fsVerityMutex sync.Mutex // protects fsVerityDigests
|
||||
fsVerityDigests map[string]string
|
||||
fsVerityMutex sync.Mutex
|
||||
|
||||
// Private state of .ApplyDiff
|
||||
// ==========
|
||||
gzipReader *pgzip.Reader
|
||||
zstdReader *zstd.Decoder
|
||||
rawReader io.Reader
|
||||
useFsVerity graphdriver.DifferFsVerity
|
||||
}
|
||||
|
||||
var xattrsToIgnore = map[string]interface{}{
|
||||
|
@ -185,7 +192,7 @@ func (c *chunkedDiffer) convertTarToZstdChunked(destDirectory string, payload *o
|
|||
}
|
||||
|
||||
// GetDiffer returns a differ than can be used with ApplyDiffWithDiffer.
|
||||
// If it returns an error that implements IsErrFallbackToOrdinaryLayerDownload, the caller can
|
||||
// If it returns an error that matches ErrFallbackToOrdinaryLayerDownload, the caller can
|
||||
// retry the operation with a different method.
|
||||
func GetDiffer(ctx context.Context, store storage.Store, blobDigest digest.Digest, blobSize int64, annotations map[string]string, iss ImageSourceSeekable) (graphdriver.Differ, error) {
|
||||
pullOptions := parsePullOptions(store)
|
||||
|
@ -208,65 +215,94 @@ func GetDiffer(ctx context.Context, store storage.Store, blobDigest digest.Diges
|
|||
return nil, newErrFallbackToOrdinaryLayerDownload(fmt.Errorf("graph driver %s does not support partial pull", graphDriver.String()))
|
||||
}
|
||||
|
||||
differ, canFallback, err := getProperDiffer(store, blobDigest, blobSize, annotations, iss, pullOptions)
|
||||
differ, err := getProperDiffer(store, blobDigest, blobSize, annotations, iss, pullOptions)
|
||||
if err != nil {
|
||||
if !canFallback {
|
||||
var fallbackErr ErrFallbackToOrdinaryLayerDownload
|
||||
if !errors.As(err, &fallbackErr) {
|
||||
return nil, err
|
||||
}
|
||||
// If convert_images is enabled, always attempt to convert it instead of returning an error or falling back to a different method.
|
||||
if pullOptions.convertImages {
|
||||
logrus.Debugf("Created differ to convert blob %q", blobDigest)
|
||||
return makeConvertFromRawDiffer(store, blobDigest, blobSize, iss, pullOptions)
|
||||
if !pullOptions.convertImages {
|
||||
return nil, err
|
||||
}
|
||||
return nil, newErrFallbackToOrdinaryLayerDownload(err)
|
||||
var canConvertErr errFallbackCanConvert
|
||||
if !errors.As(err, &canConvertErr) {
|
||||
// We are supposed to use makeConvertFromRawDiffer, but that would not work.
|
||||
// Fail, and make sure the error does _not_ match ErrFallbackToOrdinaryLayerDownload: use only the error text,
|
||||
// discard all type information.
|
||||
return nil, fmt.Errorf("neither a partial pull nor convert_images is possible: %s", err.Error())
|
||||
}
|
||||
logrus.Debugf("Created differ to convert blob %q", blobDigest)
|
||||
return makeConvertFromRawDiffer(store, blobDigest, blobSize, iss, pullOptions)
|
||||
}
|
||||
|
||||
return differ, nil
|
||||
}
|
||||
|
||||
// errFallbackCanConvert is an an error type _accompanying_ ErrFallbackToOrdinaryLayerDownload
|
||||
// within getProperDiffer, to mark that using makeConvertFromRawDiffer makes sense.
|
||||
// This is used to distinguish between cases where the environment does not support partial pulls
|
||||
// (e.g. a registry does not support range requests) and convert_images is still possible,
|
||||
// from cases where the image content is unacceptable for partial pulls (e.g. exceeds memory limits)
|
||||
// and convert_images would not help.
|
||||
type errFallbackCanConvert struct {
|
||||
err error
|
||||
}
|
||||
|
||||
func (e errFallbackCanConvert) Error() string {
|
||||
return e.err.Error()
|
||||
}
|
||||
|
||||
func (e errFallbackCanConvert) Unwrap() error {
|
||||
return e.err
|
||||
}
|
||||
|
||||
// getProperDiffer is an implementation detail of GetDiffer.
|
||||
// It returns a “proper” differ (not a convert_images one) if possible.
|
||||
// On error, the second return value is true if a fallback to an alternative (either the makeConverToRaw differ, or a non-partial pull)
|
||||
// is permissible.
|
||||
func getProperDiffer(store storage.Store, blobDigest digest.Digest, blobSize int64, annotations map[string]string, iss ImageSourceSeekable, pullOptions pullOptions) (graphdriver.Differ, bool, error) {
|
||||
// May return an error matching ErrFallbackToOrdinaryLayerDownload if a fallback to an alternative
|
||||
// (either makeConvertFromRawDiffer, or a non-partial pull) is permissible.
|
||||
func getProperDiffer(store storage.Store, blobDigest digest.Digest, blobSize int64, annotations map[string]string, iss ImageSourceSeekable, pullOptions pullOptions) (graphdriver.Differ, error) {
|
||||
zstdChunkedTOCDigestString, hasZstdChunkedTOC := annotations[minimal.ManifestChecksumKey]
|
||||
estargzTOCDigestString, hasEstargzTOC := annotations[estargz.TOCJSONDigestAnnotation]
|
||||
|
||||
switch {
|
||||
case hasZstdChunkedTOC && hasEstargzTOC:
|
||||
return nil, false, errors.New("both zstd:chunked and eStargz TOC found")
|
||||
return nil, errors.New("both zstd:chunked and eStargz TOC found")
|
||||
|
||||
case hasZstdChunkedTOC:
|
||||
zstdChunkedTOCDigest, err := digest.Parse(zstdChunkedTOCDigestString)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
return nil, err
|
||||
}
|
||||
differ, canFallback, err := makeZstdChunkedDiffer(store, blobSize, zstdChunkedTOCDigest, annotations, iss, pullOptions)
|
||||
differ, err := makeZstdChunkedDiffer(store, blobSize, zstdChunkedTOCDigest, annotations, iss, pullOptions)
|
||||
if err != nil {
|
||||
logrus.Debugf("Could not create zstd:chunked differ for blob %q: %v", blobDigest, err)
|
||||
return nil, canFallback, err
|
||||
return nil, err
|
||||
}
|
||||
logrus.Debugf("Created zstd:chunked differ for blob %q", blobDigest)
|
||||
return differ, false, nil
|
||||
return differ, nil
|
||||
|
||||
case hasEstargzTOC:
|
||||
estargzTOCDigest, err := digest.Parse(estargzTOCDigestString)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
return nil, err
|
||||
}
|
||||
differ, canFallback, err := makeEstargzChunkedDiffer(store, blobSize, estargzTOCDigest, iss, pullOptions)
|
||||
differ, err := makeEstargzChunkedDiffer(store, blobSize, estargzTOCDigest, iss, pullOptions)
|
||||
if err != nil {
|
||||
logrus.Debugf("Could not create estargz differ for blob %q: %v", blobDigest, err)
|
||||
return nil, canFallback, err
|
||||
return nil, err
|
||||
}
|
||||
logrus.Debugf("Created eStargz differ for blob %q", blobDigest)
|
||||
return differ, false, nil
|
||||
return differ, nil
|
||||
|
||||
default: // no TOC
|
||||
message := "no TOC found"
|
||||
if !pullOptions.convertImages {
|
||||
return nil, true, errors.New("no TOC found and convert_images is not configured")
|
||||
message = "no TOC found and convert_images is not configured"
|
||||
}
|
||||
return nil, errFallbackCanConvert{
|
||||
newErrFallbackToOrdinaryLayerDownload(errors.New(message)),
|
||||
}
|
||||
return nil, true, errors.New("no TOC found")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -277,95 +313,100 @@ func makeConvertFromRawDiffer(store storage.Store, blobDigest digest.Digest, blo
|
|||
}
|
||||
|
||||
return &chunkedDiffer{
|
||||
fsVerityDigests: make(map[string]string),
|
||||
blobDigest: blobDigest,
|
||||
blobSize: blobSize,
|
||||
uncompressedTarSize: -1, // Will be computed later
|
||||
pullOptions: pullOptions,
|
||||
stream: iss,
|
||||
blobDigest: blobDigest,
|
||||
blobSize: blobSize,
|
||||
|
||||
convertToZstdChunked: true,
|
||||
copyBuffer: makeCopyBuffer(),
|
||||
layersCache: layersCache,
|
||||
pullOptions: pullOptions,
|
||||
stream: iss,
|
||||
|
||||
uncompressedTarSize: -1, // Will be computed later
|
||||
|
||||
layersCache: layersCache,
|
||||
copyBuffer: makeCopyBuffer(),
|
||||
fsVerityDigests: make(map[string]string),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// makeZstdChunkedDiffer sets up a chunkedDiffer for a zstd:chunked layer.
|
||||
//
|
||||
// On error, the second return value is true if a fallback to an alternative (either the makeConverToRaw differ, or a non-partial pull)
|
||||
// is permissible.
|
||||
func makeZstdChunkedDiffer(store storage.Store, blobSize int64, tocDigest digest.Digest, annotations map[string]string, iss ImageSourceSeekable, pullOptions pullOptions) (*chunkedDiffer, bool, error) {
|
||||
// It may return an error matching ErrFallbackToOrdinaryLayerDownload / errFallbackCanConvert.
|
||||
func makeZstdChunkedDiffer(store storage.Store, blobSize int64, tocDigest digest.Digest, annotations map[string]string, iss ImageSourceSeekable, pullOptions pullOptions) (*chunkedDiffer, error) {
|
||||
manifest, toc, tarSplit, tocOffset, err := readZstdChunkedManifest(iss, tocDigest, annotations)
|
||||
if err != nil {
|
||||
// If the error is a bad request to the server, then signal to the caller that it can try a different method.
|
||||
var badRequestErr ErrBadRequest
|
||||
return nil, errors.As(err, &badRequestErr), fmt.Errorf("read zstd:chunked manifest: %w", err)
|
||||
if err != nil { // May be ErrFallbackToOrdinaryLayerDownload / errFallbackCanConvert
|
||||
return nil, fmt.Errorf("read zstd:chunked manifest: %w", err)
|
||||
}
|
||||
|
||||
var uncompressedTarSize int64 = -1
|
||||
if tarSplit != nil {
|
||||
uncompressedTarSize, err = tarSizeFromTarSplit(tarSplit)
|
||||
if err != nil {
|
||||
return nil, false, fmt.Errorf("computing size from tar-split: %w", err)
|
||||
return nil, fmt.Errorf("computing size from tar-split: %w", err)
|
||||
}
|
||||
} else if !pullOptions.insecureAllowUnpredictableImageContents { // With no tar-split, we can't compute the traditional UncompressedDigest.
|
||||
return nil, true, fmt.Errorf("zstd:chunked layers without tar-split data don't support partial pulls with guaranteed consistency with non-partial pulls")
|
||||
return nil, errFallbackCanConvert{
|
||||
newErrFallbackToOrdinaryLayerDownload(fmt.Errorf("zstd:chunked layers without tar-split data don't support partial pulls with guaranteed consistency with non-partial pulls")),
|
||||
}
|
||||
}
|
||||
|
||||
layersCache, err := getLayersCache(store)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &chunkedDiffer{
|
||||
fsVerityDigests: make(map[string]string),
|
||||
blobSize: blobSize,
|
||||
uncompressedTarSize: uncompressedTarSize,
|
||||
pullOptions: pullOptions,
|
||||
stream: iss,
|
||||
blobSize: blobSize,
|
||||
|
||||
fileType: fileTypeZstdChunked,
|
||||
|
||||
tocDigest: tocDigest,
|
||||
copyBuffer: makeCopyBuffer(),
|
||||
fileType: fileTypeZstdChunked,
|
||||
layersCache: layersCache,
|
||||
tocOffset: tocOffset,
|
||||
manifest: manifest,
|
||||
toc: toc,
|
||||
pullOptions: pullOptions,
|
||||
stream: iss,
|
||||
tarSplit: tarSplit,
|
||||
tocOffset: tocOffset,
|
||||
}, false, nil
|
||||
uncompressedTarSize: uncompressedTarSize,
|
||||
|
||||
layersCache: layersCache,
|
||||
copyBuffer: makeCopyBuffer(),
|
||||
fsVerityDigests: make(map[string]string),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// makeZstdChunkedDiffer sets up a chunkedDiffer for an estargz layer.
|
||||
//
|
||||
// On error, the second return value is true if a fallback to an alternative (either the makeConverToRaw differ, or a non-partial pull)
|
||||
// is permissible.
|
||||
func makeEstargzChunkedDiffer(store storage.Store, blobSize int64, tocDigest digest.Digest, iss ImageSourceSeekable, pullOptions pullOptions) (*chunkedDiffer, bool, error) {
|
||||
// makeEstargzChunkedDiffer sets up a chunkedDiffer for an estargz layer.
|
||||
// It may return an error matching ErrFallbackToOrdinaryLayerDownload / errFallbackCanConvert.
|
||||
func makeEstargzChunkedDiffer(store storage.Store, blobSize int64, tocDigest digest.Digest, iss ImageSourceSeekable, pullOptions pullOptions) (*chunkedDiffer, error) {
|
||||
if !pullOptions.insecureAllowUnpredictableImageContents { // With no tar-split, we can't compute the traditional UncompressedDigest.
|
||||
return nil, true, fmt.Errorf("estargz layers don't support partial pulls with guaranteed consistency with non-partial pulls")
|
||||
return nil, errFallbackCanConvert{
|
||||
newErrFallbackToOrdinaryLayerDownload(fmt.Errorf("estargz layers don't support partial pulls with guaranteed consistency with non-partial pulls")),
|
||||
}
|
||||
}
|
||||
|
||||
manifest, tocOffset, err := readEstargzChunkedManifest(iss, blobSize, tocDigest)
|
||||
if err != nil {
|
||||
// If the error is a bad request to the server, then signal to the caller that it can try a different method.
|
||||
var badRequestErr ErrBadRequest
|
||||
return nil, errors.As(err, &badRequestErr), fmt.Errorf("read zstd:chunked manifest: %w", err)
|
||||
if err != nil { // May be ErrFallbackToOrdinaryLayerDownload / errFallbackCanConvert
|
||||
return nil, fmt.Errorf("read zstd:chunked manifest: %w", err)
|
||||
}
|
||||
layersCache, err := getLayersCache(store)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &chunkedDiffer{
|
||||
fsVerityDigests: make(map[string]string),
|
||||
blobSize: blobSize,
|
||||
uncompressedTarSize: -1, // We would have to read and decompress the whole layer
|
||||
pullOptions: pullOptions,
|
||||
stream: iss,
|
||||
blobSize: blobSize,
|
||||
|
||||
fileType: fileTypeEstargz,
|
||||
|
||||
tocDigest: tocDigest,
|
||||
copyBuffer: makeCopyBuffer(),
|
||||
fileType: fileTypeEstargz,
|
||||
layersCache: layersCache,
|
||||
manifest: manifest,
|
||||
pullOptions: pullOptions,
|
||||
stream: iss,
|
||||
tocOffset: tocOffset,
|
||||
}, false, nil
|
||||
manifest: manifest,
|
||||
uncompressedTarSize: -1, // We would have to read and decompress the whole layer
|
||||
|
||||
layersCache: layersCache,
|
||||
copyBuffer: makeCopyBuffer(),
|
||||
fsVerityDigests: make(map[string]string),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func makeCopyBuffer() []byte {
|
||||
|
|
|
@ -13,5 +13,5 @@ import (
|
|||
|
||||
// GetDiffer returns a differ than can be used with ApplyDiffWithDiffer.
|
||||
func GetDiffer(ctx context.Context, store storage.Store, blobDigest digest.Digest, blobSize int64, annotations map[string]string, iss ImageSourceSeekable) (graphdriver.Differ, error) {
|
||||
return nil, errors.New("format not supported on this system")
|
||||
return nil, newErrFallbackToOrdinaryLayerDownload(errors.New("format not supported on this system"))
|
||||
}
|
||||
|
|
|
@ -179,7 +179,7 @@ github.com/containers/buildah/pkg/sshagent
|
|||
github.com/containers/buildah/pkg/util
|
||||
github.com/containers/buildah/pkg/volumes
|
||||
github.com/containers/buildah/util
|
||||
# github.com/containers/common v0.61.1-0.20250124131345-fa339b6b6eda
|
||||
# github.com/containers/common v0.62.0
|
||||
## explicit; go 1.22.8
|
||||
github.com/containers/common/internal
|
||||
github.com/containers/common/internal/attributedstring
|
||||
|
@ -252,7 +252,7 @@ github.com/containers/conmon/runner/config
|
|||
# github.com/containers/gvisor-tap-vsock v0.8.2
|
||||
## explicit; go 1.22.0
|
||||
github.com/containers/gvisor-tap-vsock/pkg/types
|
||||
# github.com/containers/image/v5 v5.33.2-0.20250122233652-b5c6aff95ca7
|
||||
# github.com/containers/image/v5 v5.34.0
|
||||
## explicit; go 1.22.8
|
||||
github.com/containers/image/v5/copy
|
||||
github.com/containers/image/v5/directory
|
||||
|
@ -364,7 +364,7 @@ github.com/containers/psgo/internal/dev
|
|||
github.com/containers/psgo/internal/host
|
||||
github.com/containers/psgo/internal/proc
|
||||
github.com/containers/psgo/internal/process
|
||||
# github.com/containers/storage v1.56.2-0.20250123125217-80d3c0e77d29
|
||||
# github.com/containers/storage v1.57.1
|
||||
## explicit; go 1.22.0
|
||||
github.com/containers/storage
|
||||
github.com/containers/storage/drivers
|
||||
|
|
Loading…
Reference in New Issue