diff --git a/cmd/podman/containers/unpause.go b/cmd/podman/containers/unpause.go index 3b7acdab531..270f582b7fe 100644 --- a/cmd/podman/containers/unpause.go +++ b/cmd/podman/containers/unpause.go @@ -2,7 +2,6 @@ package containers import ( "context" - "errors" "fmt" "os" "strings" @@ -12,9 +11,7 @@ import ( "github.com/containers/podman/v5/cmd/podman/utils" "github.com/containers/podman/v5/cmd/podman/validate" "github.com/containers/podman/v5/pkg/domain/entities" - "github.com/containers/podman/v5/pkg/rootless" "github.com/spf13/cobra" - "go.podman.io/common/pkg/cgroups" "go.podman.io/common/pkg/completion" ) @@ -88,18 +85,9 @@ func init() { } func unpause(_ *cobra.Command, args []string) error { - var ( - errs utils.OutputErrors - ) + var errs utils.OutputErrors args = utils.RemoveSlash(args) - if rootless.IsRootless() && !registry.IsRemote() { - cgroupv2, _ := cgroups.IsCgroup2UnifiedMode() - if !cgroupv2 { - return errors.New("unpause is not supported for cgroupv1 rootless containers") - } - } - for _, cidFile := range unpauseCidFiles { content, err := os.ReadFile(cidFile) if err != nil { diff --git a/cmd/podman/main.go b/cmd/podman/main.go index 21585116d42..a12ef43162d 100644 --- a/cmd/podman/main.go +++ b/cmd/podman/main.go @@ -53,6 +53,8 @@ func main() { } logiface.SetLogger(logrusLogger{}) + checkSupportedCgroups() + if filepath.Base(os.Args[0]) == registry.PodmanSh || (len(os.Args[0]) > 0 && filepath.Base(os.Args[0][1:]) == registry.PodmanSh) { shell := strings.TrimPrefix(os.Args[0], "-") diff --git a/cmd/podman/main_cgroups_linux.go b/cmd/podman/main_cgroups_linux.go new file mode 100644 index 00000000000..fee19873f46 --- /dev/null +++ b/cmd/podman/main_cgroups_linux.go @@ -0,0 +1,18 @@ +//go:build linux + +package main + +import ( + "github.com/sirupsen/logrus" + "go.podman.io/common/pkg/cgroups" +) + +func checkSupportedCgroups() { + unified, err := cgroups.IsCgroup2UnifiedMode() + if err != nil { + logrus.Fatalf("Error determining cgroups mode") + } + if !unified { + logrus.Fatalf("Cgroups v1 not supported") + } +} diff --git a/cmd/podman/main_cgroups_unsupported.go b/cmd/podman/main_cgroups_unsupported.go new file mode 100644 index 00000000000..bef14a364de --- /dev/null +++ b/cmd/podman/main_cgroups_unsupported.go @@ -0,0 +1,15 @@ +//go:build windows || darwin || freebsd + +package main + +import ( + "github.com/sirupsen/logrus" + "go.podman.io/common/pkg/cgroups" +) + +func checkSupportedCgroups() { + unified, _ := cgroups.IsCgroup2UnifiedMode() + if !unified { + logrus.Debugln("Non-linux environment. Non-fatal cgroups check") + } +} diff --git a/docs/source/locale/ja/LC_MESSAGES/markdown.po b/docs/source/locale/ja/LC_MESSAGES/markdown.po index 649857577dc..7cbce7c8ea5 100644 --- a/docs/source/locale/ja/LC_MESSAGES/markdown.po +++ b/docs/source/locale/ja/LC_MESSAGES/markdown.po @@ -8458,8 +8458,7 @@ msgstr "" #: ../../source/markdown/podman-create.1.md:185 #: ../../source/markdown/podman-run.1.md:204 msgid "" -"If the host uses cgroups v1, the default is set to **host**. On cgroups " -"v2, the default is **private**." +The default is **private**." msgstr "" #: ../../source/markdown/podman-create.1.md:191 @@ -23003,7 +23002,7 @@ msgstr "" #: ../../source/markdown/podman-pod-stats.1.md:11 msgid "" "Display a live stream of containers in one or more pods resource usage " -"statistics. Running rootless is only supported on cgroups v2." +"statistics." msgstr "" #: ../../source/markdown/podman-pod-stats.1.md:17 @@ -30162,11 +30161,7 @@ msgid "update a container with a new cpu quota and period" msgstr "" #: ../../source/markdown/podman-update.1.md:331 -msgid "update a container with all available options for cgroups v2" -msgstr "" - -#: ../../source/markdown/podman-update.1.md:336 -msgid "update a container with all available options for cgroups v1" +msgid "update a container with all available options" msgstr "" #: ../../source/markdown/podman-update.1.md:342 diff --git a/docs/source/markdown/options/cgroupns.md b/docs/source/markdown/options/cgroupns.md index 71fa2486882..675ecf82554 100644 --- a/docs/source/markdown/options/cgroupns.md +++ b/docs/source/markdown/options/cgroupns.md @@ -11,4 +11,4 @@ Set the cgroup namespace mode for the container. - **private**: create a new cgroup namespace. - **ns:**_path_: join the namespace at the specified path. -If the host uses cgroups v1, the default is set to **host**. On cgroups v2, the default is **private**. +The default is **private**. diff --git a/docs/source/markdown/podman-pod-stats.1.md.in b/docs/source/markdown/podman-pod-stats.1.md.in index 943e36c8cd9..4e17a2d520e 100644 --- a/docs/source/markdown/podman-pod-stats.1.md.in +++ b/docs/source/markdown/podman-pod-stats.1.md.in @@ -7,7 +7,7 @@ podman\-pod\-stats - Display a live stream of resource usage stats for container **podman pod stats** [*options*] [*pod*] ## DESCRIPTION -Display a live stream of containers in one or more pods resource usage statistics. Running rootless is only supported on cgroups v2. +Display a live stream of containers in one or more pods resource usage statistics. ## OPTIONS diff --git a/docs/source/markdown/podman-stats.1.md.in b/docs/source/markdown/podman-stats.1.md.in index 1c01e7f433e..e87ba848247 100644 --- a/docs/source/markdown/podman-stats.1.md.in +++ b/docs/source/markdown/podman-stats.1.md.in @@ -11,11 +11,7 @@ podman\-stats - Display a live stream of one or more container's resource usage ## DESCRIPTION Display a live stream of one or more containers' resource usage statistics -Note: Podman stats does not work in rootless environments that use cgroups v1. -Podman stats relies on cgroup information for statistics, and cgroup v1 is not -supported for rootless use cases. - -Note: Rootless environments that use cgroups v2 are not able to report statistics +Note: Rootless environments are not able to report statistics about their networking usage. ## OPTIONS diff --git a/go.mod b/go.mod index efb43b9b389..0242deaeef4 100644 --- a/go.mod +++ b/go.mod @@ -47,7 +47,7 @@ require ( github.com/moby/sys/user v0.4.0 github.com/moby/term v0.5.2 github.com/nxadm/tail v1.4.11 - github.com/onsi/ginkgo/v2 v2.26.0 + github.com/onsi/ginkgo/v2 v2.27.1 github.com/onsi/gomega v1.38.2 github.com/opencontainers/cgroups v0.0.5 github.com/opencontainers/go-digest v1.0.0 @@ -93,7 +93,7 @@ require ( github.com/containerd/errdefs/pkg v0.3.0 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v1.0.0-rc.1 // indirect - github.com/containerd/stargz-snapshotter/estargz v0.17.0 // indirect + github.com/containerd/stargz-snapshotter/estargz v0.18.0 // indirect github.com/containerd/typeurl/v2 v2.2.3 // indirect github.com/containernetworking/cni v1.3.0 // indirect github.com/containers/common v0.62.2 // indirect @@ -127,7 +127,7 @@ require ( github.com/hashicorp/go-retryablehttp v0.7.8 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jinzhu/copier v0.4.0 // indirect - github.com/klauspost/compress v1.18.0 // indirect + github.com/klauspost/compress v1.18.1 // indirect github.com/kr/fs v0.1.0 // indirect github.com/letsencrypt/boulder v0.0.0-20240620165639-de9c06129bec // indirect github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 // indirect @@ -147,7 +147,7 @@ require ( github.com/morikuni/aec v1.0.0 // indirect github.com/opencontainers/runc v1.3.2 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/pkg/sftp v1.13.9 // indirect + github.com/pkg/sftp v1.13.10 // indirect github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect @@ -170,7 +170,7 @@ require ( github.com/tklauser/numcpus v0.10.0 // indirect github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 // indirect github.com/ulikunitz/xz v0.5.15 // indirect - github.com/vbatts/tar-split v0.12.1 // indirect + github.com/vbatts/tar-split v0.12.2 // indirect github.com/vishvananda/netns v0.0.5 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect @@ -192,3 +192,7 @@ require ( gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect tags.cncf.io/container-device-interface/specs-go v1.0.0 // indirect ) + +replace go.podman.io/common => github.com/lsm5/container-libs/common v0.0.0-20251023145256-2c7c0ea9cefe + +replace go.podman.io/buildah => github.com/lsm5/buildah v0.0.0-20251023152205-884c02fbd526 diff --git a/go.sum b/go.sum index 54f93b33f32..9649e71d5dc 100644 --- a/go.sum +++ b/go.sum @@ -47,8 +47,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v1.0.0-rc.1 h1:83KIq4yy1erSRgOVHNk1HYdPvzdJ5CnsWaRoJX4C41E= github.com/containerd/platforms v1.0.0-rc.1/go.mod h1:J71L7B+aiM5SdIEqmd9wp6THLVRzJGXfNuWCZCllLA4= -github.com/containerd/stargz-snapshotter/estargz v0.17.0 h1:+TyQIsR/zSFI1Rm31EQBwpAA1ovYgIKHy7kctL3sLcE= -github.com/containerd/stargz-snapshotter/estargz v0.17.0/go.mod h1:s06tWAiJcXQo9/8AReBCIo/QxcXFZ2n4qfsRnpl71SM= +github.com/containerd/stargz-snapshotter/estargz v0.18.0 h1:Ny5yptQgEXSkDFKvlKJGTvf1YJ+4xD8V+hXqoRG0n74= +github.com/containerd/stargz-snapshotter/estargz v0.18.0/go.mod h1:7hfU1BO2KB3axZl0dRQCdnHrIWw7TRDdK6L44Rdeuo0= github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40= github.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk= github.com/containernetworking/cni v1.3.0 h1:v6EpN8RznAZj9765HhXQrtXgX+ECGebEYEmnuFjskwo= @@ -135,8 +135,8 @@ github.com/gkampitakis/ciinfo v0.3.2 h1:JcuOPk8ZU7nZQjdUhctuhQofk7BGHuIy0c9Ez8BN github.com/gkampitakis/ciinfo v0.3.2/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo= github.com/gkampitakis/go-diff v1.3.2 h1:Qyn0J9XJSDTgnsgHRdz9Zp24RaJeKMUHg2+PDZZdC4M= github.com/gkampitakis/go-diff v1.3.2/go.mod h1:LLgOrpqleQe26cte8s36HTWcTmMEur6OPYerdAAS9tk= -github.com/gkampitakis/go-snaps v0.5.14 h1:3fAqdB6BCPKHDMHAKRwtPUwYexKtGrNuw8HX/T/4neo= -github.com/gkampitakis/go-snaps v0.5.14/go.mod h1:HNpx/9GoKisdhw9AFOBT1N7DBs9DiHo/hGheFGBZ+mc= +github.com/gkampitakis/go-snaps v0.5.15 h1:amyJrvM1D33cPHwVrjo9jQxX8g/7E2wYdZ+01KS3zGE= +github.com/gkampitakis/go-snaps v0.5.15/go.mod h1:HNpx/9GoKisdhw9AFOBT1N7DBs9DiHo/hGheFGBZ+mc= github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE= github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -221,8 +221,8 @@ github.com/kevinburke/ssh_config v1.4.0 h1:6xxtP5bZ2E4NF5tuQulISpTO2z8XbtH8cg1PW github.com/kevinburke/ssh_config v1.4.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= -github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= +github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co= +github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0= github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= @@ -235,6 +235,10 @@ github.com/letsencrypt/boulder v0.0.0-20240620165639-de9c06129bec h1:2tTW6cDth2T github.com/letsencrypt/boulder v0.0.0-20240620165639-de9c06129bec/go.mod h1:TmwEoGCwIti7BCeJ9hescZgRtatxRE+A72pCoPfmcfk= github.com/linuxkit/virtsock v0.0.0-20241009230534-cb6a20cc0422 h1:XvRuyDDRvi+UDxHN/M4MW4HxjmNVMmUKQj/+AbgsYgk= github.com/linuxkit/virtsock v0.0.0-20241009230534-cb6a20cc0422/go.mod h1:JLgfq4XMVbvfNlAXla/41lZnp21O72a/wWHGJefAvgQ= +github.com/lsm5/container-libs/common v0.0.0-20251023145256-2c7c0ea9cefe h1:8qD/aUDCGvHUUVa5iEQmuuQ3Ldl4j3N52iXOSx2mfzc= +github.com/lsm5/container-libs/common v0.0.0-20251023145256-2c7c0ea9cefe/go.mod h1:SYowhhZOMlSbIdVmx+qEwBRRcFMUr9EAgqRLWBZDb8s= +github.com/lsm5/buildah v0.0.0-20251017145416-1c35ea0ae809 h1:Xl7p6J9gfYA7TX0Z7VTNygqpEq7MZdrLX+EhsUdUOPc= +github.com/lsm5/buildah v0.0.0-20251017145416-1c35ea0ae809/go.mod h1:DOj6mclvkxcijXOmZTybYPZpuDv5ZyqoyjZSwfs/ikk= github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 h1:7UMa6KCCMjZEMDtTVdcGu0B1GmmC7QJKiCCjyTAWQy0= github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k= github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= @@ -296,8 +300,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= -github.com/onsi/ginkgo/v2 v2.26.0 h1:1J4Wut1IlYZNEAWIV3ALrT9NfiaGW2cDCJQSFQMs/gE= -github.com/onsi/ginkgo/v2 v2.26.0/go.mod h1:qhEywmzWTBUY88kfO0BRvX4py7scov9yR+Az2oavUzw= +github.com/onsi/ginkgo/v2 v2.27.1 h1:0LJC8MpUSQnfnp4n/3W3GdlmJP3ENGF0ZPzjQGLPP7s= +github.com/onsi/ginkgo/v2 v2.27.1/go.mod h1:wmy3vCqiBjirARfVhAqFpYt8uvX0yaFe+GudAqqcCqA= github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A= github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= github.com/opencontainers/cgroups v0.0.5 h1:DRITAqcOnY0uSBzIpt1RYWLjh5DPDiqUs4fY6Y0ktls= @@ -320,8 +324,8 @@ github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.13.9 h1:4NGkvGudBL7GteO3m6qnaQ4pC0Kvf0onSVc9gR3EWBw= -github.com/pkg/sftp v1.13.9/go.mod h1:OBN7bVXdstkFFN/gdnHPUb5TE8eb8G1Rp9wCItqjkkA= +github.com/pkg/sftp v1.13.10 h1:+5FbKNTe5Z9aspU88DPIKJ9z2KZoaGCu6Sr6kKR/5mU= +github.com/pkg/sftp v1.13.10/go.mod h1:bJ1a7uDhrX/4OII+agvy28lzRvQrmIQuaHrcI1HbeGA= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -385,12 +389,9 @@ github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3A github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 h1:pnnLyeX7o/5aX8qUQ69P/mLojDqwda8hFOCBTmP/6hw= github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6/go.mod h1:39R/xuhNgVhi+K0/zst4TLrJrVmbm6LVgl4A0+ZFS5M= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/sylabs/sif/v2 v2.22.0 h1:Y+xXufp4RdgZe02SR3nWEg7S6q4tPWN237WHYzkDSKA= @@ -419,8 +420,8 @@ github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 h1:pyC9PaHYZFgEKFdlp3G8 github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701/go.mod h1:P3a5rG4X7tI17Nn3aOIAYr5HbIMukwXG0urG0WuL8OA= github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY= github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/vbatts/tar-split v0.12.1 h1:CqKoORW7BUWBe7UL/iqTVvkTBOF8UvOMKOIZykxnnbo= -github.com/vbatts/tar-split v0.12.1/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA= +github.com/vbatts/tar-split v0.12.2 h1:w/Y6tjxpeiFMR47yzZPlPj/FcPLpXbTUi/9H7d3CPa4= +github.com/vbatts/tar-split v0.12.2/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA= github.com/vbauerster/mpb/v8 v8.10.2 h1:2uBykSHAYHekE11YvJhKxYmLATKHAGorZwFlyNw4hHM= github.com/vbauerster/mpb/v8 v8.10.2/go.mod h1:+Ja4P92E3/CorSZgfDtK46D7AVbDqmBQRTmyTqPElo0= github.com/vishvananda/netlink v1.3.1 h1:3AEMt62VKqz90r0tmNhog0r/PpWKmrEShJU0wJW6bV0= @@ -471,8 +472,6 @@ go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKr go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= -go.podman.io/common v0.66.0 h1:KElE3HKLFdMdJL+jv5ExBiX2Dh4Qcv8ovmzaBGRsyZM= -go.podman.io/common v0.66.0/go.mod h1:aNd2a0S7pY+fx1X5kpQYuF4hbwLU8ZOccuVrhu7h1Xc= go.podman.io/image/v5 v5.38.0 h1:aUKrCANkPvze1bnhLJsaubcfz0d9v/bSDLnwsXJm6G4= go.podman.io/image/v5 v5.38.0/go.mod h1:hSIoIUzgBnmc4DjoIdzk63aloqVbD7QXDMkSE/cvG90= go.podman.io/storage v1.61.0 h1:5hD/oyRYt1f1gxgvect+8syZBQhGhV28dCw2+CZpx0Q= @@ -491,7 +490,6 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM= diff --git a/libpod/container_internal.go b/libpod/container_internal.go index 268663da796..dce601119a1 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -1361,7 +1361,7 @@ func (c *Container) waitForHealthy(ctx context.Context) error { } // Whether a container should use `all` when stopping -func (c *Container) stopWithAll() (bool, error) { +func (c *Container) stopWithAll() bool { // If the container is running in a PID Namespace, then killing the // primary pid is enough to kill the container. If it is not running in // a pid namespace then the OCI Runtime needs to kill ALL processes in @@ -1373,29 +1373,17 @@ func (c *Container) stopWithAll() (bool, error) { if all { if c.config.NoCgroups { all = false - } else if rootless.IsRootless() { - // Only do this check if we need to - unified, err := cgroups.IsCgroup2UnifiedMode() - if err != nil { - return false, err - } - if !unified { - all = false - } } } - return all, nil + return all } // Internal, non-locking function to stop container func (c *Container) stop(timeout uint) error { logrus.Debugf("Stopping ctr %s (timeout %d)", c.ID(), timeout) - all, err := c.stopWithAll() - if err != nil { - return err - } + all := c.stopWithAll() // OK, the following code looks a bit weird but we have to make sure we can stop // containers with the restart policy always, to do this we have to set @@ -1502,7 +1490,7 @@ func (c *Container) waitForConmonToExitAndSave() error { // could open a pidfd on container PID1 before // this to get the real exit code... But I'm not // that dedicated. - all, _ := c.stopWithAll() + all := c.stopWithAll() if err := c.ociRuntime.StopContainer(c, 0, all); err != nil { logrus.Errorf("Error stopping container %s after Conmon exited prematurely: %v", c.ID(), err) } diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index a0054ebed37..fea5cc115fe 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -3,7 +3,6 @@ package libpod import ( - "errors" "fmt" "io/fs" "os" @@ -30,9 +29,7 @@ import ( "golang.org/x/sys/unix" ) -var ( - bindOptions = []string{define.TypeBind, "rprivate"} -) +var bindOptions = []string{define.TypeBind, "rprivate"} func (c *Container) mountSHM(shmOptions string) error { contextType := "context" @@ -267,11 +264,6 @@ func (c *Container) setupSystemd(mounts []spec.Mount, g generate.Generator) erro g.AddMount(tmpfsMnt) } - unified, err := cgroups.IsCgroup2UnifiedMode() - if err != nil { - return err - } - hasCgroupNs := false for _, ns := range c.config.Spec.Linux.Namespaces { if ns.Type == spec.CgroupNamespace { @@ -280,69 +272,25 @@ func (c *Container) setupSystemd(mounts []spec.Mount, g generate.Generator) erro } } - if unified { - g.RemoveMount("/sys/fs/cgroup") + g.RemoveMount("/sys/fs/cgroup") - var systemdMnt spec.Mount - if hasCgroupNs { - systemdMnt = spec.Mount{ - Destination: "/sys/fs/cgroup", - Type: "cgroup", - Source: "cgroup", - Options: []string{"private", "rw"}, - } - } else { - systemdMnt = spec.Mount{ - Destination: "/sys/fs/cgroup", - Type: define.TypeBind, - Source: "/sys/fs/cgroup", - Options: []string{define.TypeBind, "private", "rw"}, - } + var systemdMnt spec.Mount + if hasCgroupNs { + systemdMnt = spec.Mount{ + Destination: "/sys/fs/cgroup", + Type: "cgroup", + Source: "cgroup", + Options: []string{"private", "rw"}, } - g.AddMount(systemdMnt) } else { - hasSystemdMount := MountExists(mounts, "/sys/fs/cgroup/systemd") - if hasCgroupNs && !hasSystemdMount { - return errors.New("cgroup namespace is not supported with cgroup v1 and systemd mode") - } - mountOptions := []string{define.TypeBind, "rprivate"} - - if !hasSystemdMount { - skipMount := hasSystemdMount - var statfs unix.Statfs_t - if err := unix.Statfs("/sys/fs/cgroup/systemd", &statfs); err != nil { - if errors.Is(err, os.ErrNotExist) { - // If the mount is missing on the host, we cannot bind mount it so - // just skip it. - skipMount = true - } - mountOptions = append(mountOptions, "nodev", "noexec", "nosuid") - } else { - if statfs.Flags&unix.MS_NODEV == unix.MS_NODEV { - mountOptions = append(mountOptions, "nodev") - } - if statfs.Flags&unix.MS_NOEXEC == unix.MS_NOEXEC { - mountOptions = append(mountOptions, "noexec") - } - if statfs.Flags&unix.MS_NOSUID == unix.MS_NOSUID { - mountOptions = append(mountOptions, "nosuid") - } - if statfs.Flags&unix.MS_RDONLY == unix.MS_RDONLY { - mountOptions = append(mountOptions, "ro") - } - } - if !skipMount { - systemdMnt := spec.Mount{ - Destination: "/sys/fs/cgroup/systemd", - Type: define.TypeBind, - Source: "/sys/fs/cgroup/systemd", - Options: mountOptions, - } - g.AddMount(systemdMnt) - g.AddLinuxMaskedPaths("/sys/fs/cgroup/systemd/release_agent") - } + systemdMnt = spec.Mount{ + Destination: "/sys/fs/cgroup", + Type: define.TypeBind, + Source: "/sys/fs/cgroup", + Options: []string{define.TypeBind, "private", "rw"}, } } + g.AddMount(systemdMnt) return nil } @@ -385,16 +333,12 @@ func isRootlessCgroupSet(cgroup string) bool { } func (c *Container) expectPodCgroup() (bool, error) { - unified, err := cgroups.IsCgroup2UnifiedMode() - if err != nil { - return false, err - } cgroupManager := c.CgroupManager() switch { case c.config.NoCgroups: return false, nil case cgroupManager == config.SystemdCgroupsManager: - return !rootless.IsRootless() || unified, nil + return true, nil case cgroupManager == config.CgroupfsCgroupsManager: return !rootless.IsRootless(), nil default: @@ -404,10 +348,6 @@ func (c *Container) expectPodCgroup() (bool, error) { // Get cgroup path in a format suitable for the OCI spec func (c *Container) getOCICgroupPath() (string, error) { - unified, err := cgroups.IsCgroup2UnifiedMode() - if err != nil { - return "", err - } cgroupManager := c.CgroupManager() switch { case c.config.NoCgroups: @@ -425,7 +365,7 @@ func (c *Container) getOCICgroupPath() (string, error) { systemdCgroups := fmt.Sprintf("%s:libpod:%s", path.Base(c.config.CgroupParent), c.ID()) logrus.Debugf("Setting Cgroups for container %s to %s", c.ID(), systemdCgroups) return systemdCgroups, nil - case (rootless.IsRootless() && (cgroupManager == config.CgroupfsCgroupsManager || !unified)): + case (rootless.IsRootless() && (cgroupManager == config.CgroupfsCgroupsManager)): if c.config.CgroupParent == "" || !isRootlessCgroupSet(c.config.CgroupParent) { return "", nil } diff --git a/libpod/info_linux.go b/libpod/info_linux.go index 2ab534070b2..edad644d2b8 100644 --- a/libpod/info_linux.go +++ b/libpod/info_linux.go @@ -30,14 +30,8 @@ func (r *Runtime) setPlatformHostInfo(info *define.HostInfo) error { return fmt.Errorf("getting Seccomp profile path: %w", err) } - // Cgroups version - unified, err := cgroups.IsCgroup2UnifiedMode() - if err != nil { - return fmt.Errorf("reading cgroups mode: %w", err) - } - // Get Map of all available controllers - availableControllers, err := cgroups.AvailableControllers(nil, unified) + availableControllers, err := cgroups.AvailableControllers() if err != nil { return fmt.Errorf("getting available cgroup controllers: %w", err) } @@ -55,12 +49,6 @@ func (r *Runtime) setPlatformHostInfo(info *define.HostInfo) error { } info.Slirp4NetNS = define.SlirpInfo{} - cgroupVersion := "v1" - if unified { - cgroupVersion = "v2" - } - info.CgroupsVersion = cgroupVersion - slirp4netnsPath := r.config.Engine.NetworkCmdPath if slirp4netnsPath == "" { slirp4netnsPath, _ = r.config.FindHelperBinary(slirp4netns.BinaryName, true) diff --git a/libpod/runtime_linux.go b/libpod/runtime_linux.go index 07f9db5e2ac..746070e6f57 100644 --- a/libpod/runtime_linux.go +++ b/libpod/runtime_linux.go @@ -12,21 +12,10 @@ import ( "github.com/containers/podman/v5/pkg/rootless" "github.com/containers/podman/v5/pkg/systemd" "github.com/sirupsen/logrus" - "go.podman.io/common/pkg/cgroups" ) func checkCgroups2UnifiedMode(runtime *Runtime) { - unified, _ := cgroups.IsCgroup2UnifiedMode() - // DELETE ON RHEL9 - if !unified { - _, ok := os.LookupEnv("PODMAN_IGNORE_CGROUPSV1_WARNING") - if !ok { - logrus.Warn("Using cgroups-v1 which is deprecated in favor of cgroups-v2 with Podman v5 and will be removed in a future version. Set environment variable `PODMAN_IGNORE_CGROUPSV1_WARNING` to hide this warning.") - } - } - // DELETE ON RHEL9 - - if unified && rootless.IsRootless() && !systemd.IsSystemdSessionValid(rootless.GetRootlessUID()) { + if rootless.IsRootless() && !systemd.IsSystemdSessionValid(rootless.GetRootlessUID()) { // If user is rootless and XDG_RUNTIME_DIR is found, podman will not proceed with /tmp directory // it will try to use existing XDG_RUNTIME_DIR // if current user has no write access to XDG_RUNTIME_DIR we will fail later diff --git a/libpod/runtime_pod_linux.go b/libpod/runtime_pod_linux.go index 0dec268d445..ff750c1337b 100644 --- a/libpod/runtime_pod_linux.go +++ b/libpod/runtime_pod_linux.go @@ -122,7 +122,7 @@ func (p *Pod) removePodCgroup() error { // hard - instead, just log errors. conmonCgroupPath := filepath.Join(p.state.CgroupPath, "conmon") conmonCgroup, err := cgroups.Load(conmonCgroupPath) - if err != nil && err != cgroups.ErrCgroupDeleted && err != cgroups.ErrCgroupV1Rootless { + if err != nil && err != cgroups.ErrCgroupDeleted { return fmt.Errorf("retrieving pod %s conmon cgroup: %w", p.ID(), err) } if err == nil { @@ -131,7 +131,7 @@ func (p *Pod) removePodCgroup() error { } } cgroup, err := cgroups.Load(p.state.CgroupPath) - if err != nil && err != cgroups.ErrCgroupDeleted && err != cgroups.ErrCgroupV1Rootless { + if err != nil && err != cgroups.ErrCgroupDeleted { return fmt.Errorf("retrieving pod %s cgroup: %w", p.ID(), err) } if err == nil { diff --git a/pkg/domain/infra/runtime_libpod.go b/pkg/domain/infra/runtime_libpod.go index 34cea76b2fd..9a4a08b043d 100644 --- a/pkg/domain/infra/runtime_libpod.go +++ b/pkg/domain/infra/runtime_libpod.go @@ -20,7 +20,6 @@ import ( "github.com/containers/podman/v5/pkg/util" "github.com/sirupsen/logrus" flag "github.com/spf13/pflag" - "go.podman.io/common/pkg/cgroups" "go.podman.io/storage/pkg/idtools" "go.podman.io/storage/types" ) @@ -182,14 +181,6 @@ func getRuntime(ctx context.Context, fs *flag.FlagSet, opts *engineOpts) (*libpo if fs.Changed("cgroup-manager") { options = append(options, libpod.WithCgroupManager(cfg.ContainersConf.Engine.CgroupManager)) - } else { - unified, err := cgroups.IsCgroup2UnifiedMode() - if err != nil { - return nil, err - } - if rootless.IsRootless() && !unified { - options = append(options, libpod.WithCgroupManager("cgroupfs")) - } } // TODO flag to set libpod static dir? diff --git a/pkg/specgen/generate/validate_linux.go b/pkg/specgen/generate/validate_linux.go index 0fa8a915228..658e45dd2de 100644 --- a/pkg/specgen/generate/validate_linux.go +++ b/pkg/specgen/generate/validate_linux.go @@ -3,171 +3,14 @@ package generate import ( - "errors" - "fmt" "os" "path/filepath" - "reflect" - "github.com/containers/podman/v5/pkg/rootless" "github.com/containers/podman/v5/pkg/specgen" - "github.com/opencontainers/runtime-spec/specs-go" "go.podman.io/common/pkg/cgroups" - "go.podman.io/common/pkg/sysinfo" "go.podman.io/storage/pkg/fileutils" ) -// Verify resource limits are sanely set when running on cgroup v1. -func verifyContainerResourcesCgroupV1(s *specgen.SpecGenerator) ([]string, error) { - warnings := []string{} - - sysInfo := sysinfo.New(true) - - // If ResourceLimits is nil, return without warning - resourceNil := &specgen.SpecGenerator{} - resourceNil.ResourceLimits = &specs.LinuxResources{} - if s.ResourceLimits == nil || reflect.DeepEqual(s.ResourceLimits, resourceNil.ResourceLimits) { - return nil, nil - } - - // Cgroups V1 rootless system does not support Resource limits - if rootless.IsRootless() { - s.ResourceLimits = nil - return []string{"Resource limits are not supported and ignored on cgroups V1 rootless systems"}, nil - } - - if s.ResourceLimits.Unified != nil { - return nil, errors.New("cannot use --cgroup-conf without cgroup v2") - } - - // Memory checks - if s.ResourceLimits.Memory != nil { - memory := s.ResourceLimits.Memory - if memory.Limit != nil && !sysInfo.MemoryLimit { - warnings = append(warnings, "Your kernel does not support memory limit capabilities or the cgroup is not mounted. Limitation discarded.") - memory.Limit = nil - memory.Swap = nil - } - if memory.Limit != nil && memory.Swap != nil && !sysInfo.SwapLimit { - warnings = append(warnings, "Your kernel does not support swap limit capabilities or the cgroup is not mounted. Memory limited without swap.") - memory.Swap = nil - } - if memory.Limit != nil && memory.Swap != nil && *memory.Swap < *memory.Limit { - return warnings, errors.New("minimum memoryswap limit should be larger than memory limit, see usage") - } - if memory.Limit == nil && memory.Swap != nil { - return warnings, errors.New("you should always set a memory limit when using a memoryswap limit, see usage") - } - if memory.Swappiness != nil { - if !sysInfo.MemorySwappiness { - warnings = append(warnings, "Your kernel does not support memory swappiness capabilities, or the cgroup is not mounted. Memory swappiness discarded.") - memory.Swappiness = nil - } else if *memory.Swappiness > 100 { - return warnings, fmt.Errorf("invalid value: %v, valid memory swappiness range is 0-100", *memory.Swappiness) - } - } - if memory.Reservation != nil && !sysInfo.MemoryReservation { - warnings = append(warnings, "Your kernel does not support memory soft limit capabilities or the cgroup is not mounted. Limitation discarded.") - memory.Reservation = nil - } - if memory.Limit != nil && memory.Reservation != nil && *memory.Limit < *memory.Reservation { - return warnings, errors.New("minimum memory limit cannot be less than memory reservation limit, see usage") - } - if memory.DisableOOMKiller != nil && *memory.DisableOOMKiller && !sysInfo.OomKillDisable { - warnings = append(warnings, "Your kernel does not support OomKillDisable. OomKillDisable discarded.") - memory.DisableOOMKiller = nil - } - } - - // Pids checks - if s.ResourceLimits.Pids != nil { - // TODO: Should this be 0, or checking that ResourceLimits.Pids - // is set at all? - if s.ResourceLimits.Pids.Limit >= 0 && !sysInfo.PidsLimit { - warnings = append(warnings, "Your kernel does not support pids limit capabilities or the cgroup is not mounted. PIDs limit discarded.") - s.ResourceLimits.Pids = nil - } - } - - // CPU checks - if s.ResourceLimits.CPU != nil { - cpu := s.ResourceLimits.CPU - if cpu.Shares != nil && !sysInfo.CPUShares { - warnings = append(warnings, "Your kernel does not support CPU shares or the cgroup is not mounted. Shares discarded.") - cpu.Shares = nil - } - if cpu.Period != nil && !sysInfo.CPUCfsPeriod { - warnings = append(warnings, "Your kernel does not support CPU cfs period or the cgroup is not mounted. Period discarded.") - cpu.Period = nil - } - if cpu.Period != nil && (*cpu.Period < 1000 || *cpu.Period > 1000000) { - return warnings, errors.New("CPU cfs period cannot be less than 1ms (i.e. 1000) or larger than 1s (i.e. 1000000)") - } - if cpu.Quota != nil && !sysInfo.CPUCfsQuota { - warnings = append(warnings, "Your kernel does not support CPU cfs quota or the cgroup is not mounted. Quota discarded.") - cpu.Quota = nil - } - if cpu.Quota != nil && *cpu.Quota < 1000 { - return warnings, errors.New("CPU cfs quota cannot be less than 1ms (i.e. 1000)") - } - if (cpu.Cpus != "" || cpu.Mems != "") && !sysInfo.Cpuset { - warnings = append(warnings, "Your kernel does not support cpuset or the cgroup is not mounted. CPUset discarded.") - cpu.Cpus = "" - cpu.Mems = "" - } - - cpusAvailable, err := sysInfo.IsCpusetCpusAvailable(cpu.Cpus) - if err != nil { - return warnings, fmt.Errorf("invalid value %s for cpuset cpus", cpu.Cpus) - } - if !cpusAvailable { - return warnings, fmt.Errorf("requested CPUs are not available - requested %s, available: %s", cpu.Cpus, sysInfo.Cpus) - } - - memsAvailable, err := sysInfo.IsCpusetMemsAvailable(cpu.Mems) - if err != nil { - return warnings, fmt.Errorf("invalid value %s for cpuset mems", cpu.Mems) - } - if !memsAvailable { - return warnings, fmt.Errorf("requested memory nodes are not available - requested %s, available: %s", cpu.Mems, sysInfo.Mems) - } - } - - // Blkio checks - if s.ResourceLimits.BlockIO != nil { - blkio := s.ResourceLimits.BlockIO - if blkio.Weight != nil && !sysInfo.BlkioWeight { - warnings = append(warnings, "Your kernel does not support Block I/O weight or the cgroup is not mounted. Weight discarded.") - blkio.Weight = nil - } - if blkio.Weight != nil && (*blkio.Weight > 1000 || *blkio.Weight < 10) { - return warnings, errors.New("range of blkio weight is from 10 to 1000") - } - if len(blkio.WeightDevice) > 0 && !sysInfo.BlkioWeightDevice { - warnings = append(warnings, "Your kernel does not support Block I/O weight_device or the cgroup is not mounted. Weight-device discarded.") - blkio.WeightDevice = nil - } - if len(blkio.ThrottleReadBpsDevice) > 0 && !sysInfo.BlkioReadBpsDevice { - warnings = append(warnings, "Your kernel does not support BPS Block I/O read limit or the cgroup is not mounted. Block I/O BPS read limit discarded") - blkio.ThrottleReadBpsDevice = nil - } - if len(blkio.ThrottleWriteBpsDevice) > 0 && !sysInfo.BlkioWriteBpsDevice { - warnings = append(warnings, "Your kernel does not support BPS Block I/O write limit or the cgroup is not mounted. Block I/O BPS write limit discarded.") - blkio.ThrottleWriteBpsDevice = nil - } - if len(blkio.ThrottleReadIOPSDevice) > 0 && !sysInfo.BlkioReadIOpsDevice { - warnings = append(warnings, "Your kernel does not support IOPS Block read limit or the cgroup is not mounted. Block I/O IOPS read limit discarded.") - blkio.ThrottleReadIOPSDevice = nil - } - if len(blkio.ThrottleWriteIOPSDevice) > 0 && !sysInfo.BlkioWriteIOpsDevice { - warnings = append(warnings, "Your kernel does not support IOPS Block I/O write limit or the cgroup is not mounted. Block I/O IOPS write limit discarded.") - blkio.ThrottleWriteIOPSDevice = nil - } - } - - return warnings, nil -} - // Verify resource limits are sanely set when running on cgroup v2. func verifyContainerResourcesCgroupV2(s *specgen.SpecGenerator) ([]string, error) { warnings := []string{} @@ -225,12 +68,9 @@ func verifyContainerResourcesCgroupV2(s *specgen.SpecGenerator) ([]string, error // Verify resource limits are sanely set, removing any limits that are not // possible with the current cgroups config. func verifyContainerResources(s *specgen.SpecGenerator) ([]string, error) { - cgroup2, err := cgroups.IsCgroup2UnifiedMode() + _, err := cgroups.IsCgroup2UnifiedMode() if err != nil { return []string{}, err } - if cgroup2 { - return verifyContainerResourcesCgroupV2(s) - } - return verifyContainerResourcesCgroupV1(s) + return verifyContainerResourcesCgroupV2(s) } diff --git a/test/apiv2/25-containersMore.at b/test/apiv2/25-containersMore.at index a7679817add..47a922d6370 100644 --- a/test/apiv2/25-containersMore.at +++ b/test/apiv2/25-containersMore.at @@ -28,15 +28,6 @@ if root || have_cgroupsv2; then .Name=foo t POST libpod/containers/foo/unpause 204 -else - # cgroupsv1 rootless : pause and unpause are not supported in cgroups v1 rootless - t POST libpod/containers/foo/pause 500 \ - .cause="this container does not have a cgroup" \ - .message~".*pause containers on rootless containers with cgroup V1" - - t POST libpod/containers/foo/unpause 500 \ - .cause="container state improper" \ - .message~".*is not paused, can't unpause: container state improper" fi t GET libpod/containers/foo/json 200 \ diff --git a/test/apiv2/40-pods.at b/test/apiv2/40-pods.at index b50cb1686ed..6cc73783a2f 100644 --- a/test/apiv2/40-pods.at +++ b/test/apiv2/40-pods.at @@ -47,14 +47,7 @@ t POST libpod/pods/fakename/start 404 \ .cause="no such pod" \ .message="no pod with name or ID fakename found: no such pod" -if root || have_cgroupsv2; then - t POST libpod/pods/foo/pause 200 -else - # Rootless cgroupsv1 : unsupported - t POST "libpod/pods/foo/pause (rootless cgroups v1)" 500 \ - .cause="this container does not have a cgroup" \ - .message~".*pause pods containing rootless containers with cgroup V1" -fi +t POST libpod/pods/foo/pause 200 t POST libpod/pods/foo/unpause 200 t POST "libpod/pods/foo/unpause (2nd unpause in a row)" 200 t POST "libpod/pods/fakename/unpause" 404\ @@ -108,28 +101,21 @@ t POST libpod/pods/bar/stop?t=1 200 \ t POST libpod/pods/bar/start 200 -if root || have_cgroupsv2; then - t GET libpod/pods/stats?all=true 200 - is $(jq '. | length' <<<"$output") 3 "stats?all=true: number of records found" +t GET libpod/pods/stats?all=true 200 +is $(jq '. | length' <<<"$output") 3 "stats?all=true: number of records found" - t GET libpod/pods/stats?namesOrIDs=foo 200 - is $(jq '. | length' <<<"$output") 1 "stats?namesOrIDs=foo: number of records found" +t GET libpod/pods/stats?namesOrIDs=foo 200 +is $(jq '. | length' <<<"$output") 1 "stats?namesOrIDs=foo: number of records found" - t GET libpod/pods/stats?namesOrIDs=fakename 404 \ - .cause="no such pod" \ +t GET libpod/pods/stats?namesOrIDs=fakename 404 \ + .cause="no such pod" \ .message="unable to get list of pods: no pod with name or ID fakename found: no such pod" - t GET "libpod/pods/stats?all=true&namesOrIDs=foo" 500 \ - .cause="--all, --latest and arguments cannot be used together" \ - .message="--all, --latest and arguments cannot be used together" +t GET "libpod/pods/stats?all=true&namesOrIDs=foo" 500 \ + .cause="--all, --latest and arguments cannot be used together" \ + .message="--all, --latest and arguments cannot be used together" - t DELETE libpod/pods/bar?force=true 200 -else - # Rootless cgroupsv1 : libpod/pods/stats is unsupported - t GET libpod/pods/stats?all=true 500 \ - .cause="pod stats is not supported in rootless mode without cgroups v2" \ - .message~"pod stats is not supported in rootless mode without cgroups v2" -fi +t DELETE libpod/pods/bar?force=true 200 # test the fake name t GET libpod/pods/fakename/top 404 \ @@ -161,10 +147,7 @@ t DELETE libpod/pods/foo 200 t DELETE "libpod/pods/foo (pod has already been deleted)" 404 # Expect this to time out -if root || have_cgroupsv2; then - # Rootless cgroupsv1 : libpod/pods/stats is unsupported - APIV2_TEST_EXPECT_TIMEOUT=5 t GET "libpod/pods/stats?stream=true&delay=1" 999 -fi +APIV2_TEST_EXPECT_TIMEOUT=5 t GET "libpod/pods/stats?stream=true&delay=1" 999 podman pod create --name=specgen diff --git a/test/e2e/cleanup_test.go b/test/e2e/cleanup_test.go index 6fe96028c9b..e115cb6598f 100644 --- a/test/e2e/cleanup_test.go +++ b/test/e2e/cleanup_test.go @@ -98,7 +98,6 @@ var _ = Describe("Podman container cleanup", func() { }) It("podman cleanup paused container", func() { - SkipIfRootlessCgroupsV1("Pause is not supported in cgroups v1") session := podmanTest.RunTopContainer("paused") session.WaitWithDefaultTimeout() Expect(session).Should(ExitCleanly()) diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go index 2e45559a553..37fe5460bc0 100644 --- a/test/e2e/common_test.go +++ b/test/e2e/common_test.go @@ -38,7 +38,6 @@ import ( . "github.com/onsi/gomega" . "github.com/onsi/gomega/gexec" "github.com/sirupsen/logrus" - "go.podman.io/common/pkg/cgroups" "go.podman.io/common/pkg/libartifact" "go.podman.io/storage/pkg/ioutils" "go.podman.io/storage/pkg/lockfile" @@ -53,7 +52,6 @@ var ( CGROUP_MANAGER = "systemd" RESTORE_IMAGES = []string{ALPINE, BB, NGINX_IMAGE} defaultWaitTimeout = 90 - CGROUPSV2, _ = cgroups.IsCgroup2UnifiedMode() ) // PodmanTestIntegration struct for command line options @@ -784,7 +782,7 @@ func (p *PodmanTestIntegration) RunTopContainer(name string) *PodmanSessionInteg // runs top. If the name passed != "", it will have a name, command args can also be passed in func (p *PodmanTestIntegration) RunTopContainerWithArgs(name string, args []string) *PodmanSessionIntegration { // In proxy environment, some tests need to the --http-proxy=false option (#16684) - var podmanArgs = []string{"run", "--http-proxy=false"} + podmanArgs := []string{"run", "--http-proxy=false"} if name != "" { podmanArgs = append(podmanArgs, "--name", name) } @@ -803,7 +801,7 @@ func (p *PodmanTestIntegration) RunTopContainerWithArgs(name string, args []stri // RunLsContainer runs a simple container in the background that // simply runs ls. If the name passed != "", it will have a name func (p *PodmanTestIntegration) RunLsContainer(name string) (*PodmanSessionIntegration, int, string) { - var podmanArgs = []string{"run"} + podmanArgs := []string{"run"} if name != "" { podmanArgs = append(podmanArgs, "--name", name) } @@ -822,7 +820,7 @@ func (p *PodmanTestIntegration) RunLsContainer(name string) (*PodmanSessionInteg // RunNginxWithHealthCheck runs the alpine nginx container with an optional name and adds a healthcheck into it func (p *PodmanTestIntegration) RunNginxWithHealthCheck(name string) (*PodmanSessionIntegration, string) { - var podmanArgs = []string{"run"} + podmanArgs := []string{"run"} if name != "" { podmanArgs = append(podmanArgs, "--name", name) } @@ -835,7 +833,7 @@ func (p *PodmanTestIntegration) RunNginxWithHealthCheck(name string) (*PodmanSes // RunContainerWithNetworkTest runs the fedoraMinimal curl with the specified network mode. func (p *PodmanTestIntegration) RunContainerWithNetworkTest(mode string) *PodmanSessionIntegration { - var podmanArgs = []string{"run"} + podmanArgs := []string{"run"} if mode != "" { podmanArgs = append(podmanArgs, "--network", mode) } @@ -845,7 +843,7 @@ func (p *PodmanTestIntegration) RunContainerWithNetworkTest(mode string) *Podman } func (p *PodmanTestIntegration) RunLsContainerInPod(name, pod string) (*PodmanSessionIntegration, int, string) { - var podmanArgs = []string{"run", "--pod", pod} + podmanArgs := []string{"run", "--pod", pod} if name != "" { podmanArgs = append(podmanArgs, "--name", name) } @@ -1006,7 +1004,7 @@ func (s *PodmanSessionIntegration) InspectPodArrToJSON() []define.InspectPodData // CreatePod creates a pod with no infra container // it optionally takes a pod name func (p *PodmanTestIntegration) CreatePod(options map[string][]string) (*PodmanSessionIntegration, int, string) { - var args = []string{"pod", "create", "--infra=false", "--share", ""} + args := []string{"pod", "create", "--infra=false", "--share", ""} for k, values := range options { for _, v := range values { args = append(args, k+"="+v) @@ -1019,7 +1017,7 @@ func (p *PodmanTestIntegration) CreatePod(options map[string][]string) (*PodmanS } func (p *PodmanTestIntegration) CreateVolume(options map[string][]string) (*PodmanSessionIntegration, int, string) { - var args = []string{"volume", "create"} + args := []string{"volume", "create"} for k, values := range options { for _, v := range values { args = append(args, k+"="+v) @@ -1083,13 +1081,6 @@ func SkipIfRunc(p *PodmanTestIntegration, reason string) { } } -func SkipIfRootlessCgroupsV1(reason string) { - checkReason(reason) - if isRootless() && !CGROUPSV2 { - Skip("[rootless]: " + reason) - } -} - func SkipIfRootless(reason string) { checkReason(reason) if isRootless() { @@ -1182,24 +1173,6 @@ func isRootless() bool { return os.Geteuid() != 0 } -func isCgroupsV1() bool { - return !CGROUPSV2 -} - -func SkipIfCgroupV1(reason string) { - checkReason(reason) - if isCgroupsV1() { - Skip(reason) - } -} - -func SkipIfCgroupV2(reason string) { - checkReason(reason) - if CGROUPSV2 { - Skip(reason) - } -} - func isContainerized() bool { // This is set to "podman" by podman automatically return os.Getenv("container") != "" @@ -1382,8 +1355,10 @@ func (p *PodmanTestIntegration) makeOptions(args []string, options PodmanExecOpt podmanOptions = append(podmanOptions, strings.Split(p.StorageOptions, " ")...) if !options.NoCache { - cacheOptions := []string{"--storage-opt", - fmt.Sprintf("%s.imagestore=%s", p.PodmanTest.ImageCacheFS, p.PodmanTest.ImageCacheDir)} + cacheOptions := []string{ + "--storage-opt", + fmt.Sprintf("%s.imagestore=%s", p.PodmanTest.ImageCacheFS, p.PodmanTest.ImageCacheDir), + } podmanOptions = append(cacheOptions, podmanOptions...) } podmanOptions = append(podmanOptions, args...) diff --git a/test/e2e/container_clone_test.go b/test/e2e/container_clone_test.go index b974a107bb0..2b6afbcd0c1 100644 --- a/test/e2e/container_clone_test.go +++ b/test/e2e/container_clone_test.go @@ -15,7 +15,6 @@ var _ = Describe("Podman container clone", func() { }) It("podman container clone basic test", func() { - SkipIfRootlessCgroupsV1("starting a container with the memory limits not supported") create := podmanTest.Podman([]string{"create", ALPINE}) create.WaitWithDefaultTimeout() Expect(create).To(ExitCleanly()) @@ -68,7 +67,6 @@ var _ = Describe("Podman container clone", func() { }) It("podman container clone resource limits override", func() { - SkipIfRootlessCgroupsV1("Not supported for rootless + CgroupsV1") create := podmanTest.Podman([]string{"create", "--cpus=5", ALPINE}) create.WaitWithDefaultTimeout() Expect(create).To(ExitCleanly()) @@ -144,7 +142,6 @@ var _ = Describe("Podman container clone", func() { }) It("podman container clone in a pod", func() { - SkipIfRootlessCgroupsV1("starting a container with the memory limits not supported") run := podmanTest.Podman([]string{"run", "-dt", "--pod", "new:1234", ALPINE, "sleep", "20"}) run.WaitWithDefaultTimeout() Expect(run).To(ExitCleanly()) diff --git a/test/e2e/containers_conf_test.go b/test/e2e/containers_conf_test.go index 01c9d3f2348..7e5cbb9abfb 100644 --- a/test/e2e/containers_conf_test.go +++ b/test/e2e/containers_conf_test.go @@ -20,7 +20,6 @@ import ( ) var _ = Describe("Verify podman containers.conf usage", func() { - BeforeEach(func() { confPath, err := filepath.Abs("config/containers.conf") Expect(err).ToNot(HaveOccurred()) @@ -28,11 +27,9 @@ var _ = Describe("Verify podman containers.conf usage", func() { if IsRemote() { podmanTest.RestartRemoteService() } - }) It("limits test", func() { - SkipIfRootlessCgroupsV1("Setting limits not supported on cgroupv1 for rootless users") // containers.conf is set to "nofile=500:500" session := podmanTest.Podman([]string{"run", "--rm", fedoraMinimal, "ulimit", "-n"}) session.WaitWithDefaultTimeout() @@ -55,11 +52,9 @@ var _ = Describe("Verify podman containers.conf usage", func() { } else { Expect(session.OutputToString()).To(Not(Equal("500"))) } - }) It("oom-score-adj", func() { - SkipIfRootlessCgroupsV1("Setting limits not supported on cgroupv1 for rootless users") // containers.conf is set to "oom_score_adj=999" session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "cat", "/proc/self/oom_score_adj"}) session.WaitWithDefaultTimeout() @@ -85,15 +80,10 @@ var _ = Describe("Verify podman containers.conf usage", func() { } else { Expect(session.OutputToString()).To(ContainSubstring("0")) } - } - }) It("cgroup_conf in containers.conf", func() { - if isCgroupsV1() { - Skip("Setting cgroup_confs not supported on cgroupv1") - } // FIXME: Needs crun-1.8.2-2 to allow this with --cgroup-manager=cgroupfs, once this is available remove the skip below. SkipIfRootless("--cgroup-manager=cgoupfs and --cgroup-conf not supported in rootless mode with crun") conffile := filepath.Join(podmanTest.TempDir, "container.conf") @@ -152,7 +142,6 @@ var _ = Describe("Verify podman containers.conf usage", func() { }) It("add capabilities", func() { - SkipIfRootlessCgroupsV1("Not supported for rootless + CGroupsV1") cap := podmanTest.Podman([]string{"run", ALPINE, "grep", "CapEff", "/proc/self/status"}) cap.WaitWithDefaultTimeout() Expect(cap).Should(ExitCleanly()) @@ -198,7 +187,6 @@ var _ = Describe("Verify podman containers.conf usage", func() { }) verifyNSHandling := func(nspath, option string) { - SkipIfRootlessCgroupsV1("Not supported for rootless + CgroupsV1") os.Setenv("CONTAINERS_CONF", "config/containers-ns.conf") if IsRemote() { podmanTest.RestartRemoteService() @@ -812,7 +800,6 @@ var _ = Describe("Verify podman containers.conf usage", func() { } It("podman containers.conf container_name_as_hostname", func() { - // With default containers.conf // Start container with no options diff --git a/test/e2e/cp_test.go b/test/e2e/cp_test.go index 4ecb741692b..e80dd3d9da1 100644 --- a/test/e2e/cp_test.go +++ b/test/e2e/cp_test.go @@ -73,7 +73,6 @@ var _ = Describe("Podman cp", func() { // Copy a file to the container, then back to the host in --pid=host It("podman cp --pid=host file", func() { - SkipIfRootlessCgroupsV1("Not supported for rootless + CgroupsV1") srcFile, err := os.CreateTemp("", "") Expect(err).ToNot(HaveOccurred()) defer srcFile.Close() diff --git a/test/e2e/create_test.go b/test/e2e/create_test.go index 195bfa3d174..c0e0ae375dd 100644 --- a/test/e2e/create_test.go +++ b/test/e2e/create_test.go @@ -427,7 +427,6 @@ var _ = Describe("Podman create", func() { }) It("podman create with -m 1000000 sets swap to 2000000", func() { - SkipIfRootlessCgroupsV1("Not supported for rootless + CgroupsV1") numMem := 1000000 ctrName := "testCtr" session := podmanTest.Podman([]string{"create", "-t", "-m", fmt.Sprintf("%db", numMem), "--name", ctrName, ALPINE, "/bin/sh"}) @@ -442,7 +441,6 @@ var _ = Describe("Podman create", func() { }) It("podman create --cpus 5 sets nanocpus", func() { - SkipIfRootlessCgroupsV1("Not supported for rootless + CgroupsV1") numCpus := 5 nanoCPUs := numCpus * 1000000000 ctrName := "testCtr" diff --git a/test/e2e/generate_kube_test.go b/test/e2e/generate_kube_test.go index 82fa1101f8e..97cef1873e0 100644 --- a/test/e2e/generate_kube_test.go +++ b/test/e2e/generate_kube_test.go @@ -608,7 +608,6 @@ var _ = Describe("Podman kube generate", func() { }) It("on pod with memory limit", func() { - SkipIfRootlessCgroupsV1("Not supported for rootless + CgroupsV1") podName := "testMemoryLimit" podSession := podmanTest.Podman([]string{"pod", "create", "--name", podName}) podSession.WaitWithDefaultTimeout() @@ -634,7 +633,6 @@ var _ = Describe("Podman kube generate", func() { }) It("on pod with cpu limit", func() { - SkipIfRootlessCgroupsV1("Not supported for rootless + CgroupsV1") podName := "testCpuLimit" podSession := podmanTest.Podman([]string{"pod", "create", "--name", podName}) podSession.WaitWithDefaultTimeout() diff --git a/test/e2e/generate_spec_test.go b/test/e2e/generate_spec_test.go index 981f912e46e..025df3e727a 100644 --- a/test/e2e/generate_spec_test.go +++ b/test/e2e/generate_spec_test.go @@ -8,7 +8,6 @@ import ( . "github.com/containers/podman/v5/test/utils" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - . "github.com/onsi/gomega/gexec" ) var _ = Describe("Podman generate spec", func() { @@ -24,7 +23,6 @@ var _ = Describe("Podman generate spec", func() { }) It("podman generate spec basic usage", func() { - SkipIfRootlessCgroupsV1("Not supported for rootless + CgroupsV1") session := podmanTest.Podman([]string{"create", "--cpus", "5", "--name", "specgen", ALPINE}) session.WaitWithDefaultTimeout() Expect(session).Should(ExitCleanly()) @@ -35,7 +33,6 @@ var _ = Describe("Podman generate spec", func() { }) It("podman generate spec file", func() { - SkipIfRootlessCgroupsV1("Not supported for rootless + CgroupsV1") session := podmanTest.Podman([]string{"create", "--cpus", "5", "--name", "specgen", ALPINE}) session.WaitWithDefaultTimeout() Expect(session).Should(ExitCleanly()) @@ -61,11 +58,6 @@ var _ = Describe("Podman generate spec", func() { session = podmanTest.Podman([]string{"generate", "spec", "--compact", "podspecgen"}) session.WaitWithDefaultTimeout() - if isRootless() && !CGROUPSV2 { - Expect(session).Should(Exit(0)) - Expect(session.ErrorToString()).Should(ContainSubstring("Resource limits are not supported and ignored on cgroups V1 rootless")) - } else { - Expect(session).Should(ExitCleanly()) - } + Expect(session).Should(ExitCleanly()) }) }) diff --git a/test/e2e/info_test.go b/test/e2e/info_test.go index b9dcb6873dc..e7d961e9198 100644 --- a/test/e2e/info_test.go +++ b/test/e2e/info_test.go @@ -133,7 +133,6 @@ var _ = Describe("Podman Info", func() { It("Podman info must contain cgroupControllers with RelevantControllers", func() { SkipIfRootless("Hard to tell which controllers are going to be enabled for rootless") - SkipIfRootlessCgroupsV1("Disable cgroups not supported on cgroupv1 for rootless users") session := podmanTest.Podman([]string{"info", "--format", "{{.Host.CgroupControllers}}"}) session.WaitWithDefaultTimeout() Expect(session).To(ExitCleanly()) diff --git a/test/e2e/kill_test.go b/test/e2e/kill_test.go index 86e12857ee5..cf0f4bb0f41 100644 --- a/test/e2e/kill_test.go +++ b/test/e2e/kill_test.go @@ -108,7 +108,6 @@ var _ = Describe("Podman kill", func() { }) It("podman kill paused container", func() { - SkipIfRootlessCgroupsV1("pause is not supported for cgroupv1 rootless") ctrName := "testctr" session := podmanTest.RunTopContainer(ctrName) session.WaitWithDefaultTimeout() diff --git a/test/e2e/network_connect_disconnect_test.go b/test/e2e/network_connect_disconnect_test.go index f33c6de62bc..7bd1bc1e04b 100644 --- a/test/e2e/network_connect_disconnect_test.go +++ b/test/e2e/network_connect_disconnect_test.go @@ -50,7 +50,6 @@ var _ = Describe("Podman network connect and disconnect", func() { }) It("podman network disconnect", func() { - SkipIfRootlessCgroupsV1("stats not supported under rootless CgroupsV1") netName := "aliasTest" + stringid.GenerateRandomID() session := podmanTest.Podman([]string{"network", "create", netName}) session.WaitWithDefaultTimeout() @@ -175,7 +174,6 @@ var _ = Describe("Podman network connect and disconnect", func() { }) It("podman network connect", func() { - SkipIfRootlessCgroupsV1("stats not supported under rootless CgroupsV1") netName := "aliasTest" + stringid.GenerateRandomID() session := podmanTest.Podman([]string{"network", "create", netName}) session.WaitWithDefaultTimeout() diff --git a/test/e2e/pause_test.go b/test/e2e/pause_test.go index e9451a897a9..faf320ee864 100644 --- a/test/e2e/pause_test.go +++ b/test/e2e/pause_test.go @@ -18,21 +18,16 @@ var _ = Describe("Podman pause", func() { createdState := "created" BeforeEach(func() { - SkipIfRootlessCgroupsV1("Pause is not supported in cgroups v1") - - if CGROUPSV2 { - b, err := os.ReadFile("/proc/self/cgroup") - if err != nil { - Skip("cannot read self cgroup") - } - - path := filepath.Join("/sys/fs/cgroup", strings.TrimSuffix(strings.Replace(string(b), "0::", "", 1), "\n"), "cgroup.freeze") - _, err = os.Stat(path) - if err != nil { - Skip("freezer controller not available on the current kernel") - } + b, err := os.ReadFile("/proc/self/cgroup") + if err != nil { + Skip("cannot read self cgroup") } + path := filepath.Join("/sys/fs/cgroup", strings.TrimSuffix(strings.Replace(string(b), "0::", "", 1), "\n"), "cgroup.freeze") + _, err = os.Stat(path) + if err != nil { + Skip("freezer controller not available on the current kernel") + } }) It("podman pause bogus container", func() { diff --git a/test/e2e/pod_create_test.go b/test/e2e/pod_create_test.go index 534d88423ba..8327c21ab4d 100644 --- a/test/e2e/pod_create_test.go +++ b/test/e2e/pod_create_test.go @@ -768,7 +768,6 @@ ENTRYPOINT ["sleep","99999"] // Too complicated to differentiate in test context, so we ignore the first part // and just check for the "no container" substring, which is common to both. Expect(podCreate).Should(ExitWithError(125, `no container with name or ID "randomfakeid" found: no such container`)) - }) It("podman pod create with --userns=keep-id", func() { @@ -1045,7 +1044,6 @@ ENTRYPOINT ["sleep","99999"] session.WaitWithDefaultTimeout() Expect(session).Should(ExitCleanly()) Expect(session.OutputToString()).To(Equal("1:3")) - }) It("podman pod create --volumes-from", func() { @@ -1154,7 +1152,6 @@ ENTRYPOINT ["sleep","99999"] inspect := podmanTest.InspectContainer(ctrCreate.OutputToString()) Expect(inspect[0]).To(HaveField("AppArmorProfile", apparmor.Profile)) - }) It("podman pod create --sysctl test", func() { @@ -1192,12 +1189,9 @@ ENTRYPOINT ["sleep","99999"] session.WaitWithDefaultTimeout() Expect(session).Should(ExitCleanly()) Expect(session.OutputToString()).NotTo(ContainSubstring("kernel.msgmax = 65535")) - }) It("podman pod create --share-parent test", func() { - SkipIfRootlessCgroupsV1("rootless cannot use cgroups with cgroupsv1") - SkipIfCgroupV1("CgroupMode shows 'host' on CGv1, not CID (issue 15013, wontfix") podCreate := podmanTest.Podman([]string{"pod", "create", "--share-parent=false"}) podCreate.WaitWithDefaultTimeout() Expect(podCreate).Should(ExitCleanly()) @@ -1236,7 +1230,6 @@ ENTRYPOINT ["sleep","99999"] podCreate3 := podmanTest.Podman([]string{"pod", "create", "--share", "cgroup"}) podCreate3.WaitWithDefaultTimeout() Expect(podCreate3).ShouldNot(ExitCleanly()) - }) It("podman pod create infra inheritance test", func() { diff --git a/test/e2e/pod_infra_container_test.go b/test/e2e/pod_infra_container_test.go index c76da6cd7b9..35e87d7dcfb 100644 --- a/test/e2e/pod_infra_container_test.go +++ b/test/e2e/pod_infra_container_test.go @@ -227,7 +227,6 @@ var _ = Describe("Podman pod create", func() { }) It("podman pod container can override pod pid NS", func() { - SkipIfRootlessCgroupsV1("Not supported for rootless + CgroupsV1") session := podmanTest.Podman([]string{"pod", "create", "--share", "pid"}) session.WaitWithDefaultTimeout() Expect(session).Should(ExitCleanly()) diff --git a/test/e2e/pod_kill_test.go b/test/e2e/pod_kill_test.go index 7ae98d6e620..15020862a9a 100644 --- a/test/e2e/pod_kill_test.go +++ b/test/e2e/pod_kill_test.go @@ -108,7 +108,6 @@ var _ = Describe("Podman pod kill", func() { }) It("podman pod kill all", func() { - SkipIfRootlessCgroupsV1("Not supported for rootless + CgroupsV1") _, ec, podid := podmanTest.CreatePod(nil) Expect(ec).To(Equal(0)) diff --git a/test/e2e/pod_pause_test.go b/test/e2e/pod_pause_test.go index 3e673dcc7f4..57d3c086f62 100644 --- a/test/e2e/pod_pause_test.go +++ b/test/e2e/pod_pause_test.go @@ -11,10 +11,6 @@ import ( var _ = Describe("Podman pod pause", func() { pausedState := "Paused" - BeforeEach(func() { - SkipIfRootlessCgroupsV1("Pause is not supported in cgroups v1") - }) - It("podman pod pause bogus pod", func() { session := podmanTest.Podman([]string{"pod", "pause", "foobar"}) session.WaitWithDefaultTimeout() diff --git a/test/e2e/pod_ps_test.go b/test/e2e/pod_ps_test.go index e94b52d59bc..5442a2d755d 100644 --- a/test/e2e/pod_ps_test.go +++ b/test/e2e/pod_ps_test.go @@ -157,7 +157,6 @@ var _ = Describe("Podman ps", func() { }) It("podman pod ps --ctr-names", func() { - SkipIfRootlessCgroupsV1("Not supported for rootless + CgroupsV1") _, ec, podid := podmanTest.CreatePod(nil) Expect(ec).To(Equal(0)) diff --git a/test/e2e/pod_stats_test.go b/test/e2e/pod_stats_test.go index f2259b9136f..a0d7cd8aad1 100644 --- a/test/e2e/pod_stats_test.go +++ b/test/e2e/pod_stats_test.go @@ -9,14 +9,6 @@ import ( ) var _ = Describe("Podman pod stats", func() { - - BeforeEach(func() { - SkipIfRootlessCgroupsV1("Tests fail with both CGv1 + required --cgroup-manager=cgroupfs") - if isContainerized() { - SkipIfCgroupV1("All tests fail Error: unable to load cgroup at ...: cgroup deleted") - } - }) - It("podman pod stats should run with no pods", func() { session := podmanTest.Podman([]string{"pod", "stats", "--no-stream"}) session.WaitWithDefaultTimeout() diff --git a/test/e2e/run_cgroup_parent_test.go b/test/e2e/run_cgroup_parent_test.go index fc72c24f55a..91fb1cc39a7 100644 --- a/test/e2e/run_cgroup_parent_test.go +++ b/test/e2e/run_cgroup_parent_test.go @@ -16,11 +16,6 @@ import ( const cgroupRoot = "/sys/fs/cgroup" var _ = Describe("Podman run with --cgroup-parent", func() { - - BeforeEach(func() { - SkipIfRootlessCgroupsV1("cgroup parent is not supported in cgroups v1") - }) - Specify("valid --cgroup-parent using cgroupfs", func() { if !Containerized() { Skip("Must be containerized to run this test.") @@ -48,7 +43,6 @@ var _ = Describe("Podman run with --cgroup-parent", func() { }) Specify("always honor --cgroup-parent", func() { - SkipIfCgroupV1("test not supported in cgroups v1") if Containerized() || podmanTest.CgroupManager == "cgroupfs" { Skip("Requires Systemd cgroup manager support") } diff --git a/test/e2e/run_cpu_test.go b/test/e2e/run_cpu_test.go index e35c40048c8..42ceb75e14f 100644 --- a/test/e2e/run_cpu_test.go +++ b/test/e2e/run_cpu_test.go @@ -12,97 +12,50 @@ import ( ) var _ = Describe("Podman run cpu", func() { - BeforeEach(func() { - SkipIfRootlessCgroupsV1("Setting CPU not supported on cgroupv1 for rootless users") - - if CGROUPSV2 { - if err := os.WriteFile("/sys/fs/cgroup/cgroup.subtree_control", []byte("+cpuset"), 0o644); err != nil { - Skip("cpuset controller not available on the current kernel") - } + if err := os.WriteFile("/sys/fs/cgroup/cgroup.subtree_control", []byte("+cpuset"), 0o644); err != nil { + Skip("cpuset controller not available on the current kernel") } }) It("podman run cpu-period", func() { - var result *PodmanSessionIntegration - if CGROUPSV2 { - result = podmanTest.Podman([]string{"run", "--rm", "--cpu-period=5000", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/cpu.max"}) - } else { - result = podmanTest.Podman([]string{"run", "--rm", "--cpu-period=5000", ALPINE, "cat", "/sys/fs/cgroup/cpu/cpu.cfs_period_us"}) - } + result := podmanTest.Podman([]string{"run", "--rm", "--cpu-period=5000", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/cpu.max"}) result.WaitWithDefaultTimeout() Expect(result).Should(ExitCleanly()) Expect(result.OutputToString()).To(ContainSubstring("5000")) }) It("podman run cpu-quota", func() { - var result *PodmanSessionIntegration - - if CGROUPSV2 { - result = podmanTest.Podman([]string{"run", "--rm", "--cpu-quota=5000", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/cpu.max"}) - } else { - result = podmanTest.Podman([]string{"run", "--rm", "--cpu-quota=5000", ALPINE, "cat", "/sys/fs/cgroup/cpu/cpu.cfs_quota_us"}) - } + result := podmanTest.Podman([]string{"run", "--rm", "--cpu-quota=5000", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/cpu.max"}) result.WaitWithDefaultTimeout() Expect(result).Should(ExitCleanly()) Expect(result.OutputToString()).To(ContainSubstring("5000")) }) It("podman run cpus", func() { - if CGROUPSV2 { - result := podmanTest.Podman([]string{"run", "--rm", "--cpu-quota=5000", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/cpu.max"}) - result.WaitWithDefaultTimeout() - Expect(result).Should(ExitCleanly()) - Expect(result.OutputToString()).To(Equal("5000 100000")) - } else { - result := podmanTest.Podman([]string{"run", "--rm", "--cpus=0.5", ALPINE, "cat", "/sys/fs/cgroup/cpu/cpu.cfs_period_us"}) - result.WaitWithDefaultTimeout() - Expect(result).Should(ExitCleanly()) - Expect(result.OutputToString()).To(Equal("100000")) - - result = podmanTest.Podman([]string{"run", "--rm", "--cpus=0.5", ALPINE, "cat", "/sys/fs/cgroup/cpu/cpu.cfs_quota_us"}) - result.WaitWithDefaultTimeout() - Expect(result).Should(ExitCleanly()) - Expect(result.OutputToString()).To(Equal("50000")) - } + result := podmanTest.Podman([]string{"run", "--rm", "--cpu-quota=5000", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/cpu.max"}) + result.WaitWithDefaultTimeout() + Expect(result).Should(ExitCleanly()) + Expect(result.OutputToString()).To(Equal("5000 100000")) }) It("podman run cpu-shares", func() { - if CGROUPSV2 { - // [2-262144] is mapped to [1-10000] - result := podmanTest.Podman([]string{"run", "--rm", "--cpu-shares=262144", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/cpu.weight"}) - result.WaitWithDefaultTimeout() - Expect(result).Should(ExitCleanly()) - Expect(result.OutputToString()).To(Equal("10000")) - } else { - result := podmanTest.Podman([]string{"run", "--rm", "-c", "2", ALPINE, "cat", "/sys/fs/cgroup/cpu/cpu.shares"}) - result.WaitWithDefaultTimeout() - Expect(result).Should(ExitCleanly()) - Expect(result.OutputToString()).To(Equal("2")) - } + // [2-262144] is mapped to [1-10000] + result := podmanTest.Podman([]string{"run", "--rm", "--cpu-shares=262144", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/cpu.weight"}) + result.WaitWithDefaultTimeout() + Expect(result).Should(ExitCleanly()) + Expect(result.OutputToString()).To(Equal("10000")) }) It("podman run cpuset-cpus", func() { - var result *PodmanSessionIntegration - - if CGROUPSV2 { - result = podmanTest.Podman([]string{"run", "--rm", "--cpuset-cpus=0", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/cpuset.cpus.effective"}) - } else { - result = podmanTest.Podman([]string{"run", "--rm", "--cpuset-cpus=0", ALPINE, "cat", "/sys/fs/cgroup/cpuset/cpuset.cpus"}) - } + result := podmanTest.Podman([]string{"run", "--rm", "--cpuset-cpus=0", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/cpuset.cpus.effective"}) result.WaitWithDefaultTimeout() Expect(result).Should(ExitCleanly()) Expect(result.OutputToString()).To(Equal("0")) }) It("podman run cpuset-mems", func() { - var result *PodmanSessionIntegration - - if CGROUPSV2 { - result = podmanTest.Podman([]string{"run", "--rm", "--cpuset-mems=0", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/cpuset.mems.effective"}) - } else { - result = podmanTest.Podman([]string{"run", "--rm", "--cpuset-mems=0", ALPINE, "cat", "/sys/fs/cgroup/cpuset/cpuset.mems"}) - } + result := podmanTest.Podman([]string{"run", "--rm", "--cpuset-mems=0", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/cpuset.mems.effective"}) result.WaitWithDefaultTimeout() Expect(result).Should(ExitCleanly()) Expect(result.OutputToString()).To(Equal("0")) @@ -121,7 +74,6 @@ var _ = Describe("Podman run cpu", func() { }) It("podman run invalid cpu-rt-period with cgroupsv2", func() { - SkipIfCgroupV1("testing options that only work in cgroup v2") result := podmanTest.Podman([]string{"run", "--rm", "--cpu-rt-period=5000", ALPINE, "ls"}) result.WaitWithDefaultTimeout() Expect(result).Should(Exit(0)) @@ -129,7 +81,6 @@ var _ = Describe("Podman run cpu", func() { }) It("podman run invalid cpu-rt-runtime with cgroupsv2", func() { - SkipIfCgroupV1("testing options that only work in cgroup v2") result := podmanTest.Podman([]string{"run", "--rm", "--cpu-rt-runtime=5000", ALPINE, "ls"}) result.WaitWithDefaultTimeout() Expect(result).Should(Exit(0)) diff --git a/test/e2e/run_memory_test.go b/test/e2e/run_memory_test.go index 4e9cf5c32a4..0f60211a8eb 100644 --- a/test/e2e/run_memory_test.go +++ b/test/e2e/run_memory_test.go @@ -3,75 +3,34 @@ package integration import ( - "fmt" - . "github.com/containers/podman/v5/test/utils" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) var _ = Describe("Podman run memory", func() { - - BeforeEach(func() { - SkipIfRootlessCgroupsV1("Setting Memory not supported on cgroupv1 for rootless users") - }) - It("podman run memory test", func() { - var session *PodmanSessionIntegration - - if CGROUPSV2 { - session = podmanTest.Podman([]string{"run", "--memory=40m", "--net=none", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/memory.max"}) - } else { - session = podmanTest.Podman([]string{"run", "--memory=40m", ALPINE, "cat", "/sys/fs/cgroup/memory/memory.limit_in_bytes"}) - } + session := podmanTest.Podman([]string{"run", "--memory=40m", "--net=none", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/memory.max"}) session.WaitWithDefaultTimeout() Expect(session).Should(ExitCleanly()) Expect(session.OutputToString()).To(Equal("41943040")) }) It("podman run memory-reservation test", func() { - var session *PodmanSessionIntegration - - if CGROUPSV2 { - session = podmanTest.Podman([]string{"run", "--memory-reservation=40m", "--net=none", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/memory.low"}) - } else { - session = podmanTest.Podman([]string{"run", "--memory-reservation=40m", ALPINE, "cat", "/sys/fs/cgroup/memory/memory.soft_limit_in_bytes"}) - } - + session := podmanTest.Podman([]string{"run", "--memory-reservation=40m", "--net=none", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/memory.low"}) session.WaitWithDefaultTimeout() Expect(session).Should(ExitCleanly()) Expect(session.OutputToString()).To(Equal("41943040")) }) It("podman run memory-swap test", func() { - var ( - session *PodmanSessionIntegration - expect string - ) - - if CGROUPSV2 { - session = podmanTest.Podman([]string{"run", "--memory=20m", "--memory-swap=30M", "--net=none", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/memory.swap.max"}) - expect = "10485760" - } else { - session = podmanTest.Podman([]string{"run", "--memory=20m", "--memory-swap=30M", ALPINE, "cat", "/sys/fs/cgroup/memory/memory.memsw.limit_in_bytes"}) - expect = "31457280" - } + session := podmanTest.Podman([]string{"run", "--memory=20m", "--memory-swap=30M", "--net=none", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/memory.swap.max"}) + expect := "10485760" session.WaitWithDefaultTimeout() Expect(session).Should(ExitCleanly()) Expect(session.OutputToString()).To(Equal(expect)) }) - for _, limit := range []string{"0", "15", "100"} { - testName := fmt.Sprintf("podman run memory-swappiness test(%s)", limit) - It(testName, func() { - SkipIfCgroupV2("memory-swappiness not supported on cgroupV2") - session := podmanTest.Podman([]string{"run", fmt.Sprintf("--memory-swappiness=%s", limit), ALPINE, "cat", "/sys/fs/cgroup/memory/memory.swappiness"}) - session.WaitWithDefaultTimeout() - Expect(session).Should(ExitCleanly()) - Expect(session.OutputToString()).To(Equal(limit)) - }) - } - It("podman run memory test on oomkilled container", func() { mem := SystemExec("cat", []string{"/proc/sys/vm/overcommit_memory"}) mem.WaitWithDefaultTimeout() diff --git a/test/e2e/run_ns_test.go b/test/e2e/run_ns_test.go index 3cae4592ab8..0a5bf3810c3 100644 --- a/test/e2e/run_ns_test.go +++ b/test/e2e/run_ns_test.go @@ -14,7 +14,6 @@ import ( var _ = Describe("Podman run ns", func() { It("podman run pidns test", func() { - SkipIfRootlessCgroupsV1("Not supported for rootless + CgroupsV1") session := podmanTest.Podman([]string{"run", fedoraMinimal, "bash", "-c", "echo $$"}) session.WaitWithDefaultTimeout() Expect(session).Should(ExitCleanly()) @@ -93,7 +92,6 @@ var _ = Describe("Podman run ns", func() { }) It("podman run --ipc=host --pid=host", func() { - SkipIfRootlessCgroupsV1("Not supported for rootless + CgroupsV1") cmd := exec.Command("ls", "-l", "/proc/self/ns/pid") res, err := cmd.Output() Expect(err).ToNot(HaveOccurred()) diff --git a/test/e2e/run_selinux_test.go b/test/e2e/run_selinux_test.go index dad1eb4e4f1..dadcb6b9dd4 100644 --- a/test/e2e/run_selinux_test.go +++ b/test/e2e/run_selinux_test.go @@ -239,7 +239,6 @@ var _ = Describe("Podman run", func() { }) It("podman test --pid=host", func() { - SkipIfRootlessCgroupsV1("Not supported for rootless + CgroupsV1") session := podmanTest.Podman([]string{"run", "--pid=host", ALPINE, "cat", "/proc/self/attr/current"}) session.WaitWithDefaultTimeout() Expect(session).Should(ExitCleanly()) diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index 2b40ce5abed..b07e0fadb7b 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -25,7 +25,6 @@ import ( ) var _ = Describe("Podman run", func() { - It("podman run a container based on local image", func() { session := podmanTest.Podman([]string{"run", ALPINE, "ls"}) session.WaitWithDefaultTimeout() @@ -228,7 +227,6 @@ var _ = Describe("Podman run", func() { Expect(session).Should(Exit(0)) Expect(session.ErrorToString()).To(ContainSubstring("Trying to pull " + BB_GLIBC)) Expect(session.ErrorToString()).To(ContainSubstring("Writing manifest to image destination")) - }) It("podman run --tls-verify", func() { @@ -274,8 +272,10 @@ var _ = Describe("Podman run", func() { Expect(err).ShouldNot(HaveOccurred()) // Change image in predictable way to validate export - csession := podmanTest.Podman([]string{"run", "--name", uniqueString, ALPINE, - "/bin/sh", "-c", fmt.Sprintf("echo %s > %s", uniqueString, testFilePath)}) + csession := podmanTest.Podman([]string{ + "run", "--name", uniqueString, ALPINE, + "/bin/sh", "-c", fmt.Sprintf("echo %s > %s", uniqueString, testFilePath), + }) csession.WaitWithDefaultTimeout() Expect(csession).Should(ExitCleanly()) @@ -292,8 +292,10 @@ var _ = Describe("Podman run", func() { Expect(filepath.Join(rootfs, uls)).Should(BeADirectory()) // Other tests confirm SELinux types, just confirm --rootfs is working. - session := podmanTest.Podman([]string{"run", "-i", "--security-opt", "label=disable", - "--rootfs", rootfs, "cat", testFilePath}) + session := podmanTest.Podman([]string{ + "run", "-i", "--security-opt", "label=disable", + "--rootfs", rootfs, "cat", testFilePath, + }) session.WaitWithDefaultTimeout() Expect(session).Should(ExitCleanly()) @@ -309,15 +311,19 @@ var _ = Describe("Podman run", func() { } // Test --rootfs with an external overlay // use --rm to remove container and confirm if we did not leak anything - osession := podmanTest.Podman([]string{"run", "-i", "--rm", "--security-opt", "label=disable", - "--rootfs", rootfs + ":O", "cat", testFilePath}) + osession := podmanTest.Podman([]string{ + "run", "-i", "--rm", "--security-opt", "label=disable", + "--rootfs", rootfs + ":O", "cat", testFilePath, + }) osession.WaitWithDefaultTimeout() Expect(osession).Should(ExitCleanly()) Expect(osession.OutputToString()).To(Equal(uniqueString)) // Test podman start stop with overlay - osession = podmanTest.Podman([]string{"run", "--name", "overlay-foo", "--security-opt", "label=disable", - "--rootfs", rootfs + ":O", "echo", "hello"}) + osession = podmanTest.Podman([]string{ + "run", "--name", "overlay-foo", "--security-opt", "label=disable", + "--rootfs", rootfs + ":O", "echo", "hello", + }) osession.WaitWithDefaultTimeout() Expect(osession).Should(ExitCleanly()) Expect(osession.OutputToString()).To(Equal("hello")) @@ -335,15 +341,19 @@ var _ = Describe("Podman run", func() { Expect(osession).Should(ExitCleanly()) // Test --rootfs with an external overlay with --uidmap - osession = podmanTest.Podman([]string{"run", "--uidmap", "0:1234:5678", "--rm", "--security-opt", "label=disable", - "--rootfs", rootfs + ":O", "cat", "/proc/self/uid_map"}) + osession = podmanTest.Podman([]string{ + "run", "--uidmap", "0:1234:5678", "--rm", "--security-opt", "label=disable", + "--rootfs", rootfs + ":O", "cat", "/proc/self/uid_map", + }) osession.WaitWithDefaultTimeout() Expect(osession).Should(ExitCleanly()) Expect(osession.OutputToString()).To(Equal("0 1234 5678")) // Test --rootfs with an external overlay with --userns=auto - osession = podmanTest.Podman([]string{"run", "--userns=auto", "--rm", "--security-opt", "label=disable", - "--rootfs", rootfs + ":O", "cat", "/proc/self/uid_map"}) + osession = podmanTest.Podman([]string{ + "run", "--userns=auto", "--rm", "--security-opt", "label=disable", + "--rootfs", rootfs + ":O", "cat", "/proc/self/uid_map", + }) osession.WaitWithDefaultTimeout() Expect(osession).Should(ExitCleanly()) Expect(osession.OutputToString()).To(ContainSubstring("1024")) @@ -513,8 +523,6 @@ var _ = Describe("Podman run", func() { }) It("podman run security-opt unmask on /sys/fs/cgroup", func() { - - SkipIfCgroupV1("podman umask on /sys/fs/cgroup will fail with cgroups V1") SkipIfRootless("/sys/fs/cgroup rw access is needed") rwOnCgroups := "/sys/fs/cgroup cgroup2 rw" session := podmanTest.Podman([]string{"run", "--security-opt", "unmask=ALL", "--security-opt", "mask=/sys/fs/cgroup", ALPINE, "cat", "/proc/mounts"}) @@ -725,8 +733,6 @@ USER bin`, BB) }) It("podman run limits test", func() { - SkipIfRootlessCgroupsV1("Setting limits not supported on cgroupv1 for rootless users") - if !isRootless() { session := podmanTest.Podman([]string{"run", "--rm", "--ulimit", "rtprio=99", "--cap-add=sys_nice", fedoraMinimal, "cat", "/proc/self/sched"}) session.WaitWithDefaultTimeout() @@ -743,13 +749,6 @@ USER bin`, BB) Expect(session).Should(ExitCleanly()) Expect(session.OutputToString()).To(ContainSubstring("1024")) - if !CGROUPSV2 { - // --oom-kill-disable not supported on cgroups v2. - session = podmanTest.Podman([]string{"run", "--rm", "--oom-kill-disable=true", fedoraMinimal, "echo", "memory-hog"}) - session.WaitWithDefaultTimeout() - Expect(session).Should(ExitCleanly()) - } - session = podmanTest.Podman([]string{"run", "--rm", "--oom-score-adj=999", fedoraMinimal, "cat", "/proc/self/oom_score_adj"}) session.WaitWithDefaultTimeout() Expect(session).Should(ExitCleanly()) @@ -824,106 +823,59 @@ USER bin`, BB) }) It("podman run blkio-weight test", func() { - SkipIfRootlessCgroupsV1("Setting blkio-weight not supported on cgroupv1 for rootless users") SkipIfRootless("By default systemd doesn't delegate io to rootless users") - if CGROUPSV2 { - if _, err := os.Stat("/sys/fs/cgroup/io.stat"); os.IsNotExist(err) { - Skip("Kernel does not have io.stat") - } - if _, err := os.Stat("/sys/fs/cgroup/system.slice/io.bfq.weight"); os.IsNotExist(err) { - Skip("Kernel does not support BFQ IO scheduler") - } - session := podmanTest.Podman([]string{"run", "--rm", "--blkio-weight=15", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/io.bfq.weight"}) - session.WaitWithDefaultTimeout() - Expect(session).Should(ExitCleanly()) - // there was a documentation issue in the kernel that reported a different range [1-10000] for the io controller. - // older versions of crun/runc used it. For the time being allow both versions to pass the test. - // FIXME: drop "|51" once all the runtimes we test have the fix in place. - Expect(strings.Replace(session.OutputToString(), "default ", "", 1)).To(MatchRegexp("15|51")) - } else { - if _, err := os.Stat("/sys/fs/cgroup/blkio/blkio.weight"); os.IsNotExist(err) { - Skip("Kernel does not support blkio.weight") - } - session := podmanTest.Podman([]string{"run", "--rm", "--blkio-weight=15", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.weight"}) - session.WaitWithDefaultTimeout() - Expect(session).Should(ExitCleanly()) - Expect(session.OutputToString()).To(ContainSubstring("15")) + if _, err := os.Stat("/sys/fs/cgroup/io.stat"); os.IsNotExist(err) { + Skip("Kernel does not have io.stat") + } + if _, err := os.Stat("/sys/fs/cgroup/system.slice/io.bfq.weight"); os.IsNotExist(err) { + Skip("Kernel does not support BFQ IO scheduler") } + session := podmanTest.Podman([]string{"run", "--rm", "--blkio-weight=15", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/io.bfq.weight"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(ExitCleanly()) + // there was a documentation issue in the kernel that reported a different range [1-10000] for the io controller. + // older versions of crun/runc used it. For the time being allow both versions to pass the test. + // FIXME: drop "|51" once all the runtimes we test have the fix in place. + Expect(strings.Replace(session.OutputToString(), "default ", "", 1)).To(MatchRegexp("15|51")) }) It("podman run device-read-bps test", func() { SkipIfRootless("Setting device-read-bps not supported for rootless users") skipWithoutDevNullb0() - var session *PodmanSessionIntegration - - if CGROUPSV2 { - session = podmanTest.Podman([]string{"run", "--rm", "--device-read-bps=/dev/nullb0:1mb", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/io.max"}) - } else { - session = podmanTest.Podman([]string{"run", "--rm", "--device-read-bps=/dev/nullb0:1mb", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.read_bps_device"}) - } + session := podmanTest.Podman([]string{"run", "--rm", "--device-read-bps=/dev/nullb0:1mb", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/io.max"}) session.WaitWithDefaultTimeout() Expect(session).Should(ExitCleanly()) - if !CGROUPSV2 { // TODO: Test Simplification. For now, we only care about exit(0) w/ cgroupsv2 - Expect(session.OutputToString()).To(ContainSubstring("1048576")) - } }) It("podman run device-write-bps test", func() { SkipIfRootless("Setting device-write-bps not supported for rootless users") skipWithoutDevNullb0() - var session *PodmanSessionIntegration - - if CGROUPSV2 { - session = podmanTest.Podman([]string{"run", "--rm", "--device-write-bps=/dev/nullb0:1mb", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/io.max"}) - } else { - session = podmanTest.Podman([]string{"run", "--rm", "--device-write-bps=/dev/nullb0:1mb", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.write_bps_device"}) - } + session := podmanTest.Podman([]string{"run", "--rm", "--device-write-bps=/dev/nullb0:1mb", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/io.max"}) session.WaitWithDefaultTimeout() Expect(session).Should(ExitCleanly()) - if !CGROUPSV2 { // TODO: Test Simplification. For now, we only care about exit(0) w/ cgroupsv2 - Expect(session.OutputToString()).To(ContainSubstring("1048576")) - } }) It("podman run device-read-iops test", func() { SkipIfRootless("Setting device-read-iops not supported for rootless users") skipWithoutDevNullb0() - var session *PodmanSessionIntegration - - if CGROUPSV2 { - session = podmanTest.Podman([]string{"run", "--rm", "--device-read-iops=/dev/nullb0:100", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/io.max"}) - } else { - session = podmanTest.Podman([]string{"run", "--rm", "--device-read-iops=/dev/nullb0:100", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.read_iops_device"}) - } + session := podmanTest.Podman([]string{"run", "--rm", "--device-read-iops=/dev/nullb0:100", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/io.max"}) session.WaitWithDefaultTimeout() Expect(session).Should(ExitCleanly()) - if !CGROUPSV2 { // TODO: Test Simplification. For now, we only care about exit(0) w/ cgroupsv2 - Expect(session.OutputToString()).To(ContainSubstring("100")) - } }) It("podman run device-write-iops test", func() { SkipIfRootless("Setting device-write-iops not supported for rootless users") skipWithoutDevNullb0() - var session *PodmanSessionIntegration - - if CGROUPSV2 { - session = podmanTest.Podman([]string{"run", "--rm", "--device-write-iops=/dev/nullb0:100", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/io.max"}) - } else { - session = podmanTest.Podman([]string{"run", "--rm", "--device-write-iops=/dev/nullb0:100", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.write_iops_device"}) - } + session := podmanTest.Podman([]string{"run", "--rm", "--device-write-iops=/dev/nullb0:100", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/io.max"}) session.WaitWithDefaultTimeout() Expect(session).Should(ExitCleanly()) - if !CGROUPSV2 { // TODO: Test Simplification. For now, we only care about exit(0) w/ cgroupsv2 - Expect(session.OutputToString()).To(ContainSubstring("100")) - } }) It("podman run notify_socket", func() { @@ -1665,7 +1617,6 @@ VOLUME %s`, ALPINE, volPath, volPath) session.WaitWithDefaultTimeout() Expect(session).To(ExitWithError(125, "--no-hosts and --hosts-file cannot be set together")) }) - }) It("podman run with restart-policy always restarts containers", func() { @@ -1726,7 +1677,6 @@ VOLUME %s`, ALPINE, volPath, volPath) It("podman run with cgroups=split", func() { SkipIfNotSystemd(podmanTest.CgroupManager, "do not test --cgroups=split if not running on systemd") - SkipIfRootlessCgroupsV1("Disable cgroups not supported on cgroupv1 for rootless users") SkipIfRemote("--cgroups=split cannot be used in remote mode") checkLines := func(lines []string) { @@ -1736,14 +1686,6 @@ VOLUME %s`, ALPINE, volPath, volPath) if len(parts) < 2 { continue } - if !CGROUPSV2 { - // ignore unified on cgroup v1. - // both runc and crun do not set it. - // crun does not set named hierarchies. - if parts[1] == "" || strings.Contains(parts[1], "name=") { - continue - } - } if parts[2] == "/" { continue } @@ -1780,7 +1722,6 @@ VOLUME %s`, ALPINE, volPath, volPath) }) It("podman run with cgroups=disabled runs without cgroups", func() { - SkipIfRootlessCgroupsV1("Disable cgroups not supported on cgroupv1 for rootless users") // Only works on crun if !strings.Contains(podmanTest.OCIRuntime, "crun") { Skip("Test only works on crun") @@ -1814,7 +1755,6 @@ VOLUME %s`, ALPINE, volPath, volPath) }) It("podman run with cgroups=enabled makes cgroups", func() { - SkipIfRootlessCgroupsV1("Enable cgroups not supported on cgroupv1 for rootless users") // Only works on crun if !strings.Contains(podmanTest.OCIRuntime, "crun") { Skip("Test only works on crun") @@ -1822,7 +1762,7 @@ VOLUME %s`, ALPINE, volPath, volPath) curCgroupsBytes, err := os.ReadFile("/proc/self/cgroup") Expect(err).ToNot(HaveOccurred()) - var curCgroups = string(curCgroupsBytes) + curCgroups := string(curCgroupsBytes) GinkgoWriter.Printf("Output:\n%s\n", curCgroups) Expect(curCgroups).To(Not(Equal(""))) @@ -1839,7 +1779,7 @@ VOLUME %s`, ALPINE, volPath, volPath) ctrCgroupsBytes, err := os.ReadFile(fmt.Sprintf("/proc/%d/cgroup", pid)) Expect(err).ToNot(HaveOccurred()) - var ctrCgroups = string(ctrCgroupsBytes) + ctrCgroups := string(ctrCgroupsBytes) GinkgoWriter.Printf("Output\n:%s\n", ctrCgroups) Expect(curCgroups).To(Not(Equal(ctrCgroups))) }) @@ -1959,11 +1899,9 @@ VOLUME %s`, ALPINE, volPath, volPath) h := strconv.Itoa(t.Hour()) Expect(session.OutputToString()).To(ContainSubstring(z)) Expect(session.OutputToString()).To(ContainSubstring(h)) - }) It("podman run verify pids-limit", func() { - SkipIfCgroupV1("pids-limit not supported on cgroup V1") limit := "4321" session := podmanTest.Podman([]string{"run", "--pids-limit", limit, "--net=none", "--rm", ALPINE, "cat", "/sys/fs/cgroup/pids.max"}) session.WaitWithDefaultTimeout() @@ -2091,7 +2029,6 @@ WORKDIR /madethis`, BB) session.WaitWithDefaultTimeout() Expect(session).Should(ExitCleanly()) Expect(session.OutputToString()).To(ContainSubstring("mysecret")) - }) It("podman run --secret source=mysecret,type=mount", func() { @@ -2113,7 +2050,6 @@ WORKDIR /madethis`, BB) session.WaitWithDefaultTimeout() Expect(session).Should(ExitCleanly()) Expect(session.OutputToString()).To(ContainSubstring("mysecret")) - }) It("podman run --secret source=mysecret,type=mount with target", func() { @@ -2135,7 +2071,6 @@ WORKDIR /madethis`, BB) session.WaitWithDefaultTimeout() Expect(session).Should(ExitCleanly()) Expect(session.OutputToString()).To(ContainSubstring("mysecret_target")) - }) It("podman run --secret source=mysecret,type=mount with target at /tmp", func() { @@ -2157,7 +2092,6 @@ WORKDIR /madethis`, BB) session.WaitWithDefaultTimeout() Expect(session).Should(ExitCleanly()) Expect(session.OutputToString()).To(ContainSubstring("mysecret_target2")) - }) It("podman run --secret source=mysecret,type=env", func() { diff --git a/test/e2e/stats_test.go b/test/e2e/stats_test.go index 446cd21e8e0..6ee5f9ff389 100644 --- a/test/e2e/stats_test.go +++ b/test/e2e/stats_test.go @@ -15,14 +15,6 @@ import ( // TODO: we need to check the output. Currently, we only check the exit codes // which is not enough. var _ = Describe("Podman stats", func() { - - BeforeEach(func() { - SkipIfRootlessCgroupsV1("stats not supported on cgroupv1 for rootless users") - if isContainerized() { - SkipIfCgroupV1("stats not supported inside cgroupv1 container environment") - } - }) - It("podman stats with bogus container", func() { session := podmanTest.Podman([]string{"stats", "--no-stream", "123"}) session.WaitWithDefaultTimeout() diff --git a/test/e2e/systemd_test.go b/test/e2e/systemd_test.go index 05c46021e09..f2c50c3a986 100644 --- a/test/e2e/systemd_test.go +++ b/test/e2e/systemd_test.go @@ -15,7 +15,6 @@ import ( ) var _ = Describe("Podman systemd", func() { - It("podman run container with systemd PID1", func() { ctrName := "testSystemd" run := podmanTest.Podman([]string{"run", "--name", ctrName, "-t", "-i", "-d", SYSTEMD_IMAGE, "/sbin/init"}) @@ -42,10 +41,6 @@ var _ = Describe("Podman systemd", func() { Expect(conData).To(HaveLen(1)) Expect(conData[0].Config).To(HaveField("SystemdMode", true)) - // stats not supported w/ CGv1 rootless or containerized - if isCgroupsV1() && (isRootless() || isContainerized()) { - return - } stats := podmanTest.Podman([]string{"stats", "--no-stream", ctrName}) stats.WaitWithDefaultTimeout() Expect(stats).Should(ExitCleanly()) diff --git a/test/e2e/toolbox_test.go b/test/e2e/toolbox_test.go index b24650b56c6..ac2e67d293f 100644 --- a/test/e2e/toolbox_test.go +++ b/test/e2e/toolbox_test.go @@ -102,7 +102,6 @@ var _ = Describe("Toolbox-specific testing", func() { if podmanTest.RemoteTest { Skip("Shm size check does not work with a remote client") } - SkipIfRootlessCgroupsV1("Not supported for rootless + CgroupsV1") var session *PodmanSessionIntegration var cmd *exec.Cmd var hostShmSize, containerShmSize int diff --git a/test/e2e/update_test.go b/test/e2e/update_test.go index 167a63ab787..262987a7941 100644 --- a/test/e2e/update_test.go +++ b/test/e2e/update_test.go @@ -12,56 +12,7 @@ import ( ) var _ = Describe("Podman update", func() { - - It("podman update container all options v1", func() { - SkipIfCgroupV2("testing flags that only work in cgroup v1") - SkipIfRootless("many of these handlers are not enabled while rootless in CI") - session := podmanTest.Podman([]string{"run", "-dt", ALPINE}) - session.WaitWithDefaultTimeout() - Expect(session).Should(ExitCleanly()) - - ctrID := session.OutputToString() - - commonArgs := []string{ - "update", - "--cpus", "5", - "--cpuset-cpus", "0", - "--cpu-shares", "123", - "--cpuset-mems", "0", - "--memory", "1G", - "--memory-swap", "2G", - "--memory-reservation", "2G", - "--memory-swappiness", "50", - "--pids-limit", "123", ctrID} - - session = podmanTest.Podman(commonArgs) - session.WaitWithDefaultTimeout() - Expect(session).Should(ExitCleanly()) - - // checking cpu quota from --cpus - podmanTest.CheckFileInContainerSubstring(ctrID, "/sys/fs/cgroup/cpu/cpu.cfs_quota_us", "500000") - - // checking cpuset-cpus - podmanTest.CheckFileInContainer(ctrID, "/sys/fs/cgroup/cpuset/cpuset.cpus", "0") - - // checking cpuset-mems - podmanTest.CheckFileInContainer(ctrID, "/sys/fs/cgroup/cpuset/cpuset.mems", "0") - - // checking memory limit - podmanTest.CheckFileInContainerSubstring(ctrID, "/sys/fs/cgroup/memory/memory.limit_in_bytes", "1073741824") - - // checking memory-swap - podmanTest.CheckFileInContainerSubstring(ctrID, "/sys/fs/cgroup/memory/memory.memsw.limit_in_bytes", "2147483648") - - // checking cpu-shares - podmanTest.CheckFileInContainerSubstring(ctrID, "/sys/fs/cgroup/cpu/cpu.shares", "123") - - // checking pids-limit - podmanTest.CheckFileInContainerSubstring(ctrID, "/sys/fs/cgroup/pids/pids.max", "123") - }) - It("podman update container unspecified pid limit", func() { - SkipIfCgroupV1("testing flags that only work in cgroup v2") SkipIfRootless("many of these handlers are not enabled while rootless in CI") session := podmanTest.Podman([]string{"run", "-dt", "--pids-limit", "-1", ALPINE}) session.WaitWithDefaultTimeout() @@ -72,7 +23,8 @@ var _ = Describe("Podman update", func() { commonArgs := []string{ "update", "--cpus", "5", - ctrID} + ctrID, + } session = podmanTest.Podman(commonArgs) session.WaitWithDefaultTimeout() @@ -85,7 +37,6 @@ var _ = Describe("Podman update", func() { }) It("podman update container all options v2", func() { - SkipIfCgroupV1("testing flags that only work in cgroup v2") SkipIfRootless("many of these handlers are not enabled while rootless in CI") skipWithoutDevNullb0() session := podmanTest.Podman([]string{"run", "-dt", ALPINE}) @@ -109,7 +60,8 @@ var _ = Describe("Podman update", func() { "--device-read-iops", "/dev/nullb0:1000", "--device-write-iops", "/dev/nullb0:1000", "--pids-limit", "123", - ctrID} + ctrID, + } session = podmanTest.Podman(commonArgs) session.WaitWithDefaultTimeout() @@ -174,7 +126,6 @@ var _ = Describe("Podman update", func() { }) It("podman update persists changes", func() { - SkipIfCgroupV1("testing flags that only work in cgroup v2") SkipIfRootless("many of these handlers are not enabled while rootless in CI") memoryInspect := ".HostConfig.Memory" diff --git a/test/system/030-run.bats b/test/system/030-run.bats index 70840d92aa3..692843b1e22 100644 --- a/test/system/030-run.bats +++ b/test/system/030-run.bats @@ -122,7 +122,6 @@ EOF # bats test_tags=ci:parallel @test "podman run - uidmapping has no /sys/kernel mounts" { - skip_if_cgroupsv1 "run --uidmap fails on cgroups v1 (issue 15025, wontfix)" skip_if_rootless "cannot umount as rootless" run_podman run --rm --uidmap 0:100:10000 $IMAGE mount @@ -1081,7 +1080,6 @@ EOF # rhbz#1902979 : podman run fails to update /etc/hosts when --uidmap is provided # bats test_tags=ci:parallel @test "podman run update /etc/hosts" { - skip_if_cgroupsv1 "run --uidmap fails on cgroups v1 (issue 15025, wontfix)" HOST=$(random_string 25) run_podman run --uidmap 0:10001:10002 --rm --hostname ${HOST} $IMAGE grep ${HOST} /etc/hosts is "${lines[0]}" ".*${HOST}.*" @@ -1443,21 +1441,14 @@ EOF # bats test_tags=ci:parallel @test "podman run --net=host --cgroupns=host with read only cgroupfs" { - skip_if_rootless_cgroupsv1 - if is_cgroupsv1; then - # verify that the memory controller is mounted read-only - run_podman run --net=host --cgroupns=host --rm $IMAGE cat /proc/self/mountinfo - assert "$output" =~ "/sys/fs/cgroup/memory ro.* cgroup cgroup" - else - # verify that the last /sys/fs/cgroup mount is read-only - run_podman run --net=host --cgroupns=host --rm $IMAGE sh -c "grep ' / /sys/fs/cgroup ' /proc/self/mountinfo | tail -n 1" - assert "$output" =~ "/sys/fs/cgroup ro" + # verify that the last /sys/fs/cgroup mount is read-only + run_podman run --net=host --cgroupns=host --rm $IMAGE sh -c "grep ' / /sys/fs/cgroup ' /proc/self/mountinfo | tail -n 1" + assert "$output" =~ "/sys/fs/cgroup ro" - # verify that it works also with a cgroupns - run_podman run --net=host --cgroupns=private --rm $IMAGE sh -c "grep ' / /sys/fs/cgroup ' /proc/self/mountinfo | tail -n 1" - assert "$output" =~ "/sys/fs/cgroup ro" - fi + # verify that it works also with a cgroupns + run_podman run --net=host --cgroupns=private --rm $IMAGE sh -c "grep ' / /sys/fs/cgroup ' /proc/self/mountinfo | tail -n 1" + assert "$output" =~ "/sys/fs/cgroup ro" } # bats test_tags=ci:parallel diff --git a/test/system/170-run-userns.bats b/test/system/170-run-userns.bats index b56e2c12e4e..267358fd149 100644 --- a/test/system/170-run-userns.bats +++ b/test/system/170-run-userns.bats @@ -33,7 +33,6 @@ function _require_crun() { # bats test_tags=ci:parallel @test "podman --group-add without keep-groups while in a userns" { - skip_if_cgroupsv1 "run --uidmap fails on cgroups v1 (issue 15025, wontfix)" skip_if_rootless "chroot is not allowed in rootless mode" skip_if_remote "--group-add keep-groups not supported in remote mode" run chroot --groups 1234,5678 / ${PODMAN} run --rm --uidmap 0:200000:5000 --group-add 457 $IMAGE id @@ -42,7 +41,6 @@ function _require_crun() { # bats test_tags=ci:parallel @test "rootful pod with custom ID mapping" { - skip_if_cgroupsv1 "run --uidmap fails on cgroups v1 (issue 15025, wontfix)" skip_if_rootless "does not work rootless - rootful feature" random_pod_name=p_$(safename) run_podman pod create --uidmap 0:200000:5000 --name=$random_pod_name diff --git a/test/system/200-pod.bats b/test/system/200-pod.bats index 1887e68ec45..f59223cd250 100644 --- a/test/system/200-pod.bats +++ b/test/system/200-pod.bats @@ -535,7 +535,6 @@ spec: @test "pod resource limits" { skip_if_remote "resource limits only implemented on non-remote" skip_if_rootless "resource limits only work with root" - skip_if_cgroupsv1 "resource limits only meaningful on cgroups V2" # create loopback device lofile=${PODMAN_TMPDIR}/disk.img @@ -762,7 +761,6 @@ function thingy_with_unique_id() { # bats test_tags=ci:parallel @test "podman pod cleans cgroup and keeps limits" { skip_if_remote "we cannot check cgroup settings" - skip_if_rootless_cgroupsv1 "rootless cannot use cgroups on v1" for infra in true false; do run_podman pod create --infra=$infra --memory=256M diff --git a/test/system/250-systemd.bats b/test/system/250-systemd.bats index 89b8c80aae6..5cadd34becc 100644 --- a/test/system/250-systemd.bats +++ b/test/system/250-systemd.bats @@ -316,13 +316,6 @@ LISTEN_FDNAMES=listen_fdnames" | sort) run_podman rm $cname } -@test "podman --systemd fails on cgroup v1 with a private cgroupns" { - skip_if_cgroupsv2 - - run_podman 126 run --systemd=always --cgroupns=private $IMAGE true - assert "$output" =~ ".*cgroup namespace is not supported with cgroup v1 and systemd mode" -} - # https://github.com/containers/podman/issues/13153 @test "podman rootless-netns processes should be in different cgroup" { is_rootless || skip "only meaningful for rootless" diff --git a/test/system/252-quadlet.bats b/test/system/252-quadlet.bats index 901295db9ec..bbcf502c819 100644 --- a/test/system/252-quadlet.bats +++ b/test/system/252-quadlet.bats @@ -20,7 +20,6 @@ function start_time() { function setup() { skip_if_remote "quadlet tests are meaningless over remote" - skip_if_rootless_cgroupsv1 "Can't use --cgroups=split w/ CGv1 (issue 17456, wontfix)" skip_if_journald_unavailable "Needed for RHEL. FIXME: we might be able to re-enable a subset of tests." test -x "$QUADLET" || die "Cannot run quadlet tests without executable \$QUADLET ($QUADLET)" diff --git a/test/system/253-podman-quadlet.bats b/test/system/253-podman-quadlet.bats index 892a0c6fc1a..775532abaaa 100644 --- a/test/system/253-podman-quadlet.bats +++ b/test/system/253-podman-quadlet.bats @@ -10,7 +10,6 @@ load helpers.systemd function setup() { skip_if_remote "podman quadlet is not implemented for remote setup yet" - skip_if_rootless_cgroupsv1 "Can't use --cgroups=split w/ CGv1 (issue 17456, wontfix)" skip_if_journald_unavailable "Needed for RHEL. FIXME: we might be able to re-enable a subset of tests." test -x "$QUADLET" || die "Cannot run quadlet tests without executable \$QUADLET ($QUADLET)" diff --git a/test/system/400-unprivileged-access.bats b/test/system/400-unprivileged-access.bats index a253ad5cc02..9f89dad83e3 100644 --- a/test/system/400-unprivileged-access.bats +++ b/test/system/400-unprivileged-access.bats @@ -7,7 +7,6 @@ load helpers @test "podman container storage is not accessible by unprivileged users" { - skip_if_cgroupsv1 "run --uidmap fails on cgroups v1 (issue 15025, wontfix)" skip_if_rootless "test meaningless without suid" skip_if_remote diff --git a/test/system/410-selinux.bats b/test/system/410-selinux.bats index f360e91446a..e0e1c867f8f 100644 --- a/test/system/410-selinux.bats +++ b/test/system/410-selinux.bats @@ -152,10 +152,6 @@ function check_label() { @test "podman selinux: shared context in (some) namespaces" { skip_if_no_selinux - # rootless users have no usable cgroups with cgroupsv1, so containers - # must use a pid namespace and not join an existing one. - skip_if_rootless_cgroupsv1 - if [[ $(podman_runtime) == "runc" ]]; then skip "some sort of runc bug, not worth fixing (issue 11784, wontfix)" fi diff --git a/test/system/420-cgroups.bats b/test/system/420-cgroups.bats index d0bfd36b664..512dec89e14 100644 --- a/test/system/420-cgroups.bats +++ b/test/system/420-cgroups.bats @@ -9,8 +9,6 @@ load helpers @test "podman run, preserves initial --cgroup-manager" { skip_if_remote "podman-remote does not support --cgroup-manager" - skip_if_rootless_cgroupsv1 - # Find out our default cgroup manager, and from that, get the non-default run_podman info --format '{{.Host.CgroupManager}}' case "$output" in @@ -41,7 +39,6 @@ load helpers # bats test_tags=ci:parallel @test "podman run --cgroups=disabled keeps the current cgroup" { skip_if_remote "podman-remote does not support --cgroups=disabled" - skip_if_rootless_cgroupsv1 runtime=$(podman_runtime) if [[ $runtime != "crun" ]]; then skip "runtime is $runtime; --cgroups=disabled requires crun" diff --git a/test/system/500-networking.bats b/test/system/500-networking.bats index 7fc58713ea6..c96122bf4fe 100644 --- a/test/system/500-networking.bats +++ b/test/system/500-networking.bats @@ -114,7 +114,6 @@ load helpers.network # Issue #5466 - port-forwarding doesn't work with this option and -d # FIXME: random_rfc1918_subnet is not parallel-safe @test "podman networking: port with --userns=keep-id for rootless or --uidmap=* for rootful" { - skip_if_cgroupsv1 "run --uidmap fails on cgroups v1 (issue 15025, wontfix)" for cidr in "" "$(random_rfc1918_subnet).0/24"; do myport=$(random_free_port 52000-52999) if [[ -z $cidr ]]; then @@ -878,7 +877,6 @@ EOF # bats test_tags=ci:parallel @test "podman run /etc/* permissions" { - skip_if_cgroupsv1 "run --uidmap fails on cgroups v1 (issue 15025, wontfix)" userns="--userns=keep-id" if ! is_rootless; then userns="--uidmap=0:1111111:65536 --gidmap=0:1111111:65536" @@ -992,8 +990,6 @@ EOF # Test for https://github.com/containers/podman/issues/18615 # CANNOT BE PARALLELIZED due to strict checking of /run/netns @test "podman network cleanup --userns + --restart" { - skip_if_cgroupsv1 "run --uidmap fails on cgroups v1 (issue 15025, wontfix)" - local net1=net-a-$(safename) # use /29 subnet to limit available ip space, a 29 gives 5 usable addresses (6 - 1 for the gw) local subnet="$(random_rfc1918_subnet).0/29" diff --git a/test/system/600-completion.bats b/test/system/600-completion.bats index 0afc1660789..df07fa8cd88 100644 --- a/test/system/600-completion.bats +++ b/test/system/600-completion.bats @@ -18,17 +18,6 @@ function setup() { basic_setup } -# Returns true if we are able to podman-pause -function _can_pause() { - # Even though we're just trying completion, not an actual unpause, - # podman barfs with: - # Error: unpause is not supported for cgroupv1 rootless containers - if is_rootless && is_cgroupsv1; then - return 1 - fi - return 0 -} - function check_shell_completion() { local count=0 @@ -98,11 +87,6 @@ function check_shell_completion() { ;; *CONTAINER*) - # podman unpause fails early on rootless cgroupsv1 - if [[ $cmd = "unpause" ]] && ! _can_pause; then - continue 2 - fi - name=$random_container_name # special case podman cp suggest containers names with a colon if [[ $cmd = "cp" ]]; then @@ -281,9 +265,7 @@ function _check_no_suggestions() { run_podman create --name created-$random_container_name $IMAGE run_podman run --name running-$random_container_name -d $IMAGE top run_podman run --name pause-$random_container_name -d $IMAGE top - if _can_pause; then - run_podman pause pause-$random_container_name - fi + run_podman pause pause-$random_container_name run_podman run --name exited-$random_container_name -d $IMAGE echo exited # create pods for each state diff --git a/test/system/helpers.bash b/test/system/helpers.bash index 5abfe872d37..6d80681066f 100644 --- a/test/system/helpers.bash +++ b/test/system/helpers.bash @@ -757,11 +757,6 @@ function is_remote() { [[ "$PODMAN" =~ -remote ]] } -function is_cgroupsv1() { - # WARNING: This will break if there's ever a cgroups v3 - ! is_cgroupsv2 -} - # True if cgroups v2 are enabled function is_cgroupsv2() { cgroup_type=$(stat -f -c %T /sys/fs/cgroup) @@ -938,36 +933,6 @@ function skip_if_no_selinux() { fi } -####################### -# skip_if_cgroupsv1 # ...with an optional message -####################### -function skip_if_cgroupsv1() { - if ! is_cgroupsv2; then - skip "${1:-test requires cgroupsv2}" - fi -} - -####################### -# skip_if_cgroupsv2 # ...with an optional message -####################### -function skip_if_cgroupsv2() { - if is_cgroupsv2; then - skip "${1:-test requires cgroupsv1}" - fi -} - -###################### -# skip_if_rootless_cgroupsv1 # ...with an optional message -###################### -function skip_if_rootless_cgroupsv1() { - if is_rootless; then - if ! is_cgroupsv2; then - local msg=$(_add_label_if_missing "$1" "rootless cgroupvs1") - skip "${msg:-not supported as rootless under cgroupsv1}" - fi - fi -} - ################################## # skip_if_journald_unavailable # rhbz#1895105: rootless journald permissions ################################## diff --git a/vendor/github.com/containerd/stargz-snapshotter/estargz/build.go b/vendor/github.com/containerd/stargz-snapshotter/estargz/build.go index 8b804b7dde4..16bdc90b202 100644 --- a/vendor/github.com/containerd/stargz-snapshotter/estargz/build.go +++ b/vendor/github.com/containerd/stargz-snapshotter/estargz/build.go @@ -42,6 +42,8 @@ import ( "golang.org/x/sync/errgroup" ) +type GzipHelperFunc func(io.Reader) (io.ReadCloser, error) + type options struct { chunkSize int compressionLevel int @@ -50,6 +52,7 @@ type options struct { compression Compression ctx context.Context minChunkSize int + gzipHelperFunc GzipHelperFunc } type Option func(o *options) error @@ -127,6 +130,18 @@ func WithMinChunkSize(minChunkSize int) Option { } } +// WithGzipHelperFunc option specifies a custom function to decompress gzip-compressed layers. +// When a gzip-compressed layer is detected, this function will be used instead of the +// Go standard library gzip decompression for better performance. +// The function should take an io.Reader as input and return an io.ReadCloser. +// If nil, the Go standard library gzip.NewReader will be used. +func WithGzipHelperFunc(gzipHelperFunc GzipHelperFunc) Option { + return func(o *options) error { + o.gzipHelperFunc = gzipHelperFunc + return nil + } +} + // Blob is an eStargz blob. type Blob struct { io.ReadCloser @@ -186,7 +201,7 @@ func Build(tarBlob *io.SectionReader, opt ...Option) (_ *Blob, rErr error) { rErr = fmt.Errorf("error from context %q: %w", cErr, rErr) } }() - tarBlob, err := decompressBlob(tarBlob, layerFiles) + tarBlob, err := decompressBlob(tarBlob, layerFiles, opts.gzipHelperFunc) if err != nil { return nil, err } @@ -649,7 +664,7 @@ func (cr *countReadSeeker) currentPos() int64 { return *cr.cPos } -func decompressBlob(org *io.SectionReader, tmp *tempFiles) (*io.SectionReader, error) { +func decompressBlob(org *io.SectionReader, tmp *tempFiles, gzipHelperFunc GzipHelperFunc) (*io.SectionReader, error) { if org.Size() < 4 { return org, nil } @@ -660,7 +675,13 @@ func decompressBlob(org *io.SectionReader, tmp *tempFiles) (*io.SectionReader, e var dR io.Reader if bytes.Equal([]byte{0x1F, 0x8B, 0x08}, src[:3]) { // gzip - dgR, err := gzip.NewReader(io.NewSectionReader(org, 0, org.Size())) + var dgR io.ReadCloser + var err error + if gzipHelperFunc != nil { + dgR, err = gzipHelperFunc(io.NewSectionReader(org, 0, org.Size())) + } else { + dgR, err = gzip.NewReader(io.NewSectionReader(org, 0, org.Size())) + } if err != nil { return nil, err } diff --git a/vendor/github.com/containerd/stargz-snapshotter/estargz/estargz.go b/vendor/github.com/containerd/stargz-snapshotter/estargz/estargz.go index f4d55465584..ff91a37add5 100644 --- a/vendor/github.com/containerd/stargz-snapshotter/estargz/estargz.go +++ b/vendor/github.com/containerd/stargz-snapshotter/estargz/estargz.go @@ -307,6 +307,15 @@ func (r *Reader) initFields() error { } } + if len(r.m) == 0 { + r.m[""] = &TOCEntry{ + Name: "", + Type: "dir", + Mode: 0755, + NumLink: 1, + } + } + return nil } diff --git a/vendor/github.com/containerd/stargz-snapshotter/estargz/testutil.go b/vendor/github.com/containerd/stargz-snapshotter/estargz/testutil.go index a8dcdb868e6..ff165e090e3 100644 --- a/vendor/github.com/containerd/stargz-snapshotter/estargz/testutil.go +++ b/vendor/github.com/containerd/stargz-snapshotter/estargz/testutil.go @@ -38,7 +38,6 @@ import ( "reflect" "sort" "strings" - "testing" "time" "github.com/containerd/stargz-snapshotter/estargz/errorutil" @@ -49,16 +48,48 @@ import ( // TestingController is Compression with some helper methods necessary for testing. type TestingController interface { Compression - TestStreams(t *testing.T, b []byte, streams []int64) - DiffIDOf(*testing.T, []byte) string + TestStreams(t TestingT, b []byte, streams []int64) + DiffIDOf(TestingT, []byte) string String() string } +// TestingT is the minimal set of testing.T required to run the +// tests defined in CompressionTestSuite. This interface exists to prevent +// leaking the testing package from being exposed outside tests. +type TestingT interface { + Errorf(format string, args ...any) + FailNow() + Failed() bool + Fatal(args ...any) + Fatalf(format string, args ...any) + Logf(format string, args ...any) + Parallel() +} + +// Runner allows running subtests of TestingT. This exists instead of adding +// a Run method to TestingT interface because the Run implementation of +// testing.T would not satisfy the interface. +type Runner func(t TestingT, name string, fn func(t TestingT)) + +type TestRunner struct { + TestingT + Runner Runner +} + +func (r *TestRunner) Run(name string, run func(*TestRunner)) { + r.Runner(r.TestingT, name, func(t TestingT) { + run(&TestRunner{TestingT: t, Runner: r.Runner}) + }) +} + // CompressionTestSuite tests this pkg with controllers can build valid eStargz blobs and parse them. -func CompressionTestSuite(t *testing.T, controllers ...TestingControllerFactory) { - t.Run("testBuild", func(t *testing.T) { t.Parallel(); testBuild(t, controllers...) }) - t.Run("testDigestAndVerify", func(t *testing.T) { t.Parallel(); testDigestAndVerify(t, controllers...) }) - t.Run("testWriteAndOpen", func(t *testing.T) { t.Parallel(); testWriteAndOpen(t, controllers...) }) +func CompressionTestSuite(t *TestRunner, controllers ...TestingControllerFactory) { + t.Run("testBuild", func(t *TestRunner) { t.Parallel(); testBuild(t, controllers...) }) + t.Run("testDigestAndVerify", func(t *TestRunner) { + t.Parallel() + testDigestAndVerify(t, controllers...) + }) + t.Run("testWriteAndOpen", func(t *TestRunner) { t.Parallel(); testWriteAndOpen(t, controllers...) }) } type TestingControllerFactory func() TestingController @@ -79,7 +110,7 @@ var allowedPrefix = [4]string{"", "./", "/", "../"} // testBuild tests the resulting stargz blob built by this pkg has the same // contents as the normal stargz blob. -func testBuild(t *testing.T, controllers ...TestingControllerFactory) { +func testBuild(t *TestRunner, controllers ...TestingControllerFactory) { tests := []struct { name string chunkSize int @@ -165,7 +196,7 @@ func testBuild(t *testing.T, controllers ...TestingControllerFactory) { prefix := prefix for _, minChunkSize := range tt.minChunkSize { minChunkSize := minChunkSize - t.Run(tt.name+"-"+fmt.Sprintf("compression=%v,prefix=%q,src=%d,format=%s,minChunkSize=%d", newCL(), prefix, srcCompression, srcTarFormat, minChunkSize), func(t *testing.T) { + t.Run(tt.name+"-"+fmt.Sprintf("compression=%v,prefix=%q,src=%d,format=%s,minChunkSize=%d", newCL(), prefix, srcCompression, srcTarFormat, minChunkSize), func(t *TestRunner) { tarBlob := buildTar(t, tt.in, prefix, srcTarFormat) // Test divideEntries() entries, err := sortEntries(tarBlob, nil, nil) // identical order @@ -265,7 +296,7 @@ func testBuild(t *testing.T, controllers ...TestingControllerFactory) { } } -func isSameTarGz(t *testing.T, cla TestingController, a []byte, clb TestingController, b []byte) bool { +func isSameTarGz(t TestingT, cla TestingController, a []byte, clb TestingController, b []byte) bool { aGz, err := cla.Reader(bytes.NewReader(a)) if err != nil { t.Fatalf("failed to read A") @@ -325,7 +356,7 @@ func isSameTarGz(t *testing.T, cla TestingController, a []byte, clb TestingContr return true } -func isSameVersion(t *testing.T, cla TestingController, a []byte, clb TestingController, b []byte) bool { +func isSameVersion(t TestingT, cla TestingController, a []byte, clb TestingController, b []byte) bool { aJTOC, _, err := parseStargz(io.NewSectionReader(bytes.NewReader(a), 0, int64(len(a))), cla) if err != nil { t.Fatalf("failed to parse A: %v", err) @@ -339,7 +370,7 @@ func isSameVersion(t *testing.T, cla TestingController, a []byte, clb TestingCon return aJTOC.Version == bJTOC.Version } -func isSameEntries(t *testing.T, a, b *Reader) bool { +func isSameEntries(t TestingT, a, b *Reader) bool { aroot, ok := a.Lookup("") if !ok { t.Fatalf("failed to get root of A") @@ -353,7 +384,7 @@ func isSameEntries(t *testing.T, a, b *Reader) bool { return contains(t, aEntry, bEntry) && contains(t, bEntry, aEntry) } -func compressBlob(t *testing.T, src *io.SectionReader, srcCompression int) *io.SectionReader { +func compressBlob(t TestingT, src *io.SectionReader, srcCompression int) *io.SectionReader { buf := new(bytes.Buffer) var w io.WriteCloser var err error @@ -387,7 +418,7 @@ type stargzEntry struct { // contains checks if all child entries in "b" are also contained in "a". // This function also checks if the files/chunks contain the same contents among "a" and "b". -func contains(t *testing.T, a, b stargzEntry) bool { +func contains(t TestingT, a, b stargzEntry) bool { ae, ar := a.e, a.r be, br := b.e, b.r t.Logf("Comparing: %q vs %q", ae.Name, be.Name) @@ -498,7 +529,7 @@ func equalEntry(a, b *TOCEntry) bool { a.Digest == b.Digest } -func readOffset(t *testing.T, r *io.SectionReader, offset int64, e stargzEntry) ([]byte, int64, bool) { +func readOffset(t TestingT, r *io.SectionReader, offset int64, e stargzEntry) ([]byte, int64, bool) { ce, ok := e.r.ChunkEntryForOffset(e.e.Name, offset) if !ok { return nil, 0, false @@ -517,7 +548,7 @@ func readOffset(t *testing.T, r *io.SectionReader, offset int64, e stargzEntry) return data[:n], offset + ce.ChunkSize, true } -func dumpTOCJSON(t *testing.T, tocJSON *JTOC) string { +func dumpTOCJSON(t TestingT, tocJSON *JTOC) string { jtocData, err := json.Marshal(*tocJSON) if err != nil { t.Fatalf("failed to marshal TOC JSON: %v", err) @@ -531,20 +562,19 @@ func dumpTOCJSON(t *testing.T, tocJSON *JTOC) string { const chunkSize = 3 -// type check func(t *testing.T, sgzData []byte, tocDigest digest.Digest, dgstMap map[string]digest.Digest, compressionLevel int) -type check func(t *testing.T, sgzData []byte, tocDigest digest.Digest, dgstMap map[string]digest.Digest, controller TestingController, newController TestingControllerFactory) +type check func(t *TestRunner, sgzData []byte, tocDigest digest.Digest, dgstMap map[string]digest.Digest, controller TestingController, newController TestingControllerFactory) // testDigestAndVerify runs specified checks against sample stargz blobs. -func testDigestAndVerify(t *testing.T, controllers ...TestingControllerFactory) { +func testDigestAndVerify(t *TestRunner, controllers ...TestingControllerFactory) { tests := []struct { name string - tarInit func(t *testing.T, dgstMap map[string]digest.Digest) (blob []tarEntry) + tarInit func(t TestingT, dgstMap map[string]digest.Digest) (blob []tarEntry) checks []check minChunkSize []int }{ { name: "no-regfile", - tarInit: func(t *testing.T, dgstMap map[string]digest.Digest) (blob []tarEntry) { + tarInit: func(t TestingT, dgstMap map[string]digest.Digest) (blob []tarEntry) { return tarOf( dir("test/"), ) @@ -559,7 +589,7 @@ func testDigestAndVerify(t *testing.T, controllers ...TestingControllerFactory) }, { name: "small-files", - tarInit: func(t *testing.T, dgstMap map[string]digest.Digest) (blob []tarEntry) { + tarInit: func(t TestingT, dgstMap map[string]digest.Digest) (blob []tarEntry) { return tarOf( regDigest(t, "baz.txt", "", dgstMap), regDigest(t, "foo.txt", "a", dgstMap), @@ -583,7 +613,7 @@ func testDigestAndVerify(t *testing.T, controllers ...TestingControllerFactory) }, { name: "big-files", - tarInit: func(t *testing.T, dgstMap map[string]digest.Digest) (blob []tarEntry) { + tarInit: func(t TestingT, dgstMap map[string]digest.Digest) (blob []tarEntry) { return tarOf( regDigest(t, "baz.txt", "bazbazbazbazbazbazbaz", dgstMap), regDigest(t, "foo.txt", "a", dgstMap), @@ -607,7 +637,7 @@ func testDigestAndVerify(t *testing.T, controllers ...TestingControllerFactory) { name: "with-non-regfiles", minChunkSize: []int{0, 64000}, - tarInit: func(t *testing.T, dgstMap map[string]digest.Digest) (blob []tarEntry) { + tarInit: func(t TestingT, dgstMap map[string]digest.Digest) (blob []tarEntry) { return tarOf( regDigest(t, "baz.txt", "bazbazbazbazbazbazbaz", dgstMap), regDigest(t, "foo.txt", "a", dgstMap), @@ -654,7 +684,7 @@ func testDigestAndVerify(t *testing.T, controllers ...TestingControllerFactory) srcTarFormat := srcTarFormat for _, minChunkSize := range tt.minChunkSize { minChunkSize := minChunkSize - t.Run(tt.name+"-"+fmt.Sprintf("compression=%v,prefix=%q,format=%s,minChunkSize=%d", newCL(), prefix, srcTarFormat, minChunkSize), func(t *testing.T) { + t.Run(tt.name+"-"+fmt.Sprintf("compression=%v,prefix=%q,format=%s,minChunkSize=%d", newCL(), prefix, srcTarFormat, minChunkSize), func(t *TestRunner) { // Get original tar file and chunk digests dgstMap := make(map[string]digest.Digest) tarBlob := buildTar(t, tt.tarInit(t, dgstMap), prefix, srcTarFormat) @@ -690,7 +720,7 @@ func testDigestAndVerify(t *testing.T, controllers ...TestingControllerFactory) // checkStargzTOC checks the TOC JSON of the passed stargz has the expected // digest and contains valid chunks. It walks all entries in the stargz and // checks all chunk digests stored to the TOC JSON match the actual contents. -func checkStargzTOC(t *testing.T, sgzData []byte, tocDigest digest.Digest, dgstMap map[string]digest.Digest, controller TestingController, newController TestingControllerFactory) { +func checkStargzTOC(t *TestRunner, sgzData []byte, tocDigest digest.Digest, dgstMap map[string]digest.Digest, controller TestingController, newController TestingControllerFactory) { sgz, err := Open( io.NewSectionReader(bytes.NewReader(sgzData), 0, int64(len(sgzData))), WithDecompressors(controller), @@ -801,7 +831,7 @@ func checkStargzTOC(t *testing.T, sgzData []byte, tocDigest digest.Digest, dgstM // checkVerifyTOC checks the verification works for the TOC JSON of the passed // stargz. It walks all entries in the stargz and checks the verifications for // all chunks work. -func checkVerifyTOC(t *testing.T, sgzData []byte, tocDigest digest.Digest, dgstMap map[string]digest.Digest, controller TestingController, newController TestingControllerFactory) { +func checkVerifyTOC(t *TestRunner, sgzData []byte, tocDigest digest.Digest, dgstMap map[string]digest.Digest, controller TestingController, newController TestingControllerFactory) { sgz, err := Open( io.NewSectionReader(bytes.NewReader(sgzData), 0, int64(len(sgzData))), WithDecompressors(controller), @@ -882,9 +912,9 @@ func checkVerifyTOC(t *testing.T, sgzData []byte, tocDigest digest.Digest, dgstM // checkVerifyInvalidTOCEntryFail checks if misconfigured TOC JSON can be // detected during the verification and the verification returns an error. func checkVerifyInvalidTOCEntryFail(filename string) check { - return func(t *testing.T, sgzData []byte, tocDigest digest.Digest, dgstMap map[string]digest.Digest, controller TestingController, newController TestingControllerFactory) { + return func(t *TestRunner, sgzData []byte, tocDigest digest.Digest, dgstMap map[string]digest.Digest, controller TestingController, newController TestingControllerFactory) { funcs := map[string]rewriteFunc{ - "lost digest in a entry": func(t *testing.T, toc *JTOC, sgz *io.SectionReader) { + "lost digest in a entry": func(t TestingT, toc *JTOC, sgz *io.SectionReader) { var found bool for _, e := range toc.Entries { if cleanEntryName(e.Name) == filename { @@ -902,7 +932,7 @@ func checkVerifyInvalidTOCEntryFail(filename string) check { t.Fatalf("rewrite target not found") } }, - "duplicated entry offset": func(t *testing.T, toc *JTOC, sgz *io.SectionReader) { + "duplicated entry offset": func(t TestingT, toc *JTOC, sgz *io.SectionReader) { var ( sampleEntry *TOCEntry targetEntry *TOCEntry @@ -929,7 +959,7 @@ func checkVerifyInvalidTOCEntryFail(filename string) check { } for name, rFunc := range funcs { - t.Run(name, func(t *testing.T) { + t.Run(name, func(t *TestRunner) { newSgz, newTocDigest := rewriteTOCJSON(t, io.NewSectionReader(bytes.NewReader(sgzData), 0, int64(len(sgzData))), rFunc, controller) buf := new(bytes.Buffer) if _, err := io.Copy(buf, newSgz); err != nil { @@ -958,7 +988,7 @@ func checkVerifyInvalidTOCEntryFail(filename string) check { // checkVerifyInvalidStargzFail checks if the verification detects that the // given stargz file doesn't match to the expected digest and returns error. func checkVerifyInvalidStargzFail(invalid *io.SectionReader) check { - return func(t *testing.T, sgzData []byte, tocDigest digest.Digest, dgstMap map[string]digest.Digest, controller TestingController, newController TestingControllerFactory) { + return func(t *TestRunner, sgzData []byte, tocDigest digest.Digest, dgstMap map[string]digest.Digest, controller TestingController, newController TestingControllerFactory) { cl := newController() rc, err := Build(invalid, WithChunkSize(chunkSize), WithCompression(cl)) if err != nil { @@ -990,7 +1020,7 @@ func checkVerifyInvalidStargzFail(invalid *io.SectionReader) check { // checkVerifyBrokenContentFail checks if the verifier detects broken contents // that doesn't match to the expected digest and returns error. func checkVerifyBrokenContentFail(filename string) check { - return func(t *testing.T, sgzData []byte, tocDigest digest.Digest, dgstMap map[string]digest.Digest, controller TestingController, newController TestingControllerFactory) { + return func(t *TestRunner, sgzData []byte, tocDigest digest.Digest, dgstMap map[string]digest.Digest, controller TestingController, newController TestingControllerFactory) { // Parse stargz file sgz, err := Open( io.NewSectionReader(bytes.NewReader(sgzData), 0, int64(len(sgzData))), @@ -1047,9 +1077,9 @@ func chunkID(name string, offset, size int64) string { return fmt.Sprintf("%s-%d-%d", cleanEntryName(name), offset, size) } -type rewriteFunc func(t *testing.T, toc *JTOC, sgz *io.SectionReader) +type rewriteFunc func(t TestingT, toc *JTOC, sgz *io.SectionReader) -func rewriteTOCJSON(t *testing.T, sgz *io.SectionReader, rewrite rewriteFunc, controller TestingController) (newSgz io.Reader, tocDigest digest.Digest) { +func rewriteTOCJSON(t TestingT, sgz *io.SectionReader, rewrite rewriteFunc, controller TestingController) (newSgz io.Reader, tocDigest digest.Digest) { decodedJTOC, jtocOffset, err := parseStargz(sgz, controller) if err != nil { t.Fatalf("failed to extract TOC JSON: %v", err) @@ -1120,7 +1150,7 @@ func parseStargz(sgz *io.SectionReader, controller TestingController) (decodedJT return decodedJTOC, tocOffset, nil } -func testWriteAndOpen(t *testing.T, controllers ...TestingControllerFactory) { +func testWriteAndOpen(t *TestRunner, controllers ...TestingControllerFactory) { const content = "Some contents" invalidUtf8 := "\xff\xfe\xfd" @@ -1464,7 +1494,7 @@ func testWriteAndOpen(t *testing.T, controllers ...TestingControllerFactory) { for _, srcTarFormat := range []tar.Format{tar.FormatUSTAR, tar.FormatPAX, tar.FormatGNU} { srcTarFormat := srcTarFormat for _, lossless := range []bool{true, false} { - t.Run(tt.name+"-"+fmt.Sprintf("compression=%v,prefix=%q,lossless=%v,format=%s", newCL(), prefix, lossless, srcTarFormat), func(t *testing.T) { + t.Run(tt.name+"-"+fmt.Sprintf("compression=%v,prefix=%q,lossless=%v,format=%s", newCL(), prefix, lossless, srcTarFormat), func(t *TestRunner) { var tr io.Reader = buildTar(t, tt.in, prefix, srcTarFormat) origTarDgstr := digest.Canonical.Digester() tr = io.TeeReader(tr, origTarDgstr.Hash()) @@ -1530,6 +1560,9 @@ func testWriteAndOpen(t *testing.T, controllers ...TestingControllerFactory) { if err != nil { t.Fatalf("stargz.Open: %v", err) } + if _, ok := r.Lookup(""); !ok { + t.Fatalf("failed to lookup rootdir: %v", err) + } wantTOCVersion := 1 if tt.wantTOCVersion > 0 { wantTOCVersion = tt.wantTOCVersion @@ -1628,7 +1661,7 @@ func digestFor(content string) string { type numTOCEntries int -func (n numTOCEntries) check(t *testing.T, r *Reader) { +func (n numTOCEntries) check(t TestingT, r *Reader) { if r.toc == nil { t.Fatal("nil TOC") } @@ -1648,15 +1681,15 @@ func (n numTOCEntries) check(t *testing.T, r *Reader) { func checks(s ...stargzCheck) []stargzCheck { return s } type stargzCheck interface { - check(t *testing.T, r *Reader) + check(t TestingT, r *Reader) } -type stargzCheckFn func(*testing.T, *Reader) +type stargzCheckFn func(TestingT, *Reader) -func (f stargzCheckFn) check(t *testing.T, r *Reader) { f(t, r) } +func (f stargzCheckFn) check(t TestingT, r *Reader) { f(t, r) } func maxDepth(max int) stargzCheck { - return stargzCheckFn(func(t *testing.T, r *Reader) { + return stargzCheckFn(func(t TestingT, r *Reader) { e, ok := r.Lookup("") if !ok { t.Fatal("root directory not found") @@ -1673,7 +1706,7 @@ func maxDepth(max int) stargzCheck { }) } -func getMaxDepth(t *testing.T, e *TOCEntry, current, limit int) (max int, rErr error) { +func getMaxDepth(t TestingT, e *TOCEntry, current, limit int) (max int, rErr error) { if current > limit { return -1, fmt.Errorf("walkMaxDepth: exceeds limit: current:%d > limit:%d", current, limit) @@ -1695,7 +1728,7 @@ func getMaxDepth(t *testing.T, e *TOCEntry, current, limit int) (max int, rErr e } func hasFileLen(file string, wantLen int) stargzCheck { - return stargzCheckFn(func(t *testing.T, r *Reader) { + return stargzCheckFn(func(t TestingT, r *Reader) { for _, ent := range r.toc.Entries { if ent.Name == file { if ent.Type != "reg" { @@ -1711,7 +1744,7 @@ func hasFileLen(file string, wantLen int) stargzCheck { } func hasFileXattrs(file, name, value string) stargzCheck { - return stargzCheckFn(func(t *testing.T, r *Reader) { + return stargzCheckFn(func(t TestingT, r *Reader) { for _, ent := range r.toc.Entries { if ent.Name == file { if ent.Type != "reg" { @@ -1738,7 +1771,7 @@ func hasFileXattrs(file, name, value string) stargzCheck { } func hasFileDigest(file string, digest string) stargzCheck { - return stargzCheckFn(func(t *testing.T, r *Reader) { + return stargzCheckFn(func(t TestingT, r *Reader) { ent, ok := r.Lookup(file) if !ok { t.Fatalf("didn't find TOCEntry for file %q", file) @@ -1750,7 +1783,7 @@ func hasFileDigest(file string, digest string) stargzCheck { } func hasFileContentsWithPreRead(file string, offset int, want string, extra ...chunkInfo) stargzCheck { - return stargzCheckFn(func(t *testing.T, r *Reader) { + return stargzCheckFn(func(t TestingT, r *Reader) { extraMap := make(map[string]chunkInfo) for _, e := range extra { extraMap[e.name] = e @@ -1797,7 +1830,7 @@ func hasFileContentsWithPreRead(file string, offset int, want string, extra ...c } func hasFileContentsRange(file string, offset int, want string) stargzCheck { - return stargzCheckFn(func(t *testing.T, r *Reader) { + return stargzCheckFn(func(t TestingT, r *Reader) { f, err := r.OpenFile(file) if err != nil { t.Fatal(err) @@ -1814,7 +1847,7 @@ func hasFileContentsRange(file string, offset int, want string) stargzCheck { } func hasChunkEntries(file string, wantChunks int) stargzCheck { - return stargzCheckFn(func(t *testing.T, r *Reader) { + return stargzCheckFn(func(t TestingT, r *Reader) { ent, ok := r.Lookup(file) if !ok { t.Fatalf("no file for %q", file) @@ -1858,7 +1891,7 @@ func hasChunkEntries(file string, wantChunks int) stargzCheck { } func entryHasChildren(dir string, want ...string) stargzCheck { - return stargzCheckFn(func(t *testing.T, r *Reader) { + return stargzCheckFn(func(t TestingT, r *Reader) { want := append([]string(nil), want...) var got []string ent, ok := r.Lookup(dir) @@ -1877,7 +1910,7 @@ func entryHasChildren(dir string, want ...string) stargzCheck { } func hasDir(file string) stargzCheck { - return stargzCheckFn(func(t *testing.T, r *Reader) { + return stargzCheckFn(func(t TestingT, r *Reader) { for _, ent := range r.toc.Entries { if ent.Name == cleanEntryName(file) { if ent.Type != "dir" { @@ -1891,7 +1924,7 @@ func hasDir(file string) stargzCheck { } func hasDirLinkCount(file string, count int) stargzCheck { - return stargzCheckFn(func(t *testing.T, r *Reader) { + return stargzCheckFn(func(t TestingT, r *Reader) { for _, ent := range r.toc.Entries { if ent.Name == cleanEntryName(file) { if ent.Type != "dir" { @@ -1909,7 +1942,7 @@ func hasDirLinkCount(file string, count int) stargzCheck { } func hasMode(file string, mode os.FileMode) stargzCheck { - return stargzCheckFn(func(t *testing.T, r *Reader) { + return stargzCheckFn(func(t TestingT, r *Reader) { for _, ent := range r.toc.Entries { if ent.Name == cleanEntryName(file) { if ent.Stat().Mode() != mode { @@ -1924,7 +1957,7 @@ func hasMode(file string, mode os.FileMode) stargzCheck { } func hasSymlink(file, target string) stargzCheck { - return stargzCheckFn(func(t *testing.T, r *Reader) { + return stargzCheckFn(func(t TestingT, r *Reader) { for _, ent := range r.toc.Entries { if ent.Name == file { if ent.Type != "symlink" { @@ -1940,7 +1973,7 @@ func hasSymlink(file, target string) stargzCheck { } func lookupMatch(name string, want *TOCEntry) stargzCheck { - return stargzCheckFn(func(t *testing.T, r *Reader) { + return stargzCheckFn(func(t TestingT, r *Reader) { e, ok := r.Lookup(name) if !ok { t.Fatalf("failed to Lookup entry %q", name) @@ -1953,7 +1986,7 @@ func lookupMatch(name string, want *TOCEntry) stargzCheck { } func hasEntryOwner(entry string, owner owner) stargzCheck { - return stargzCheckFn(func(t *testing.T, r *Reader) { + return stargzCheckFn(func(t TestingT, r *Reader) { ent, ok := r.Lookup(strings.TrimSuffix(entry, "/")) if !ok { t.Errorf("entry %q not found", entry) @@ -1967,7 +2000,7 @@ func hasEntryOwner(entry string, owner owner) stargzCheck { } func mustSameEntry(files ...string) stargzCheck { - return stargzCheckFn(func(t *testing.T, r *Reader) { + return stargzCheckFn(func(t TestingT, r *Reader) { var first *TOCEntry for _, f := range files { if first == nil { @@ -2039,7 +2072,7 @@ func (f tarEntryFunc) appendTar(tw *tar.Writer, prefix string, format tar.Format return f(tw, prefix, format) } -func buildTar(t *testing.T, ents []tarEntry, prefix string, opts ...interface{}) *io.SectionReader { +func buildTar(t TestingT, ents []tarEntry, prefix string, opts ...interface{}) *io.SectionReader { format := tar.FormatUnknown for _, opt := range opts { switch v := opt.(type) { @@ -2248,7 +2281,7 @@ func noPrefetchLandmark() tarEntry { }) } -func regDigest(t *testing.T, name string, contentStr string, digestMap map[string]digest.Digest) tarEntry { +func regDigest(t TestingT, name string, contentStr string, digestMap map[string]digest.Digest) tarEntry { if digestMap == nil { t.Fatalf("digest map mustn't be nil") } @@ -2318,7 +2351,7 @@ func (f fileInfoOnlyMode) ModTime() time.Time { return time.Now() } func (f fileInfoOnlyMode) IsDir() bool { return os.FileMode(f).IsDir() } func (f fileInfoOnlyMode) Sys() interface{} { return nil } -func CheckGzipHasStreams(t *testing.T, b []byte, streams []int64) { +func CheckGzipHasStreams(t TestingT, b []byte, streams []int64) { if len(streams) == 0 { return // nop } @@ -2356,7 +2389,7 @@ func CheckGzipHasStreams(t *testing.T, b []byte, streams []int64) { } } -func GzipDiffIDOf(t *testing.T, b []byte) string { +func GzipDiffIDOf(t TestingT, b []byte) string { h := sha256.New() zr, err := gzip.NewReader(bytes.NewReader(b)) if err != nil { diff --git a/vendor/github.com/containers/buildah/info.go b/vendor/github.com/containers/buildah/info.go index d0dd48932fb..b06c30ffdcd 100644 --- a/vendor/github.com/containers/buildah/info.go +++ b/vendor/github.com/containers/buildah/info.go @@ -55,12 +55,11 @@ func hostInfo() map[string]any { if err != nil { logrus.Error(err, "err reading cgroups mode") } - cgroupVersion := "v1" - ociruntime := util.Runtime() - if unified { - cgroupVersion = "v2" + if !unified { + logrus.Fatalf("Did not detect Cgroups v2.") } - info["CgroupVersion"] = cgroupVersion + + ociruntime := util.Runtime() info["OCIRuntime"] = ociruntime mi, err := system.ReadMemInfo() diff --git a/vendor/github.com/containers/buildah/internal/mkcw/embed/entrypoint_amd64.gz b/vendor/github.com/containers/buildah/internal/mkcw/embed/entrypoint_amd64.gz index 953670818fe..c2399f9e904 100644 Binary files a/vendor/github.com/containers/buildah/internal/mkcw/embed/entrypoint_amd64.gz and b/vendor/github.com/containers/buildah/internal/mkcw/embed/entrypoint_amd64.gz differ diff --git a/vendor/github.com/klauspost/compress/flate/deflate.go b/vendor/github.com/klauspost/compress/flate/deflate.go index af53fb860cc..4e92f5998a8 100644 --- a/vendor/github.com/klauspost/compress/flate/deflate.go +++ b/vendor/github.com/klauspost/compress/flate/deflate.go @@ -6,11 +6,12 @@ package flate import ( - "encoding/binary" "errors" "fmt" "io" "math" + + "github.com/klauspost/compress/internal/le" ) const ( @@ -234,12 +235,9 @@ func (d *compressor) fillWindow(b []byte) { // Calculate 256 hashes at the time (more L1 cache hits) loops := (n + 256 - minMatchLength) / 256 - for j := 0; j < loops; j++ { + for j := range loops { startindex := j * 256 - end := startindex + 256 + minMatchLength - 1 - if end > n { - end = n - } + end := min(startindex+256+minMatchLength-1, n) tocheck := d.window[startindex:end] dstSize := len(tocheck) - minMatchLength + 1 @@ -269,18 +267,12 @@ func (d *compressor) fillWindow(b []byte) { // We only look at chainCount possibilities before giving up. // pos = s.index, prevHead = s.chainHead-s.hashOffset, prevLength=minMatchLength-1, lookahead func (d *compressor) findMatch(pos int, prevHead int, lookahead int) (length, offset int, ok bool) { - minMatchLook := maxMatchLength - if lookahead < minMatchLook { - minMatchLook = lookahead - } + minMatchLook := min(lookahead, maxMatchLength) win := d.window[0 : pos+minMatchLook] // We quit when we get a match that's at least nice long - nice := len(win) - pos - if d.nice < nice { - nice = d.nice - } + nice := min(d.nice, len(win)-pos) // If we've got a match that's good enough, only look in 1/4 the chain. tries := d.chain @@ -288,10 +280,7 @@ func (d *compressor) findMatch(pos int, prevHead int, lookahead int) (length, of wEnd := win[pos+length] wPos := win[pos:] - minIndex := pos - windowSize - if minIndex < 0 { - minIndex = 0 - } + minIndex := max(pos-windowSize, 0) offset = 0 if d.chain < 100 { @@ -374,7 +363,7 @@ func (d *compressor) writeStoredBlock(buf []byte) error { // of the supplied slice. // The caller must ensure that len(b) >= 4. func hash4(b []byte) uint32 { - return hash4u(binary.LittleEndian.Uint32(b), hashBits) + return hash4u(le.Load32(b, 0), hashBits) } // hash4 returns the hash of u to fit in a hash table with h bits. @@ -389,7 +378,7 @@ func bulkHash4(b []byte, dst []uint32) { if len(b) < 4 { return } - hb := binary.LittleEndian.Uint32(b) + hb := le.Load32(b, 0) dst[0] = hash4u(hb, hashBits) end := len(b) - 4 + 1 @@ -480,10 +469,7 @@ func (d *compressor) deflateLazy() { prevOffset := s.offset s.length = minMatchLength - 1 s.offset = 0 - minIndex := s.index - windowSize - if minIndex < 0 { - minIndex = 0 - } + minIndex := max(s.index-windowSize, 0) if s.chainHead-s.hashOffset >= minIndex && lookahead > prevLength && prevLength < d.lazy { if newLength, newOffset, ok := d.findMatch(s.index, s.chainHead-s.hashOffset, lookahead); ok { @@ -503,10 +489,7 @@ func (d *compressor) deflateLazy() { if prevLength < maxMatchLength-checkOff { prevIndex := s.index - 1 if prevIndex+prevLength < s.maxInsertIndex { - end := lookahead - if lookahead > maxMatchLength+checkOff { - end = maxMatchLength + checkOff - } + end := min(lookahead, maxMatchLength+checkOff) end += prevIndex // Hash at match end. @@ -603,15 +586,9 @@ func (d *compressor) deflateLazy() { // table. newIndex := s.index + prevLength - 1 // Calculate missing hashes - end := newIndex - if end > s.maxInsertIndex { - end = s.maxInsertIndex - } + end := min(newIndex, s.maxInsertIndex) end += minMatchLength - 1 - startindex := s.index + 1 - if startindex > s.maxInsertIndex { - startindex = s.maxInsertIndex - } + startindex := min(s.index+1, s.maxInsertIndex) tocheck := d.window[startindex:end] dstSize := len(tocheck) - minMatchLength + 1 if dstSize > 0 { diff --git a/vendor/github.com/klauspost/compress/flate/dict_decoder.go b/vendor/github.com/klauspost/compress/flate/dict_decoder.go index bb36351a5af..cb855abc4ba 100644 --- a/vendor/github.com/klauspost/compress/flate/dict_decoder.go +++ b/vendor/github.com/klauspost/compress/flate/dict_decoder.go @@ -104,10 +104,7 @@ func (dd *dictDecoder) writeCopy(dist, length int) int { dstBase := dd.wrPos dstPos := dstBase srcPos := dstPos - dist - endPos := dstPos + length - if endPos > len(dd.hist) { - endPos = len(dd.hist) - } + endPos := min(dstPos+length, len(dd.hist)) // Copy non-overlapping section after destination position. // diff --git a/vendor/github.com/klauspost/compress/flate/fast_encoder.go b/vendor/github.com/klauspost/compress/flate/fast_encoder.go index 0e8b1630c04..791c9dcbfd9 100644 --- a/vendor/github.com/klauspost/compress/flate/fast_encoder.go +++ b/vendor/github.com/klauspost/compress/flate/fast_encoder.go @@ -7,7 +7,6 @@ package flate import ( "fmt" - "math/bits" "github.com/klauspost/compress/internal/le" ) @@ -151,29 +150,9 @@ func (e *fastGen) matchlen(s, t int, src []byte) int32 { panic(fmt.Sprint(s, "-", t, "(", s-t, ") > maxMatchLength (", maxMatchOffset, ")")) } } - s1 := min(s+maxMatchLength-4, len(src)) - left := s1 - s - n := int32(0) - for left >= 8 { - diff := le.Load64(src, s) ^ le.Load64(src, t) - if diff != 0 { - return n + int32(bits.TrailingZeros64(diff)>>3) - } - s += 8 - t += 8 - n += 8 - left -= 8 - } - - a := src[s:s1] + a := src[s:min(s+maxMatchLength-4, len(src))] b := src[t:] - for i := range a { - if a[i] != b[i] { - break - } - n++ - } - return n + return int32(matchLen(a, b)) } // matchlenLong will return the match length between offsets and t in src. @@ -193,29 +172,7 @@ func (e *fastGen) matchlenLong(s, t int, src []byte) int32 { panic(fmt.Sprint(s, "-", t, "(", s-t, ") > maxMatchLength (", maxMatchOffset, ")")) } } - // Extend the match to be as long as possible. - left := len(src) - s - n := int32(0) - for left >= 8 { - diff := le.Load64(src, s) ^ le.Load64(src, t) - if diff != 0 { - return n + int32(bits.TrailingZeros64(diff)>>3) - } - s += 8 - t += 8 - n += 8 - left -= 8 - } - - a := src[s:] - b := src[t:] - for i := range a { - if a[i] != b[i] { - break - } - n++ - } - return n + return int32(matchLen(src[s:], src[t:])) } // Reset the encoding table. diff --git a/vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go b/vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go index afdc8c053a0..03a1796979b 100644 --- a/vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go +++ b/vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go @@ -211,7 +211,9 @@ func (w *huffmanBitWriter) flush() { n++ } w.bits = 0 - w.write(w.bytes[:n]) + if n > 0 { + w.write(w.bytes[:n]) + } w.nbytes = 0 } @@ -303,10 +305,7 @@ func (w *huffmanBitWriter) generateCodegen(numLiterals int, numOffsets int, litE w.codegenFreq[size]++ count-- for count >= 3 { - n := 6 - if n > count { - n = count - } + n := min(6, count) codegen[outIndex] = 16 outIndex++ codegen[outIndex] = uint8(n - 3) @@ -316,10 +315,7 @@ func (w *huffmanBitWriter) generateCodegen(numLiterals int, numOffsets int, litE } } else { for count >= 11 { - n := 138 - if n > count { - n = count - } + n := min(138, count) codegen[outIndex] = 18 outIndex++ codegen[outIndex] = uint8(n - 11) @@ -438,8 +434,8 @@ func (w *huffmanBitWriter) writeOutBits() { w.nbits -= 48 n := w.nbytes - // We over-write, but faster... - le.Store64(w.bytes[n:], bits) + // We overwrite, but faster... + le.Store64(w.bytes[:], n, bits) n += 6 if n >= bufferFlushSize { @@ -472,7 +468,7 @@ func (w *huffmanBitWriter) writeDynamicHeader(numLiterals int, numOffsets int, n w.writeBits(int32(numOffsets-1), 5) w.writeBits(int32(numCodegens-4), 4) - for i := 0; i < numCodegens; i++ { + for i := range numCodegens { value := uint(w.codegenEncoding.codes[codegenOrder[i]].len()) w.writeBits(int32(value), 3) } @@ -650,7 +646,7 @@ func (w *huffmanBitWriter) writeBlockDynamic(tokens *tokens, eof bool, input []b w.lastHeader = 0 } - numLiterals, numOffsets := w.indexTokens(tokens, !sync) + numLiterals, numOffsets := w.indexTokens(tokens, fillReuse && !sync) extraBits := 0 ssize, storable := w.storedSize(input) @@ -855,8 +851,7 @@ func (w *huffmanBitWriter) writeTokens(tokens []token, leCodes, oeCodes []hcode) bits |= c.code64() << (nbits & 63) nbits += c.len() if nbits >= 48 { - le.Store64(w.bytes[nbytes:], bits) - //*(*uint64)(unsafe.Pointer(&w.bytes[nbytes])) = bits + le.Store64(w.bytes[:], nbytes, bits) bits >>= 48 nbits -= 48 nbytes += 6 @@ -883,8 +878,7 @@ func (w *huffmanBitWriter) writeTokens(tokens []token, leCodes, oeCodes []hcode) bits |= c.code64() << (nbits & 63) nbits += c.len() if nbits >= 48 { - le.Store64(w.bytes[nbytes:], bits) - //*(*uint64)(unsafe.Pointer(&w.bytes[nbytes])) = bits + le.Store64(w.bytes[:], nbytes, bits) bits >>= 48 nbits -= 48 nbytes += 6 @@ -906,8 +900,7 @@ func (w *huffmanBitWriter) writeTokens(tokens []token, leCodes, oeCodes []hcode) bits |= uint64(extraLength) << (nbits & 63) nbits += extraLengthBits if nbits >= 48 { - le.Store64(w.bytes[nbytes:], bits) - //*(*uint64)(unsafe.Pointer(&w.bytes[nbytes])) = bits + le.Store64(w.bytes[:], nbytes, bits) bits >>= 48 nbits -= 48 nbytes += 6 @@ -932,8 +925,7 @@ func (w *huffmanBitWriter) writeTokens(tokens []token, leCodes, oeCodes []hcode) bits |= c.code64() << (nbits & 63) nbits += c.len() if nbits >= 48 { - le.Store64(w.bytes[nbytes:], bits) - //*(*uint64)(unsafe.Pointer(&w.bytes[nbytes])) = bits + le.Store64(w.bytes[:], nbytes, bits) bits >>= 48 nbits -= 48 nbytes += 6 @@ -954,8 +946,7 @@ func (w *huffmanBitWriter) writeTokens(tokens []token, leCodes, oeCodes []hcode) bits |= uint64((offset-(offsetComb>>8))&matchOffsetOnlyMask) << (nbits & 63) nbits += uint8(offsetComb) if nbits >= 48 { - le.Store64(w.bytes[nbytes:], bits) - //*(*uint64)(unsafe.Pointer(&w.bytes[nbytes])) = bits + le.Store64(w.bytes[:], nbytes, bits) bits >>= 48 nbits -= 48 nbytes += 6 @@ -1108,7 +1099,7 @@ func (w *huffmanBitWriter) writeBlockHuff(eof bool, input []byte, sync bool) { // We must have at least 48 bits free. if nbits >= 8 { n := nbits >> 3 - le.Store64(w.bytes[nbytes:], bits) + le.Store64(w.bytes[:], nbytes, bits) bits >>= (n * 8) & 63 nbits -= n * 8 nbytes += n @@ -1137,8 +1128,7 @@ func (w *huffmanBitWriter) writeBlockHuff(eof bool, input []byte, sync bool) { // Remaining... for _, t := range input { if nbits >= 48 { - le.Store64(w.bytes[nbytes:], bits) - //*(*uint64)(unsafe.Pointer(&w.bytes[nbytes])) = bits + le.Store64(w.bytes[:], nbytes, bits) bits >>= 48 nbits -= 48 nbytes += 6 diff --git a/vendor/github.com/klauspost/compress/flate/huffman_code.go b/vendor/github.com/klauspost/compress/flate/huffman_code.go index be7b58b473f..5f901bd0fe8 100644 --- a/vendor/github.com/klauspost/compress/flate/huffman_code.go +++ b/vendor/github.com/klauspost/compress/flate/huffman_code.go @@ -91,7 +91,7 @@ func generateFixedLiteralEncoding() *huffmanEncoder { h := newHuffmanEncoder(literalCount) codes := h.codes var ch uint16 - for ch = 0; ch < literalCount; ch++ { + for ch = range uint16(literalCount) { var bits uint16 var size uint8 switch { diff --git a/vendor/github.com/klauspost/compress/flate/inflate.go b/vendor/github.com/klauspost/compress/flate/inflate.go index 0d7b437f1c6..6e90126db03 100644 --- a/vendor/github.com/klauspost/compress/flate/inflate.go +++ b/vendor/github.com/klauspost/compress/flate/inflate.go @@ -485,7 +485,7 @@ func (f *decompressor) readHuffman() error { f.nb -= 5 + 5 + 4 // (HCLEN+4)*3 bits: code lengths in the magic codeOrder order. - for i := 0; i < nclen; i++ { + for i := range nclen { for f.nb < 3 { if err := f.moreBits(); err != nil { return err @@ -776,7 +776,7 @@ func fixedHuffmanDecoderInit() { fixedOnce.Do(func() { // These come from the RFC section 3.2.6. var bits [288]int - for i := 0; i < 144; i++ { + for i := range 144 { bits[i] = 8 } for i := 144; i < 256; i++ { diff --git a/vendor/github.com/klauspost/compress/flate/level5.go b/vendor/github.com/klauspost/compress/flate/level5.go index 6e5c21502f7..a22ad7d1255 100644 --- a/vendor/github.com/klauspost/compress/flate/level5.go +++ b/vendor/github.com/klauspost/compress/flate/level5.go @@ -677,10 +677,7 @@ func (e *fastEncL5Window) matchlen(s, t int32, src []byte) int32 { panic(fmt.Sprint(s, "-", t, "(", s-t, ") > maxMatchLength (", maxMatchOffset, ")")) } } - s1 := int(s) + maxMatchLength - 4 - if s1 > len(src) { - s1 = len(src) - } + s1 := min(int(s)+maxMatchLength-4, len(src)) // Extend the match to be as long as possible. return int32(matchLen(src[s:s1], src[t:])) diff --git a/vendor/github.com/klauspost/compress/flate/stateless.go b/vendor/github.com/klauspost/compress/flate/stateless.go index 13b9b100dbc..90b74f7acdd 100644 --- a/vendor/github.com/klauspost/compress/flate/stateless.go +++ b/vendor/github.com/klauspost/compress/flate/stateless.go @@ -56,7 +56,7 @@ func NewStatelessWriter(dst io.Writer) io.WriteCloser { // bitWriterPool contains bit writers that can be reused. var bitWriterPool = sync.Pool{ - New: func() interface{} { + New: func() any { return newHuffmanBitWriter(nil) }, } @@ -184,7 +184,7 @@ func statelessEnc(dst *tokens, src []byte, startAt int16) { // Index until startAt if startAt > 0 { cv := load3232(src, 0) - for i := int16(0); i < startAt; i++ { + for i := range startAt { table[hashSL(cv)] = tableEntry{offset: i} cv = (cv >> 8) | (uint32(src[i+4]) << 24) } diff --git a/vendor/github.com/klauspost/compress/fse/bitwriter.go b/vendor/github.com/klauspost/compress/fse/bitwriter.go index e82fa3bb7b6..d58b3fe4237 100644 --- a/vendor/github.com/klauspost/compress/fse/bitwriter.go +++ b/vendor/github.com/klauspost/compress/fse/bitwriter.go @@ -143,7 +143,7 @@ func (b *bitWriter) flush32() { // flushAlign will flush remaining full bytes and align to next byte boundary. func (b *bitWriter) flushAlign() { nbBytes := (b.nBits + 7) >> 3 - for i := uint8(0); i < nbBytes; i++ { + for i := range nbBytes { b.out = append(b.out, byte(b.bitContainer>>(i*8))) } b.nBits = 0 diff --git a/vendor/github.com/klauspost/compress/fse/compress.go b/vendor/github.com/klauspost/compress/fse/compress.go index 074018d8f94..8c8baa4fc2c 100644 --- a/vendor/github.com/klauspost/compress/fse/compress.go +++ b/vendor/github.com/klauspost/compress/fse/compress.go @@ -396,7 +396,7 @@ func (s *Scratch) buildCTable() error { if v > largeLimit { s.zeroBits = true } - for nbOccurrences := int16(0); nbOccurrences < v; nbOccurrences++ { + for range v { tableSymbol[position] = symbol position = (position + step) & tableMask for position > highThreshold { diff --git a/vendor/github.com/klauspost/compress/huff0/bitwriter.go b/vendor/github.com/klauspost/compress/huff0/bitwriter.go index 0ebc9aaac76..41db94cded0 100644 --- a/vendor/github.com/klauspost/compress/huff0/bitwriter.go +++ b/vendor/github.com/klauspost/compress/huff0/bitwriter.go @@ -85,7 +85,7 @@ func (b *bitWriter) flush32() { // flushAlign will flush remaining full bytes and align to next byte boundary. func (b *bitWriter) flushAlign() { nbBytes := (b.nBits + 7) >> 3 - for i := uint8(0); i < nbBytes; i++ { + for i := range nbBytes { b.out = append(b.out, byte(b.bitContainer>>(i*8))) } b.nBits = 0 diff --git a/vendor/github.com/klauspost/compress/huff0/compress.go b/vendor/github.com/klauspost/compress/huff0/compress.go index 84aa3d12f00..a97cf1b5d35 100644 --- a/vendor/github.com/klauspost/compress/huff0/compress.go +++ b/vendor/github.com/klauspost/compress/huff0/compress.go @@ -276,7 +276,7 @@ func (s *Scratch) compress4X(src []byte) ([]byte, error) { offsetIdx := len(s.Out) s.Out = append(s.Out, sixZeros[:]...) - for i := 0; i < 4; i++ { + for i := range 4 { toDo := src if len(toDo) > segmentSize { toDo = toDo[:segmentSize] @@ -312,7 +312,7 @@ func (s *Scratch) compress4Xp(src []byte) ([]byte, error) { segmentSize := (len(src) + 3) / 4 var wg sync.WaitGroup wg.Add(4) - for i := 0; i < 4; i++ { + for i := range 4 { toDo := src if len(toDo) > segmentSize { toDo = toDo[:segmentSize] @@ -326,7 +326,7 @@ func (s *Scratch) compress4Xp(src []byte) ([]byte, error) { }(i) } wg.Wait() - for i := 0; i < 4; i++ { + for i := range 4 { o := s.tmpOut[i] if len(o) > math.MaxUint16 { // We cannot store the size in the jump table diff --git a/vendor/github.com/klauspost/compress/huff0/decompress.go b/vendor/github.com/klauspost/compress/huff0/decompress.go index 0f56b02d747..7d0efa8818a 100644 --- a/vendor/github.com/klauspost/compress/huff0/decompress.go +++ b/vendor/github.com/klauspost/compress/huff0/decompress.go @@ -626,7 +626,7 @@ func (d *Decoder) decompress4X8bit(dst, src []byte) ([]byte, error) { var br [4]bitReaderBytes start := 6 - for i := 0; i < 3; i++ { + for i := range 3 { length := int(src[i*2]) | (int(src[i*2+1]) << 8) if start+length >= len(src) { return nil, errors.New("truncated input (or invalid offset)") @@ -798,10 +798,7 @@ func (d *Decoder) decompress4X8bit(dst, src []byte) ([]byte, error) { remainBytes := dstEvery - (decoded / 4) for i := range br { offset := dstEvery * i - endsAt := offset + remainBytes - if endsAt > len(out) { - endsAt = len(out) - } + endsAt := min(offset+remainBytes, len(out)) br := &br[i] bitsLeft := br.remaining() for bitsLeft > 0 { @@ -864,7 +861,7 @@ func (d *Decoder) decompress4X8bit(dst, src []byte) ([]byte, error) { func (d *Decoder) decompress4X8bitExactly(dst, src []byte) ([]byte, error) { var br [4]bitReaderBytes start := 6 - for i := 0; i < 3; i++ { + for i := range 3 { length := int(src[i*2]) | (int(src[i*2+1]) << 8) if start+length >= len(src) { return nil, errors.New("truncated input (or invalid offset)") @@ -1035,10 +1032,7 @@ func (d *Decoder) decompress4X8bitExactly(dst, src []byte) ([]byte, error) { remainBytes := dstEvery - (decoded / 4) for i := range br { offset := dstEvery * i - endsAt := offset + remainBytes - if endsAt > len(out) { - endsAt = len(out) - } + endsAt := min(offset+remainBytes, len(out)) br := &br[i] bitsLeft := br.remaining() for bitsLeft > 0 { diff --git a/vendor/github.com/klauspost/compress/huff0/decompress_amd64.go b/vendor/github.com/klauspost/compress/huff0/decompress_amd64.go index ba7e8e6b027..99ddd4af97c 100644 --- a/vendor/github.com/klauspost/compress/huff0/decompress_amd64.go +++ b/vendor/github.com/klauspost/compress/huff0/decompress_amd64.go @@ -58,7 +58,7 @@ func (d *Decoder) Decompress4X(dst, src []byte) ([]byte, error) { var br [4]bitReaderShifted // Decode "jump table" start := 6 - for i := 0; i < 3; i++ { + for i := range 3 { length := int(src[i*2]) | (int(src[i*2+1]) << 8) if start+length >= len(src) { return nil, errors.New("truncated input (or invalid offset)") @@ -109,10 +109,7 @@ func (d *Decoder) Decompress4X(dst, src []byte) ([]byte, error) { remainBytes := dstEvery - (decoded / 4) for i := range br { offset := dstEvery * i - endsAt := offset + remainBytes - if endsAt > len(out) { - endsAt = len(out) - } + endsAt := min(offset+remainBytes, len(out)) br := &br[i] bitsLeft := br.remaining() for bitsLeft > 0 { diff --git a/vendor/github.com/klauspost/compress/huff0/huff0.go b/vendor/github.com/klauspost/compress/huff0/huff0.go index 77ecd68e0a7..67d9e05b6cc 100644 --- a/vendor/github.com/klauspost/compress/huff0/huff0.go +++ b/vendor/github.com/klauspost/compress/huff0/huff0.go @@ -201,7 +201,7 @@ func (c cTable) write(s *Scratch) error { for i := range hist[:16] { hist[i] = 0 } - for n := uint8(0); n < maxSymbolValue; n++ { + for n := range maxSymbolValue { v := bitsToWeight[c[n].nBits] & 15 huffWeight[n] = v hist[v]++ @@ -271,7 +271,7 @@ func (c cTable) estTableSize(s *Scratch) (sz int, err error) { for i := range hist[:16] { hist[i] = 0 } - for n := uint8(0); n < maxSymbolValue; n++ { + for n := range maxSymbolValue { v := bitsToWeight[c[n].nBits] & 15 huffWeight[n] = v hist[v]++ diff --git a/vendor/github.com/klauspost/compress/internal/le/unsafe_disabled.go b/vendor/github.com/klauspost/compress/internal/le/unsafe_disabled.go index 0cfb5c0e278..4f2a0d8c58d 100644 --- a/vendor/github.com/klauspost/compress/internal/le/unsafe_disabled.go +++ b/vendor/github.com/klauspost/compress/internal/le/unsafe_disabled.go @@ -37,6 +37,6 @@ func Store32(b []byte, v uint32) { } // Store64 will store v at b. -func Store64(b []byte, v uint64) { - binary.LittleEndian.PutUint64(b, v) +func Store64[I Indexer](b []byte, i I, v uint64) { + binary.LittleEndian.PutUint64(b[i:], v) } diff --git a/vendor/github.com/klauspost/compress/internal/le/unsafe_enabled.go b/vendor/github.com/klauspost/compress/internal/le/unsafe_enabled.go index ada45cd909e..218a38bc4a5 100644 --- a/vendor/github.com/klauspost/compress/internal/le/unsafe_enabled.go +++ b/vendor/github.com/klauspost/compress/internal/le/unsafe_enabled.go @@ -38,18 +38,15 @@ func Load64[I Indexer](b []byte, i I) uint64 { // Store16 will store v at b. func Store16(b []byte, v uint16) { - //binary.LittleEndian.PutUint16(b, v) *(*uint16)(unsafe.Pointer(unsafe.SliceData(b))) = v } // Store32 will store v at b. func Store32(b []byte, v uint32) { - //binary.LittleEndian.PutUint32(b, v) *(*uint32)(unsafe.Pointer(unsafe.SliceData(b))) = v } -// Store64 will store v at b. -func Store64(b []byte, v uint64) { - //binary.LittleEndian.PutUint64(b, v) - *(*uint64)(unsafe.Pointer(unsafe.SliceData(b))) = v +// Store64 will store v at b[i:]. +func Store64[I Indexer](b []byte, i I, v uint64) { + *(*uint64)(unsafe.Add(unsafe.Pointer(unsafe.SliceData(b)), i)) = v } diff --git a/vendor/github.com/klauspost/compress/internal/snapref/decode.go b/vendor/github.com/klauspost/compress/internal/snapref/decode.go index 40796a49d65..a2c82fcd226 100644 --- a/vendor/github.com/klauspost/compress/internal/snapref/decode.go +++ b/vendor/github.com/klauspost/compress/internal/snapref/decode.go @@ -209,7 +209,7 @@ func (r *Reader) fill() error { if !r.readFull(r.buf[:len(magicBody)], false) { return r.err } - for i := 0; i < len(magicBody); i++ { + for i := range len(magicBody) { if r.buf[i] != magicBody[i] { r.err = ErrCorrupt return r.err diff --git a/vendor/github.com/klauspost/compress/internal/snapref/encode.go b/vendor/github.com/klauspost/compress/internal/snapref/encode.go index 13c6040a5de..860a994167a 100644 --- a/vendor/github.com/klauspost/compress/internal/snapref/encode.go +++ b/vendor/github.com/klauspost/compress/internal/snapref/encode.go @@ -20,8 +20,10 @@ import ( func Encode(dst, src []byte) []byte { if n := MaxEncodedLen(len(src)); n < 0 { panic(ErrTooLarge) - } else if len(dst) < n { + } else if cap(dst) < n { dst = make([]byte, n) + } else { + dst = dst[:n] } // The block starts with the varint-encoded length of the decompressed bytes. diff --git a/vendor/github.com/klauspost/compress/zstd/bitwriter.go b/vendor/github.com/klauspost/compress/zstd/bitwriter.go index 1952f175b0d..b22b297e62a 100644 --- a/vendor/github.com/klauspost/compress/zstd/bitwriter.go +++ b/vendor/github.com/klauspost/compress/zstd/bitwriter.go @@ -88,7 +88,7 @@ func (b *bitWriter) flush32() { // flushAlign will flush remaining full bytes and align to next byte boundary. func (b *bitWriter) flushAlign() { nbBytes := (b.nBits + 7) >> 3 - for i := uint8(0); i < nbBytes; i++ { + for i := range nbBytes { b.out = append(b.out, byte(b.bitContainer>>(i*8))) } b.nBits = 0 diff --git a/vendor/github.com/klauspost/compress/zstd/blockdec.go b/vendor/github.com/klauspost/compress/zstd/blockdec.go index 0dd742fd2a6..2329e996f86 100644 --- a/vendor/github.com/klauspost/compress/zstd/blockdec.go +++ b/vendor/github.com/klauspost/compress/zstd/blockdec.go @@ -54,11 +54,11 @@ const ( ) var ( - huffDecoderPool = sync.Pool{New: func() interface{} { + huffDecoderPool = sync.Pool{New: func() any { return &huff0.Scratch{} }} - fseDecoderPool = sync.Pool{New: func() interface{} { + fseDecoderPool = sync.Pool{New: func() any { return &fseDecoder{} }} ) @@ -553,7 +553,7 @@ func (b *blockDec) prepareSequences(in []byte, hist *history) (err error) { if compMode&3 != 0 { return errors.New("corrupt block: reserved bits not zero") } - for i := uint(0); i < 3; i++ { + for i := range uint(3) { mode := seqCompMode((compMode >> (6 - i*2)) & 3) if debugDecoder { println("Table", tableIndex(i), "is", mode) diff --git a/vendor/github.com/klauspost/compress/zstd/decoder.go b/vendor/github.com/klauspost/compress/zstd/decoder.go index ea2a19376c1..30df5513d56 100644 --- a/vendor/github.com/klauspost/compress/zstd/decoder.go +++ b/vendor/github.com/klauspost/compress/zstd/decoder.go @@ -373,11 +373,9 @@ func (d *Decoder) DecodeAll(input, dst []byte) ([]byte, error) { if cap(dst) == 0 && !d.o.limitToCap { // Allocate len(input) * 2 by default if nothing is provided // and we didn't get frame content size. - size := len(input) * 2 - // Cap to 1 MB. - if size > 1<<20 { - size = 1 << 20 - } + size := min( + // Cap to 1 MB. + len(input)*2, 1<<20) if uint64(size) > d.o.maxDecodedSize { size = int(d.o.maxDecodedSize) } diff --git a/vendor/github.com/klauspost/compress/zstd/dict.go b/vendor/github.com/klauspost/compress/zstd/dict.go index b7b83164bc7..2ffbfdf379e 100644 --- a/vendor/github.com/klauspost/compress/zstd/dict.go +++ b/vendor/github.com/klauspost/compress/zstd/dict.go @@ -194,17 +194,17 @@ func BuildDict(o BuildDictOptions) ([]byte, error) { hist := o.History contents := o.Contents debug := o.DebugOut != nil - println := func(args ...interface{}) { + println := func(args ...any) { if o.DebugOut != nil { fmt.Fprintln(o.DebugOut, args...) } } - printf := func(s string, args ...interface{}) { + printf := func(s string, args ...any) { if o.DebugOut != nil { fmt.Fprintf(o.DebugOut, s, args...) } } - print := func(args ...interface{}) { + print := func(args ...any) { if o.DebugOut != nil { fmt.Fprint(o.DebugOut, args...) } @@ -424,16 +424,10 @@ func BuildDict(o BuildDictOptions) ([]byte, error) { } // Literal table - avgSize := litTotal - if avgSize > huff0.BlockSizeMax/2 { - avgSize = huff0.BlockSizeMax / 2 - } + avgSize := min(litTotal, huff0.BlockSizeMax/2) huffBuff := make([]byte, 0, avgSize) // Target size - div := litTotal / avgSize - if div < 1 { - div = 1 - } + div := max(litTotal/avgSize, 1) if debug { println("Huffman weights:") } @@ -454,7 +448,7 @@ func BuildDict(o BuildDictOptions) ([]byte, error) { huffBuff = append(huffBuff, 255) } scratch := &huff0.Scratch{TableLog: 11} - for tries := 0; tries < 255; tries++ { + for tries := range 255 { scratch = &huff0.Scratch{TableLog: 11} _, _, err = huff0.Compress1X(huffBuff, scratch) if err == nil { @@ -471,7 +465,7 @@ func BuildDict(o BuildDictOptions) ([]byte, error) { // Bail out.... Just generate something huffBuff = append(huffBuff, bytes.Repeat([]byte{255}, 10000)...) - for i := 0; i < 128; i++ { + for i := range 128 { huffBuff = append(huffBuff, byte(i)) } continue diff --git a/vendor/github.com/klauspost/compress/zstd/enc_base.go b/vendor/github.com/klauspost/compress/zstd/enc_base.go index 7d250c67f59..c1192ec38f4 100644 --- a/vendor/github.com/klauspost/compress/zstd/enc_base.go +++ b/vendor/github.com/klauspost/compress/zstd/enc_base.go @@ -8,7 +8,7 @@ import ( ) const ( - dictShardBits = 6 + dictShardBits = 7 ) type fastBase struct { @@ -41,11 +41,9 @@ func (e *fastBase) AppendCRC(dst []byte) []byte { // or a window size small enough to contain the input size, if > 0. func (e *fastBase) WindowSize(size int64) int32 { if size > 0 && size < int64(e.maxMatchOff) { - b := int32(1) << uint(bits.Len(uint(size))) - // Keep minimum window. - if b < 1024 { - b = 1024 - } + b := max( + // Keep minimum window. + int32(1)< tMin && s > nextEmit && src[offset-1] == src[s-1] && l < maxMatchLength { s-- offset-- @@ -382,10 +377,7 @@ encodeLoop: nextEmit = s // Index skipped... - end := s - if s > sLimit+4 { - end = sLimit + 4 - } + end := min(s, sLimit+4) off := index0 + e.cur for index0 < end { cv0 := load6432(src, index0) @@ -444,10 +436,7 @@ encodeLoop: nextEmit = s // Index old s + 1 -> s - 1 or sLimit - end := s - if s > sLimit-4 { - end = sLimit - 4 - } + end := min(s, sLimit-4) off := index0 + e.cur for index0 < end { diff --git a/vendor/github.com/klauspost/compress/zstd/enc_better.go b/vendor/github.com/klauspost/compress/zstd/enc_better.go index 84a79fde767..85dcd28c32e 100644 --- a/vendor/github.com/klauspost/compress/zstd/enc_better.go +++ b/vendor/github.com/klauspost/compress/zstd/enc_better.go @@ -190,10 +190,7 @@ encodeLoop: // and have to do special offset treatment. startLimit := nextEmit + 1 - tMin := s - e.maxMatchOff - if tMin < 0 { - tMin = 0 - } + tMin := max(s-e.maxMatchOff, 0) for repIndex > tMin && start > startLimit && src[repIndex-1] == src[start-1] && seq.matchLen < maxMatchLength-zstdMinMatch-1 { repIndex-- start-- @@ -252,10 +249,7 @@ encodeLoop: // and have to do special offset treatment. startLimit := nextEmit + 1 - tMin := s - e.maxMatchOff - if tMin < 0 { - tMin = 0 - } + tMin := max(s-e.maxMatchOff, 0) for repIndex > tMin && start > startLimit && src[repIndex-1] == src[start-1] && seq.matchLen < maxMatchLength-zstdMinMatch-1 { repIndex-- start-- @@ -480,10 +474,7 @@ encodeLoop: l := matched // Extend backwards - tMin := s - e.maxMatchOff - if tMin < 0 { - tMin = 0 - } + tMin := max(s-e.maxMatchOff, 0) for t > tMin && s > nextEmit && src[t-1] == src[s-1] && l < maxMatchLength { s-- t-- @@ -719,10 +710,7 @@ encodeLoop: // and have to do special offset treatment. startLimit := nextEmit + 1 - tMin := s - e.maxMatchOff - if tMin < 0 { - tMin = 0 - } + tMin := max(s-e.maxMatchOff, 0) for repIndex > tMin && start > startLimit && src[repIndex-1] == src[start-1] && seq.matchLen < maxMatchLength-zstdMinMatch-1 { repIndex-- start-- @@ -783,10 +771,7 @@ encodeLoop: // and have to do special offset treatment. startLimit := nextEmit + 1 - tMin := s - e.maxMatchOff - if tMin < 0 { - tMin = 0 - } + tMin := max(s-e.maxMatchOff, 0) for repIndex > tMin && start > startLimit && src[repIndex-1] == src[start-1] && seq.matchLen < maxMatchLength-zstdMinMatch-1 { repIndex-- start-- @@ -1005,10 +990,7 @@ encodeLoop: l := matched // Extend backwards - tMin := s - e.maxMatchOff - if tMin < 0 { - tMin = 0 - } + tMin := max(s-e.maxMatchOff, 0) for t > tMin && s > nextEmit && src[t-1] == src[s-1] && l < maxMatchLength { s-- t-- diff --git a/vendor/github.com/klauspost/compress/zstd/enc_dfast.go b/vendor/github.com/klauspost/compress/zstd/enc_dfast.go index d36be7bd8c2..cf8cad00dcf 100644 --- a/vendor/github.com/klauspost/compress/zstd/enc_dfast.go +++ b/vendor/github.com/klauspost/compress/zstd/enc_dfast.go @@ -13,7 +13,7 @@ const ( dFastLongLen = 8 // Bytes used for table hash dLongTableShardCnt = 1 << (dFastLongTableBits - dictShardBits) // Number of shards in the table - dLongTableShardSize = dFastLongTableSize / tableShardCnt // Size of an individual shard + dLongTableShardSize = dFastLongTableSize / dLongTableShardCnt // Size of an individual shard dFastShortTableBits = tableBits // Bits used in the short match table dFastShortTableSize = 1 << dFastShortTableBits // Size of the table @@ -149,10 +149,7 @@ encodeLoop: // and have to do special offset treatment. startLimit := nextEmit + 1 - tMin := s - e.maxMatchOff - if tMin < 0 { - tMin = 0 - } + tMin := max(s-e.maxMatchOff, 0) for repIndex > tMin && start > startLimit && src[repIndex-1] == src[start-1] && seq.matchLen < maxMatchLength-zstdMinMatch-1 { repIndex-- start-- @@ -266,10 +263,7 @@ encodeLoop: l := e.matchlen(s+4, t+4, src) + 4 // Extend backwards - tMin := s - e.maxMatchOff - if tMin < 0 { - tMin = 0 - } + tMin := max(s-e.maxMatchOff, 0) for t > tMin && s > nextEmit && src[t-1] == src[s-1] && l < maxMatchLength { s-- t-- @@ -462,10 +456,7 @@ encodeLoop: // and have to do special offset treatment. startLimit := nextEmit + 1 - tMin := s - e.maxMatchOff - if tMin < 0 { - tMin = 0 - } + tMin := max(s-e.maxMatchOff, 0) for repIndex > tMin && start > startLimit && src[repIndex-1] == src[start-1] { repIndex-- start-- @@ -576,10 +567,7 @@ encodeLoop: l := int32(matchLen(src[s+4:], src[t+4:])) + 4 // Extend backwards - tMin := s - e.maxMatchOff - if tMin < 0 { - tMin = 0 - } + tMin := max(s-e.maxMatchOff, 0) for t > tMin && s > nextEmit && src[t-1] == src[s-1] { s-- t-- @@ -809,10 +797,7 @@ encodeLoop: // and have to do special offset treatment. startLimit := nextEmit + 1 - tMin := s - e.maxMatchOff - if tMin < 0 { - tMin = 0 - } + tMin := max(s-e.maxMatchOff, 0) for repIndex > tMin && start > startLimit && src[repIndex-1] == src[start-1] && seq.matchLen < maxMatchLength-zstdMinMatch-1 { repIndex-- start-- @@ -927,10 +912,7 @@ encodeLoop: l := e.matchlen(s+4, t+4, src) + 4 // Extend backwards - tMin := s - e.maxMatchOff - if tMin < 0 { - tMin = 0 - } + tMin := max(s-e.maxMatchOff, 0) for t > tMin && s > nextEmit && src[t-1] == src[s-1] && l < maxMatchLength { s-- t-- diff --git a/vendor/github.com/klauspost/compress/zstd/enc_fast.go b/vendor/github.com/klauspost/compress/zstd/enc_fast.go index f45a3da7dae..9180a3a5820 100644 --- a/vendor/github.com/klauspost/compress/zstd/enc_fast.go +++ b/vendor/github.com/klauspost/compress/zstd/enc_fast.go @@ -143,10 +143,7 @@ encodeLoop: // and have to do special offset treatment. startLimit := nextEmit + 1 - sMin := s - e.maxMatchOff - if sMin < 0 { - sMin = 0 - } + sMin := max(s-e.maxMatchOff, 0) for repIndex > sMin && start > startLimit && src[repIndex-1] == src[start-1] && seq.matchLen < maxMatchLength-zstdMinMatch { repIndex-- start-- @@ -223,10 +220,7 @@ encodeLoop: l := e.matchlen(s+4, t+4, src) + 4 // Extend backwards - tMin := s - e.maxMatchOff - if tMin < 0 { - tMin = 0 - } + tMin := max(s-e.maxMatchOff, 0) for t > tMin && s > nextEmit && src[t-1] == src[s-1] && l < maxMatchLength { s-- t-- @@ -387,10 +381,7 @@ encodeLoop: // and have to do special offset treatment. startLimit := nextEmit + 1 - sMin := s - e.maxMatchOff - if sMin < 0 { - sMin = 0 - } + sMin := max(s-e.maxMatchOff, 0) for repIndex > sMin && start > startLimit && src[repIndex-1] == src[start-1] { repIndex-- start-- @@ -469,10 +460,7 @@ encodeLoop: l := e.matchlen(s+4, t+4, src) + 4 // Extend backwards - tMin := s - e.maxMatchOff - if tMin < 0 { - tMin = 0 - } + tMin := max(s-e.maxMatchOff, 0) for t > tMin && s > nextEmit && src[t-1] == src[s-1] { s-- t-- @@ -655,10 +643,7 @@ encodeLoop: // and have to do special offset treatment. startLimit := nextEmit + 1 - sMin := s - e.maxMatchOff - if sMin < 0 { - sMin = 0 - } + sMin := max(s-e.maxMatchOff, 0) for repIndex > sMin && start > startLimit && src[repIndex-1] == src[start-1] && seq.matchLen < maxMatchLength-zstdMinMatch { repIndex-- start-- @@ -735,10 +720,7 @@ encodeLoop: l := e.matchlen(s+4, t+4, src) + 4 // Extend backwards - tMin := s - e.maxMatchOff - if tMin < 0 { - tMin = 0 - } + tMin := max(s-e.maxMatchOff, 0) for t > tMin && s > nextEmit && src[t-1] == src[s-1] && l < maxMatchLength { s-- t-- diff --git a/vendor/github.com/klauspost/compress/zstd/framedec.go b/vendor/github.com/klauspost/compress/zstd/framedec.go index e47af66e7c9..d88f067e5c2 100644 --- a/vendor/github.com/klauspost/compress/zstd/framedec.go +++ b/vendor/github.com/klauspost/compress/zstd/framedec.go @@ -238,10 +238,7 @@ func (d *frameDec) reset(br byteBuffer) error { if d.WindowSize == 0 && d.SingleSegment { // We may not need window in this case. - d.WindowSize = d.FrameContentSize - if d.WindowSize < MinWindowSize { - d.WindowSize = MinWindowSize - } + d.WindowSize = max(d.FrameContentSize, MinWindowSize) if d.WindowSize > d.o.maxDecodedSize { if debugDecoder { printf("window size %d > max %d\n", d.WindowSize, d.o.maxWindowSize) diff --git a/vendor/github.com/klauspost/compress/zstd/fse_encoder.go b/vendor/github.com/klauspost/compress/zstd/fse_encoder.go index ab26326a8ff..3a0f4e7fbe6 100644 --- a/vendor/github.com/klauspost/compress/zstd/fse_encoder.go +++ b/vendor/github.com/klauspost/compress/zstd/fse_encoder.go @@ -149,7 +149,7 @@ func (s *fseEncoder) buildCTable() error { if v > largeLimit { s.zeroBits = true } - for nbOccurrences := int16(0); nbOccurrences < v; nbOccurrences++ { + for range v { tableSymbol[position] = symbol position = (position + step) & tableMask for position > highThreshold { diff --git a/vendor/github.com/klauspost/compress/zstd/seqdec.go b/vendor/github.com/klauspost/compress/zstd/seqdec.go index 9a7de82f9ef..0bfb0e43c7b 100644 --- a/vendor/github.com/klauspost/compress/zstd/seqdec.go +++ b/vendor/github.com/klauspost/compress/zstd/seqdec.go @@ -231,10 +231,7 @@ func (s *sequenceDecs) decodeSync(hist []byte) error { llTable, mlTable, ofTable := s.litLengths.fse.dt[:maxTablesize], s.matchLengths.fse.dt[:maxTablesize], s.offsets.fse.dt[:maxTablesize] llState, mlState, ofState := s.litLengths.state.state, s.matchLengths.state.state, s.offsets.state.state out := s.out - maxBlockSize := maxCompressedBlockSize - if s.windowSize < maxBlockSize { - maxBlockSize = s.windowSize - } + maxBlockSize := min(s.windowSize, maxCompressedBlockSize) if debugDecoder { println("decodeSync: decoding", seqs, "sequences", br.remain(), "bits remain on stream") diff --git a/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.go b/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.go index c59f17e07ad..1f8c3cec28c 100644 --- a/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.go +++ b/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.go @@ -79,10 +79,7 @@ func (s *sequenceDecs) decodeSyncSimple(hist []byte) (bool, error) { br := s.br - maxBlockSize := maxCompressedBlockSize - if s.windowSize < maxBlockSize { - maxBlockSize = s.windowSize - } + maxBlockSize := min(s.windowSize, maxCompressedBlockSize) ctx := decodeSyncAsmContext{ llTable: s.litLengths.fse.dt[:maxTablesize], @@ -237,10 +234,7 @@ func sequenceDecs_decode_56_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeAsmC func (s *sequenceDecs) decode(seqs []seqVals) error { br := s.br - maxBlockSize := maxCompressedBlockSize - if s.windowSize < maxBlockSize { - maxBlockSize = s.windowSize - } + maxBlockSize := min(s.windowSize, maxCompressedBlockSize) ctx := decodeAsmContext{ llTable: s.litLengths.fse.dt[:maxTablesize], diff --git a/vendor/github.com/klauspost/compress/zstd/simple_go124.go b/vendor/github.com/klauspost/compress/zstd/simple_go124.go new file mode 100644 index 00000000000..2efc0497bf9 --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/simple_go124.go @@ -0,0 +1,56 @@ +// Copyright 2025+ Klaus Post. All rights reserved. +// License information can be found in the LICENSE file. + +//go:build go1.24 + +package zstd + +import ( + "errors" + "runtime" + "sync" + "weak" +) + +var weakMu sync.Mutex +var simpleEnc weak.Pointer[Encoder] +var simpleDec weak.Pointer[Decoder] + +// EncodeTo appends the encoded data from src to dst. +func EncodeTo(dst []byte, src []byte) []byte { + weakMu.Lock() + enc := simpleEnc.Value() + if enc == nil { + var err error + enc, err = NewWriter(nil, WithEncoderConcurrency(runtime.NumCPU()), WithWindowSize(1<<20), WithLowerEncoderMem(true), WithZeroFrames(true)) + if err != nil { + panic("failed to create simple encoder: " + err.Error()) + } + simpleEnc = weak.Make(enc) + } + weakMu.Unlock() + + return enc.EncodeAll(src, dst) +} + +// DecodeTo appends the decoded data from src to dst. +// The maximum decoded size is 1GiB, +// not including what may already be in dst. +func DecodeTo(dst []byte, src []byte) ([]byte, error) { + weakMu.Lock() + dec := simpleDec.Value() + if dec == nil { + var err error + dec, err = NewReader(nil, WithDecoderConcurrency(runtime.NumCPU()), WithDecoderLowmem(true), WithDecoderMaxMemory(1<<30)) + if err != nil { + weakMu.Unlock() + return nil, errors.New("failed to create simple decoder: " + err.Error()) + } + runtime.SetFinalizer(dec, func(d *Decoder) { + d.Close() + }) + simpleDec = weak.Make(dec) + } + weakMu.Unlock() + return dec.DecodeAll(src, dst) +} diff --git a/vendor/github.com/klauspost/compress/zstd/snappy.go b/vendor/github.com/klauspost/compress/zstd/snappy.go index a17381b8f89..336c2889304 100644 --- a/vendor/github.com/klauspost/compress/zstd/snappy.go +++ b/vendor/github.com/klauspost/compress/zstd/snappy.go @@ -257,7 +257,7 @@ func (r *SnappyConverter) Convert(in io.Reader, w io.Writer) (int64, error) { if !r.readFull(r.buf[:len(snappyMagicBody)], false) { return written, r.err } - for i := 0; i < len(snappyMagicBody); i++ { + for i := range len(snappyMagicBody) { if r.buf[i] != snappyMagicBody[i] { println("r.buf[i] != snappyMagicBody[i]", r.buf[i], snappyMagicBody[i], i) r.err = ErrSnappyCorrupt diff --git a/vendor/github.com/klauspost/compress/zstd/zip.go b/vendor/github.com/klauspost/compress/zstd/zip.go index 29c15c8c4ef..3198d718926 100644 --- a/vendor/github.com/klauspost/compress/zstd/zip.go +++ b/vendor/github.com/klauspost/compress/zstd/zip.go @@ -19,7 +19,7 @@ const ZipMethodWinZip = 93 const ZipMethodPKWare = 20 // zipReaderPool is the default reader pool. -var zipReaderPool = sync.Pool{New: func() interface{} { +var zipReaderPool = sync.Pool{New: func() any { z, err := NewReader(nil, WithDecoderLowmem(true), WithDecoderMaxWindow(128<<20), WithDecoderConcurrency(1)) if err != nil { panic(err) diff --git a/vendor/github.com/klauspost/compress/zstd/zstd.go b/vendor/github.com/klauspost/compress/zstd/zstd.go index 6252b46ae6f..1a869710d2c 100644 --- a/vendor/github.com/klauspost/compress/zstd/zstd.go +++ b/vendor/github.com/klauspost/compress/zstd/zstd.go @@ -98,13 +98,13 @@ var ( ErrDecoderNilInput = errors.New("nil input provided as reader") ) -func println(a ...interface{}) { +func println(a ...any) { if debug || debugDecoder || debugEncoder { log.Println(a...) } } -func printf(format string, a ...interface{}) { +func printf(format string, a ...any) { if debug || debugDecoder || debugEncoder { log.Printf(format, a...) } diff --git a/vendor/github.com/onsi/ginkgo/v2/CHANGELOG.md b/vendor/github.com/onsi/ginkgo/v2/CHANGELOG.md index 9db388356cc..f3ed259c1e8 100644 --- a/vendor/github.com/onsi/ginkgo/v2/CHANGELOG.md +++ b/vendor/github.com/onsi/ginkgo/v2/CHANGELOG.md @@ -1,3 +1,31 @@ +## 2.27.1 + +### Fixes +- Fix Ginkgo Reporter slice-bounds panic [606c1cb] +- Bug Fix: Add GinkoTBWrapper.Attr() and GinkoTBWrapper.Output() [a6463b3] + +## 2.27.0 + +### Features + +#### Transforming Nodes during Tree Construction + +This release adds support for `NodeArgsTransformer`s that can be registered with `AddTreeConstructionNodeArgsTransformer`. + +These are called during the tree construction phase as nodes are constructed and can modify the node strings and decorators. This enables frameworks built on top of Ginkgo to modify Ginkgo nodes and enforce conventions. + +Learn more [here](https://onsi.github.io/ginkgo/#advanced-transforming-node-arguments-during-tree-construction). + +#### Spec Prioritization + +A new `SpecPriority(int)` decorator has been added. Ginkgo will honor priority when ordering specs, ensuring that higher priority specs start running before lower priority specs + +Learn more [here](https://onsi.github.io/ginkgo/#prioritizing-specs). + +### Maintenance +- Bump rexml from 3.4.0 to 3.4.2 in /docs (#1595) [1333dae] +- Bump github.com/gkampitakis/go-snaps from 0.5.14 to 0.5.15 (#1600) [17ae63e] + ## 2.26.0 ### Features diff --git a/vendor/github.com/onsi/ginkgo/v2/core_dsl.go b/vendor/github.com/onsi/ginkgo/v2/core_dsl.go index ec41e8837c8..7e165e47382 100644 --- a/vendor/github.com/onsi/ginkgo/v2/core_dsl.go +++ b/vendor/github.com/onsi/ginkgo/v2/core_dsl.go @@ -501,6 +501,38 @@ func pushNode(node internal.Node, errors []error) bool { return true } +// NodeArgsTransformer is a hook which is called by the test construction DSL methods +// before creating the new node. If it returns any error, the test suite +// prints those errors and exits. The text and arguments can be modified, +// which includes directly changing the args slice that is passed in. +// Arguments have been flattened already, i.e. none of the entries in args is another []any. +// The result may be nested. +// +// The node type is provided for information and remains the same. +// +// The offset is valid for calling NewLocation directly in the +// implementation of TransformNodeArgs to find the location where +// the Ginkgo DSL function is called. An additional offset supplied +// by the caller via args is already included. +// +// A NodeArgsTransformer can be registered with AddTreeConstructionNodeArgsTransformer. +type NodeArgsTransformer func(nodeType types.NodeType, offset Offset, text string, args []any) (string, []any, []error) + +// AddTreeConstructionNodeArgsTransformer registers a NodeArgsTransformer. +// Only nodes which get created after registering a NodeArgsTransformer +// are transformed by it. The returned function can be called to +// unregister the transformer. +// +// Both may only be called during the construction phase. +// +// If there is more than one registered transformer, then the most +// recently added ones get called first. +func AddTreeConstructionNodeArgsTransformer(transformer NodeArgsTransformer) func() { + // This conversion could be avoided with a type alias, but type aliases make + // developer documentation less useful. + return internal.AddTreeConstructionNodeArgsTransformer(internal.NodeArgsTransformer(transformer)) +} + /* Describe nodes are Container nodes that allow you to organize your specs. A Describe node's closure can contain any number of Setup nodes (e.g. BeforeEach, AfterEach, JustBeforeEach), and Subject nodes (i.e. It). @@ -512,7 +544,7 @@ You can learn more at https://onsi.github.io/ginkgo/#organizing-specs-with-conta In addition, container nodes can be decorated with a variety of decorators. You can learn more here: https://onsi.github.io/ginkgo/#decorator-reference */ func Describe(text string, args ...any) bool { - return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeContainer, text, args...)) + return pushNode(internal.NewNode(internal.TransformNewNodeArgs(exitIfErrors, deprecationTracker, types.NodeTypeContainer, text, args...))) } /* @@ -520,7 +552,7 @@ FDescribe focuses specs within the Describe block. */ func FDescribe(text string, args ...any) bool { args = append(args, internal.Focus) - return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeContainer, text, args...)) + return pushNode(internal.NewNode(internal.TransformNewNodeArgs(exitIfErrors, deprecationTracker, types.NodeTypeContainer, text, args...))) } /* @@ -528,7 +560,7 @@ PDescribe marks specs within the Describe block as pending. */ func PDescribe(text string, args ...any) bool { args = append(args, internal.Pending) - return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeContainer, text, args...)) + return pushNode(internal.NewNode(internal.TransformNewNodeArgs(exitIfErrors, deprecationTracker, types.NodeTypeContainer, text, args...))) } /* @@ -541,21 +573,21 @@ var XDescribe = PDescribe /* Context is an alias for Describe - it generates the exact same kind of Container node */ var Context, FContext, PContext, XContext = Describe, FDescribe, PDescribe, XDescribe -/* When is an alias for Describe - it generates the exact same kind of Container node */ +/* When is an alias for Describe - it generates the exact same kind of Container node with "when " as prefix for the text. */ func When(text string, args ...any) bool { - return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeContainer, "when "+text, args...)) + return pushNode(internal.NewNode(internal.TransformNewNodeArgs(exitIfErrors, deprecationTracker, types.NodeTypeContainer, "when "+text, args...))) } -/* When is an alias for Describe - it generates the exact same kind of Container node */ +/* When is an alias for Describe - it generates the exact same kind of Container node with "when " as prefix for the text. */ func FWhen(text string, args ...any) bool { args = append(args, internal.Focus) - return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeContainer, "when "+text, args...)) + return pushNode(internal.NewNode(internal.TransformNewNodeArgs(exitIfErrors, deprecationTracker, types.NodeTypeContainer, "when "+text, args...))) } /* When is an alias for Describe - it generates the exact same kind of Container node */ func PWhen(text string, args ...any) bool { args = append(args, internal.Pending) - return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeContainer, "when "+text, args...)) + return pushNode(internal.NewNode(internal.TransformNewNodeArgs(exitIfErrors, deprecationTracker, types.NodeTypeContainer, "when "+text, args...))) } var XWhen = PWhen @@ -571,7 +603,7 @@ You can learn more at https://onsi.github.io/ginkgo/#spec-subjects-it In addition, subject nodes can be decorated with a variety of decorators. You can learn more here: https://onsi.github.io/ginkgo/#decorator-reference */ func It(text string, args ...any) bool { - return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeIt, text, args...)) + return pushNode(internal.NewNode(internal.TransformNewNodeArgs(exitIfErrors, deprecationTracker, types.NodeTypeIt, text, args...))) } /* @@ -579,7 +611,7 @@ FIt allows you to focus an individual It. */ func FIt(text string, args ...any) bool { args = append(args, internal.Focus) - return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeIt, text, args...)) + return pushNode(internal.NewNode(internal.TransformNewNodeArgs(exitIfErrors, deprecationTracker, types.NodeTypeIt, text, args...))) } /* @@ -587,7 +619,7 @@ PIt allows you to mark an individual It as pending. */ func PIt(text string, args ...any) bool { args = append(args, internal.Pending) - return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeIt, text, args...)) + return pushNode(internal.NewNode(internal.TransformNewNodeArgs(exitIfErrors, deprecationTracker, types.NodeTypeIt, text, args...))) } /* @@ -634,7 +666,7 @@ You can learn more here: https://onsi.github.io/ginkgo/#suite-setup-and-cleanup- func BeforeSuite(body any, args ...any) bool { combinedArgs := []any{body} combinedArgs = append(combinedArgs, args...) - return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeBeforeSuite, "", combinedArgs...)) + return pushNode(internal.NewNode(internal.TransformNewNodeArgs(exitIfErrors, deprecationTracker, types.NodeTypeBeforeSuite, "", combinedArgs...))) } /* @@ -653,7 +685,7 @@ You can learn more here: https://onsi.github.io/ginkgo/#suite-setup-and-cleanup- func AfterSuite(body any, args ...any) bool { combinedArgs := []any{body} combinedArgs = append(combinedArgs, args...) - return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeAfterSuite, "", combinedArgs...)) + return pushNode(internal.NewNode(internal.TransformNewNodeArgs(exitIfErrors, deprecationTracker, types.NodeTypeAfterSuite, "", combinedArgs...))) } /* @@ -691,7 +723,7 @@ func SynchronizedBeforeSuite(process1Body any, allProcessBody any, args ...any) combinedArgs := []any{process1Body, allProcessBody} combinedArgs = append(combinedArgs, args...) - return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeSynchronizedBeforeSuite, "", combinedArgs...)) + return pushNode(internal.NewNode(internal.TransformNewNodeArgs(exitIfErrors, deprecationTracker, types.NodeTypeSynchronizedBeforeSuite, "", combinedArgs...))) } /* @@ -711,7 +743,7 @@ func SynchronizedAfterSuite(allProcessBody any, process1Body any, args ...any) b combinedArgs := []any{allProcessBody, process1Body} combinedArgs = append(combinedArgs, args...) - return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeSynchronizedAfterSuite, "", combinedArgs...)) + return pushNode(internal.NewNode(internal.TransformNewNodeArgs(exitIfErrors, deprecationTracker, types.NodeTypeSynchronizedAfterSuite, "", combinedArgs...))) } /* @@ -724,7 +756,7 @@ You cannot nest any other Ginkgo nodes within a BeforeEach node's closure. You can learn more here: https://onsi.github.io/ginkgo/#extracting-common-setup-beforeeach */ func BeforeEach(args ...any) bool { - return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeBeforeEach, "", args...)) + return pushNode(internal.NewNode(internal.TransformNewNodeArgs(exitIfErrors, deprecationTracker, types.NodeTypeBeforeEach, "", args...))) } /* @@ -737,7 +769,7 @@ You cannot nest any other Ginkgo nodes within a JustBeforeEach node's closure. You can learn more and see some examples here: https://onsi.github.io/ginkgo/#separating-creation-and-configuration-justbeforeeach */ func JustBeforeEach(args ...any) bool { - return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeJustBeforeEach, "", args...)) + return pushNode(internal.NewNode(internal.TransformNewNodeArgs(exitIfErrors, deprecationTracker, types.NodeTypeJustBeforeEach, "", args...))) } /* @@ -752,7 +784,7 @@ You cannot nest any other Ginkgo nodes within an AfterEach node's closure. You can learn more here: https://onsi.github.io/ginkgo/#spec-cleanup-aftereach-and-defercleanup */ func AfterEach(args ...any) bool { - return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeAfterEach, "", args...)) + return pushNode(internal.NewNode(internal.TransformNewNodeArgs(exitIfErrors, deprecationTracker, types.NodeTypeAfterEach, "", args...))) } /* @@ -764,7 +796,7 @@ You cannot nest any other Ginkgo nodes within a JustAfterEach node's closure. You can learn more and see some examples here: https://onsi.github.io/ginkgo/#separating-diagnostics-collection-and-teardown-justaftereach */ func JustAfterEach(args ...any) bool { - return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeJustAfterEach, "", args...)) + return pushNode(internal.NewNode(internal.TransformNewNodeArgs(exitIfErrors, deprecationTracker, types.NodeTypeJustAfterEach, "", args...))) } /* @@ -779,7 +811,7 @@ You can learn more about Ordered Containers at: https://onsi.github.io/ginkgo/#o And you can learn more about BeforeAll at: https://onsi.github.io/ginkgo/#setup-in-ordered-containers-beforeall-and-afterall */ func BeforeAll(args ...any) bool { - return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeBeforeAll, "", args...)) + return pushNode(internal.NewNode(internal.TransformNewNodeArgs(exitIfErrors, deprecationTracker, types.NodeTypeBeforeAll, "", args...))) } /* @@ -796,7 +828,7 @@ You can learn more about Ordered Containers at: https://onsi.github.io/ginkgo/#o And you can learn more about AfterAll at: https://onsi.github.io/ginkgo/#setup-in-ordered-containers-beforeall-and-afterall */ func AfterAll(args ...any) bool { - return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeAfterAll, "", args...)) + return pushNode(internal.NewNode(internal.TransformNewNodeArgs(exitIfErrors, deprecationTracker, types.NodeTypeAfterAll, "", args...))) } /* diff --git a/vendor/github.com/onsi/ginkgo/v2/decorator_dsl.go b/vendor/github.com/onsi/ginkgo/v2/decorator_dsl.go index 8bee5acebdb..e331d7cf8cd 100644 --- a/vendor/github.com/onsi/ginkgo/v2/decorator_dsl.go +++ b/vendor/github.com/onsi/ginkgo/v2/decorator_dsl.go @@ -154,6 +154,13 @@ Nodes that do not finish within a GracePeriod will be leaked and Ginkgo will pro */ type GracePeriod = internal.GracePeriod +/* +SpecPriority allows you to assign a priority to a spec or container. + +Specs with higher priority will be scheduled to run before specs with lower priority. The default priority is 0 and negative priorities are allowed. +*/ +type SpecPriority = internal.SpecPriority + /* SuppressProgressReporting is a decorator that allows you to disable progress reporting of a particular node. This is useful if `ginkgo -v -progress` is generating too much noise; particularly if you have a `ReportAfterEach` node that is running for every skipped spec and is generating lots of progress reports. diff --git a/vendor/github.com/onsi/ginkgo/v2/ginkgo_t_dsl.go b/vendor/github.com/onsi/ginkgo/v2/ginkgo_t_dsl.go index cabf2814571..40d1e1ab5ce 100644 --- a/vendor/github.com/onsi/ginkgo/v2/ginkgo_t_dsl.go +++ b/vendor/github.com/onsi/ginkgo/v2/ginkgo_t_dsl.go @@ -190,3 +190,9 @@ func (g *GinkgoTBWrapper) Skipped() bool { func (g *GinkgoTBWrapper) TempDir() string { return g.GinkgoT.TempDir() } +func (g *GinkgoTBWrapper) Attr(key, value string) { + g.GinkgoT.Attr(key, value) +} +func (g *GinkgoTBWrapper) Output() io.Writer { + return g.GinkgoT.Output() +} diff --git a/vendor/github.com/onsi/ginkgo/v2/internal/group.go b/vendor/github.com/onsi/ginkgo/v2/internal/group.go index b88fe2060a5..cc794903e7e 100644 --- a/vendor/github.com/onsi/ginkgo/v2/internal/group.go +++ b/vendor/github.com/onsi/ginkgo/v2/internal/group.go @@ -110,6 +110,7 @@ func newGroup(suite *Suite) *group { } } +// initialReportForSpec constructs a new SpecReport right before running the spec. func (g *group) initialReportForSpec(spec Spec) types.SpecReport { return types.SpecReport{ ContainerHierarchyTexts: spec.Nodes.WithType(types.NodeTypeContainer).Texts(), @@ -127,6 +128,35 @@ func (g *group) initialReportForSpec(spec Spec) types.SpecReport { IsInOrderedContainer: !spec.Nodes.FirstNodeMarkedOrdered().IsZero(), MaxFlakeAttempts: spec.Nodes.GetMaxFlakeAttempts(), MaxMustPassRepeatedly: spec.Nodes.GetMaxMustPassRepeatedly(), + SpecPriority: spec.Nodes.GetSpecPriority(), + } +} + +// constructionNodeReportForTreeNode constructs a new SpecReport right before invoking the body +// of a container node during construction of the full tree. +func constructionNodeReportForTreeNode(node *TreeNode) *types.ConstructionNodeReport { + var report types.ConstructionNodeReport + // Walk up the tree and set attributes accordingly. + addNodeToReportForNode(&report, node) + return &report +} + +// addNodeToReportForNode is conceptually similar to initialReportForSpec and therefore placed here +// although it doesn't do anything with a group. +func addNodeToReportForNode(report *types.ConstructionNodeReport, node *TreeNode) { + if node.Parent != nil { + // First add the parent node, then the current one. + addNodeToReportForNode(report, node.Parent) + } + report.ContainerHierarchyTexts = append(report.ContainerHierarchyTexts, node.Node.Text) + report.ContainerHierarchyLocations = append(report.ContainerHierarchyLocations, node.Node.CodeLocation) + report.ContainerHierarchyLabels = append(report.ContainerHierarchyLabels, node.Node.Labels) + report.ContainerHierarchySemVerConstraints = append(report.ContainerHierarchySemVerConstraints, node.Node.SemVerConstraints) + if node.Node.MarkedSerial { + report.IsSerial = true + } + if node.Node.MarkedOrdered { + report.IsInOrderedContainer = true } } diff --git a/vendor/github.com/onsi/ginkgo/v2/internal/node.go b/vendor/github.com/onsi/ginkgo/v2/internal/node.go index 647368feacb..2bccec2dbf0 100644 --- a/vendor/github.com/onsi/ginkgo/v2/internal/node.go +++ b/vendor/github.com/onsi/ginkgo/v2/internal/node.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "reflect" + "slices" "sort" "sync" "time" @@ -46,22 +47,24 @@ type Node struct { ReportEachBody func(SpecContext, types.SpecReport) ReportSuiteBody func(SpecContext, types.Report) - MarkedFocus bool - MarkedPending bool - MarkedSerial bool - MarkedOrdered bool - MarkedContinueOnFailure bool - MarkedOncePerOrdered bool - FlakeAttempts int - MustPassRepeatedly int - Labels Labels - SemVerConstraints SemVerConstraints - PollProgressAfter time.Duration - PollProgressInterval time.Duration - NodeTimeout time.Duration - SpecTimeout time.Duration - GracePeriod time.Duration - AroundNodes types.AroundNodes + MarkedFocus bool + MarkedPending bool + MarkedSerial bool + MarkedOrdered bool + MarkedContinueOnFailure bool + MarkedOncePerOrdered bool + FlakeAttempts int + MustPassRepeatedly int + Labels Labels + SemVerConstraints SemVerConstraints + PollProgressAfter time.Duration + PollProgressInterval time.Duration + NodeTimeout time.Duration + SpecTimeout time.Duration + GracePeriod time.Duration + AroundNodes types.AroundNodes + HasExplicitlySetSpecPriority bool + SpecPriority int NodeIDWhereCleanupWasGenerated uint } @@ -92,6 +95,7 @@ type PollProgressAfter time.Duration type NodeTimeout time.Duration type SpecTimeout time.Duration type GracePeriod time.Duration +type SpecPriority int type Labels []string @@ -182,6 +186,8 @@ func isDecoration(arg any) bool { return true case t == reflect.TypeOf(types.AroundNodeDecorator{}): return true + case t == reflect.TypeOf(SpecPriority(0)): + return true case t.Kind() == reflect.Slice && isSliceOfDecorations(arg): return true default: @@ -227,7 +233,7 @@ func NewNode(deprecationTracker *types.DeprecationTracker, nodeType types.NodeTy } } - args = unrollInterfaceSlice(args) + args = UnrollInterfaceSlice(args) remainingArgs := []any{} // First get the CodeLocation up-to-date @@ -322,6 +328,12 @@ func NewNode(deprecationTracker *types.DeprecationTracker, nodeType types.NodeTy if nodeType.Is(types.NodeTypeContainer) { appendError(types.GinkgoErrors.InvalidDecoratorForNodeType(node.CodeLocation, nodeType, "GracePeriod")) } + case t == reflect.TypeOf(SpecPriority(0)): + if !nodeType.Is(types.NodeTypesForContainerAndIt) { + appendError(types.GinkgoErrors.InvalidDecoratorForNodeType(node.CodeLocation, nodeType, "SpecPriority")) + } + node.SpecPriority = int(arg.(SpecPriority)) + node.HasExplicitlySetSpecPriority = true case t == reflect.TypeOf(types.AroundNodeDecorator{}): node.AroundNodes = append(node.AroundNodes, arg.(types.AroundNodeDecorator)) case t == reflect.TypeOf(Labels{}): @@ -636,7 +648,7 @@ func NewCleanupNode(deprecationTracker *types.DeprecationTracker, fail func(stri }) } - return NewNode(deprecationTracker, types.NodeTypeCleanupInvalid, "", finalArgs...) + return NewNode(deprecationTracker, types.NodeTypeCleanupInvalid, "", finalArgs) } func (n Node) IsZero() bool { @@ -983,7 +995,16 @@ func (n Nodes) GetMaxMustPassRepeatedly() int { return maxMustPassRepeatedly } -func unrollInterfaceSlice(args any) []any { +func (n Nodes) GetSpecPriority() int { + for i := len(n) - 1; i >= 0; i-- { + if n[i].HasExplicitlySetSpecPriority { + return n[i].SpecPriority + } + } + return 0 +} + +func UnrollInterfaceSlice(args any) []any { v := reflect.ValueOf(args) if v.Kind() != reflect.Slice { return []any{args} @@ -992,10 +1013,66 @@ func unrollInterfaceSlice(args any) []any { for i := 0; i < v.Len(); i++ { el := reflect.ValueOf(v.Index(i).Interface()) if el.Kind() == reflect.Slice && el.Type() != reflect.TypeOf(Labels{}) && el.Type() != reflect.TypeOf(SemVerConstraints{}) { - out = append(out, unrollInterfaceSlice(el.Interface())...) + out = append(out, UnrollInterfaceSlice(el.Interface())...) } else { out = append(out, v.Index(i).Interface()) } } return out } + +type NodeArgsTransformer func(nodeType types.NodeType, offset Offset, text string, args []any) (string, []any, []error) + +func AddTreeConstructionNodeArgsTransformer(transformer NodeArgsTransformer) func() { + id := nodeArgsTransformerCounter + nodeArgsTransformerCounter++ + nodeArgsTransformers = append(nodeArgsTransformers, registeredNodeArgsTransformer{id, transformer}) + return func() { + nodeArgsTransformers = slices.DeleteFunc(nodeArgsTransformers, func(transformer registeredNodeArgsTransformer) bool { + return transformer.id == id + }) + } +} + +var ( + nodeArgsTransformerCounter int64 + nodeArgsTransformers []registeredNodeArgsTransformer +) + +type registeredNodeArgsTransformer struct { + id int64 + transformer NodeArgsTransformer +} + +// TransformNewNodeArgs is the helper for DSL functions which handles NodeArgsTransformers. +// +// Its return valus are intentionally the same as the internal.NewNode parameters, +// which makes it possible to chain the invocations: +// +// NewNode(transformNewNodeArgs(...)) +func TransformNewNodeArgs(exitIfErrors func([]error), deprecationTracker *types.DeprecationTracker, nodeType types.NodeType, text string, args ...any) (*types.DeprecationTracker, types.NodeType, string, []any) { + var errs []error + + // Most recent first... + // + // This intentionally doesn't use slices.Backward because + // using iterators influences stack unwinding. + for i := len(nodeArgsTransformers) - 1; i >= 0; i-- { + transformer := nodeArgsTransformers[i].transformer + args = UnrollInterfaceSlice(args) + + // We do not really need to recompute this on additional loop iterations, + // but its fast and simpler this way. + var offset Offset + for _, arg := range args { + if o, ok := arg.(Offset); ok { + offset = o + } + } + offset += 3 // The DSL function, this helper, and the TransformNodeArgs implementation. + + text, args, errs = transformer(nodeType, offset, text, args) + exitIfErrors(errs) + } + return deprecationTracker, nodeType, text, args +} diff --git a/vendor/github.com/onsi/ginkgo/v2/internal/ordering.go b/vendor/github.com/onsi/ginkgo/v2/internal/ordering.go index 84eea0a59e6..da58d54f957 100644 --- a/vendor/github.com/onsi/ginkgo/v2/internal/ordering.go +++ b/vendor/github.com/onsi/ginkgo/v2/internal/ordering.go @@ -125,7 +125,7 @@ func OrderSpecs(specs Specs, suiteConfig types.SuiteConfig) (GroupedSpecIndices, // pick out a representative spec representativeSpec := specs[executionGroups[groupID][0]] - // and grab the node on the spec that will represent which shufflable group this execution group belongs tu + // and grab the node on the spec that will represent which shufflable group this execution group belongs to shufflableGroupingNode := representativeSpec.Nodes.FirstNodeWithType(nodeTypesToShuffle) //add the execution group to its shufflable group @@ -138,14 +138,35 @@ func OrderSpecs(specs Specs, suiteConfig types.SuiteConfig) (GroupedSpecIndices, } } + // now, for each shuffleable group, we compute the priority + shufflableGroupingIDPriorities := map[uint]int{} + for shufflableGroupingID, groupIDs := range shufflableGroupingIDToGroupIDs { + // the priority of a shufflable grouping is the max priority of any spec in any execution group in the shufflable grouping + maxPriority := -1 << 31 // min int + for _, groupID := range groupIDs { + for _, specIdx := range executionGroups[groupID] { + specPriority := specs[specIdx].Nodes.GetSpecPriority() + maxPriority = max(specPriority, maxPriority) + } + } + shufflableGroupingIDPriorities[shufflableGroupingID] = maxPriority + } + // now we permute the sorted shufflable grouping IDs and build the ordered Groups - orderedGroups := GroupedSpecIndices{} permutation := r.Perm(len(shufflableGroupingIDs)) - for _, j := range permutation { - //let's get the execution group IDs for this shufflable group: - executionGroupIDsForJ := shufflableGroupingIDToGroupIDs[shufflableGroupingIDs[j]] - // and we'll add their associated specindices to the orderedGroups slice: - for _, executionGroupID := range executionGroupIDsForJ { + shuffledGroupingIds := make([]uint, len(shufflableGroupingIDs)) + for i, j := range permutation { + shuffledGroupingIds[i] = shufflableGroupingIDs[j] + } + // now, we need to stable sort the shuffledGroupingIds by priority (higher priority first) + sort.SliceStable(shuffledGroupingIds, func(i, j int) bool { + return shufflableGroupingIDPriorities[shuffledGroupingIds[i]] > shufflableGroupingIDPriorities[shuffledGroupingIds[j]] + }) + + // we can now take these prioritized, shuffled, groupings and form the final set of ordered spec groups + orderedGroups := GroupedSpecIndices{} + for _, id := range shuffledGroupingIds { + for _, executionGroupID := range shufflableGroupingIDToGroupIDs[id] { orderedGroups = append(orderedGroups, executionGroups[executionGroupID]) } } diff --git a/vendor/github.com/onsi/ginkgo/v2/internal/suite.go b/vendor/github.com/onsi/ginkgo/v2/internal/suite.go index 14a0688f89e..ef76cd099e6 100644 --- a/vendor/github.com/onsi/ginkgo/v2/internal/suite.go +++ b/vendor/github.com/onsi/ginkgo/v2/internal/suite.go @@ -42,6 +42,8 @@ type Suite struct { config types.SuiteConfig deadline time.Time + currentConstructionNodeReport *types.ConstructionNodeReport + skipAll bool report types.Report currentSpecReport types.SpecReport @@ -203,6 +205,14 @@ func (suite *Suite) PushNode(node Node) error { err = types.GinkgoErrors.CaughtPanicDuringABuildPhase(e, node.CodeLocation) } }() + + // Ensure that code running in the body of the container node + // has access to information about the current container node(s). + suite.currentConstructionNodeReport = constructionNodeReportForTreeNode(suite.tree) + defer func() { + suite.currentConstructionNodeReport = nil + }() + node.Body(nil) return err }() @@ -332,6 +342,16 @@ func (suite *Suite) By(text string, callback ...func()) error { return nil } +func (suite *Suite) CurrentConstructionNodeReport() types.ConstructionNodeReport { + suite.selectiveLock.Lock() + defer suite.selectiveLock.Unlock() + report := suite.currentConstructionNodeReport + if report == nil { + panic("CurrentConstructionNodeReport may only be called during construction of the spec tree") + } + return *report +} + /* Spec Running methods - used during PhaseRun */ diff --git a/vendor/github.com/onsi/ginkgo/v2/reporters/default_reporter.go b/vendor/github.com/onsi/ginkgo/v2/reporters/default_reporter.go index 8c3714b8ae6..026d9cf9b37 100644 --- a/vendor/github.com/onsi/ginkgo/v2/reporters/default_reporter.go +++ b/vendor/github.com/onsi/ginkgo/v2/reporters/default_reporter.go @@ -381,13 +381,22 @@ func (r *DefaultReporter) emitTimeline(indent uint, report types.SpecReport, tim cursor := 0 for _, entry := range timeline { tl := entry.GetTimelineLocation() - if tl.Offset < len(gw) { - r.emit(r.fi(indent, "%s", gw[cursor:tl.Offset])) - cursor = tl.Offset - } else if cursor < len(gw) { + + end := tl.Offset + if end > len(gw) { + end = len(gw) + } + if end < cursor { + end = cursor + } + if cursor < end && cursor <= len(gw) && end <= len(gw) { + r.emit(r.fi(indent, "%s", gw[cursor:end])) + cursor = end + } else if cursor < len(gw) && end == len(gw) { r.emit(r.fi(indent, "%s", gw[cursor:])) cursor = len(gw) } + switch x := entry.(type) { case types.Failure: if isVeryVerbose { @@ -404,7 +413,7 @@ func (r *DefaultReporter) emitTimeline(indent uint, report types.SpecReport, tim case types.ReportEntry: r.emitReportEntry(indent, x) case types.ProgressReport: - r.emitProgressReport(indent, false, false, x) + r.emitProgressReport(indent, false, isVeryVerbose, x) case types.SpecEvent: if isVeryVerbose || !x.IsOnlyVisibleAtVeryVerbose() || r.conf.ShowNodeEvents { r.emitSpecEvent(indent, x, isVeryVerbose) diff --git a/vendor/github.com/onsi/ginkgo/v2/reporting_dsl.go b/vendor/github.com/onsi/ginkgo/v2/reporting_dsl.go index dd135054d4a..4e86dba84d8 100644 --- a/vendor/github.com/onsi/ginkgo/v2/reporting_dsl.go +++ b/vendor/github.com/onsi/ginkgo/v2/reporting_dsl.go @@ -27,6 +27,8 @@ CurrentSpecReport returns information about the current running spec. The returned object is a types.SpecReport which includes helper methods to make extracting information about the spec easier. +During construction of the test tree the result is empty. + You can learn more about SpecReport here: https://pkg.go.dev/github.com/onsi/ginkgo/types#SpecReport You can learn more about CurrentSpecReport() here: https://onsi.github.io/ginkgo/#getting-a-report-for-the-current-spec */ @@ -34,6 +36,31 @@ func CurrentSpecReport() SpecReport { return global.Suite.CurrentSpecReport() } +/* +ConstructionNodeReport describes the container nodes during construction of +the spec tree. It provides a subset of the information that is provided +by SpecReport at runtime. + +It is documented here: [types.ConstructionNodeReport] +*/ +type ConstructionNodeReport = types.ConstructionNodeReport + +/* +CurrentConstructionNodeReport returns information about the current container nodes +that are leading to the current path in the spec tree. +The returned object is a types.ConstructionNodeReport which includes helper methods +to make extracting information about the spec easier. + +May only be called during construction of the spec tree. It panics when +called while tests are running. Use CurrentSpecReport instead in that +phase. + +You can learn more about ConstructionNodeReport here: [types.ConstructionNodeReport] +*/ +func CurrentTreeConstructionNodeReport() ConstructionNodeReport { + return global.Suite.CurrentConstructionNodeReport() +} + /* ReportEntryVisibility governs the visibility of ReportEntries in Ginkgo's console reporter @@ -92,7 +119,7 @@ func ReportBeforeEach(body any, args ...any) bool { combinedArgs := []any{body} combinedArgs = append(combinedArgs, args...) - return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeReportBeforeEach, "", combinedArgs...)) + return pushNode(internal.NewNode(internal.TransformNewNodeArgs(exitIfErrors, deprecationTracker, types.NodeTypeReportBeforeEach, "", combinedArgs...))) } /* @@ -116,7 +143,7 @@ func ReportAfterEach(body any, args ...any) bool { combinedArgs := []any{body} combinedArgs = append(combinedArgs, args...) - return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeReportAfterEach, "", combinedArgs...)) + return pushNode(internal.NewNode(internal.TransformNewNodeArgs(exitIfErrors, deprecationTracker, types.NodeTypeReportAfterEach, "", combinedArgs...))) } /* @@ -145,7 +172,7 @@ You can learn about interruptible nodes here: https://onsi.github.io/ginkgo/#spe func ReportBeforeSuite(body any, args ...any) bool { combinedArgs := []any{body} combinedArgs = append(combinedArgs, args...) - return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeReportBeforeSuite, "", combinedArgs...)) + return pushNode(internal.NewNode(internal.TransformNewNodeArgs(exitIfErrors, deprecationTracker, types.NodeTypeReportBeforeSuite, "", combinedArgs...))) } /* @@ -177,7 +204,7 @@ You can learn about interruptible nodes here: https://onsi.github.io/ginkgo/#spe func ReportAfterSuite(text string, body any, args ...any) bool { combinedArgs := []any{body} combinedArgs = append(combinedArgs, args...) - return pushNode(internal.NewNode(deprecationTracker, types.NodeTypeReportAfterSuite, text, combinedArgs...)) + return pushNode(internal.NewNode(internal.TransformNewNodeArgs(exitIfErrors, deprecationTracker, types.NodeTypeReportAfterSuite, text, combinedArgs...))) } func registerReportAfterSuiteNodeForAutogeneratedReports(reporterConfig types.ReporterConfig) { @@ -222,9 +249,11 @@ func registerReportAfterSuiteNodeForAutogeneratedReports(reporterConfig types.Re flags = append(flags, "--teamcity-report") } pushNode(internal.NewNode( - deprecationTracker, types.NodeTypeReportAfterSuite, - fmt.Sprintf("Autogenerated ReportAfterSuite for %s", strings.Join(flags, " ")), - body, - types.NewCustomCodeLocation("autogenerated by Ginkgo"), + internal.TransformNewNodeArgs( + exitIfErrors, deprecationTracker, types.NodeTypeReportAfterSuite, + fmt.Sprintf("Autogenerated ReportAfterSuite for %s", strings.Join(flags, " ")), + body, + types.NewCustomCodeLocation("autogenerated by Ginkgo"), + ), )) } diff --git a/vendor/github.com/onsi/ginkgo/v2/table_dsl.go b/vendor/github.com/onsi/ginkgo/v2/table_dsl.go index b9e0ca9ef76..1031aa85545 100644 --- a/vendor/github.com/onsi/ginkgo/v2/table_dsl.go +++ b/vendor/github.com/onsi/ginkgo/v2/table_dsl.go @@ -309,11 +309,11 @@ func generateTable(description string, isSubtree bool, args ...any) { internalNodeType = types.NodeTypeContainer } - pushNode(internal.NewNode(deprecationTracker, internalNodeType, description, internalNodeArgs...)) + pushNode(internal.NewNode(internal.TransformNewNodeArgs(exitIfErrors, deprecationTracker, internalNodeType, description, internalNodeArgs...))) } }) - pushNode(internal.NewNode(deprecationTracker, types.NodeTypeContainer, description, containerNodeArgs...)) + pushNode(internal.NewNode(internal.TransformNewNodeArgs(exitIfErrors, deprecationTracker, types.NodeTypeContainer, description, containerNodeArgs...))) } func invokeFunction(function any, parameters []any) []reflect.Value { diff --git a/vendor/github.com/onsi/ginkgo/v2/types/types.go b/vendor/github.com/onsi/ginkgo/v2/types/types.go index b8e864a5d26..9981a0dd686 100644 --- a/vendor/github.com/onsi/ginkgo/v2/types/types.go +++ b/vendor/github.com/onsi/ginkgo/v2/types/types.go @@ -20,6 +20,57 @@ func init() { } } +// ConstructionNodeReport captures information about a Ginkgo spec. +type ConstructionNodeReport struct { + // ContainerHierarchyTexts is a slice containing the text strings of + // all Describe/Context/When containers in this spec's hierarchy. + ContainerHierarchyTexts []string + + // ContainerHierarchyLocations is a slice containing the CodeLocations of + // all Describe/Context/When containers in this spec's hierarchy. + ContainerHierarchyLocations []CodeLocation + + // ContainerHierarchyLabels is a slice containing the labels of + // all Describe/Context/When containers in this spec's hierarchy + ContainerHierarchyLabels [][]string + + // ContainerHierarchySemVerConstraints is a slice containing the semVerConstraints of + // all Describe/Context/When containers in this spec's hierarchy + ContainerHierarchySemVerConstraints [][]string + + // IsSerial captures whether the any container has the Serial decorator + IsSerial bool + + // IsInOrderedContainer captures whether any container is an Ordered container + IsInOrderedContainer bool +} + +// FullText returns a concatenation of all the report.ContainerHierarchyTexts and report.LeafNodeText +func (report ConstructionNodeReport) FullText() string { + texts := []string{} + texts = append(texts, report.ContainerHierarchyTexts...) + texts = slices.DeleteFunc(texts, func(t string) bool { + return t == "" + }) + return strings.Join(texts, " ") +} + +// Labels returns a deduped set of all the spec's Labels. +func (report ConstructionNodeReport) Labels() []string { + out := []string{} + seen := map[string]bool{} + for _, labels := range report.ContainerHierarchyLabels { + for _, label := range labels { + if !seen[label] { + seen[label] = true + out = append(out, label) + } + } + } + + return out +} + // Report captures information about a Ginkgo test run type Report struct { //SuitePath captures the absolute path to the test suite @@ -146,6 +197,9 @@ type SpecReport struct { LeafNodeSemVerConstraints []string LeafNodeText string + // Captures the Spec Priority + SpecPriority int + // State captures whether the spec has passed, failed, etc. State SpecState diff --git a/vendor/github.com/onsi/ginkgo/v2/types/version.go b/vendor/github.com/onsi/ginkgo/v2/types/version.go index a30e68be1ad..855e7cbd977 100644 --- a/vendor/github.com/onsi/ginkgo/v2/types/version.go +++ b/vendor/github.com/onsi/ginkgo/v2/types/version.go @@ -1,3 +1,3 @@ package types -const VERSION = "2.26.0" +const VERSION = "2.27.1" diff --git a/vendor/github.com/pkg/sftp/SECURITY.md b/vendor/github.com/pkg/sftp/SECURITY.md new file mode 100644 index 00000000000..9ebc2631ff5 --- /dev/null +++ b/vendor/github.com/pkg/sftp/SECURITY.md @@ -0,0 +1,13 @@ +# Security Policy + +## Supported Versions + +Security updates are provided for the latest released version of this package. +We also welcome vulnerability reports for the development version to help us ensure it is secure before the next release. + +## Reporting a Vulnerability + +If you believe you’ve found a security vulnerability in this project, we strongly encourage you to report it privately using GitHub’s [security advisory system](https://github.com/pkg/sftp/security/advisories/new). +This will allow us to review and address the issue before public disclosure. + +Thank you for helping us keep the project secure. diff --git a/vendor/github.com/pkg/sftp/client.go b/vendor/github.com/pkg/sftp/client.go index 0d4d9a91835..307a35ea5b6 100644 --- a/vendor/github.com/pkg/sftp/client.go +++ b/vendor/github.com/pkg/sftp/client.go @@ -158,6 +158,17 @@ func UseFstat(value bool) ClientOption { } } +// CopyStderrTo specifies a writer to which the standard error of the remote sftp-server command should be written. +// +// The writer passed in will not be automatically closed. +// It is the responsibility of the caller to coordinate closure of any writers. +func CopyStderrTo(wr io.Writer) ClientOption { + return func(c *Client) error { + c.stderrTo = wr + return nil + } +} + // Client represents an SFTP session on a *ssh.ClientConn SSH connection. // Multiple Clients can be active on a single SSH connection, and a Client // may be called concurrently from multiple Goroutines. @@ -166,6 +177,8 @@ func UseFstat(value bool) ClientOption { type Client struct { clientConn + stderrTo io.Writer + ext map[string]string // Extensions (name -> data). maxPacket int // max packet size read or written. @@ -186,9 +199,7 @@ func NewClient(conn *ssh.Client, opts ...ClientOption) (*Client, error) { if err != nil { return nil, err } - if err := s.RequestSubsystem("sftp"); err != nil { - return nil, err - } + pw, err := s.StdinPipe() if err != nil { return nil, err @@ -197,15 +208,27 @@ func NewClient(conn *ssh.Client, opts ...ClientOption) (*Client, error) { if err != nil { return nil, err } + perr, err := s.StderrPipe() + if err != nil { + return nil, err + } - return NewClientPipe(pr, pw, opts...) + if err := s.RequestSubsystem("sftp"); err != nil { + return nil, err + } + + return newClientPipe(pr, perr, pw, s.Wait, opts...) } // NewClientPipe creates a new SFTP client given a Reader and a WriteCloser. // This can be used for connecting to an SFTP server over TCP/TLS or by using // the system's ssh client program (e.g. via exec.Command). func NewClientPipe(rd io.Reader, wr io.WriteCloser, opts ...ClientOption) (*Client, error) { - sftp := &Client{ + return newClientPipe(rd, nil, wr, nil, opts...) +} + +func newClientPipe(rd, stderr io.Reader, wr io.WriteCloser, wait func() error, opts ...ClientOption) (*Client, error) { + c := &Client{ clientConn: clientConn{ conn: conn{ Reader: rd, @@ -213,6 +236,7 @@ func NewClientPipe(rd io.Reader, wr io.WriteCloser, opts ...ClientOption) (*Clie }, inflight: make(map[uint32]chan<- result), closed: make(chan struct{}), + wait: wait, }, ext: make(map[string]string), @@ -222,32 +246,50 @@ func NewClientPipe(rd io.Reader, wr io.WriteCloser, opts ...ClientOption) (*Clie } for _, opt := range opts { - if err := opt(sftp); err != nil { + if err := opt(c); err != nil { wr.Close() return nil, err } } - if err := sftp.sendInit(); err != nil { + if stderr != nil { + wr := io.Discard + if c.stderrTo != nil { + wr = c.stderrTo + } + + go func() { + // DO NOT close the writer! + // Programs may pass in `os.Stderr` to write the remote stderr to, + // and the program may continue after disconnect by reconnecting. + // But if we've closed their stderr, then we just messed everything up. + + if _, err := io.Copy(wr, stderr); err != nil { + debug("error copying stderr: %v", err) + } + }() + } + + if err := c.sendInit(); err != nil { wr.Close() return nil, fmt.Errorf("error sending init packet to server: %w", err) } - if err := sftp.recvVersion(); err != nil { + if err := c.recvVersion(); err != nil { wr.Close() return nil, fmt.Errorf("error receiving version packet from server: %w", err) } - sftp.clientConn.wg.Add(1) + c.clientConn.wg.Add(1) go func() { - defer sftp.clientConn.wg.Done() + defer c.clientConn.wg.Done() - if err := sftp.clientConn.recv(); err != nil { - sftp.clientConn.broadcastErr(err) + if err := c.clientConn.recv(); err != nil { + c.clientConn.broadcastErr(err) } }() - return sftp, nil + return c, nil } // Create creates the named file mode 0666 (before umask), truncating it if it diff --git a/vendor/github.com/pkg/sftp/conn.go b/vendor/github.com/pkg/sftp/conn.go index 93bc37bf715..e68a2bd06ff 100644 --- a/vendor/github.com/pkg/sftp/conn.go +++ b/vendor/github.com/pkg/sftp/conn.go @@ -22,7 +22,7 @@ type conn struct { // For the client mode just pass 0. // It returns io.EOF if the connection is closed and // there are no more packets to read. -func (c *conn) recvPacket(orderID uint32) (uint8, []byte, error) { +func (c *conn) recvPacket(orderID uint32) (fxp, []byte, error) { return recvPacket(c, c.alloc, orderID) } @@ -43,6 +43,8 @@ type clientConn struct { conn wg sync.WaitGroup + wait func() error // if non-nil, call this during Wait() to get a possible remote status error. + sync.Mutex // protects inflight inflight map[uint32]chan<- result // outstanding requests @@ -55,6 +57,27 @@ type clientConn struct { // goroutines. func (c *clientConn) Wait() error { <-c.closed + + if c.wait == nil { + // Only return this error if c.wait won't return something more useful. + return c.err + } + + if err := c.wait(); err != nil { + + // TODO: when https://github.com/golang/go/issues/35025 is fixed, + // we can remove this if block entirely. + // Right now, it’s always going to return this, so it is not useful. + // But we have this code here so that as soon as the ssh library is updated, + // we can return a possibly more useful error. + if err.Error() == "ssh: session not started" { + return c.err + } + + return err + } + + // c.wait returned no error; so, let's return something maybe more useful. return c.err } @@ -119,7 +142,7 @@ func (c *clientConn) getChannel(sid uint32) (chan<- result, bool) { // result captures the result of receiving the a packet from the server type result struct { - typ byte + typ fxp data []byte err error } @@ -129,7 +152,7 @@ type idmarshaler interface { encoding.BinaryMarshaler } -func (c *clientConn) sendPacket(ctx context.Context, ch chan result, p idmarshaler) (byte, []byte, error) { +func (c *clientConn) sendPacket(ctx context.Context, ch chan result, p idmarshaler) (fxp, []byte, error) { if cap(ch) < 1 { ch = make(chan result, 1) } diff --git a/vendor/github.com/pkg/sftp/packet.go b/vendor/github.com/pkg/sftp/packet.go index bfe6a3c9770..3836ab6f20c 100644 --- a/vendor/github.com/pkg/sftp/packet.go +++ b/vendor/github.com/pkg/sftp/packet.go @@ -304,16 +304,22 @@ func sendPacket(w io.Writer, m encoding.BinaryMarshaler) error { return nil } -func recvPacket(r io.Reader, alloc *allocator, orderID uint32) (uint8, []byte, error) { +func recvPacket(r io.Reader, alloc *allocator, orderID uint32) (fxp, []byte, error) { var b []byte if alloc != nil { b = alloc.GetPage(orderID) } else { b = make([]byte, 4) } - if _, err := io.ReadFull(r, b[:4]); err != nil { - return 0, nil, err + + if n, err := io.ReadFull(r, b[:4]); err != nil { + if err == io.EOF { + return 0, nil, err + } + + return 0, nil, fmt.Errorf("error reading packet length: %d of 4: %w", n, err) } + length, _ := unmarshalUint32(b) if length > maxMsgLength { debug("recv packet %d bytes too long", length) @@ -323,24 +329,39 @@ func recvPacket(r io.Reader, alloc *allocator, orderID uint32) (uint8, []byte, e debug("recv packet of 0 bytes too short") return 0, nil, errShortPacket } + if alloc == nil { b = make([]byte, length) } - if _, err := io.ReadFull(r, b[:length]); err != nil { + + n, err := io.ReadFull(r, b[:length]) + b = b[:n] + + if err != nil { + debug("recv packet error: %d of %d bytes: %x", n, length, b) + // ReadFull only returns EOF if it has read no bytes. // In this case, that means a partial packet, and thus unexpected. if err == io.EOF { err = io.ErrUnexpectedEOF } - debug("recv packet %d bytes: err %v", length, err) - return 0, nil, err + + if n == 0 { + return 0, nil, fmt.Errorf("error reading packet body: %d of %d: %w", n, length, err) + } + + return 0, nil, fmt.Errorf("error reading packet body: %d of %d: (%s) %w", n, length, fxp(b[0]), err) } + + typ, payload := fxp(b[0]), b[1:n] + if debugDumpRxPacketBytes { - debug("recv packet: %s %d bytes %x", fxp(b[0]), length, b[1:length]) + debug("recv packet: %s %d bytes %x", typ, length, payload) } else if debugDumpRxPacket { - debug("recv packet: %s %d bytes", fxp(b[0]), length) + debug("recv packet: %s %d bytes", typ, length) } - return b[0], b[1:length], nil + + return typ, payload, nil } type extensionPair struct { diff --git a/vendor/github.com/pkg/sftp/request-example.go b/vendor/github.com/pkg/sftp/request-example.go index 519b3b76806..f003e7114c0 100644 --- a/vendor/github.com/pkg/sftp/request-example.go +++ b/vendor/github.com/pkg/sftp/request-example.go @@ -20,7 +20,7 @@ const maxSymlinkFollows = 5 var errTooManySymlinks = errors.New("too many symbolic links") -// InMemHandler returns a Hanlders object with the test handlers. +// InMemHandler returns a Handlers object with the test handlers. func InMemHandler() Handlers { root := &root{ rootFile: &memFile{name: "/", modtime: time.Now(), isdir: true}, @@ -449,7 +449,7 @@ func (fs *root) Lstat(r *Request) (ListerAt, error) { return listerat{file}, nil } -// In memory file-system-y thing that the Hanlders live on +// In memory file-system-y thing that the Handlers live on type root struct { rootFile *memFile mockErr error diff --git a/vendor/github.com/pkg/sftp/request-server.go b/vendor/github.com/pkg/sftp/request-server.go index 11047e6b10a..08c24d7f6fa 100644 --- a/vendor/github.com/pkg/sftp/request-server.go +++ b/vendor/github.com/pkg/sftp/request-server.go @@ -148,7 +148,7 @@ func (rs *RequestServer) serveLoop(pktChan chan<- orderedRequest) error { var err error var pkt requestPacket - var pktType uint8 + var pktType fxp var pktBytes []byte for { @@ -158,7 +158,7 @@ func (rs *RequestServer) serveLoop(pktChan chan<- orderedRequest) error { return err } - pkt, err = makePacket(rxPacket{fxp(pktType), pktBytes}) + pkt, err = makePacket(rxPacket{pktType, pktBytes}) if err != nil { switch { case errors.Is(err, errUnknownExtendedPacket): diff --git a/vendor/github.com/pkg/sftp/server.go b/vendor/github.com/pkg/sftp/server.go index cd656d8fbf0..7735c42c4e5 100644 --- a/vendor/github.com/pkg/sftp/server.go +++ b/vendor/github.com/pkg/sftp/server.go @@ -390,7 +390,7 @@ func (svr *Server) Serve() error { var err error var pkt requestPacket - var pktType uint8 + var pktType fxp var pktBytes []byte for { pktType, pktBytes, err = svr.serverConn.recvPacket(svr.pktMgr.getNextOrderID()) @@ -403,7 +403,7 @@ func (svr *Server) Serve() error { break } - pkt, err = makePacket(rxPacket{fxp(pktType), pktBytes}) + pkt, err = makePacket(rxPacket{pktType, pktBytes}) if err != nil { switch { case errors.Is(err, errUnknownExtendedPacket): diff --git a/vendor/github.com/pkg/sftp/sftp.go b/vendor/github.com/pkg/sftp/sftp.go index 778c8f3d731..1e698bb2782 100644 --- a/vendor/github.com/pkg/sftp/sftp.go +++ b/vendor/github.com/pkg/sftp/sftp.go @@ -184,15 +184,15 @@ func (f fx) String() string { } type unexpectedPacketErr struct { - want, got uint8 + want, got fxp } func (u *unexpectedPacketErr) Error() string { - return fmt.Sprintf("sftp: unexpected packet: want %v, got %v", fxp(u.want), fxp(u.got)) + return fmt.Sprintf("sftp: unexpected packet: want %v, got %v", u.want, u.got) } -func unimplementedPacketErr(u uint8) error { - return fmt.Errorf("sftp: unimplemented packet type: got %v", fxp(u)) +func unimplementedPacketErr(u fxp) error { + return fmt.Errorf("sftp: unimplemented packet type: got %v", u) } type unexpectedIDErr struct{ want, got uint32 } diff --git a/vendor/github.com/vbatts/tar-split/archive/tar/common.go b/vendor/github.com/vbatts/tar-split/archive/tar/common.go index dee9e47e4ae..e687a08c966 100644 --- a/vendor/github.com/vbatts/tar-split/archive/tar/common.go +++ b/vendor/github.com/vbatts/tar-split/archive/tar/common.go @@ -34,6 +34,7 @@ var ( errMissData = errors.New("archive/tar: sparse file references non-existent data") errUnrefData = errors.New("archive/tar: sparse file contains unreferenced data") errWriteHole = errors.New("archive/tar: write non-NUL byte in sparse hole") + errSparseTooLong = errors.New("archive/tar: sparse map too long") ) type headerError []string diff --git a/vendor/github.com/vbatts/tar-split/archive/tar/reader.go b/vendor/github.com/vbatts/tar-split/archive/tar/reader.go index 248a7ccb15a..a645c41605f 100644 --- a/vendor/github.com/vbatts/tar-split/archive/tar/reader.go +++ b/vendor/github.com/vbatts/tar-split/archive/tar/reader.go @@ -581,12 +581,17 @@ func readGNUSparseMap1x0(r io.Reader) (sparseDatas, error) { cntNewline int64 buf bytes.Buffer blk block + totalSize int ) // feedTokens copies data in blocks from r into buf until there are // at least cnt newlines in buf. It will not read more blocks than needed. feedTokens := func(n int64) error { for cntNewline < n { + totalSize += len(blk) + if totalSize > maxSpecialFileSize { + return errSparseTooLong + } if _, err := mustReadFull(r, blk[:]); err != nil { return err } @@ -619,8 +624,8 @@ func readGNUSparseMap1x0(r io.Reader) (sparseDatas, error) { } // Parse for all member entries. - // numEntries is trusted after this since a potential attacker must have - // committed resources proportional to what this library used. + // numEntries is trusted after this since feedTokens limits the number of + // tokens based on maxSpecialFileSize. if err := feedTokens(2 * numEntries); err != nil { return nil, err } diff --git a/vendor/go.podman.io/common/pkg/cgroups/blkio_linux.go b/vendor/go.podman.io/common/pkg/cgroups/blkio_linux.go index 4d85ba4a707..c1b73f2fd81 100644 --- a/vendor/go.podman.io/common/pkg/cgroups/blkio_linux.go +++ b/vendor/go.podman.io/common/pkg/cgroups/blkio_linux.go @@ -3,10 +3,6 @@ package cgroups import ( - "bufio" - "errors" - "fmt" - "os" "path/filepath" "strconv" "strings" @@ -26,23 +22,16 @@ func getBlkioHandler() *linuxBlkioHandler { // Apply set the specified constraints. func (c *linuxBlkioHandler) Apply(ctr *CgroupControl, res *cgroups.Resources) error { - if ctr.cgroup2 { - man, err := fs2.NewManager(ctr.config, filepath.Join(cgroupRoot, ctr.config.Path)) - if err != nil { - return err - } - return man.Set(res) + man, err := fs2.NewManager(ctr.config, filepath.Join(cgroupRoot, ctr.config.Path)) + if err != nil { + return err } - path := filepath.Join(cgroupRoot, Blkio, ctr.config.Path) - return c.Blkio.Set(path, res) + return man.Set(res) } // Create the cgroup. func (c *linuxBlkioHandler) Create(ctr *CgroupControl) (bool, error) { - if ctr.cgroup2 { - return false, nil - } - return ctr.createCgroupDirectory(Blkio) + return false, nil } // Destroy the cgroup. @@ -54,94 +43,45 @@ func (c *linuxBlkioHandler) Destroy(ctr *CgroupControl) error { func (c *linuxBlkioHandler) Stat(ctr *CgroupControl, m *cgroups.Stats) error { var ioServiceBytesRecursive []cgroups.BlkioStatEntry - if ctr.cgroup2 { - // more details on the io.stat file format:X https://facebookmicrosites.github.io/cgroup2/docs/io-controller.html - values, err := readCgroup2MapFile(ctr, "io.stat") + // more details on the io.stat file format:X https://facebookmicrosites.github.io/cgroup2/docs/io-controller.html + values, err := readCgroup2MapFile(ctr, "io.stat") + if err != nil { + return err + } + for k, v := range values { + d := strings.Split(k, ":") + if len(d) != 2 { + continue + } + minor, err := strconv.ParseUint(d[0], 10, 0) if err != nil { return err } - for k, v := range values { - d := strings.Split(k, ":") - if len(d) != 2 { - continue - } - minor, err := strconv.ParseUint(d[0], 10, 0) - if err != nil { - return err - } - major, err := strconv.ParseUint(d[1], 10, 0) - if err != nil { - return err - } - - for _, item := range v { - d := strings.Split(item, "=") - if len(d) != 2 { - continue - } - op := d[0] - - // Accommodate the cgroup v1 naming - switch op { - case "rbytes": - op = "read" - case "wbytes": - op = "write" - } - - value, err := strconv.ParseUint(d[1], 10, 0) - if err != nil { - return err - } - - entry := cgroups.BlkioStatEntry{ - Op: op, - Major: major, - Minor: minor, - Value: value, - } - ioServiceBytesRecursive = append(ioServiceBytesRecursive, entry) - } - } - } else { - BlkioRoot := ctr.getCgroupv1Path(Blkio) - - p := filepath.Join(BlkioRoot, "blkio.throttle.io_service_bytes_recursive") - f, err := os.Open(p) + major, err := strconv.ParseUint(d[1], 10, 0) if err != nil { - if errors.Is(err, os.ErrNotExist) { - return nil - } - return fmt.Errorf("open %s: %w", p, err) + return err } - defer f.Close() - scanner := bufio.NewScanner(f) - for scanner.Scan() { - line := scanner.Text() - parts := strings.Fields(line) - if len(parts) < 3 { - continue - } - d := strings.Split(parts[0], ":") + for _, item := range v { + d := strings.Split(item, "=") if len(d) != 2 { continue } - minor, err := strconv.ParseUint(d[0], 10, 0) - if err != nil { - return err - } - major, err := strconv.ParseUint(d[1], 10, 0) - if err != nil { - return err + op := d[0] + + // Accommodate the cgroup v1 naming + switch op { + case "rbytes": + op = "read" + case "wbytes": + op = "write" } - op := parts[1] - - value, err := strconv.ParseUint(parts[2], 10, 0) + value, err := strconv.ParseUint(d[1], 10, 0) if err != nil { return err } + entry := cgroups.BlkioStatEntry{ Op: op, Major: major, @@ -150,9 +90,6 @@ func (c *linuxBlkioHandler) Stat(ctr *CgroupControl, m *cgroups.Stats) error { } ioServiceBytesRecursive = append(ioServiceBytesRecursive, entry) } - if err := scanner.Err(); err != nil { - return fmt.Errorf("parse %s: %w", p, err) - } } m.BlkioStats.IoServiceBytesRecursive = ioServiceBytesRecursive return nil diff --git a/vendor/go.podman.io/common/pkg/cgroups/cgroups_linux.go b/vendor/go.podman.io/common/pkg/cgroups/cgroups_linux.go index 1c66a8d9cc4..6a87f3602fa 100644 --- a/vendor/go.podman.io/common/pkg/cgroups/cgroups_linux.go +++ b/vendor/go.podman.io/common/pkg/cgroups/cgroups_linux.go @@ -8,11 +8,9 @@ import ( "context" "errors" "fmt" - "maps" "math" "os" "path/filepath" - "slices" "strconv" "strings" "sync" @@ -32,9 +30,7 @@ import ( var ( // ErrCgroupDeleted means the cgroup was deleted. ErrCgroupDeleted = errors.New("cgroup deleted") - // ErrCgroupV1Rootless means the cgroup v1 were attempted to be used in rootless environment. - ErrCgroupV1Rootless = errors.New("no support for CGroups V1 in rootless environments") - ErrStatCgroup = errors.New("no cgroup available for gathering user statistics") + ErrStatCgroup = errors.New("no cgroup available for gathering user statistics") isUnifiedOnce sync.Once isUnified bool @@ -43,12 +39,8 @@ var ( // CgroupControl controls a cgroup hierarchy. type CgroupControl struct { - cgroup2 bool config *cgroups.Cgroup systemd bool - // List of additional cgroup subsystems joined that - // do not have a custom handler. - additionalControllers []controller } type controller struct { @@ -92,63 +84,37 @@ func init() { } // getAvailableControllers get the available controllers. -func getAvailableControllers(exclude map[string]controllerHandler, cgroup2 bool) ([]controller, error) { - if cgroup2 { - controllers := []controller{} - controllersFile := filepath.Join(cgroupRoot, "cgroup.controllers") - - // rootless cgroupv2: check available controllers for current user, systemd or servicescope will inherit - if unshare.IsRootless() { - userSlice, err := getCgroupPathForCurrentProcess() - if err != nil { - return controllers, err - } - // userSlice already contains '/' so not adding here - basePath := cgroupRoot + userSlice - controllersFile = filepath.Join(basePath, "cgroup.controllers") - } - controllersFileBytes, err := os.ReadFile(controllersFile) - if err != nil { - return nil, fmt.Errorf("failed while reading controllers for cgroup v2: %w", err) - } - for controllerName := range strings.FieldsSeq(string(controllersFileBytes)) { - c := controller{ - name: controllerName, - symlink: false, - } - controllers = append(controllers, c) - } - return controllers, nil - } - - subsystems, _ := cgroupV1GetAllSubsystems() +func getAvailableControllers() ([]controller, error) { controllers := []controller{} - // cgroupv1 and rootless: No subsystem is available: delegation is unsafe. - if unshare.IsRootless() { - return controllers, nil - } + controllersFile := filepath.Join(cgroupRoot, "cgroup.controllers") - for _, name := range subsystems { - if _, found := exclude[name]; found { - continue - } - fileInfo, err := os.Stat(cgroupRoot + "/" + name) + // rootless cgroupv2: check available controllers for current user, systemd or servicescope will inherit + if unshare.IsRootless() { + userSlice, err := getCgroupPathForCurrentProcess() if err != nil { - continue + return controllers, err } + // userSlice already contains '/' so not adding here + basePath := cgroupRoot + userSlice + controllersFile = filepath.Join(basePath, "cgroup.controllers") + } + controllersFileBytes, err := os.ReadFile(controllersFile) + if err != nil { + return nil, fmt.Errorf("failed while reading controllers for cgroup v2: %w", err) + } + for controllerName := range strings.FieldsSeq(string(controllersFileBytes)) { c := controller{ - name: name, - symlink: !fileInfo.IsDir(), + name: controllerName, + symlink: false, } controllers = append(controllers, c) } - return controllers, nil } // AvailableControllers get string:bool map of all the available controllers. -func AvailableControllers(exclude map[string]controllerHandler, cgroup2 bool) ([]string, error) { - availableControllers, err := getAvailableControllers(exclude, cgroup2) +func AvailableControllers() ([]string, error) { + availableControllers, err := getAvailableControllers() if err != nil { return nil, err } @@ -160,31 +126,6 @@ func AvailableControllers(exclude map[string]controllerHandler, cgroup2 bool) ([ return controllerList, nil } -func cgroupV1GetAllSubsystems() ([]string, error) { - f, err := os.Open("/proc/cgroups") - if err != nil { - return nil, err - } - defer f.Close() - - subsystems := []string{} - - s := bufio.NewScanner(f) - for s.Scan() { - text := s.Text() - if text[0] != '#' { - parts := strings.Fields(text) - if len(parts) >= 4 && parts[3] != "0" { - subsystems = append(subsystems, parts[0]) - } - } - } - if err := s.Err(); err != nil { - return nil, err - } - return subsystems, nil -} - func getCgroupPathForCurrentProcess() (string, error) { path := fmt.Sprintf("/proc/%d/cgroup", os.Getpid()) f, err := os.Open(path) @@ -225,10 +166,8 @@ func (c *CgroupControl) initialize() (err error) { } } }() - if c.cgroup2 { - if err := createCgroupv2Path(filepath.Join(cgroupRoot, c.config.Path)); err != nil { - return fmt.Errorf("creating cgroup path %s: %w", c.config.Path, err) - } + if err := createCgroupv2Path(filepath.Join(cgroupRoot, c.config.Path)); err != nil { + return fmt.Errorf("creating cgroup path %s: %w", c.config.Path, err) } for name, handler := range handlers { created, err := handler.Create(c) @@ -239,20 +178,6 @@ func (c *CgroupControl) initialize() (err error) { createdSoFar[name] = handler } } - - if !c.cgroup2 { - // We won't need to do this for cgroup v2 - for _, ctr := range c.additionalControllers { - if ctr.symlink { - continue - } - path := c.getCgroupv1Path(ctr.name) - if err := os.MkdirAll(path, 0o755); err != nil { - return fmt.Errorf("creating cgroup path for %s: %w", ctr.name, err) - } - } - } - return nil } @@ -297,26 +222,13 @@ func readFileByKeyAsUint64(path, key string) (uint64, error) { // New creates a new cgroup control. func New(path string, resources *cgroups.Resources) (*CgroupControl, error) { - cgroup2, err := IsCgroup2UnifiedMode() - if err != nil { - return nil, err - } control := &CgroupControl{ - cgroup2: cgroup2, config: &cgroups.Cgroup{ Path: path, Resources: resources, }, } - if !cgroup2 { - controllers, err := getAvailableControllers(handlers, false) - if err != nil { - return nil, err - } - control.additionalControllers = controllers - } - if err := control.initialize(); err != nil { return nil, err } @@ -326,12 +238,7 @@ func New(path string, resources *cgroups.Resources) (*CgroupControl, error) { // NewSystemd creates a new cgroup control. func NewSystemd(path string, resources *cgroups.Resources) (*CgroupControl, error) { - cgroup2, err := IsCgroup2UnifiedMode() - if err != nil { - return nil, err - } control := &CgroupControl{ - cgroup2: cgroup2, systemd: true, config: &cgroups.Cgroup{ Path: path, @@ -345,45 +252,12 @@ func NewSystemd(path string, resources *cgroups.Resources) (*CgroupControl, erro // Load loads an existing cgroup control. func Load(path string) (*CgroupControl, error) { - cgroup2, err := IsCgroup2UnifiedMode() - if err != nil { - return nil, err - } control := &CgroupControl{ - cgroup2: cgroup2, systemd: false, config: &cgroups.Cgroup{ Path: path, }, } - if !cgroup2 { - controllers, err := getAvailableControllers(handlers, false) - if err != nil { - return nil, err - } - control.additionalControllers = controllers - } - if !cgroup2 { - oneExists := false - // check that the cgroup exists at least under one controller - for name := range handlers { - p := control.getCgroupv1Path(name) - if err := fileutils.Exists(p); err == nil { - oneExists = true - break - } - } - - // if there is no controller at all, raise an error - if !oneExists { - if unshare.IsRootless() { - return nil, ErrCgroupV1Rootless - } - // compatible with the error code - // used by containerd/cgroups - return nil, ErrCgroupDeleted - } - } return control, nil } @@ -448,26 +322,7 @@ func (c *CgroupControl) DeleteByPathConn(path string, conn *systemdDbus.Conn) er if c.systemd { return systemdDestroyConn(path, conn) } - if c.cgroup2 { - return rmDirRecursively(filepath.Join(cgroupRoot, c.config.Path)) - } - var lastError error - for _, h := range handlers { - if err := h.Destroy(c); err != nil { - lastError = err - } - } - - for _, ctr := range c.additionalControllers { - if ctr.symlink { - continue - } - p := c.getCgroupv1Path(ctr.name) - if err := rmDirRecursively(p); err != nil { - lastError = fmt.Errorf("remove %s: %w", p, err) - } - } - return lastError + return rmDirRecursively(filepath.Join(cgroupRoot, c.config.Path)) } // DeleteByPath deletes the specified cgroup path. @@ -495,32 +350,8 @@ func (c *CgroupControl) Update(resources *cgroups.Resources) error { // AddPid moves the specified pid to the cgroup. func (c *CgroupControl) AddPid(pid int) error { - pidString := []byte(fmt.Sprintf("%d\n", pid)) - - if c.cgroup2 { - path := filepath.Join(cgroupRoot, c.config.Path) - return fs2.CreateCgroupPath(path, c.config) - } - - names := slices.Collect(maps.Keys(handlers)) - - for _, c := range c.additionalControllers { - if !c.symlink { - names = append(names, c.name) - } - } - - for _, n := range names { - // If we aren't using cgroup2, we won't write correctly to unified hierarchy - if !c.cgroup2 && n == "unified" { - continue - } - p := filepath.Join(c.getCgroupv1Path(n), "tasks") - if err := os.WriteFile(p, pidString, 0o644); err != nil { - return fmt.Errorf("write %s: %w", p, err) - } - } - return nil + path := filepath.Join(cgroupRoot, c.config.Path) + return fs2.CreateCgroupPath(path, c.config) } // Stat returns usage statistics for the cgroup. @@ -573,23 +404,6 @@ func readCgroup2MapFile(ctr *CgroupControl, name string) (map[string][]string, e return readCgroupMapPath(p) } -func (c *CgroupControl) createCgroupDirectory(controller string) (bool, error) { - cPath := c.getCgroupv1Path(controller) - err := fileutils.Exists(cPath) - if err == nil { - return false, nil - } - - if !errors.Is(err, os.ErrNotExist) { - return false, err - } - - if err := os.MkdirAll(cPath, 0o755); err != nil { - return false, fmt.Errorf("creating cgroup for %s: %w", controller, err) - } - return true, nil -} - var TestMode bool func createCgroupv2Path(path string) (deferredError error) { @@ -671,32 +485,6 @@ func cleanString(s string) string { return strings.Trim(s, "\n") } -func readAcct(ctr *CgroupControl, name string) (uint64, error) { - p := filepath.Join(ctr.getCgroupv1Path(CPUAcct), name) - return readFileAsUint64(p) -} - -func readAcctList(ctr *CgroupControl, name string) ([]uint64, error) { - p := filepath.Join(ctr.getCgroupv1Path(CPUAcct), name) - data, err := os.ReadFile(p) - if err != nil { - return nil, err - } - r := []uint64{} - for s := range strings.SplitSeq(string(data), " ") { - s = cleanString(s) - if s == "" { - break - } - v, err := strconv.ParseUint(s, 10, 64) - if err != nil { - return nil, fmt.Errorf("parsing %s: %w", s, err) - } - r = append(r, v) - } - return r, nil -} - func cpusetCopyFromParent(path string, cgroupv2 bool) error { for _, file := range []string{"cpuset.cpus", "cpuset.mems"} { if _, err := cpusetCopyFileFromParent(path, file, cgroupv2); err != nil { @@ -739,15 +527,6 @@ func cpusetCopyFileFromParent(dir, file string, cgroupv2 bool) ([]byte, error) { // SystemCPUUsage returns the system usage for all the cgroups. func SystemCPUUsage() (uint64, error) { - cgroupv2, err := IsCgroup2UnifiedMode() - if err != nil { - return 0, err - } - if !cgroupv2 { - p := filepath.Join(cgroupRoot, CPUAcct, "cpuacct.usage") - return readFileAsUint64(p) - } - files, err := os.ReadDir(cgroupRoot) if err != nil { return 0, err @@ -775,7 +554,7 @@ func SystemCPUUsage() (uint64, error) { return total, nil } -// IsCgroup2UnifiedMode returns whether we are running in cgroup 2 cgroup2 mode. +// IsCgroup2UnifiedMode returns whether we are running in cgroup 2 unified mode. func IsCgroup2UnifiedMode() (bool, error) { isUnifiedOnce.Do(func() { var st syscall.Statfs_t @@ -800,11 +579,6 @@ func UserConnection(uid int) (*systemdDbus.Conn, error) { func UserOwnsCurrentSystemdCgroup() (bool, error) { uid := os.Geteuid() - cgroup2, err := IsCgroup2UnifiedMode() - if err != nil { - return false, err - } - f, err := os.Open("/proc/self/cgroup") if err != nil { return false, err @@ -822,20 +596,11 @@ func UserOwnsCurrentSystemdCgroup() (bool, error) { // If we are on a cgroup v2 system and there are cgroup v1 controllers // mounted, ignore them when the current process is at the root cgroup. - if cgroup2 && parts[1] != "" && parts[2] == "/" { + if parts[1] != "" && parts[2] == "/" { continue } - var cgroupPath string - - if cgroup2 { - cgroupPath = filepath.Join(cgroupRoot, parts[2]) - } else { - if parts[1] != "name=systemd" { - continue - } - cgroupPath = filepath.Join(cgroupRoot, "systemd", parts[2]) - } + cgroupPath := filepath.Join(cgroupRoot, parts[2]) st, err := os.Stat(cgroupPath) if err != nil { diff --git a/vendor/go.podman.io/common/pkg/cgroups/cgroups_unsupported.go b/vendor/go.podman.io/common/pkg/cgroups/cgroups_unsupported.go index 5940dc82d94..fc87f168807 100644 --- a/vendor/go.podman.io/common/pkg/cgroups/cgroups_unsupported.go +++ b/vendor/go.podman.io/common/pkg/cgroups/cgroups_unsupported.go @@ -2,7 +2,7 @@ package cgroups -// IsCgroup2UnifiedMode returns whether we are running in cgroup 2 cgroup2 mode. +// IsCgroup2UnifiedMode returns whether we are running in cgroup 2 unified mode. func IsCgroup2UnifiedMode() (bool, error) { return false, nil } diff --git a/vendor/go.podman.io/common/pkg/cgroups/cpu_linux.go b/vendor/go.podman.io/common/pkg/cgroups/cpu_linux.go index 899a86d5d39..beecd5a0ede 100644 --- a/vendor/go.podman.io/common/pkg/cgroups/cpu_linux.go +++ b/vendor/go.podman.io/common/pkg/cgroups/cpu_linux.go @@ -3,8 +3,6 @@ package cgroups import ( - "errors" - "os" "path/filepath" "strconv" @@ -23,23 +21,16 @@ func getCPUHandler() *linuxCPUHandler { // Apply set the specified constraints. func (c *linuxCPUHandler) Apply(ctr *CgroupControl, res *cgroups.Resources) error { - if ctr.cgroup2 { - man, err := fs2.NewManager(ctr.config, filepath.Join(cgroupRoot, ctr.config.Path)) - if err != nil { - return err - } - return man.Set(res) + man, err := fs2.NewManager(ctr.config, filepath.Join(cgroupRoot, ctr.config.Path)) + if err != nil { + return err } - path := filepath.Join(cgroupRoot, CPU, ctr.config.Path) - return c.CPU.Set(path, res) + return man.Set(res) } // Create the cgroup. func (c *linuxCPUHandler) Create(ctr *CgroupControl) (bool, error) { - if ctr.cgroup2 { - return false, nil - } - return ctr.createCgroupDirectory(CPU) + return false, nil } // Destroy the cgroup. @@ -51,47 +42,23 @@ func (c *linuxCPUHandler) Destroy(ctr *CgroupControl) error { func (c *linuxCPUHandler) Stat(ctr *CgroupControl, m *cgroups.Stats) error { var err error cpu := cgroups.CpuStats{} - if ctr.cgroup2 { - values, err := readCgroup2MapFile(ctr, "cpu.stat") + values, err := readCgroup2MapFile(ctr, "cpu.stat") + if err != nil { + return err + } + if val, found := values["usage_usec"]; found { + cpu.CpuUsage.TotalUsage, err = strconv.ParseUint(cleanString(val[0]), 10, 64) if err != nil { return err } - if val, found := values["usage_usec"]; found { - cpu.CpuUsage.TotalUsage, err = strconv.ParseUint(cleanString(val[0]), 10, 64) - if err != nil { - return err - } - cpu.CpuUsage.UsageInKernelmode *= 1000 - } - if val, found := values["system_usec"]; found { - cpu.CpuUsage.UsageInKernelmode, err = strconv.ParseUint(cleanString(val[0]), 10, 64) - if err != nil { - return err - } - cpu.CpuUsage.TotalUsage *= 1000 - } - } else { - cpu.CpuUsage.TotalUsage, err = readAcct(ctr, "cpuacct.usage") - if err != nil { - if !errors.Is(err, os.ErrNotExist) { - return err - } - cpu.CpuUsage.TotalUsage = 0 - } - cpu.CpuUsage.UsageInKernelmode, err = readAcct(ctr, "cpuacct.usage_sys") - if err != nil { - if !errors.Is(err, os.ErrNotExist) { - return err - } - cpu.CpuUsage.UsageInKernelmode = 0 - } - cpu.CpuUsage.PercpuUsage, err = readAcctList(ctr, "cpuacct.usage_percpu") + cpu.CpuUsage.UsageInKernelmode *= 1000 + } + if val, found := values["system_usec"]; found { + cpu.CpuUsage.UsageInKernelmode, err = strconv.ParseUint(cleanString(val[0]), 10, 64) if err != nil { - if !errors.Is(err, os.ErrNotExist) { - return err - } - cpu.CpuUsage.PercpuUsage = nil + return err } + cpu.CpuUsage.TotalUsage *= 1000 } m.CpuStats = cpu return nil diff --git a/vendor/go.podman.io/common/pkg/cgroups/cpuset_linux.go b/vendor/go.podman.io/common/pkg/cgroups/cpuset_linux.go index 10b2298e12a..c13f082911a 100644 --- a/vendor/go.podman.io/common/pkg/cgroups/cpuset_linux.go +++ b/vendor/go.podman.io/common/pkg/cgroups/cpuset_linux.go @@ -20,28 +20,17 @@ func getCpusetHandler() *linuxCpusetHandler { // Apply set the specified constraints. func (c *linuxCpusetHandler) Apply(ctr *CgroupControl, res *cgroups.Resources) error { - if ctr.cgroup2 { - man, err := fs2.NewManager(ctr.config, filepath.Join(cgroupRoot, ctr.config.Path)) - if err != nil { - return err - } - return man.Set(res) + man, err := fs2.NewManager(ctr.config, filepath.Join(cgroupRoot, ctr.config.Path)) + if err != nil { + return err } - path := filepath.Join(cgroupRoot, CPUset, ctr.config.Path) - return c.CPUSet.Set(path, res) + return man.Set(res) } // Create the cgroup. func (c *linuxCpusetHandler) Create(ctr *CgroupControl) (bool, error) { - if ctr.cgroup2 { - path := filepath.Join(cgroupRoot, ctr.config.Path) - return true, cpusetCopyFromParent(path, true) - } - created, err := ctr.createCgroupDirectory(CPUset) - if !created || err != nil { - return created, err - } - return true, cpusetCopyFromParent(ctr.getCgroupv1Path(CPUset), false) + path := filepath.Join(cgroupRoot, ctr.config.Path) + return true, cpusetCopyFromParent(path, true) } // Destroy the cgroup. diff --git a/vendor/go.podman.io/common/pkg/cgroups/memory_linux.go b/vendor/go.podman.io/common/pkg/cgroups/memory_linux.go index 7f619003080..c54cb2c91da 100644 --- a/vendor/go.podman.io/common/pkg/cgroups/memory_linux.go +++ b/vendor/go.podman.io/common/pkg/cgroups/memory_linux.go @@ -20,23 +20,16 @@ func getMemoryHandler() *linuxMemHandler { // Apply set the specified constraints. func (c *linuxMemHandler) Apply(ctr *CgroupControl, res *cgroups.Resources) error { - if ctr.cgroup2 { - man, err := fs2.NewManager(ctr.config, filepath.Join(cgroupRoot, ctr.config.Path)) - if err != nil { - return err - } - return man.Set(res) + man, err := fs2.NewManager(ctr.config, filepath.Join(cgroupRoot, ctr.config.Path)) + if err != nil { + return err } - path := filepath.Join(cgroupRoot, Memory, ctr.config.Path) - return c.Mem.Set(path, res) + return man.Set(res) } // Create the cgroup. func (c *linuxMemHandler) Create(ctr *CgroupControl) (bool, error) { - if ctr.cgroup2 { - return false, nil - } - return ctr.createCgroupDirectory(Memory) + return false, nil } // Destroy the cgroup. @@ -52,48 +45,25 @@ func (c *linuxMemHandler) Stat(ctr *CgroupControl, m *cgroups.Stats) error { var memoryRoot string var limitFilename string - if ctr.cgroup2 { - memoryRoot = filepath.Join(cgroupRoot, ctr.config.Path) - limitFilename = "memory.max" - - // Read memory.current - current, err := readFileAsUint64(filepath.Join(memoryRoot, "memory.current")) - if err != nil { - return err - } - - // Read inactive_file from memory.stat - inactiveFile, err := readFileByKeyAsUint64(filepath.Join(memoryRoot, "memory.stat"), "inactive_file") - if err != nil { - return err - } - - // Docker calculation: memory.current - memory.stat['inactive_file'] - memUsage.Usage.Usage = 0 - if inactiveFile < current { - memUsage.Usage.Usage = current - inactiveFile - } - } else { - memoryRoot = ctr.getCgroupv1Path(Memory) - limitFilename = "memory.limit_in_bytes" - - // Read memory.usage_in_bytes - usageInBytes, err := readFileAsUint64(filepath.Join(memoryRoot, "memory.usage_in_bytes")) - if err != nil { - return err - } - - // Read total_inactive_file from memory.stat - totalInactiveFile, err := readFileByKeyAsUint64(filepath.Join(memoryRoot, "memory.stat"), "total_inactive_file") - if err != nil { - return err - } - - // Docker calculation: memory.usage_in_bytes - memory.stat['total_inactive_file'] - memUsage.Usage.Usage = 0 - if totalInactiveFile < usageInBytes { - memUsage.Usage.Usage = usageInBytes - totalInactiveFile - } + memoryRoot = filepath.Join(cgroupRoot, ctr.config.Path) + limitFilename = "memory.max" + + // Read memory.current + current, err := readFileAsUint64(filepath.Join(memoryRoot, "memory.current")) + if err != nil { + return err + } + + // Read inactive_file from memory.stat + inactiveFile, err := readFileByKeyAsUint64(filepath.Join(memoryRoot, "memory.stat"), "inactive_file") + if err != nil { + return err + } + + // Docker calculation: memory.current - memory.stat['inactive_file'] + memUsage.Usage.Usage = 0 + if inactiveFile < current { + memUsage.Usage.Usage = current - inactiveFile } memUsage.Usage.Limit, err = readFileAsUint64(filepath.Join(memoryRoot, limitFilename)) diff --git a/vendor/go.podman.io/common/pkg/cgroups/pids_linux.go b/vendor/go.podman.io/common/pkg/cgroups/pids_linux.go index 82202830e02..c7881dccd2a 100644 --- a/vendor/go.podman.io/common/pkg/cgroups/pids_linux.go +++ b/vendor/go.podman.io/common/pkg/cgroups/pids_linux.go @@ -20,24 +20,16 @@ func getPidsHandler() *linuxPidHandler { // Apply set the specified constraints. func (c *linuxPidHandler) Apply(ctr *CgroupControl, res *cgroups.Resources) error { - if ctr.cgroup2 { - man, err := fs2.NewManager(ctr.config, filepath.Join(cgroupRoot, ctr.config.Path)) - if err != nil { - return err - } - return man.Set(res) + man, err := fs2.NewManager(ctr.config, filepath.Join(cgroupRoot, ctr.config.Path)) + if err != nil { + return err } - - path := filepath.Join(cgroupRoot, Pids, ctr.config.Path) - return c.Pid.Set(path, res) + return man.Set(res) } // Create the cgroup. func (c *linuxPidHandler) Create(ctr *CgroupControl) (bool, error) { - if ctr.cgroup2 { - return false, nil - } - return ctr.createCgroupDirectory(Pids) + return false, nil } // Destroy the cgroup. @@ -52,12 +44,7 @@ func (c *linuxPidHandler) Stat(ctr *CgroupControl, m *cgroups.Stats) error { return nil } - var PIDRoot string - if ctr.cgroup2 { - PIDRoot = filepath.Join(cgroupRoot, ctr.config.Path) - } else { - PIDRoot = ctr.getCgroupv1Path(Pids) - } + PIDRoot := filepath.Join(cgroupRoot, ctr.config.Path) current, err := readFileAsUint64(filepath.Join(PIDRoot, "pids.current")) if err != nil { diff --git a/vendor/go.podman.io/common/pkg/cgroups/systemd_linux.go b/vendor/go.podman.io/common/pkg/cgroups/systemd_linux.go index c0bc6d9d384..15ba00b139c 100644 --- a/vendor/go.podman.io/common/pkg/cgroups/systemd_linux.go +++ b/vendor/go.podman.io/common/pkg/cgroups/systemd_linux.go @@ -32,13 +32,7 @@ func systemdCreate(resources *cgroups.Resources, path string, c *systemdDbus.Con systemdDbus.PropDescription("cgroup " + name), systemdDbus.PropWants(slice), } - var ioString string - v2, _ := IsCgroup2UnifiedMode() - if v2 { - ioString = "IOAccounting" - } else { - ioString = "BlockIOAccounting" - } + ioString := "IOAccounting" pMap := map[string]bool{ "DefaultDependencies": false, "MemoryAccounting": true, @@ -57,7 +51,7 @@ func systemdCreate(resources *cgroups.Resources, path string, c *systemdDbus.Con properties = append(properties, p) } - uMap, sMap, bMap, iMap, structMap, err := resourcesToProps(resources, v2) + uMap, sMap, bMap, iMap, structMap, err := resourcesToProps(resources, true) if err != nil { lastError = err continue @@ -176,13 +170,8 @@ func resourcesToProps(res *cgroups.Resources, v2 bool) (map[string]uint64, map[s if res.CpuShares != 0 { // convert from shares to weight. weight only supports 1-10000 - v2, _ := IsCgroup2UnifiedMode() - if v2 { - wt := (1 + ((res.CpuShares-2)*9999)/262142) - uMap["CPUWeight"] = wt - } else { - uMap["CPUShares"] = res.CpuShares - } + wt := (1 + ((res.CpuShares-2)*9999)/262142) + uMap["CPUWeight"] = wt } // CPUSet diff --git a/vendor/go.podman.io/common/pkg/cgroups/utils_linux.go b/vendor/go.podman.io/common/pkg/cgroups/utils_linux.go index a1b18a96952..68034cc45c4 100644 --- a/vendor/go.podman.io/common/pkg/cgroups/utils_linux.go +++ b/vendor/go.podman.io/common/pkg/cgroups/utils_linux.go @@ -15,7 +15,6 @@ import ( "github.com/opencontainers/cgroups" "github.com/sirupsen/logrus" - "go.podman.io/storage/pkg/fileutils" "golang.org/x/sys/unix" ) @@ -207,11 +206,6 @@ func MoveUnderCgroup(cgroup, subtree string, processes []uint32) error { } defer f.Close() - unifiedMode, err := IsCgroup2UnifiedMode() - if err != nil { - return err - } - scanner := bufio.NewScanner(f) for scanner.Scan() { line := scanner.Text() @@ -221,24 +215,12 @@ func MoveUnderCgroup(cgroup, subtree string, processes []uint32) error { } // root cgroup, skip it - if parts[2] == "/" && (!unifiedMode || parts[1] != "") { + if parts[2] == "/" && parts[1] != "" { continue } cgroupRoot := "/sys/fs/cgroup" - // Special case the unified mount on hybrid cgroup and named hierarchies. - // This works on Fedora 31, but we should really parse the mounts to see - // where the cgroup hierarchy is mounted. - if parts[1] == "" && !unifiedMode { - // If it is not using unified mode, the cgroup v2 hierarchy is - // usually mounted under /sys/fs/cgroup/unified - cgroupRoot = filepath.Join(cgroupRoot, "unified") - - // Ignore the unified mount if it doesn't exist - if err := fileutils.Exists(cgroupRoot); err != nil && os.IsNotExist(err) { - continue - } - } else if parts[1] != "" { + if parts[1] != "" { // Assume the controller is mounted at /sys/fs/cgroup/$CONTROLLER. controller := strings.TrimPrefix(parts[1], "name=") cgroupRoot = filepath.Join(cgroupRoot, controller) @@ -292,15 +274,6 @@ var ( // it is running in the root cgroup on a system that uses cgroupv2. func MaybeMoveToSubCgroup() error { maybeMoveToSubCgroupSync.Do(func() { - unifiedMode, err := IsCgroup2UnifiedMode() - if err != nil { - maybeMoveToSubCgroupSyncErr = err - return - } - if !unifiedMode { - maybeMoveToSubCgroupSyncErr = nil - return - } cgroup, err := GetOwnCgroup() if err != nil { maybeMoveToSubCgroupSyncErr = err diff --git a/vendor/go.podman.io/common/pkg/config/default.go b/vendor/go.podman.io/common/pkg/config/default.go index 3bf0bc16929..8548ec5d7a6 100644 --- a/vendor/go.podman.io/common/pkg/config/default.go +++ b/vendor/go.podman.io/common/pkg/config/default.go @@ -15,7 +15,6 @@ import ( "go.podman.io/common/internal/attributedstring" nettypes "go.podman.io/common/libnetwork/types" "go.podman.io/common/pkg/apparmor" - "go.podman.io/common/pkg/cgroupv2" "go.podman.io/storage/pkg/fileutils" "go.podman.io/storage/pkg/homedir" "go.podman.io/storage/pkg/unshare" @@ -230,10 +229,7 @@ func defaultConfig() (*Config, error) { } } - cgroupNS := "host" - if cgroup2, _ := cgroupv2.Enabled(); cgroup2 { - cgroupNS = "private" - } + cgroupNS := "private" return &Config{ Containers: ContainersConfig{ @@ -652,12 +648,7 @@ func (c *Config) PidsLimit() int64 { if c.Engine.CgroupManager != SystemdCgroupsManager { return 0 } - cgroup2, _ := cgroupv2.Enabled() - if !cgroup2 { - return 0 - } } - return c.Containers.PidsLimit } diff --git a/vendor/go.podman.io/common/pkg/config/systemd.go b/vendor/go.podman.io/common/pkg/config/systemd.go index e7c15b59094..120656528f0 100644 --- a/vendor/go.podman.io/common/pkg/config/systemd.go +++ b/vendor/go.podman.io/common/pkg/config/systemd.go @@ -7,7 +7,6 @@ import ( "path/filepath" "sync" - "go.podman.io/common/pkg/cgroupv2" "go.podman.io/common/pkg/systemd" "go.podman.io/storage/pkg/unshare" ) @@ -26,8 +25,7 @@ func defaultCgroupManager() string { if !useSystemd() { return CgroupfsCgroupsManager } - enabled, err := cgroupv2.Enabled() - if err == nil && !enabled && unshare.IsRootless() { + if unshare.IsRootless() { return CgroupfsCgroupsManager } diff --git a/vendor/go.podman.io/common/pkg/sysinfo/sysinfo_linux.go b/vendor/go.podman.io/common/pkg/sysinfo/sysinfo_linux.go index ea98d49481c..efb0a8ce6b3 100644 --- a/vendor/go.podman.io/common/pkg/sysinfo/sysinfo_linux.go +++ b/vendor/go.podman.io/common/pkg/sysinfo/sysinfo_linux.go @@ -9,7 +9,6 @@ import ( "github.com/opencontainers/cgroups" "github.com/sirupsen/logrus" - "go.podman.io/common/pkg/cgroupv2" "go.podman.io/storage/pkg/fileutils" "golang.org/x/sys/unix" ) @@ -41,7 +40,6 @@ func New(quiet bool) *SysInfo { sysInfo.cgroupCPUInfo = checkCgroupCPU(cgMounts, quiet) sysInfo.cgroupBlkioInfo = checkCgroupBlkioInfo(cgMounts, quiet) sysInfo.cgroupCpusetInfo = checkCgroupCpusetInfo(cgMounts, quiet) - sysInfo.cgroupPids = checkCgroupPids(cgMounts, quiet) } _, ok := cgMounts["devices"] @@ -227,28 +225,6 @@ func checkCgroupCpusetInfo(cgMounts map[string]string, quiet bool) cgroupCpusetI } } -// checkCgroupPids reads the pids information from the pids cgroup mount point. -func checkCgroupPids(cgMounts map[string]string, quiet bool) cgroupPids { - cgroup2, err := cgroupv2.Enabled() - if err != nil { - logrus.Errorf("Failed to check cgroups version: %v", err) - return cgroupPids{} - } - if !cgroup2 { - _, ok := cgMounts["pids"] - if !ok { - if !quiet { - logrus.Warn("Unable to find pids cgroup in mounts") - } - return cgroupPids{} - } - } - - return cgroupPids{ - PidsLimit: true, - } -} - func cgroupEnabled(mountPoint, name string) bool { err := fileutils.Exists(path.Join(mountPoint, name)) return err == nil diff --git a/vendor/go.podman.io/common/pkg/systemd/systemd_linux.go b/vendor/go.podman.io/common/pkg/systemd/systemd_linux.go index a189cfbe052..82e3b8014cc 100644 --- a/vendor/go.podman.io/common/pkg/systemd/systemd_linux.go +++ b/vendor/go.podman.io/common/pkg/systemd/systemd_linux.go @@ -88,11 +88,7 @@ func MovePauseProcessToScope(pausePidPath string) { } if err != nil { - unified, err2 := cgroups.IsCgroup2UnifiedMode() - if err2 != nil { - logrus.Warnf("Failed to detect if running with cgroup unified: %v", err) - } - if RunsOnSystemd() && unified { + if RunsOnSystemd() { logrus.Warnf("Failed to add pause process to systemd sandbox cgroup: %v", err) } else { logrus.Debugf("Failed to add pause process to systemd sandbox cgroup: %v", err) diff --git a/vendor/go.podman.io/common/version/version.go b/vendor/go.podman.io/common/version/version.go index ad62f22ac32..4a2be1fe1e2 100644 --- a/vendor/go.podman.io/common/version/version.go +++ b/vendor/go.podman.io/common/version/version.go @@ -1,4 +1,4 @@ package version // Version is the version of the build. -const Version = "0.66.0" +const Version = "0.67.0-dev" diff --git a/vendor/modules.txt b/vendor/modules.txt index 25c9b916dbb..9cfb789b82e 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -56,8 +56,8 @@ github.com/containerd/log # github.com/containerd/platforms v1.0.0-rc.1 ## explicit; go 1.20 github.com/containerd/platforms -# github.com/containerd/stargz-snapshotter/estargz v0.17.0 -## explicit; go 1.23.0 +# github.com/containerd/stargz-snapshotter/estargz v0.18.0 +## explicit; go 1.24.0 github.com/containerd/stargz-snapshotter/estargz github.com/containerd/stargz-snapshotter/estargz/errorutil # github.com/containerd/typeurl/v2 v2.2.3 @@ -369,8 +369,8 @@ github.com/json-iterator/go # github.com/kevinburke/ssh_config v1.4.0 ## explicit; go 1.18 github.com/kevinburke/ssh_config -# github.com/klauspost/compress v1.18.0 -## explicit; go 1.22 +# github.com/klauspost/compress v1.18.1 +## explicit; go 1.23 github.com/klauspost/compress github.com/klauspost/compress/flate github.com/klauspost/compress/fse @@ -478,7 +478,7 @@ github.com/nxadm/tail/ratelimiter github.com/nxadm/tail/util github.com/nxadm/tail/watch github.com/nxadm/tail/winfile -# github.com/onsi/ginkgo/v2 v2.26.0 +# github.com/onsi/ginkgo/v2 v2.27.1 ## explicit; go 1.23.0 github.com/onsi/ginkgo/v2 github.com/onsi/ginkgo/v2/config @@ -562,8 +562,8 @@ github.com/openshift/imagebuilder/strslice # github.com/pkg/errors v0.9.1 ## explicit github.com/pkg/errors -# github.com/pkg/sftp v1.13.9 -## explicit; go 1.15 +# github.com/pkg/sftp v1.13.10 +## explicit; go 1.23.0 github.com/pkg/sftp github.com/pkg/sftp/internal/encoding/ssh/filexfer github.com/pkg/sftp/internal/encoding/ssh/filexfer/openssh @@ -680,7 +680,7 @@ github.com/ulikunitz/xz github.com/ulikunitz/xz/internal/hash github.com/ulikunitz/xz/internal/xlog github.com/ulikunitz/xz/lzma -# github.com/vbatts/tar-split v0.12.1 +# github.com/vbatts/tar-split v0.12.2 ## explicit; go 1.17 github.com/vbatts/tar-split/archive/tar github.com/vbatts/tar-split/tar/asm @@ -740,7 +740,7 @@ go.opentelemetry.io/otel/trace go.opentelemetry.io/otel/trace/embedded go.opentelemetry.io/otel/trace/internal/telemetry go.opentelemetry.io/otel/trace/noop -# go.podman.io/common v0.66.0 +# go.podman.io/common v0.66.0 => github.com/lsm5/container-libs/common v0.0.0-20251023145256-2c7c0ea9cefe ## explicit; go 1.24.2 go.podman.io/common/internal go.podman.io/common/internal/attributedstring @@ -1189,3 +1189,5 @@ tags.cncf.io/container-device-interface/pkg/parser # tags.cncf.io/container-device-interface/specs-go v1.0.0 ## explicit; go 1.19 tags.cncf.io/container-device-interface/specs-go +# go.podman.io/common => github.com/lsm5/container-libs/common v0.0.0-20251023145256-2c7c0ea9cefe +# go.podman.io/buildah => github.com/lsm5/buildah v0.0.0-20251023152205-884c02fbd526