From 1c111eead74ccace0dc94dbf2930a622c21e34a5 Mon Sep 17 00:00:00 2001 From: Brent Baude Date: Tue, 28 Jan 2025 13:44:14 -0600 Subject: [PATCH 01/58] error with libkrun on intel-based machines libkrun is not supported on Intel. We should error. Signed-off-by: Brent Baude --- cmd/podman/machine/machine.go | 5 +++++ pkg/machine/provider/platform_darwin.go | 7 ++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/cmd/podman/machine/machine.go b/cmd/podman/machine/machine.go index 1dd65c1ec8..d7db502418 100644 --- a/cmd/podman/machine/machine.go +++ b/cmd/podman/machine/machine.go @@ -8,6 +8,7 @@ import ( "os" "path/filepath" "regexp" + "runtime" "strings" "sync" "time" @@ -15,6 +16,7 @@ import ( "github.com/containers/podman/v5/cmd/podman/registry" "github.com/containers/podman/v5/cmd/podman/validate" "github.com/containers/podman/v5/libpod/events" + "github.com/containers/podman/v5/pkg/machine/define" "github.com/containers/podman/v5/pkg/machine/env" provider2 "github.com/containers/podman/v5/pkg/machine/provider" "github.com/containers/podman/v5/pkg/machine/vmconfigs" @@ -57,6 +59,9 @@ func machinePreRunE(c *cobra.Command, args []string) error { if err != nil { return err } + if provider.VMType() == define.LibKrun && runtime.GOARCH == "amd64" { + return errors.New("libkrun is not supported on Intel based machines. Please revert to the applehv provider") + } return rootlessOnly(c, args) } diff --git a/pkg/machine/provider/platform_darwin.go b/pkg/machine/provider/platform_darwin.go index f4241d5b62..d15a11bdb7 100644 --- a/pkg/machine/provider/platform_darwin.go +++ b/pkg/machine/provider/platform_darwin.go @@ -43,10 +43,11 @@ func Get() (vmconfigs.VMProvider, error) { } func GetAll() []vmconfigs.VMProvider { - return []vmconfigs.VMProvider{ - new(applehv.AppleHVStubber), - new(libkrun.LibKrunStubber), + configs := []vmconfigs.VMProvider{new(applehv.AppleHVStubber)} + if runtime.GOARCH == "arm64" { + configs = append(configs, new(libkrun.LibKrunStubber)) } + return configs } // SupportedProviders returns the providers that are supported on the host operating system From fa0e8f05827cdb4844ef01f5a333a1df1d11c16d Mon Sep 17 00:00:00 2001 From: Mario Loriedo Date: Tue, 28 Jan 2025 19:09:06 +0100 Subject: [PATCH 02/58] Safer use of `filepath.EvalSymlinks()` on Windows The behavior of function `path/filepath.EvalSymlinks()` has changed in Go v1.23: - https://go-review.googlesource.com/c/go/+/565136 - https://go.dev/doc/go1.23#minor_library_changes - https://tip.golang.org/doc/godebug As a consequences, starting with Podman 5.3.0, when installing on Windows (WSL) using scoop, Podman fails to start because it fails to find helper binaries. Scoop copies Podman binaries in a folder of type Junction and `EvalSymlinks` returns an error. The problem is described in #24557. To address this problem we are checking if a path is a `Symlink` before calling `EvalSymlinks` and, if it's not (hardlinks, mount points or canonical files), we are calling `path/filepath.Clean` for consistency. In fact `path/filepath.EvalSymlinks`, after evaluating a symlink target, calls `Clean` too. Signed-off-by: Mario Loriedo --- pkg/machine/machine_windows.go | 24 +++++- pkg/machine/machine_windows_test.go | 116 ++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 pkg/machine/machine_windows_test.go diff --git a/pkg/machine/machine_windows.go b/pkg/machine/machine_windows.go index 174980fc29..dd59876ad3 100644 --- a/pkg/machine/machine_windows.go +++ b/pkg/machine/machine_windows.go @@ -251,7 +251,7 @@ func FindExecutablePeer(name string) (string, error) { return "", err } - exe, err = filepath.EvalSymlinks(exe) + exe, err = EvalSymlinksOrClean(exe) if err != nil { return "", err } @@ -259,6 +259,28 @@ func FindExecutablePeer(name string) (string, error) { return filepath.Join(filepath.Dir(exe), name), nil } +func EvalSymlinksOrClean(filePath string) (string, error) { + fileInfo, err := os.Lstat(filePath) + if err != nil { + return "", err + } + if fileInfo.Mode()&fs.ModeSymlink != 0 { + // Only call filepath.EvalSymlinks if it is a symlink. + // Starting with v1.23, EvalSymlinks returns an error for mount points. + // See https://go-review.googlesource.com/c/go/+/565136 for reference. + filePath, err = filepath.EvalSymlinks(filePath) + if err != nil { + return "", err + } + } else { + // Call filepath.Clean when filePath is not a symlink. That's for + // consistency with the symlink case (filepath.EvalSymlinks calls + // Clean after evaluating filePath). + filePath = filepath.Clean(filePath) + } + return filePath, nil +} + func GetWinProxyStateDir(name string, vmtype define.VMType) (string, error) { dir, err := env.GetDataDir(vmtype) if err != nil { diff --git a/pkg/machine/machine_windows_test.go b/pkg/machine/machine_windows_test.go new file mode 100644 index 0000000000..48f3eafd53 --- /dev/null +++ b/pkg/machine/machine_windows_test.go @@ -0,0 +1,116 @@ +//go:build windows + +package machine + +import ( + "os" + "os/exec" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// CreateNewItemWithPowerShell creates a new item using PowerShell. +// It's an helper to easily create junctions on Windows (as well as other file types). +// It constructs a PowerShell command to create a new item at the specified path with the given item type. +// If a target is provided, it includes it in the command. +// +// Parameters: +// - t: The testing.T instance. +// - path: The path where the new item will be created. +// - itemType: The type of the item to be created (e.g., "File", "SymbolicLink", "Junction"). +// - target: The target for the new item, if applicable. +func CreateNewItemWithPowerShell(t *testing.T, path string, itemType string, target string) { + var pwshCmd string + pwshCmd = "New-Item -Path " + path + " -ItemType " + itemType + if target != "" { + pwshCmd += " -Target " + target + } + cmd := exec.Command("pwsh", "-Command", pwshCmd) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + err := cmd.Run() + require.NoError(t, err) +} + +// TestEvalSymlinksOrClean tests the EvalSymlinksOrClean function. +// In particular it verifies that EvalSymlinksOrClean behaves as +// filepath.EvalSymlink before Go 1.23 - with the exception of +// files under a mount point (juntion) that aren't resolved +// anymore. +// The old behavior of filepath.EvalSymlinks can be tested with +// the directive "//go:debug winsymlink=0" and replacing EvalSymlinksOrClean() +// with filepath.EvalSymlink(). +func TestEvalSymlinksOrClean(t *testing.T) { + // Create a temporary directory to store the normal file + normalFileDir := t.TempDir() + + // Create a temporary directory to store the (hard/sym)link files + linkFilesDir := t.TempDir() + + // Create a temporary directory where the mount point will be created + mountPointDir := t.TempDir() + + // Create a normal file + normalFile := filepath.Join(normalFileDir, "testFile") + CreateNewItemWithPowerShell(t, normalFile, "File", "") + + // Create a symlink file + symlinkFile := filepath.Join(linkFilesDir, "testSymbolicLink") + CreateNewItemWithPowerShell(t, symlinkFile, "SymbolicLink", normalFile) + + // Create a hardlink file + hardlinkFile := filepath.Join(linkFilesDir, "testHardLink") + CreateNewItemWithPowerShell(t, hardlinkFile, "HardLink", normalFile) + + // Create a mount point file + mountPoint := filepath.Join(mountPointDir, "testJunction") + mountPointFile := filepath.Join(mountPoint, "testFile") + CreateNewItemWithPowerShell(t, mountPoint, "Junction", normalFileDir) + + // Replaces the backslashes with forward slashes in the normal file path + normalFileWithBadSeparators := filepath.ToSlash(normalFile) + + tests := []struct { + name string + filePath string + want string + }{ + { + name: "Normal file", + filePath: normalFile, + want: normalFile, + }, + { + name: "File under a mount point (juntion)", + filePath: mountPointFile, + want: mountPointFile, + }, + { + name: "Symbolic link", + filePath: symlinkFile, + want: normalFile, + }, + { + name: "Hard link", + filePath: hardlinkFile, + want: hardlinkFile, + }, + { + name: "Bad separators in path", + filePath: normalFileWithBadSeparators, + want: normalFile, + }, + } + + for _, tt := range tests { + assert := assert.New(t) + t.Run(tt.name, func(t *testing.T) { + got, err := EvalSymlinksOrClean(tt.filePath) + require.NoError(t, err) + assert.Equal(tt.want, got) + }) + } +} From d52277db75a05853cdb392ef914e67cbc8987aee Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Wed, 29 Jan 2025 15:14:32 -0500 Subject: [PATCH 03/58] Update release notes for v5.4.0-rc2 Signed-off-by: Matthew Heon --- RELEASE_NOTES.md | 76 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index c1f9b86831..acfd7e0ea1 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,81 @@ # Release Notes +## 5.4.0 +### Features +- A preview of Podman's support for OCI artifacts has been added through the `podman artifact` suite of commands, including `add`, `inspect`, `ls`, `pull`, `push`, and `rm`. This support is very early and not fully complete, and the command line interface for these tools has not been finalized. We welcome feedback on the new artifact experience through our issue tracker! +- The `podman update` command now supports a wide variety of options related to healthchecks (including `--health-cmd` to define a new healthcheck and `--no-healthcheck` to disable an existing healthcheck), allowing healthchecks to be added to, removed from, and otherwise updated on existing containers. You can find full details on the 15 added options in the manpage. +- The `--mount type=volume` option for the `podman run`, `podman create`, and `podman volume create` commands now supports a new option, `subpath=`, to make only a subset of the volume visible in the container ([#20661](https://github.com/containers/podman/issues/20661)). +- The `--userns=keep-id` option for the `podman run`, `podman create`, and `podman pod create` commands now supports a new option, `--userns=keep-id:size=`, to configure the size of the user namespace ([#24387](https://github.com/containers/podman/issues/24837)). +- The `podman kube play` command now supports Container Device Interface (CDI) devices ([#17833](https://github.com/containers/podman/issues/17833)). +- Quadlet `.pod` files now support a new field, `ShmSize`, to specify the size of the pod's shared SHM ([#22915](https://github.com/containers/podman/issues/22915)). +- The `podman run`, `podman create`, and `podman pod create` commands now support a new option, `--hosts-file`, to define the base file used for `/etc/hosts` in the container. +- The `podman run`, `podman create`, and `podman pod create` commands now support a new option, `--no-hostname`, which disables the creation of `/etc/hostname` in the container ([#25002](https://github.com/containers/podman/issues/25002)). +- The `podman network create` command now supports a new option for `bridge` networks, `--opt mode=unmanaged`, which allows Podman to use an existing network bridge on the system without changes. +- The `--network` option to `podman run`, `podman create`, and `podman pod create` now accepts a new option for `bridge` networks, `host_interface_name`, which specifies a name for the network interface created outside the container. +- The `podman manifest rm` command now supports a new option, `--ignore`, to not error when removing manifests that do not exist. +- The `podman system prune` command now supports a new option, `--build`, to remove build containers leftover from prematurely terminated builds. +- The `podman events` command now generates events for the creation and removal of networks ([#24032](https://github.com/containers/podman/issues/24032)). + +### Breaking Changes +- Due to a lack of availability of hardware to test on, the Podman maintainers are no longer capable of providing full support for Podman on Intel Macs. Binaries and machine images will still be produced, and pull requests related to MacOS on Intel systems will still be merged, but bugs will be fixed on a best effort basis only. We welcome any potential new maintainers who would be able to assist in restoring full support. +- Quadlet previously incorrectly allowed `:` as a character to define comments. This was a mistake; developer intent and documentation was that `#` and `;` were to be used as comment characters instead, matching systemd. This has been corrected, and semicolons now define comments instead of colons. + +### Changes +- Podman now passes container hostnames to Netavark, which will use them for any DHCP requests for the container. +- Partial pulls of `zstd:chunked` images now only happen for images that have a `RootFS.DiffID` entry in the image's OCI config JSON, and require the layer contents to match. This resolves issues with image ID ambiguity when partial pulls were enabled. + +### Bugfixes +- Fixed a bug where `podman machine` VMs on WSL could fail to start when using usermode networking could fail to start due to a port conflict ([#20327](https://github.com/containers/podman/issues/20327)). +- Fixed a bug where overlay mounts could not be made at paths where the image specifies a volume ([#24555](https://github.com/containers/podman/issues/24555)). +- Fixed a bug where the `podman build` command did not honor the `no_pivot_root` setting from `containers.conf` ([#24546](https://github.com/containers/podman/issues/24546)). +- Fixed a bug where volumes would have the wrong permissions if `podman cp` was used to copy into a fresh volume in a container that had never been started. +- Fixed a bug where using `podman cp` to copy into a named volume requiring a mount (image volumes, volumes backed by a volume plugin, or other volumes with options) would fail when the container being copied into was stopped. +- Fixed a bug where rlimits would be set incorrectly when Podman was run as root but without `CAP_SYS_RESOURCE` ([#24692](https://github.com/containers/podman/issues/24692)). +- Fixed a bug where the `podman stats --all` command would fail if a container started with `--cgroups=none` was present ([#24632](https://github.com/containers/podman/issues/24632)). +- Fixed a bug where the `podman info` command would only return details on one image store even if additional image stores were configured in `storage.conf`. +- Fixed a bug where the `podman update` command could reset resource limits that were not being modified to default ([#24610](https://github.com/containers/podman/issues/24610)). +- Fixed a bug where the remote Podman client's `podman update` command could not update resource limits on devices mounted into the container ([#24734](https://github.com/containers/podman/issues/24734)). +- Fixed a bug where the `podman manifest annotate` command could panic when the `--index` option was used ([#24750](https://github.com/containers/podman/issues/24750)). +- Fixed a bug where a Quadlet container reusing another container's network could cause errors if the second container was not already running. +- Fixed a bug where Quadlet files containing lines with a trailing backslash could cause an infinite loop during parsing ([#24810](https://github.com/containers/podman/issues/24810)). +- Fixed a bug where Quadlet would, when run as a non-root user, not generate for files in subfolders of `/etc/containers/systemd/users/` ([#24783](https://github.com/containers/podman/issues/24783)). +- Fixed a bug where values in Quadlet files containing octal escape sequences were incorrectly unescaped. +- Fixed a bug where `podman generate kube` could generate persistent volumes with mixed-case names or names containing an underscore, which are not supported by Kubernetes ([#16542](https://github.com/containers/podman/issues/16542)). +- Fixed a bug where the `ptmxmode` option to `--mount type=devpts` did not function. +- Fixed a bug where shell completion on Windows would include `.exe` in the executable name, breaking completion on some shells. +- Fixed a bug where the output of `podman inspect` on containers did not include the ID of the network the container was joined to, improving Docker compatibility ([#24910](https://github.com/containers/podman/issues/24910)). +- Fixed a bug where containers created with the remote API incorrectly included a create command ([#25026](https://github.com/containers/podman/issues/25026)). +- Fixed a bug where it was possible to specify the `libkrun` backend for VMs on Intel Macs (`libkrun` only supports Arm systems). + +### API +- The Compat and Libpod Build APIs for Images now support a new query parameter, `nohosts`, which (when set to true) does not create `/etc/hosts` in the image when building. + +### Misc +- The Docker alias script has been fixed to better handle variable substitution. +- Fixed a bug where `podman-restart.service` functioned incorrectly when no containers were present. + +## 5.3.2 +### Security +- This release contains Buildah v1.38.1 which addresses [CVE-2024-11218](https://github.com/advisories/GHSA-5vpc-35f4-r8w6). + +### Bugfixes +- Fixed a bug where Quadlet `.build` files could create an invalid podman command line when `Pull=` was used ([#24599](https://github.com/containers/podman/issues/24599)). +- Fixed a bug where the Mac installer did not install the Podman manpages ([#24756](https://github.com/containers/podman/issues/24756)). + +### Misc +- Updated Buildah to v1.38.1 +- Updated the containers/common library to v0.61.1 +- Updated the containers/storage library to v1.56.1 +- Updated the containers/image library to v5.33.1 + +## 5.3.1 +### Bugfixes +- Fixed a bug where the `--ignition-path` option to `podman machine init` would prevent creation of necessary files for the VM, rendering it unusable ([#23544](https://github.com/containers/podman/issues/23544)). +- Fixed a bug where rootless containers using the `bridge` networking mode would be unable to start due to a panic caused by a nil pointer dereference ([#24566](https://github.com/containers/podman/issues/24566)). +- Fixed a bug where Podman containers would try to set increased rlimits when started in a user namespace, rendering containers unable to start ([#24508](https://github.com/containers/podman/issues/24508)). +- Fixed a bug where certain SSH configurations would make the remote Podman client unable to connect to the server ([#24567](https://github.com/containers/podman/issues/24567)). +- Fixed a bug where the Windows installer could install WSLv2 when upgrading an existing Podman installation that used the Hyper-V virtualization backend. + ## 5.3.0 ### Features - The `podman kube generate` and `podman kube play` commands can now create and run Kubernetes Job YAML ([#17011](https://github.com/containers/podman/issues/17011)). From 14f6a69dd3f8d7922549dd5ed2b773b6ea5bb30e Mon Sep 17 00:00:00 2001 From: Matt Heon Date: Wed, 29 Jan 2025 15:15:38 -0500 Subject: [PATCH 04/58] Bump to v5.4.0-rc2 Signed-off-by: Matt Heon --- version/rawversion/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version/rawversion/version.go b/version/rawversion/version.go index a2f65f18d6..70e6cd3388 100644 --- a/version/rawversion/version.go +++ b/version/rawversion/version.go @@ -7,4 +7,4 @@ package rawversion // // NOTE: remember to bump the version at the top of the top-level README.md // file when this is bumped. -const RawVersion = "5.4.0-dev" +const RawVersion = "5.4.0-rc2" From d475b48766ecdbf4e65087e346905304844b8183 Mon Sep 17 00:00:00 2001 From: Matt Heon Date: Wed, 29 Jan 2025 15:15:54 -0500 Subject: [PATCH 05/58] Bump to v5.4.0-dev Signed-off-by: Matt Heon --- version/rawversion/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version/rawversion/version.go b/version/rawversion/version.go index 70e6cd3388..a2f65f18d6 100644 --- a/version/rawversion/version.go +++ b/version/rawversion/version.go @@ -7,4 +7,4 @@ package rawversion // // NOTE: remember to bump the version at the top of the top-level README.md // file when this is bumped. -const RawVersion = "5.4.0-rc2" +const RawVersion = "5.4.0-dev" From bba28688f779bd7241006708d464ac0a498d540e Mon Sep 17 00:00:00 2001 From: Brent Baude Date: Mon, 27 Jan 2025 12:41:48 -0600 Subject: [PATCH 06/58] Remove usused Kind() function The Kind() exported function is unused in our code; moreover, the function cannot be accurate because in the case of darwin, applehv and libkrun use the same config in the struct and therefore, we cannot identify the provider via that method. Signed-off-by: Brent Baude --- pkg/machine/vmconfigs/machine.go | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/pkg/machine/vmconfigs/machine.go b/pkg/machine/vmconfigs/machine.go index 8627a0b19e..256c20ae4a 100644 --- a/pkg/machine/vmconfigs/machine.go +++ b/pkg/machine/vmconfigs/machine.go @@ -303,24 +303,6 @@ func (mc *MachineConfig) LogFile() (*define.VMFile, error) { return rtDir.AppendToNewVMFile(mc.Name+".log", nil) } -func (mc *MachineConfig) Kind() (define.VMType, error) { - // Not super in love with this approach - if mc.QEMUHypervisor != nil { - return define.QemuVirt, nil - } - if mc.AppleHypervisor != nil { - return define.AppleHvVirt, nil - } - if mc.HyperVHypervisor != nil { - return define.HyperVVirt, nil - } - if mc.WSLHypervisor != nil { - return define.WSLVirt, nil - } - - return define.UnknownVirt, nil -} - func (mc *MachineConfig) IsFirstBoot() (bool, error) { never, err := time.Parse(time.RFC3339, "0001-01-01T00:00:00Z") if err != nil { From 03b100563e1488efcb4bd7b4cb968335c1f9f94c Mon Sep 17 00:00:00 2001 From: Brent Baude Date: Mon, 27 Jan 2025 12:43:28 -0600 Subject: [PATCH 07/58] Remove unnecessary error handling A function in the reset code does not return an error. Simply removing the error variable and check for the condition (which was always false or nil) Signed-off-by: Brent Baude --- cmd/podman/machine/reset.go | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/cmd/podman/machine/reset.go b/cmd/podman/machine/reset.go index 2d49d8f8cd..bcfb88eabe 100644 --- a/cmd/podman/machine/reset.go +++ b/cmd/podman/machine/reset.go @@ -47,15 +47,8 @@ func init() { } func reset(_ *cobra.Command, _ []string) error { - var ( - err error - ) - - providers := provider2.GetAll() - if err != nil { - return err - } - for _, p := range providers { + allProviders := provider2.GetAll() + for _, p := range allProviders { hasPerms := provider2.HasPermsForProvider(p.VMType()) isInstalled, err := provider2.IsInstalled(p.VMType()) if !hasPerms && (isInstalled || err != nil) && !resetOptions.Force { @@ -65,7 +58,7 @@ func reset(_ *cobra.Command, _ []string) error { } if !resetOptions.Force { - listResponse, err := shim.List(providers, machine.ListOptions{}) + listResponse, err := shim.List(allProviders, machine.ListOptions{}) if err != nil { return err } @@ -82,7 +75,7 @@ func reset(_ *cobra.Command, _ []string) error { return nil } } - return shim.Reset(providers, resetOptions) + return shim.Reset(allProviders, resetOptions) } func resetConfirmationMessage(listResponse []*machine.ListResponse) { From 599da8c50b9068df4694b8388031ab7798ba48a5 Mon Sep 17 00:00:00 2001 From: Brent Baude Date: Mon, 27 Jan 2025 12:45:01 -0600 Subject: [PATCH 08/58] Prevent two podman machines running on darwin As issue #25112 points out, it was possible to start a machine on one of the darwin providers and then switch providers and start another one with a different name. This PR firstly prevents that use which is a forbidden use case. Secondarily, performed some minor cleanup on the error messages being used so that the error would be specific to this condition. This bug fix is for darwin only. In the case of Windows, we probably need to answer the question I raised in #24067 first, which is whether we want to stop allowing WSL to run multiple machines. Fixes #25112 Signed-off-by: Brent Baude --- pkg/machine/define/errors.go | 22 ++++++++++++++------ pkg/machine/e2e/start_test.go | 10 +++++---- pkg/machine/shim/host.go | 38 ++++++++++++++++++++++++++--------- 3 files changed, 50 insertions(+), 20 deletions(-) diff --git a/pkg/machine/define/errors.go b/pkg/machine/define/errors.go index 1a32bc5165..5b241c7566 100644 --- a/pkg/machine/define/errors.go +++ b/pkg/machine/define/errors.go @@ -8,12 +8,9 @@ import ( ) var ( - ErrNoSuchVM = errors.New("VM does not exist") - ErrWrongState = errors.New("VM in wrong state to perform action") - ErrVMAlreadyExists = errors.New("VM already exists") - ErrVMAlreadyRunning = errors.New("VM already running or starting") - ErrMultipleActiveVM = errors.New("only one VM can be active at a time") - ErrNotImplemented = errors.New("functionality not implemented") + ErrWrongState = errors.New("VM in wrong state to perform action") + ErrVMAlreadyExists = errors.New("VM already exists") + ErrNotImplemented = errors.New("functionality not implemented") ) type ErrVMRunningCannotDestroyed struct { @@ -49,3 +46,16 @@ type ErrIncompatibleMachineConfig struct { func (err *ErrIncompatibleMachineConfig) Error() string { return fmt.Sprintf("incompatible machine config %q (%s) for this version of Podman", err.Path, err.Name) } + +type ErrMultipleActiveVM struct { + Name string + Provider string +} + +func (err *ErrMultipleActiveVM) Error() string { + msg := "" + if err.Provider != "" { + msg = " on the " + err.Provider + " provider" + } + return fmt.Sprintf("%s already starting or running%s: only one VM can be active at a time", err.Name, msg) +} diff --git a/pkg/machine/e2e/start_test.go b/pkg/machine/e2e/start_test.go index 1ee43206dd..73a25b5eb4 100644 --- a/pkg/machine/e2e/start_test.go +++ b/pkg/machine/e2e/start_test.go @@ -61,8 +61,10 @@ var _ = Describe("podman machine start", func() { }) It("start machine already started", func() { + name := randomString() i := new(initMachine) - session, err := mb.setCmd(i.withImage(mb.imagePath)).run() + machineTestBuilderInit := mb.setName(name).setCmd(i.withImage(mb.imagePath)) + session, err := machineTestBuilderInit.run() Expect(err).ToNot(HaveOccurred()) Expect(session).To(Exit(0)) s := new(startMachine) @@ -78,7 +80,7 @@ var _ = Describe("podman machine start", func() { startSession, err = mb.setCmd(s).run() Expect(err).ToNot(HaveOccurred()) Expect(startSession).To(Exit(125)) - Expect(startSession.errorToString()).To(ContainSubstring("VM already running or starting")) + Expect(startSession.errorToString()).To(ContainSubstring(fmt.Sprintf("Error: unable to start %q: already running", machineTestBuilderInit.name))) }) It("start machine with conflict on SSH port", func() { @@ -210,10 +212,10 @@ var _ = Describe("podman machine start", func() { Expect(startSession1).To(Or(Exit(0), Exit(125)), "start command should succeed or fail with 125") if startSession1.ExitCode() == 0 { Expect(startSession2).To(Exit(125), "first start worked, second start must fail") - Expect(startSession2.errorToString()).To(ContainSubstring("machine %s is already running: only one VM can be active at a time", machine1)) + Expect(startSession2.errorToString()).To(ContainSubstring("%s already starting or running: only one VM can be active at a time", machine1)) } else { Expect(startSession2).To(Exit(0), "first start failed, second start succeed") - Expect(startSession1.errorToString()).To(ContainSubstring("machine %s is already running: only one VM can be active at a time", machine2)) + Expect(startSession1.errorToString()).To(ContainSubstring("%s already starting or running: only one VM can be active at a time", machine2)) } }) }) diff --git a/pkg/machine/shim/host.go b/pkg/machine/shim/host.go index b0daa19ba9..1315c9adb9 100644 --- a/pkg/machine/shim/host.go +++ b/pkg/machine/shim/host.go @@ -265,7 +265,7 @@ func VMExists(name string, vmstubbers []vmconfigs.VMProvider) (*vmconfigs.Machin return nil, false, err } if mc, found := mcs[name]; found { - return mc, true, nil + return mc.MachineConfig, true, nil } // Check with the provider hypervisor for _, vmstubber := range vmstubbers { @@ -281,31 +281,46 @@ func VMExists(name string, vmstubbers []vmconfigs.VMProvider) (*vmconfigs.Machin } // checkExclusiveActiveVM checks if any of the machines are already running -func checkExclusiveActiveVM(provider vmconfigs.VMProvider, mc *vmconfigs.MachineConfig) error { +func checkExclusiveActiveVM(currentProvider vmconfigs.VMProvider, mc *vmconfigs.MachineConfig) error { + providers := provider.GetAll() // Check if any other machines are running; if so, we error - localMachines, err := getMCsOverProviders([]vmconfigs.VMProvider{provider}) + localMachines, err := getMCsOverProviders(providers) if err != nil { return err } + for name, localMachine := range localMachines { - state, err := provider.State(localMachine, false) + state, err := localMachine.Provider.State(localMachine.MachineConfig, false) if err != nil { return err } if state == machineDefine.Running || state == machineDefine.Starting { if mc.Name == name { - return fmt.Errorf("unable to start %q: machine %s: %w", mc.Name, name, machineDefine.ErrVMAlreadyRunning) + return fmt.Errorf("unable to start %q: already running", mc.Name) + } + + // A machine is running in the current provider + if currentProvider.VMType() == localMachine.Provider.VMType() { + fail := machineDefine.ErrMultipleActiveVM{Name: name} + return fmt.Errorf("unable to start %q: %w", mc.Name, &fail) } - return fmt.Errorf("unable to start %q: machine %s is already running: %w", mc.Name, name, machineDefine.ErrMultipleActiveVM) + // A machine is running in an alternate provider + fail := machineDefine.ErrMultipleActiveVM{Name: name, Provider: localMachine.Provider.VMType().String()} + return fmt.Errorf("unable to start: %w", &fail) } } return nil } +type knownMachineConfig struct { + Provider vmconfigs.VMProvider + MachineConfig *vmconfigs.MachineConfig +} + // getMCsOverProviders loads machineconfigs from a config dir derived from the "provider". it returns only what is known on // disk so things like status may be incomplete or inaccurate -func getMCsOverProviders(vmstubbers []vmconfigs.VMProvider) (map[string]*vmconfigs.MachineConfig, error) { - mcs := make(map[string]*vmconfigs.MachineConfig) +func getMCsOverProviders(vmstubbers []vmconfigs.VMProvider) (map[string]knownMachineConfig, error) { + mcs := make(map[string]knownMachineConfig) for _, stubber := range vmstubbers { dirs, err := env.GetMachineDirs(stubber.VMType()) if err != nil { @@ -320,7 +335,10 @@ func getMCsOverProviders(vmstubbers []vmconfigs.VMProvider) (map[string]*vmconfi // iterate known mcs and add the stubbers for mcName, mc := range stubberMCs { if _, ok := mcs[mcName]; !ok { - mcs[mcName] = mc + mcs[mcName] = knownMachineConfig{ + Provider: stubber, + MachineConfig: mc, + } } } } @@ -414,7 +432,7 @@ func Start(mc *vmconfigs.MachineConfig, mp vmconfigs.VMProvider, dirs *machineDe } if state == machineDefine.Running || state == machineDefine.Starting { - return fmt.Errorf("machine %s: %w", mc.Name, machineDefine.ErrVMAlreadyRunning) + return fmt.Errorf("unable to start %q: already running", mc.Name) } } From 5f6adf4d80ba790e634335c1aa69c83aa25ddbb2 Mon Sep 17 00:00:00 2001 From: Brent Baude Date: Wed, 29 Jan 2025 07:58:04 -0600 Subject: [PATCH 09/58] Move detection of libkrun and intel A review comment post merge suggested I move the detection of libkrun and intel into the provider.Get() Signed-off-by: Brent Baude --- cmd/podman/machine/machine.go | 5 ----- pkg/machine/provider/platform_darwin.go | 4 ++++ 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/cmd/podman/machine/machine.go b/cmd/podman/machine/machine.go index d7db502418..1dd65c1ec8 100644 --- a/cmd/podman/machine/machine.go +++ b/cmd/podman/machine/machine.go @@ -8,7 +8,6 @@ import ( "os" "path/filepath" "regexp" - "runtime" "strings" "sync" "time" @@ -16,7 +15,6 @@ import ( "github.com/containers/podman/v5/cmd/podman/registry" "github.com/containers/podman/v5/cmd/podman/validate" "github.com/containers/podman/v5/libpod/events" - "github.com/containers/podman/v5/pkg/machine/define" "github.com/containers/podman/v5/pkg/machine/env" provider2 "github.com/containers/podman/v5/pkg/machine/provider" "github.com/containers/podman/v5/pkg/machine/vmconfigs" @@ -59,9 +57,6 @@ func machinePreRunE(c *cobra.Command, args []string) error { if err != nil { return err } - if provider.VMType() == define.LibKrun && runtime.GOARCH == "amd64" { - return errors.New("libkrun is not supported on Intel based machines. Please revert to the applehv provider") - } return rootlessOnly(c, args) } diff --git a/pkg/machine/provider/platform_darwin.go b/pkg/machine/provider/platform_darwin.go index d15a11bdb7..5751b42a93 100644 --- a/pkg/machine/provider/platform_darwin.go +++ b/pkg/machine/provider/platform_darwin.go @@ -2,6 +2,7 @@ package provider import ( "bytes" + "errors" "fmt" "os" "os/exec" @@ -36,6 +37,9 @@ func Get() (vmconfigs.VMProvider, error) { case define.AppleHvVirt: return new(applehv.AppleHVStubber), nil case define.LibKrun: + if runtime.GOARCH == "amd64" { + return nil, errors.New("libkrun is not supported on Intel based machines. Please revert to the applehv provider") + } return new(libkrun.LibKrunStubber), nil default: return nil, fmt.Errorf("unsupported virtualization provider: `%s`", resolvedVMType.String()) From 25674e05cde3a107790f6f479b69b0ddb6810510 Mon Sep 17 00:00:00 2001 From: tomsweeneyredhat Date: Fri, 31 Jan 2025 18:36:02 -0500 Subject: [PATCH 10/58] [v5.4] Bump c/storage to v1.57.1, c/image v5.34.0, c/common v0.62.0 If not already bumped, this will bump: c/storage v1.57.1 c/image v5.34.0 c/common v0.62.0 in preparation for Podman v5.4 and beyond. Buildah will be vendored in a separate PR. Signed-off-by: tomsweeneyredhat --- go.mod | 8 +- go.sum | 15 +- .../common/libnetwork/cni/config.go | 2 +- .../internal/rootlessnetns/netns_linux.go | 9 + .../common/libnetwork/internal/util/bridge.go | 10 +- .../common/libnetwork/netavark/config.go | 21 +- .../containers/common/version/version.go | 2 +- .../image/v5/docker/registries_d.go | 6 + .../sysregistriesv2/system_registries_v2.go | 6 + .../v5/pkg/tlsclientconfig/tlsclientconfig.go | 10 +- .../containers/image/v5/version/version.go | 4 +- vendor/github.com/containers/storage/VERSION | 2 +- .../storage/pkg/chunked/compression_linux.go | 26 +- .../storage/pkg/chunked/storage_linux.go | 239 ++++++++++-------- .../pkg/chunked/storage_unsupported.go | 2 +- vendor/github.com/spf13/pflag/.editorconfig | 12 + vendor/github.com/spf13/pflag/.golangci.yaml | 4 + vendor/github.com/spf13/pflag/flag.go | 29 ++- vendor/github.com/spf13/pflag/ip.go | 3 + vendor/github.com/spf13/pflag/ipnet_slice.go | 147 +++++++++++ vendor/github.com/spf13/pflag/string_array.go | 4 - vendor/modules.txt | 8 +- 22 files changed, 414 insertions(+), 155 deletions(-) create mode 100644 vendor/github.com/spf13/pflag/.editorconfig create mode 100644 vendor/github.com/spf13/pflag/.golangci.yaml create mode 100644 vendor/github.com/spf13/pflag/ipnet_slice.go diff --git a/go.mod b/go.mod index 4dec8a91a9..597791f546 100644 --- a/go.mod +++ b/go.mod @@ -14,14 +14,14 @@ require ( github.com/checkpoint-restore/go-criu/v7 v7.2.0 github.com/containernetworking/plugins v1.5.1 github.com/containers/buildah v1.38.1-0.20250125114111-92015b7f4301 - github.com/containers/common v0.61.1-0.20250124131345-fa339b6b6eda + github.com/containers/common v0.62.0 github.com/containers/conmon v2.0.20+incompatible github.com/containers/gvisor-tap-vsock v0.8.2 - github.com/containers/image/v5 v5.33.2-0.20250122233652-b5c6aff95ca7 + github.com/containers/image/v5 v5.34.0 github.com/containers/libhvee v0.9.0 github.com/containers/ocicrypt v1.2.1 github.com/containers/psgo v1.9.0 - github.com/containers/storage v1.56.2-0.20250123125217-80d3c0e77d29 + github.com/containers/storage v1.57.1 github.com/containers/winquit v1.1.0 github.com/coreos/go-systemd/v22 v22.5.1-0.20231103132048-7d375ecc2b09 github.com/crc-org/crc/v2 v2.45.0 @@ -66,7 +66,7 @@ require ( github.com/shirou/gopsutil/v4 v4.24.12 github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.8.1 - github.com/spf13/pflag v1.0.5 + github.com/spf13/pflag v1.0.6 github.com/stretchr/testify v1.10.0 github.com/vbauerster/mpb/v8 v8.9.1 github.com/vishvananda/netlink v1.3.1-0.20240922070040-084abd93d350 diff --git a/go.sum b/go.sum index b3183c2d05..e69198f24e 100644 --- a/go.sum +++ b/go.sum @@ -78,14 +78,14 @@ github.com/containernetworking/plugins v1.5.1 h1:T5ji+LPYjjgW0QM+KyrigZbLsZ8jaX+ github.com/containernetworking/plugins v1.5.1/go.mod h1:MIQfgMayGuHYs0XdNudf31cLLAC+i242hNm6KuDGqCM= github.com/containers/buildah v1.38.1-0.20250125114111-92015b7f4301 h1:eqHczpfbWOjyvQAkuCmzsZPds657cPXxXniXLcKFHdQ= github.com/containers/buildah v1.38.1-0.20250125114111-92015b7f4301/go.mod h1:UOhJzUS2A0uyZR/TygObcg2Og+nJ02pwMfVhIQBRIN8= -github.com/containers/common v0.61.1-0.20250124131345-fa339b6b6eda h1:ltztaW234A8UvR3xz0hY4eD8ABo3B6gd3kGKVHPqGuE= -github.com/containers/common v0.61.1-0.20250124131345-fa339b6b6eda/go.mod h1:mWhwkYaWR5bXeOwq3ruzdmH9gaT2pex00C6pd4VXuvM= +github.com/containers/common v0.62.0 h1:Sl9WE5h7Y/F3bejrMAA4teP1EcY9ygqJmW4iwSloZ10= +github.com/containers/common v0.62.0/go.mod h1:Yec+z8mrSq4rydHofrnDCBqAcNA/BGrSg1kfFUL6F6s= github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg= github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I= github.com/containers/gvisor-tap-vsock v0.8.2 h1:uQMBCCHlIIj62fPjbvgm6AL5EzsP6TP5eviByOJEsOg= github.com/containers/gvisor-tap-vsock v0.8.2/go.mod h1:EMRe2o63ddq2zxcP0hTysmxCf/5JlaNEg8/gpzP0ox4= -github.com/containers/image/v5 v5.33.2-0.20250122233652-b5c6aff95ca7 h1:dTKluTTlijEdQmTZPK1wTX39qXb4F93/GPHhq+vlC3U= -github.com/containers/image/v5 v5.33.2-0.20250122233652-b5c6aff95ca7/go.mod h1:NyH4/AlLW8cvPgtwbCMzz71dr9SOh8/WP9ua5c9Akc8= +github.com/containers/image/v5 v5.34.0 h1:HPqQaDUsox/3mC1pbOyLAIQEp0JhQqiUZ+6JiFIZLDI= +github.com/containers/image/v5 v5.34.0/go.mod h1:/WnvUSEfdqC/ahMRd4YJDBLrpYWkGl018rB77iB3FDo= github.com/containers/libhvee v0.9.0 h1:5UxJMka1lDfxTeITA25Pd8QVVttJAG43eQS1Getw1tc= github.com/containers/libhvee v0.9.0/go.mod h1:p44VJd8jMIx3SRN1eM6PxfCEwXQE0lJ0dQppCAlzjPQ= github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 h1:Qzk5C6cYglewc+UyGf6lc8Mj2UaPTHy/iF2De0/77CA= @@ -96,8 +96,8 @@ github.com/containers/ocicrypt v1.2.1 h1:0qIOTT9DoYwcKmxSt8QJt+VzMY18onl9jUXsxpV github.com/containers/ocicrypt v1.2.1/go.mod h1:aD0AAqfMp0MtwqWgHM1bUwe1anx0VazI108CRrSKINQ= github.com/containers/psgo v1.9.0 h1:eJ74jzSaCHnWt26OlKZROSyUyRcGDf+gYBdXnxrMW4g= github.com/containers/psgo v1.9.0/go.mod h1:0YoluUm43Mz2UnBIh1P+6V6NWcbpTL5uRtXyOcH0B5A= -github.com/containers/storage v1.56.2-0.20250123125217-80d3c0e77d29 h1:3L1QCfh72xytLizQeswDaKcB5ajq54DuFRcAy/C3P3c= -github.com/containers/storage v1.56.2-0.20250123125217-80d3c0e77d29/go.mod h1:i/Hb4lu7YgFr9G0K6BMjqW0BLJO1sFsnWQwj2UoWCUM= +github.com/containers/storage v1.57.1 h1:hKPoFsuBcB3qTzBxa4IFpZMRzUuL5Xhv/BE44W0XHx8= +github.com/containers/storage v1.57.1/go.mod h1:i/Hb4lu7YgFr9G0K6BMjqW0BLJO1sFsnWQwj2UoWCUM= github.com/containers/winquit v1.1.0 h1:jArun04BNDQvt2W0Y78kh9TazN2EIEMG5Im6/JY7+pE= github.com/containers/winquit v1.1.0/go.mod h1:PsPeZlnbkmGGIToMPHF1zhWjBUkd8aHjMOr/vFcPxw8= github.com/coreos/go-oidc/v3 v3.12.0 h1:sJk+8G2qq94rDI6ehZ71Bol3oUHy63qNYmkiSjrc/Jo= @@ -471,8 +471,9 @@ github.com/smallstep/pkcs7 v0.1.1 h1:x+rPdt2W088V9Vkjho4KtoggyktZJlMduZAtRHm68LU github.com/smallstep/pkcs7 v0.1.1/go.mod h1:dL6j5AIz9GHjVEBTXtW+QliALcgM19RtXaTeyxI+AfA= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= +github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 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= diff --git a/vendor/github.com/containers/common/libnetwork/cni/config.go b/vendor/github.com/containers/common/libnetwork/cni/config.go index 43f3bfef46..9b45c1589c 100644 --- a/vendor/github.com/containers/common/libnetwork/cni/config.go +++ b/vendor/github.com/containers/common/libnetwork/cni/config.go @@ -86,7 +86,7 @@ func (n *cniNetwork) networkCreate(newNetwork *types.Network, defaultNet bool) ( switch newNetwork.Driver { case types.BridgeNetworkDriver: internalutil.MapDockerBridgeDriverOptions(newNetwork) - err = internalutil.CreateBridge(n, newNetwork, usedNetworks, n.defaultsubnetPools) + err = internalutil.CreateBridge(n, newNetwork, usedNetworks, n.defaultsubnetPools, true) if err != nil { return nil, err } diff --git a/vendor/github.com/containers/common/libnetwork/internal/rootlessnetns/netns_linux.go b/vendor/github.com/containers/common/libnetwork/internal/rootlessnetns/netns_linux.go index 7fac465a62..2655587654 100644 --- a/vendor/github.com/containers/common/libnetwork/internal/rootlessnetns/netns_linux.go +++ b/vendor/github.com/containers/common/libnetwork/internal/rootlessnetns/netns_linux.go @@ -135,6 +135,15 @@ func (n *Netns) getOrCreateNetns() (ns.NetNS, bool, error) { } // In case of errors continue and setup the network cmd again. } else { + // Special case, the file might exist already but is not a valid netns. + // One reason could be that a previous setup was killed between creating + // the file and mounting it. Or if the file is not on tmpfs (deleted on boot) + // you might run into it as well: https://github.com/containers/podman/issues/25144 + // We have to do this because NewNSAtPath fails with EEXIST otherwise + if errors.As(err, &ns.NSPathNotNSErr{}) { + // We don't care if this fails, NewNSAtPath() should return the real error. + _ = os.Remove(nsPath) + } logrus.Debugf("Creating rootless network namespace at %q", nsPath) // We have to create the netns dir again here because it is possible // that cleanup() removed it. diff --git a/vendor/github.com/containers/common/libnetwork/internal/util/bridge.go b/vendor/github.com/containers/common/libnetwork/internal/util/bridge.go index b75e9a57f4..44cd555c17 100644 --- a/vendor/github.com/containers/common/libnetwork/internal/util/bridge.go +++ b/vendor/github.com/containers/common/libnetwork/internal/util/bridge.go @@ -10,11 +10,13 @@ import ( "github.com/containers/common/pkg/config" ) -func CreateBridge(n NetUtil, network *types.Network, usedNetworks []*net.IPNet, subnetPools []config.SubnetPool) error { +func CreateBridge(n NetUtil, network *types.Network, usedNetworks []*net.IPNet, subnetPools []config.SubnetPool, checkBridgeConflict bool) error { if network.NetworkInterface != "" { - bridges := GetBridgeInterfaceNames(n) - if slices.Contains(bridges, network.NetworkInterface) { - return fmt.Errorf("bridge name %s already in use", network.NetworkInterface) + if checkBridgeConflict { + bridges := GetBridgeInterfaceNames(n) + if slices.Contains(bridges, network.NetworkInterface) { + return fmt.Errorf("bridge name %s already in use", network.NetworkInterface) + } } if !types.NameRegex.MatchString(network.NetworkInterface) { return fmt.Errorf("bridge name %s invalid: %w", network.NetworkInterface, types.RegexError) diff --git a/vendor/github.com/containers/common/libnetwork/netavark/config.go b/vendor/github.com/containers/common/libnetwork/netavark/config.go index 3305258b6c..4916f725e1 100644 --- a/vendor/github.com/containers/common/libnetwork/netavark/config.go +++ b/vendor/github.com/containers/common/libnetwork/netavark/config.go @@ -169,11 +169,9 @@ func (n *netavarkNetwork) networkCreate(newNetwork *types.Network, defaultNet bo switch newNetwork.Driver { case types.BridgeNetworkDriver: internalutil.MapDockerBridgeDriverOptions(newNetwork) - err = internalutil.CreateBridge(n, newNetwork, usedNetworks, n.defaultsubnetPools) - if err != nil { - return nil, err - } - // validate the given options, we do not need them but just check to make sure they are valid + + var vlan int + // validate the given options, for key, value := range newNetwork.Options { switch key { case types.MTUOption: @@ -183,7 +181,7 @@ func (n *netavarkNetwork) networkCreate(newNetwork *types.Network, defaultNet bo } case types.VLANOption: - _, err = internalutil.ParseVlan(value) + vlan, err = internalutil.ParseVlan(value) if err != nil { return nil, err } @@ -218,6 +216,17 @@ func (n *netavarkNetwork) networkCreate(newNetwork *types.Network, defaultNet bo return nil, fmt.Errorf("unsupported bridge network option %s", key) } } + + // If there is no vlan there should be no other config with the same bridge. + // However with vlan we want to allow that so that you can have different + // configs on the same bridge but different vlans + // https://github.com/containers/common/issues/2095 + checkBridgeConflict := vlan == 0 + err = internalutil.CreateBridge(n, newNetwork, usedNetworks, n.defaultsubnetPools, checkBridgeConflict) + if err != nil { + return nil, err + } + case types.MacVLANNetworkDriver, types.IPVLANNetworkDriver: err = createIpvlanOrMacvlan(newNetwork) if err != nil { diff --git a/vendor/github.com/containers/common/version/version.go b/vendor/github.com/containers/common/version/version.go index 2cdbff5b29..f676ffa999 100644 --- a/vendor/github.com/containers/common/version/version.go +++ b/vendor/github.com/containers/common/version/version.go @@ -1,4 +1,4 @@ package version // Version is the version of the build. -const Version = "0.62.0-dev" +const Version = "0.62.0" diff --git a/vendor/github.com/containers/image/v5/docker/registries_d.go b/vendor/github.com/containers/image/v5/docker/registries_d.go index 3619c3baef..89d48cc4fe 100644 --- a/vendor/github.com/containers/image/v5/docker/registries_d.go +++ b/vendor/github.com/containers/image/v5/docker/registries_d.go @@ -3,6 +3,7 @@ package docker import ( "errors" "fmt" + "io/fs" "net/url" "os" "path" @@ -129,6 +130,11 @@ func loadAndMergeConfig(dirPath string) (*registryConfiguration, error) { configPath := filepath.Join(dirPath, configName) configBytes, err := os.ReadFile(configPath) if err != nil { + if errors.Is(err, fs.ErrNotExist) { + // file must have been removed between the directory listing + // and the open call, ignore that as it is a expected race + continue + } return nil, err } diff --git a/vendor/github.com/containers/image/v5/pkg/sysregistriesv2/system_registries_v2.go b/vendor/github.com/containers/image/v5/pkg/sysregistriesv2/system_registries_v2.go index 1b161474da..9ac050512a 100644 --- a/vendor/github.com/containers/image/v5/pkg/sysregistriesv2/system_registries_v2.go +++ b/vendor/github.com/containers/image/v5/pkg/sysregistriesv2/system_registries_v2.go @@ -1,6 +1,7 @@ package sysregistriesv2 import ( + "errors" "fmt" "io/fs" "os" @@ -744,6 +745,11 @@ func tryUpdatingCache(ctx *types.SystemContext, wrapper configWrapper) (*parsedC // Enforce v2 format for drop-in-configs. dropIn, err := loadConfigFile(path, true) if err != nil { + if errors.Is(err, fs.ErrNotExist) { + // file must have been removed between the directory listing + // and the open call, ignore that as it is a expected race + continue + } return nil, fmt.Errorf("loading drop-in registries configuration %q: %w", path, err) } config.updateWithConfigurationFrom(dropIn) diff --git a/vendor/github.com/containers/image/v5/pkg/tlsclientconfig/tlsclientconfig.go b/vendor/github.com/containers/image/v5/pkg/tlsclientconfig/tlsclientconfig.go index f6c0576e07..4e0ee57e91 100644 --- a/vendor/github.com/containers/image/v5/pkg/tlsclientconfig/tlsclientconfig.go +++ b/vendor/github.com/containers/image/v5/pkg/tlsclientconfig/tlsclientconfig.go @@ -3,6 +3,7 @@ package tlsclientconfig import ( "crypto/tls" "crypto/x509" + "errors" "fmt" "net" "net/http" @@ -36,12 +37,9 @@ func SetupCertificates(dir string, tlsc *tls.Config) error { logrus.Debugf(" crt: %s", fullPath) data, err := os.ReadFile(fullPath) if err != nil { - if os.IsNotExist(err) { - // Dangling symbolic link? - // Race with someone who deleted the - // file after we read the directory's - // list of contents? - logrus.Warnf("error reading certificate %q: %v", fullPath, err) + if errors.Is(err, os.ErrNotExist) { + // file must have been removed between the directory listing + // and the open call, ignore that as it is a expected race continue } return err diff --git a/vendor/github.com/containers/image/v5/version/version.go b/vendor/github.com/containers/image/v5/version/version.go index 701e87f352..0322755ba1 100644 --- a/vendor/github.com/containers/image/v5/version/version.go +++ b/vendor/github.com/containers/image/v5/version/version.go @@ -8,10 +8,10 @@ const ( // VersionMinor is for functionality in a backwards-compatible manner VersionMinor = 34 // VersionPatch is for backwards-compatible bug fixes - VersionPatch = 1 + VersionPatch = 0 // VersionDev indicates development branch. Releases will be empty string. - VersionDev = "-dev" + VersionDev = "" ) // Version is the specification version that the package types support. diff --git a/vendor/github.com/containers/storage/VERSION b/vendor/github.com/containers/storage/VERSION index a38254646f..b4cf7c0db5 100644 --- a/vendor/github.com/containers/storage/VERSION +++ b/vendor/github.com/containers/storage/VERSION @@ -1 +1 @@ -1.57.0-dev +1.57.1 diff --git a/vendor/github.com/containers/storage/pkg/chunked/compression_linux.go b/vendor/github.com/containers/storage/pkg/chunked/compression_linux.go index 229ce366e4..67cc6cf082 100644 --- a/vendor/github.com/containers/storage/pkg/chunked/compression_linux.go +++ b/vendor/github.com/containers/storage/pkg/chunked/compression_linux.go @@ -23,7 +23,7 @@ import ( const ( // maxTocSize is the maximum size of a blob that we will attempt to process. // It is used to prevent DoS attacks from layers that embed a very large TOC file. - maxTocSize = (1 << 20) * 50 + maxTocSize = (1 << 20) * 150 ) var typesToTar = map[string]byte{ @@ -44,6 +44,8 @@ func typeToTarType(t string) (byte, error) { return r, nil } +// readEstargzChunkedManifest reads the estargz manifest from the seekable stream blobStream. +// It may return an error matching ErrFallbackToOrdinaryLayerDownload / errFallbackCanConvert. func readEstargzChunkedManifest(blobStream ImageSourceSeekable, blobSize int64, tocDigest digest.Digest) ([]byte, int64, error) { // information on the format here https://github.com/containerd/stargz-snapshotter/blob/main/docs/stargz-estargz.md footerSize := int64(51) @@ -54,6 +56,10 @@ func readEstargzChunkedManifest(blobStream ImageSourceSeekable, blobSize int64, footer := make([]byte, footerSize) streamsOrErrors, err := getBlobAt(blobStream, ImageSourceChunk{Offset: uint64(blobSize - footerSize), Length: uint64(footerSize)}) if err != nil { + var badRequestErr ErrBadRequest + if errors.As(err, &badRequestErr) { + err = errFallbackCanConvert{newErrFallbackToOrdinaryLayerDownload(err)} + } return nil, 0, err } @@ -84,11 +90,16 @@ func readEstargzChunkedManifest(blobStream ImageSourceSeekable, blobSize int64, size := int64(blobSize - footerSize - tocOffset) // set a reasonable limit if size > maxTocSize { - return nil, 0, errors.New("manifest too big") + // Not errFallbackCanConvert: we would still use too much memory. + return nil, 0, newErrFallbackToOrdinaryLayerDownload(fmt.Errorf("estargz manifest too big to process in memory (%d bytes)", size)) } streamsOrErrors, err = getBlobAt(blobStream, ImageSourceChunk{Offset: uint64(tocOffset), Length: uint64(size)}) if err != nil { + var badRequestErr ErrBadRequest + if errors.As(err, &badRequestErr) { + err = errFallbackCanConvert{newErrFallbackToOrdinaryLayerDownload(err)} + } return nil, 0, err } @@ -148,6 +159,7 @@ func readEstargzChunkedManifest(blobStream ImageSourceSeekable, blobSize int64, // readZstdChunkedManifest reads the zstd:chunked manifest from the seekable stream blobStream. // Returns (manifest blob, parsed manifest, tar-split blob or nil, manifest offset). +// It may return an error matching ErrFallbackToOrdinaryLayerDownload / errFallbackCanConvert. func readZstdChunkedManifest(blobStream ImageSourceSeekable, tocDigest digest.Digest, annotations map[string]string) (_ []byte, _ *minimal.TOC, _ []byte, _ int64, retErr error) { offsetMetadata := annotations[minimal.ManifestInfoKey] if offsetMetadata == "" { @@ -173,10 +185,12 @@ func readZstdChunkedManifest(blobStream ImageSourceSeekable, tocDigest digest.Di // set a reasonable limit if manifestChunk.Length > maxTocSize { - return nil, nil, nil, 0, errors.New("manifest too big") + // Not errFallbackCanConvert: we would still use too much memory. + return nil, nil, nil, 0, newErrFallbackToOrdinaryLayerDownload(fmt.Errorf("zstd:chunked manifest too big to process in memory (%d bytes compressed)", manifestChunk.Length)) } if manifestLengthUncompressed > maxTocSize { - return nil, nil, nil, 0, errors.New("manifest too big") + // Not errFallbackCanConvert: we would still use too much memory. + return nil, nil, nil, 0, newErrFallbackToOrdinaryLayerDownload(fmt.Errorf("zstd:chunked manifest too big to process in memory (%d bytes uncompressed)", manifestLengthUncompressed)) } chunks := []ImageSourceChunk{manifestChunk} @@ -186,6 +200,10 @@ func readZstdChunkedManifest(blobStream ImageSourceSeekable, tocDigest digest.Di streamsOrErrors, err := getBlobAt(blobStream, chunks...) if err != nil { + var badRequestErr ErrBadRequest + if errors.As(err, &badRequestErr) { + err = errFallbackCanConvert{newErrFallbackToOrdinaryLayerDownload(err)} + } return nil, nil, nil, 0, err } diff --git a/vendor/github.com/containers/storage/pkg/chunked/storage_linux.go b/vendor/github.com/containers/storage/pkg/chunked/storage_linux.go index cbc96b39cb..8f46798512 100644 --- a/vendor/github.com/containers/storage/pkg/chunked/storage_linux.go +++ b/vendor/github.com/containers/storage/pkg/chunked/storage_linux.go @@ -62,46 +62,53 @@ const ( type compressedFileType int type chunkedDiffer struct { + // Initial parameters, used throughout and never modified + // ========== + pullOptions pullOptions stream ImageSourceSeekable - manifest []byte - toc *minimal.TOC // The parsed contents of manifest, or nil if not yet available - tarSplit []byte - layersCache *layersCache - tocOffset int64 - fileType compressedFileType - - copyBuffer []byte - - gzipReader *pgzip.Reader - zstdReader *zstd.Decoder - rawReader io.Reader - - // tocDigest is the digest of the TOC document when the layer - // is partially pulled. - tocDigest digest.Digest + // blobDigest is the digest of the whole compressed layer. It is used if + // convertToZstdChunked to validate a layer when it is converted since there + // is no TOC referenced by the manifest. + blobDigest digest.Digest + blobSize int64 + // Input format + // ========== + fileType compressedFileType // convertedToZstdChunked is set to true if the layer needs to // be converted to the zstd:chunked format before it can be // handled. convertToZstdChunked bool + // Chunked metadata + // This is usually set in GetDiffer, but if convertToZstdChunked, it is only computed in chunkedDiffer.ApplyDiff + // ========== + // tocDigest is the digest of the TOC document when the layer + // is partially pulled, or "" if not relevant to consumers. + tocDigest digest.Digest + tocOffset int64 + manifest []byte + toc *minimal.TOC // The parsed contents of manifest, or nil if not yet available + tarSplit []byte + uncompressedTarSize int64 // -1 if unknown // skipValidation is set to true if the individual files in // the layer are trusted and should not be validated. skipValidation bool - // blobDigest is the digest of the whole compressed layer. It is used if - // convertToZstdChunked to validate a layer when it is converted since there - // is no TOC referenced by the manifest. - blobDigest digest.Digest - - blobSize int64 - uncompressedTarSize int64 // -1 if unknown - - pullOptions pullOptions - - useFsVerity graphdriver.DifferFsVerity + // Long-term caches + // This is set in GetDiffer, when the caller must not hold any storage locks, and later consumed in .ApplyDiff() + // ========== + layersCache *layersCache + copyBuffer []byte + fsVerityMutex sync.Mutex // protects fsVerityDigests fsVerityDigests map[string]string - fsVerityMutex sync.Mutex + + // Private state of .ApplyDiff + // ========== + gzipReader *pgzip.Reader + zstdReader *zstd.Decoder + rawReader io.Reader + useFsVerity graphdriver.DifferFsVerity } var xattrsToIgnore = map[string]interface{}{ @@ -185,7 +192,7 @@ func (c *chunkedDiffer) convertTarToZstdChunked(destDirectory string, payload *o } // GetDiffer returns a differ than can be used with ApplyDiffWithDiffer. -// If it returns an error that implements IsErrFallbackToOrdinaryLayerDownload, the caller can +// If it returns an error that matches ErrFallbackToOrdinaryLayerDownload, the caller can // retry the operation with a different method. func GetDiffer(ctx context.Context, store storage.Store, blobDigest digest.Digest, blobSize int64, annotations map[string]string, iss ImageSourceSeekable) (graphdriver.Differ, error) { pullOptions := parsePullOptions(store) @@ -208,65 +215,94 @@ func GetDiffer(ctx context.Context, store storage.Store, blobDigest digest.Diges return nil, newErrFallbackToOrdinaryLayerDownload(fmt.Errorf("graph driver %s does not support partial pull", graphDriver.String())) } - differ, canFallback, err := getProperDiffer(store, blobDigest, blobSize, annotations, iss, pullOptions) + differ, err := getProperDiffer(store, blobDigest, blobSize, annotations, iss, pullOptions) if err != nil { - if !canFallback { + var fallbackErr ErrFallbackToOrdinaryLayerDownload + if !errors.As(err, &fallbackErr) { return nil, err } // If convert_images is enabled, always attempt to convert it instead of returning an error or falling back to a different method. - if pullOptions.convertImages { - logrus.Debugf("Created differ to convert blob %q", blobDigest) - return makeConvertFromRawDiffer(store, blobDigest, blobSize, iss, pullOptions) + if !pullOptions.convertImages { + return nil, err } - return nil, newErrFallbackToOrdinaryLayerDownload(err) + var canConvertErr errFallbackCanConvert + if !errors.As(err, &canConvertErr) { + // We are supposed to use makeConvertFromRawDiffer, but that would not work. + // Fail, and make sure the error does _not_ match ErrFallbackToOrdinaryLayerDownload: use only the error text, + // discard all type information. + return nil, fmt.Errorf("neither a partial pull nor convert_images is possible: %s", err.Error()) + } + logrus.Debugf("Created differ to convert blob %q", blobDigest) + return makeConvertFromRawDiffer(store, blobDigest, blobSize, iss, pullOptions) } return differ, nil } +// errFallbackCanConvert is an an error type _accompanying_ ErrFallbackToOrdinaryLayerDownload +// within getProperDiffer, to mark that using makeConvertFromRawDiffer makes sense. +// This is used to distinguish between cases where the environment does not support partial pulls +// (e.g. a registry does not support range requests) and convert_images is still possible, +// from cases where the image content is unacceptable for partial pulls (e.g. exceeds memory limits) +// and convert_images would not help. +type errFallbackCanConvert struct { + err error +} + +func (e errFallbackCanConvert) Error() string { + return e.err.Error() +} + +func (e errFallbackCanConvert) Unwrap() error { + return e.err +} + // getProperDiffer is an implementation detail of GetDiffer. // It returns a “proper” differ (not a convert_images one) if possible. -// On error, the second return value is true if a fallback to an alternative (either the makeConverToRaw differ, or a non-partial pull) -// is permissible. -func getProperDiffer(store storage.Store, blobDigest digest.Digest, blobSize int64, annotations map[string]string, iss ImageSourceSeekable, pullOptions pullOptions) (graphdriver.Differ, bool, error) { +// May return an error matching ErrFallbackToOrdinaryLayerDownload if a fallback to an alternative +// (either makeConvertFromRawDiffer, or a non-partial pull) is permissible. +func getProperDiffer(store storage.Store, blobDigest digest.Digest, blobSize int64, annotations map[string]string, iss ImageSourceSeekable, pullOptions pullOptions) (graphdriver.Differ, error) { zstdChunkedTOCDigestString, hasZstdChunkedTOC := annotations[minimal.ManifestChecksumKey] estargzTOCDigestString, hasEstargzTOC := annotations[estargz.TOCJSONDigestAnnotation] switch { case hasZstdChunkedTOC && hasEstargzTOC: - return nil, false, errors.New("both zstd:chunked and eStargz TOC found") + return nil, errors.New("both zstd:chunked and eStargz TOC found") case hasZstdChunkedTOC: zstdChunkedTOCDigest, err := digest.Parse(zstdChunkedTOCDigestString) if err != nil { - return nil, false, err + return nil, err } - differ, canFallback, err := makeZstdChunkedDiffer(store, blobSize, zstdChunkedTOCDigest, annotations, iss, pullOptions) + differ, err := makeZstdChunkedDiffer(store, blobSize, zstdChunkedTOCDigest, annotations, iss, pullOptions) if err != nil { logrus.Debugf("Could not create zstd:chunked differ for blob %q: %v", blobDigest, err) - return nil, canFallback, err + return nil, err } logrus.Debugf("Created zstd:chunked differ for blob %q", blobDigest) - return differ, false, nil + return differ, nil case hasEstargzTOC: estargzTOCDigest, err := digest.Parse(estargzTOCDigestString) if err != nil { - return nil, false, err + return nil, err } - differ, canFallback, err := makeEstargzChunkedDiffer(store, blobSize, estargzTOCDigest, iss, pullOptions) + differ, err := makeEstargzChunkedDiffer(store, blobSize, estargzTOCDigest, iss, pullOptions) if err != nil { logrus.Debugf("Could not create estargz differ for blob %q: %v", blobDigest, err) - return nil, canFallback, err + return nil, err } logrus.Debugf("Created eStargz differ for blob %q", blobDigest) - return differ, false, nil + return differ, nil default: // no TOC + message := "no TOC found" if !pullOptions.convertImages { - return nil, true, errors.New("no TOC found and convert_images is not configured") + message = "no TOC found and convert_images is not configured" + } + return nil, errFallbackCanConvert{ + newErrFallbackToOrdinaryLayerDownload(errors.New(message)), } - return nil, true, errors.New("no TOC found") } } @@ -277,95 +313,100 @@ func makeConvertFromRawDiffer(store storage.Store, blobDigest digest.Digest, blo } return &chunkedDiffer{ - fsVerityDigests: make(map[string]string), - blobDigest: blobDigest, - blobSize: blobSize, - uncompressedTarSize: -1, // Will be computed later + pullOptions: pullOptions, + stream: iss, + blobDigest: blobDigest, + blobSize: blobSize, + convertToZstdChunked: true, - copyBuffer: makeCopyBuffer(), - layersCache: layersCache, - pullOptions: pullOptions, - stream: iss, + + uncompressedTarSize: -1, // Will be computed later + + layersCache: layersCache, + copyBuffer: makeCopyBuffer(), + fsVerityDigests: make(map[string]string), }, nil } // makeZstdChunkedDiffer sets up a chunkedDiffer for a zstd:chunked layer. -// -// On error, the second return value is true if a fallback to an alternative (either the makeConverToRaw differ, or a non-partial pull) -// is permissible. -func makeZstdChunkedDiffer(store storage.Store, blobSize int64, tocDigest digest.Digest, annotations map[string]string, iss ImageSourceSeekable, pullOptions pullOptions) (*chunkedDiffer, bool, error) { +// It may return an error matching ErrFallbackToOrdinaryLayerDownload / errFallbackCanConvert. +func makeZstdChunkedDiffer(store storage.Store, blobSize int64, tocDigest digest.Digest, annotations map[string]string, iss ImageSourceSeekable, pullOptions pullOptions) (*chunkedDiffer, error) { manifest, toc, tarSplit, tocOffset, err := readZstdChunkedManifest(iss, tocDigest, annotations) - if err != nil { - // If the error is a bad request to the server, then signal to the caller that it can try a different method. - var badRequestErr ErrBadRequest - return nil, errors.As(err, &badRequestErr), fmt.Errorf("read zstd:chunked manifest: %w", err) + if err != nil { // May be ErrFallbackToOrdinaryLayerDownload / errFallbackCanConvert + return nil, fmt.Errorf("read zstd:chunked manifest: %w", err) } var uncompressedTarSize int64 = -1 if tarSplit != nil { uncompressedTarSize, err = tarSizeFromTarSplit(tarSplit) if err != nil { - return nil, false, fmt.Errorf("computing size from tar-split: %w", err) + return nil, fmt.Errorf("computing size from tar-split: %w", err) } } else if !pullOptions.insecureAllowUnpredictableImageContents { // With no tar-split, we can't compute the traditional UncompressedDigest. - return nil, true, fmt.Errorf("zstd:chunked layers without tar-split data don't support partial pulls with guaranteed consistency with non-partial pulls") + return nil, errFallbackCanConvert{ + newErrFallbackToOrdinaryLayerDownload(fmt.Errorf("zstd:chunked layers without tar-split data don't support partial pulls with guaranteed consistency with non-partial pulls")), + } } layersCache, err := getLayersCache(store) if err != nil { - return nil, false, err + return nil, err } return &chunkedDiffer{ - fsVerityDigests: make(map[string]string), - blobSize: blobSize, - uncompressedTarSize: uncompressedTarSize, + pullOptions: pullOptions, + stream: iss, + blobSize: blobSize, + + fileType: fileTypeZstdChunked, + tocDigest: tocDigest, - copyBuffer: makeCopyBuffer(), - fileType: fileTypeZstdChunked, - layersCache: layersCache, + tocOffset: tocOffset, manifest: manifest, toc: toc, - pullOptions: pullOptions, - stream: iss, tarSplit: tarSplit, - tocOffset: tocOffset, - }, false, nil + uncompressedTarSize: uncompressedTarSize, + + layersCache: layersCache, + copyBuffer: makeCopyBuffer(), + fsVerityDigests: make(map[string]string), + }, nil } -// makeZstdChunkedDiffer sets up a chunkedDiffer for an estargz layer. -// -// On error, the second return value is true if a fallback to an alternative (either the makeConverToRaw differ, or a non-partial pull) -// is permissible. -func makeEstargzChunkedDiffer(store storage.Store, blobSize int64, tocDigest digest.Digest, iss ImageSourceSeekable, pullOptions pullOptions) (*chunkedDiffer, bool, error) { +// makeEstargzChunkedDiffer sets up a chunkedDiffer for an estargz layer. +// It may return an error matching ErrFallbackToOrdinaryLayerDownload / errFallbackCanConvert. +func makeEstargzChunkedDiffer(store storage.Store, blobSize int64, tocDigest digest.Digest, iss ImageSourceSeekable, pullOptions pullOptions) (*chunkedDiffer, error) { if !pullOptions.insecureAllowUnpredictableImageContents { // With no tar-split, we can't compute the traditional UncompressedDigest. - return nil, true, fmt.Errorf("estargz layers don't support partial pulls with guaranteed consistency with non-partial pulls") + return nil, errFallbackCanConvert{ + newErrFallbackToOrdinaryLayerDownload(fmt.Errorf("estargz layers don't support partial pulls with guaranteed consistency with non-partial pulls")), + } } manifest, tocOffset, err := readEstargzChunkedManifest(iss, blobSize, tocDigest) - if err != nil { - // If the error is a bad request to the server, then signal to the caller that it can try a different method. - var badRequestErr ErrBadRequest - return nil, errors.As(err, &badRequestErr), fmt.Errorf("read zstd:chunked manifest: %w", err) + if err != nil { // May be ErrFallbackToOrdinaryLayerDownload / errFallbackCanConvert + return nil, fmt.Errorf("read zstd:chunked manifest: %w", err) } layersCache, err := getLayersCache(store) if err != nil { - return nil, false, err + return nil, err } return &chunkedDiffer{ - fsVerityDigests: make(map[string]string), - blobSize: blobSize, - uncompressedTarSize: -1, // We would have to read and decompress the whole layer + pullOptions: pullOptions, + stream: iss, + blobSize: blobSize, + + fileType: fileTypeEstargz, + tocDigest: tocDigest, - copyBuffer: makeCopyBuffer(), - fileType: fileTypeEstargz, - layersCache: layersCache, - manifest: manifest, - pullOptions: pullOptions, - stream: iss, tocOffset: tocOffset, - }, false, nil + manifest: manifest, + uncompressedTarSize: -1, // We would have to read and decompress the whole layer + + layersCache: layersCache, + copyBuffer: makeCopyBuffer(), + fsVerityDigests: make(map[string]string), + }, nil } func makeCopyBuffer() []byte { diff --git a/vendor/github.com/containers/storage/pkg/chunked/storage_unsupported.go b/vendor/github.com/containers/storage/pkg/chunked/storage_unsupported.go index 7be0adeb8a..fe3d36c76b 100644 --- a/vendor/github.com/containers/storage/pkg/chunked/storage_unsupported.go +++ b/vendor/github.com/containers/storage/pkg/chunked/storage_unsupported.go @@ -13,5 +13,5 @@ import ( // GetDiffer returns a differ than can be used with ApplyDiffWithDiffer. func GetDiffer(ctx context.Context, store storage.Store, blobDigest digest.Digest, blobSize int64, annotations map[string]string, iss ImageSourceSeekable) (graphdriver.Differ, error) { - return nil, errors.New("format not supported on this system") + return nil, newErrFallbackToOrdinaryLayerDownload(errors.New("format not supported on this system")) } diff --git a/vendor/github.com/spf13/pflag/.editorconfig b/vendor/github.com/spf13/pflag/.editorconfig new file mode 100644 index 0000000000..4492e9f9fe --- /dev/null +++ b/vendor/github.com/spf13/pflag/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +[*.go] +indent_style = tab diff --git a/vendor/github.com/spf13/pflag/.golangci.yaml b/vendor/github.com/spf13/pflag/.golangci.yaml new file mode 100644 index 0000000000..b274f24845 --- /dev/null +++ b/vendor/github.com/spf13/pflag/.golangci.yaml @@ -0,0 +1,4 @@ +linters: + disable-all: true + enable: + - nolintlint diff --git a/vendor/github.com/spf13/pflag/flag.go b/vendor/github.com/spf13/pflag/flag.go index 24a5036e95..7c058de374 100644 --- a/vendor/github.com/spf13/pflag/flag.go +++ b/vendor/github.com/spf13/pflag/flag.go @@ -160,7 +160,7 @@ type FlagSet struct { args []string // arguments after flags argsLenAtDash int // len(args) when a '--' was located when parsing, or -1 if no -- errorHandling ErrorHandling - output io.Writer // nil means stderr; use out() accessor + output io.Writer // nil means stderr; use Output() accessor interspersed bool // allow interspersed option/non-option args normalizeNameFunc func(f *FlagSet, name string) NormalizedName @@ -255,13 +255,20 @@ func (f *FlagSet) normalizeFlagName(name string) NormalizedName { return n(f, name) } -func (f *FlagSet) out() io.Writer { +// Output returns the destination for usage and error messages. os.Stderr is returned if +// output was not set or was set to nil. +func (f *FlagSet) Output() io.Writer { if f.output == nil { return os.Stderr } return f.output } +// Name returns the name of the flag set. +func (f *FlagSet) Name() string { + return f.name +} + // SetOutput sets the destination for usage and error messages. // If output is nil, os.Stderr is used. func (f *FlagSet) SetOutput(output io.Writer) { @@ -358,7 +365,7 @@ func (f *FlagSet) ShorthandLookup(name string) *Flag { } if len(name) > 1 { msg := fmt.Sprintf("can not look up shorthand which is more than one ASCII character: %q", name) - fmt.Fprintf(f.out(), msg) + fmt.Fprintf(f.Output(), msg) panic(msg) } c := name[0] @@ -482,7 +489,7 @@ func (f *FlagSet) Set(name, value string) error { } if flag.Deprecated != "" { - fmt.Fprintf(f.out(), "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated) + fmt.Fprintf(f.Output(), "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated) } return nil } @@ -523,7 +530,7 @@ func Set(name, value string) error { // otherwise, the default values of all defined flags in the set. func (f *FlagSet) PrintDefaults() { usages := f.FlagUsages() - fmt.Fprint(f.out(), usages) + fmt.Fprint(f.Output(), usages) } // defaultIsZeroValue returns true if the default value for this flag represents @@ -758,7 +765,7 @@ func PrintDefaults() { // defaultUsage is the default function to print a usage message. func defaultUsage(f *FlagSet) { - fmt.Fprintf(f.out(), "Usage of %s:\n", f.name) + fmt.Fprintf(f.Output(), "Usage of %s:\n", f.name) f.PrintDefaults() } @@ -844,7 +851,7 @@ func (f *FlagSet) AddFlag(flag *Flag) { _, alreadyThere := f.formal[normalizedFlagName] if alreadyThere { msg := fmt.Sprintf("%s flag redefined: %s", f.name, flag.Name) - fmt.Fprintln(f.out(), msg) + fmt.Fprintln(f.Output(), msg) panic(msg) // Happens only if flags are declared with identical names } if f.formal == nil { @@ -860,7 +867,7 @@ func (f *FlagSet) AddFlag(flag *Flag) { } if len(flag.Shorthand) > 1 { msg := fmt.Sprintf("%q shorthand is more than one ASCII character", flag.Shorthand) - fmt.Fprintf(f.out(), msg) + fmt.Fprintf(f.Output(), msg) panic(msg) } if f.shorthands == nil { @@ -870,7 +877,7 @@ func (f *FlagSet) AddFlag(flag *Flag) { used, alreadyThere := f.shorthands[c] if alreadyThere { msg := fmt.Sprintf("unable to redefine %q shorthand in %q flagset: it's already used for %q flag", c, f.name, used.Name) - fmt.Fprintf(f.out(), msg) + fmt.Fprintf(f.Output(), msg) panic(msg) } f.shorthands[c] = flag @@ -909,7 +916,7 @@ func VarP(value Value, name, shorthand, usage string) { func (f *FlagSet) failf(format string, a ...interface{}) error { err := fmt.Errorf(format, a...) if f.errorHandling != ContinueOnError { - fmt.Fprintln(f.out(), err) + fmt.Fprintln(f.Output(), err) f.usage() } return err @@ -1060,7 +1067,7 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse } if flag.ShorthandDeprecated != "" { - fmt.Fprintf(f.out(), "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated) + fmt.Fprintf(f.Output(), "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated) } err = fn(flag, value) diff --git a/vendor/github.com/spf13/pflag/ip.go b/vendor/github.com/spf13/pflag/ip.go index 3d414ba69f..06b8bcb572 100644 --- a/vendor/github.com/spf13/pflag/ip.go +++ b/vendor/github.com/spf13/pflag/ip.go @@ -16,6 +16,9 @@ func newIPValue(val net.IP, p *net.IP) *ipValue { func (i *ipValue) String() string { return net.IP(*i).String() } func (i *ipValue) Set(s string) error { + if s == "" { + return nil + } ip := net.ParseIP(strings.TrimSpace(s)) if ip == nil { return fmt.Errorf("failed to parse IP: %q", s) diff --git a/vendor/github.com/spf13/pflag/ipnet_slice.go b/vendor/github.com/spf13/pflag/ipnet_slice.go new file mode 100644 index 0000000000..6b541aa879 --- /dev/null +++ b/vendor/github.com/spf13/pflag/ipnet_slice.go @@ -0,0 +1,147 @@ +package pflag + +import ( + "fmt" + "io" + "net" + "strings" +) + +// -- ipNetSlice Value +type ipNetSliceValue struct { + value *[]net.IPNet + changed bool +} + +func newIPNetSliceValue(val []net.IPNet, p *[]net.IPNet) *ipNetSliceValue { + ipnsv := new(ipNetSliceValue) + ipnsv.value = p + *ipnsv.value = val + return ipnsv +} + +// Set converts, and assigns, the comma-separated IPNet argument string representation as the []net.IPNet value of this flag. +// If Set is called on a flag that already has a []net.IPNet assigned, the newly converted values will be appended. +func (s *ipNetSliceValue) Set(val string) error { + + // remove all quote characters + rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "") + + // read flag arguments with CSV parser + ipNetStrSlice, err := readAsCSV(rmQuote.Replace(val)) + if err != nil && err != io.EOF { + return err + } + + // parse ip values into slice + out := make([]net.IPNet, 0, len(ipNetStrSlice)) + for _, ipNetStr := range ipNetStrSlice { + _, n, err := net.ParseCIDR(strings.TrimSpace(ipNetStr)) + if err != nil { + return fmt.Errorf("invalid string being converted to CIDR: %s", ipNetStr) + } + out = append(out, *n) + } + + if !s.changed { + *s.value = out + } else { + *s.value = append(*s.value, out...) + } + + s.changed = true + + return nil +} + +// Type returns a string that uniquely represents this flag's type. +func (s *ipNetSliceValue) Type() string { + return "ipNetSlice" +} + +// String defines a "native" format for this net.IPNet slice flag value. +func (s *ipNetSliceValue) String() string { + + ipNetStrSlice := make([]string, len(*s.value)) + for i, n := range *s.value { + ipNetStrSlice[i] = n.String() + } + + out, _ := writeAsCSV(ipNetStrSlice) + return "[" + out + "]" +} + +func ipNetSliceConv(val string) (interface{}, error) { + val = strings.Trim(val, "[]") + // Emtpy string would cause a slice with one (empty) entry + if len(val) == 0 { + return []net.IPNet{}, nil + } + ss := strings.Split(val, ",") + out := make([]net.IPNet, len(ss)) + for i, sval := range ss { + _, n, err := net.ParseCIDR(strings.TrimSpace(sval)) + if err != nil { + return nil, fmt.Errorf("invalid string being converted to CIDR: %s", sval) + } + out[i] = *n + } + return out, nil +} + +// GetIPNetSlice returns the []net.IPNet value of a flag with the given name +func (f *FlagSet) GetIPNetSlice(name string) ([]net.IPNet, error) { + val, err := f.getFlagType(name, "ipNetSlice", ipNetSliceConv) + if err != nil { + return []net.IPNet{}, err + } + return val.([]net.IPNet), nil +} + +// IPNetSliceVar defines a ipNetSlice flag with specified name, default value, and usage string. +// The argument p points to a []net.IPNet variable in which to store the value of the flag. +func (f *FlagSet) IPNetSliceVar(p *[]net.IPNet, name string, value []net.IPNet, usage string) { + f.VarP(newIPNetSliceValue(value, p), name, "", usage) +} + +// IPNetSliceVarP is like IPNetSliceVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) IPNetSliceVarP(p *[]net.IPNet, name, shorthand string, value []net.IPNet, usage string) { + f.VarP(newIPNetSliceValue(value, p), name, shorthand, usage) +} + +// IPNetSliceVar defines a []net.IPNet flag with specified name, default value, and usage string. +// The argument p points to a []net.IPNet variable in which to store the value of the flag. +func IPNetSliceVar(p *[]net.IPNet, name string, value []net.IPNet, usage string) { + CommandLine.VarP(newIPNetSliceValue(value, p), name, "", usage) +} + +// IPNetSliceVarP is like IPNetSliceVar, but accepts a shorthand letter that can be used after a single dash. +func IPNetSliceVarP(p *[]net.IPNet, name, shorthand string, value []net.IPNet, usage string) { + CommandLine.VarP(newIPNetSliceValue(value, p), name, shorthand, usage) +} + +// IPNetSlice defines a []net.IPNet flag with specified name, default value, and usage string. +// The return value is the address of a []net.IPNet variable that stores the value of that flag. +func (f *FlagSet) IPNetSlice(name string, value []net.IPNet, usage string) *[]net.IPNet { + p := []net.IPNet{} + f.IPNetSliceVarP(&p, name, "", value, usage) + return &p +} + +// IPNetSliceP is like IPNetSlice, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) IPNetSliceP(name, shorthand string, value []net.IPNet, usage string) *[]net.IPNet { + p := []net.IPNet{} + f.IPNetSliceVarP(&p, name, shorthand, value, usage) + return &p +} + +// IPNetSlice defines a []net.IPNet flag with specified name, default value, and usage string. +// The return value is the address of a []net.IP variable that stores the value of the flag. +func IPNetSlice(name string, value []net.IPNet, usage string) *[]net.IPNet { + return CommandLine.IPNetSliceP(name, "", value, usage) +} + +// IPNetSliceP is like IPNetSlice, but accepts a shorthand letter that can be used after a single dash. +func IPNetSliceP(name, shorthand string, value []net.IPNet, usage string) *[]net.IPNet { + return CommandLine.IPNetSliceP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/string_array.go b/vendor/github.com/spf13/pflag/string_array.go index 4894af8180..d1ff0a96ba 100644 --- a/vendor/github.com/spf13/pflag/string_array.go +++ b/vendor/github.com/spf13/pflag/string_array.go @@ -31,11 +31,7 @@ func (s *stringArrayValue) Append(val string) error { func (s *stringArrayValue) Replace(val []string) error { out := make([]string, len(val)) for i, d := range val { - var err error out[i] = d - if err != nil { - return err - } } *s.value = out return nil diff --git a/vendor/modules.txt b/vendor/modules.txt index ca91683c69..833d09f543 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -179,7 +179,7 @@ github.com/containers/buildah/pkg/sshagent github.com/containers/buildah/pkg/util github.com/containers/buildah/pkg/volumes github.com/containers/buildah/util -# github.com/containers/common v0.61.1-0.20250124131345-fa339b6b6eda +# github.com/containers/common v0.62.0 ## explicit; go 1.22.8 github.com/containers/common/internal github.com/containers/common/internal/attributedstring @@ -252,7 +252,7 @@ github.com/containers/conmon/runner/config # github.com/containers/gvisor-tap-vsock v0.8.2 ## explicit; go 1.22.0 github.com/containers/gvisor-tap-vsock/pkg/types -# github.com/containers/image/v5 v5.33.2-0.20250122233652-b5c6aff95ca7 +# github.com/containers/image/v5 v5.34.0 ## explicit; go 1.22.8 github.com/containers/image/v5/copy github.com/containers/image/v5/directory @@ -364,7 +364,7 @@ github.com/containers/psgo/internal/dev github.com/containers/psgo/internal/host github.com/containers/psgo/internal/proc github.com/containers/psgo/internal/process -# github.com/containers/storage v1.56.2-0.20250123125217-80d3c0e77d29 +# github.com/containers/storage v1.57.1 ## explicit; go 1.22.0 github.com/containers/storage github.com/containers/storage/drivers @@ -1045,7 +1045,7 @@ github.com/smallstep/pkcs7/internal/legacy/x509 # github.com/spf13/cobra v1.8.1 ## explicit; go 1.15 github.com/spf13/cobra -# github.com/spf13/pflag v1.0.5 +# github.com/spf13/pflag v1.0.6 ## explicit; go 1.12 github.com/spf13/pflag # github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 From e24ccdd27baf3e898f83aa60691d5bcaff08e7a5 Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Wed, 22 Jan 2025 13:38:56 +0100 Subject: [PATCH 11/58] libpod: remove unused ExecStartAndAttach() Signed-off-by: Paul Holzinger --- libpod/container_exec.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/libpod/container_exec.go b/libpod/container_exec.go index 42f6eae9e4..69a1c356d2 100644 --- a/libpod/container_exec.go +++ b/libpod/container_exec.go @@ -284,11 +284,7 @@ func (c *Container) ExecStart(sessionID string) error { return c.save() } -func (c *Container) ExecStartAndAttach(sessionID string, streams *define.AttachStreams, newSize *resize.TerminalSize) error { - return c.execStartAndAttach(sessionID, streams, newSize, false) -} - -// ExecStartAndAttach starts and attaches to an exec session in a container. +// execStartAndAttach starts and attaches to an exec session in a container. // newSize resizes the tty to this size before the process is started, must be nil if the exec session has no tty func (c *Container) execStartAndAttach(sessionID string, streams *define.AttachStreams, newSize *resize.TerminalSize, isHealthcheck bool) error { if !c.batched { From 9e2e7f2a77ab81fdddf101d47c2ccc7c3fb5929d Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Wed, 22 Jan 2025 11:15:15 +0100 Subject: [PATCH 12/58] podman exec: correctly support detaching podman exec support detaching early via the detach key sequence. In that case the podman process should exit successfully but the container exec process keeps running. Now I wrote automated test for both podman run and exec detach but this uncovered several larger issues: - detach sequence parsing is broken[1] - podman-remote exec detach is broken[2] - detach in general seems to be buggy/racy, seeing lot of flakes that fail to restore the terminal and get an EIO instead, i.e. "Unable to restore terminal: input/output error" Thus I cannot add tests for now but this commit should at least fix the obvoius case as reported by the user so I like to get this in regardless and I will work through the other issues once I have more time. Fixes #24895 [1] https://github.com/containers/common/pull/2302 [2] https://github.com/containers/podman/issues/25089 Signed-off-by: Paul Holzinger --- libpod/container_exec.go | 42 +++++++++++++++++++++++---- libpod/util.go | 2 +- pkg/api/handlers/compat/exec.go | 2 +- pkg/domain/infra/tunnel/containers.go | 36 +++++++++++++++++++---- 4 files changed, 68 insertions(+), 14 deletions(-) diff --git a/libpod/container_exec.go b/libpod/container_exec.go index 69a1c356d2..c9efc707f5 100644 --- a/libpod/container_exec.go +++ b/libpod/container_exec.go @@ -287,9 +287,14 @@ func (c *Container) ExecStart(sessionID string) error { // execStartAndAttach starts and attaches to an exec session in a container. // newSize resizes the tty to this size before the process is started, must be nil if the exec session has no tty func (c *Container) execStartAndAttach(sessionID string, streams *define.AttachStreams, newSize *resize.TerminalSize, isHealthcheck bool) error { + unlock := true if !c.batched { c.lock.Lock() - defer c.lock.Unlock() + defer func() { + if unlock { + c.lock.Unlock() + } + }() if err := c.syncContainer(); err != nil { return err @@ -344,6 +349,12 @@ func (c *Container) execStartAndAttach(sessionID string, streams *define.AttachS } tmpErr := <-attachChan + // user detached + if errors.Is(tmpErr, define.ErrDetach) { + // ensure we the defer does not unlock as we are not locked here + unlock = false + return tmpErr + } if lastErr != nil { logrus.Errorf("Container %s exec session %s error: %v", c.ID(), session.ID(), lastErr) } @@ -431,9 +442,14 @@ func (c *Container) ExecHTTPStartAndAttach(sessionID string, r *http.Request, w close(hijackDone) }() + unlock := true if !c.batched { c.lock.Lock() - defer c.lock.Unlock() + defer func() { + if unlock { + c.lock.Unlock() + } + }() if err := c.syncContainer(); err != nil { return err @@ -514,6 +530,12 @@ func (c *Container) ExecHTTPStartAndAttach(sessionID string, r *http.Request, w } tmpErr := <-attachChan + // user detached + if errors.Is(tmpErr, define.ErrDetach) { + // ensure we the defer does not unlock as we are not locked here + unlock = false + return tmpErr + } if lastErr != nil { logrus.Errorf("Container %s exec session %s error: %v", c.ID(), session.ID(), lastErr) } @@ -765,11 +787,14 @@ func (c *Container) exec(config *ExecConfig, streams *define.AttachStreams, resi if err != nil { return -1, err } + cleanup := true defer func() { - if err := c.ExecRemove(sessionID, false); err != nil { - if retErr == nil && !errors.Is(err, define.ErrNoSuchExecSession) { - exitCode = -1 - retErr = err + if cleanup { + if err := c.ExecRemove(sessionID, false); err != nil { + if retErr == nil && !errors.Is(err, define.ErrNoSuchExecSession) { + exitCode = -1 + retErr = err + } } } }() @@ -803,6 +828,11 @@ func (c *Container) exec(config *ExecConfig, streams *define.AttachStreams, resi } if err := c.execStartAndAttach(sessionID, streams, size, isHealthcheck); err != nil { + // user detached, there will be no exit just exit without reporting an error + if errors.Is(err, define.ErrDetach) { + cleanup = false + return 0, nil + } return -1, err } diff --git a/libpod/util.go b/libpod/util.go index 49c9f10c27..67ba151c04 100644 --- a/libpod/util.go +++ b/libpod/util.go @@ -149,7 +149,7 @@ func checkDependencyContainer(depCtr, ctr *Container) error { // hijackWriteError writes an error to a hijacked HTTP session. func hijackWriteError(toWrite error, cid string, terminal bool, httpBuf *bufio.ReadWriter) { - if toWrite != nil { + if toWrite != nil && !errors.Is(toWrite, define.ErrDetach) { errString := []byte(fmt.Sprintf("Error: %v\n", toWrite)) if !terminal { // We need a header. diff --git a/pkg/api/handlers/compat/exec.go b/pkg/api/handlers/compat/exec.go index 7c28458d57..a83bf749a9 100644 --- a/pkg/api/handlers/compat/exec.go +++ b/pkg/api/handlers/compat/exec.go @@ -200,7 +200,7 @@ func ExecStartHandler(w http.ResponseWriter, r *http.Request) { t := r.Context().Value(api.IdleTrackerKey).(*idle.Tracker) defer t.Close() - if err != nil { + if err != nil && !errors.Is(err, define.ErrDetach) { // Cannot report error to client as a 500 as the Upgrade set status to 101 logErr(err) } diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go index daee6a8219..99a9c6510a 100644 --- a/pkg/domain/infra/tunnel/containers.go +++ b/pkg/domain/infra/tunnel/containers.go @@ -666,6 +666,7 @@ func startAndAttach(ic *ContainerEngine, name string, detachKeys *string, sigPro go func() { err := containers.Attach(ic.ClientCtx, name, input, output, errput, attachReady, options) attachErr <- err + close(attachErr) }() // Wait for the attach to actually happen before starting // the container. @@ -683,13 +684,36 @@ func startAndAttach(ic *ContainerEngine, name string, detachKeys *string, sigPro return -1, err } - // call wait immediately after start to avoid racing against container removal when it was created with --rm - exitCode, err := containers.Wait(cancelCtx, name, nil) - if err != nil { - return -1, err - } - code = int(exitCode) + // Call wait immediately after start to avoid racing against container removal when it was created with --rm. + // It must be run in a separate goroutine to so we do not block when attach returns early, i.e. user + // detaches in which case wait would not return. + waitChan := make(chan error) + go func() { + defer close(waitChan) + + exitCode, err := containers.Wait(cancelCtx, name, nil) + if err != nil { + waitChan <- fmt.Errorf("wait for container: %w", err) + return + } + code = int(exitCode) + }() + select { + case err := <-waitChan: + if err != nil { + return -1, err + } + case err := <-attachErr: + if err != nil { + return -1, err + } + // also wait for the wait to be complete in this case + err = <-waitChan + if err != nil { + return -1, err + } + } case err := <-attachErr: return -1, err } From fe02e390afd01694163e7ca9582a401df5bea80c Mon Sep 17 00:00:00 2001 From: tomsweeneyredhat Date: Mon, 3 Feb 2025 11:55:24 -0500 Subject: [PATCH 13/58] [v5.4] Bump Buildah to v1.39.0 Bump Buildah to v1.39.0 in preparation for Podman v5.4. Signed-off-by: tomsweeneyredhat --- go.mod | 2 +- go.sum | 4 +- .../github.com/containers/buildah/.cirrus.yml | 5 + .../containers/buildah/CHANGELOG.md | 91 +++++++++++++++++++ .../containers/buildah/changelog.txt | 90 ++++++++++++++++++ .../containers/buildah/define/types.go | 2 +- vendor/modules.txt | 2 +- 7 files changed, 191 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 597791f546..e8e83a6ef4 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/checkpoint-restore/checkpointctl v1.3.0 github.com/checkpoint-restore/go-criu/v7 v7.2.0 github.com/containernetworking/plugins v1.5.1 - github.com/containers/buildah v1.38.1-0.20250125114111-92015b7f4301 + github.com/containers/buildah v1.39.0 github.com/containers/common v0.62.0 github.com/containers/conmon v2.0.20+incompatible github.com/containers/gvisor-tap-vsock v0.8.2 diff --git a/go.sum b/go.sum index e69198f24e..44c677215a 100644 --- a/go.sum +++ b/go.sum @@ -76,8 +76,8 @@ github.com/containernetworking/cni v1.2.3 h1:hhOcjNVUQTnzdRJ6alC5XF+wd9mfGIUaj8F github.com/containernetworking/cni v1.2.3/go.mod h1:DuLgF+aPd3DzcTQTtp/Nvl1Kim23oFKdm2okJzBQA5M= github.com/containernetworking/plugins v1.5.1 h1:T5ji+LPYjjgW0QM+KyrigZbLsZ8jaX+E5J/EcKOE4gQ= github.com/containernetworking/plugins v1.5.1/go.mod h1:MIQfgMayGuHYs0XdNudf31cLLAC+i242hNm6KuDGqCM= -github.com/containers/buildah v1.38.1-0.20250125114111-92015b7f4301 h1:eqHczpfbWOjyvQAkuCmzsZPds657cPXxXniXLcKFHdQ= -github.com/containers/buildah v1.38.1-0.20250125114111-92015b7f4301/go.mod h1:UOhJzUS2A0uyZR/TygObcg2Og+nJ02pwMfVhIQBRIN8= +github.com/containers/buildah v1.39.0 h1:/OpzH7eMQYLg6pyguk6vugqScoZm8fIiN6wgMre9nUY= +github.com/containers/buildah v1.39.0/go.mod h1:PTC4lCOwVfT3esN7Kxf2j8Aa3uqxsyUZudECLeGJlkY= github.com/containers/common v0.62.0 h1:Sl9WE5h7Y/F3bejrMAA4teP1EcY9ygqJmW4iwSloZ10= github.com/containers/common v0.62.0/go.mod h1:Yec+z8mrSq4rydHofrnDCBqAcNA/BGrSg1kfFUL6F6s= github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg= diff --git a/vendor/github.com/containers/buildah/.cirrus.yml b/vendor/github.com/containers/buildah/.cirrus.yml index 632e18ef32..7aa0e309f1 100644 --- a/vendor/github.com/containers/buildah/.cirrus.yml +++ b/vendor/github.com/containers/buildah/.cirrus.yml @@ -234,6 +234,7 @@ integration_task: gce_instance: image_name: "$IMAGE_NAME" + cpu: 4 # Separate scripts for separate outputs, makes debugging easier. setup_script: '${SCRIPT_BASE}/setup.sh |& ${_TIMESTAMP}' @@ -281,6 +282,7 @@ integration_rootless_task: gce_instance: image_name: "$IMAGE_NAME" + cpu: 4 # Separate scripts for separate outputs, makes debugging easier. setup_script: '${SCRIPT_BASE}/setup.sh |& ${_TIMESTAMP}' @@ -299,6 +301,9 @@ in_podman_task: skip: *not_build_docs depends_on: *smoke_vendor + gce_instance: + cpu: 4 + env: # This is key, cause the scripts to re-execute themselves inside a container. IN_PODMAN: 'true' diff --git a/vendor/github.com/containers/buildah/CHANGELOG.md b/vendor/github.com/containers/buildah/CHANGELOG.md index c290b574c1..e28a49a34d 100644 --- a/vendor/github.com/containers/buildah/CHANGELOG.md +++ b/vendor/github.com/containers/buildah/CHANGELOG.md @@ -2,6 +2,97 @@ # Changelog +## v1.39.0 (2025-01-31) + + Bump c/storage v1.57.1, c/image 5.34.0, c/common v0.62.0 + Update module github.com/containers/storage to v1.57.0 + CI, .cirrus: parallelize containerized integration + ed's comment: cleanup + use seperate blobinfocache for flaky test + bump CI VMs to 4 CPUs (was: 2) for integration tests + cleanup, debug, and disable parallel in blobcache tests + bats tests - parallelize + pkg/overlay: cleanups + RPM: include check section to silence rpmlint + RPM: use default gobuild macro on RHEL + tests: remove masked /sys/dev/block check + vendor to latest c/{common,image,storage} + build, run: record hash or digest in image history + Accept image names as sources for cache mounts + Run(): always clean up options.ExternalImageMounts + refactor: replace golang.org/x/exp with stdlib + Update to c/image @main + fix broken doc link + run_freebsd.go: only import runtime-spec once + fix(deps): update module github.com/docker/docker to v27.5.1+incompatible + bump github.com/vbatts/tar-split + Add more checks to the --mount flag parsing logic + chroot mount flags integration test: copy binaries + fix(deps): update module github.com/moby/buildkit to v0.19.0 + relabel(): correct a misleading parameter name + Fix TOCTOU error when bind and cache mounts use "src" values + define.TempDirForURL(): always use an intermediate subdirectory + internal/volume.GetBindMount(): discard writes in bind mounts + pkg/overlay: add a MountLabel flag to Options + pkg/overlay: add a ForceMount flag to Options + Add internal/volumes.bindFromChroot() + Add an internal/open package + fix(deps): update module github.com/containers/common to v0.61.1 + fix(deps): update module github.com/containers/image/v5 to v5.33.1 + [CI:DOCS] Touch up changelogs + fix(deps): update module github.com/docker/docker to v27.5.0+incompatible + copy-preserving-extended-attributes: use a different base image + fix(deps): update github.com/containers/luksy digest to a3a812d + chore(deps): update module golang.org/x/net to v0.33.0 [security] + fix(deps): update module golang.org/x/crypto to v0.32.0 + New VM Images + fix(deps): update module github.com/opencontainers/runc to v1.2.4 + fix(deps): update module github.com/docker/docker to v27.4.1+incompatible + fix(deps): update module github.com/containers/ocicrypt to v1.2.1 + Add support for --security-opt mask and unmask + Allow cache mounts to be stages or additional build contexts + [skip-ci] RPM: cleanup changelog conditionals + fix(deps): update module github.com/cyphar/filepath-securejoin to v0.3.6 + fix(deps): update module github.com/moby/buildkit to v0.18.2 + Fix an error message in the chroot unit test + copier: use .PAXRecords instead of .Xattrs + chroot: on Linux, try to pivot_root before falling back to chroot + manifest add: add --artifact-annotation + Add context to an error message + Update module golang.org/x/crypto to v0.31.0 + Update module github.com/opencontainers/runc to v1.2.3 + Update module github.com/docker/docker to v27.4.0+incompatible + Update module github.com/cyphar/filepath-securejoin to v0.3.5 + CI: don't build a binary in the unit tests task + CI: use /tmp for $GOCACHE + CI: remove dependencies on the cross-build task + CI: run cross-compile task with make -j + Update module github.com/docker/docker to v27.4.0-rc.4+incompatible + Update module github.com/moby/buildkit to v0.18.1 + Update module golang.org/x/crypto to v0.30.0 + Update golang.org/x/exp digest to 2d47ceb + Update github.com/opencontainers/runtime-tools digest to f7e3563 + [skip-ci] Packit: remove rhel copr build jobs + [skip-ci] Packit: switch to fedora-all for copr + Update module github.com/stretchr/testify to v1.10.0 + Update module github.com/moby/buildkit to v0.17.2 + Makefile: use `find` to detect source files + Tests: make _prefetch() parallel-safe + Update module github.com/opencontainers/runc to v1.2.2 + executor: allow to specify --no-pivot-root + Update module github.com/moby/sys/capability to v0.4.0 + Makefile: mv codespell config to .codespellrc + Fix some codespell errors + Makefile,install.md: rm gopath stuff + Makefile: rm targets working on .. + build: rm exclude_graphdriver_devicemapper tag + Makefile: rm unused var + Finish updating to go 1.22 + CI VMs: bump again + Bump to Buidah v1.39.0-dev + stage_executor: set avoidLookingCache only if mounting stage + imagebuildah: additionalContext is not a local built stage + ## v1.38.0 (2024-11-08) Bump to c/common v0.61.0, c/image v5.33.0, c/storage v1.56.0 diff --git a/vendor/github.com/containers/buildah/changelog.txt b/vendor/github.com/containers/buildah/changelog.txt index c199c840e1..f1d0263992 100644 --- a/vendor/github.com/containers/buildah/changelog.txt +++ b/vendor/github.com/containers/buildah/changelog.txt @@ -1,3 +1,93 @@ +- Changelog for v1.39.0 (2025-01-31) + * Bump c/storage v1.57.1, c/image 5.34.0, c/common v0.62.0 + * Update module github.com/containers/storage to v1.57.0 + * CI, .cirrus: parallelize containerized integration + * ed's comment: cleanup + * use seperate blobinfocache for flaky test + * bump CI VMs to 4 CPUs (was: 2) for integration tests + * cleanup, debug, and disable parallel in blobcache tests + * bats tests - parallelize + * pkg/overlay: cleanups + * RPM: include check section to silence rpmlint + * RPM: use default gobuild macro on RHEL + * tests: remove masked /sys/dev/block check + * vendor to latest c/{common,image,storage} + * build, run: record hash or digest in image history + * Accept image names as sources for cache mounts + * Run(): always clean up options.ExternalImageMounts + * refactor: replace golang.org/x/exp with stdlib + * Update to c/image @main + * fix broken doc link + * run_freebsd.go: only import runtime-spec once + * fix(deps): update module github.com/docker/docker to v27.5.1+incompatible + * bump github.com/vbatts/tar-split + * Add more checks to the --mount flag parsing logic + * chroot mount flags integration test: copy binaries + * fix(deps): update module github.com/moby/buildkit to v0.19.0 + * relabel(): correct a misleading parameter name + * Fix TOCTOU error when bind and cache mounts use "src" values + * define.TempDirForURL(): always use an intermediate subdirectory + * internal/volume.GetBindMount(): discard writes in bind mounts + * pkg/overlay: add a MountLabel flag to Options + * pkg/overlay: add a ForceMount flag to Options + * Add internal/volumes.bindFromChroot() + * Add an internal/open package + * fix(deps): update module github.com/containers/common to v0.61.1 + * fix(deps): update module github.com/containers/image/v5 to v5.33.1 + * [CI:DOCS] Touch up changelogs + * fix(deps): update module github.com/docker/docker to v27.5.0+incompatible + * copy-preserving-extended-attributes: use a different base image + * fix(deps): update github.com/containers/luksy digest to a3a812d + * chore(deps): update module golang.org/x/net to v0.33.0 [security] + * fix(deps): update module golang.org/x/crypto to v0.32.0 + * New VM Images + * fix(deps): update module github.com/opencontainers/runc to v1.2.4 + * fix(deps): update module github.com/docker/docker to v27.4.1+incompatible + * fix(deps): update module github.com/containers/ocicrypt to v1.2.1 + * Add support for --security-opt mask and unmask + * Allow cache mounts to be stages or additional build contexts + * [skip-ci] RPM: cleanup changelog conditionals + * fix(deps): update module github.com/cyphar/filepath-securejoin to v0.3.6 + * fix(deps): update module github.com/moby/buildkit to v0.18.2 + * Fix an error message in the chroot unit test + * copier: use .PAXRecords instead of .Xattrs + * chroot: on Linux, try to pivot_root before falling back to chroot + * manifest add: add --artifact-annotation + * Add context to an error message + * Update module golang.org/x/crypto to v0.31.0 + * Update module github.com/opencontainers/runc to v1.2.3 + * Update module github.com/docker/docker to v27.4.0+incompatible + * Update module github.com/cyphar/filepath-securejoin to v0.3.5 + * CI: don't build a binary in the unit tests task + * CI: use /tmp for $GOCACHE + * CI: remove dependencies on the cross-build task + * CI: run cross-compile task with make -j + * Update module github.com/docker/docker to v27.4.0-rc.4+incompatible + * Update module github.com/moby/buildkit to v0.18.1 + * Update module golang.org/x/crypto to v0.30.0 + * Update golang.org/x/exp digest to 2d47ceb + * Update github.com/opencontainers/runtime-tools digest to f7e3563 + * [skip-ci] Packit: remove rhel copr build jobs + * [skip-ci] Packit: switch to fedora-all for copr + * Update module github.com/stretchr/testify to v1.10.0 + * Update module github.com/moby/buildkit to v0.17.2 + * Makefile: use `find` to detect source files + * Tests: make _prefetch() parallel-safe + * Update module github.com/opencontainers/runc to v1.2.2 + * executor: allow to specify --no-pivot-root + * Update module github.com/moby/sys/capability to v0.4.0 + * Makefile: mv codespell config to .codespellrc + * Fix some codespell errors + * Makefile,install.md: rm gopath stuff + * Makefile: rm targets working on .. + * build: rm exclude_graphdriver_devicemapper tag + * Makefile: rm unused var + * Finish updating to go 1.22 + * CI VMs: bump again + * Bump to Buidah v1.39.0-dev + * stage_executor: set avoidLookingCache only if mounting stage + * imagebuildah: additionalContext is not a local built stage + - Changelog for v1.38.0 (2024-11-08) * Bump to c/common v0.61.0, c/image v5.33.0, c/storage v1.56.0 * fix(deps): update module golang.org/x/crypto to v0.29.0 diff --git a/vendor/github.com/containers/buildah/define/types.go b/vendor/github.com/containers/buildah/define/types.go index 5ec4820230..d3df78dad3 100644 --- a/vendor/github.com/containers/buildah/define/types.go +++ b/vendor/github.com/containers/buildah/define/types.go @@ -29,7 +29,7 @@ const ( // identify working containers. Package = "buildah" // Version for the Package. Also used by .packit.sh for Packit builds. - Version = "1.39.0-dev" + Version = "1.39.0" // DefaultRuntime if containers.conf fails. DefaultRuntime = "runc" diff --git a/vendor/modules.txt b/vendor/modules.txt index 833d09f543..b21c2b1867 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -147,7 +147,7 @@ github.com/containernetworking/cni/pkg/version # github.com/containernetworking/plugins v1.5.1 ## explicit; go 1.20 github.com/containernetworking/plugins/pkg/ns -# github.com/containers/buildah v1.38.1-0.20250125114111-92015b7f4301 +# github.com/containers/buildah v1.39.0 ## explicit; go 1.22.8 github.com/containers/buildah github.com/containers/buildah/bind From d4f581786242ea1bcd4a9c1a17e3f387154f293c Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Mon, 3 Feb 2025 15:54:34 +0100 Subject: [PATCH 14/58] update gvproxy version The current macos installer gvproxy version has a number of issues around dns handling[1,2]. They should be fixed now in 0.8.3 as they reverted the dns changes back to the 0.7.5 code. This should make it work like it used to be. Our 5.3.2 installer ships the 0.7.5 version so users of the podman installer never noticed that but we got plenty of reports from brew users. This needs to be backported into v5.4 to make sure we do not ship the broken version as part of the installer. [1] https://github.com/containers/gvisor-tap-vsock/issues/462 [2] https://github.com/containers/gvisor-tap-vsock/issues/466 Signed-off-by: Paul Holzinger --- contrib/pkginstaller/Makefile | 2 +- go.mod | 2 +- go.sum | 4 ++-- vendor/modules.txt | 2 +- winmake.ps1 | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/contrib/pkginstaller/Makefile b/contrib/pkginstaller/Makefile index 5540edca28..0c46b36af8 100644 --- a/contrib/pkginstaller/Makefile +++ b/contrib/pkginstaller/Makefile @@ -6,7 +6,7 @@ ifeq ($(ARCH), aarch64) else GOARCH:=$(ARCH) endif -GVPROXY_VERSION ?= 0.8.1 +GVPROXY_VERSION ?= 0.8.3 VFKIT_VERSION ?= 0.6.0 KRUNKIT_VERSION ?= 0.1.4 GVPROXY_RELEASE_URL ?= https://github.com/containers/gvisor-tap-vsock/releases/download/v$(GVPROXY_VERSION)/gvproxy-darwin diff --git a/go.mod b/go.mod index 597791f546..940bc0fa1b 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/containers/buildah v1.38.1-0.20250125114111-92015b7f4301 github.com/containers/common v0.62.0 github.com/containers/conmon v2.0.20+incompatible - github.com/containers/gvisor-tap-vsock v0.8.2 + github.com/containers/gvisor-tap-vsock v0.8.3 github.com/containers/image/v5 v5.34.0 github.com/containers/libhvee v0.9.0 github.com/containers/ocicrypt v1.2.1 diff --git a/go.sum b/go.sum index e69198f24e..922346df25 100644 --- a/go.sum +++ b/go.sum @@ -82,8 +82,8 @@ github.com/containers/common v0.62.0 h1:Sl9WE5h7Y/F3bejrMAA4teP1EcY9ygqJmW4iwSlo github.com/containers/common v0.62.0/go.mod h1:Yec+z8mrSq4rydHofrnDCBqAcNA/BGrSg1kfFUL6F6s= github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg= github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I= -github.com/containers/gvisor-tap-vsock v0.8.2 h1:uQMBCCHlIIj62fPjbvgm6AL5EzsP6TP5eviByOJEsOg= -github.com/containers/gvisor-tap-vsock v0.8.2/go.mod h1:EMRe2o63ddq2zxcP0hTysmxCf/5JlaNEg8/gpzP0ox4= +github.com/containers/gvisor-tap-vsock v0.8.3 h1:Am3VdjXTn8Mn+dNhgkiRcCFOTSM8u9aWKLW3KTHOGjk= +github.com/containers/gvisor-tap-vsock v0.8.3/go.mod h1:46MvrqNuRNbjV4ZsZ3mHVJjR2Eh+fpyRh72EvWWFFjU= github.com/containers/image/v5 v5.34.0 h1:HPqQaDUsox/3mC1pbOyLAIQEp0JhQqiUZ+6JiFIZLDI= github.com/containers/image/v5 v5.34.0/go.mod h1:/WnvUSEfdqC/ahMRd4YJDBLrpYWkGl018rB77iB3FDo= github.com/containers/libhvee v0.9.0 h1:5UxJMka1lDfxTeITA25Pd8QVVttJAG43eQS1Getw1tc= diff --git a/vendor/modules.txt b/vendor/modules.txt index 833d09f543..44acb01129 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -249,7 +249,7 @@ github.com/containers/common/version # github.com/containers/conmon v2.0.20+incompatible ## explicit github.com/containers/conmon/runner/config -# github.com/containers/gvisor-tap-vsock v0.8.2 +# github.com/containers/gvisor-tap-vsock v0.8.3 ## explicit; go 1.22.0 github.com/containers/gvisor-tap-vsock/pkg/types # github.com/containers/image/v5 v5.34.0 diff --git a/winmake.ps1 b/winmake.ps1 index 6aa8907611..6e9948b01b 100644 --- a/winmake.ps1 +++ b/winmake.ps1 @@ -39,7 +39,7 @@ function Win-SSHProxy { New-Item -ItemType Directory -Force -Path "./bin/windows" if (-Not $Version) { - $Version = "v0.8.1" + $Version = "v0.8.3" } curl.exe -sSL -o "./bin/windows/gvproxy.exe" --retry 5 "https://github.com/containers/gvisor-tap-vsock/releases/download/$Version/gvproxy-windowsgui.exe" curl.exe -sSL -o "./bin/windows/win-sshproxy.exe" --retry 5 "https://github.com/containers/gvisor-tap-vsock/releases/download/$Version/win-sshproxy.exe" From cadf0815547fa89ac35d1f84fd146c438aef049a Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Mon, 3 Feb 2025 17:41:35 +0100 Subject: [PATCH 15/58] rpm: add attr as dependency for podman-tests Since commit 06c103469d we are using getfattr in system tests, that caused failures in gating tests[1] as getfattr was not installed. So add attr as dependency. [1] https://artifacts.dev.testing-farm.io/d93b6849-e526-46e9-a7c3-874bad4217a9/work-tests.yml8_p4nfkf/tests-n75vnz0u/test.podman-root.bats.log Signed-off-by: Paul Holzinger --- rpm/podman.spec | 1 + 1 file changed, 1 insertion(+) diff --git a/rpm/podman.spec b/rpm/podman.spec index 852b780f67..b27772fde3 100644 --- a/rpm/podman.spec +++ b/rpm/podman.spec @@ -142,6 +142,7 @@ Requires: %{name} = %{epoch}:%{version}-%{release} %if %{defined fedora} Requires: bats %endif +Requires: attr Requires: jq Requires: skopeo Requires: nmap-ncat From 9b67d4c285c4581d5531fdb46c006999100e59e8 Mon Sep 17 00:00:00 2001 From: Mario Loriedo Date: Mon, 3 Feb 2025 13:32:41 +0100 Subject: [PATCH 16/58] Force use of iptables on Windows WSL This is a workaround for #25201 and helps with upgrading the WSL image to Fedora 41. Signed-off-by: Mario Loriedo --- pkg/machine/wsl/declares.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkg/machine/wsl/declares.go b/pkg/machine/wsl/declares.go index a1f13ae310..bbc4215a7e 100644 --- a/pkg/machine/wsl/declares.go +++ b/pkg/machine/wsl/declares.go @@ -12,6 +12,11 @@ const containersConf = `[containers] [engine] cgroup_manager = "cgroupfs" + +# Using iptables until we fix nftables on WSL: +# https://github.com/containers/podman/issues/25201 +[network] +firewall_driver="iptables" ` const registriesConf = `unqualified-search-registries=["docker.io"] From 48459db0764e9b9df537c492322355d5787e3a07 Mon Sep 17 00:00:00 2001 From: Lokesh Mandvekar Date: Fri, 31 Jan 2025 16:18:48 +0530 Subject: [PATCH 17/58] RPM: adjust qemu dependencies We only need qemu-system-[x86|aarch64]-core based on the architecture along with qemu-img. So, there's no need to pull in all of qemu. The qemu-system-[x86|aarch64]-core packages are not present on CentOS Stream and RHEL, so we use qemu-kvm there instead. Ref: https://github.com/containers/podman/pull/24369/files#r1883658262 Signed-off-by: Lokesh Mandvekar --- rpm/podman.spec | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/rpm/podman.spec b/rpm/podman.spec index b27772fde3..26db8eaaff 100644 --- a/rpm/podman.spec +++ b/rpm/podman.spec @@ -24,6 +24,8 @@ %if %{defined fedora} %define build_with_btrfs 1 +# qemu-system* isn't packageed for CentOS Stream / RHEL +%define qemu 1 %endif %if %{defined copr_username} @@ -188,7 +190,17 @@ when `%{_bindir}/%{name}sh` is set as a login shell or set as os.Args[0]. Summary: Metapackage for setting up %{name} machine Requires: %{name} = %{epoch}:%{version}-%{release} Requires: gvisor-tap-vsock -Requires: qemu +%if %{defined qemu} +%ifarch aarch64 +Requires: qemu-system-aarch64-core +%endif +%ifarch x86_64 +Requires: qemu-system-x86-core +%endif +%else +Requires: qemu-kvm +%endif +Requires: qemu-img Requires: virtiofsd ExclusiveArch: x86_64 aarch64 From 5feb81d9fffe9456688ad846c8b39b18c14ad685 Mon Sep 17 00:00:00 2001 From: Lokesh Mandvekar Date: Fri, 31 Jan 2025 17:15:17 +0530 Subject: [PATCH 18/58] RPM: include empty check to silence rpmlint Signed-off-by: Lokesh Mandvekar --- rpm/podman.spec | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rpm/podman.spec b/rpm/podman.spec index 26db8eaaff..8e2635a304 100644 --- a/rpm/podman.spec +++ b/rpm/podman.spec @@ -309,6 +309,9 @@ ln -s ../virtiofsd %{buildroot}%{_libexecdir}/%{name} #define license tag if not already defined %{!?_licensedir:%global license %doc} +# Include empty check to silence rpmlint warning +%check + %files -f %{name}.file-list %license LICENSE vendor/modules.txt %doc README.md CONTRIBUTING.md install.md transfer.md From 8ee7b117b662a9599875f01b55d0105d69e87210 Mon Sep 17 00:00:00 2001 From: Jake Correnti Date: Fri, 17 Jan 2025 11:34:06 -0500 Subject: [PATCH 19/58] Add `machine init --playbook` Allow the user to provide an Ansible playbook file on init which will then be run on boot. Signed-off-by: Jake Correnti Signed-off-by: Brent Baude --- cmd/podman/machine/init.go | 4 ++ .../markdown/podman-machine-init.1.md.in | 9 +++ pkg/machine/define/initopts.go | 1 + pkg/machine/e2e/config_init_test.go | 32 ++++++--- pkg/machine/e2e/init_test.go | 67 +++++++++++++++++++ pkg/machine/ignition/ignition.go | 45 +++++++++++++ pkg/machine/shim/host.go | 37 ++++++++++ pkg/machine/vmconfigs/config.go | 8 +++ pkg/machine/wsl/machine.go | 8 ++- pkg/machine/wsl/stubber.go | 2 +- 10 files changed, 200 insertions(+), 13 deletions(-) diff --git a/cmd/podman/machine/init.go b/cmd/podman/machine/init.go index 69afdc02c6..a3db264c2f 100644 --- a/cmd/podman/machine/init.go +++ b/cmd/podman/machine/init.go @@ -62,6 +62,10 @@ func init() { ) _ = initCmd.RegisterFlagCompletionFunc(cpusFlagName, completion.AutocompleteNone) + runPlaybookFlagName := "playbook" + flags.StringVar(&initOpts.PlaybookPath, runPlaybookFlagName, "", "Run an Ansible playbook after first boot") + _ = initCmd.RegisterFlagCompletionFunc(runPlaybookFlagName, completion.AutocompleteDefault) + diskSizeFlagName := "disk-size" flags.Uint64Var( &initOpts.DiskSize, diff --git a/docs/source/markdown/podman-machine-init.1.md.in b/docs/source/markdown/podman-machine-init.1.md.in index af603e0d4e..775362a9e9 100644 --- a/docs/source/markdown/podman-machine-init.1.md.in +++ b/docs/source/markdown/podman-machine-init.1.md.in @@ -80,6 +80,8 @@ is copied into the user's CONF_DIR and renamed. Additionally, no SSH keys are g Fully qualified registry, path, or URL to a VM image. Registry target must be in the form of `docker://registry/repo/image:version`. +Note: Only images provided by podman will be supported. + #### **--memory**, **-m**=*number* Memory (in MiB). Note: 1024MiB = 1GiB. @@ -88,6 +90,13 @@ Memory (in MiB). Note: 1024MiB = 1GiB. Start the virtual machine immediately after it has been initialized. +#### **--playbook** + +Add the provided Ansible playbook to the machine and execute it after the first boot. + +Note: The playbook will be executed with the same privileges given to the user in the virtual machine. The playbook provided cannot include other files from the host system, as they will not be copied. +Use of the `--playbook` flag will require the image to include Ansible. The default image provided will have Ansible included. + #### **--rootful** Whether this machine prefers rootful (`true`) or rootless (`false`) diff --git a/pkg/machine/define/initopts.go b/pkg/machine/define/initopts.go index 4ddf87ca19..b1ccaaa6b7 100644 --- a/pkg/machine/define/initopts.go +++ b/pkg/machine/define/initopts.go @@ -3,6 +3,7 @@ package define import "net/url" type InitOptions struct { + PlaybookPath string CPUS uint64 DiskSize uint64 IgnitionPath string diff --git a/pkg/machine/e2e/config_init_test.go b/pkg/machine/e2e/config_init_test.go index 0423010477..031f4395f7 100644 --- a/pkg/machine/e2e/config_init_test.go +++ b/pkg/machine/e2e/config_init_test.go @@ -11,19 +11,21 @@ import ( type initMachine struct { /* - --cpus uint Number of CPUs (default 1) - --disk-size uint Disk size in GiB (default 100) - --ignition-path string Path to ignition file - --username string Username of the remote user (default "core" for FCOS, "user" for Fedora) - --image-path string Path to bootable image (default "testing") - -m, --memory uint Memory in MiB (default 2048) - --now Start machine now - --rootful Whether this machine should prefer rootful container execution - --timezone string Set timezone (default "local") - -v, --volume stringArray Volumes to mount, source:target - --volume-driver string Optional volume driver + --cpus uint Number of CPUs (default 1) + --disk-size uint Disk size in GiB (default 100) + --ignition-path string Path to ignition file + --username string Username of the remote user (default "core" for FCOS, "user" for Fedora) + --image-path string Path to bootable image (default "testing") + -m, --memory uint Memory in MiB (default 2048) + --now Start machine now + --rootful Whether this machine should prefer rootful container execution + --playbook string Run an ansible playbook after first boot + --timezone string Set timezone (default "local") + -v, --volume stringArray Volumes to mount, source:target + --volume-driver string Optional volume driver */ + playbook string cpus *uint diskSize *uint ignitionPath string @@ -73,6 +75,9 @@ func (i *initMachine) buildCmd(m *machineTestBuilder) []string { if i.rootful { cmd = append(cmd, "--rootful") } + if l := len(i.playbook); l > 0 { + cmd = append(cmd, "--playbook", i.playbook) + } if i.userModeNetworking { cmd = append(cmd, "--user-mode-networking") } @@ -152,6 +157,11 @@ func (i *initMachine) withRootful(r bool) *initMachine { return i } +func (i *initMachine) withRunPlaybook(p string) *initMachine { + i.playbook = p + return i +} + func (i *initMachine) withUserModeNetworking(r bool) *initMachine { //nolint:unused i.userModeNetworking = r return i diff --git a/pkg/machine/e2e/init_test.go b/pkg/machine/e2e/init_test.go index bd5fe683c5..8e3bc72b92 100644 --- a/pkg/machine/e2e/init_test.go +++ b/pkg/machine/e2e/init_test.go @@ -98,6 +98,73 @@ var _ = Describe("podman machine init", func() { } }) + It("run playbook", func() { + str := randomString() + + // ansible playbook file to create a text file containing a random string + playbookContents := fmt.Sprintf(`- name: Simple podman machine example + hosts: localhost + tasks: + - name: create a file + ansible.builtin.copy: + dest: ~/foobar.txt + content: "%s\n"`, str) + + playbookPath := filepath.Join(GinkgoT().TempDir(), "playbook.yaml") + + // create the playbook file + playbookFile, err := os.Create(playbookPath) + Expect(err).ToNot(HaveOccurred()) + defer playbookFile.Close() + + // write the desired contents into the file + _, err = playbookFile.WriteString(playbookContents) + Expect(err).To(Not(HaveOccurred())) + + name := randomString() + i := new(initMachine) + session, err := mb.setName(name).setCmd(i.withImage(mb.imagePath).withRunPlaybook(playbookPath).withNow()).run() + Expect(err).ToNot(HaveOccurred()) + Expect(session).To(Exit(0)) + + // ensure the contents of the playbook file didn't change when getting copied + ssh := new(sshMachine) + sshSession, err := mb.setName(name).setCmd(ssh.withSSHCommand([]string{"cat", "playbook.yaml"})).run() + Expect(err).ToNot(HaveOccurred()) + Expect(sshSession).To(Exit(0)) + Expect(sshSession.outputToStringSlice()).To(Equal(strings.Split(playbookContents, "\n"))) + + // wait until the playbook.service is done before checking to make sure the playbook was a success + playbookFinished := false + for range 900 { + sshSession, err = mb.setName(name).setCmd(ssh.withSSHCommand([]string{"systemctl", "is-active", "playbook.service"})).run() + Expect(err).ToNot(HaveOccurred()) + + if sshSession.outputToString() == "inactive" { + playbookFinished = true + break + } + + time.Sleep(10 * time.Millisecond) + } + + if !playbookFinished { + Fail("playbook.service did not finish") + } + + // output the contents of the file generated by the playbook + guestUser := "core" + if isWSL() { + guestUser = "user" + } + sshSession, err = mb.setName(name).setCmd(ssh.withSSHCommand([]string{"cat", fmt.Sprintf("/home/%s/foobar.txt", guestUser)})).run() + Expect(err).ToNot(HaveOccurred()) + Expect(sshSession).To(Exit(0)) + + // check its the same as the random number or string that we generated + Expect(sshSession.outputToString()).To(Equal(str)) + }) + It("simple init with start", func() { i := initMachine{} session, err := mb.setCmd(i.withImage(mb.imagePath)).run() diff --git a/pkg/machine/ignition/ignition.go b/pkg/machine/ignition/ignition.go index 62bf7a872f..3995ef714c 100644 --- a/pkg/machine/ignition/ignition.go +++ b/pkg/machine/ignition/ignition.go @@ -685,6 +685,51 @@ done ` } +func (i *IgnitionBuilder) AddPlaybook(contents string, destPath string, username string) error { + // create the ignition file object + f := File{ + Node: Node{ + Group: GetNodeGrp(username), + Path: destPath, + User: GetNodeUsr(username), + }, + FileEmbedded1: FileEmbedded1{ + Append: nil, + Contents: Resource{ + Source: EncodeDataURLPtr(contents), + }, + Mode: IntToPtr(0744), + }, + } + + // call ignitionBuilder.WithFile + // add the config file to the ignition object + i.WithFile(f) + + unit := parser.NewUnitFile() + unit.Add("Unit", "After", "ready.service") + unit.Add("Unit", "ConditionFirstBoot", "yes") + unit.Add("Service", "Type", "oneshot") + unit.Add("Service", "User", username) + unit.Add("Service", "Group", username) + unit.Add("Service", "ExecStart", fmt.Sprintf("ansible-playbook %s", destPath)) + unit.Add("Install", "WantedBy", "default.target") + unitContents, err := unit.ToString() + if err != nil { + return err + } + + // create a systemd service + playbookUnit := Unit{ + Enabled: BoolToPtr(true), + Name: "playbook.service", + Contents: &unitContents, + } + i.WithUnit(playbookUnit) + + return nil +} + func GetNetRecoveryUnitFile() *parser.UnitFile { recoveryUnit := parser.NewUnitFile() recoveryUnit.Add("Unit", "Description", "Verifies health of network and recovers if necessary") diff --git a/pkg/machine/shim/host.go b/pkg/machine/shim/host.go index 1315c9adb9..82e70be8fa 100644 --- a/pkg/machine/shim/host.go +++ b/pkg/machine/shim/host.go @@ -4,6 +4,7 @@ import ( "bufio" "errors" "fmt" + "io" "os" "path/filepath" "runtime" @@ -207,6 +208,32 @@ func Init(opts machineDefine.InitOptions, mp vmconfigs.VMProvider) error { } } + if len(opts.PlaybookPath) > 0 { + f, err := os.Open(opts.PlaybookPath) + if err != nil { + return err + } + s, err := io.ReadAll(f) + if err != nil { + return fmt.Errorf("read playbook: %w", err) + } + + playbookDest := fmt.Sprintf("/home/%s/%s", userName, "playbook.yaml") + + if mp.VMType() != machineDefine.WSLVirt { + err = ignBuilder.AddPlaybook(string(s), playbookDest, userName) + if err != nil { + return err + } + } + + mc.Ansible = &vmconfigs.AnsibleConfig{ + PlaybookPath: playbookDest, + Contents: string(s), + User: userName, + } + } + readyIgnOpts, err := mp.PrepareIgnition(mc, &ignBuilder) if err != nil { return err @@ -543,6 +570,16 @@ func Start(mc *vmconfigs.MachineConfig, mp vmconfigs.VMProvider, dirs *machineDe } } + isFirstBoot, err := mc.IsFirstBoot() + if err != nil { + logrus.Error(err) + } + if mp.VMType() == machineDefine.WSLVirt && mc.Ansible != nil && isFirstBoot { + if err := machine.CommonSSHSilent(mc.Ansible.User, mc.SSH.IdentityPath, mc.Name, mc.SSH.Port, []string{"ansible-playbook", mc.Ansible.PlaybookPath}); err != nil { + logrus.Error(err) + } + } + // Provider is responsible for waiting if mp.UseProviderNetworkSetup() { return nil diff --git a/pkg/machine/vmconfigs/config.go b/pkg/machine/vmconfigs/config.go index 417d5b3fe1..a45fee6432 100644 --- a/pkg/machine/vmconfigs/config.go +++ b/pkg/machine/vmconfigs/config.go @@ -53,6 +53,8 @@ type MachineConfig struct { Starting bool Rosetta bool + + Ansible *AnsibleConfig } type machineImage interface { //nolint:unused @@ -148,3 +150,9 @@ type VMStats struct { // LastUp contains the last recorded uptime LastUp time.Time } + +type AnsibleConfig struct { + PlaybookPath string + Contents string + User string +} diff --git a/pkg/machine/wsl/machine.go b/pkg/machine/wsl/machine.go index 38c1a91261..3355f6b2b5 100644 --- a/pkg/machine/wsl/machine.go +++ b/pkg/machine/wsl/machine.go @@ -148,7 +148,7 @@ func createKeys(mc *vmconfigs.MachineConfig, dist string) error { return nil } -func configureSystem(mc *vmconfigs.MachineConfig, dist string) error { +func configureSystem(mc *vmconfigs.MachineConfig, dist string, ansibleConfig *vmconfigs.AnsibleConfig) error { user := mc.SSH.RemoteUsername if err := wslInvoke(dist, "sh", "-c", fmt.Sprintf(appendPort, mc.SSH.Port, mc.SSH.Port)); err != nil { return fmt.Errorf("could not configure SSH port for guest OS: %w", err) @@ -167,6 +167,12 @@ func configureSystem(mc *vmconfigs.MachineConfig, dist string) error { return fmt.Errorf("could not generate systemd-sysusers override for guest OS: %w", err) } + if ansibleConfig != nil { + if err := wslPipe(ansibleConfig.Contents, dist, "sh", "-c", fmt.Sprintf("cat > %s", ansibleConfig.PlaybookPath)); err != nil { + return fmt.Errorf("could not generate playbook file for guest os: %w", err) + } + } + lingerCmd := withUser("cat > /home/[USER]/.config/systemd/[USER]/linger-example.service", user) if err := wslPipe(lingerService, dist, "sh", "-c", lingerCmd); err != nil { return fmt.Errorf("could not generate linger service for guest OS: %w", err) diff --git a/pkg/machine/wsl/stubber.go b/pkg/machine/wsl/stubber.go index 073b0b04bf..75b12fad03 100644 --- a/pkg/machine/wsl/stubber.go +++ b/pkg/machine/wsl/stubber.go @@ -68,7 +68,7 @@ func (w WSLStubber) CreateVM(opts define.CreateVMOpts, mc *vmconfigs.MachineConf } fmt.Println("Configuring system...") - if err = configureSystem(mc, dist); err != nil { + if err = configureSystem(mc, dist, mc.Ansible); err != nil { return err } From bc5de3dfc7a074f64da701cc843fde6ef3d726bd Mon Sep 17 00:00:00 2001 From: Federico Di Pierro Date: Mon, 20 Jan 2025 09:15:31 +0100 Subject: [PATCH 20/58] fix(pkg/rootless): avoid memleak during init() contructor. `argv[0]`, ie: the full buffer allocated by `get_cmd_line_args`, was going to be freed only if `can_use_shortcut()` was called. Instead, let `init()` always manage `argv0` lifecycle. Signed-off-by: Federico Di Pierro --- pkg/rootless/rootless_linux.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/rootless/rootless_linux.c b/pkg/rootless/rootless_linux.c index ddb97b3346..4f71d49e5c 100644 --- a/pkg/rootless/rootless_linux.c +++ b/pkg/rootless/rootless_linux.c @@ -364,7 +364,6 @@ get_cmd_line_args (int *argc_out) static bool can_use_shortcut (char **argv) { - cleanup_free char *argv0 = NULL; bool ret = true; int argc; @@ -372,8 +371,6 @@ can_use_shortcut (char **argv) return false; #endif - argv0 = argv[0]; - if (strstr (argv[0], "podman") == NULL) return false; @@ -439,6 +436,7 @@ static void __attribute__((constructor)) init() const char *listen_fds; const char *listen_fdnames; cleanup_free char **argv = NULL; + cleanup_free char *argv0 = NULL; cleanup_dir DIR *d = NULL; int argc; @@ -496,6 +494,8 @@ static void __attribute__((constructor)) init() fprintf(stderr, "cannot retrieve cmd line"); _exit (EXIT_FAILURE); } + // Even if unused, this is needed to ensure we properly free the memory + argv0 = argv[0]; if (geteuid () != 0 || getenv ("_CONTAINERS_USERNS_CONFIGURED") == NULL) do_preexec_hooks(argv, argc); From 57b9709b690930c1eaad47b37a8c562f67ea3b55 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Thu, 30 Jan 2025 11:53:28 +0100 Subject: [PATCH 21/58] util: replace Walk with WalkDir Closes: https://github.com/containers/podman/issues/25163 Signed-off-by: Giuseppe Scrivano --- cmd/podman/common/completion.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cmd/podman/common/completion.go b/cmd/podman/common/completion.go index 3476f33be8..d4a8058bc7 100644 --- a/cmd/podman/common/completion.go +++ b/cmd/podman/common/completion.go @@ -3,6 +3,7 @@ package common import ( "bufio" "fmt" + "io/fs" "os" "path" "path/filepath" @@ -1646,8 +1647,8 @@ func AutocompleteContainersConfModules(cmd *cobra.Command, args []string, toComp for _, d := range dirs { cleanedD := filepath.Clean(d) moduleD := cleanedD + string(os.PathSeparator) - _ = filepath.Walk(d, - func(path string, f os.FileInfo, err error) error { + _ = filepath.WalkDir(d, + func(path string, d fs.DirEntry, err error) error { if err != nil { return err } @@ -1657,7 +1658,7 @@ func AutocompleteContainersConfModules(cmd *cobra.Command, args []string, toComp return nil } - if filepath.Clean(path) == cleanedD || f.IsDir() { + if filepath.Clean(path) == cleanedD || d.IsDir() { return nil } From bc8124fd6232e73f16c03128efae8ca33d6175b4 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Thu, 30 Jan 2025 21:07:21 +0100 Subject: [PATCH 22/58] pkg/api: honor cdi devices from the hostconfig pass down the devices specifies in the resources block so that CDI devices in the compose file are honored. Tested manually with the following compose file: services: testgpupodman_count: image: ubuntu:latest command: ["nvidia-smi"] profiles: [gpu] deploy: resources: reservations: devices: - driver: nvidia count: 1 capabilities: [gpu] testgpupodman_deviceid: image: docker.io/ubuntu:latest command: ["nvidia-smi"] deploy: resources: reservations: devices: - driver: cdi device_ids: ['nvidia.com/gpu=all'] capabilities: [gpu] Closes: https://github.com/containers/podman/issues/19338 Signed-off-by: Giuseppe Scrivano --- pkg/api/handlers/compat/containers_create.go | 5 +++++ test/compose/cdi_device/README.md | 9 +++++++++ test/compose/cdi_device/device.json | 14 ++++++++++++++ test/compose/cdi_device/docker-compose.yml | 15 +++++++++++++++ test/compose/cdi_device/setup.sh | 9 +++++++++ test/compose/cdi_device/teardown.sh | 3 +++ test/compose/cdi_device/tests.sh | 11 +++++++++++ 7 files changed, 66 insertions(+) create mode 100644 test/compose/cdi_device/README.md create mode 100644 test/compose/cdi_device/device.json create mode 100644 test/compose/cdi_device/docker-compose.yml create mode 100644 test/compose/cdi_device/setup.sh create mode 100644 test/compose/cdi_device/teardown.sh create mode 100644 test/compose/cdi_device/tests.sh diff --git a/pkg/api/handlers/compat/containers_create.go b/pkg/api/handlers/compat/containers_create.go index 14b37804f3..02253b9b2a 100644 --- a/pkg/api/handlers/compat/containers_create.go +++ b/pkg/api/handlers/compat/containers_create.go @@ -163,6 +163,11 @@ func cliOpts(cc handlers.CreateContainerConfig, rtc *config.Config) (*entities.C for _, dev := range cc.HostConfig.Devices { devices = append(devices, fmt.Sprintf("%s:%s:%s", dev.PathOnHost, dev.PathInContainer, dev.CgroupPermissions)) } + for _, r := range cc.HostConfig.Resources.DeviceRequests { + if r.Driver == "cdi" { + devices = append(devices, r.DeviceIDs...) + } + } // iterate blkreaddevicebps readBps := make([]string, 0, len(cc.HostConfig.BlkioDeviceReadBps)) diff --git a/test/compose/cdi_device/README.md b/test/compose/cdi_device/README.md new file mode 100644 index 0000000000..961af83fc7 --- /dev/null +++ b/test/compose/cdi_device/README.md @@ -0,0 +1,9 @@ +cdi devices +=========== + +This test copies a CDI device file on a tmpfs mounted on /etc/cdi, then checks that the CDI device in the compose file is present in a container. The test is skipped when running as rootless. + +Validation +------------ + +* The CDI device is present in the container. diff --git a/test/compose/cdi_device/device.json b/test/compose/cdi_device/device.json new file mode 100644 index 0000000000..d489906914 --- /dev/null +++ b/test/compose/cdi_device/device.json @@ -0,0 +1,14 @@ +{ + "cdiVersion": "0.3.0", + "kind": "vendor.com/device", + "devices": [ + { + "name": "myKmsg", + "containerEdits": { + "mounts": [ + {"hostPath": "/dev/kmsg", "containerPath": "/dev/kmsg1", "options": ["rw", "rprivate", "rbind"]} + ] + } + } + ] +} diff --git a/test/compose/cdi_device/docker-compose.yml b/test/compose/cdi_device/docker-compose.yml new file mode 100644 index 0000000000..dfbeb2e906 --- /dev/null +++ b/test/compose/cdi_device/docker-compose.yml @@ -0,0 +1,15 @@ +services: + test: + image: alpine + command: ["top"] + volumes: + - /dev:/dev-host + security_opt: + - label=disable + deploy: + resources: + reservations: + devices: + - driver: cdi + device_ids: ['vendor.com/device=myKmsg'] + capabilities: [] diff --git a/test/compose/cdi_device/setup.sh b/test/compose/cdi_device/setup.sh new file mode 100644 index 0000000000..224caa5443 --- /dev/null +++ b/test/compose/cdi_device/setup.sh @@ -0,0 +1,9 @@ +if is_rootless; then + reason=" - can't write to /etc/cdi" + _show_ok skip "$testname # skip$reason" + exit 0 +fi + +mkdir -p /etc/cdi +mount -t tmpfs tmpfs /etc/cdi +cp device.json /etc/cdi diff --git a/test/compose/cdi_device/teardown.sh b/test/compose/cdi_device/teardown.sh new file mode 100644 index 0000000000..770afd1269 --- /dev/null +++ b/test/compose/cdi_device/teardown.sh @@ -0,0 +1,3 @@ +if ! is_rootless; then + umount -l /etc/cdi +fi diff --git a/test/compose/cdi_device/tests.sh b/test/compose/cdi_device/tests.sh new file mode 100644 index 0000000000..230ad1d10e --- /dev/null +++ b/test/compose/cdi_device/tests.sh @@ -0,0 +1,11 @@ +# -*- bash -*- + +ctr_name="cdi_device-test-1" + +podman exec "$ctr_name" sh -c 'stat -c "%t:%T" /dev-host/kmsg' + +expected=$output + +podman exec "$ctr_name" sh -c 'stat -c "%t:%T" /dev/kmsg1' + +is "$output" "$expected" "$testname : device /dev/kmsg1 has the same rdev as /dev/kmsg on the host" From 4cd76ef27bfafebfcda4e9cab839745f785cfbff Mon Sep 17 00:00:00 2001 From: Brent Baude Date: Mon, 20 Jan 2025 14:01:23 -0600 Subject: [PATCH 23/58] Add type and annotations to artifact add podman artifact add now supports two new command line switches. --type string that describes the type of artifact --annotation string slice in the form of key=val These new options allow users to "tag" information in on their artifacts for any number of purposes down the line RUN-2446 Signed-off-by: Brent Baude --- cmd/podman/artifact/add.go | 32 +++++++++++++++++-- docs/source/markdown/.gitignore | 1 + .../markdown/options/annotation.manifest.md | 2 +- ...t-add.1.md => podman-artifact-add.1.md.in} | 9 ++++++ pkg/api/handlers/libpod/manifests.go | 27 ++++++++-------- pkg/domain/entities/artifact.go | 3 +- pkg/domain/entities/engine_image.go | 2 +- pkg/domain/infra/abi/artifact.go | 11 +++++-- pkg/domain/infra/tunnel/artifact.go | 4 +-- pkg/domain/utils/utils.go | 15 +++++++++ pkg/libartifact/store/store.go | 26 +++++++++++---- pkg/libartifact/types/config.go | 6 ++++ test/e2e/artifact_test.go | 25 +++++++++++++++ 13 files changed, 133 insertions(+), 30 deletions(-) rename docs/source/markdown/{podman-artifact-add.1.md => podman-artifact-add.1.md.in} (82%) diff --git a/cmd/podman/artifact/add.go b/cmd/podman/artifact/add.go index 3f3d2fb286..a92018fb3f 100644 --- a/cmd/podman/artifact/add.go +++ b/cmd/podman/artifact/add.go @@ -3,15 +3,17 @@ package artifact import ( "fmt" + "github.com/containers/common/pkg/completion" "github.com/containers/podman/v5/cmd/podman/common" "github.com/containers/podman/v5/cmd/podman/registry" "github.com/containers/podman/v5/pkg/domain/entities" + "github.com/containers/podman/v5/pkg/domain/utils" "github.com/spf13/cobra" ) var ( addCmd = &cobra.Command{ - Use: "add ARTIFACT PATH [...PATH]", + Use: "add [options] ARTIFACT PATH [...PATH]", Short: "Add an OCI artifact to the local store", Long: "Add an OCI artifact to the local store from the local filesystem", RunE: add, @@ -22,15 +24,41 @@ var ( } ) +type artifactAddOptions struct { + ArtifactType string + Annotations []string +} + +var ( + addOpts artifactAddOptions +) + func init() { registry.Commands = append(registry.Commands, registry.CliCommand{ Command: addCmd, Parent: artifactCmd, }) + flags := addCmd.Flags() + + annotationFlagName := "annotation" + flags.StringArrayVar(&addOpts.Annotations, annotationFlagName, nil, "set an `annotation` for the specified artifact") + _ = addCmd.RegisterFlagCompletionFunc(annotationFlagName, completion.AutocompleteNone) + + addTypeFlagName := "type" + flags.StringVar(&addOpts.ArtifactType, addTypeFlagName, "", "Use type to describe an artifact") + _ = addCmd.RegisterFlagCompletionFunc(addTypeFlagName, completion.AutocompleteNone) } func add(cmd *cobra.Command, args []string) error { - report, err := registry.ImageEngine().ArtifactAdd(registry.Context(), args[0], args[1:], entities.ArtifactAddoptions{}) + opts := new(entities.ArtifactAddOptions) + + annots, err := utils.ParseAnnotations(addOpts.Annotations) + if err != nil { + return err + } + opts.Annotations = annots + opts.ArtifactType = addOpts.ArtifactType + report, err := registry.ImageEngine().ArtifactAdd(registry.Context(), args[0], args[1:], opts) if err != nil { return err } diff --git a/docs/source/markdown/.gitignore b/docs/source/markdown/.gitignore index 370b2e81c9..8e05f6967f 100644 --- a/docs/source/markdown/.gitignore +++ b/docs/source/markdown/.gitignore @@ -1,3 +1,4 @@ +podman-artifact-add.1.md podman-artifact-pull.1.md podman-artifact-push.1.md podman-attach.1.md diff --git a/docs/source/markdown/options/annotation.manifest.md b/docs/source/markdown/options/annotation.manifest.md index 472fc40b40..e5b931dae1 100644 --- a/docs/source/markdown/options/annotation.manifest.md +++ b/docs/source/markdown/options/annotation.manifest.md @@ -1,5 +1,5 @@ ####> This option file is used in: -####> podman manifest add, manifest annotate +####> podman artifact add, manifest add, manifest annotate ####> If file is edited, make sure the changes ####> are applicable to all of those. #### **--annotation**=*annotation=value* diff --git a/docs/source/markdown/podman-artifact-add.1.md b/docs/source/markdown/podman-artifact-add.1.md.in similarity index 82% rename from docs/source/markdown/podman-artifact-add.1.md rename to docs/source/markdown/podman-artifact-add.1.md.in index 6ad757a3e4..35a99f9958 100644 --- a/docs/source/markdown/podman-artifact-add.1.md +++ b/docs/source/markdown/podman-artifact-add.1.md.in @@ -19,10 +19,15 @@ added. ## OPTIONS +@@option annotation.manifest + #### **--help** Print usage statement. +#### **--type** + +Set a type for the artifact being added. ## EXAMPLES @@ -39,6 +44,10 @@ $ podman artifact add quay.io/myartifact/myml:latest /tmp/foobar1.ml /tmp/foobar 1487acae11b5a30948c50762882036b41ac91a7b9514be8012d98015c95ddb78 ``` +Set an annotation for an artifact +``` +$ podman artifact add --annotation date=2025-01-30 quay.io/myartifact/myml:latest /tmp/foobar1.ml +``` ## SEE ALSO diff --git a/pkg/api/handlers/libpod/manifests.go b/pkg/api/handlers/libpod/manifests.go index ca1ae26673..3aaf0fd33e 100644 --- a/pkg/api/handlers/libpod/manifests.go +++ b/pkg/api/handlers/libpod/manifests.go @@ -29,6 +29,7 @@ import ( "github.com/containers/podman/v5/pkg/channel" "github.com/containers/podman/v5/pkg/domain/entities" "github.com/containers/podman/v5/pkg/domain/infra/abi" + domainUtils "github.com/containers/podman/v5/pkg/domain/utils" "github.com/containers/podman/v5/pkg/errorhandling" "github.com/gorilla/mux" "github.com/gorilla/schema" @@ -520,24 +521,17 @@ func ManifestModify(w http.ResponseWriter, r *http.Request) { return } - annotationsFromAnnotationSlice := func(annotation []string) map[string]string { - annotations := make(map[string]string) - for _, annotationSpec := range annotation { - key, val, hasVal := strings.Cut(annotationSpec, "=") - if !hasVal { - utils.Error(w, http.StatusBadRequest, fmt.Errorf("no value given for annotation %q", key)) - return nil - } - annotations[key] = val - } - return annotations - } if len(body.ManifestAddOptions.Annotation) != 0 { if len(body.ManifestAddOptions.Annotations) != 0 { utils.Error(w, http.StatusBadRequest, fmt.Errorf("can not set both Annotation and Annotations")) return } - body.ManifestAddOptions.Annotations = annotationsFromAnnotationSlice(body.ManifestAddOptions.Annotation) + annots, err := domainUtils.ParseAnnotations(body.ManifestAddOptions.Annotation) + if err != nil { + utils.Error(w, http.StatusBadRequest, err) + return + } + body.ManifestAddOptions.Annotations = annots body.ManifestAddOptions.Annotation = nil } if len(body.ManifestAddOptions.IndexAnnotation) != 0 { @@ -545,7 +539,12 @@ func ManifestModify(w http.ResponseWriter, r *http.Request) { utils.Error(w, http.StatusBadRequest, fmt.Errorf("can not set both IndexAnnotation and IndexAnnotations")) return } - body.ManifestAddOptions.IndexAnnotations = annotationsFromAnnotationSlice(body.ManifestAddOptions.IndexAnnotation) + annots, err := domainUtils.ParseAnnotations(body.ManifestAddOptions.IndexAnnotation) + if err != nil { + utils.Error(w, http.StatusBadRequest, err) + return + } + body.ManifestAddOptions.IndexAnnotations = annots body.ManifestAddOptions.IndexAnnotation = nil } diff --git a/pkg/domain/entities/artifact.go b/pkg/domain/entities/artifact.go index 29f788a594..5103401e8e 100644 --- a/pkg/domain/entities/artifact.go +++ b/pkg/domain/entities/artifact.go @@ -9,7 +9,8 @@ import ( "github.com/opencontainers/go-digest" ) -type ArtifactAddoptions struct { +type ArtifactAddOptions struct { + Annotations map[string]string ArtifactType string } diff --git a/pkg/domain/entities/engine_image.go b/pkg/domain/entities/engine_image.go index 04b215ac82..d93883b68b 100644 --- a/pkg/domain/entities/engine_image.go +++ b/pkg/domain/entities/engine_image.go @@ -9,7 +9,7 @@ import ( ) type ImageEngine interface { //nolint:interfacebloat - ArtifactAdd(ctx context.Context, name string, paths []string, opts ArtifactAddoptions) (*ArtifactAddReport, error) + ArtifactAdd(ctx context.Context, name string, paths []string, opts *ArtifactAddOptions) (*ArtifactAddReport, error) ArtifactInspect(ctx context.Context, name string, opts ArtifactInspectOptions) (*ArtifactInspectReport, error) ArtifactList(ctx context.Context, opts ArtifactListOptions) ([]*ArtifactListReport, error) ArtifactPull(ctx context.Context, name string, opts ArtifactPullOptions) (*ArtifactPullReport, error) diff --git a/pkg/domain/infra/abi/artifact.go b/pkg/domain/infra/abi/artifact.go index 126db79e26..fe1c3c12c8 100644 --- a/pkg/domain/infra/abi/artifact.go +++ b/pkg/domain/infra/abi/artifact.go @@ -11,6 +11,7 @@ import ( "github.com/containers/common/libimage" "github.com/containers/podman/v5/pkg/domain/entities" "github.com/containers/podman/v5/pkg/libartifact/store" + "github.com/containers/podman/v5/pkg/libartifact/types" ) func getDefaultArtifactStore(ir *ImageEngine) string { @@ -152,12 +153,18 @@ func (ir *ImageEngine) ArtifactPush(ctx context.Context, name string, opts entit err = artStore.Push(ctx, name, name, copyOpts) return &entities.ArtifactPushReport{}, err } -func (ir *ImageEngine) ArtifactAdd(ctx context.Context, name string, paths []string, opts entities.ArtifactAddoptions) (*entities.ArtifactAddReport, error) { +func (ir *ImageEngine) ArtifactAdd(ctx context.Context, name string, paths []string, opts *entities.ArtifactAddOptions) (*entities.ArtifactAddReport, error) { artStore, err := store.NewArtifactStore(getDefaultArtifactStore(ir), ir.Libpod.SystemContext()) if err != nil { return nil, err } - artifactDigest, err := artStore.Add(ctx, name, paths, opts.ArtifactType) + + addOptions := types.AddOptions{ + Annotations: opts.Annotations, + ArtifactType: opts.ArtifactType, + } + + artifactDigest, err := artStore.Add(ctx, name, paths, &addOptions) if err != nil { return nil, err } diff --git a/pkg/domain/infra/tunnel/artifact.go b/pkg/domain/infra/tunnel/artifact.go index 99657707dd..c404da95f0 100644 --- a/pkg/domain/infra/tunnel/artifact.go +++ b/pkg/domain/infra/tunnel/artifact.go @@ -9,7 +9,7 @@ import ( // TODO For now, no remote support has been added. We need the API to firm up first. -func ArtifactAdd(ctx context.Context, path, name string, opts entities.ArtifactAddoptions) error { +func ArtifactAdd(ctx context.Context, path, name string, opts entities.ArtifactAddOptions) error { return fmt.Errorf("not implemented") } @@ -33,6 +33,6 @@ func (ir *ImageEngine) ArtifactPush(ctx context.Context, name string, opts entit return nil, fmt.Errorf("not implemented") } -func (ir *ImageEngine) ArtifactAdd(ctx context.Context, name string, paths []string, opts entities.ArtifactAddoptions) (*entities.ArtifactAddReport, error) { +func (ir *ImageEngine) ArtifactAdd(ctx context.Context, name string, paths []string, opts *entities.ArtifactAddOptions) (*entities.ArtifactAddReport, error) { return nil, fmt.Errorf("not implemented") } diff --git a/pkg/domain/utils/utils.go b/pkg/domain/utils/utils.go index ca7a3210fb..e1bd488637 100644 --- a/pkg/domain/utils/utils.go +++ b/pkg/domain/utils/utils.go @@ -1,6 +1,7 @@ package utils import ( + "fmt" "net/url" "strings" @@ -39,3 +40,17 @@ func ToURLValues(f []string) (filters url.Values) { } return } + +// ParseAnnotations takes a string slice of options, expected to be "key=val" and returns +// a string map where the map index is the key and points to the value +func ParseAnnotations(options []string) (map[string]string, error) { + annotations := make(map[string]string) + for _, annotationSpec := range options { + key, val, hasVal := strings.Cut(annotationSpec, "=") + if !hasVal { + return nil, fmt.Errorf("no value given for annotation %q", key) + } + annotations[key] = val + } + return annotations, nil +} diff --git a/pkg/libartifact/store/store.go b/pkg/libartifact/store/store.go index c33e17d9ef..fff26cb10d 100644 --- a/pkg/libartifact/store/store.go +++ b/pkg/libartifact/store/store.go @@ -8,6 +8,7 @@ import ( "errors" "fmt" "io" + "maps" "net/http" "os" "path/filepath" @@ -160,7 +161,8 @@ func (as ArtifactStore) Push(ctx context.Context, src, dest string, opts libimag // Add takes one or more local files and adds them to the local artifact store. The empty // string input is for possible custom artifact types. -func (as ArtifactStore) Add(ctx context.Context, dest string, paths []string, _ string) (*digest.Digest, error) { +func (as ArtifactStore) Add(ctx context.Context, dest string, paths []string, options *libartTypes.AddOptions) (*digest.Digest, error) { + annots := maps.Clone(options.Annotations) if len(dest) == 0 { return nil, ErrEmptyArtifactName } @@ -191,6 +193,13 @@ func (as ArtifactStore) Add(ctx context.Context, dest string, paths []string, _ defer imageDest.Close() for _, path := range paths { + // currently we don't allow override of the filename ; if a user requirement emerges, + // we could seemingly accommodate but broadens possibilities of something bad happening + // for things like `artifact extract` + if _, hasTitle := options.Annotations[specV1.AnnotationTitle]; hasTitle { + return nil, fmt.Errorf("cannot override filename with %s annotation", specV1.AnnotationTitle) + } + // get the new artifact into the local store newBlobDigest, newBlobSize, err := layout.PutBlobFromLocalFile(ctx, imageDest, path) if err != nil { @@ -200,14 +209,16 @@ func (as ArtifactStore) Add(ctx context.Context, dest string, paths []string, _ if err != nil { return nil, err } - newArtifactAnnotations := map[string]string{} - newArtifactAnnotations[specV1.AnnotationTitle] = filepath.Base(path) + + annots[specV1.AnnotationTitle] = filepath.Base(path) + newLayer := specV1.Descriptor{ MediaType: detectedType, Digest: newBlobDigest, Size: newBlobSize, - Annotations: newArtifactAnnotations, + Annotations: annots, } + artifactManifestLayers = append(artifactManifestLayers, newLayer) } @@ -215,11 +226,12 @@ func (as ArtifactStore) Add(ctx context.Context, dest string, paths []string, _ Versioned: specs.Versioned{SchemaVersion: 2}, MediaType: specV1.MediaTypeImageManifest, // TODO This should probably be configurable once the CLI is capable - ArtifactType: "", - Config: specV1.DescriptorEmptyJSON, - Layers: artifactManifestLayers, + Config: specV1.DescriptorEmptyJSON, + Layers: artifactManifestLayers, } + artifactManifest.ArtifactType = options.ArtifactType + rawData, err := json.Marshal(artifactManifest) if err != nil { return nil, err diff --git a/pkg/libartifact/types/config.go b/pkg/libartifact/types/config.go index c52d677942..c458e646a6 100644 --- a/pkg/libartifact/types/config.go +++ b/pkg/libartifact/types/config.go @@ -3,3 +3,9 @@ package types // GetArtifactOptions is a struct containing options that for obtaining artifacts. // It is meant for future growth or changes required without wacking the API type GetArtifactOptions struct{} + +// AddOptions are additional descriptors of an artifact file +type AddOptions struct { + Annotations map[string]string `json:"annotations,omitempty"` + ArtifactType string `json:",omitempty"` +} diff --git a/test/e2e/artifact_test.go b/test/e2e/artifact_test.go index 13deb8589a..b54747433c 100644 --- a/test/e2e/artifact_test.go +++ b/test/e2e/artifact_test.go @@ -67,6 +67,31 @@ var _ = Describe("Podman artifact", func() { Expect(addAgain.ErrorToString()).To(Equal(fmt.Sprintf("Error: artifact %s already exists", artifact1Name))) }) + It("podman artifact add with options", func() { + artifact1Name := "localhost/test/artifact1" + artifact1File, err := createArtifactFile(1024) + Expect(err).ToNot(HaveOccurred()) + + artifactType := "octet/foobar" + annotation1 := "color=blue" + annotation2 := "flavor=lemon" + + podmanTest.PodmanExitCleanly([]string{"artifact", "add", "--type", artifactType, "--annotation", annotation1, "--annotation", annotation2, artifact1Name, artifact1File}...) + inspectSingleSession := podmanTest.PodmanExitCleanly([]string{"artifact", "inspect", artifact1Name}...) + a := libartifact.Artifact{} + err = json.Unmarshal([]byte(inspectSingleSession.OutputToString()), &a) + Expect(err).ToNot(HaveOccurred()) + Expect(a.Name).To(Equal(artifact1Name)) + Expect(a.Manifests[0].ArtifactType).To(Equal(artifactType)) + Expect(a.Manifests[0].Layers[0].Annotations["color"]).To(Equal("blue")) + Expect(a.Manifests[0].Layers[0].Annotations["flavor"]).To(Equal("lemon")) + + failSession := podmanTest.Podman([]string{"artifact", "add", "--annotation", "org.opencontainers.image.title=foobar", "foobar", artifact1File}) + failSession.WaitWithDefaultTimeout() + Expect(failSession).Should(Exit(125)) + Expect(failSession.ErrorToString()).Should(Equal("Error: cannot override filename with org.opencontainers.image.title annotation")) + }) + It("podman artifact add multiple", func() { artifact1File1, err := createArtifactFile(1024) Expect(err).ToNot(HaveOccurred()) From 9e83191c8f52de34998fb2fb29e727d957178a1f Mon Sep 17 00:00:00 2001 From: Brent Baude Date: Fri, 31 Jan 2025 08:12:50 -0600 Subject: [PATCH 24/58] Add --no-trunc to artifact ls added a --no-trunc flag to artifact ls, which follows what images has done. by default now, the ls output will have the shortened 12 character digest. the --no-trunc will output the full digest. Signed-off-by: Brent Baude --- cmd/podman/artifact/list.go | 15 +++++++++++---- docs/source/markdown/.gitignore | 1 + docs/source/markdown/options/no-trunc.md | 7 +++++++ ...act-ls.1.md => podman-artifact-ls.1.md.in} | 19 +++++++++++++------ docs/source/markdown/podman-images.1.md.in | 4 +--- test/e2e/artifact_test.go | 14 +++++++++++++- 6 files changed, 46 insertions(+), 14 deletions(-) create mode 100644 docs/source/markdown/options/no-trunc.md rename docs/source/markdown/{podman-artifact-ls.1.md => podman-artifact-ls.1.md.in} (74%) diff --git a/cmd/podman/artifact/list.go b/cmd/podman/artifact/list.go index e9ad56542b..de15adce91 100644 --- a/cmd/podman/artifact/list.go +++ b/cmd/podman/artifact/list.go @@ -31,7 +31,8 @@ var ( ) type listFlagType struct { - format string + format string + noTrunc bool } type artifactListOutput struct { @@ -54,6 +55,7 @@ func init() { formatFlagName := "format" flags.StringVar(&listFlag.format, formatFlagName, defaultArtifactListOutputFormat, "Format volume output using JSON or a Go template") _ = listCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(&artifactListOutput{})) + flags.BoolVar(&listFlag.noTrunc, "no-trunc", false, "Do not truncate output") } func list(cmd *cobra.Command, _ []string) error { @@ -95,10 +97,15 @@ func outputTemplate(cmd *cobra.Command, lrs []*entities.ArtifactListReport) erro if err != nil { return err } - // TODO when we default to shorter ids, i would foresee a switch - // like images that will show the full ids. + + artifactHash := artifactDigest.Encoded()[0:12] + // If the user does not want truncated hashes + if listFlag.noTrunc { + artifactHash = artifactDigest.Encoded() + } + artifacts = append(artifacts, artifactListOutput{ - Digest: artifactDigest.Encoded(), + Digest: artifactHash, Repository: named.Name(), Size: units.HumanSize(float64(lr.Artifact.TotalSizeBytes())), Tag: tag, diff --git a/docs/source/markdown/.gitignore b/docs/source/markdown/.gitignore index 8e05f6967f..3dd3b2e7d4 100644 --- a/docs/source/markdown/.gitignore +++ b/docs/source/markdown/.gitignore @@ -1,4 +1,5 @@ podman-artifact-add.1.md +podman-artifact-ls.1.md podman-artifact-pull.1.md podman-artifact-push.1.md podman-attach.1.md diff --git a/docs/source/markdown/options/no-trunc.md b/docs/source/markdown/options/no-trunc.md new file mode 100644 index 0000000000..887893934d --- /dev/null +++ b/docs/source/markdown/options/no-trunc.md @@ -0,0 +1,7 @@ +####> This option file is used in: +####> podman artifact ls, images +####> If file is edited, make sure the changes +####> are applicable to all of those. +#### **--no-trunc** + +Do not truncate the output (default *false*). diff --git a/docs/source/markdown/podman-artifact-ls.1.md b/docs/source/markdown/podman-artifact-ls.1.md.in similarity index 74% rename from docs/source/markdown/podman-artifact-ls.1.md rename to docs/source/markdown/podman-artifact-ls.1.md.in index 720c1dec36..585b51a8d0 100644 --- a/docs/source/markdown/podman-artifact-ls.1.md +++ b/docs/source/markdown/podman-artifact-ls.1.md.in @@ -29,23 +29,30 @@ Print results with a Go template. | .Tag | Tag of the artifact name | +@@option no-trunc ## EXAMPLES List artifacts in the local store ``` $ podman artifact ls -REPOSITORY TAG DIGEST SIZE -quay.io/artifact/foobar1 latest ab609fad386df1433f461b0643d9cf575560baf633809dcc9c190da6cc3a3c29 2.097GB -quay.io/artifact/foobar2 special cd734b558ceb8ccc0281ca76530e1dea1eb479407d3163f75fb601bffb6f73d0 12.58MB - +REPOSITORY TAG DIGEST SIZE +quay.io/artifact/foobar1 latest ab609fad386d 2.097GB +quay.io/artifact/foobar2 special cd734b558ceb 12.58MB +``` +List artifacts in the local store without truncating the digest ``` +REPOSITORY TAG DIGEST SIZE +quay.io/artifact/foobar1 latest ab609fad386df1433f461b0643d9cf575560baf633809dcc9c190da6cc3a3c29 2.097GB +quay.io/artifact/foobar2 special cd734b558ceb8ccc0281ca76530e1dea1eb479407d3163f75fb601bffb6f73d0 12.58MB +``` + List artifact digests and size using a --format ``` $ podman artifact ls --format "{{.Digest}} {{.Size}}" -ab609fad386df1433f461b0643d9cf575560baf633809dcc9c190da6cc3a3c29 2.097GB -cd734b558ceb8ccc0281ca76530e1dea1eb479407d3163f75fb601bffb6f73d0 12.58MB +ab609fad386d 2.097GB +cd734b558ceb 12.58MB ``` diff --git a/docs/source/markdown/podman-images.1.md.in b/docs/source/markdown/podman-images.1.md.in index fda6af0479..6c26107105 100644 --- a/docs/source/markdown/podman-images.1.md.in +++ b/docs/source/markdown/podman-images.1.md.in @@ -106,9 +106,7 @@ Valid placeholders for the Go template are listed below: Display the history of image names. If an image gets re-tagged or untagged, then the image name history gets prepended (latest image first). This is especially useful when undoing a tag operation or an image does not contain any name because it has been untagged. -#### **--no-trunc** - -Do not truncate the output (default *false*). +@@option no-trunc @@option noheading diff --git a/test/e2e/artifact_test.go b/test/e2e/artifact_test.go index b54747433c..7c74e89a5b 100644 --- a/test/e2e/artifact_test.go +++ b/test/e2e/artifact_test.go @@ -22,7 +22,7 @@ var _ = Describe("Podman artifact", func() { artifact1File, err := createArtifactFile(4192) Expect(err).ToNot(HaveOccurred()) artifact1Name := "localhost/test/artifact1" - podmanTest.PodmanExitCleanly([]string{"artifact", "add", artifact1Name, artifact1File}...) + add1 := podmanTest.PodmanExitCleanly([]string{"artifact", "add", artifact1Name, artifact1File}...) artifact2File, err := createArtifactFile(10240) Expect(err).ToNot(HaveOccurred()) @@ -43,6 +43,18 @@ var _ = Describe("Podman artifact", func() { // Make sure the names are what we expect Expect(output).To(ContainElement(artifact1Name)) Expect(output).To(ContainElement(artifact2Name)) + + // Check default digest length (should be 12) + defaultFormatSession := podmanTest.PodmanExitCleanly([]string{"artifact", "ls", "--format", "{{.Digest}}"}...) + defaultOutput := defaultFormatSession.OutputToStringArray()[0] + Expect(defaultOutput).To(HaveLen(12)) + + // Check with --no-trunc and verify the len of the digest is the same as the len what was returned when the artifact + // was added + noTruncSession := podmanTest.PodmanExitCleanly([]string{"artifact", "ls", "--no-trunc", "--format", "{{.Digest}}"}...) + truncOutput := noTruncSession.OutputToStringArray()[0] + Expect(truncOutput).To(HaveLen(len(add1.OutputToString()))) + }) It("podman artifact simple add", func() { From 522f9de9e3af1a224c714d89fa72d80b1b388789 Mon Sep 17 00:00:00 2001 From: Brent Baude Date: Mon, 3 Feb 2025 10:02:17 -0600 Subject: [PATCH 25/58] Add --noheading to artifact ls like images and containers, it could be handy to have a --noheading option that removes the headings on the output. Signed-off-by: Brent Baude --- cmd/podman/artifact/list.go | 8 +++++--- docs/source/markdown/options/noheading.md | 2 +- docs/source/markdown/podman-artifact-ls.1.md.in | 11 ++++++++++- test/e2e/artifact_test.go | 6 ++++++ 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/cmd/podman/artifact/list.go b/cmd/podman/artifact/list.go index de15adce91..e2bd843ff6 100644 --- a/cmd/podman/artifact/list.go +++ b/cmd/podman/artifact/list.go @@ -31,8 +31,9 @@ var ( ) type listFlagType struct { - format string - noTrunc bool + format string + noHeading bool + noTrunc bool } type artifactListOutput struct { @@ -55,6 +56,7 @@ func init() { formatFlagName := "format" flags.StringVar(&listFlag.format, formatFlagName, defaultArtifactListOutputFormat, "Format volume output using JSON or a Go template") _ = listCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(&artifactListOutput{})) + flags.BoolVarP(&listFlag.noHeading, "noheading", "n", false, "Do not print column headings") flags.BoolVar(&listFlag.noTrunc, "no-trunc", false, "Do not truncate output") } @@ -132,7 +134,7 @@ func outputTemplate(cmd *cobra.Command, lrs []*entities.ArtifactListReport) erro return err } - if rpt.RenderHeaders { + if rpt.RenderHeaders && !listFlag.noHeading { if err := rpt.Execute(headers); err != nil { return fmt.Errorf("failed to write report column headers: %w", err) } diff --git a/docs/source/markdown/options/noheading.md b/docs/source/markdown/options/noheading.md index c07212a3b8..623d21180a 100644 --- a/docs/source/markdown/options/noheading.md +++ b/docs/source/markdown/options/noheading.md @@ -1,5 +1,5 @@ ####> This option file is used in: -####> podman image trust, images, machine list, network ls, pod ps, secret ls, volume ls +####> podman artifact ls, image trust, images, machine list, network ls, pod ps, secret ls, volume ls ####> If file is edited, make sure the changes ####> are applicable to all of those. #### **--noheading**, **-n** diff --git a/docs/source/markdown/podman-artifact-ls.1.md.in b/docs/source/markdown/podman-artifact-ls.1.md.in index 585b51a8d0..552df70424 100644 --- a/docs/source/markdown/podman-artifact-ls.1.md.in +++ b/docs/source/markdown/podman-artifact-ls.1.md.in @@ -28,9 +28,10 @@ Print results with a Go template. | .Size | Size artifact in human readable units | | .Tag | Tag of the artifact name | - @@option no-trunc +@@option noheading + ## EXAMPLES List artifacts in the local store @@ -43,11 +44,19 @@ quay.io/artifact/foobar2 special cd734b558ceb 12.58MB List artifacts in the local store without truncating the digest ``` +$ podman artifact ls --no-trunc REPOSITORY TAG DIGEST SIZE quay.io/artifact/foobar1 latest ab609fad386df1433f461b0643d9cf575560baf633809dcc9c190da6cc3a3c29 2.097GB quay.io/artifact/foobar2 special cd734b558ceb8ccc0281ca76530e1dea1eb479407d3163f75fb601bffb6f73d0 12.58MB ``` +List artifacts in the local store without the title header +``` +$ podman artifact ls --noheading +quay.io/artifact/foobar1 latest ab609fad386d 2.097GB +quay.io/artifact/foobar2 special cd734b558ceb 12.58MB +``` + List artifact digests and size using a --format ``` $ podman artifact ls --format "{{.Digest}} {{.Size}}" diff --git a/test/e2e/artifact_test.go b/test/e2e/artifact_test.go index 7c74e89a5b..eb9e9a6a10 100644 --- a/test/e2e/artifact_test.go +++ b/test/e2e/artifact_test.go @@ -55,6 +55,12 @@ var _ = Describe("Podman artifact", func() { truncOutput := noTruncSession.OutputToStringArray()[0] Expect(truncOutput).To(HaveLen(len(add1.OutputToString()))) + // check with --noheading and verify the header is not present through a line count AND substring match + noHeaderSession := podmanTest.PodmanExitCleanly([]string{"artifact", "ls", "--noheading"}...) + noHeaderOutput := noHeaderSession.OutputToStringArray() + Expect(noHeaderOutput).To(HaveLen(2)) + Expect(noHeaderOutput).ToNot(ContainElement("REPOSITORY")) + }) It("podman artifact simple add", func() { From d5989990d5ede11aee0461ac7ff3225ce54b4299 Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Mon, 3 Feb 2025 19:23:08 +0100 Subject: [PATCH 26/58] test/e2e: improve write/removeConf() First use proper ginkgo error handling to ensure errors are actually reported and fail the test. Mark it as helper function to have better stack traces. Then use a atomic write function to prevent issues with partial written files. I think this is causing CI flakes[1]. Lastly fix the file permissions, do not make it world writable and do not set the executable bit on the file. [1] https://api.cirrus-ci.com/v1/artifact/task/5985244932734976/html/int-podman-fedora-41-root-host-sqlite.log.html#t--Podman-network-podman-network-ID-test--1 Signed-off-by: Paul Holzinger --- test/e2e/common_test.go | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go index 898efbc889..af9d523be7 100644 --- a/test/e2e/common_test.go +++ b/test/e2e/common_test.go @@ -28,6 +28,7 @@ import ( "github.com/containers/podman/v5/pkg/inspect" . "github.com/containers/podman/v5/test/utils" "github.com/containers/podman/v5/utils" + "github.com/containers/storage/pkg/ioutils" "github.com/containers/storage/pkg/lockfile" "github.com/containers/storage/pkg/reexec" "github.com/containers/storage/pkg/stringid" @@ -1187,19 +1188,21 @@ func (p *PodmanTestIntegration) makeOptions(args []string, options PodmanExecOpt } func writeConf(conf []byte, confPath string) { - if _, err := os.Stat(filepath.Dir(confPath)); os.IsNotExist(err) { - if err := os.MkdirAll(filepath.Dir(confPath), 0o777); err != nil { - GinkgoWriter.Println(err) - } - } - if err := os.WriteFile(confPath, conf, 0o777); err != nil { - GinkgoWriter.Println(err) - } + GinkgoHelper() + err := os.MkdirAll(filepath.Dir(confPath), 0o755) + Expect(err).ToNot(HaveOccurred()) + + err = ioutils.AtomicWriteFile(confPath, conf, 0o644) + Expect(err).ToNot(HaveOccurred()) } func removeConf(confPath string) { - if err := os.Remove(confPath); err != nil { - GinkgoWriter.Println(err) + GinkgoHelper() + err := os.Remove(confPath) + // Network remove test will remove the config and then this can fail. + // If the config does not exists no reason to hard error here. + if !errors.Is(err, os.ErrNotExist) { + Expect(err).ToNot(HaveOccurred()) } } From 141eae99b85181277a05ac586089cbd25052c698 Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Mon, 3 Feb 2025 12:18:16 +0100 Subject: [PATCH 27/58] artifact: only allow single manifest Allowing for multiple manifest per artifact just makes the code and cli design harder to work with it. It is not clear how mounting, extracting or edit on a multi manifest artifact should have worked. A single manifest should make the code much easier to work with. Signed-off-by: Paul Holzinger --- pkg/libartifact/artifact.go | 38 ++++++++++++------------------ pkg/libartifact/store/store.go | 42 +++++++++++----------------------- test/e2e/artifact_test.go | 12 ++++------ 3 files changed, 31 insertions(+), 61 deletions(-) diff --git a/pkg/libartifact/artifact.go b/pkg/libartifact/artifact.go index 326ea72f2c..7d8304e533 100644 --- a/pkg/libartifact/artifact.go +++ b/pkg/libartifact/artifact.go @@ -11,17 +11,17 @@ import ( ) type Artifact struct { - Manifests []manifest.OCI1 - Name string + // Manifest is the OCI manifest for the artifact with the name. + // In a valid artifact the Manifest is guaranteed to not be nil. + Manifest *manifest.OCI1 + Name string } // TotalSizeBytes returns the total bytes of the all the artifact layers func (a *Artifact) TotalSizeBytes() int64 { var s int64 - for _, artifact := range a.Manifests { - for _, layer := range artifact.Layers { - s += layer.Size - } + for _, layer := range a.Manifest.Layers { + s += layer.Size } return s } @@ -45,13 +45,7 @@ func (a *Artifact) SetName(name string) { } func (a *Artifact) GetDigest() (*digest.Digest, error) { - if len(a.Manifests) > 1 { - return nil, fmt.Errorf("not supported: multiple manifests found in artifact") - } - if len(a.Manifests) < 1 { - return nil, fmt.Errorf("not supported: no manifests found in artifact") - } - b, err := json.Marshal(a.Manifests[0]) + b, err := json.Marshal(a.Manifest) if err != nil { return nil, err } @@ -72,17 +66,13 @@ func (al ArtifactList) GetByNameOrDigest(nameOrDigest string) (*Artifact, bool, } // Before giving up, check by digest for _, artifact := range al { - // TODO Here we have to assume only a single manifest for the artifact; this will - // need to evolve - if len(artifact.Manifests) > 0 { - artifactDigest, err := artifact.GetDigest() - if err != nil { - return nil, false, err - } - // If the artifact's digest matches or is a prefix of ... - if artifactDigest.Encoded() == nameOrDigest || strings.HasPrefix(artifactDigest.Encoded(), nameOrDigest) { - return artifact, true, nil - } + artifactDigest, err := artifact.GetDigest() + if err != nil { + return nil, false, err + } + // If the artifact's digest matches or is a prefix of ... + if artifactDigest.Encoded() == nameOrDigest || strings.HasPrefix(artifactDigest.Encoded(), nameOrDigest) { + return artifact, true, nil } } return nil, false, fmt.Errorf("no artifact found with name or digest of %s", nameOrDigest) diff --git a/pkg/libartifact/store/store.go b/pkg/libartifact/store/store.go index fff26cb10d..8a0364c247 100644 --- a/pkg/libartifact/store/store.go +++ b/pkg/libartifact/store/store.go @@ -299,13 +299,13 @@ func (as ArtifactStore) getArtifacts(ctx context.Context, _ *libartTypes.GetArti if err != nil { return nil, err } - manifests, err := getManifests(ctx, imgSrc, nil) + manifest, err := getManifest(ctx, imgSrc) imgSrc.Close() if err != nil { return nil, err } artifact := libartifact.Artifact{ - Manifests: manifests, + Manifest: manifest, } if val, ok := l.ManifestDescriptor.Annotations[specV1.AnnotationRefName]; ok { artifact.SetName(val) @@ -316,41 +316,25 @@ func (as ArtifactStore) getArtifacts(ctx context.Context, _ *libartTypes.GetArti return al, nil } -// getManifests takes an imgSrc and starting digest (nil means "top") and collects all the manifests "under" -// it. this func calls itself recursively with a new startingDigest assuming that we are dealing with -// an index list -func getManifests(ctx context.Context, imgSrc types.ImageSource, startingDigest *digest.Digest) ([]manifest.OCI1, error) { - var ( - manifests []manifest.OCI1 - ) - b, manifestType, err := imgSrc.GetManifest(ctx, startingDigest) +// getManifest takes an imgSrc and returns the manifest for the imgSrc. +// A OCI index list is not supported and will return an error. +func getManifest(ctx context.Context, imgSrc types.ImageSource) (*manifest.OCI1, error) { + b, manifestType, err := imgSrc.GetManifest(ctx, nil) if err != nil { return nil, err } - // this assumes that there are only single, and multi-images - if !manifest.MIMETypeIsMultiImage(manifestType) { - // these are the keepers - mani, err := manifest.OCI1FromManifest(b) - if err != nil { - return nil, err - } - manifests = append(manifests, *mani) - return manifests, nil + // We only support a single flat manifest and not an oci index list + if manifest.MIMETypeIsMultiImage(manifestType) { + return nil, fmt.Errorf("manifest %q is index list", imgSrc.Reference().StringWithinTransport()) } - // We are dealing with an oci index list - maniList, err := manifest.OCI1IndexFromManifest(b) + + // parse the single manifest + mani, err := manifest.OCI1FromManifest(b) if err != nil { return nil, err } - for _, m := range maniList.Manifests { - iterManifests, err := getManifests(ctx, imgSrc, &m.Digest) - if err != nil { - return nil, err - } - manifests = append(manifests, iterManifests...) - } - return manifests, nil + return mani, nil } func createEmptyStanza(path string) error { diff --git a/test/e2e/artifact_test.go b/test/e2e/artifact_test.go index eb9e9a6a10..c3cfe504eb 100644 --- a/test/e2e/artifact_test.go +++ b/test/e2e/artifact_test.go @@ -100,9 +100,9 @@ var _ = Describe("Podman artifact", func() { err = json.Unmarshal([]byte(inspectSingleSession.OutputToString()), &a) Expect(err).ToNot(HaveOccurred()) Expect(a.Name).To(Equal(artifact1Name)) - Expect(a.Manifests[0].ArtifactType).To(Equal(artifactType)) - Expect(a.Manifests[0].Layers[0].Annotations["color"]).To(Equal("blue")) - Expect(a.Manifests[0].Layers[0].Annotations["flavor"]).To(Equal("lemon")) + Expect(a.Manifest.ArtifactType).To(Equal(artifactType)) + Expect(a.Manifest.Layers[0].Annotations["color"]).To(Equal("blue")) + Expect(a.Manifest.Layers[0].Annotations["flavor"]).To(Equal("lemon")) failSession := podmanTest.Podman([]string{"artifact", "add", "--annotation", "org.opencontainers.image.title=foobar", "foobar", artifact1File}) failSession.WaitWithDefaultTimeout() @@ -128,11 +128,7 @@ var _ = Describe("Podman artifact", func() { Expect(err).ToNot(HaveOccurred()) Expect(a.Name).To(Equal(artifact1Name)) - var layerCount int - for _, layer := range a.Manifests { - layerCount += len(layer.Layers) - } - Expect(layerCount).To(Equal(2)) + Expect(a.Manifest.Layers).To(HaveLen(2)) }) It("podman artifact push and pull", func() { From 02eac2979c68a3b48ac726e20d7b9df2e64dc1ae Mon Sep 17 00:00:00 2001 From: Ashley Cui Date: Thu, 5 Dec 2024 23:05:19 -0500 Subject: [PATCH 28/58] Add BuildOrigin field to podman info BuildOrigin is a field that can be set at build time by packagers. This helps us trace how and where the binary was built and installed from, allowing us to see if the issue is due to a specfic installation or a general podman bug. This field shows up in podman version and in podman info when populated. Note that podman info has a new field, Client, that only appears when running podman info using the remote client. Automatically set the BuildOrigin field when building the macOS pkginstaller to pkginstaller. Usage: make podman-remote BUILD_ORIGIN="mypackaging" Signed-off-by: Ashley Cui --- Makefile | 1 + cmd/podman/client.go | 14 +++++++------ cmd/podman/system/info.go | 22 ++++++++++++++++---- cmd/podman/system/version.go | 2 ++ contrib/pkginstaller/package.sh | 3 ++- libpod/define/version.go | 37 +++++++++++++++++++-------------- test/e2e/info_test.go | 12 +++++++++++ 7 files changed, 64 insertions(+), 27 deletions(-) diff --git a/Makefile b/Makefile index 7c85d61dd8..49b3ff3831 100644 --- a/Makefile +++ b/Makefile @@ -119,6 +119,7 @@ GOFLAGS ?= -trimpath LDFLAGS_PODMAN ?= \ $(if $(GIT_COMMIT),-X $(LIBPOD)/define.gitCommit=$(GIT_COMMIT),) \ $(if $(BUILD_INFO),-X $(LIBPOD)/define.buildInfo=$(BUILD_INFO),) \ + $(if $(BUILD_ORIGIN),-X $(LIBPOD)/define.buildOrigin=$(BUILD_ORIGIN),) \ -X $(LIBPOD)/config._installPrefix=$(PREFIX) \ -X $(LIBPOD)/config._etcDir=$(ETCDIR) \ -X $(PROJECT)/v5/pkg/systemd/quadlet._binDir=$(BINDIR) \ diff --git a/cmd/podman/client.go b/cmd/podman/client.go index b42a43520d..46c889b955 100644 --- a/cmd/podman/client.go +++ b/cmd/podman/client.go @@ -3,9 +3,10 @@ package main import "github.com/containers/podman/v5/libpod/define" type clientInfo struct { - OSArch string `json:"OS"` - Provider string `json:"provider"` - Version string `json:"version"` + OSArch string `json:"OS"` + Provider string `json:"provider"` + Version string `json:"version"` + BuildOrigin string `json:"buildOrigin,omitempty" yaml:",omitempty"` } func getClientInfo() (*clientInfo, error) { @@ -18,8 +19,9 @@ func getClientInfo() (*clientInfo, error) { return nil, err } return &clientInfo{ - OSArch: vinfo.OsArch, - Provider: p, - Version: vinfo.Version, + OSArch: vinfo.OsArch, + Provider: p, + Version: vinfo.Version, + BuildOrigin: vinfo.BuildOrigin, }, nil } diff --git a/cmd/podman/system/info.go b/cmd/podman/system/info.go index 071e2021ba..47c47ae539 100644 --- a/cmd/podman/system/info.go +++ b/cmd/podman/system/info.go @@ -45,6 +45,11 @@ var ( debug bool ) +type infoReport struct { + define.Info + Client *define.Version `json:",omitempty" yaml:",omitempty"` +} + func init() { registry.Commands = append(registry.Commands, registry.CliCommand{ Command: infoCommand, @@ -74,12 +79,21 @@ func info(cmd *cobra.Command, args []string) error { if err != nil { return err } + remote := registry.IsRemote() + info.Host.ServiceIsRemote = remote - info.Host.ServiceIsRemote = registry.IsRemote() + infoReport := infoReport{ + Info: *info, + } + + if remote { + clientVers, _ := define.GetVersion() + infoReport.Client = &clientVers + } switch { case report.IsJSON(inFormat): - b, err := json.MarshalIndent(info, "", " ") + b, err := json.MarshalIndent(infoReport, "", " ") if err != nil { return err } @@ -94,9 +108,9 @@ func info(cmd *cobra.Command, args []string) error { if err != nil { return err } - return rpt.Execute(info) + return rpt.Execute(infoReport) default: - b, err := yaml.Marshal(info) + b, err := yaml.Marshal(infoReport) if err != nil { return err } diff --git a/cmd/podman/system/version.go b/cmd/podman/system/version.go index 48ea151135..eb70b1ef72 100644 --- a/cmd/podman/system/version.go +++ b/cmd/podman/system/version.go @@ -97,6 +97,7 @@ API Version:\t{{.APIVersion}} Go Version:\t{{.GoVersion}} {{if .GitCommit -}}Git Commit:\t{{.GitCommit}}\n{{end -}} Built:\t{{.BuiltTime}} +{{if .BuildOrigin -}}Build Origin:\t{{.BuildOrigin}}\n{{end -}} OS/Arch:\t{{.OsArch}} {{- end}} @@ -108,6 +109,7 @@ API Version:\t{{.APIVersion}} Go Version:\t{{.GoVersion}} {{if .GitCommit -}}Git Commit:\t{{.GitCommit}}\n{{end -}} Built:\t{{.BuiltTime}} +{{if .BuildOrigin -}}Build Origin:\t{{.BuildOrigin}}\n{{end -}} OS/Arch:\t{{.OsArch}} {{- end}}{{- end}} ` diff --git a/contrib/pkginstaller/package.sh b/contrib/pkginstaller/package.sh index 42528c96c5..1b34001f6b 100755 --- a/contrib/pkginstaller/package.sh +++ b/contrib/pkginstaller/package.sh @@ -9,6 +9,7 @@ PRODUCTSIGN_IDENTITY=${PRODUCTSIGN_IDENTITY:-mock} NO_CODESIGN=${NO_CODESIGN:-0} HELPER_BINARIES_DIR="/opt/podman/bin" MACHINE_POLICY_JSON_DIR="/opt/podman/config" +BUILD_ORIGIN="pkginstaller" tmpBin="contrib/pkginstaller/tmp-bin" @@ -47,7 +48,7 @@ function build_podman() { } function build_podman_arch(){ - make -B GOARCH="$1" podman-remote HELPER_BINARIES_DIR="${HELPER_BINARIES_DIR}" + make -B GOARCH="$1" podman-remote HELPER_BINARIES_DIR="${HELPER_BINARIES_DIR}" BUILD_ORIGIN="${BUILD_ORIGIN}" make -B GOARCH="$1" podman-mac-helper mkdir -p "${tmpBin}" cp bin/darwin/podman "${tmpBin}/podman-$1" diff --git a/libpod/define/version.go b/libpod/define/version.go index 13a8fdb778..6832aeac38 100644 --- a/libpod/define/version.go +++ b/libpod/define/version.go @@ -16,18 +16,22 @@ var ( // BuildInfo is the time at which the binary was built // It will be populated by the Makefile. buildInfo string + // BuildOrigin is the packager of the binary. + // It will be populated at build-time. + buildOrigin string ) // Version is an output struct for API type Version struct { - APIVersion string - Version string - GoVersion string - GitCommit string - BuiltTime string - Built int64 - OsArch string - Os string + APIVersion string + Version string + GoVersion string + GitCommit string + BuiltTime string + Built int64 + BuildOrigin string `json:",omitempty" yaml:",omitempty"` + OsArch string + Os string } // GetVersion returns a VersionOutput struct for API and podman @@ -43,13 +47,14 @@ func GetVersion() (Version, error) { } } return Version{ - APIVersion: version.APIVersion[version.Libpod][version.CurrentAPI].String(), - Version: version.Version.String(), - GoVersion: runtime.Version(), - GitCommit: gitCommit, - BuiltTime: time.Unix(buildTime, 0).Format(time.ANSIC), - Built: buildTime, - OsArch: runtime.GOOS + "/" + runtime.GOARCH, - Os: runtime.GOOS, + APIVersion: version.APIVersion[version.Libpod][version.CurrentAPI].String(), + Version: version.Version.String(), + GoVersion: runtime.Version(), + GitCommit: gitCommit, + BuiltTime: time.Unix(buildTime, 0).Format(time.ANSIC), + Built: buildTime, + BuildOrigin: buildOrigin, + OsArch: runtime.GOOS + "/" + runtime.GOARCH, + Os: runtime.GOOS, }, nil } diff --git a/test/e2e/info_test.go b/test/e2e/info_test.go index 87c8902621..028ee8a6a1 100644 --- a/test/e2e/info_test.go +++ b/test/e2e/info_test.go @@ -291,4 +291,16 @@ var _ = Describe("Podman Info", func() { Expect(info).ToNot(ExitCleanly()) podmanTest.StartRemoteService() // Start service again so teardown runs clean }) + + It("Podman info: check client information", func() { + info := podmanTest.Podman([]string{"info", "--format", "{{ .Client }}"}) + info.WaitWithDefaultTimeout() + Expect(info).To(ExitCleanly()) + // client info should only appear when using the remote client + if IsRemote() { + Expect(info.OutputToString()).ToNot(Equal("")) + } else { + Expect(info.OutputToString()).To(Equal("")) + } + }) }) From 6c78bad0dd2aa9619a168d9e686010d9b3e66e97 Mon Sep 17 00:00:00 2001 From: Matt Heon Date: Tue, 4 Feb 2025 13:43:31 -0500 Subject: [PATCH 29/58] Update release notes for v5.4.0-rc3 Signed-off-by: Matt Heon --- RELEASE_NOTES.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index acfd7e0ea1..1d8b7d63ef 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -7,6 +7,7 @@ - The `--mount type=volume` option for the `podman run`, `podman create`, and `podman volume create` commands now supports a new option, `subpath=`, to make only a subset of the volume visible in the container ([#20661](https://github.com/containers/podman/issues/20661)). - The `--userns=keep-id` option for the `podman run`, `podman create`, and `podman pod create` commands now supports a new option, `--userns=keep-id:size=`, to configure the size of the user namespace ([#24387](https://github.com/containers/podman/issues/24837)). - The `podman kube play` command now supports Container Device Interface (CDI) devices ([#17833](https://github.com/containers/podman/issues/17833)). +- The `podman machine init` command now supports a new option, `--playbook`, to run an Ansible playbook in the created VM on first boot for initial configuration. - Quadlet `.pod` files now support a new field, `ShmSize`, to specify the size of the pod's shared SHM ([#22915](https://github.com/containers/podman/issues/22915)). - The `podman run`, `podman create`, and `podman pod create` commands now support a new option, `--hosts-file`, to define the base file used for `/etc/hosts` in the container. - The `podman run`, `podman create`, and `podman pod create` commands now support a new option, `--no-hostname`, which disables the creation of `/etc/hostname` in the container ([#25002](https://github.com/containers/podman/issues/25002)). @@ -23,6 +24,7 @@ ### Changes - Podman now passes container hostnames to Netavark, which will use them for any DHCP requests for the container. - Partial pulls of `zstd:chunked` images now only happen for images that have a `RootFS.DiffID` entry in the image's OCI config JSON, and require the layer contents to match. This resolves issues with image ID ambiguity when partial pulls were enabled. +- Packagers can now set the `BUILD_ORIGIN` environment variable when building podman from the `Makefile`. This provides information on who built the Podman binary, and is displayed in `podman version` and `podman info`. This will help upstream bug reports, allowing maintainers to trace how and where the binary was built and installed from. ### Bugfixes - Fixed a bug where `podman machine` VMs on WSL could fail to start when using usermode networking could fail to start due to a port conflict ([#20327](https://github.com/containers/podman/issues/20327)). @@ -46,13 +48,20 @@ - Fixed a bug where the output of `podman inspect` on containers did not include the ID of the network the container was joined to, improving Docker compatibility ([#24910](https://github.com/containers/podman/issues/24910)). - Fixed a bug where containers created with the remote API incorrectly included a create command ([#25026](https://github.com/containers/podman/issues/25026)). - Fixed a bug where it was possible to specify the `libkrun` backend for VMs on Intel Macs (`libkrun` only supports Arm systems). +- Fixed a bug where `libkrun` and `applehv` VMs from `podman machine` could be started at the same time on Macs ([#25112](https://github.com/containers/podman/issues/25112)). +- Fixed a bug where `podman exec` commands could not detach from the exec session using the detach keys ([#24895](https://github.com/containers/podman/issues/24895)). ### API - The Compat and Libpod Build APIs for Images now support a new query parameter, `nohosts`, which (when set to true) does not create `/etc/hosts` in the image when building. +- Fixed a bug where the Compat Create API for Containers did not honor CDI devices, preventing (among other things) the use of GPUs with `docker compose` ([#19338](https://github.com/containers/podman/issues/19338)). ### Misc - The Docker alias script has been fixed to better handle variable substitution. - Fixed a bug where `podman-restart.service` functioned incorrectly when no containers were present. +- Updated Buildah to v1.39.0 +- Updated the containers/common library to v0.62.0 +- Updated the containers/storage library to v1.57.1 +- Updated the containers/image library to v5.34.0 ## 5.3.2 ### Security From ad54787bf09265e12d446871d2c09809a59d8f4a Mon Sep 17 00:00:00 2001 From: Matt Heon Date: Tue, 4 Feb 2025 15:17:47 -0500 Subject: [PATCH 30/58] Bump to v5.4.0-rc3 Signed-off-by: Matt Heon --- version/rawversion/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version/rawversion/version.go b/version/rawversion/version.go index a2f65f18d6..4ccf7415a1 100644 --- a/version/rawversion/version.go +++ b/version/rawversion/version.go @@ -7,4 +7,4 @@ package rawversion // // NOTE: remember to bump the version at the top of the top-level README.md // file when this is bumped. -const RawVersion = "5.4.0-dev" +const RawVersion = "5.4.0-rc3" From 0f01f00f035c2c0ea71a722c4a124ffb96b86598 Mon Sep 17 00:00:00 2001 From: Matt Heon Date: Tue, 4 Feb 2025 15:18:49 -0500 Subject: [PATCH 31/58] Bump to v5.4.0-dev Signed-off-by: Matt Heon --- version/rawversion/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version/rawversion/version.go b/version/rawversion/version.go index 4ccf7415a1..a2f65f18d6 100644 --- a/version/rawversion/version.go +++ b/version/rawversion/version.go @@ -7,4 +7,4 @@ package rawversion // // NOTE: remember to bump the version at the top of the top-level README.md // file when this is bumped. -const RawVersion = "5.4.0-rc3" +const RawVersion = "5.4.0-dev" From fa263d2cc9147943652e1d50783ba1173d03d456 Mon Sep 17 00:00:00 2001 From: Matt Heon Date: Wed, 5 Feb 2025 08:16:17 -0500 Subject: [PATCH 32/58] Set Cirrus DEST_BRANCH appropriately to fix CI Signed-off-by: Matt Heon --- .cirrus.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cirrus.yml b/.cirrus.yml index 2061952b2b..5c7545ea8e 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -6,7 +6,7 @@ env: #### Global variables used for all tasks #### # Name of the ultimate destination branch for this CI run, PR or post-merge. - DEST_BRANCH: "main" + DEST_BRANCH: "v5.4" # Sane (default) value for GOPROXY and GOSUMDB. GOPROXY: "https://proxy.golang.org,direct" GOSUMDB: "sum.golang.org" From d280feb96cbd2af651fac5b2f5e76de0df0685ea Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Thu, 6 Feb 2025 13:49:51 +0100 Subject: [PATCH 33/58] rootless: fix hang on s390x avoid using the glibc fork() function after using directly the clone() syscall, as it confuses glibc causing the fork() to hang in some cases. The issue has been observed only on s390x, and the fix was confirmed in the issue discussion. Closes: https://github.com/containers/podman/issues/25184 Signed-off-by: Giuseppe Scrivano --- pkg/rootless/rootless_linux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/rootless/rootless_linux.c b/pkg/rootless/rootless_linux.c index 4f71d49e5c..3d74af6a6c 100644 --- a/pkg/rootless/rootless_linux.c +++ b/pkg/rootless/rootless_linux.c @@ -658,7 +658,7 @@ create_pause_process (const char *pause_pid_file_path, char **argv) if (pipe (p) < 0) return -1; - pid = fork (); + pid = syscall_clone (SIGCHLD, NULL); if (pid < 0) { close (p[0]); @@ -689,7 +689,7 @@ create_pause_process (const char *pause_pid_file_path, char **argv) close (p[0]); setsid (); - pid = fork (); + pid = syscall_clone (SIGCHLD, NULL); if (pid < 0) _exit (EXIT_FAILURE); From 18249e10c1d369aae36b7327a478124d4d66ccbd Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Thu, 6 Feb 2025 18:39:33 +0100 Subject: [PATCH 34/58] Makefile: escape BUILD_ORIGIN properly When trying to pass a string with spaces that broke the go command cli parsing, the full argument must be put in quotes to avoid escaping issues. Signed-off-by: Paul Holzinger --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 49b3ff3831..079c180777 100644 --- a/Makefile +++ b/Makefile @@ -119,7 +119,7 @@ GOFLAGS ?= -trimpath LDFLAGS_PODMAN ?= \ $(if $(GIT_COMMIT),-X $(LIBPOD)/define.gitCommit=$(GIT_COMMIT),) \ $(if $(BUILD_INFO),-X $(LIBPOD)/define.buildInfo=$(BUILD_INFO),) \ - $(if $(BUILD_ORIGIN),-X $(LIBPOD)/define.buildOrigin=$(BUILD_ORIGIN),) \ + $(if $(BUILD_ORIGIN),-X "$(LIBPOD)/define.buildOrigin=$(BUILD_ORIGIN)",) \ -X $(LIBPOD)/config._installPrefix=$(PREFIX) \ -X $(LIBPOD)/config._etcDir=$(ETCDIR) \ -X $(PROJECT)/v5/pkg/systemd/quadlet._binDir=$(BINDIR) \ From 6218d42ed64e66ac1d0bbe4e7e883e9eb0484142 Mon Sep 17 00:00:00 2001 From: Lokesh Mandvekar Date: Wed, 5 Feb 2025 20:12:12 +0530 Subject: [PATCH 35/58] RPM: cleanup macro defs The default `gobuild` macro on CentOS Stream 9 now includes support for `BUILDTAGS`. CentOS Stream envs now also define `_user_tmpfilesdir` macro by default. Both these definitions are no longer needed here. `libtrust_openssl` buildtag is also set in spec wherever relevant. Signed-off-by: Lokesh Mandvekar --- rpm/podman.spec | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/rpm/podman.spec b/rpm/podman.spec index 8e2635a304..303037ac6d 100644 --- a/rpm/podman.spec +++ b/rpm/podman.spec @@ -7,21 +7,8 @@ %global debug_package %{nil} %endif -# RHEL's default %%gobuild macro doesn't account for the BUILDTAGS variable, so we -# set it separately here and do not depend on RHEL's go-[s]rpm-macros package -# until that's fixed. -# c9s bz: https://bugzilla.redhat.com/show_bug.cgi?id=2227328 -%if %{defined rhel} && 0%{?rhel} < 10 -%define gobuild(o:) go build -buildmode pie -compiler gc -tags="rpm_crashtraceback libtrust_openssl ${BUILDTAGS:-}" -ldflags "-linkmode=external -compressdwarf=false ${LDFLAGS:-} -B 0x$(head -c20 /dev/urandom|od -An -tx1|tr -d ' \\n') -extldflags '%__global_ldflags'" -a -v -x %{?**}; -%endif - %global gomodulesmode GO111MODULE=on -%if %{defined rhel} -# _user_tmpfiles.d currently undefined on rhel -%global _user_tmpfilesdir %{_datadir}/user-tmpfiles.d -%endif - %if %{defined fedora} %define build_with_btrfs 1 # qemu-system* isn't packageed for CentOS Stream / RHEL @@ -32,6 +19,11 @@ %define copr_build 1 %endif +# Only RHEL and CentOS Stream rpms are built with fips-enabled go compiler +%if %{defined rhel} +%define fips_enabled 1 +%endif + %global container_base_path github.com/containers %global container_base_url https://%{container_base_path} @@ -251,6 +243,14 @@ LDFLAGS="-X %{ld_libpod}/define.buildInfo=${SOURCE_DATE_EPOCH:-$(date +%s)} \ export BASEBUILDTAGS="seccomp exclude_graphdriver_devicemapper $(hack/systemd_tag.sh) $(hack/libsubid_tag.sh)" +# libtrust_openssl buildtag switches to using the FIPS-compatible func +# `ecdsa.HashSign`. +# Ref 1: https://github.com/golang-fips/go/blob/main/patches/015-add-hash-sign-verify.patch#L22 +# Ref 2: https://github.com/containers/libtrust/blob/main/ec_key_openssl.go#L23 +%if %{defined fips_enabled} +export BASEBUILDTAGS="$BASEBUILDTAGS libtrust_openssl" +%endif + # build %%{name} export BUILDTAGS="$BASEBUILDTAGS $(hack/btrfs_installed_tag.sh) $(hack/btrfs_tag.sh) $(hack/libdm_tag.sh)" %gobuild -o bin/%{name} ./cmd/%{name} From f34d6c76dbe697984fc7a2a0e4f294738c9a91e5 Mon Sep 17 00:00:00 2001 From: Lokesh Mandvekar Date: Mon, 10 Feb 2025 16:36:42 +0530 Subject: [PATCH 36/58] RPM: set buildOrigin in LDFLAG For Copr builds, it will mention the Copr info from where the rpm is installed. For non-copr builds, it will mention the value of the packager macro if set, and skip this field altogether if not. On local rpm builds, this shows: ``` Build Origin: Lokesh Mandvekar ``` On koji rpm builds, this shows: ``` Build Origin: Fedora Project ``` On copr rpm builds (for eg. rhcontainerbot/playground), this shows: ``` Build Origin: Copr: rhcontainerbot/playground ``` Signed-off-by: Lokesh Mandvekar --- rpm/podman.spec | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/rpm/podman.spec b/rpm/podman.spec index 303037ac6d..a1d41e6a3e 100644 --- a/rpm/podman.spec +++ b/rpm/podman.spec @@ -37,6 +37,12 @@ # podman-machine subpackage will be present only on these architectures %global machine_arches x86_64 aarch64 +%if %{defined copr_build} +%define build_origin Copr: %{?copr_username}/%{?copr_projectname} +%else +%define build_origin %{?packager} +%endif + Name: podman %if %{defined copr_build} Epoch: 102 @@ -234,6 +240,7 @@ export CGO_CFLAGS+=" -m64 -mtune=generic -fcf-protection=full" export GOPROXY=direct LDFLAGS="-X %{ld_libpod}/define.buildInfo=${SOURCE_DATE_EPOCH:-$(date +%s)} \ + -X "%{ld_libpod}/define.buildOrigin=%{build_origin}" \ -X %{ld_libpod}/config._installPrefix=%{_prefix} \ -X %{ld_libpod}/config._etcDir=%{_sysconfdir} \ -X %{ld_project}/pkg/systemd/quadlet._binDir=%{_bindir}" From 13ebc5860cbec2164725073148ea3ea1b2844cbb Mon Sep 17 00:00:00 2001 From: Lokesh Mandvekar Date: Mon, 10 Feb 2025 18:19:52 +0530 Subject: [PATCH 37/58] Update rpm/podman.spec Co-authored-by: Paul Holzinger Signed-off-by: Lokesh Mandvekar --- rpm/podman.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpm/podman.spec b/rpm/podman.spec index a1d41e6a3e..b6a60cedfa 100644 --- a/rpm/podman.spec +++ b/rpm/podman.spec @@ -240,7 +240,7 @@ export CGO_CFLAGS+=" -m64 -mtune=generic -fcf-protection=full" export GOPROXY=direct LDFLAGS="-X %{ld_libpod}/define.buildInfo=${SOURCE_DATE_EPOCH:-$(date +%s)} \ - -X "%{ld_libpod}/define.buildOrigin=%{build_origin}" \ + -X \"%{ld_libpod}/define.buildOrigin=%{build_origin}\" \ -X %{ld_libpod}/config._installPrefix=%{_prefix} \ -X %{ld_libpod}/config._etcDir=%{_sysconfdir} \ -X %{ld_project}/pkg/systemd/quadlet._binDir=%{_bindir}" From 3d917a395cf6b9654955c38dfc5797d443613773 Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Tue, 11 Feb 2025 12:17:11 +0100 Subject: [PATCH 38/58] docs: add v5.4 to API reference Signed-off-by: Paul Holzinger --- docs/source/Reference.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/source/Reference.rst b/docs/source/Reference.rst index 61dcc64dc1..3f84612907 100644 --- a/docs/source/Reference.rst +++ b/docs/source/Reference.rst @@ -7,6 +7,8 @@ Show the API documentation for version: * `latest (main branch) <_static/api.html>`_ +* `version 5.4 <_static/api.html?version=v5.4>`_ + * `version 5.3 <_static/api.html?version=v5.3>`_ * `version 5.2 <_static/api.html?version=v5.2>`_ From 2612e3c2334f8be84bab18828371a9cb4ce07d13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Rod=C3=A1k?= Date: Tue, 11 Feb 2025 11:15:02 +0100 Subject: [PATCH 39/58] Bump FreeBSD version to 13.4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Version 13.3 is EOL. See https://www.freebsd.org/releases/ Signed-off-by: Jan Rodák --- .cirrus.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cirrus.yml b/.cirrus.yml index 5c7545ea8e..5bd128b978 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -322,7 +322,7 @@ freebsd_alt_build_task: TEST_FLAVOR: "altbuild" ALT_NAME: 'FreeBSD Cross' freebsd_instance: - image_family: freebsd-13-3 + image_family: freebsd-13-4 setup_script: - pkg install -y gpgme bash go-md2man gmake gsed gnugrep go pkgconf zstd build_amd64_script: From 3d344ffd2673586f70abb8aee362cdbb2af1aa11 Mon Sep 17 00:00:00 2001 From: Matt Heon Date: Thu, 5 Dec 2024 08:35:36 -0500 Subject: [PATCH 40/58] In SQLite state, use defaults for empty-string checks As part of our database init, we perform a check of the current values for a few fields (graph driver, graph root, static dir, and a few more) to validate that Libpod is being started with a sane & sensible config, and the user's containers can actually be expected to work. Basically, we take the current runtime config and compare against values cached in the database from the first time Podman was run. We've had some issues with this logic before this year around symlink resolution, but this is a new edge case. Somehow, the database is being loaded with the empty string for some fields (at least graph driver) which is causing comparisons to fail because we will never compare against "" for those fields - we insert the default value instead, assuming we have one. Having a value of "" in the database largely invalidates the check so arguably we could just drop it, but what BoltDB did - and what SQLite does after this patch - is to use the default value for comparison instead of "". This should still catch some edge cases, and shouldn't be too harmful. What this does not do is identify or solve the reason that we are seeing the empty string in the database at all. From my read on the logic, it must mean that the graph driver is explicitly set to "" in the c/storage config at the time Podman is first run and I'm not precisely sure how that happens. Fixes #24738 Signed-off-by: Matt Heon --- libpod/sqlite_state.go | 24 ++++++++++++++++++++++++ test/system/005-info.bats | 23 +++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/libpod/sqlite_state.go b/libpod/sqlite_state.go index 1e979727d1..ea42f8e3e8 100644 --- a/libpod/sqlite_state.go +++ b/libpod/sqlite_state.go @@ -383,6 +383,30 @@ func (s *SQLiteState) ValidateDBConfig(runtime *Runtime) (defErr error) { return fmt.Errorf("retrieving DB config: %w", err) } + // Sometimes, for as-yet unclear reasons, the database value ends up set + // to the empty string. If it does, this evaluation is always going to + // fail, and libpod will be unusable. + // At this point, the check is effectively meaningless - we don't + // actually know the settings we should be checking against. The best + // thing we can do (and what BoltDB did in this case) is to compare + // against the default, on the assumption that is what was in use. + // TODO: We can't remove this code without breaking existing SQLite DBs + // that already have incorrect values in the database, but we should + // investigate why this is happening and try and prevent the creation of + // new databases with these garbage checks. + if graphRoot == "" { + logrus.Debugf("Database uses empty-string graph root, substituting default %q", storeOpts.GraphRoot) + graphRoot = storeOpts.GraphRoot + } + if runRoot == "" { + logrus.Debugf("Database uses empty-string run root, substituting default %q", storeOpts.RunRoot) + runRoot = storeOpts.RunRoot + } + if graphDriver == "" { + logrus.Debugf("Database uses empty-string graph driver, substituting default %q", storeOpts.GraphDriverName) + graphDriver = storeOpts.GraphDriverName + } + checkField := func(fieldName, dbVal, ourVal string, isPath bool) error { if isPath { // Tolerate symlinks when possible - most relevant for OStree systems diff --git a/test/system/005-info.bats b/test/system/005-info.bats index ef1c345b29..4887a89422 100644 --- a/test/system/005-info.bats +++ b/test/system/005-info.bats @@ -305,4 +305,27 @@ EOF run_podman $safe_opts system reset --force } +@test "podman - empty string defaults for certain values" { + skip_if_remote "Test uses nonstandard paths for c/storage directories" + + # We just want this to be empty - so graph driver will be set to the empty string + touch $PODMAN_TMPDIR/storage.conf + + safe_opts=$(podman_isolation_opts ${PODMAN_TMPDIR}) + + # Force all custom directories so we don't pick up an existing database + CONTAINERS_STORAGE_CONF=$PODMAN_TMPDIR/storage.conf run_podman 0+w $safe_opts info + require_warning "The storage 'driver' option should be set" \ + "c/storage should warn on empty storage driver" + + # Now add a valid graph driver to storage.conf + cat >$PODMAN_TMPDIR/storage.conf < Date: Tue, 11 Feb 2025 11:02:20 -0500 Subject: [PATCH 41/58] Update release notes for v5.4.0 final Signed-off-by: Matt Heon --- RELEASE_NOTES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 1d8b7d63ef..f47e4e199b 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -50,6 +50,7 @@ - Fixed a bug where it was possible to specify the `libkrun` backend for VMs on Intel Macs (`libkrun` only supports Arm systems). - Fixed a bug where `libkrun` and `applehv` VMs from `podman machine` could be started at the same time on Macs ([#25112](https://github.com/containers/podman/issues/25112)). - Fixed a bug where `podman exec` commands could not detach from the exec session using the detach keys ([#24895](https://github.com/containers/podman/issues/24895)). +- Fixed a bug where Podman would fail to start due to a database configuration mismatch when certain fields were configured to the empty string ([#24738](https://github.com/containers/podman/issues/24738)). ### API - The Compat and Libpod Build APIs for Images now support a new query parameter, `nohosts`, which (when set to true) does not create `/etc/hosts` in the image when building. From f9f7d48b24b1ca4403f189caaeab1cb8ff4a9aa2 Mon Sep 17 00:00:00 2001 From: Matt Heon Date: Tue, 11 Feb 2025 11:03:25 -0500 Subject: [PATCH 42/58] Bump to v5.4.0 Signed-off-by: Matt Heon --- version/rawversion/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version/rawversion/version.go b/version/rawversion/version.go index a2f65f18d6..1affbe48a8 100644 --- a/version/rawversion/version.go +++ b/version/rawversion/version.go @@ -7,4 +7,4 @@ package rawversion // // NOTE: remember to bump the version at the top of the top-level README.md // file when this is bumped. -const RawVersion = "5.4.0-dev" +const RawVersion = "5.4.0" From af9d576cce0ae9fc50c4d2355424322a89d2dbae Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Wed, 12 Feb 2025 18:07:52 +0100 Subject: [PATCH 43/58] cirrus: remove functional tests As discussed at the cabal October 8, 2024 we have no need for these tests on RHEL branches. See commit 0ed2c91 for more details. Signed-off-by: Paul Holzinger --- .cirrus.yml | 940 +---------------------------- contrib/cirrus/cirrus_yaml_test.py | 4 +- 2 files changed, 12 insertions(+), 932 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index 5bd128b978..0f23668f48 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -212,813 +212,6 @@ build_aarch64_task: repo_artifacts: *repo_artifacts always: *runner_stats - -# There are several other important variations of podman which -# must always build successfully. Most of them are handled in -# this task, though a few need dedicated tasks which follow. -alt_build_task: - name: "$ALT_NAME" - alias: alt_build - # Don't create task on rhel-release builds - # Docs: ./contrib/cirrus/CIModes.md - only_if: &no_rhel_release | - $CIRRUS_BRANCH !=~ 'v[0-9\.]+-rhel' && - $CIRRUS_BASE_BRANCH !=~ 'v[0-9\.]+-rhel' - env: - <<: *stdenvars - TEST_FLAVOR: "altbuild" - gce_instance: *fastvm - matrix: - - env: - ALT_NAME: 'Build Each Commit' - - env: - # TODO: Replace with task using `winmake` to build - # binary and archive installation zip file. - ALT_NAME: 'Windows Cross' # N/B: Referenced by URLencoded strings elsewhere - - env: - ALT_NAME: 'Alt Arch. x86 Cross' - - env: - ALT_NAME: 'Alt Arch. ARM Cross' - - env: - ALT_NAME: 'Alt Arch. MIPS Cross' - - env: - ALT_NAME: 'Alt Arch. MIPS64 Cross' - - env: - ALT_NAME: 'Alt Arch. Other Cross' - # This task cannot make use of the shared repo.tar.zst artifact. - clone_script: *full_clone - setup_script: *setup - main_script: *main - # Produce a new repo.tar.zst artifact for consumption by 'artifacts' task. - repo_prep_script: *repo_prep - repo_artifacts: *repo_artifacts - always: *runner_stats - - -# Confirm building the remote client, natively on a Mac OS-X VM. -osx_alt_build_task: - name: "Build for MacOS amd64+arm64" # N/B: Referenced by URLencoded strings elsewhere - alias: osx_alt_build - # Docs: ./contrib/cirrus/CIModes.md - only_if: *no_rhel_release # RHEL never releases podman mac installer binary - persistent_worker: &mac_pw - labels: - os: darwin - arch: arm64 - purpose: prod - env: &mac_env - CIRRUS_SHELL: "/bin/bash" # sh is the default - CIRRUS_WORKING_DIR: "$HOME/ci/task-${CIRRUS_TASK_ID}" # Isolation: $HOME will be set to "ci" dir. - # Prevent cache-pollution fron one task to the next. - GOPATH: "$CIRRUS_WORKING_DIR/.go" - GOCACHE: "$CIRRUS_WORKING_DIR/.go/cache" - GOENV: "$CIRRUS_WORKING_DIR/.go/support" - GOSRC: "$HOME/ci/task-${CIRRUS_TASK_ID}" - clone_script: *full_clone - # This host is/was shared with potentially many other CI tasks. - # The previous task may have been canceled or aborted. - prep_script: &mac_cleanup "contrib/cirrus/mac_cleanup.sh" - lint_script: - - make golangci-lint - basic_build_script: - - make .install.ginkgo - - make podman-remote - - make podman-mac-helper - build_pkginstaller_script: - - pushd contrib/pkginstaller - - make ARCH=amd64 NO_CODESIGN=1 pkginstaller - - make ARCH=aarch64 NO_CODESIGN=1 pkginstaller - - make ARCH=universal NO_CODESIGN=1 pkginstaller - - popd - build_amd64_script: - - make podman-remote-release-darwin_amd64.zip - # Building arm podman needs to be the last thing built in this task - # The Mac tests rely this Podman binary to run, and the CI Mac is ARM-based - build_arm64_script: - - make podman-remote-release-darwin_arm64.zip - # Produce a new repo.tar.zst artifact for consumption by dependent tasks. - repo_prep_script: *repo_prep - repo_artifacts: *repo_artifacts - # This host is/was shared with potentially many other CI tasks. - # Ensure nothing is left running while waiting for the next task. - always: - task_cleanup_script: *mac_cleanup - - -# Build freebsd release natively on a FreeBSD VM. -freebsd_alt_build_task: - name: "FreeBSD Cross" - alias: freebsd_alt_build - # Only run on 'main' and PRs against 'main' - # Docs: ./contrib/cirrus/CIModes.md - only_if: $CIRRUS_BRANCH == 'main' || $CIRRUS_BASE_BRANCH == 'main' - env: - <<: *stdenvars - # Functional FreeBSD builds must be built natively since they depend on CGO - DISTRO_NV: freebsd-13 - VM_IMAGE_NAME: notyet - CTR_FQIN: notyet - CIRRUS_SHELL: "/bin/sh" - TEST_FLAVOR: "altbuild" - ALT_NAME: 'FreeBSD Cross' - freebsd_instance: - image_family: freebsd-13-4 - setup_script: - - pkg install -y gpgme bash go-md2man gmake gsed gnugrep go pkgconf zstd - build_amd64_script: - - gmake podman-release - # This task cannot make use of the shared repo.tar.zst artifact and must - # produce a new repo.tar.zst artifact for consumption by 'artifacts' task. - repo_prep_script: *repo_prep - repo_artifacts: *repo_artifacts - - -# Status aggregator for all builds. This task simply makes dependency -# management easier, and results in a simpler graph that using YAML -# anchors/aliases. -build_success_task: - name: "Total Build Success" - alias: build_success - depends_on: - - validate-source - - build - - build_aarch64 - - alt_build - - osx_alt_build - - freebsd_alt_build - env: - CTR_FQIN: ${FEDORA_CONTAINER_FQIN} - container: &smallcontainer - image: ${CTR_FQIN} - # Resources are limited across ALL currently executing tasks - # ref: https://cirrus-ci.org/guide/linux/#linux-containers - cpu: 1 - memory: 1 - clone_script: &noop mkdir -p "$CIRRUS_WORKING_DIR" - script: *noop - - -# Exercise the "libpod" API with a small set of common -# operations to ensure they are functional. -bindings_task: - name: "Test Bindings" - alias: bindings - # Docs: ./contrib/cirrus/CIModes.md (Cirrus Task contexts and runtime modes) - # only when: - main rules (see doc above); or - # - bindings test code is changed; or - # - actual source code changed - only_if: >- - $CIRRUS_PR == '' || - $CIRRUS_CHANGE_TITLE =~ '.*CI:ALL.*' || - changesInclude('.cirrus.yml', 'Makefile', 'contrib/cirrus/**', 'vendor/**', 'test/tools/**', 'test/registries*.conf', 'hack/**', 'version/rawversion/*') || - changesInclude('pkg/bindings/test/**') || - (changesInclude('**/*.go', '**/*.c', '**/*.h') && !changesIncludeOnly('test/**', 'pkg/machine/e2e/**')) - depends_on: &build - - build_success - gce_instance: &standardvm - <<: *fastvm - cpu: 2 - env: - <<: *stdenvars - TEST_FLAVOR: bindings - # N/B: This script depends on ${DISTRO_NV} being defined for the task. - clone_script: &get_gosrc | - cd /tmp - echo "$ARTCURL/Build%20for%20${DISTRO_NV}/repo/repo.tar.zst" - time $ARTCURL/Build%20for%20${DISTRO_NV}/repo/repo.tar.zst - time tar -xf /tmp/repo.tar.zst -C $GOSRC - setup_script: *setup - main_script: *main - always: &logs_artifacts - <<: *runner_stats - # Required for `contrib/cirrus/logformatter` to work properly - html_artifacts: - path: ./*.html - type: text/html - server_log_artifacts: - path: ./podman-server.log - type: text/plain - cleanup_tracer_artifacts: - path: ./podman-cleanup-tracer.log - type: text/plain - df_script: '$SCRIPT_BASE/logcollector.sh df' - audit_log_script: '$SCRIPT_BASE/logcollector.sh audit' - journal_script: '$SCRIPT_BASE/logcollector.sh journal' - podman_system_info_script: '$SCRIPT_BASE/logcollector.sh podman' - time_script: '$SCRIPT_BASE/logcollector.sh time' - - -# Build the "libpod" API documentation `swagger.yaml` and -# publish it to google-cloud-storage (GCS). -swagger_task: - name: "Test Swagger" - alias: swagger - depends_on: *build - gce_instance: *standardvm - env: - <<: *stdenvars - TEST_FLAVOR: swagger - CTR_FQIN: 'quay.io/libpod/gcsupld:${IMAGE_SUFFIX}' - GCPJSON: ENCRYPTED[927dc01e755eaddb4242b0845cf86c9098d1e3dffac38c70aefb1487fd8b4fe6dd6ae627b3bffafaba70e2c63172664e] - GCPNAME: ENCRYPTED[c145e9c16b6fb88d476944a454bf4c1ccc84bb4ecaca73bdd28bdacef0dfa7959ebc8171a27b2e4064d66093b2cdba49] - GCPPROJECT: 'libpod-218412' - clone_script: *get_gosrc - setup_script: *setup - main_script: *main - always: - <<: *runner_stats - swagger_artifacts: - path: ./swagger.yaml - type: text/plain - - -win_installer_task: - name: "Verify Win Installer Build" - matrix: - - env: - CONTAINERS_MACHINE_PROVIDER: 'wsl' - - env: - CONTAINERS_MACHINE_PROVIDER: 'hyperv' - alias: win_installer - only_if: *no_rhel_release - depends_on: *build - ec2_instance: &windows - image: "${WINDOWS_AMI}" - type: m5.large - region: us-east-1 - platform: windows - env: &winenv - CIRRUS_WORKING_DIR: &wincwd "${LOCALAPPDATA}\\cirrus-ci-build" - CIRRUS_SHELL: powershell - PATH: "${PATH};C:\\ProgramData\\chocolatey\\bin" - DISTRO_NV: "windows" - PRIV_NAME: "rootless" - # Fake version, we are only testing the installer functions, so version doesn't matter - WIN_INST_VER: 9.9.9 - # It's HIGHLY desireable to use the same binary throughout CI. Otherwise, if - # there's a toolchain or build-environment specific problem, it can be incredibly - # difficult (and non-obvious) to debug. - clone_script: &winclone | - $ErrorActionPreference = 'Stop' - $ProgressPreference = 'SilentlyContinue' - New-Item -ItemType Directory -Force -Path "$ENV:CIRRUS_WORKING_DIR" - Set-Location "$ENV:CIRRUS_WORKING_DIR" - $uri = "${ENV:ART_URL}/Windows Cross/repo/repo.tar.zst" - Write-Host "Downloading $uri" - For($i = 0;;) { - Try { - Invoke-WebRequest -UseBasicParsing -ErrorAction Stop -OutFile "repo.tar.zst" ` - -Uri "$uri" - Break - } Catch { - if (++$i -gt 6) { - throw $_.Exception - } - Write-Host "Download failed - retrying:" $_.Exception.Response.StatusCode - Start-Sleep -Seconds 10 - } - } - Write-Host "zstd -d repo.tar.zst" - zstd -d repo.tar.zst - if ($LASTEXITCODE -ne 0) { - throw "Extract repo.tar.zst failed" - Exit 1 - } - Write-Host "arc unarchive repo.tar .\" - arc unarchive repo.tar .\repo - if ($LASTEXITCODE -ne 0) { - throw "Unarchive repo.tar failed" - Exit 1 - } - Get-ChildItem -Path . - Get-ChildItem -Path .\repo - main_script: ".\\repo\\contrib\\cirrus\\win-installer-main.ps1" - - -# Verify podman is compatible with the docker python-module. -docker-py_test_task: - name: Docker-py Compat. - alias: docker-py_test - # Docs: ./contrib/cirrus/CIModes.md (Cirrus Task contexts and runtime modes) - # only when: - main rules (see doc above); or - # - docker-py test code is changed; or - # - actual source code changed - only_if: >- - $CIRRUS_PR == '' || - $CIRRUS_CHANGE_TITLE =~ '.*CI:ALL.*' || - changesInclude('.cirrus.yml', 'Makefile', 'contrib/cirrus/**', 'vendor/**', 'test/tools/**', 'test/registries*.conf', 'hack/**', 'version/rawversion/*') || - changesInclude('test/python/**') || - (changesInclude('**/*.go', '**/*.c', '**/*.h') && !changesIncludeOnly('test/**', 'pkg/machine/e2e/**')) - depends_on: *build - gce_instance: *standardvm - env: - <<: *stdenvars - TEST_FLAVOR: docker-py - TEST_ENVIRON: container - clone_script: *get_gosrc - setup_script: *setup - main_script: *main - always: *runner_stats - - -# Does exactly what it says, execute the podman unit-tests on Fedora. -unit_test_task: - name: "Unit tests on $DISTRO_NV" - alias: unit_test - # Docs: ./contrib/cirrus/CIModes.md (Cirrus Task contexts and runtime modes) - # only when: - main rules (see doc above); or - # - unit test files are changed (contains a false positves such as test/e2e/ - # but that should not be an issue, it only runs when it doesn't have to) - # - actual source code changed - only_if: >- - $CIRRUS_PR == '' || - $CIRRUS_CHANGE_TITLE =~ '.*CI:ALL.*' || - changesInclude('.cirrus.yml', 'Makefile', 'contrib/cirrus/**', 'vendor/**', 'test/tools/**', 'test/registries*.conf', 'hack/**', 'version/rawversion/*') || - changesInclude('**/*_test.go') || - (changesInclude('**/*.go', '**/*.c', '**/*.h') && !changesIncludeOnly('test/**', 'pkg/machine/e2e/**')) - depends_on: *build - matrix: - - env: *stdenvars - # Special-case: Rootless on latest Fedora (standard) VM - - name: "Rootless unit on $DISTRO_NV" - env: - <<: *stdenvars - PRIV_NAME: rootless - gce_instance: *standardvm - env: - TEST_FLAVOR: unit - clone_script: *get_gosrc - setup_script: *setup - main_script: *main - always: *logs_artifacts - - -apiv2_test_task: - name: "APIv2 test on $DISTRO_NV ($PRIV_NAME)" - alias: apiv2_test - # Docs: ./contrib/cirrus/CIModes.md (Cirrus Task contexts and runtime modes) - # only when: - main rules (see doc above); or - # - apiv2 test code is changed; or - # - actual source code changed - only_if: >- - $CIRRUS_PR == '' || - $CIRRUS_CHANGE_TITLE =~ '.*CI:ALL.*' || - changesInclude('.cirrus.yml', 'Makefile', 'contrib/cirrus/**', 'vendor/**', 'test/tools/**', 'test/registries*.conf', 'hack/**', 'version/rawversion/*') || - changesInclude('test/apiv2/**', 'test/python/**') || - (changesInclude('**/*.go', '**/*.c', '**/*.h') && !changesIncludeOnly('test/**', 'pkg/machine/e2e/**')) - depends_on: *build - gce_instance: *standardvm - env: - <<: *stdenvars - TEST_FLAVOR: apiv2 - matrix: - - env: - PRIV_NAME: root - - env: - PRIV_NAME: rootless - clone_script: *get_gosrc - setup_script: *setup - main_script: *main - always: *logs_artifacts - - -compose_test_task: - name: "$TEST_FLAVOR test on $DISTRO_NV ($PRIV_NAME)" - alias: compose_test - # Docs: ./contrib/cirrus/CIModes.md (Cirrus Task contexts and runtime modes) - # only when: - main rules (see doc above); or - # - compose test code is changed; or - # - actual source code changed - only_if: >- - $CIRRUS_PR == '' || - $CIRRUS_CHANGE_TITLE =~ '.*CI:ALL.*' || - changesInclude('.cirrus.yml', 'Makefile', 'contrib/cirrus/**', 'vendor/**', 'test/tools/**', 'test/registries*.conf', 'hack/**', 'version/rawversion/*') || - changesInclude('test/compose/**') || - (changesInclude('**/*.go', '**/*.c', '**/*.h') && !changesIncludeOnly('test/**', 'pkg/machine/e2e/**')) - depends_on: *build - gce_instance: *standardvm - matrix: - - env: - PRIV_NAME: root - - env: - PRIV_NAME: rootless - env: - <<: *stdenvars - TEST_FLAVOR: compose_v2 - clone_script: *get_gosrc - setup_script: *setup - main_script: *main - always: *logs_artifacts - - -# versions, as root, without involving the podman-remote client. -local_integration_test_task: &local_integration_test_task - # Integration-test task name convention: - # - name: &std_name_fmt "$TEST_FLAVOR $PODBIN_NAME $DISTRO_NV $PRIV_NAME $TEST_ENVIRON ${CI_DESIRED_DATABASE}" - alias: local_integration_test - # Docs: ./contrib/cirrus/CIModes.md (Cirrus Task contexts and runtime modes) - # only when: - main rules (see doc above); or - # - int test code is changed; or - # - actual source code changed - only_if: &only_if_int_test >- - $CIRRUS_PR == '' || - $CIRRUS_CHANGE_TITLE =~ '.*CI:ALL.*' || - changesInclude('.cirrus.yml', 'Makefile', 'contrib/cirrus/**', 'vendor/**', 'test/tools/**', 'test/registries*.conf', 'hack/**', 'version/rawversion/*') || - changesInclude('test/e2e/**', 'test/utils/**') || - (changesInclude('**/*.go', '**/*.c', '**/*.h') && !changesIncludeOnly('test/**', 'pkg/machine/e2e/**')) - depends_on: *build - matrix: *platform_axis - # integration tests scale well with cpu as they are parallelized - # so we give these tests 4 cores to make them faster - gce_instance: *fastvm - env: - TEST_FLAVOR: int - clone_script: *get_gosrc - setup_script: *setup - main_script: *main - always: &int_logs_artifacts - <<: *logs_artifacts - ginkgo_node_logs_artifacts: - path: ./test/e2e/ginkgo-node-*.log - type: text/plain - - -# Nearly identical to `local_integration_test` except all operations -# are performed through the podman-remote client vs a podman "server" -# running on the same host. -remote_integration_test_task: - <<: *local_integration_test_task - alias: remote_integration_test - env: - TEST_FLAVOR: int - PODBIN_NAME: remote - - -# Run the complete set of integration tests from inside a container. -# This verifies all/most operations function with "podman-in-podman". -container_integration_test_task: - name: *std_name_fmt - alias: container_integration_test - # Docs: ./contrib/cirrus/CIModes.md - only_if: *only_if_int_test - depends_on: *build - matrix: &fedora_vm_axis - - env: - DISTRO_NV: ${FEDORA_NAME} - VM_IMAGE_NAME: ${FEDORA_CACHE_IMAGE_NAME} - CTR_FQIN: ${FEDORA_CONTAINER_FQIN} - - env: - DISTRO_NV: ${PRIOR_FEDORA_NAME} - VM_IMAGE_NAME: ${PRIOR_FEDORA_CACHE_IMAGE_NAME} - CTR_FQIN: ${PRIOR_FEDORA_CONTAINER_FQIN} - CI_DESIRED_DATABASE: boltdb - gce_instance: *fastvm - env: - TEST_FLAVOR: int - TEST_ENVIRON: container - clone_script: *get_gosrc - setup_script: *setup - main_script: *main - always: *int_logs_artifacts - - -# Execute most integration tests as a regular (non-root) user. -rootless_integration_test_task: - name: *std_name_fmt - alias: rootless_integration_test - # Docs: ./contrib/cirrus/CIModes.md - only_if: *only_if_int_test - depends_on: *build - matrix: *platform_axis - gce_instance: *fastvm - env: - TEST_FLAVOR: int - PRIV_NAME: rootless - clone_script: *get_gosrc - setup_script: *setup - main_script: *main - always: *int_logs_artifacts - - -podman_machine_task: - name: *std_name_fmt - alias: podman_machine - # Docs: ./contrib/cirrus/CIModes.md (Cirrus Task contexts and runtime modes) - # only when: - main rules (see doc above); or - # - machine code files are changed - only_if: &only_if_machine_test >- - $CIRRUS_PR == '' || - $CIRRUS_CHANGE_TITLE =~ '.*CI:ALL.*' || - changesInclude('.cirrus.yml', 'Makefile', 'contrib/cirrus/**', 'vendor/**', 'test/tools/**', 'test/registries*.conf', 'hack/**', 'version/rawversion/*') || - changesInclude('cmd/podman/machine/**', 'pkg/machine/**', '**/*machine*.go') - depends_on: *build - ec2_instance: - image: "${VM_IMAGE_NAME}" - type: "${EC2_INST_TYPE}" - region: us-east-1 - timeout_in: 30m - env: - EC2_INST_TYPE: "m5zn.metal" # Bare-metal instance is required - TEST_FLAVOR: "machine-linux" - PRIV_NAME: "rootless" # intended use-case - DISTRO_NV: "${FEDORA_NAME}" - VM_IMAGE_NAME: "${FEDORA_AMI}" - clone_script: *get_gosrc - setup_script: *setup - main_script: *main - always: *int_logs_artifacts - - -podman_machine_aarch64_task: - name: *std_name_fmt - alias: podman_machine_aarch64 - only_if: *only_if_machine_test - depends_on: *build - ec2_instance: - <<: *standard_build_ec2_aarch64 - timeout_in: 30m - env: - TEST_FLAVOR: "machine-linux" - EC2_INST_TYPE: c6g.metal - PRIV_NAME: "rootless" # intended use-case - DISTRO_NV: "${FEDORA_AARCH64_NAME}" - VM_IMAGE_NAME: "${FEDORA_AARCH64_AMI}" - clone_script: &get_gosrc_aarch64 | - cd /tmp - echo "$ARTCURL/build_aarch64/repo/repo.tar.zst" - time $ARTCURL/build_aarch64/repo/repo.tar.zst - time tar -xf /tmp/repo.tar.zst -C $GOSRC - setup_script: *setup - main_script: *main - always: *int_logs_artifacts - - -podman_machine_windows_task: - name: *std_name_fmt - alias: podman_machine_windows - # Docs: ./contrib/cirrus/CIModes.md - only_if: *only_if_machine_test - # Special case, we do not run macos/windows builds on rhel branches. - # Thus the machine task should not be run too, while we use only_if - # everywhere to do so here it would mean we would need duplicate the - # full big only_if condition which is more difficult to maintain so - # use the skip here. - skip: &skip_rhel_release | - $CIRRUS_BRANCH =~ 'v[0-9\.]+-rhel' || - $CIRRUS_BASE_BRANCH =~ 'v[0-9\.]+-rhel' - depends_on: *build - ec2_instance: - <<: *windows - type: m5zn.metal - platform: windows - timeout_in: 45m - env: *winenv - matrix: - - env: - TEST_FLAVOR: "machine-wsl" - - env: - TEST_FLAVOR: "machine-hyperv" - clone_script: *winclone - main_script: ".\\repo\\contrib\\cirrus\\win-podman-machine-main.ps1" - always: - # Required for `contrib/cirrus/logformatter` to work properly - html_artifacts: - path: ./*.html - type: text/html - - -podman_machine_mac_task: - name: *std_name_fmt - alias: podman_machine_mac - only_if: *only_if_machine_test - skip: *skip_rhel_release - depends_on: *build - persistent_worker: *mac_pw - timeout_in: 45m - env: - <<: *mac_env - DISTRO_NV: "darwin" - PRIV_NAME: "rootless" # intended use-case - matrix: - - env: - # See contrib/cirrus/mac_runner.sh - TEST_FLAVOR: "machine-applehv" - - env: - # See contrib/cirrus/mac_runner.sh - TEST_FLAVOR: "machine-libkrun" - clone_script: # artifacts from osx_alt_build_task - - mkdir -p $CIRRUS_WORKING_DIR - - cd $CIRRUS_WORKING_DIR - - $ARTCURL/Build%20for%20MacOS%20amd64%2Barm64/repo/repo.tar.zst - - tar -xf repo.tar.zst - # This host is/was shared with potentially many other CI tasks. - # The previous task may have been canceled or aborted. - prep_script: *mac_cleanup - setup_script: "contrib/cirrus/mac_setup.sh" - env_script: "contrib/cirrus/mac_env.sh" - # TODO: Timeout bumped b/c initial image download (~5min) and VM - # resize (~2min) causes test-timeout (90s default). Should - # tests deal with this internally? - test_script: - - "contrib/cirrus/mac_runner.sh" - # This host is/was shared with potentially many other CI tasks. - # Ensure nothing is left running while waiting for the next task. - always: - # Required for `contrib/cirrus/logformatter` to work properly - html_artifacts: - path: ./*.html - type: text/html - task_cleanup_script: *mac_cleanup - - -# Always run subsequent to integration tests. While parallelism is lost -# with runtime, debugging system-test failures can be more challenging -# for some golang developers. Otherwise the following tasks run across -# the same matrix as the integration-tests (above). -local_system_test_task: &local_system_test_task - name: *std_name_fmt - alias: local_system_test - # Docs: ./contrib/cirrus/CIModes.md (Cirrus Task contexts and runtime modes) - # only when: - main rules (see doc above); or - # - sys test code is changed; or - # - actual source code changed - only_if: &only_if_system_test >- - $CIRRUS_PR == '' || - $CIRRUS_CHANGE_TITLE =~ '.*CI:ALL.*' || - changesInclude('.cirrus.yml', 'Makefile', 'contrib/cirrus/**', 'vendor/**', 'test/tools/**', 'test/registries*.conf', 'hack/**', 'version/rawversion/*') || - changesInclude('test/system/**') || - (changesInclude('**/*.go', '**/*.c', '**/*.h') && !changesIncludeOnly('test/**', 'pkg/machine/e2e/**')) - depends_on: *build - matrix: *platform_axis - gce_instance: *fastvm - timeout_in: 25m - env: - TEST_FLAVOR: sys - clone_script: *get_gosrc - setup_script: *setup - main_script: *main - always: *logs_artifacts - - -local_system_test_aarch64_task: &local_system_test_task_aarch64 - name: *std_name_fmt - alias: local_system_test_aarch64 - # Docs: ./contrib/cirrus/CIModes.md - only_if: *only_if_system_test - depends_on: *build - ec2_instance: *standard_build_ec2_aarch64 - timeout_in: 35m - env: - <<: *stdenvars_aarch64 - TEST_FLAVOR: sys - DISTRO_NV: ${FEDORA_AARCH64_NAME} - clone_script: *get_gosrc_aarch64 - setup_script: *setup - main_script: *main - always: *logs_artifacts - - -remote_system_test_task: - <<: *local_system_test_task - alias: remote_system_test - env: - TEST_FLAVOR: sys - PODBIN_NAME: remote - - -remote_system_test_aarch64_task: - <<: *local_system_test_task_aarch64 - alias: remote_system_test_aarch64 - env: - TEST_FLAVOR: sys - PODBIN_NAME: remote - - -rootless_remote_system_test_task: - matrix: - # Minimal sanity testing: only the latest Fedora - - env: - DISTRO_NV: ${FEDORA_NAME} - # Not used here, is used in other tasks - VM_IMAGE_NAME: ${FEDORA_CACHE_IMAGE_NAME} - CTR_FQIN: ${FEDORA_CONTAINER_FQIN} - <<: *local_system_test_task - alias: rootless_remote_system_test - gce_instance: *fastvm - timeout_in: 25m - env: - TEST_FLAVOR: sys - PODBIN_NAME: remote - PRIV_NAME: rootless - - -rootless_system_test_task: - name: *std_name_fmt - alias: rootless_system_test - # Docs: ./contrib/cirrus/CIModes.md - only_if: *only_if_system_test - depends_on: *build - matrix: *platform_axis - gce_instance: *fastvm - timeout_in: 25m - env: - TEST_FLAVOR: sys - PRIV_NAME: rootless - clone_script: *get_gosrc - setup_script: *setup - main_script: *main - always: *logs_artifacts - - -farm_test_task: - name: *std_name_fmt - alias: farm_test - # Docs: ./contrib/cirrus/CIModes.md (Cirrus Task contexts and runtime modes) - # only when: - main rules (see doc above); or - # - farm test code is changed or one of the shared helper import files from the system test; or - # - actual source code changed - only_if: >- - $CIRRUS_PR == '' || - $CIRRUS_CHANGE_TITLE =~ '.*CI:ALL.*' || - changesInclude('.cirrus.yml', 'Makefile', 'contrib/cirrus/**', 'vendor/**', 'test/tools/**', 'test/registries*.conf', 'hack/**', 'version/rawversion/*') || - changesInclude('test/farm/**', 'test/system/*.bash') || - (changesInclude('**/*.go', '**/*.c', '**/*.h') && !changesIncludeOnly('test/**', 'pkg/machine/e2e/**')) - depends_on: *build - gce_instance: *standardvm - env: - <<: *stdenvars - TEST_FLAVOR: farm - PRIV_NAME: rootless - clone_script: *get_gosrc - setup_script: *setup - main_script: *main - always: *logs_artifacts - -buildah_bud_test_task: - name: *std_name_fmt - alias: buildah_bud_test - # Docs: ./contrib/cirrus/CIModes.md (Cirrus Task contexts and runtime modes) - # only when: - main rules (see doc above); or - # - podman build source code files or bud tests files are changed - # (vendor updates, i.e. buildah, are already covered in the main rules) - only_if: >- - $CIRRUS_PR == '' || - $CIRRUS_CHANGE_TITLE =~ '.*CI:ALL.*' || - changesInclude('.cirrus.yml', 'Makefile', 'contrib/cirrus/**', 'vendor/**', 'test/tools/**', 'test/registries*.conf', 'hack/**', 'version/rawversion/*') || - changesInclude('**/*build*.go', 'test/buildah-bud/**') - depends_on: *build - env: - <<: *stdenvars - TEST_FLAVOR: bud - matrix: - - env: - PODBIN_NAME: podman - - env: - PODBIN_NAME: remote - gce_instance: *standardvm - timeout_in: 45m - clone_script: *get_gosrc - setup_script: *setup - main_script: *main - always: *int_logs_artifacts - -upgrade_test_task: - name: "Upgrade test: from $PODMAN_UPGRADE_FROM" - alias: upgrade_test - # Docs: ./contrib/cirrus/CIModes.md (Cirrus Task contexts and runtime modes) - # only when: - main rules (see doc above); or - # - upgrade test code is changed or one of the shared helper import files from the system test; or - # - actual source code changed - only_if: >- - $CIRRUS_PR == '' || - $CIRRUS_CHANGE_TITLE =~ '.*CI:ALL.*' || - changesInclude('.cirrus.yml', 'Makefile', 'contrib/cirrus/**', 'vendor/**', 'test/tools/**', 'test/registries*.conf', 'hack/**', 'version/rawversion/*') || - changesInclude('test/upgrade/**', 'test/system/*.bash') || - (changesInclude('**/*.go', '**/*.c', '**/*.h') && !changesIncludeOnly('test/**', 'pkg/machine/e2e/**')) - depends_on: *build - matrix: - - env: - # 2024-02: as long as possible/reasonable, try to keep - # one version < 4.8 so we can test boltdb. v4.3.1 is - # the lowest we can go right now, builds before that - # have netavark <1.4 which hangs on f39 kernel (#21863). - PODMAN_UPGRADE_FROM: v4.3.1 - - env: - PODMAN_UPGRADE_FROM: v4.8.0 - gce_instance: *standardvm - env: - TEST_FLAVOR: upgrade_test - DISTRO_NV: ${FEDORA_NAME} - VM_IMAGE_NAME: ${FEDORA_CACHE_IMAGE_NAME} - # Never force a DB, let the old version decide its default - CI_DESIRED_DATABASE: - clone_script: *get_gosrc - setup_script: *setup - main_script: *main - always: *logs_artifacts - - # This task is critical. It updates the "last-used by" timestamp stored # in metadata for all VM images. This mechanism functions in tandem with # an out-of-band pruning operation to remove disused VM images. @@ -1046,7 +239,7 @@ meta_task: GCPJSON: ENCRYPTED[3a198350077849c8df14b723c0f4c9fece9ebe6408d35982e7adf2105a33f8e0e166ed3ed614875a0887e1af2b8775f4] GCPNAME: ENCRYPTED[2f9738ef295a706f66a13891b40e8eaa92a89e0e87faf8bed66c41eca72bf76cfd190a6f2d0e8444c631fdf15ed32ef6] GCPPROJECT: libpod-218412 - clone_script: *noop + clone_script: &noop mkdir -p "$CIRRUS_WORKING_DIR" script: /usr/local/bin/entrypoint.sh @@ -1059,130 +252,17 @@ success_task: alias: success # N/B: ALL tasks must be listed here, minus their '_task' suffix. depends_on: - - build_success - - bindings - - swagger - - win_installer - - docker-py_test - - unit_test - - apiv2_test - - compose_test - - local_integration_test - - remote_integration_test - - container_integration_test - - rootless_integration_test - - podman_machine - - podman_machine_aarch64 - - podman_machine_windows - - podman_machine_mac - - local_system_test - - local_system_test_aarch64 - - remote_system_test - - remote_system_test_aarch64 - - rootless_remote_system_test - - rootless_system_test - - farm_test - - buildah_bud_test - - upgrade_test + - validate-source + - build + - build_aarch64 - meta env: CTR_FQIN: ${FEDORA_CONTAINER_FQIN} - container: *smallcontainer + container: &smallcontainer + image: ${CTR_FQIN} + # Resources are limited across ALL currently executing tasks + # ref: https://cirrus-ci.org/guide/linux/#linux-containers + cpu: 1 + memory: 1 clone_script: *noop script: *noop - -# WARNING: Most of the artifacts captured here are also have their -# permalinks present in the `DOWNLOADS.md` file. Any changes made -# here, should probably be reflected in that document. -artifacts_task: - name: "Artifacts" - alias: artifacts - # Docs: ./contrib/cirrus/CIModes.md - only_if: *no_rhel_release - depends_on: - - success - # This task is a secondary/convenience for downstream consumers, don't - # block development progress if there is a failure in a PR, only break - # when running on branches or tags. - allow_failures: $CIRRUS_PR != '' - container: *smallcontainer - env: - CTR_FQIN: ${FEDORA_CONTAINER_FQIN} - TEST_ENVIRON: container - # In order to keep the download URL and Cirrus-CI artifact.zip contents - # simple, nothing should exist in $CIRRUS_WORKING_DIR except for artifacts. - clone_script: *noop - fedora_binaries_script: - - mkdir -p /tmp/fed - - cd /tmp/fed - - $ARTCURL/Build%20for%20${FEDORA_NAME}/repo/repo.tar.zst - - tar -xf repo.tar.zst - - cp ./bin/* $CIRRUS_WORKING_DIR/ - win_binaries_script: - - mkdir -p /tmp/win - - cd /tmp/win - - $ARTCURL/Windows%20Cross/repo/repo.tar.zst - - tar -xf repo.tar.zst - - mv ./podman-remote*.zip $CIRRUS_WORKING_DIR/ - osx_binaries_script: - - mkdir -p /tmp/osx - - cd /tmp/osx - - $ARTCURL/Build%20for%20MacOS%20amd64%2Barm64/repo/repo.tar.zst - - tar -xf repo.tar.zst - - mv ./podman-remote-release-darwin_*.zip $CIRRUS_WORKING_DIR/ - - mv ./contrib/pkginstaller/out/podman-installer-macos-*.pkg $CIRRUS_WORKING_DIR/ - always: - contents_script: ls -la $CIRRUS_WORKING_DIR - # Produce downloadable files and an automatic zip-file accessible - # by a consistent URL, based on contents of $CIRRUS_WORKING_DIR - # Ref: https://cirrus-ci.org/guide/writing-tasks/#latest-build-artifacts - binary_artifacts: - path: ./* - type: application/octet-stream - - -# When a new tag is pushed, confirm that the code and commits -# meet criteria for an official release. -release_task: - name: "Verify Release" - alias: release - # This should _only_ run for new tags - # Docs: ./contrib/cirrus/CIModes.md - only_if: $CIRRUS_TAG != '' - depends_on: - - build_success - - success - gce_instance: *standardvm - env: - <<: *stdenvars - TEST_FLAVOR: release - clone_script: *get_gosrc - setup_script: *setup - main_script: *main - - -# When preparing to release a new version, this task may be manually -# activated at the PR stage to verify the build is proper for a potential -# podman release. -# -# Note: This cannot use a YAML alias on 'release_task' as of this -# comment, it is incompatible with 'trigger_type: manual' -release_test_task: - name: "Optional Release Test" - alias: release_test - # Release-PRs always include "release" or "Bump" in the title - # Docs: ./contrib/cirrus/CIModes.md - only_if: $CIRRUS_CHANGE_TITLE =~ '.*((release)|(bump)).*' - # Allow running manually only as part of release-related builds - # see RELEASE_PROCESS.md - trigger_type: manual - depends_on: - - build_success - - success - gce_instance: *standardvm - env: - <<: *stdenvars - TEST_FLAVOR: release - clone_script: *get_gosrc - setup_script: *setup - main_script: *main diff --git a/contrib/cirrus/cirrus_yaml_test.py b/contrib/cirrus/cirrus_yaml_test.py index cfa1098a84..4bfdf68f87 100755 --- a/contrib/cirrus/cirrus_yaml_test.py +++ b/contrib/cirrus/cirrus_yaml_test.py @@ -27,9 +27,9 @@ class TestDependsOn(TestCaseBase): ALL_TASK_NAMES = None # All tasks must be listed as a dependency of one/more of these tasks - SUCCESS_DEPS_EXCLUDE = set(['build_success', 'success']) + SUCCESS_DEPS_EXCLUDE = set(['success']) # Tasks which do not influence any success aggregator (above) - NONSUCCESS_TASKS = set(['artifacts', 'release', 'release_test']) + NONSUCCESS_TASKS = set() def setUp(self): super().setUp() From a640863c7c34e69ab6dad4721b68d03cf5ea2734 Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Wed, 12 Feb 2025 18:08:42 +0100 Subject: [PATCH 44/58] cirrus: fix DEST_BRANCH Signed-off-by: Paul Holzinger --- .cirrus.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cirrus.yml b/.cirrus.yml index 0f23668f48..d398521335 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -6,7 +6,7 @@ env: #### Global variables used for all tasks #### # Name of the ultimate destination branch for this CI run, PR or post-merge. - DEST_BRANCH: "v5.4" + DEST_BRANCH: "v5.4-rhel" # Sane (default) value for GOPROXY and GOSUMDB. GOPROXY: "https://proxy.golang.org,direct" GOSUMDB: "sum.golang.org" From b6092e268e08707e45b3b0a34e675e7709cfff0c Mon Sep 17 00:00:00 2001 From: tomsweeneyredhat Date: Tue, 4 Mar 2025 18:35:02 -0500 Subject: [PATCH 45/58] [v5.4-rhel] Bump c/image to v5.34.1, c/common v0.62.1, ... c/buildah v1.39.2 Bump: c/image v5.34.1 c/common v0.62.1 c/buildah v1.39.2 To bring BYOPKI signature verification into the RHEL 9.6 and 10.0 ZeroDay deliveries. Also updates github.com/go-jose/go-jose/v3 to v3.0.4 which fixes CVE-2025-27144. Fixes: https://issues.redhat.com/browse/RHEL-79694, https://issues.redhat.com/browse/RHEL-79695 Signed-off-by: tomsweeneyredhat --- go.mod | 10 +- go.sum | 20 +- .../github.com/containers/buildah/.cirrus.yml | 2 +- .../containers/buildah/CHANGELOG.md | 9 + .../containers/buildah/changelog.txt | 8 + .../containers/buildah/chroot/run_linux.go | 2 +- .../containers/buildah/define/types.go | 2 +- .../containers/common/version/version.go | 2 +- .../image/v5/signature/fulcio_cert.go | 28 ++- .../containers/image/v5/signature/pki_cert.go | 74 +++++++ .../v5/signature/policy_config_sigstore.go | 192 +++++++++++++++++- .../v5/signature/policy_eval_sigstore.go | 99 ++++++++- .../image/v5/signature/policy_types.go | 37 +++- .../containers/image/v5/version/version.go | 2 +- vendor/github.com/go-jose/go-jose/v3/jwe.go | 5 +- vendor/github.com/go-jose/go-jose/v3/jws.go | 5 +- .../go-jose/go-jose/v4/CONTRIBUTING.md | 6 - .../github.com/go-jose/go-jose/v4/README.md | 10 +- vendor/github.com/go-jose/go-jose/v4/jwe.go | 5 +- vendor/github.com/go-jose/go-jose/v4/jwk.go | 4 +- vendor/github.com/go-jose/go-jose/v4/jws.go | 5 +- vendor/modules.txt | 10 +- 22 files changed, 464 insertions(+), 73 deletions(-) create mode 100644 vendor/github.com/containers/image/v5/signature/pki_cert.go diff --git a/go.mod b/go.mod index e37a2bca2d..f39d6154f7 100644 --- a/go.mod +++ b/go.mod @@ -13,11 +13,11 @@ require ( github.com/checkpoint-restore/checkpointctl v1.3.0 github.com/checkpoint-restore/go-criu/v7 v7.2.0 github.com/containernetworking/plugins v1.5.1 - github.com/containers/buildah v1.39.0 - github.com/containers/common v0.62.0 + github.com/containers/buildah v1.39.2 + github.com/containers/common v0.62.1 github.com/containers/conmon v2.0.20+incompatible github.com/containers/gvisor-tap-vsock v0.8.3 - github.com/containers/image/v5 v5.34.0 + github.com/containers/image/v5 v5.34.1 github.com/containers/libhvee v0.9.0 github.com/containers/ocicrypt v1.2.1 github.com/containers/psgo v1.9.0 @@ -123,8 +123,8 @@ require ( github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/gin-gonic/gin v1.10.0 // indirect - github.com/go-jose/go-jose/v3 v3.0.3 // indirect - github.com/go-jose/go-jose/v4 v4.0.4 // indirect + github.com/go-jose/go-jose/v3 v3.0.4 // indirect + github.com/go-jose/go-jose/v4 v4.0.5 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.3.0 // indirect diff --git a/go.sum b/go.sum index a9474e337b..30ad14eccf 100644 --- a/go.sum +++ b/go.sum @@ -76,16 +76,16 @@ github.com/containernetworking/cni v1.2.3 h1:hhOcjNVUQTnzdRJ6alC5XF+wd9mfGIUaj8F github.com/containernetworking/cni v1.2.3/go.mod h1:DuLgF+aPd3DzcTQTtp/Nvl1Kim23oFKdm2okJzBQA5M= github.com/containernetworking/plugins v1.5.1 h1:T5ji+LPYjjgW0QM+KyrigZbLsZ8jaX+E5J/EcKOE4gQ= github.com/containernetworking/plugins v1.5.1/go.mod h1:MIQfgMayGuHYs0XdNudf31cLLAC+i242hNm6KuDGqCM= -github.com/containers/buildah v1.39.0 h1:/OpzH7eMQYLg6pyguk6vugqScoZm8fIiN6wgMre9nUY= -github.com/containers/buildah v1.39.0/go.mod h1:PTC4lCOwVfT3esN7Kxf2j8Aa3uqxsyUZudECLeGJlkY= -github.com/containers/common v0.62.0 h1:Sl9WE5h7Y/F3bejrMAA4teP1EcY9ygqJmW4iwSloZ10= -github.com/containers/common v0.62.0/go.mod h1:Yec+z8mrSq4rydHofrnDCBqAcNA/BGrSg1kfFUL6F6s= +github.com/containers/buildah v1.39.2 h1:YaFMNnuTr7wKYKQDHkm7yyP9HhWVrNB4DA+DjYUS9k4= +github.com/containers/buildah v1.39.2/go.mod h1:Vb4sDbEq06qQqk29mcGw/1qit8dyukpfL4hwNQ5t+z8= +github.com/containers/common v0.62.1 h1:durvu7Kelb8PYgX7bwuAg/d5LKj2hs3cAaqcU7Vnqus= +github.com/containers/common v0.62.1/go.mod h1:n9cEboBmY3AnTk1alkq4t7sLM4plwkDCiaWbsf67YxE= github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg= github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I= github.com/containers/gvisor-tap-vsock v0.8.3 h1:Am3VdjXTn8Mn+dNhgkiRcCFOTSM8u9aWKLW3KTHOGjk= github.com/containers/gvisor-tap-vsock v0.8.3/go.mod h1:46MvrqNuRNbjV4ZsZ3mHVJjR2Eh+fpyRh72EvWWFFjU= -github.com/containers/image/v5 v5.34.0 h1:HPqQaDUsox/3mC1pbOyLAIQEp0JhQqiUZ+6JiFIZLDI= -github.com/containers/image/v5 v5.34.0/go.mod h1:/WnvUSEfdqC/ahMRd4YJDBLrpYWkGl018rB77iB3FDo= +github.com/containers/image/v5 v5.34.1 h1:/m2bkFnuedTyNkzma8s7cFLjeefPIb4trjyafWhIlwM= +github.com/containers/image/v5 v5.34.1/go.mod h1:/WnvUSEfdqC/ahMRd4YJDBLrpYWkGl018rB77iB3FDo= github.com/containers/libhvee v0.9.0 h1:5UxJMka1lDfxTeITA25Pd8QVVttJAG43eQS1Getw1tc= github.com/containers/libhvee v0.9.0/go.mod h1:p44VJd8jMIx3SRN1eM6PxfCEwXQE0lJ0dQppCAlzjPQ= github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 h1:Qzk5C6cYglewc+UyGf6lc8Mj2UaPTHy/iF2De0/77CA= @@ -168,10 +168,10 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= -github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k= -github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= -github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E= -github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc= +github.com/go-jose/go-jose/v3 v3.0.4 h1:Wp5HA7bLQcKnf6YYao/4kpRpVMp/yf6+pJKV8WFSaNY= +github.com/go-jose/go-jose/v3 v3.0.4/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= +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= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= diff --git a/vendor/github.com/containers/buildah/.cirrus.yml b/vendor/github.com/containers/buildah/.cirrus.yml index 7aa0e309f1..121df5c49b 100644 --- a/vendor/github.com/containers/buildah/.cirrus.yml +++ b/vendor/github.com/containers/buildah/.cirrus.yml @@ -6,7 +6,7 @@ env: #### Global variables used for all tasks #### # Name of the ultimate destination branch for this CI run, PR or post-merge. - DEST_BRANCH: "main" + DEST_BRANCH: "release-1.39" GOPATH: "/var/tmp/go" GOSRC: "${GOPATH}/src/github.com/containers/buildah" GOCACHE: "/tmp/go-build" diff --git a/vendor/github.com/containers/buildah/CHANGELOG.md b/vendor/github.com/containers/buildah/CHANGELOG.md index e28a49a34d..98d053105a 100644 --- a/vendor/github.com/containers/buildah/CHANGELOG.md +++ b/vendor/github.com/containers/buildah/CHANGELOG.md @@ -2,6 +2,15 @@ # Changelog +## v1.39.2 (2025-03-03) + + [release-1.39] Bump c/image to v5.34.1, c/common v0.62.1 + +## v1.39.1 (2025-02-25) + + chroot createPlatformContainer: use MS_REMOUNT + chore(deps): update module github.com/go-jose/go-jose/v4 to v4.0.5 [security] + ## v1.39.0 (2025-01-31) Bump c/storage v1.57.1, c/image 5.34.0, c/common v0.62.0 diff --git a/vendor/github.com/containers/buildah/changelog.txt b/vendor/github.com/containers/buildah/changelog.txt index f1d0263992..db6ed8cad4 100644 --- a/vendor/github.com/containers/buildah/changelog.txt +++ b/vendor/github.com/containers/buildah/changelog.txt @@ -1,3 +1,11 @@ +- Changelog for v1.39.2 (2025-03-03) + * [release-1.39] Bump c/image to v5.34.1, c/common v0.62.1 + +- Changelog for v1.39.1 (2025-02-25) + + * chroot createPlatformContainer: use MS_REMOUNT + * chore(deps): update module github.com/go-jose/go-jose/v4 to v4.0.5 [security] + - Changelog for v1.39.0 (2025-01-31) * Bump c/storage v1.57.1, c/image 5.34.0, c/common v0.62.0 * Update module github.com/containers/storage to v1.57.0 diff --git a/vendor/github.com/containers/buildah/chroot/run_linux.go b/vendor/github.com/containers/buildah/chroot/run_linux.go index 694010b98e..76900d7f0c 100644 --- a/vendor/github.com/containers/buildah/chroot/run_linux.go +++ b/vendor/github.com/containers/buildah/chroot/run_linux.go @@ -263,7 +263,7 @@ func createPlatformContainer(options runUsingChrootExecSubprocOptions) error { return fmt.Errorf("changing to host root directory: %w", err) } // make sure we only unmount things under this tree - if err := unix.Mount(".", ".", "bind", unix.MS_BIND|unix.MS_SLAVE|unix.MS_REC, ""); err != nil { + if err := unix.Mount(".", ".", "bind", unix.MS_REMOUNT|unix.MS_BIND|unix.MS_SLAVE|unix.MS_REC, ""); err != nil { return fmt.Errorf("tweaking mount flags on host root directory before unmounting from mount namespace: %w", err) } // detach this (unnamed?) old directory diff --git a/vendor/github.com/containers/buildah/define/types.go b/vendor/github.com/containers/buildah/define/types.go index d3df78dad3..234cb340ec 100644 --- a/vendor/github.com/containers/buildah/define/types.go +++ b/vendor/github.com/containers/buildah/define/types.go @@ -29,7 +29,7 @@ const ( // identify working containers. Package = "buildah" // Version for the Package. Also used by .packit.sh for Packit builds. - Version = "1.39.0" + Version = "1.39.2" // DefaultRuntime if containers.conf fails. DefaultRuntime = "runc" diff --git a/vendor/github.com/containers/common/version/version.go b/vendor/github.com/containers/common/version/version.go index f676ffa999..43e89ee32b 100644 --- a/vendor/github.com/containers/common/version/version.go +++ b/vendor/github.com/containers/common/version/version.go @@ -1,4 +1,4 @@ package version // Version is the version of the build. -const Version = "0.62.0" +const Version = "0.62.1" diff --git a/vendor/github.com/containers/image/v5/signature/fulcio_cert.go b/vendor/github.com/containers/image/v5/signature/fulcio_cert.go index 31dfdd3422..a3c2048040 100644 --- a/vendor/github.com/containers/image/v5/signature/fulcio_cert.go +++ b/vendor/github.com/containers/image/v5/signature/fulcio_cert.go @@ -108,19 +108,10 @@ func (f *fulcioTrustRoot) verifyFulcioCertificateAtTime(relevantTime time.Time, } } - untrustedLeafCerts, err := cryptoutils.UnmarshalCertificatesFromPEM(untrustedCertificateBytes) + untrustedCertificate, err := parseLeafCertFromPEM(untrustedCertificateBytes) if err != nil { - return nil, internal.NewInvalidSignatureError(fmt.Sprintf("parsing leaf certificate: %v", err)) - } - switch len(untrustedLeafCerts) { - case 0: - return nil, internal.NewInvalidSignatureError("no certificate found in signature certificate data") - case 1: - break // OK - default: - return nil, internal.NewInvalidSignatureError("unexpected multiple certificates present in signature certificate data") + return nil, err } - untrustedCertificate := untrustedLeafCerts[0] // Go rejects Subject Alternative Name that has no DNSNames, EmailAddresses, IPAddresses and URIs; // we match SAN ourselves, so override that. @@ -195,6 +186,21 @@ func (f *fulcioTrustRoot) verifyFulcioCertificateAtTime(relevantTime time.Time, return untrustedCertificate.PublicKey, nil } +func parseLeafCertFromPEM(untrustedCertificateBytes []byte) (*x509.Certificate, error) { + untrustedLeafCerts, err := cryptoutils.UnmarshalCertificatesFromPEM(untrustedCertificateBytes) + if err != nil { + return nil, internal.NewInvalidSignatureError(fmt.Sprintf("parsing leaf certificate: %v", err)) + } + switch len(untrustedLeafCerts) { + case 0: + return nil, internal.NewInvalidSignatureError("no certificate found in signature certificate data") + case 1: // OK + return untrustedLeafCerts[0], nil + default: + return nil, internal.NewInvalidSignatureError("unexpected multiple certificates present in signature certificate data") + } +} + func verifyRekorFulcio(rekorPublicKeys []*ecdsa.PublicKey, fulcioTrustRoot *fulcioTrustRoot, untrustedRekorSET []byte, untrustedCertificateBytes []byte, untrustedIntermediateChainBytes []byte, untrustedBase64Signature string, untrustedPayloadBytes []byte) (crypto.PublicKey, error) { diff --git a/vendor/github.com/containers/image/v5/signature/pki_cert.go b/vendor/github.com/containers/image/v5/signature/pki_cert.go new file mode 100644 index 0000000000..20624540fa --- /dev/null +++ b/vendor/github.com/containers/image/v5/signature/pki_cert.go @@ -0,0 +1,74 @@ +package signature + +import ( + "crypto" + "crypto/x509" + "errors" + "fmt" + "slices" + + "github.com/containers/image/v5/signature/internal" + "github.com/sigstore/sigstore/pkg/cryptoutils" +) + +type pkiTrustRoot struct { + caRootsCertificates *x509.CertPool + caIntermediateCertificates *x509.CertPool + subjectEmail string + subjectHostname string +} + +func (p *pkiTrustRoot) validate() error { + if p.subjectEmail == "" && p.subjectHostname == "" { + return errors.New("Internal inconsistency: PKI use set up without subject email or subject hostname") + } + return nil +} + +func verifyPKI(pkiTrustRoot *pkiTrustRoot, untrustedCertificateBytes []byte, untrustedIntermediateChainBytes []byte) (crypto.PublicKey, error) { + var untrustedIntermediatePool *x509.CertPool + if pkiTrustRoot.caIntermediateCertificates != nil { + untrustedIntermediatePool = pkiTrustRoot.caIntermediateCertificates.Clone() + } else { + untrustedIntermediatePool = x509.NewCertPool() + } + if len(untrustedIntermediateChainBytes) > 0 { + untrustedIntermediateChain, err := cryptoutils.UnmarshalCertificatesFromPEM(untrustedIntermediateChainBytes) + if err != nil { + return nil, internal.NewInvalidSignatureError(fmt.Sprintf("loading certificate chain: %v", err)) + } + if len(untrustedIntermediateChain) > 1 { + for _, untrustedIntermediateCert := range untrustedIntermediateChain[:len(untrustedIntermediateChain)-1] { + untrustedIntermediatePool.AddCert(untrustedIntermediateCert) + } + } + } + + untrustedCertificate, err := parseLeafCertFromPEM(untrustedCertificateBytes) + if err != nil { + return nil, err + } + + if _, err := untrustedCertificate.Verify(x509.VerifyOptions{ + Intermediates: untrustedIntermediatePool, + Roots: pkiTrustRoot.caRootsCertificates, + KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageCodeSigning}, + }); err != nil { + return nil, internal.NewInvalidSignatureError(fmt.Sprintf("veryfing leaf certificate failed: %v", err)) + } + + if pkiTrustRoot.subjectEmail != "" { + if !slices.Contains(untrustedCertificate.EmailAddresses, pkiTrustRoot.subjectEmail) { + return nil, internal.NewInvalidSignatureError(fmt.Sprintf("Required email %q not found (got %q)", + pkiTrustRoot.subjectEmail, + untrustedCertificate.EmailAddresses)) + } + } + if pkiTrustRoot.subjectHostname != "" { + if err = untrustedCertificate.VerifyHostname(pkiTrustRoot.subjectHostname); err != nil { + return nil, internal.NewInvalidSignatureError(fmt.Sprintf("Unexpected subject hostname: %v", err)) + } + } + + return untrustedCertificate.PublicKey, nil +} diff --git a/vendor/github.com/containers/image/v5/signature/policy_config_sigstore.go b/vendor/github.com/containers/image/v5/signature/policy_config_sigstore.go index 965901e187..6393b66ea6 100644 --- a/vendor/github.com/containers/image/v5/signature/policy_config_sigstore.go +++ b/vendor/github.com/containers/image/v5/signature/policy_config_sigstore.go @@ -71,6 +71,17 @@ func PRSigstoreSignedWithFulcio(fulcio PRSigstoreSignedFulcio) PRSigstoreSignedO } } +// PRSigstoreSignedWithPKI specifies a value for the "pki" field when calling NewPRSigstoreSigned. +func PRSigstoreSignedWithPKI(p PRSigstoreSignedPKI) PRSigstoreSignedOption { + return func(pr *prSigstoreSigned) error { + if pr.PKI != nil { + return InvalidPolicyFormatError(`"pki" already specified`) + } + pr.PKI = p + return nil + } +} + // PRSigstoreSignedWithRekorPublicKeyPath specifies a value for the "rekorPublicKeyPath" field when calling NewPRSigstoreSigned. func PRSigstoreSignedWithRekorPublicKeyPath(rekorPublicKeyPath string) PRSigstoreSignedOption { return func(pr *prSigstoreSigned) error { @@ -159,8 +170,11 @@ func newPRSigstoreSigned(options ...PRSigstoreSignedOption) (*prSigstoreSigned, if res.Fulcio != nil { keySources++ } + if res.PKI != nil { + keySources++ + } if keySources != 1 { - return nil, InvalidPolicyFormatError("exactly one of keyPath, keyPaths, keyData, keyDatas and fulcio must be specified") + return nil, InvalidPolicyFormatError("exactly one of keyPath, keyPaths, keyData, keyDatas, fulcio, and pki must be specified") } rekorSources := 0 @@ -182,6 +196,9 @@ func newPRSigstoreSigned(options ...PRSigstoreSignedOption) (*prSigstoreSigned, if res.Fulcio != nil && rekorSources == 0 { return nil, InvalidPolicyFormatError("At least one of rekorPublickeyPath, rekorPublicKeyPaths, rekorPublickeyData and rekorPublicKeyDatas must be specified if fulcio is used") } + if res.PKI != nil && rekorSources > 0 { + return nil, InvalidPolicyFormatError("rekorPublickeyPath, rekorPublicKeyPaths, rekorPublickeyData and rekorPublicKeyDatas are not supported for pki") + } if res.SignedIdentity == nil { return nil, InvalidPolicyFormatError("signedIdentity not specified") @@ -218,9 +235,10 @@ var _ json.Unmarshaler = (*prSigstoreSigned)(nil) func (pr *prSigstoreSigned) UnmarshalJSON(data []byte) error { *pr = prSigstoreSigned{} var tmp prSigstoreSigned - var gotKeyPath, gotKeyPaths, gotKeyData, gotKeyDatas, gotFulcio bool + var gotKeyPath, gotKeyPaths, gotKeyData, gotKeyDatas, gotFulcio, gotPKI bool var gotRekorPublicKeyPath, gotRekorPublicKeyPaths, gotRekorPublicKeyData, gotRekorPublicKeyDatas bool var fulcio prSigstoreSignedFulcio + var pki prSigstoreSignedPKI var signedIdentity json.RawMessage if err := internal.ParanoidUnmarshalJSONObject(data, func(key string) any { switch key { @@ -253,6 +271,9 @@ func (pr *prSigstoreSigned) UnmarshalJSON(data []byte) error { case "rekorPublicKeyDatas": gotRekorPublicKeyDatas = true return &tmp.RekorPublicKeyDatas + case "pki": + gotPKI = true + return &pki case "signedIdentity": return &signedIdentity default: @@ -303,6 +324,9 @@ func (pr *prSigstoreSigned) UnmarshalJSON(data []byte) error { if gotRekorPublicKeyDatas { opts = append(opts, PRSigstoreSignedWithRekorPublicKeyDatas(tmp.RekorPublicKeyDatas)) } + if gotPKI { + opts = append(opts, PRSigstoreSignedWithPKI(&pki)) + } opts = append(opts, PRSigstoreSignedWithSignedIdentity(tmp.SignedIdentity)) res, err := newPRSigstoreSigned(opts...) @@ -440,3 +464,167 @@ func (f *prSigstoreSignedFulcio) UnmarshalJSON(data []byte) error { *f = *res return nil } + +// PRSigstoreSignedPKIOption is a way to pass values to NewPRSigstoreSignedPKI +type PRSigstoreSignedPKIOption func(*prSigstoreSignedPKI) error + +// PRSigstoreSignedPKIWithCARootsPath specifies a value for the "caRootsPath" field when calling NewPRSigstoreSignedPKI +func PRSigstoreSignedPKIWithCARootsPath(caRootsPath string) PRSigstoreSignedPKIOption { + return func(p *prSigstoreSignedPKI) error { + if p.CARootsPath != "" { + return InvalidPolicyFormatError(`"caRootsPath" already specified`) + } + p.CARootsPath = caRootsPath + return nil + } +} + +// PRSigstoreSignedPKIWithCARootsData specifies a value for the "caRootsData" field when calling NewPRSigstoreSignedPKI +func PRSigstoreSignedPKIWithCARootsData(caRootsData []byte) PRSigstoreSignedPKIOption { + return func(p *prSigstoreSignedPKI) error { + if p.CARootsData != nil { + return InvalidPolicyFormatError(`"caRootsData" already specified`) + } + p.CARootsData = caRootsData + return nil + } +} + +// PRSigstoreSignedPKIWithCAIntermediatesPath specifies a value for the "caIntermediatesPath" field when calling NewPRSigstoreSignedPKI +func PRSigstoreSignedPKIWithCAIntermediatesPath(caIntermediatesPath string) PRSigstoreSignedPKIOption { + return func(p *prSigstoreSignedPKI) error { + if p.CAIntermediatesPath != "" { + return InvalidPolicyFormatError(`"caIntermediatesPath" already specified`) + } + p.CAIntermediatesPath = caIntermediatesPath + return nil + } +} + +// PRSigstoreSignedPKIWithCAIntermediatesData specifies a value for the "caIntermediatesData" field when calling NewPRSigstoreSignedPKI +func PRSigstoreSignedPKIWithCAIntermediatesData(caIntermediatesData []byte) PRSigstoreSignedPKIOption { + return func(p *prSigstoreSignedPKI) error { + if p.CAIntermediatesData != nil { + return InvalidPolicyFormatError(`"caIntermediatesData" already specified`) + } + p.CAIntermediatesData = caIntermediatesData + return nil + } +} + +// PRSigstoreSignedPKIWithSubjectEmail specifies a value for the "subjectEmail" field when calling NewPRSigstoreSignedPKI +func PRSigstoreSignedPKIWithSubjectEmail(subjectEmail string) PRSigstoreSignedPKIOption { + return func(p *prSigstoreSignedPKI) error { + if p.SubjectEmail != "" { + return InvalidPolicyFormatError(`"subjectEmail" already specified`) + } + p.SubjectEmail = subjectEmail + return nil + } +} + +// PRSigstoreSignedPKIWithSubjectHostname specifies a value for the "subjectHostname" field when calling NewPRSigstoreSignedPKI +func PRSigstoreSignedPKIWithSubjectHostname(subjectHostname string) PRSigstoreSignedPKIOption { + return func(p *prSigstoreSignedPKI) error { + if p.SubjectHostname != "" { + return InvalidPolicyFormatError(`"subjectHostname" already specified`) + } + p.SubjectHostname = subjectHostname + return nil + } +} + +// newPRSigstoreSignedPKI is NewPRSigstoreSignedPKI, except it returns the private type +func newPRSigstoreSignedPKI(options ...PRSigstoreSignedPKIOption) (*prSigstoreSignedPKI, error) { + res := prSigstoreSignedPKI{} + for _, o := range options { + if err := o(&res); err != nil { + return nil, err + } + } + + if res.CARootsPath != "" && res.CARootsData != nil { + return nil, InvalidPolicyFormatError("caRootsPath and caRootsData cannot be used simultaneously") + } + if res.CARootsPath == "" && res.CARootsData == nil { + return nil, InvalidPolicyFormatError("At least one of caRootsPath and caRootsData must be specified") + } + + if res.CAIntermediatesPath != "" && res.CAIntermediatesData != nil { + return nil, InvalidPolicyFormatError("caIntermediatesPath and caIntermediatesData cannot be used simultaneously") + } + + if res.SubjectEmail == "" && res.SubjectHostname == "" { + return nil, InvalidPolicyFormatError("At least one of subjectEmail, subjectHostname must be specified") + } + + return &res, nil +} + +// NewPRSigstoreSignedPKI returns a PRSigstoreSignedPKI based on options. +func NewPRSigstoreSignedPKI(options ...PRSigstoreSignedPKIOption) (PRSigstoreSignedPKI, error) { + return newPRSigstoreSignedPKI(options...) +} + +// Compile-time check that prSigstoreSignedPKI implements json.Unmarshaler. +var _ json.Unmarshaler = (*prSigstoreSignedPKI)(nil) + +func (p *prSigstoreSignedPKI) UnmarshalJSON(data []byte) error { + *p = prSigstoreSignedPKI{} + var tmp prSigstoreSignedPKI + var gotCARootsPath, gotCARootsData, gotCAIntermediatesPath, gotCAIntermediatesData, gotSubjectEmail, gotSubjectHostname bool + if err := internal.ParanoidUnmarshalJSONObject(data, func(key string) any { + switch key { + case "caRootsPath": + gotCARootsPath = true + return &tmp.CARootsPath + case "caRootsData": + gotCARootsData = true + return &tmp.CARootsData + case "caIntermediatesPath": + gotCAIntermediatesPath = true + return &tmp.CAIntermediatesPath + case "caIntermediatesData": + gotCAIntermediatesData = true + return &tmp.CAIntermediatesData + case "subjectEmail": + gotSubjectEmail = true + return &tmp.SubjectEmail + case "subjectHostname": + gotSubjectHostname = true + return &tmp.SubjectHostname + default: + return nil + } + }); err != nil { + return err + } + + var opts []PRSigstoreSignedPKIOption + if gotCARootsPath { + opts = append(opts, PRSigstoreSignedPKIWithCARootsPath(tmp.CARootsPath)) + } + if gotCARootsData { + opts = append(opts, PRSigstoreSignedPKIWithCARootsData(tmp.CARootsData)) + } + if gotCAIntermediatesPath { + opts = append(opts, PRSigstoreSignedPKIWithCAIntermediatesPath(tmp.CAIntermediatesPath)) + } + if gotCAIntermediatesData { + opts = append(opts, PRSigstoreSignedPKIWithCAIntermediatesData(tmp.CAIntermediatesData)) + } + if gotSubjectEmail { + opts = append(opts, PRSigstoreSignedPKIWithSubjectEmail(tmp.SubjectEmail)) + } + if gotSubjectHostname { + opts = append(opts, PRSigstoreSignedPKIWithSubjectHostname(tmp.SubjectHostname)) + } + + res, err := newPRSigstoreSignedPKI(opts...) + if err != nil { + return err + } + + *p = *res + return nil +} diff --git a/vendor/github.com/containers/image/v5/signature/policy_eval_sigstore.go b/vendor/github.com/containers/image/v5/signature/policy_eval_sigstore.go index 9c553771cb..faede787a1 100644 --- a/vendor/github.com/containers/image/v5/signature/policy_eval_sigstore.go +++ b/vendor/github.com/containers/image/v5/signature/policy_eval_sigstore.go @@ -97,11 +97,64 @@ func (f *prSigstoreSignedFulcio) prepareTrustRoot() (*fulcioTrustRoot, error) { return &fulcio, nil } +// prepareTrustRoot creates a pkiTrustRoot from the input data. +// (This also prevents external implementations of this interface, ensuring that prSigstoreSignedPKI is the only one.) +func (p *prSigstoreSignedPKI) prepareTrustRoot() (*pkiTrustRoot, error) { + caRootsCertPEMs, err := loadBytesFromConfigSources(configBytesSources{ + inconsistencyErrorMessage: `Internal inconsistency: both "caRootsPath" and "caRootsData" specified`, + path: p.CARootsPath, + data: p.CARootsData, + }) + if err != nil { + return nil, err + } + if len(caRootsCertPEMs) != 1 { + return nil, errors.New(`Internal inconsistency: PKI specified with not exactly one of "caRootsPath" nor "caRootsData"`) + } + rootsCerts := x509.NewCertPool() + if ok := rootsCerts.AppendCertsFromPEM(caRootsCertPEMs[0]); !ok { + return nil, errors.New("error loading PKI CA Roots certificates") + } + pki := pkiTrustRoot{ + caRootsCertificates: rootsCerts, + subjectEmail: p.SubjectEmail, + subjectHostname: p.SubjectHostname, + } + caIntermediateCertPEMs, err := loadBytesFromConfigSources(configBytesSources{ + inconsistencyErrorMessage: `Internal inconsistency: both "caIntermediatesPath" and "caIntermediatesData" specified`, + path: p.CAIntermediatesPath, + data: p.CAIntermediatesData, + }) + if err != nil { + return nil, err + } + if caIntermediateCertPEMs != nil { + if len(caIntermediateCertPEMs) != 1 { + return nil, errors.New(`Internal inconsistency: PKI specified with invalid value from "caIntermediatesPath" or "caIntermediatesData"`) + } + intermediatePool := x509.NewCertPool() + trustedIntermediates, err := cryptoutils.UnmarshalCertificatesFromPEM(caIntermediateCertPEMs[0]) + if err != nil { + return nil, internal.NewInvalidSignatureError(fmt.Sprintf("loading trusted intermediate certificates: %v", err)) + } + for _, trustedIntermediateCert := range trustedIntermediates { + intermediatePool.AddCert(trustedIntermediateCert) + } + pki.caIntermediateCertificates = intermediatePool + } + + if err := pki.validate(); err != nil { + return nil, err + } + return &pki, nil +} + // sigstoreSignedTrustRoot contains an already parsed version of the prSigstoreSigned policy type sigstoreSignedTrustRoot struct { publicKeys []crypto.PublicKey fulcio *fulcioTrustRoot rekorPublicKeys []*ecdsa.PublicKey + pki *pkiTrustRoot } func (pr *prSigstoreSigned) prepareTrustRoot() (*sigstoreSignedTrustRoot, error) { @@ -166,6 +219,14 @@ func (pr *prSigstoreSigned) prepareTrustRoot() (*sigstoreSignedTrustRoot, error) } } + if pr.PKI != nil { + p, err := pr.PKI.prepareTrustRoot() + if err != nil { + return nil, err + } + res.pki = p + } + return &res, nil } @@ -189,13 +250,23 @@ func (pr *prSigstoreSigned) isSignatureAccepted(ctx context.Context, image priva } untrustedPayload := sig.UntrustedPayload() + keySources := 0 + if trustRoot.publicKeys != nil { + keySources++ + } + if trustRoot.fulcio != nil { + keySources++ + } + if trustRoot.pki != nil { + keySources++ + } + var publicKeys []crypto.PublicKey switch { - case trustRoot.publicKeys != nil && trustRoot.fulcio != nil: // newPRSigstoreSigned rejects such combinations. - return sarRejected, errors.New("Internal inconsistency: Both a public key and Fulcio CA specified") - case trustRoot.publicKeys == nil && trustRoot.fulcio == nil: // newPRSigstoreSigned rejects such combinations. - return sarRejected, errors.New("Internal inconsistency: Neither a public key nor a Fulcio CA specified") - + case keySources > 1: // newPRSigstoreSigned rejects more than one key sources. + return sarRejected, errors.New("Internal inconsistency: More than one of public key, Fulcio, or PKI specified") + case keySources == 0: // newPRSigstoreSigned rejects empty key sources. + return sarRejected, errors.New("Internal inconsistency: A public key, Fulcio, or PKI must be specified.") case trustRoot.publicKeys != nil: if trustRoot.rekorPublicKeys != nil { untrustedSET, ok := untrustedAnnotations[signature.SigstoreSETAnnotationKey] @@ -254,6 +325,24 @@ func (pr *prSigstoreSigned) isSignatureAccepted(ctx context.Context, image priva return sarRejected, err } publicKeys = []crypto.PublicKey{pk} + + case trustRoot.pki != nil: + if trustRoot.rekorPublicKeys != nil { // newPRSigstoreSigned rejects such combinations. + return sarRejected, errors.New("Internal inconsistency: PKI specified with a Rekor public key") + } + untrustedCert, ok := untrustedAnnotations[signature.SigstoreCertificateAnnotationKey] + if !ok { + return sarRejected, fmt.Errorf("missing %s annotation", signature.SigstoreCertificateAnnotationKey) + } + var untrustedIntermediateChainBytes []byte + if untrustedIntermediateChain, ok := untrustedAnnotations[signature.SigstoreIntermediateCertificateChainAnnotationKey]; ok { + untrustedIntermediateChainBytes = []byte(untrustedIntermediateChain) + } + pk, err := verifyPKI(trustRoot.pki, []byte(untrustedCert), untrustedIntermediateChainBytes) + if err != nil { + return sarRejected, err + } + publicKeys = []crypto.PublicKey{pk} } if len(publicKeys) == 0 { diff --git a/vendor/github.com/containers/image/v5/signature/policy_types.go b/vendor/github.com/containers/image/v5/signature/policy_types.go index 32aa1c0ad4..2db0c45914 100644 --- a/vendor/github.com/containers/image/v5/signature/policy_types.go +++ b/vendor/github.com/containers/image/v5/signature/policy_types.go @@ -111,16 +111,16 @@ type prSignedBaseLayer struct { type prSigstoreSigned struct { prCommon - // KeyPath is a pathname to a local file containing the trusted key. Exactly one of KeyPath, KeyPaths, KeyData, KeyDatas and Fulcio must be specified. + // KeyPath is a pathname to a local file containing the trusted key. Exactly one of KeyPath, KeyPaths, KeyData, KeyDatas, Fulcio, and PKI must be specified. KeyPath string `json:"keyPath,omitempty"` - // KeyPaths is a set of pathnames to local files containing the trusted key(s). Exactly one of KeyPath, KeyPaths, KeyData, KeyDatas and Fulcio must be specified. + // KeyPaths is a set of pathnames to local files containing the trusted key(s). Exactly one of KeyPath, KeyPaths, KeyData, KeyDatas, Fulcio, and PKI must be specified. KeyPaths []string `json:"keyPaths,omitempty"` - // KeyData contains the trusted key, base64-encoded. Exactly one of KeyPath, KeyPaths, KeyData, KeyDatas and Fulcio must be specified. + // KeyData contains the trusted key, base64-encoded. Exactly one of KeyPath, KeyPaths, KeyData, KeyDatas, Fulcio, and PKI must be specified. KeyData []byte `json:"keyData,omitempty"` - // KeyDatas is a set of trusted keys, base64-encoded. Exactly one of KeyPath, KeyPaths, KeyData, KeyDatas and Fulcio must be specified. + // KeyDatas is a set of trusted keys, base64-encoded. Exactly one of KeyPath, KeyPaths, KeyData, KeyDatas, Fulcio, and PKI must be specified. KeyDatas [][]byte `json:"keyDatas,omitempty"` - // Fulcio specifies which Fulcio-generated certificates are accepted. Exactly one of KeyPath, KeyPaths, KeyData, KeyDatas and Fulcio must be specified. + // Fulcio specifies which Fulcio-generated certificates are accepted. Exactly one of KeyPath, KeyPaths, KeyData, KeyDatas, Fulcio, and PKI must be specified. // If Fulcio is specified, one of RekorPublicKeyPath or RekorPublicKeyData must be specified as well. Fulcio PRSigstoreSignedFulcio `json:"fulcio,omitempty"` @@ -141,6 +141,9 @@ type prSigstoreSigned struct { // otherwise it is optional (and Rekor inclusion is not required if a Rekor public key is not specified). RekorPublicKeyDatas [][]byte `json:"rekorPublicKeyDatas,omitempty"` + // PKI specifies which PKI-generated certificates are accepted. Exactly one of KeyPath, KeyPaths, KeyData, KeyDatas, Fulcio, and PKI must be specified. + PKI PRSigstoreSignedPKI `json:"pki,omitempty"` + // SignedIdentity specifies what image identity the signature must be claiming about the image. // Defaults to "matchRepoDigestOrExact" if not specified. // Note that /usr/bin/cosign interoperability might require using repo-only matching. @@ -167,6 +170,30 @@ type prSigstoreSignedFulcio struct { SubjectEmail string `json:"subjectEmail,omitempty"` } +// PRSigstoreSignedPKI contains PKI configuration options for a "sigstoreSigned" PolicyRequirement. +type PRSigstoreSignedPKI interface { + // prepareTrustRoot creates a pkiTrustRoot from the input data. + // (This also prevents external implementations of this interface, ensuring that prSigstoreSignedPKI is the only one.) + prepareTrustRoot() (*pkiTrustRoot, error) +} + +// prSigstoreSignedPKI contains non-fulcio certificate PKI configuration options for prSigstoreSigned +type prSigstoreSignedPKI struct { + // CARootsPath a path to a file containing accepted CA root certificates, in PEM format. Exactly one of CARootsPath and CARootsData must be specified. + CARootsPath string `json:"caRootsPath"` + // CARootsData contains accepted CA root certificates in PEM format, all of that base64-encoded. Exactly one of CARootsPath and CARootsData must be specified. + CARootsData []byte `json:"caRootsData"` + // CAIntermediatesPath a path to a file containing accepted CA intermediate certificates, in PEM format. Only one of CAIntermediatesPath or CAIntermediatesData can be specified, not both. + CAIntermediatesPath string `json:"caIntermediatesPath"` + // CAIntermediatesData contains accepted CA intermediate certificates in PEM format, all of that base64-encoded. Only one of CAIntermediatesPath or CAIntermediatesData can be specified, not both. + CAIntermediatesData []byte `json:"caIntermediatesData"` + + // SubjectEmail specifies the expected email address imposed on the subject to which the certificate was issued. At least one of SubjectEmail and SubjectHostname must be specified. + SubjectEmail string `json:"subjectEmail"` + // SubjectHostname specifies the expected hostname imposed on the subject to which the certificate was issued. At least one of SubjectEmail and SubjectHostname must be specified. + SubjectHostname string `json:"subjectHostname"` +} + // PolicyReferenceMatch specifies a set of image identities accepted in PolicyRequirement. // The type is public, but its implementation is private. diff --git a/vendor/github.com/containers/image/v5/version/version.go b/vendor/github.com/containers/image/v5/version/version.go index 0322755ba1..cb61f56294 100644 --- a/vendor/github.com/containers/image/v5/version/version.go +++ b/vendor/github.com/containers/image/v5/version/version.go @@ -8,7 +8,7 @@ const ( // VersionMinor is for functionality in a backwards-compatible manner VersionMinor = 34 // VersionPatch is for backwards-compatible bug fixes - VersionPatch = 0 + VersionPatch = 1 // VersionDev indicates development branch. Releases will be empty string. VersionDev = "" diff --git a/vendor/github.com/go-jose/go-jose/v3/jwe.go b/vendor/github.com/go-jose/go-jose/v3/jwe.go index 4267ac7502..1ba4ae0c00 100644 --- a/vendor/github.com/go-jose/go-jose/v3/jwe.go +++ b/vendor/github.com/go-jose/go-jose/v3/jwe.go @@ -202,10 +202,11 @@ func (parsed *rawJSONWebEncryption) sanitized() (*JSONWebEncryption, error) { // parseEncryptedCompact parses a message in compact format. func parseEncryptedCompact(input string) (*JSONWebEncryption, error) { - parts := strings.Split(input, ".") - if len(parts) != 5 { + // Five parts is four separators + if strings.Count(input, ".") != 4 { return nil, fmt.Errorf("go-jose/go-jose: compact JWE format must have five parts") } + parts := strings.SplitN(input, ".", 5) rawProtected, err := base64URLDecode(parts[0]) if err != nil { diff --git a/vendor/github.com/go-jose/go-jose/v3/jws.go b/vendor/github.com/go-jose/go-jose/v3/jws.go index e37007dbb8..401fc18ac4 100644 --- a/vendor/github.com/go-jose/go-jose/v3/jws.go +++ b/vendor/github.com/go-jose/go-jose/v3/jws.go @@ -275,10 +275,11 @@ func (parsed *rawJSONWebSignature) sanitized() (*JSONWebSignature, error) { // parseSignedCompact parses a message in compact format. func parseSignedCompact(input string, payload []byte) (*JSONWebSignature, error) { - parts := strings.Split(input, ".") - if len(parts) != 3 { + // Three parts is two separators + if strings.Count(input, ".") != 2 { return nil, fmt.Errorf("go-jose/go-jose: compact JWS format must have three parts") } + parts := strings.SplitN(input, ".", 3) if parts[1] != "" && payload != nil { return nil, fmt.Errorf("go-jose/go-jose: payload is not detached") diff --git a/vendor/github.com/go-jose/go-jose/v4/CONTRIBUTING.md b/vendor/github.com/go-jose/go-jose/v4/CONTRIBUTING.md index b63e1f8fee..4b4805add6 100644 --- a/vendor/github.com/go-jose/go-jose/v4/CONTRIBUTING.md +++ b/vendor/github.com/go-jose/go-jose/v4/CONTRIBUTING.md @@ -7,9 +7,3 @@ When submitting code, please make every effort to follow existing conventions and style in order to keep the code as readable as possible. Please also make sure all tests pass by running `go test`, and format your code with `go fmt`. We also recommend using `golint` and `errcheck`. - -Before your code can be accepted into the project you must also sign the -Individual Contributor License Agreement. We use [cla-assistant.io][1] and you -will be prompted to sign once a pull request is opened. - -[1]: https://cla-assistant.io/ diff --git a/vendor/github.com/go-jose/go-jose/v4/README.md b/vendor/github.com/go-jose/go-jose/v4/README.md index 79a7c5ecc8..02b5749546 100644 --- a/vendor/github.com/go-jose/go-jose/v4/README.md +++ b/vendor/github.com/go-jose/go-jose/v4/README.md @@ -9,14 +9,6 @@ Package jose aims to provide an implementation of the Javascript Object Signing and Encryption set of standards. This includes support for JSON Web Encryption, JSON Web Signature, and JSON Web Token standards. -**Disclaimer**: This library contains encryption software that is subject to -the U.S. Export Administration Regulations. You may not export, re-export, -transfer or download this code or any part of it in violation of any United -States law, directive or regulation. In particular this software may not be -exported or re-exported in any form or on any media to Iran, North Sudan, -Syria, Cuba, or North Korea, or to denied persons or entities mentioned on any -US maintained blocked list. - ## Overview The implementation follows the @@ -109,6 +101,6 @@ allows attaching a key id. Examples can be found in the Godoc reference for this package. The -[`jose-util`](https://github.com/go-jose/go-jose/tree/v4/jose-util) +[`jose-util`](https://github.com/go-jose/go-jose/tree/main/jose-util) subdirectory also contains a small command-line utility which might be useful as an example as well. diff --git a/vendor/github.com/go-jose/go-jose/v4/jwe.go b/vendor/github.com/go-jose/go-jose/v4/jwe.go index 89f03ee3e1..9f1322dccc 100644 --- a/vendor/github.com/go-jose/go-jose/v4/jwe.go +++ b/vendor/github.com/go-jose/go-jose/v4/jwe.go @@ -288,10 +288,11 @@ func ParseEncryptedCompact( keyAlgorithms []KeyAlgorithm, contentEncryption []ContentEncryption, ) (*JSONWebEncryption, error) { - parts := strings.Split(input, ".") - if len(parts) != 5 { + // Five parts is four separators + if strings.Count(input, ".") != 4 { return nil, fmt.Errorf("go-jose/go-jose: compact JWE format must have five parts") } + parts := strings.SplitN(input, ".", 5) rawProtected, err := base64.RawURLEncoding.DecodeString(parts[0]) if err != nil { diff --git a/vendor/github.com/go-jose/go-jose/v4/jwk.go b/vendor/github.com/go-jose/go-jose/v4/jwk.go index 8a52842106..9e57e93ba2 100644 --- a/vendor/github.com/go-jose/go-jose/v4/jwk.go +++ b/vendor/github.com/go-jose/go-jose/v4/jwk.go @@ -239,10 +239,10 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) { keyPub = key } } else { - err = fmt.Errorf("go-jose/go-jose: unknown curve %s'", raw.Crv) + return fmt.Errorf("go-jose/go-jose: unknown curve %s'", raw.Crv) } default: - err = fmt.Errorf("go-jose/go-jose: unknown json web key type '%s'", raw.Kty) + return fmt.Errorf("go-jose/go-jose: unknown json web key type '%s'", raw.Kty) } if err != nil { diff --git a/vendor/github.com/go-jose/go-jose/v4/jws.go b/vendor/github.com/go-jose/go-jose/v4/jws.go index 3a912301af..d09d8ba507 100644 --- a/vendor/github.com/go-jose/go-jose/v4/jws.go +++ b/vendor/github.com/go-jose/go-jose/v4/jws.go @@ -327,10 +327,11 @@ func parseSignedCompact( payload []byte, signatureAlgorithms []SignatureAlgorithm, ) (*JSONWebSignature, error) { - parts := strings.Split(input, ".") - if len(parts) != 3 { + // Three parts is two separators + if strings.Count(input, ".") != 2 { return nil, fmt.Errorf("go-jose/go-jose: compact JWS format must have three parts") } + parts := strings.SplitN(input, ".", 3) if parts[1] != "" && payload != nil { return nil, fmt.Errorf("go-jose/go-jose: payload is not detached") diff --git a/vendor/modules.txt b/vendor/modules.txt index b86bb34343..a440bdb047 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -147,7 +147,7 @@ github.com/containernetworking/cni/pkg/version # github.com/containernetworking/plugins v1.5.1 ## explicit; go 1.20 github.com/containernetworking/plugins/pkg/ns -# github.com/containers/buildah v1.39.0 +# github.com/containers/buildah v1.39.2 ## explicit; go 1.22.8 github.com/containers/buildah github.com/containers/buildah/bind @@ -179,7 +179,7 @@ github.com/containers/buildah/pkg/sshagent github.com/containers/buildah/pkg/util github.com/containers/buildah/pkg/volumes github.com/containers/buildah/util -# github.com/containers/common v0.62.0 +# github.com/containers/common v0.62.1 ## explicit; go 1.22.8 github.com/containers/common/internal github.com/containers/common/internal/attributedstring @@ -252,7 +252,7 @@ github.com/containers/conmon/runner/config # github.com/containers/gvisor-tap-vsock v0.8.3 ## explicit; go 1.22.0 github.com/containers/gvisor-tap-vsock/pkg/types -# github.com/containers/image/v5 v5.34.0 +# github.com/containers/image/v5 v5.34.1 ## explicit; go 1.22.8 github.com/containers/image/v5/copy github.com/containers/image/v5/directory @@ -557,12 +557,12 @@ github.com/gin-gonic/gin/binding github.com/gin-gonic/gin/internal/bytesconv github.com/gin-gonic/gin/internal/json github.com/gin-gonic/gin/render -# github.com/go-jose/go-jose/v3 v3.0.3 +# github.com/go-jose/go-jose/v3 v3.0.4 ## explicit; go 1.12 github.com/go-jose/go-jose/v3 github.com/go-jose/go-jose/v3/cipher github.com/go-jose/go-jose/v3/json -# github.com/go-jose/go-jose/v4 v4.0.4 +# github.com/go-jose/go-jose/v4 v4.0.5 ## explicit; go 1.21 github.com/go-jose/go-jose/v4 github.com/go-jose/go-jose/v4/cipher From a28e9fa3b894b28843747136559ecbf5628b07e3 Mon Sep 17 00:00:00 2001 From: Matt Heon Date: Thu, 27 Feb 2025 10:38:53 -0500 Subject: [PATCH 46/58] Create quota before _data dir for volumes This resolves an ordering issue that prevented quotas from being applied. XFS quotas are applied recursively, but only for subdirectories created after the quota is applied; if we create `_data` before the quota, and then use `_data` for all data in the volume, the quota will never be used by the volume. Also, add a test that volume quotas are working as designed using an XFS formatted loop device in the system tests. This should prevent any further regressions on basic quota functionality, such as quotas being shared between volumes. Fixes #25368 Fixes https://issues.redhat.com/browse/RHEL-82198 Fixes https://issues.redhat.com/browse/RHEL-82199 Signed-off-by: Matt Heon --- libpod/runtime_volume_common.go | 27 ++++++----- rpm/podman.spec | 1 + test/system/161-volume-quotas.bats | 78 ++++++++++++++++++++++++++++++ test/system/README.md | 1 + 4 files changed, 96 insertions(+), 11 deletions(-) create mode 100644 test/system/161-volume-quotas.bats diff --git a/libpod/runtime_volume_common.go b/libpod/runtime_volume_common.go index f215667c16..c5cee9b997 100644 --- a/libpod/runtime_volume_common.go +++ b/libpod/runtime_volume_common.go @@ -168,16 +168,11 @@ func (r *Runtime) newVolume(ctx context.Context, noCreatePluginVolume bool, opti if err := idtools.SafeChown(volPathRoot, volume.config.UID, volume.config.GID); err != nil { return nil, fmt.Errorf("chowning volume directory %q to %d:%d: %w", volPathRoot, volume.config.UID, volume.config.GID, err) } - fullVolPath := filepath.Join(volPathRoot, "_data") - if err := os.MkdirAll(fullVolPath, 0755); err != nil { - return nil, fmt.Errorf("creating volume directory %q: %w", fullVolPath, err) - } - if err := idtools.SafeChown(fullVolPath, volume.config.UID, volume.config.GID); err != nil { - return nil, fmt.Errorf("chowning volume directory %q to %d:%d: %w", fullVolPath, volume.config.UID, volume.config.GID, err) - } - if err := LabelVolumePath(fullVolPath, volume.config.MountLabel); err != nil { - return nil, err - } + + // Setting quotas must happen *before* the _data inner directory + // is created, as the volume must be empty for the quota to be + // properly applied - if any subdirectories exist before the + // quota is applied, the quota will not be applied to them. switch { case volume.config.DisableQuota: if volume.config.Size > 0 || volume.config.Inodes > 0 { @@ -206,10 +201,20 @@ func (r *Runtime) newVolume(ctx context.Context, noCreatePluginVolume bool, opti // subdirectory - so the quota ID assignment logic works // properly. if err := q.SetQuota(volPathRoot, quota); err != nil { - return nil, fmt.Errorf("failed to set size quota size=%d inodes=%d for volume directory %q: %w", volume.config.Size, volume.config.Inodes, fullVolPath, err) + return nil, fmt.Errorf("failed to set size quota size=%d inodes=%d for volume directory %q: %w", volume.config.Size, volume.config.Inodes, volPathRoot, err) } } + fullVolPath := filepath.Join(volPathRoot, "_data") + if err := os.MkdirAll(fullVolPath, 0755); err != nil { + return nil, fmt.Errorf("creating volume directory %q: %w", fullVolPath, err) + } + if err := idtools.SafeChown(fullVolPath, volume.config.UID, volume.config.GID); err != nil { + return nil, fmt.Errorf("chowning volume directory %q to %d:%d: %w", fullVolPath, volume.config.UID, volume.config.GID, err) + } + if err := LabelVolumePath(fullVolPath, volume.config.MountLabel); err != nil { + return nil, err + } volume.config.MountPoint = fullVolPath } diff --git a/rpm/podman.spec b/rpm/podman.spec index b6a60cedfa..d6eaf9ae6e 100644 --- a/rpm/podman.spec +++ b/rpm/podman.spec @@ -151,6 +151,7 @@ Requires: openssl Requires: socat Requires: buildah Requires: gnupg +Requires: xfsprogs %description tests %{summary} diff --git a/test/system/161-volume-quotas.bats b/test/system/161-volume-quotas.bats new file mode 100644 index 0000000000..8019499509 --- /dev/null +++ b/test/system/161-volume-quotas.bats @@ -0,0 +1,78 @@ +#!/usr/bin/env bats -*- bats -*- +# +# podman volume XFS quota tests +# +# bats file_tags=distro-integration +# + +load helpers + +function setup() { + basic_setup + + run_podman '?' volume rm -a +} + +function teardown() { + run_podman '?' rm -af -t 0 + run_podman '?' volume rm -a + + loop=$PODMAN_TMPDIR/disk.img + vol_path=$PODMAN_TMPDIR/volpath + if [ -f ${loop} ]; then + if [ -d ${vol_path} ]; then + if mountpoint ${vol_path}; then + umount "$vol_path" + fi + rm -rf "$vol_path" + fi + + while read path dev; do + if [[ "$path" == "$loop" ]]; then + losetup -d $dev + fi + done < <(losetup -l --noheadings --output BACK-FILE,NAME) + rm -f $loop + fi + + basic_teardown +} + +@test "podman volumes with XFS quotas" { + skip_if_rootless "Quotas are only possible with root" + skip_if_remote "Requires --root flag, not possible w/ remote" + + # Minimum XFS filesystem size is 300mb + loop=$PODMAN_TMPDIR/disk.img + fallocate -l 300m ${loop} + run -0 losetup -f --show $loop + loop_dev="$output" + mkfs.xfs $loop_dev + + safe_opts=$(podman_isolation_opts ${PODMAN_TMPDIR}) + vol_path=$PODMAN_TMPDIR/volpath + mkdir -p $vol_path + safe_opts="$safe_opts --volumepath=$vol_path" + mount -t xfs -o defaults,pquota $loop_dev $vol_path + + vol_one="testvol1" + run_podman $safe_opts volume create --opt o=size=2m $vol_one + + vol_two="testvol2" + run_podman $safe_opts volume create --opt o=size=4m $vol_two + + ctrname="testctr" + run_podman $safe_opts run -d --name=$ctrname -i -v $vol_one:/one -v $vol_two:/two $IMAGE top + + run_podman $safe_opts exec $ctrname dd if=/dev/zero of=/one/oneMB bs=1M count=1 + run_podman 1 $safe_opts exec $ctrname dd if=/dev/zero of=/one/twoMB bs=1M count=1 + assert "$output" =~ "No space left on device" + run_podman $safe_opts exec $ctrname dd if=/dev/zero of=/two/threeMB bs=1M count=3 + run_podman 1 $safe_opts exec $ctrname dd if=/dev/zero of=/two/oneMB bs=1M count=1 + assert "$output" =~ "No space left on device" + + run_podman $safe_opts rm -f -t 0 $ctrname + run_podman $safe_opts volume rm -af +} + +# vim: filetype=sh diff --git a/test/system/README.md b/test/system/README.md index 1800a1fd17..fdd873a655 100644 --- a/test/system/README.md +++ b/test/system/README.md @@ -92,6 +92,7 @@ Requirements - socat - buildah - gnupg +- xfsprogs Further Details From 56bfad1b0df1a79c1cdee0d03caccf1fb10c82bf Mon Sep 17 00:00:00 2001 From: Brent Baude Date: Tue, 18 Feb 2025 08:40:52 -0600 Subject: [PATCH 47/58] [v5.4-rhel] wire up --retry-delay for artifact pull fixed a bug in the artifact code where --retry-delay was being discarded. Fixes: https://issues.redhat.com/browse/RUN-2511 Fixes: https://issues.redhat.com/browse/RHEL-80259, https://issues.redhat.com/browse/RHEL-80260 Signed-off-by: Brent Baude Signed-off-by: tomsweeneyredhat --- cmd/podman/artifact/pull.go | 22 ---------------------- pkg/domain/infra/abi/artifact.go | 8 +++++++- test/e2e/artifact_test.go | 7 +++++++ 3 files changed, 14 insertions(+), 23 deletions(-) diff --git a/cmd/podman/artifact/pull.go b/cmd/podman/artifact/pull.go index 12d78c46fb..f6d0e27304 100644 --- a/cmd/podman/artifact/pull.go +++ b/cmd/podman/artifact/pull.go @@ -116,28 +116,6 @@ func artifactPull(cmd *cobra.Command, args []string) error { } } - // TODO Once we have a decision about the flag removal above, this should be safe to delete - /* - platform, err := cmd.Flags().GetString("platform") - if err != nil { - return err - } - if platform != "" { - if pullOptions.Arch != "" || pullOptions.OS != "" { - return errors.New("--platform option can not be specified with --arch or --os") - } - - specs := strings.Split(platform, "/") - pullOptions.OS = specs[0] // may be empty - if len(specs) > 1 { - pullOptions.Arch = specs[1] - if len(specs) > 2 { - pullOptions.Variant = specs[2] - } - } - } - */ - if pullOptions.CredentialsCLI != "" { creds, err := util.ParseRegistryCreds(pullOptions.CredentialsCLI) if err != nil { diff --git a/pkg/domain/infra/abi/artifact.go b/pkg/domain/infra/abi/artifact.go index fe1c3c12c8..6145c7b59b 100644 --- a/pkg/domain/infra/abi/artifact.go +++ b/pkg/domain/infra/abi/artifact.go @@ -63,12 +63,18 @@ func (ir *ImageEngine) ArtifactPull(ctx context.Context, name string, opts entit pullOptions.CertDirPath = opts.CertDirPath pullOptions.Username = opts.Username pullOptions.Password = opts.Password - // pullOptions.Architecture = opts.Arch pullOptions.SignaturePolicyPath = opts.SignaturePolicyPath pullOptions.InsecureSkipTLSVerify = opts.InsecureSkipTLSVerify pullOptions.Writer = opts.Writer pullOptions.OciDecryptConfig = opts.OciDecryptConfig pullOptions.MaxRetries = opts.MaxRetries + if opts.RetryDelay != "" { + duration, err := time.ParseDuration(opts.RetryDelay) + if err != nil { + return nil, err + } + pullOptions.RetryDelay = &duration + } if !opts.Quiet && pullOptions.Writer == nil { pullOptions.Writer = os.Stderr diff --git a/test/e2e/artifact_test.go b/test/e2e/artifact_test.go index c3cfe504eb..e6b5466f9a 100644 --- a/test/e2e/artifact_test.go +++ b/test/e2e/artifact_test.go @@ -132,6 +132,13 @@ var _ = Describe("Podman artifact", func() { }) It("podman artifact push and pull", func() { + // Before starting a registry, try to pull a bogus image from a bogus registry + // using retry-delay + retrySession := podmanTest.Podman([]string{"artifact", "pull", "--retry", "1", "--retry-delay", "100ms", "127.0.0.1/mybadimagename"}) + retrySession.WaitWithDefaultTimeout() + Expect(retrySession).Should(ExitWithError(125, "connect: connection refused")) + Expect(retrySession.ErrorToString()).To(ContainSubstring("retrying in 100ms ...")) + artifact1File, err := createArtifactFile(1024) Expect(err).ToNot(HaveOccurred()) From 6753a57e6cceca13b5dfd778fd228d9833f7b928 Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Wed, 26 Feb 2025 15:49:09 -0800 Subject: [PATCH 48/58] [v5.4-rhel] podman run: fix --pids-limit -1 wrt runc Since commit c25cc7230 ("Allow a value of -1 to set unlimited pids limit") podman converts the pids-limit value of -1 to 0 for OCI spec. Unfortunately, different runtimes (crun and runc) treat pids.limit=0 differently, and the runtime-spec definition is somewhat vague (see [1]). Long term fix belongs to runtime-spec and then runtimes should follow it. Short term fix is do not convert -1 to 0 (as all runtimes treat -1 as unlimited). [NO NEW TESTS NEEDED] -- this is covered by test added in commit 553e53d44. Fixes: https://issues.redhat.com/browse/RHEL-80973 [1]: https://github.com/opencontainers/runc/issues/4014#issuecomment-1888185352 Fixes: https://issues.redhat.com/browse/RHEL-82424, https://issues.redhat.com/browse/RHEL-82425 In the RHEL 9.6 and 10.0 ZeroDay streams Signed-off-by: Kir Kolyshkin Signed-off-by: tomsweeneyredhat --- cmd/podman/containers/create.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cmd/podman/containers/create.go b/cmd/podman/containers/create.go index 921e904610..4ac53095c2 100644 --- a/cmd/podman/containers/create.go +++ b/cmd/podman/containers/create.go @@ -212,10 +212,6 @@ func replaceContainer(name string) error { func createOrUpdateFlags(cmd *cobra.Command, vals *entities.ContainerCreateOptions) error { if cmd.Flags().Changed("pids-limit") { val := cmd.Flag("pids-limit").Value.String() - // Convert -1 to 0, so that -1 maps to unlimited pids limit - if val == "-1" { - val = "0" - } pidsLimit, err := strconv.ParseInt(val, 10, 32) if err != nil { return err From 5f8299513c3cfc2e2d5d3e3c39311fd44dc1896f Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Tue, 11 Mar 2025 19:17:51 +0100 Subject: [PATCH 49/58] cirrus: only run single build Update cirrus.yml to the latest image based of 5.4-rhel, then disable validate as there no point for it when we do backports. And only perform a single build on the f41. Signed-off-by: Paul Holzinger --- .cirrus.yml | 91 ++++++++++++++++------------------------------------- 1 file changed, 27 insertions(+), 64 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index d398521335..9fe53d37b2 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -78,49 +78,6 @@ gcp_credentials: ENCRYPTED[a28959877b2c9c36f151781b0a05407218cda646c7d047fc556e4 aws_credentials: ENCRYPTED[4ca070bffe28eb9b27d63c568b52970dd46f119c3a83b8e443241e895dbf1737580b4d84eed27a311a2b74287ef9f79f] - -validate-source_task: - name: "Validate source code changes" - alias: validate-source - # This task is primarily intended to catch human-errors early on, in a - # PR context. Skip running it everywhere else. - only_if: &is_pr "$CIRRUS_PR != ''" - gce_instance: - image_project: libpod-218412 - zone: "us-central1-a" - # golangci-lint is a very, very hungry beast. - cpu: 8 - memory: "16Gb" - # Required to be 200gig, do not modify - has i/o performance impact - # according to gcloud CLI tool warning messages. - disk: 200 - image_name: "${FEDORA_CACHE_IMAGE_NAME}" # from stdenvars - env: - TEST_FLAVOR: validate-source - # NOTE: The default way Cirrus-CI clones is *NOT* compatible with - # environment expectations in contrib/cirrus/lib.sh. Specifically - # the 'origin' remote must be defined, and all remote branches/tags - # must be available for reference from CI scripts. - clone_script: &full_clone | - set -exo pipefail - cd / - rm -rf $CIRRUS_WORKING_DIR - mkdir -p $CIRRUS_WORKING_DIR - git clone --recursive --branch=$DEST_BRANCH https://x-access-token:${CIRRUS_REPO_CLONE_TOKEN}@github.com/${CIRRUS_REPO_FULL_NAME}.git $CIRRUS_WORKING_DIR - cd $CIRRUS_WORKING_DIR - git remote update origin - if [[ -n "$CIRRUS_PR" ]]; then # running for a PR - git fetch origin pull/$CIRRUS_PR/head:pull/$CIRRUS_PR - git checkout pull/$CIRRUS_PR - else - git reset --hard $CIRRUS_CHANGE_IN_REPO - fi - # Standard setup stage call, used by nearly every task in CI. - setup_script: &setup '$GOSRC/$SCRIPT_BASE/setup_environment.sh' - # Standard main execution stage call, used by nearly every task in CI. - main_script: &main '/usr/bin/time --verbose --output="$STATS_LOGFILE" $GOSRC/$SCRIPT_BASE/runner.sh' - - # N/B: This matrix of build tasks are critical to CI, along with the following # aarch64 task. They build binaries for all CI platforms, and versions. On # success, the contents of the repository are preserved as an artifact for @@ -145,32 +102,39 @@ build_task: # Not used here, is used in other tasks VM_IMAGE_NAME: ${FEDORA_CACHE_IMAGE_NAME} CTR_FQIN: ${FEDORA_CONTAINER_FQIN} - - env: - DISTRO_NV: ${PRIOR_FEDORA_NAME} - VM_IMAGE_NAME: ${PRIOR_FEDORA_CACHE_IMAGE_NAME} - CTR_FQIN: ${PRIOR_FEDORA_CONTAINER_FQIN} - CI_DESIRED_DATABASE: boltdb - CI_DESIRED_STORAGE: vfs - - env: - <<: *stdenvars - DISTRO_NV: ${RAWHIDE_NAME} - VM_IMAGE_NAME: ${RAWHIDE_CACHE_IMAGE_NAME} - CI_DESIRED_STORAGE: composefs - CTR_FQIN: "" - - env: - DISTRO_NV: ${DEBIAN_NAME} - VM_IMAGE_NAME: ${DEBIAN_CACHE_IMAGE_NAME} env: TEST_FLAVOR: build - clone_script: *full_clone + # NOTE: The default way Cirrus-CI clones is *NOT* compatible with + # environment expectations in contrib/cirrus/lib.sh. Specifically + # the 'origin' remote must be defined, and all remote branches/tags + # must be available for reference from CI scripts. + clone_script: &full_clone | + set -exo pipefail + cd / + rm -rf $CIRRUS_WORKING_DIR + mkdir -p $CIRRUS_WORKING_DIR + if [[ -z "$CIRRUS_PR" ]]; then + DEST_BRANCH="$CIRRUS_BRANCH" + else + DEST_BRANCH="$CIRRUS_BASE_BRANCH" + fi + git clone --recursive --branch=$DEST_BRANCH https://x-access-token:${CIRRUS_REPO_CLONE_TOKEN}@github.com/${CIRRUS_REPO_FULL_NAME}.git $CIRRUS_WORKING_DIR + cd $CIRRUS_WORKING_DIR + git remote update origin + if [[ -n "$CIRRUS_PR" ]]; then # running for a PR + git fetch origin pull/$CIRRUS_PR/head:pull/$CIRRUS_PR + git checkout pull/$CIRRUS_PR + else + git reset --hard $CIRRUS_CHANGE_IN_REPO + fi # Attempt to prevent flakes by confirming basic environment expectations, # network service connectivity and essential container image availability. # TODO: Rename to "ci-sanity" and move into task that runs in parallel to build prebuild_script: &prebuild $SCRIPT_BASE/prebuild.sh - setup_script: *setup - # Attempt to prevent flakes by confirming automation environment and - # all required external/3rd-party services are available and functional. - main_script: *main + # Standard setup stage call, used by nearly every task in CI. + setup_script: &setup '$GOSRC/$SCRIPT_BASE/setup_environment.sh' + # Standard main execution stage call, used by nearly every task in CI. + main_script: &main '/usr/bin/time --verbose --output="$STATS_LOGFILE" $GOSRC/$SCRIPT_BASE/runner.sh' # Attempt to catch code-quality and vendoring problems early. postbuild_script: &postbuild $SCRIPT_BASE/postbuild.sh # Cirrus-CI is very slow uploading one file at time, and the repo contains @@ -252,7 +216,6 @@ success_task: alias: success # N/B: ALL tasks must be listed here, minus their '_task' suffix. depends_on: - - validate-source - build - build_aarch64 - meta From 64aaa455fb839fc76f09f2076589835b8825e055 Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Tue, 11 Mar 2025 19:17:51 +0100 Subject: [PATCH 50/58] remove packit jobs Signed-off-by: Paul Holzinger --- .packit.yaml | 126 --------------------------------------------------- 1 file changed, 126 deletions(-) delete mode 100644 .packit.yaml diff --git a/.packit.yaml b/.packit.yaml deleted file mode 100644 index 637e02041b..0000000000 --- a/.packit.yaml +++ /dev/null @@ -1,126 +0,0 @@ ---- -# See the documentation for more information: -# https://packit.dev/docs/configuration/ - -downstream_package_name: podman -upstream_tag_template: v{version} - -packages: - podman-fedora: - pkg_tool: fedpkg - specfile_path: rpm/podman.spec - podman-centos: - pkg_tool: centpkg - specfile_path: rpm/podman.spec - podman-eln: - specfile_path: rpm/podman.spec - -srpm_build_deps: - - git-archive-all - - make - -actions: - fix-spec-file: - - "bash .packit.sh" - -jobs: - - job: copr_build - trigger: pull_request - packages: [podman-fedora] - notifications: &packit_build_failure_notification - failure_comment: - message: "Ephemeral COPR build failed. @containers/packit-build please check." - enable_net: true - targets: - - fedora-all-x86_64 - - fedora-all-aarch64 - - - job: copr_build - trigger: pull_request - packages: [podman-eln] - notifications: *packit_build_failure_notification - enable_net: true - targets: - fedora-eln-x86_64: - additional_repos: - - "https://kojipkgs.fedoraproject.org/repos/eln-build/latest/x86_64/" - fedora-eln-aarch64: - additional_repos: - - "https://kojipkgs.fedoraproject.org/repos/eln-build/latest/aarch64/" - - - job: copr_build - trigger: pull_request - packages: [podman-centos] - notifications: *packit_build_failure_notification - enable_net: true - targets: - - centos-stream-9-x86_64 - - centos-stream-9-aarch64 - - centos-stream-10-x86_64 - - centos-stream-10-aarch64 - - # Run on commit to main branch - - job: copr_build - trigger: commit - packages: [podman-fedora] - notifications: - failure_comment: - message: "podman-next COPR build failed. @containers/packit-build please check." - branch: main - owner: rhcontainerbot - project: podman-next - enable_net: true - - - job: tests - identifier: cockpit-revdeps - trigger: pull_request - packages: [podman-fedora] - notifications: - failure_comment: - message: "Cockpit tests failed for commit {commit_sha}. @martinpitt, @jelly, @mvollmer please check." - targets: - - fedora-latest-stable - - fedora-development - tf_extra_params: - environments: - - artifacts: - - type: repository-file - id: https://copr.fedorainfracloud.org/coprs/g/cockpit/main-builds/repo/fedora-$releasever/group_cockpit-main-builds-fedora-$releasever.repo - - type: repository-file - id: https://copr.fedorainfracloud.org/coprs/rhcontainerbot/podman-next/repo/fedora-$releasever/rhcontainerbot-podman-next-fedora-$releasever.repo - tmt: - context: - revdeps: "yes" - - - job: propose_downstream - trigger: release - update_release: false - packages: [podman-fedora] - dist_git_branches: &fedora_targets - - fedora-all - - - job: propose_downstream - trigger: release - update_release: false - packages: [podman-centos] - dist_git_branches: - - c10s - - - job: koji_build - trigger: commit - packages: [podman-fedora] - sidetag_group: podman-releases - dist_git_branches: *fedora_targets - - - job: bodhi_update - trigger: koji_build - packages: [podman-fedora] - sidetag_group: podman-releases - # Dependencies are not rpm dependencies, but packages that should go in the - # same bodhi update - # Ref: https://packit.dev/docs/fedora-releases-guide/releasing-multiple-packages - dependencies: - - buildah - - containers-common - - skopeo - dist_git_branches: *fedora_targets From 82c6daa21decd5a2c60366ceff7a215bfe423709 Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Tue, 11 Mar 2025 19:17:59 +0100 Subject: [PATCH 51/58] vendor: bump to golang.org/x/crypto@v0.36.0 Fixes: CVE-2025-22869 Fixes: https://issues.redhat.com/browse/RHEL-82775 Fixes: https://issues.redhat.com/browse/RHEL-82776 Fixes: https://issues.redhat.com/browse/RHEL-81319 Fixes: https://issues.redhat.com/browse/OCPBUGS-52552 Signed-off-by: Paul Holzinger --- go.mod | 12 +- go.sum | 18 +-- vendor/golang.org/x/crypto/ssh/handshake.go | 61 ++++++++-- vendor/golang.org/x/crypto/ssh/messages.go | 2 + vendor/golang.org/x/crypto/ssh/server.go | 50 ++++++-- vendor/golang.org/x/crypto/ssh/tcpip.go | 2 +- vendor/golang.org/x/sync/errgroup/errgroup.go | 3 +- vendor/golang.org/x/sync/errgroup/go120.go | 13 -- .../golang.org/x/sync/errgroup/pre_go120.go | 14 --- vendor/golang.org/x/sys/cpu/cpu.go | 3 + vendor/golang.org/x/sys/cpu/cpu_x86.go | 21 +++- vendor/golang.org/x/sys/unix/auxv.go | 36 ++++++ .../golang.org/x/sys/unix/auxv_unsupported.go | 13 ++ .../golang.org/x/sys/unix/syscall_solaris.go | 87 +++++++++++++ vendor/golang.org/x/sys/unix/zerrors_linux.go | 20 ++- .../x/sys/unix/zerrors_linux_386.go | 3 + .../x/sys/unix/zerrors_linux_amd64.go | 3 + .../x/sys/unix/zerrors_linux_arm.go | 3 + .../x/sys/unix/zerrors_linux_arm64.go | 4 + .../x/sys/unix/zerrors_linux_loong64.go | 3 + .../x/sys/unix/zerrors_linux_mips.go | 3 + .../x/sys/unix/zerrors_linux_mips64.go | 3 + .../x/sys/unix/zerrors_linux_mips64le.go | 3 + .../x/sys/unix/zerrors_linux_mipsle.go | 3 + .../x/sys/unix/zerrors_linux_ppc.go | 3 + .../x/sys/unix/zerrors_linux_ppc64.go | 3 + .../x/sys/unix/zerrors_linux_ppc64le.go | 3 + .../x/sys/unix/zerrors_linux_riscv64.go | 3 + .../x/sys/unix/zerrors_linux_s390x.go | 3 + .../x/sys/unix/zerrors_linux_sparc64.go | 3 + .../x/sys/unix/zsyscall_solaris_amd64.go | 114 ++++++++++++++++++ .../x/sys/unix/zsysnum_linux_386.go | 4 + .../x/sys/unix/zsysnum_linux_amd64.go | 4 + .../x/sys/unix/zsysnum_linux_arm.go | 4 + .../x/sys/unix/zsysnum_linux_arm64.go | 4 + .../x/sys/unix/zsysnum_linux_loong64.go | 4 + .../x/sys/unix/zsysnum_linux_mips.go | 4 + .../x/sys/unix/zsysnum_linux_mips64.go | 4 + .../x/sys/unix/zsysnum_linux_mips64le.go | 4 + .../x/sys/unix/zsysnum_linux_mipsle.go | 4 + .../x/sys/unix/zsysnum_linux_ppc.go | 4 + .../x/sys/unix/zsysnum_linux_ppc64.go | 4 + .../x/sys/unix/zsysnum_linux_ppc64le.go | 4 + .../x/sys/unix/zsysnum_linux_riscv64.go | 4 + .../x/sys/unix/zsysnum_linux_s390x.go | 4 + .../x/sys/unix/zsysnum_linux_sparc64.go | 4 + vendor/golang.org/x/sys/unix/ztypes_linux.go | 6 +- vendor/golang.org/x/text/language/parse.go | 2 +- vendor/modules.txt | 20 +-- 49 files changed, 517 insertions(+), 86 deletions(-) delete mode 100644 vendor/golang.org/x/sync/errgroup/go120.go delete mode 100644 vendor/golang.org/x/sync/errgroup/pre_go120.go create mode 100644 vendor/golang.org/x/sys/unix/auxv.go create mode 100644 vendor/golang.org/x/sys/unix/auxv_unsupported.go diff --git a/go.mod b/go.mod index f39d6154f7..bb850d8e5b 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/containers/podman/v5 // Warning: if there is a "toolchain" directive anywhere in this file (and most of the // time there shouldn't be), its version must be an exact match to the "go" directive. -go 1.22.8 +go 1.23.0 require ( github.com/BurntSushi/toml v1.4.0 @@ -71,13 +71,13 @@ require ( github.com/vbauerster/mpb/v8 v8.9.1 github.com/vishvananda/netlink v1.3.1-0.20240922070040-084abd93d350 go.etcd.io/bbolt v1.3.11 - golang.org/x/crypto v0.32.0 + golang.org/x/crypto v0.36.0 golang.org/x/exp v0.0.0-20250103183323-7d7fa50e5329 golang.org/x/net v0.34.0 - golang.org/x/sync v0.10.0 - golang.org/x/sys v0.29.0 - golang.org/x/term v0.28.0 - golang.org/x/text v0.21.0 + golang.org/x/sync v0.12.0 + golang.org/x/sys v0.31.0 + golang.org/x/term v0.30.0 + golang.org/x/text v0.23.0 google.golang.org/protobuf v1.36.3 gopkg.in/inf.v0 v0.9.1 gopkg.in/yaml.v3 v3.0.1 diff --git a/go.sum b/go.sum index 30ad14eccf..38565e5e7d 100644 --- a/go.sum +++ b/go.sum @@ -582,8 +582,8 @@ golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq 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.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= -golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= +golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20250103183323-7d7fa50e5329 h1:9kj3STMvgqy3YA4VQXBrN7925ICMxD5wzMRcgA30588= golang.org/x/exp v0.0.0-20250103183323-7d7fa50e5329/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c= @@ -633,8 +633,9 @@ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= +golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -666,8 +667,8 @@ golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= -golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -678,8 +679,8 @@ golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= -golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= -golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= +golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= +golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= @@ -688,8 +689,9 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/vendor/golang.org/x/crypto/ssh/handshake.go b/vendor/golang.org/x/crypto/ssh/handshake.go index 56cdc7c21c..c9202b05da 100644 --- a/vendor/golang.org/x/crypto/ssh/handshake.go +++ b/vendor/golang.org/x/crypto/ssh/handshake.go @@ -25,6 +25,11 @@ const debugHandshake = false // quickly. const chanSize = 16 +// maxPendingPackets sets the maximum number of packets to queue while waiting +// for KEX to complete. This limits the total pending data to maxPendingPackets +// * maxPacket bytes, which is ~16.8MB. +const maxPendingPackets = 64 + // keyingTransport is a packet based transport that supports key // changes. It need not be thread-safe. It should pass through // msgNewKeys in both directions. @@ -73,13 +78,22 @@ type handshakeTransport struct { incoming chan []byte readError error - mu sync.Mutex - writeError error - sentInitPacket []byte - sentInitMsg *kexInitMsg - pendingPackets [][]byte // Used when a key exchange is in progress. + mu sync.Mutex + // Condition for the above mutex. It is used to notify a completed key + // exchange or a write failure. Writes can wait for this condition while a + // key exchange is in progress. + writeCond *sync.Cond + writeError error + sentInitPacket []byte + sentInitMsg *kexInitMsg + // Used to queue writes when a key exchange is in progress. The length is + // limited by pendingPacketsSize. Once full, writes will block until the key + // exchange is completed or an error occurs. If not empty, it is emptied + // all at once when the key exchange is completed in kexLoop. + pendingPackets [][]byte writePacketsLeft uint32 writeBytesLeft int64 + userAuthComplete bool // whether the user authentication phase is complete // If the read loop wants to schedule a kex, it pings this // channel, and the write loop will send out a kex @@ -133,6 +147,7 @@ func newHandshakeTransport(conn keyingTransport, config *Config, clientVersion, config: config, } + t.writeCond = sync.NewCond(&t.mu) t.resetReadThresholds() t.resetWriteThresholds() @@ -259,6 +274,7 @@ func (t *handshakeTransport) recordWriteError(err error) { defer t.mu.Unlock() if t.writeError == nil && err != nil { t.writeError = err + t.writeCond.Broadcast() } } @@ -362,6 +378,8 @@ write: } } t.pendingPackets = t.pendingPackets[:0] + // Unblock writePacket if waiting for KEX. + t.writeCond.Broadcast() t.mu.Unlock() } @@ -552,26 +570,44 @@ func (t *handshakeTransport) sendKexInit() error { return nil } +var errSendBannerPhase = errors.New("ssh: SendAuthBanner outside of authentication phase") + func (t *handshakeTransport) writePacket(p []byte) error { + t.mu.Lock() + defer t.mu.Unlock() + switch p[0] { case msgKexInit: return errors.New("ssh: only handshakeTransport can send kexInit") case msgNewKeys: return errors.New("ssh: only handshakeTransport can send newKeys") + case msgUserAuthBanner: + if t.userAuthComplete { + return errSendBannerPhase + } + case msgUserAuthSuccess: + t.userAuthComplete = true } - t.mu.Lock() - defer t.mu.Unlock() if t.writeError != nil { return t.writeError } if t.sentInitMsg != nil { - // Copy the packet so the writer can reuse the buffer. - cp := make([]byte, len(p)) - copy(cp, p) - t.pendingPackets = append(t.pendingPackets, cp) - return nil + if len(t.pendingPackets) < maxPendingPackets { + // Copy the packet so the writer can reuse the buffer. + cp := make([]byte, len(p)) + copy(cp, p) + t.pendingPackets = append(t.pendingPackets, cp) + return nil + } + for t.sentInitMsg != nil { + // Block and wait for KEX to complete or an error. + t.writeCond.Wait() + if t.writeError != nil { + return t.writeError + } + } } if t.writeBytesLeft > 0 { @@ -588,6 +624,7 @@ func (t *handshakeTransport) writePacket(p []byte) error { if err := t.pushPacket(p); err != nil { t.writeError = err + t.writeCond.Broadcast() } return nil diff --git a/vendor/golang.org/x/crypto/ssh/messages.go b/vendor/golang.org/x/crypto/ssh/messages.go index b55f860564..118427bc05 100644 --- a/vendor/golang.org/x/crypto/ssh/messages.go +++ b/vendor/golang.org/x/crypto/ssh/messages.go @@ -818,6 +818,8 @@ func decode(packet []byte) (interface{}, error) { return new(userAuthSuccessMsg), nil case msgUserAuthFailure: msg = new(userAuthFailureMsg) + case msgUserAuthBanner: + msg = new(userAuthBannerMsg) case msgUserAuthPubKeyOk: msg = new(userAuthPubKeyOkMsg) case msgGlobalRequest: diff --git a/vendor/golang.org/x/crypto/ssh/server.go b/vendor/golang.org/x/crypto/ssh/server.go index 5b5ccd96f4..1839ddc6a4 100644 --- a/vendor/golang.org/x/crypto/ssh/server.go +++ b/vendor/golang.org/x/crypto/ssh/server.go @@ -59,6 +59,27 @@ type GSSAPIWithMICConfig struct { Server GSSAPIServer } +// SendAuthBanner implements [ServerPreAuthConn]. +func (s *connection) SendAuthBanner(msg string) error { + return s.transport.writePacket(Marshal(&userAuthBannerMsg{ + Message: msg, + })) +} + +func (*connection) unexportedMethodForFutureProofing() {} + +// ServerPreAuthConn is the interface available on an incoming server +// connection before authentication has completed. +type ServerPreAuthConn interface { + unexportedMethodForFutureProofing() // permits growing ServerPreAuthConn safely later, ala testing.TB + + ConnMetadata + + // SendAuthBanner sends a banner message to the client. + // It returns an error once the authentication phase has ended. + SendAuthBanner(string) error +} + // ServerConfig holds server specific configuration data. type ServerConfig struct { // Config contains configuration shared between client and server. @@ -118,6 +139,12 @@ type ServerConfig struct { // attempts. AuthLogCallback func(conn ConnMetadata, method string, err error) + // PreAuthConnCallback, if non-nil, is called upon receiving a new connection + // before any authentication has started. The provided ServerPreAuthConn + // can be used at any time before authentication is complete, including + // after this callback has returned. + PreAuthConnCallback func(ServerPreAuthConn) + // ServerVersion is the version identification string to announce in // the public handshake. // If empty, a reasonable default is used. @@ -488,6 +515,10 @@ func (b *BannerError) Error() string { } func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, error) { + if config.PreAuthConnCallback != nil { + config.PreAuthConnCallback(s) + } + sessionID := s.transport.getSessionID() var cache pubKeyCache var perms *Permissions @@ -495,7 +526,7 @@ func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, err authFailures := 0 noneAuthCount := 0 var authErrs []error - var displayedBanner bool + var calledBannerCallback bool partialSuccessReturned := false // Set the initial authentication callbacks from the config. They can be // changed if a PartialSuccessError is returned. @@ -542,14 +573,10 @@ userAuthLoop: s.user = userAuthReq.User - if !displayedBanner && config.BannerCallback != nil { - displayedBanner = true - msg := config.BannerCallback(s) - if msg != "" { - bannerMsg := &userAuthBannerMsg{ - Message: msg, - } - if err := s.transport.writePacket(Marshal(bannerMsg)); err != nil { + if !calledBannerCallback && config.BannerCallback != nil { + calledBannerCallback = true + if msg := config.BannerCallback(s); msg != "" { + if err := s.SendAuthBanner(msg); err != nil { return nil, err } } @@ -762,10 +789,7 @@ userAuthLoop: var bannerErr *BannerError if errors.As(authErr, &bannerErr) { if bannerErr.Message != "" { - bannerMsg := &userAuthBannerMsg{ - Message: bannerErr.Message, - } - if err := s.transport.writePacket(Marshal(bannerMsg)); err != nil { + if err := s.SendAuthBanner(bannerErr.Message); err != nil { return nil, err } } diff --git a/vendor/golang.org/x/crypto/ssh/tcpip.go b/vendor/golang.org/x/crypto/ssh/tcpip.go index ef5059a11d..93d844f035 100644 --- a/vendor/golang.org/x/crypto/ssh/tcpip.go +++ b/vendor/golang.org/x/crypto/ssh/tcpip.go @@ -459,7 +459,7 @@ func (c *Client) dial(laddr string, lport int, raddr string, rport int) (Channel return nil, err } go DiscardRequests(in) - return ch, err + return ch, nil } type tcpChan struct { diff --git a/vendor/golang.org/x/sync/errgroup/errgroup.go b/vendor/golang.org/x/sync/errgroup/errgroup.go index 948a3ee63d..a4ea5d14f1 100644 --- a/vendor/golang.org/x/sync/errgroup/errgroup.go +++ b/vendor/golang.org/x/sync/errgroup/errgroup.go @@ -46,7 +46,7 @@ func (g *Group) done() { // returns a non-nil error or the first time Wait returns, whichever occurs // first. func WithContext(ctx context.Context) (*Group, context.Context) { - ctx, cancel := withCancelCause(ctx) + ctx, cancel := context.WithCancelCause(ctx) return &Group{cancel: cancel}, ctx } @@ -118,6 +118,7 @@ func (g *Group) TryGo(f func() error) bool { // SetLimit limits the number of active goroutines in this group to at most n. // A negative value indicates no limit. +// A limit of zero will prevent any new goroutines from being added. // // Any subsequent call to the Go method will block until it can add an active // goroutine without exceeding the configured limit. diff --git a/vendor/golang.org/x/sync/errgroup/go120.go b/vendor/golang.org/x/sync/errgroup/go120.go deleted file mode 100644 index f93c740b63..0000000000 --- a/vendor/golang.org/x/sync/errgroup/go120.go +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.20 - -package errgroup - -import "context" - -func withCancelCause(parent context.Context) (context.Context, func(error)) { - return context.WithCancelCause(parent) -} diff --git a/vendor/golang.org/x/sync/errgroup/pre_go120.go b/vendor/golang.org/x/sync/errgroup/pre_go120.go deleted file mode 100644 index 88ce33434e..0000000000 --- a/vendor/golang.org/x/sync/errgroup/pre_go120.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.20 - -package errgroup - -import "context" - -func withCancelCause(parent context.Context) (context.Context, func(error)) { - ctx, cancel := context.WithCancel(parent) - return ctx, func(error) { cancel() } -} diff --git a/vendor/golang.org/x/sys/cpu/cpu.go b/vendor/golang.org/x/sys/cpu/cpu.go index 02609d5b21..9c105f23af 100644 --- a/vendor/golang.org/x/sys/cpu/cpu.go +++ b/vendor/golang.org/x/sys/cpu/cpu.go @@ -72,6 +72,9 @@ var X86 struct { HasSSSE3 bool // Supplemental streaming SIMD extension 3 HasSSE41 bool // Streaming SIMD extension 4 and 4.1 HasSSE42 bool // Streaming SIMD extension 4 and 4.2 + HasAVXIFMA bool // Advanced vector extension Integer Fused Multiply Add + HasAVXVNNI bool // Advanced vector extension Vector Neural Network Instructions + HasAVXVNNIInt8 bool // Advanced vector extension Vector Neural Network Int8 instructions _ CacheLinePad } diff --git a/vendor/golang.org/x/sys/cpu/cpu_x86.go b/vendor/golang.org/x/sys/cpu/cpu_x86.go index 600a680786..1e642f3304 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_x86.go +++ b/vendor/golang.org/x/sys/cpu/cpu_x86.go @@ -53,6 +53,9 @@ func initOptions() { {Name: "sse41", Feature: &X86.HasSSE41}, {Name: "sse42", Feature: &X86.HasSSE42}, {Name: "ssse3", Feature: &X86.HasSSSE3}, + {Name: "avxifma", Feature: &X86.HasAVXIFMA}, + {Name: "avxvnni", Feature: &X86.HasAVXVNNI}, + {Name: "avxvnniint8", Feature: &X86.HasAVXVNNIInt8}, // These capabilities should always be enabled on amd64: {Name: "sse2", Feature: &X86.HasSSE2, Required: runtime.GOARCH == "amd64"}, @@ -106,7 +109,7 @@ func archInit() { return } - _, ebx7, ecx7, edx7 := cpuid(7, 0) + eax7, ebx7, ecx7, edx7 := cpuid(7, 0) X86.HasBMI1 = isSet(3, ebx7) X86.HasAVX2 = isSet(5, ebx7) && osSupportsAVX X86.HasBMI2 = isSet(8, ebx7) @@ -134,14 +137,24 @@ func archInit() { X86.HasAVX512VAES = isSet(9, ecx7) X86.HasAVX512VBMI2 = isSet(6, ecx7) X86.HasAVX512BITALG = isSet(12, ecx7) - - eax71, _, _, _ := cpuid(7, 1) - X86.HasAVX512BF16 = isSet(5, eax71) } X86.HasAMXTile = isSet(24, edx7) X86.HasAMXInt8 = isSet(25, edx7) X86.HasAMXBF16 = isSet(22, edx7) + + // These features depend on the second level of extended features. + if eax7 >= 1 { + eax71, _, _, edx71 := cpuid(7, 1) + if X86.HasAVX512 { + X86.HasAVX512BF16 = isSet(5, eax71) + } + if X86.HasAVX { + X86.HasAVXIFMA = isSet(23, eax71) + X86.HasAVXVNNI = isSet(4, eax71) + X86.HasAVXVNNIInt8 = isSet(4, edx71) + } + } } func isSet(bitpos uint, value uint32) bool { diff --git a/vendor/golang.org/x/sys/unix/auxv.go b/vendor/golang.org/x/sys/unix/auxv.go new file mode 100644 index 0000000000..37a82528f5 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/auxv.go @@ -0,0 +1,36 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.21 && (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos) + +package unix + +import ( + "syscall" + "unsafe" +) + +//go:linkname runtime_getAuxv runtime.getAuxv +func runtime_getAuxv() []uintptr + +// Auxv returns the ELF auxiliary vector as a sequence of key/value pairs. +// The returned slice is always a fresh copy, owned by the caller. +// It returns an error on non-ELF platforms, or if the auxiliary vector cannot be accessed, +// which happens in some locked-down environments and build modes. +func Auxv() ([][2]uintptr, error) { + vec := runtime_getAuxv() + vecLen := len(vec) + + if vecLen == 0 { + return nil, syscall.ENOENT + } + + if vecLen%2 != 0 { + return nil, syscall.EINVAL + } + + result := make([]uintptr, vecLen) + copy(result, vec) + return unsafe.Slice((*[2]uintptr)(unsafe.Pointer(&result[0])), vecLen/2), nil +} diff --git a/vendor/golang.org/x/sys/unix/auxv_unsupported.go b/vendor/golang.org/x/sys/unix/auxv_unsupported.go new file mode 100644 index 0000000000..1200487f2e --- /dev/null +++ b/vendor/golang.org/x/sys/unix/auxv_unsupported.go @@ -0,0 +1,13 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !go1.21 && (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos) + +package unix + +import "syscall" + +func Auxv() ([][2]uintptr, error) { + return nil, syscall.ENOTSUP +} diff --git a/vendor/golang.org/x/sys/unix/syscall_solaris.go b/vendor/golang.org/x/sys/unix/syscall_solaris.go index 21974af064..abc3955477 100644 --- a/vendor/golang.org/x/sys/unix/syscall_solaris.go +++ b/vendor/golang.org/x/sys/unix/syscall_solaris.go @@ -1102,3 +1102,90 @@ func (s *Strioctl) SetInt(i int) { func IoctlSetStrioctlRetInt(fd int, req int, s *Strioctl) (int, error) { return ioctlPtrRet(fd, req, unsafe.Pointer(s)) } + +// Ucred Helpers +// See ucred(3c) and getpeerucred(3c) + +//sys getpeerucred(fd uintptr, ucred *uintptr) (err error) +//sys ucredFree(ucred uintptr) = ucred_free +//sys ucredGet(pid int) (ucred uintptr, err error) = ucred_get +//sys ucredGeteuid(ucred uintptr) (uid int) = ucred_geteuid +//sys ucredGetegid(ucred uintptr) (gid int) = ucred_getegid +//sys ucredGetruid(ucred uintptr) (uid int) = ucred_getruid +//sys ucredGetrgid(ucred uintptr) (gid int) = ucred_getrgid +//sys ucredGetsuid(ucred uintptr) (uid int) = ucred_getsuid +//sys ucredGetsgid(ucred uintptr) (gid int) = ucred_getsgid +//sys ucredGetpid(ucred uintptr) (pid int) = ucred_getpid + +// Ucred is an opaque struct that holds user credentials. +type Ucred struct { + ucred uintptr +} + +// We need to ensure that ucredFree is called on the underlying ucred +// when the Ucred is garbage collected. +func ucredFinalizer(u *Ucred) { + ucredFree(u.ucred) +} + +func GetPeerUcred(fd uintptr) (*Ucred, error) { + var ucred uintptr + err := getpeerucred(fd, &ucred) + if err != nil { + return nil, err + } + result := &Ucred{ + ucred: ucred, + } + // set the finalizer on the result so that the ucred will be freed + runtime.SetFinalizer(result, ucredFinalizer) + return result, nil +} + +func UcredGet(pid int) (*Ucred, error) { + ucred, err := ucredGet(pid) + if err != nil { + return nil, err + } + result := &Ucred{ + ucred: ucred, + } + // set the finalizer on the result so that the ucred will be freed + runtime.SetFinalizer(result, ucredFinalizer) + return result, nil +} + +func (u *Ucred) Geteuid() int { + defer runtime.KeepAlive(u) + return ucredGeteuid(u.ucred) +} + +func (u *Ucred) Getruid() int { + defer runtime.KeepAlive(u) + return ucredGetruid(u.ucred) +} + +func (u *Ucred) Getsuid() int { + defer runtime.KeepAlive(u) + return ucredGetsuid(u.ucred) +} + +func (u *Ucred) Getegid() int { + defer runtime.KeepAlive(u) + return ucredGetegid(u.ucred) +} + +func (u *Ucred) Getrgid() int { + defer runtime.KeepAlive(u) + return ucredGetrgid(u.ucred) +} + +func (u *Ucred) Getsgid() int { + defer runtime.KeepAlive(u) + return ucredGetsgid(u.ucred) +} + +func (u *Ucred) Getpid() int { + defer runtime.KeepAlive(u) + return ucredGetpid(u.ucred) +} diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux.go b/vendor/golang.org/x/sys/unix/zerrors_linux.go index 6ebc48b3fe..4f432bfe8f 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux.go @@ -1245,6 +1245,7 @@ const ( FAN_REPORT_DFID_NAME = 0xc00 FAN_REPORT_DFID_NAME_TARGET = 0x1e00 FAN_REPORT_DIR_FID = 0x400 + FAN_REPORT_FD_ERROR = 0x2000 FAN_REPORT_FID = 0x200 FAN_REPORT_NAME = 0x800 FAN_REPORT_PIDFD = 0x80 @@ -1330,8 +1331,10 @@ const ( FUSE_SUPER_MAGIC = 0x65735546 FUTEXFS_SUPER_MAGIC = 0xbad1dea F_ADD_SEALS = 0x409 + F_CREATED_QUERY = 0x404 F_DUPFD = 0x0 F_DUPFD_CLOEXEC = 0x406 + F_DUPFD_QUERY = 0x403 F_EXLCK = 0x4 F_GETFD = 0x1 F_GETFL = 0x3 @@ -1551,6 +1554,7 @@ const ( IPPROTO_ROUTING = 0x2b IPPROTO_RSVP = 0x2e IPPROTO_SCTP = 0x84 + IPPROTO_SMC = 0x100 IPPROTO_TCP = 0x6 IPPROTO_TP = 0x1d IPPROTO_UDP = 0x11 @@ -1623,6 +1627,8 @@ const ( IPV6_UNICAST_IF = 0x4c IPV6_USER_FLOW = 0xe IPV6_V6ONLY = 0x1a + IPV6_VERSION = 0x60 + IPV6_VERSION_MASK = 0xf0 IPV6_XFRM_POLICY = 0x23 IP_ADD_MEMBERSHIP = 0x23 IP_ADD_SOURCE_MEMBERSHIP = 0x27 @@ -1867,6 +1873,7 @@ const ( MADV_UNMERGEABLE = 0xd MADV_WILLNEED = 0x3 MADV_WIPEONFORK = 0x12 + MAP_DROPPABLE = 0x8 MAP_FILE = 0x0 MAP_FIXED = 0x10 MAP_FIXED_NOREPLACE = 0x100000 @@ -1967,6 +1974,7 @@ const ( MSG_PEEK = 0x2 MSG_PROXY = 0x10 MSG_RST = 0x1000 + MSG_SOCK_DEVMEM = 0x2000000 MSG_SYN = 0x400 MSG_TRUNC = 0x20 MSG_TRYHARD = 0x4 @@ -2083,6 +2091,7 @@ const ( NFC_ATR_REQ_MAXSIZE = 0x40 NFC_ATR_RES_GB_MAXSIZE = 0x2f NFC_ATR_RES_MAXSIZE = 0x40 + NFC_ATS_MAXSIZE = 0x14 NFC_COMM_ACTIVE = 0x0 NFC_COMM_PASSIVE = 0x1 NFC_DEVICE_NAME_MAXSIZE = 0x8 @@ -2163,6 +2172,7 @@ const ( NFNL_SUBSYS_QUEUE = 0x3 NFNL_SUBSYS_ULOG = 0x4 NFS_SUPER_MAGIC = 0x6969 + NFT_BITWISE_BOOL = 0x0 NFT_CHAIN_FLAGS = 0x7 NFT_CHAIN_MAXNAMELEN = 0x100 NFT_CT_MAX = 0x17 @@ -2491,6 +2501,7 @@ const ( PR_GET_PDEATHSIG = 0x2 PR_GET_SECCOMP = 0x15 PR_GET_SECUREBITS = 0x1b + PR_GET_SHADOW_STACK_STATUS = 0x4a PR_GET_SPECULATION_CTRL = 0x34 PR_GET_TAGGED_ADDR_CTRL = 0x38 PR_GET_THP_DISABLE = 0x2a @@ -2499,6 +2510,7 @@ const ( PR_GET_TIMING = 0xd PR_GET_TSC = 0x19 PR_GET_UNALIGN = 0x5 + PR_LOCK_SHADOW_STACK_STATUS = 0x4c PR_MCE_KILL = 0x21 PR_MCE_KILL_CLEAR = 0x0 PR_MCE_KILL_DEFAULT = 0x2 @@ -2525,6 +2537,8 @@ const ( PR_PAC_GET_ENABLED_KEYS = 0x3d PR_PAC_RESET_KEYS = 0x36 PR_PAC_SET_ENABLED_KEYS = 0x3c + PR_PMLEN_MASK = 0x7f000000 + PR_PMLEN_SHIFT = 0x18 PR_PPC_DEXCR_CTRL_CLEAR = 0x4 PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC = 0x10 PR_PPC_DEXCR_CTRL_EDITABLE = 0x1 @@ -2592,6 +2606,7 @@ const ( PR_SET_PTRACER = 0x59616d61 PR_SET_SECCOMP = 0x16 PR_SET_SECUREBITS = 0x1c + PR_SET_SHADOW_STACK_STATUS = 0x4b PR_SET_SPECULATION_CTRL = 0x35 PR_SET_SYSCALL_USER_DISPATCH = 0x3b PR_SET_TAGGED_ADDR_CTRL = 0x37 @@ -2602,6 +2617,9 @@ const ( PR_SET_UNALIGN = 0x6 PR_SET_VMA = 0x53564d41 PR_SET_VMA_ANON_NAME = 0x0 + PR_SHADOW_STACK_ENABLE = 0x1 + PR_SHADOW_STACK_PUSH = 0x4 + PR_SHADOW_STACK_WRITE = 0x2 PR_SME_GET_VL = 0x40 PR_SME_SET_VL = 0x3f PR_SME_SET_VL_ONEXEC = 0x40000 @@ -2911,7 +2929,6 @@ const ( RTM_NEWNEXTHOP = 0x68 RTM_NEWNEXTHOPBUCKET = 0x74 RTM_NEWNSID = 0x58 - RTM_NEWNVLAN = 0x70 RTM_NEWPREFIX = 0x34 RTM_NEWQDISC = 0x24 RTM_NEWROUTE = 0x18 @@ -2920,6 +2937,7 @@ const ( RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c RTM_NEWTUNNEL = 0x78 + RTM_NEWVLAN = 0x70 RTM_NR_FAMILIES = 0x1b RTM_NR_MSGTYPES = 0x6c RTM_SETDCB = 0x4f diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go index c0d45e3205..75207613c7 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go @@ -116,6 +116,8 @@ const ( IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -304,6 +306,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go index c731d24f02..c68acda535 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go @@ -116,6 +116,8 @@ const ( IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -305,6 +307,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go index 680018a4a7..a8c607ab86 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go @@ -115,6 +115,8 @@ const ( IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -310,6 +312,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go index a63909f308..18563dd8d3 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go @@ -109,6 +109,7 @@ const ( F_SETOWN = 0x8 F_UNLCK = 0x2 F_WRLCK = 0x1 + GCS_MAGIC = 0x47435300 HIDIOCGRAWINFO = 0x80084803 HIDIOCGRDESC = 0x90044802 HIDIOCGRDESCSIZE = 0x80044801 @@ -119,6 +120,8 @@ const ( IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -302,6 +305,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go index 9b0a2573fe..22912cdaa9 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go @@ -116,6 +116,8 @@ const ( IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -297,6 +299,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go index 958e6e0645..29344eb37a 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go @@ -115,6 +115,8 @@ const ( IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x80 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9 + IPV6_FLOWINFO_MASK = 0xfffffff + IPV6_FLOWLABEL_MASK = 0xfffff ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -303,6 +305,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go index 50c7f25bd1..20d51fb96a 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go @@ -115,6 +115,8 @@ const ( IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x80 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9 + IPV6_FLOWINFO_MASK = 0xfffffff + IPV6_FLOWLABEL_MASK = 0xfffff ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -303,6 +305,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go index ced21d66d9..321b60902a 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go @@ -115,6 +115,8 @@ const ( IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x80 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -303,6 +305,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go index 226c044190..9bacdf1e27 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go @@ -115,6 +115,8 @@ const ( IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x80 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -303,6 +305,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go index 3122737cd4..c224272615 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go @@ -115,6 +115,8 @@ const ( IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9 + IPV6_FLOWINFO_MASK = 0xfffffff + IPV6_FLOWLABEL_MASK = 0xfffff ISIG = 0x80 IUCLC = 0x1000 IXOFF = 0x400 @@ -358,6 +360,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go index eb5d3467ed..6270c8ee13 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go @@ -115,6 +115,8 @@ const ( IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9 + IPV6_FLOWINFO_MASK = 0xfffffff + IPV6_FLOWLABEL_MASK = 0xfffff ISIG = 0x80 IUCLC = 0x1000 IXOFF = 0x400 @@ -362,6 +364,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go index e921ebc60b..9966c1941f 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go @@ -115,6 +115,8 @@ const ( IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 ISIG = 0x80 IUCLC = 0x1000 IXOFF = 0x400 @@ -362,6 +364,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go index 38ba81c55c..848e5fcc42 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go @@ -115,6 +115,8 @@ const ( IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -294,6 +296,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go index 71f0400977..669b2adb80 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go @@ -115,6 +115,8 @@ const ( IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9 + IPV6_FLOWINFO_MASK = 0xfffffff + IPV6_FLOWLABEL_MASK = 0xfffff ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -366,6 +368,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go index c44a313322..4834e57514 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go @@ -119,6 +119,8 @@ const ( IN_CLOEXEC = 0x400000 IN_NONBLOCK = 0x4000 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9 + IPV6_FLOWINFO_MASK = 0xfffffff + IPV6_FLOWLABEL_MASK = 0xfffff ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -357,6 +359,7 @@ const ( SCM_TIMESTAMPING_OPT_STATS = 0x38 SCM_TIMESTAMPING_PKTINFO = 0x3c SCM_TIMESTAMPNS = 0x21 + SCM_TS_OPT_ID = 0x5a SCM_TXTIME = 0x3f SCM_WIFI_STATUS = 0x25 SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103 diff --git a/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go index 829b87feb8..c6545413c4 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go @@ -141,6 +141,16 @@ import ( //go:cgo_import_dynamic libc_getpeername getpeername "libsocket.so" //go:cgo_import_dynamic libc_setsockopt setsockopt "libsocket.so" //go:cgo_import_dynamic libc_recvfrom recvfrom "libsocket.so" +//go:cgo_import_dynamic libc_getpeerucred getpeerucred "libc.so" +//go:cgo_import_dynamic libc_ucred_get ucred_get "libc.so" +//go:cgo_import_dynamic libc_ucred_geteuid ucred_geteuid "libc.so" +//go:cgo_import_dynamic libc_ucred_getegid ucred_getegid "libc.so" +//go:cgo_import_dynamic libc_ucred_getruid ucred_getruid "libc.so" +//go:cgo_import_dynamic libc_ucred_getrgid ucred_getrgid "libc.so" +//go:cgo_import_dynamic libc_ucred_getsuid ucred_getsuid "libc.so" +//go:cgo_import_dynamic libc_ucred_getsgid ucred_getsgid "libc.so" +//go:cgo_import_dynamic libc_ucred_getpid ucred_getpid "libc.so" +//go:cgo_import_dynamic libc_ucred_free ucred_free "libc.so" //go:cgo_import_dynamic libc_port_create port_create "libc.so" //go:cgo_import_dynamic libc_port_associate port_associate "libc.so" //go:cgo_import_dynamic libc_port_dissociate port_dissociate "libc.so" @@ -280,6 +290,16 @@ import ( //go:linkname procgetpeername libc_getpeername //go:linkname procsetsockopt libc_setsockopt //go:linkname procrecvfrom libc_recvfrom +//go:linkname procgetpeerucred libc_getpeerucred +//go:linkname procucred_get libc_ucred_get +//go:linkname procucred_geteuid libc_ucred_geteuid +//go:linkname procucred_getegid libc_ucred_getegid +//go:linkname procucred_getruid libc_ucred_getruid +//go:linkname procucred_getrgid libc_ucred_getrgid +//go:linkname procucred_getsuid libc_ucred_getsuid +//go:linkname procucred_getsgid libc_ucred_getsgid +//go:linkname procucred_getpid libc_ucred_getpid +//go:linkname procucred_free libc_ucred_free //go:linkname procport_create libc_port_create //go:linkname procport_associate libc_port_associate //go:linkname procport_dissociate libc_port_dissociate @@ -420,6 +440,16 @@ var ( procgetpeername, procsetsockopt, procrecvfrom, + procgetpeerucred, + procucred_get, + procucred_geteuid, + procucred_getegid, + procucred_getruid, + procucred_getrgid, + procucred_getsuid, + procucred_getsgid, + procucred_getpid, + procucred_free, procport_create, procport_associate, procport_dissociate, @@ -2029,6 +2059,90 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func getpeerucred(fd uintptr, ucred *uintptr) (err error) { + _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procgetpeerucred)), 2, uintptr(fd), uintptr(unsafe.Pointer(ucred)), 0, 0, 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredGet(pid int) (ucred uintptr, err error) { + r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procucred_get)), 1, uintptr(pid), 0, 0, 0, 0, 0) + ucred = uintptr(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredGeteuid(ucred uintptr) (uid int) { + r0, _, _ := sysvicall6(uintptr(unsafe.Pointer(&procucred_geteuid)), 1, uintptr(ucred), 0, 0, 0, 0, 0) + uid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredGetegid(ucred uintptr) (gid int) { + r0, _, _ := sysvicall6(uintptr(unsafe.Pointer(&procucred_getegid)), 1, uintptr(ucred), 0, 0, 0, 0, 0) + gid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredGetruid(ucred uintptr) (uid int) { + r0, _, _ := sysvicall6(uintptr(unsafe.Pointer(&procucred_getruid)), 1, uintptr(ucred), 0, 0, 0, 0, 0) + uid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredGetrgid(ucred uintptr) (gid int) { + r0, _, _ := sysvicall6(uintptr(unsafe.Pointer(&procucred_getrgid)), 1, uintptr(ucred), 0, 0, 0, 0, 0) + gid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredGetsuid(ucred uintptr) (uid int) { + r0, _, _ := sysvicall6(uintptr(unsafe.Pointer(&procucred_getsuid)), 1, uintptr(ucred), 0, 0, 0, 0, 0) + uid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredGetsgid(ucred uintptr) (gid int) { + r0, _, _ := sysvicall6(uintptr(unsafe.Pointer(&procucred_getsgid)), 1, uintptr(ucred), 0, 0, 0, 0, 0) + gid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredGetpid(ucred uintptr) (pid int) { + r0, _, _ := sysvicall6(uintptr(unsafe.Pointer(&procucred_getpid)), 1, uintptr(ucred), 0, 0, 0, 0, 0) + pid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredFree(ucred uintptr) { + sysvicall6(uintptr(unsafe.Pointer(&procucred_free)), 1, uintptr(ucred), 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func port_create() (n int, err error) { r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procport_create)), 0, 0, 0, 0, 0, 0, 0) n = int(r0) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go index 524b0820cb..c79aaff306 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go @@ -458,4 +458,8 @@ const ( SYS_LSM_SET_SELF_ATTR = 460 SYS_LSM_LIST_MODULES = 461 SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go index f485dbf456..5eb450695e 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go @@ -381,4 +381,8 @@ const ( SYS_LSM_SET_SELF_ATTR = 460 SYS_LSM_LIST_MODULES = 461 SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go index 70b35bf3b0..05e5029744 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go @@ -422,4 +422,8 @@ const ( SYS_LSM_SET_SELF_ATTR = 460 SYS_LSM_LIST_MODULES = 461 SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go index 1893e2fe88..38c53ec51b 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go @@ -325,4 +325,8 @@ const ( SYS_LSM_SET_SELF_ATTR = 460 SYS_LSM_LIST_MODULES = 461 SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go index 16a4017da0..31d2e71a18 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go @@ -321,4 +321,8 @@ const ( SYS_LSM_SET_SELF_ATTR = 460 SYS_LSM_LIST_MODULES = 461 SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go index 7e567f1eff..f4184a336b 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go @@ -442,4 +442,8 @@ const ( SYS_LSM_SET_SELF_ATTR = 4460 SYS_LSM_LIST_MODULES = 4461 SYS_MSEAL = 4462 + SYS_SETXATTRAT = 4463 + SYS_GETXATTRAT = 4464 + SYS_LISTXATTRAT = 4465 + SYS_REMOVEXATTRAT = 4466 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go index 38ae55e5ef..05b9962278 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go @@ -372,4 +372,8 @@ const ( SYS_LSM_SET_SELF_ATTR = 5460 SYS_LSM_LIST_MODULES = 5461 SYS_MSEAL = 5462 + SYS_SETXATTRAT = 5463 + SYS_GETXATTRAT = 5464 + SYS_LISTXATTRAT = 5465 + SYS_REMOVEXATTRAT = 5466 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go index 55e92e60a8..43a256e9e6 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go @@ -372,4 +372,8 @@ const ( SYS_LSM_SET_SELF_ATTR = 5460 SYS_LSM_LIST_MODULES = 5461 SYS_MSEAL = 5462 + SYS_SETXATTRAT = 5463 + SYS_GETXATTRAT = 5464 + SYS_LISTXATTRAT = 5465 + SYS_REMOVEXATTRAT = 5466 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go index 60658d6a02..eea5ddfc22 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go @@ -442,4 +442,8 @@ const ( SYS_LSM_SET_SELF_ATTR = 4460 SYS_LSM_LIST_MODULES = 4461 SYS_MSEAL = 4462 + SYS_SETXATTRAT = 4463 + SYS_GETXATTRAT = 4464 + SYS_LISTXATTRAT = 4465 + SYS_REMOVEXATTRAT = 4466 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go index e203e8a7ed..0d777bfbb1 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go @@ -449,4 +449,8 @@ const ( SYS_LSM_SET_SELF_ATTR = 460 SYS_LSM_LIST_MODULES = 461 SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go index 5944b97d54..b446365025 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go @@ -421,4 +421,8 @@ const ( SYS_LSM_SET_SELF_ATTR = 460 SYS_LSM_LIST_MODULES = 461 SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go index c66d416dad..0c7d21c188 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go @@ -421,4 +421,8 @@ const ( SYS_LSM_SET_SELF_ATTR = 460 SYS_LSM_LIST_MODULES = 461 SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go index a5459e766f..8405391698 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go @@ -326,4 +326,8 @@ const ( SYS_LSM_SET_SELF_ATTR = 460 SYS_LSM_LIST_MODULES = 461 SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go index 01d86825bb..fcf1b790d6 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go @@ -387,4 +387,8 @@ const ( SYS_LSM_SET_SELF_ATTR = 460 SYS_LSM_LIST_MODULES = 461 SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go index 7b703e77cd..52d15b5f9d 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go @@ -400,4 +400,8 @@ const ( SYS_LSM_SET_SELF_ATTR = 460 SYS_LSM_LIST_MODULES = 461 SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 ) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux.go b/vendor/golang.org/x/sys/unix/ztypes_linux.go index 5537148dcb..a46abe6472 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux.go @@ -4747,7 +4747,7 @@ const ( NL80211_ATTR_MAC_HINT = 0xc8 NL80211_ATTR_MAC_MASK = 0xd7 NL80211_ATTR_MAX_AP_ASSOC_STA = 0xca - NL80211_ATTR_MAX = 0x14c + NL80211_ATTR_MAX = 0x14d NL80211_ATTR_MAX_CRIT_PROT_DURATION = 0xb4 NL80211_ATTR_MAX_CSA_COUNTERS = 0xce NL80211_ATTR_MAX_MATCH_SETS = 0x85 @@ -5519,7 +5519,7 @@ const ( NL80211_MNTR_FLAG_CONTROL = 0x3 NL80211_MNTR_FLAG_COOK_FRAMES = 0x5 NL80211_MNTR_FLAG_FCSFAIL = 0x1 - NL80211_MNTR_FLAG_MAX = 0x6 + NL80211_MNTR_FLAG_MAX = 0x7 NL80211_MNTR_FLAG_OTHER_BSS = 0x4 NL80211_MNTR_FLAG_PLCPFAIL = 0x2 NL80211_MPATH_FLAG_ACTIVE = 0x1 @@ -6174,3 +6174,5 @@ type SockDiagReq struct { Family uint8 Protocol uint8 } + +const RTM_NEWNVLAN = 0x70 diff --git a/vendor/golang.org/x/text/language/parse.go b/vendor/golang.org/x/text/language/parse.go index 4d57222e77..053336e286 100644 --- a/vendor/golang.org/x/text/language/parse.go +++ b/vendor/golang.org/x/text/language/parse.go @@ -59,7 +59,7 @@ func (c CanonType) Parse(s string) (t Tag, err error) { if changed { tt.RemakeString() } - return makeTag(tt), err + return makeTag(tt), nil } // Compose creates a Tag from individual parts, which may be of type Tag, Base, diff --git a/vendor/modules.txt b/vendor/modules.txt index a440bdb047..53de0abe78 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1179,8 +1179,8 @@ go.opentelemetry.io/otel/trace/embedded # golang.org/x/arch v0.8.0 ## explicit; go 1.18 golang.org/x/arch/x86/x86asm -# golang.org/x/crypto v0.32.0 -## explicit; go 1.20 +# golang.org/x/crypto v0.36.0 +## explicit; go 1.23.0 golang.org/x/crypto/argon2 golang.org/x/crypto/blake2b golang.org/x/crypto/blowfish @@ -1236,23 +1236,23 @@ golang.org/x/net/trace ## explicit; go 1.18 golang.org/x/oauth2 golang.org/x/oauth2/internal -# golang.org/x/sync v0.10.0 -## explicit; go 1.18 +# golang.org/x/sync v0.12.0 +## explicit; go 1.23.0 golang.org/x/sync/errgroup golang.org/x/sync/semaphore -# golang.org/x/sys v0.29.0 -## explicit; go 1.18 +# golang.org/x/sys v0.31.0 +## explicit; go 1.23.0 golang.org/x/sys/cpu golang.org/x/sys/plan9 golang.org/x/sys/unix golang.org/x/sys/windows golang.org/x/sys/windows/registry golang.org/x/sys/windows/svc/eventlog -# golang.org/x/term v0.28.0 -## explicit; go 1.18 +# golang.org/x/term v0.30.0 +## explicit; go 1.23.0 golang.org/x/term -# golang.org/x/text v0.21.0 -## explicit; go 1.18 +# golang.org/x/text v0.23.0 +## explicit; go 1.23.0 golang.org/x/text/encoding golang.org/x/text/encoding/charmap golang.org/x/text/encoding/htmlindex From a6a7bcd01747a2bd5c19981523d3b473fbd88f45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Rod=C3=A1k?= Date: Sun, 9 Mar 2025 17:59:53 +0100 Subject: [PATCH 52/58] [v5.4] Fix HealthCheck log destination, count, and size defaults MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GoLang sets unset values to the default value of the type. This means that the destination of the log is an empty string and the count and size are set to 0. However, this means that size and count are unbounded, and this is not the default behavior. Fixes: https://github.com/containers/podman/issues/25473 Fixes: https://issues.redhat.com/browse/RHEL-83262 Fixes: https://issues.redhat.com/browse/RHEL-83557 Fixes: https://issues.redhat.com/browse/RHEL-83556 Signed-off-by: Jan Rodák (cherry picked from commit fff42ac232ecdece93b0ea6053a84f5c3318ea72) Signed-off-by: Jan Rodák --- libpod/container.go | 21 +++ libpod/container_config.go | 9 +- libpod/container_inspect.go | 6 +- libpod/container_internal.go | 6 +- libpod/events.go | 2 +- libpod/healthcheck.go | 12 +- libpod/options.go | 6 +- pkg/api/handlers/libpod/containers_create.go | 2 + pkg/domain/entities/pods.go | 10 +- pkg/domain/infra/abi/containers.go | 4 - pkg/domain/infra/abi/generate.go | 7 +- pkg/specgen/generate/container.go | 20 ++- pkg/specgen/generate/kube/kube.go | 7 +- pkg/specgen/generate/pod_create.go | 5 - pkg/specgen/specgen.go | 15 ++- test/apiv2/20-containers.at | 5 +- test/system/220-healthcheck.bats | 132 ++++++------------- test/upgrade/test-upgrade.bats | 5 + 18 files changed, 139 insertions(+), 135 deletions(-) diff --git a/libpod/container.go b/libpod/container.go index fb9ca11800..5389df0b39 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -1291,6 +1291,27 @@ func (c *Container) HealthCheckConfig() *manifest.Schema2HealthConfig { return c.config.HealthCheckConfig } +func (c *Container) HealthCheckLogDestination() string { + if c.config.HealthLogDestination == nil { + return define.DefaultHealthCheckLocalDestination + } + return *c.config.HealthLogDestination +} + +func (c *Container) HealthCheckMaxLogCount() uint { + if c.config.HealthMaxLogCount == nil { + return define.DefaultHealthMaxLogCount + } + return *c.config.HealthMaxLogCount +} + +func (c *Container) HealthCheckMaxLogSize() uint { + if c.config.HealthMaxLogSize == nil { + return define.DefaultHealthMaxLogSize + } + return *c.config.HealthMaxLogSize +} + // AutoRemove indicates whether the container will be removed after it is executed func (c *Container) AutoRemove() bool { spec := c.config.Spec diff --git a/libpod/container_config.go b/libpod/container_config.go index 3ccfad43c1..8df73190e8 100644 --- a/libpod/container_config.go +++ b/libpod/container_config.go @@ -416,13 +416,16 @@ type ContainerMiscConfig struct { // HealthCheckOnFailureAction defines an action to take once the container turns unhealthy. HealthCheckOnFailureAction define.HealthCheckOnFailureAction `json:"healthcheck_on_failure_action"` // HealthLogDestination defines the destination where the log is stored - HealthLogDestination string `json:"healthLogDestination,omitempty"` + // Nil value means the default value (local). + HealthLogDestination *string `json:"healthLogDestination,omitempty"` // HealthMaxLogCount is maximum number of attempts in the HealthCheck log file. // ('0' value means an infinite number of attempts in the log file) - HealthMaxLogCount uint `json:"healthMaxLogCount,omitempty"` + // Nil value means the default value (5). + HealthMaxLogCount *uint `json:"healthMaxLogCount,omitempty"` // HealthMaxLogSize is the maximum length in characters of stored HealthCheck log // ("0" value means an infinite log length) - HealthMaxLogSize uint `json:"healthMaxLogSize,omitempty"` + // Nil value means the default value (500). + HealthMaxLogSize *uint `json:"healthMaxLogSize,omitempty"` // StartupHealthCheckConfig is the configuration of the startup // healthcheck for the container. This will run before the regular HC // runs, and when it passes the regular HC will be activated. diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go index a173d59a6c..19c3178089 100644 --- a/libpod/container_inspect.go +++ b/libpod/container_inspect.go @@ -437,11 +437,11 @@ func (c *Container) generateInspectContainerConfig(spec *spec.Spec) *define.Insp ctrConfig.HealthcheckOnFailureAction = c.config.HealthCheckOnFailureAction.String() - ctrConfig.HealthLogDestination = c.config.HealthLogDestination + ctrConfig.HealthLogDestination = c.HealthCheckLogDestination() - ctrConfig.HealthMaxLogCount = c.config.HealthMaxLogCount + ctrConfig.HealthMaxLogCount = c.HealthCheckMaxLogCount() - ctrConfig.HealthMaxLogSize = c.config.HealthMaxLogSize + ctrConfig.HealthMaxLogSize = c.HealthCheckMaxLogSize() ctrConfig.CreateCommand = c.config.CreateCommand diff --git a/libpod/container_internal.go b/libpod/container_internal.go index ca2eee1208..3cf15b6985 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -2839,11 +2839,11 @@ func (c *Container) updateGlobalHealthCheckConfiguration(globalOptions define.Gl } if globalOptions.HealthMaxLogCount != nil { - c.config.HealthMaxLogCount = *globalOptions.HealthMaxLogCount + c.config.HealthMaxLogCount = globalOptions.HealthMaxLogCount } if globalOptions.HealthMaxLogSize != nil { - c.config.HealthMaxLogSize = *globalOptions.HealthMaxLogSize + c.config.HealthMaxLogSize = globalOptions.HealthMaxLogSize } if globalOptions.HealthLogDestination != nil { @@ -2851,7 +2851,7 @@ func (c *Container) updateGlobalHealthCheckConfiguration(globalOptions define.Gl if err != nil { return err } - c.config.HealthLogDestination = dest + c.config.HealthLogDestination = &dest } if err := c.runtime.state.SafeRewriteContainerConfig(c, "", "", c.config); err != nil { diff --git a/libpod/events.go b/libpod/events.go index 82738e36ff..cfb91471b0 100644 --- a/libpod/events.go +++ b/libpod/events.go @@ -49,7 +49,7 @@ func (c *Container) newContainerEventWithInspectData(status events.Status, healt e.Image = c.config.RootfsImageName e.Type = events.Container e.HealthStatus = healthCheckResult.Status - if c.config.HealthLogDestination == define.HealthCheckEventsLoggerDestination { + if c.HealthCheckLogDestination() == define.HealthCheckEventsLoggerDestination { if len(healthCheckResult.Log) > 0 { logData, err := json.Marshal(healthCheckResult.Log[len(healthCheckResult.Log)-1]) if err != nil { diff --git a/libpod/healthcheck.go b/libpod/healthcheck.go index 32723d6cf7..62312c5546 100644 --- a/libpod/healthcheck.go +++ b/libpod/healthcheck.go @@ -136,8 +136,8 @@ func (c *Container) runHealthCheck(ctx context.Context, isStartup bool) (define. } eventLog := output.String() - if c.config.HealthMaxLogSize != 0 && len(eventLog) > int(c.config.HealthMaxLogSize) { - eventLog = eventLog[:c.config.HealthMaxLogSize] + if c.HealthCheckMaxLogSize() != 0 && len(eventLog) > int(c.HealthCheckMaxLogSize()) { + eventLog = eventLog[:c.HealthCheckMaxLogSize()] } if timeEnd.Sub(timeStart) > c.HealthCheckConfig().Timeout { @@ -150,7 +150,7 @@ func (c *Container) runHealthCheck(ctx context.Context, isStartup bool) (define. healthCheckResult, err := c.updateHealthCheckLog(hcl, inStartPeriod, isStartup) if err != nil { - return hcResult, "", fmt.Errorf("unable to update health check log %s for %s: %w", c.config.HealthLogDestination, c.ID(), err) + return hcResult, "", fmt.Errorf("unable to update health check log %s for %s: %w", c.getHealthCheckLogDestination(), c.ID(), err) } // Write HC event with appropriate status as the last thing before we @@ -404,7 +404,7 @@ func (c *Container) updateHealthCheckLog(hcl define.HealthCheckLog, inStartPerio } } healthCheck.Log = append(healthCheck.Log, hcl) - if c.config.HealthMaxLogCount != 0 && len(healthCheck.Log) > int(c.config.HealthMaxLogCount) { + if c.HealthCheckMaxLogCount() != 0 && len(healthCheck.Log) > int(c.HealthCheckMaxLogCount()) { healthCheck.Log = healthCheck.Log[1:] } return healthCheck, c.writeHealthCheckLog(healthCheck) @@ -420,11 +420,11 @@ func (c *Container) witeToFileHealthCheckResults(path string, result define.Heal func (c *Container) getHealthCheckLogDestination() string { var destination string - switch c.config.HealthLogDestination { + switch c.HealthCheckLogDestination() { case define.DefaultHealthCheckLocalDestination, define.HealthCheckEventsLoggerDestination, "": destination = filepath.Join(filepath.Dir(c.state.RunDir), "healthcheck.log") default: - destination = filepath.Join(c.config.HealthLogDestination, c.ID()+"-healthcheck.log") + destination = filepath.Join(c.HealthCheckLogDestination(), c.ID()+"-healthcheck.log") } return destination } diff --git a/libpod/options.go b/libpod/options.go index 4578a8ed26..9232cb9791 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -1536,7 +1536,7 @@ func WithHealthCheckLogDestination(destination string) CtrCreateOption { if err != nil { return err } - ctr.config.HealthLogDestination = dest + ctr.config.HealthLogDestination = &dest return nil } } @@ -1547,7 +1547,7 @@ func WithHealthCheckMaxLogCount(maxLogCount uint) CtrCreateOption { if ctr.valid { return define.ErrCtrFinalized } - ctr.config.HealthMaxLogCount = maxLogCount + ctr.config.HealthMaxLogCount = &maxLogCount return nil } } @@ -1558,7 +1558,7 @@ func WithHealthCheckMaxLogSize(maxLogSize uint) CtrCreateOption { if ctr.valid { return define.ErrCtrFinalized } - ctr.config.HealthMaxLogSize = maxLogSize + ctr.config.HealthMaxLogSize = &maxLogSize return nil } } diff --git a/pkg/api/handlers/libpod/containers_create.go b/pkg/api/handlers/libpod/containers_create.go index 1fcf1c413d..6b375fccaa 100644 --- a/pkg/api/handlers/libpod/containers_create.go +++ b/pkg/api/handlers/libpod/containers_create.go @@ -45,6 +45,8 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) { }, ContainerHealthCheckConfig: specgen.ContainerHealthCheckConfig{ HealthLogDestination: define.DefaultHealthCheckLocalDestination, + HealthMaxLogCount: define.DefaultHealthMaxLogCount, + HealthMaxLogSize: define.DefaultHealthMaxLogSize, }, } diff --git a/pkg/domain/entities/pods.go b/pkg/domain/entities/pods.go index 1ae81e87dd..0218378d92 100644 --- a/pkg/domain/entities/pods.go +++ b/pkg/domain/entities/pods.go @@ -5,6 +5,7 @@ import ( "strings" commonFlag "github.com/containers/common/pkg/flag" + "github.com/containers/podman/v5/libpod/define" "github.com/containers/podman/v5/pkg/domain/entities/types" "github.com/containers/podman/v5/pkg/specgen" "github.com/containers/podman/v5/pkg/util" @@ -275,9 +276,12 @@ type ContainerCreateOptions struct { func NewInfraContainerCreateOptions() ContainerCreateOptions { options := ContainerCreateOptions{ - IsInfra: true, - ImageVolume: "anonymous", - MemorySwappiness: -1, + IsInfra: true, + ImageVolume: "anonymous", + MemorySwappiness: -1, + HealthLogDestination: define.DefaultHealthCheckLocalDestination, + HealthMaxLogCount: define.DefaultHealthMaxLogCount, + HealthMaxLogSize: define.DefaultHealthMaxLogSize, } return options } diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go index 5b9481d694..c08f0ab3fb 100644 --- a/pkg/domain/infra/abi/containers.go +++ b/pkg/domain/infra/abi/containers.go @@ -1760,10 +1760,6 @@ func (ic *ContainerEngine) ContainerClone(ctx context.Context, ctrCloneOpts enti spec.Name = generate.CheckName(ic.Libpod, n, true) } - spec.HealthLogDestination = define.DefaultHealthCheckLocalDestination - spec.HealthMaxLogCount = define.DefaultHealthMaxLogCount - spec.HealthMaxLogSize = define.DefaultHealthMaxLogSize - rtSpec, spec, opts, err := generate.MakeContainer(context.Background(), ic.Libpod, spec, true, c) if err != nil { return nil, err diff --git a/pkg/domain/infra/abi/generate.go b/pkg/domain/infra/abi/generate.go index 58e6020132..3df05af958 100644 --- a/pkg/domain/infra/abi/generate.go +++ b/pkg/domain/infra/abi/generate.go @@ -59,7 +59,12 @@ func (ic *ContainerEngine) GenerateSpec(ctx context.Context, opts *entities.Gene } else if p, err := ic.Libpod.LookupPod(opts.ID); err == nil { pspec = &specgen.PodSpecGenerator{} pspec.Name = p.Name() - _, err := generateUtils.PodConfigToSpec(ic.Libpod, pspec, &entities.ContainerCreateOptions{}, opts.ID) + _, err := generateUtils.PodConfigToSpec(ic.Libpod, pspec, + &entities.ContainerCreateOptions{ + HealthLogDestination: define.DefaultHealthCheckLocalDestination, + HealthMaxLogCount: define.DefaultHealthMaxLogCount, + HealthMaxLogSize: define.DefaultHealthMaxLogSize, + }, opts.ID) if err != nil { return nil, err } diff --git a/pkg/specgen/generate/container.go b/pkg/specgen/generate/container.go index c69512027a..85547b7c7f 100644 --- a/pkg/specgen/generate/container.go +++ b/pkg/specgen/generate/container.go @@ -444,9 +444,23 @@ func ConfigToSpec(rt *libpod.Runtime, specg *specgen.SpecGenerator, containerID } } - specg.HealthLogDestination = conf.HealthLogDestination - specg.HealthMaxLogCount = conf.HealthMaxLogCount - specg.HealthMaxLogSize = conf.HealthMaxLogSize + if conf.HealthLogDestination != nil { + specg.HealthLogDestination = *conf.HealthLogDestination + } else { + specg.HealthLogDestination = define.DefaultHealthCheckLocalDestination + } + + if conf.HealthMaxLogCount != nil { + specg.HealthMaxLogCount = *conf.HealthMaxLogCount + } else { + specg.HealthMaxLogCount = define.DefaultHealthMaxLogCount + } + + if conf.HealthMaxLogSize != nil { + specg.HealthMaxLogSize = *conf.HealthMaxLogSize + } else { + specg.HealthMaxLogSize = define.DefaultHealthMaxLogSize + } specg.IDMappings = &conf.IDMappings specg.ContainerCreateCommand = conf.CreateCommand diff --git a/pkg/specgen/generate/kube/kube.go b/pkg/specgen/generate/kube/kube.go index f02339319e..6c5782a202 100644 --- a/pkg/specgen/generate/kube/kube.go +++ b/pkg/specgen/generate/kube/kube.go @@ -404,6 +404,10 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener s.Annotations[define.InspectAnnotationInit] = init } + s.HealthLogDestination = define.DefaultHealthCheckLocalDestination + s.HealthMaxLogCount = define.DefaultHealthMaxLogCount + s.HealthMaxLogSize = define.DefaultHealthMaxLogSize + if publishAll, ok := opts.Annotations[define.InspectAnnotationPublishAll+"/"+opts.Container.Name]; ok { if opts.IsInfra { publishAllAsBool, err := strconv.ParseBool(publishAll) @@ -417,9 +421,6 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener } s.Annotations[define.KubeHealthCheckAnnotation] = "true" - s.HealthLogDestination = define.DefaultHealthCheckLocalDestination - s.HealthMaxLogCount = define.DefaultHealthMaxLogCount - s.HealthMaxLogSize = define.DefaultHealthMaxLogSize // Environment Variables envs := map[string]string{} diff --git a/pkg/specgen/generate/pod_create.go b/pkg/specgen/generate/pod_create.go index d835e15d7a..f0a14ce86c 100644 --- a/pkg/specgen/generate/pod_create.go +++ b/pkg/specgen/generate/pod_create.go @@ -86,11 +86,6 @@ func MakePod(p *entities.PodSpec, rt *libpod.Runtime) (_ *libpod.Pod, finalErr e p.PodSpecGen.InfraContainerSpec.ResourceLimits = nil p.PodSpecGen.InfraContainerSpec.WeightDevice = nil - // Set default for HealthCheck - p.PodSpecGen.InfraContainerSpec.HealthLogDestination = define.DefaultHealthCheckLocalDestination - p.PodSpecGen.InfraContainerSpec.HealthMaxLogCount = define.DefaultHealthMaxLogCount - p.PodSpecGen.InfraContainerSpec.HealthMaxLogSize = define.DefaultHealthMaxLogSize - rtSpec, spec, opts, err := MakeContainer(context.Background(), rt, p.PodSpecGen.InfraContainerSpec, false, nil) if err != nil { return nil, err diff --git a/pkg/specgen/specgen.go b/pkg/specgen/specgen.go index c5ba5fe17f..3efe4c9ce6 100644 --- a/pkg/specgen/specgen.go +++ b/pkg/specgen/specgen.go @@ -602,14 +602,17 @@ type ContainerHealthCheckConfig struct { // Requires that HealthConfig be set. // Optional. StartupHealthConfig *define.StartupHealthCheck `json:"startupHealthConfig,omitempty"` - // HealthLogDestination defines the destination where the log is stored - HealthLogDestination string `json:"healthLogDestination,omitempty"` + // HealthLogDestination defines the destination where the log is stored. + // TODO (6.0): In next major release convert it to pointer and use omitempty + HealthLogDestination string `json:"healthLogDestination"` // HealthMaxLogCount is maximum number of attempts in the HealthCheck log file. - // ('0' value means an infinite number of attempts in the log file) - HealthMaxLogCount uint `json:"healthMaxLogCount,omitempty"` + // ('0' value means an infinite number of attempts in the log file). + // TODO (6.0): In next major release convert it to pointer and use omitempty + HealthMaxLogCount uint `json:"healthMaxLogCount"` // HealthMaxLogSize is the maximum length in characters of stored HealthCheck log - // ("0" value means an infinite log length) - HealthMaxLogSize uint `json:"healthMaxLogSize,omitempty"` + // ("0" value means an infinite log length). + // TODO (6.0): In next major release convert it to pointer and use omitempty + HealthMaxLogSize uint `json:"healthMaxLogSize"` } // SpecGenerator creates an OCI spec and Libpod configuration options to create diff --git a/test/apiv2/20-containers.at b/test/apiv2/20-containers.at index 14379f4751..56c617939c 100644 --- a/test/apiv2/20-containers.at +++ b/test/apiv2/20-containers.at @@ -199,7 +199,10 @@ t GET libpod/containers/${cid}/json 200 \ .State.Running=false \ .State.ExitCode=0 \ .Config.Umask=0022 \ - .Config.CreateCommand=null + .Config.CreateCommand=null \ + .Config.HealthLogDestination=local \ + .Config.HealthcheckMaxLogCount=5 \ + .Config.HealthcheckMaxLogSize=500 t DELETE libpod/containers/$cid 200 .[0].Id=$cid CNAME=myfoo diff --git a/test/system/220-healthcheck.bats b/test/system/220-healthcheck.bats index f232d6ea4f..00b788858a 100644 --- a/test/system/220-healthcheck.bats +++ b/test/system/220-healthcheck.bats @@ -316,107 +316,59 @@ function _check_health_log { assert "$count" $comparison $expect_count "Number of matching health log messages" } -@test "podman healthcheck --health-max-log-count default value (5)" { - local msg="healthmsg-$(random_string)" - local ctrname="c-h-$(safename)" - _create_container_with_health_log_settings $ctrname $msg "{{.Config.HealthMaxLogCount}}" "" "5" "HealthMaxLogCount is the expected default" - - for i in $(seq 1 10); - do - run_podman healthcheck run $ctrname - is "$output" "" "unexpected output from podman healthcheck run (pass $i)" - done - - _check_health_log $ctrname $msg -eq 5 - - run_podman rm -t 0 -f $ctrname -} - -@test "podman healthcheck --health-max-log-count infinite value (0)" { - local repeat_count=10 - local msg="healthmsg-$(random_string)" - local ctrname="c-h-$(safename)" - _create_container_with_health_log_settings $ctrname $msg "{{.Config.HealthMaxLogCount}}" "--health-max-log-count 0" "0" "HealthMaxLogCount" - - # This is run one more time than repeat_count to check that the cap is working. - for i in $(seq 1 $(($repeat_count + 1))); - do - run_podman healthcheck run $ctrname - is "$output" "" "unexpected output from podman healthcheck run (pass $i)" - done - - # The healthcheck is triggered by the podman when the container is started, but its execution depends on systemd. - # And since `run_podman healthcheck run` is also run manually, it will result in two runs. - _check_health_log $ctrname $msg -ge 11 - - run_podman rm -t 0 -f $ctrname -} - - -@test "podman healthcheck --health-max-log-count 10" { - local repeat_count=10 - local msg="healthmsg-$(random_string)" - local ctrname="c-h-$(safename)" - _create_container_with_health_log_settings $ctrname $msg "{{.Config.HealthMaxLogCount}}" "--health-max-log-count $repeat_count" "$repeat_count" "HealthMaxLogCount" - - # This is run one more time than repeat_count to check that the cap is working. - for i in $(seq 1 $(($repeat_count + 1))); - do - run_podman healthcheck run $ctrname - is "$output" "" "unexpected output from podman healthcheck run (pass $i)" - done - - _check_health_log $ctrname $msg -eq $repeat_count - - run_podman rm -t 0 -f $ctrname +@test "podman healthcheck --health-max-log-count values" { + # flag | expected value | op | log count + test=" + | 5 | -eq | 5 + --health-max-log-count 0 | 0 | -ge | 11 + --health-max-log-count=0 | 0 | -ge | 11 + --health-max-log-count 10 | 10 | -eq | 10 + --health-max-log-count=10 | 10 | -eq | 10 + " + + while read flag value op logs_count ; do + local msg="healthmsg-$(random_string)" + local ctrname="c-h-$(safename)" + _create_container_with_health_log_settings $ctrname $msg "{{.Config.HealthMaxLogCount}}" $flag $value "HealthMaxLogCount" + + for i in $(seq 1 $((logs_count + 5))); + do + run_podman healthcheck run $ctrname + is "$output" "" "unexpected output from podman healthcheck run (pass $i)" + done + + _check_health_log $ctrname $msg $op $logs_count + + run_podman rm -t 0 -f $ctrname + done < <(parse_table "$tests") } -@test "podman healthcheck --health-max-log-size 10" { - local msg="healthmsg-$(random_string)" - local ctrname="c-h-$(safename)" - _create_container_with_health_log_settings $ctrname $msg "{{.Config.HealthMaxLogSize}}" "--health-max-log-size 10" "10" "HealthMaxLogSize" - - run_podman healthcheck run $ctrname - is "$output" "" "output from 'podman healthcheck run'" - - local substr=${msg:0:10} - _check_health_log $ctrname "$substr}]\$" -eq 1 - - run_podman rm -t 0 -f $ctrname -} - -@test "podman healthcheck --health-max-log-size infinite value (0)" { +@test "podman healthcheck --health-max-log-size values" { local s=$(printf "healthmsg-%1000s") local long_msg=${s// /$(random_string)} - local ctrname="c-h-$(safename)" - _create_container_with_health_log_settings $ctrname $long_msg "{{.Config.HealthMaxLogSize}}" "--health-max-log-size 0" "0" "HealthMaxLogSize" - run_podman healthcheck run $ctrname - is "$output" "" "output from 'podman healthcheck run'" + # flag | expected value | exp_msg + test=" + | 500 | ${long_msg:0:500}}]\$ + --health-max-log-size 0 | 0 | $long_msg}]\$ + --health-max-log-size=0 | 0 | $long_msg}]\$ + --health-max-log-size 10 | 10 | ${long_msg:0:10}}]\$ + --health-max-log-size=10 | 10 | ${long_msg:0:10}}]\$ + " - # The healthcheck is triggered by the podman when the container is started, but its execution depends on systemd. - # And since `run_podman healthcheck run` is also run manually, it will result in two runs. - _check_health_log $ctrname "$long_msg" -ge 1 - - run_podman rm -t 0 -f $ctrname -} - -@test "podman healthcheck --health-max-log-size default value (500)" { - local s=$(printf "healthmsg-%1000s") - local long_msg=${s// /$(random_string)} - local ctrname="c-h-$(safename)" - _create_container_with_health_log_settings $ctrname $long_msg "{{.Config.HealthMaxLogSize}}" "" "500" "HealthMaxLogSize is the expected default" + while read flag value exp_msg ; do + local ctrname="c-h-$(safename)" + _create_container_with_health_log_settings $ctrname $long_msg "{{.Config.HealthMaxLogSize}}" $flag $value "HealthMaxLogSize" - run_podman healthcheck run $ctrname - is "$output" "" "output from 'podman healthcheck run'" + run_podman healthcheck run $ctrname + is "$output" "" "output from 'podman healthcheck run'" - local expect_msg="${long_msg:0:500}" - _check_health_log $ctrname "$expect_msg}]\$" -eq 1 + _check_health_log $ctrname $exp_msg -eq 1 - run_podman rm -t 0 -f $ctrname + run_podman rm -t 0 -f $ctrname + done < <(parse_table "$tests") } - @test "podman healthcheck --health-log-destination file" { local TMP_DIR_HEALTHCHECK="$PODMAN_TMPDIR/healthcheck" mkdir $TMP_DIR_HEALTHCHECK diff --git a/test/upgrade/test-upgrade.bats b/test/upgrade/test-upgrade.bats index 3686c63f1f..4760aac216 100644 --- a/test/upgrade/test-upgrade.bats +++ b/test/upgrade/test-upgrade.bats @@ -274,6 +274,11 @@ failed | exited | 17 done < <(parse_table "$tests") } +@test "inspect - HealthCheck Defaults" { + run_podman inspect --format '{{.Config.HealthMaxLogSize}}--{{.Config.HealthMaxLogCount}}--{{.Config.HealthLogDestination}}' myrunningcontainer + assert "$output" == "500--5--local" "HealthCheck Default values of Log size, count and destination" +} + @test "network - curl" { run -0 curl --max-time 3 -s 127.0.0.1:$HOST_PORT/index.txt is "$output" "$RANDOM_STRING_1" "curl on running container" From 0fb468f32a199a46c053a4f63074fa5d0dd2ce67 Mon Sep 17 00:00:00 2001 From: tomsweeneyredhat Date: Fri, 14 Mar 2025 16:06:00 -0400 Subject: [PATCH 53/58] [v5.4-rhel] Bump to Buildah v1.39.3 Bump Buildah to v1.39.3. In the process also bump: c/storage v1.57.2 c/image v5.34.2 c/common v0.62.2 This is the last step in the dance and fixes: https://issues.redhat.com/browse/RHEL-82509, https://issues.redhat.com/browse/RHEL-82511 Force private propagation of ID mapped mounts. Signed-off-by: tomsweeneyredhat --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- .../github.com/containers/buildah/CHANGELOG.md | 4 ++++ .../github.com/containers/buildah/changelog.txt | 3 +++ .../containers/buildah/define/types.go | 2 +- .../containers/common/version/version.go | 2 +- .../containers/image/v5/version/version.go | 2 +- vendor/github.com/containers/storage/Makefile | 2 +- vendor/github.com/containers/storage/VERSION | 2 +- .../storage/pkg/idmap/idmapped_utils.go | 5 +++-- vendor/modules.txt | 8 ++++---- 11 files changed, 31 insertions(+), 23 deletions(-) diff --git a/go.mod b/go.mod index bb850d8e5b..a808cee8d9 100644 --- a/go.mod +++ b/go.mod @@ -13,15 +13,15 @@ require ( github.com/checkpoint-restore/checkpointctl v1.3.0 github.com/checkpoint-restore/go-criu/v7 v7.2.0 github.com/containernetworking/plugins v1.5.1 - github.com/containers/buildah v1.39.2 - github.com/containers/common v0.62.1 + github.com/containers/buildah v1.39.3 + github.com/containers/common v0.62.2 github.com/containers/conmon v2.0.20+incompatible github.com/containers/gvisor-tap-vsock v0.8.3 - github.com/containers/image/v5 v5.34.1 + github.com/containers/image/v5 v5.34.2 github.com/containers/libhvee v0.9.0 github.com/containers/ocicrypt v1.2.1 github.com/containers/psgo v1.9.0 - github.com/containers/storage v1.57.1 + github.com/containers/storage v1.57.2 github.com/containers/winquit v1.1.0 github.com/coreos/go-systemd/v22 v22.5.1-0.20231103132048-7d375ecc2b09 github.com/crc-org/crc/v2 v2.45.0 diff --git a/go.sum b/go.sum index 38565e5e7d..fc84988202 100644 --- a/go.sum +++ b/go.sum @@ -76,16 +76,16 @@ github.com/containernetworking/cni v1.2.3 h1:hhOcjNVUQTnzdRJ6alC5XF+wd9mfGIUaj8F github.com/containernetworking/cni v1.2.3/go.mod h1:DuLgF+aPd3DzcTQTtp/Nvl1Kim23oFKdm2okJzBQA5M= github.com/containernetworking/plugins v1.5.1 h1:T5ji+LPYjjgW0QM+KyrigZbLsZ8jaX+E5J/EcKOE4gQ= github.com/containernetworking/plugins v1.5.1/go.mod h1:MIQfgMayGuHYs0XdNudf31cLLAC+i242hNm6KuDGqCM= -github.com/containers/buildah v1.39.2 h1:YaFMNnuTr7wKYKQDHkm7yyP9HhWVrNB4DA+DjYUS9k4= -github.com/containers/buildah v1.39.2/go.mod h1:Vb4sDbEq06qQqk29mcGw/1qit8dyukpfL4hwNQ5t+z8= -github.com/containers/common v0.62.1 h1:durvu7Kelb8PYgX7bwuAg/d5LKj2hs3cAaqcU7Vnqus= -github.com/containers/common v0.62.1/go.mod h1:n9cEboBmY3AnTk1alkq4t7sLM4plwkDCiaWbsf67YxE= +github.com/containers/buildah v1.39.3 h1:JAIbtTblL6XIdhfH+/5ndSR++0yonF2409jlQ+rD8SE= +github.com/containers/buildah v1.39.3/go.mod h1:WtjZt6kqSVzibr7AVkW9QlLok6pB0jlLe2LedgmL4+s= +github.com/containers/common v0.62.2 h1:xO45OOoeq17EZMIDZoSyRqg7GXGcRHa9sXlrr75zH+U= +github.com/containers/common v0.62.2/go.mod h1:veFiR9iq2j3CHXtB4YnPHuOkSRdhIQ3bAY8AFMP/5bE= github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg= github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I= github.com/containers/gvisor-tap-vsock v0.8.3 h1:Am3VdjXTn8Mn+dNhgkiRcCFOTSM8u9aWKLW3KTHOGjk= github.com/containers/gvisor-tap-vsock v0.8.3/go.mod h1:46MvrqNuRNbjV4ZsZ3mHVJjR2Eh+fpyRh72EvWWFFjU= -github.com/containers/image/v5 v5.34.1 h1:/m2bkFnuedTyNkzma8s7cFLjeefPIb4trjyafWhIlwM= -github.com/containers/image/v5 v5.34.1/go.mod h1:/WnvUSEfdqC/ahMRd4YJDBLrpYWkGl018rB77iB3FDo= +github.com/containers/image/v5 v5.34.2 h1:3r1etun4uJYq5197tcymUcI1h6+zyzKS9PtRtBlEKMI= +github.com/containers/image/v5 v5.34.2/go.mod h1:MG++slvQSZVq5ejAcLdu4APGsKGMb0YHHnAo7X28fdE= github.com/containers/libhvee v0.9.0 h1:5UxJMka1lDfxTeITA25Pd8QVVttJAG43eQS1Getw1tc= github.com/containers/libhvee v0.9.0/go.mod h1:p44VJd8jMIx3SRN1eM6PxfCEwXQE0lJ0dQppCAlzjPQ= github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 h1:Qzk5C6cYglewc+UyGf6lc8Mj2UaPTHy/iF2De0/77CA= @@ -96,8 +96,8 @@ github.com/containers/ocicrypt v1.2.1 h1:0qIOTT9DoYwcKmxSt8QJt+VzMY18onl9jUXsxpV github.com/containers/ocicrypt v1.2.1/go.mod h1:aD0AAqfMp0MtwqWgHM1bUwe1anx0VazI108CRrSKINQ= github.com/containers/psgo v1.9.0 h1:eJ74jzSaCHnWt26OlKZROSyUyRcGDf+gYBdXnxrMW4g= github.com/containers/psgo v1.9.0/go.mod h1:0YoluUm43Mz2UnBIh1P+6V6NWcbpTL5uRtXyOcH0B5A= -github.com/containers/storage v1.57.1 h1:hKPoFsuBcB3qTzBxa4IFpZMRzUuL5Xhv/BE44W0XHx8= -github.com/containers/storage v1.57.1/go.mod h1:i/Hb4lu7YgFr9G0K6BMjqW0BLJO1sFsnWQwj2UoWCUM= +github.com/containers/storage v1.57.2 h1:2roCtTyE9pzIaBDHibK72DTnYkPmwWaq5uXxZdaWK4U= +github.com/containers/storage v1.57.2/go.mod h1:i/Hb4lu7YgFr9G0K6BMjqW0BLJO1sFsnWQwj2UoWCUM= github.com/containers/winquit v1.1.0 h1:jArun04BNDQvt2W0Y78kh9TazN2EIEMG5Im6/JY7+pE= github.com/containers/winquit v1.1.0/go.mod h1:PsPeZlnbkmGGIToMPHF1zhWjBUkd8aHjMOr/vFcPxw8= github.com/coreos/go-oidc/v3 v3.12.0 h1:sJk+8G2qq94rDI6ehZ71Bol3oUHy63qNYmkiSjrc/Jo= diff --git a/vendor/github.com/containers/buildah/CHANGELOG.md b/vendor/github.com/containers/buildah/CHANGELOG.md index 98d053105a..b3f4c4e33a 100644 --- a/vendor/github.com/containers/buildah/CHANGELOG.md +++ b/vendor/github.com/containers/buildah/CHANGELOG.md @@ -2,6 +2,10 @@ # Changelog +## v1.39.3 (2025-03-12) + + [release-1.39] Bump c/storage to v1.57.2, c/image v5.34.2, c/common v0.62.2 + ## v1.39.2 (2025-03-03) [release-1.39] Bump c/image to v5.34.1, c/common v0.62.1 diff --git a/vendor/github.com/containers/buildah/changelog.txt b/vendor/github.com/containers/buildah/changelog.txt index db6ed8cad4..02e1abd24b 100644 --- a/vendor/github.com/containers/buildah/changelog.txt +++ b/vendor/github.com/containers/buildah/changelog.txt @@ -1,3 +1,6 @@ +- Changelog for v1.39.3 (2025-03-12) + * [release-1.39] Bump c/storage to v1.57.2, c/image v5.34.2, c/common v0.62.2 + - Changelog for v1.39.2 (2025-03-03) * [release-1.39] Bump c/image to v5.34.1, c/common v0.62.1 diff --git a/vendor/github.com/containers/buildah/define/types.go b/vendor/github.com/containers/buildah/define/types.go index 234cb340ec..d2a820b855 100644 --- a/vendor/github.com/containers/buildah/define/types.go +++ b/vendor/github.com/containers/buildah/define/types.go @@ -29,7 +29,7 @@ const ( // identify working containers. Package = "buildah" // Version for the Package. Also used by .packit.sh for Packit builds. - Version = "1.39.2" + Version = "1.39.3" // DefaultRuntime if containers.conf fails. DefaultRuntime = "runc" diff --git a/vendor/github.com/containers/common/version/version.go b/vendor/github.com/containers/common/version/version.go index 43e89ee32b..6487190a35 100644 --- a/vendor/github.com/containers/common/version/version.go +++ b/vendor/github.com/containers/common/version/version.go @@ -1,4 +1,4 @@ package version // Version is the version of the build. -const Version = "0.62.1" +const Version = "0.62.2" diff --git a/vendor/github.com/containers/image/v5/version/version.go b/vendor/github.com/containers/image/v5/version/version.go index cb61f56294..6c0cc885d5 100644 --- a/vendor/github.com/containers/image/v5/version/version.go +++ b/vendor/github.com/containers/image/v5/version/version.go @@ -8,7 +8,7 @@ const ( // VersionMinor is for functionality in a backwards-compatible manner VersionMinor = 34 // VersionPatch is for backwards-compatible bug fixes - VersionPatch = 1 + VersionPatch = 2 // VersionDev indicates development branch. Releases will be empty string. VersionDev = "" diff --git a/vendor/github.com/containers/storage/Makefile b/vendor/github.com/containers/storage/Makefile index 888fef8427..518fd7f6e4 100644 --- a/vendor/github.com/containers/storage/Makefile +++ b/vendor/github.com/containers/storage/Makefile @@ -35,7 +35,7 @@ TESTFLAGS := $(shell $(GO) test -race $(BUILDFLAGS) ./pkg/stringutils 2>&1 > /de # N/B: This value is managed by Renovate, manual changes are # possible, as long as they don't disturb the formatting # (i.e. DO NOT ADD A 'v' prefix!) -GOLANGCI_LINT_VERSION := 1.63.4 +GOLANGCI_LINT_VERSION := 1.64.5 default all: local-binary docs local-validate local-cross ## validate all checks, build and cross-build\nbinaries and docs diff --git a/vendor/github.com/containers/storage/VERSION b/vendor/github.com/containers/storage/VERSION index b4cf7c0db5..0af844be06 100644 --- a/vendor/github.com/containers/storage/VERSION +++ b/vendor/github.com/containers/storage/VERSION @@ -1 +1 @@ -1.57.1 +1.57.2 diff --git a/vendor/github.com/containers/storage/pkg/idmap/idmapped_utils.go b/vendor/github.com/containers/storage/pkg/idmap/idmapped_utils.go index db31da768a..4a75b70fd9 100644 --- a/vendor/github.com/containers/storage/pkg/idmap/idmapped_utils.go +++ b/vendor/github.com/containers/storage/pkg/idmap/idmapped_utils.go @@ -33,8 +33,9 @@ func CreateIDMappedMount(source, target string, pid int) error { if err := unix.MountSetattr(targetDirFd, "", unix.AT_EMPTY_PATH|unix.AT_RECURSIVE, &unix.MountAttr{ - Attr_set: unix.MOUNT_ATTR_IDMAP, - Userns_fd: uint64(userNsFile.Fd()), + Attr_set: unix.MOUNT_ATTR_IDMAP, + Userns_fd: uint64(userNsFile.Fd()), + Propagation: unix.MS_PRIVATE, }); err != nil { return &os.PathError{Op: "mount_setattr", Path: source, Err: err} } diff --git a/vendor/modules.txt b/vendor/modules.txt index 53de0abe78..2adcafc6e8 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -147,7 +147,7 @@ github.com/containernetworking/cni/pkg/version # github.com/containernetworking/plugins v1.5.1 ## explicit; go 1.20 github.com/containernetworking/plugins/pkg/ns -# github.com/containers/buildah v1.39.2 +# github.com/containers/buildah v1.39.3 ## explicit; go 1.22.8 github.com/containers/buildah github.com/containers/buildah/bind @@ -179,7 +179,7 @@ github.com/containers/buildah/pkg/sshagent github.com/containers/buildah/pkg/util github.com/containers/buildah/pkg/volumes github.com/containers/buildah/util -# github.com/containers/common v0.62.1 +# github.com/containers/common v0.62.2 ## explicit; go 1.22.8 github.com/containers/common/internal github.com/containers/common/internal/attributedstring @@ -252,7 +252,7 @@ github.com/containers/conmon/runner/config # github.com/containers/gvisor-tap-vsock v0.8.3 ## explicit; go 1.22.0 github.com/containers/gvisor-tap-vsock/pkg/types -# github.com/containers/image/v5 v5.34.1 +# github.com/containers/image/v5 v5.34.2 ## explicit; go 1.22.8 github.com/containers/image/v5/copy github.com/containers/image/v5/directory @@ -364,7 +364,7 @@ github.com/containers/psgo/internal/dev github.com/containers/psgo/internal/host github.com/containers/psgo/internal/proc github.com/containers/psgo/internal/process -# github.com/containers/storage v1.57.1 +# github.com/containers/storage v1.57.2 ## explicit; go 1.22.0 github.com/containers/storage github.com/containers/storage/drivers From 7289dee40b0fdf7418155ddeb1a38ea645b6b1b8 Mon Sep 17 00:00:00 2001 From: tomsweeneyredhat Date: Fri, 28 Mar 2025 11:34:03 -0400 Subject: [PATCH 54/58] [v5.4-rhel] Bump Buildah to v1.39.4 Bump Buildah to v1.39.4. This will fix a DDIF issue as noted in: https://issues.redhat.com/browse/RHEL-85212 and https://github.com/containers/podman/issues/25593. This also addresesses an Image Mode issue when tweaking mount variables as noted in: https://issues.redhat.com/browse/RHEL-79560 Fixes: https://issues.redhat.com/browse/RHEL-85218, https://issues.redhat.com/browse/RHEL-85219, https://issues.redhat.com/browse/RHEL-85116, https://issues.redhat.com/browse/RHEL-85117 Signed-off-by: tomsweeneyredhat --- go.mod | 6 +- go.sum | 12 ++-- .../containers/buildah/CHANGELOG.md | 5 ++ .../containers/buildah/changelog.txt | 4 ++ .../containers/buildah/chroot/run_linux.go | 2 +- .../containers/buildah/define/types.go | 2 +- .../containers/common/version/version.go | 2 +- .../image/v5/tarball/tarball_src.go | 61 ++++++++++++------- .../containers/image/v5/version/version.go | 2 +- vendor/modules.txt | 6 +- 10 files changed, 64 insertions(+), 38 deletions(-) diff --git a/go.mod b/go.mod index a808cee8d9..ab49d148b6 100644 --- a/go.mod +++ b/go.mod @@ -13,11 +13,11 @@ require ( github.com/checkpoint-restore/checkpointctl v1.3.0 github.com/checkpoint-restore/go-criu/v7 v7.2.0 github.com/containernetworking/plugins v1.5.1 - github.com/containers/buildah v1.39.3 - github.com/containers/common v0.62.2 + github.com/containers/buildah v1.39.4 + github.com/containers/common v0.62.3 github.com/containers/conmon v2.0.20+incompatible github.com/containers/gvisor-tap-vsock v0.8.3 - github.com/containers/image/v5 v5.34.2 + github.com/containers/image/v5 v5.34.3 github.com/containers/libhvee v0.9.0 github.com/containers/ocicrypt v1.2.1 github.com/containers/psgo v1.9.0 diff --git a/go.sum b/go.sum index fc84988202..b48572114d 100644 --- a/go.sum +++ b/go.sum @@ -76,16 +76,16 @@ github.com/containernetworking/cni v1.2.3 h1:hhOcjNVUQTnzdRJ6alC5XF+wd9mfGIUaj8F github.com/containernetworking/cni v1.2.3/go.mod h1:DuLgF+aPd3DzcTQTtp/Nvl1Kim23oFKdm2okJzBQA5M= github.com/containernetworking/plugins v1.5.1 h1:T5ji+LPYjjgW0QM+KyrigZbLsZ8jaX+E5J/EcKOE4gQ= github.com/containernetworking/plugins v1.5.1/go.mod h1:MIQfgMayGuHYs0XdNudf31cLLAC+i242hNm6KuDGqCM= -github.com/containers/buildah v1.39.3 h1:JAIbtTblL6XIdhfH+/5ndSR++0yonF2409jlQ+rD8SE= -github.com/containers/buildah v1.39.3/go.mod h1:WtjZt6kqSVzibr7AVkW9QlLok6pB0jlLe2LedgmL4+s= -github.com/containers/common v0.62.2 h1:xO45OOoeq17EZMIDZoSyRqg7GXGcRHa9sXlrr75zH+U= -github.com/containers/common v0.62.2/go.mod h1:veFiR9iq2j3CHXtB4YnPHuOkSRdhIQ3bAY8AFMP/5bE= +github.com/containers/buildah v1.39.4 h1:XTL1+N9wJcSAqXUl4ReFK286QWLTIGp44jBqs9Qd2y0= +github.com/containers/buildah v1.39.4/go.mod h1:EPFAYD/27eXceT8shzWxKg+asgorc8nzrjiG9qFCqTk= +github.com/containers/common v0.62.3 h1:aOGryqXfW6aKBbHbqOveH7zB+ihavUN03X/2pUSvWFI= +github.com/containers/common v0.62.3/go.mod h1:3R8kDox2prC9uj/a2hmXj/YjZz5sBEUNrcDiw51S0Lo= github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg= github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I= github.com/containers/gvisor-tap-vsock v0.8.3 h1:Am3VdjXTn8Mn+dNhgkiRcCFOTSM8u9aWKLW3KTHOGjk= github.com/containers/gvisor-tap-vsock v0.8.3/go.mod h1:46MvrqNuRNbjV4ZsZ3mHVJjR2Eh+fpyRh72EvWWFFjU= -github.com/containers/image/v5 v5.34.2 h1:3r1etun4uJYq5197tcymUcI1h6+zyzKS9PtRtBlEKMI= -github.com/containers/image/v5 v5.34.2/go.mod h1:MG++slvQSZVq5ejAcLdu4APGsKGMb0YHHnAo7X28fdE= +github.com/containers/image/v5 v5.34.3 h1:/cMgfyA4Y7ILH7nzWP/kqpkE5Df35Ek4bp5ZPvJOVmI= +github.com/containers/image/v5 v5.34.3/go.mod h1:MG++slvQSZVq5ejAcLdu4APGsKGMb0YHHnAo7X28fdE= github.com/containers/libhvee v0.9.0 h1:5UxJMka1lDfxTeITA25Pd8QVVttJAG43eQS1Getw1tc= github.com/containers/libhvee v0.9.0/go.mod h1:p44VJd8jMIx3SRN1eM6PxfCEwXQE0lJ0dQppCAlzjPQ= github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 h1:Qzk5C6cYglewc+UyGf6lc8Mj2UaPTHy/iF2De0/77CA= diff --git a/vendor/github.com/containers/buildah/CHANGELOG.md b/vendor/github.com/containers/buildah/CHANGELOG.md index b3f4c4e33a..fe4a9b8575 100644 --- a/vendor/github.com/containers/buildah/CHANGELOG.md +++ b/vendor/github.com/containers/buildah/CHANGELOG.md @@ -2,6 +2,11 @@ # Changelog +## v1.39.4 (2025-03-27) + + [release-1.39] Bump c/image to v5.34.3, c/common v0.62.3 + createPlatformContainer: drop MS_REMOUNT|MS_BIND + ## v1.39.3 (2025-03-12) [release-1.39] Bump c/storage to v1.57.2, c/image v5.34.2, c/common v0.62.2 diff --git a/vendor/github.com/containers/buildah/changelog.txt b/vendor/github.com/containers/buildah/changelog.txt index 02e1abd24b..1c2be4aadb 100644 --- a/vendor/github.com/containers/buildah/changelog.txt +++ b/vendor/github.com/containers/buildah/changelog.txt @@ -1,3 +1,7 @@ +- Changelog for v1.39.4 (2025-03-27) + * [release-1.39] Bump c/image to v5.34.3, c/common v0.62.3 + * createPlatformContainer: drop MS_REMOUNT|MS_BIND + - Changelog for v1.39.3 (2025-03-12) * [release-1.39] Bump c/storage to v1.57.2, c/image v5.34.2, c/common v0.62.2 diff --git a/vendor/github.com/containers/buildah/chroot/run_linux.go b/vendor/github.com/containers/buildah/chroot/run_linux.go index 76900d7f0c..cd19fa0173 100644 --- a/vendor/github.com/containers/buildah/chroot/run_linux.go +++ b/vendor/github.com/containers/buildah/chroot/run_linux.go @@ -263,7 +263,7 @@ func createPlatformContainer(options runUsingChrootExecSubprocOptions) error { return fmt.Errorf("changing to host root directory: %w", err) } // make sure we only unmount things under this tree - if err := unix.Mount(".", ".", "bind", unix.MS_REMOUNT|unix.MS_BIND|unix.MS_SLAVE|unix.MS_REC, ""); err != nil { + if err := unix.Mount(".", ".", "", unix.MS_SLAVE|unix.MS_REC, ""); err != nil { return fmt.Errorf("tweaking mount flags on host root directory before unmounting from mount namespace: %w", err) } // detach this (unnamed?) old directory diff --git a/vendor/github.com/containers/buildah/define/types.go b/vendor/github.com/containers/buildah/define/types.go index d2a820b855..65b3a1bf28 100644 --- a/vendor/github.com/containers/buildah/define/types.go +++ b/vendor/github.com/containers/buildah/define/types.go @@ -29,7 +29,7 @@ const ( // identify working containers. Package = "buildah" // Version for the Package. Also used by .packit.sh for Packit builds. - Version = "1.39.3" + Version = "1.39.4" // DefaultRuntime if containers.conf fails. DefaultRuntime = "runc" diff --git a/vendor/github.com/containers/common/version/version.go b/vendor/github.com/containers/common/version/version.go index 6487190a35..cef52d7aba 100644 --- a/vendor/github.com/containers/common/version/version.go +++ b/vendor/github.com/containers/common/version/version.go @@ -1,4 +1,4 @@ package version // Version is the version of the build. -const Version = "0.62.2" +const Version = "0.62.3" diff --git a/vendor/github.com/containers/image/v5/tarball/tarball_src.go b/vendor/github.com/containers/image/v5/tarball/tarball_src.go index 7d4a83bc91..283a32d0ee 100644 --- a/vendor/github.com/containers/image/v5/tarball/tarball_src.go +++ b/vendor/github.com/containers/image/v5/tarball/tarball_src.go @@ -14,8 +14,9 @@ import ( "github.com/containers/image/v5/internal/imagesource/impl" "github.com/containers/image/v5/internal/imagesource/stubs" + "github.com/containers/image/v5/pkg/compression" + compressionTypes "github.com/containers/image/v5/pkg/compression/types" "github.com/containers/image/v5/types" - "github.com/klauspost/pgzip" digest "github.com/opencontainers/go-digest" imgspecs "github.com/opencontainers/image-spec/specs-go" imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" @@ -82,31 +83,47 @@ func (r *tarballReference) NewImageSource(ctx context.Context, sys *types.System } } - // Default to assuming the layer is compressed. - layerType := imgspecv1.MediaTypeImageLayerGzip - // Set up to digest the file as it is. blobIDdigester := digest.Canonical.Digester() reader = io.TeeReader(reader, blobIDdigester.Hash()) - // Set up to digest the file after we maybe decompress it. - diffIDdigester := digest.Canonical.Digester() - uncompressed, err := pgzip.NewReader(reader) - if err == nil { - // It is compressed, so the diffID is the digest of the uncompressed version - reader = io.TeeReader(uncompressed, diffIDdigester.Hash()) - } else { - // It is not compressed, so the diffID and the blobID are going to be the same - diffIDdigester = blobIDdigester - layerType = imgspecv1.MediaTypeImageLayer - uncompressed = nil - } - // TODO: This can take quite some time, and should ideally be cancellable using ctx.Done(). - if _, err := io.Copy(io.Discard, reader); err != nil { - return nil, fmt.Errorf("error reading %q: %w", filename, err) - } - if uncompressed != nil { - uncompressed.Close() + var layerType string + var diffIDdigester digest.Digester + // If necessary, digest the file after we decompress it. + if err := func() error { // A scope for defer + format, decompressor, reader, err := compression.DetectCompressionFormat(reader) + if err != nil { + return err + } + if decompressor != nil { + uncompressed, err := decompressor(reader) + if err != nil { + return err + } + defer uncompressed.Close() + // It is compressed, so the diffID is the digest of the uncompressed version + diffIDdigester = digest.Canonical.Digester() + reader = io.TeeReader(uncompressed, diffIDdigester.Hash()) + switch format.Name() { + case compressionTypes.GzipAlgorithmName: + layerType = imgspecv1.MediaTypeImageLayerGzip + case compressionTypes.ZstdAlgorithmName: + layerType = imgspecv1.MediaTypeImageLayerZstd + default: // This is incorrect, but we have no good options, and it is what this transport was historically doing. + layerType = imgspecv1.MediaTypeImageLayerGzip + } + } else { + // It is not compressed, so the diffID and the blobID are going to be the same + diffIDdigester = blobIDdigester + layerType = imgspecv1.MediaTypeImageLayer + } + // TODO: This can take quite some time, and should ideally be cancellable using ctx.Done(). + if _, err := io.Copy(io.Discard, reader); err != nil { + return fmt.Errorf("error reading %q: %w", filename, err) + } + return nil + }(); err != nil { + return nil, err } // Grab our uncompressed and possibly-compressed digests and sizes. diff --git a/vendor/github.com/containers/image/v5/version/version.go b/vendor/github.com/containers/image/v5/version/version.go index 6c0cc885d5..611324a2ee 100644 --- a/vendor/github.com/containers/image/v5/version/version.go +++ b/vendor/github.com/containers/image/v5/version/version.go @@ -8,7 +8,7 @@ const ( // VersionMinor is for functionality in a backwards-compatible manner VersionMinor = 34 // VersionPatch is for backwards-compatible bug fixes - VersionPatch = 2 + VersionPatch = 3 // VersionDev indicates development branch. Releases will be empty string. VersionDev = "" diff --git a/vendor/modules.txt b/vendor/modules.txt index 2adcafc6e8..2652f02e13 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -147,7 +147,7 @@ github.com/containernetworking/cni/pkg/version # github.com/containernetworking/plugins v1.5.1 ## explicit; go 1.20 github.com/containernetworking/plugins/pkg/ns -# github.com/containers/buildah v1.39.3 +# github.com/containers/buildah v1.39.4 ## explicit; go 1.22.8 github.com/containers/buildah github.com/containers/buildah/bind @@ -179,7 +179,7 @@ github.com/containers/buildah/pkg/sshagent github.com/containers/buildah/pkg/util github.com/containers/buildah/pkg/volumes github.com/containers/buildah/util -# github.com/containers/common v0.62.2 +# github.com/containers/common v0.62.3 ## explicit; go 1.22.8 github.com/containers/common/internal github.com/containers/common/internal/attributedstring @@ -252,7 +252,7 @@ github.com/containers/conmon/runner/config # github.com/containers/gvisor-tap-vsock v0.8.3 ## explicit; go 1.22.0 github.com/containers/gvisor-tap-vsock/pkg/types -# github.com/containers/image/v5 v5.34.2 +# github.com/containers/image/v5 v5.34.3 ## explicit; go 1.22.8 github.com/containers/image/v5/copy github.com/containers/image/v5/directory From ae4b00cb9df8b4a21164744b91f41eb8cb499ac5 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Mon, 17 Feb 2025 10:39:35 +0100 Subject: [PATCH 55/58] test: remove duplicate test "podman run exit ExecErrorCodeCannotInvoke" does the same thing. Signed-off-by: Giuseppe Scrivano (cherry picked from commit 35d2a65e3ac2326c33242101f1344134136feb7e) --- test/e2e/run_test.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index 7ccc1e7411..ffd60ca6c7 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -1135,12 +1135,6 @@ echo -n madeit-$teststring >$tmpfile Expect(session).Should(ExitWithError(125, `invalid stream "asdfasdf" for --attach - must be one of stdin, stdout, or stderr: invalid argument`)) }) - It("podman run exit code on failure to exec", func() { - session := podmanTest.Podman([]string{"run", ALPINE, "/etc"}) - session.WaitWithDefaultTimeout() - Expect(session).Should(ExitWithError(126, "open executable: Operation not permitted: OCI permission denied")) - }) - It("podman run error on exec", func() { session := podmanTest.Podman([]string{"run", ALPINE, "sh", "-c", "exit 100"}) session.WaitWithDefaultTimeout() From 170d8630f16bcb0265294c2fad837aac2f6d5e7b Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Mon, 17 Feb 2025 09:12:31 +0100 Subject: [PATCH 56/58] test: adapt tests new crun error messages Needed-by: https://github.com/containers/crun/pull/1672 Signed-off-by: Giuseppe Scrivano (cherry picked from commit c65bb903b63c60a1ef2ccd3c21e118c4784d2f6b) --- libpod/define/exec_codes.go | 1 + test/e2e/exec_test.go | 15 ++++++++------- test/e2e/run_entrypoint_test.go | 2 +- test/e2e/run_exit_test.go | 2 +- test/system/030-run.bats | 6 +++--- test/utils/matchers.go | 31 +++++++++++++++++++++++++------ 6 files changed, 39 insertions(+), 18 deletions(-) diff --git a/libpod/define/exec_codes.go b/libpod/define/exec_codes.go index 46a8e9d86a..c2bdb2380d 100644 --- a/libpod/define/exec_codes.go +++ b/libpod/define/exec_codes.go @@ -46,6 +46,7 @@ func ExitCode(err error) int { e := strings.ToLower(err.Error()) logrus.Debugf("ExitCode msg: %q", e) if strings.Contains(e, "not found") || + strings.Contains(e, "executable path is empty") || strings.Contains(e, "no such file") { return ExecErrorCodeNotFound } diff --git a/test/e2e/exec_test.go b/test/e2e/exec_test.go index 846bbd0273..8ab0d363b3 100644 --- a/test/e2e/exec_test.go +++ b/test/e2e/exec_test.go @@ -421,19 +421,20 @@ var _ = Describe("Podman exec", func() { session := podmanTest.Podman([]string{"exec", "test1", "/etc"}) session.WaitWithDefaultTimeout() - // crun (and, we hope, any other future runtimes) - expectedStatus := 126 - expectedMessage := "open executable: Operation not permitted: OCI permission denied" - // ...but it's much more complicated under runc (#19552) if podmanTest.OCIRuntime == "runc" { - expectedMessage = `exec failed: unable to start container process: exec: "/etc": is a directory` - expectedStatus = 255 + expectedMessage := `exec failed: unable to start container process: exec: "/etc": is a directory` + expectedStatus := 255 if IsRemote() { expectedStatus = 125 } + Expect(session).Should(ExitWithError(expectedStatus, expectedMessage)) + } else { + // crun (and, we hope, any other future runtimes) + expectedStatus := 126 + expectedMessage := ".*(open executable|the path `/etc` is not a regular file): Operation not permitted: OCI permission denied.*" + Expect(session).Should(ExitWithErrorRegex(expectedStatus, expectedMessage)) } - Expect(session).Should(ExitWithError(expectedStatus, expectedMessage)) }) It("podman exec command not found", func() { diff --git a/test/e2e/run_entrypoint_test.go b/test/e2e/run_entrypoint_test.go index 6fe07cf9ef..db7fbfec24 100644 --- a/test/e2e/run_entrypoint_test.go +++ b/test/e2e/run_entrypoint_test.go @@ -18,7 +18,7 @@ CMD [] podmanTest.BuildImage(dockerfile, "foobar.com/entrypoint:latest", "false") session := podmanTest.Podman([]string{"run", "foobar.com/entrypoint:latest"}) session.WaitWithDefaultTimeout() - Expect(session).Should(ExitWithError(126, "open executable: Operation not permitted: OCI permission denied")) + Expect(session).Should(ExitWithErrorRegex(126, ".*(open executable|executable path is empty): Operation not permitted: OCI permission denied.*")) }) It("podman run entrypoint == [\"\"]", func() { diff --git a/test/e2e/run_exit_test.go b/test/e2e/run_exit_test.go index 412bd6df11..900f2a21d5 100644 --- a/test/e2e/run_exit_test.go +++ b/test/e2e/run_exit_test.go @@ -22,7 +22,7 @@ var _ = Describe("Podman run exit", func() { It("podman run exit ExecErrorCodeCannotInvoke", func() { result := podmanTest.Podman([]string{"run", ALPINE, "/etc"}) result.WaitWithDefaultTimeout() - Expect(result).Should(ExitWithError(define.ExecErrorCodeCannotInvoke, "open executable: Operation not permitted: OCI permission denied")) + Expect(result).Should(ExitWithErrorRegex(define.ExecErrorCodeCannotInvoke, ".*(open executable|the path `/etc` is not a regular file): Operation not permitted: OCI permission denied.*")) }) It("podman run exit ExecErrorCodeNotFound", func() { diff --git a/test/system/030-run.bats b/test/system/030-run.bats index 99def8d069..1adb73ca3f 100644 --- a/test/system/030-run.bats +++ b/test/system/030-run.bats @@ -10,7 +10,7 @@ load helpers.network err_no_such_cmd="Error:.*/no/such/command.*[Nn]o such file or directory" # runc: RHEL8 on 2023-07-17: "is a directory". # Everything else (crun; runc on debian): "permission denied" - err_no_exec_dir="Error:.*exec.*\\\(permission denied\\\|is a directory\\\)" + err_no_exec_dir="Error:.*\\\(exec.*\\\(permission denied\\\|is a directory\\\)\\\|is not a regular file\\\)" tests=" true | 0 | @@ -1657,14 +1657,14 @@ search | $IMAGE | # runc and crun emit different diagnostics runtime=$(podman_runtime) case "$runtime" in - crun) expect='crun: executable file `` not found in $PATH: No such file or directory: OCI runtime attempted to invoke a command that was not found' ;; + crun) expect='\(executable file `` not found in $PATH: No such file or directory: OCI runtime attempted to invoke a command that was not found\|executable path is empty\)' ;; runc) expect='runc: runc create failed: unable to start container process: exec: "": executable file not found in $PATH: OCI runtime attempted to invoke a command that was not found' ;; *) skip "Unknown runtime '$runtime'" ;; esac # The '.*' in the error below is for dealing with podman-remote, which # includes "error preparing container for attach" in output. - is "$output" "Error.*: $expect" "podman emits useful diagnostic when no entrypoint is set" + is "$output" "Error.* $expect" "podman emits useful diagnostic when no entrypoint is set" } # bats test_tags=ci:parallel diff --git a/test/utils/matchers.go b/test/utils/matchers.go index a452d19675..bf9c31d4ad 100644 --- a/test/utils/matchers.go +++ b/test/utils/matchers.go @@ -3,6 +3,7 @@ package utils import ( "encoding/json" "fmt" + "regexp" "strings" "github.com/onsi/gomega/format" @@ -17,10 +18,11 @@ type podmanSession interface { type ExitMatcher struct { types.GomegaMatcher - ExpectedExitCode int - ExitCode int - ExpectedStderr string - msg string + ExpectedExitCode int + ExitCode int + ExpectedStderr string + ExpectedStderrRegex string + msg string } // ExitWithError checks both exit code and stderr, fails if either does not match @@ -29,6 +31,12 @@ func ExitWithError(expectExitCode int, expectStderr string) *ExitMatcher { return &ExitMatcher{ExpectedExitCode: expectExitCode, ExpectedStderr: expectStderr} } +// ExitWithErrorRegex checks both exit code and the stderr regex, fails if either does not match +// Modeled after the gomega Exit() matcher and also operates on sessions. +func ExitWithErrorRegex(expectExitCode int, expectStderrRegex string) *ExitMatcher { + return &ExitMatcher{ExpectedExitCode: expectExitCode, ExpectedStderrRegex: expectStderrRegex} +} + // Match follows gexec.Matcher interface. func (matcher *ExitMatcher) Match(actual interface{}) (success bool, err error) { session, ok := actual.(podmanSession) @@ -49,12 +57,23 @@ func (matcher *ExitMatcher) Match(actual interface{}) (success bool, err error) return false, nil } - if matcher.ExpectedStderr != "" { + switch { + case matcher.ExpectedStderrRegex != "": + matched, err := regexp.MatchString(matcher.ExpectedStderrRegex, session.ErrorToString()) + if err != nil { + matcher.msg = fmt.Sprintf("Invalid regex pattern: %s", err) + return false, err + } + if !matched { + matcher.msg = fmt.Sprintf("Command exited %d as expected, but stderr did not match regex '%s'", matcher.ExitCode, matcher.ExpectedStderrRegex) + return false, nil + } + case matcher.ExpectedStderr != "": if !strings.Contains(session.ErrorToString(), matcher.ExpectedStderr) { matcher.msg = fmt.Sprintf("Command exited %d as expected, but did not emit '%s'", matcher.ExitCode, matcher.ExpectedStderr) return false, nil } - } else { + default: if session.ErrorToString() != "" { matcher.msg = "Command exited with expected exit status, but emitted unwanted stderr" return false, nil From a7ac20d9130556f286c0bd692bf5d0473c2daf37 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Tue, 18 Feb 2025 10:21:13 +0100 Subject: [PATCH 57/58] oci: report empty exec path as ENOENT unify the error codes returned by runc and crun. Fix the tests to work with both runtimes, as well as the https://github.com/containers/crun/pull/1672 changes in progress for crun. Follow-up for https://github.com/containers/podman/pull/25340 Closes: https://issues.redhat.com/browse/RHEL-85826 Signed-off-by: Giuseppe Scrivano (cherry picked from commit 4695564730abf8432102f8a07546afc9f87f855b) --- libpod/oci_util.go | 2 +- test/e2e/exec_test.go | 9 +++------ test/e2e/run_entrypoint_test.go | 7 ++++++- test/e2e/run_exit_test.go | 6 ++++-- test/system/030-run.bats | 2 +- 5 files changed, 15 insertions(+), 11 deletions(-) diff --git a/libpod/oci_util.go b/libpod/oci_util.go index 5d30c8b8f7..292f59a117 100644 --- a/libpod/oci_util.go +++ b/libpod/oci_util.go @@ -152,7 +152,7 @@ func getOCIRuntimeError(name, runtimeMsg string) error { } return fmt.Errorf("%s: %s: %w", name, strings.Trim(errStr, "\n"), define.ErrOCIRuntimePermissionDenied) } - if match := regexp.MustCompile("(?i).*executable file not found in.*|.*no such file or directory.*").FindString(runtimeMsg); match != "" { + if match := regexp.MustCompile("(?i).*executable file not found in.*|.*no such file or directory.*|.*open executable.*").FindString(runtimeMsg); match != "" { errStr := match if includeFullOutput { errStr = runtimeMsg diff --git a/test/e2e/exec_test.go b/test/e2e/exec_test.go index 8ab0d363b3..6c3acc4864 100644 --- a/test/e2e/exec_test.go +++ b/test/e2e/exec_test.go @@ -400,17 +400,14 @@ var _ = Describe("Podman exec", func() { setup.WaitWithDefaultTimeout() Expect(setup).Should(ExitCleanly()) - expect := "chdir to `/missing`: No such file or directory" - if podmanTest.OCIRuntime == "runc" { - expect = "chdir to cwd" - } + expect := ".*(chdir to cwd|chdir to `/missing`: No such file or directory).*" session := podmanTest.Podman([]string{"exec", "--workdir", "/missing", "test1", "pwd"}) session.WaitWithDefaultTimeout() - Expect(session).To(ExitWithError(127, expect)) + Expect(session).To(ExitWithErrorRegex(127, expect)) session = podmanTest.Podman([]string{"exec", "-w", "/missing", "test1", "pwd"}) session.WaitWithDefaultTimeout() - Expect(session).To(ExitWithError(127, expect)) + Expect(session).To(ExitWithErrorRegex(127, expect)) }) It("podman exec cannot be invoked", func() { diff --git a/test/e2e/run_entrypoint_test.go b/test/e2e/run_entrypoint_test.go index db7fbfec24..d4f8363bb6 100644 --- a/test/e2e/run_entrypoint_test.go +++ b/test/e2e/run_entrypoint_test.go @@ -18,7 +18,12 @@ CMD [] podmanTest.BuildImage(dockerfile, "foobar.com/entrypoint:latest", "false") session := podmanTest.Podman([]string{"run", "foobar.com/entrypoint:latest"}) session.WaitWithDefaultTimeout() - Expect(session).Should(ExitWithErrorRegex(126, ".*(open executable|executable path is empty): Operation not permitted: OCI permission denied.*")) + if session.ExitCode() == 126 { + // special case for crun <= 1.20, remove once a new version is out + Expect(session).Should(ExitWithError(126, "open executable: Operation not permitted: OCI permission denied")) + return + } + Expect(session).Should(ExitWithErrorRegex(127, ".*(executable file not found in \\$PATH|cannot find `` in \\$PATH).*: OCI runtime attempted to invoke a command that was not found.*")) }) It("podman run entrypoint == [\"\"]", func() { diff --git a/test/e2e/run_exit_test.go b/test/e2e/run_exit_test.go index 900f2a21d5..618059b133 100644 --- a/test/e2e/run_exit_test.go +++ b/test/e2e/run_exit_test.go @@ -22,13 +22,15 @@ var _ = Describe("Podman run exit", func() { It("podman run exit ExecErrorCodeCannotInvoke", func() { result := podmanTest.Podman([]string{"run", ALPINE, "/etc"}) result.WaitWithDefaultTimeout() - Expect(result).Should(ExitWithErrorRegex(define.ExecErrorCodeCannotInvoke, ".*(open executable|the path `/etc` is not a regular file): Operation not permitted: OCI permission denied.*")) + expected := ".*(exec: \"/etc\": is a directory|(open executable|the path `/etc` is not a regular file): Operation not permitted: OCI permission denied).*" + Expect(result).Should(ExitWithErrorRegex(define.ExecErrorCodeCannotInvoke, expected)) }) It("podman run exit ExecErrorCodeNotFound", func() { result := podmanTest.Podman([]string{"run", ALPINE, "foobar"}) result.WaitWithDefaultTimeout() - Expect(result).Should(ExitWithError(define.ExecErrorCodeNotFound, "executable file `foobar` not found in $PATH: No such file or directory: OCI runtime attempted to invoke a command that was not found")) + expected := ".*(executable file not found in \\$PATH|executable file `foobar` not found in \\$PATH: No such file or directory: OCI runtime attempted to invoke a command that was not found).*" + Expect(result).Should(ExitWithErrorRegex(define.ExecErrorCodeNotFound, expected)) }) It("podman run exit 0", func() { diff --git a/test/system/030-run.bats b/test/system/030-run.bats index 1adb73ca3f..ee430d4b4c 100644 --- a/test/system/030-run.bats +++ b/test/system/030-run.bats @@ -1657,7 +1657,7 @@ search | $IMAGE | # runc and crun emit different diagnostics runtime=$(podman_runtime) case "$runtime" in - crun) expect='\(executable file `` not found in $PATH: No such file or directory: OCI runtime attempted to invoke a command that was not found\|executable path is empty\)' ;; + crun) expect='\(executable file `` not found in $PATH\|cannot find `` in $PATH\): No such file or directory: OCI runtime attempted to invoke a command that was not found' ;; runc) expect='runc: runc create failed: unable to start container process: exec: "": executable file not found in $PATH: OCI runtime attempted to invoke a command that was not found' ;; *) skip "Unknown runtime '$runtime'" ;; esac From 7b53a64c3c6eecfb9542e81d0250cb9684fd51e0 Mon Sep 17 00:00:00 2001 From: Matt Heon Date: Tue, 11 Feb 2025 14:51:34 -0500 Subject: [PATCH 58/58] [v5.4-rhel] Remove persist directory when cleaning up Conmon files This seems to have been added as part of the cleanup of our handling of OOM files, but code was never added to remove it, so we leaked a single directory with an exit file and OOM file per container run. Apparently have been doing this for a while - I'd guess since March of '23 - so I'm surprised more people didn't notice. Fixes #25291 Fixes: https://issues.redhat.com/browse/RHEL-86544, https://issues.redhat.com/browse/RHEL-86550 Signed-off-by: Matt Heon Signed-off-by: tomsweeneyredhat --- libpod/container_internal.go | 14 ++++++++++---- libpod/oci.go | 8 ++++++++ libpod/oci_conmon_common.go | 5 +++++ libpod/oci_missing.go | 6 ++++++ 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/libpod/container_internal.go b/libpod/container_internal.go index 3cf15b6985..54b10b8ddb 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -153,6 +153,10 @@ func (c *Container) oomFilePath() (string, error) { return c.ociRuntime.OOMFilePath(c) } +func (c *Container) persistDirPath() (string, error) { + return c.ociRuntime.PersistDirectoryPath(c) +} + // Wait for the container's exit file to appear. // When it does, update our state based on it. func (c *Container) waitForExitFileAndSync() error { @@ -766,13 +770,15 @@ func (c *Container) removeConmonFiles() error { return fmt.Errorf("removing container %s exit file: %w", c.ID(), err) } - // Remove the oom file - oomFile, err := c.oomFilePath() + // Remove the persist directory + persistDir, err := c.persistDirPath() if err != nil { return err } - if err := os.Remove(oomFile); err != nil && !errors.Is(err, fs.ErrNotExist) { - return fmt.Errorf("removing container %s oom file: %w", c.ID(), err) + if persistDir != "" { + if err := os.RemoveAll(persistDir); err != nil && !errors.Is(err, fs.ErrNotExist) { + return fmt.Errorf("removing container %s persist directory: %w", c.ID(), err) + } } return nil diff --git a/libpod/oci.go b/libpod/oci.go index e0d7406339..f14b4acf83 100644 --- a/libpod/oci.go +++ b/libpod/oci.go @@ -153,6 +153,14 @@ type OCIRuntime interface { //nolint:interfacebloat // This is the path to that file for a given container. OOMFilePath(ctr *Container) (string, error) + // PersistDirectoryPath is the path to a container's persist directory. + // Not all OCI runtime implementations will have a persist directory. + // If they do, it may contain files such as the exit file and the OOM + // file. + // If the directory does not exist, the empty string and no error should + // be returned. + PersistDirectoryPath(ctr *Container) (string, error) + // RuntimeInfo returns verbose information about the runtime. RuntimeInfo() (*define.ConmonInfo, *define.OCIRuntimeInfo, error) diff --git a/libpod/oci_conmon_common.go b/libpod/oci_conmon_common.go index 8aa103fb49..1b0f4c42da 100644 --- a/libpod/oci_conmon_common.go +++ b/libpod/oci_conmon_common.go @@ -862,6 +862,11 @@ func (r *ConmonOCIRuntime) OOMFilePath(ctr *Container) (string, error) { return filepath.Join(r.persistDir, ctr.ID(), "oom"), nil } +// PersistDirectoryPath is the path to the container's persist directory. +func (r *ConmonOCIRuntime) PersistDirectoryPath(ctr *Container) (string, error) { + return filepath.Join(r.persistDir, ctr.ID()), nil +} + // RuntimeInfo provides information on the runtime. func (r *ConmonOCIRuntime) RuntimeInfo() (*define.ConmonInfo, *define.OCIRuntimeInfo, error) { runtimePackage := version.Package(r.path) diff --git a/libpod/oci_missing.go b/libpod/oci_missing.go index 98eb91ef8d..bfdbbf228e 100644 --- a/libpod/oci_missing.go +++ b/libpod/oci_missing.go @@ -226,6 +226,12 @@ func (r *MissingRuntime) OOMFilePath(ctr *Container) (string, error) { return filepath.Join(r.persistDir, ctr.ID(), "oom"), nil } +// PersistDirectoryPath is the path to the container's persist directory. +// It may include files like the exit file and OOM file. +func (r *MissingRuntime) PersistDirectoryPath(ctr *Container) (string, error) { + return filepath.Join(r.persistDir, ctr.ID()), nil +} + // RuntimeInfo returns information on the missing runtime func (r *MissingRuntime) RuntimeInfo() (*define.ConmonInfo, *define.OCIRuntimeInfo, error) { ocirt := define.OCIRuntimeInfo{