diff options
226 files changed, 3512 insertions, 2599 deletions
diff --git a/cmd/podman-mac-helper/install.go b/cmd/podman-mac-helper/install.go index 7b8753820..713bdfcdf 100644 --- a/cmd/podman-mac-helper/install.go +++ b/cmd/podman-mac-helper/install.go @@ -193,7 +193,7 @@ func verifyRootDeep(path string) error { func installExecutable(user string) (string, error) { // Since the installed executable runs as root, as a precaution verify root ownership of - // the entire installation path, and utilize sticky + read only perms for the helper path + // the entire installation path, and utilize sticky + read-only perms for the helper path // suffix. The goal is to help users harden against privilege escalation from loose // filesystem permissions. // diff --git a/cmd/podman/common/completion.go b/cmd/podman/common/completion.go index 89e53c180..ae30f2875 100644 --- a/cmd/podman/common/completion.go +++ b/cmd/podman/common/completion.go @@ -520,6 +520,16 @@ func AutocompletePodsRunning(cmd *cobra.Command, args []string, toComplete strin return getPods(cmd, toComplete, completeDefault, "running", "degraded") } +// AutoCompletePodsPause - Autocomplete only paused pod names +// When a pod has a few containers paused, that ends up in degraded state +// So autocomplete degraded pod names as well +func AutoCompletePodsPause(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if !validCurrentCmdLine(cmd, args, toComplete) { + return nil, cobra.ShellCompDirectiveNoFileComp + } + return getPods(cmd, toComplete, completeDefault, "paused", "degraded") +} + // AutocompleteForKube - Autocomplete all Podman objects supported by kube generate. func AutocompleteForKube(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if !validCurrentCmdLine(cmd, args, toComplete) { diff --git a/cmd/podman/common/create.go b/cmd/podman/common/create.go index e25bdd241..c1a744011 100644 --- a/cmd/podman/common/create.go +++ b/cmd/podman/common/create.go @@ -544,13 +544,6 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions, ) _ = cmd.RegisterFlagCompletionFunc(userFlagName, AutocompleteUserFlag) - utsFlagName := "uts" - createFlags.String( - utsFlagName, "", - "UTS namespace to use", - ) - _ = cmd.RegisterFlagCompletionFunc(utsFlagName, AutocompleteNamespace) - mountFlagName := "mount" createFlags.StringArrayVar( &cf.Mount, @@ -684,6 +677,14 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions, ) _ = cmd.RegisterFlagCompletionFunc(usernsFlagName, AutocompleteUserNamespace) + utsFlagName := "uts" + createFlags.StringVar( + &cf.UTS, + utsFlagName, "", + "UTS namespace to use", + ) + _ = cmd.RegisterFlagCompletionFunc(utsFlagName, AutocompleteNamespace) + cgroupParentFlagName := "cgroup-parent" createFlags.StringVar( &cf.CgroupParent, @@ -863,14 +864,6 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions, ) _ = cmd.RegisterFlagCompletionFunc(cpusetMemsFlagName, completion.AutocompleteNone) - memoryFlagName := "memory" - createFlags.StringVarP( - &cf.Memory, - memoryFlagName, "m", "", - "Memory limit "+sizeWithUnitFormat, - ) - _ = cmd.RegisterFlagCompletionFunc(memoryFlagName, completion.AutocompleteNone) - memoryReservationFlagName := "memory-reservation" createFlags.StringVar( &cf.MemoryReservation, @@ -912,4 +905,12 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions, "CPUs in which to allow execution (0-3, 0,1)", ) _ = cmd.RegisterFlagCompletionFunc(cpusetCpusFlagName, completion.AutocompleteNone) + + memoryFlagName := "memory" + createFlags.StringVarP( + &cf.Memory, + memoryFlagName, "m", "", + "Memory limit "+sizeWithUnitFormat, + ) + _ = cmd.RegisterFlagCompletionFunc(memoryFlagName, completion.AutocompleteNone) } diff --git a/cmd/podman/containers/clone.go b/cmd/podman/containers/clone.go index f8d5a2d80..9881a791c 100644 --- a/cmd/podman/containers/clone.go +++ b/cmd/podman/containers/clone.go @@ -63,7 +63,7 @@ func clone(cmd *cobra.Command, args []string) error { ctrClone.Image = args[2] if !cliVals.RootFS { rawImageName := args[0] - name, err := PullImage(ctrClone.Image, ctrClone.CreateOpts) + name, err := PullImage(ctrClone.Image, &ctrClone.CreateOpts) if err != nil { return err } diff --git a/cmd/podman/containers/create.go b/cmd/podman/containers/create.go index aa7040bcc..7d0f4d9ae 100644 --- a/cmd/podman/containers/create.go +++ b/cmd/podman/containers/create.go @@ -141,7 +141,7 @@ func create(cmd *cobra.Command, args []string) error { rawImageName := "" if !cliVals.RootFS { rawImageName = args[0] - name, err := PullImage(args[0], cliVals) + name, err := PullImage(args[0], &cliVals) if err != nil { return err } @@ -224,7 +224,6 @@ func CreateInit(c *cobra.Command, vals entities.ContainerCreateOptions, isInfra return vals, errors.New("--cpu-quota and --cpus cannot be set together") } vals.IPC = c.Flag("ipc").Value.String() - vals.UTS = c.Flag("uts").Value.String() vals.PID = c.Flag("pid").Value.String() vals.CgroupNS = c.Flag("cgroupns").Value.String() @@ -305,7 +304,8 @@ func CreateInit(c *cobra.Command, vals entities.ContainerCreateOptions, isInfra return vals, nil } -func PullImage(imageName string, cliVals entities.ContainerCreateOptions) (string, error) { +// Pulls image if any also parses and populates OS, Arch and Variant in specified container create options +func PullImage(imageName string, cliVals *entities.ContainerCreateOptions) (string, error) { pullPolicy, err := config.ParsePullPolicy(cliVals.Pull) if err != nil { return "", err diff --git a/cmd/podman/containers/run.go b/cmd/podman/containers/run.go index 1176b866d..ef13ea95e 100644 --- a/cmd/podman/containers/run.go +++ b/cmd/podman/containers/run.go @@ -141,7 +141,7 @@ func run(cmd *cobra.Command, args []string) error { rawImageName := "" if !cliVals.RootFS { rawImageName = args[0] - name, err := PullImage(args[0], cliVals) + name, err := PullImage(args[0], &cliVals) if err != nil { return err } @@ -192,6 +192,9 @@ func run(cmd *cobra.Command, args []string) error { return err } s.RawImageName = rawImageName + s.ImageOS = cliVals.OS + s.ImageArch = cliVals.Arch + s.ImageVariant = cliVals.Variant s.Passwd = &runOpts.Passwd runOpts.Spec = s diff --git a/cmd/podman/machine/info.go b/cmd/podman/machine/info.go new file mode 100644 index 000000000..9932027d8 --- /dev/null +++ b/cmd/podman/machine/info.go @@ -0,0 +1,182 @@ +//go:build amd64 || arm64 +// +build amd64 arm64 + +package machine + +import ( + "fmt" + "html/template" + "os" + "runtime" + + "github.com/containers/common/pkg/completion" + "github.com/containers/common/pkg/config" + "github.com/containers/common/pkg/report" + "github.com/containers/podman/v4/cmd/podman/common" + "github.com/containers/podman/v4/cmd/podman/registry" + "github.com/containers/podman/v4/cmd/podman/validate" + "github.com/containers/podman/v4/libpod/define" + "github.com/containers/podman/v4/pkg/machine" + "github.com/ghodss/yaml" + "github.com/spf13/cobra" +) + +var infoDescription = `Display information pertaining to the machine host.` + +var ( + infoCmd = &cobra.Command{ + Use: "info [options]", + Short: "Display machine host info", + Long: infoDescription, + PersistentPreRunE: rootlessOnly, + RunE: info, + Args: validate.NoArgs, + ValidArgsFunction: completion.AutocompleteNone, + Example: `podman machine info`, + } +) + +var ( + inFormat string +) + +// Info contains info on the machine host and version info +type Info struct { + Host *HostInfo `json:"Host"` + Version define.Version `json:"Version"` +} + +// HostInfo contains info on the machine host +type HostInfo struct { + Arch string `json:"Arch"` + CurrentMachine string `json:"CurrentMachine"` + DefaultMachine string `json:"DefaultMachine"` + EventsDir string `json:"EventsDir"` + MachineConfigDir string `json:"MachineConfigDir"` + MachineImageDir string `json:"MachineImageDir"` + MachineState string `json:"MachineState"` + NumberOfMachines int `json:"NumberOfMachines"` + OS string `json:"OS"` + VMType string `json:"VMType"` +} + +func init() { + registry.Commands = append(registry.Commands, registry.CliCommand{ + Command: infoCmd, + Parent: machineCmd, + }) + + flags := infoCmd.Flags() + formatFlagName := "format" + flags.StringVarP(&inFormat, formatFlagName, "f", "", "Change the output format to JSON or a Go template") + _ = infoCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(&define.Info{})) +} + +func info(cmd *cobra.Command, args []string) error { + info := Info{} + version, err := define.GetVersion() + if err != nil { + return fmt.Errorf("error getting version info %w", err) + } + info.Version = version + + host, err := hostInfo() + if err != nil { + return err + } + info.Host = host + + switch { + case report.IsJSON(inFormat): + b, err := json.MarshalIndent(info, "", " ") + if err != nil { + return err + } + fmt.Println(string(b)) + case cmd.Flags().Changed("format"): + tmpl := template.New(cmd.Name()).Funcs(template.FuncMap(report.DefaultFuncs)) + inFormat = report.NormalizeFormat(inFormat) + tmpl, err := tmpl.Parse(inFormat) + if err != nil { + return err + } + return tmpl.Execute(os.Stdout, info) + default: + b, err := yaml.Marshal(info) + if err != nil { + return err + } + fmt.Println(string(b)) + } + + return nil +} + +func hostInfo() (*HostInfo, error) { + host := HostInfo{} + + host.Arch = runtime.GOARCH + host.OS = runtime.GOOS + + provider := GetSystemDefaultProvider() + var listOpts machine.ListOptions + listResponse, err := provider.List(listOpts) + if err != nil { + return nil, fmt.Errorf("failed to get machines %w", err) + } + + host.NumberOfMachines = len(listResponse) + + cfg, err := config.ReadCustomConfig() + if err != nil { + return nil, err + } + + // Default state of machine is stopped + host.MachineState = "Stopped" + for _, vm := range listResponse { + // Set default machine if found + if vm.Name == cfg.Engine.ActiveService { + host.DefaultMachine = vm.Name + } + // If machine is running or starting, it is automatically the current machine + if vm.Running { + host.CurrentMachine = vm.Name + host.MachineState = "Running" + } else if vm.Starting { + host.CurrentMachine = vm.Name + host.MachineState = "Starting" + } + } + // If no machines are starting or running, set current machine to default machine + // If no default machines are found, do not report a default machine or a state + if host.CurrentMachine == "" { + if host.DefaultMachine == "" { + host.MachineState = "" + } else { + host.CurrentMachine = host.DefaultMachine + } + } + + host.VMType = provider.VMType() + + dataDir, err := machine.GetDataDir(host.VMType) + if err != nil { + return nil, fmt.Errorf("failed to get machine image dir") + } + host.MachineImageDir = dataDir + + confDir, err := machine.GetConfDir(host.VMType) + if err != nil { + return nil, fmt.Errorf("failed to get machine config dir %w", err) + } + host.MachineConfigDir = confDir + + eventsDir, err := eventSockDir() + if err != nil { + return nil, fmt.Errorf("failed to get events dir: %w", err) + } + host.EventsDir = eventsDir + + return &host, nil +} diff --git a/cmd/podman/machine/machine.go b/cmd/podman/machine/machine.go index 5a8a06b9d..0618337cc 100644 --- a/cmd/podman/machine/machine.go +++ b/cmd/podman/machine/machine.go @@ -101,12 +101,6 @@ func resolveEventSock() ([]string, error) { return []string{sock}, nil } - xdg, err := util.GetRuntimeDir() - if err != nil { - logrus.Warnf("Failed to get runtime dir, machine events will not be published: %s", err) - return nil, nil - } - re := regexp.MustCompile(`machine_events.*\.sock`) sockPaths := make([]string, 0) fn := func(path string, info os.DirEntry, err error) error { @@ -125,8 +119,12 @@ func resolveEventSock() ([]string, error) { sockPaths = append(sockPaths, path) return nil } + sockDir, err := eventSockDir() + if err != nil { + logrus.Warnf("Failed to get runtime dir, machine events will not be published: %s", err) + } - if err := filepath.WalkDir(filepath.Join(xdg, "podman"), fn); err != nil { + if err := filepath.WalkDir(sockDir, fn); err != nil { if errors.Is(err, os.ErrNotExist) { return nil, nil } @@ -135,6 +133,14 @@ func resolveEventSock() ([]string, error) { return sockPaths, nil } +func eventSockDir() (string, error) { + xdg, err := util.GetRuntimeDir() + if err != nil { + return "", err + } + return filepath.Join(xdg, "podman"), nil +} + func newMachineEvent(status events.Status, event events.Event) { openEventSock.Do(initMachineEvents) diff --git a/cmd/podman/pods/create.go b/cmd/podman/pods/create.go index 45ad2dfd0..aea8a7229 100644 --- a/cmd/podman/pods/create.go +++ b/cmd/podman/pods/create.go @@ -277,6 +277,7 @@ func create(cmd *cobra.Command, args []string) error { if err != nil { return err } + podSpec.Volumes = podSpec.InfraContainerSpec.Volumes podSpec.ImageVolumes = podSpec.InfraContainerSpec.ImageVolumes podSpec.OverlayVolumes = podSpec.InfraContainerSpec.OverlayVolumes diff --git a/cmd/podman/pods/unpause.go b/cmd/podman/pods/unpause.go index 8a0a24e98..47b29458b 100644 --- a/cmd/podman/pods/unpause.go +++ b/cmd/podman/pods/unpause.go @@ -24,9 +24,7 @@ var ( Args: func(cmd *cobra.Command, args []string) error { return validate.CheckAllLatestAndIDFile(cmd, args, false, "") }, - // TODO have a function which shows only pods which could be unpaused - // for now show all - ValidArgsFunction: common.AutocompletePods, + ValidArgsFunction: common.AutoCompletePodsPause, Example: `podman pod unpause podID1 podID2 podman pod unpause --all podman pod unpause --latest`, @@ -43,7 +41,7 @@ func init() { Parent: podCmd, }) flags := unpauseCommand.Flags() - flags.BoolVarP(&unpauseOptions.All, "all", "a", false, "Pause all running pods") + flags.BoolVarP(&unpauseOptions.All, "all", "a", false, "Unpause all running pods") validate.AddLatestFlag(unpauseCommand, &unpauseOptions.Latest) } diff --git a/cmd/podman/system/df.go b/cmd/podman/system/df.go index 2fcc12feb..5b8126be6 100644 --- a/cmd/podman/system/df.go +++ b/cmd/podman/system/df.go @@ -78,11 +78,11 @@ func printSummary(cmd *cobra.Command, reports *entities.SystemDfReport) error { } } imageSummary := dfSummary{ - Type: "Images", - Total: len(reports.Images), - Active: active, - size: size, - reclaimable: reclaimable, + Type: "Images", + Total: len(reports.Images), + Active: active, + RawSize: size, + RawReclaimable: reclaimable, } dfSummaries = append(dfSummaries, &imageSummary) @@ -100,11 +100,11 @@ func printSummary(cmd *cobra.Command, reports *entities.SystemDfReport) error { conSize += c.RWSize } containerSummary := dfSummary{ - Type: "Containers", - Total: len(reports.Containers), - Active: conActive, - size: conSize, - reclaimable: conReclaimable, + Type: "Containers", + Total: len(reports.Containers), + Active: conActive, + RawSize: conSize, + RawReclaimable: conReclaimable, } dfSummaries = append(dfSummaries, &containerSummary) @@ -120,11 +120,11 @@ func printSummary(cmd *cobra.Command, reports *entities.SystemDfReport) error { volumesReclaimable += v.ReclaimableSize } volumeSummary := dfSummary{ - Type: "Local Volumes", - Total: len(reports.Volumes), - Active: activeVolumes, - size: volumesSize, - reclaimable: volumesReclaimable, + Type: "Local Volumes", + Total: len(reports.Volumes), + Active: activeVolumes, + RawSize: volumesSize, + RawReclaimable: volumesReclaimable, } dfSummaries = append(dfSummaries, &volumeSummary) @@ -277,22 +277,22 @@ func (d *dfVolume) Size() string { } type dfSummary struct { - Type string - Total int - Active int - size int64 - reclaimable int64 + Type string + Total int + Active int + RawSize int64 `json:"Size"` + RawReclaimable int64 `json:"Reclaimable"` } func (d *dfSummary) Size() string { - return units.HumanSize(float64(d.size)) + return units.HumanSize(float64(d.RawSize)) } func (d *dfSummary) Reclaimable() string { percent := 0 // make sure to check this to prevent div by zero problems - if d.size > 0 { - percent = int(math.Round(float64(d.reclaimable) / float64(d.size) * float64(100))) + if d.RawSize > 0 { + percent = int(math.Round(float64(d.RawReclaimable) / float64(d.RawSize) * float64(100))) } - return fmt.Sprintf("%s (%d%%)", units.HumanSize(float64(d.reclaimable)), percent) + return fmt.Sprintf("%s (%d%%)", units.HumanSize(float64(d.RawReclaimable)), percent) } diff --git a/docs/play_kube_support.md b/docs/play_kube_support.md index cf983bc04..3cfd3fa50 100644 --- a/docs/play_kube_support.md +++ b/docs/play_kube_support.md @@ -150,3 +150,26 @@ Note: **N/A** means that the option cannot be supported in a single-node Podman | selector | | | resources.limits | | | resources.requests | ✅ | + +## ConfigMap Fields + +| Field | Support | +|------------|---------| +| binaryData | | +| data | ✅ | +| immutable | | + +## Deployment Fields + +| Field | Support | +|---------------------------------------|---------| +| replicas | ✅ | +| selector | ✅ | +| template | ✅ | +| minReadySeconds | | +| strategy.type | | +| strategy.rollingUpdate.maxSurge | | +| strategy.rollingUpdate.maxUnavailable | | +| revisionHistoryLimit | | +| progressDeadlineSeconds | | +| paused | | diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md index 425ce7bcc..403327d82 100644 --- a/docs/source/markdown/podman-create.1.md +++ b/docs/source/markdown/podman-create.1.md @@ -881,11 +881,11 @@ Suppress output information when pulling images #### **--read-only** -Mount the container's root filesystem as read only. +Mount the container's root filesystem as read-only. By default a container will have its root filesystem writable allowing processes to write files anywhere. By specifying the `--read-only` flag the container will have -its root filesystem mounted as read only prohibiting any writes. +its root filesystem mounted as read-only prohibiting any writes. #### **--read-only-tmpfs** @@ -1006,8 +1006,8 @@ Note: Labeling can be disabled for all containers by setting label=false in the possible mount options are specified in the **proc(5)** man page. -- **unmask**=_ALL_ or _/path/1:/path/2_, or shell expanded paths (/proc/*): Paths to unmask separated by a colon. If set to **ALL**, it will unmask all the paths that are masked or made read only by default. - The default masked paths are **/proc/acpi, /proc/kcore, /proc/keys, /proc/latency_stats, /proc/sched_debug, /proc/scsi, /proc/timer_list, /proc/timer_stats, /sys/firmware, and /sys/fs/selinux.** The default paths that are read only are **/proc/asound, /proc/bus, /proc/fs, /proc/irq, /proc/sys, /proc/sysrq-trigger, /sys/fs/cgroup**. +- **unmask**=_ALL_ or _/path/1:/path/2_, or shell expanded paths (/proc/*): Paths to unmask separated by a colon. If set to **ALL**, it will unmask all the paths that are masked or made read-only by default. + The default masked paths are **/proc/acpi, /proc/kcore, /proc/keys, /proc/latency_stats, /proc/sched_debug, /proc/scsi, /proc/timer_list, /proc/timer_stats, /sys/firmware, and /sys/fs/selinux.** The default paths that are read-only are **/proc/asound, /proc/bus, /proc/fs, /proc/irq, /proc/sys, /proc/sysrq-trigger, /sys/fs/cgroup**. Note: Labeling can be disabled for all containers by setting label=false in the **containers.conf** (`/etc/containers/containers.conf` or `$HOME/.config/containers/containers.conf`) file. diff --git a/docs/source/markdown/podman-machine-info.1.md b/docs/source/markdown/podman-machine-info.1.md new file mode 100644 index 000000000..33c207d32 --- /dev/null +++ b/docs/source/markdown/podman-machine-info.1.md @@ -0,0 +1,36 @@ +% podman-machine-info(1) + +## NAME +podman\-machine\-info - Display machine host info + +## SYNOPSIS +**podman machine info** + +## DESCRIPTION + +Display information pertaining to the machine host. +Rootless only, as all `podman machine` commands can be only be used with rootless Podman. + +## OPTIONS + +#### **--format**=*format*, **-f** + +Change output format to "json" or a Go template. + +#### **--help** + +Print usage statement. + +## EXAMPLES + +``` +$ podman machine info +$ podman machine info --format json +$ podman machine info --format {{.Host.Arch}} +``` + +## SEE ALSO +**[podman(1)](podman.1.md)**, **[podman-machine(1)](podman-machine.1.md)** + +## HISTORY +June 2022, Originally compiled by Ashley Cui <acui@redhat.com> diff --git a/docs/source/markdown/podman-machine-init.1.md b/docs/source/markdown/podman-machine-init.1.md index 2adb15e6a..21c98b2c7 100644 --- a/docs/source/markdown/podman-machine-init.1.md +++ b/docs/source/markdown/podman-machine-init.1.md @@ -76,15 +76,33 @@ Set the timezone for the machine and containers. Valid values are `local` or a `timezone` such as `America/Chicago`. A value of `local`, which is the default, means to use the timezone of the machine host. -#### **--volume**, **-v**=*source:target* +#### **--volume**, **-v**=*source:target[:options]* Mounts a volume from source to target. Create a mount. If /host-dir:/machine-dir is specified as the `*source:target*`, Podman mounts _host-dir_ in the host to _machine-dir_ in the Podman machine. -The root filesystem is mounted read-only in the default operating system, -so mounts must be created under the /mnt directory. +Additional options may be specified as a comma-separated string. Recognized +options are: +* **ro**: mount volume read-only +* **rw**: mount volume read/write (default) +* **security_model=[model]**: specify 9p security model (see below) + +The 9p security model [determines] https://wiki.qemu.org/Documentation/9psetup#Starting_the_Guest_directly +if and how the 9p filesystem translates some filesystem operations before +actual storage on the host. The +default value of *mapped-xattr* specifies that 9p store symlinks and some file +attributes as extended attributes on the host. This is suitable when the host +and the guest do not need to interoperate on the shared filesystem, but has +caveats for actual shared access; notably, symlinks on the host are not usable +on the guest and vice versa. If interoperability is required, then choose +*none* instead, but keep in mind that the guest will not be able to do things +that the user running the virtual machine cannot do, e.g. create files owned by +another user. Using *none* is almost certainly the best choice for read-only +volumes. + +Example: `-v "$HOME/git:$HOME/git:ro,security_model=none"` Default volume mounts are defined in *containers.conf*. Unless changed, the default values is `$HOME:$HOME`. diff --git a/docs/source/markdown/podman-machine.1.md b/docs/source/markdown/podman-machine.1.md index c55226e02..6197b8d4e 100644 --- a/docs/source/markdown/podman-machine.1.md +++ b/docs/source/markdown/podman-machine.1.md @@ -20,6 +20,7 @@ All `podman machine` commands are rootless only. | Command | Man Page | Description | |---------|------------------------------------------------------|-----------------------------------| +| info | [podman-machine-info(1)](podman-machine-info.1.md) | Display machine host info | | init | [podman-machine-init(1)](podman-machine-init.1.md) | Initialize a new virtual machine | | inspect | [podman-machine-inspect(1)](podman-machine-inspect.1.md) | Inspect one or more virtual machines | | list | [podman-machine-list(1)](podman-machine-list.1.md) | List virtual machines | @@ -30,7 +31,7 @@ All `podman machine` commands are rootless only. | stop | [podman-machine-stop(1)](podman-machine-stop.1.md) | Stop a virtual machine | ## SEE ALSO -**[podman(1)](podman.1.md)**, **[podman-machine-init(1)](podman-machine-init.1.md)**, **[podman-machine-list(1)](podman-machine-list.1.md)**, **[podman-machine-rm(1)](podman-machine-rm.1.md)**, **[podman-machine-ssh(1)](podman-machine-ssh.1.md)**, **[podman-machine-start(1)](podman-machine-start.1.md)**, **[podman-machine-stop(1)](podman-machine-stop.1.md)**, **[podman-machine-inspect(1)](podman-machine-inspect.1.md)** +**[podman(1)](podman.1.md)**, **[podman-machine-info(1)](podman-machine-info.1.md)**, **[podman-machine-init(1)](podman-machine-init.1.md)**, **[podman-machine-list(1)](podman-machine-list.1.md)**, **[podman-machine-rm(1)](podman-machine-rm.1.md)**, **[podman-machine-ssh(1)](podman-machine-ssh.1.md)**, **[podman-machine-start(1)](podman-machine-start.1.md)**, **[podman-machine-stop(1)](podman-machine-stop.1.md)**, **[podman-machine-inspect(1)](podman-machine-inspect.1.md)** ## HISTORY March 2021, Originally compiled by Ashley Cui <acui@redhat.com> diff --git a/docs/source/markdown/podman-pod-clone.1.md b/docs/source/markdown/podman-pod-clone.1.md index e44e9fa3c..d90d1efb9 100644 --- a/docs/source/markdown/podman-pod-clone.1.md +++ b/docs/source/markdown/podman-pod-clone.1.md @@ -80,6 +80,16 @@ Add metadata to a pod (e.g., --label com.example.key=value). Read in a line delimited file of labels. +#### **--memory**, **-m**=*limit* + +Memory limit (format: `<number>[<unit>]`, where unit = b (bytes), k (kibibytes), m (mebibytes), or g (gibibytes)) + +Constrains the memory available to a container. If the host +supports swap memory, then the **-m** memory setting can be larger than physical +RAM. If a limit of 0 is specified (not using **-m**), the container's memory is +not limited. The actual limit may be rounded up to a multiple of the operating +system's page size (the value would be very large, that's millions of trillions). + #### **--name**, **-n** Set a custom name for the cloned pod. The default if not specified is of the syntax: **<ORIGINAL_NAME>-clone** @@ -119,8 +129,8 @@ Note: Labeling can be disabled for all pods/containers by setting label=false in - `proc-opts=OPTIONS` : Comma-separated list of options to use for the /proc mount. More details for the possible mount options are specified in the **proc(5)** man page. -- **unmask**=_ALL_ or _/path/1:/path/2_, or shell expanded paths (/proc/*): Paths to unmask separated by a colon. If set to **ALL**, it will unmask all the paths that are masked or made read only by default. - The default masked paths are **/proc/acpi, /proc/kcore, /proc/keys, /proc/latency_stats, /proc/sched_debug, /proc/scsi, /proc/timer_list, /proc/timer_stats, /sys/firmware, and /sys/fs/selinux.** The default paths that are read only are **/proc/asound, /proc/bus, /proc/fs, /proc/irq, /proc/sys, /proc/sysrq-trigger, /sys/fs/cgroup**. +- **unmask**=_ALL_ or _/path/1:/path/2_, or shell expanded paths (/proc/*): Paths to unmask separated by a colon. If set to **ALL**, it will unmask all the paths that are masked or made read-only by default. + The default masked paths are **/proc/acpi, /proc/kcore, /proc/keys, /proc/latency_stats, /proc/sched_debug, /proc/scsi, /proc/timer_list, /proc/timer_stats, /sys/firmware, and /sys/fs/selinux.** The default paths that are read-only are **/proc/asound, /proc/bus, /proc/fs, /proc/irq, /proc/sys, /proc/sysrq-trigger, /sys/fs/cgroup**. Note: Labeling can be disabled for all containers by setting label=false in the **containers.conf** (`/etc/containers/containers.conf` or `$HOME/.config/containers/containers.conf`) file. @@ -201,6 +211,15 @@ Valid _mode_ values are: - *nomap*: creates a user namespace where the current rootless user's UID:GID are not mapped into the container. This option is ignored for containers created by the root user. +#### **--uts**=*mode* + +Set the UTS namespace mode for the pod. The following values are supported: + +- **host**: use the host's UTS namespace inside the pod. +- **private**: create a new namespace for the pod (default). +- **ns:[path]**: run the pod in the given existing UTS namespace. + + #### **--volume**, **-v**[=*[[SOURCE-VOLUME|HOST-DIR:]CONTAINER-DIR[:OPTIONS]]*] Create a bind mount. If ` -v /HOST-DIR:/CONTAINER-DIR` is specified, Podman diff --git a/docs/source/markdown/podman-pod-create.1.md b/docs/source/markdown/podman-pod-create.1.md index e63623169..53d1e3327 100644 --- a/docs/source/markdown/podman-pod-create.1.md +++ b/docs/source/markdown/podman-pod-create.1.md @@ -164,6 +164,16 @@ according to RFC4862. To specify multiple static MAC addresses per pod, set multiple networks using the **--network** option with a static MAC address specified for each using the `mac` mode for that option. +#### **--memory**, **-m**=*limit* + +Memory limit (format: `<number>[<unit>]`, where unit = b (bytes), k (kibibytes), m (mebibytes), or g (gibibytes)) + +Constrains the memory available to a container. If the host +supports swap memory, then the **-m** memory setting can be larger than physical +RAM. If a limit of 0 is specified (not using **-m**), the container's memory is +not limited. The actual limit may be rounded up to a multiple of the operating +system's page size (the value would be very large, that's millions of trillions). + #### **--name**=*name*, **-n** @@ -283,8 +293,8 @@ Note: Labeling can be disabled for all pods/containers by setting label=false in - `proc-opts=OPTIONS` : Comma-separated list of options to use for the /proc mount. More details for the possible mount options are specified in the **proc(5)** man page. -- **unmask**=_ALL_ or _/path/1:/path/2_, or shell expanded paths (/proc/*): Paths to unmask separated by a colon. If set to **ALL**, it will unmask all the paths that are masked or made read only by default. - The default masked paths are **/proc/acpi, /proc/kcore, /proc/keys, /proc/latency_stats, /proc/sched_debug, /proc/scsi, /proc/timer_list, /proc/timer_stats, /sys/firmware, and /sys/fs/selinux.** The default paths that are read only are **/proc/asound, /proc/bus, /proc/fs, /proc/irq, /proc/sys, /proc/sysrq-trigger, /sys/fs/cgroup**. +- **unmask**=_ALL_ or _/path/1:/path/2_, or shell expanded paths (/proc/*): Paths to unmask separated by a colon. If set to **ALL**, it will unmask all the paths that are masked or made read-only by default. + The default masked paths are **/proc/acpi, /proc/kcore, /proc/keys, /proc/latency_stats, /proc/sched_debug, /proc/scsi, /proc/timer_list, /proc/timer_stats, /sys/firmware, and /sys/fs/selinux.** The default paths that are read-only are **/proc/asound, /proc/bus, /proc/fs, /proc/irq, /proc/sys, /proc/sysrq-trigger, /sys/fs/cgroup**. Note: Labeling can be disabled for all containers by setting label=false in the **containers.conf** (`/etc/containers/containers.conf` or `$HOME/.config/containers/containers.conf`) file. @@ -371,6 +381,14 @@ Valid _mode_ values are: - *nomap*: creates a user namespace where the current rootless user's UID:GID are not mapped into the container. This option is not allowed for containers created by the root user. +#### **--uts**=*mode* + +Set the UTS namespace mode for the pod. The following values are supported: + +- **host**: use the host's UTS namespace inside the pod. +- **private**: create a new namespace for the pod (default). +- **ns:[path]**: run the pod in the given existing UTS namespace. + #### **--volume**, **-v**[=*[[SOURCE-VOLUME|HOST-DIR:]CONTAINER-DIR[:OPTIONS]]*] Create a bind mount. If you specify, ` -v /HOST-DIR:/CONTAINER-DIR`, Podman diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md index 5b45c3350..8f71c3706 100644 --- a/docs/source/markdown/podman-run.1.md +++ b/docs/source/markdown/podman-run.1.md @@ -919,11 +919,11 @@ Suppress output information when pulling images #### **--read-only** -Mount the container's root filesystem as read only. +Mount the container's root filesystem as read-only. By default a container will have its root filesystem writable allowing processes to write files anywhere. By specifying the **--read-only** flag, the container will have -its root filesystem mounted as read only prohibiting any writes. +its root filesystem mounted as read-only prohibiting any writes. #### **--read-only-tmpfs** @@ -1051,8 +1051,8 @@ Note: Labeling can be disabled for all containers by setting label=false in the - **proc-opts**=_OPTIONS_ : Comma-separated list of options to use for the /proc mount. More details for the possible mount options are specified in the **proc(5)** man page. -- **unmask**=_ALL_ or _/path/1:/path/2_, or shell expanded paths (/proc/*): Paths to unmask separated by a colon. If set to **ALL**, it will unmask all the paths that are masked or made read only by default. - The default masked paths are **/proc/acpi, /proc/kcore, /proc/keys, /proc/latency_stats, /proc/sched_debug, /proc/scsi, /proc/timer_list, /proc/timer_stats, /sys/firmware, and /sys/fs/selinux.**. The default paths that are read only are **/proc/asound**, **/proc/bus**, **/proc/fs**, **/proc/irq**, **/proc/sys**, **/proc/sysrq-trigger**, **/sys/fs/cgroup**. +- **unmask**=_ALL_ or _/path/1:/path/2_, or shell expanded paths (/proc/*): Paths to unmask separated by a colon. If set to **ALL**, it will unmask all the paths that are masked or made read-only by default. + The default masked paths are **/proc/acpi, /proc/kcore, /proc/keys, /proc/latency_stats, /proc/sched_debug, /proc/scsi, /proc/timer_list, /proc/timer_stats, /sys/firmware, and /sys/fs/selinux.**. The default paths that are read-only are **/proc/asound**, **/proc/bus**, **/proc/fs**, **/proc/irq**, **/proc/sys**, **/proc/sysrq-trigger**, **/sys/fs/cgroup**. Note: Labeling can be disabled for all containers by setting **label=false** in the **containers.conf**(5) file. @@ -1603,7 +1603,7 @@ content. Installing packages into _/usr_, for example. In production, applications seldom need to write to the image. Container applications write to volumes if they need to write to file systems at all. Applications can be made more secure by running them in read-only mode using the **--read-only** switch. -This protects the containers image from modification. Read only containers may +This protects the containers image from modification. Read-only containers may still need to write temporary data. The best way to handle this is to mount tmpfs directories on _/run_ and _/tmp_. diff --git a/docs/tutorials/remote_client.md b/docs/tutorials/remote_client.md index 27b97e6f5..5cd679193 100644 --- a/docs/tutorials/remote_client.md +++ b/docs/tutorials/remote_client.md @@ -54,7 +54,7 @@ host: In order for the Podman client to communicate with the server you need to enable and start the SSH daemon on your Linux machine, if it is not currently enabled. ``` -sudo systemctl enable --now -s sshd +sudo systemctl enable --now sshd ``` #### Setting up SSH @@ -12,7 +12,7 @@ require ( github.com/containernetworking/cni v1.1.1 github.com/containernetworking/plugins v1.1.1 github.com/containers/buildah v1.26.1-0.20220609225314-e66309ebde8c - github.com/containers/common v0.48.1-0.20220628131511-a8336c1613fe + github.com/containers/common v0.48.1-0.20220705175712-dd1c331887b9 github.com/containers/conmon v2.0.20+incompatible github.com/containers/image/v5 v5.21.2-0.20220617075545-929f14a56f5c github.com/containers/ocicrypt v1.1.5 @@ -338,8 +338,8 @@ github.com/containernetworking/plugins v1.1.1/go.mod h1:Sr5TH/eBsGLXK/h71HeLfX19 github.com/containers/buildah v1.26.1-0.20220609225314-e66309ebde8c h1:/fKyiLFFuceBPZGJ0Lig7ElURhfsslAOw1BOcItD+X8= github.com/containers/buildah v1.26.1-0.20220609225314-e66309ebde8c/go.mod h1:b0L+u2Dam7soWGn5sVTK31L++Xrf80AbGvK5z9D2+lw= github.com/containers/common v0.48.1-0.20220608111710-dbecabbe82c9/go.mod h1:WBLwq+i7bicCpH54V70HM6s7jqDAESTlYnd05XXp0ac= -github.com/containers/common v0.48.1-0.20220628131511-a8336c1613fe h1:H5YI9PXhDB974IkSCUaha+AF60TunRdHaGElZroYx7M= -github.com/containers/common v0.48.1-0.20220628131511-a8336c1613fe/go.mod h1:UDe7OTpNdtJA2T80Sp7yB0yTaj79f4kMNQbTsNxsqoY= +github.com/containers/common v0.48.1-0.20220705175712-dd1c331887b9 h1:KeGIf6Z1R+16Sq+5/fhkoCCKa7wjQ6Ksnmo0beU1E2U= +github.com/containers/common v0.48.1-0.20220705175712-dd1c331887b9/go.mod h1:Zt3D/IhgFyG1oaBrqsbn9NdH/4fkjsO2Y0ahP12ieu4= 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/image/v5 v5.21.2-0.20220511203756-fe4fd4ed8be4/go.mod h1:OsX9sFexyGF0FCNAjfcVFv3IwMqDyLyV/WQY/roLPcE= @@ -1268,7 +1268,6 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= diff --git a/hack/install_golangci.sh b/hack/install_golangci.sh index 4ef6bc83b..896d59901 100755 --- a/hack/install_golangci.sh +++ b/hack/install_golangci.sh @@ -9,14 +9,17 @@ function install() { curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s v$VERSION } -BIN="./bin/golangci-lint" +# Undocumented behavior: golangci-lint installer requires $BINDIR in env, +# will default to ./bin but we can't rely on that. +export BINDIR="./bin" +BIN="$BINDIR/golangci-lint" if [ ! -x "$BIN" ]; then install else # Prints its own file name as part of --version output $BIN --version | grep "$VERSION" if [ $? -eq 0 ]; then - echo "Using existing $(dirname $BIN)/$($BIN --version)" + echo "Using existing $BINDIR/$($BIN --version)" else install fi diff --git a/hack/podman-registry-go/registry.go b/hack/podman-registry-go/registry.go index af8f3117c..d66d092b6 100644 --- a/hack/podman-registry-go/registry.go +++ b/hack/podman-registry-go/registry.go @@ -1,10 +1,10 @@ package registry import ( + "fmt" "strings" "github.com/containers/podman/v4/utils" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -57,7 +57,7 @@ func StartWithOptions(options *Options) (*Registry, error) { // Start a registry. out, err := utils.ExecCmd(binary, args...) if err != nil { - return nil, errors.Wrapf(err, "error running %q: %s", binary, out) + return nil, fmt.Errorf("error running %q: %s: %w", binary, out, err) } // Parse the output. @@ -68,7 +68,7 @@ func StartWithOptions(options *Options) (*Registry, error) { } spl := strings.Split(s, "=") if len(spl) != 2 { - return nil, errors.Errorf("unexpected output format %q: want 'PODMAN_...=...'", s) + return nil, fmt.Errorf("unexpected output format %q: want 'PODMAN_...=...'", s) } key := spl[0] val := strings.TrimSuffix(strings.TrimPrefix(spl[1], "\""), "\"") @@ -88,16 +88,16 @@ func StartWithOptions(options *Options) (*Registry, error) { // Extra sanity check. if registry.Image == "" { - return nil, errors.Errorf("unexpected output %q: %q missing", out, ImageKey) + return nil, fmt.Errorf("unexpected output %q: %q missing", out, ImageKey) } if registry.User == "" { - return nil, errors.Errorf("unexpected output %q: %q missing", out, UserKey) + return nil, fmt.Errorf("unexpected output %q: %q missing", out, UserKey) } if registry.Password == "" { - return nil, errors.Errorf("unexpected output %q: %q missing", out, PassKey) + return nil, fmt.Errorf("unexpected output %q: %q missing", out, PassKey) } if registry.Port == "" { - return nil, errors.Errorf("unexpected output %q: %q missing", out, PortKey) + return nil, fmt.Errorf("unexpected output %q: %q missing", out, PortKey) } registry.running = true @@ -112,7 +112,7 @@ func (r *Registry) Stop() error { return nil } if _, err := utils.ExecCmd(binary, "-P", r.Port, "stop"); err != nil { - return errors.Wrapf(err, "error stopping registry (%v) with %q", *r, binary) + return fmt.Errorf("error stopping registry (%v) with %q: %w", *r, binary, err) } r.running = false return nil diff --git a/libpod/boltdb_state.go b/libpod/boltdb_state.go index 471f64b84..81f11410b 100644 --- a/libpod/boltdb_state.go +++ b/libpod/boltdb_state.go @@ -2,6 +2,7 @@ package libpod import ( "bytes" + "errors" "fmt" "net" "os" @@ -13,7 +14,6 @@ import ( "github.com/containers/common/libnetwork/types" "github.com/containers/podman/v4/libpod/define" jsoniter "github.com/json-iterator/go" - "github.com/pkg/errors" "github.com/sirupsen/logrus" bolt "go.etcd.io/bbolt" ) @@ -85,7 +85,7 @@ func NewBoltState(path string, runtime *Runtime) (State, error) { db, err := bolt.Open(path, 0600, nil) if err != nil { - return nil, errors.Wrapf(err, "error opening database %s", path) + return nil, fmt.Errorf("error opening database %s: %w", path, err) } // Everywhere else, we use s.deferredCloseDBCon(db) to ensure the state's DB // mutex is also unlocked. @@ -123,7 +123,7 @@ func NewBoltState(path string, runtime *Runtime) (State, error) { return nil }) if err != nil { - return nil, errors.Wrapf(err, "error checking DB schema") + return nil, fmt.Errorf("error checking DB schema: %w", err) } if !needsUpdate { @@ -135,13 +135,13 @@ func NewBoltState(path string, runtime *Runtime) (State, error) { err = db.Update(func(tx *bolt.Tx) error { for _, bkt := range createBuckets { if _, err := tx.CreateBucketIfNotExists(bkt); err != nil { - return errors.Wrapf(err, "error creating bucket %s", string(bkt)) + return fmt.Errorf("error creating bucket %s: %w", string(bkt), err) } } return nil }) if err != nil { - return nil, errors.Wrapf(err, "error creating buckets for DB") + return nil, fmt.Errorf("error creating buckets for DB: %w", err) } state.valid = true @@ -220,11 +220,11 @@ func (s *BoltState) Refresh() error { return nil }) if err != nil { - return errors.Wrapf(err, "error reading exit codes bucket") + return fmt.Errorf("error reading exit codes bucket: %w", err) } for _, id := range toRemoveExitCodes { if err := exitCodeBucket.Delete([]byte(id)); err != nil { - return errors.Wrapf(err, "error removing exit code for ID %s", id) + return fmt.Errorf("error removing exit code for ID %s: %w", id, err) } } @@ -234,11 +234,11 @@ func (s *BoltState) Refresh() error { return nil }) if err != nil { - return errors.Wrapf(err, "reading timestamps bucket") + return fmt.Errorf("reading timestamps bucket: %w", err) } for _, id := range toRemoveTimeStamps { if err := timeStampBucket.Delete([]byte(id)); err != nil { - return errors.Wrapf(err, "removing timestamp for ID %s", id) + return fmt.Errorf("removing timestamp for ID %s: %w", id, err) } } @@ -270,13 +270,13 @@ func (s *BoltState) Refresh() error { // Get the state stateBytes := podBkt.Get(stateKey) if stateBytes == nil { - return errors.Wrapf(define.ErrInternal, "pod %s missing state key", string(id)) + return fmt.Errorf("pod %s missing state key: %w", string(id), define.ErrInternal) } state := new(podState) if err := json.Unmarshal(stateBytes, state); err != nil { - return errors.Wrapf(err, "error unmarshalling state for pod %s", string(id)) + return fmt.Errorf("error unmarshalling state for pod %s: %w", string(id), err) } // Clear the Cgroup path @@ -284,11 +284,11 @@ func (s *BoltState) Refresh() error { newStateBytes, err := json.Marshal(state) if err != nil { - return errors.Wrapf(err, "error marshalling modified state for pod %s", string(id)) + return fmt.Errorf("error marshalling modified state for pod %s: %w", string(id), err) } if err := podBkt.Put(stateKey, newStateBytes); err != nil { - return errors.Wrapf(err, "error updating state for pod %s in DB", string(id)) + return fmt.Errorf("error updating state for pod %s in DB: %w", string(id), err) } // It's not a container, nothing to do @@ -297,30 +297,30 @@ func (s *BoltState) Refresh() error { // First, delete the network namespace if err := ctrBkt.Delete(netNSKey); err != nil { - return errors.Wrapf(err, "error removing network namespace for container %s", string(id)) + return fmt.Errorf("error removing network namespace for container %s: %w", string(id), err) } stateBytes := ctrBkt.Get(stateKey) if stateBytes == nil { // Badly formatted container bucket - return errors.Wrapf(define.ErrInternal, "container %s missing state in DB", string(id)) + return fmt.Errorf("container %s missing state in DB: %w", string(id), define.ErrInternal) } state := new(ContainerState) if err := json.Unmarshal(stateBytes, state); err != nil { - return errors.Wrapf(err, "error unmarshalling state for container %s", string(id)) + return fmt.Errorf("error unmarshalling state for container %s: %w", string(id), err) } resetState(state) newStateBytes, err := json.Marshal(state) if err != nil { - return errors.Wrapf(err, "error marshalling modified state for container %s", string(id)) + return fmt.Errorf("error marshalling modified state for container %s: %w", string(id), err) } if err := ctrBkt.Put(stateKey, newStateBytes); err != nil { - return errors.Wrapf(err, "error updating state for container %s in DB", string(id)) + return fmt.Errorf("error updating state for container %s in DB: %w", string(id), err) } // Delete all exec sessions, if there are any @@ -338,7 +338,7 @@ func (s *BoltState) Refresh() error { } for _, execID := range toRemove { if err := ctrExecBkt.Delete([]byte(execID)); err != nil { - return errors.Wrapf(err, "error removing exec session %s from container %s", execID, string(id)) + return fmt.Errorf("error removing exec session %s from container %s: %w", execID, string(id), err) } } } @@ -358,12 +358,12 @@ func (s *BoltState) Refresh() error { if testID := namesBucket.Get(name); testID != nil { logrus.Infof("Found dangling name %s (ID %s) in database", string(name), id) if err := namesBucket.Delete(name); err != nil { - return errors.Wrapf(err, "error removing dangling name %s (ID %s) from database", string(name), id) + return fmt.Errorf("error removing dangling name %s (ID %s) from database: %w", string(name), id, err) } } } if err := idBucket.Delete([]byte(id)); err != nil { - return errors.Wrapf(err, "error removing dangling ID %s from database", id) + return fmt.Errorf("error removing dangling ID %s from database: %w", id, err) } } @@ -371,7 +371,7 @@ func (s *BoltState) Refresh() error { err = allVolsBucket.ForEach(func(id, name []byte) error { dbVol := volBucket.Bucket(id) if dbVol == nil { - return errors.Wrapf(define.ErrInternal, "inconsistency in state - volume %s is in all volumes bucket but volume not found", string(id)) + return fmt.Errorf("inconsistency in state - volume %s is in all volumes bucket but volume not found: %w", string(id), define.ErrInternal) } // Get the state @@ -384,7 +384,7 @@ func (s *BoltState) Refresh() error { oldState := new(VolumeState) if err := json.Unmarshal(volStateBytes, oldState); err != nil { - return errors.Wrapf(err, "error unmarshalling state for volume %s", string(id)) + return fmt.Errorf("error unmarshalling state for volume %s: %w", string(id), err) } // Reset mount count to 0 @@ -393,11 +393,11 @@ func (s *BoltState) Refresh() error { newState, err := json.Marshal(oldState) if err != nil { - return errors.Wrapf(err, "error marshalling state for volume %s", string(id)) + return fmt.Errorf("error marshalling state for volume %s: %w", string(id), err) } if err := dbVol.Put(stateKey, newState); err != nil { - return errors.Wrapf(err, "error storing new state for volume %s", string(id)) + return fmt.Errorf("error storing new state for volume %s: %w", string(id), err) } return nil @@ -421,7 +421,7 @@ func (s *BoltState) Refresh() error { for _, execSession := range toRemoveExec { if err := execBucket.Delete([]byte(execSession)); err != nil { - return errors.Wrapf(err, "error deleting exec session %s registry from database", execSession) + return fmt.Errorf("error deleting exec session %s registry from database: %w", execSession, err) } } @@ -643,7 +643,7 @@ func (s *BoltState) LookupContainerID(idOrName string) (string, error) { if s.namespaceBytes != nil { ns := nsBucket.Get(fullID) if !bytes.Equal(ns, s.namespaceBytes) { - return errors.Wrapf(define.ErrNoSuchCtr, "no container found with name or ID %s", idOrName) + return fmt.Errorf("no container found with name or ID %s: %w", idOrName, define.ErrNoSuchCtr) } } id = fullID @@ -768,7 +768,7 @@ func (s *BoltState) AddContainer(ctr *Container) error { } if ctr.config.Pod != "" { - return errors.Wrapf(define.ErrInvalidArg, "cannot add a container that belongs to a pod with AddContainer - use AddContainerToPod") + return fmt.Errorf("cannot add a container that belongs to a pod with AddContainer - use AddContainerToPod: %w", define.ErrInvalidArg) } return s.addContainer(ctr, nil) @@ -783,7 +783,7 @@ func (s *BoltState) RemoveContainer(ctr *Container) error { } if ctr.config.Pod != "" { - return errors.Wrapf(define.ErrPodExists, "container %s is part of a pod, use RemoveContainerFromPod instead", ctr.ID()) + return fmt.Errorf("container %s is part of a pod, use RemoveContainerFromPod instead: %w", ctr.ID(), define.ErrPodExists) } db, err := s.getDBCon() @@ -809,7 +809,7 @@ func (s *BoltState) UpdateContainer(ctr *Container) error { } if s.namespace != "" && s.namespace != ctr.config.Namespace { - return errors.Wrapf(define.ErrNSMismatch, "container %s is in namespace %q, does not match our namespace %q", ctr.ID(), ctr.config.Namespace, s.namespace) + return fmt.Errorf("container %s is in namespace %q, does not match our namespace %q: %w", ctr.ID(), ctr.config.Namespace, s.namespace, define.ErrNSMismatch) } newState := new(ContainerState) @@ -832,16 +832,16 @@ func (s *BoltState) UpdateContainer(ctr *Container) error { ctrToUpdate := ctrBucket.Bucket(ctrID) if ctrToUpdate == nil { ctr.valid = false - return errors.Wrapf(define.ErrNoSuchCtr, "container %s does not exist in database", ctr.ID()) + return fmt.Errorf("container %s does not exist in database: %w", ctr.ID(), define.ErrNoSuchCtr) } newStateBytes := ctrToUpdate.Get(stateKey) if newStateBytes == nil { - return errors.Wrapf(define.ErrInternal, "container %s does not have a state key in DB", ctr.ID()) + return fmt.Errorf("container %s does not have a state key in DB: %w", ctr.ID(), define.ErrInternal) } if err := json.Unmarshal(newStateBytes, newState); err != nil { - return errors.Wrapf(err, "error unmarshalling container %s state", ctr.ID()) + return fmt.Errorf("error unmarshalling container %s state: %w", ctr.ID(), err) } netNSBytes := ctrToUpdate.Get(netNSKey) @@ -881,12 +881,12 @@ func (s *BoltState) SaveContainer(ctr *Container) error { } if s.namespace != "" && s.namespace != ctr.config.Namespace { - return errors.Wrapf(define.ErrNSMismatch, "container %s is in namespace %q, does not match our namespace %q", ctr.ID(), ctr.config.Namespace, s.namespace) + return fmt.Errorf("container %s is in namespace %q, does not match our namespace %q: %w", ctr.ID(), ctr.config.Namespace, s.namespace, define.ErrNSMismatch) } stateJSON, err := json.Marshal(ctr.state) if err != nil { - return errors.Wrapf(err, "error marshalling container %s state to JSON", ctr.ID()) + return fmt.Errorf("error marshalling container %s state to JSON: %w", ctr.ID(), err) } netNSPath := getNetNSPath(ctr) @@ -907,22 +907,22 @@ func (s *BoltState) SaveContainer(ctr *Container) error { ctrToSave := ctrBucket.Bucket(ctrID) if ctrToSave == nil { ctr.valid = false - return errors.Wrapf(define.ErrNoSuchCtr, "container %s does not exist in DB", ctr.ID()) + return fmt.Errorf("container %s does not exist in DB: %w", ctr.ID(), define.ErrNoSuchCtr) } // Update the state if err := ctrToSave.Put(stateKey, stateJSON); err != nil { - return errors.Wrapf(err, "error updating container %s state in DB", ctr.ID()) + return fmt.Errorf("error updating container %s state in DB: %w", ctr.ID(), err) } if netNSPath != "" { if err := ctrToSave.Put(netNSKey, []byte(netNSPath)); err != nil { - return errors.Wrapf(err, "error updating network namespace path for container %s in DB", ctr.ID()) + return fmt.Errorf("error updating network namespace path for container %s in DB: %w", ctr.ID(), err) } } else { // Delete the existing network namespace if err := ctrToSave.Delete(netNSKey); err != nil { - return errors.Wrapf(err, "error removing network namespace path for container %s in DB", ctr.ID()) + return fmt.Errorf("error removing network namespace path for container %s in DB: %w", ctr.ID(), err) } } @@ -944,7 +944,7 @@ func (s *BoltState) ContainerInUse(ctr *Container) ([]string, error) { } if s.namespace != "" && s.namespace != ctr.config.Namespace { - return nil, errors.Wrapf(define.ErrNSMismatch, "container %s is in namespace %q, does not match our namespace %q", ctr.ID(), ctr.config.Namespace, s.namespace) + return nil, fmt.Errorf("container %s is in namespace %q, does not match our namespace %q: %w", ctr.ID(), ctr.config.Namespace, s.namespace, define.ErrNSMismatch) } depCtrs := []string{} @@ -964,12 +964,12 @@ func (s *BoltState) ContainerInUse(ctr *Container) ([]string, error) { ctrDB := ctrBucket.Bucket([]byte(ctr.ID())) if ctrDB == nil { ctr.valid = false - return errors.Wrapf(define.ErrNoSuchCtr, "no container with ID %q found in DB", ctr.ID()) + return fmt.Errorf("no container with ID %q found in DB: %w", ctr.ID(), define.ErrNoSuchCtr) } dependsBkt := ctrDB.Bucket(dependenciesBkt) if dependsBkt == nil { - return errors.Wrapf(define.ErrInternal, "container %s has no dependencies bucket", ctr.ID()) + return fmt.Errorf("container %s has no dependencies bucket: %w", ctr.ID(), define.ErrInternal) } // Iterate through and add dependencies @@ -1022,7 +1022,7 @@ func (s *BoltState) AllContainers() ([]*Container, error) { // be much less helpful. ctrExists := ctrBucket.Bucket(id) if ctrExists == nil { - return errors.Wrapf(define.ErrInternal, "state is inconsistent - container ID %s in all containers, but container not found", string(id)) + return fmt.Errorf("state is inconsistent - container ID %s in all containers, but container not found: %w", string(id), define.ErrInternal) } ctr := new(Container) @@ -1034,7 +1034,7 @@ func (s *BoltState) AllContainers() ([]*Container, error) { // ignore it safely. // We just won't include the container in the // results. - if errors.Cause(err) != define.ErrNSMismatch { + if !errors.Is(err, define.ErrNSMismatch) { // Even if it's not an NS mismatch, it's // not worth erroring over. // If we do, a single bad container JSON @@ -1066,7 +1066,7 @@ func (s *BoltState) GetNetworks(ctr *Container) (map[string]types.PerNetworkOpti } if s.namespace != "" && s.namespace != ctr.config.Namespace { - return nil, errors.Wrapf(define.ErrNSMismatch, "container %s is in namespace %q, does not match our namespace %q", ctr.ID(), ctr.config.Namespace, s.namespace) + return nil, fmt.Errorf("container %s is in namespace %q, does not match our namespace %q: %w", ctr.ID(), ctr.config.Namespace, s.namespace, define.ErrNSMismatch) } // if the network mode is not bridge return no networks @@ -1095,7 +1095,7 @@ func (s *BoltState) GetNetworks(ctr *Container) (map[string]types.PerNetworkOpti dbCtr := ctrBucket.Bucket(ctrID) if dbCtr == nil { ctr.valid = false - return errors.Wrapf(define.ErrNoSuchCtr, "container %s does not exist in database", ctr.ID()) + return fmt.Errorf("container %s does not exist in database: %w", ctr.ID(), define.ErrNoSuchCtr) } ctrNetworkBkt := dbCtr.Bucket(networksBkt) @@ -1133,7 +1133,7 @@ func (s *BoltState) GetNetworks(ctr *Container) (map[string]types.PerNetworkOpti dbCtr := ctrBucket.Bucket(ctrID) if dbCtr == nil { ctr.valid = false - return errors.Wrapf(define.ErrNoSuchCtr, "container %s does not exist in database", ctr.ID()) + return fmt.Errorf("container %s does not exist in database: %w", ctr.ID(), define.ErrNoSuchCtr) } var networkList []string @@ -1142,7 +1142,7 @@ func (s *BoltState) GetNetworks(ctr *Container) (map[string]types.PerNetworkOpti if ctrNetworkBkt == nil { ctrNetworkBkt, err = dbCtr.CreateBucket(networksBkt) if err != nil { - return errors.Wrapf(err, "error creating networks bucket for container %s", ctr.ID()) + return fmt.Errorf("error creating networks bucket for container %s: %w", ctr.ID(), err) } // the container has no networks in the db lookup config and write to the db networkList = ctr.config.NetworksDeprecated @@ -1166,7 +1166,7 @@ func (s *BoltState) GetNetworks(ctr *Container) (map[string]types.PerNetworkOpti if ctr.state.NetInterfaceDescriptions != nil { eth, exists := ctr.state.NetInterfaceDescriptions.getInterfaceByName(network) if !exists { - return errors.Errorf("no network interface name for container %s on network %s", ctr.config.ID, network) + return fmt.Errorf("no network interface name for container %s on network %s", ctr.config.ID, network) } intName = eth } else { @@ -1240,16 +1240,16 @@ func (s *BoltState) NetworkConnect(ctr *Container, network string, opts types.Pe } if network == "" { - return errors.Wrapf(define.ErrInvalidArg, "network names must not be empty") + return fmt.Errorf("network names must not be empty: %w", define.ErrInvalidArg) } if s.namespace != "" && s.namespace != ctr.config.Namespace { - return errors.Wrapf(define.ErrNSMismatch, "container %s is in namespace %q, does not match our namespace %q", ctr.ID(), ctr.config.Namespace, s.namespace) + return fmt.Errorf("container %s is in namespace %q, does not match our namespace %q: %w", ctr.ID(), ctr.config.Namespace, s.namespace, define.ErrNSMismatch) } optBytes, err := json.Marshal(opts) if err != nil { - return errors.Wrapf(err, "error marshalling network options JSON for container %s", ctr.ID()) + return fmt.Errorf("error marshalling network options JSON for container %s: %w", ctr.ID(), err) } ctrID := []byte(ctr.ID()) @@ -1269,21 +1269,21 @@ func (s *BoltState) NetworkConnect(ctr *Container, network string, opts types.Pe dbCtr := ctrBucket.Bucket(ctrID) if dbCtr == nil { ctr.valid = false - return errors.Wrapf(define.ErrNoSuchCtr, "container %s does not exist in database", ctr.ID()) + return fmt.Errorf("container %s does not exist in database: %w", ctr.ID(), define.ErrNoSuchCtr) } ctrNetworksBkt := dbCtr.Bucket(networksBkt) if ctrNetworksBkt == nil { - return errors.Wrapf(define.ErrNoSuchNetwork, "container %s does not have a network bucket", ctr.ID()) + return fmt.Errorf("container %s does not have a network bucket: %w", ctr.ID(), define.ErrNoSuchNetwork) } netConnected := ctrNetworksBkt.Get([]byte(network)) if netConnected != nil { - return errors.Wrapf(define.ErrNetworkExists, "container %s is already connected to network %q", ctr.ID(), network) + return fmt.Errorf("container %s is already connected to network %q: %w", ctr.ID(), network, define.ErrNetworkExists) } // Add the network if err := ctrNetworksBkt.Put([]byte(network), optBytes); err != nil { - return errors.Wrapf(err, "error adding container %s to network %s in DB", ctr.ID(), network) + return fmt.Errorf("error adding container %s to network %s in DB: %w", ctr.ID(), network, err) } return nil @@ -1302,11 +1302,11 @@ func (s *BoltState) NetworkDisconnect(ctr *Container, network string) error { } if network == "" { - return errors.Wrapf(define.ErrInvalidArg, "network names must not be empty") + return fmt.Errorf("network names must not be empty: %w", define.ErrInvalidArg) } if s.namespace != "" && s.namespace != ctr.config.Namespace { - return errors.Wrapf(define.ErrNSMismatch, "container %s is in namespace %q, does not match our namespace %q", ctr.ID(), ctr.config.Namespace, s.namespace) + return fmt.Errorf("container %s is in namespace %q, does not match our namespace %q: %w", ctr.ID(), ctr.config.Namespace, s.namespace, define.ErrNSMismatch) } ctrID := []byte(ctr.ID()) @@ -1326,21 +1326,21 @@ func (s *BoltState) NetworkDisconnect(ctr *Container, network string) error { dbCtr := ctrBucket.Bucket(ctrID) if dbCtr == nil { ctr.valid = false - return errors.Wrapf(define.ErrNoSuchCtr, "container %s does not exist in database", ctr.ID()) + return fmt.Errorf("container %s does not exist in database: %w", ctr.ID(), define.ErrNoSuchCtr) } ctrAliasesBkt := dbCtr.Bucket(aliasesBkt) ctrNetworksBkt := dbCtr.Bucket(networksBkt) if ctrNetworksBkt == nil { - return errors.Wrapf(define.ErrNoSuchNetwork, "container %s is not connected to any CNI networks, so cannot disconnect", ctr.ID()) + return fmt.Errorf("container %s is not connected to any CNI networks, so cannot disconnect: %w", ctr.ID(), define.ErrNoSuchNetwork) } netConnected := ctrNetworksBkt.Get([]byte(network)) if netConnected == nil { - return errors.Wrapf(define.ErrNoSuchNetwork, "container %s is not connected to CNI network %q", ctr.ID(), network) + return fmt.Errorf("container %s is not connected to CNI network %q: %w", ctr.ID(), network, define.ErrNoSuchNetwork) } if err := ctrNetworksBkt.Delete([]byte(network)); err != nil { - return errors.Wrapf(err, "error removing container %s from network %s", ctr.ID(), network) + return fmt.Errorf("error removing container %s from network %s: %w", ctr.ID(), network, err) } if ctrAliasesBkt != nil { @@ -1350,7 +1350,7 @@ func (s *BoltState) NetworkDisconnect(ctr *Container, network string) error { } if err := ctrAliasesBkt.DeleteBucket([]byte(network)); err != nil { - return errors.Wrapf(err, "error removing container %s network aliases for network %s", ctr.ID(), network) + return fmt.Errorf("error removing container %s network aliases for network %s: %w", ctr.ID(), network, err) } } @@ -1548,7 +1548,7 @@ func (s *BoltState) PruneContainerExitCodes() error { }) }) if err != nil { - return errors.Wrapf(err, "reading exit codes to prune") + return fmt.Errorf("reading exit codes to prune: %w", err) } if len(toRemoveIDs) > 0 { @@ -1582,7 +1582,7 @@ func (s *BoltState) PruneContainerExitCodes() error { return finalErr }) if err != nil { - return errors.Wrapf(err, "pruning exit codes") + return fmt.Errorf("pruning exit codes: %w", err) } } @@ -1621,25 +1621,25 @@ func (s *BoltState) AddExecSession(ctr *Container, session *ExecSession) error { dbCtr := ctrBucket.Bucket(ctrID) if dbCtr == nil { ctr.valid = false - return errors.Wrapf(define.ErrNoSuchCtr, "container %s is not present in the database", ctr.ID()) + return fmt.Errorf("container %s is not present in the database: %w", ctr.ID(), define.ErrNoSuchCtr) } ctrExecSessionBucket, err := dbCtr.CreateBucketIfNotExists(execBkt) if err != nil { - return errors.Wrapf(err, "error creating exec sessions bucket for container %s", ctr.ID()) + return fmt.Errorf("error creating exec sessions bucket for container %s: %w", ctr.ID(), err) } execExists := execBucket.Get(sessionID) if execExists != nil { - return errors.Wrapf(define.ErrExecSessionExists, "an exec session with ID %s already exists", session.ID()) + return fmt.Errorf("an exec session with ID %s already exists: %w", session.ID(), define.ErrExecSessionExists) } if err := execBucket.Put(sessionID, ctrID); err != nil { - return errors.Wrapf(err, "error adding exec session %s to DB", session.ID()) + return fmt.Errorf("error adding exec session %s to DB: %w", session.ID(), err) } if err := ctrExecSessionBucket.Put(sessionID, ctrID); err != nil { - return errors.Wrapf(err, "error adding exec session %s to container %s in DB", session.ID(), ctr.ID()) + return fmt.Errorf("error adding exec session %s to container %s in DB: %w", session.ID(), ctr.ID(), err) } return nil @@ -1673,7 +1673,7 @@ func (s *BoltState) GetExecSession(id string) (string, error) { ctr := execBucket.Get([]byte(id)) if ctr == nil { - return errors.Wrapf(define.ErrNoSuchExecSession, "no exec session with ID %s found", id) + return fmt.Errorf("no exec session with ID %s found: %w", id, define.ErrNoSuchExecSession) } ctrID = string(ctr) return nil @@ -1712,11 +1712,11 @@ func (s *BoltState) RemoveExecSession(session *ExecSession) error { } // Check that container ID matches if string(sessionExists) != session.ContainerID() { - return errors.Wrapf(define.ErrInternal, "database inconsistency: exec session %s points to container %s in state but %s in database", session.ID(), session.ContainerID(), string(sessionExists)) + return fmt.Errorf("database inconsistency: exec session %s points to container %s in state but %s in database: %w", session.ID(), session.ContainerID(), string(sessionExists), define.ErrInternal) } if err := execBucket.Delete(sessionID); err != nil { - return errors.Wrapf(err, "error removing exec session %s from database", session.ID()) + return fmt.Errorf("error removing exec session %s from database: %w", session.ID(), err) } dbCtr := ctrBucket.Bucket(containerID) @@ -1739,7 +1739,7 @@ func (s *BoltState) RemoveExecSession(session *ExecSession) error { ctrSessionExists := ctrExecBucket.Get(sessionID) if ctrSessionExists != nil { if err := ctrExecBucket.Delete(sessionID); err != nil { - return errors.Wrapf(err, "error removing exec session %s from container %s in database", session.ID(), session.ContainerID()) + return fmt.Errorf("error removing exec session %s from container %s in database: %w", session.ID(), session.ContainerID(), err) } } @@ -1847,7 +1847,7 @@ func (s *BoltState) RemoveContainerExecSessions(ctr *Container) error { for _, session := range sessions { if err := ctrExecSessions.Delete([]byte(session)); err != nil { - return errors.Wrapf(err, "error removing container %s exec session %s from database", ctr.ID(), session) + return fmt.Errorf("error removing container %s exec session %s from database: %w", ctr.ID(), session, err) } // Check if the session exists in the global table // before removing. It should, but in cases where the DB @@ -1858,10 +1858,10 @@ func (s *BoltState) RemoveContainerExecSessions(ctr *Container) error { continue } if string(sessionExists) != ctr.ID() { - return errors.Wrapf(define.ErrInternal, "database mismatch: exec session %s is associated with containers %s and %s", session, ctr.ID(), string(sessionExists)) + return fmt.Errorf("database mismatch: exec session %s is associated with containers %s and %s: %w", session, ctr.ID(), string(sessionExists), define.ErrInternal) } if err := execBucket.Delete([]byte(session)); err != nil { - return errors.Wrapf(err, "error removing container %s exec session %s from exec sessions", ctr.ID(), session) + return fmt.Errorf("error removing container %s exec session %s from exec sessions: %w", ctr.ID(), session, err) } } @@ -1884,7 +1884,7 @@ func (s *BoltState) RewriteContainerConfig(ctr *Container, newCfg *ContainerConf newCfgJSON, err := json.Marshal(newCfg) if err != nil { - return errors.Wrapf(err, "error marshalling new configuration JSON for container %s", ctr.ID()) + return fmt.Errorf("error marshalling new configuration JSON for container %s: %w", ctr.ID(), err) } db, err := s.getDBCon() @@ -1902,11 +1902,11 @@ func (s *BoltState) RewriteContainerConfig(ctr *Container, newCfg *ContainerConf ctrDB := ctrBkt.Bucket([]byte(ctr.ID())) if ctrDB == nil { ctr.valid = false - return errors.Wrapf(define.ErrNoSuchCtr, "no container with ID %q found in DB", ctr.ID()) + return fmt.Errorf("no container with ID %q found in DB: %w", ctr.ID(), define.ErrNoSuchCtr) } if err := ctrDB.Put(configKey, newCfgJSON); err != nil { - return errors.Wrapf(err, "error updating container %s config JSON", ctr.ID()) + return fmt.Errorf("error updating container %s config JSON: %w", ctr.ID(), err) } return nil @@ -1929,15 +1929,15 @@ func (s *BoltState) SafeRewriteContainerConfig(ctr *Container, oldName, newName } if newName != "" && newCfg.Name != newName { - return errors.Wrapf(define.ErrInvalidArg, "new name %s for container %s must match name in given container config", newName, ctr.ID()) + return fmt.Errorf("new name %s for container %s must match name in given container config: %w", newName, ctr.ID(), define.ErrInvalidArg) } if newName != "" && oldName == "" { - return errors.Wrapf(define.ErrInvalidArg, "must provide old name for container if a new name is given") + return fmt.Errorf("must provide old name for container if a new name is given: %w", define.ErrInvalidArg) } newCfgJSON, err := json.Marshal(newCfg) if err != nil { - return errors.Wrapf(err, "error marshalling new configuration JSON for container %s", ctr.ID()) + return fmt.Errorf("error marshalling new configuration JSON for container %s: %w", ctr.ID(), err) } db, err := s.getDBCon() @@ -1969,7 +1969,7 @@ func (s *BoltState) SafeRewriteContainerConfig(ctr *Container, oldName, newName // rename. needsRename = false } else { - return errors.Wrapf(define.ErrCtrExists, "name %s already in use, cannot rename container %s", newName, ctr.ID()) + return fmt.Errorf("name %s already in use, cannot rename container %s: %w", newName, ctr.ID(), define.ErrCtrExists) } } @@ -1978,16 +1978,16 @@ func (s *BoltState) SafeRewriteContainerConfig(ctr *Container, oldName, newName // buckets are ID-indexed so we just need to // overwrite the values there. if err := namesBkt.Delete([]byte(oldName)); err != nil { - return errors.Wrapf(err, "error deleting container %s old name from DB for rename", ctr.ID()) + return fmt.Errorf("error deleting container %s old name from DB for rename: %w", ctr.ID(), err) } if err := idBkt.Put([]byte(ctr.ID()), []byte(newName)); err != nil { - return errors.Wrapf(err, "error renaming container %s in ID bucket in DB", ctr.ID()) + return fmt.Errorf("error renaming container %s in ID bucket in DB: %w", ctr.ID(), err) } if err := namesBkt.Put([]byte(newName), []byte(ctr.ID())); err != nil { - return errors.Wrapf(err, "error adding new name %s for container %s in DB", newName, ctr.ID()) + return fmt.Errorf("error adding new name %s for container %s in DB: %w", newName, ctr.ID(), err) } if err := allCtrsBkt.Put([]byte(ctr.ID()), []byte(newName)); err != nil { - return errors.Wrapf(err, "error renaming container %s in all containers bucket in DB", ctr.ID()) + return fmt.Errorf("error renaming container %s in all containers bucket in DB: %w", ctr.ID(), err) } if ctr.config.Pod != "" { podsBkt, err := getPodBucket(tx) @@ -1996,14 +1996,14 @@ func (s *BoltState) SafeRewriteContainerConfig(ctr *Container, oldName, newName } podBkt := podsBkt.Bucket([]byte(ctr.config.Pod)) if podBkt == nil { - return errors.Wrapf(define.ErrInternal, "bucket for pod %s does not exist", ctr.config.Pod) + return fmt.Errorf("bucket for pod %s does not exist: %w", ctr.config.Pod, define.ErrInternal) } podCtrBkt := podBkt.Bucket(containersBkt) if podCtrBkt == nil { - return errors.Wrapf(define.ErrInternal, "pod %s does not have a containers bucket", ctr.config.Pod) + return fmt.Errorf("pod %s does not have a containers bucket: %w", ctr.config.Pod, define.ErrInternal) } if err := podCtrBkt.Put([]byte(ctr.ID()), []byte(newName)); err != nil { - return errors.Wrapf(err, "error renaming container %s in pod %s members bucket", ctr.ID(), ctr.config.Pod) + return fmt.Errorf("error renaming container %s in pod %s members bucket: %w", ctr.ID(), ctr.config.Pod, err) } } } @@ -2017,11 +2017,11 @@ func (s *BoltState) SafeRewriteContainerConfig(ctr *Container, oldName, newName ctrDB := ctrBkt.Bucket([]byte(ctr.ID())) if ctrDB == nil { ctr.valid = false - return errors.Wrapf(define.ErrNoSuchCtr, "no container with ID %q found in DB", ctr.ID()) + return fmt.Errorf("no container with ID %q found in DB: %w", ctr.ID(), define.ErrNoSuchCtr) } if err := ctrDB.Put(configKey, newCfgJSON); err != nil { - return errors.Wrapf(err, "error updating container %s config JSON", ctr.ID()) + return fmt.Errorf("error updating container %s config JSON: %w", ctr.ID(), err) } return nil @@ -2043,7 +2043,7 @@ func (s *BoltState) RewritePodConfig(pod *Pod, newCfg *PodConfig) error { newCfgJSON, err := json.Marshal(newCfg) if err != nil { - return errors.Wrapf(err, "error marshalling new configuration JSON for pod %s", pod.ID()) + return fmt.Errorf("error marshalling new configuration JSON for pod %s: %w", pod.ID(), err) } db, err := s.getDBCon() @@ -2061,11 +2061,11 @@ func (s *BoltState) RewritePodConfig(pod *Pod, newCfg *PodConfig) error { podDB := podBkt.Bucket([]byte(pod.ID())) if podDB == nil { pod.valid = false - return errors.Wrapf(define.ErrNoSuchPod, "no pod with ID %s found in DB", pod.ID()) + return fmt.Errorf("no pod with ID %s found in DB: %w", pod.ID(), define.ErrNoSuchPod) } if err := podDB.Put(configKey, newCfgJSON); err != nil { - return errors.Wrapf(err, "error updating pod %s config JSON", pod.ID()) + return fmt.Errorf("error updating pod %s config JSON: %w", pod.ID(), err) } return nil @@ -2087,7 +2087,7 @@ func (s *BoltState) RewriteVolumeConfig(volume *Volume, newCfg *VolumeConfig) er newCfgJSON, err := json.Marshal(newCfg) if err != nil { - return errors.Wrapf(err, "error marshalling new configuration JSON for volume %q", volume.Name()) + return fmt.Errorf("error marshalling new configuration JSON for volume %q: %w", volume.Name(), err) } db, err := s.getDBCon() @@ -2105,11 +2105,11 @@ func (s *BoltState) RewriteVolumeConfig(volume *Volume, newCfg *VolumeConfig) er volDB := volBkt.Bucket([]byte(volume.Name())) if volDB == nil { volume.valid = false - return errors.Wrapf(define.ErrNoSuchVolume, "no volume with name %q found in DB", volume.Name()) + return fmt.Errorf("no volume with name %q found in DB: %w", volume.Name(), define.ErrNoSuchVolume) } if err := volDB.Put(configKey, newCfgJSON); err != nil { - return errors.Wrapf(err, "error updating volume %q config JSON", volume.Name()) + return fmt.Errorf("error updating volume %q config JSON: %w", volume.Name(), err) } return nil @@ -2233,7 +2233,7 @@ func (s *BoltState) LookupPod(idOrName string) (*Pod, error) { } if strings.HasPrefix(string(checkID), idOrName) { if exists { - return errors.Wrapf(define.ErrPodExists, "more than one result for ID or name %s", idOrName) + return fmt.Errorf("more than one result for ID or name %s: %w", idOrName, define.ErrPodExists) } id = checkID exists = true @@ -2245,9 +2245,9 @@ func (s *BoltState) LookupPod(idOrName string) (*Pod, error) { return err } else if !exists { if isCtr { - return errors.Wrapf(define.ErrNoSuchPod, "%s is a container, not a pod", idOrName) + return fmt.Errorf("%s is a container, not a pod: %w", idOrName, define.ErrNoSuchPod) } - return errors.Wrapf(define.ErrNoSuchPod, "no pod with name or ID %s found", idOrName) + return fmt.Errorf("no pod with name or ID %s found: %w", idOrName, define.ErrNoSuchPod) } // We might have found a container ID, but it's OK @@ -2323,7 +2323,7 @@ func (s *BoltState) PodHasContainer(pod *Pod, id string) (bool, error) { } if s.namespace != "" && s.namespace != pod.config.Namespace { - return false, errors.Wrapf(define.ErrNSMismatch, "pod %s is in namespace %q but we are in namespace %q", pod.ID(), pod.config.Namespace, s.namespace) + return false, fmt.Errorf("pod %s is in namespace %q but we are in namespace %q: %w", pod.ID(), pod.config.Namespace, s.namespace, define.ErrNSMismatch) } ctrID := []byte(id) @@ -2347,13 +2347,13 @@ func (s *BoltState) PodHasContainer(pod *Pod, id string) (bool, error) { podDB := podBkt.Bucket(podID) if podDB == nil { pod.valid = false - return errors.Wrapf(define.ErrNoSuchPod, "pod %s not found in database", pod.ID()) + return fmt.Errorf("pod %s not found in database: %w", pod.ID(), define.ErrNoSuchPod) } // Get pod containers bucket podCtrs := podDB.Bucket(containersBkt) if podCtrs == nil { - return errors.Wrapf(define.ErrInternal, "pod %s missing containers bucket in DB", pod.ID()) + return fmt.Errorf("pod %s missing containers bucket in DB: %w", pod.ID(), define.ErrInternal) } // Don't bother with a namespace check on the container - @@ -2386,7 +2386,7 @@ func (s *BoltState) PodContainersByID(pod *Pod) ([]string, error) { } if s.namespace != "" && s.namespace != pod.config.Namespace { - return nil, errors.Wrapf(define.ErrNSMismatch, "pod %s is in namespace %q but we are in namespace %q", pod.ID(), pod.config.Namespace, s.namespace) + return nil, fmt.Errorf("pod %s is in namespace %q but we are in namespace %q: %w", pod.ID(), pod.config.Namespace, s.namespace, define.ErrNSMismatch) } podID := []byte(pod.ID()) @@ -2409,13 +2409,13 @@ func (s *BoltState) PodContainersByID(pod *Pod) ([]string, error) { podDB := podBkt.Bucket(podID) if podDB == nil { pod.valid = false - return errors.Wrapf(define.ErrNoSuchPod, "pod %s not found in database", pod.ID()) + return fmt.Errorf("pod %s not found in database: %w", pod.ID(), define.ErrNoSuchPod) } // Get pod containers bucket podCtrs := podDB.Bucket(containersBkt) if podCtrs == nil { - return errors.Wrapf(define.ErrInternal, "pod %s missing containers bucket in DB", pod.ID()) + return fmt.Errorf("pod %s missing containers bucket in DB: %w", pod.ID(), define.ErrInternal) } // Iterate through all containers in the pod @@ -2448,7 +2448,7 @@ func (s *BoltState) PodContainers(pod *Pod) ([]*Container, error) { } if s.namespace != "" && s.namespace != pod.config.Namespace { - return nil, errors.Wrapf(define.ErrNSMismatch, "pod %s is in namespace %q but we are in namespace %q", pod.ID(), pod.config.Namespace, s.namespace) + return nil, fmt.Errorf("pod %s is in namespace %q but we are in namespace %q: %w", pod.ID(), pod.config.Namespace, s.namespace, define.ErrNSMismatch) } podID := []byte(pod.ID()) @@ -2476,13 +2476,13 @@ func (s *BoltState) PodContainers(pod *Pod) ([]*Container, error) { podDB := podBkt.Bucket(podID) if podDB == nil { pod.valid = false - return errors.Wrapf(define.ErrNoSuchPod, "pod %s not found in database", pod.ID()) + return fmt.Errorf("pod %s not found in database: %w", pod.ID(), define.ErrNoSuchPod) } // Get pod containers bucket podCtrs := podDB.Bucket(containersBkt) if podCtrs == nil { - return errors.Wrapf(define.ErrInternal, "pod %s missing containers bucket in DB", pod.ID()) + return fmt.Errorf("pod %s missing containers bucket in DB: %w", pod.ID(), define.ErrInternal) } // Iterate through all containers in the pod @@ -2522,7 +2522,7 @@ func (s *BoltState) AddVolume(volume *Volume) error { volConfigJSON, err := json.Marshal(volume.config) if err != nil { - return errors.Wrapf(err, "error marshalling volume %s config to JSON", volume.Name()) + return fmt.Errorf("error marshalling volume %s config to JSON: %w", volume.Name(), err) } // Volume state is allowed to not exist @@ -2530,7 +2530,7 @@ func (s *BoltState) AddVolume(volume *Volume) error { if volume.state != nil { volStateJSON, err = json.Marshal(volume.state) if err != nil { - return errors.Wrapf(err, "error marshalling volume %s state to JSON", volume.Name()) + return fmt.Errorf("error marshalling volume %s state to JSON: %w", volume.Name(), err) } } @@ -2554,34 +2554,34 @@ func (s *BoltState) AddVolume(volume *Volume) error { // Check if we already have a volume with the given name volExists := allVolsBkt.Get(volName) if volExists != nil { - return errors.Wrapf(define.ErrVolumeExists, "name %s is in use", volume.Name()) + return fmt.Errorf("name %s is in use: %w", volume.Name(), define.ErrVolumeExists) } // We are good to add the volume // Make a bucket for it newVol, err := volBkt.CreateBucket(volName) if err != nil { - return errors.Wrapf(err, "error creating bucket for volume %s", volume.Name()) + return fmt.Errorf("error creating bucket for volume %s: %w", volume.Name(), err) } // Make a subbucket for the containers using the volume. Dependent container IDs will be addedremoved to // this bucket in addcontainer/removeContainer if _, err := newVol.CreateBucket(volDependenciesBkt); err != nil { - return errors.Wrapf(err, "error creating bucket for containers using volume %s", volume.Name()) + return fmt.Errorf("error creating bucket for containers using volume %s: %w", volume.Name(), err) } if err := newVol.Put(configKey, volConfigJSON); err != nil { - return errors.Wrapf(err, "error storing volume %s configuration in DB", volume.Name()) + return fmt.Errorf("error storing volume %s configuration in DB: %w", volume.Name(), err) } if volStateJSON != nil { if err := newVol.Put(stateKey, volStateJSON); err != nil { - return errors.Wrapf(err, "error storing volume %s state in DB", volume.Name()) + return fmt.Errorf("error storing volume %s state in DB: %w", volume.Name(), err) } } if err := allVolsBkt.Put(volName, volName); err != nil { - return errors.Wrapf(err, "error storing volume %s in all volumes bucket in DB", volume.Name()) + return fmt.Errorf("error storing volume %s in all volumes bucket in DB: %w", volume.Name(), err) } return nil @@ -2623,7 +2623,7 @@ func (s *BoltState) RemoveVolume(volume *Volume) error { volDB := volBkt.Bucket(volName) if volDB == nil { volume.valid = false - return errors.Wrapf(define.ErrNoSuchVolume, "volume %s does not exist in DB", volume.Name()) + return fmt.Errorf("volume %s does not exist in DB: %w", volume.Name(), define.ErrNoSuchVolume) } // Check if volume is not being used by any container @@ -2650,20 +2650,20 @@ func (s *BoltState) RemoveVolume(volume *Volume) error { return nil }) if err != nil { - return errors.Wrapf(err, "error getting list of dependencies from dependencies bucket for volumes %q", volume.Name()) + return fmt.Errorf("error getting list of dependencies from dependencies bucket for volumes %q: %w", volume.Name(), err) } if len(deps) > 0 { - return errors.Wrapf(define.ErrVolumeBeingUsed, "volume %s is being used by container(s) %s", volume.Name(), strings.Join(deps, ",")) + return fmt.Errorf("volume %s is being used by container(s) %s: %w", volume.Name(), strings.Join(deps, ","), define.ErrVolumeBeingUsed) } } // volume is ready for removal // Let's kick it out if err := allVolsBkt.Delete(volName); err != nil { - return errors.Wrapf(err, "error removing volume %s from all volumes bucket in DB", volume.Name()) + return fmt.Errorf("error removing volume %s from all volumes bucket in DB: %w", volume.Name(), err) } if err := volBkt.DeleteBucket(volName); err != nil { - return errors.Wrapf(err, "error removing volume %s from DB", volume.Name()) + return fmt.Errorf("error removing volume %s from DB: %w", volume.Name(), err) } return nil @@ -2699,7 +2699,7 @@ func (s *BoltState) UpdateVolume(volume *Volume) error { volToUpdate := volBucket.Bucket(volumeName) if volToUpdate == nil { volume.valid = false - return errors.Wrapf(define.ErrNoSuchVolume, "no volume with name %s found in database", volume.Name()) + return fmt.Errorf("no volume with name %s found in database: %w", volume.Name(), define.ErrNoSuchVolume) } stateBytes := volToUpdate.Get(stateKey) @@ -2710,7 +2710,7 @@ func (s *BoltState) UpdateVolume(volume *Volume) error { } if err := json.Unmarshal(stateBytes, newState); err != nil { - return errors.Wrapf(err, "error unmarshalling volume %s state", volume.Name()) + return fmt.Errorf("error unmarshalling volume %s state: %w", volume.Name(), err) } return nil @@ -2740,7 +2740,7 @@ func (s *BoltState) SaveVolume(volume *Volume) error { if volume.state != nil { stateJSON, err := json.Marshal(volume.state) if err != nil { - return errors.Wrapf(err, "error marshalling volume %s state to JSON", volume.Name()) + return fmt.Errorf("error marshalling volume %s state to JSON: %w", volume.Name(), err) } newStateJSON = stateJSON } @@ -2760,7 +2760,7 @@ func (s *BoltState) SaveVolume(volume *Volume) error { volToUpdate := volBucket.Bucket(volumeName) if volToUpdate == nil { volume.valid = false - return errors.Wrapf(define.ErrNoSuchVolume, "no volume with name %s found in database", volume.Name()) + return fmt.Errorf("no volume with name %s found in database: %w", volume.Name(), define.ErrNoSuchVolume) } return volToUpdate.Put(stateKey, newStateJSON) @@ -2797,7 +2797,7 @@ func (s *BoltState) AllVolumes() ([]*Volume, error) { // This check can be removed if performance becomes an // issue, but much less helpful errors will be produced if volExists == nil { - return errors.Wrapf(define.ErrInternal, "inconsistency in state - volume %s is in all volumes bucket but volume not found", string(id)) + return fmt.Errorf("inconsistency in state - volume %s is in all volumes bucket but volume not found: %w", string(id), define.ErrInternal) } volume := new(Volume) @@ -2805,7 +2805,7 @@ func (s *BoltState) AllVolumes() ([]*Volume, error) { volume.state = new(VolumeState) if err := s.getVolumeFromDB(id, volume, volBucket); err != nil { - if errors.Cause(err) != define.ErrNSMismatch { + if !errors.Is(err, define.ErrNSMismatch) { logrus.Errorf("Retrieving volume %s from the database: %v", string(id), err) } } else { @@ -2904,7 +2904,7 @@ func (s *BoltState) LookupVolume(name string) (*Volume, error) { err = allVolsBkt.ForEach(func(checkName, checkName2 []byte) error { if strings.HasPrefix(string(checkName), name) { if foundMatch { - return errors.Wrapf(define.ErrVolumeExists, "more than one result for volume name %q", name) + return fmt.Errorf("more than one result for volume name %q: %w", name, define.ErrVolumeExists) } foundMatch = true volName = checkName @@ -2916,7 +2916,7 @@ func (s *BoltState) LookupVolume(name string) (*Volume, error) { } if !foundMatch { - return errors.Wrapf(define.ErrNoSuchVolume, "no volume with name %q found", name) + return fmt.Errorf("no volume with name %q found: %w", name, define.ErrNoSuchVolume) } return s.getVolumeFromDB(volName, volume, volBkt) @@ -3002,12 +3002,12 @@ func (s *BoltState) VolumeInUse(volume *Volume) ([]string, error) { volDB := volBucket.Bucket([]byte(volume.Name())) if volDB == nil { volume.valid = false - return errors.Wrapf(define.ErrNoSuchVolume, "no volume with name %s found in DB", volume.Name()) + return fmt.Errorf("no volume with name %s found in DB: %w", volume.Name(), define.ErrNoSuchVolume) } dependsBkt := volDB.Bucket(volDependenciesBkt) if dependsBkt == nil { - return errors.Wrapf(define.ErrInternal, "volume %s has no dependencies bucket", volume.Name()) + return fmt.Errorf("volume %s has no dependencies bucket: %w", volume.Name(), define.ErrInternal) } // Iterate through and add dependencies @@ -3047,7 +3047,7 @@ func (s *BoltState) AddPod(pod *Pod) error { } if s.namespace != "" && s.namespace != pod.config.Namespace { - return errors.Wrapf(define.ErrNSMismatch, "pod %s is in namespace %q but we are in namespace %q", pod.ID(), pod.config.Namespace, s.namespace) + return fmt.Errorf("pod %s is in namespace %q but we are in namespace %q: %w", pod.ID(), pod.config.Namespace, s.namespace, define.ErrNSMismatch) } podID := []byte(pod.ID()) @@ -3060,12 +3060,12 @@ func (s *BoltState) AddPod(pod *Pod) error { podConfigJSON, err := json.Marshal(pod.config) if err != nil { - return errors.Wrapf(err, "error marshalling pod %s config to JSON", pod.ID()) + return fmt.Errorf("error marshalling pod %s config to JSON: %w", pod.ID(), err) } podStateJSON, err := json.Marshal(pod.state) if err != nil { - return errors.Wrapf(err, "error marshalling pod %s state to JSON", pod.ID()) + return fmt.Errorf("error marshalling pod %s state to JSON: %w", pod.ID(), err) } db, err := s.getDBCon() @@ -3107,7 +3107,7 @@ func (s *BoltState) AddPod(pod *Pod) error { if allPodsBkt.Get(idExist) == nil { err = define.ErrCtrExists } - return errors.Wrapf(err, "ID \"%s\" is in use", pod.ID()) + return fmt.Errorf("ID \"%s\" is in use: %w", pod.ID(), err) } nameExist := namesBkt.Get(podName) if nameExist != nil { @@ -3115,47 +3115,47 @@ func (s *BoltState) AddPod(pod *Pod) error { if allPodsBkt.Get(nameExist) == nil { err = define.ErrCtrExists } - return errors.Wrapf(err, "name \"%s\" is in use", pod.Name()) + return fmt.Errorf("name \"%s\" is in use: %w", pod.Name(), err) } // We are good to add the pod // Make a bucket for it newPod, err := podBkt.CreateBucket(podID) if err != nil { - return errors.Wrapf(err, "error creating bucket for pod %s", pod.ID()) + return fmt.Errorf("error creating bucket for pod %s: %w", pod.ID(), err) } // Make a subbucket for pod containers if _, err := newPod.CreateBucket(containersBkt); err != nil { - return errors.Wrapf(err, "error creating bucket for pod %s containers", pod.ID()) + return fmt.Errorf("error creating bucket for pod %s containers: %w", pod.ID(), err) } if err := newPod.Put(configKey, podConfigJSON); err != nil { - return errors.Wrapf(err, "error storing pod %s configuration in DB", pod.ID()) + return fmt.Errorf("error storing pod %s configuration in DB: %w", pod.ID(), err) } if err := newPod.Put(stateKey, podStateJSON); err != nil { - return errors.Wrapf(err, "error storing pod %s state JSON in DB", pod.ID()) + return fmt.Errorf("error storing pod %s state JSON in DB: %w", pod.ID(), err) } if podNamespace != nil { if err := newPod.Put(namespaceKey, podNamespace); err != nil { - return errors.Wrapf(err, "error storing pod %s namespace in DB", pod.ID()) + return fmt.Errorf("error storing pod %s namespace in DB: %w", pod.ID(), err) } if err := nsBkt.Put(podID, podNamespace); err != nil { - return errors.Wrapf(err, "error storing pod %s namespace in DB", pod.ID()) + return fmt.Errorf("error storing pod %s namespace in DB: %w", pod.ID(), err) } } // Add us to the ID and names buckets if err := idsBkt.Put(podID, podName); err != nil { - return errors.Wrapf(err, "error storing pod %s ID in DB", pod.ID()) + return fmt.Errorf("error storing pod %s ID in DB: %w", pod.ID(), err) } if err := namesBkt.Put(podName, podID); err != nil { - return errors.Wrapf(err, "error storing pod %s name in DB", pod.Name()) + return fmt.Errorf("error storing pod %s name in DB: %w", pod.Name(), err) } if err := allPodsBkt.Put(podID, podName); err != nil { - return errors.Wrapf(err, "error storing pod %s in all pods bucket in DB", pod.ID()) + return fmt.Errorf("error storing pod %s in all pods bucket in DB: %w", pod.ID(), err) } return nil @@ -3179,7 +3179,7 @@ func (s *BoltState) RemovePod(pod *Pod) error { } if s.namespace != "" && s.namespace != pod.config.Namespace { - return errors.Wrapf(define.ErrNSMismatch, "pod %s is in namespace %q but we are in namespace %q", pod.ID(), pod.config.Namespace, s.namespace) + return fmt.Errorf("pod %s is in namespace %q but we are in namespace %q: %w", pod.ID(), pod.config.Namespace, s.namespace, define.ErrNSMismatch) } podID := []byte(pod.ID()) @@ -3221,7 +3221,7 @@ func (s *BoltState) RemovePod(pod *Pod) error { podDB := podBkt.Bucket(podID) if podDB == nil { pod.valid = false - return errors.Wrapf(define.ErrNoSuchPod, "pod %s does not exist in DB", pod.ID()) + return fmt.Errorf("pod %s does not exist in DB: %w", pod.ID(), define.ErrNoSuchPod) } // Check if pod is empty @@ -3233,26 +3233,26 @@ func (s *BoltState) RemovePod(pod *Pod) error { if podCtrsBkt != nil { cursor := podCtrsBkt.Cursor() if id, _ := cursor.First(); id != nil { - return errors.Wrapf(define.ErrCtrExists, "pod %s is not empty", pod.ID()) + return fmt.Errorf("pod %s is not empty: %w", pod.ID(), define.ErrCtrExists) } } // Pod is empty, and ready for removal // Let's kick it out if err := idsBkt.Delete(podID); err != nil { - return errors.Wrapf(err, "error removing pod %s ID from DB", pod.ID()) + return fmt.Errorf("error removing pod %s ID from DB: %w", pod.ID(), err) } if err := namesBkt.Delete(podName); err != nil { - return errors.Wrapf(err, "error removing pod %s name (%s) from DB", pod.ID(), pod.Name()) + return fmt.Errorf("error removing pod %s name (%s) from DB: %w", pod.ID(), pod.Name(), err) } if err := nsBkt.Delete(podID); err != nil { - return errors.Wrapf(err, "error removing pod %s namespace from DB", pod.ID()) + return fmt.Errorf("error removing pod %s namespace from DB: %w", pod.ID(), err) } if err := allPodsBkt.Delete(podID); err != nil { - return errors.Wrapf(err, "error removing pod %s ID from all pods bucket in DB", pod.ID()) + return fmt.Errorf("error removing pod %s ID from all pods bucket in DB: %w", pod.ID(), err) } if err := podBkt.DeleteBucket(podID); err != nil { - return errors.Wrapf(err, "error removing pod %s from DB", pod.ID()) + return fmt.Errorf("error removing pod %s from DB: %w", pod.ID(), err) } return nil @@ -3275,7 +3275,7 @@ func (s *BoltState) RemovePodContainers(pod *Pod) error { } if s.namespace != "" && s.namespace != pod.config.Namespace { - return errors.Wrapf(define.ErrNSMismatch, "pod %s is in namespace %q but we are in namespace %q", pod.ID(), pod.config.Namespace, s.namespace) + return fmt.Errorf("pod %s is in namespace %q but we are in namespace %q: %w", pod.ID(), pod.config.Namespace, s.namespace, define.ErrNSMismatch) } podID := []byte(pod.ID()) @@ -3316,12 +3316,12 @@ func (s *BoltState) RemovePodContainers(pod *Pod) error { podDB := podBkt.Bucket(podID) if podDB == nil { pod.valid = false - return errors.Wrapf(define.ErrNoSuchPod, "pod %s does not exist in DB", pod.ID()) + return fmt.Errorf("pod %s does not exist in DB: %w", pod.ID(), define.ErrNoSuchPod) } podCtrsBkt := podDB.Bucket(containersBkt) if podCtrsBkt == nil { - return errors.Wrapf(define.ErrInternal, "pod %s does not have a containers bucket", pod.ID()) + return fmt.Errorf("pod %s does not have a containers bucket: %w", pod.ID(), define.ErrInternal) } // Traverse all containers in the pod with a cursor @@ -3332,7 +3332,7 @@ func (s *BoltState) RemovePodContainers(pod *Pod) error { if ctr == nil { // This should never happen // State is inconsistent - return errors.Wrapf(define.ErrNoSuchCtr, "pod %s referenced nonexistent container %s", pod.ID(), string(id)) + return fmt.Errorf("pod %s referenced nonexistent container %s: %w", pod.ID(), string(id), define.ErrNoSuchCtr) } ctrDeps := ctr.Bucket(dependenciesBkt) // This should never be nil, but if it is, we're @@ -3341,7 +3341,7 @@ func (s *BoltState) RemovePodContainers(pod *Pod) error { err = ctrDeps.ForEach(func(depID, name []byte) error { exists := podCtrsBkt.Get(depID) if exists == nil { - return errors.Wrapf(define.ErrCtrExists, "container %s has dependency %s outside of pod %s", string(id), string(depID), pod.ID()) + return fmt.Errorf("container %s has dependency %s outside of pod %s: %w", string(id), string(depID), pod.ID(), define.ErrCtrExists) } return nil }) @@ -3353,19 +3353,19 @@ func (s *BoltState) RemovePodContainers(pod *Pod) error { // Dependencies are set, we're clear to remove if err := ctrBkt.DeleteBucket(id); err != nil { - return errors.Wrapf(define.ErrInternal, "error deleting container %s from DB", string(id)) + return fmt.Errorf("error deleting container %s from DB: %w", string(id), define.ErrInternal) } if err := idsBkt.Delete(id); err != nil { - return errors.Wrapf(err, "error deleting container %s ID in DB", string(id)) + return fmt.Errorf("error deleting container %s ID in DB: %w", string(id), err) } if err := namesBkt.Delete(name); err != nil { - return errors.Wrapf(err, "error deleting container %s name in DB", string(id)) + return fmt.Errorf("error deleting container %s name in DB: %w", string(id), err) } if err := allCtrsBkt.Delete(id); err != nil { - return errors.Wrapf(err, "error deleting container %s ID from all containers bucket in DB", string(id)) + return fmt.Errorf("error deleting container %s ID from all containers bucket in DB: %w", string(id), err) } return nil @@ -3376,10 +3376,10 @@ func (s *BoltState) RemovePodContainers(pod *Pod) error { // Delete and recreate the bucket to empty it if err := podDB.DeleteBucket(containersBkt); err != nil { - return errors.Wrapf(err, "error removing pod %s containers bucket", pod.ID()) + return fmt.Errorf("error removing pod %s containers bucket: %w", pod.ID(), err) } if _, err := podDB.CreateBucket(containersBkt); err != nil { - return errors.Wrapf(err, "error recreating pod %s containers bucket", pod.ID()) + return fmt.Errorf("error recreating pod %s containers bucket: %w", pod.ID(), err) } return nil @@ -3407,7 +3407,7 @@ func (s *BoltState) AddContainerToPod(pod *Pod, ctr *Container) error { } if ctr.config.Pod != pod.ID() { - return errors.Wrapf(define.ErrNoSuchCtr, "container %s is not part of pod %s", ctr.ID(), pod.ID()) + return fmt.Errorf("container %s is not part of pod %s: %w", ctr.ID(), pod.ID(), define.ErrNoSuchCtr) } return s.addContainer(ctr, pod) @@ -3426,19 +3426,19 @@ func (s *BoltState) RemoveContainerFromPod(pod *Pod, ctr *Container) error { if s.namespace != "" { if s.namespace != pod.config.Namespace { - return errors.Wrapf(define.ErrNSMismatch, "pod %s is in namespace %q but we are in namespace %q", pod.ID(), pod.config.Namespace, s.namespace) + return fmt.Errorf("pod %s is in namespace %q but we are in namespace %q: %w", pod.ID(), pod.config.Namespace, s.namespace, define.ErrNSMismatch) } if s.namespace != ctr.config.Namespace { - return errors.Wrapf(define.ErrNSMismatch, "container %s in in namespace %q but we are in namespace %q", ctr.ID(), ctr.config.Namespace, s.namespace) + return fmt.Errorf("container %s in in namespace %q but we are in namespace %q: %w", ctr.ID(), ctr.config.Namespace, s.namespace, define.ErrNSMismatch) } } if ctr.config.Pod == "" { - return errors.Wrapf(define.ErrNoSuchPod, "container %s is not part of a pod, use RemoveContainer instead", ctr.ID()) + return fmt.Errorf("container %s is not part of a pod, use RemoveContainer instead: %w", ctr.ID(), define.ErrNoSuchPod) } if ctr.config.Pod != pod.ID() { - return errors.Wrapf(define.ErrInvalidArg, "container %s is not part of pod %s", ctr.ID(), pod.ID()) + return fmt.Errorf("container %s is not part of pod %s: %w", ctr.ID(), pod.ID(), define.ErrInvalidArg) } db, err := s.getDBCon() @@ -3464,7 +3464,7 @@ func (s *BoltState) UpdatePod(pod *Pod) error { } if s.namespace != "" && s.namespace != pod.config.Namespace { - return errors.Wrapf(define.ErrNSMismatch, "pod %s is in namespace %q but we are in namespace %q", pod.ID(), pod.config.Namespace, s.namespace) + return fmt.Errorf("pod %s is in namespace %q but we are in namespace %q: %w", pod.ID(), pod.config.Namespace, s.namespace, define.ErrNSMismatch) } newState := new(podState) @@ -3486,17 +3486,17 @@ func (s *BoltState) UpdatePod(pod *Pod) error { podDB := podBkt.Bucket(podID) if podDB == nil { pod.valid = false - return errors.Wrapf(define.ErrNoSuchPod, "no pod with ID %s found in database", pod.ID()) + return fmt.Errorf("no pod with ID %s found in database: %w", pod.ID(), define.ErrNoSuchPod) } // Get the pod state JSON podStateBytes := podDB.Get(stateKey) if podStateBytes == nil { - return errors.Wrapf(define.ErrInternal, "pod %s is missing state key in DB", pod.ID()) + return fmt.Errorf("pod %s is missing state key in DB: %w", pod.ID(), define.ErrInternal) } if err := json.Unmarshal(podStateBytes, newState); err != nil { - return errors.Wrapf(err, "error unmarshalling pod %s state JSON", pod.ID()) + return fmt.Errorf("error unmarshalling pod %s state JSON: %w", pod.ID(), err) } return nil @@ -3521,12 +3521,12 @@ func (s *BoltState) SavePod(pod *Pod) error { } if s.namespace != "" && s.namespace != pod.config.Namespace { - return errors.Wrapf(define.ErrNSMismatch, "pod %s is in namespace %q but we are in namespace %q", pod.ID(), pod.config.Namespace, s.namespace) + return fmt.Errorf("pod %s is in namespace %q but we are in namespace %q: %w", pod.ID(), pod.config.Namespace, s.namespace, define.ErrNSMismatch) } stateJSON, err := json.Marshal(pod.state) if err != nil { - return errors.Wrapf(err, "error marshalling pod %s state to JSON", pod.ID()) + return fmt.Errorf("error marshalling pod %s state to JSON: %w", pod.ID(), err) } db, err := s.getDBCon() @@ -3546,12 +3546,12 @@ func (s *BoltState) SavePod(pod *Pod) error { podDB := podBkt.Bucket(podID) if podDB == nil { pod.valid = false - return errors.Wrapf(define.ErrNoSuchPod, "no pod with ID %s found in database", pod.ID()) + return fmt.Errorf("no pod with ID %s found in database: %w", pod.ID(), define.ErrNoSuchPod) } // Set the pod state JSON if err := podDB.Put(stateKey, stateJSON); err != nil { - return errors.Wrapf(err, "error updating pod %s state in database", pod.ID()) + return fmt.Errorf("error updating pod %s state in database: %w", pod.ID(), err) } return nil @@ -3593,7 +3593,7 @@ func (s *BoltState) AllPods() ([]*Pod, error) { // This check can be removed if performance becomes an // issue, but much less helpful errors will be produced if podExists == nil { - return errors.Wrapf(define.ErrInternal, "inconsistency in state - pod %s is in all pods bucket but pod not found", string(id)) + return fmt.Errorf("inconsistency in state - pod %s is in all pods bucket but pod not found: %w", string(id), define.ErrInternal) } pod := new(Pod) @@ -3601,7 +3601,7 @@ func (s *BoltState) AllPods() ([]*Pod, error) { pod.state = new(podState) if err := s.getPodFromDB(id, pod, podBucket); err != nil { - if errors.Cause(err) != define.ErrNSMismatch { + if !errors.Is(err, define.ErrNSMismatch) { logrus.Errorf("Retrieving pod %s from the database: %v", string(id), err) } } else { diff --git a/libpod/boltdb_state_internal.go b/libpod/boltdb_state_internal.go index 11b4aa049..f28fadfa9 100644 --- a/libpod/boltdb_state_internal.go +++ b/libpod/boltdb_state_internal.go @@ -2,6 +2,7 @@ package libpod import ( "bytes" + "fmt" "os" "path/filepath" "runtime" @@ -10,7 +11,6 @@ import ( "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/rootless" "github.com/containers/storage" - "github.com/pkg/errors" "github.com/sirupsen/logrus" bolt "go.etcd.io/bbolt" ) @@ -195,7 +195,7 @@ func checkRuntimeConfig(db *bolt.DB, rt *Runtime) error { } if err := configBkt.Put(missing.key, dbValue); err != nil { - return errors.Wrapf(err, "error updating %s in DB runtime config", missing.name) + return fmt.Errorf("error updating %s in DB runtime config: %w", missing.name, err) } } @@ -236,8 +236,8 @@ func readOnlyValidateConfig(bucket *bolt.Bucket, toCheck dbConfigValidation) (bo return true, nil } - return true, errors.Wrapf(define.ErrDBBadConfig, "database %s %q does not match our %s %q", - toCheck.name, dbValue, toCheck.name, toCheck.runtimeValue) + return true, fmt.Errorf("database %s %q does not match our %s %q: %w", + toCheck.name, dbValue, toCheck.name, toCheck.runtimeValue, define.ErrDBBadConfig) } return true, nil @@ -254,7 +254,7 @@ func (s *BoltState) getDBCon() (*bolt.DB, error) { db, err := bolt.Open(s.dbPath, 0600, nil) if err != nil { - return nil, errors.Wrapf(err, "error opening database %s", s.dbPath) + return nil, fmt.Errorf("error opening database %s: %w", s.dbPath, err) } return db, nil @@ -283,7 +283,7 @@ func (s *BoltState) closeDBCon(db *bolt.DB) error { func getIDBucket(tx *bolt.Tx) (*bolt.Bucket, error) { bkt := tx.Bucket(idRegistryBkt) if bkt == nil { - return nil, errors.Wrapf(define.ErrDBBadConfig, "id registry bucket not found in DB") + return nil, fmt.Errorf("id registry bucket not found in DB: %w", define.ErrDBBadConfig) } return bkt, nil } @@ -291,7 +291,7 @@ func getIDBucket(tx *bolt.Tx) (*bolt.Bucket, error) { func getNamesBucket(tx *bolt.Tx) (*bolt.Bucket, error) { bkt := tx.Bucket(nameRegistryBkt) if bkt == nil { - return nil, errors.Wrapf(define.ErrDBBadConfig, "name registry bucket not found in DB") + return nil, fmt.Errorf("name registry bucket not found in DB: %w", define.ErrDBBadConfig) } return bkt, nil } @@ -299,7 +299,7 @@ func getNamesBucket(tx *bolt.Tx) (*bolt.Bucket, error) { func getNSBucket(tx *bolt.Tx) (*bolt.Bucket, error) { bkt := tx.Bucket(nsRegistryBkt) if bkt == nil { - return nil, errors.Wrapf(define.ErrDBBadConfig, "namespace registry bucket not found in DB") + return nil, fmt.Errorf("namespace registry bucket not found in DB: %w", define.ErrDBBadConfig) } return bkt, nil } @@ -307,7 +307,7 @@ func getNSBucket(tx *bolt.Tx) (*bolt.Bucket, error) { func getCtrBucket(tx *bolt.Tx) (*bolt.Bucket, error) { bkt := tx.Bucket(ctrBkt) if bkt == nil { - return nil, errors.Wrapf(define.ErrDBBadConfig, "containers bucket not found in DB") + return nil, fmt.Errorf("containers bucket not found in DB: %w", define.ErrDBBadConfig) } return bkt, nil } @@ -315,7 +315,7 @@ func getCtrBucket(tx *bolt.Tx) (*bolt.Bucket, error) { func getAllCtrsBucket(tx *bolt.Tx) (*bolt.Bucket, error) { bkt := tx.Bucket(allCtrsBkt) if bkt == nil { - return nil, errors.Wrapf(define.ErrDBBadConfig, "all containers bucket not found in DB") + return nil, fmt.Errorf("all containers bucket not found in DB: %w", define.ErrDBBadConfig) } return bkt, nil } @@ -323,7 +323,7 @@ func getAllCtrsBucket(tx *bolt.Tx) (*bolt.Bucket, error) { func getPodBucket(tx *bolt.Tx) (*bolt.Bucket, error) { bkt := tx.Bucket(podBkt) if bkt == nil { - return nil, errors.Wrapf(define.ErrDBBadConfig, "pods bucket not found in DB") + return nil, fmt.Errorf("pods bucket not found in DB: %w", define.ErrDBBadConfig) } return bkt, nil } @@ -331,7 +331,7 @@ func getPodBucket(tx *bolt.Tx) (*bolt.Bucket, error) { func getAllPodsBucket(tx *bolt.Tx) (*bolt.Bucket, error) { bkt := tx.Bucket(allPodsBkt) if bkt == nil { - return nil, errors.Wrapf(define.ErrDBBadConfig, "all pods bucket not found in DB") + return nil, fmt.Errorf("all pods bucket not found in DB: %w", define.ErrDBBadConfig) } return bkt, nil } @@ -339,7 +339,7 @@ func getAllPodsBucket(tx *bolt.Tx) (*bolt.Bucket, error) { func getVolBucket(tx *bolt.Tx) (*bolt.Bucket, error) { bkt := tx.Bucket(volBkt) if bkt == nil { - return nil, errors.Wrapf(define.ErrDBBadConfig, "volumes bucket not found in DB") + return nil, fmt.Errorf("volumes bucket not found in DB: %w", define.ErrDBBadConfig) } return bkt, nil } @@ -347,7 +347,7 @@ func getVolBucket(tx *bolt.Tx) (*bolt.Bucket, error) { func getAllVolsBucket(tx *bolt.Tx) (*bolt.Bucket, error) { bkt := tx.Bucket(allVolsBkt) if bkt == nil { - return nil, errors.Wrapf(define.ErrDBBadConfig, "all volumes bucket not found in DB") + return nil, fmt.Errorf("all volumes bucket not found in DB: %w", define.ErrDBBadConfig) } return bkt, nil } @@ -355,7 +355,7 @@ func getAllVolsBucket(tx *bolt.Tx) (*bolt.Bucket, error) { func getExecBucket(tx *bolt.Tx) (*bolt.Bucket, error) { bkt := tx.Bucket(execBkt) if bkt == nil { - return nil, errors.Wrapf(define.ErrDBBadConfig, "exec bucket not found in DB") + return nil, fmt.Errorf("exec bucket not found in DB: %w", define.ErrDBBadConfig) } return bkt, nil } @@ -363,7 +363,7 @@ func getExecBucket(tx *bolt.Tx) (*bolt.Bucket, error) { func getRuntimeConfigBucket(tx *bolt.Tx) (*bolt.Bucket, error) { bkt := tx.Bucket(runtimeConfigBkt) if bkt == nil { - return nil, errors.Wrapf(define.ErrDBBadConfig, "runtime configuration bucket not found in DB") + return nil, fmt.Errorf("runtime configuration bucket not found in DB: %w", define.ErrDBBadConfig) } return bkt, nil } @@ -371,7 +371,7 @@ func getRuntimeConfigBucket(tx *bolt.Tx) (*bolt.Bucket, error) { func getExitCodeBucket(tx *bolt.Tx) (*bolt.Bucket, error) { bkt := tx.Bucket(exitCodeBkt) if bkt == nil { - return nil, errors.Wrapf(define.ErrDBBadConfig, "exit-code container bucket not found in DB") + return nil, fmt.Errorf("exit-code container bucket not found in DB: %w", define.ErrDBBadConfig) } return bkt, nil } @@ -379,7 +379,7 @@ func getExitCodeBucket(tx *bolt.Tx) (*bolt.Bucket, error) { func getExitCodeTimeStampBucket(tx *bolt.Tx) (*bolt.Bucket, error) { bkt := tx.Bucket(exitCodeTimeStampBkt) if bkt == nil { - return nil, errors.Wrapf(define.ErrDBBadConfig, "exit-code time stamp bucket not found in DB") + return nil, fmt.Errorf("exit-code time stamp bucket not found in DB: %w", define.ErrDBBadConfig) } return bkt, nil } @@ -387,23 +387,23 @@ func getExitCodeTimeStampBucket(tx *bolt.Tx) (*bolt.Bucket, error) { func (s *BoltState) getContainerConfigFromDB(id []byte, config *ContainerConfig, ctrsBkt *bolt.Bucket) error { ctrBkt := ctrsBkt.Bucket(id) if ctrBkt == nil { - return errors.Wrapf(define.ErrNoSuchCtr, "container %s not found in DB", string(id)) + return fmt.Errorf("container %s not found in DB: %w", string(id), define.ErrNoSuchCtr) } if s.namespaceBytes != nil { ctrNamespaceBytes := ctrBkt.Get(namespaceKey) if !bytes.Equal(s.namespaceBytes, ctrNamespaceBytes) { - return errors.Wrapf(define.ErrNSMismatch, "cannot retrieve container %s as it is part of namespace %q and we are in namespace %q", string(id), string(ctrNamespaceBytes), s.namespace) + return fmt.Errorf("cannot retrieve container %s as it is part of namespace %q and we are in namespace %q: %w", string(id), string(ctrNamespaceBytes), s.namespace, define.ErrNSMismatch) } } configBytes := ctrBkt.Get(configKey) if configBytes == nil { - return errors.Wrapf(define.ErrInternal, "container %s missing config key in DB", string(id)) + return fmt.Errorf("container %s missing config key in DB: %w", string(id), define.ErrInternal) } if err := json.Unmarshal(configBytes, config); err != nil { - return errors.Wrapf(err, "error unmarshalling container %s config", string(id)) + return fmt.Errorf("error unmarshalling container %s config: %w", string(id), err) } // convert ports to the new format if needed @@ -426,7 +426,7 @@ func (s *BoltState) getContainerFromDB(id []byte, ctr *Container, ctrsBkt *bolt. // Get the lock lock, err := s.runtime.lockManager.RetrieveLock(ctr.config.LockID) if err != nil { - return errors.Wrapf(err, "error retrieving lock for container %s", string(id)) + return fmt.Errorf("error retrieving lock for container %s: %w", string(id), err) } ctr.lock = lock @@ -473,29 +473,29 @@ func (s *BoltState) getContainerFromDB(id []byte, ctr *Container, ctrsBkt *bolt. func (s *BoltState) getPodFromDB(id []byte, pod *Pod, podBkt *bolt.Bucket) error { podDB := podBkt.Bucket(id) if podDB == nil { - return errors.Wrapf(define.ErrNoSuchPod, "pod with ID %s not found", string(id)) + return fmt.Errorf("pod with ID %s not found: %w", string(id), define.ErrNoSuchPod) } if s.namespaceBytes != nil { podNamespaceBytes := podDB.Get(namespaceKey) if !bytes.Equal(s.namespaceBytes, podNamespaceBytes) { - return errors.Wrapf(define.ErrNSMismatch, "cannot retrieve pod %s as it is part of namespace %q and we are in namespace %q", string(id), string(podNamespaceBytes), s.namespace) + return fmt.Errorf("cannot retrieve pod %s as it is part of namespace %q and we are in namespace %q: %w", string(id), string(podNamespaceBytes), s.namespace, define.ErrNSMismatch) } } podConfigBytes := podDB.Get(configKey) if podConfigBytes == nil { - return errors.Wrapf(define.ErrInternal, "pod %s is missing configuration key in DB", string(id)) + return fmt.Errorf("pod %s is missing configuration key in DB: %w", string(id), define.ErrInternal) } if err := json.Unmarshal(podConfigBytes, pod.config); err != nil { - return errors.Wrapf(err, "error unmarshalling pod %s config from DB", string(id)) + return fmt.Errorf("error unmarshalling pod %s config from DB: %w", string(id), err) } // Get the lock lock, err := s.runtime.lockManager.RetrieveLock(pod.config.LockID) if err != nil { - return errors.Wrapf(err, "error retrieving lock for pod %s", string(id)) + return fmt.Errorf("error retrieving lock for pod %s: %w", string(id), err) } pod.lock = lock @@ -508,23 +508,23 @@ func (s *BoltState) getPodFromDB(id []byte, pod *Pod, podBkt *bolt.Bucket) error func (s *BoltState) getVolumeFromDB(name []byte, volume *Volume, volBkt *bolt.Bucket) error { volDB := volBkt.Bucket(name) if volDB == nil { - return errors.Wrapf(define.ErrNoSuchVolume, "volume with name %s not found", string(name)) + return fmt.Errorf("volume with name %s not found: %w", string(name), define.ErrNoSuchVolume) } volConfigBytes := volDB.Get(configKey) if volConfigBytes == nil { - return errors.Wrapf(define.ErrInternal, "volume %s is missing configuration key in DB", string(name)) + return fmt.Errorf("volume %s is missing configuration key in DB: %w", string(name), define.ErrInternal) } if err := json.Unmarshal(volConfigBytes, volume.config); err != nil { - return errors.Wrapf(err, "error unmarshalling volume %s config from DB", string(name)) + return fmt.Errorf("error unmarshalling volume %s config from DB: %w", string(name), err) } // Volume state is allowed to be nil for legacy compatibility volStateBytes := volDB.Get(stateKey) if volStateBytes != nil { if err := json.Unmarshal(volStateBytes, volume.state); err != nil { - return errors.Wrapf(err, "error unmarshalling volume %s state from DB", string(name)) + return fmt.Errorf("error unmarshalling volume %s state from DB: %w", string(name), err) } } @@ -546,7 +546,7 @@ func (s *BoltState) getVolumeFromDB(name []byte, volume *Volume, volBkt *bolt.Bu // Get the lock lock, err := s.runtime.lockManager.RetrieveLock(volume.config.LockID) if err != nil { - return errors.Wrapf(err, "error retrieving lock for volume %q", string(name)) + return fmt.Errorf("error retrieving lock for volume %q: %w", string(name), err) } volume.lock = lock @@ -560,8 +560,8 @@ func (s *BoltState) getVolumeFromDB(name []byte, volume *Volume, volBkt *bolt.Bu // If pod is not nil, the container is added to the pod as well func (s *BoltState) addContainer(ctr *Container, pod *Pod) error { if s.namespace != "" && s.namespace != ctr.config.Namespace { - return errors.Wrapf(define.ErrNSMismatch, "cannot add container %s as it is in namespace %q and we are in namespace %q", - ctr.ID(), s.namespace, ctr.config.Namespace) + return fmt.Errorf("cannot add container %s as it is in namespace %q and we are in namespace %q: %w", + ctr.ID(), s.namespace, ctr.config.Namespace, define.ErrNSMismatch) } // Set the original networks to nil. We can save some space by not storing it in the config @@ -572,11 +572,11 @@ func (s *BoltState) addContainer(ctr *Container, pod *Pod) error { // JSON container structs to insert into DB configJSON, err := json.Marshal(ctr.config) if err != nil { - return errors.Wrapf(err, "error marshalling container %s config to JSON", ctr.ID()) + return fmt.Errorf("error marshalling container %s config to JSON: %w", ctr.ID(), err) } stateJSON, err := json.Marshal(ctr.state) if err != nil { - return errors.Wrapf(err, "error marshalling container %s state to JSON", ctr.ID()) + return fmt.Errorf("error marshalling container %s state to JSON: %w", ctr.ID(), err) } netNSPath := getNetNSPath(ctr) dependsCtrs := ctr.Dependencies() @@ -594,16 +594,16 @@ func (s *BoltState) addContainer(ctr *Container, pod *Pod) error { for net, opts := range configNetworks { // Check that we don't have any empty network names if net == "" { - return errors.Wrapf(define.ErrInvalidArg, "network names cannot be an empty string") + return fmt.Errorf("network names cannot be an empty string: %w", define.ErrInvalidArg) } if opts.InterfaceName == "" { - return errors.Wrapf(define.ErrInvalidArg, "network interface name cannot be an empty string") + return fmt.Errorf("network interface name cannot be an empty string: %w", define.ErrInvalidArg) } // always add the short id as alias for docker compat opts.Aliases = append(opts.Aliases, ctr.config.ID[:12]) optBytes, err := json.Marshal(opts) if err != nil { - return errors.Wrapf(err, "error marshalling network options JSON for container %s", ctr.ID()) + return fmt.Errorf("error marshalling network options JSON for container %s: %w", ctr.ID(), err) } networks[net] = optBytes } @@ -659,17 +659,17 @@ func (s *BoltState) addContainer(ctr *Container, pod *Pod) error { podDB = podBucket.Bucket(podID) if podDB == nil { pod.valid = false - return errors.Wrapf(define.ErrNoSuchPod, "pod %s does not exist in database", pod.ID()) + return fmt.Errorf("pod %s does not exist in database: %w", pod.ID(), define.ErrNoSuchPod) } podCtrs = podDB.Bucket(containersBkt) if podCtrs == nil { - return errors.Wrapf(define.ErrInternal, "pod %s does not have a containers bucket", pod.ID()) + return fmt.Errorf("pod %s does not have a containers bucket: %w", pod.ID(), define.ErrInternal) } podNS := podDB.Get(namespaceKey) if !bytes.Equal(podNS, ctrNamespace) { - return errors.Wrapf(define.ErrNSMismatch, "container %s is in namespace %s and pod %s is in namespace %s", - ctr.ID(), ctr.config.Namespace, pod.ID(), pod.config.Namespace) + return fmt.Errorf("container %s is in namespace %s and pod %s is in namespace %s: %w", + ctr.ID(), ctr.config.Namespace, pod.ID(), pod.config.Namespace, define.ErrNSMismatch) } } @@ -680,7 +680,7 @@ func (s *BoltState) addContainer(ctr *Container, pod *Pod) error { if allCtrsBucket.Get(idExist) == nil { err = define.ErrPodExists } - return errors.Wrapf(err, "ID \"%s\" is in use", ctr.ID()) + return fmt.Errorf("ID \"%s\" is in use: %w", ctr.ID(), err) } nameExist := namesBucket.Get(ctrName) if nameExist != nil { @@ -688,66 +688,66 @@ func (s *BoltState) addContainer(ctr *Container, pod *Pod) error { if allCtrsBucket.Get(nameExist) == nil { err = define.ErrPodExists } - return errors.Wrapf(err, "name \"%s\" is in use", ctr.Name()) + return fmt.Errorf("name \"%s\" is in use: %w", ctr.Name(), err) } // No overlapping containers // Add the new container to the DB if err := idsBucket.Put(ctrID, ctrName); err != nil { - return errors.Wrapf(err, "error adding container %s ID to DB", ctr.ID()) + return fmt.Errorf("error adding container %s ID to DB: %w", ctr.ID(), err) } if err := namesBucket.Put(ctrName, ctrID); err != nil { - return errors.Wrapf(err, "error adding container %s name (%s) to DB", ctr.ID(), ctr.Name()) + return fmt.Errorf("error adding container %s name (%s) to DB: %w", ctr.ID(), ctr.Name(), err) } if ctrNamespace != nil { if err := nsBucket.Put(ctrID, ctrNamespace); err != nil { - return errors.Wrapf(err, "error adding container %s namespace (%q) to DB", ctr.ID(), ctr.Namespace()) + return fmt.Errorf("error adding container %s namespace (%q) to DB: %w", ctr.ID(), ctr.Namespace(), err) } } if err := allCtrsBucket.Put(ctrID, ctrName); err != nil { - return errors.Wrapf(err, "error adding container %s to all containers bucket in DB", ctr.ID()) + return fmt.Errorf("error adding container %s to all containers bucket in DB: %w", ctr.ID(), err) } newCtrBkt, err := ctrBucket.CreateBucket(ctrID) if err != nil { - return errors.Wrapf(err, "error adding container %s bucket to DB", ctr.ID()) + return fmt.Errorf("error adding container %s bucket to DB: %w", ctr.ID(), err) } if err := newCtrBkt.Put(configKey, configJSON); err != nil { - return errors.Wrapf(err, "error adding container %s config to DB", ctr.ID()) + return fmt.Errorf("error adding container %s config to DB: %w", ctr.ID(), err) } if err := newCtrBkt.Put(stateKey, stateJSON); err != nil { - return errors.Wrapf(err, "error adding container %s state to DB", ctr.ID()) + return fmt.Errorf("error adding container %s state to DB: %w", ctr.ID(), err) } if ctrNamespace != nil { if err := newCtrBkt.Put(namespaceKey, ctrNamespace); err != nil { - return errors.Wrapf(err, "error adding container %s namespace to DB", ctr.ID()) + return fmt.Errorf("error adding container %s namespace to DB: %w", ctr.ID(), err) } } if pod != nil { if err := newCtrBkt.Put(podIDKey, []byte(pod.ID())); err != nil { - return errors.Wrapf(err, "error adding container %s pod to DB", ctr.ID()) + return fmt.Errorf("error adding container %s pod to DB: %w", ctr.ID(), err) } } if netNSPath != "" { if err := newCtrBkt.Put(netNSKey, []byte(netNSPath)); err != nil { - return errors.Wrapf(err, "error adding container %s netns path to DB", ctr.ID()) + return fmt.Errorf("error adding container %s netns path to DB: %w", ctr.ID(), err) } } if len(networks) > 0 { ctrNetworksBkt, err := newCtrBkt.CreateBucket(networksBkt) if err != nil { - return errors.Wrapf(err, "error creating networks bucket for container %s", ctr.ID()) + return fmt.Errorf("error creating networks bucket for container %s: %w", ctr.ID(), err) } for network, opts := range networks { if err := ctrNetworksBkt.Put([]byte(network), opts); err != nil { - return errors.Wrapf(err, "error adding network %q to networks bucket for container %s", network, ctr.ID()) + return fmt.Errorf("error adding network %q to networks bucket for container %s: %w", network, ctr.ID(), err) } } } if _, err := newCtrBkt.CreateBucket(dependenciesBkt); err != nil { - return errors.Wrapf(err, "error creating dependencies bucket for container %s", ctr.ID()) + return fmt.Errorf("error creating dependencies bucket for container %s: %w", ctr.ID(), err) } // Add dependencies for the container @@ -756,42 +756,42 @@ func (s *BoltState) addContainer(ctr *Container, pod *Pod) error { depCtrBkt := ctrBucket.Bucket(depCtrID) if depCtrBkt == nil { - return errors.Wrapf(define.ErrNoSuchCtr, "container %s depends on container %s, but it does not exist in the DB", ctr.ID(), dependsCtr) + return fmt.Errorf("container %s depends on container %s, but it does not exist in the DB: %w", ctr.ID(), dependsCtr, define.ErrNoSuchCtr) } depCtrPod := depCtrBkt.Get(podIDKey) if pod != nil { // If we're part of a pod, make sure the dependency is part of the same pod if depCtrPod == nil { - return errors.Wrapf(define.ErrInvalidArg, "container %s depends on container %s which is not in pod %s", ctr.ID(), dependsCtr, pod.ID()) + return fmt.Errorf("container %s depends on container %s which is not in pod %s: %w", ctr.ID(), dependsCtr, pod.ID(), define.ErrInvalidArg) } if string(depCtrPod) != pod.ID() { - return errors.Wrapf(define.ErrInvalidArg, "container %s depends on container %s which is in a different pod (%s)", ctr.ID(), dependsCtr, string(depCtrPod)) + return fmt.Errorf("container %s depends on container %s which is in a different pod (%s): %w", ctr.ID(), dependsCtr, string(depCtrPod), define.ErrInvalidArg) } } else if depCtrPod != nil { // If we're not part of a pod, we cannot depend on containers in a pod - return errors.Wrapf(define.ErrInvalidArg, "container %s depends on container %s which is in a pod - containers not in pods cannot depend on containers in pods", ctr.ID(), dependsCtr) + return fmt.Errorf("container %s depends on container %s which is in a pod - containers not in pods cannot depend on containers in pods: %w", ctr.ID(), dependsCtr, define.ErrInvalidArg) } depNamespace := depCtrBkt.Get(namespaceKey) if !bytes.Equal(ctrNamespace, depNamespace) { - return errors.Wrapf(define.ErrNSMismatch, "container %s in namespace %q depends on container %s in namespace %q - namespaces must match", ctr.ID(), ctr.config.Namespace, dependsCtr, string(depNamespace)) + return fmt.Errorf("container %s in namespace %q depends on container %s in namespace %q - namespaces must match: %w", ctr.ID(), ctr.config.Namespace, dependsCtr, string(depNamespace), define.ErrNSMismatch) } depCtrDependsBkt := depCtrBkt.Bucket(dependenciesBkt) if depCtrDependsBkt == nil { - return errors.Wrapf(define.ErrInternal, "container %s does not have a dependencies bucket", dependsCtr) + return fmt.Errorf("container %s does not have a dependencies bucket: %w", dependsCtr, define.ErrInternal) } if err := depCtrDependsBkt.Put(ctrID, ctrName); err != nil { - return errors.Wrapf(err, "error adding ctr %s as dependency of container %s", ctr.ID(), dependsCtr) + return fmt.Errorf("error adding ctr %s as dependency of container %s: %w", ctr.ID(), dependsCtr, err) } } // Add ctr to pod if pod != nil && podCtrs != nil { if err := podCtrs.Put(ctrID, ctrName); err != nil { - return errors.Wrapf(err, "error adding container %s to pod %s", ctr.ID(), pod.ID()) + return fmt.Errorf("error adding container %s to pod %s: %w", ctr.ID(), pod.ID(), err) } } @@ -799,16 +799,16 @@ func (s *BoltState) addContainer(ctr *Container, pod *Pod) error { for _, vol := range ctr.config.NamedVolumes { volDB := volBkt.Bucket([]byte(vol.Name)) if volDB == nil { - return errors.Wrapf(define.ErrNoSuchVolume, "no volume with name %s found in database when adding container %s", vol.Name, ctr.ID()) + return fmt.Errorf("no volume with name %s found in database when adding container %s: %w", vol.Name, ctr.ID(), define.ErrNoSuchVolume) } ctrDepsBkt, err := volDB.CreateBucketIfNotExists(volDependenciesBkt) if err != nil { - return errors.Wrapf(err, "error creating volume %s dependencies bucket to add container %s", vol.Name, ctr.ID()) + return fmt.Errorf("error creating volume %s dependencies bucket to add container %s: %w", vol.Name, ctr.ID(), err) } if depExists := ctrDepsBkt.Get(ctrID); depExists == nil { if err := ctrDepsBkt.Put(ctrID, ctrID); err != nil { - return errors.Wrapf(err, "error adding container %s to volume %s dependencies", ctr.ID(), vol.Name) + return fmt.Errorf("error adding container %s to volume %s dependencies: %w", ctr.ID(), vol.Name, err) } } } @@ -868,7 +868,7 @@ func (s *BoltState) removeContainer(ctr *Container, pod *Pod, tx *bolt.Tx) error podDB = podBucket.Bucket(podID) if podDB == nil { pod.valid = false - return errors.Wrapf(define.ErrNoSuchPod, "no pod with ID %s found in DB", pod.ID()) + return fmt.Errorf("no pod with ID %s found in DB: %w", pod.ID(), define.ErrNoSuchPod) } } @@ -876,17 +876,17 @@ func (s *BoltState) removeContainer(ctr *Container, pod *Pod, tx *bolt.Tx) error ctrExists := ctrBucket.Bucket(ctrID) if ctrExists == nil { ctr.valid = false - return errors.Wrapf(define.ErrNoSuchCtr, "no container with ID %s found in DB", ctr.ID()) + return fmt.Errorf("no container with ID %s found in DB: %w", ctr.ID(), define.ErrNoSuchCtr) } // Compare namespace // We can't remove containers not in our namespace if s.namespace != "" { if s.namespace != ctr.config.Namespace { - return errors.Wrapf(define.ErrNSMismatch, "container %s is in namespace %q, does not match our namespace %q", ctr.ID(), ctr.config.Namespace, s.namespace) + return fmt.Errorf("container %s is in namespace %q, does not match our namespace %q: %w", ctr.ID(), ctr.config.Namespace, s.namespace, define.ErrNSMismatch) } if pod != nil && s.namespace != pod.config.Namespace { - return errors.Wrapf(define.ErrNSMismatch, "pod %s is in namespace %q, does not match out namespace %q", pod.ID(), pod.config.Namespace, s.namespace) + return fmt.Errorf("pod %s is in namespace %q, does not match out namespace %q: %w", pod.ID(), pod.config.Namespace, s.namespace, define.ErrNSMismatch) } } @@ -899,10 +899,10 @@ func (s *BoltState) removeContainer(ctr *Container, pod *Pod, tx *bolt.Tx) error } else { ctrInPod := podCtrs.Get(ctrID) if ctrInPod == nil { - return errors.Wrapf(define.ErrNoSuchCtr, "container %s is not in pod %s", ctr.ID(), pod.ID()) + return fmt.Errorf("container %s is not in pod %s: %w", ctr.ID(), pod.ID(), define.ErrNoSuchCtr) } if err := podCtrs.Delete(ctrID); err != nil { - return errors.Wrapf(err, "error removing container %s from pod %s", ctr.ID(), pod.ID()) + return fmt.Errorf("error removing container %s from pod %s: %w", ctr.ID(), pod.ID(), err) } } } @@ -920,14 +920,14 @@ func (s *BoltState) removeContainer(ctr *Container, pod *Pod, tx *bolt.Tx) error return err } if len(sessions) > 0 { - return errors.Wrapf(define.ErrExecSessionExists, "container %s has active exec sessions: %s", ctr.ID(), strings.Join(sessions, ", ")) + return fmt.Errorf("container %s has active exec sessions: %s: %w", ctr.ID(), strings.Join(sessions, ", "), define.ErrExecSessionExists) } } // Does the container have dependencies? ctrDepsBkt := ctrExists.Bucket(dependenciesBkt) if ctrDepsBkt == nil { - return errors.Wrapf(define.ErrInternal, "container %s does not have a dependencies bucket", ctr.ID()) + return fmt.Errorf("container %s does not have a dependencies bucket: %w", ctr.ID(), define.ErrInternal) } deps := []string{} err = ctrDepsBkt.ForEach(func(id, value []byte) error { @@ -939,25 +939,25 @@ func (s *BoltState) removeContainer(ctr *Container, pod *Pod, tx *bolt.Tx) error return err } if len(deps) != 0 { - return errors.Wrapf(define.ErrDepExists, "container %s is a dependency of the following containers: %s", ctr.ID(), strings.Join(deps, ", ")) + return fmt.Errorf("container %s is a dependency of the following containers: %s: %w", ctr.ID(), strings.Join(deps, ", "), define.ErrDepExists) } if err := ctrBucket.DeleteBucket(ctrID); err != nil { - return errors.Wrapf(define.ErrInternal, "error deleting container %s from DB", ctr.ID()) + return fmt.Errorf("error deleting container %s from DB: %w", ctr.ID(), define.ErrInternal) } if err := idsBucket.Delete(ctrID); err != nil { - return errors.Wrapf(err, "error deleting container %s ID in DB", ctr.ID()) + return fmt.Errorf("error deleting container %s ID in DB: %w", ctr.ID(), err) } if err := namesBucket.Delete(ctrName); err != nil { - return errors.Wrapf(err, "error deleting container %s name in DB", ctr.ID()) + return fmt.Errorf("error deleting container %s name in DB: %w", ctr.ID(), err) } if err := nsBucket.Delete(ctrID); err != nil { - return errors.Wrapf(err, "error deleting container %s namespace in DB", ctr.ID()) + return fmt.Errorf("error deleting container %s namespace in DB: %w", ctr.ID(), err) } if err := allCtrsBucket.Delete(ctrID); err != nil { - return errors.Wrapf(err, "error deleting container %s from all containers bucket in DB", ctr.ID()) + return fmt.Errorf("error deleting container %s from all containers bucket in DB: %w", ctr.ID(), err) } depCtrs := ctr.Dependencies() @@ -986,7 +986,7 @@ func (s *BoltState) removeContainer(ctr *Container, pod *Pod, tx *bolt.Tx) error } if err := depCtrDependsBkt.Delete(ctrID); err != nil { - return errors.Wrapf(err, "error removing container %s as a dependency of container %s", ctr.ID(), depCtr) + return fmt.Errorf("error removing container %s as a dependency of container %s: %w", ctr.ID(), depCtr, err) } } @@ -1001,11 +1001,11 @@ func (s *BoltState) removeContainer(ctr *Container, pod *Pod, tx *bolt.Tx) error ctrDepsBkt := volDB.Bucket(volDependenciesBkt) if ctrDepsBkt == nil { - return errors.Wrapf(define.ErrInternal, "volume %s is missing container dependencies bucket, cannot remove container %s from dependencies", vol.Name, ctr.ID()) + return fmt.Errorf("volume %s is missing container dependencies bucket, cannot remove container %s from dependencies: %w", vol.Name, ctr.ID(), define.ErrInternal) } if depExists := ctrDepsBkt.Get(ctrID); depExists == nil { if err := ctrDepsBkt.Delete(ctrID); err != nil { - return errors.Wrapf(err, "error deleting container %s dependency on volume %s", ctr.ID(), vol.Name) + return fmt.Errorf("error deleting container %s dependency on volume %s: %w", ctr.ID(), vol.Name, err) } } } @@ -1062,7 +1062,7 @@ func (s *BoltState) lookupContainerID(idOrName string, ctrBucket, namesBucket, n } if strings.HasPrefix(string(checkID), idOrName) { if exists { - return errors.Wrapf(define.ErrCtrExists, "more than one result for container ID %s", idOrName) + return fmt.Errorf("more than one result for container ID %s: %w", idOrName, define.ErrCtrExists) } id = checkID exists = true @@ -1075,9 +1075,9 @@ func (s *BoltState) lookupContainerID(idOrName string, ctrBucket, namesBucket, n return nil, err } else if !exists { if isPod { - return nil, errors.Wrapf(define.ErrNoSuchCtr, "%q is a pod, not a container", idOrName) + return nil, fmt.Errorf("%q is a pod, not a container: %w", idOrName, define.ErrNoSuchCtr) } - return nil, errors.Wrapf(define.ErrNoSuchCtr, "no container with name or ID %q found", idOrName) + return nil, fmt.Errorf("no container with name or ID %q found: %w", idOrName, define.ErrNoSuchCtr) } return id, nil } diff --git a/libpod/boltdb_state_linux.go b/libpod/boltdb_state_linux.go index 8bb10fb63..813afd8bf 100644 --- a/libpod/boltdb_state_linux.go +++ b/libpod/boltdb_state_linux.go @@ -4,8 +4,9 @@ package libpod import ( + "fmt" + "github.com/containers/podman/v4/libpod/define" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -29,7 +30,7 @@ func replaceNetNS(netNSPath string, ctr *Container, newState *ContainerState) er newState.NetNS = ns } else { if ctr.ensureState(define.ContainerStateRunning, define.ContainerStatePaused) { - return errors.Wrapf(err, "error joining network namespace of container %s", ctr.ID()) + return fmt.Errorf("error joining network namespace of container %s: %w", ctr.ID(), err) } logrus.Errorf("Joining network namespace for container %s: %v", ctr.ID(), err) diff --git a/libpod/container.go b/libpod/container.go index 3a15cfbdb..4e2d93860 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -19,7 +19,6 @@ import ( "github.com/containers/podman/v4/libpod/lock" "github.com/containers/storage" spec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -355,14 +354,14 @@ func (c *Container) specFromState() (*spec.Spec, error) { returnSpec = new(spec.Spec) content, err := ioutil.ReadAll(f) if err != nil { - return nil, errors.Wrapf(err, "error reading container config") + return nil, fmt.Errorf("error reading container config: %w", err) } if err := json.Unmarshal(content, &returnSpec); err != nil { - return nil, errors.Wrapf(err, "error unmarshalling container config") + return nil, fmt.Errorf("error unmarshalling container config: %w", err) } } else if !os.IsNotExist(err) { // ignore when the file does not exist - return nil, errors.Wrapf(err, "error opening container config") + return nil, fmt.Errorf("error opening container config: %w", err) } return returnSpec, nil @@ -518,7 +517,7 @@ func (c *Container) PortMappings() ([]types.PortMapping, error) { if len(c.config.NetNsCtr) > 0 { netNsCtr, err := c.runtime.GetContainer(c.config.NetNsCtr) if err != nil { - return nil, errors.Wrapf(err, "unable to look up network namespace for container %s", c.ID()) + return nil, fmt.Errorf("unable to look up network namespace for container %s: %w", c.ID(), err) } return netNsCtr.PortMappings() } @@ -705,7 +704,7 @@ func (c *Container) Mounted() (bool, string, error) { c.lock.Lock() defer c.lock.Unlock() if err := c.syncContainer(); err != nil { - return false, "", errors.Wrapf(err, "error updating container %s state", c.ID()) + return false, "", fmt.Errorf("error updating container %s state: %w", c.ID(), err) } } // We cannot directly return c.state.Mountpoint as it is not guaranteed @@ -735,7 +734,7 @@ func (c *Container) StartedTime() (time.Time, error) { c.lock.Lock() defer c.lock.Unlock() if err := c.syncContainer(); err != nil { - return time.Time{}, errors.Wrapf(err, "error updating container %s state", c.ID()) + return time.Time{}, fmt.Errorf("error updating container %s state: %w", c.ID(), err) } } return c.state.StartedTime, nil @@ -747,7 +746,7 @@ func (c *Container) FinishedTime() (time.Time, error) { c.lock.Lock() defer c.lock.Unlock() if err := c.syncContainer(); err != nil { - return time.Time{}, errors.Wrapf(err, "error updating container %s state", c.ID()) + return time.Time{}, fmt.Errorf("error updating container %s state: %w", c.ID(), err) } } return c.state.FinishedTime, nil @@ -762,7 +761,7 @@ func (c *Container) ExitCode() (int32, bool, error) { c.lock.Lock() defer c.lock.Unlock() if err := c.syncContainer(); err != nil { - return 0, false, errors.Wrapf(err, "error updating container %s state", c.ID()) + return 0, false, fmt.Errorf("error updating container %s state: %w", c.ID(), err) } } return c.state.ExitCode, c.state.Exited, nil @@ -774,7 +773,7 @@ func (c *Container) OOMKilled() (bool, error) { c.lock.Lock() defer c.lock.Unlock() if err := c.syncContainer(); err != nil { - return false, errors.Wrapf(err, "error updating container %s state", c.ID()) + return false, fmt.Errorf("error updating container %s state: %w", c.ID(), err) } } return c.state.OOMKilled, nil @@ -845,7 +844,7 @@ func (c *Container) execSessionNoCopy(id string) (*ExecSession, error) { session, ok := c.state.ExecSessions[id] if !ok { - return nil, errors.Wrapf(define.ErrNoSuchExecSession, "no exec session with ID %s found in container %s", id, c.ID()) + return nil, fmt.Errorf("no exec session with ID %s found in container %s: %w", id, c.ID(), define.ErrNoSuchExecSession) } return session, nil @@ -861,7 +860,7 @@ func (c *Container) ExecSession(id string) (*ExecSession, error) { returnSession := new(ExecSession) if err := JSONDeepCopy(session, returnSession); err != nil { - return nil, errors.Wrapf(err, "error copying contents of container %s exec session %s", c.ID(), session.ID()) + return nil, fmt.Errorf("error copying contents of container %s exec session %s: %w", c.ID(), session.ID(), err) } return returnSession, nil @@ -921,7 +920,7 @@ func (c *Container) NamespacePath(linuxNS LinuxNS) (string, error) { //nolint:in c.lock.Lock() defer c.lock.Unlock() if err := c.syncContainer(); err != nil { - return "", errors.Wrapf(err, "error updating container %s state", c.ID()) + return "", fmt.Errorf("error updating container %s state: %w", c.ID(), err) } } @@ -932,11 +931,11 @@ func (c *Container) NamespacePath(linuxNS LinuxNS) (string, error) { //nolint:in // If the container is not running, an error will be returned func (c *Container) namespacePath(linuxNS LinuxNS) (string, error) { //nolint:interfacer if c.state.State != define.ContainerStateRunning && c.state.State != define.ContainerStatePaused { - return "", errors.Wrapf(define.ErrCtrStopped, "cannot get namespace path unless container %s is running", c.ID()) + return "", fmt.Errorf("cannot get namespace path unless container %s is running: %w", c.ID(), define.ErrCtrStopped) } if linuxNS == InvalidNS { - return "", errors.Wrapf(define.ErrInvalidArg, "invalid namespace requested from container %s", c.ID()) + return "", fmt.Errorf("invalid namespace requested from container %s: %w", c.ID(), define.ErrInvalidArg) } return fmt.Sprintf("/proc/%d/ns/%s", c.state.PID, linuxNS.String()), nil @@ -959,7 +958,7 @@ func (c *Container) CgroupPath() (string, error) { c.lock.Lock() defer c.lock.Unlock() if err := c.syncContainer(); err != nil { - return "", errors.Wrapf(err, "error updating container %s state", c.ID()) + return "", fmt.Errorf("error updating container %s state: %w", c.ID(), err) } } return c.cGroupPath() @@ -971,10 +970,10 @@ func (c *Container) CgroupPath() (string, error) { // NOTE: only call this when owning the container's lock. func (c *Container) cGroupPath() (string, error) { if c.config.NoCgroups || c.config.CgroupsMode == "disabled" { - return "", errors.Wrapf(define.ErrNoCgroups, "this container is not creating cgroups") + return "", fmt.Errorf("this container is not creating cgroups: %w", define.ErrNoCgroups) } if c.state.State != define.ContainerStateRunning && c.state.State != define.ContainerStatePaused { - return "", errors.Wrapf(define.ErrCtrStopped, "cannot get cgroup path unless container %s is running", c.ID()) + return "", fmt.Errorf("cannot get cgroup path unless container %s is running: %w", c.ID(), define.ErrCtrStopped) } // Read /proc/{PID}/cgroup and find the *longest* cgroup entry. That's @@ -995,7 +994,7 @@ func (c *Container) cGroupPath() (string, error) { // If the file doesn't exist, it means the container could have been terminated // so report it. if os.IsNotExist(err) { - return "", errors.Wrapf(define.ErrCtrStopped, "cannot get cgroup path unless container %s is running", c.ID()) + return "", fmt.Errorf("cannot get cgroup path unless container %s is running: %w", c.ID(), define.ErrCtrStopped) } return "", err } @@ -1024,7 +1023,7 @@ func (c *Container) cGroupPath() (string, error) { } if len(cgroupPath) == 0 { - return "", errors.Errorf("could not find any cgroup in %q", procPath) + return "", fmt.Errorf("could not find any cgroup in %q", procPath) } cgroupManager := c.CgroupManager() @@ -1059,7 +1058,7 @@ func (c *Container) RootFsSize() (int64, error) { c.lock.Lock() defer c.lock.Unlock() if err := c.syncContainer(); err != nil { - return -1, errors.Wrapf(err, "error updating container %s state", c.ID()) + return -1, fmt.Errorf("error updating container %s state: %w", c.ID(), err) } } return c.rootFsSize() @@ -1071,7 +1070,7 @@ func (c *Container) RWSize() (int64, error) { c.lock.Lock() defer c.lock.Unlock() if err := c.syncContainer(); err != nil { - return -1, errors.Wrapf(err, "error updating container %s state", c.ID()) + return -1, fmt.Errorf("error updating container %s state: %w", c.ID(), err) } } return c.rwSize() @@ -1118,7 +1117,7 @@ func (c *Container) IsInitCtr() bool { return len(c.config.InitContainerType) > 0 } -// IsReadOnly returns whether the container is running in read only mode +// IsReadOnly returns whether the container is running in read-only mode func (c *Container) IsReadOnly() bool { return c.config.Spec.Root.Readonly } @@ -1173,7 +1172,7 @@ func (c *Container) ContainerState() (*ContainerState, error) { } returnConfig := new(ContainerState) if err := JSONDeepCopy(c.state, returnConfig); err != nil { - return nil, errors.Wrapf(err, "error copying container %s state", c.ID()) + return nil, fmt.Errorf("error copying container %s state: %w", c.ID(), err) } return c.state, nil } @@ -1336,3 +1335,52 @@ func (c *Container) getNetworkStatus() map[string]types.StatusBlock { } return nil } + +func (c *Container) NamespaceMode(ns spec.LinuxNamespaceType, ctrSpec *spec.Spec) string { + switch ns { + case spec.UTSNamespace: + if c.config.UTSNsCtr != "" { + return fmt.Sprintf("container:%s", c.config.UTSNsCtr) + } + case spec.CgroupNamespace: + if c.config.CgroupNsCtr != "" { + return fmt.Sprintf("container:%s", c.config.CgroupNsCtr) + } + case spec.IPCNamespace: + if c.config.IPCNsCtr != "" { + return fmt.Sprintf("container:%s", c.config.IPCNsCtr) + } + case spec.PIDNamespace: + if c.config.PIDNsCtr != "" { + return fmt.Sprintf("container:%s", c.config.PIDNsCtr) + } + case spec.UserNamespace: + if c.config.UserNsCtr != "" { + return fmt.Sprintf("container:%s", c.config.UserNsCtr) + } + case spec.NetworkNamespace: + if c.config.NetNsCtr != "" { + return fmt.Sprintf("container:%s", c.config.NetNsCtr) + } + case spec.MountNamespace: + if c.config.MountNsCtr != "" { + return fmt.Sprintf("container:%s", c.config.MountNsCtr) + } + } + + if ctrSpec.Linux != nil { + // Locate the spec's given namespace. + // If there is none, it's namespace=host. + // If there is one and it has a path, it's "ns:". + // If there is no path, it's default - the empty string. + for _, availableNS := range ctrSpec.Linux.Namespaces { + if availableNS.Type == ns { + if availableNS.Path != "" { + return fmt.Sprintf("ns:%s", availableNS.Path) + } + return "private" + } + } + } + return "host" +} diff --git a/libpod/container_api.go b/libpod/container_api.go index f35cce772..dbd5fc1fb 100644 --- a/libpod/container_api.go +++ b/libpod/container_api.go @@ -2,6 +2,7 @@ package libpod import ( "context" + "errors" "fmt" "io" "io/ioutil" @@ -10,11 +11,11 @@ import ( "sync" "time" + "github.com/containers/common/pkg/resize" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/libpod/events" "github.com/containers/podman/v4/pkg/signal" "github.com/containers/storage/pkg/archive" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -39,7 +40,7 @@ func (c *Container) Init(ctx context.Context, recursive bool) error { } if !c.ensureState(define.ContainerStateConfigured, define.ContainerStateStopped, define.ContainerStateExited) { - return errors.Wrapf(define.ErrCtrStateInvalid, "container %s has already been created in runtime", c.ID()) + return fmt.Errorf("container %s has already been created in runtime: %w", c.ID(), define.ErrCtrStateInvalid) } if !recursive { @@ -103,7 +104,7 @@ func (c *Container) Start(ctx context.Context, recursive bool) error { // Attach call occurs before Start). // In overall functionality, it is identical to the Start call, with the added // side effect that an attach session will also be started. -func (c *Container) StartAndAttach(ctx context.Context, streams *define.AttachStreams, keys string, resize <-chan define.TerminalSize, recursive bool) (<-chan error, error) { +func (c *Container) StartAndAttach(ctx context.Context, streams *define.AttachStreams, keys string, resize <-chan resize.TerminalSize, recursive bool) (<-chan error, error) { if !c.batched { c.lock.Lock() defer c.lock.Unlock() @@ -197,7 +198,7 @@ func (c *Container) StopWithTimeout(timeout uint) error { } if !c.ensureState(define.ContainerStateCreated, define.ContainerStateRunning, define.ContainerStateStopping) { - return errors.Wrapf(define.ErrCtrStateInvalid, "can only stop created or running containers. %s is in state %s", c.ID(), c.state.State.String()) + return fmt.Errorf("can only stop created or running containers. %s is in state %s: %w", c.ID(), c.state.State.String(), define.ErrCtrStateInvalid) } return c.stop(timeout) @@ -221,7 +222,7 @@ func (c *Container) Kill(signal uint) error { // stop the container and if that is taking too long, a user // may have decided to kill the container after all. default: - return errors.Wrapf(define.ErrCtrStateInvalid, "can only kill running containers. %s is in state %s", c.ID(), c.state.State.String()) + return fmt.Errorf("can only kill running containers. %s is in state %s: %w", c.ID(), c.state.State.String(), define.ErrCtrStateInvalid) } // Hardcode all = false, we only use all when removing. @@ -239,9 +240,9 @@ func (c *Container) Kill(signal uint) error { // Attach attaches to a container. // This function returns when the attach finishes. It does not hold the lock for // the duration of its runtime, only using it at the beginning to verify state. -func (c *Container) Attach(streams *define.AttachStreams, keys string, resize <-chan define.TerminalSize) error { +func (c *Container) Attach(streams *define.AttachStreams, keys string, resize <-chan resize.TerminalSize) error { if c.LogDriver() == define.PassthroughLogging { - return errors.Wrapf(define.ErrNoLogs, "this container is using the 'passthrough' log driver, cannot attach") + return fmt.Errorf("this container is using the 'passthrough' log driver, cannot attach: %w", define.ErrNoLogs) } if !c.batched { c.lock.Lock() @@ -254,7 +255,7 @@ func (c *Container) Attach(streams *define.AttachStreams, keys string, resize <- } if !c.ensureState(define.ContainerStateCreated, define.ContainerStateRunning) { - return errors.Wrapf(define.ErrCtrStateInvalid, "can only attach to created or running containers") + return fmt.Errorf("can only attach to created or running containers: %w", define.ErrCtrStateInvalid) } // HACK: This is really gross, but there isn't a better way without @@ -320,11 +321,11 @@ func (c *Container) HTTPAttach(r *http.Request, w http.ResponseWriter, streams * } if !c.ensureState(define.ContainerStateCreated, define.ContainerStateRunning) { - return errors.Wrapf(define.ErrCtrStateInvalid, "can only attach to created or running containers") + return fmt.Errorf("can only attach to created or running containers: %w", define.ErrCtrStateInvalid) } if !streamAttach && !streamLogs { - return errors.Wrapf(define.ErrInvalidArg, "must specify at least one of stream or logs") + return fmt.Errorf("must specify at least one of stream or logs: %w", define.ErrInvalidArg) } logrus.Infof("Performing HTTP Hijack attach to container %s", c.ID()) @@ -335,7 +336,7 @@ func (c *Container) HTTPAttach(r *http.Request, w http.ResponseWriter, streams * // AttachResize resizes the container's terminal, which is displayed by Attach // and HTTPAttach. -func (c *Container) AttachResize(newSize define.TerminalSize) error { +func (c *Container) AttachResize(newSize resize.TerminalSize) error { if !c.batched { c.lock.Lock() defer c.lock.Unlock() @@ -346,7 +347,7 @@ func (c *Container) AttachResize(newSize define.TerminalSize) error { } if !c.ensureState(define.ContainerStateCreated, define.ContainerStateRunning) { - return errors.Wrapf(define.ErrCtrStateInvalid, "can only resize created or running containers") + return fmt.Errorf("can only resize created or running containers: %w", define.ErrCtrStateInvalid) } logrus.Infof("Resizing TTY of container %s", c.ID()) @@ -383,20 +384,20 @@ func (c *Container) Unmount(force bool) error { if c.state.Mounted { mounted, err := c.runtime.storageService.MountedContainerImage(c.ID()) if err != nil { - return errors.Wrapf(err, "can't determine how many times %s is mounted, refusing to unmount", c.ID()) + return fmt.Errorf("can't determine how many times %s is mounted, refusing to unmount: %w", c.ID(), err) } if mounted == 1 { if c.ensureState(define.ContainerStateRunning, define.ContainerStatePaused) { - return errors.Wrapf(define.ErrCtrStateInvalid, "cannot unmount storage for container %s as it is running or paused", c.ID()) + return fmt.Errorf("cannot unmount storage for container %s as it is running or paused: %w", c.ID(), define.ErrCtrStateInvalid) } execSessions, err := c.getActiveExecSessions() if err != nil { return err } if len(execSessions) != 0 { - return errors.Wrapf(define.ErrCtrStateInvalid, "container %s has active exec sessions, refusing to unmount", c.ID()) + return fmt.Errorf("container %s has active exec sessions, refusing to unmount: %w", c.ID(), define.ErrCtrStateInvalid) } - return errors.Wrapf(define.ErrInternal, "can't unmount %s last mount, it is still in use", c.ID()) + return fmt.Errorf("can't unmount %s last mount, it is still in use: %w", c.ID(), define.ErrInternal) } } defer c.newContainerEvent(events.Unmount) @@ -415,10 +416,10 @@ func (c *Container) Pause() error { } if c.state.State == define.ContainerStatePaused { - return errors.Wrapf(define.ErrCtrStateInvalid, "%q is already paused", c.ID()) + return fmt.Errorf("%q is already paused: %w", c.ID(), define.ErrCtrStateInvalid) } if c.state.State != define.ContainerStateRunning { - return errors.Wrapf(define.ErrCtrStateInvalid, "%q is not running, can't pause", c.state.State) + return fmt.Errorf("%q is not running, can't pause: %w", c.state.State, define.ErrCtrStateInvalid) } defer c.newContainerEvent(events.Pause) return c.pause() @@ -436,7 +437,7 @@ func (c *Container) Unpause() error { } if c.state.State != define.ContainerStatePaused { - return errors.Wrapf(define.ErrCtrStateInvalid, "%q is not paused, can't unpause", c.ID()) + return fmt.Errorf("%q is not paused, can't unpause: %w", c.ID(), define.ErrCtrStateInvalid) } defer c.newContainerEvent(events.Unpause) return c.unpause() @@ -455,7 +456,7 @@ func (c *Container) Export(path string) error { } if c.state.State == define.ContainerStateRemoving { - return errors.Wrapf(define.ErrCtrStateInvalid, "cannot mount container %s as it is being removed", c.ID()) + return fmt.Errorf("cannot mount container %s as it is being removed: %w", c.ID(), define.ErrCtrStateInvalid) } defer c.newContainerEvent(events.Mount) @@ -666,22 +667,21 @@ func (c *Container) Cleanup(ctx context.Context) error { defer c.lock.Unlock() if err := c.syncContainer(); err != nil { - switch errors.Cause(err) { // When the container has already been removed, the OCI runtime directory remain. - case define.ErrNoSuchCtr, define.ErrCtrRemoved: + if errors.Is(err, define.ErrNoSuchCtr) || errors.Is(err, define.ErrCtrRemoved) { if err := c.cleanupRuntime(ctx); err != nil { - return errors.Wrapf(err, "error cleaning up container %s from OCI runtime", c.ID()) + return fmt.Errorf("error cleaning up container %s from OCI runtime: %w", c.ID(), err) } - default: - logrus.Errorf("Syncing container %s status: %v", c.ID(), err) + return nil } + logrus.Errorf("Syncing container %s status: %v", c.ID(), err) return err } } // Check if state is good if !c.ensureState(define.ContainerStateConfigured, define.ContainerStateCreated, define.ContainerStateStopped, define.ContainerStateStopping, define.ContainerStateExited) { - return errors.Wrapf(define.ErrCtrStateInvalid, "container %s is running or paused, refusing to clean up", c.ID()) + return fmt.Errorf("container %s is running or paused, refusing to clean up: %w", c.ID(), define.ErrCtrStateInvalid) } // Handle restart policy. @@ -703,7 +703,7 @@ func (c *Container) Cleanup(ctx context.Context) error { return err } if len(sessions) > 0 { - return errors.Wrapf(define.ErrCtrStateInvalid, "container %s has active exec sessions, refusing to clean up", c.ID()) + return fmt.Errorf("container %s has active exec sessions, refusing to clean up: %w", c.ID(), define.ErrCtrStateInvalid) } defer c.newContainerEvent(events.Cleanup) @@ -761,19 +761,8 @@ func (c *Container) Sync() error { defer c.lock.Unlock() } - // If runtime knows about the container, update its status in runtime - // And then save back to disk - if c.ensureState(define.ContainerStateCreated, define.ContainerStateRunning, define.ContainerStatePaused, define.ContainerStateStopped, define.ContainerStateStopping) { - oldState := c.state.State - if err := c.ociRuntime.UpdateContainerStatus(c); err != nil { - return err - } - // Only save back to DB if state changed - if c.state.State != oldState { - if err := c.save(); err != nil { - return err - } - } + if err := c.syncContainer(); err != nil { + return err } defer c.newContainerEvent(events.Sync) @@ -800,7 +789,7 @@ func (c *Container) ReloadNetwork() error { } if !c.ensureState(define.ContainerStateCreated, define.ContainerStateRunning) { - return errors.Wrapf(define.ErrCtrStateInvalid, "cannot reload network unless container network has been configured") + return fmt.Errorf("cannot reload network unless container network has been configured: %w", define.ErrCtrStateInvalid) } return c.reloadNetwork() diff --git a/libpod/container_commit.go b/libpod/container_commit.go index 7018ee7d8..c93c9c7bb 100644 --- a/libpod/container_commit.go +++ b/libpod/container_commit.go @@ -2,6 +2,7 @@ package libpod import ( "context" + "errors" "fmt" "strings" @@ -12,7 +13,6 @@ import ( "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/libpod/events" libpodutil "github.com/containers/podman/v4/pkg/util" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -34,7 +34,7 @@ type ContainerCommitOptions struct { // image func (c *Container) Commit(ctx context.Context, destImage string, options ContainerCommitOptions) (*libimage.Image, error) { if c.config.Rootfs != "" { - return nil, errors.Errorf("cannot commit a container that uses an exploded rootfs") + return nil, errors.New("cannot commit a container that uses an exploded rootfs") } if !c.batched { @@ -48,7 +48,7 @@ func (c *Container) Commit(ctx context.Context, destImage string, options Contai if c.state.State == define.ContainerStateRunning && options.Pause { if err := c.pause(); err != nil { - return nil, errors.Wrapf(err, "error pausing container %q to commit", c.ID()) + return nil, fmt.Errorf("error pausing container %q to commit: %w", c.ID(), err) } defer func() { if err := c.unpause(); err != nil { @@ -136,7 +136,7 @@ func (c *Container) Commit(ctx context.Context, destImage string, options Contai if include { vol, err := c.runtime.GetVolume(v.Name) if err != nil { - return nil, errors.Wrapf(err, "volume %s used in container %s has been removed", v.Name, c.ID()) + return nil, fmt.Errorf("volume %s used in container %s has been removed: %w", v.Name, c.ID(), err) } if vol.Anonymous() { importBuilder.AddVolume(v.Dest) @@ -202,7 +202,7 @@ func (c *Container) Commit(ctx context.Context, destImage string, options Contai imageRef, err := is.Transport.ParseStoreReference(c.runtime.store, resolvedImageName) if err != nil { - return nil, errors.Wrapf(err, "error parsing target image name %q", destImage) + return nil, fmt.Errorf("error parsing target image name %q: %w", destImage, err) } commitRef = imageRef } diff --git a/libpod/container_copy_linux.go b/libpod/container_copy_linux.go index 6835b2f1f..557fead1e 100644 --- a/libpod/container_copy_linux.go +++ b/libpod/container_copy_linux.go @@ -4,6 +4,8 @@ package libpod import ( + "errors" + "fmt" "io" "os" "path/filepath" @@ -18,7 +20,6 @@ import ( "github.com/containers/storage/pkg/archive" "github.com/containers/storage/pkg/idtools" "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/sys/unix" ) @@ -196,7 +197,7 @@ func getContainerUser(container *Container, mountPoint string) (specs.User, erro if !strings.Contains(userspec, ":") { groups, err2 := chrootuser.GetAdditionalGroupsForUser(mountPoint, uint64(u.UID)) if err2 != nil { - if errors.Cause(err2) != chrootuser.ErrNoSuchUser && err == nil { + if !errors.Is(err2, chrootuser.ErrNoSuchUser) && err == nil { err = err2 } } else { @@ -253,7 +254,7 @@ func (c *Container) joinMountAndExec(f func() error) error { inHostPidNS, err := c.inHostPidNS() if err != nil { - errChan <- errors.Wrap(err, "checking inHostPidNS") + errChan <- fmt.Errorf("checking inHostPidNS: %w", err) return } var pidFD *os.File diff --git a/libpod/container_exec.go b/libpod/container_exec.go index b112273d0..d3c80e896 100644 --- a/libpod/container_exec.go +++ b/libpod/container_exec.go @@ -2,6 +2,8 @@ package libpod import ( "context" + "errors" + "fmt" "io/ioutil" "net/http" "os" @@ -9,10 +11,10 @@ import ( "strconv" "time" + "github.com/containers/common/pkg/resize" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/libpod/events" "github.com/containers/storage/pkg/stringid" - "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/sys/unix" ) @@ -112,7 +114,7 @@ func (e *ExecSession) ContainerID() string { // configuration and current state. func (e *ExecSession) Inspect() (*define.InspectExecSession, error) { if e.Config == nil { - return nil, errors.Wrapf(define.ErrInternal, "given exec session does not have a configuration block") + return nil, fmt.Errorf("given exec session does not have a configuration block: %w", define.ErrInternal) } output := new(define.InspectExecSession) @@ -165,18 +167,18 @@ func (c *Container) ExecCreate(config *ExecConfig) (string, error) { // Verify our config if config == nil { - return "", errors.Wrapf(define.ErrInvalidArg, "must provide a configuration to ExecCreate") + return "", fmt.Errorf("must provide a configuration to ExecCreate: %w", define.ErrInvalidArg) } if len(config.Command) == 0 { - return "", errors.Wrapf(define.ErrInvalidArg, "must provide a non-empty command to start an exec session") + return "", fmt.Errorf("must provide a non-empty command to start an exec session: %w", define.ErrInvalidArg) } if config.ExitCommandDelay > 0 && len(config.ExitCommand) == 0 { - return "", errors.Wrapf(define.ErrInvalidArg, "must provide a non-empty exit command if giving an exit command delay") + return "", fmt.Errorf("must provide a non-empty exit command if giving an exit command delay: %w", define.ErrInvalidArg) } // Verify that we are in a good state to continue if !c.ensureState(define.ContainerStateRunning) { - return "", errors.Wrapf(define.ErrCtrStateInvalid, "can only create exec sessions on running containers") + return "", fmt.Errorf("can only create exec sessions on running containers: %w", define.ErrCtrStateInvalid) } // Generate an ID for our new exec session @@ -203,7 +205,7 @@ func (c *Container) ExecCreate(config *ExecConfig) (string, error) { session.State = define.ExecStateCreated session.Config = new(ExecConfig) if err := JSONDeepCopy(config, session.Config); err != nil { - return "", errors.Wrapf(err, "error copying exec configuration into exec session") + return "", fmt.Errorf("error copying exec configuration into exec session: %w", err) } if len(session.Config.ExitCommand) > 0 { @@ -243,16 +245,16 @@ func (c *Container) ExecStart(sessionID string) error { // Verify that we are in a good state to continue if !c.ensureState(define.ContainerStateRunning) { - return errors.Wrapf(define.ErrCtrStateInvalid, "can only start exec sessions when their container is running") + return fmt.Errorf("can only start exec sessions when their container is running: %w", define.ErrCtrStateInvalid) } session, ok := c.state.ExecSessions[sessionID] if !ok { - return errors.Wrapf(define.ErrNoSuchExecSession, "container %s has no exec session with ID %s", c.ID(), sessionID) + return fmt.Errorf("container %s has no exec session with ID %s: %w", c.ID(), sessionID, define.ErrNoSuchExecSession) } if session.State != define.ExecStateCreated { - return errors.Wrapf(define.ErrExecSessionStateInvalid, "can only start created exec sessions, while container %s session %s state is %q", c.ID(), session.ID(), session.State.String()) + return fmt.Errorf("can only start created exec sessions, while container %s session %s state is %q: %w", c.ID(), session.ID(), session.State.String(), define.ErrExecSessionStateInvalid) } logrus.Infof("Going to start container %s exec session %s and attach to it", c.ID(), session.ID()) @@ -277,13 +279,13 @@ func (c *Container) ExecStart(sessionID string) error { return c.save() } -func (c *Container) ExecStartAndAttach(sessionID string, streams *define.AttachStreams, newSize *define.TerminalSize) error { +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. // 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 *define.TerminalSize, isHealthcheck bool) error { +func (c *Container) execStartAndAttach(sessionID string, streams *define.AttachStreams, newSize *resize.TerminalSize, isHealthcheck bool) error { if !c.batched { c.lock.Lock() defer c.lock.Unlock() @@ -295,16 +297,16 @@ func (c *Container) execStartAndAttach(sessionID string, streams *define.AttachS // Verify that we are in a good state to continue if !c.ensureState(define.ContainerStateRunning) { - return errors.Wrapf(define.ErrCtrStateInvalid, "can only start exec sessions when their container is running") + return fmt.Errorf("can only start exec sessions when their container is running: %w", define.ErrCtrStateInvalid) } session, ok := c.state.ExecSessions[sessionID] if !ok { - return errors.Wrapf(define.ErrNoSuchExecSession, "container %s has no exec session with ID %s", c.ID(), sessionID) + return fmt.Errorf("container %s has no exec session with ID %s: %w", c.ID(), sessionID, define.ErrNoSuchExecSession) } if session.State != define.ExecStateCreated { - return errors.Wrapf(define.ErrExecSessionStateInvalid, "can only start created exec sessions, while container %s session %s state is %q", c.ID(), session.ID(), session.State.String()) + return fmt.Errorf("can only start created exec sessions, while container %s session %s state is %q: %w", c.ID(), session.ID(), session.State.String(), define.ErrExecSessionStateInvalid) } logrus.Infof("Going to start container %s exec session %s and attach to it", c.ID(), session.ID()) @@ -370,7 +372,7 @@ func (c *Container) execStartAndAttach(sessionID string, streams *define.AttachS if lastErr != nil { logrus.Errorf("Container %s exec session %s error: %v", c.ID(), session.ID(), lastErr) } - return errors.Wrapf(err, "error syncing container %s state to update exec session %s", c.ID(), sessionID) + return fmt.Errorf("error syncing container %s state to update exec session %s: %w", c.ID(), sessionID, err) } // Now handle the error from readExecExitCode above. @@ -422,7 +424,7 @@ func (c *Container) execStartAndAttach(sessionID string, streams *define.AttachS // ExecHTTPStartAndAttach starts and performs an HTTP attach to an exec session. // 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) ExecHTTPStartAndAttach(sessionID string, r *http.Request, w http.ResponseWriter, - streams *HTTPAttachStreams, detachKeys *string, cancel <-chan bool, hijackDone chan<- bool, newSize *define.TerminalSize) error { + streams *HTTPAttachStreams, detachKeys *string, cancel <-chan bool, hijackDone chan<- bool, newSize *resize.TerminalSize) error { // TODO: How do we combine streams with the default streams set in the exec session? // Ensure that we don't leak a goroutine here @@ -441,16 +443,16 @@ func (c *Container) ExecHTTPStartAndAttach(sessionID string, r *http.Request, w session, ok := c.state.ExecSessions[sessionID] if !ok { - return errors.Wrapf(define.ErrNoSuchExecSession, "container %s has no exec session with ID %s", c.ID(), sessionID) + return fmt.Errorf("container %s has no exec session with ID %s: %w", c.ID(), sessionID, define.ErrNoSuchExecSession) } // Verify that we are in a good state to continue if !c.ensureState(define.ContainerStateRunning) { - return errors.Wrapf(define.ErrCtrStateInvalid, "can only start exec sessions when their container is running") + return fmt.Errorf("can only start exec sessions when their container is running: %w", define.ErrCtrStateInvalid) } if session.State != define.ExecStateCreated { - return errors.Wrapf(define.ErrExecSessionStateInvalid, "can only start created exec sessions, while container %s session %s state is %q", c.ID(), session.ID(), session.State.String()) + return fmt.Errorf("can only start created exec sessions, while container %s session %s state is %q: %w", c.ID(), session.ID(), session.State.String(), define.ErrExecSessionStateInvalid) } logrus.Infof("Going to start container %s exec session %s and attach to it", c.ID(), session.ID()) @@ -567,11 +569,11 @@ func (c *Container) ExecStop(sessionID string, timeout *uint) error { session, ok := c.state.ExecSessions[sessionID] if !ok { - return errors.Wrapf(define.ErrNoSuchExecSession, "container %s has no exec session with ID %s", c.ID(), sessionID) + return fmt.Errorf("container %s has no exec session with ID %s: %w", c.ID(), sessionID, define.ErrNoSuchExecSession) } if session.State != define.ExecStateRunning { - return errors.Wrapf(define.ErrExecSessionStateInvalid, "container %s exec session %s is %q, can only stop running sessions", c.ID(), session.ID(), session.State.String()) + return fmt.Errorf("container %s exec session %s is %q, can only stop running sessions: %w", c.ID(), session.ID(), session.State.String(), define.ErrExecSessionStateInvalid) } logrus.Infof("Stopping container %s exec session %s", c.ID(), session.ID()) @@ -617,7 +619,7 @@ func (c *Container) ExecCleanup(sessionID string) error { session, ok := c.state.ExecSessions[sessionID] if !ok { - return errors.Wrapf(define.ErrNoSuchExecSession, "container %s has no exec session with ID %s", c.ID(), sessionID) + return fmt.Errorf("container %s has no exec session with ID %s: %w", c.ID(), sessionID, define.ErrNoSuchExecSession) } if session.State == define.ExecStateRunning { @@ -628,7 +630,7 @@ func (c *Container) ExecCleanup(sessionID string) error { } if alive { - return errors.Wrapf(define.ErrExecSessionStateInvalid, "cannot clean up container %s exec session %s as it is running", c.ID(), session.ID()) + return fmt.Errorf("cannot clean up container %s exec session %s as it is running: %w", c.ID(), session.ID(), define.ErrExecSessionStateInvalid) } if err := retrieveAndWriteExecExitCode(c, session.ID()); err != nil { @@ -655,7 +657,7 @@ func (c *Container) ExecRemove(sessionID string, force bool) error { session, ok := c.state.ExecSessions[sessionID] if !ok { - return errors.Wrapf(define.ErrNoSuchExecSession, "container %s has no exec session with ID %s", c.ID(), sessionID) + return fmt.Errorf("container %s has no exec session with ID %s: %w", c.ID(), sessionID, define.ErrNoSuchExecSession) } logrus.Infof("Removing container %s exec session %s", c.ID(), session.ID()) @@ -676,7 +678,7 @@ func (c *Container) ExecRemove(sessionID string, force bool) error { if session.State == define.ExecStateRunning { if !force { - return errors.Wrapf(define.ErrExecSessionStateInvalid, "container %s exec session %s is still running, cannot remove", c.ID(), session.ID()) + return fmt.Errorf("container %s exec session %s is still running, cannot remove: %w", c.ID(), session.ID(), define.ErrExecSessionStateInvalid) } // Stop the session @@ -710,7 +712,7 @@ func (c *Container) ExecRemove(sessionID string, force bool) error { // ExecResize resizes the TTY of the given exec session. Only available if the // exec session created a TTY. -func (c *Container) ExecResize(sessionID string, newSize define.TerminalSize) error { +func (c *Container) ExecResize(sessionID string, newSize resize.TerminalSize) error { if !c.batched { c.lock.Lock() defer c.lock.Unlock() @@ -722,13 +724,13 @@ func (c *Container) ExecResize(sessionID string, newSize define.TerminalSize) er session, ok := c.state.ExecSessions[sessionID] if !ok { - return errors.Wrapf(define.ErrNoSuchExecSession, "container %s has no exec session with ID %s", c.ID(), sessionID) + return fmt.Errorf("container %s has no exec session with ID %s: %w", c.ID(), sessionID, define.ErrNoSuchExecSession) } logrus.Infof("Resizing container %s exec session %s to %+v", c.ID(), session.ID(), newSize) if session.State != define.ExecStateRunning { - return errors.Wrapf(define.ErrExecSessionStateInvalid, "cannot resize container %s exec session %s as it is not running", c.ID(), session.ID()) + return fmt.Errorf("cannot resize container %s exec session %s as it is not running: %w", c.ID(), session.ID(), define.ErrExecSessionStateInvalid) } // The exec session may have exited since we last updated. @@ -744,7 +746,7 @@ func (c *Container) ExecResize(sessionID string, newSize define.TerminalSize) er logrus.Errorf("Saving state of container %s: %v", c.ID(), err) } - return errors.Wrapf(define.ErrExecSessionStateInvalid, "cannot resize container %s exec session %s as it has stopped", c.ID(), session.ID()) + return fmt.Errorf("cannot resize container %s exec session %s as it has stopped: %w", c.ID(), session.ID(), define.ErrExecSessionStateInvalid) } // Make sure the exec session is still running. @@ -752,14 +754,14 @@ func (c *Container) ExecResize(sessionID string, newSize define.TerminalSize) er return c.ociRuntime.ExecAttachResize(c, sessionID, newSize) } -func (c *Container) Exec(config *ExecConfig, streams *define.AttachStreams, resize <-chan define.TerminalSize) (int, error) { +func (c *Container) Exec(config *ExecConfig, streams *define.AttachStreams, resize <-chan resize.TerminalSize) (int, error) { return c.exec(config, streams, resize, false) } // Exec emulates the old Libpod exec API, providing a single call to create, // run, and remove an exec session. Returns exit code and error. Exit code is // not guaranteed to be set sanely if error is not nil. -func (c *Container) exec(config *ExecConfig, streams *define.AttachStreams, resize <-chan define.TerminalSize, isHealthcheck bool) (int, error) { +func (c *Container) exec(config *ExecConfig, streams *define.AttachStreams, resizeChan <-chan resize.TerminalSize, isHealthcheck bool) (int, error) { sessionID, err := c.ExecCreate(config) if err != nil { return -1, err @@ -772,15 +774,15 @@ func (c *Container) exec(config *ExecConfig, streams *define.AttachStreams, resi // API there. // TODO: Refactor so this is closed here, before we remove the exec // session. - var size *define.TerminalSize - if resize != nil { - s := <-resize + var size *resize.TerminalSize + if resizeChan != nil { + s := <-resizeChan size = &s go func() { logrus.Debugf("Sending resize events to exec session %s", sessionID) - for resizeRequest := range resize { + for resizeRequest := range resizeChan { if err := c.ExecResize(sessionID, resizeRequest); err != nil { - if errors.Cause(err) == define.ErrExecSessionStateInvalid { + if errors.Is(err, define.ErrExecSessionStateInvalid) { // The exec session stopped // before we could resize. logrus.Infof("Missed resize on exec session %s, already stopped", sessionID) @@ -799,7 +801,7 @@ func (c *Container) exec(config *ExecConfig, streams *define.AttachStreams, resi session, err := c.execSessionNoCopy(sessionID) if err != nil { - if errors.Cause(err) == define.ErrNoSuchExecSession { + if errors.Is(err, define.ErrNoSuchExecSession) { // TODO: If a proper Context is ever plumbed in here, we // should use it. // As things stand, though, it's not worth it - this @@ -807,7 +809,7 @@ func (c *Container) exec(config *ExecConfig, streams *define.AttachStreams, resi // streaming. diedEvent, err := c.runtime.GetExecDiedEvent(context.Background(), c.ID(), sessionID) if err != nil { - return -1, errors.Wrapf(err, "error retrieving exec session %s exit code", sessionID) + return -1, fmt.Errorf("error retrieving exec session %s exit code: %w", sessionID, err) } return diedEvent.ContainerExitCode, nil } @@ -815,7 +817,7 @@ func (c *Container) exec(config *ExecConfig, streams *define.AttachStreams, resi } exitCode := session.ExitCode if err := c.ExecRemove(sessionID, false); err != nil { - if errors.Cause(err) == define.ErrNoSuchExecSession { + if errors.Is(err, define.ErrNoSuchExecSession) { return exitCode, nil } return -1, err @@ -837,7 +839,7 @@ func (c *Container) cleanupExecBundle(sessionID string) (err error) { } if pathErr, ok := err.(*os.PathError); ok { err = pathErr.Err - if errors.Cause(err) == unix.ENOTEMPTY || errors.Cause(err) == unix.EBUSY { + if errors.Is(err, unix.ENOTEMPTY) || errors.Is(err, unix.EBUSY) { // give other processes a chance to use the container if !c.batched { if err := c.save(); err != nil { @@ -909,7 +911,7 @@ func (c *Container) createExecBundle(sessionID string) (retErr error) { if err := os.MkdirAll(c.execExitFileDir(sessionID), execDirPermission); err != nil { // The directory is allowed to exist if !os.IsExist(err) { - return errors.Wrapf(err, "error creating OCI runtime exit file path %s", c.execExitFileDir(sessionID)) + return fmt.Errorf("error creating OCI runtime exit file path %s: %w", c.execExitFileDir(sessionID), err) } } return nil @@ -948,7 +950,7 @@ func (c *Container) getExecSessionPID(sessionID string) (int, error) { return oldSession.PID, nil } - return -1, errors.Wrapf(define.ErrNoSuchExecSession, "no exec session with ID %s found in container %s", sessionID, c.ID()) + return -1, fmt.Errorf("no exec session with ID %s found in container %s: %w", sessionID, c.ID(), define.ErrNoSuchExecSession) } // getKnownExecSessions gets a list of all exec sessions we think are running, @@ -1062,7 +1064,7 @@ func (c *Container) removeAllExecSessions() error { } // Delete all exec sessions if err := c.runtime.state.RemoveContainerExecSessions(c); err != nil { - if errors.Cause(err) != define.ErrCtrRemoved { + if !errors.Is(err, define.ErrCtrRemoved) { if lastErr != nil { logrus.Errorf("Stopping container %s exec sessions: %v", c.ID(), lastErr) } @@ -1072,7 +1074,7 @@ func (c *Container) removeAllExecSessions() error { c.state.ExecSessions = nil c.state.LegacyExecSessions = nil if err := c.save(); err != nil { - if errors.Cause(err) != define.ErrCtrRemoved { + if !errors.Is(err, define.ErrCtrRemoved) { if lastErr != nil { logrus.Errorf("Stopping container %s exec sessions: %v", c.ID(), lastErr) } @@ -1113,13 +1115,13 @@ func writeExecExitCode(c *Container, sessionID string, exitCode int) error { // If we can't do this, no point in continuing, any attempt to save // would write garbage to the DB. if err := c.syncContainer(); err != nil { - if errors.Cause(err) == define.ErrNoSuchCtr || errors.Cause(err) == define.ErrCtrRemoved { + if errors.Is(err, define.ErrNoSuchCtr) || errors.Is(err, define.ErrCtrRemoved) { // Container's entirely removed. We can't save status, // but the container's entirely removed, so we don't // need to. Exit without error. return nil } - return errors.Wrapf(err, "error syncing container %s state to remove exec session %s", c.ID(), sessionID) + return fmt.Errorf("error syncing container %s state to remove exec session %s: %w", c.ID(), sessionID, err) } return justWriteExecExitCode(c, sessionID, exitCode) diff --git a/libpod/container_graph.go b/libpod/container_graph.go index eeb0f02fa..67b1abc34 100644 --- a/libpod/container_graph.go +++ b/libpod/container_graph.go @@ -2,10 +2,10 @@ package libpod import ( "context" + "fmt" "strings" "github.com/containers/podman/v4/libpod/define" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -60,7 +60,7 @@ func BuildContainerGraph(ctrs []*Container) (*ContainerGraph, error) { // Get the dep's node depNode, ok := graph.nodes[dep] if !ok { - return nil, errors.Wrapf(define.ErrNoSuchCtr, "container %s depends on container %s not found in input list", node.id, dep) + return nil, fmt.Errorf("container %s depends on container %s not found in input list: %w", node.id, dep, define.ErrNoSuchCtr) } // Add the dependent node to the node's dependencies @@ -85,7 +85,7 @@ func BuildContainerGraph(ctrs []*Container) (*ContainerGraph, error) { if err != nil { return nil, err } else if cycle { - return nil, errors.Wrapf(define.ErrInternal, "cycle found in container dependency graph") + return nil, fmt.Errorf("cycle found in container dependency graph: %w", define.ErrInternal) } return graph, nil @@ -150,7 +150,7 @@ func detectCycles(graph *ContainerGraph) (bool, error) { if info.lowLink == info.index { l := len(stack) if l == 0 { - return false, errors.Wrapf(define.ErrInternal, "empty stack in detectCycles") + return false, fmt.Errorf("empty stack in detectCycles: %w", define.ErrInternal) } // Pop off the stack @@ -160,7 +160,7 @@ func detectCycles(graph *ContainerGraph) (bool, error) { // Popped item is no longer on the stack, mark as such topInfo, ok := nodes[topOfStack.id] if !ok { - return false, errors.Wrapf(define.ErrInternal, "error finding node info for %s", topOfStack.id) + return false, fmt.Errorf("error finding node info for %s: %w", topOfStack.id, define.ErrInternal) } topInfo.onStack = false @@ -203,7 +203,7 @@ func startNode(ctx context.Context, node *containerNode, setError bool, ctrError if setError { // Mark us as visited, and set an error ctrsVisited[node.id] = true - ctrErrors[node.id] = errors.Wrapf(define.ErrCtrStateInvalid, "a dependency of container %s failed to start", node.id) + ctrErrors[node.id] = fmt.Errorf("a dependency of container %s failed to start: %w", node.id, define.ErrCtrStateInvalid) // Hit anyone who depends on us, and set errors on them too for _, successor := range node.dependedOn { @@ -243,7 +243,7 @@ func startNode(ctx context.Context, node *containerNode, setError bool, ctrError } else if len(depsStopped) > 0 { // Our dependencies are not running depsList := strings.Join(depsStopped, ",") - ctrErrors[node.id] = errors.Wrapf(define.ErrCtrStateInvalid, "the following dependencies of container %s are not running: %s", node.id, depsList) + ctrErrors[node.id] = fmt.Errorf("the following dependencies of container %s are not running: %s: %w", node.id, depsList, define.ErrCtrStateInvalid) ctrErrored = true } diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go index 93240812d..fa2130a28 100644 --- a/libpod/container_inspect.go +++ b/libpod/container_inspect.go @@ -1,6 +1,7 @@ package libpod import ( + "errors" "fmt" "sort" "strings" @@ -14,7 +15,6 @@ import ( spec "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-tools/generate" "github.com/opencontainers/runtime-tools/validate" - "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/syndtr/gocapability/capability" ) @@ -24,15 +24,15 @@ import ( func (c *Container) inspectLocked(size bool) (*define.InspectContainerData, error) { storeCtr, err := c.runtime.store.Container(c.ID()) if err != nil { - return nil, errors.Wrapf(err, "error getting container from store %q", c.ID()) + return nil, fmt.Errorf("error getting container from store %q: %w", c.ID(), err) } layer, err := c.runtime.store.Layer(storeCtr.LayerID) if err != nil { - return nil, errors.Wrapf(err, "error reading information about layer %q", storeCtr.LayerID) + return nil, fmt.Errorf("error reading information about layer %q: %w", storeCtr.LayerID, err) } driverData, err := driver.GetDriverData(c.runtime.store, layer.ID) if err != nil { - return nil, errors.Wrapf(err, "error getting graph driver info %q", c.ID()) + return nil, fmt.Errorf("error getting graph driver info %q: %w", c.ID(), err) } return c.getContainerInspectData(size, driverData) } @@ -241,7 +241,7 @@ func (c *Container) GetMounts(namedVolumes []*ContainerNamedVolume, imageVolumes // volume. volFromDB, err := c.runtime.state.Volume(volume.Name) if err != nil { - return nil, errors.Wrapf(err, "error looking up volume %s in container %s config", volume.Name, c.ID()) + return nil, fmt.Errorf("error looking up volume %s in container %s config: %w", volume.Name, c.ID(), err) } mountStruct.Driver = volFromDB.Driver() @@ -794,28 +794,8 @@ func (c *Container) generateInspectContainerHostConfig(ctrSpec *spec.Spec, named hostConfig.PidMode = pidMode // UTS namespace mode - utsMode := "" - if c.config.UTSNsCtr != "" { - utsMode = fmt.Sprintf("container:%s", c.config.UTSNsCtr) - } else if ctrSpec.Linux != nil { - // Locate the spec's UTS namespace. - // If there is none, it's uts=host. - // If there is one and it has a path, it's "ns:". - // If there is no path, it's default - the empty string. - for _, ns := range ctrSpec.Linux.Namespaces { - if ns.Type == spec.UTSNamespace { - if ns.Path != "" { - utsMode = fmt.Sprintf("ns:%s", ns.Path) - } else { - utsMode = "private" - } - break - } - } - if utsMode == "" { - utsMode = "host" - } - } + utsMode := c.NamespaceMode(spec.UTSNamespace, ctrSpec) + hostConfig.UTSMode = utsMode // User namespace mode diff --git a/libpod/container_internal.go b/libpod/container_internal.go index 3b01ee6c8..560b4a1c1 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -3,6 +3,7 @@ package libpod import ( "bytes" "context" + "errors" "fmt" "io" "io/ioutil" @@ -41,7 +42,6 @@ import ( spec "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-tools/generate" "github.com/opencontainers/selinux/go-selinux/label" - "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/sys/unix" ) @@ -85,7 +85,7 @@ func (c *Container) rootFsSize() (int64, error) { for layer.Parent != "" { layerSize, err := c.runtime.store.DiffSize(layer.Parent, layer.ID) if err != nil { - return size, errors.Wrapf(err, "getting diffsize of layer %q and its parent %q", layer.ID, layer.Parent) + return size, fmt.Errorf("getting diffsize of layer %q and its parent %q: %w", layer.ID, layer.Parent, err) } size += layerSize layer, err = c.runtime.store.Layer(layer.Parent) @@ -201,12 +201,12 @@ func (c *Container) handleExitFile(exitFile string, fi os.FileInfo) error { c.state.FinishedTime = ctime.Created(fi) statusCodeStr, err := ioutil.ReadFile(exitFile) if err != nil { - return errors.Wrapf(err, "failed to read exit file for container %s", c.ID()) + return fmt.Errorf("failed to read exit file for container %s: %w", c.ID(), err) } statusCode, err := strconv.Atoi(string(statusCodeStr)) if err != nil { - return errors.Wrapf(err, "error converting exit status code (%q) for container %s to int", - c.ID(), statusCodeStr) + return fmt.Errorf("error converting exit status code (%q, err) for container %s to int: %w", + c.ID(), statusCodeStr, err) } c.state.ExitCode = int32(statusCode) @@ -268,7 +268,7 @@ func (c *Container) handleRestartPolicy(ctx context.Context) (_ bool, retErr err if c.ensureState(define.ContainerStateRunning, define.ContainerStatePaused) { return false, nil } else if c.state.State == define.ContainerStateUnknown { - return false, errors.Wrapf(define.ErrInternal, "invalid container state encountered in restart attempt") + return false, fmt.Errorf("invalid container state encountered in restart attempt: %w", define.ErrInternal) } c.newContainerEvent(events.Restart) @@ -371,7 +371,7 @@ func (c *Container) syncContainer() error { } if !c.valid { - return errors.Wrapf(define.ErrCtrRemoved, "container %s is not valid", c.ID()) + return fmt.Errorf("container %s is not valid: %w", c.ID(), define.ErrCtrRemoved) } return nil @@ -430,16 +430,16 @@ func (c *Container) setupStorageMapping(dest, from *storage.IDMappingOptions) { // Create container root filesystem for use func (c *Container) setupStorage(ctx context.Context) error { if !c.valid { - return errors.Wrapf(define.ErrCtrRemoved, "container %s is not valid", c.ID()) + return fmt.Errorf("container %s is not valid: %w", c.ID(), define.ErrCtrRemoved) } if c.state.State != define.ContainerStateConfigured { - return errors.Wrapf(define.ErrCtrStateInvalid, "container %s must be in Configured state to have storage set up", c.ID()) + return fmt.Errorf("container %s must be in Configured state to have storage set up: %w", c.ID(), define.ErrCtrStateInvalid) } // Need both an image ID and image name, plus a bool telling us whether to use the image configuration if c.config.Rootfs == "" && (c.config.RootfsImageID == "" || c.config.RootfsImageName == "") { - return errors.Wrapf(define.ErrInvalidArg, "must provide image ID and image name to use an image") + return fmt.Errorf("must provide image ID and image name to use an image: %w", define.ErrInvalidArg) } options := storage.ContainerOptions{ IDMappingOptions: storage.IDMappingOptions{ @@ -475,7 +475,7 @@ func (c *Container) setupStorage(ctx context.Context) error { defOptions, err := storage.GetMountOptions(c.runtime.store.GraphDriverName(), c.runtime.store.GraphOptions()) if err != nil { - return errors.Wrapf(err, "error getting default mount options") + return fmt.Errorf("error getting default mount options: %w", err) } var newOptions []string for _, opt := range defOptions { @@ -505,12 +505,12 @@ func (c *Container) setupStorage(ctx context.Context) error { } containerInfo, containerInfoErr = c.runtime.storageService.CreateContainerStorage(ctx, c.runtime.imageContext, c.config.RootfsImageName, c.config.RootfsImageID, c.config.Name, c.config.ID, options) - if !generateName || errors.Cause(containerInfoErr) != storage.ErrDuplicateName { + if !generateName || !errors.Is(containerInfoErr, storage.ErrDuplicateName) { break } } if containerInfoErr != nil { - return errors.Wrapf(containerInfoErr, "error creating container storage") + return fmt.Errorf("error creating container storage: %w", containerInfoErr) } // only reconfig IDMappings if layer was mounted from storage @@ -552,7 +552,7 @@ func (c *Container) setupStorage(ctx context.Context) error { artifacts := filepath.Join(c.config.StaticDir, artifactsDir) if err := os.MkdirAll(artifacts, 0755); err != nil { - return errors.Wrap(err, "error creating artifacts directory") + return fmt.Errorf("error creating artifacts directory: %w", err) } return nil @@ -581,16 +581,16 @@ func (c *Container) processLabel(processLabel string) (string, error) { // Tear down a container's storage prior to removal func (c *Container) teardownStorage() error { if c.ensureState(define.ContainerStateRunning, define.ContainerStatePaused) { - return errors.Wrapf(define.ErrCtrStateInvalid, "cannot remove storage for container %s as it is running or paused", c.ID()) + return fmt.Errorf("cannot remove storage for container %s as it is running or paused: %w", c.ID(), define.ErrCtrStateInvalid) } artifacts := filepath.Join(c.config.StaticDir, artifactsDir) if err := os.RemoveAll(artifacts); err != nil { - return errors.Wrapf(err, "error removing container %s artifacts %q", c.ID(), artifacts) + return fmt.Errorf("error removing container %s artifacts %q: %w", c.ID(), artifacts, err) } if err := c.cleanupStorage(); err != nil { - return errors.Wrapf(err, "failed to clean up container %s storage", c.ID()) + return fmt.Errorf("failed to clean up container %s storage: %w", c.ID(), err) } if err := c.runtime.storageService.DeleteContainer(c.ID()); err != nil { @@ -598,12 +598,12 @@ func (c *Container) teardownStorage() error { // error - we wanted it gone, it is already gone. // Potentially another tool using containers/storage already // removed it? - if errors.Cause(err) == storage.ErrNotAContainer || errors.Cause(err) == storage.ErrContainerUnknown { + if errors.Is(err, storage.ErrNotAContainer) || errors.Is(err, storage.ErrContainerUnknown) { logrus.Infof("Storage for container %s already removed", c.ID()) return nil } - return errors.Wrapf(err, "error removing container %s root filesystem", c.ID()) + return fmt.Errorf("error removing container %s root filesystem: %w", c.ID(), err) } return nil @@ -647,14 +647,14 @@ func (c *Container) refresh() error { } if !c.valid { - return errors.Wrapf(define.ErrCtrRemoved, "container %s is not valid - may have been removed", c.ID()) + return fmt.Errorf("container %s is not valid - may have been removed: %w", c.ID(), define.ErrCtrRemoved) } // We need to get the container's temporary directory from c/storage // It was lost in the reboot and must be recreated dir, err := c.runtime.storageService.GetRunDir(c.ID()) if err != nil { - return errors.Wrapf(err, "error retrieving temporary directory for container %s", c.ID()) + return fmt.Errorf("error retrieving temporary directory for container %s: %w", c.ID(), err) } c.state.RunDir = dir @@ -668,7 +668,7 @@ func (c *Container) refresh() error { } root := filepath.Join(c.runtime.config.Engine.TmpDir, "containers-root", c.ID()) if err := os.MkdirAll(root, 0755); err != nil { - return errors.Wrapf(err, "error creating userNS tmpdir for container %s", c.ID()) + return fmt.Errorf("error creating userNS tmpdir for container %s: %w", c.ID(), err) } if err := os.Chown(root, c.RootUID(), c.RootGID()); err != nil { return err @@ -678,7 +678,7 @@ func (c *Container) refresh() error { // We need to pick up a new lock lock, err := c.runtime.lockManager.AllocateAndRetrieveLock(c.config.LockID) if err != nil { - return errors.Wrapf(err, "error acquiring lock %d for container %s", c.config.LockID, c.ID()) + return fmt.Errorf("error acquiring lock %d for container %s: %w", c.config.LockID, c.ID(), err) } c.lock = lock @@ -693,13 +693,13 @@ func (c *Container) refresh() error { if c.config.rewrite { // SafeRewriteContainerConfig must be used with care. Make sure to not change config fields by accident. if err := c.runtime.state.SafeRewriteContainerConfig(c, "", "", c.config); err != nil { - return errors.Wrapf(err, "failed to rewrite the config for container %s", c.config.ID) + return fmt.Errorf("failed to rewrite the config for container %s: %w", c.config.ID, err) } c.config.rewrite = false } if err := c.save(); err != nil { - return errors.Wrapf(err, "error refreshing state for container %s", c.ID()) + return fmt.Errorf("error refreshing state for container %s: %w", c.ID(), err) } // Remove ctl and attach files, which may persist across reboot @@ -716,26 +716,26 @@ func (c *Container) removeConmonFiles() error { // Files are allowed to not exist, so ignore ENOENT attachFile, err := c.AttachSocketPath() if err != nil { - return errors.Wrapf(err, "failed to get attach socket path for container %s", c.ID()) + return fmt.Errorf("failed to get attach socket path for container %s: %w", c.ID(), err) } if err := os.Remove(attachFile); err != nil && !os.IsNotExist(err) { - return errors.Wrapf(err, "error removing container %s attach file", c.ID()) + return fmt.Errorf("error removing container %s attach file: %w", c.ID(), err) } ctlFile := filepath.Join(c.bundlePath(), "ctl") if err := os.Remove(ctlFile); err != nil && !os.IsNotExist(err) { - return errors.Wrapf(err, "error removing container %s ctl file", c.ID()) + return fmt.Errorf("error removing container %s ctl file: %w", c.ID(), err) } winszFile := filepath.Join(c.bundlePath(), "winsz") if err := os.Remove(winszFile); err != nil && !os.IsNotExist(err) { - return errors.Wrapf(err, "error removing container %s winsz file", c.ID()) + return fmt.Errorf("error removing container %s winsz file: %w", c.ID(), err) } oomFile := filepath.Join(c.bundlePath(), "oom") if err := os.Remove(oomFile); err != nil && !os.IsNotExist(err) { - return errors.Wrapf(err, "error removing container %s OOM file", c.ID()) + return fmt.Errorf("error removing container %s OOM file: %w", c.ID(), err) } // Remove the exit file so we don't leak memory in tmpfs @@ -744,7 +744,7 @@ func (c *Container) removeConmonFiles() error { return err } if err := os.Remove(exitFile); err != nil && !os.IsNotExist(err) { - return errors.Wrapf(err, "error removing container %s exit file", c.ID()) + return fmt.Errorf("error removing container %s exit file: %w", c.ID(), err) } return nil @@ -755,7 +755,7 @@ func (c *Container) export(path string) error { if !c.state.Mounted { containerMount, err := c.runtime.store.Mount(c.ID(), c.config.MountLabel) if err != nil { - return errors.Wrapf(err, "mounting container %q", c.ID()) + return fmt.Errorf("mounting container %q: %w", c.ID(), err) } mountPoint = containerMount defer func() { @@ -767,12 +767,12 @@ func (c *Container) export(path string) error { input, err := archive.Tar(mountPoint, archive.Uncompressed) if err != nil { - return errors.Wrapf(err, "error reading container directory %q", c.ID()) + return fmt.Errorf("error reading container directory %q: %w", c.ID(), err) } outFile, err := os.Create(path) if err != nil { - return errors.Wrapf(err, "error creating file %q", path) + return fmt.Errorf("error creating file %q: %w", path, err) } defer outFile.Close() @@ -788,7 +788,7 @@ func (c *Container) getArtifactPath(name string) string { // save container state to the database func (c *Container) save() error { if err := c.runtime.state.SaveContainer(c); err != nil { - return errors.Wrapf(err, "error saving container %s state", c.ID()) + return fmt.Errorf("error saving container %s state: %w", c.ID(), err) } return nil } @@ -799,7 +799,7 @@ func (c *Container) save() error { func (c *Container) prepareToStart(ctx context.Context, recursive bool) (retErr error) { // Container must be created or stopped to be started if !c.ensureState(define.ContainerStateConfigured, define.ContainerStateCreated, define.ContainerStateStopped, define.ContainerStateExited) { - return errors.Wrapf(define.ErrCtrStateInvalid, "container %s must be in Created or Stopped state to be started", c.ID()) + return fmt.Errorf("container %s must be in Created or Stopped state to be started: %w", c.ID(), define.ErrCtrStateInvalid) } if !recursive { @@ -842,11 +842,11 @@ func (c *Container) prepareToStart(ctx context.Context, recursive bool) (retErr func (c *Container) checkDependenciesAndHandleError() error { notRunning, err := c.checkDependenciesRunning() if err != nil { - return errors.Wrapf(err, "error checking dependencies for container %s", c.ID()) + return fmt.Errorf("error checking dependencies for container %s: %w", c.ID(), err) } if len(notRunning) > 0 { depString := strings.Join(notRunning, ",") - return errors.Wrapf(define.ErrCtrStateInvalid, "some dependencies of container %s are not started: %s", c.ID(), depString) + return fmt.Errorf("some dependencies of container %s are not started: %s: %w", c.ID(), depString, define.ErrCtrStateInvalid) } return nil @@ -861,7 +861,7 @@ func (c *Container) startDependencies(ctx context.Context) error { depVisitedCtrs := make(map[string]*Container) if err := c.getAllDependencies(depVisitedCtrs); err != nil { - return errors.Wrapf(err, "error starting dependency for container %s", c.ID()) + return fmt.Errorf("error starting dependency for container %s: %w", c.ID(), err) } // Because of how Go handles passing slices through functions, a slice cannot grow between function calls @@ -874,7 +874,7 @@ func (c *Container) startDependencies(ctx context.Context) error { // Build a dependency graph of containers graph, err := BuildContainerGraph(depCtrs) if err != nil { - return errors.Wrapf(err, "error generating dependency graph for container %s", c.ID()) + return fmt.Errorf("error generating dependency graph for container %s: %w", c.ID(), err) } // If there are no containers without dependencies, we can't start @@ -884,7 +884,7 @@ func (c *Container) startDependencies(ctx context.Context) error { if len(graph.nodes) == 0 { return nil } - return errors.Wrapf(define.ErrNoSuchCtr, "All dependencies have dependencies of %s", c.ID()) + return fmt.Errorf("all dependencies have dependencies of %s: %w", c.ID(), define.ErrNoSuchCtr) } ctrErrors := make(map[string]error) @@ -900,7 +900,7 @@ func (c *Container) startDependencies(ctx context.Context) error { for _, e := range ctrErrors { logrus.Errorf("%q", e) } - return errors.Wrapf(define.ErrInternal, "error starting some containers") + return fmt.Errorf("error starting some containers: %w", define.ErrInternal) } return nil } @@ -956,13 +956,13 @@ func (c *Container) checkDependenciesRunning() ([]string, error) { // Get the dependency container depCtr, err := c.runtime.state.Container(dep) if err != nil { - return nil, errors.Wrapf(err, "error retrieving dependency %s of container %s from state", dep, c.ID()) + return nil, fmt.Errorf("error retrieving dependency %s of container %s from state: %w", dep, c.ID(), err) } // Check the status state, err := depCtr.State() if err != nil { - return nil, errors.Wrapf(err, "error retrieving state of dependency %s of container %s", dep, c.ID()) + return nil, fmt.Errorf("error retrieving state of dependency %s of container %s: %w", dep, c.ID(), err) } if state != define.ContainerStateRunning && !depCtr.config.IsInfra { notRunning = append(notRunning, dep) @@ -1155,9 +1155,9 @@ func (c *Container) reinit(ctx context.Context, retainRetries bool) error { func (c *Container) initAndStart(ctx context.Context) (retErr error) { // If we are ContainerStateUnknown, throw an error if c.state.State == define.ContainerStateUnknown { - return errors.Wrapf(define.ErrCtrStateInvalid, "container %s is in an unknown state", c.ID()) + return fmt.Errorf("container %s is in an unknown state: %w", c.ID(), define.ErrCtrStateInvalid) } else if c.state.State == define.ContainerStateRemoving { - return errors.Wrapf(define.ErrCtrStateInvalid, "cannot start container %s as it is being removed", c.ID()) + return fmt.Errorf("cannot start container %s as it is being removed: %w", c.ID(), define.ErrCtrStateInvalid) } // If we are running, do nothing @@ -1166,7 +1166,7 @@ func (c *Container) initAndStart(ctx context.Context) (retErr error) { } // If we are paused, throw an error if c.state.State == define.ContainerStatePaused { - return errors.Wrapf(define.ErrCtrStateInvalid, "cannot start paused container %s", c.ID()) + return fmt.Errorf("cannot start paused container %s: %w", c.ID(), define.ErrCtrStateInvalid) } defer func() { @@ -1276,7 +1276,7 @@ func (c *Container) stop(timeout uint) error { // is held when busy-waiting for the container to be stopped. c.state.State = define.ContainerStateStopping if err := c.save(); err != nil { - return errors.Wrapf(err, "error saving container %s state before stopping", c.ID()) + return fmt.Errorf("error saving container %s state before stopping: %w", c.ID(), err) } if !c.batched { c.lock.Unlock() @@ -1287,19 +1287,18 @@ func (c *Container) stop(timeout uint) error { if !c.batched { c.lock.Lock() if err := c.syncContainer(); err != nil { - switch errors.Cause(err) { - // If the container has already been removed (e.g., via - // the cleanup process), set the container state to "stopped". - case define.ErrNoSuchCtr, define.ErrCtrRemoved: + if errors.Is(err, define.ErrNoSuchCtr) || errors.Is(err, define.ErrCtrRemoved) { + // If the container has already been removed (e.g., via + // the cleanup process), set the container state to "stopped". c.state.State = define.ContainerStateStopped return stopErr - default: - if stopErr != nil { - logrus.Errorf("Syncing container %s status: %v", c.ID(), err) - return stopErr - } - return err } + + if stopErr != nil { + logrus.Errorf("Syncing container %s status: %v", c.ID(), err) + return stopErr + } + return err } } @@ -1337,7 +1336,7 @@ func (c *Container) stop(timeout uint) error { } if err := c.save(); err != nil { - return errors.Wrapf(err, "error saving container %s state after stopping", c.ID()) + return fmt.Errorf("error saving container %s state after stopping: %w", c.ID(), err) } // Wait until we have an exit file, and sync once we do @@ -1351,16 +1350,16 @@ func (c *Container) stop(timeout uint) error { // Internal, non-locking function to pause a container func (c *Container) pause() error { if c.config.NoCgroups { - return errors.Wrapf(define.ErrNoCgroups, "cannot pause without using Cgroups") + return fmt.Errorf("cannot pause without using Cgroups: %w", define.ErrNoCgroups) } if rootless.IsRootless() { cgroupv2, err := cgroups.IsCgroup2UnifiedMode() if err != nil { - return errors.Wrap(err, "failed to determine cgroupversion") + return fmt.Errorf("failed to determine cgroupversion: %w", err) } if !cgroupv2 { - return errors.Wrap(define.ErrNoCgroups, "can not pause containers on rootless containers with cgroup V1") + return fmt.Errorf("can not pause containers on rootless containers with cgroup V1: %w", define.ErrNoCgroups) } } @@ -1379,7 +1378,7 @@ func (c *Container) pause() error { // Internal, non-locking function to unpause a container func (c *Container) unpause() error { if c.config.NoCgroups { - return errors.Wrapf(define.ErrNoCgroups, "cannot unpause without using Cgroups") + return fmt.Errorf("cannot unpause without using Cgroups: %w", define.ErrNoCgroups) } if err := c.ociRuntime.UnpauseContainer(c); err != nil { @@ -1397,7 +1396,7 @@ func (c *Container) unpause() error { // Internal, non-locking function to restart a container func (c *Container) restartWithTimeout(ctx context.Context, timeout uint) (retErr error) { if !c.ensureState(define.ContainerStateConfigured, define.ContainerStateCreated, define.ContainerStateRunning, define.ContainerStateStopped, define.ContainerStateExited) { - return errors.Wrapf(define.ErrCtrStateInvalid, "unable to restart a container in a paused or unknown state") + return fmt.Errorf("unable to restart a container in a paused or unknown state: %w", define.ErrCtrStateInvalid) } c.newContainerEvent(events.Restart) @@ -1472,7 +1471,7 @@ func (c *Container) mountStorage() (_ string, deferredErr error) { if !c.config.NoShm { mounted, err := mount.Mounted(c.config.ShmDir) if err != nil { - return "", errors.Wrapf(err, "unable to determine if %q is mounted", c.config.ShmDir) + return "", fmt.Errorf("unable to determine if %q is mounted: %w", c.config.ShmDir, err) } if !mounted && !MountExists(c.config.Spec.Mounts, "/dev/shm") { @@ -1481,7 +1480,7 @@ func (c *Container) mountStorage() (_ string, deferredErr error) { return "", err } if err := os.Chown(c.config.ShmDir, c.RootUID(), c.RootGID()); err != nil { - return "", errors.Wrapf(err, "failed to chown %s", c.config.ShmDir) + return "", fmt.Errorf("failed to chown %s: %w", c.config.ShmDir, err) } defer func() { if deferredErr != nil { @@ -1501,11 +1500,11 @@ func (c *Container) mountStorage() (_ string, deferredErr error) { overlayDest := c.runtime.RunRoot() contentDir, err := overlay.GenerateStructure(overlayDest, c.ID(), "rootfs", c.RootUID(), c.RootGID()) if err != nil { - return "", errors.Wrapf(err, "rootfs-overlay: failed to create TempDir in the %s directory", overlayDest) + return "", fmt.Errorf("rootfs-overlay: failed to create TempDir in the %s directory: %w", overlayDest, err) } overlayMount, err := overlay.Mount(contentDir, c.config.Rootfs, overlayDest, c.RootUID(), c.RootGID(), c.runtime.store.GraphOptions()) if err != nil { - return "", errors.Wrapf(err, "rootfs-overlay: creating overlay failed %q", c.config.Rootfs) + return "", fmt.Errorf("rootfs-overlay: creating overlay failed %q: %w", c.config.Rootfs, err) } // Seems fuse-overlayfs is not present @@ -1515,7 +1514,7 @@ func (c *Container) mountStorage() (_ string, deferredErr error) { mountOpts := label.FormatMountLabel(strings.Join(overlayMount.Options, ","), c.MountLabel()) err = mount.Mount("overlay", overlayMount.Source, overlayMount.Type, mountOpts) if err != nil { - return "", errors.Wrapf(err, "rootfs-overlay: creating overlay failed %q from native overlay", c.config.Rootfs) + return "", fmt.Errorf("rootfs-overlay: creating overlay failed %q from native overlay: %w", c.config.Rootfs, err) } } @@ -1526,7 +1525,7 @@ func (c *Container) mountStorage() (_ string, deferredErr error) { } hostUID, hostGID, err := butil.GetHostIDs(util.IDtoolsToRuntimeSpec(c.config.IDMappings.UIDMap), util.IDtoolsToRuntimeSpec(c.config.IDMappings.GIDMap), uint32(execUser.Uid), uint32(execUser.Gid)) if err != nil { - return "", errors.Wrap(err, "unable to get host UID and host GID") + return "", fmt.Errorf("unable to get host UID and host GID: %w", err) } //note: this should not be recursive, if using external rootfs users should be responsible on configuring ownership. @@ -1553,30 +1552,30 @@ func (c *Container) mountStorage() (_ string, deferredErr error) { dirfd, err := unix.Open(mountPoint, unix.O_RDONLY|unix.O_PATH, 0) if err != nil { - return "", errors.Wrap(err, "open mount point") + return "", fmt.Errorf("open mount point: %w", err) } defer unix.Close(dirfd) err = unix.Mkdirat(dirfd, "etc", 0755) if err != nil && !os.IsExist(err) { - return "", errors.Wrap(err, "create /etc") + return "", fmt.Errorf("create /etc: %w", err) } // If the etc directory was created, chown it to root in the container if err == nil && (rootUID != 0 || rootGID != 0) { err = unix.Fchownat(dirfd, "etc", rootUID, rootGID, unix.AT_SYMLINK_NOFOLLOW) if err != nil { - return "", errors.Wrap(err, "chown /etc") + return "", fmt.Errorf("chown /etc: %w", err) } } etcInTheContainerPath, err := securejoin.SecureJoin(mountPoint, "etc") if err != nil { - return "", errors.Wrap(err, "resolve /etc in the container") + return "", fmt.Errorf("resolve /etc in the container: %w", err) } etcInTheContainerFd, err := unix.Open(etcInTheContainerPath, unix.O_RDONLY|unix.O_PATH, 0) if err != nil { - return "", errors.Wrap(err, "open /etc in the container") + return "", fmt.Errorf("open /etc in the container: %w", err) } defer unix.Close(etcInTheContainerFd) @@ -1584,13 +1583,13 @@ func (c *Container) mountStorage() (_ string, deferredErr error) { // create it, so that mount command within the container will work. err = unix.Symlinkat("/proc/mounts", etcInTheContainerFd, "mtab") if err != nil && !os.IsExist(err) { - return "", errors.Wrap(err, "creating /etc/mtab symlink") + return "", fmt.Errorf("creating /etc/mtab symlink: %w", err) } // If the symlink was created, then also chown it to root in the container if err == nil && (rootUID != 0 || rootGID != 0) { err = unix.Fchownat(etcInTheContainerFd, "mtab", rootUID, rootGID, unix.AT_SYMLINK_NOFOLLOW) if err != nil { - return "", errors.Wrap(err, "chown /etc/mtab") + return "", fmt.Errorf("chown /etc/mtab: %w", err) } } @@ -1624,17 +1623,17 @@ func (c *Container) mountNamedVolume(v *ContainerNamedVolume, mountpoint string) logrus.Debugf("Going to mount named volume %s", v.Name) vol, err := c.runtime.state.Volume(v.Name) if err != nil { - return nil, errors.Wrapf(err, "error retrieving named volume %s for container %s", v.Name, c.ID()) + return nil, fmt.Errorf("error retrieving named volume %s for container %s: %w", v.Name, c.ID(), err) } if vol.config.LockID == c.config.LockID { - return nil, errors.Wrapf(define.ErrWillDeadlock, "container %s and volume %s share lock ID %d", c.ID(), vol.Name(), c.config.LockID) + return nil, fmt.Errorf("container %s and volume %s share lock ID %d: %w", c.ID(), vol.Name(), c.config.LockID, define.ErrWillDeadlock) } vol.lock.Lock() defer vol.lock.Unlock() if vol.needsMount() { if err := vol.mount(); err != nil { - return nil, errors.Wrapf(err, "error mounting volume %s for container %s", vol.Name(), c.ID()) + return nil, fmt.Errorf("error mounting volume %s for container %s: %w", vol.Name(), c.ID(), err) } } // The volume may need a copy-up. Check the state. @@ -1647,7 +1646,7 @@ func (c *Container) mountNamedVolume(v *ContainerNamedVolume, mountpoint string) srcDir, err := securejoin.SecureJoin(mountpoint, v.Dest) if err != nil { - return nil, errors.Wrapf(err, "error calculating destination path to copy up container %s volume %s", c.ID(), vol.Name()) + return nil, fmt.Errorf("error calculating destination path to copy up container %s volume %s: %w", c.ID(), vol.Name(), err) } // Do a manual stat on the source directory to verify existence. // Skip the rest if it exists. @@ -1658,7 +1657,7 @@ func (c *Container) mountNamedVolume(v *ContainerNamedVolume, mountpoint string) // up. return vol, nil } - return nil, errors.Wrapf(err, "error identifying source directory for copy up into volume %s", vol.Name()) + return nil, fmt.Errorf("error identifying source directory for copy up into volume %s: %w", vol.Name(), err) } // If it's not a directory we're mounting over it. if !srcStat.IsDir() { @@ -1670,7 +1669,7 @@ func (c *Container) mountNamedVolume(v *ContainerNamedVolume, mountpoint string) // RHBZ#1928643 srcContents, err := ioutil.ReadDir(srcDir) if err != nil { - return nil, errors.Wrapf(err, "error reading contents of source directory for copy up into volume %s", vol.Name()) + return nil, fmt.Errorf("error reading contents of source directory for copy up into volume %s: %w", vol.Name(), err) } if len(srcContents) == 0 { return vol, nil @@ -1680,7 +1679,7 @@ func (c *Container) mountNamedVolume(v *ContainerNamedVolume, mountpoint string) volMount := vol.mountPoint() contents, err := ioutil.ReadDir(volMount) if err != nil { - return nil, errors.Wrapf(err, "error listing contents of volume %s mountpoint when copying up from container %s", vol.Name(), c.ID()) + return nil, fmt.Errorf("error listing contents of volume %s mountpoint when copying up from container %s: %w", vol.Name(), c.ID(), err) } if len(contents) > 0 { // The volume is not empty. It was likely modified @@ -1722,11 +1721,11 @@ func (c *Container) mountNamedVolume(v *ContainerNamedVolume, mountpoint string) if err2 != nil { logrus.Errorf("Streaming contents of container %s directory for volume copy-up: %v", c.ID(), err2) } - return nil, errors.Wrapf(err, "error copying up to volume %s", vol.Name()) + return nil, fmt.Errorf("error copying up to volume %s: %w", vol.Name(), err) } if err := <-errChan; err != nil { - return nil, errors.Wrapf(err, "error streaming container content for copy up into volume %s", vol.Name()) + return nil, fmt.Errorf("error streaming container content for copy up into volume %s: %w", vol.Name(), err) } } return vol, nil @@ -1792,7 +1791,7 @@ func (c *Container) cleanupStorage() error { // error // We still want to be able to kick the container out of the // state - if errors.Cause(err) == storage.ErrNotAContainer || errors.Cause(err) == storage.ErrContainerUnknown || errors.Cause(err) == storage.ErrLayerNotMounted { + if errors.Is(err, storage.ErrNotAContainer) || errors.Is(err, storage.ErrContainerUnknown) || errors.Is(err, storage.ErrLayerNotMounted) { logrus.Errorf("Storage for container %s has been removed", c.ID()) } else { if cleanupErr != nil { @@ -1809,7 +1808,7 @@ func (c *Container) cleanupStorage() error { if cleanupErr != nil { logrus.Errorf("Unmounting container %s: %v", c.ID(), cleanupErr) } - cleanupErr = errors.Wrapf(err, "error retrieving named volume %s for container %s", v.Name, c.ID()) + cleanupErr = fmt.Errorf("error retrieving named volume %s for container %s: %w", v.Name, c.ID(), err) // We need to try and unmount every volume, so continue // if they fail. @@ -1822,7 +1821,7 @@ func (c *Container) cleanupStorage() error { if cleanupErr != nil { logrus.Errorf("Unmounting container %s: %v", c.ID(), cleanupErr) } - cleanupErr = errors.Wrapf(err, "error unmounting volume %s for container %s", vol.Name(), c.ID()) + cleanupErr = fmt.Errorf("error unmounting volume %s for container %s: %w", vol.Name(), c.ID(), err) } vol.lock.Unlock() } @@ -1847,7 +1846,7 @@ func (c *Container) cleanup(ctx context.Context) error { // Clean up network namespace, if present if err := c.cleanupNetwork(); err != nil { - lastError = errors.Wrapf(err, "error removing container %s network", c.ID()) + lastError = fmt.Errorf("error removing container %s network: %w", c.ID(), err) } // cleanup host entry if it is shared @@ -1885,7 +1884,7 @@ func (c *Container) cleanup(ctx context.Context) error { if lastError != nil { logrus.Errorf("Unmounting container %s storage: %v", c.ID(), err) } else { - lastError = errors.Wrapf(err, "error unmounting container %s storage", c.ID()) + lastError = fmt.Errorf("error unmounting container %s storage: %w", c.ID(), err) } } @@ -1969,11 +1968,11 @@ func (c *Container) stopPodIfNeeded(ctx context.Context) error { // hooks. func (c *Container) delete(ctx context.Context) error { if err := c.ociRuntime.DeleteContainer(c); err != nil { - return errors.Wrapf(err, "error removing container %s from runtime", c.ID()) + return fmt.Errorf("error removing container %s from runtime: %w", c.ID(), err) } if err := c.postDeleteHooks(ctx); err != nil { - return errors.Wrapf(err, "container %s poststop hooks", c.ID()) + return fmt.Errorf("container %s poststop hooks: %w", c.ID(), err) } return nil @@ -2032,7 +2031,7 @@ func (c *Container) writeStringToRundir(destFile, contents string) (string, erro destFileName := filepath.Join(c.state.RunDir, destFile) if err := os.Remove(destFileName); err != nil && !os.IsNotExist(err) { - return "", errors.Wrapf(err, "error removing %s for container %s", destFile, c.ID()) + return "", fmt.Errorf("error removing %s for container %s: %w", destFile, c.ID(), err) } if err := writeStringToPath(destFileName, contents, c.config.MountLabel, c.RootUID(), c.RootGID()); err != nil { @@ -2066,22 +2065,22 @@ func (c *Container) saveSpec(spec *spec.Spec) error { jsonPath := filepath.Join(c.bundlePath(), "config.json") if _, err := os.Stat(jsonPath); err != nil { if !os.IsNotExist(err) { - return errors.Wrapf(err, "error doing stat on container %s spec", c.ID()) + return fmt.Errorf("error doing stat on container %s spec: %w", c.ID(), err) } // The spec does not exist, we're fine } else { // The spec exists, need to remove it if err := os.Remove(jsonPath); err != nil { - return errors.Wrapf(err, "error replacing runtime spec for container %s", c.ID()) + return fmt.Errorf("error replacing runtime spec for container %s: %w", c.ID(), err) } } fileJSON, err := json.Marshal(spec) if err != nil { - return errors.Wrapf(err, "error exporting runtime spec for container %s to JSON", c.ID()) + return fmt.Errorf("error exporting runtime spec for container %s to JSON: %w", c.ID(), err) } if err := ioutil.WriteFile(jsonPath, fileJSON, 0644); err != nil { - return errors.Wrapf(err, "error writing runtime spec JSON for container %s to disk", c.ID()) + return fmt.Errorf("error writing runtime spec JSON for container %s to disk: %w", c.ID(), err) } logrus.Debugf("Created OCI spec for container %s at %s", c.ID(), jsonPath) @@ -2144,19 +2143,19 @@ func (c *Container) setupOCIHooks(ctx context.Context, config *spec.Spec) (map[s // mount mounts the container's root filesystem func (c *Container) mount() (string, error) { if c.state.State == define.ContainerStateRemoving { - return "", errors.Wrapf(define.ErrCtrStateInvalid, "cannot mount container %s as it is being removed", c.ID()) + return "", fmt.Errorf("cannot mount container %s as it is being removed: %w", c.ID(), define.ErrCtrStateInvalid) } mountPoint, err := c.runtime.storageService.MountContainerImage(c.ID()) if err != nil { - return "", errors.Wrapf(err, "error mounting storage for container %s", c.ID()) + return "", fmt.Errorf("error mounting storage for container %s: %w", c.ID(), err) } mountPoint, err = filepath.EvalSymlinks(mountPoint) if err != nil { - return "", errors.Wrapf(err, "error resolving storage path for container %s", c.ID()) + return "", fmt.Errorf("error resolving storage path for container %s: %w", c.ID(), err) } if err := os.Chown(mountPoint, c.RootUID(), c.RootGID()); err != nil { - return "", errors.Wrapf(err, "cannot chown %s to %d:%d", mountPoint, c.RootUID(), c.RootGID()) + return "", fmt.Errorf("cannot chown %s to %d:%d: %w", mountPoint, c.RootUID(), c.RootGID(), err) } return mountPoint, nil } @@ -2165,7 +2164,7 @@ func (c *Container) mount() (string, error) { func (c *Container) unmount(force bool) error { // Also unmount storage if _, err := c.runtime.storageService.UnmountContainerImage(c.ID(), force); err != nil { - return errors.Wrapf(err, "error unmounting container %s root filesystem", c.ID()) + return fmt.Errorf("error unmounting container %s root filesystem: %w", c.ID(), err) } return nil @@ -2178,11 +2177,11 @@ func (c *Container) unmount(force bool) error { // Returns nil if safe to remove, or an error describing why it's unsafe if not. func (c *Container) checkReadyForRemoval() error { if c.state.State == define.ContainerStateUnknown { - return errors.Wrapf(define.ErrCtrStateInvalid, "container %s is in invalid state", c.ID()) + return fmt.Errorf("container %s is in invalid state: %w", c.ID(), define.ErrCtrStateInvalid) } if c.ensureState(define.ContainerStateRunning, define.ContainerStatePaused) && !c.IsInfra() { - return errors.Wrapf(define.ErrCtrStateInvalid, "cannot remove container %s as it is %s - running or paused containers cannot be removed without force", c.ID(), c.state.State.String()) + return fmt.Errorf("cannot remove container %s as it is %s - running or paused containers cannot be removed without force: %w", c.ID(), c.state.State.String(), define.ErrCtrStateInvalid) } // Check exec sessions @@ -2191,7 +2190,7 @@ func (c *Container) checkReadyForRemoval() error { return err } if len(sessions) != 0 { - return errors.Wrapf(define.ErrCtrStateInvalid, "cannot remove container %s as it has active exec sessions", c.ID()) + return fmt.Errorf("cannot remove container %s as it has active exec sessions: %w", c.ID(), define.ErrCtrStateInvalid) } return nil @@ -2294,7 +2293,7 @@ func (c *Container) checkExitFile() error { return nil } - return errors.Wrapf(err, "error running stat on container %s exit file", c.ID()) + return fmt.Errorf("error running stat on container %s exit file: %w", c.ID(), err) } // Alright, it exists. Transition to Stopped state. @@ -2332,11 +2331,11 @@ func (c *Container) extractSecretToCtrStorage(secr *ContainerSecret) error { hostUID, hostGID, err := butil.GetHostIDs(util.IDtoolsToRuntimeSpec(c.config.IDMappings.UIDMap), util.IDtoolsToRuntimeSpec(c.config.IDMappings.GIDMap), secr.UID, secr.GID) if err != nil { - return errors.Wrap(err, "unable to extract secret") + return fmt.Errorf("unable to extract secret: %w", err) } err = ioutil.WriteFile(secretFile, data, 0644) if err != nil { - return errors.Wrapf(err, "unable to create %s", secretFile) + return fmt.Errorf("unable to create %s: %w", secretFile, err) } if err := os.Lchown(secretFile, int(hostUID), int(hostGID)); err != nil { return err diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 0f4bf0f55..390e95258 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -5,6 +5,7 @@ package libpod import ( "context" + "errors" "fmt" "io" "io/ioutil" @@ -57,7 +58,6 @@ import ( "github.com/opencontainers/runtime-tools/generate" "github.com/opencontainers/selinux/go-selinux" "github.com/opencontainers/selinux/go-selinux/label" - "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/sys/unix" ) @@ -65,7 +65,7 @@ import ( func (c *Container) mountSHM(shmOptions string) error { if err := unix.Mount("shm", c.config.ShmDir, "tmpfs", unix.MS_NOEXEC|unix.MS_NOSUID|unix.MS_NODEV, label.FormatMountLabel(shmOptions, c.config.MountLabel)); err != nil { - return errors.Wrapf(err, "failed to mount shm tmpfs %q", c.config.ShmDir) + return fmt.Errorf("failed to mount shm tmpfs %q: %w", c.config.ShmDir, err) } return nil } @@ -73,7 +73,7 @@ func (c *Container) mountSHM(shmOptions string) error { func (c *Container) unmountSHM(mount string) error { if err := unix.Unmount(mount, 0); err != nil { if err != syscall.EINVAL && err != syscall.ENOENT { - return errors.Wrapf(err, "error unmounting container %s SHM mount %s", c.ID(), mount) + return fmt.Errorf("error unmounting container %s SHM mount %s: %w", c.ID(), mount, err) } // If it's just an EINVAL or ENOENT, debug logs only logrus.Debugf("Container %s failed to unmount %s : %v", c.ID(), mount, err) @@ -152,7 +152,7 @@ func (c *Container) prepare() error { // createErr is guaranteed non-nil, so print // unconditionally logrus.Errorf("Preparing container %s: %v", c.ID(), createErr) - createErr = errors.Wrapf(err, "error unmounting storage for container %s after network create failure", c.ID()) + createErr = fmt.Errorf("error unmounting storage for container %s after network create failure: %w", c.ID(), err) } } @@ -161,7 +161,7 @@ func (c *Container) prepare() error { if createErr != nil { if err := c.cleanupNetwork(); err != nil { logrus.Errorf("Preparing container %s: %v", c.ID(), createErr) - createErr = errors.Wrapf(err, "error cleaning up container %s network after setup failure", c.ID()) + createErr = fmt.Errorf("error cleaning up container %s network after setup failure: %w", c.ID(), err) } } @@ -251,7 +251,7 @@ func (c *Container) resolveWorkDir() error { st, err := os.Stat(resolvedWorkdir) if err == nil { if !st.IsDir() { - return errors.Errorf("workdir %q exists on container %s, but is not a directory", workdir, c.ID()) + return fmt.Errorf("workdir %q exists on container %s, but is not a directory", workdir, c.ID()) } return nil } @@ -265,11 +265,11 @@ func (c *Container) resolveWorkDir() error { if c.isWorkDirSymlink(resolvedWorkdir) { return nil } - return errors.Errorf("workdir %q does not exist on container %s", workdir, c.ID()) + return fmt.Errorf("workdir %q does not exist on container %s", workdir, c.ID()) } // This might be a serious error (e.g., permission), so // we need to return the full error. - return errors.Wrapf(err, "error detecting workdir %q on container %s", workdir, c.ID()) + return fmt.Errorf("error detecting workdir %q on container %s: %w", workdir, c.ID(), err) } return nil } @@ -277,16 +277,16 @@ func (c *Container) resolveWorkDir() error { if os.IsExist(err) { return nil } - return errors.Wrapf(err, "error creating container %s workdir", c.ID()) + return fmt.Errorf("error creating container %s workdir: %w", c.ID(), err) } // Ensure container entrypoint is created (if required). uid, gid, _, err := chrootuser.GetUser(c.state.Mountpoint, c.User()) if err != nil { - return errors.Wrapf(err, "error looking up %s inside of the container %s", c.User(), c.ID()) + return fmt.Errorf("error looking up %s inside of the container %s: %w", c.User(), c.ID(), err) } if err := os.Chown(resolvedWorkdir, int(uid), int(gid)); err != nil { - return errors.Wrapf(err, "error chowning container %s workdir to container root", c.ID()) + return fmt.Errorf("error chowning container %s workdir to container root: %w", c.ID(), err) } return nil @@ -485,7 +485,7 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { for _, namedVol := range c.config.NamedVolumes { volume, err := c.runtime.GetVolume(namedVol.Name) if err != nil { - return nil, errors.Wrapf(err, "error retrieving volume %s to add to container %s", namedVol.Name, c.ID()) + return nil, fmt.Errorf("error retrieving volume %s to add to container %s: %w", namedVol.Name, c.ID(), err) } mountPoint, err := volume.MountPoint() if err != nil { @@ -522,7 +522,7 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { overlayMount, err = overlay.MountWithOptions(contentDir, mountPoint, namedVol.Dest, overlayOpts) if err != nil { - return nil, errors.Wrapf(err, "mounting overlay failed %q", mountPoint) + return nil, fmt.Errorf("mounting overlay failed %q: %w", mountPoint, err) } for _, o := range namedVol.Options { @@ -622,7 +622,7 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { overlayMount, err := overlay.MountWithOptions(contentDir, overlayVol.Source, overlayVol.Dest, overlayOpts) if err != nil { - return nil, errors.Wrapf(err, "mounting overlay failed %q", overlayVol.Source) + return nil, fmt.Errorf("mounting overlay failed %q: %w", overlayVol.Source, err) } // Check overlay volume options @@ -646,16 +646,16 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { // Mount the specified image. img, _, err := c.runtime.LibimageRuntime().LookupImage(volume.Source, nil) if err != nil { - return nil, errors.Wrapf(err, "error creating image volume %q:%q", volume.Source, volume.Dest) + return nil, fmt.Errorf("error creating image volume %q:%q: %w", volume.Source, volume.Dest, err) } mountPoint, err := img.Mount(ctx, nil, "") if err != nil { - return nil, errors.Wrapf(err, "error mounting image volume %q:%q", volume.Source, volume.Dest) + return nil, fmt.Errorf("error mounting image volume %q:%q: %w", volume.Source, volume.Dest, err) } contentDir, err := overlay.TempDir(c.config.StaticDir, c.RootUID(), c.RootGID()) if err != nil { - return nil, errors.Wrapf(err, "failed to create TempDir in the %s directory", c.config.StaticDir) + return nil, fmt.Errorf("failed to create TempDir in the %s directory: %w", c.config.StaticDir, err) } var overlayMount spec.Mount @@ -665,7 +665,7 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { overlayMount, err = overlay.MountReadOnly(contentDir, mountPoint, volume.Dest, c.RootUID(), c.RootGID(), c.runtime.store.GraphOptions()) } if err != nil { - return nil, errors.Wrapf(err, "creating overlay mount for image %q failed", volume.Source) + return nil, fmt.Errorf("creating overlay mount for image %q failed: %w", volume.Source, err) } g.AddMount(overlayMount) } @@ -690,7 +690,7 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { if c.config.Umask != "" { decVal, err := strconv.ParseUint(c.config.Umask, 8, 32) if err != nil { - return nil, errors.Wrapf(err, "Invalid Umask Value") + return nil, fmt.Errorf("invalid Umask Value: %w", err) } umask := uint32(decVal) g.Config.Process.User.Umask = &umask @@ -700,7 +700,7 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { if len(c.config.Groups) > 0 { gids, err := lookup.GetContainerGroups(c.config.Groups, c.state.Mountpoint, overrides) if err != nil { - return nil, errors.Wrapf(err, "error looking up supplemental groups for container %s", c.ID()) + return nil, fmt.Errorf("error looking up supplemental groups for container %s: %w", c.ID(), err) } for _, gid := range gids { g.AddProcessAdditionalGid(gid) @@ -709,7 +709,7 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { if c.Systemd() { if err := c.setupSystemd(g.Mounts(), g); err != nil { - return nil, errors.Wrapf(err, "error adding systemd-specific mounts") + return nil, fmt.Errorf("error adding systemd-specific mounts: %w", err) } } @@ -725,7 +725,7 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { // Check whether the current user namespace has enough gids available. availableGids, err := rootless.GetAvailableGids() if err != nil { - return nil, errors.Wrapf(err, "cannot read number of available GIDs") + return nil, fmt.Errorf("cannot read number of available GIDs: %w", err) } gidMappings = []idtools.IDMap{{ ContainerID: 0, @@ -881,7 +881,7 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { } _, err := registry.InjectDevices(g.Config, c.config.CDIDevices...) if err != nil { - return nil, errors.Wrapf(err, "error setting up CDI devices") + return nil, fmt.Errorf("error setting up CDI devices: %w", err) } } @@ -905,7 +905,7 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { if m.Type == "tmpfs" { finalPath, err := securejoin.SecureJoin(c.state.Mountpoint, m.Destination) if err != nil { - return nil, errors.Wrapf(err, "error resolving symlinks for mount destination %s", m.Destination) + return nil, fmt.Errorf("error resolving symlinks for mount destination %s: %w", m.Destination, err) } trimmedPath := strings.TrimPrefix(finalPath, strings.TrimSuffix(c.state.Mountpoint, "/")) m.Destination = trimmedPath @@ -934,7 +934,7 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { // Warning: precreate hooks may alter g.Config in place. if c.state.ExtensionStageHooks, err = c.setupOCIHooks(ctx, g.Config); err != nil { - return nil, errors.Wrapf(err, "error setting up OCI Hooks") + return nil, fmt.Errorf("error setting up OCI Hooks: %w", err) } if len(c.config.EnvSecrets) > 0 { manager, err := c.runtime.SecretsManager() @@ -986,11 +986,11 @@ func (c *Container) mountNotifySocket(g generate.Generator) error { logrus.Debugf("Checking notify %q dir", notifyDir) if err := os.MkdirAll(notifyDir, 0755); err != nil { if !os.IsExist(err) { - return errors.Wrapf(err, "unable to create notify %q dir", notifyDir) + return fmt.Errorf("unable to create notify %q dir: %w", notifyDir, err) } } if err := label.Relabel(notifyDir, c.MountLabel(), true); err != nil { - return errors.Wrapf(err, "relabel failed %q", notifyDir) + return fmt.Errorf("relabel failed %q: %w", notifyDir, err) } logrus.Debugf("Add bindmount notify %q dir", notifyDir) if _, ok := c.state.BindMounts["/run/notify"]; !ok { @@ -1113,7 +1113,7 @@ func (c *Container) setupSystemd(mounts []spec.Mount, g generate.Generator) erro func (c *Container) addNamespaceContainer(g *generate.Generator, ns LinuxNS, ctr string, specNS spec.LinuxNamespaceType) error { nsCtr, err := c.runtime.state.Container(ctr) if err != nil { - return errors.Wrapf(err, "error retrieving dependency %s of container %s from state", ctr, c.ID()) + return fmt.Errorf("error retrieving dependency %s of container %s from state: %w", ctr, c.ID(), err) } if specNS == spec.UTSNamespace { @@ -1200,7 +1200,7 @@ func (c *Container) createCheckpointImage(ctx context.Context, options Container // Create storage reference imageRef, err := is.Transport.ParseStoreReference(c.runtime.store, options.CreateImage) if err != nil { - return errors.Errorf("Failed to parse image name") + return errors.New("failed to parse image name") } // Build an image scratch @@ -1264,23 +1264,23 @@ func (c *Container) exportCheckpoint(options ContainerCheckpointOptions) error { // Check if the dependency is an infra container. If it is we can checkpoint // the container out of the Pod. if c.config.Pod == "" { - return errors.Errorf("cannot export checkpoints of containers with dependencies") + return errors.New("cannot export checkpoints of containers with dependencies") } pod, err := c.runtime.state.Pod(c.config.Pod) if err != nil { - return errors.Wrapf(err, "container %s is in pod %s, but pod cannot be retrieved", c.ID(), c.config.Pod) + return fmt.Errorf("container %s is in pod %s, but pod cannot be retrieved: %w", c.ID(), c.config.Pod, err) } infraID, err := pod.InfraContainerID() if err != nil { - return errors.Wrapf(err, "cannot retrieve infra container ID for pod %s", c.config.Pod) + return fmt.Errorf("cannot retrieve infra container ID for pod %s: %w", c.config.Pod, err) } if c.Dependencies()[0] != infraID { - return errors.Errorf("cannot export checkpoints of containers with dependencies") + return errors.New("cannot export checkpoints of containers with dependencies") } } if len(c.Dependencies()) > 1 { - return errors.Errorf("cannot export checkpoints of containers with dependencies") + return errors.New("cannot export checkpoints of containers with dependencies") } logrus.Debugf("Exporting checkpoint image of container %q to %q", c.ID(), options.TargetFile) @@ -1308,7 +1308,7 @@ func (c *Container) exportCheckpoint(options ContainerCheckpointOptions) error { // To correctly track deleted files, let's go through the output of 'podman diff' rootFsChanges, err := c.runtime.GetDiff("", c.ID(), define.DiffContainer) if err != nil { - return errors.Wrapf(err, "error exporting root file-system diff for %q", c.ID()) + return fmt.Errorf("error exporting root file-system diff for %q: %w", c.ID(), err) } addToTarFiles, err := crutils.CRCreateRootFsDiffTar(&rootFsChanges, c.state.Mountpoint, c.bundlePath()) @@ -1325,7 +1325,7 @@ func (c *Container) exportCheckpoint(options ContainerCheckpointOptions) error { // Create an archive for each volume associated with the container if !options.IgnoreVolumes { if err := os.MkdirAll(expVolDir, 0700); err != nil { - return errors.Wrapf(err, "error creating volumes export directory %q", expVolDir) + return fmt.Errorf("error creating volumes export directory %q: %w", expVolDir, err) } for _, v := range c.config.NamedVolumes { @@ -1334,7 +1334,7 @@ func (c *Container) exportCheckpoint(options ContainerCheckpointOptions) error { volumeTarFile, err := os.Create(volumeTarFileFullPath) if err != nil { - return errors.Wrapf(err, "error creating %q", volumeTarFileFullPath) + return fmt.Errorf("error creating %q: %w", volumeTarFileFullPath, err) } volume, err := c.runtime.GetVolume(v.Name) @@ -1347,7 +1347,7 @@ func (c *Container) exportCheckpoint(options ContainerCheckpointOptions) error { return err } if mp == "" { - return errors.Wrapf(define.ErrInternal, "volume %s is not mounted, cannot export", volume.Name()) + return fmt.Errorf("volume %s is not mounted, cannot export: %w", volume.Name(), define.ErrInternal) } input, err := archive.TarWithOptions(mp, &archive.TarOptions{ @@ -1355,7 +1355,7 @@ func (c *Container) exportCheckpoint(options ContainerCheckpointOptions) error { IncludeSourceDir: true, }) if err != nil { - return errors.Wrapf(err, "error reading volume directory %q", v.Dest) + return fmt.Errorf("error reading volume directory %q: %w", v.Dest, err) } _, err = io.Copy(volumeTarFile, input) @@ -1375,12 +1375,12 @@ func (c *Container) exportCheckpoint(options ContainerCheckpointOptions) error { }) if err != nil { - return errors.Wrapf(err, "error reading checkpoint directory %q", c.ID()) + return fmt.Errorf("error reading checkpoint directory %q: %w", c.ID(), err) } outFile, err := os.Create(options.TargetFile) if err != nil { - return errors.Wrapf(err, "error creating checkpoint export file %q", options.TargetFile) + return fmt.Errorf("error creating checkpoint export file %q: %w", options.TargetFile, err) } defer outFile.Close() @@ -1406,10 +1406,10 @@ func (c *Container) exportCheckpoint(options ContainerCheckpointOptions) error { func (c *Container) checkpointRestoreSupported(version int) error { if !criu.CheckForCriu(version) { - return errors.Errorf("checkpoint/restore requires at least CRIU %d", version) + return fmt.Errorf("checkpoint/restore requires at least CRIU %d", version) } if !c.ociRuntime.SupportsCheckpoint() { - return errors.Errorf("configured runtime does not support checkpoint/restore") + return errors.New("configured runtime does not support checkpoint/restore") } return nil } @@ -1420,11 +1420,11 @@ func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointO } if c.state.State != define.ContainerStateRunning { - return nil, 0, errors.Wrapf(define.ErrCtrStateInvalid, "%q is not running, cannot checkpoint", c.state.State) + return nil, 0, fmt.Errorf("%q is not running, cannot checkpoint: %w", c.state.State, define.ErrCtrStateInvalid) } if c.AutoRemove() && options.TargetFile == "" { - return nil, 0, errors.Errorf("cannot checkpoint containers that have been started with '--rm' unless '--export' is used") + return nil, 0, errors.New("cannot checkpoint containers that have been started with '--rm' unless '--export' is used") } if err := c.resolveCheckpointImageName(&options); err != nil { @@ -1517,12 +1517,12 @@ func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointO } statsDirectory, err := os.Open(c.bundlePath()) if err != nil { - return nil, errors.Wrapf(err, "Not able to open %q", c.bundlePath()) + return nil, fmt.Errorf("not able to open %q: %w", c.bundlePath(), err) } dumpStatistics, err := stats.CriuGetDumpStats(statsDirectory) if err != nil { - return nil, errors.Wrap(err, "Displaying checkpointing statistics not possible") + return nil, fmt.Errorf("displaying checkpointing statistics not possible: %w", err) } return &define.CRIUCheckpointRestoreStatistics{ @@ -1568,7 +1568,7 @@ func (c *Container) generateContainerSpec() error { g := generate.NewFromSpec(c.config.Spec) if err := c.saveSpec(g.Config); err != nil { - return errors.Wrap(err, "saving imported container specification for restore failed") + return fmt.Errorf("saving imported container specification for restore failed: %w", err) } return nil @@ -1626,14 +1626,14 @@ func (c *Container) importCheckpointTar(input string) error { func (c *Container) importPreCheckpoint(input string) error { archiveFile, err := os.Open(input) if err != nil { - return errors.Wrap(err, "failed to open pre-checkpoint archive for import") + return fmt.Errorf("failed to open pre-checkpoint archive for import: %w", err) } defer archiveFile.Close() err = archive.Untar(archiveFile, c.bundlePath(), nil) if err != nil { - return errors.Wrapf(err, "Unpacking of pre-checkpoint archive %s failed", input) + return fmt.Errorf("unpacking of pre-checkpoint archive %s failed: %w", input, err) } return nil } @@ -1650,11 +1650,11 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti } if options.Pod != "" && !crutils.CRRuntimeSupportsPodCheckpointRestore(c.ociRuntime.Path()) { - return nil, 0, errors.Errorf("runtime %s does not support pod restore", c.ociRuntime.Path()) + return nil, 0, fmt.Errorf("runtime %s does not support pod restore", c.ociRuntime.Path()) } if !c.ensureState(define.ContainerStateConfigured, define.ContainerStateExited) { - return nil, 0, errors.Wrapf(define.ErrCtrStateInvalid, "container %s is running or paused, cannot restore", c.ID()) + return nil, 0, fmt.Errorf("container %s is running or paused, cannot restore: %w", c.ID(), define.ErrCtrStateInvalid) } if options.ImportPrevious != "" { @@ -1676,7 +1676,7 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti // Let's try to stat() CRIU's inventory file. If it does not exist, it makes // no sense to try a restore. This is a minimal check if a checkpoint exist. if _, err := os.Stat(filepath.Join(c.CheckpointPath(), "inventory.img")); os.IsNotExist(err) { - return nil, 0, errors.Wrapf(err, "a complete checkpoint for this container cannot be found, cannot restore") + return nil, 0, fmt.Errorf("a complete checkpoint for this container cannot be found, cannot restore: %w", err) } if err := crutils.CRCreateFileWithLabel(c.bundlePath(), "restore.log", c.MountLabel()); err != nil { @@ -1774,23 +1774,23 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti // the ones from the infrastructure container. pod, err := c.runtime.LookupPod(options.Pod) if err != nil { - return nil, 0, errors.Wrapf(err, "pod %q cannot be retrieved", options.Pod) + return nil, 0, fmt.Errorf("pod %q cannot be retrieved: %w", options.Pod, err) } infraContainer, err := pod.InfraContainer() if err != nil { - return nil, 0, errors.Wrapf(err, "cannot retrieved infra container from pod %q", options.Pod) + return nil, 0, fmt.Errorf("cannot retrieved infra container from pod %q: %w", options.Pod, err) } infraContainer.lock.Lock() if err := infraContainer.syncContainer(); err != nil { infraContainer.lock.Unlock() - return nil, 0, errors.Wrapf(err, "Error syncing infrastructure container %s status", infraContainer.ID()) + return nil, 0, fmt.Errorf("error syncing infrastructure container %s status: %w", infraContainer.ID(), err) } if infraContainer.state.State != define.ContainerStateRunning { if err := infraContainer.initAndStart(ctx); err != nil { infraContainer.lock.Unlock() - return nil, 0, errors.Wrapf(err, "Error starting infrastructure container %s status", infraContainer.ID()) + return nil, 0, fmt.Errorf("error starting infrastructure container %s status: %w", infraContainer.ID(), err) } } infraContainer.lock.Unlock() @@ -1798,7 +1798,7 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti if c.config.IPCNsCtr != "" { nsPath, err := infraContainer.namespacePath(IPCNS) if err != nil { - return nil, 0, errors.Wrapf(err, "cannot retrieve IPC namespace path for Pod %q", options.Pod) + return nil, 0, fmt.Errorf("cannot retrieve IPC namespace path for Pod %q: %w", options.Pod, err) } if err := g.AddOrReplaceLinuxNamespace(string(spec.IPCNamespace), nsPath); err != nil { return nil, 0, err @@ -1808,7 +1808,7 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti if c.config.NetNsCtr != "" { nsPath, err := infraContainer.namespacePath(NetNS) if err != nil { - return nil, 0, errors.Wrapf(err, "cannot retrieve network namespace path for Pod %q", options.Pod) + return nil, 0, fmt.Errorf("cannot retrieve network namespace path for Pod %q: %w", options.Pod, err) } if err := g.AddOrReplaceLinuxNamespace(string(spec.NetworkNamespace), nsPath); err != nil { return nil, 0, err @@ -1818,7 +1818,7 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti if c.config.PIDNsCtr != "" { nsPath, err := infraContainer.namespacePath(PIDNS) if err != nil { - return nil, 0, errors.Wrapf(err, "cannot retrieve PID namespace path for Pod %q", options.Pod) + return nil, 0, fmt.Errorf("cannot retrieve PID namespace path for Pod %q: %w", options.Pod, err) } if err := g.AddOrReplaceLinuxNamespace(string(spec.PIDNamespace), nsPath); err != nil { return nil, 0, err @@ -1828,7 +1828,7 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti if c.config.UTSNsCtr != "" { nsPath, err := infraContainer.namespacePath(UTSNS) if err != nil { - return nil, 0, errors.Wrapf(err, "cannot retrieve UTS namespace path for Pod %q", options.Pod) + return nil, 0, fmt.Errorf("cannot retrieve UTS namespace path for Pod %q: %w", options.Pod, err) } if err := g.AddOrReplaceLinuxNamespace(string(spec.UTSNamespace), nsPath); err != nil { return nil, 0, err @@ -1838,7 +1838,7 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti if c.config.CgroupNsCtr != "" { nsPath, err := infraContainer.namespacePath(CgroupNS) if err != nil { - return nil, 0, errors.Wrapf(err, "cannot retrieve Cgroup namespace path for Pod %q", options.Pod) + return nil, 0, fmt.Errorf("cannot retrieve Cgroup namespace path for Pod %q: %w", options.Pod, err) } if err := g.AddOrReplaceLinuxNamespace(string(spec.CgroupNamespace), nsPath); err != nil { return nil, 0, err @@ -1906,13 +1906,13 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti volumeFile, err := os.Open(volumeFilePath) if err != nil { - return nil, 0, errors.Wrapf(err, "failed to open volume file %s", volumeFilePath) + return nil, 0, fmt.Errorf("failed to open volume file %s: %w", volumeFilePath, err) } defer volumeFile.Close() volume, err := c.runtime.GetVolume(v.Name) if err != nil { - return nil, 0, errors.Wrapf(err, "failed to retrieve volume %s", v.Name) + return nil, 0, fmt.Errorf("failed to retrieve volume %s: %w", v.Name, err) } mountPoint, err := volume.MountPoint() @@ -1920,10 +1920,10 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti return nil, 0, err } if mountPoint == "" { - return nil, 0, errors.Wrapf(err, "unable to import volume %s as it is not mounted", volume.Name()) + return nil, 0, fmt.Errorf("unable to import volume %s as it is not mounted: %w", volume.Name(), err) } if err := archive.UntarUncompressed(volumeFile, mountPoint, nil); err != nil { - return nil, 0, errors.Wrapf(err, "Failed to extract volume %s to %s", volumeFilePath, mountPoint) + return nil, 0, fmt.Errorf("failed to extract volume %s to %s: %w", volumeFilePath, mountPoint, err) } } } @@ -1950,12 +1950,12 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti } statsDirectory, err := os.Open(c.bundlePath()) if err != nil { - return nil, errors.Wrapf(err, "Not able to open %q", c.bundlePath()) + return nil, fmt.Errorf("not able to open %q: %w", c.bundlePath(), err) } restoreStatistics, err := stats.CriuGetRestoreStats(statsDirectory) if err != nil { - return nil, errors.Wrap(err, "Displaying restore statistics not possible") + return nil, fmt.Errorf("displaying restore statistics not possible: %w", err) } return &define.CRIUCheckpointRestoreStatistics{ @@ -2033,7 +2033,7 @@ func (c *Container) getRootNetNsDepCtr() (depCtr *Container, err error) { depCtr, err = c.runtime.state.Container(nextCtr) if err != nil { - return nil, errors.Wrapf(err, "error fetching dependency %s of container %s", c.config.NetNsCtr, c.ID()) + return nil, fmt.Errorf("error fetching dependency %s of container %s: %w", c.config.NetNsCtr, c.ID(), err) } // This should never happen without an error if depCtr == nil { @@ -2062,7 +2062,7 @@ func (c *Container) mountIntoRootDirs(mountName string, mountPath string) error // Make standard bind mounts to include in the container func (c *Container) makeBindMounts() error { if err := os.Chown(c.state.RunDir, c.RootUID(), c.RootGID()); err != nil { - return errors.Wrap(err, "cannot chown run directory") + return fmt.Errorf("cannot chown run directory: %w", err) } if c.state.BindMounts == nil { @@ -2080,13 +2080,13 @@ func (c *Container) makeBindMounts() error { if c.config.NetNsCtr == "" { if resolvePath, ok := c.state.BindMounts["/etc/resolv.conf"]; ok { if err := os.Remove(resolvePath); err != nil && !os.IsNotExist(err) { - return errors.Wrapf(err, "container %s", c.ID()) + return fmt.Errorf("container %s: %w", c.ID(), err) } delete(c.state.BindMounts, "/etc/resolv.conf") } if hostsPath, ok := c.state.BindMounts["/etc/hosts"]; ok { if err := os.Remove(hostsPath); err != nil && !os.IsNotExist(err) { - return errors.Wrapf(err, "container %s", c.ID()) + return fmt.Errorf("container %s: %w", c.ID(), err) } delete(c.state.BindMounts, "/etc/hosts") } @@ -2099,13 +2099,13 @@ func (c *Container) makeBindMounts() error { // them. depCtr, err := c.getRootNetNsDepCtr() if err != nil { - return errors.Wrapf(err, "error fetching network namespace dependency container for container %s", c.ID()) + return fmt.Errorf("error fetching network namespace dependency container for container %s: %w", c.ID(), err) } // We need that container's bind mounts bindMounts, err := depCtr.BindMounts() if err != nil { - return errors.Wrapf(err, "error fetching bind mounts from dependency %s of container %s", depCtr.ID(), c.ID()) + return fmt.Errorf("error fetching bind mounts from dependency %s of container %s: %w", depCtr.ID(), c.ID(), err) } // The other container may not have a resolv.conf or /etc/hosts @@ -2115,7 +2115,7 @@ func (c *Container) makeBindMounts() error { err := c.mountIntoRootDirs("/etc/resolv.conf", resolvPath) if err != nil { - return errors.Wrapf(err, "error assigning mounts to container %s", c.ID()) + return fmt.Errorf("error assigning mounts to container %s: %w", c.ID(), err) } } @@ -2135,13 +2135,13 @@ func (c *Container) makeBindMounts() error { err = etchosts.Add(hostsPath, getLocalhostHostEntry(c)) lock.Unlock() if err != nil { - return errors.Wrapf(err, "error creating hosts file for container %s which depends on container %s", c.ID(), depCtr.ID()) + return fmt.Errorf("error creating hosts file for container %s which depends on container %s: %w", c.ID(), depCtr.ID(), err) } // finally, save it in the new container err = c.mountIntoRootDirs(config.DefaultHostsFile, hostsPath) if err != nil { - return errors.Wrapf(err, "error assigning mounts to container %s", c.ID()) + return fmt.Errorf("error assigning mounts to container %s: %w", c.ID(), err) } } @@ -2156,13 +2156,13 @@ func (c *Container) makeBindMounts() error { } else { if !c.config.UseImageResolvConf { if err := c.generateResolvConf(); err != nil { - return errors.Wrapf(err, "error creating resolv.conf for container %s", c.ID()) + return fmt.Errorf("error creating resolv.conf for container %s: %w", c.ID(), err) } } if !c.config.UseImageHosts { if err := c.createHosts(); err != nil { - return errors.Wrapf(err, "error creating hosts file for container %s", c.ID()) + return fmt.Errorf("error creating hosts file for container %s: %w", c.ID(), err) } } } @@ -2180,7 +2180,7 @@ func (c *Container) makeBindMounts() error { } } else if !c.config.UseImageHosts && c.state.BindMounts["/etc/hosts"] == "" { if err := c.createHosts(); err != nil { - return errors.Wrapf(err, "error creating hosts file for container %s", c.ID()) + return fmt.Errorf("error creating hosts file for container %s: %w", c.ID(), err) } } @@ -2192,7 +2192,7 @@ func (c *Container) makeBindMounts() error { if c.config.Passwd == nil || *c.config.Passwd { newPasswd, newGroup, err := c.generatePasswdAndGroup() if err != nil { - return errors.Wrapf(err, "error creating temporary passwd file for container %s", c.ID()) + return fmt.Errorf("error creating temporary passwd file for container %s: %w", c.ID(), err) } if newPasswd != "" { // Make /etc/passwd @@ -2213,7 +2213,7 @@ func (c *Container) makeBindMounts() error { if _, ok := c.state.BindMounts["/etc/hostname"]; !ok { hostnamePath, err := c.writeStringToRundir("hostname", c.Hostname()) if err != nil { - return errors.Wrapf(err, "error creating hostname file for container %s", c.ID()) + return fmt.Errorf("error creating hostname file for container %s: %w", c.ID(), err) } c.state.BindMounts["/etc/hostname"] = hostnamePath } @@ -2225,7 +2225,7 @@ func (c *Container) makeBindMounts() error { if ctrTimezone != "local" { _, err = time.LoadLocation(ctrTimezone) if err != nil { - return errors.Wrapf(err, "error finding timezone for container %s", c.ID()) + return fmt.Errorf("error finding timezone for container %s: %w", c.ID(), err) } } if _, ok := c.state.BindMounts["/etc/localtime"]; !ok { @@ -2233,18 +2233,18 @@ func (c *Container) makeBindMounts() error { if ctrTimezone == "local" { zonePath, err = filepath.EvalSymlinks("/etc/localtime") if err != nil { - return errors.Wrapf(err, "error finding local timezone for container %s", c.ID()) + return fmt.Errorf("error finding local timezone for container %s: %w", c.ID(), err) } } else { zone := filepath.Join("/usr/share/zoneinfo", ctrTimezone) zonePath, err = filepath.EvalSymlinks(zone) if err != nil { - return errors.Wrapf(err, "error setting timezone for container %s", c.ID()) + return fmt.Errorf("error setting timezone for container %s: %w", c.ID(), err) } } localtimePath, err := c.copyTimezoneFile(zonePath) if err != nil { - return errors.Wrapf(err, "error setting timezone for container %s", c.ID()) + return fmt.Errorf("error setting timezone for container %s: %w", c.ID(), err) } c.state.BindMounts["/etc/localtime"] = localtimePath } @@ -2282,7 +2282,7 @@ rootless=%d } containerenvPath, err := c.writeStringToRundir(".containerenv", containerenv) if err != nil { - return errors.Wrapf(err, "error creating containerenv file for container %s", c.ID()) + return fmt.Errorf("error creating containerenv file for container %s: %w", c.ID(), err) } c.state.BindMounts["/run/.containerenv"] = containerenvPath } @@ -2303,7 +2303,7 @@ rootless=%d if len(c.Secrets()) > 0 { // create /run/secrets if subscriptions did not create if err := c.createSecretMountDir(); err != nil { - return errors.Wrapf(err, "error creating secrets mount") + return fmt.Errorf("error creating secrets mount: %w", err) } for _, secret := range c.Secrets() { secretFileName := secret.Name @@ -2397,7 +2397,7 @@ func (c *Container) generateResolvConf() error { Path: destPath, Searches: search, }); err != nil { - return errors.Wrapf(err, "error building resolv.conf for container %s", c.ID()) + return fmt.Errorf("error building resolv.conf for container %s: %w", c.ID(), err) } return c.bindMountRootFile(destPath, resolvconf.DefaultResolvConf) @@ -2598,7 +2598,7 @@ func (c *Container) generateCurrentUserGroupEntry() (string, int, error) { g, err := user.LookupGroupId(strconv.Itoa(gid)) if err != nil { - return "", 0, errors.Wrapf(err, "failed to get current group") + return "", 0, fmt.Errorf("failed to get current group: %w", err) } // Look up group name to see if it exists in the image. @@ -2620,7 +2620,7 @@ func (c *Container) generateCurrentUserGroupEntry() (string, int, error) { if uid != 0 { u, err := user.LookupId(strconv.Itoa(uid)) if err != nil { - return "", 0, errors.Wrapf(err, "failed to get current user to make group entry") + return "", 0, fmt.Errorf("failed to get current user to make group entry: %w", err) } username = u.Username } @@ -2718,7 +2718,7 @@ func (c *Container) generateCurrentUserPasswdEntry() (string, int, int, error) { u, err := user.LookupId(strconv.Itoa(uid)) if err != nil { - return "", 0, 0, errors.Wrapf(err, "failed to get current user") + return "", 0, 0, fmt.Errorf("failed to get current user: %w", err) } pwd, err := c.userPasswdEntry(u) if err != nil { @@ -2820,7 +2820,7 @@ func (c *Container) generateUserPasswdEntry(addedUID int) (string, error) { } else { group, err := lookup.GetGroup(c.state.Mountpoint, groupspec) if err != nil { - return "", errors.Wrapf(err, "unable to get gid %s from group file", groupspec) + return "", fmt.Errorf("unable to get gid %s from group file: %w", groupspec, err) } gid = group.Gid } @@ -2929,7 +2929,7 @@ func (c *Container) generatePasswdAndGroup() (string, string, error) { logrus.Debugf("Making /etc/passwd for container %s", c.ID()) originPasswdFile, err := securejoin.SecureJoin(c.state.Mountpoint, "/etc/passwd") if err != nil { - return "", "", errors.Wrapf(err, "error creating path to container %s /etc/passwd", c.ID()) + return "", "", fmt.Errorf("error creating path to container %s /etc/passwd: %w", c.ID(), err) } orig, err := ioutil.ReadFile(originPasswdFile) if err != nil && !os.IsNotExist(err) { @@ -2937,7 +2937,7 @@ func (c *Container) generatePasswdAndGroup() (string, string, error) { } passwdFile, err := c.writeStringToStaticDir("passwd", string(orig)+passwdEntry) if err != nil { - return "", "", errors.Wrapf(err, "failed to create temporary passwd file") + return "", "", fmt.Errorf("failed to create temporary passwd file: %w", err) } if err := os.Chmod(passwdFile, 0644); err != nil { return "", "", err @@ -2947,17 +2947,17 @@ func (c *Container) generatePasswdAndGroup() (string, string, error) { logrus.Debugf("Modifying container %s /etc/passwd", c.ID()) containerPasswd, err := securejoin.SecureJoin(c.state.Mountpoint, "/etc/passwd") if err != nil { - return "", "", errors.Wrapf(err, "error looking up location of container %s /etc/passwd", c.ID()) + return "", "", fmt.Errorf("error looking up location of container %s /etc/passwd: %w", c.ID(), err) } f, err := os.OpenFile(containerPasswd, os.O_APPEND|os.O_WRONLY, 0600) if err != nil { - return "", "", errors.Wrapf(err, "container %s", c.ID()) + return "", "", fmt.Errorf("container %s: %w", c.ID(), err) } defer f.Close() if _, err := f.WriteString(passwdEntry); err != nil { - return "", "", errors.Wrapf(err, "unable to append to container %s /etc/passwd", c.ID()) + return "", "", fmt.Errorf("unable to append to container %s /etc/passwd: %w", c.ID(), err) } default: logrus.Debugf("Not modifying container %s /etc/passwd", c.ID()) @@ -2975,7 +2975,7 @@ func (c *Container) generatePasswdAndGroup() (string, string, error) { logrus.Debugf("Making /etc/group for container %s", c.ID()) originGroupFile, err := securejoin.SecureJoin(c.state.Mountpoint, "/etc/group") if err != nil { - return "", "", errors.Wrapf(err, "error creating path to container %s /etc/group", c.ID()) + return "", "", fmt.Errorf("error creating path to container %s /etc/group: %w", c.ID(), err) } orig, err := ioutil.ReadFile(originGroupFile) if err != nil && !os.IsNotExist(err) { @@ -2983,7 +2983,7 @@ func (c *Container) generatePasswdAndGroup() (string, string, error) { } groupFile, err := c.writeStringToStaticDir("group", string(orig)+groupEntry) if err != nil { - return "", "", errors.Wrapf(err, "failed to create temporary group file") + return "", "", fmt.Errorf("failed to create temporary group file: %w", err) } if err := os.Chmod(groupFile, 0644); err != nil { return "", "", err @@ -2993,17 +2993,17 @@ func (c *Container) generatePasswdAndGroup() (string, string, error) { logrus.Debugf("Modifying container %s /etc/group", c.ID()) containerGroup, err := securejoin.SecureJoin(c.state.Mountpoint, "/etc/group") if err != nil { - return "", "", errors.Wrapf(err, "error looking up location of container %s /etc/group", c.ID()) + return "", "", fmt.Errorf("error looking up location of container %s /etc/group: %w", c.ID(), err) } f, err := os.OpenFile(containerGroup, os.O_APPEND|os.O_WRONLY, 0600) if err != nil { - return "", "", errors.Wrapf(err, "container %s", c.ID()) + return "", "", fmt.Errorf("container %s: %w", c.ID(), err) } defer f.Close() if _, err := f.WriteString(groupEntry); err != nil { - return "", "", errors.Wrapf(err, "unable to append to container %s /etc/group", c.ID()) + return "", "", fmt.Errorf("unable to append to container %s /etc/group: %w", c.ID(), err) } default: logrus.Debugf("Not modifying container %s /etc/group", c.ID()) @@ -3038,7 +3038,7 @@ func (c *Container) expectPodCgroup() (bool, error) { case cgroupManager == config.CgroupfsCgroupsManager: return !rootless.IsRootless(), nil default: - return false, errors.Wrapf(define.ErrInvalidArg, "invalid cgroup mode %s requested for pods", cgroupManager) + return false, fmt.Errorf("invalid cgroup mode %s requested for pods: %w", cgroupManager, define.ErrInvalidArg) } } @@ -3075,7 +3075,7 @@ func (c *Container) getOCICgroupPath() (string, error) { logrus.Debugf("Setting Cgroup path for container %s to %s", c.ID(), cgroupPath) return cgroupPath, nil default: - return "", errors.Wrapf(define.ErrInvalidArg, "invalid cgroup manager %s requested", cgroupManager) + return "", fmt.Errorf("invalid cgroup manager %s requested: %w", cgroupManager, define.ErrInvalidArg) } } @@ -3086,7 +3086,7 @@ func (c *Container) copyTimezoneFile(zonePath string) (string, error) { return "", err } if file.IsDir() { - return "", errors.New("Invalid timezone: is a directory") + return "", errors.New("invalid timezone: is a directory") } src, err := os.Open(zonePath) if err != nil { @@ -3120,14 +3120,14 @@ func (c *Container) cleanupOverlayMounts() error { func (c *Container) checkFileExistsInRootfs(file string) (bool, error) { checkPath, err := securejoin.SecureJoin(c.state.Mountpoint, file) if err != nil { - return false, errors.Wrapf(err, "cannot create path to container %s file %q", c.ID(), file) + return false, fmt.Errorf("cannot create path to container %s file %q: %w", c.ID(), file, err) } stat, err := os.Stat(checkPath) if err != nil { if os.IsNotExist(err) { return false, nil } - return false, errors.Wrapf(err, "container %s", c.ID()) + return false, fmt.Errorf("container %s: %w", c.ID(), err) } if stat.IsDir() { return false, nil @@ -3163,7 +3163,7 @@ func (c *Container) createSecretMountDir() error { func (c *Container) fixVolumePermissions(v *ContainerNamedVolume) error { vol, err := c.runtime.state.Volume(v.Name) if err != nil { - return errors.Wrapf(err, "error retrieving named volume %s for container %s", v.Name, c.ID()) + return fmt.Errorf("error retrieving named volume %s for container %s: %w", v.Name, c.ID(), err) } vol.lock.Lock() @@ -3190,7 +3190,7 @@ func (c *Container) fixVolumePermissions(v *ContainerNamedVolume) error { mappings := idtools.NewIDMappingsFromMaps(c.config.IDMappings.UIDMap, c.config.IDMappings.GIDMap) newPair, err := mappings.ToHost(p) if err != nil { - return errors.Wrapf(err, "error mapping user %d:%d", uid, gid) + return fmt.Errorf("error mapping user %d:%d: %w", uid, gid, err) } uid = newPair.UID gid = newPair.GID diff --git a/libpod/container_log.go b/libpod/container_log.go index da6d51670..a9e0fe065 100644 --- a/libpod/container_log.go +++ b/libpod/container_log.go @@ -2,6 +2,7 @@ package libpod import ( "context" + "errors" "fmt" "os" "time" @@ -10,7 +11,6 @@ import ( "github.com/containers/podman/v4/libpod/events" "github.com/containers/podman/v4/libpod/logs" "github.com/nxadm/tail/watch" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -35,9 +35,9 @@ func (r *Runtime) Log(ctx context.Context, containers []*Container, options *log func (c *Container) ReadLog(ctx context.Context, options *logs.LogOptions, logChannel chan *logs.LogLine, colorID int64) error { switch c.LogDriver() { case define.PassthroughLogging: - return errors.Wrapf(define.ErrNoLogs, "this container is using the 'passthrough' log driver, cannot read logs") + return fmt.Errorf("this container is using the 'passthrough' log driver, cannot read logs: %w", define.ErrNoLogs) case define.NoLogging: - return errors.Wrapf(define.ErrNoLogs, "this container is using the 'none' log driver, cannot read logs") + return fmt.Errorf("this container is using the 'none' log driver, cannot read logs: %w", define.ErrNoLogs) case define.JournaldLogging: return c.readFromJournal(ctx, options, logChannel, colorID) case define.JSONLogging: @@ -47,7 +47,7 @@ func (c *Container) ReadLog(ctx context.Context, options *logs.LogOptions, logCh case define.KubernetesLogging, "": return c.readFromLogFile(ctx, options, logChannel, colorID) default: - return errors.Wrapf(define.ErrInternal, "unrecognized log driver %q, cannot read logs", c.LogDriver()) + return fmt.Errorf("unrecognized log driver %q, cannot read logs: %w", c.LogDriver(), define.ErrInternal) } } @@ -55,10 +55,10 @@ func (c *Container) readFromLogFile(ctx context.Context, options *logs.LogOption t, tailLog, err := logs.GetLogFile(c.LogPath(), options) if err != nil { // If the log file does not exist, this is not fatal. - if os.IsNotExist(errors.Cause(err)) { + if errors.Is(err, os.ErrNotExist) { return nil } - return errors.Wrapf(err, "unable to read log file %s for %s ", c.ID(), c.LogPath()) + return fmt.Errorf("unable to read log file %s for %s : %w", c.ID(), c.LogPath(), err) } options.WaitGroup.Add(1) if len(tailLog) > 0 { @@ -103,7 +103,7 @@ func (c *Container) readFromLogFile(ctx context.Context, options *logs.LogOption // until EOF. state, err := c.State() if err != nil || state != define.ContainerStateRunning { - if err != nil && errors.Cause(err) != define.ErrNoSuchCtr { + if err != nil && !errors.Is(err, define.ErrNoSuchCtr) { logrus.Errorf("Getting container state: %v", err) } go func() { diff --git a/libpod/container_log_linux.go b/libpod/container_log_linux.go index 7f90332c7..0686caed2 100644 --- a/libpod/container_log_linux.go +++ b/libpod/container_log_linux.go @@ -5,6 +5,7 @@ package libpod import ( "context" + "errors" "fmt" "strings" "time" @@ -14,7 +15,6 @@ import ( "github.com/containers/podman/v4/libpod/logs" "github.com/coreos/go-systemd/v22/journal" "github.com/coreos/go-systemd/v22/sdjournal" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -49,7 +49,7 @@ func (c *Container) readFromJournal(ctx context.Context, options *logs.LogOption // We need the container's events in the same journal to guarantee // consistency, see #10323. if options.Follow && c.runtime.config.Engine.EventsLogger != "journald" { - return errors.Errorf("using --follow with the journald --log-driver but without the journald --events-backend (%s) is not supported", c.runtime.config.Engine.EventsLogger) + return fmt.Errorf("using --follow with the journald --log-driver but without the journald --events-backend (%s) is not supported", c.runtime.config.Engine.EventsLogger) } journal, err := sdjournal.NewJournal() @@ -63,21 +63,21 @@ func (c *Container) readFromJournal(ctx context.Context, options *logs.LogOption // Add the filters for events. match := sdjournal.Match{Field: "SYSLOG_IDENTIFIER", Value: "podman"} if err := journal.AddMatch(match.String()); err != nil { - return errors.Wrapf(err, "adding filter to journald logger: %v", match) + return fmt.Errorf("adding filter to journald logger: %v: %w", match, err) } match = sdjournal.Match{Field: "PODMAN_ID", Value: c.ID()} if err := journal.AddMatch(match.String()); err != nil { - return errors.Wrapf(err, "adding filter to journald logger: %v", match) + return fmt.Errorf("adding filter to journald logger: %v: %w", match, err) } // Add the filter for logs. Note the disjunction so that we match // either the events or the logs. if err := journal.AddDisjunction(); err != nil { - return errors.Wrap(err, "adding filter disjunction to journald logger") + return fmt.Errorf("adding filter disjunction to journald logger: %w", err) } match = sdjournal.Match{Field: "CONTAINER_ID_FULL", Value: c.ID()} if err := journal.AddMatch(match.String()); err != nil { - return errors.Wrapf(err, "adding filter to journald logger: %v", match) + return fmt.Errorf("adding filter to journald logger: %v: %w", match, err) } if err := journal.SeekHead(); err != nil { @@ -85,12 +85,12 @@ func (c *Container) readFromJournal(ctx context.Context, options *logs.LogOption } // API requires Next() immediately after SeekHead(). if _, err := journal.Next(); err != nil { - return errors.Wrap(err, "next journal") + return fmt.Errorf("next journal: %w", err) } // API requires a next|prev before getting a cursor. if _, err := journal.Previous(); err != nil { - return errors.Wrap(err, "previous journal") + return fmt.Errorf("previous journal: %w", err) } // Note that the initial cursor may not yet be ready, so we'll do an @@ -111,7 +111,7 @@ func (c *Container) readFromJournal(ctx context.Context, options *logs.LogOption break } if cursorError != nil { - return errors.Wrap(cursorError, "initial journal cursor") + return fmt.Errorf("initial journal cursor: %w", cursorError) } options.WaitGroup.Add(1) @@ -255,7 +255,7 @@ func journalFormatterWithID(entry *sdjournal.JournalEntry) (string, error) { id, ok := entry.Fields["CONTAINER_ID_FULL"] if !ok { - return "", fmt.Errorf("no CONTAINER_ID_FULL field present in journal entry") + return "", errors.New("no CONTAINER_ID_FULL field present in journal entry") } if len(id) > 12 { id = id[:12] @@ -290,7 +290,7 @@ func formatterPrefix(entry *sdjournal.JournalEntry) (string, error) { output := fmt.Sprintf("%s ", tsString) priority, ok := entry.Fields["PRIORITY"] if !ok { - return "", errors.Errorf("no PRIORITY field present in journal entry") + return "", errors.New("no PRIORITY field present in journal entry") } switch priority { case journaldLogOut: @@ -298,7 +298,7 @@ func formatterPrefix(entry *sdjournal.JournalEntry) (string, error) { case journaldLogErr: output += "stderr " default: - return "", errors.Errorf("unexpected PRIORITY field in journal entry") + return "", errors.New("unexpected PRIORITY field in journal entry") } // if CONTAINER_PARTIAL_MESSAGE is defined, the log type is "P" @@ -315,7 +315,7 @@ func formatterMessage(entry *sdjournal.JournalEntry) (string, error) { // Finally, append the message msg, ok := entry.Fields["MESSAGE"] if !ok { - return "", fmt.Errorf("no MESSAGE field present in journal entry") + return "", errors.New("no MESSAGE field present in journal entry") } msg = strings.TrimSuffix(msg, "\n") return msg, nil diff --git a/libpod/container_log_unsupported.go b/libpod/container_log_unsupported.go index c84a578cc..bb74a810d 100644 --- a/libpod/container_log_unsupported.go +++ b/libpod/container_log_unsupported.go @@ -5,16 +5,16 @@ package libpod import ( "context" + "fmt" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/libpod/logs" - "github.com/pkg/errors" ) func (c *Container) readFromJournal(_ context.Context, _ *logs.LogOptions, _ chan *logs.LogLine, colorID int64) error { - return errors.Wrapf(define.ErrOSNotSupported, "Journald logging only enabled with systemd on linux") + return fmt.Errorf("journald logging only enabled with systemd on linux: %w", define.ErrOSNotSupported) } func (c *Container) initializeJournal(ctx context.Context) error { - return errors.Wrapf(define.ErrOSNotSupported, "Journald logging only enabled with systemd on linux") + return fmt.Errorf("journald logging only enabled with systemd on linux: %w", define.ErrOSNotSupported) } diff --git a/libpod/container_path_resolution.go b/libpod/container_path_resolution.go index 80a3749f5..35622d623 100644 --- a/libpod/container_path_resolution.go +++ b/libpod/container_path_resolution.go @@ -1,12 +1,12 @@ package libpod import ( + "fmt" "path/filepath" "strings" securejoin "github.com/cyphar/filepath-securejoin" "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -65,7 +65,7 @@ func (c *Container) resolvePath(mountPoint string, containerPath string) (string return "", "", err } if mountPoint == "" { - return "", "", errors.Errorf("volume %s is not mounted, cannot copy into it", volume.Name()) + return "", "", fmt.Errorf("volume %s is not mounted, cannot copy into it", volume.Name()) } // We found a matching volume for searchPath. We now diff --git a/libpod/container_stat_linux.go b/libpod/container_stat_linux.go index bbe3edbb3..72aabb516 100644 --- a/libpod/container_stat_linux.go +++ b/libpod/container_stat_linux.go @@ -4,6 +4,8 @@ package libpod import ( + "errors" + "fmt" "os" "path/filepath" "strings" @@ -11,7 +13,6 @@ import ( "github.com/containers/buildah/copier" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/copy" - "github.com/pkg/errors" ) // statInsideMount stats the specified path *inside* the container's mount and PID @@ -150,10 +151,10 @@ func secureStat(root string, path string) (*copier.StatForItem, error) { } if len(globStats) != 1 { - return nil, errors.Errorf("internal error: secureStat: expected 1 item but got %d", len(globStats)) + return nil, fmt.Errorf("internal error: secureStat: expected 1 item but got %d", len(globStats)) } if len(globStats) != 1 { - return nil, errors.Errorf("internal error: secureStat: expected 1 result but got %d", len(globStats[0].Results)) + return nil, fmt.Errorf("internal error: secureStat: expected 1 result but got %d", len(globStats[0].Results)) } // NOTE: the key in the map differ from `glob` when hitting symlink. @@ -167,7 +168,7 @@ func secureStat(root string, path string) (*copier.StatForItem, error) { if stat.IsSymlink { target, err := copier.Eval(root, path, copier.EvalOptions{}) if err != nil { - return nil, errors.Wrap(err, "error evaluating symlink in container") + return nil, fmt.Errorf("error evaluating symlink in container: %w", err) } // Need to make sure the symlink is relative to the root! target = strings.TrimPrefix(target, root) diff --git a/libpod/container_top_linux.go b/libpod/container_top_linux.go index b30e0c732..5571edf73 100644 --- a/libpod/container_top_linux.go +++ b/libpod/container_top_linux.go @@ -5,6 +5,7 @@ package libpod import ( "bufio" + "errors" "fmt" "os" "strconv" @@ -14,7 +15,6 @@ import ( "github.com/containers/podman/v4/pkg/rootless" "github.com/containers/psgo" "github.com/google/shlex" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -22,15 +22,15 @@ import ( // []string for output func (c *Container) Top(descriptors []string) ([]string, error) { if c.config.NoCgroups { - return nil, errors.Wrapf(define.ErrNoCgroups, "cannot run top on container %s as it did not create a cgroup", c.ID()) + return nil, fmt.Errorf("cannot run top on container %s as it did not create a cgroup: %w", c.ID(), define.ErrNoCgroups) } conStat, err := c.State() if err != nil { - return nil, errors.Wrapf(err, "unable to look up state for %s", c.ID()) + return nil, fmt.Errorf("unable to look up state for %s: %w", c.ID(), err) } if conStat != define.ContainerStateRunning { - return nil, errors.Errorf("top can only be used on running containers") + return nil, errors.New("top can only be used on running containers") } // Also support comma-separated input. @@ -59,7 +59,7 @@ func (c *Container) Top(descriptors []string) ([]string, error) { for _, d := range descriptors { shSplit, err := shlex.Split(d) if err != nil { - return nil, fmt.Errorf("parsing ps args: %v", err) + return nil, fmt.Errorf("parsing ps args: %w", err) } for _, s := range shSplit { if s != "" { @@ -70,7 +70,7 @@ func (c *Container) Top(descriptors []string) ([]string, error) { output, err = c.execPS(psDescriptors) if err != nil { - return nil, errors.Wrapf(err, "error executing ps(1) in the container") + return nil, fmt.Errorf("error executing ps(1) in the container: %w", err) } // Trick: filter the ps command from the output instead of @@ -157,7 +157,7 @@ func (c *Container) execPS(args []string) ([]string, error) { if err != nil { return nil, err } else if ec != 0 { - return nil, errors.Errorf("Runtime failed with exit status: %d and output: %s", ec, strings.Join(stderr, " ")) + return nil, fmt.Errorf("runtime failed with exit status: %d and output: %s", ec, strings.Join(stderr, " ")) } if logrus.GetLevel() >= logrus.DebugLevel { diff --git a/libpod/container_validate.go b/libpod/container_validate.go index cfbdd2b1e..e280c60d2 100644 --- a/libpod/container_validate.go +++ b/libpod/container_validate.go @@ -5,7 +5,6 @@ import ( "github.com/containers/podman/v4/libpod/define" spec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" ) // Validate that the configuration of a container is valid. @@ -16,17 +15,17 @@ func (c *Container) validate() error { // If one of RootfsImageIDor RootfsImageName are set, both must be set. if (imageIDSet || imageNameSet) && !(imageIDSet && imageNameSet) { - return errors.Wrapf(define.ErrInvalidArg, "both RootfsImageName and RootfsImageID must be set if either is set") + return fmt.Errorf("both RootfsImageName and RootfsImageID must be set if either is set: %w", define.ErrInvalidArg) } // Cannot set RootfsImageID and Rootfs at the same time if imageIDSet && rootfsSet { - return errors.Wrapf(define.ErrInvalidArg, "cannot set both an image ID and rootfs for a container") + return fmt.Errorf("cannot set both an image ID and rootfs for a container: %w", define.ErrInvalidArg) } // Must set at least one of RootfsImageID or Rootfs if !(imageIDSet || rootfsSet) { - return errors.Wrapf(define.ErrInvalidArg, "must set root filesystem source to either image or rootfs") + return fmt.Errorf("must set root filesystem source to either image or rootfs: %w", define.ErrInvalidArg) } // A container cannot be marked as an infra and service container at @@ -38,62 +37,62 @@ func (c *Container) validate() error { // Cannot make a network namespace if we are joining another container's // network namespace if c.config.CreateNetNS && c.config.NetNsCtr != "" { - return errors.Wrapf(define.ErrInvalidArg, "cannot both create a network namespace and join another container's network namespace") + return fmt.Errorf("cannot both create a network namespace and join another container's network namespace: %w", define.ErrInvalidArg) } if c.config.CgroupsMode == cgroupSplit && c.config.CgroupParent != "" { - return errors.Wrapf(define.ErrInvalidArg, "cannot specify --cgroup-mode=split with a cgroup-parent") + return fmt.Errorf("cannot specify --cgroup-mode=split with a cgroup-parent: %w", define.ErrInvalidArg) } // Not creating cgroups has a number of requirements, mostly related to // the PID namespace. if c.config.NoCgroups || c.config.CgroupsMode == "disabled" { if c.config.PIDNsCtr != "" { - return errors.Wrapf(define.ErrInvalidArg, "cannot join another container's PID namespace if not creating cgroups") + return fmt.Errorf("cannot join another container's PID namespace if not creating cgroups: %w", define.ErrInvalidArg) } if c.config.CgroupParent != "" { - return errors.Wrapf(define.ErrInvalidArg, "cannot set cgroup parent if not creating cgroups") + return fmt.Errorf("cannot set cgroup parent if not creating cgroups: %w", define.ErrInvalidArg) } // Ensure we have a PID namespace if c.config.Spec.Linux == nil { - return errors.Wrapf(define.ErrInvalidArg, "must provide Linux namespace configuration in OCI spec when using NoCgroups") + return fmt.Errorf("must provide Linux namespace configuration in OCI spec when using NoCgroups: %w", define.ErrInvalidArg) } foundPid := false for _, ns := range c.config.Spec.Linux.Namespaces { if ns.Type == spec.PIDNamespace { foundPid = true if ns.Path != "" { - return errors.Wrapf(define.ErrInvalidArg, "containers not creating Cgroups must create a private PID namespace - cannot use another") + return fmt.Errorf("containers not creating Cgroups must create a private PID namespace - cannot use another: %w", define.ErrInvalidArg) } break } } if !foundPid { - return errors.Wrapf(define.ErrInvalidArg, "containers not creating Cgroups must create a private PID namespace") + return fmt.Errorf("containers not creating Cgroups must create a private PID namespace: %w", define.ErrInvalidArg) } } // Can only set static IP or MAC is creating a network namespace. if !c.config.CreateNetNS && (c.config.StaticIP != nil || c.config.StaticMAC != nil) { - return errors.Wrapf(define.ErrInvalidArg, "cannot set static IP or MAC address if not creating a network namespace") + return fmt.Errorf("cannot set static IP or MAC address if not creating a network namespace: %w", define.ErrInvalidArg) } // Cannot set static IP or MAC if joining >1 CNI network. if len(c.config.Networks) > 1 && (c.config.StaticIP != nil || c.config.StaticMAC != nil) { - return errors.Wrapf(define.ErrInvalidArg, "cannot set static IP or MAC address if joining more than one network") + return fmt.Errorf("cannot set static IP or MAC address if joining more than one network: %w", define.ErrInvalidArg) } // Using image resolv.conf conflicts with various DNS settings. if c.config.UseImageResolvConf && (len(c.config.DNSSearch) > 0 || len(c.config.DNSServer) > 0 || len(c.config.DNSOption) > 0) { - return errors.Wrapf(define.ErrInvalidArg, "cannot configure DNS options if using image's resolv.conf") + return fmt.Errorf("cannot configure DNS options if using image's resolv.conf: %w", define.ErrInvalidArg) } if c.config.UseImageHosts && len(c.config.HostAdd) > 0 { - return errors.Wrapf(define.ErrInvalidArg, "cannot add to /etc/hosts if using image's /etc/hosts") + return fmt.Errorf("cannot add to /etc/hosts if using image's /etc/hosts: %w", define.ErrInvalidArg) } // Check named volume, overlay volume and image volume destination conflist @@ -102,7 +101,7 @@ func (c *Container) validate() error { // Don't check if they already exist. // If they don't we will automatically create them. if _, ok := destinations[vol.Dest]; ok { - return errors.Wrapf(define.ErrInvalidArg, "two volumes found with destination %s", vol.Dest) + return fmt.Errorf("two volumes found with destination %s: %w", vol.Dest, define.ErrInvalidArg) } destinations[vol.Dest] = true } @@ -110,7 +109,7 @@ func (c *Container) validate() error { // Don't check if they already exist. // If they don't we will automatically create them. if _, ok := destinations[vol.Dest]; ok { - return errors.Wrapf(define.ErrInvalidArg, "two volumes found with destination %s", vol.Dest) + return fmt.Errorf("two volumes found with destination %s: %w", vol.Dest, define.ErrInvalidArg) } destinations[vol.Dest] = true } @@ -118,7 +117,7 @@ func (c *Container) validate() error { // Don't check if they already exist. // If they don't we will automatically create them. if _, ok := destinations[vol.Dest]; ok { - return errors.Wrapf(define.ErrInvalidArg, "two volumes found with destination %s", vol.Dest) + return fmt.Errorf("two volumes found with destination %s: %w", vol.Dest, define.ErrInvalidArg) } destinations[vol.Dest] = true } @@ -126,13 +125,13 @@ func (c *Container) validate() error { // If User in the OCI spec is set, require that c.config.User is set for // security reasons (a lot of our code relies on c.config.User). if c.config.User == "" && (c.config.Spec.Process.User.UID != 0 || c.config.Spec.Process.User.GID != 0) { - return errors.Wrapf(define.ErrInvalidArg, "please set User explicitly via WithUser() instead of in OCI spec directly") + return fmt.Errorf("please set User explicitly via WithUser() instead of in OCI spec directly: %w", define.ErrInvalidArg) } // Init-ctrs must be used inside a Pod. Check if a init container type is // passed and if no pod is passed if len(c.config.InitContainerType) > 0 && len(c.config.Pod) < 1 { - return errors.Wrap(define.ErrInvalidArg, "init containers must be created in a pod") + return fmt.Errorf("init containers must be created in a pod: %w", define.ErrInvalidArg) } return nil } diff --git a/libpod/define/containerstate.go b/libpod/define/containerstate.go index 9ad3aec08..00080ef37 100644 --- a/libpod/define/containerstate.go +++ b/libpod/define/containerstate.go @@ -1,9 +1,8 @@ package define import ( + "fmt" "time" - - "github.com/pkg/errors" ) // ContainerStatus represents the current state of a container @@ -91,7 +90,7 @@ func StringToContainerStatus(status string) (ContainerStatus, error) { case ContainerStateRemoving.String(): return ContainerStateRemoving, nil default: - return ContainerStateUnknown, errors.Wrapf(ErrInvalidArg, "unknown container state: %s", status) + return ContainerStateUnknown, fmt.Errorf("unknown container state: %s: %w", status, ErrInvalidArg) } } diff --git a/libpod/define/errors.go b/libpod/define/errors.go index 9757a85b1..b858e1989 100644 --- a/libpod/define/errors.go +++ b/libpod/define/errors.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/containers/common/libnetwork/types" + "github.com/containers/common/pkg/util" ) var ( @@ -92,7 +93,7 @@ var ( // ErrDetach indicates that an attach session was manually detached by // the user. - ErrDetach = errors.New("detached from container") + ErrDetach = util.ErrDetach // ErrWillDeadlock indicates that the requested operation will cause a // deadlock. This is usually caused by upgrade issues, and is resolved diff --git a/libpod/define/exec_codes.go b/libpod/define/exec_codes.go index f94616b33..3f2da4910 100644 --- a/libpod/define/exec_codes.go +++ b/libpod/define/exec_codes.go @@ -1,9 +1,9 @@ package define import ( + "errors" "strings" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -23,10 +23,10 @@ const ( // has a predefined exit code associated. If so, it returns that, otherwise it returns // the exit code originally stated in libpod.Exec() func TranslateExecErrorToExitCode(originalEC int, err error) int { - if errors.Cause(err) == ErrOCIRuntimePermissionDenied { + if errors.Is(err, ErrOCIRuntimePermissionDenied) { return ExecErrorCodeCannotInvoke } - if errors.Cause(err) == ErrOCIRuntimeNotFound { + if errors.Is(err, ErrOCIRuntimeNotFound) { return ExecErrorCodeNotFound } return originalEC diff --git a/libpod/define/healthchecks.go b/libpod/define/healthchecks.go index bde449d30..f71274350 100644 --- a/libpod/define/healthchecks.go +++ b/libpod/define/healthchecks.go @@ -47,3 +47,13 @@ const ( // DefaultHealthCheckTimeout default value DefaultHealthCheckTimeout = "30s" ) + +// HealthConfig.Test options +const ( + // HealthConfigTestNone disables healthcheck + HealthConfigTestNone = "NONE" + // HealthConfigTestCmd execs arguments directly + HealthConfigTestCmd = "CMD" + // HealthConfigTestCmdShell runs commands with the system's default shell + HealthConfigTestCmdShell = "CMD-SHELL" +) diff --git a/libpod/define/pod_inspect.go b/libpod/define/pod_inspect.go index c387856e5..2afef48c4 100644 --- a/libpod/define/pod_inspect.go +++ b/libpod/define/pod_inspect.go @@ -69,6 +69,8 @@ type InspectPodData struct { VolumesFrom []string `json:"volumes_from,omitempty"` // SecurityOpt contains the specified security labels and related SELinux information SecurityOpts []string `json:"security_opt,omitempty"` + // MemoryLimit contains the specified cgroup memory limit for the pod + MemoryLimit uint64 `json:"memory_limit,omitempty"` } // InspectPodInfraConfig contains the configuration of the pod's infra @@ -120,6 +122,8 @@ type InspectPodInfraConfig struct { PidNS string `json:"pid_ns,omitempty"` // UserNS is the usernamespace that all the containers in the pod will join. UserNS string `json:"userns,omitempty"` + // UtsNS is the uts namespace that all containers in the pod will join + UtsNS string `json:"uts_ns,omitempty"` } // InspectPodContainerInfo contains information on a container in a pod. diff --git a/libpod/define/terminal.go b/libpod/define/terminal.go deleted file mode 100644 index ce8955544..000000000 --- a/libpod/define/terminal.go +++ /dev/null @@ -1,7 +0,0 @@ -package define - -// TerminalSize represents the width and height of a terminal. -type TerminalSize struct { - Width uint16 - Height uint16 -} diff --git a/libpod/diff.go b/libpod/diff.go index 86fa063ec..8f0ad9355 100644 --- a/libpod/diff.go +++ b/libpod/diff.go @@ -1,10 +1,11 @@ package libpod import ( + "fmt" + "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/libpod/layers" "github.com/containers/storage/pkg/archive" - "github.com/pkg/errors" ) var initInodes = map[string]bool{ @@ -76,5 +77,5 @@ func (r *Runtime) getLayerID(id string, diffType define.DiffType) (string, error } lastErr = err } - return "", errors.Wrapf(lastErr, "%s not found", id) + return "", fmt.Errorf("%s not found: %w", id, lastErr) } diff --git a/libpod/events.go b/libpod/events.go index bb50df92d..c9e4c9d26 100644 --- a/libpod/events.go +++ b/libpod/events.go @@ -6,7 +6,6 @@ import ( "sync" "github.com/containers/podman/v4/libpod/events" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -178,7 +177,7 @@ func (r *Runtime) GetLastContainerEvent(ctx context.Context, nameOrID string, co return nil, err } if len(containerEvents) < 1 { - return nil, errors.Wrapf(events.ErrEventNotFound, "%s not found", containerEvent.String()) + return nil, fmt.Errorf("%s not found: %w", containerEvent.String(), events.ErrEventNotFound) } // return the last element in the slice return containerEvents[len(containerEvents)-1], nil @@ -201,7 +200,7 @@ func (r *Runtime) GetExecDiedEvent(ctx context.Context, nameOrID, execSessionID // There *should* only be one event maximum. // But... just in case... let's not blow up if there's more than one. if len(containerEvents) < 1 { - return nil, errors.Wrapf(events.ErrEventNotFound, "exec died event for session %s (container %s) not found", execSessionID, nameOrID) + return nil, fmt.Errorf("exec died event for session %s (container %s) not found: %w", execSessionID, nameOrID, events.ErrEventNotFound) } return containerEvents[len(containerEvents)-1], nil } diff --git a/libpod/events/config.go b/libpod/events/config.go index a678baa2d..4ea45a00e 100644 --- a/libpod/events/config.go +++ b/libpod/events/config.go @@ -2,9 +2,8 @@ package events import ( "context" + "errors" "time" - - "github.com/pkg/errors" ) // EventerType ... diff --git a/libpod/events/events.go b/libpod/events/events.go index a8001ab95..764481e51 100644 --- a/libpod/events/events.go +++ b/libpod/events/events.go @@ -2,16 +2,16 @@ package events import ( "encoding/json" + "errors" "fmt" "time" "github.com/containers/storage/pkg/stringid" - "github.com/pkg/errors" ) // ErrNoJournaldLogging indicates that there is no journald logging // supported (requires libsystemd) -var ErrNoJournaldLogging = errors.New("No support for journald logging") +var ErrNoJournaldLogging = errors.New("no support for journald logging") // String returns a string representation of EventerType func (et EventerType) String() string { @@ -140,7 +140,7 @@ func StringToType(name string) (Type, error) { case "": return "", ErrEventTypeBlank } - return "", errors.Errorf("unknown event type %q", name) + return "", fmt.Errorf("unknown event type %q", name) } // StringToStatus converts a string to an Event Status @@ -225,5 +225,5 @@ func StringToStatus(name string) (Status, error) { case Untag.String(): return Untag, nil } - return "", errors.Errorf("unknown event status %q", name) + return "", fmt.Errorf("unknown event status %q", name) } diff --git a/libpod/events/events_linux.go b/libpod/events/events_linux.go index 4320f2190..e7801af5b 100644 --- a/libpod/events/events_linux.go +++ b/libpod/events/events_linux.go @@ -1,9 +1,9 @@ package events import ( + "fmt" "strings" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -14,7 +14,7 @@ func NewEventer(options EventerOptions) (Eventer, error) { case strings.ToUpper(Journald.String()): eventer, err := newEventJournalD(options) if err != nil { - return nil, errors.Wrapf(err, "eventer creation") + return nil, fmt.Errorf("eventer creation: %w", err) } return eventer, nil case strings.ToUpper(LogFile.String()): @@ -24,6 +24,6 @@ func NewEventer(options EventerOptions) (Eventer, error) { case strings.ToUpper(Memory.String()): return NewMemoryEventer(), nil default: - return nil, errors.Errorf("unknown event logger type: %s", strings.ToUpper(options.EventerType)) + return nil, fmt.Errorf("unknown event logger type: %s", strings.ToUpper(options.EventerType)) } } diff --git a/libpod/events/events_unsupported.go b/libpod/events/events_unsupported.go index 25c175524..d766402a9 100644 --- a/libpod/events/events_unsupported.go +++ b/libpod/events/events_unsupported.go @@ -3,7 +3,7 @@ package events -import "github.com/pkg/errors" +import "errors" // NewEventer creates an eventer based on the eventer type func NewEventer(options EventerOptions) (Eventer, error) { diff --git a/libpod/events/filters.go b/libpod/events/filters.go index 64c162db2..d5b96e7ec 100644 --- a/libpod/events/filters.go +++ b/libpod/events/filters.go @@ -1,11 +1,11 @@ package events import ( + "fmt" "strings" "time" "github.com/containers/podman/v4/pkg/util" - "github.com/pkg/errors" ) func generateEventFilter(filter, filterValue string) (func(e *Event) bool, error) { @@ -74,7 +74,7 @@ func generateEventFilter(filter, filterValue string) (func(e *Event) bool, error return found }, nil } - return nil, errors.Errorf("%s is an invalid filter", filter) + return nil, fmt.Errorf("%s is an invalid filter", filter) } func generateEventSinceOption(timeSince time.Time) func(e *Event) bool { @@ -92,7 +92,7 @@ func generateEventUntilOption(timeUntil time.Time) func(e *Event) bool { func parseFilter(filter string) (string, string, error) { filterSplit := strings.SplitN(filter, "=", 2) if len(filterSplit) != 2 { - return "", "", errors.Errorf("%s is an invalid filter", filter) + return "", "", fmt.Errorf("%s is an invalid filter", filter) } return filterSplit[0], filterSplit[1], nil } @@ -137,7 +137,7 @@ func generateEventFilters(filters []string, since, until string) (map[string][]E if len(since) > 0 { timeSince, err := util.ParseInputTime(since, true) if err != nil { - return nil, errors.Wrapf(err, "unable to convert since time of %s", since) + return nil, fmt.Errorf("unable to convert since time of %s: %w", since, err) } filterFunc := generateEventSinceOption(timeSince) filterMap["since"] = []EventFilter{filterFunc} @@ -146,7 +146,7 @@ func generateEventFilters(filters []string, since, until string) (map[string][]E if len(until) > 0 { timeUntil, err := util.ParseInputTime(until, false) if err != nil { - return nil, errors.Wrapf(err, "unable to convert until time of %s", until) + return nil, fmt.Errorf("unable to convert until time of %s: %w", until, err) } filterFunc := generateEventUntilOption(timeUntil) filterMap["until"] = []EventFilter{filterFunc} diff --git a/libpod/events/journal_linux.go b/libpod/events/journal_linux.go index 036638d34..0a0a768d0 100644 --- a/libpod/events/journal_linux.go +++ b/libpod/events/journal_linux.go @@ -6,13 +6,14 @@ package events import ( "context" "encoding/json" + "errors" + "fmt" "strconv" "time" "github.com/containers/podman/v4/pkg/util" "github.com/coreos/go-systemd/v22/journal" "github.com/coreos/go-systemd/v22/sdjournal" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -73,7 +74,7 @@ func (e EventJournalD) Read(ctx context.Context, options ReadOptions) error { defer close(options.EventChannel) filterMap, err := generateEventFilters(options.Filters, options.Since, options.Until) if err != nil { - return errors.Wrapf(err, "failed to parse event filters") + return fmt.Errorf("failed to parse event filters: %w", err) } var untilTime time.Time @@ -96,29 +97,29 @@ func (e EventJournalD) Read(ctx context.Context, options ReadOptions) error { // match only podman journal entries podmanJournal := sdjournal.Match{Field: "SYSLOG_IDENTIFIER", Value: "podman"} if err := j.AddMatch(podmanJournal.String()); err != nil { - return errors.Wrap(err, "failed to add journal filter for event log") + return fmt.Errorf("failed to add journal filter for event log: %w", err) } if len(options.Since) == 0 && len(options.Until) == 0 && options.Stream { if err := j.SeekTail(); err != nil { - return errors.Wrap(err, "failed to seek end of journal") + return fmt.Errorf("failed to seek end of journal: %w", err) } // After SeekTail calling Next moves to a random entry. // To prevent this we have to call Previous first. // see: https://bugs.freedesktop.org/show_bug.cgi?id=64614 if _, err := j.Previous(); err != nil { - return errors.Wrap(err, "failed to move journal cursor to previous entry") + return fmt.Errorf("failed to move journal cursor to previous entry: %w", err) } } // the api requires a next|prev before getting a cursor if _, err := j.Next(); err != nil { - return errors.Wrap(err, "failed to move journal cursor to next entry") + return fmt.Errorf("failed to move journal cursor to next entry: %w", err) } prevCursor, err := j.GetCursor() if err != nil { - return errors.Wrap(err, "failed to get journal cursor") + return fmt.Errorf("failed to get journal cursor: %w", err) } for { select { @@ -130,11 +131,11 @@ func (e EventJournalD) Read(ctx context.Context, options ReadOptions) error { } if _, err := j.Next(); err != nil { - return errors.Wrap(err, "failed to move journal cursor to next entry") + return fmt.Errorf("failed to move journal cursor to next entry: %w", err) } newCursor, err := j.GetCursor() if err != nil { - return errors.Wrap(err, "failed to get journal cursor") + return fmt.Errorf("failed to get journal cursor: %w", err) } if prevCursor == newCursor { if !options.Stream || (len(options.Until) > 0 && time.Now().After(untilTime)) { @@ -151,14 +152,14 @@ func (e EventJournalD) Read(ctx context.Context, options ReadOptions) error { entry, err := j.GetEntry() if err != nil { - return errors.Wrap(err, "failed to read journal entry") + return fmt.Errorf("failed to read journal entry: %w", err) } newEvent, err := newEventFromJournalEntry(entry) if err != nil { // We can't decode this event. // Don't fail hard - that would make events unusable. // Instead, log and continue. - if errors.Cause(err) != ErrEventTypeBlank { + if !errors.Is(err, ErrEventTypeBlank) { logrus.Errorf("Unable to decode event: %v", err) } continue diff --git a/libpod/events/logfile.go b/libpod/events/logfile.go index 21fdd8027..4dafd8600 100644 --- a/libpod/events/logfile.go +++ b/libpod/events/logfile.go @@ -6,6 +6,7 @@ package events import ( "bufio" "context" + "errors" "fmt" "io" "io/ioutil" @@ -16,7 +17,6 @@ import ( "github.com/containers/podman/v4/pkg/util" "github.com/containers/storage/pkg/lockfile" "github.com/nxadm/tail" - "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/sys/unix" ) @@ -90,7 +90,7 @@ func (e EventLogFile) Read(ctx context.Context, options ReadOptions) error { defer close(options.EventChannel) filterMap, err := generateEventFilters(options.Filters, options.Since, options.Until) if err != nil { - return errors.Wrapf(err, "failed to parse event filters") + return fmt.Errorf("failed to parse event filters: %w", err) } t, err := e.getTail(options) if err != nil { @@ -136,7 +136,7 @@ func (e EventLogFile) Read(ctx context.Context, options ReadOptions) error { case Image, Volume, Pod, System, Container, Network: // no-op default: - return errors.Errorf("event type %s is not valid in %s", event.Type.String(), e.options.LogFilePath) + return fmt.Errorf("event type %s is not valid in %s", event.Type.String(), e.options.LogFilePath) } if copy && applyFilters(event, filterMap) { options.EventChannel <- event diff --git a/libpod/healthcheck.go b/libpod/healthcheck.go index 95c70b60e..9b9d12b17 100644 --- a/libpod/healthcheck.go +++ b/libpod/healthcheck.go @@ -2,6 +2,8 @@ package libpod import ( "bufio" + "errors" + "fmt" "io/ioutil" "os" "path/filepath" @@ -9,7 +11,6 @@ import ( "time" "github.com/containers/podman/v4/libpod/define" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -26,7 +27,7 @@ const ( func (r *Runtime) HealthCheck(name string) (define.HealthCheckStatus, error) { container, err := r.LookupContainer(name) if err != nil { - return define.HealthCheckContainerNotFound, errors.Wrapf(err, "unable to look up %s to perform a health check", name) + return define.HealthCheckContainerNotFound, fmt.Errorf("unable to look up %s to perform a health check: %w", name, err) } hcStatus, err := checkHealthCheckCanBeRun(container) if err == nil { @@ -44,14 +45,14 @@ func (c *Container) runHealthCheck() (define.HealthCheckStatus, error) { ) hcCommand := c.HealthCheckConfig().Test if len(hcCommand) < 1 { - return define.HealthCheckNotDefined, errors.Errorf("container %s has no defined healthcheck", c.ID()) + return define.HealthCheckNotDefined, fmt.Errorf("container %s has no defined healthcheck", c.ID()) } switch hcCommand[0] { - case "", "NONE": - return define.HealthCheckNotDefined, errors.Errorf("container %s has no defined healthcheck", c.ID()) - case "CMD": + case "", define.HealthConfigTestNone: + return define.HealthCheckNotDefined, fmt.Errorf("container %s has no defined healthcheck", c.ID()) + case define.HealthConfigTestCmd: newCommand = hcCommand[1:] - case "CMD-SHELL": + case define.HealthConfigTestCmdShell: // TODO: SHELL command from image not available in Container - use Docker default newCommand = []string{"/bin/sh", "-c", strings.Join(hcCommand[1:], " ")} default: @@ -59,11 +60,11 @@ func (c *Container) runHealthCheck() (define.HealthCheckStatus, error) { newCommand = hcCommand } if len(newCommand) < 1 || newCommand[0] == "" { - return define.HealthCheckNotDefined, errors.Errorf("container %s has no defined healthcheck", c.ID()) + return define.HealthCheckNotDefined, fmt.Errorf("container %s has no defined healthcheck", c.ID()) } rPipe, wPipe, err := os.Pipe() if err != nil { - return define.HealthCheckInternalError, errors.Wrapf(err, "unable to create pipe for healthcheck session") + return define.HealthCheckInternalError, fmt.Errorf("unable to create pipe for healthcheck session: %w", err) } defer wPipe.Close() defer rPipe.Close() @@ -92,11 +93,10 @@ func (c *Container) runHealthCheck() (define.HealthCheckStatus, error) { config.Command = newCommand exitCode, hcErr := c.exec(config, streams, nil, true) if hcErr != nil { - errCause := errors.Cause(hcErr) hcResult = define.HealthCheckFailure - if errCause == define.ErrOCIRuntimeNotFound || - errCause == define.ErrOCIRuntimePermissionDenied || - errCause == define.ErrOCIRuntime { + if errors.Is(hcErr, define.ErrOCIRuntimeNotFound) || + errors.Is(hcErr, define.ErrOCIRuntimePermissionDenied) || + errors.Is(hcErr, define.ErrOCIRuntime) { returnCode = 1 hcErr = nil } else { @@ -125,11 +125,11 @@ func (c *Container) runHealthCheck() (define.HealthCheckStatus, error) { if timeEnd.Sub(timeStart) > c.HealthCheckConfig().Timeout { returnCode = -1 hcResult = define.HealthCheckFailure - hcErr = errors.Errorf("healthcheck command exceeded timeout of %s", c.HealthCheckConfig().Timeout.String()) + hcErr = fmt.Errorf("healthcheck command exceeded timeout of %s", c.HealthCheckConfig().Timeout.String()) } hcl := newHealthCheckLog(timeStart, timeEnd, returnCode, eventLog) if err := c.updateHealthCheckLog(hcl, inStartPeriod); err != nil { - return hcResult, errors.Wrapf(err, "unable to update health check log %s for %s", c.healthCheckLogPath(), c.ID()) + return hcResult, fmt.Errorf("unable to update health check log %s for %s: %w", c.healthCheckLogPath(), c.ID(), err) } return hcResult, hcErr } @@ -140,10 +140,10 @@ func checkHealthCheckCanBeRun(c *Container) (define.HealthCheckStatus, error) { return define.HealthCheckInternalError, err } if cstate != define.ContainerStateRunning { - return define.HealthCheckContainerStopped, errors.Errorf("container %s is not running", c.ID()) + return define.HealthCheckContainerStopped, fmt.Errorf("container %s is not running", c.ID()) } if !c.HasHealthCheck() { - return define.HealthCheckNotDefined, errors.Errorf("container %s has no defined healthcheck", c.ID()) + return define.HealthCheckNotDefined, fmt.Errorf("container %s has no defined healthcheck", c.ID()) } return define.HealthCheckDefined, nil } @@ -167,7 +167,7 @@ func (c *Container) updateHealthStatus(status string) error { healthCheck.Status = status newResults, err := json.Marshal(healthCheck) if err != nil { - return errors.Wrapf(err, "unable to marshall healthchecks for writing status") + return fmt.Errorf("unable to marshall healthchecks for writing status: %w", err) } return ioutil.WriteFile(c.healthCheckLogPath(), newResults, 0700) } @@ -201,7 +201,7 @@ func (c *Container) updateHealthCheckLog(hcl define.HealthCheckLog, inStartPerio } newResults, err := json.Marshal(healthCheck) if err != nil { - return errors.Wrapf(err, "unable to marshall healthchecks for writing") + return fmt.Errorf("unable to marshall healthchecks for writing: %w", err) } return ioutil.WriteFile(c.healthCheckLogPath(), newResults, 0700) } @@ -222,10 +222,10 @@ func (c *Container) getHealthCheckLog() (define.HealthCheckResults, error) { } b, err := ioutil.ReadFile(c.healthCheckLogPath()) if err != nil { - return healthCheck, errors.Wrap(err, "failed to read health check log file") + return healthCheck, fmt.Errorf("failed to read health check log file: %w", err) } if err := json.Unmarshal(b, &healthCheck); err != nil { - return healthCheck, errors.Wrapf(err, "failed to unmarshal existing healthcheck results in %s", c.healthCheckLogPath()) + return healthCheck, fmt.Errorf("failed to unmarshal existing healthcheck results in %s: %w", c.healthCheckLogPath(), err) } return healthCheck, nil } @@ -241,7 +241,7 @@ func (c *Container) HealthCheckStatus() (string, error) { // This function does not lock the container. func (c *Container) healthCheckStatus() (string, error) { if !c.HasHealthCheck() { - return "", errors.Errorf("container %s has no defined healthcheck", c.ID()) + return "", fmt.Errorf("container %s has no defined healthcheck", c.ID()) } if err := c.syncContainer(); err != nil { @@ -250,7 +250,7 @@ func (c *Container) healthCheckStatus() (string, error) { results, err := c.getHealthCheckLog() if err != nil { - return "", errors.Wrapf(err, "unable to get healthcheck log for %s", c.ID()) + return "", fmt.Errorf("unable to get healthcheck log for %s: %w", c.ID(), err) } return results.Status, nil diff --git a/libpod/healthcheck_linux.go b/libpod/healthcheck_linux.go index 1e03db542..3fb6dfb91 100644 --- a/libpod/healthcheck_linux.go +++ b/libpod/healthcheck_linux.go @@ -10,7 +10,6 @@ import ( "github.com/containers/podman/v4/pkg/errorhandling" "github.com/containers/podman/v4/pkg/rootless" "github.com/containers/podman/v4/pkg/systemd" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -21,7 +20,7 @@ func (c *Container) createTimer() error { } podman, err := os.Executable() if err != nil { - return errors.Wrapf(err, "failed to get path for podman for a health check timer") + return fmt.Errorf("failed to get path for podman for a health check timer: %w", err) } var cmd = []string{} @@ -36,13 +35,13 @@ func (c *Container) createTimer() error { conn, err := systemd.ConnectToDBUS() if err != nil { - return errors.Wrapf(err, "unable to get systemd connection to add healthchecks") + return fmt.Errorf("unable to get systemd connection to add healthchecks: %w", err) } conn.Close() logrus.Debugf("creating systemd-transient files: %s %s", "systemd-run", cmd) systemdRun := exec.Command("systemd-run", cmd...) if output, err := systemdRun.CombinedOutput(); err != nil { - return errors.Errorf("%s", output) + return fmt.Errorf("%s", output) } return nil } @@ -65,7 +64,7 @@ func (c *Container) startTimer() error { } conn, err := systemd.ConnectToDBUS() if err != nil { - return errors.Wrapf(err, "unable to get systemd connection to start healthchecks") + return fmt.Errorf("unable to get systemd connection to start healthchecks: %w", err) } defer conn.Close() @@ -89,7 +88,7 @@ func (c *Container) removeTransientFiles(ctx context.Context) error { } conn, err := systemd.ConnectToDBUS() if err != nil { - return errors.Wrapf(err, "unable to get systemd connection to remove healthchecks") + return fmt.Errorf("unable to get systemd connection to remove healthchecks: %w", err) } defer conn.Close() diff --git a/libpod/info.go b/libpod/info.go index 561d11524..c4193b40d 100644 --- a/libpod/info.go +++ b/libpod/info.go @@ -3,6 +3,7 @@ package libpod import ( "bufio" "bytes" + "errors" "fmt" "io/ioutil" "math" @@ -25,7 +26,6 @@ import ( "github.com/containers/storage" "github.com/containers/storage/pkg/system" "github.com/opencontainers/selinux/go-selinux" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -34,20 +34,20 @@ func (r *Runtime) info() (*define.Info, error) { info := define.Info{} versionInfo, err := define.GetVersion() if err != nil { - return nil, errors.Wrapf(err, "error getting version info") + return nil, fmt.Errorf("error getting version info: %w", err) } info.Version = versionInfo // get host information hostInfo, err := r.hostInfo() if err != nil { - return nil, errors.Wrapf(err, "error getting host info") + return nil, fmt.Errorf("error getting host info: %w", err) } info.Host = hostInfo // get store information storeInfo, err := r.storeInfo() if err != nil { - return nil, errors.Wrapf(err, "error getting store info") + return nil, fmt.Errorf("error getting store info: %w", err) } info.Store = storeInfo registries := make(map[string]interface{}) @@ -55,14 +55,14 @@ func (r *Runtime) info() (*define.Info, error) { sys := r.SystemContext() data, err := sysregistriesv2.GetRegistries(sys) if err != nil { - return nil, errors.Wrapf(err, "error getting registries") + return nil, fmt.Errorf("error getting registries: %w", err) } for _, reg := range data { registries[reg.Prefix] = reg } regs, err := sysregistriesv2.UnqualifiedSearchRegistries(sys) if err != nil { - return nil, errors.Wrapf(err, "error getting registries") + return nil, fmt.Errorf("error getting registries: %w", err) } if len(regs) > 0 { registries["search"] = regs @@ -86,36 +86,36 @@ func (r *Runtime) hostInfo() (*define.HostInfo, error) { // lets say OS, arch, number of cpus, amount of memory, maybe os distribution/version, hostname, kernel version, uptime mi, err := system.ReadMemInfo() if err != nil { - return nil, errors.Wrapf(err, "error reading memory info") + return nil, fmt.Errorf("error reading memory info: %w", err) } hostDistributionInfo := r.GetHostDistributionInfo() kv, err := readKernelVersion() if err != nil { - return nil, errors.Wrapf(err, "error reading kernel version") + return nil, fmt.Errorf("error reading kernel version: %w", err) } host, err := os.Hostname() if err != nil { - return nil, errors.Wrapf(err, "error getting hostname") + return nil, fmt.Errorf("error getting hostname: %w", err) } seccompProfilePath, err := DefaultSeccompPath() if err != nil { - return nil, errors.Wrapf(err, "error getting Seccomp profile path") + return nil, fmt.Errorf("error getting Seccomp profile path: %w", err) } // Cgroups version unified, err := cgroups.IsCgroup2UnifiedMode() if err != nil { - return nil, errors.Wrapf(err, "error reading cgroups mode") + return nil, fmt.Errorf("error reading cgroups mode: %w", err) } // Get Map of all available controllers availableControllers, err := cgroups.GetAvailableControllers(nil, unified) if err != nil { - return nil, errors.Wrapf(err, "error getting available cgroup controllers") + return nil, fmt.Errorf("error getting available cgroup controllers: %w", err) } cpuUtil, err := getCPUUtilization() if err != nil { @@ -178,11 +178,11 @@ func (r *Runtime) hostInfo() (*define.HostInfo, error) { if rootless.IsRootless() { uidmappings, err := rootless.ReadMappingsProc("/proc/self/uid_map") if err != nil { - return nil, errors.Wrapf(err, "error reading uid mappings") + return nil, fmt.Errorf("error reading uid mappings: %w", err) } gidmappings, err := rootless.ReadMappingsProc("/proc/self/gid_map") if err != nil { - return nil, errors.Wrapf(err, "error reading gid mappings") + return nil, fmt.Errorf("error reading gid mappings: %w", err) } idmappings := define.IDMappings{ GIDMap: gidmappings, @@ -201,7 +201,7 @@ func (r *Runtime) hostInfo() (*define.HostInfo, error) { duration, err := procUptime() if err != nil { - return nil, errors.Wrapf(err, "error reading up time") + return nil, fmt.Errorf("error reading up time: %w", err) } uptime := struct { @@ -240,7 +240,7 @@ func (r *Runtime) getContainerStoreInfo() (define.ContainerStore, error) { for _, con := range cons { state, err := con.State() if err != nil { - if errors.Cause(err) == define.ErrNoSuchCtr { + if errors.Is(err, define.ErrNoSuchCtr) { // container was probably removed cs.Number-- continue @@ -271,7 +271,7 @@ func (r *Runtime) storeInfo() (*define.StoreInfo, error) { } images, err := r.store.Images() if err != nil { - return nil, errors.Wrapf(err, "error getting number of images") + return nil, fmt.Errorf("error getting number of images: %w", err) } conInfo, err := r.getContainerStoreInfo() if err != nil { @@ -281,7 +281,7 @@ func (r *Runtime) storeInfo() (*define.StoreInfo, error) { var grStats syscall.Statfs_t if err := syscall.Statfs(r.store.GraphRoot(), &grStats); err != nil { - return nil, errors.Wrapf(err, "unable to collect graph root usasge for %q", r.store.GraphRoot()) + return nil, fmt.Errorf("unable to collect graph root usasge for %q: %w", r.store.GraphRoot(), err) } allocated := uint64(grStats.Bsize) * grStats.Blocks info := define.StoreInfo{ @@ -407,15 +407,15 @@ func getCPUUtilization() (*define.CPUUsage, error) { func statToPercent(stats []string) (*define.CPUUsage, error) { userTotal, err := strconv.ParseFloat(stats[1], 64) if err != nil { - return nil, errors.Wrapf(err, "unable to parse user value %q", stats[1]) + return nil, fmt.Errorf("unable to parse user value %q: %w", stats[1], err) } systemTotal, err := strconv.ParseFloat(stats[3], 64) if err != nil { - return nil, errors.Wrapf(err, "unable to parse system value %q", stats[3]) + return nil, fmt.Errorf("unable to parse system value %q: %w", stats[3], err) } idleTotal, err := strconv.ParseFloat(stats[4], 64) if err != nil { - return nil, errors.Wrapf(err, "unable to parse idle value %q", stats[4]) + return nil, fmt.Errorf("unable to parse idle value %q: %w", stats[4], err) } total := userTotal + systemTotal + idleTotal s := define.CPUUsage{ diff --git a/libpod/kube.go b/libpod/kube.go index bd4230d66..3cb0489b3 100644 --- a/libpod/kube.go +++ b/libpod/kube.go @@ -2,6 +2,7 @@ package libpod import ( "context" + "errors" "fmt" "math/rand" "os" @@ -27,7 +28,6 @@ import ( "github.com/containers/podman/v4/pkg/util" "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-tools/generate" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -53,11 +53,11 @@ func (p *Pod) GenerateForKube(ctx context.Context) (*v1.Pod, []v1.ServicePort, e } // If the pod has no containers, no sense to generate YAML if len(allContainers) == 0 { - return nil, servicePorts, errors.Errorf("pod %s has no containers", p.ID()) + return nil, servicePorts, fmt.Errorf("pod %s has no containers", p.ID()) } // If only an infra container is present, makes no sense to generate YAML if len(allContainers) == 1 && p.HasInfraContainer() { - return nil, servicePorts, errors.Errorf("pod %s only has an infra container", p.ID()) + return nil, servicePorts, fmt.Errorf("pod %s only has an infra container", p.ID()) } extraHost := make([]v1.HostAlias, 0) @@ -573,7 +573,7 @@ func containerToV1Container(ctx context.Context, c *Container) (v1.Container, [] if !c.Privileged() && len(c.config.Spec.Linux.Devices) > 0 { // TODO Enable when we can support devices and their names kubeContainer.VolumeDevices = generateKubeVolumeDeviceFromLinuxDevice(c.config.Spec.Linux.Devices) - return kubeContainer, kubeVolumes, nil, annotations, errors.Wrapf(define.ErrNotImplemented, "linux devices") + return kubeContainer, kubeVolumes, nil, annotations, fmt.Errorf("linux devices: %w", define.ErrNotImplemented) } if len(c.config.UserVolumes) > 0 { @@ -743,7 +743,7 @@ func portMappingToContainerPort(portMappings []types.PortMapping) ([]v1.Containe case "SCTP": protocol = v1.ProtocolSCTP default: - return containerPorts, errors.Errorf("unknown network protocol %s", p.Protocol) + return containerPorts, fmt.Errorf("unknown network protocol %s", p.Protocol) } for i := uint16(0); i < p.Range; i++ { cp := v1.ContainerPort{ @@ -772,7 +772,7 @@ func libpodEnvVarsToKubeEnvVars(envs []string, imageEnvs []string) ([]v1.EnvVar, for _, e := range envs { split := strings.SplitN(e, "=", 2) if len(split) != 2 { - return envVars, errors.Errorf("environment variable %s is malformed; should be key=value", e) + return envVars, fmt.Errorf("environment variable %s is malformed; should be key=value", e) } if defaultEnv[split[0]] == split[1] { continue @@ -892,11 +892,11 @@ func isHostPathDirectory(hostPathSource string) (bool, error) { func convertVolumePathToName(hostSourcePath string) (string, error) { if len(hostSourcePath) == 0 { - return "", errors.Errorf("hostSourcePath must be specified to generate volume name") + return "", errors.New("hostSourcePath must be specified to generate volume name") } if len(hostSourcePath) == 1 { if hostSourcePath != "/" { - return "", errors.Errorf("hostSourcePath malformatted: %s", hostSourcePath) + return "", fmt.Errorf("hostSourcePath malformatted: %s", hostSourcePath) } // add special case name return "root", nil @@ -1025,7 +1025,7 @@ func generateKubeSecurityContext(c *Container) (*v1.SecurityContext, error) { defer c.lock.Unlock() } if err := c.syncContainer(); err != nil { - return nil, errors.Wrapf(err, "unable to sync container during YAML generation") + return nil, fmt.Errorf("unable to sync container during YAML generation: %w", err) } mountpoint := c.state.Mountpoint @@ -1033,7 +1033,7 @@ func generateKubeSecurityContext(c *Container) (*v1.SecurityContext, error) { var err error mountpoint, err = c.mount() if err != nil { - return nil, errors.Wrapf(err, "failed to mount %s mountpoint", c.ID()) + return nil, fmt.Errorf("failed to mount %s mountpoint: %w", c.ID(), err) } defer func() { if err := c.unmount(false); err != nil { diff --git a/libpod/lock/file/file_lock.go b/libpod/lock/file/file_lock.go index 145aa6e26..1379e690a 100644 --- a/libpod/lock/file/file_lock.go +++ b/libpod/lock/file/file_lock.go @@ -1,6 +1,7 @@ package file import ( + "fmt" "io/ioutil" "os" "path/filepath" @@ -8,7 +9,6 @@ import ( "syscall" "github.com/containers/storage" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -23,7 +23,7 @@ type FileLocks struct { //nolint:revive // struct name stutters func CreateFileLock(path string) (*FileLocks, error) { _, err := os.Stat(path) if err == nil { - return nil, errors.Wrapf(syscall.EEXIST, "directory %s exists", path) + return nil, fmt.Errorf("directory %s exists: %w", path, syscall.EEXIST) } if err := os.MkdirAll(path, 0711); err != nil { return nil, err @@ -57,11 +57,11 @@ func OpenFileLock(path string) (*FileLocks, error) { // Close() is only intended to be used while testing the locks. func (locks *FileLocks) Close() error { if !locks.valid { - return errors.Wrapf(syscall.EINVAL, "locks have already been closed") + return fmt.Errorf("locks have already been closed: %w", syscall.EINVAL) } err := os.RemoveAll(locks.lockPath) if err != nil { - return errors.Wrapf(err, "deleting directory %s", locks.lockPath) + return fmt.Errorf("deleting directory %s: %w", locks.lockPath, err) } return nil } @@ -73,7 +73,7 @@ func (locks *FileLocks) getLockPath(lck uint32) string { // AllocateLock allocates a lock and returns the index of the lock that was allocated. func (locks *FileLocks) AllocateLock() (uint32, error) { if !locks.valid { - return 0, errors.Wrapf(syscall.EINVAL, "locks have already been closed") + return 0, fmt.Errorf("locks have already been closed: %w", syscall.EINVAL) } id := uint32(0) @@ -84,7 +84,7 @@ func (locks *FileLocks) AllocateLock() (uint32, error) { if os.IsExist(err) { continue } - return 0, errors.Wrap(err, "creating lock file") + return 0, fmt.Errorf("creating lock file: %w", err) } f.Close() break @@ -98,12 +98,12 @@ func (locks *FileLocks) AllocateLock() (uint32, error) { // returned. func (locks *FileLocks) AllocateGivenLock(lck uint32) error { if !locks.valid { - return errors.Wrapf(syscall.EINVAL, "locks have already been closed") + return fmt.Errorf("locks have already been closed: %w", syscall.EINVAL) } f, err := os.OpenFile(locks.getLockPath(lck), os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666) if err != nil { - return errors.Wrapf(err, "error creating lock %d", lck) + return fmt.Errorf("error creating lock %d: %w", lck, err) } f.Close() @@ -115,10 +115,10 @@ func (locks *FileLocks) AllocateGivenLock(lck uint32) error { // The given lock must be already allocated, or an error will be returned. func (locks *FileLocks) DeallocateLock(lck uint32) error { if !locks.valid { - return errors.Wrapf(syscall.EINVAL, "locks have already been closed") + return fmt.Errorf("locks have already been closed: %w", syscall.EINVAL) } if err := os.Remove(locks.getLockPath(lck)); err != nil { - return errors.Wrapf(err, "deallocating lock %d", lck) + return fmt.Errorf("deallocating lock %d: %w", lck, err) } return nil } @@ -127,11 +127,11 @@ func (locks *FileLocks) DeallocateLock(lck uint32) error { // other containers and pods. func (locks *FileLocks) DeallocateAllLocks() error { if !locks.valid { - return errors.Wrapf(syscall.EINVAL, "locks have already been closed") + return fmt.Errorf("locks have already been closed: %w", syscall.EINVAL) } files, err := ioutil.ReadDir(locks.lockPath) if err != nil { - return errors.Wrapf(err, "error reading directory %s", locks.lockPath) + return fmt.Errorf("error reading directory %s: %w", locks.lockPath, err) } var lastErr error for _, f := range files { @@ -148,12 +148,12 @@ func (locks *FileLocks) DeallocateAllLocks() error { // LockFileLock locks the given lock. func (locks *FileLocks) LockFileLock(lck uint32) error { if !locks.valid { - return errors.Wrapf(syscall.EINVAL, "locks have already been closed") + return fmt.Errorf("locks have already been closed: %w", syscall.EINVAL) } l, err := storage.GetLockfile(locks.getLockPath(lck)) if err != nil { - return errors.Wrapf(err, "error acquiring lock") + return fmt.Errorf("error acquiring lock: %w", err) } l.Lock() @@ -163,11 +163,11 @@ func (locks *FileLocks) LockFileLock(lck uint32) error { // UnlockFileLock unlocks the given lock. func (locks *FileLocks) UnlockFileLock(lck uint32) error { if !locks.valid { - return errors.Wrapf(syscall.EINVAL, "locks have already been closed") + return fmt.Errorf("locks have already been closed: %w", syscall.EINVAL) } l, err := storage.GetLockfile(locks.getLockPath(lck)) if err != nil { - return errors.Wrapf(err, "error acquiring lock") + return fmt.Errorf("error acquiring lock: %w", err) } l.Unlock() diff --git a/libpod/lock/in_memory_locks.go b/libpod/lock/in_memory_locks.go index f7f47760c..f00f01032 100644 --- a/libpod/lock/in_memory_locks.go +++ b/libpod/lock/in_memory_locks.go @@ -1,9 +1,9 @@ package lock import ( + "errors" + "fmt" "sync" - - "github.com/pkg/errors" ) // Mutex holds a single mutex and whether it has been allocated. @@ -49,7 +49,7 @@ type InMemoryManager struct { // of locks. func NewInMemoryManager(numLocks uint32) (Manager, error) { if numLocks == 0 { - return nil, errors.Errorf("must provide a non-zero number of locks") + return nil, errors.New("must provide a non-zero number of locks") } manager := new(InMemoryManager) @@ -78,13 +78,13 @@ func (m *InMemoryManager) AllocateLock() (Locker, error) { } } - return nil, errors.Errorf("all locks have been allocated") + return nil, errors.New("all locks have been allocated") } // RetrieveLock retrieves a lock from the manager. func (m *InMemoryManager) RetrieveLock(id uint32) (Locker, error) { if id >= m.numLocks { - return nil, errors.Errorf("given lock ID %d is too large - this manager only supports lock indexes up to %d", id, m.numLocks-1) + return nil, fmt.Errorf("given lock ID %d is too large - this manager only supports lock indexes up to %d", id, m.numLocks-1) } return m.locks[id], nil @@ -94,11 +94,11 @@ func (m *InMemoryManager) RetrieveLock(id uint32) (Locker, error) { // use) and returns it. func (m *InMemoryManager) AllocateAndRetrieveLock(id uint32) (Locker, error) { if id >= m.numLocks { - return nil, errors.Errorf("given lock ID %d is too large - this manager only supports lock indexes up to %d", id, m.numLocks) + return nil, fmt.Errorf("given lock ID %d is too large - this manager only supports lock indexes up to %d", id, m.numLocks) } if m.locks[id].allocated { - return nil, errors.Errorf("given lock ID %d is already in use, cannot reallocate", id) + return nil, fmt.Errorf("given lock ID %d is already in use, cannot reallocate", id) } m.locks[id].allocated = true diff --git a/libpod/lock/shm/shm_lock.go b/libpod/lock/shm/shm_lock.go index 6eaf37e48..3334a4018 100644 --- a/libpod/lock/shm/shm_lock.go +++ b/libpod/lock/shm/shm_lock.go @@ -11,11 +11,12 @@ package shm import "C" import ( + "errors" + "fmt" "runtime" "syscall" "unsafe" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -40,7 +41,7 @@ type SHMLocks struct { // size used by the underlying implementation. func CreateSHMLock(path string, numLocks uint32) (*SHMLocks, error) { if numLocks == 0 { - return nil, errors.Wrapf(syscall.EINVAL, "number of locks must be greater than 0") + return nil, fmt.Errorf("number of locks must be greater than 0: %w", syscall.EINVAL) } locks := new(SHMLocks) @@ -52,7 +53,7 @@ func CreateSHMLock(path string, numLocks uint32) (*SHMLocks, error) { lockStruct := C.setup_lock_shm(cPath, C.uint32_t(numLocks), &errCode) if lockStruct == nil { // We got a null pointer, so something errored - return nil, errors.Wrapf(syscall.Errno(-1*errCode), "failed to create %d locks in %s", numLocks, path) + return nil, fmt.Errorf("failed to create %d locks in %s: %w", numLocks, path, syscall.Errno(-1*errCode)) } locks.lockStruct = lockStruct @@ -69,7 +70,7 @@ func CreateSHMLock(path string, numLocks uint32) (*SHMLocks, error) { // segment was created with. func OpenSHMLock(path string, numLocks uint32) (*SHMLocks, error) { if numLocks == 0 { - return nil, errors.Wrapf(syscall.EINVAL, "number of locks must be greater than 0") + return nil, fmt.Errorf("number of locks must be greater than 0: %w", syscall.EINVAL) } locks := new(SHMLocks) @@ -81,7 +82,7 @@ func OpenSHMLock(path string, numLocks uint32) (*SHMLocks, error) { lockStruct := C.open_lock_shm(cPath, C.uint32_t(numLocks), &errCode) if lockStruct == nil { // We got a null pointer, so something errored - return nil, errors.Wrapf(syscall.Errno(-1*errCode), "failed to open %d locks in %s", numLocks, path) + return nil, fmt.Errorf("failed to open %d locks in %s: %w", numLocks, path, syscall.Errno(-1*errCode)) } locks.lockStruct = lockStruct @@ -103,7 +104,7 @@ func (locks *SHMLocks) GetMaxLocks() uint32 { // Close() is only intended to be used while testing the locks. func (locks *SHMLocks) Close() error { if !locks.valid { - return errors.Wrapf(syscall.EINVAL, "locks have already been closed") + return fmt.Errorf("locks have already been closed: %w", syscall.EINVAL) } locks.valid = false @@ -124,7 +125,7 @@ func (locks *SHMLocks) Close() error { // created will result in an error, and no semaphore will be allocated. func (locks *SHMLocks) AllocateSemaphore() (uint32, error) { if !locks.valid { - return 0, errors.Wrapf(syscall.EINVAL, "locks have already been closed") + return 0, fmt.Errorf("locks have already been closed: %w", syscall.EINVAL) } // This returns a U64, so we have the full u32 range available for @@ -138,7 +139,7 @@ func (locks *SHMLocks) AllocateSemaphore() (uint32, error) { // that there's no room in the SHM inn for this lock, this tends to send normal people // down the path of checking disk-space which is not actually their problem. // Give a clue that it's actually due to num_locks filling up. - var errFull = errors.Errorf("allocation failed; exceeded num_locks (%d)", locks.maxLocks) + var errFull = fmt.Errorf("allocation failed; exceeded num_locks (%d)", locks.maxLocks) return uint32(retCode), errFull } return uint32(retCode), syscall.Errno(-1 * retCode) @@ -153,7 +154,7 @@ func (locks *SHMLocks) AllocateSemaphore() (uint32, error) { // returned. func (locks *SHMLocks) AllocateGivenSemaphore(sem uint32) error { if !locks.valid { - return errors.Wrapf(syscall.EINVAL, "locks have already been closed") + return fmt.Errorf("locks have already been closed: %w", syscall.EINVAL) } retCode := C.allocate_given_semaphore(locks.lockStruct, C.uint32_t(sem)) @@ -169,11 +170,11 @@ func (locks *SHMLocks) AllocateGivenSemaphore(sem uint32) error { // The given semaphore must be already allocated, or an error will be returned. func (locks *SHMLocks) DeallocateSemaphore(sem uint32) error { if !locks.valid { - return errors.Wrapf(syscall.EINVAL, "locks have already been closed") + return fmt.Errorf("locks have already been closed: %w", syscall.EINVAL) } if sem > locks.maxLocks { - return errors.Wrapf(syscall.EINVAL, "given semaphore %d is higher than maximum locks count %d", sem, locks.maxLocks) + return fmt.Errorf("given semaphore %d is higher than maximum locks count %d: %w", sem, locks.maxLocks, syscall.EINVAL) } retCode := C.deallocate_semaphore(locks.lockStruct, C.uint32_t(sem)) @@ -189,7 +190,7 @@ func (locks *SHMLocks) DeallocateSemaphore(sem uint32) error { // other containers and pods. func (locks *SHMLocks) DeallocateAllSemaphores() error { if !locks.valid { - return errors.Wrapf(syscall.EINVAL, "locks have already been closed") + return fmt.Errorf("locks have already been closed: %w", syscall.EINVAL) } retCode := C.deallocate_all_semaphores(locks.lockStruct) @@ -210,11 +211,11 @@ func (locks *SHMLocks) DeallocateAllSemaphores() error { // succeed. func (locks *SHMLocks) LockSemaphore(sem uint32) error { if !locks.valid { - return errors.Wrapf(syscall.EINVAL, "locks have already been closed") + return fmt.Errorf("locks have already been closed: %w", syscall.EINVAL) } if sem > locks.maxLocks { - return errors.Wrapf(syscall.EINVAL, "given semaphore %d is higher than maximum locks count %d", sem, locks.maxLocks) + return fmt.Errorf("given semaphore %d is higher than maximum locks count %d: %w", sem, locks.maxLocks, syscall.EINVAL) } // For pthread mutexes, we have to guarantee lock and unlock happen in @@ -238,11 +239,11 @@ func (locks *SHMLocks) LockSemaphore(sem uint32) error { // succeed. func (locks *SHMLocks) UnlockSemaphore(sem uint32) error { if !locks.valid { - return errors.Wrapf(syscall.EINVAL, "locks have already been closed") + return fmt.Errorf("locks have already been closed: %w", syscall.EINVAL) } if sem > locks.maxLocks { - return errors.Wrapf(syscall.EINVAL, "given semaphore %d is higher than maximum locks count %d", sem, locks.maxLocks) + return fmt.Errorf("given semaphore %d is higher than maximum locks count %d: %w", sem, locks.maxLocks, syscall.EINVAL) } retCode := C.unlock_semaphore(locks.lockStruct, C.uint32_t(sem)) diff --git a/libpod/lock/shm_lock_manager_linux.go b/libpod/lock/shm_lock_manager_linux.go index 3076cd864..fa20bc353 100644 --- a/libpod/lock/shm_lock_manager_linux.go +++ b/libpod/lock/shm_lock_manager_linux.go @@ -4,10 +4,10 @@ package lock import ( + "fmt" "syscall" "github.com/containers/podman/v4/libpod/lock/shm" - "github.com/pkg/errors" ) // SHMLockManager manages shared memory locks. @@ -66,8 +66,8 @@ func (m *SHMLockManager) AllocateAndRetrieveLock(id uint32) (Locker, error) { lock.manager = m if id >= m.locks.GetMaxLocks() { - return nil, errors.Wrapf(syscall.EINVAL, "lock ID %d is too large - max lock size is %d", - id, m.locks.GetMaxLocks()-1) + return nil, fmt.Errorf("lock ID %d is too large - max lock size is %d: %w", + id, m.locks.GetMaxLocks()-1, syscall.EINVAL) } if err := m.locks.AllocateGivenSemaphore(id); err != nil { @@ -84,8 +84,8 @@ func (m *SHMLockManager) RetrieveLock(id uint32) (Locker, error) { lock.manager = m if id >= m.locks.GetMaxLocks() { - return nil, errors.Wrapf(syscall.EINVAL, "lock ID %d is too large - max lock size is %d", - id, m.locks.GetMaxLocks()-1) + return nil, fmt.Errorf("lock ID %d is too large - max lock size is %d: %w", + id, m.locks.GetMaxLocks()-1, syscall.EINVAL) } return lock, nil diff --git a/libpod/logs/log.go b/libpod/logs/log.go index 4d7d5ac58..43da8d904 100644 --- a/libpod/logs/log.go +++ b/libpod/logs/log.go @@ -1,6 +1,7 @@ package logs import ( + "errors" "fmt" "io" "os" @@ -10,7 +11,6 @@ import ( "github.com/containers/podman/v4/libpod/logs/reversereader" "github.com/nxadm/tail" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -105,7 +105,7 @@ func getTailLog(path string, tail int) ([]*LogLine, error) { for { s, err := rr.Read() if err != nil { - if errors.Cause(err) == io.EOF { + if errors.Is(err, io.EOF) { inputs <- []string{leftover} } else { logrus.Error(err) @@ -228,11 +228,11 @@ func (l *LogLine) Until(until time.Time) bool { func NewLogLine(line string) (*LogLine, error) { splitLine := strings.Split(line, " ") if len(splitLine) < 4 { - return nil, errors.Errorf("'%s' is not a valid container log line", line) + return nil, fmt.Errorf("'%s' is not a valid container log line", line) } logTime, err := time.Parse(LogTimeFormat, splitLine[0]) if err != nil { - return nil, errors.Wrapf(err, "unable to convert time %s from container log", splitLine[0]) + return nil, fmt.Errorf("unable to convert time %s from container log: %w", splitLine[0], err) } l := LogLine{ Time: logTime, @@ -249,11 +249,11 @@ func NewLogLine(line string) (*LogLine, error) { func NewJournaldLogLine(line string, withID bool) (*LogLine, error) { splitLine := strings.Split(line, " ") if len(splitLine) < 4 { - return nil, errors.Errorf("'%s' is not a valid container log line", line) + return nil, fmt.Errorf("'%s' is not a valid container log line", line) } logTime, err := time.Parse(LogTimeFormat, splitLine[0]) if err != nil { - return nil, errors.Wrapf(err, "unable to convert time %s from container log", splitLine[0]) + return nil, fmt.Errorf("unable to convert time %s from container log: %w", splitLine[0], err) } var msg, id string if withID { diff --git a/libpod/logs/reversereader/reversereader.go b/libpod/logs/reversereader/reversereader.go index 4fa1a3f88..f2e71fb61 100644 --- a/libpod/logs/reversereader/reversereader.go +++ b/libpod/logs/reversereader/reversereader.go @@ -1,10 +1,10 @@ package reversereader import ( + "errors" + "fmt" "io" "os" - - "github.com/pkg/errors" ) // ReverseReader structure for reading a file backwards @@ -49,12 +49,12 @@ func NewReverseReader(reader *os.File) (*ReverseReader, error) { // then sets the newoff set one pagesize less than the previous read. func (r *ReverseReader) Read() (string, error) { if r.offset < 0 { - return "", errors.Wrap(io.EOF, "at beginning of file") + return "", fmt.Errorf("at beginning of file: %w", io.EOF) } // Read from given offset b := make([]byte, r.readSize) n, err := r.reader.ReadAt(b, r.offset) - if err != nil && errors.Cause(err) != io.EOF { + if err != nil && !errors.Is(err, io.EOF) { return "", err } if int64(n) < r.readSize { diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go index a83423c9f..c05796768 100644 --- a/libpod/networking_linux.go +++ b/libpod/networking_linux.go @@ -6,6 +6,7 @@ package libpod import ( "crypto/rand" "crypto/sha256" + "errors" "fmt" "io/ioutil" "net" @@ -36,7 +37,6 @@ import ( "github.com/containers/storage/pkg/lockfile" "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/selinux/go-selinux/label" - "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/vishvananda/netlink" "golang.org/x/sys/unix" @@ -127,19 +127,19 @@ func (r *RootlessNetNS) Do(toRun func() error) error { // this must happen inside the netns thread. err := unix.Unshare(unix.CLONE_NEWNS) if err != nil { - return errors.Wrapf(err, "cannot create a new mount namespace") + return fmt.Errorf("cannot create a new mount namespace: %w", err) } xdgRuntimeDir, err := util.GetRuntimeDir() if err != nil { - return errors.Wrap(err, "could not get runtime directory") + return fmt.Errorf("could not get runtime directory: %w", err) } newXDGRuntimeDir := r.getPath(xdgRuntimeDir) // 1. Mount the netns into the new run to keep them accessible. // Otherwise cni setup will fail because it cannot access the netns files. err = unix.Mount(xdgRuntimeDir, newXDGRuntimeDir, "none", unix.MS_BIND|unix.MS_SHARED|unix.MS_REC, "") if err != nil { - return errors.Wrap(err, "failed to mount runtime directory for rootless netns") + return fmt.Errorf("failed to mount runtime directory for rootless netns: %w", err) } // 2. Also keep /run/systemd if it exists. @@ -150,7 +150,7 @@ func (r *RootlessNetNS) Do(toRun func() error) error { newRunSystemd := r.getPath(runSystemd) err = unix.Mount(runSystemd, newRunSystemd, "none", unix.MS_BIND|unix.MS_REC, "") if err != nil { - return errors.Wrap(err, "failed to mount /run/systemd directory for rootless netns") + return fmt.Errorf("failed to mount /run/systemd directory for rootless netns: %w", err) } } @@ -185,7 +185,7 @@ func (r *RootlessNetNS) Do(toRun func() error) error { fi, err := os.Lstat(path) if err != nil { - return errors.Wrap(err, "failed to stat resolv.conf path") + return fmt.Errorf("failed to stat resolv.conf path: %w", err) } // no link, just continue @@ -195,7 +195,7 @@ func (r *RootlessNetNS) Do(toRun func() error) error { link, err := os.Readlink(path) if err != nil { - return errors.Wrap(err, "failed to read resolv.conf symlink") + return fmt.Errorf("failed to read resolv.conf symlink: %w", err) } linkCount++ if filepath.IsAbs(link) { @@ -231,25 +231,25 @@ func (r *RootlessNetNS) Do(toRun func() error) error { rsr := r.getPath("/run/systemd/resolve") err = unix.Mount("", rsr, "tmpfs", unix.MS_NOEXEC|unix.MS_NOSUID|unix.MS_NODEV, "") if err != nil { - return errors.Wrapf(err, "failed to mount tmpfs on %q for rootless netns", rsr) + return fmt.Errorf("failed to mount tmpfs on %q for rootless netns: %w", rsr, err) } } if strings.HasPrefix(resolvePath, "/run/") { resolvePath = r.getPath(resolvePath) err = os.MkdirAll(filepath.Dir(resolvePath), 0700) if err != nil { - return errors.Wrap(err, "failed to create rootless-netns resolv.conf directory") + return fmt.Errorf("failed to create rootless-netns resolv.conf directory: %w", err) } // we want to bind mount on this file so we have to create the file first _, err = os.OpenFile(resolvePath, os.O_CREATE|os.O_RDONLY, 0700) if err != nil { - return errors.Wrap(err, "failed to create rootless-netns resolv.conf file") + return fmt.Errorf("failed to create rootless-netns resolv.conf file: %w", err) } } // mount resolv.conf to make use of the host dns err = unix.Mount(r.getPath("resolv.conf"), resolvePath, "none", unix.MS_BIND, "") if err != nil { - return errors.Wrap(err, "failed to mount resolv.conf for rootless netns") + return fmt.Errorf("failed to mount resolv.conf for rootless netns: %w", err) } // 4. CNI plugins need access to /var/lib/cni and /run @@ -274,14 +274,14 @@ func (r *RootlessNetNS) Do(toRun func() error) error { // make sure to mount var first err = unix.Mount(varDir, varTarget, "none", unix.MS_BIND, "") if err != nil { - return errors.Wrapf(err, "failed to mount %s for rootless netns", varTarget) + return fmt.Errorf("failed to mount %s for rootless netns: %w", varTarget, err) } // 5. Mount the new prepared run dir to /run, it has to be recursive to keep the other bind mounts. runDir := r.getPath("run") err = unix.Mount(runDir, "/run", "none", unix.MS_BIND|unix.MS_REC, "") if err != nil { - return errors.Wrap(err, "failed to mount /run for rootless netns") + return fmt.Errorf("failed to mount /run for rootless netns: %w", err) } // run the given function in the correct namespace @@ -377,7 +377,7 @@ func (r *Runtime) GetRootlessNetNs(new bool) (*RootlessNetNS, error) { lfile := filepath.Join(runDir, "rootless-netns.lock") lock, err := lockfile.GetLockfile(lfile) if err != nil { - return nil, errors.Wrap(err, "failed to get rootless-netns lockfile") + return nil, fmt.Errorf("failed to get rootless-netns lockfile: %w", err) } lock.Lock() defer func() { @@ -391,7 +391,7 @@ func (r *Runtime) GetRootlessNetNs(new bool) (*RootlessNetNS, error) { rootlessNetNsDir := filepath.Join(runDir, rootlessNetNsName) err = os.MkdirAll(rootlessNetNsDir, 0700) if err != nil { - return nil, errors.Wrap(err, "could not create rootless-netns directory") + return nil, fmt.Errorf("could not create rootless-netns directory: %w", err) } nsDir, err := netns.GetNSRunDir() @@ -411,13 +411,13 @@ func (r *Runtime) GetRootlessNetNs(new bool) (*RootlessNetNS, error) { if err != nil { if !new { // return a error if we could not get the namespace and should no create one - return nil, errors.Wrap(err, "error getting rootless network namespace") + return nil, fmt.Errorf("error getting rootless network namespace: %w", err) } // create a new namespace logrus.Debugf("creating rootless network namespace with name %q", netnsName) ns, err = netns.NewNSWithName(netnsName) if err != nil { - return nil, errors.Wrap(err, "error creating rootless network namespace") + return nil, fmt.Errorf("error creating rootless network namespace: %w", err) } // set up slirp4netns here path := r.config.Engine.NetworkCmdPath @@ -431,7 +431,7 @@ func (r *Runtime) GetRootlessNetNs(new bool) (*RootlessNetNS, error) { syncR, syncW, err := os.Pipe() if err != nil { - return nil, errors.Wrapf(err, "failed to open pipe") + return nil, fmt.Errorf("failed to open pipe: %w", err) } defer errorhandling.CloseQuiet(syncR) defer errorhandling.CloseQuiet(syncW) @@ -442,7 +442,7 @@ func (r *Runtime) GetRootlessNetNs(new bool) (*RootlessNetNS, error) { } slirpFeatures, err := checkSlirpFlags(path) if err != nil { - return nil, errors.Wrapf(err, "error checking slirp4netns binary %s: %q", path, err) + return nil, fmt.Errorf("error checking slirp4netns binary %s: %q: %w", path, err, err) } cmdArgs, err := createBasicSlirp4netnsCmdArgs(netOptions, slirpFeatures) if err != nil { @@ -470,25 +470,25 @@ func (r *Runtime) GetRootlessNetNs(new bool) (*RootlessNetNS, error) { logPath := filepath.Join(r.config.Engine.TmpDir, "slirp4netns-rootless-netns.log") logFile, err := os.Create(logPath) if err != nil { - return nil, errors.Wrapf(err, "failed to open slirp4netns log file %s", logPath) + return nil, fmt.Errorf("failed to open slirp4netns log file %s: %w", logPath, err) } defer logFile.Close() // Unlink immediately the file so we won't need to worry about cleaning it up later. // It is still accessible through the open fd logFile. if err := os.Remove(logPath); err != nil { - return nil, errors.Wrapf(err, "delete file %s", logPath) + return nil, fmt.Errorf("delete file %s: %w", logPath, err) } cmd.Stdout = logFile cmd.Stderr = logFile if err := cmd.Start(); err != nil { - return nil, errors.Wrapf(err, "failed to start slirp4netns process") + return nil, fmt.Errorf("failed to start slirp4netns process: %w", err) } // create pid file for the slirp4netns process // this is need to kill the process in the cleanup pid := strconv.Itoa(cmd.Process.Pid) err = ioutil.WriteFile(filepath.Join(rootlessNetNsDir, rootlessNetNsSilrp4netnsPidFile), []byte(pid), 0700) if err != nil { - return nil, errors.Wrap(err, "unable to write rootless-netns slirp4netns pid file") + return nil, fmt.Errorf("unable to write rootless-netns slirp4netns pid file: %w", err) } defer func() { @@ -513,17 +513,17 @@ func (r *Runtime) GetRootlessNetNs(new bool) (*RootlessNetNS, error) { // build a new resolv.conf file which uses the slirp4netns dns server address resolveIP, err := GetSlirp4netnsDNS(nil) if err != nil { - return nil, errors.Wrap(err, "failed to determine default slirp4netns DNS address") + return nil, fmt.Errorf("failed to determine default slirp4netns DNS address: %w", err) } if netOptions.cidr != "" { _, cidr, err := net.ParseCIDR(netOptions.cidr) if err != nil { - return nil, errors.Wrap(err, "failed to parse slirp4netns cidr") + return nil, fmt.Errorf("failed to parse slirp4netns cidr: %w", err) } resolveIP, err = GetSlirp4netnsDNS(cidr) if err != nil { - return nil, errors.Wrapf(err, "failed to determine slirp4netns DNS address from cidr: %s", cidr.String()) + return nil, fmt.Errorf("failed to determine slirp4netns DNS address from cidr: %s: %w", cidr.String(), err) } } @@ -537,35 +537,35 @@ func (r *Runtime) GetRootlessNetNs(new bool) (*RootlessNetNS, error) { KeepHostServers: true, Nameservers: []string{resolveIP.String()}, }); err != nil { - return nil, errors.Wrap(err, "failed to create rootless netns resolv.conf") + return nil, fmt.Errorf("failed to create rootless netns resolv.conf: %w", err) } // create cni directories to store files // they will be bind mounted to the correct location in a extra mount ns err = os.MkdirAll(filepath.Join(rootlessNetNsDir, persistentCNIDir), 0700) if err != nil { - return nil, errors.Wrap(err, "could not create rootless-netns var directory") + return nil, fmt.Errorf("could not create rootless-netns var directory: %w", err) } runDir := filepath.Join(rootlessNetNsDir, "run") err = os.MkdirAll(runDir, 0700) if err != nil { - return nil, errors.Wrap(err, "could not create rootless-netns run directory") + return nil, fmt.Errorf("could not create rootless-netns run directory: %w", err) } // relabel the new run directory to the iptables /run label // this is important, otherwise the iptables command will fail err = label.Relabel(runDir, "system_u:object_r:iptables_var_run_t:s0", false) if err != nil { - return nil, errors.Wrap(err, "could not create relabel rootless-netns run directory") + return nil, fmt.Errorf("could not create relabel rootless-netns run directory: %w", err) } // create systemd run directory err = os.MkdirAll(filepath.Join(runDir, "systemd"), 0700) if err != nil { - return nil, errors.Wrap(err, "could not create rootless-netns systemd directory") + return nil, fmt.Errorf("could not create rootless-netns systemd directory: %w", err) } // create the directory for the netns files at the same location // relative to the rootless-netns location err = os.MkdirAll(filepath.Join(rootlessNetNsDir, nsDir), 0700) if err != nil { - return nil, errors.Wrap(err, "could not create rootless-netns netns directory") + return nil, fmt.Errorf("could not create rootless-netns netns directory: %w", err) } } @@ -675,7 +675,7 @@ func (r *Runtime) configureNetNS(ctr *Container, ctrNS ns.NetNS) (status map[str func (r *Runtime) createNetNS(ctr *Container) (n ns.NetNS, q map[string]types.StatusBlock, retErr error) { ctrNS, err := netns.NewNS() if err != nil { - return nil, nil, errors.Wrapf(err, "error creating network namespace for container %s", ctr.ID()) + return nil, nil, fmt.Errorf("error creating network namespace for container %s: %w", ctr.ID(), err) } defer func() { if retErr != nil { @@ -702,7 +702,7 @@ func (r *Runtime) setupNetNS(ctr *Container) error { b := make([]byte, 16) if _, err := rand.Reader.Read(b); err != nil { - return errors.Wrapf(err, "failed to generate random netns name") + return fmt.Errorf("failed to generate random netns name: %w", err) } nsPath, err := netns.GetNSRunDir() if err != nil { @@ -723,7 +723,7 @@ func (r *Runtime) setupNetNS(ctr *Container) error { } if err := unix.Mount(nsProcess, nsPath, "none", unix.MS_BIND, ""); err != nil { - return errors.Wrapf(err, "cannot mount %s", nsPath) + return fmt.Errorf("cannot mount %s: %w", nsPath, err) } netNS, err := ns.GetNS(nsPath) @@ -742,7 +742,7 @@ func (r *Runtime) setupNetNS(ctr *Container) error { func joinNetNS(path string) (ns.NetNS, error) { netNS, err := ns.GetNS(path) if err != nil { - return nil, errors.Wrapf(err, "error retrieving network namespace at %s", path) + return nil, fmt.Errorf("error retrieving network namespace at %s: %w", path, err) } return netNS, nil @@ -758,7 +758,7 @@ func (r *Runtime) closeNetNS(ctr *Container) error { } if err := ctr.state.NetNS.Close(); err != nil { - return errors.Wrapf(err, "error closing network namespace for container %s", ctr.ID()) + return fmt.Errorf("error closing network namespace for container %s: %w", ctr.ID(), err) } ctr.state.NetNS = nil @@ -774,8 +774,10 @@ func (r *Runtime) teardownNetwork(ns string, opts types.NetworkOptions) error { return err } tearDownPod := func() error { - err := r.network.Teardown(ns, types.TeardownOptions{NetworkOptions: opts}) - return errors.Wrapf(err, "error tearing down network namespace configuration for container %s", opts.ContainerID) + if err := r.network.Teardown(ns, types.TeardownOptions{NetworkOptions: opts}); err != nil { + return fmt.Errorf("error tearing down network namespace configuration for container %s: %w", opts.ContainerID, err) + } + return nil } // rootlessNetNS is nil if we are root @@ -826,12 +828,12 @@ func (r *Runtime) teardownNetNS(ctr *Container) error { // First unmount the namespace if err := netns.UnmountNS(ctr.state.NetNS); err != nil { - return errors.Wrapf(err, "error unmounting network namespace for container %s", ctr.ID()) + return fmt.Errorf("error unmounting network namespace for container %s: %w", ctr.ID(), err) } // Now close the open file descriptor if err := ctr.state.NetNS.Close(); err != nil { - return errors.Wrapf(err, "error closing network namespace for container %s", ctr.ID()) + return fmt.Errorf("error closing network namespace for container %s: %w", ctr.ID(), err) } ctr.state.NetNS = nil @@ -864,7 +866,7 @@ func getContainerNetNS(ctr *Container) (string, *Container, error) { // It returns nil when it is set to bridge and an error otherwise. func isBridgeNetMode(n namespaces.NetworkMode) error { if !n.IsBridge() { - return errors.Wrapf(define.ErrNetworkModeInvalid, "%q is not supported", n) + return fmt.Errorf("%q is not supported: %w", n, define.ErrNetworkModeInvalid) } return nil } @@ -880,7 +882,7 @@ func isBridgeNetMode(n namespaces.NetworkMode) error { // extend this to stop + restart slirp4netns func (r *Runtime) reloadContainerNetwork(ctr *Container) (map[string]types.StatusBlock, error) { if ctr.state.NetNS == nil { - return nil, errors.Wrapf(define.ErrCtrStateInvalid, "container %s network is not configured, refusing to reload", ctr.ID()) + return nil, fmt.Errorf("container %s network is not configured, refusing to reload: %w", ctr.ID(), define.ErrCtrStateInvalid) } if err := isBridgeNetMode(ctr.config.NetMode); err != nil { return nil, err @@ -1047,7 +1049,7 @@ func (c *Container) getContainerNetworkInfo() (*define.InspectNetworkSettings, e // If we have networks - handle that here if len(networks) > 0 { if len(networks) != len(netStatus) { - return nil, errors.Wrapf(define.ErrInternal, "network inspection mismatch: asked to join %d network(s) %v, but have information on %d network(s)", len(networks), networks, len(netStatus)) + return nil, fmt.Errorf("network inspection mismatch: asked to join %d network(s) %v, but have information on %d network(s): %w", len(networks), networks, len(netStatus), define.ErrInternal) } settings.Networks = make(map[string]*define.InspectAdditionalNetwork) @@ -1072,7 +1074,7 @@ func (c *Container) getContainerNetworkInfo() (*define.InspectNetworkSettings, e // If not joining networks, we should have at most 1 result if len(netStatus) > 1 { - return nil, errors.Wrapf(define.ErrInternal, "should have at most 1 network status result if not joining networks, instead got %d", len(netStatus)) + return nil, fmt.Errorf("should have at most 1 network status result if not joining networks, instead got %d: %w", len(netStatus), define.ErrInternal) } if len(netStatus) == 1 { @@ -1225,7 +1227,7 @@ func (c *Container) NetworkDisconnect(nameOrID, netName string, force bool) erro _, nameExists := networks[netName] if !nameExists && len(networks) > 0 { - return errors.Errorf("container %s is not connected to network %s", nameOrID, netName) + return fmt.Errorf("container %s is not connected to network %s", nameOrID, netName) } if err := c.syncContainer(); err != nil { @@ -1244,7 +1246,7 @@ func (c *Container) NetworkDisconnect(nameOrID, netName string, force bool) erro } if c.state.NetNS == nil { - return errors.Wrapf(define.ErrNoNetwork, "unable to disconnect %s from %s", nameOrID, netName) + return fmt.Errorf("unable to disconnect %s from %s: %w", nameOrID, netName, define.ErrNoNetwork) } opts := types.NetworkOptions{ @@ -1362,7 +1364,7 @@ func (c *Container) NetworkConnect(nameOrID, netName string, netOpts types.PerNe return nil } if c.state.NetNS == nil { - return errors.Wrapf(define.ErrNoNetwork, "unable to connect %s to %s", nameOrID, netName) + return fmt.Errorf("unable to connect %s to %s: %w", nameOrID, netName, define.ErrNoNetwork) } opts := types.NetworkOptions{ diff --git a/libpod/networking_slirp4netns.go b/libpod/networking_slirp4netns.go index 788834435..4a6462d46 100644 --- a/libpod/networking_slirp4netns.go +++ b/libpod/networking_slirp4netns.go @@ -5,6 +5,7 @@ package libpod import ( "bytes" + "errors" "fmt" "io" "io/ioutil" @@ -24,7 +25,6 @@ import ( "github.com/containers/podman/v4/pkg/rootless" "github.com/containers/podman/v4/pkg/rootlessport" "github.com/containers/podman/v4/pkg/servicereaper" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -68,7 +68,7 @@ func checkSlirpFlags(path string) (*slirpFeatures, error) { cmd := exec.Command(path, "--help") out, err := cmd.CombinedOutput() if err != nil { - return nil, errors.Wrapf(err, "slirp4netns %q", out) + return nil, fmt.Errorf("slirp4netns %q: %w", out, err) } return &slirpFeatures{ HasDisableHostLoopback: strings.Contains(string(out), "--disable-host-loopback"), @@ -95,14 +95,14 @@ func parseSlirp4netnsNetworkOptions(r *Runtime, extraOptions []string) (*slirp4n for _, o := range slirpOptions { parts := strings.SplitN(o, "=", 2) if len(parts) < 2 { - return nil, errors.Errorf("unknown option for slirp4netns: %q", o) + return nil, fmt.Errorf("unknown option for slirp4netns: %q", o) } option, value := parts[0], parts[1] switch option { case "cidr": ipv4, _, err := net.ParseCIDR(value) if err != nil || ipv4.To4() == nil { - return nil, errors.Errorf("invalid cidr %q", value) + return nil, fmt.Errorf("invalid cidr %q", value) } slirp4netnsOpts.cidr = value case "port_handler": @@ -112,7 +112,7 @@ func parseSlirp4netnsNetworkOptions(r *Runtime, extraOptions []string) (*slirp4n case "rootlesskit": slirp4netnsOpts.isSlirpHostForward = false default: - return nil, errors.Errorf("unknown port_handler for slirp4netns: %q", value) + return nil, fmt.Errorf("unknown port_handler for slirp4netns: %q", value) } case "allow_host_loopback": switch value { @@ -121,7 +121,7 @@ func parseSlirp4netnsNetworkOptions(r *Runtime, extraOptions []string) (*slirp4n case "false": slirp4netnsOpts.disableHostLoopback = true default: - return nil, errors.Errorf("invalid value of allow_host_loopback for slirp4netns: %q", value) + return nil, fmt.Errorf("invalid value of allow_host_loopback for slirp4netns: %q", value) } case "enable_ipv6": switch value { @@ -130,14 +130,14 @@ func parseSlirp4netnsNetworkOptions(r *Runtime, extraOptions []string) (*slirp4n case "false": slirp4netnsOpts.enableIPv6 = false default: - return nil, errors.Errorf("invalid value of enable_ipv6 for slirp4netns: %q", value) + return nil, fmt.Errorf("invalid value of enable_ipv6 for slirp4netns: %q", value) } case "outbound_addr": ipv4 := net.ParseIP(value) if ipv4 == nil || ipv4.To4() == nil { _, err := net.InterfaceByName(value) if err != nil { - return nil, errors.Errorf("invalid outbound_addr %q", value) + return nil, fmt.Errorf("invalid outbound_addr %q", value) } } slirp4netnsOpts.outboundAddr = value @@ -146,7 +146,7 @@ func parseSlirp4netnsNetworkOptions(r *Runtime, extraOptions []string) (*slirp4n if ipv6 == nil || ipv6.To4() != nil { _, err := net.InterfaceByName(value) if err != nil { - return nil, errors.Errorf("invalid outbound_addr6: %q", value) + return nil, fmt.Errorf("invalid outbound_addr6: %q", value) } } slirp4netnsOpts.outboundAddr6 = value @@ -154,10 +154,10 @@ func parseSlirp4netnsNetworkOptions(r *Runtime, extraOptions []string) (*slirp4n var err error slirp4netnsOpts.mtu, err = strconv.Atoi(value) if slirp4netnsOpts.mtu < 68 || err != nil { - return nil, errors.Errorf("invalid mtu %q", value) + return nil, fmt.Errorf("invalid mtu %q", value) } default: - return nil, errors.Errorf("unknown option for slirp4netns: %q", o) + return nil, fmt.Errorf("unknown option for slirp4netns: %q", o) } } return slirp4netnsOpts, nil @@ -180,31 +180,31 @@ func createBasicSlirp4netnsCmdArgs(options *slirp4netnsNetworkOptions, features if options.cidr != "" { if !features.HasCIDR { - return nil, errors.Errorf("cidr not supported") + return nil, fmt.Errorf("cidr not supported") } cmdArgs = append(cmdArgs, fmt.Sprintf("--cidr=%s", options.cidr)) } if options.enableIPv6 { if !features.HasIPv6 { - return nil, errors.Errorf("enable_ipv6 not supported") + return nil, fmt.Errorf("enable_ipv6 not supported") } cmdArgs = append(cmdArgs, "--enable-ipv6") } if options.outboundAddr != "" { if !features.HasOutboundAddr { - return nil, errors.Errorf("outbound_addr not supported") + return nil, fmt.Errorf("outbound_addr not supported") } cmdArgs = append(cmdArgs, fmt.Sprintf("--outbound-addr=%s", options.outboundAddr)) } if options.outboundAddr6 != "" { if !features.HasOutboundAddr || !features.HasIPv6 { - return nil, errors.Errorf("outbound_addr6 not supported") + return nil, fmt.Errorf("outbound_addr6 not supported") } if !options.enableIPv6 { - return nil, errors.Errorf("enable_ipv6=true is required for outbound_addr6") + return nil, fmt.Errorf("enable_ipv6=true is required for outbound_addr6") } cmdArgs = append(cmdArgs, fmt.Sprintf("--outbound-addr6=%s", options.outboundAddr6)) } @@ -225,7 +225,7 @@ func (r *Runtime) setupSlirp4netns(ctr *Container, netns ns.NetNS) error { syncR, syncW, err := os.Pipe() if err != nil { - return errors.Wrapf(err, "failed to open pipe") + return fmt.Errorf("failed to open pipe: %w", err) } defer errorhandling.CloseQuiet(syncR) defer errorhandling.CloseQuiet(syncW) @@ -243,7 +243,7 @@ func (r *Runtime) setupSlirp4netns(ctr *Container, netns ns.NetNS) error { } slirpFeatures, err := checkSlirpFlags(path) if err != nil { - return errors.Wrapf(err, "error checking slirp4netns binary %s: %q", path, err) + return fmt.Errorf("error checking slirp4netns binary %s: %q: %w", path, err, err) } cmdArgs, err := createBasicSlirp4netnsCmdArgs(netOptions, slirpFeatures) if err != nil { @@ -266,7 +266,7 @@ func (r *Runtime) setupSlirp4netns(ctr *Container, netns ns.NetNS) error { if !ctr.config.PostConfigureNetNS { ctr.rootlessSlirpSyncR, ctr.rootlessSlirpSyncW, err = os.Pipe() if err != nil { - return errors.Wrapf(err, "failed to create rootless network sync pipe") + return fmt.Errorf("failed to create rootless network sync pipe: %w", err) } netnsPath = netns.Path() cmdArgs = append(cmdArgs, "--netns-type=path", netnsPath, "tap0") @@ -295,13 +295,13 @@ func (r *Runtime) setupSlirp4netns(ctr *Container, netns ns.NetNS) error { logFile, err := os.Create(logPath) if err != nil { - return errors.Wrapf(err, "failed to open slirp4netns log file %s", logPath) + return fmt.Errorf("failed to open slirp4netns log file %s: %w", logPath, err) } defer logFile.Close() // Unlink immediately the file so we won't need to worry about cleaning it up later. // It is still accessible through the open fd logFile. if err := os.Remove(logPath); err != nil { - return errors.Wrapf(err, "delete file %s", logPath) + return fmt.Errorf("delete file %s: %w", logPath, err) } cmd.Stdout = logFile cmd.Stderr = logFile @@ -357,7 +357,7 @@ func (r *Runtime) setupSlirp4netns(ctr *Container, netns ns.NetNS) error { if netOptions.enableIPv6 { slirpReadyWg.Done() } - return errors.Wrapf(err, "failed to start slirp4netns process") + return fmt.Errorf("failed to start slirp4netns process: %w", err) } defer func() { servicereaper.AddPID(cmd.Process.Pid) @@ -381,7 +381,7 @@ func (r *Runtime) setupSlirp4netns(ctr *Container, netns ns.NetNS) error { if netOptions.cidr != "" { ipv4, ipv4network, err := net.ParseCIDR(netOptions.cidr) if err != nil || ipv4.To4() == nil { - return errors.Errorf("invalid cidr %q", netOptions.cidr) + return fmt.Errorf("invalid cidr %q", netOptions.cidr) } ctr.slirp4netnsSubnet = ipv4network } @@ -405,7 +405,7 @@ func GetSlirp4netnsIP(subnet *net.IPNet) (*net.IP, error) { } expectedIP, err := addToIP(slirpSubnet, uint32(100)) if err != nil { - return nil, errors.Wrapf(err, "error calculating expected ip for slirp4netns") + return nil, fmt.Errorf("error calculating expected ip for slirp4netns: %w", err) } return expectedIP, nil } @@ -419,7 +419,7 @@ func GetSlirp4netnsGateway(subnet *net.IPNet) (*net.IP, error) { } expectedGatewayIP, err := addToIP(slirpSubnet, uint32(2)) if err != nil { - return nil, errors.Wrapf(err, "error calculating expected gateway ip for slirp4netns") + return nil, fmt.Errorf("error calculating expected gateway ip for slirp4netns: %w", err) } return expectedGatewayIP, nil } @@ -433,7 +433,7 @@ func GetSlirp4netnsDNS(subnet *net.IPNet) (*net.IP, error) { } expectedDNSIP, err := addToIP(slirpSubnet, uint32(3)) if err != nil { - return nil, errors.Wrapf(err, "error calculating expected dns ip for slirp4netns") + return nil, fmt.Errorf("error calculating expected dns ip for slirp4netns: %w", err) } return expectedDNSIP, nil } @@ -448,11 +448,11 @@ func addToIP(subnet *net.IPNet, offset uint32) (*net.IP, error) { ipNewRaw := ipInteger + offset // Avoid overflows if ipNewRaw < ipInteger { - return nil, errors.Errorf("integer overflow while calculating ip address offset, %s + %d", ipFixed, offset) + return nil, fmt.Errorf("integer overflow while calculating ip address offset, %s + %d", ipFixed, offset) } ipNew := net.IPv4(byte(ipNewRaw>>24), byte(ipNewRaw>>16&0xFF), byte(ipNewRaw>>8)&0xFF, byte(ipNewRaw&0xFF)) if !subnet.Contains(ipNew) { - return nil, errors.Errorf("calculated ip address %s is not within given subnet %s", ipNew.String(), subnet.String()) + return nil, fmt.Errorf("calculated ip address %s is not within given subnet %s", ipNew.String(), subnet.String()) } return &ipNew, nil } @@ -465,7 +465,7 @@ func waitForSync(syncR *os.File, cmd *exec.Cmd, logFile io.ReadSeeker, timeout t b := make([]byte, 16) for { if err := syncR.SetDeadline(time.Now().Add(timeout)); err != nil { - return errors.Wrapf(err, "error setting %s pipe timeout", prog) + return fmt.Errorf("error setting %s pipe timeout: %w", prog, err) } // FIXME: return err as soon as proc exits, without waiting for timeout if _, err := syncR.Read(b); err == nil { @@ -476,7 +476,7 @@ func waitForSync(syncR *os.File, cmd *exec.Cmd, logFile io.ReadSeeker, timeout t var status syscall.WaitStatus pid, err := syscall.Wait4(cmd.Process.Pid, &status, syscall.WNOHANG, nil) if err != nil { - return errors.Wrapf(err, "failed to read %s process status", prog) + return fmt.Errorf("failed to read %s process status: %w", prog, err) } if pid != cmd.Process.Pid { continue @@ -488,16 +488,16 @@ func waitForSync(syncR *os.File, cmd *exec.Cmd, logFile io.ReadSeeker, timeout t } logContent, err := ioutil.ReadAll(logFile) if err != nil { - return errors.Wrapf(err, "%s failed", prog) + return fmt.Errorf("%s failed: %w", prog, err) } - return errors.Errorf("%s failed: %q", prog, logContent) + return fmt.Errorf("%s failed: %q", prog, logContent) } if status.Signaled() { - return errors.Errorf("%s killed by signal", prog) + return fmt.Errorf("%s killed by signal", prog) } continue } - return errors.Wrapf(err, "failed to read from %s sync pipe", prog) + return fmt.Errorf("failed to read from %s sync pipe: %w", prog, err) } } return nil @@ -506,7 +506,7 @@ func waitForSync(syncR *os.File, cmd *exec.Cmd, logFile io.ReadSeeker, timeout t func (r *Runtime) setupRootlessPortMappingViaRLK(ctr *Container, netnsPath string, netStatus map[string]types.StatusBlock) error { syncR, syncW, err := os.Pipe() if err != nil { - return errors.Wrapf(err, "failed to open pipe") + return fmt.Errorf("failed to open pipe: %w", err) } defer errorhandling.CloseQuiet(syncR) defer errorhandling.CloseQuiet(syncW) @@ -514,19 +514,19 @@ func (r *Runtime) setupRootlessPortMappingViaRLK(ctr *Container, netnsPath strin logPath := filepath.Join(ctr.runtime.config.Engine.TmpDir, fmt.Sprintf("rootlessport-%s.log", ctr.config.ID)) logFile, err := os.Create(logPath) if err != nil { - return errors.Wrapf(err, "failed to open rootlessport log file %s", logPath) + return fmt.Errorf("failed to open rootlessport log file %s: %w", logPath, err) } defer logFile.Close() // Unlink immediately the file so we won't need to worry about cleaning it up later. // It is still accessible through the open fd logFile. if err := os.Remove(logPath); err != nil { - return errors.Wrapf(err, "delete file %s", logPath) + return fmt.Errorf("delete file %s: %w", logPath, err) } if !ctr.config.PostConfigureNetNS { ctr.rootlessPortSyncR, ctr.rootlessPortSyncW, err = os.Pipe() if err != nil { - return errors.Wrapf(err, "failed to create rootless port sync pipe") + return fmt.Errorf("failed to create rootless port sync pipe: %w", err) } } @@ -566,7 +566,7 @@ func (r *Runtime) setupRootlessPortMappingViaRLK(ctr *Container, netnsPath strin Setpgid: true, } if err := cmd.Start(); err != nil { - return errors.Wrapf(err, "failed to start rootlessport process") + return fmt.Errorf("failed to start rootlessport process: %w", err) } defer func() { servicereaper.AddPID(cmd.Process.Pid) @@ -579,7 +579,7 @@ func (r *Runtime) setupRootlessPortMappingViaRLK(ctr *Container, netnsPath strin if stdoutStr != "" { // err contains full debug log and too verbose, so return stdoutStr logrus.Debug(err) - return errors.Errorf("rootlessport " + strings.TrimSuffix(stdoutStr, "\n")) + return fmt.Errorf("rootlessport " + strings.TrimSuffix(stdoutStr, "\n")) } return err } @@ -612,7 +612,7 @@ func (r *Runtime) setupRootlessPortMappingViaSlirp(ctr *Container, cmd *exec.Cmd // wait that API socket file appears before trying to use it. if _, err := WaitForFile(apiSocket, chWait, pidWaitTimeout); err != nil { - return errors.Wrapf(err, "waiting for slirp4nets to create the api socket file %s", apiSocket) + return fmt.Errorf("waiting for slirp4nets to create the api socket file %s: %w", apiSocket, err) } // for each port we want to add we need to open a connection to the slirp4netns control socket @@ -639,7 +639,7 @@ func (r *Runtime) setupRootlessPortMappingViaSlirp(ctr *Container, cmd *exec.Cmd func openSlirp4netnsPort(apiSocket, proto, hostip string, hostport, guestport uint16) error { conn, err := net.Dial("unix", apiSocket) if err != nil { - return errors.Wrapf(err, "cannot open connection to %s", apiSocket) + return fmt.Errorf("cannot open connection to %s: %w", apiSocket, err) } defer func() { if err := conn.Close(); err != nil { @@ -659,27 +659,27 @@ func openSlirp4netnsPort(apiSocket, proto, hostip string, hostport, guestport ui // to the socket, as requested by slirp4netns. data, err := json.Marshal(&apiCmd) if err != nil { - return errors.Wrapf(err, "cannot marshal JSON for slirp4netns") + return fmt.Errorf("cannot marshal JSON for slirp4netns: %w", err) } if _, err := conn.Write([]byte(fmt.Sprintf("%s\n", data))); err != nil { - return errors.Wrapf(err, "cannot write to control socket %s", apiSocket) + return fmt.Errorf("cannot write to control socket %s: %w", apiSocket, err) } if err := conn.(*net.UnixConn).CloseWrite(); err != nil { - return errors.Wrapf(err, "cannot shutdown the socket %s", apiSocket) + return fmt.Errorf("cannot shutdown the socket %s: %w", apiSocket, err) } buf := make([]byte, 2048) readLength, err := conn.Read(buf) if err != nil { - return errors.Wrapf(err, "cannot read from control socket %s", apiSocket) + return fmt.Errorf("cannot read from control socket %s: %w", apiSocket, err) } // if there is no 'error' key in the received JSON data, then the operation was // successful. var y map[string]interface{} if err := json.Unmarshal(buf[0:readLength], &y); err != nil { - return errors.Wrapf(err, "error parsing error status from slirp4netns") + return fmt.Errorf("error parsing error status from slirp4netns: %w", err) } if e, found := y["error"]; found { - return errors.Errorf("from slirp4netns while setting up port redirection: %v", e) + return fmt.Errorf("from slirp4netns while setting up port redirection: %v", e) } return nil } @@ -722,21 +722,21 @@ func (c *Container) reloadRootlessRLKPortMapping() error { conn, err := openUnixSocket(filepath.Join(c.runtime.config.Engine.TmpDir, "rp", c.config.ID)) if err != nil { - return errors.Wrap(err, "could not reload rootless port mappings, port forwarding may no longer work correctly") + return fmt.Errorf("could not reload rootless port mappings, port forwarding may no longer work correctly: %w", err) } defer conn.Close() enc := json.NewEncoder(conn) err = enc.Encode(childIP) if err != nil { - return errors.Wrap(err, "port reloading failed") + return fmt.Errorf("port reloading failed: %w", err) } b, err := ioutil.ReadAll(conn) if err != nil { - return errors.Wrap(err, "port reloading failed") + return fmt.Errorf("port reloading failed: %w", err) } data := string(b) if data != "OK" { - return errors.Errorf("port reloading failed: %s", data) + return fmt.Errorf("port reloading failed: %s", data) } return nil } diff --git a/libpod/oci.go b/libpod/oci.go index 90862969c..70053db1b 100644 --- a/libpod/oci.go +++ b/libpod/oci.go @@ -3,6 +3,7 @@ package libpod import ( "net/http" + "github.com/containers/common/pkg/resize" "github.com/containers/podman/v4/libpod/define" ) @@ -66,7 +67,7 @@ type OCIRuntime interface { // client. HTTPAttach(ctr *Container, r *http.Request, w http.ResponseWriter, streams *HTTPAttachStreams, detachKeys *string, cancel <-chan bool, hijackDone chan<- bool, streamAttach, streamLogs bool) error // AttachResize resizes the terminal in use by the given container. - AttachResize(ctr *Container, newSize define.TerminalSize) error + AttachResize(ctr *Container, newSize resize.TerminalSize) error // ExecContainer executes a command in a running container. // Returns an int (PID of exec session), error channel (errors from @@ -76,7 +77,7 @@ type OCIRuntime interface { // running, in a goroutine that will return via the chan error in the // return signature. // newSize resizes the tty to this size before the process is started, must be nil if the exec session has no tty - ExecContainer(ctr *Container, sessionID string, options *ExecOptions, streams *define.AttachStreams, newSize *define.TerminalSize) (int, chan error, error) + ExecContainer(ctr *Container, sessionID string, options *ExecOptions, streams *define.AttachStreams, newSize *resize.TerminalSize) (int, chan error, error) // ExecContainerHTTP executes a command in a running container and // attaches its standard streams to a provided hijacked HTTP session. // Maintains the same invariants as ExecContainer (returns on session @@ -84,14 +85,14 @@ type OCIRuntime interface { // The HTTP attach itself maintains the same invariants as HTTPAttach. // newSize resizes the tty to this size before the process is started, must be nil if the exec session has no tty ExecContainerHTTP(ctr *Container, sessionID string, options *ExecOptions, r *http.Request, w http.ResponseWriter, - streams *HTTPAttachStreams, cancel <-chan bool, hijackDone chan<- bool, holdConnOpen <-chan bool, newSize *define.TerminalSize) (int, chan error, error) + streams *HTTPAttachStreams, cancel <-chan bool, hijackDone chan<- bool, holdConnOpen <-chan bool, newSize *resize.TerminalSize) (int, chan error, error) // ExecContainerDetached executes a command in a running container, but // does not attach to it. Returns the PID of the exec session and an // error (if starting the exec session failed) ExecContainerDetached(ctr *Container, sessionID string, options *ExecOptions, stdin bool) (int, error) // ExecAttachResize resizes the terminal of a running exec session. Only // allowed with sessions that were created with a TTY. - ExecAttachResize(ctr *Container, sessionID string, newSize define.TerminalSize) error + ExecAttachResize(ctr *Container, sessionID string, newSize resize.TerminalSize) error // ExecStopContainer stops a given exec session in a running container. // SIGTERM with be sent initially, then SIGKILL after the given timeout. // If timeout is 0, SIGKILL will be sent immediately, and SIGTERM will @@ -161,7 +162,7 @@ type AttachOptions struct { DetachKeys *string // InitialSize is the initial size of the terminal. Set before the // attach begins. - InitialSize *define.TerminalSize + InitialSize *resize.TerminalSize // AttachReady signals when the attach has successfully completed and // streaming has begun. AttachReady chan<- bool diff --git a/libpod/oci_conmon_attach_linux.go b/libpod/oci_conmon_attach_linux.go index 26f9ba083..aa55aa6f5 100644 --- a/libpod/oci_conmon_attach_linux.go +++ b/libpod/oci_conmon_attach_linux.go @@ -4,6 +4,7 @@ package libpod import ( + "errors" "fmt" "io" "net" @@ -12,12 +13,11 @@ import ( "syscall" "github.com/containers/common/pkg/config" + "github.com/containers/common/pkg/resize" + "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/errorhandling" - "github.com/containers/podman/v4/pkg/kubeutils" - "github.com/containers/podman/v4/utils" "github.com/moby/term" - "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/sys/unix" ) @@ -45,14 +45,14 @@ func (r *ConmonOCIRuntime) Attach(c *Container, params *AttachOptions) error { passthrough := c.LogDriver() == define.PassthroughLogging if params == nil || params.Streams == nil { - return errors.Wrapf(define.ErrInternal, "must provide parameters to Attach") + return fmt.Errorf("must provide parameters to Attach: %w", define.ErrInternal) } if !params.Streams.AttachOutput && !params.Streams.AttachError && !params.Streams.AttachInput && !passthrough { - return errors.Wrapf(define.ErrInvalidArg, "must provide at least one stream to attach to") + return fmt.Errorf("must provide at least one stream to attach to: %w", define.ErrInvalidArg) } if params.Start && params.Started == nil { - return errors.Wrapf(define.ErrInternal, "started chan not passed when startContainer set") + return fmt.Errorf("started chan not passed when startContainer set: %w", define.ErrInternal) } keys := config.DefaultDetachKeys @@ -83,7 +83,7 @@ func (r *ConmonOCIRuntime) Attach(c *Container, params *AttachOptions) error { conn, err = openUnixSocket(attachSock) if err != nil { - return errors.Wrapf(err, "failed to connect to container's attach socket: %v", attachSock) + return fmt.Errorf("failed to connect to container's attach socket: %v: %w", attachSock, err) } defer func() { if err := conn.Close(); err != nil { @@ -130,12 +130,12 @@ func (r *ConmonOCIRuntime) Attach(c *Container, params *AttachOptions) error { // 4. attachToExec sends on startFd, signalling it has attached to the socket and child is ready to go // 5. child receives on startFd, runs the runtime exec command // attachToExec is responsible for closing startFd and attachFd -func (c *Container) attachToExec(streams *define.AttachStreams, keys *string, sessionID string, startFd, attachFd *os.File, newSize *define.TerminalSize) error { +func (c *Container) attachToExec(streams *define.AttachStreams, keys *string, sessionID string, startFd, attachFd *os.File, newSize *resize.TerminalSize) error { if !streams.AttachOutput && !streams.AttachError && !streams.AttachInput { - return errors.Wrapf(define.ErrInvalidArg, "must provide at least one stream to attach to") + return fmt.Errorf("must provide at least one stream to attach to: %w", define.ErrInvalidArg) } if startFd == nil || attachFd == nil { - return errors.Wrapf(define.ErrInvalidArg, "start sync pipe and attach sync pipe must be defined for exec attach") + return fmt.Errorf("start sync pipe and attach sync pipe must be defined for exec attach: %w", define.ErrInvalidArg) } defer errorhandling.CloseQuiet(startFd) @@ -174,7 +174,7 @@ func (c *Container) attachToExec(streams *define.AttachStreams, keys *string, se // 2: then attach conn, err := openUnixSocket(sockPath) if err != nil { - return errors.Wrapf(err, "failed to connect to container's attach socket: %v", sockPath) + return fmt.Errorf("failed to connect to container's attach socket: %v: %w", sockPath, err) } defer func() { if err := conn.Close(); err != nil { @@ -200,13 +200,13 @@ func processDetachKeys(keys string) ([]byte, error) { } detachKeys, err := term.ToBytes(keys) if err != nil { - return nil, errors.Wrapf(err, "invalid detach keys") + return nil, fmt.Errorf("invalid detach keys: %w", err) } return detachKeys, nil } -func registerResizeFunc(resize <-chan define.TerminalSize, bundlePath string) { - kubeutils.HandleResizing(resize, func(size define.TerminalSize) { +func registerResizeFunc(r <-chan resize.TerminalSize, bundlePath string) { + resize.HandleResizing(r, func(size resize.TerminalSize) { controlPath := filepath.Join(bundlePath, "ctl") controlFile, err := os.OpenFile(controlPath, unix.O_WRONLY, 0) if err != nil { @@ -232,7 +232,7 @@ func setupStdioChannels(streams *define.AttachStreams, conn *net.UnixConn, detac go func() { var err error if streams.AttachInput { - _, err = utils.CopyDetachable(conn, streams.InputStream, detachKeys) + _, err = util.CopyDetachable(conn, streams.InputStream, detachKeys) } stdinDone <- err }() diff --git a/libpod/oci_conmon_exec_linux.go b/libpod/oci_conmon_exec_linux.go index 70124bec1..16cd7ef9f 100644 --- a/libpod/oci_conmon_exec_linux.go +++ b/libpod/oci_conmon_exec_linux.go @@ -1,6 +1,7 @@ package libpod import ( + "errors" "fmt" "io/ioutil" "net/http" @@ -13,28 +14,28 @@ import ( "github.com/containers/common/pkg/capabilities" "github.com/containers/common/pkg/config" + "github.com/containers/common/pkg/resize" + cutil "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/errorhandling" "github.com/containers/podman/v4/pkg/lookup" "github.com/containers/podman/v4/pkg/util" - "github.com/containers/podman/v4/utils" spec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/sys/unix" ) // ExecContainer executes a command in a running container -func (r *ConmonOCIRuntime) ExecContainer(c *Container, sessionID string, options *ExecOptions, streams *define.AttachStreams, newSize *define.TerminalSize) (int, chan error, error) { +func (r *ConmonOCIRuntime) ExecContainer(c *Container, sessionID string, options *ExecOptions, streams *define.AttachStreams, newSize *resize.TerminalSize) (int, chan error, error) { if options == nil { - return -1, nil, errors.Wrapf(define.ErrInvalidArg, "must provide an ExecOptions struct to ExecContainer") + return -1, nil, fmt.Errorf("must provide an ExecOptions struct to ExecContainer: %w", define.ErrInvalidArg) } if len(options.Cmd) == 0 { - return -1, nil, errors.Wrapf(define.ErrInvalidArg, "must provide a command to execute") + return -1, nil, fmt.Errorf("must provide a command to execute: %w", define.ErrInvalidArg) } if sessionID == "" { - return -1, nil, errors.Wrapf(define.ErrEmptyID, "must provide a session ID for exec") + return -1, nil, fmt.Errorf("must provide a session ID for exec: %w", define.ErrEmptyID) } // TODO: Should we default this to false? @@ -73,7 +74,7 @@ func (r *ConmonOCIRuntime) ExecContainer(c *Container, sessionID string, options }() if err := execCmd.Wait(); err != nil { - return -1, nil, errors.Wrapf(err, "cannot run conmon") + return -1, nil, fmt.Errorf("cannot run conmon: %w", err) } pid, err := readConmonPipeData(r.name, pipes.syncPipe, ociLog) @@ -84,15 +85,15 @@ func (r *ConmonOCIRuntime) ExecContainer(c *Container, sessionID string, options // ExecContainerHTTP executes a new command in an existing container and // forwards its standard streams over an attach func (r *ConmonOCIRuntime) ExecContainerHTTP(ctr *Container, sessionID string, options *ExecOptions, req *http.Request, w http.ResponseWriter, - streams *HTTPAttachStreams, cancel <-chan bool, hijackDone chan<- bool, holdConnOpen <-chan bool, newSize *define.TerminalSize) (int, chan error, error) { + streams *HTTPAttachStreams, cancel <-chan bool, hijackDone chan<- bool, holdConnOpen <-chan bool, newSize *resize.TerminalSize) (int, chan error, error) { if streams != nil { if !streams.Stdin && !streams.Stdout && !streams.Stderr { - return -1, nil, errors.Wrapf(define.ErrInvalidArg, "must provide at least one stream to attach to") + return -1, nil, fmt.Errorf("must provide at least one stream to attach to: %w", define.ErrInvalidArg) } } if options == nil { - return -1, nil, errors.Wrapf(define.ErrInvalidArg, "must provide exec options to ExecContainerHTTP") + return -1, nil, fmt.Errorf("must provide exec options to ExecContainerHTTP: %w", define.ErrInvalidArg) } detachString := config.DefaultDetachKeys @@ -156,7 +157,7 @@ type conmonPipeData struct { // not attach to it. func (r *ConmonOCIRuntime) ExecContainerDetached(ctr *Container, sessionID string, options *ExecOptions, stdin bool) (int, error) { if options == nil { - return -1, errors.Wrapf(define.ErrInvalidArg, "must provide exec options to ExecContainerHTTP") + return -1, fmt.Errorf("must provide exec options to ExecContainerHTTP: %w", define.ErrInvalidArg) } var ociLog string @@ -187,7 +188,7 @@ func (r *ConmonOCIRuntime) ExecContainerDetached(ctr *Container, sessionID strin // Wait for conmon to succeed, when return. if err := execCmd.Wait(); err != nil { - return -1, errors.Wrapf(err, "cannot run conmon") + return -1, fmt.Errorf("cannot run conmon: %w", err) } pid, err := readConmonPipeData(r.name, pipes.syncPipe, ociLog) @@ -196,7 +197,7 @@ func (r *ConmonOCIRuntime) ExecContainerDetached(ctr *Container, sessionID strin } // ExecAttachResize resizes the TTY of the given exec session. -func (r *ConmonOCIRuntime) ExecAttachResize(ctr *Container, sessionID string, newSize define.TerminalSize) error { +func (r *ConmonOCIRuntime) ExecAttachResize(ctr *Container, sessionID string, newSize resize.TerminalSize) error { controlFile, err := openControlFile(ctr, ctr.execBundlePath(sessionID)) if err != nil { return err @@ -204,7 +205,7 @@ func (r *ConmonOCIRuntime) ExecAttachResize(ctr *Container, sessionID string, ne defer controlFile.Close() if _, err = fmt.Fprintf(controlFile, "%d %d %d\n", 1, newSize.Height, newSize.Width); err != nil { - return errors.Wrapf(err, "failed to write to ctl file to resize terminal") + return fmt.Errorf("failed to write to ctl file to resize terminal: %w", err) } return nil @@ -225,7 +226,7 @@ func (r *ConmonOCIRuntime) ExecStopContainer(ctr *Container, sessionID string, t if err == unix.ESRCH { return nil } - return errors.Wrapf(err, "error pinging container %s exec session %s PID %d with signal 0", ctr.ID(), sessionID, pid) + return fmt.Errorf("error pinging container %s exec session %s PID %d with signal 0: %w", ctr.ID(), sessionID, pid, err) } if timeout > 0 { @@ -235,7 +236,7 @@ func (r *ConmonOCIRuntime) ExecStopContainer(ctr *Container, sessionID string, t if err == unix.ESRCH { return nil } - return errors.Wrapf(err, "error killing container %s exec session %s PID %d with SIGTERM", ctr.ID(), sessionID, pid) + return fmt.Errorf("error killing container %s exec session %s PID %d with SIGTERM: %w", ctr.ID(), sessionID, pid, err) } // Wait for the PID to stop @@ -253,12 +254,12 @@ func (r *ConmonOCIRuntime) ExecStopContainer(ctr *Container, sessionID string, t if err == unix.ESRCH { return nil } - return errors.Wrapf(err, "error killing container %s exec session %s PID %d with SIGKILL", ctr.ID(), sessionID, pid) + return fmt.Errorf("error killing container %s exec session %s PID %d with SIGKILL: %w", ctr.ID(), sessionID, pid, err) } // Wait for the PID to stop if err := waitPidStop(pid, killContainerTimeout); err != nil { - return errors.Wrapf(err, "timed out waiting for container %s exec session %s PID %d to stop after SIGKILL", ctr.ID(), sessionID, pid) + return fmt.Errorf("timed out waiting for container %s exec session %s PID %d to stop after SIGKILL: %w", ctr.ID(), sessionID, pid, err) } return nil @@ -279,7 +280,7 @@ func (r *ConmonOCIRuntime) ExecUpdateStatus(ctr *Container, sessionID string) (b if err == unix.ESRCH { return false, nil } - return false, errors.Wrapf(err, "error pinging container %s exec session %s PID %d with signal 0", ctr.ID(), sessionID, pid) + return false, fmt.Errorf("error pinging container %s exec session %s PID %d with signal 0: %w", ctr.ID(), sessionID, pid, err) } return true, nil @@ -289,7 +290,7 @@ func (r *ConmonOCIRuntime) ExecUpdateStatus(ctr *Container, sessionID string) (b func (r *ConmonOCIRuntime) ExecAttachSocketPath(ctr *Container, sessionID string) (string, error) { // We don't even use container, so don't validity check it if sessionID == "" { - return "", errors.Wrapf(define.ErrInvalidArg, "must provide a valid session ID to get attach socket path") + return "", fmt.Errorf("must provide a valid session ID to get attach socket path: %w", define.ErrInvalidArg) } return filepath.Join(ctr.execBundlePath(sessionID), "attach"), nil @@ -325,20 +326,20 @@ func (r *ConmonOCIRuntime) startExec(c *Container, sessionID string, options *Ex pipes := new(execPipes) if options == nil { - return nil, nil, errors.Wrapf(define.ErrInvalidArg, "must provide an ExecOptions struct to ExecContainer") + return nil, nil, fmt.Errorf("must provide an ExecOptions struct to ExecContainer: %w", define.ErrInvalidArg) } if len(options.Cmd) == 0 { - return nil, nil, errors.Wrapf(define.ErrInvalidArg, "must provide a command to execute") + return nil, nil, fmt.Errorf("must provide a command to execute: %w", define.ErrInvalidArg) } if sessionID == "" { - return nil, nil, errors.Wrapf(define.ErrEmptyID, "must provide a session ID for exec") + return nil, nil, fmt.Errorf("must provide a session ID for exec: %w", define.ErrEmptyID) } // create sync pipe to receive the pid parentSyncPipe, childSyncPipe, err := newPipe() if err != nil { - return nil, nil, errors.Wrapf(err, "error creating socket pair") + return nil, nil, fmt.Errorf("error creating socket pair: %w", err) } pipes.syncPipe = parentSyncPipe @@ -352,7 +353,7 @@ func (r *ConmonOCIRuntime) startExec(c *Container, sessionID string, options *Ex // attachToExec is responsible for closing parentStartPipe childStartPipe, parentStartPipe, err := newPipe() if err != nil { - return nil, nil, errors.Wrapf(err, "error creating socket pair") + return nil, nil, fmt.Errorf("error creating socket pair: %w", err) } pipes.startPipe = parentStartPipe @@ -362,7 +363,7 @@ func (r *ConmonOCIRuntime) startExec(c *Container, sessionID string, options *Ex // attachToExec is responsible for closing parentAttachPipe parentAttachPipe, childAttachPipe, err := newPipe() if err != nil { - return nil, nil, errors.Wrapf(err, "error creating socket pair") + return nil, nil, fmt.Errorf("error creating socket pair: %w", err) } pipes.attachPipe = parentAttachPipe @@ -471,7 +472,7 @@ func (r *ConmonOCIRuntime) startExec(c *Container, sessionID string, options *Ex childrenClosed = true if err != nil { - return nil, nil, errors.Wrapf(err, "cannot start container %s", c.ID()) + return nil, nil, fmt.Errorf("cannot start container %s: %w", c.ID(), err) } if err := r.moveConmonToCgroupAndSignal(c, execCmd, parentStartPipe); err != nil { return nil, nil, err @@ -487,14 +488,14 @@ func (r *ConmonOCIRuntime) startExec(c *Container, sessionID string, options *Ex } // Attach to a container over HTTP -func attachExecHTTP(c *Container, sessionID string, r *http.Request, w http.ResponseWriter, streams *HTTPAttachStreams, pipes *execPipes, detachKeys []byte, isTerminal bool, cancel <-chan bool, hijackDone chan<- bool, holdConnOpen <-chan bool, execCmd *exec.Cmd, conmonPipeDataChan chan<- conmonPipeData, ociLog string, newSize *define.TerminalSize, runtimeName string) (deferredErr error) { +func attachExecHTTP(c *Container, sessionID string, r *http.Request, w http.ResponseWriter, streams *HTTPAttachStreams, pipes *execPipes, detachKeys []byte, isTerminal bool, cancel <-chan bool, hijackDone chan<- bool, holdConnOpen <-chan bool, execCmd *exec.Cmd, conmonPipeDataChan chan<- conmonPipeData, ociLog string, newSize *resize.TerminalSize, runtimeName string) (deferredErr error) { // NOTE: As you may notice, the attach code is quite complex. // Many things happen concurrently and yet are interdependent. // If you ever change this function, make sure to write to the // conmonPipeDataChan in case of an error. if pipes == nil || pipes.startPipe == nil || pipes.attachPipe == nil { - err := errors.Wrapf(define.ErrInvalidArg, "must provide a start and attach pipe to finish an exec attach") + err := fmt.Errorf("must provide a start and attach pipe to finish an exec attach: %w", define.ErrInvalidArg) conmonPipeDataChan <- conmonPipeData{-1, err} return err } @@ -537,7 +538,7 @@ func attachExecHTTP(c *Container, sessionID string, r *http.Request, w http.Resp conn, err := openUnixSocket(sockPath) if err != nil { conmonPipeDataChan <- conmonPipeData{-1, err} - return errors.Wrapf(err, "failed to connect to container's attach socket: %v", sockPath) + return fmt.Errorf("failed to connect to container's attach socket: %v: %w", sockPath, err) } defer func() { if err := conn.Close(); err != nil { @@ -558,13 +559,13 @@ func attachExecHTTP(c *Container, sessionID string, r *http.Request, w http.Resp hijacker, ok := w.(http.Hijacker) if !ok { conmonPipeDataChan <- conmonPipeData{-1, err} - return errors.Errorf("unable to hijack connection") + return errors.New("unable to hijack connection") } httpCon, httpBuf, err := hijacker.Hijack() if err != nil { conmonPipeDataChan <- conmonPipeData{-1, err} - return errors.Wrapf(err, "error hijacking connection") + return fmt.Errorf("error hijacking connection: %w", err) } hijackDone <- true @@ -575,7 +576,7 @@ func attachExecHTTP(c *Container, sessionID string, r *http.Request, w http.Resp // Force a flush after the header is written. if err := httpBuf.Flush(); err != nil { conmonPipeDataChan <- conmonPipeData{-1, err} - return errors.Wrapf(err, "error flushing HTTP hijack header") + return fmt.Errorf("error flushing HTTP hijack header: %w", err) } go func() { @@ -607,7 +608,7 @@ func attachExecHTTP(c *Container, sessionID string, r *http.Request, w http.Resp if attachStdin { go func() { logrus.Debugf("Beginning STDIN copy") - _, err := utils.CopyDetachable(conn, httpBuf, detachKeys) + _, err := cutil.CopyDetachable(conn, httpBuf, detachKeys) logrus.Debugf("STDIN copy completed") stdinChan <- err }() @@ -723,7 +724,7 @@ func prepareProcessExec(c *Container, options *ExecOptions, env []string, sessio if len(addGroups) > 0 { sgids, err = lookup.GetContainerGroups(addGroups, c.state.Mountpoint, overrides) if err != nil { - return nil, errors.Wrapf(err, "error looking up supplemental groups for container %s exec session %s", c.ID(), sessionID) + return nil, fmt.Errorf("error looking up supplemental groups for container %s exec session %s: %w", c.ID(), sessionID, err) } } diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go index 7a9ae7ee5..0cdfe90e9 100644 --- a/libpod/oci_conmon_linux.go +++ b/libpod/oci_conmon_linux.go @@ -7,6 +7,7 @@ import ( "bufio" "bytes" "context" + "errors" "fmt" "io" "io/ioutil" @@ -28,6 +29,8 @@ import ( "github.com/containers/common/pkg/cgroups" "github.com/containers/common/pkg/config" + "github.com/containers/common/pkg/resize" + cutil "github.com/containers/common/pkg/util" conmonConfig "github.com/containers/conmon/runner/config" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/libpod/logs" @@ -41,7 +44,6 @@ import ( pmount "github.com/containers/storage/pkg/mount" spec "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/selinux/go-selinux/label" - "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/sys/unix" ) @@ -81,7 +83,7 @@ type ConmonOCIRuntime struct { // libpod. func newConmonOCIRuntime(name string, paths []string, conmonPath string, runtimeFlags []string, runtimeCfg *config.Config) (OCIRuntime, error) { if name == "" { - return nil, errors.Wrapf(define.ErrInvalidArg, "the OCI runtime must be provided a non-empty name") + return nil, fmt.Errorf("the OCI runtime must be provided a non-empty name: %w", define.ErrInvalidArg) } // Make lookup tables for runtime support @@ -125,7 +127,7 @@ func newConmonOCIRuntime(name string, paths []string, conmonPath string, runtime if os.IsNotExist(err) { continue } - return nil, errors.Wrapf(err, "cannot stat OCI runtime %s path", name) + return nil, fmt.Errorf("cannot stat OCI runtime %s path: %w", name, err) } if !stat.Mode().IsRegular() { continue @@ -146,7 +148,7 @@ func newConmonOCIRuntime(name string, paths []string, conmonPath string, runtime } if !foundPath { - return nil, errors.Wrapf(define.ErrInvalidArg, "no valid executable found for OCI runtime %s", name) + return nil, fmt.Errorf("no valid executable found for OCI runtime %s: %w", name, define.ErrInvalidArg) } runtime.exitsDir = filepath.Join(runtime.tmpDir, "exits") @@ -155,7 +157,7 @@ func newConmonOCIRuntime(name string, paths []string, conmonPath string, runtime if err := os.MkdirAll(runtime.exitsDir, 0750); err != nil { // The directory is allowed to exist if !os.IsExist(err) { - return nil, errors.Wrapf(err, "error creating OCI runtime exit files directory") + return nil, fmt.Errorf("error creating OCI runtime exit files directory: %w", err) } } return runtime, nil @@ -231,7 +233,7 @@ func (r *ConmonOCIRuntime) CreateContainer(ctr *Container, restoreOptions *Conta // changes are propagated to the host. err = unix.Mount("/sys", "/sys", "none", unix.MS_REC|unix.MS_SLAVE, "") if err != nil { - return 0, errors.Wrapf(err, "cannot make /sys slave") + return 0, fmt.Errorf("cannot make /sys slave: %w", err) } mounts, err := pmount.GetMounts() @@ -244,7 +246,7 @@ func (r *ConmonOCIRuntime) CreateContainer(ctr *Container, restoreOptions *Conta } err = unix.Unmount(m.Mountpoint, 0) if err != nil && !os.IsNotExist(err) { - return 0, errors.Wrapf(err, "cannot unmount %s", m.Mountpoint) + return 0, fmt.Errorf("cannot unmount %s: %w", m.Mountpoint, err) } } return r.createOCIContainer(ctr, restoreOptions) @@ -282,17 +284,17 @@ func (r *ConmonOCIRuntime) UpdateContainerStatus(ctr *Container) error { outPipe, err := cmd.StdoutPipe() if err != nil { - return errors.Wrapf(err, "getting stdout pipe") + return fmt.Errorf("getting stdout pipe: %w", err) } errPipe, err := cmd.StderrPipe() if err != nil { - return errors.Wrapf(err, "getting stderr pipe") + return fmt.Errorf("getting stderr pipe: %w", err) } if err := cmd.Start(); err != nil { out, err2 := ioutil.ReadAll(errPipe) if err2 != nil { - return errors.Wrapf(err, "error getting container %s state", ctr.ID()) + return fmt.Errorf("error getting container %s state: %w", ctr.ID(), err) } if strings.Contains(string(out), "does not exist") || strings.Contains(string(out), "No such file") { if err := ctr.removeConmonFiles(); err != nil { @@ -303,7 +305,7 @@ func (r *ConmonOCIRuntime) UpdateContainerStatus(ctr *Container) error { ctr.state.State = define.ContainerStateExited return nil } - return errors.Wrapf(err, "error getting container %s state. stderr/out: %s", ctr.ID(), out) + return fmt.Errorf("error getting container %s state. stderr/out: %s: %w", ctr.ID(), out, err) } defer func() { _ = cmd.Wait() @@ -314,10 +316,10 @@ func (r *ConmonOCIRuntime) UpdateContainerStatus(ctr *Container) error { } out, err := ioutil.ReadAll(outPipe) if err != nil { - return errors.Wrapf(err, "error reading stdout: %s", ctr.ID()) + return fmt.Errorf("error reading stdout: %s: %w", ctr.ID(), err) } if err := json.NewDecoder(bytes.NewBuffer(out)).Decode(state); err != nil { - return errors.Wrapf(err, "error decoding container status for container %s", ctr.ID()) + return fmt.Errorf("error decoding container status for container %s: %w", ctr.ID(), err) } ctr.state.PID = state.Pid @@ -331,8 +333,8 @@ func (r *ConmonOCIRuntime) UpdateContainerStatus(ctr *Container) error { case "stopped": ctr.state.State = define.ContainerStateStopped default: - return errors.Wrapf(define.ErrInternal, "unrecognized status returned by runtime for container %s: %s", - ctr.ID(), state.Status) + return fmt.Errorf("unrecognized status returned by runtime for container %s: %s: %w", + ctr.ID(), state.Status, define.ErrInternal) } // Only grab exit status if we were not already stopped @@ -400,7 +402,7 @@ func (r *ConmonOCIRuntime) KillContainer(ctr *Container, signal uint, all bool) if ctr.ensureState(define.ContainerStateStopped, define.ContainerStateExited) { return define.ErrCtrStateInvalid } - return errors.Wrapf(err, "error sending signal to container %s", ctr.ID()) + return fmt.Errorf("error sending signal to container %s: %w", ctr.ID(), err) } return nil @@ -457,7 +459,7 @@ func (r *ConmonOCIRuntime) StopContainer(ctr *Container, timeout uint, all bool) return nil } - return errors.Wrapf(err, "error sending SIGKILL to container %s", ctr.ID()) + return fmt.Errorf("error sending SIGKILL to container %s: %w", ctr.ID(), err) } // Give runtime a few seconds to make it happen @@ -514,7 +516,7 @@ func (r *ConmonOCIRuntime) HTTPAttach(ctr *Container, req *http.Request, w http. if streams != nil { if !streams.Stdin && !streams.Stdout && !streams.Stderr { - return errors.Wrapf(define.ErrInvalidArg, "must specify at least one stream to attach to") + return fmt.Errorf("must specify at least one stream to attach to: %w", define.ErrInvalidArg) } } @@ -527,7 +529,7 @@ func (r *ConmonOCIRuntime) HTTPAttach(ctr *Container, req *http.Request, w http. if streamAttach { newConn, err := openUnixSocket(attachSock) if err != nil { - return errors.Wrapf(err, "failed to connect to container's attach socket: %v", attachSock) + return fmt.Errorf("failed to connect to container's attach socket: %v: %w", attachSock, err) } conn = newConn defer func() { @@ -562,12 +564,12 @@ func (r *ConmonOCIRuntime) HTTPAttach(ctr *Container, req *http.Request, w http. // Alright, let's hijack. hijacker, ok := w.(http.Hijacker) if !ok { - return errors.Errorf("unable to hijack connection") + return fmt.Errorf("unable to hijack connection") } httpCon, httpBuf, err := hijacker.Hijack() if err != nil { - return errors.Wrapf(err, "error hijacking connection") + return fmt.Errorf("error hijacking connection: %w", err) } hijackDone <- true @@ -576,7 +578,7 @@ func (r *ConmonOCIRuntime) HTTPAttach(ctr *Container, req *http.Request, w http. // Force a flush after the header is written. if err := httpBuf.Flush(); err != nil { - return errors.Wrapf(err, "error flushing HTTP hijack header") + return fmt.Errorf("error flushing HTTP hijack header: %w", err) } defer func() { @@ -691,7 +693,7 @@ func (r *ConmonOCIRuntime) HTTPAttach(ctr *Container, req *http.Request, w http. // Next, STDIN. Avoid entirely if attachStdin unset. if attachStdin { go func() { - _, err := utils.CopyDetachable(conn, httpBuf, detach) + _, err := cutil.CopyDetachable(conn, httpBuf, detach) logrus.Debugf("STDIN copy completed") stdinChan <- err }() @@ -722,7 +724,8 @@ func (r *ConmonOCIRuntime) HTTPAttach(ctr *Container, req *http.Request, w http. // isRetryable returns whether the error was caused by a blocked syscall or the // specified operation on a non blocking file descriptor wasn't ready for completion. func isRetryable(err error) bool { - if errno, isErrno := errors.Cause(err).(syscall.Errno); isErrno { + var errno syscall.Errno + if errors.As(err, &errno) { return errno == syscall.EINTR || errno == syscall.EAGAIN } return false @@ -737,15 +740,15 @@ func openControlFile(ctr *Container, parentDir string) (*os.File, error) { return controlFile, nil } if !isRetryable(err) { - return nil, errors.Wrapf(err, "could not open ctl file for terminal resize for container %s", ctr.ID()) + return nil, fmt.Errorf("could not open ctl file for terminal resize for container %s: %w", ctr.ID(), err) } time.Sleep(time.Second / 10) } - return nil, errors.Errorf("timeout waiting for %q", controlPath) + return nil, fmt.Errorf("timeout waiting for %q", controlPath) } // AttachResize resizes the terminal used by the given container. -func (r *ConmonOCIRuntime) AttachResize(ctr *Container, newSize define.TerminalSize) error { +func (r *ConmonOCIRuntime) AttachResize(ctr *Container, newSize resize.TerminalSize) error { controlFile, err := openControlFile(ctr, ctr.bundlePath()) if err != nil { return err @@ -754,7 +757,7 @@ func (r *ConmonOCIRuntime) AttachResize(ctr *Container, newSize define.TerminalS logrus.Debugf("Received a resize event for container %s: %+v", ctr.ID(), newSize) if _, err = fmt.Fprintf(controlFile, "%d %d %d\n", 1, newSize.Height, newSize.Width); err != nil { - return errors.Wrapf(err, "failed to write to ctl file to resize terminal") + return fmt.Errorf("failed to write to ctl file to resize terminal: %w", err) } return nil @@ -862,7 +865,7 @@ func (r *ConmonOCIRuntime) CheckConmonRunning(ctr *Container) (bool, error) { if err == unix.ESRCH { return false, nil } - return false, errors.Wrapf(err, "error pinging container %s conmon with signal 0", ctr.ID()) + return false, fmt.Errorf("error pinging container %s conmon with signal 0: %w", ctr.ID(), err) } return true, nil } @@ -894,7 +897,7 @@ func (r *ConmonOCIRuntime) SupportsKVM() bool { // AttachSocketPath is the path to a single container's attach socket. func (r *ConmonOCIRuntime) AttachSocketPath(ctr *Container) (string, error) { if ctr == nil { - return "", errors.Wrapf(define.ErrInvalidArg, "must provide a valid container to get attach socket path") + return "", fmt.Errorf("must provide a valid container to get attach socket path: %w", define.ErrInvalidArg) } return filepath.Join(ctr.bundlePath(), "attach"), nil @@ -903,7 +906,7 @@ func (r *ConmonOCIRuntime) AttachSocketPath(ctr *Container) (string, error) { // ExitFilePath is the path to a container's exit file. func (r *ConmonOCIRuntime) ExitFilePath(ctr *Container) (string, error) { if ctr == nil { - return "", errors.Wrapf(define.ErrInvalidArg, "must provide a valid container to get exit file path") + return "", fmt.Errorf("must provide a valid container to get exit file path: %w", define.ErrInvalidArg) } return filepath.Join(r.exitsDir, ctr.ID()), nil } @@ -914,11 +917,11 @@ func (r *ConmonOCIRuntime) RuntimeInfo() (*define.ConmonInfo, *define.OCIRuntime conmonPackage := packageVersion(r.conmonPath) runtimeVersion, err := r.getOCIRuntimeVersion() if err != nil { - return nil, nil, errors.Wrapf(err, "error getting version of OCI runtime %s", r.name) + return nil, nil, fmt.Errorf("error getting version of OCI runtime %s: %w", r.name, err) } conmonVersion, err := r.getConmonVersion() if err != nil { - return nil, nil, errors.Wrapf(err, "error getting conmon version") + return nil, nil, fmt.Errorf("error getting conmon version: %w", err) } conmon := define.ConmonInfo{ @@ -988,7 +991,7 @@ func waitPidStop(pid int, timeout time.Duration) error { return nil case <-time.After(timeout): close(chControl) - return errors.Errorf("given PIDs did not die within timeout") + return fmt.Errorf("given PIDs did not die within timeout") } } @@ -1004,7 +1007,7 @@ func (r *ConmonOCIRuntime) getLogTag(ctr *Container) (string, error) { } tmpl, err := template.New("container").Parse(logTag) if err != nil { - return "", errors.Wrapf(err, "template parsing error %s", logTag) + return "", fmt.Errorf("template parsing error %s: %w", logTag, err) } var b bytes.Buffer err = tmpl.Execute(&b, data) @@ -1025,13 +1028,13 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co parentSyncPipe, childSyncPipe, err := newPipe() if err != nil { - return 0, errors.Wrapf(err, "error creating socket pair") + return 0, fmt.Errorf("error creating socket pair: %w", err) } defer errorhandling.CloseQuiet(parentSyncPipe) childStartPipe, parentStartPipe, err := newPipe() if err != nil { - return 0, errors.Wrapf(err, "error creating socket pair for start pipe") + return 0, fmt.Errorf("error creating socket pair for start pipe: %w", err) } defer errorhandling.CloseQuiet(parentStartPipe) @@ -1202,12 +1205,12 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co if havePortMapping { ctr.rootlessPortSyncR, ctr.rootlessPortSyncW, err = os.Pipe() if err != nil { - return 0, errors.Wrapf(err, "failed to create rootless port sync pipe") + return 0, fmt.Errorf("failed to create rootless port sync pipe: %w", err) } } ctr.rootlessSlirpSyncR, ctr.rootlessSlirpSyncW, err = os.Pipe() if err != nil { - return 0, errors.Wrapf(err, "failed to create rootless network sync pipe") + return 0, fmt.Errorf("failed to create rootless network sync pipe: %w", err) } } else { if ctr.rootlessSlirpSyncR != nil { @@ -1544,7 +1547,7 @@ func readConmonPipeData(runtimeName string, pipe *os.File, ociLog string) (int, } } } - return -1, errors.Wrapf(ss.err, "container create failed (no logs from conmon)") + return -1, fmt.Errorf("container create failed (no logs from conmon): %w", ss.err) } logrus.Debugf("Received: %d", ss.si.Data) if ss.si.Data < 0 { @@ -1561,11 +1564,11 @@ func readConmonPipeData(runtimeName string, pipe *os.File, ociLog string) (int, if ss.si.Message != "" { return ss.si.Data, getOCIRuntimeError(runtimeName, ss.si.Message) } - return ss.si.Data, errors.Wrapf(define.ErrInternal, "container create failed") + return ss.si.Data, fmt.Errorf("container create failed: %w", define.ErrInternal) } data = ss.si.Data case <-time.After(define.ContainerCreateTimeout): - return -1, errors.Wrapf(define.ErrInternal, "container creation timeout") + return -1, fmt.Errorf("container creation timeout: %w", define.ErrInternal) } return data, nil } diff --git a/libpod/oci_missing.go b/libpod/oci_missing.go index fd8160830..2ab2b4577 100644 --- a/libpod/oci_missing.go +++ b/libpod/oci_missing.go @@ -6,8 +6,8 @@ import ( "path/filepath" "sync" + "github.com/containers/common/pkg/resize" "github.com/containers/podman/v4/libpod/define" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -119,18 +119,18 @@ func (r *MissingRuntime) HTTPAttach(ctr *Container, req *http.Request, w http.Re } // AttachResize is not available as the runtime is missing -func (r *MissingRuntime) AttachResize(ctr *Container, newSize define.TerminalSize) error { +func (r *MissingRuntime) AttachResize(ctr *Container, newSize resize.TerminalSize) error { return r.printError() } // ExecContainer is not available as the runtime is missing -func (r *MissingRuntime) ExecContainer(ctr *Container, sessionID string, options *ExecOptions, streams *define.AttachStreams, newSize *define.TerminalSize) (int, chan error, error) { +func (r *MissingRuntime) ExecContainer(ctr *Container, sessionID string, options *ExecOptions, streams *define.AttachStreams, newSize *resize.TerminalSize) (int, chan error, error) { return -1, nil, r.printError() } // ExecContainerHTTP is not available as the runtime is missing func (r *MissingRuntime) ExecContainerHTTP(ctr *Container, sessionID string, options *ExecOptions, req *http.Request, w http.ResponseWriter, - streams *HTTPAttachStreams, cancel <-chan bool, hijackDone chan<- bool, holdConnOpen <-chan bool, newSize *define.TerminalSize) (int, chan error, error) { + streams *HTTPAttachStreams, cancel <-chan bool, hijackDone chan<- bool, holdConnOpen <-chan bool, newSize *resize.TerminalSize) (int, chan error, error) { return -1, nil, r.printError() } @@ -140,7 +140,7 @@ func (r *MissingRuntime) ExecContainerDetached(ctr *Container, sessionID string, } // ExecAttachResize is not available as the runtime is missing. -func (r *MissingRuntime) ExecAttachResize(ctr *Container, sessionID string, newSize define.TerminalSize) error { +func (r *MissingRuntime) ExecAttachResize(ctr *Container, sessionID string, newSize resize.TerminalSize) error { return r.printError() } @@ -209,7 +209,7 @@ func (r *MissingRuntime) ExecAttachSocketPath(ctr *Container, sessionID string) // the container, but Conmon should still place an exit file for it. func (r *MissingRuntime) ExitFilePath(ctr *Container) (string, error) { if ctr == nil { - return "", errors.Wrapf(define.ErrInvalidArg, "must provide a valid container to get exit file path") + return "", fmt.Errorf("must provide a valid container to get exit file path: %w", define.ErrInvalidArg) } return filepath.Join(r.exitsDir, ctr.ID()), nil } @@ -227,5 +227,5 @@ func (r *MissingRuntime) RuntimeInfo() (*define.ConmonInfo, *define.OCIRuntimeIn // Return an error indicating the runtime is missing func (r *MissingRuntime) printError() error { - return errors.Wrapf(define.ErrOCIRuntimeNotFound, "runtime %s is missing", r.name) + return fmt.Errorf("runtime %s is missing: %w", r.name, define.ErrOCIRuntimeNotFound) } diff --git a/libpod/oci_util.go b/libpod/oci_util.go index 64edfdef2..e118348fa 100644 --- a/libpod/oci_util.go +++ b/libpod/oci_util.go @@ -10,7 +10,6 @@ import ( "github.com/containers/common/libnetwork/types" "github.com/containers/podman/v4/libpod/define" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -70,7 +69,7 @@ func bindPort(protocol, hostIP string, port uint16, isV6 bool, sctpWarning *bool addr, err = net.ResolveUDPAddr("udp4", fmt.Sprintf("%s:%d", hostIP, port)) } if err != nil { - return nil, errors.Wrapf(err, "cannot resolve the UDP address") + return nil, fmt.Errorf("cannot resolve the UDP address: %w", err) } proto := "udp4" @@ -79,11 +78,11 @@ func bindPort(protocol, hostIP string, port uint16, isV6 bool, sctpWarning *bool } server, err := net.ListenUDP(proto, addr) if err != nil { - return nil, errors.Wrapf(err, "cannot listen on the UDP port") + return nil, fmt.Errorf("cannot listen on the UDP port: %w", err) } file, err = server.File() if err != nil { - return nil, errors.Wrapf(err, "cannot get file for UDP socket") + return nil, fmt.Errorf("cannot get file for UDP socket: %w", err) } // close the listener // note that this does not affect the fd, see the godoc for server.File() @@ -103,7 +102,7 @@ func bindPort(protocol, hostIP string, port uint16, isV6 bool, sctpWarning *bool addr, err = net.ResolveTCPAddr("tcp4", fmt.Sprintf("%s:%d", hostIP, port)) } if err != nil { - return nil, errors.Wrapf(err, "cannot resolve the TCP address") + return nil, fmt.Errorf("cannot resolve the TCP address: %w", err) } proto := "tcp4" @@ -112,11 +111,11 @@ func bindPort(protocol, hostIP string, port uint16, isV6 bool, sctpWarning *bool } server, err := net.ListenTCP(proto, addr) if err != nil { - return nil, errors.Wrapf(err, "cannot listen on the TCP port") + return nil, fmt.Errorf("cannot listen on the TCP port: %w", err) } file, err = server.File() if err != nil { - return nil, errors.Wrapf(err, "cannot get file for TCP socket") + return nil, fmt.Errorf("cannot get file for TCP socket: %w", err) } // close the listener // note that this does not affect the fd, see the godoc for server.File() @@ -144,14 +143,14 @@ func getOCIRuntimeError(name, runtimeMsg string) error { if includeFullOutput { errStr = runtimeMsg } - return errors.Wrapf(define.ErrOCIRuntimePermissionDenied, "%s: %s", name, strings.Trim(errStr, "\n")) + 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 != "" { errStr := match if includeFullOutput { errStr = runtimeMsg } - return errors.Wrapf(define.ErrOCIRuntimeNotFound, "%s: %s", name, strings.Trim(errStr, "\n")) + return fmt.Errorf("%s: %s: %w", name, strings.Trim(errStr, "\n"), define.ErrOCIRuntimeNotFound) } if match := regexp.MustCompile("`/proc/[a-z0-9-].+/attr.*`").FindString(runtimeMsg); match != "" { errStr := match @@ -159,11 +158,11 @@ func getOCIRuntimeError(name, runtimeMsg string) error { errStr = runtimeMsg } if strings.HasSuffix(match, "/exec`") { - return errors.Wrapf(define.ErrSetSecurityAttribute, "%s: %s", name, strings.Trim(errStr, "\n")) + return fmt.Errorf("%s: %s: %w", name, strings.Trim(errStr, "\n"), define.ErrSetSecurityAttribute) } else if strings.HasSuffix(match, "/current`") { - return errors.Wrapf(define.ErrGetSecurityAttribute, "%s: %s", name, strings.Trim(errStr, "\n")) + return fmt.Errorf("%s: %s: %w", name, strings.Trim(errStr, "\n"), define.ErrGetSecurityAttribute) } - return errors.Wrapf(define.ErrSecurityAttribute, "%s: %s", name, strings.Trim(errStr, "\n")) + return fmt.Errorf("%s: %s: %w", name, strings.Trim(errStr, "\n"), define.ErrSecurityAttribute) } - return errors.Wrapf(define.ErrOCIRuntime, "%s: %s", name, strings.Trim(runtimeMsg, "\n")) + return fmt.Errorf("%s: %s: %w", name, strings.Trim(runtimeMsg, "\n"), define.ErrOCIRuntime) } diff --git a/libpod/options.go b/libpod/options.go index 3f9a0424a..f03980017 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -1,6 +1,7 @@ package libpod import ( + "errors" "fmt" "net" "os" @@ -25,7 +26,6 @@ import ( "github.com/containers/storage/pkg/idtools" "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-tools/generate" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -141,7 +141,7 @@ func WithOCIRuntime(runtime string) RuntimeOption { } if runtime == "" { - return errors.Wrapf(define.ErrInvalidArg, "must provide a valid path") + return fmt.Errorf("must provide a valid path: %w", define.ErrInvalidArg) } rt.config.Engine.OCIRuntime = runtime @@ -159,7 +159,7 @@ func WithConmonPath(path string) RuntimeOption { } if path == "" { - return errors.Wrapf(define.ErrInvalidArg, "must provide a valid path") + return fmt.Errorf("must provide a valid path: %w", define.ErrInvalidArg) } rt.config.Engine.ConmonPath = []string{path} @@ -219,8 +219,8 @@ func WithCgroupManager(manager string) RuntimeOption { } if manager != config.CgroupfsCgroupsManager && manager != config.SystemdCgroupsManager { - return errors.Wrapf(define.ErrInvalidArg, "Cgroup manager must be one of %s and %s", - config.CgroupfsCgroupsManager, config.SystemdCgroupsManager) + return fmt.Errorf("cgroup manager must be one of %s and %s: %w", + config.CgroupfsCgroupsManager, config.SystemdCgroupsManager, define.ErrInvalidArg) } rt.config.Engine.CgroupManager = manager @@ -250,7 +250,7 @@ func WithRegistriesConf(path string) RuntimeOption { logrus.Debugf("Setting custom registries.conf: %q", path) return func(rt *Runtime) error { if _, err := os.Stat(path); err != nil { - return errors.Wrap(err, "locating specified registries.conf") + return fmt.Errorf("locating specified registries.conf: %w", err) } if rt.imageContext == nil { rt.imageContext = &types.SystemContext{ @@ -272,7 +272,7 @@ func WithHooksDir(hooksDirs ...string) RuntimeOption { for _, hooksDir := range hooksDirs { if hooksDir == "" { - return errors.Wrap(define.ErrInvalidArg, "empty-string hook directories are not supported") + return fmt.Errorf("empty-string hook directories are not supported: %w", define.ErrInvalidArg) } } @@ -494,7 +494,7 @@ func WithMigrateRuntime(requestedRuntime string) RuntimeOption { } if requestedRuntime == "" { - return errors.Wrapf(define.ErrInvalidArg, "must provide a non-empty name for new runtime") + return fmt.Errorf("must provide a non-empty name for new runtime: %w", define.ErrInvalidArg) } rt.migrateRuntime = requestedRuntime @@ -513,7 +513,7 @@ func WithEventsLogger(logger string) RuntimeOption { } if !events.IsValidEventer(logger) { - return errors.Wrapf(define.ErrInvalidArg, "%q is not a valid events backend", logger) + return fmt.Errorf("%q is not a valid events backend: %w", logger, define.ErrInvalidArg) } rt.config.Engine.EventsLogger = logger @@ -622,7 +622,7 @@ func WithSdNotifyMode(mode string) CtrCreateOption { // verify values if len(mode) > 0 && !cutil.StringInSlice(strings.ToLower(mode), SdNotifyModeValues) { - return errors.Wrapf(define.ErrInvalidArg, "--sdnotify values must be one of %q", strings.Join(SdNotifyModeValues, ", ")) + return fmt.Errorf("--sdnotify values must be one of %q: %w", strings.Join(SdNotifyModeValues, ", "), define.ErrInvalidArg) } ctr.config.SdNotifyMode = mode @@ -770,9 +770,9 @@ func WithStopSignal(signal syscall.Signal) CtrCreateOption { } if signal == 0 { - return errors.Wrapf(define.ErrInvalidArg, "stop signal cannot be 0") + return fmt.Errorf("stop signal cannot be 0: %w", define.ErrInvalidArg) } else if signal > 64 { - return errors.Wrapf(define.ErrInvalidArg, "stop signal cannot be greater than 64 (SIGRTMAX)") + return fmt.Errorf("stop signal cannot be greater than 64 (SIGRTMAX): %w", define.ErrInvalidArg) } ctr.config.StopSignal = uint(signal) @@ -1080,11 +1080,11 @@ func WithLogDriver(driver string) CtrCreateOption { } switch driver { case "": - return errors.Wrapf(define.ErrInvalidArg, "log driver must be set") + return fmt.Errorf("log driver must be set: %w", define.ErrInvalidArg) case define.JournaldLogging, define.KubernetesLogging, define.JSONLogging, define.NoLogging, define.PassthroughLogging: break default: - return errors.Wrapf(define.ErrInvalidArg, "invalid log driver") + return fmt.Errorf("invalid log driver: %w", define.ErrInvalidArg) } ctr.config.LogDriver = driver @@ -1100,7 +1100,7 @@ func WithLogPath(path string) CtrCreateOption { return define.ErrCtrFinalized } if path == "" { - return errors.Wrapf(define.ErrInvalidArg, "log path must be set") + return fmt.Errorf("log path must be set: %w", define.ErrInvalidArg) } ctr.config.LogPath = path @@ -1116,7 +1116,7 @@ func WithLogTag(tag string) CtrCreateOption { return define.ErrCtrFinalized } if tag == "" { - return errors.Wrapf(define.ErrInvalidArg, "log tag must be set") + return fmt.Errorf("log tag must be set: %w", define.ErrInvalidArg) } ctr.config.LogTag = tag @@ -1139,7 +1139,7 @@ func WithCgroupsMode(mode string) CtrCreateOption { case "enabled", "no-conmon", cgroupSplit: ctr.config.CgroupsMode = mode default: - return errors.Wrapf(define.ErrInvalidArg, "Invalid cgroup mode %q", mode) + return fmt.Errorf("invalid cgroup mode %q: %w", mode, define.ErrInvalidArg) } return nil @@ -1154,7 +1154,7 @@ func WithCgroupParent(parent string) CtrCreateOption { } if parent == "" { - return errors.Wrapf(define.ErrInvalidArg, "cgroup parent cannot be empty") + return fmt.Errorf("cgroup parent cannot be empty: %w", define.ErrInvalidArg) } ctr.config.CgroupParent = parent @@ -1184,7 +1184,7 @@ func WithDNS(dnsServers []string) CtrCreateOption { for _, i := range dnsServers { result := net.ParseIP(i) if result == nil { - return errors.Wrapf(define.ErrInvalidArg, "invalid IP address %s", i) + return fmt.Errorf("invalid IP address %s: %w", i, define.ErrInvalidArg) } dns = append(dns, result) } @@ -1201,7 +1201,7 @@ func WithDNSOption(dnsOptions []string) CtrCreateOption { return define.ErrCtrFinalized } if ctr.config.UseImageResolvConf { - return errors.Wrapf(define.ErrInvalidArg, "cannot add DNS options if container will not create /etc/resolv.conf") + return fmt.Errorf("cannot add DNS options if container will not create /etc/resolv.conf: %w", define.ErrInvalidArg) } ctr.config.DNSOption = append(ctr.config.DNSOption, dnsOptions...) return nil @@ -1375,7 +1375,7 @@ func WithRestartPolicy(policy string) CtrCreateOption { case define.RestartPolicyNone, define.RestartPolicyNo, define.RestartPolicyOnFailure, define.RestartPolicyAlways, define.RestartPolicyUnlessStopped: ctr.config.RestartPolicy = policy default: - return errors.Wrapf(define.ErrInvalidArg, "%q is not a valid restart policy", policy) + return fmt.Errorf("%q is not a valid restart policy: %w", policy, define.ErrInvalidArg) } return nil @@ -1407,7 +1407,7 @@ func WithNamedVolumes(volumes []*ContainerNamedVolume) CtrCreateOption { for _, vol := range volumes { mountOpts, err := util.ProcessOptions(vol.Options, false, "") if err != nil { - return errors.Wrapf(err, "processing options for named volume %q mounted at %q", vol.Name, vol.Dest) + return fmt.Errorf("processing options for named volume %q mounted at %q: %w", vol.Name, vol.Dest, err) } ctr.config.NamedVolumes = append(ctr.config.NamedVolumes, &ContainerNamedVolume{ @@ -1720,7 +1720,7 @@ func WithTimezone(path string) CtrCreateOption { } // We don't want to mount a timezone directory if file.IsDir() { - return errors.New("Invalid timezone: is a directory") + return errors.New("invalid timezone: is a directory") } } @@ -1736,7 +1736,7 @@ func WithUmask(umask string) CtrCreateOption { return define.ErrCtrFinalized } if !define.UmaskRegex.MatchString(umask) { - return errors.Wrapf(define.ErrInvalidArg, "Invalid umask string %s", umask) + return fmt.Errorf("invalid umask string %s: %w", umask, define.ErrInvalidArg) } ctr.config.Umask = umask return nil @@ -1809,7 +1809,7 @@ func WithInitCtrType(containerType string) CtrCreateOption { ctr.config.InitContainerType = containerType return nil } - return errors.Errorf("%s is invalid init container type", containerType) + return fmt.Errorf("%s is invalid init container type", containerType) } } @@ -1843,12 +1843,12 @@ func WithInfraConfig(compatibleOptions InfraInherit) CtrCreateOption { } compatMarshal, err := json.Marshal(compatibleOptions) if err != nil { - return errors.New("Could not marshal compatible options") + return errors.New("could not marshal compatible options") } err = json.Unmarshal(compatMarshal, ctr.config) if err != nil { - return errors.New("Could not unmarshal compatible options into contrainer config") + return errors.New("could not unmarshal compatible options into contrainer config") } return nil } diff --git a/libpod/plugin/volume_api.go b/libpod/plugin/volume_api.go index 332ab912b..0a5eaae53 100644 --- a/libpod/plugin/volume_api.go +++ b/libpod/plugin/volume_api.go @@ -3,6 +3,7 @@ package plugin import ( "bytes" "context" + "fmt" "io/ioutil" "net" "net/http" @@ -12,11 +13,12 @@ import ( "sync" "time" + "errors" + "github.com/containers/podman/v4/libpod/define" "github.com/docker/go-plugins-helpers/sdk" "github.com/docker/go-plugins-helpers/volume" jsoniter "github.com/json-iterator/go" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -75,7 +77,7 @@ func validatePlugin(newPlugin *VolumePlugin) error { // Hit the Activate endpoint to find out if it is, and if so what kind req, err := http.NewRequest("POST", "http://plugin"+activatePath, nil) if err != nil { - return errors.Wrapf(err, "error making request to volume plugin %s activation endpoint", newPlugin.Name) + return fmt.Errorf("error making request to volume plugin %s activation endpoint: %w", newPlugin.Name, err) } req.Header.Set("Host", newPlugin.getURI()) @@ -83,25 +85,25 @@ func validatePlugin(newPlugin *VolumePlugin) error { resp, err := newPlugin.Client.Do(req) if err != nil { - return errors.Wrapf(err, "error sending request to plugin %s activation endpoint", newPlugin.Name) + return fmt.Errorf("error sending request to plugin %s activation endpoint: %w", newPlugin.Name, err) } defer resp.Body.Close() // Response code MUST be 200. Anything else, we have to assume it's not // a valid plugin. if resp.StatusCode != 200 { - return errors.Wrapf(ErrNotPlugin, "got status code %d from activation endpoint for plugin %s", resp.StatusCode, newPlugin.Name) + return fmt.Errorf("got status code %d from activation endpoint for plugin %s: %w", resp.StatusCode, newPlugin.Name, ErrNotPlugin) } // Read and decode the body so we can tell if this is a volume plugin. respBytes, err := ioutil.ReadAll(resp.Body) if err != nil { - return errors.Wrapf(err, "error reading activation response body from plugin %s", newPlugin.Name) + return fmt.Errorf("error reading activation response body from plugin %s: %w", newPlugin.Name, err) } respStruct := new(activateResponse) if err := json.Unmarshal(respBytes, respStruct); err != nil { - return errors.Wrapf(err, "error unmarshalling plugin %s activation response", newPlugin.Name) + return fmt.Errorf("error unmarshalling plugin %s activation response: %w", newPlugin.Name, err) } foundVolume := false @@ -113,7 +115,7 @@ func validatePlugin(newPlugin *VolumePlugin) error { } if !foundVolume { - return errors.Wrapf(ErrNotVolumePlugin, "plugin %s does not implement volume plugin, instead provides %s", newPlugin.Name, strings.Join(respStruct.Implements, ", ")) + return fmt.Errorf("plugin %s does not implement volume plugin, instead provides %s: %w", newPlugin.Name, strings.Join(respStruct.Implements, ", "), ErrNotVolumePlugin) } if plugins == nil { @@ -135,7 +137,7 @@ func GetVolumePlugin(name string, path string, timeout int) (*VolumePlugin, erro if exists { // This shouldn't be possible, but just in case... if plugin.SocketPath != filepath.Clean(path) { - return nil, errors.Wrapf(define.ErrInvalidArg, "requested path %q for volume plugin %s does not match pre-existing path for plugin, %q", path, name, plugin.SocketPath) + return nil, fmt.Errorf("requested path %q for volume plugin %s does not match pre-existing path for plugin, %q: %w", path, name, plugin.SocketPath, define.ErrInvalidArg) } return plugin, nil @@ -169,10 +171,10 @@ func GetVolumePlugin(name string, path string, timeout int) (*VolumePlugin, erro stat, err := os.Stat(newPlugin.SocketPath) if err != nil { - return nil, errors.Wrapf(err, "cannot access plugin %s socket %q", name, newPlugin.SocketPath) + return nil, fmt.Errorf("cannot access plugin %s socket %q: %w", name, newPlugin.SocketPath, err) } if stat.Mode()&os.ModeSocket == 0 { - return nil, errors.Wrapf(ErrNotPlugin, "volume %s path %q is not a unix socket", name, newPlugin.SocketPath) + return nil, fmt.Errorf("volume %s path %q is not a unix socket: %w", name, newPlugin.SocketPath, ErrNotPlugin) } if err := validatePlugin(newPlugin); err != nil { @@ -194,10 +196,10 @@ func (p *VolumePlugin) verifyReachable() error { pluginsLock.Lock() defer pluginsLock.Unlock() delete(plugins, p.Name) - return errors.Wrapf(ErrPluginRemoved, p.Name) + return fmt.Errorf("%s: %w", p.Name, ErrPluginRemoved) } - return errors.Wrapf(err, "error accessing plugin %s", p.Name) + return fmt.Errorf("error accessing plugin %s: %w", p.Name, err) } return nil } @@ -213,13 +215,13 @@ func (p *VolumePlugin) sendRequest(toJSON interface{}, endpoint string) (*http.R if toJSON != nil { reqJSON, err = json.Marshal(toJSON) if err != nil { - return nil, errors.Wrapf(err, "error marshalling request JSON for volume plugin %s endpoint %s", p.Name, endpoint) + return nil, fmt.Errorf("error marshalling request JSON for volume plugin %s endpoint %s: %w", p.Name, endpoint, err) } } req, err := http.NewRequest("POST", "http://plugin"+endpoint, bytes.NewReader(reqJSON)) if err != nil { - return nil, errors.Wrapf(err, "error making request to volume plugin %s endpoint %s", p.Name, endpoint) + return nil, fmt.Errorf("error making request to volume plugin %s endpoint %s: %w", p.Name, endpoint, err) } req.Header.Set("Host", p.getURI()) @@ -227,7 +229,7 @@ func (p *VolumePlugin) sendRequest(toJSON interface{}, endpoint string) (*http.R resp, err := p.Client.Do(req) if err != nil { - return nil, errors.Wrapf(err, "error sending request to volume plugin %s endpoint %s", p.Name, endpoint) + return nil, fmt.Errorf("error sending request to volume plugin %s endpoint %s: %w", p.Name, endpoint, err) } // We are *deliberately not closing* response here. It is the // responsibility of the caller to do so after reading the response. @@ -241,9 +243,9 @@ func (p *VolumePlugin) makeErrorResponse(err, endpoint, volName string) error { err = "empty error from plugin" } if volName != "" { - return errors.Wrapf(errors.New(err), "error on %s on volume %s in volume plugin %s", endpoint, volName, p.Name) + return fmt.Errorf("error on %s on volume %s in volume plugin %s: %w", endpoint, volName, p.Name, errors.New(err)) } - return errors.Wrapf(errors.New(err), "error on %s in volume plugin %s", endpoint, p.Name) + return fmt.Errorf("error on %s in volume plugin %s: %w", endpoint, p.Name, errors.New(err)) } // Handle error responses from plugin @@ -255,12 +257,12 @@ func (p *VolumePlugin) handleErrorResponse(resp *http.Response, endpoint, volNam if resp.StatusCode != 200 { errResp, err := ioutil.ReadAll(resp.Body) if err != nil { - return errors.Wrapf(err, "error reading response body from volume plugin %s", p.Name) + return fmt.Errorf("error reading response body from volume plugin %s: %w", p.Name, err) } errStruct := new(volume.ErrorResponse) if err := json.Unmarshal(errResp, errStruct); err != nil { - return errors.Wrapf(err, "error unmarshalling JSON response from volume plugin %s", p.Name) + return fmt.Errorf("error unmarshalling JSON response from volume plugin %s: %w", p.Name, err) } return p.makeErrorResponse(errStruct.Err, endpoint, volName) @@ -272,7 +274,7 @@ func (p *VolumePlugin) handleErrorResponse(resp *http.Response, endpoint, volNam // CreateVolume creates a volume in the plugin. func (p *VolumePlugin) CreateVolume(req *volume.CreateRequest) error { if req == nil { - return errors.Wrapf(define.ErrInvalidArg, "must provide non-nil request to CreateVolume") + return fmt.Errorf("must provide non-nil request to CreateVolume: %w", define.ErrInvalidArg) } if err := p.verifyReachable(); err != nil { @@ -310,12 +312,12 @@ func (p *VolumePlugin) ListVolumes() ([]*volume.Volume, error) { volumeRespBytes, err := ioutil.ReadAll(resp.Body) if err != nil { - return nil, errors.Wrapf(err, "error reading response body from volume plugin %s", p.Name) + return nil, fmt.Errorf("error reading response body from volume plugin %s: %w", p.Name, err) } volumeResp := new(volume.ListResponse) if err := json.Unmarshal(volumeRespBytes, volumeResp); err != nil { - return nil, errors.Wrapf(err, "error unmarshalling volume plugin %s list response", p.Name) + return nil, fmt.Errorf("error unmarshalling volume plugin %s list response: %w", p.Name, err) } return volumeResp.Volumes, nil @@ -324,7 +326,7 @@ func (p *VolumePlugin) ListVolumes() ([]*volume.Volume, error) { // GetVolume gets a single volume from the plugin. func (p *VolumePlugin) GetVolume(req *volume.GetRequest) (*volume.Volume, error) { if req == nil { - return nil, errors.Wrapf(define.ErrInvalidArg, "must provide non-nil request to GetVolume") + return nil, fmt.Errorf("must provide non-nil request to GetVolume: %w", define.ErrInvalidArg) } if err := p.verifyReachable(); err != nil { @@ -345,12 +347,12 @@ func (p *VolumePlugin) GetVolume(req *volume.GetRequest) (*volume.Volume, error) getRespBytes, err := ioutil.ReadAll(resp.Body) if err != nil { - return nil, errors.Wrapf(err, "error reading response body from volume plugin %s", p.Name) + return nil, fmt.Errorf("error reading response body from volume plugin %s: %w", p.Name, err) } getResp := new(volume.GetResponse) if err := json.Unmarshal(getRespBytes, getResp); err != nil { - return nil, errors.Wrapf(err, "error unmarshalling volume plugin %s get response", p.Name) + return nil, fmt.Errorf("error unmarshalling volume plugin %s get response: %w", p.Name, err) } return getResp.Volume, nil @@ -359,7 +361,7 @@ func (p *VolumePlugin) GetVolume(req *volume.GetRequest) (*volume.Volume, error) // RemoveVolume removes a single volume from the plugin. func (p *VolumePlugin) RemoveVolume(req *volume.RemoveRequest) error { if req == nil { - return errors.Wrapf(define.ErrInvalidArg, "must provide non-nil request to RemoveVolume") + return fmt.Errorf("must provide non-nil request to RemoveVolume: %w", define.ErrInvalidArg) } if err := p.verifyReachable(); err != nil { @@ -380,7 +382,7 @@ func (p *VolumePlugin) RemoveVolume(req *volume.RemoveRequest) error { // GetVolumePath gets the path the given volume is mounted at. func (p *VolumePlugin) GetVolumePath(req *volume.PathRequest) (string, error) { if req == nil { - return "", errors.Wrapf(define.ErrInvalidArg, "must provide non-nil request to GetVolumePath") + return "", fmt.Errorf("must provide non-nil request to GetVolumePath: %w", define.ErrInvalidArg) } if err := p.verifyReachable(); err != nil { @@ -401,12 +403,12 @@ func (p *VolumePlugin) GetVolumePath(req *volume.PathRequest) (string, error) { pathRespBytes, err := ioutil.ReadAll(resp.Body) if err != nil { - return "", errors.Wrapf(err, "error reading response body from volume plugin %s", p.Name) + return "", fmt.Errorf("error reading response body from volume plugin %s: %w", p.Name, err) } pathResp := new(volume.PathResponse) if err := json.Unmarshal(pathRespBytes, pathResp); err != nil { - return "", errors.Wrapf(err, "error unmarshalling volume plugin %s path response", p.Name) + return "", fmt.Errorf("error unmarshalling volume plugin %s path response: %w", p.Name, err) } return pathResp.Mountpoint, nil @@ -417,7 +419,7 @@ func (p *VolumePlugin) GetVolumePath(req *volume.PathRequest) (string, error) { // the path the volume has been mounted at. func (p *VolumePlugin) MountVolume(req *volume.MountRequest) (string, error) { if req == nil { - return "", errors.Wrapf(define.ErrInvalidArg, "must provide non-nil request to MountVolume") + return "", fmt.Errorf("must provide non-nil request to MountVolume: %w", define.ErrInvalidArg) } if err := p.verifyReachable(); err != nil { @@ -438,12 +440,12 @@ func (p *VolumePlugin) MountVolume(req *volume.MountRequest) (string, error) { mountRespBytes, err := ioutil.ReadAll(resp.Body) if err != nil { - return "", errors.Wrapf(err, "error reading response body from volume plugin %s", p.Name) + return "", fmt.Errorf("error reading response body from volume plugin %s: %w", p.Name, err) } mountResp := new(volume.MountResponse) if err := json.Unmarshal(mountRespBytes, mountResp); err != nil { - return "", errors.Wrapf(err, "error unmarshalling volume plugin %s path response", p.Name) + return "", fmt.Errorf("error unmarshalling volume plugin %s path response: %w", p.Name, err) } return mountResp.Mountpoint, nil @@ -453,7 +455,7 @@ func (p *VolumePlugin) MountVolume(req *volume.MountRequest) (string, error) { // container that is unmounting, used for internal record-keeping by the plugin. func (p *VolumePlugin) UnmountVolume(req *volume.UnmountRequest) error { if req == nil { - return errors.Wrapf(define.ErrInvalidArg, "must provide non-nil request to UnmountVolume") + return fmt.Errorf("must provide non-nil request to UnmountVolume: %w", define.ErrInvalidArg) } if err := p.verifyReachable(); err != nil { diff --git a/libpod/pod.go b/libpod/pod.go index 2502c41a9..e059c9416 100644 --- a/libpod/pod.go +++ b/libpod/pod.go @@ -1,6 +1,7 @@ package libpod import ( + "errors" "fmt" "sort" "strings" @@ -10,7 +11,6 @@ import ( "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/libpod/lock" "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" ) // Pod represents a group of containers that are managed together. @@ -169,6 +169,23 @@ func (p *Pod) CPUQuota() int64 { return 0 } +// MemoryLimit returns the pod Memory Limit +func (p *Pod) MemoryLimit() uint64 { + if p.state.InfraContainerID == "" { + return 0 + } + infra, err := p.runtime.GetContainer(p.state.InfraContainerID) + if err != nil { + return 0 + } + conf := infra.config.Spec + if conf != nil && conf.Linux != nil && conf.Linux.Resources != nil && conf.Linux.Resources.Memory != nil && conf.Linux.Resources.Memory.Limit != nil { + val := *conf.Linux.Resources.Memory.Limit + return uint64(val) + } + return 0 +} + // NetworkMode returns the Network mode given by the user ex: pod, private... func (p *Pod) NetworkMode() string { infra, err := p.runtime.GetContainer(p.state.InfraContainerID) @@ -295,7 +312,7 @@ func (p *Pod) CgroupPath() (string, error) { return "", err } if p.state.InfraContainerID == "" { - return "", errors.Wrap(define.ErrNoSuchCtr, "pod has no infra container") + return "", fmt.Errorf("pod has no infra container: %w", define.ErrNoSuchCtr) } return p.state.CgroupPath, nil } @@ -369,7 +386,7 @@ func (p *Pod) infraContainer() (*Container, error) { return nil, err } if id == "" { - return nil, errors.Wrap(define.ErrNoSuchCtr, "pod has no infra container") + return nil, fmt.Errorf("pod has no infra container: %w", define.ErrNoSuchCtr) } return p.runtime.state.Container(id) @@ -409,7 +426,7 @@ func (p *Pod) GetPodStats(previousContainerStats map[string]*define.ContainerSta newStats, err := c.GetContainerStats(previousContainerStats[c.ID()]) // If the container wasn't running, don't include it // but also suppress the error - if err != nil && errors.Cause(err) != define.ErrCtrStateInvalid { + if err != nil && !errors.Is(err, define.ErrCtrStateInvalid) { return nil, err } if err == nil { diff --git a/libpod/pod_api.go b/libpod/pod_api.go index fefe0e329..c1d54d55e 100644 --- a/libpod/pod_api.go +++ b/libpod/pod_api.go @@ -2,6 +2,7 @@ package libpod import ( "context" + "errors" "fmt" "github.com/containers/common/pkg/cgroups" @@ -10,7 +11,6 @@ import ( "github.com/containers/podman/v4/pkg/parallel" "github.com/containers/podman/v4/pkg/rootless" "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -32,7 +32,7 @@ func (p *Pod) startInitContainers(ctx context.Context) error { return err } if rc != 0 { - return errors.Errorf("init container %s exited with code %d", initCon.ID(), rc) + return fmt.Errorf("init container %s exited with code %d", initCon.ID(), rc) } // If the container is a once init container, we need to remove it // after it runs @@ -42,7 +42,7 @@ func (p *Pod) startInitContainers(ctx context.Context) error { var time *uint if err := p.runtime.removeContainer(ctx, initCon, false, false, true, time); err != nil { icLock.Unlock() - return errors.Wrapf(err, "failed to remove once init container %s", initCon.ID()) + return fmt.Errorf("failed to remove once init container %s: %w", initCon.ID(), err) } // Removing a container this way requires an explicit call to clean up the db if err := p.runtime.state.RemoveContainerFromPod(p, initCon); err != nil { @@ -92,12 +92,12 @@ func (p *Pod) Start(ctx context.Context) (map[string]error, error) { // Build a dependency graph of containers in the pod graph, err := BuildContainerGraph(allCtrs) if err != nil { - return nil, errors.Wrapf(err, "error generating dependency graph for pod %s", p.ID()) + return nil, fmt.Errorf("error generating dependency graph for pod %s: %w", p.ID(), err) } // If there are no containers without dependencies, we can't start // Error out if len(graph.noDepNodes) == 0 { - return nil, errors.Wrapf(define.ErrNoSuchCtr, "no containers in pod %s have no dependencies, cannot start pod", p.ID()) + return nil, fmt.Errorf("no containers in pod %s have no dependencies, cannot start pod: %w", p.ID(), define.ErrNoSuchCtr) } ctrErrors := make(map[string]error) @@ -109,7 +109,7 @@ func (p *Pod) Start(ctx context.Context) (map[string]error, error) { } if len(ctrErrors) > 0 { - return ctrErrors, errors.Wrapf(define.ErrPodPartialFail, "error starting some containers") + return ctrErrors, fmt.Errorf("error starting some containers: %w", define.ErrPodPartialFail) } defer p.newPodEvent(events.Start) return nil, nil @@ -193,7 +193,7 @@ func (p *Pod) stopWithTimeout(ctx context.Context, cleanup bool, timeout int) (m // Get returned error for every container we worked on for id, channel := range ctrErrChan { if err := <-channel; err != nil { - if errors.Cause(err) == define.ErrCtrStateInvalid || errors.Cause(err) == define.ErrCtrStopped { + if errors.Is(err, define.ErrCtrStateInvalid) || errors.Is(err, define.ErrCtrStopped) { continue } ctrErrors[id] = err @@ -201,7 +201,7 @@ func (p *Pod) stopWithTimeout(ctx context.Context, cleanup bool, timeout int) (m } if len(ctrErrors) > 0 { - return ctrErrors, errors.Wrapf(define.ErrPodPartialFail, "error stopping some containers") + return ctrErrors, fmt.Errorf("error stopping some containers: %w", define.ErrPodPartialFail) } if err := p.maybeStopServiceContainer(); err != nil { @@ -297,7 +297,7 @@ func (p *Pod) Cleanup(ctx context.Context) (map[string]error, error) { // Get returned error for every container we worked on for id, channel := range ctrErrChan { if err := <-channel; err != nil { - if errors.Cause(err) == define.ErrCtrStateInvalid || errors.Cause(err) == define.ErrCtrStopped { + if errors.Is(err, define.ErrCtrStateInvalid) || errors.Is(err, define.ErrCtrStopped) { continue } ctrErrors[id] = err @@ -305,7 +305,7 @@ func (p *Pod) Cleanup(ctx context.Context) (map[string]error, error) { } if len(ctrErrors) > 0 { - return ctrErrors, errors.Wrapf(define.ErrPodPartialFail, "error cleaning up some containers") + return ctrErrors, fmt.Errorf("error cleaning up some containers: %w", define.ErrPodPartialFail) } if err := p.maybeStopServiceContainer(); err != nil { @@ -338,10 +338,10 @@ func (p *Pod) Pause(ctx context.Context) (map[string]error, error) { if rootless.IsRootless() { cgroupv2, err := cgroups.IsCgroup2UnifiedMode() if err != nil { - return nil, errors.Wrap(err, "failed to determine cgroupversion") + return nil, fmt.Errorf("failed to determine cgroupversion: %w", err) } if !cgroupv2 { - return nil, errors.Wrap(define.ErrNoCgroups, "can not pause pods containing rootless containers with cgroup V1") + return nil, fmt.Errorf("can not pause pods containing rootless containers with cgroup V1: %w", define.ErrNoCgroups) } } @@ -368,7 +368,7 @@ func (p *Pod) Pause(ctx context.Context) (map[string]error, error) { // Get returned error for every container we worked on for id, channel := range ctrErrChan { if err := <-channel; err != nil { - if errors.Cause(err) == define.ErrCtrStateInvalid || errors.Cause(err) == define.ErrCtrStopped { + if errors.Is(err, define.ErrCtrStateInvalid) || errors.Is(err, define.ErrCtrStopped) { continue } ctrErrors[id] = err @@ -376,7 +376,7 @@ func (p *Pod) Pause(ctx context.Context) (map[string]error, error) { } if len(ctrErrors) > 0 { - return ctrErrors, errors.Wrapf(define.ErrPodPartialFail, "error pausing some containers") + return ctrErrors, fmt.Errorf("error pausing some containers: %w", define.ErrPodPartialFail) } return nil, nil } @@ -424,7 +424,7 @@ func (p *Pod) Unpause(ctx context.Context) (map[string]error, error) { // Get returned error for every container we worked on for id, channel := range ctrErrChan { if err := <-channel; err != nil { - if errors.Cause(err) == define.ErrCtrStateInvalid || errors.Cause(err) == define.ErrCtrStopped { + if errors.Is(err, define.ErrCtrStateInvalid) || errors.Is(err, define.ErrCtrStopped) { continue } ctrErrors[id] = err @@ -432,7 +432,7 @@ func (p *Pod) Unpause(ctx context.Context) (map[string]error, error) { } if len(ctrErrors) > 0 { - return ctrErrors, errors.Wrapf(define.ErrPodPartialFail, "error unpausing some containers") + return ctrErrors, fmt.Errorf("error unpausing some containers: %w", define.ErrPodPartialFail) } return nil, nil } @@ -470,7 +470,7 @@ func (p *Pod) Restart(ctx context.Context) (map[string]error, error) { // Build a dependency graph of containers in the pod graph, err := BuildContainerGraph(allCtrs) if err != nil { - return nil, errors.Wrapf(err, "error generating dependency graph for pod %s", p.ID()) + return nil, fmt.Errorf("error generating dependency graph for pod %s: %w", p.ID(), err) } ctrErrors := make(map[string]error) @@ -479,7 +479,7 @@ func (p *Pod) Restart(ctx context.Context) (map[string]error, error) { // If there are no containers without dependencies, we can't start // Error out if len(graph.noDepNodes) == 0 { - return nil, errors.Wrapf(define.ErrNoSuchCtr, "no containers in pod %s have no dependencies, cannot start pod", p.ID()) + return nil, fmt.Errorf("no containers in pod %s have no dependencies, cannot start pod: %w", p.ID(), define.ErrNoSuchCtr) } // Traverse the graph beginning at nodes with no dependencies @@ -488,7 +488,7 @@ func (p *Pod) Restart(ctx context.Context) (map[string]error, error) { } if len(ctrErrors) > 0 { - return ctrErrors, errors.Wrapf(define.ErrPodPartialFail, "error stopping some containers") + return ctrErrors, fmt.Errorf("error stopping some containers: %w", define.ErrPodPartialFail) } p.newPodEvent(events.Stop) p.newPodEvent(events.Start) @@ -539,7 +539,7 @@ func (p *Pod) Kill(ctx context.Context, signal uint) (map[string]error, error) { // Get returned error for every container we worked on for id, channel := range ctrErrChan { if err := <-channel; err != nil { - if errors.Cause(err) == define.ErrCtrStateInvalid || errors.Cause(err) == define.ErrCtrStopped { + if errors.Is(err, define.ErrCtrStateInvalid) || errors.Is(err, define.ErrCtrStopped) { continue } ctrErrors[id] = err @@ -547,7 +547,7 @@ func (p *Pod) Kill(ctx context.Context, signal uint) (map[string]error, error) { } if len(ctrErrors) > 0 { - return ctrErrors, errors.Wrapf(define.ErrPodPartialFail, "error killing some containers") + return ctrErrors, fmt.Errorf("error killing some containers: %w", define.ErrPodPartialFail) } if err := p.maybeStopServiceContainer(); err != nil { @@ -676,6 +676,7 @@ func (p *Pod) Inspect() (*define.InspectPodData, error) { infraConfig.CPUSetCPUs = p.ResourceLim().CPU.Cpus infraConfig.PidNS = p.NamespaceMode(specs.PIDNamespace) infraConfig.UserNS = p.NamespaceMode(specs.UserNamespace) + infraConfig.UtsNS = p.NamespaceMode(specs.UTSNamespace) namedVolumes, mounts := infra.SortUserVolumes(infra.config.Spec) inspectMounts, err = infra.GetMounts(namedVolumes, infra.config.ImageVolumes, mounts) infraSecurity = infra.GetSecurityOptions() @@ -751,6 +752,7 @@ func (p *Pod) Inspect() (*define.InspectPodData, error) { CPUSetCPUs: p.ResourceLim().CPU.Cpus, CPUPeriod: p.CPUPeriod(), CPUQuota: p.CPUQuota(), + MemoryLimit: p.MemoryLimit(), Mounts: inspectMounts, Devices: devices, BlkioDeviceReadBps: deviceLimits, diff --git a/libpod/pod_internal.go b/libpod/pod_internal.go index 1502bcb06..a86cd6d21 100644 --- a/libpod/pod_internal.go +++ b/libpod/pod_internal.go @@ -9,7 +9,6 @@ import ( "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/rootless" "github.com/containers/storage/pkg/stringid" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -39,7 +38,7 @@ func (p *Pod) updatePod() error { // Save pod state to database func (p *Pod) save() error { if err := p.runtime.state.SavePod(p); err != nil { - return errors.Wrapf(err, "error saving pod %s state", p.ID()) + return fmt.Errorf("error saving pod %s state: %w", p.ID(), err) } return nil @@ -61,7 +60,7 @@ func (p *Pod) refresh() error { // Retrieve the pod's lock lock, err := p.runtime.lockManager.AllocateAndRetrieveLock(p.config.LockID) if err != nil { - return errors.Wrapf(err, "error retrieving lock %d for pod %s", p.config.LockID, p.ID()) + return fmt.Errorf("error retrieving lock %d for pod %s: %w", p.config.LockID, p.ID(), err) } p.lock = lock @@ -81,7 +80,7 @@ func (p *Pod) refresh() error { logrus.Debugf("setting pod cgroup to %s", p.state.CgroupPath) } default: - return errors.Wrapf(define.ErrInvalidArg, "unknown cgroups manager %s specified", p.runtime.config.Engine.CgroupManager) + return fmt.Errorf("unknown cgroups manager %s specified: %w", p.runtime.config.Engine.CgroupManager, define.ErrInvalidArg) } } diff --git a/libpod/reset.go b/libpod/reset.go index 30eab50fb..b3ece03bf 100644 --- a/libpod/reset.go +++ b/libpod/reset.go @@ -2,6 +2,7 @@ package libpod import ( "context" + "errors" "fmt" "os" "path/filepath" @@ -13,7 +14,6 @@ import ( "github.com/containers/podman/v4/pkg/rootless" "github.com/containers/podman/v4/pkg/util" "github.com/containers/storage" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -49,7 +49,7 @@ func (r *Runtime) removeAllDirs() error { // Volume path if err := os.RemoveAll(r.config.Engine.VolumePath); err != nil { - lastErr = errors.Wrapf(err, "removing volume path") + lastErr = fmt.Errorf("removing volume path: %w", err) } // Tmpdir @@ -57,7 +57,7 @@ func (r *Runtime) removeAllDirs() error { if lastErr != nil { logrus.Errorf("Reset: %v", lastErr) } - lastErr = errors.Wrapf(err, "removing tmp dir") + lastErr = fmt.Errorf("removing tmp dir: %w", err) } // Runroot @@ -65,7 +65,7 @@ func (r *Runtime) removeAllDirs() error { if lastErr != nil { logrus.Errorf("Reset: %v", lastErr) } - lastErr = errors.Wrapf(err, "removing run root") + lastErr = fmt.Errorf("removing run root: %w", err) } // Static dir @@ -73,7 +73,7 @@ func (r *Runtime) removeAllDirs() error { if lastErr != nil { logrus.Errorf("Reset: %v", lastErr) } - lastErr = errors.Wrapf(err, "removing static dir") + lastErr = fmt.Errorf("removing static dir: %w", err) } // Graph root @@ -81,7 +81,7 @@ func (r *Runtime) removeAllDirs() error { if lastErr != nil { logrus.Errorf("Reset: %v", lastErr) } - lastErr = errors.Wrapf(err, "removing graph root") + lastErr = fmt.Errorf("removing graph root: %w", err) } return lastErr @@ -96,7 +96,7 @@ func (r *Runtime) reset(ctx context.Context) error { } for _, p := range pods { if err := r.RemovePod(ctx, p, true, true, timeout); err != nil { - if errors.Cause(err) == define.ErrNoSuchPod { + if errors.Is(err, define.ErrNoSuchPod) { continue } logrus.Errorf("Removing Pod %s: %v", p.ID(), err) @@ -111,7 +111,7 @@ func (r *Runtime) reset(ctx context.Context) error { for _, c := range ctrs { if err := r.RemoveContainer(ctx, c, true, true, timeout); err != nil { if err := r.RemoveStorageContainer(c.ID(), true); err != nil { - if errors.Cause(err) == define.ErrNoSuchCtr { + if errors.Is(err, define.ErrNoSuchCtr) { continue } logrus.Errorf("Removing container %s: %v", c.ID(), err) @@ -134,7 +134,7 @@ func (r *Runtime) reset(ctx context.Context) error { } for _, v := range volumes { if err := r.RemoveVolume(ctx, v, true, timeout); err != nil { - if errors.Cause(err) == define.ErrNoSuchVolume { + if errors.Is(err, define.ErrNoSuchVolume) { continue } logrus.Errorf("Removing volume %s: %v", v.config.Name, err) @@ -164,7 +164,7 @@ func (r *Runtime) reset(ctx context.Context) error { if prevError != nil { logrus.Error(prevError) } - prevError = errors.Errorf("failed to remove runtime graph root dir %s, since it is the same as XDG_RUNTIME_DIR", graphRoot) + prevError = fmt.Errorf("failed to remove runtime graph root dir %s, since it is the same as XDG_RUNTIME_DIR", graphRoot) } else { if err := os.RemoveAll(graphRoot); err != nil { if prevError != nil { @@ -178,7 +178,7 @@ func (r *Runtime) reset(ctx context.Context) error { if prevError != nil { logrus.Error(prevError) } - prevError = errors.Errorf("failed to remove runtime root dir %s, since it is the same as XDG_RUNTIME_DIR", runRoot) + prevError = fmt.Errorf("failed to remove runtime root dir %s, since it is the same as XDG_RUNTIME_DIR", runRoot) } else { if err := os.RemoveAll(runRoot); err != nil { if prevError != nil { @@ -199,7 +199,7 @@ func (r *Runtime) reset(ctx context.Context) error { if prevError != nil { logrus.Error(prevError) } - prevError = errors.Errorf("failed to remove runtime tmpdir %s, since it is the same as XDG_RUNTIME_DIR", tempDir) + prevError = fmt.Errorf("failed to remove runtime tmpdir %s, since it is the same as XDG_RUNTIME_DIR", tempDir) } else { if err := os.RemoveAll(tempDir); err != nil { if prevError != nil { diff --git a/libpod/runtime.go b/libpod/runtime.go index da57c20c7..ea4b34954 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -4,6 +4,7 @@ import ( "bufio" "bytes" "context" + "errors" "fmt" "os" "os/exec" @@ -40,7 +41,6 @@ import ( "github.com/containers/storage/pkg/unshare" "github.com/docker/docker/pkg/namesgenerator" spec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -146,7 +146,7 @@ func SetXdgDirs() error { } } if err := os.Setenv("XDG_RUNTIME_DIR", runtimeDir); err != nil { - return errors.Wrapf(err, "cannot set XDG_RUNTIME_DIR") + return fmt.Errorf("cannot set XDG_RUNTIME_DIR: %w", err) } if rootless.IsRootless() && os.Getenv("DBUS_SESSION_BUS_ADDRESS") == "" { @@ -163,7 +163,7 @@ func SetXdgDirs() error { return err } if err := os.Setenv("XDG_CONFIG_HOME", cfgHomeDir); err != nil { - return errors.Wrapf(err, "cannot set XDG_CONFIG_HOME") + return fmt.Errorf("cannot set XDG_CONFIG_HOME: %w", err) } } return nil @@ -214,7 +214,7 @@ func newRuntimeFromConfig(conf *config.Config, options ...RuntimeOption) (*Runti // Overwrite config with user-given configuration options for _, opt := range options { if err := opt(runtime); err != nil { - return nil, errors.Wrapf(err, "error configuring runtime") + return nil, fmt.Errorf("error configuring runtime: %w", err) } } @@ -225,12 +225,12 @@ func newRuntimeFromConfig(conf *config.Config, options ...RuntimeOption) (*Runti } os.Exit(1) return nil - }); err != nil && errors.Cause(err) != shutdown.ErrHandlerExists { + }); err != nil && !errors.Is(err, shutdown.ErrHandlerExists) { logrus.Errorf("Registering shutdown handler for libpod: %v", err) } if err := shutdown.Start(); err != nil { - return nil, errors.Wrapf(err, "error starting shutdown signal handler") + return nil, fmt.Errorf("error starting shutdown signal handler: %w", err) } if err := makeRuntime(runtime); err != nil { @@ -256,10 +256,10 @@ func getLockManager(runtime *Runtime) (lock.Manager, error) { lockPath := filepath.Join(runtime.config.Engine.TmpDir, "locks") manager, err = lock.OpenFileLockManager(lockPath) if err != nil { - if os.IsNotExist(errors.Cause(err)) { + if errors.Is(err, os.ErrNotExist) { manager, err = lock.NewFileLockManager(lockPath) if err != nil { - return nil, errors.Wrapf(err, "failed to get new file lock manager") + return nil, fmt.Errorf("failed to get new file lock manager: %w", err) } } else { return nil, err @@ -275,19 +275,19 @@ func getLockManager(runtime *Runtime) (lock.Manager, error) { manager, err = lock.OpenSHMLockManager(lockPath, runtime.config.Engine.NumLocks) if err != nil { switch { - case os.IsNotExist(errors.Cause(err)): + case errors.Is(err, os.ErrNotExist): manager, err = lock.NewSHMLockManager(lockPath, runtime.config.Engine.NumLocks) if err != nil { - return nil, errors.Wrapf(err, "failed to get new shm lock manager") + return nil, fmt.Errorf("failed to get new shm lock manager: %w", err) } - case errors.Cause(err) == syscall.ERANGE && runtime.doRenumber: + case errors.Is(err, syscall.ERANGE) && runtime.doRenumber: logrus.Debugf("Number of locks does not match - removing old locks") // ERANGE indicates a lock numbering mismatch. // Since we're renumbering, this is not fatal. // Remove the earlier set of locks and recreate. if err := os.Remove(filepath.Join("/dev/shm", lockPath)); err != nil { - return nil, errors.Wrapf(err, "error removing libpod locks file %s", lockPath) + return nil, fmt.Errorf("error removing libpod locks file %s: %w", lockPath, err) } manager, err = lock.NewSHMLockManager(lockPath, runtime.config.Engine.NumLocks) @@ -299,7 +299,7 @@ func getLockManager(runtime *Runtime) (lock.Manager, error) { } } default: - return nil, errors.Wrapf(define.ErrInvalidArg, "unknown lock type %s", runtime.config.Engine.LockType) + return nil, fmt.Errorf("unknown lock type %s: %w", runtime.config.Engine.LockType, define.ErrInvalidArg) } return manager, nil } @@ -315,17 +315,17 @@ func makeRuntime(runtime *Runtime) (retErr error) { runtime.conmonPath = cPath if runtime.noStore && runtime.doReset { - return errors.Wrapf(define.ErrInvalidArg, "cannot perform system reset if runtime is not creating a store") + return fmt.Errorf("cannot perform system reset if runtime is not creating a store: %w", define.ErrInvalidArg) } if runtime.doReset && runtime.doRenumber { - return errors.Wrapf(define.ErrInvalidArg, "cannot perform system reset while renumbering locks") + return fmt.Errorf("cannot perform system reset while renumbering locks: %w", define.ErrInvalidArg) } // Make the static files directory if it does not exist if err := os.MkdirAll(runtime.config.Engine.StaticDir, 0700); err != nil { // The directory is allowed to exist - if !os.IsExist(err) { - return errors.Wrap(err, "error creating runtime static files directory") + if !errors.Is(err, os.ErrExist) { + return fmt.Errorf("error creating runtime static files directory: %w", err) } } @@ -337,9 +337,9 @@ func makeRuntime(runtime *Runtime) (retErr error) { // package. switch runtime.config.Engine.StateType { case config.InMemoryStateStore: - return errors.Wrapf(define.ErrInvalidArg, "in-memory state is currently disabled") + return fmt.Errorf("in-memory state is currently disabled: %w", define.ErrInvalidArg) case config.SQLiteStateStore: - return errors.Wrapf(define.ErrInvalidArg, "SQLite state is currently disabled") + return fmt.Errorf("SQLite state is currently disabled: %w", define.ErrInvalidArg) case config.BoltDBStateStore: dbPath := filepath.Join(runtime.config.Engine.StaticDir, "bolt_state.db") @@ -349,7 +349,7 @@ func makeRuntime(runtime *Runtime) (retErr error) { } runtime.state = state default: - return errors.Wrapf(define.ErrInvalidArg, "unrecognized state type passed (%v)", runtime.config.Engine.StateType) + return fmt.Errorf("unrecognized state type passed (%v): %w", runtime.config.Engine.StateType, define.ErrInvalidArg) } // Grab config from the database so we can reset some defaults @@ -369,7 +369,7 @@ func makeRuntime(runtime *Runtime) (retErr error) { } } - return errors.Wrapf(err, "error retrieving runtime configuration from database") + return fmt.Errorf("error retrieving runtime configuration from database: %w", err) } runtime.mergeDBConfig(dbConfig) @@ -412,7 +412,7 @@ func makeRuntime(runtime *Runtime) (retErr error) { } if err := runtime.state.SetNamespace(runtime.config.Engine.Namespace); err != nil { - return errors.Wrapf(err, "error setting libpod namespace in state") + return fmt.Errorf("error setting libpod namespace in state: %w", err) } logrus.Debugf("Set libpod namespace to %q", runtime.config.Engine.Namespace) @@ -468,16 +468,16 @@ func makeRuntime(runtime *Runtime) (retErr error) { // Create the tmpDir if err := os.MkdirAll(runtime.config.Engine.TmpDir, 0751); err != nil { // The directory is allowed to exist - if !os.IsExist(err) { - return errors.Wrap(err, "error creating tmpdir") + if !errors.Is(err, os.ErrExist) { + return fmt.Errorf("error creating tmpdir: %w", err) } } // Create events log dir if err := os.MkdirAll(filepath.Dir(runtime.config.Engine.EventsLogFilePath), 0700); err != nil { // The directory is allowed to exist - if !os.IsExist(err) { - return errors.Wrap(err, "error creating events dirs") + if !errors.Is(err, os.ErrExist) { + return fmt.Errorf("error creating events dirs: %w", err) } } @@ -514,7 +514,7 @@ func makeRuntime(runtime *Runtime) (retErr error) { } else { ociRuntime, ok := runtime.ociRuntimes[runtime.config.Engine.OCIRuntime] if !ok { - return errors.Wrapf(define.ErrInvalidArg, "default OCI runtime %q not found", runtime.config.Engine.OCIRuntime) + return fmt.Errorf("default OCI runtime %q not found: %w", runtime.config.Engine.OCIRuntime, define.ErrInvalidArg) } runtime.defaultOCIRuntime = ociRuntime } @@ -523,19 +523,19 @@ func makeRuntime(runtime *Runtime) (retErr error) { // Do we have at least one valid OCI runtime? if len(runtime.ociRuntimes) == 0 { - return errors.Wrapf(define.ErrInvalidArg, "no OCI runtime has been configured") + return fmt.Errorf("no OCI runtime has been configured: %w", define.ErrInvalidArg) } // Do we have a default runtime? if runtime.defaultOCIRuntime == nil { - return errors.Wrapf(define.ErrInvalidArg, "no default OCI runtime was configured") + return fmt.Errorf("no default OCI runtime was configured: %w", define.ErrInvalidArg) } // Make the per-boot files directory if it does not exist if err := os.MkdirAll(runtime.config.Engine.TmpDir, 0755); err != nil { // The directory is allowed to exist - if !os.IsExist(err) { - return errors.Wrapf(err, "error creating runtime temporary files directory") + if !errors.Is(err, os.ErrExist) { + return fmt.Errorf("error creating runtime temporary files directory: %w", err) } } @@ -556,7 +556,7 @@ func makeRuntime(runtime *Runtime) (retErr error) { runtimeAliveFile := filepath.Join(runtime.config.Engine.TmpDir, "alive") aliveLock, err := storage.GetLockfile(runtimeAliveLock) if err != nil { - return errors.Wrapf(err, "error acquiring runtime init lock") + return fmt.Errorf("error acquiring runtime init lock: %w", err) } // Acquire the lock and hold it until we return // This ensures that no two processes will be in runtime.refresh at once @@ -586,7 +586,7 @@ func makeRuntime(runtime *Runtime) (retErr error) { aliveLock.Unlock() // Unlock to avoid deadlock as BecomeRootInUserNS will reexec. pausePid, err := util.GetRootlessPauseProcessPidPathGivenDir(runtime.config.Engine.TmpDir) if err != nil { - return errors.Wrapf(err, "could not get pause process pid file path") + return fmt.Errorf("could not get pause process pid file path: %w", err) } became, ret, err := rootless.BecomeRootInUserNS(pausePid) if err != nil { @@ -607,10 +607,10 @@ func makeRuntime(runtime *Runtime) (retErr error) { // This will trigger on first use as well, but refreshing an // empty state only creates a single file // As such, it's not really a performance concern - if os.IsNotExist(err) { + if errors.Is(err, os.ErrNotExist) { doRefresh = true } else { - return errors.Wrapf(err, "error reading runtime status file %s", runtimeAliveFile) + return fmt.Errorf("error reading runtime status file %s: %w", runtimeAliveFile, err) } } @@ -704,14 +704,14 @@ func findConmon(conmonPaths []string) (string, error) { } if foundOutdatedConmon { - return "", errors.Wrapf(define.ErrConmonOutdated, - "please update to v%d.%d.%d or later", - conmonMinMajorVersion, conmonMinMinorVersion, conmonMinPatchVersion) + return "", fmt.Errorf( + "please update to v%d.%d.%d or later: %w", + conmonMinMajorVersion, conmonMinMinorVersion, conmonMinPatchVersion, define.ErrConmonOutdated) } - return "", errors.Wrapf(define.ErrInvalidArg, - "could not find a working conmon binary (configured options: %v)", - conmonPaths) + return "", fmt.Errorf( + "could not find a working conmon binary (configured options: %v): %w", + conmonPaths, define.ErrInvalidArg) } // probeConmon calls conmon --version and verifies it is a new enough version for @@ -728,11 +728,11 @@ func probeConmon(conmonBinary string) error { matches := r.FindStringSubmatch(out.String()) if len(matches) != 4 { - return errors.Wrap(err, define.ErrConmonVersionFormat) + return fmt.Errorf("%v: %w", define.ErrConmonVersionFormat, err) } major, err := strconv.Atoi(matches[1]) if err != nil { - return errors.Wrap(err, define.ErrConmonVersionFormat) + return fmt.Errorf("%v: %w", define.ErrConmonVersionFormat, err) } if major < conmonMinMajorVersion { return define.ErrConmonOutdated @@ -743,7 +743,7 @@ func probeConmon(conmonBinary string) error { minor, err := strconv.Atoi(matches[2]) if err != nil { - return errors.Wrap(err, define.ErrConmonVersionFormat) + return fmt.Errorf("%v: %w", define.ErrConmonVersionFormat, err) } if minor < conmonMinMinorVersion { return define.ErrConmonOutdated @@ -754,7 +754,7 @@ func probeConmon(conmonBinary string) error { patch, err := strconv.Atoi(matches[3]) if err != nil { - return errors.Wrap(err, define.ErrConmonVersionFormat) + return fmt.Errorf("%v: %w", define.ErrConmonVersionFormat, err) } if patch < conmonMinPatchVersion { return define.ErrConmonOutdated @@ -798,7 +798,7 @@ func (r *Runtime) GetConfig() (*config.Config, error) { // Copy so the caller won't be able to modify the actual config if err := JSONDeepCopy(rtConfig, config); err != nil { - return nil, errors.Wrapf(err, "error copying config") + return nil, fmt.Errorf("error copying config: %w", err) } return config, nil @@ -909,7 +909,7 @@ func (r *Runtime) Shutdown(force bool) error { // Note that the libimage runtime shuts down the store. if err := r.libimageRuntime.Shutdown(force); err != nil { - lastError = errors.Wrapf(err, "error shutting down container storage") + lastError = fmt.Errorf("error shutting down container storage: %w", err) } } if err := r.state.Close(); err != nil { @@ -941,15 +941,15 @@ func (r *Runtime) refresh(alivePath string) error { // Containers, pods, and volumes must also reacquire their locks. ctrs, err := r.state.AllContainers() if err != nil { - return errors.Wrapf(err, "error retrieving all containers from state") + return fmt.Errorf("error retrieving all containers from state: %w", err) } pods, err := r.state.AllPods() if err != nil { - return errors.Wrapf(err, "error retrieving all pods from state") + return fmt.Errorf("error retrieving all pods from state: %w", err) } vols, err := r.state.AllVolumes() if err != nil { - return errors.Wrapf(err, "error retrieving all volumes from state") + return fmt.Errorf("error retrieving all volumes from state: %w", err) } // No locks are taken during pod, volume, and container refresh. // Furthermore, the pod/volume/container refresh() functions are not @@ -977,7 +977,7 @@ func (r *Runtime) refresh(alivePath string) error { // Create a file indicating the runtime is alive and ready file, err := os.OpenFile(alivePath, os.O_RDONLY|os.O_CREATE, 0644) if err != nil { - return errors.Wrap(err, "error creating runtime status file") + return fmt.Errorf("error creating runtime status file: %w", err) } defer file.Close() @@ -998,13 +998,13 @@ func (r *Runtime) generateName() (string, error) { // Make sure container with this name does not exist if _, err := r.state.LookupContainer(name); err == nil { continue - } else if errors.Cause(err) != define.ErrNoSuchCtr { + } else if !errors.Is(err, define.ErrNoSuchCtr) { return "", err } // Make sure pod with this name does not exist if _, err := r.state.LookupPod(name); err == nil { continue - } else if errors.Cause(err) != define.ErrNoSuchPod { + } else if !errors.Is(err, define.ErrNoSuchPod) { return "", err } return name, nil @@ -1205,7 +1205,7 @@ func (r *Runtime) getVolumePlugin(volConfig *VolumeConfig) (*plugin.VolumePlugin pluginPath, ok := r.config.Engine.VolumePlugins[name] if !ok { - return nil, errors.Wrapf(define.ErrMissingPlugin, "no volume plugin with name %s available", name) + return nil, fmt.Errorf("no volume plugin with name %s available: %w", name, define.ErrMissingPlugin) } return plugin.GetVolumePlugin(name, pluginPath, timeout) diff --git a/libpod/runtime_cstorage.go b/libpod/runtime_cstorage.go index 1c528e1b8..047375628 100644 --- a/libpod/runtime_cstorage.go +++ b/libpod/runtime_cstorage.go @@ -1,11 +1,12 @@ package libpod import ( + "errors" + "fmt" "time" "github.com/containers/podman/v4/libpod/define" "github.com/containers/storage" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -38,7 +39,7 @@ func (r *Runtime) ListStorageContainers() ([]*StorageContainer, error) { // Look up if container is in state hasCtr, err := r.state.HasContainer(ctr.ID) if err != nil { - return nil, errors.Wrapf(err, "error looking up container %s in state", ctr.ID) + return nil, fmt.Errorf("error looking up container %s in state: %w", ctr.ID, err) } storageCtr.PresentInLibpod = hasCtr @@ -60,20 +61,20 @@ func (r *Runtime) StorageContainer(idOrName string) (*storage.Container, error) func (r *Runtime) RemoveStorageContainer(idOrName string, force bool) error { targetID, err := r.store.Lookup(idOrName) if err != nil { - if errors.Cause(err) == storage.ErrLayerUnknown { - return errors.Wrapf(define.ErrNoSuchCtr, "no container with ID or name %q found", idOrName) + if errors.Is(err, storage.ErrLayerUnknown) { + return fmt.Errorf("no container with ID or name %q found: %w", idOrName, define.ErrNoSuchCtr) } - return errors.Wrapf(err, "error looking up container %q", idOrName) + return fmt.Errorf("error looking up container %q: %w", idOrName, err) } // Lookup returns an ID but it's not guaranteed to be a container ID. // So we can still error here. ctr, err := r.store.Container(targetID) if err != nil { - if errors.Cause(err) == storage.ErrContainerUnknown { - return errors.Wrapf(define.ErrNoSuchCtr, "%q does not refer to a container", idOrName) + if errors.Is(err, storage.ErrContainerUnknown) { + return fmt.Errorf("%q does not refer to a container: %w", idOrName, define.ErrNoSuchCtr) } - return errors.Wrapf(err, "error retrieving container %q", idOrName) + return fmt.Errorf("error retrieving container %q: %w", idOrName, err) } // Error out if the container exists in libpod @@ -82,13 +83,13 @@ func (r *Runtime) RemoveStorageContainer(idOrName string, force bool) error { return err } if exists { - return errors.Wrapf(define.ErrCtrExists, "refusing to remove %q as it exists in libpod as container %s", idOrName, ctr.ID) + return fmt.Errorf("refusing to remove %q as it exists in libpod as container %s: %w", idOrName, ctr.ID, define.ErrCtrExists) } if !force { timesMounted, err := r.store.Mounted(ctr.ID) if err != nil { - if errors.Cause(err) == storage.ErrContainerUnknown { + if errors.Is(err, storage.ErrContainerUnknown) { // Container was removed from under us. // It's gone, so don't bother erroring. logrus.Infof("Storage for container %s already removed", ctr.ID) @@ -97,7 +98,7 @@ func (r *Runtime) RemoveStorageContainer(idOrName string, force bool) error { logrus.Warnf("Checking if container %q is mounted, attempting to delete: %v", idOrName, err) } if timesMounted > 0 { - return errors.Wrapf(define.ErrCtrStateInvalid, "container %q is mounted and cannot be removed without using force", idOrName) + return fmt.Errorf("container %q is mounted and cannot be removed without using force: %w", idOrName, define.ErrCtrStateInvalid) } } else if _, err := r.store.Unmount(ctr.ID, true); err != nil { if errors.Is(err, storage.ErrContainerUnknown) { @@ -109,12 +110,12 @@ func (r *Runtime) RemoveStorageContainer(idOrName string, force bool) error { } if err := r.store.DeleteContainer(ctr.ID); err != nil { - if errors.Cause(err) == storage.ErrNotAContainer || errors.Cause(err) == storage.ErrContainerUnknown { + if errors.Is(err, storage.ErrNotAContainer) || errors.Is(err, storage.ErrContainerUnknown) { // Container again gone, no error logrus.Infof("Storage for container %s already removed", ctr.ID) return nil } - return errors.Wrapf(err, "error removing storage for container %q", idOrName) + return fmt.Errorf("error removing storage for container %q: %w", idOrName, err) } return nil diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go index 4d34c6a08..ce0fd869d 100644 --- a/libpod/runtime_ctr.go +++ b/libpod/runtime_ctr.go @@ -2,6 +2,7 @@ package libpod import ( "context" + "errors" "fmt" "os" "path" @@ -26,7 +27,6 @@ import ( "github.com/docker/go-units" spec "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-tools/generate" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -86,7 +86,7 @@ func (r *Runtime) RestoreContainer(ctx context.Context, rSpec *spec.Spec, config ctr, err := r.initContainerVariables(rSpec, config) if err != nil { - return nil, errors.Wrapf(err, "error initializing container variables") + return nil, fmt.Errorf("error initializing container variables: %w", err) } // For an imported checkpoint no one has ever set the StartedTime. Set it now. ctr.state.StartedTime = time.Now() @@ -126,7 +126,7 @@ func (r *Runtime) RenameContainer(ctx context.Context, ctr *Container, newName s // the config was re-written. newConf, err := r.state.GetContainerConfig(ctr.ID()) if err != nil { - return nil, errors.Wrapf(err, "error retrieving container %s configuration from DB to remove", ctr.ID()) + return nil, fmt.Errorf("error retrieving container %s configuration from DB to remove: %w", ctr.ID(), err) } ctr.config = newConf @@ -143,7 +143,7 @@ func (r *Runtime) RenameContainer(ctx context.Context, ctr *Container, newName s // Set config back to the old name so reflect what is actually // present in the DB. ctr.config.Name = oldName - return nil, errors.Wrapf(err, "error renaming container %s", ctr.ID()) + return nil, fmt.Errorf("error renaming container %s: %w", ctr.ID(), err) } // Step 3: rename the container in c/storage. @@ -162,7 +162,7 @@ func (r *Runtime) RenameContainer(ctx context.Context, ctr *Container, newName s func (r *Runtime) initContainerVariables(rSpec *spec.Spec, config *ContainerConfig) (*Container, error) { if rSpec == nil { - return nil, errors.Wrapf(define.ErrInvalidArg, "must provide a valid runtime spec to create container") + return nil, fmt.Errorf("must provide a valid runtime spec to create container: %w", define.ErrInvalidArg) } ctr := new(Container) ctr.config = new(ContainerConfig) @@ -172,7 +172,7 @@ func (r *Runtime) initContainerVariables(rSpec *spec.Spec, config *ContainerConf ctr.config.ID = stringid.GenerateNonCryptoID() size, err := units.FromHumanSize(r.config.Containers.ShmSize) if err != nil { - return nil, errors.Wrapf(err, "converting containers.conf ShmSize %s to an int", r.config.Containers.ShmSize) + return nil, fmt.Errorf("converting containers.conf ShmSize %s to an int: %w", r.config.Containers.ShmSize, err) } ctr.config.ShmSize = size ctr.config.NoShm = false @@ -184,7 +184,7 @@ func (r *Runtime) initContainerVariables(rSpec *spec.Spec, config *ContainerConf // This is a restore from an imported checkpoint ctr.restoreFromCheckpoint = true if err := JSONDeepCopy(config, ctr.config); err != nil { - return nil, errors.Wrapf(err, "error copying container config for restore") + return nil, fmt.Errorf("error copying container config for restore: %w", err) } // If the ID is empty a new name for the restored container was requested if ctr.config.ID == "" { @@ -224,12 +224,12 @@ func (r *Runtime) newContainer(ctx context.Context, rSpec *spec.Spec, options .. ctr, err = r.initContainerVariables(rSpec, nil) if err != nil { - return nil, errors.Wrapf(err, "error initializing container variables") + return nil, fmt.Errorf("error initializing container variables: %w", err) } for _, option := range options { if err := option(ctr); err != nil { - return nil, errors.Wrapf(err, "error running container create option") + return nil, fmt.Errorf("error running container create option: %w", err) } } @@ -248,7 +248,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai if opts.InterfaceName != "" { // check that no name is assigned to more than network if cutil.StringInSlice(opts.InterfaceName, usedIfNames) { - return nil, errors.Errorf("network interface name %q is already assigned to another network", opts.InterfaceName) + return nil, fmt.Errorf("network interface name %q is already assigned to another network", opts.InterfaceName) } usedIfNames = append(usedIfNames, opts.InterfaceName) } @@ -296,7 +296,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai // Allocate a lock for the container lock, err := r.lockManager.AllocateLock() if err != nil { - return nil, errors.Wrapf(err, "error allocating lock for new container") + return nil, fmt.Errorf("error allocating lock for new container: %w", err) } ctr.lock = lock ctr.config.LockID = ctr.lock.ID() @@ -319,7 +319,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai } else { ociRuntime, ok := r.ociRuntimes[ctr.config.OCIRuntime] if !ok { - return nil, errors.Wrapf(define.ErrInvalidArg, "requested OCI runtime %s is not available", ctr.config.OCIRuntime) + return nil, fmt.Errorf("requested OCI runtime %s is not available: %w", ctr.config.OCIRuntime, define.ErrInvalidArg) } ctr.ociRuntime = ociRuntime } @@ -327,7 +327,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai // Check NoCgroups support if ctr.config.NoCgroups { if !ctr.ociRuntime.SupportsNoCgroups() { - return nil, errors.Wrapf(define.ErrInvalidArg, "requested OCI runtime %s is not compatible with NoCgroups", ctr.ociRuntime.Name()) + return nil, fmt.Errorf("requested OCI runtime %s is not compatible with NoCgroups: %w", ctr.ociRuntime.Name(), define.ErrInvalidArg) } } @@ -336,7 +336,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai // Get the pod from state pod, err = r.state.Pod(ctr.config.Pod) if err != nil { - return nil, errors.Wrapf(err, "cannot add container %s to pod %s", ctr.ID(), ctr.config.Pod) + return nil, fmt.Errorf("cannot add container %s to pod %s: %w", ctr.ID(), ctr.config.Pod, err) } } @@ -350,14 +350,14 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai if pod != nil && pod.config.UsePodCgroup && !ctr.IsInfra() { podCgroup, err := pod.CgroupPath() if err != nil { - return nil, errors.Wrapf(err, "error retrieving pod %s cgroup", pod.ID()) + return nil, fmt.Errorf("error retrieving pod %s cgroup: %w", pod.ID(), err) } expectPodCgroup, err := ctr.expectPodCgroup() if err != nil { return nil, err } if expectPodCgroup && podCgroup == "" { - return nil, errors.Wrapf(define.ErrInternal, "pod %s cgroup is not set", pod.ID()) + return nil, fmt.Errorf("pod %s cgroup is not set: %w", pod.ID(), define.ErrInternal) } canUseCgroup := !rootless.IsRootless() || isRootlessCgroupSet(podCgroup) if canUseCgroup { @@ -367,7 +367,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai ctr.config.CgroupParent = CgroupfsDefaultCgroupParent } } else if strings.HasSuffix(path.Base(ctr.config.CgroupParent), ".slice") { - return nil, errors.Wrapf(define.ErrInvalidArg, "systemd slice received as cgroup parent when using cgroupfs") + return nil, fmt.Errorf("systemd slice received as cgroup parent when using cgroupfs: %w", define.ErrInvalidArg) } case config.SystemdCgroupsManager: if ctr.config.CgroupParent == "" { @@ -375,7 +375,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai case pod != nil && pod.config.UsePodCgroup && !ctr.IsInfra(): podCgroup, err := pod.CgroupPath() if err != nil { - return nil, errors.Wrapf(err, "error retrieving pod %s cgroup", pod.ID()) + return nil, fmt.Errorf("error retrieving pod %s cgroup: %w", pod.ID(), err) } ctr.config.CgroupParent = podCgroup case rootless.IsRootless() && ctr.config.CgroupsMode != cgroupSplit: @@ -384,10 +384,10 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai ctr.config.CgroupParent = SystemdDefaultCgroupParent } } else if len(ctr.config.CgroupParent) < 6 || !strings.HasSuffix(path.Base(ctr.config.CgroupParent), ".slice") { - return nil, errors.Wrapf(define.ErrInvalidArg, "did not receive systemd slice as cgroup parent when using systemd to manage cgroups") + return nil, fmt.Errorf("did not receive systemd slice as cgroup parent when using systemd to manage cgroups: %w", define.ErrInvalidArg) } default: - return nil, errors.Wrapf(define.ErrInvalidArg, "unsupported Cgroup manager: %s - cannot validate cgroup parent", r.config.Engine.CgroupManager) + return nil, fmt.Errorf("unsupported Cgroup manager: %s - cannot validate cgroup parent: %w", r.config.Engine.CgroupManager, define.ErrInvalidArg) } } @@ -470,8 +470,8 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai ctrNamedVolumes = append(ctrNamedVolumes, dbVol) // The volume exists, we're good continue - } else if errors.Cause(err) != define.ErrNoSuchVolume { - return nil, errors.Wrapf(err, "error retrieving named volume %s for new container", vol.Name) + } else if !errors.Is(err, define.ErrNoSuchVolume) { + return nil, fmt.Errorf("error retrieving named volume %s for new container: %w", vol.Name, err) } } @@ -504,7 +504,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai } newVol, err := r.newVolume(false, volOptions...) if err != nil { - return nil, errors.Wrapf(err, "error creating named volume %q", vol.Name) + return nil, fmt.Errorf("error creating named volume %q: %w", vol.Name, err) } ctrNamedVolumes = append(ctrNamedVolumes, newVol) @@ -527,7 +527,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai ctr.config.ShmDir = filepath.Join(ctr.bundlePath(), "shm") if err := os.MkdirAll(ctr.config.ShmDir, 0700); err != nil { if !os.IsExist(err) { - return nil, errors.Wrap(err, "unable to create shm dir") + return nil, fmt.Errorf("unable to create shm dir: %w", err) } } ctr.config.Mounts = append(ctr.config.Mounts, ctr.config.ShmDir) @@ -596,7 +596,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo // exist once we're done. newConf, err := r.state.GetContainerConfig(c.ID()) if err != nil { - return errors.Wrapf(err, "error retrieving container %s configuration from DB to remove", c.ID()) + return fmt.Errorf("error retrieving container %s configuration from DB to remove: %w", c.ID(), err) } c.config = newConf @@ -611,12 +611,12 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo if c.config.Pod != "" && !removePod { pod, err = r.state.Pod(c.config.Pod) if err != nil { - return errors.Wrapf(err, "container %s is in pod %s, but pod cannot be retrieved", c.ID(), pod.ID()) + return fmt.Errorf("container %s is in pod %s, but pod cannot be retrieved: %w", c.ID(), pod.ID(), err) } // Lock the pod while we're removing container if pod.config.LockID == c.config.LockID { - return errors.Wrapf(define.ErrWillDeadlock, "container %s and pod %s share lock ID %d", c.ID(), pod.ID(), c.config.LockID) + return fmt.Errorf("container %s and pod %s share lock ID %d: %w", c.ID(), pod.ID(), c.config.LockID, define.ErrWillDeadlock) } pod.lock.Lock() defer pod.lock.Unlock() @@ -626,7 +626,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo infraID := pod.state.InfraContainerID if c.ID() == infraID { - return errors.Errorf("container %s is the infra container of pod %s and cannot be removed without removing the pod", c.ID(), pod.ID()) + return fmt.Errorf("container %s is the infra container of pod %s and cannot be removed without removing the pod", c.ID(), pod.ID()) } } @@ -693,7 +693,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo } if len(deps) != 0 { depsStr := strings.Join(deps, ", ") - return errors.Wrapf(define.ErrCtrExists, "container %s has dependent containers which must be removed before it: %s", c.ID(), depsStr) + return fmt.Errorf("container %s has dependent containers which must be removed before it: %s: %w", c.ID(), depsStr, define.ErrCtrExists) } } @@ -705,8 +705,8 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo } // Ignore ErrConmonDead - we couldn't retrieve the container's // exit code properly, but it's still stopped. - if err := c.stop(time); err != nil && errors.Cause(err) != define.ErrConmonDead { - return errors.Wrapf(err, "cannot remove container %s as it could not be stopped", c.ID()) + if err := c.stop(time); err != nil && !errors.Is(err, define.ErrConmonDead) { + return fmt.Errorf("cannot remove container %s as it could not be stopped: %w", c.ID(), err) } // We unlocked as part of stop() above - there's a chance someone @@ -717,7 +717,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo if ok, _ := r.state.HasContainer(c.ID()); !ok { // When the container has already been removed, the OCI runtime directory remain. if err := c.cleanupRuntime(ctx); err != nil { - return errors.Wrapf(err, "error cleaning up container %s from OCI runtime", c.ID()) + return fmt.Errorf("error cleaning up container %s from OCI runtime: %w", c.ID(), err) } return nil } @@ -729,7 +729,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo // Do this before we set ContainerStateRemoving, to ensure that we can // actually remove from the OCI runtime. if err := c.cleanup(ctx); err != nil { - cleanupErr = errors.Wrapf(err, "error cleaning up container %s", c.ID()) + cleanupErr = fmt.Errorf("error cleaning up container %s: %w", c.ID(), err) } // Set ContainerStateRemoving @@ -739,7 +739,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo if cleanupErr != nil { logrus.Errorf(err.Error()) } - return errors.Wrapf(err, "unable to set container %s removing state in database", c.ID()) + return fmt.Errorf("unable to set container %s removing state in database: %w", c.ID(), err) } // Remove all active exec sessions @@ -789,7 +789,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo // Deallocate the container's lock if err := c.lock.Free(); err != nil { if cleanupErr == nil { - cleanupErr = errors.Wrapf(err, "error freeing lock for container %s", c.ID()) + cleanupErr = fmt.Errorf("error freeing lock for container %s: %w", c.ID(), err) } else { logrus.Errorf("Free container lock: %v", err) } @@ -809,8 +809,8 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo if !volume.Anonymous() { continue } - if err := runtime.removeVolume(ctx, volume, false, timeout, false); err != nil && errors.Cause(err) != define.ErrNoSuchVolume { - if errors.Cause(err) == define.ErrVolumeBeingUsed { + if err := runtime.removeVolume(ctx, volume, false, timeout, false); err != nil && !errors.Is(err, define.ErrNoSuchVolume) { + if errors.Is(err, define.ErrVolumeBeingUsed) { // Ignore error, since podman will report original error volumesFrom, _ := c.volumesFrom() if len(volumesFrom) > 0 { @@ -891,7 +891,7 @@ func (r *Runtime) evictContainer(ctx context.Context, idOrName string, removeVol c := new(Container) c.config, err = r.state.GetContainerConfig(id) if err != nil { - return id, errors.Wrapf(err, "failed to retrieve config for ctr ID %q", id) + return id, fmt.Errorf("failed to retrieve config for ctr ID %q: %w", id, err) } c.state = new(ContainerState) @@ -903,7 +903,7 @@ func (r *Runtime) evictContainer(ctx context.Context, idOrName string, removeVol if c.config.Pod != "" { pod, err = r.state.Pod(c.config.Pod) if err != nil { - return id, errors.Wrapf(err, "container %s is in pod %s, but pod cannot be retrieved", c.ID(), pod.ID()) + return id, fmt.Errorf("container %s is in pod %s, but pod cannot be retrieved: %w", c.ID(), pod.ID(), err) } // Lock the pod while we're removing container @@ -918,7 +918,7 @@ func (r *Runtime) evictContainer(ctx context.Context, idOrName string, removeVol return "", err } if c.ID() == infraID { - return id, errors.Errorf("container %s is the infra container of pod %s and cannot be removed without removing the pod", c.ID(), pod.ID()) + return id, fmt.Errorf("container %s is the infra container of pod %s and cannot be removed without removing the pod", c.ID(), pod.ID()) } } @@ -1115,7 +1115,7 @@ func (r *Runtime) GetContainersByList(containers []string) ([]*Container, error) for _, inputContainer := range containers { ctr, err := r.LookupContainer(inputContainer) if err != nil { - return ctrs, errors.Wrapf(err, "unable to look up container %s", inputContainer) + return ctrs, fmt.Errorf("unable to look up container %s: %w", inputContainer, err) } ctrs = append(ctrs, ctr) } @@ -1128,7 +1128,7 @@ func (r *Runtime) GetLatestContainer() (*Container, error) { var lastCreatedTime time.Time ctrs, err := r.GetAllContainers() if err != nil { - return nil, errors.Wrapf(err, "unable to find latest container") + return nil, fmt.Errorf("unable to find latest container: %w", err) } if len(ctrs) == 0 { return nil, define.ErrNoSuchCtr @@ -1209,7 +1209,7 @@ func (r *Runtime) PruneContainers(filterFuncs []ContainerFilter) ([]*reports.Pru // MountStorageContainer mounts the storage container's root filesystem func (r *Runtime) MountStorageContainer(id string) (string, error) { if _, err := r.GetContainer(id); err == nil { - return "", errors.Wrapf(define.ErrCtrExists, "ctr %s is a libpod container", id) + return "", fmt.Errorf("ctr %s is a libpod container: %w", id, define.ErrCtrExists) } container, err := r.store.Container(id) if err != nil { @@ -1217,7 +1217,7 @@ func (r *Runtime) MountStorageContainer(id string) (string, error) { } mountPoint, err := r.store.Mount(container.ID, "") if err != nil { - return "", errors.Wrapf(err, "error mounting storage for container %s", id) + return "", fmt.Errorf("error mounting storage for container %s: %w", id, err) } return mountPoint, nil } @@ -1225,7 +1225,7 @@ func (r *Runtime) MountStorageContainer(id string) (string, error) { // UnmountStorageContainer unmounts the storage container's root filesystem func (r *Runtime) UnmountStorageContainer(id string, force bool) (bool, error) { if _, err := r.GetContainer(id); err == nil { - return false, errors.Wrapf(define.ErrCtrExists, "ctr %s is a libpod container", id) + return false, fmt.Errorf("ctr %s is a libpod container: %w", id, define.ErrCtrExists) } container, err := r.store.Container(id) if err != nil { @@ -1239,7 +1239,7 @@ func (r *Runtime) UnmountStorageContainer(id string, force bool) (bool, error) { func (r *Runtime) IsStorageContainerMounted(id string) (bool, string, error) { var path string if _, err := r.GetContainer(id); err == nil { - return false, "", errors.Wrapf(define.ErrCtrExists, "ctr %s is a libpod container", id) + return false, "", fmt.Errorf("ctr %s is a libpod container: %w", id, define.ErrCtrExists) } mountCnt, err := r.storageService.MountedContainerImage(id) @@ -1265,13 +1265,13 @@ func (r *Runtime) StorageContainers() ([]storage.Container, error) { storeContainers, err := r.store.Containers() if err != nil { - return nil, errors.Wrapf(err, "error reading list of all storage containers") + return nil, fmt.Errorf("error reading list of all storage containers: %w", err) } retCtrs := []storage.Container{} for _, container := range storeContainers { exists, err := r.state.HasContainer(container.ID) if err != nil && err != define.ErrNoSuchCtr { - return nil, errors.Wrapf(err, "failed to check if %s container exists in database", container.ID) + return nil, fmt.Errorf("failed to check if %s container exists in database: %w", container.ID, err) } if exists { continue diff --git a/libpod/runtime_img.go b/libpod/runtime_img.go index b13482722..d04607d2e 100644 --- a/libpod/runtime_img.go +++ b/libpod/runtime_img.go @@ -2,6 +2,8 @@ package libpod import ( "context" + "errors" + "fmt" "io" "io/ioutil" "os" @@ -13,7 +15,6 @@ import ( "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/libpod/events" "github.com/containers/podman/v4/pkg/util" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -40,14 +41,14 @@ func (r *Runtime) RemoveContainersForImageCallback(ctx context.Context) libimage if ctr.config.IsInfra { pod, err := r.state.Pod(ctr.config.Pod) if err != nil { - return errors.Wrapf(err, "container %s is in pod %s, but pod cannot be retrieved", ctr.ID(), ctr.config.Pod) + return fmt.Errorf("container %s is in pod %s, but pod cannot be retrieved: %w", ctr.ID(), ctr.config.Pod, err) } if err := r.removePod(ctx, pod, true, true, timeout); err != nil { - return errors.Wrapf(err, "removing image %s: container %s using image could not be removed", imageID, ctr.ID()) + return fmt.Errorf("removing image %s: container %s using image could not be removed: %w", imageID, ctr.ID(), err) } } else { if err := r.removeContainer(ctx, ctr, true, false, false, timeout); err != nil { - return errors.Wrapf(err, "removing image %s: container %s using image could not be removed", imageID, ctr.ID()) + return fmt.Errorf("removing image %s: container %s using image could not be removed: %w", imageID, ctr.ID(), err) } } } @@ -106,7 +107,7 @@ func (r *Runtime) Build(ctx context.Context, options buildahDefine.BuildOptions, func DownloadFromFile(reader *os.File) (string, error) { outFile, err := ioutil.TempFile(util.Tmpdir(), "import") if err != nil { - return "", errors.Wrap(err, "error creating file") + return "", fmt.Errorf("error creating file: %w", err) } defer outFile.Close() @@ -114,7 +115,7 @@ func DownloadFromFile(reader *os.File) (string, error) { _, err = io.Copy(outFile, reader) if err != nil { - return "", errors.Wrapf(err, "error saving %s to %s", reader.Name(), outFile.Name()) + return "", fmt.Errorf("error saving %s to %s: %w", reader.Name(), outFile.Name(), err) } return outFile.Name(), nil diff --git a/libpod/runtime_migrate.go b/libpod/runtime_migrate.go index f56cb83a4..139638a6b 100644 --- a/libpod/runtime_migrate.go +++ b/libpod/runtime_migrate.go @@ -14,7 +14,6 @@ import ( "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/rootless" "github.com/containers/podman/v4/pkg/util" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -22,21 +21,21 @@ func (r *Runtime) stopPauseProcess() error { if rootless.IsRootless() { pausePidPath, err := util.GetRootlessPauseProcessPidPathGivenDir(r.config.Engine.TmpDir) if err != nil { - return errors.Wrapf(err, "could not get pause process pid file path") + return fmt.Errorf("could not get pause process pid file path: %w", err) } data, err := ioutil.ReadFile(pausePidPath) if err != nil { if os.IsNotExist(err) { return nil } - return errors.Wrap(err, "cannot read pause process pid file") + return fmt.Errorf("cannot read pause process pid file: %w", err) } pausePid, err := strconv.Atoi(string(data)) if err != nil { - return errors.Wrapf(err, "cannot parse pause pid file %s", pausePidPath) + return fmt.Errorf("cannot parse pause pid file %s: %w", pausePidPath, err) } if err := os.Remove(pausePidPath); err != nil { - return errors.Wrapf(err, "cannot delete pause pid file %s", pausePidPath) + return fmt.Errorf("cannot delete pause pid file %s: %w", pausePidPath, err) } if err := syscall.Kill(pausePid, syscall.SIGKILL); err != nil { return err @@ -60,7 +59,7 @@ func (r *Runtime) migrate() error { for _, ctr := range runningContainers { fmt.Printf("stopped %s\n", ctr.ID()) if err := ctr.Stop(); err != nil { - return errors.Wrapf(err, "cannot stop container %s", ctr.ID()) + return fmt.Errorf("cannot stop container %s: %w", ctr.ID(), err) } } @@ -68,7 +67,7 @@ func (r *Runtime) migrate() error { runtimeChangeRequested := r.migrateRuntime != "" requestedRuntime, runtimeExists := r.ociRuntimes[r.migrateRuntime] if !runtimeExists && runtimeChangeRequested { - return errors.Wrapf(define.ErrInvalidArg, "change to runtime %q requested but no such runtime is defined", r.migrateRuntime) + return fmt.Errorf("change to runtime %q requested but no such runtime is defined: %w", r.migrateRuntime, define.ErrInvalidArg) } for _, ctr := range allCtrs { @@ -93,7 +92,7 @@ func (r *Runtime) migrate() error { if needsWrite { if err := r.state.RewriteContainerConfig(ctr, ctr.config); err != nil { - return errors.Wrapf(err, "error rewriting config for container %s", ctr.ID()) + return fmt.Errorf("error rewriting config for container %s: %w", ctr.ID(), err) } } } diff --git a/libpod/runtime_pod.go b/libpod/runtime_pod.go index ee3d40484..25e48de14 100644 --- a/libpod/runtime_pod.go +++ b/libpod/runtime_pod.go @@ -2,11 +2,12 @@ package libpod import ( "context" + "errors" + "fmt" "time" "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/libpod/define" - "github.com/pkg/errors" ) // Contains the public Runtime API for pods @@ -112,7 +113,7 @@ func (r *Runtime) GetLatestPod() (*Pod, error) { var lastCreatedTime time.Time pods, err := r.GetAllPods() if err != nil { - return nil, errors.Wrapf(err, "unable to get all pods") + return nil, fmt.Errorf("unable to get all pods: %w", err) } if len(pods) == 0 { return nil, define.ErrNoSuchPod @@ -146,7 +147,7 @@ func (r *Runtime) GetRunningPods() ([]*Pod, error) { pods = append(pods, c.PodID()) pod, err := r.GetPod(c.PodID()) if err != nil { - if errors.Cause(err) == define.ErrPodRemoved || errors.Cause(err) == define.ErrNoSuchPod { + if errors.Is(err, define.ErrPodRemoved) || errors.Is(err, define.ErrNoSuchPod) { continue } return nil, err diff --git a/libpod/runtime_pod_linux.go b/libpod/runtime_pod_linux.go index 1f9ebe724..75ff24e41 100644 --- a/libpod/runtime_pod_linux.go +++ b/libpod/runtime_pod_linux.go @@ -5,6 +5,7 @@ package libpod import ( "context" + "errors" "fmt" "os" "path" @@ -18,7 +19,6 @@ import ( "github.com/containers/podman/v4/pkg/rootless" "github.com/containers/podman/v4/pkg/specgen" runcconfig "github.com/opencontainers/runc/libcontainer/configs" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -38,14 +38,14 @@ func (r *Runtime) NewPod(ctx context.Context, p specgen.PodSpecGenerator, option for _, option := range options { if err := option(pod); err != nil { - return nil, errors.Wrapf(err, "error running pod create option") + return nil, fmt.Errorf("error running pod create option: %w", err) } } // Allocate a lock for the pod lock, err := r.lockManager.AllocateLock() if err != nil { - return nil, errors.Wrapf(err, "error allocating lock for new pod") + return nil, fmt.Errorf("error allocating lock for new pod: %w", err) } pod.lock = lock pod.config.LockID = pod.lock.ID() @@ -70,7 +70,7 @@ func (r *Runtime) NewPod(ctx context.Context, p specgen.PodSpecGenerator, option if pod.config.CgroupParent == "" { pod.config.CgroupParent = CgroupfsDefaultCgroupParent } else if strings.HasSuffix(path.Base(pod.config.CgroupParent), ".slice") { - return nil, errors.Wrapf(define.ErrInvalidArg, "systemd slice received as cgroup parent when using cgroupfs") + return nil, fmt.Errorf("systemd slice received as cgroup parent when using cgroupfs: %w", define.ErrInvalidArg) } // If we are set to use pod cgroups, set the cgroup parent that // all containers in the pod will share @@ -108,14 +108,14 @@ func (r *Runtime) NewPod(ctx context.Context, p specgen.PodSpecGenerator, option pod.config.CgroupParent = SystemdDefaultCgroupParent } } else if len(pod.config.CgroupParent) < 6 || !strings.HasSuffix(path.Base(pod.config.CgroupParent), ".slice") { - return nil, errors.Wrapf(define.ErrInvalidArg, "did not receive systemd slice as cgroup parent when using systemd to manage cgroups") + return nil, fmt.Errorf("did not receive systemd slice as cgroup parent when using systemd to manage cgroups: %w", define.ErrInvalidArg) } // If we are set to use pod cgroups, set the cgroup parent that // all containers in the pod will share if pod.config.UsePodCgroup { cgroupPath, err := systemdSliceFromPath(pod.config.CgroupParent, fmt.Sprintf("libpod_pod_%s", pod.ID()), p.InfraContainerSpec.ResourceLimits) if err != nil { - return nil, errors.Wrapf(err, "unable to create pod cgroup for pod %s", pod.ID()) + return nil, fmt.Errorf("unable to create pod cgroup for pod %s: %w", pod.ID(), err) } pod.state.CgroupPath = cgroupPath if p.InfraContainerSpec != nil { @@ -123,7 +123,7 @@ func (r *Runtime) NewPod(ctx context.Context, p specgen.PodSpecGenerator, option } } default: - return nil, errors.Wrapf(define.ErrInvalidArg, "unsupported Cgroup manager: %s - cannot validate cgroup parent", r.config.Engine.CgroupManager) + return nil, fmt.Errorf("unsupported Cgroup manager: %s - cannot validate cgroup parent: %w", r.config.Engine.CgroupManager, define.ErrInvalidArg) } } @@ -132,7 +132,7 @@ func (r *Runtime) NewPod(ctx context.Context, p specgen.PodSpecGenerator, option } if !pod.HasInfraContainer() && pod.SharesNamespaces() { - return nil, errors.Errorf("Pods must have an infra container to share namespaces") + return nil, errors.New("Pods must have an infra container to share namespaces") } if pod.HasInfraContainer() && !pod.SharesNamespaces() { logrus.Infof("Pod has an infra container, but shares no namespaces") @@ -157,12 +157,12 @@ func (r *Runtime) NewPod(ctx context.Context, p specgen.PodSpecGenerator, option if addPodErr = r.state.AddPod(pod); addPodErr == nil { return pod, nil } - if !generateName || (errors.Cause(addPodErr) != define.ErrPodExists && errors.Cause(addPodErr) != define.ErrCtrExists) { + if !generateName || (!errors.Is(addPodErr, define.ErrPodExists) && !errors.Is(addPodErr, define.ErrCtrExists)) { break } } if addPodErr != nil { - return nil, errors.Wrapf(addPodErr, "error adding pod to state") + return nil, fmt.Errorf("error adding pod to state: %w", addPodErr) } return pod, nil @@ -211,7 +211,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool, force = true } if !removeCtrs && numCtrs > 0 { - return errors.Wrapf(define.ErrCtrExists, "pod %s contains containers and cannot be removed", p.ID()) + return fmt.Errorf("pod %s contains containers and cannot be removed: %w", p.ID(), define.ErrCtrExists) } // Go through and lock all containers so we can operate on them all at @@ -239,7 +239,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool, // Ensure state appropriate for removal if err := ctr.checkReadyForRemoval(); err != nil { - return errors.Wrapf(err, "pod %s has containers that are not ready to be removed", p.ID()) + return fmt.Errorf("pod %s has containers that are not ready to be removed: %w", p.ID(), err) } } @@ -311,7 +311,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool, for volName := range ctrNamedVolumes { volume, err := r.state.Volume(volName) - if err != nil && errors.Cause(err) != define.ErrNoSuchVolume { + if err != nil && !errors.Is(err, define.ErrNoSuchVolume) { logrus.Errorf("Retrieving volume %s: %v", volName, err) continue } @@ -319,7 +319,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool, continue } if err := r.removeVolume(ctx, volume, false, timeout, false); err != nil { - if errors.Cause(err) == define.ErrNoSuchVolume || errors.Cause(err) == define.ErrVolumeRemoved { + if errors.Is(err, define.ErrNoSuchVolume) || errors.Is(err, define.ErrVolumeRemoved) { continue } logrus.Errorf("Removing volume %s: %v", volName, err) @@ -340,7 +340,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool, case config.SystemdCgroupsManager: if err := deleteSystemdCgroup(p.state.CgroupPath, p.ResourceLim()); err != nil { if removalErr == nil { - removalErr = errors.Wrapf(err, "error removing pod %s cgroup", p.ID()) + removalErr = fmt.Errorf("error removing pod %s cgroup: %w", p.ID(), err) } else { logrus.Errorf("Deleting pod %s cgroup %s: %v", p.ID(), p.state.CgroupPath, err) } @@ -354,7 +354,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool, conmonCgroup, err := cgroups.Load(conmonCgroupPath) if err != nil && err != cgroups.ErrCgroupDeleted && err != cgroups.ErrCgroupV1Rootless { if removalErr == nil { - removalErr = errors.Wrapf(err, "error retrieving pod %s conmon cgroup", p.ID()) + removalErr = fmt.Errorf("error retrieving pod %s conmon cgroup: %w", p.ID(), err) } else { logrus.Debugf("Error retrieving pod %s conmon cgroup %s: %v", p.ID(), conmonCgroupPath, err) } @@ -362,7 +362,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool, if err == nil { if err = conmonCgroup.Delete(); err != nil { if removalErr == nil { - removalErr = errors.Wrapf(err, "error removing pod %s conmon cgroup", p.ID()) + removalErr = fmt.Errorf("error removing pod %s conmon cgroup: %w", p.ID(), err) } else { logrus.Errorf("Deleting pod %s conmon cgroup %s: %v", p.ID(), conmonCgroupPath, err) } @@ -371,7 +371,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool, cgroup, err := cgroups.Load(p.state.CgroupPath) if err != nil && err != cgroups.ErrCgroupDeleted && err != cgroups.ErrCgroupV1Rootless { if removalErr == nil { - removalErr = errors.Wrapf(err, "error retrieving pod %s cgroup", p.ID()) + removalErr = fmt.Errorf("error retrieving pod %s cgroup: %w", p.ID(), err) } else { logrus.Errorf("Retrieving pod %s cgroup %s: %v", p.ID(), p.state.CgroupPath, err) } @@ -379,7 +379,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool, if err == nil { if err := cgroup.Delete(); err != nil { if removalErr == nil { - removalErr = errors.Wrapf(err, "error removing pod %s cgroup", p.ID()) + removalErr = fmt.Errorf("error removing pod %s cgroup: %w", p.ID(), err) } else { logrus.Errorf("Deleting pod %s cgroup %s: %v", p.ID(), p.state.CgroupPath, err) } @@ -390,7 +390,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool, // keep going so we make sure to evict the pod before // ending up with an inconsistent state. if removalErr == nil { - removalErr = errors.Wrapf(define.ErrInternal, "unrecognized cgroup manager %s when removing pod %s cgroups", p.runtime.config.Engine.CgroupManager, p.ID()) + removalErr = fmt.Errorf("unrecognized cgroup manager %s when removing pod %s cgroups: %w", p.runtime.config.Engine.CgroupManager, p.ID(), define.ErrInternal) } else { logrus.Errorf("Unknown cgroups manager %s specified - cannot remove pod %s cgroup", p.runtime.config.Engine.CgroupManager, p.ID()) } @@ -416,7 +416,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool, // Deallocate the pod lock if err := p.lock.Free(); err != nil { if removalErr == nil { - removalErr = errors.Wrapf(err, "error freeing pod %s lock", p.ID()) + removalErr = fmt.Errorf("error freeing pod %s lock: %w", p.ID(), err) } else { logrus.Errorf("Freeing pod %s lock: %v", p.ID(), err) } diff --git a/libpod/runtime_renumber.go b/libpod/runtime_renumber.go index db055f40b..9149dd72f 100644 --- a/libpod/runtime_renumber.go +++ b/libpod/runtime_renumber.go @@ -1,8 +1,9 @@ package libpod import ( + "fmt" + "github.com/containers/podman/v4/libpod/events" - "github.com/pkg/errors" ) // renumberLocks reassigns lock numbers for all containers and pods in the @@ -26,7 +27,7 @@ func (r *Runtime) renumberLocks() error { for _, ctr := range allCtrs { lock, err := r.lockManager.AllocateLock() if err != nil { - return errors.Wrapf(err, "error allocating lock for container %s", ctr.ID()) + return fmt.Errorf("error allocating lock for container %s: %w", ctr.ID(), err) } ctr.config.LockID = lock.ID() @@ -43,7 +44,7 @@ func (r *Runtime) renumberLocks() error { for _, pod := range allPods { lock, err := r.lockManager.AllocateLock() if err != nil { - return errors.Wrapf(err, "error allocating lock for pod %s", pod.ID()) + return fmt.Errorf("error allocating lock for pod %s: %w", pod.ID(), err) } pod.config.LockID = lock.ID() @@ -60,7 +61,7 @@ func (r *Runtime) renumberLocks() error { for _, vol := range allVols { lock, err := r.lockManager.AllocateLock() if err != nil { - return errors.Wrapf(err, "error allocating lock for volume %s", vol.Name()) + return fmt.Errorf("error allocating lock for volume %s: %w", vol.Name(), err) } vol.config.LockID = lock.ID() diff --git a/libpod/runtime_volume.go b/libpod/runtime_volume.go index 6872db21d..9efb30e03 100644 --- a/libpod/runtime_volume.go +++ b/libpod/runtime_volume.go @@ -2,11 +2,11 @@ package libpod import ( "context" + "errors" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/libpod/events" "github.com/containers/podman/v4/pkg/domain/entities/reports" - "github.com/pkg/errors" ) // Contains the public Runtime API for volumes @@ -133,7 +133,7 @@ func (r *Runtime) PruneVolumes(ctx context.Context, filterFuncs []VolumeFilter) report.Id = vol.Name() var timeout *uint if err := r.RemoveVolume(ctx, vol, false, timeout); err != nil { - if errors.Cause(err) != define.ErrVolumeBeingUsed && errors.Cause(err) != define.ErrVolumeRemoved { + if !errors.Is(err, define.ErrVolumeBeingUsed) && !errors.Is(err, define.ErrVolumeRemoved) { report.Err = err } else { // We didn't remove the volume for some reason diff --git a/libpod/runtime_volume_linux.go b/libpod/runtime_volume_linux.go index da8c3712d..a751d75d2 100644 --- a/libpod/runtime_volume_linux.go +++ b/libpod/runtime_volume_linux.go @@ -5,6 +5,7 @@ package libpod import ( "context" + "errors" "fmt" "os" "path/filepath" @@ -17,7 +18,6 @@ import ( "github.com/containers/storage/drivers/quota" "github.com/containers/storage/pkg/stringid" pluginapi "github.com/docker/go-plugins-helpers/volume" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -36,7 +36,7 @@ func (r *Runtime) newVolume(noCreatePluginVolume bool, options ...VolumeCreateOp volume := newVolume(r) for _, option := range options { if err := option(volume); err != nil { - return nil, errors.Wrapf(err, "running volume create option") + return nil, fmt.Errorf("running volume create option: %w", err) } } @@ -51,17 +51,17 @@ func (r *Runtime) newVolume(noCreatePluginVolume bool, options ...VolumeCreateOp // Check if volume with given name exists. exists, err := r.state.HasVolume(volume.config.Name) if err != nil { - return nil, errors.Wrapf(err, "checking if volume with name %s exists", volume.config.Name) + return nil, fmt.Errorf("checking if volume with name %s exists: %w", volume.config.Name, err) } if exists { - return nil, errors.Wrapf(define.ErrVolumeExists, "volume with name %s already exists", volume.config.Name) + return nil, fmt.Errorf("volume with name %s already exists: %w", volume.config.Name, define.ErrVolumeExists) } // Plugin can be nil if driver is local, but that's OK - superfluous // assignment doesn't hurt much. plugin, err := r.getVolumePlugin(volume.config) if err != nil { - return nil, errors.Wrapf(err, "volume %s uses volume plugin %s but it could not be retrieved", volume.config.Name, volume.config.Driver) + return nil, fmt.Errorf("volume %s uses volume plugin %s but it could not be retrieved: %w", volume.config.Name, volume.config.Driver, err) } volume.plugin = plugin @@ -73,13 +73,13 @@ func (r *Runtime) newVolume(noCreatePluginVolume bool, options ...VolumeCreateOp case "device": if strings.ToLower(volume.config.Options["type"]) == "bind" { if _, err := os.Stat(val); err != nil { - return nil, errors.Wrapf(err, "invalid volume option %s for driver 'local'", key) + return nil, fmt.Errorf("invalid volume option %s for driver 'local': %w", key, err) } } case "o", "type", "uid", "gid", "size", "inodes", "noquota", "copy", "nocopy": // Do nothing, valid keys default: - return nil, errors.Wrapf(define.ErrInvalidArg, "invalid mount option %s for driver 'local'", key) + return nil, fmt.Errorf("invalid mount option %s for driver 'local': %w", key, define.ErrInvalidArg) } } } @@ -99,17 +99,17 @@ func (r *Runtime) newVolume(noCreatePluginVolume bool, options ...VolumeCreateOp // Create the mountpoint of this volume volPathRoot := filepath.Join(r.config.Engine.VolumePath, volume.config.Name) if err := os.MkdirAll(volPathRoot, 0700); err != nil { - return nil, errors.Wrapf(err, "creating volume directory %q", volPathRoot) + return nil, fmt.Errorf("creating volume directory %q: %w", volPathRoot, err) } if err := os.Chown(volPathRoot, volume.config.UID, volume.config.GID); err != nil { - return nil, errors.Wrapf(err, "chowning volume directory %q to %d:%d", volPathRoot, volume.config.UID, volume.config.GID) + 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, errors.Wrapf(err, "creating volume directory %q", fullVolPath) + return nil, fmt.Errorf("creating volume directory %q: %w", fullVolPath, err) } if err := os.Chown(fullVolPath, volume.config.UID, volume.config.GID); err != nil { - return nil, errors.Wrapf(err, "chowning volume directory %q to %d:%d", fullVolPath, volume.config.UID, volume.config.GID) + return nil, fmt.Errorf("chowning volume directory %q to %d:%d: %w", fullVolPath, volume.config.UID, volume.config.GID, err) } if err := LabelVolumePath(fullVolPath); err != nil { return nil, err @@ -134,7 +134,7 @@ func (r *Runtime) newVolume(noCreatePluginVolume bool, options ...VolumeCreateOp } if projectQuotaSupported { if err := q.SetQuota(fullVolPath, quota); err != nil { - return nil, errors.Wrapf(err, "failed to set size quota size=%d inodes=%d for volume directory %q", volume.config.Size, volume.config.Inodes, fullVolPath) + 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) } } } @@ -144,7 +144,7 @@ func (r *Runtime) newVolume(noCreatePluginVolume bool, options ...VolumeCreateOp lock, err := r.lockManager.AllocateLock() if err != nil { - return nil, errors.Wrapf(err, "allocating lock for new volume") + return nil, fmt.Errorf("allocating lock for new volume: %w", err) } volume.lock = lock volume.config.LockID = volume.lock.ID() @@ -161,7 +161,7 @@ func (r *Runtime) newVolume(noCreatePluginVolume bool, options ...VolumeCreateOp // Add the volume to state if err := r.state.AddVolume(volume); err != nil { - return nil, errors.Wrapf(err, "adding volume to state") + return nil, fmt.Errorf("adding volume to state: %w", err) } defer volume.newVolumeEvent(events.Create) return volume, nil @@ -272,7 +272,7 @@ func makeVolumeInPluginIfNotExist(name string, options map[string]string, plugin createReq.Name = name createReq.Options = options if err := plugin.CreateVolume(createReq); err != nil { - return errors.Wrapf(err, "creating volume %q in plugin %s", name, plugin.Name) + return fmt.Errorf("creating volume %q in plugin %s: %w", name, plugin.Name, err) } } @@ -305,7 +305,7 @@ func (r *Runtime) removeVolume(ctx context.Context, v *Volume, force bool, timeo if len(deps) != 0 { depsStr := strings.Join(deps, ", ") if !force { - return errors.Wrapf(define.ErrVolumeBeingUsed, "volume %s is being used by the following container(s): %s", v.Name(), depsStr) + return fmt.Errorf("volume %s is being used by the following container(s): %s: %w", v.Name(), depsStr, define.ErrVolumeBeingUsed) } // We need to remove all containers using the volume @@ -314,17 +314,17 @@ func (r *Runtime) removeVolume(ctx context.Context, v *Volume, force bool, timeo if err != nil { // If the container's removed, no point in // erroring. - if errors.Cause(err) == define.ErrNoSuchCtr || errors.Cause(err) == define.ErrCtrRemoved { + if errors.Is(err, define.ErrNoSuchCtr) || errors.Is(err, define.ErrCtrRemoved) { continue } - return errors.Wrapf(err, "removing container %s that depends on volume %s", dep, v.Name()) + return fmt.Errorf("removing container %s that depends on volume %s: %w", dep, v.Name(), err) } logrus.Debugf("Removing container %s (depends on volume %q)", ctr.ID(), v.Name()) if err := r.removeContainer(ctx, ctr, force, false, false, timeout); err != nil { - return errors.Wrapf(err, "removing container %s that depends on volume %s", ctr.ID(), v.Name()) + return fmt.Errorf("removing container %s that depends on volume %s: %w", ctr.ID(), v.Name(), err) } } } @@ -337,7 +337,7 @@ func (r *Runtime) removeVolume(ctx context.Context, v *Volume, force bool, timeo // them. logrus.Errorf("Unmounting volume %s: %v", v.Name(), err) } else { - return errors.Wrapf(err, "unmounting volume %s", v.Name()) + return fmt.Errorf("unmounting volume %s: %w", v.Name(), err) } } @@ -353,7 +353,7 @@ func (r *Runtime) removeVolume(ctx context.Context, v *Volume, force bool, timeo // Do we have a volume driver? if v.plugin == nil { canRemove = false - removalErr = errors.Wrapf(define.ErrMissingPlugin, "cannot remove volume %s from plugin %s, but it has been removed from Podman", v.Name(), v.Driver()) + removalErr = fmt.Errorf("cannot remove volume %s from plugin %s, but it has been removed from Podman: %w", v.Name(), v.Driver(), define.ErrMissingPlugin) } else { // Ping the plugin first to verify the volume still // exists. @@ -364,14 +364,14 @@ func (r *Runtime) removeVolume(ctx context.Context, v *Volume, force bool, timeo getReq.Name = v.Name() if _, err := v.plugin.GetVolume(getReq); err != nil { canRemove = false - removalErr = errors.Wrapf(err, "volume %s could not be retrieved from plugin %s, but it has been removed from Podman", v.Name(), v.Driver()) + removalErr = fmt.Errorf("volume %s could not be retrieved from plugin %s, but it has been removed from Podman: %w", v.Name(), v.Driver(), err) } } if canRemove { req := new(pluginapi.RemoveRequest) req.Name = v.Name() if err := v.plugin.RemoveVolume(req); err != nil { - return errors.Wrapf(err, "volume %s could not be removed from plugin %s", v.Name(), v.Driver()) + return fmt.Errorf("volume %s could not be removed from plugin %s: %w", v.Name(), v.Driver(), err) } } } @@ -381,13 +381,13 @@ func (r *Runtime) removeVolume(ctx context.Context, v *Volume, force bool, timeo if removalErr != nil { logrus.Errorf("Removing volume %s from plugin %s: %v", v.Name(), v.Driver(), removalErr) } - return errors.Wrapf(err, "removing volume %s", v.Name()) + return fmt.Errorf("removing volume %s: %w", v.Name(), err) } // Free the volume's lock if err := v.lock.Free(); err != nil { if removalErr == nil { - removalErr = errors.Wrapf(err, "freeing lock for volume %s", v.Name()) + removalErr = fmt.Errorf("freeing lock for volume %s: %w", v.Name(), err) } else { logrus.Errorf("Freeing lock for volume %q: %v", v.Name(), err) } @@ -397,7 +397,7 @@ func (r *Runtime) removeVolume(ctx context.Context, v *Volume, force bool, timeo // from /var/lib/containers/storage/volumes if err := v.teardownStorage(); err != nil { if removalErr == nil { - removalErr = errors.Wrapf(err, "cleaning up volume storage for %q", v.Name()) + removalErr = fmt.Errorf("cleaning up volume storage for %q: %w", v.Name(), err) } else { logrus.Errorf("Cleaning up volume storage for volume %q: %v", v.Name(), err) } diff --git a/libpod/service.go b/libpod/service.go index c14f5e51d..a8928277f 100644 --- a/libpod/service.go +++ b/libpod/service.go @@ -2,10 +2,10 @@ package libpod import ( "context" + "errors" "fmt" "github.com/containers/podman/v4/libpod/define" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -29,7 +29,7 @@ func (p *Pod) hasServiceContainer() bool { func (p *Pod) serviceContainer() (*Container, error) { id := p.config.ServiceContainerID if id == "" { - return nil, errors.Wrap(define.ErrNoSuchCtr, "pod has no service container") + return nil, fmt.Errorf("pod has no service container: %w", define.ErrNoSuchCtr) } return p.runtime.state.Container(id) } diff --git a/libpod/shutdown/handler.go b/libpod/shutdown/handler.go index 9add05c9c..75e9b4e8a 100644 --- a/libpod/shutdown/handler.go +++ b/libpod/shutdown/handler.go @@ -1,18 +1,18 @@ package shutdown import ( + "errors" "os" "os/signal" "sync" "syscall" "time" - "github.com/pkg/errors" logrusImport "github.com/sirupsen/logrus" ) var ( - ErrHandlerExists error = errors.New("handler with given name already exists") + ErrHandlerExists = errors.New("handler with given name already exists") ) var ( diff --git a/libpod/stats.go b/libpod/stats.go index eaac9d7d0..c7e9e5128 100644 --- a/libpod/stats.go +++ b/libpod/stats.go @@ -4,6 +4,7 @@ package libpod import ( + "fmt" "math" "strings" "syscall" @@ -13,7 +14,6 @@ import ( "github.com/containers/common/pkg/cgroups" "github.com/containers/podman/v4/libpod/define" - "github.com/pkg/errors" ) // GetContainerStats gets the running stats for a given container. @@ -25,7 +25,7 @@ func (c *Container) GetContainerStats(previousStats *define.ContainerStats) (*de stats.Name = c.Name() if c.config.NoCgroups { - return nil, errors.Wrapf(define.ErrNoCgroups, "cannot run top on container %s as it did not create a cgroup", c.ID()) + return nil, fmt.Errorf("cannot run top on container %s as it did not create a cgroup: %w", c.ID(), define.ErrNoCgroups) } if !c.batched { @@ -55,13 +55,13 @@ func (c *Container) GetContainerStats(previousStats *define.ContainerStats) (*de } cgroup, err := cgroups.Load(cgroupPath) if err != nil { - return stats, errors.Wrapf(err, "unable to load cgroup at %s", cgroupPath) + return stats, fmt.Errorf("unable to load cgroup at %s: %w", cgroupPath, err) } // Ubuntu does not have swap memory in cgroups because swap is often not enabled. cgroupStats, err := cgroup.Stat() if err != nil { - return stats, errors.Wrapf(err, "unable to obtain cgroup stats") + return stats, fmt.Errorf("unable to obtain cgroup stats: %w", err) } conState := c.state.State netStats, err := getContainerNetIO(c) diff --git a/libpod/storage.go b/libpod/storage.go index a85348729..dc19a5d4f 100644 --- a/libpod/storage.go +++ b/libpod/storage.go @@ -2,6 +2,7 @@ package libpod import ( "context" + "errors" "time" istorage "github.com/containers/image/v5/storage" @@ -10,7 +11,6 @@ import ( "github.com/containers/storage" "github.com/containers/storage/pkg/idtools" v1 "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -184,7 +184,7 @@ func (r *storageService) DeleteContainer(idOrName string) error { } err = r.store.DeleteContainer(container.ID) if err != nil { - if errors.Cause(err) == storage.ErrNotAContainer || errors.Cause(err) == storage.ErrContainerUnknown { + if errors.Is(err, storage.ErrNotAContainer) || errors.Is(err, storage.ErrContainerUnknown) { logrus.Infof("Storage for container %s already removed", container.ID) } else { logrus.Debugf("Failed to delete container %q: %v", container.ID, err) @@ -218,7 +218,7 @@ func (r *storageService) GetContainerMetadata(idOrName string) (RuntimeContainer func (r *storageService) MountContainerImage(idOrName string) (string, error) { container, err := r.store.Container(idOrName) if err != nil { - if errors.Cause(err) == storage.ErrContainerUnknown { + if errors.Is(err, storage.ErrContainerUnknown) { return "", define.ErrNoSuchCtr } return "", err @@ -281,7 +281,7 @@ func (r *storageService) MountedContainerImage(idOrName string) (int, error) { func (r *storageService) GetMountpoint(id string) (string, error) { container, err := r.store.Container(id) if err != nil { - if errors.Cause(err) == storage.ErrContainerUnknown { + if errors.Is(err, storage.ErrContainerUnknown) { return "", define.ErrNoSuchCtr } return "", err @@ -297,7 +297,7 @@ func (r *storageService) GetMountpoint(id string) (string, error) { func (r *storageService) GetWorkDir(id string) (string, error) { container, err := r.store.Container(id) if err != nil { - if errors.Cause(err) == storage.ErrContainerUnknown { + if errors.Is(err, storage.ErrContainerUnknown) { return "", define.ErrNoSuchCtr } return "", err @@ -308,7 +308,7 @@ func (r *storageService) GetWorkDir(id string) (string, error) { func (r *storageService) GetRunDir(id string) (string, error) { container, err := r.store.Container(id) if err != nil { - if errors.Cause(err) == storage.ErrContainerUnknown { + if errors.Is(err, storage.ErrContainerUnknown) { return "", define.ErrNoSuchCtr } return "", err diff --git a/libpod/util.go b/libpod/util.go index 1753b4f34..a6e6a4f3e 100644 --- a/libpod/util.go +++ b/libpod/util.go @@ -20,7 +20,6 @@ import ( "github.com/fsnotify/fsnotify" spec "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/selinux/go-selinux/label" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -93,7 +92,7 @@ func WaitForFile(path string, chWait chan error, timeout time.Duration) (bool, e return false, err } case <-timeoutChan: - return false, errors.Wrapf(define.ErrInternal, "timed out waiting for file %s", path) + return false, fmt.Errorf("timed out waiting for file %s: %w", path, define.ErrInternal) } } } @@ -123,15 +122,15 @@ func sortMounts(m []spec.Mount) []spec.Mount { func validPodNSOption(p *Pod, ctrPod string) error { if p == nil { - return errors.Wrapf(define.ErrInvalidArg, "pod passed in was nil. Container may not be associated with a pod") + return fmt.Errorf("pod passed in was nil. Container may not be associated with a pod: %w", define.ErrInvalidArg) } if ctrPod == "" { - return errors.Wrapf(define.ErrInvalidArg, "container is not a member of any pod") + return fmt.Errorf("container is not a member of any pod: %w", define.ErrInvalidArg) } if ctrPod != p.ID() { - return errors.Wrapf(define.ErrInvalidArg, "pod passed in is not the pod the container is associated with") + return fmt.Errorf("pod passed in is not the pod the container is associated with: %w", define.ErrInvalidArg) } return nil } @@ -232,18 +231,18 @@ func DefaultSeccompPath() (string, error) { func checkDependencyContainer(depCtr, ctr *Container) error { state, err := depCtr.State() if err != nil { - return errors.Wrapf(err, "error accessing dependency container %s state", depCtr.ID()) + return fmt.Errorf("error accessing dependency container %s state: %w", depCtr.ID(), err) } if state == define.ContainerStateRemoving { - return errors.Wrapf(define.ErrCtrStateInvalid, "cannot use container %s as a dependency as it is being removed", depCtr.ID()) + return fmt.Errorf("cannot use container %s as a dependency as it is being removed: %w", depCtr.ID(), define.ErrCtrStateInvalid) } if depCtr.ID() == ctr.ID() { - return errors.Wrapf(define.ErrInvalidArg, "must specify another container") + return fmt.Errorf("must specify another container: %w", define.ErrInvalidArg) } if ctr.config.Pod != "" && depCtr.PodID() != ctr.config.Pod { - return errors.Wrapf(define.ErrInvalidArg, "container has joined pod %s and dependency container %s is not a member of the pod", ctr.config.Pod, depCtr.ID()) + return fmt.Errorf("container has joined pod %s and dependency container %s is not a member of the pod: %w", ctr.config.Pod, depCtr.ID(), define.ErrInvalidArg) } return nil @@ -347,7 +346,7 @@ func makeInspectPortBindings(bindings []types.PortMapping, expose map[uint16][]s func writeStringToPath(path, contents, mountLabel string, uid, gid int) error { f, err := os.Create(path) if err != nil { - return errors.Wrapf(err, "unable to create %s", path) + return fmt.Errorf("unable to create %s: %w", path, err) } defer f.Close() if err := f.Chown(uid, gid); err != nil { @@ -355,7 +354,7 @@ func writeStringToPath(path, contents, mountLabel string, uid, gid int) error { } if _, err := f.WriteString(contents); err != nil { - return errors.Wrapf(err, "unable to write %s", path) + return fmt.Errorf("unable to write %s: %w", path, err) } // Relabel runDirResolv for the container if err := label.Relabel(path, mountLabel, false); err != nil { diff --git a/libpod/util_linux.go b/libpod/util_linux.go index 414d1bff9..7c79e6ce4 100644 --- a/libpod/util_linux.go +++ b/libpod/util_linux.go @@ -13,7 +13,6 @@ import ( "github.com/containers/podman/v4/pkg/rootless" spec "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/selinux/go-selinux/label" - "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/sys/unix" ) @@ -30,7 +29,7 @@ func systemdSliceFromPath(parent, name string, resources *spec.LinuxResources) ( logrus.Debugf("Created cgroup path %s for parent %s and name %s", cgroupPath, parent, name) if err := makeSystemdCgroup(cgroupPath, resources); err != nil { - return "", errors.Wrapf(err, "error creating cgroup %s", cgroupPath) + return "", fmt.Errorf("error creating cgroup %s: %w", cgroupPath, err) } logrus.Debugf("Created cgroup %s", cgroupPath) @@ -95,7 +94,7 @@ func assembleSystemdCgroupName(baseSlice, newSlice string) (string, error) { const sliceSuffix = ".slice" if !strings.HasSuffix(baseSlice, sliceSuffix) { - return "", errors.Wrapf(define.ErrInvalidArg, "cannot assemble cgroup path with base %q - must end in .slice", baseSlice) + return "", fmt.Errorf("cannot assemble cgroup path with base %q - must end in .slice: %w", baseSlice, define.ErrInvalidArg) } noSlice := strings.TrimSuffix(baseSlice, sliceSuffix) @@ -113,17 +112,17 @@ var lvpReleaseLabel = label.ReleaseLabel func LabelVolumePath(path string) error { _, mountLabel, err := lvpInitLabels([]string{}) if err != nil { - return errors.Wrapf(err, "error getting default mountlabels") + return fmt.Errorf("error getting default mountlabels: %w", err) } if err := lvpReleaseLabel(mountLabel); err != nil { - return errors.Wrapf(err, "error releasing label %q", mountLabel) + return fmt.Errorf("error releasing label %q: %w", mountLabel, err) } if err := lvpRelabel(path, mountLabel, true); err != nil { if err == syscall.ENOTSUP { logrus.Debugf("Labeling not supported on %q", path) } else { - return errors.Wrapf(err, "error setting selinux label for %s to %q as shared", path, mountLabel) + return fmt.Errorf("error setting selinux label for %s to %q as shared: %w", path, mountLabel, err) } } return nil diff --git a/libpod/volume_inspect.go b/libpod/volume_inspect.go index 2182f04e6..dd2f3fd01 100644 --- a/libpod/volume_inspect.go +++ b/libpod/volume_inspect.go @@ -1,9 +1,10 @@ package libpod import ( + "fmt" + "github.com/containers/podman/v4/libpod/define" pluginapi "github.com/docker/go-plugins-helpers/volume" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -29,7 +30,7 @@ func (v *Volume) Inspect() (*define.InspectVolumeData, error) { data.Mountpoint = v.state.MountPoint if v.plugin == nil { - return nil, errors.Wrapf(define.ErrMissingPlugin, "volume %s uses volume plugin %s but it is not available, cannot inspect", v.Name(), v.config.Driver) + return nil, fmt.Errorf("volume %s uses volume plugin %s but it is not available, cannot inspect: %w", v.Name(), v.config.Driver, define.ErrMissingPlugin) } // Retrieve status for the volume. @@ -38,7 +39,7 @@ func (v *Volume) Inspect() (*define.InspectVolumeData, error) { req.Name = v.Name() resp, err := v.plugin.GetVolume(req) if err != nil { - return nil, errors.Wrapf(err, "error retrieving volume %s information from plugin %s", v.Name(), v.Driver()) + return nil, fmt.Errorf("error retrieving volume %s information from plugin %s: %w", v.Name(), v.Driver(), err) } if resp != nil { data.Status = resp.Status diff --git a/libpod/volume_internal.go b/libpod/volume_internal.go index 24522c0f9..43c3f9b0b 100644 --- a/libpod/volume_internal.go +++ b/libpod/volume_internal.go @@ -1,11 +1,11 @@ package libpod import ( + "fmt" "os" "path/filepath" "github.com/containers/podman/v4/libpod/define" - "github.com/pkg/errors" ) // Creates a new volume @@ -90,7 +90,7 @@ func (v *Volume) save() error { func (v *Volume) refresh() error { lock, err := v.runtime.lockManager.AllocateAndRetrieveLock(v.config.LockID) if err != nil { - return errors.Wrapf(err, "acquiring lock %d for volume %s", v.config.LockID, v.Name()) + return fmt.Errorf("acquiring lock %d for volume %s: %w", v.config.LockID, v.Name(), err) } v.lock = lock diff --git a/libpod/volume_internal_linux.go b/libpod/volume_internal_linux.go index 7d7dea9d0..cfd60554d 100644 --- a/libpod/volume_internal_linux.go +++ b/libpod/volume_internal_linux.go @@ -4,12 +4,13 @@ package libpod import ( + "errors" + "fmt" "os/exec" "strings" "github.com/containers/podman/v4/libpod/define" pluginapi "github.com/docker/go-plugins-helpers/volume" - "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/sys/unix" ) @@ -51,7 +52,7 @@ func (v *Volume) mount() error { // the same one for everything. if v.UsesVolumeDriver() { if v.plugin == nil { - return errors.Wrapf(define.ErrMissingPlugin, "volume plugin %s (needed by volume %s) missing", v.Driver(), v.Name()) + return fmt.Errorf("volume plugin %s (needed by volume %s) missing: %w", v.Driver(), v.Name(), define.ErrMissingPlugin) } req := new(pluginapi.MountRequest) @@ -83,7 +84,7 @@ func (v *Volume) mount() error { // TODO: might want to cache this path in the runtime? mountPath, err := exec.LookPath("mount") if err != nil { - return errors.Wrapf(err, "locating 'mount' binary") + return fmt.Errorf("locating 'mount' binary: %w", err) } mountArgs := []string{} if volOptions != "" { @@ -103,7 +104,7 @@ func (v *Volume) mount() error { logrus.Debugf("Running mount command: %s %s", mountPath, strings.Join(mountArgs, " ")) if output, err := mountCmd.CombinedOutput(); err != nil { logrus.Debugf("Mount %v failed with %v", mountCmd, err) - return errors.Errorf(string(output)) + return errors.New(string(output)) } logrus.Debugf("Mounted volume %s", v.Name()) @@ -148,7 +149,7 @@ func (v *Volume) unmount(force bool) error { if v.state.MountCount == 0 { if v.UsesVolumeDriver() { if v.plugin == nil { - return errors.Wrapf(define.ErrMissingPlugin, "volume plugin %s (needed by volume %s) missing", v.Driver(), v.Name()) + return fmt.Errorf("volume plugin %s (needed by volume %s) missing: %w", v.Driver(), v.Name(), define.ErrMissingPlugin) } req := new(pluginapi.UnmountRequest) @@ -168,7 +169,7 @@ func (v *Volume) unmount(force bool) error { // Ignore EINVAL - the mount no longer exists. return nil } - return errors.Wrapf(err, "unmounting volume %s", v.Name()) + return fmt.Errorf("unmounting volume %s: %w", v.Name(), err) } logrus.Debugf("Unmounted volume %s", v.Name()) } diff --git a/pkg/api/handlers/compat/containers.go b/pkg/api/handlers/compat/containers.go index 411b0efe9..ae063dc9f 100644 --- a/pkg/api/handlers/compat/containers.go +++ b/pkg/api/handlers/compat/containers.go @@ -2,6 +2,7 @@ package compat import ( "encoding/json" + "errors" "fmt" "net/http" "sort" @@ -27,7 +28,6 @@ import ( "github.com/docker/go-connections/nat" "github.com/docker/go-units" "github.com/gorilla/schema" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -46,7 +46,7 @@ func RemoveContainer(w http.ResponseWriter, r *http.Request) { } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -73,7 +73,7 @@ func RemoveContainer(w http.ResponseWriter, r *http.Request) { name := utils.GetName(r) reports, err := containerEngine.ContainerRm(r.Context(), []string{name}, options) if err != nil { - if errors.Cause(err) == define.ErrNoSuchCtr { + if errors.Is(err, define.ErrNoSuchCtr) { utils.ContainerNotFound(w, name, err) return } @@ -83,7 +83,7 @@ func RemoveContainer(w http.ResponseWriter, r *http.Request) { } if len(reports) > 0 && reports[0].Err != nil { err = reports[0].Err - if errors.Cause(err) == define.ErrNoSuchCtr { + if errors.Is(err, define.ErrNoSuchCtr) { utils.ContainerNotFound(w, name, err) return } @@ -110,12 +110,12 @@ func ListContainers(w http.ResponseWriter, r *http.Request) { filterMap, err := util.PrepareFilters(r) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to decode filter parameters for %s", r.URL.String())) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to decode filter parameters for %s: %w", r.URL.String(), err)) return } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -164,7 +164,7 @@ func ListContainers(w http.ResponseWriter, r *http.Request) { for _, ctnr := range containers { api, err := LibpodToContainer(ctnr, query.Size) if err != nil { - if errors.Cause(err) == define.ErrNoSuchCtr { + if errors.Is(err, define.ErrNoSuchCtr) { // container was removed between the initial fetch of the list and conversion logrus.Debugf("Container %s removed between initial fetch and conversion, ignoring in output", ctnr.ID()) continue @@ -187,7 +187,7 @@ func GetContainer(w http.ResponseWriter, r *http.Request) { } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -215,7 +215,7 @@ func KillContainer(w http.ResponseWriter, r *http.Request) { Signal: "KILL", } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -228,12 +228,12 @@ func KillContainer(w http.ResponseWriter, r *http.Request) { } report, err := containerEngine.ContainerKill(r.Context(), []string{name}, options) if err != nil { - if errors.Cause(err) == define.ErrCtrStateInvalid || - errors.Cause(err) == define.ErrCtrStopped { + if errors.Is(err, define.ErrCtrStateInvalid) || + errors.Is(err, define.ErrCtrStopped) { utils.Error(w, http.StatusConflict, err) return } - if errors.Cause(err) == define.ErrNoSuchCtr { + if errors.Is(err, define.ErrNoSuchCtr) { utils.ContainerNotFound(w, name, err) return } @@ -397,6 +397,15 @@ func LibpodToContainer(l *libpod.Container, sz bool) (*handlers.Container, error }, nil } +func convertSecondaryIPPrefixLen(input *define.InspectNetworkSettings, output *types.NetworkSettings) { + for index, ip := range input.SecondaryIPAddresses { + output.SecondaryIPAddresses[index].PrefixLen = ip.PrefixLength + } + for index, ip := range input.SecondaryIPv6Addresses { + output.SecondaryIPv6Addresses[index].PrefixLen = ip.PrefixLength + } +} + func LibpodToContainerJSON(l *libpod.Container, sz bool) (*types.ContainerJSON, error) { _, imageName := l.Image() inspect, err := l.Inspect(sz) @@ -512,7 +521,7 @@ func LibpodToContainerJSON(l *libpod.Container, sz bool) (*types.ContainerJSON, for ep := range inspect.HostConfig.PortBindings { splitp := strings.SplitN(ep, "/", 2) if len(splitp) != 2 { - return nil, errors.Errorf("PORT/PROTOCOL Format required for %q", ep) + return nil, fmt.Errorf("PORT/PROTOCOL Format required for %q", ep) } exposedPort, err := nat.NewPort(splitp[1], splitp[0]) if err != nil { @@ -587,6 +596,9 @@ func LibpodToContainerJSON(l *libpod.Container, sz bool) (*types.ContainerJSON, if err := json.Unmarshal(n, &networkSettings); err != nil { return nil, err } + + convertSecondaryIPPrefixLen(inspect.NetworkSettings, &networkSettings) + // do not report null instead use an empty map if networkSettings.Networks == nil { networkSettings.Networks = map[string]*network.EndpointSettings{} @@ -616,7 +628,7 @@ func RenameContainer(w http.ResponseWriter, r *http.Request) { Name string `schema:"name"` }{} if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -627,7 +639,7 @@ func RenameContainer(w http.ResponseWriter, r *http.Request) { } if _, err := runtime.RenameContainer(r.Context(), ctr, query.Name); err != nil { - if errors.Cause(err) == define.ErrPodExists || errors.Cause(err) == define.ErrCtrExists { + if errors.Is(err, define.ErrPodExists) || errors.Is(err, define.ErrCtrExists) { utils.Error(w, http.StatusConflict, err) return } diff --git a/pkg/api/handlers/compat/containers_archive.go b/pkg/api/handlers/compat/containers_archive.go index 77fbbe38a..cadfb7bd5 100644 --- a/pkg/api/handlers/compat/containers_archive.go +++ b/pkg/api/handlers/compat/containers_archive.go @@ -2,10 +2,13 @@ package compat import ( "encoding/json" + "fmt" "net/http" "os" "strings" + "errors" + "github.com/containers/podman/v4/libpod" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/api/handlers/utils" @@ -14,7 +17,6 @@ import ( "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/domain/infra/abi" "github.com/gorilla/schema" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -28,7 +30,7 @@ func Archive(w http.ResponseWriter, r *http.Request) { case http.MethodHead, http.MethodGet: handleHeadAndGet(w, r, decoder, runtime) default: - utils.Error(w, http.StatusNotImplemented, errors.Errorf("unsupported method: %v", r.Method)) + utils.Error(w, http.StatusNotImplemented, fmt.Errorf("unsupported method: %v", r.Method)) } } @@ -39,7 +41,7 @@ func handleHeadAndGet(w http.ResponseWriter, r *http.Request, decoder *schema.De err := decoder.Decode(&query, r.URL.Query()) if err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrap(err, "couldn't decode the query")) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("couldn't decode the query: %w", err)) return } @@ -65,7 +67,7 @@ func handleHeadAndGet(w http.ResponseWriter, r *http.Request, decoder *schema.De w.Header().Add(copy.XDockerContainerPathStatHeader, statHeader) } - if errors.Cause(err) == define.ErrNoSuchCtr || errors.Cause(err) == copy.ErrENOENT { + if errors.Is(err, define.ErrNoSuchCtr) || errors.Is(err, copy.ErrENOENT) { // 404 is returned for an absent container and path. The // clients must deal with it accordingly. utils.Error(w, http.StatusNotFound, err) @@ -105,14 +107,14 @@ func handlePut(w http.ResponseWriter, r *http.Request, decoder *schema.Decoder, err := decoder.Decode(&query, r.URL.Query()) if err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrap(err, "couldn't decode the query")) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("couldn't decode the query: %w", err)) return } var rename map[string]string if query.Rename != "" { if err := json.Unmarshal([]byte(query.Rename), &rename); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrap(err, "couldn't decode the query field 'rename'")) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("couldn't decode the query field 'rename': %w", err)) return } } @@ -128,10 +130,10 @@ func handlePut(w http.ResponseWriter, r *http.Request, decoder *schema.Decoder, }) if err != nil { switch { - case errors.Cause(err) == define.ErrNoSuchCtr || os.IsNotExist(err): + case errors.Is(err, define.ErrNoSuchCtr) || os.IsNotExist(err): // 404 is returned for an absent container and path. The // clients must deal with it accordingly. - utils.Error(w, http.StatusNotFound, errors.Wrap(err, "the container doesn't exists")) + utils.Error(w, http.StatusNotFound, fmt.Errorf("the container doesn't exists: %w", err)) case strings.Contains(err.Error(), "copier: put: error creating file"): // Not the best test but need to break this out for compatibility // See vendor/github.com/containers/buildah/copier/copier.go:1585 diff --git a/pkg/api/handlers/compat/containers_create.go b/pkg/api/handlers/compat/containers_create.go index 67ec52047..9fff8b4c8 100644 --- a/pkg/api/handlers/compat/containers_create.go +++ b/pkg/api/handlers/compat/containers_create.go @@ -2,6 +2,7 @@ package compat import ( "encoding/json" + "errors" "fmt" "net" "net/http" @@ -26,7 +27,6 @@ import ( "github.com/containers/storage" "github.com/docker/docker/api/types/mount" "github.com/gorilla/schema" - "github.com/pkg/errors" ) func CreateContainer(w http.ResponseWriter, r *http.Request) { @@ -38,14 +38,14 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) { // override any golang type defaults } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } // compatible configuration body := handlers.CreateContainerConfig{} if err := json.NewDecoder(r.Body).Decode(&body); err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("decode(): %w", err)) return } @@ -53,37 +53,37 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) { body.Name = query.Name if len(body.HostConfig.Links) > 0 { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(utils.ErrLinkNotSupport, "bad parameter")) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("bad parameter: %w", utils.ErrLinkNotSupport)) return } rtc, err := runtime.GetConfig() if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to get runtime config")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("unable to get runtime config: %w", err)) return } imageName, err := utils.NormalizeToDockerHub(r, body.Config.Image) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error normalizing image")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("error normalizing image: %w", err)) return } body.Config.Image = imageName newImage, resolvedName, err := runtime.LibimageRuntime().LookupImage(body.Config.Image, nil) if err != nil { - if errors.Cause(err) == storage.ErrImageUnknown { - utils.Error(w, http.StatusNotFound, errors.Wrap(err, "No such image")) + if errors.Is(err, storage.ErrImageUnknown) { + utils.Error(w, http.StatusNotFound, fmt.Errorf("no such image: %w", err)) return } - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error looking up image")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("error looking up image: %w", err)) return } // Take body structure and convert to cliopts cliOpts, args, err := cliOpts(body, rtc) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "make cli opts()")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("make cli opts(): %w", err)) return } @@ -100,7 +100,7 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) { sg := specgen.NewSpecGenerator(imgNameOrID, cliOpts.RootFS) if err := specgenutil.FillOutSpecGen(sg, cliOpts, args); err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "fill out specgen")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("fill out specgen: %w", err)) return } // moby always create the working directory @@ -109,7 +109,7 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) { ic := abi.ContainerEngine{Libpod: runtime} report, err := ic.ContainerCreate(r.Context(), sg) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "container create")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("container create: %w", err)) return } createResponse := entities.ContainerCreateResponse{ @@ -300,7 +300,7 @@ func cliOpts(cc handlers.CreateContainerConfig, rtc *config.Config) (*entities.C if len(endpoint.IPAddress) > 0 { staticIP := net.ParseIP(endpoint.IPAddress) if staticIP == nil { - return nil, nil, errors.Errorf("failed to parse the ip address %q", endpoint.IPAddress) + return nil, nil, fmt.Errorf("failed to parse the ip address %q", endpoint.IPAddress) } netOpts.StaticIPs = append(netOpts.StaticIPs, staticIP) } @@ -310,7 +310,7 @@ func cliOpts(cc handlers.CreateContainerConfig, rtc *config.Config) (*entities.C if len(endpoint.IPAMConfig.IPv4Address) > 0 { staticIP := net.ParseIP(endpoint.IPAMConfig.IPv4Address) if staticIP == nil { - return nil, nil, errors.Errorf("failed to parse the ipv4 address %q", endpoint.IPAMConfig.IPv4Address) + return nil, nil, fmt.Errorf("failed to parse the ipv4 address %q", endpoint.IPAMConfig.IPv4Address) } netOpts.StaticIPs = append(netOpts.StaticIPs, staticIP) } @@ -318,7 +318,7 @@ func cliOpts(cc handlers.CreateContainerConfig, rtc *config.Config) (*entities.C if len(endpoint.IPAMConfig.IPv6Address) > 0 { staticIP := net.ParseIP(endpoint.IPAMConfig.IPv6Address) if staticIP == nil { - return nil, nil, errors.Errorf("failed to parse the ipv6 address %q", endpoint.IPAMConfig.IPv6Address) + return nil, nil, fmt.Errorf("failed to parse the ipv6 address %q", endpoint.IPAMConfig.IPv6Address) } netOpts.StaticIPs = append(netOpts.StaticIPs, staticIP) } @@ -327,7 +327,7 @@ func cliOpts(cc handlers.CreateContainerConfig, rtc *config.Config) (*entities.C if len(endpoint.MacAddress) > 0 { staticMac, err := net.ParseMAC(endpoint.MacAddress) if err != nil { - return nil, nil, errors.Errorf("failed to parse the mac address %q", endpoint.MacAddress) + return nil, nil, fmt.Errorf("failed to parse the mac address %q", endpoint.MacAddress) } netOpts.StaticMAC = types.HardwareAddr(staticMac) } @@ -433,7 +433,7 @@ func cliOpts(cc handlers.CreateContainerConfig, rtc *config.Config) (*entities.C } if cc.HostConfig.Resources.NanoCPUs > 0 { if cliOpts.CPUPeriod != 0 || cliOpts.CPUQuota != 0 { - return nil, nil, errors.Errorf("NanoCpus conflicts with CpuPeriod and CpuQuota") + return nil, nil, fmt.Errorf("NanoCpus conflicts with CpuPeriod and CpuQuota") } cliOpts.CPUPeriod = 100000 cliOpts.CPUQuota = cc.HostConfig.Resources.NanoCPUs / 10000 @@ -479,7 +479,7 @@ func cliOpts(cc handlers.CreateContainerConfig, rtc *config.Config) (*entities.C } if err := os.MkdirAll(vol, 0o755); err != nil { if !os.IsExist(err) { - return nil, nil, errors.Wrapf(err, "error making volume mountpoint for volume %s", vol) + return nil, nil, fmt.Errorf("error making volume mountpoint for volume %s: %w", vol, err) } } } diff --git a/pkg/api/handlers/compat/containers_restart.go b/pkg/api/handlers/compat/containers_restart.go index ded6480bc..d805b95c2 100644 --- a/pkg/api/handlers/compat/containers_restart.go +++ b/pkg/api/handlers/compat/containers_restart.go @@ -1,6 +1,8 @@ package compat import ( + "errors" + "fmt" "net/http" "github.com/containers/podman/v4/libpod" @@ -10,7 +12,6 @@ import ( "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/domain/infra/abi" "github.com/gorilla/schema" - "github.com/pkg/errors" ) func RestartContainer(w http.ResponseWriter, r *http.Request) { @@ -29,7 +30,7 @@ func RestartContainer(w http.ResponseWriter, r *http.Request) { // override any golang type defaults } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -44,7 +45,7 @@ func RestartContainer(w http.ResponseWriter, r *http.Request) { } report, err := containerEngine.ContainerRestart(r.Context(), []string{name}, options) if err != nil { - if errors.Cause(err) == define.ErrNoSuchCtr { + if errors.Is(err, define.ErrNoSuchCtr) { utils.ContainerNotFound(w, name, err) return } diff --git a/pkg/api/handlers/compat/containers_stop.go b/pkg/api/handlers/compat/containers_stop.go index 1c1fb310c..33bb3a679 100644 --- a/pkg/api/handlers/compat/containers_stop.go +++ b/pkg/api/handlers/compat/containers_stop.go @@ -1,6 +1,8 @@ package compat import ( + "errors" + "fmt" "net/http" "github.com/containers/podman/v4/libpod" @@ -10,7 +12,6 @@ import ( "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/domain/infra/abi" "github.com/gorilla/schema" - "github.com/pkg/errors" ) func StopContainer(w http.ResponseWriter, r *http.Request) { @@ -29,7 +30,7 @@ func StopContainer(w http.ResponseWriter, r *http.Request) { // override any golang type defaults } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -63,7 +64,7 @@ func StopContainer(w http.ResponseWriter, r *http.Request) { } report, err := containerEngine.ContainerStop(r.Context(), []string{name}, options) if err != nil { - if errors.Cause(err) == define.ErrNoSuchCtr { + if errors.Is(err, define.ErrNoSuchCtr) { utils.ContainerNotFound(w, name, err) return } diff --git a/pkg/api/handlers/compat/exec.go b/pkg/api/handlers/compat/exec.go index a8b45c685..1b4dead8b 100644 --- a/pkg/api/handlers/compat/exec.go +++ b/pkg/api/handlers/compat/exec.go @@ -2,9 +2,12 @@ package compat import ( "encoding/json" + "errors" + "fmt" "net/http" "strings" + "github.com/containers/common/pkg/resize" "github.com/containers/podman/v4/libpod" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/api/handlers" @@ -14,7 +17,6 @@ import ( "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/specgenutil" "github.com/gorilla/mux" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -24,7 +26,7 @@ func ExecCreateHandler(w http.ResponseWriter, r *http.Request) { input := new(handlers.ExecCreateConfig) if err := json.NewDecoder(r.Body).Decode(&input); err != nil { - utils.InternalServerError(w, errors.Wrapf(err, "error decoding request body as JSON")) + utils.InternalServerError(w, fmt.Errorf("error decoding request body as JSON: %w", err)) return } @@ -48,7 +50,7 @@ func ExecCreateHandler(w http.ResponseWriter, r *http.Request) { for _, envStr := range input.Env { split := strings.SplitN(envStr, "=", 2) if len(split) != 2 { - utils.Error(w, http.StatusBadRequest, errors.Errorf("environment variable %q badly formed, must be key=value", envStr)) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("environment variable %q badly formed, must be key=value", envStr)) return } libpodConfig.Environment[split[0]] = split[1] @@ -78,14 +80,14 @@ func ExecCreateHandler(w http.ResponseWriter, r *http.Request) { sessID, err := ctr.ExecCreate(libpodConfig) if err != nil { - if errors.Cause(err) == define.ErrCtrStateInvalid { + if errors.Is(err, define.ErrCtrStateInvalid) { // Check if the container is paused. If so, return a 409 state, err := ctr.State() if err == nil { // Ignore the error != nil case. We're already // throwing an InternalServerError below. if state == define.ContainerStatePaused { - utils.Error(w, http.StatusConflict, errors.Errorf("cannot create exec session as container %s is paused", ctr.ID())) + utils.Error(w, http.StatusConflict, fmt.Errorf("cannot create exec session as container %s is paused", ctr.ID())) return } } @@ -112,7 +114,7 @@ func ExecInspectHandler(w http.ResponseWriter, r *http.Request) { session, err := sessionCtr.ExecSession(sessionID) if err != nil { - utils.InternalServerError(w, errors.Wrapf(err, "error retrieving exec session %s from container %s", sessionID, sessionCtr.ID())) + utils.InternalServerError(w, fmt.Errorf("error retrieving exec session %s from container %s: %w", sessionID, sessionCtr.ID(), err)) return } @@ -135,7 +137,7 @@ func ExecStartHandler(w http.ResponseWriter, r *http.Request) { bodyParams := new(handlers.ExecStartConfig) if err := json.NewDecoder(r.Body).Decode(&bodyParams); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to decode parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to decode parameters for %s: %w", r.URL.String(), err)) return } // TODO: Verify TTY setting against what inspect session was made with @@ -154,7 +156,7 @@ func ExecStartHandler(w http.ResponseWriter, r *http.Request) { return } if state != define.ContainerStateRunning { - utils.Error(w, http.StatusConflict, errors.Errorf("cannot exec in a container that is not running; container %s is %s", sessionCtr.ID(), state.String())) + utils.Error(w, http.StatusConflict, fmt.Errorf("cannot exec in a container that is not running; container %s is %s", sessionCtr.ID(), state.String())) return } @@ -172,12 +174,12 @@ func ExecStartHandler(w http.ResponseWriter, r *http.Request) { } logErr := func(e error) { - logrus.Error(errors.Wrapf(e, "error attaching to container %s exec session %s", sessionCtr.ID(), sessionID)) + logrus.Error(fmt.Errorf("error attaching to container %s exec session %s: %w", sessionCtr.ID(), sessionID, e)) } - var size *define.TerminalSize + var size *resize.TerminalSize if bodyParams.Tty && (bodyParams.Height > 0 || bodyParams.Width > 0) { - size = &define.TerminalSize{ + size = &resize.TerminalSize{ Height: bodyParams.Height, Width: bodyParams.Width, } diff --git a/pkg/api/handlers/compat/images.go b/pkg/api/handlers/compat/images.go index 981a38c35..2f8d151d8 100644 --- a/pkg/api/handlers/compat/images.go +++ b/pkg/api/handlers/compat/images.go @@ -2,6 +2,7 @@ package compat import ( "encoding/json" + "errors" "fmt" "io/ioutil" "net/http" @@ -24,7 +25,6 @@ import ( "github.com/containers/storage" "github.com/gorilla/schema" "github.com/opencontainers/go-digest" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -50,7 +50,7 @@ func ExportImage(w http.ResponseWriter, r *http.Request) { tmpfile, err := ioutil.TempFile("", "api.tar") if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("unable to create tempfile: %w", err)) return } defer os.Remove(tmpfile.Name()) @@ -58,7 +58,7 @@ func ExportImage(w http.ResponseWriter, r *http.Request) { name := utils.GetName(r) possiblyNormalizedName, err := utils.NormalizeToDockerHub(r, name) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error normalizing image")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("error normalizing image: %w", err)) return } @@ -70,22 +70,22 @@ func ExportImage(w http.ResponseWriter, r *http.Request) { } if err := imageEngine.Save(r.Context(), possiblyNormalizedName, nil, saveOptions); err != nil { - if errors.Cause(err) == storage.ErrImageUnknown { - utils.ImageNotFound(w, name, errors.Wrapf(err, "failed to find image %s", name)) + if errors.Is(err, storage.ErrImageUnknown) { + utils.ImageNotFound(w, name, fmt.Errorf("failed to find image %s: %w", name, err)) return } - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("unable to create tempfile: %w", err)) return } if err := tmpfile.Close(); err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to close tempfile")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("unable to close tempfile: %w", err)) return } rdr, err := os.Open(tmpfile.Name()) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "failed to read the exported tarfile")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to read the exported tarfile: %w", err)) return } defer rdr.Close() @@ -111,12 +111,12 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) { } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } rtc, err := runtime.GetConfig() if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("Decode(): %w", err)) return } sc := runtime.SystemContext() @@ -132,7 +132,7 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) { input := handlers.CreateContainerConfig{} if err := json.NewDecoder(r.Body).Decode(&input); err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("Decode(): %w", err)) return } @@ -154,7 +154,7 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) { destImage = fmt.Sprintf("%s:%s", query.Repo, query.Tag) possiblyNormalizedName, err := utils.NormalizeToDockerHub(r, destImage) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error normalizing image")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("error normalizing image: %w", err)) return } destImage = possiblyNormalizedName @@ -162,7 +162,7 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) { commitImage, err := ctr.Commit(r.Context(), destImage, options) if err != nil && !strings.Contains(err.Error(), "is not running") { - utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "CommitFailure")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("CommitFailure: %w", err)) return } utils.WriteResponse(w, http.StatusCreated, entities.IDResponse{ID: commitImage.ID()}) @@ -186,7 +186,7 @@ func CreateImageFromSrc(w http.ResponseWriter, r *http.Request) { } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } // fromSrc – Source to import. The value may be a URL from which the image can be retrieved or - to read the image from the request body. This parameter may only be used when importing an image. @@ -194,13 +194,13 @@ func CreateImageFromSrc(w http.ResponseWriter, r *http.Request) { if source == "-" { f, err := ioutil.TempFile("", "api_load.tar") if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "failed to create tempfile")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to create tempfile: %w", err)) return } source = f.Name() if err := SaveFromBody(f, r); err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "failed to write temporary file")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to write temporary file: %w", err)) } } @@ -208,7 +208,7 @@ func CreateImageFromSrc(w http.ResponseWriter, r *http.Request) { if query.Repo != "" { possiblyNormalizedName, err := utils.NormalizeToDockerHub(r, reference) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error normalizing image")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("error normalizing image: %w", err)) return } reference = possiblyNormalizedName @@ -229,7 +229,7 @@ func CreateImageFromSrc(w http.ResponseWriter, r *http.Request) { imageEngine := abi.ImageEngine{Libpod: runtime} report, err := imageEngine.Import(r.Context(), opts) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to import tarball")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("unable to import tarball: %w", err)) return } // Success @@ -265,13 +265,13 @@ func CreateImageFromImage(w http.ResponseWriter, r *http.Request) { // This is where you can override the golang default value for one of fields } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } possiblyNormalizedName, err := utils.NormalizeToDockerHub(r, mergeNameAndTagOrDigest(query.FromImage, query.Tag)) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error normalizing image")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("error normalizing image: %w", err)) return } @@ -388,7 +388,7 @@ func GetImage(w http.ResponseWriter, r *http.Request) { name := utils.GetName(r) possiblyNormalizedName, err := utils.NormalizeToDockerHub(r, name) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error normalizing image")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("error normalizing image: %w", err)) return } @@ -397,12 +397,12 @@ func GetImage(w http.ResponseWriter, r *http.Request) { // Here we need to fiddle with the error message because docker-py is looking for "No // such image" to determine on how to raise the correct exception. errMsg := strings.ReplaceAll(err.Error(), "image not known", "No such image") - utils.Error(w, http.StatusNotFound, errors.Errorf("failed to find image %s: %s", name, errMsg)) + utils.Error(w, http.StatusNotFound, fmt.Errorf("failed to find image %s: %s", name, errMsg)) return } inspect, err := handlers.ImageDataToImageInspect(r.Context(), newImage) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to convert ImageData to ImageInspect '%s'", inspect.ID)) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to convert ImageData to ImageInspect '%s': %w", inspect.ID, err)) return } utils.WriteResponse(w, http.StatusOK, inspect) @@ -421,7 +421,7 @@ func GetImages(w http.ResponseWriter, r *http.Request) { if err := decoder.Decode(&query, r.URL.Query()); err != nil { utils.Error(w, http.StatusBadRequest, - errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } if _, found := r.URL.Query()["digests"]; found && query.Digests { @@ -472,7 +472,7 @@ func LoadImages(w http.ResponseWriter, r *http.Request) { } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -480,7 +480,7 @@ func LoadImages(w http.ResponseWriter, r *http.Request) { // to load. f, err := ioutil.TempFile("", "api_load.tar") if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "failed to create tempfile")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to create tempfile: %w", err)) return } defer func() { @@ -490,7 +490,7 @@ func LoadImages(w http.ResponseWriter, r *http.Request) { } }() if err := SaveFromBody(f, r); err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "failed to write temporary file")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to write temporary file: %w", err)) return } @@ -499,12 +499,12 @@ func LoadImages(w http.ResponseWriter, r *http.Request) { loadOptions := entities.ImageLoadOptions{Input: f.Name()} loadReport, err := imageEngine.Load(r.Context(), loadOptions) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "failed to load image")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to load image: %w", err)) return } if len(loadReport.Names) < 1 { - utils.Error(w, http.StatusInternalServerError, errors.Errorf("one or more images are required")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("one or more images are required")) return } @@ -527,7 +527,7 @@ func ExportImages(w http.ResponseWriter, r *http.Request) { // This is where you can override the golang default value for one of fields } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } if len(query.Names) == 0 { @@ -539,7 +539,7 @@ func ExportImages(w http.ResponseWriter, r *http.Request) { for i, img := range query.Names { possiblyNormalizedName, err := utils.NormalizeToDockerHub(r, img) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error normalizing image")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("error normalizing image: %w", err)) return } images[i] = possiblyNormalizedName @@ -547,12 +547,12 @@ func ExportImages(w http.ResponseWriter, r *http.Request) { tmpfile, err := ioutil.TempFile("", "api.tar") if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("unable to create tempfile: %w", err)) return } defer os.Remove(tmpfile.Name()) if err := tmpfile.Close(); err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to close tempfile")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("unable to close tempfile: %w", err)) return } @@ -566,7 +566,7 @@ func ExportImages(w http.ResponseWriter, r *http.Request) { rdr, err := os.Open(tmpfile.Name()) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "failed to read the exported tarfile")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to read the exported tarfile: %w", err)) return } defer rdr.Close() diff --git a/pkg/api/handlers/compat/images_remove.go b/pkg/api/handlers/compat/images_remove.go index 35bcb36aa..b59bfd0b1 100644 --- a/pkg/api/handlers/compat/images_remove.go +++ b/pkg/api/handlers/compat/images_remove.go @@ -1,6 +1,8 @@ package compat import ( + "errors" + "fmt" "net/http" "github.com/containers/podman/v4/libpod" @@ -10,7 +12,6 @@ import ( "github.com/containers/podman/v4/pkg/domain/infra/abi" "github.com/containers/storage" "github.com/gorilla/schema" - "github.com/pkg/errors" ) func RemoveImage(w http.ResponseWriter, r *http.Request) { @@ -25,7 +26,7 @@ func RemoveImage(w http.ResponseWriter, r *http.Request) { } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } if _, found := r.URL.Query()["noprune"]; found { @@ -36,7 +37,7 @@ func RemoveImage(w http.ResponseWriter, r *http.Request) { name := utils.GetName(r) possiblyNormalizedName, err := utils.NormalizeToDockerHub(r, name) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error normalizing image")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("error normalizing image: %w", err)) return } @@ -48,12 +49,12 @@ func RemoveImage(w http.ResponseWriter, r *http.Request) { report, rmerrors := imageEngine.Remove(r.Context(), []string{possiblyNormalizedName}, options) if len(rmerrors) > 0 && rmerrors[0] != nil { err := rmerrors[0] - if errors.Cause(err) == storage.ErrImageUnknown { - utils.ImageNotFound(w, name, errors.Wrapf(err, "failed to find image %s", name)) + if errors.Is(err, storage.ErrImageUnknown) { + utils.ImageNotFound(w, name, fmt.Errorf("failed to find image %s: %w", name, err)) return } - if errors.Cause(err) == storage.ErrImageUsedByContainer { - utils.Error(w, http.StatusConflict, errors.Wrapf(err, "image %s is in use", name)) + if errors.Is(err, storage.ErrImageUsedByContainer) { + utils.Error(w, http.StatusConflict, fmt.Errorf("image %s is in use: %w", name, err)) return } utils.Error(w, http.StatusInternalServerError, err) diff --git a/pkg/api/handlers/compat/networks.go b/pkg/api/handlers/compat/networks.go index 6fdd5c6a7..65177218a 100644 --- a/pkg/api/handlers/compat/networks.go +++ b/pkg/api/handlers/compat/networks.go @@ -2,6 +2,7 @@ package compat import ( "encoding/json" + "errors" "fmt" "net" "net/http" @@ -19,7 +20,6 @@ import ( dockerNetwork "github.com/docker/docker/api/types/network" "github.com/gorilla/schema" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -36,7 +36,7 @@ func InspectNetwork(w http.ResponseWriter, r *http.Request) { } decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder) if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -133,7 +133,7 @@ func ListNetworks(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime) filterMap, err := util.PrepareFilters(r) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -161,12 +161,13 @@ func ListNetworks(w http.ResponseWriter, r *http.Request) { func CreateNetwork(w http.ResponseWriter, r *http.Request) { var ( - networkCreate types.NetworkCreateRequest - network nettypes.Network + networkCreate types.NetworkCreateRequest + network nettypes.Network + responseWarning string ) runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime) if err := json.NewDecoder(r.Body).Decode(&networkCreate); err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("Decode(): %w", err)) return } @@ -179,8 +180,40 @@ func CreateNetwork(w http.ResponseWriter, r *http.Request) { network.Internal = networkCreate.Internal network.IPv6Enabled = networkCreate.EnableIPv6 - // FIXME use docker options and convert them to valid libpod options - // network.Options = networkCreate.Options + network.Options = make(map[string]string) + + // TODO: we should consider making this constants in c/common/libnetwork/types + for opt, optVal := range networkCreate.Options { + switch opt { + case "mtu": + fallthrough + case "com.docker.network.driver.mtu": + if network.Driver == nettypes.BridgeNetworkDriver { + network.Options["mtu"] = optVal + } + case "icc": + fallthrough + case "com.docker.network.bridge.enable_icc": + // TODO: needs to be implemented + if network.Driver == nettypes.BridgeNetworkDriver { + responseWarning = "com.docker.network.bridge.enable_icc is not currently implemented" + } + case "com.docker.network.bridge.name": + if network.Driver == nettypes.BridgeNetworkDriver { + network.NetworkInterface = optVal + } + case "mode": + if network.Driver == nettypes.MacVLANNetworkDriver || network.Driver == nettypes.IPVLANNetworkDriver { + network.Options[opt] = optVal + } + case "parent": + if network.Driver == nettypes.MacVLANNetworkDriver || network.Driver == nettypes.IPVLANNetworkDriver { + network.NetworkInterface = optVal + } + default: + responseWarning = "\"" + opt + ": " + optVal + "\" is not a recognized option" + } + } // dns is only enabled for the bridge driver if network.Driver == nettypes.BridgeNetworkDriver { @@ -194,7 +227,7 @@ func CreateNetwork(w http.ResponseWriter, r *http.Request) { var err error subnet, err := nettypes.ParseCIDR(conf.Subnet) if err != nil { - utils.InternalServerError(w, errors.Wrap(err, "failed to parse subnet")) + utils.InternalServerError(w, fmt.Errorf("failed to parse subnet: %w", err)) return } s.Subnet = subnet @@ -202,7 +235,7 @@ func CreateNetwork(w http.ResponseWriter, r *http.Request) { if len(conf.Gateway) > 0 { gw := net.ParseIP(conf.Gateway) if gw == nil { - utils.InternalServerError(w, errors.Errorf("failed to parse gateway ip %s", conf.Gateway)) + utils.InternalServerError(w, fmt.Errorf("failed to parse gateway ip %s", conf.Gateway)) return } s.Gateway = gw @@ -210,17 +243,17 @@ func CreateNetwork(w http.ResponseWriter, r *http.Request) { if len(conf.IPRange) > 0 { _, net, err := net.ParseCIDR(conf.IPRange) if err != nil { - utils.InternalServerError(w, errors.Wrap(err, "failed to parse ip range")) + utils.InternalServerError(w, fmt.Errorf("failed to parse ip range: %w", err)) return } startIP, err := netutil.FirstIPInSubnet(net) if err != nil { - utils.InternalServerError(w, errors.Wrap(err, "failed to get first ip in range")) + utils.InternalServerError(w, fmt.Errorf("failed to get first ip in range: %w", err)) return } lastIP, err := netutil.LastIPInSubnet(net) if err != nil { - utils.InternalServerError(w, errors.Wrap(err, "failed to get last ip in range")) + utils.InternalServerError(w, fmt.Errorf("failed to get last ip in range: %w", err)) return } s.LeaseRange = &nettypes.LeaseRange{ @@ -242,9 +275,10 @@ func CreateNetwork(w http.ResponseWriter, r *http.Request) { body := struct { ID string `json:"Id"` - Warning string + Warning string `json:"Warning"` }{ - ID: newNetwork.ID, + ID: newNetwork.ID, + Warning: responseWarning, } utils.WriteResponse(w, http.StatusCreated, body) } @@ -262,7 +296,7 @@ func RemoveNetwork(w http.ResponseWriter, r *http.Request) { decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder) if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -278,12 +312,12 @@ func RemoveNetwork(w http.ResponseWriter, r *http.Request) { return } if len(reports) == 0 { - utils.Error(w, http.StatusInternalServerError, errors.Errorf("internal error")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("internal error")) return } report := reports[0] if report.Err != nil { - if errors.Cause(report.Err) == define.ErrNoSuchNetwork { + if errors.Is(report.Err, define.ErrNoSuchNetwork) { utils.Error(w, http.StatusNotFound, define.ErrNoSuchNetwork) return } @@ -300,7 +334,7 @@ func Connect(w http.ResponseWriter, r *http.Request) { var netConnect types.NetworkConnect if err := json.NewDecoder(r.Body).Decode(&netConnect); err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("Decode(): %w", err)) return } @@ -317,7 +351,7 @@ func Connect(w http.ResponseWriter, r *http.Request) { staticIP := net.ParseIP(netConnect.EndpointConfig.IPAddress) if staticIP == nil { utils.Error(w, http.StatusInternalServerError, - errors.Errorf("failed to parse the ip address %q", netConnect.EndpointConfig.IPAddress)) + fmt.Errorf("failed to parse the ip address %q", netConnect.EndpointConfig.IPAddress)) return } netOpts.StaticIPs = append(netOpts.StaticIPs, staticIP) @@ -329,7 +363,7 @@ func Connect(w http.ResponseWriter, r *http.Request) { staticIP := net.ParseIP(netConnect.EndpointConfig.IPAMConfig.IPv4Address) if staticIP == nil { utils.Error(w, http.StatusInternalServerError, - errors.Errorf("failed to parse the ipv4 address %q", netConnect.EndpointConfig.IPAMConfig.IPv4Address)) + fmt.Errorf("failed to parse the ipv4 address %q", netConnect.EndpointConfig.IPAMConfig.IPv4Address)) return } netOpts.StaticIPs = append(netOpts.StaticIPs, staticIP) @@ -339,7 +373,7 @@ func Connect(w http.ResponseWriter, r *http.Request) { staticIP := net.ParseIP(netConnect.EndpointConfig.IPAMConfig.IPv6Address) if staticIP == nil { utils.Error(w, http.StatusInternalServerError, - errors.Errorf("failed to parse the ipv6 address %q", netConnect.EndpointConfig.IPAMConfig.IPv6Address)) + fmt.Errorf("failed to parse the ipv6 address %q", netConnect.EndpointConfig.IPAMConfig.IPv6Address)) return } netOpts.StaticIPs = append(netOpts.StaticIPs, staticIP) @@ -350,7 +384,7 @@ func Connect(w http.ResponseWriter, r *http.Request) { staticMac, err := net.ParseMAC(netConnect.EndpointConfig.MacAddress) if err != nil { utils.Error(w, http.StatusInternalServerError, - errors.Errorf("failed to parse the mac address %q", netConnect.EndpointConfig.IPAMConfig.IPv6Address)) + fmt.Errorf("failed to parse the mac address %q", netConnect.EndpointConfig.IPAMConfig.IPv6Address)) return } netOpts.StaticMAC = nettypes.HardwareAddr(staticMac) @@ -358,11 +392,11 @@ func Connect(w http.ResponseWriter, r *http.Request) { } err := runtime.ConnectContainerToNetwork(netConnect.Container, name, netOpts) if err != nil { - if errors.Cause(err) == define.ErrNoSuchCtr { + if errors.Is(err, define.ErrNoSuchCtr) { utils.ContainerNotFound(w, netConnect.Container, err) return } - if errors.Cause(err) == define.ErrNoSuchNetwork { + if errors.Is(err, define.ErrNoSuchNetwork) { utils.Error(w, http.StatusNotFound, err) return } @@ -378,18 +412,18 @@ func Disconnect(w http.ResponseWriter, r *http.Request) { var netDisconnect types.NetworkDisconnect if err := json.NewDecoder(r.Body).Decode(&netDisconnect); err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("Decode(): %w", err)) return } name := utils.GetName(r) err := runtime.DisconnectContainerFromNetwork(netDisconnect.Container, name, netDisconnect.Force) if err != nil { - if errors.Cause(err) == define.ErrNoSuchCtr { + if errors.Is(err, define.ErrNoSuchCtr) { utils.Error(w, http.StatusNotFound, err) return } - if errors.Cause(err) == define.ErrNoSuchNetwork { + if errors.Is(err, define.ErrNoSuchNetwork) { utils.Error(w, http.StatusNotFound, err) return } @@ -404,7 +438,7 @@ func Prune(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime) filterMap, err := util.PrepareFilters(r) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("Decode(): %w", err)) return } diff --git a/pkg/api/handlers/compat/resize.go b/pkg/api/handlers/compat/resize.go index ce7340f62..a2caf6e35 100644 --- a/pkg/api/handlers/compat/resize.go +++ b/pkg/api/handlers/compat/resize.go @@ -1,17 +1,18 @@ package compat import ( + "errors" "fmt" "net/http" "strings" + "github.com/containers/common/pkg/resize" "github.com/containers/podman/v4/libpod" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/api/handlers/utils" api "github.com/containers/podman/v4/pkg/api/types" "github.com/gorilla/mux" "github.com/gorilla/schema" - "github.com/pkg/errors" ) func ResizeTTY(w http.ResponseWriter, r *http.Request) { @@ -28,11 +29,11 @@ func ResizeTTY(w http.ResponseWriter, r *http.Request) { } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } - sz := define.TerminalSize{ + sz := resize.TerminalSize{ Width: query.Width, Height: query.Height, } @@ -47,8 +48,8 @@ func ResizeTTY(w http.ResponseWriter, r *http.Request) { return } if err := ctnr.AttachResize(sz); err != nil { - if errors.Cause(err) != define.ErrCtrStateInvalid { - utils.InternalServerError(w, errors.Wrapf(err, "cannot resize container")) + if !errors.Is(err, define.ErrCtrStateInvalid) { + utils.InternalServerError(w, fmt.Errorf("cannot resize container: %w", err)) } else { utils.Error(w, http.StatusConflict, err) } @@ -65,15 +66,15 @@ func ResizeTTY(w http.ResponseWriter, r *http.Request) { return } if state, err := ctnr.State(); err != nil { - utils.InternalServerError(w, errors.Wrapf(err, "cannot obtain session container state")) + utils.InternalServerError(w, fmt.Errorf("cannot obtain session container state: %w", err)) return } else if state != define.ContainerStateRunning && !query.IgnoreNotRunning { utils.Error(w, http.StatusConflict, fmt.Errorf("container %q in wrong state %q", name, state.String())) return } if err := ctnr.ExecResize(name, sz); err != nil { - if errors.Cause(err) != define.ErrExecSessionStateInvalid || !query.IgnoreNotRunning { - utils.InternalServerError(w, errors.Wrapf(err, "cannot resize session")) + if !errors.Is(err, define.ErrExecSessionStateInvalid) || !query.IgnoreNotRunning { + utils.InternalServerError(w, fmt.Errorf("cannot resize session: %w", err)) return } } diff --git a/pkg/api/handlers/compat/secrets.go b/pkg/api/handlers/compat/secrets.go index 5031bf76b..13b3c4e24 100644 --- a/pkg/api/handlers/compat/secrets.go +++ b/pkg/api/handlers/compat/secrets.go @@ -4,7 +4,10 @@ import ( "bytes" "encoding/base64" "encoding/json" + "errors" + "fmt" "net/http" + "strings" "github.com/containers/podman/v4/libpod" "github.com/containers/podman/v4/pkg/api/handlers/utils" @@ -12,14 +15,13 @@ import ( "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/domain/infra/abi" "github.com/containers/podman/v4/pkg/util" - "github.com/pkg/errors" ) func ListSecrets(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime) filtersMap, err := util.PrepareFilters(r) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } ic := abi.ContainerEngine{Libpod: runtime} @@ -106,11 +108,11 @@ func CreateSecret(w http.ResponseWriter, r *http.Request) { }{} if err := json.NewDecoder(r.Body).Decode(&createParams); err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("Decode(): %w", err)) return } if len(createParams.Labels) > 0 { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(errors.New("bad parameter"), "labels not supported")) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("labels not supported: %w", errors.New("bad parameter"))) return } @@ -121,7 +123,7 @@ func CreateSecret(w http.ResponseWriter, r *http.Request) { ic := abi.ContainerEngine{Libpod: runtime} report, err := ic.SecretCreate(r.Context(), createParams.Name, reader, opts) if err != nil { - if errors.Cause(err).Error() == "secret name in use" { + if strings.Contains(err.Error(), "secret name in use") { utils.Error(w, http.StatusConflict, err) return } diff --git a/pkg/api/handlers/compat/volumes.go b/pkg/api/handlers/compat/volumes.go index ff0a7af02..fe6ae36aa 100644 --- a/pkg/api/handlers/compat/volumes.go +++ b/pkg/api/handlers/compat/volumes.go @@ -3,6 +3,8 @@ package compat import ( "bytes" "encoding/json" + "errors" + "fmt" "net/http" "net/url" "time" @@ -18,7 +20,6 @@ import ( docker_api_types "github.com/docker/docker/api/types" docker_api_types_volume "github.com/docker/docker/api/types/volume" "github.com/gorilla/schema" - "github.com/pkg/errors" ) func ListVolumes(w http.ResponseWriter, r *http.Request) { @@ -27,7 +28,7 @@ func ListVolumes(w http.ResponseWriter, r *http.Request) { filtersMap, err := util.PrepareFilters(r) if err != nil { utils.Error(w, http.StatusInternalServerError, - errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -36,7 +37,7 @@ func ListVolumes(w http.ResponseWriter, r *http.Request) { for filter := range *filtersMap { if filter == "opts" { utils.Error(w, http.StatusInternalServerError, - errors.Errorf("unsupported libpod filters passed to docker endpoint")) + fmt.Errorf("unsupported libpod filters passed to docker endpoint")) return } } @@ -86,13 +87,13 @@ func CreateVolume(w http.ResponseWriter, r *http.Request) { query := struct{}{} if err := decoder.Decode(&query, r.URL.Query()); err != nil { utils.Error(w, http.StatusInternalServerError, - errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } // decode params from body input := docker_api_types_volume.VolumeCreateBody{} if err := json.NewDecoder(r.Body).Decode(&input); err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("Decode(): %w", err)) return } @@ -103,7 +104,7 @@ func CreateVolume(w http.ResponseWriter, r *http.Request) { if len(input.Name) != 0 { // See if the volume exists already existingVolume, err = runtime.GetVolume(input.Name) - if err != nil && errors.Cause(err) != define.ErrNoSuchVolume { + if err != nil && !errors.Is(err, define.ErrNoSuchVolume) { utils.InternalServerError(w, err) return } @@ -219,7 +220,7 @@ func RemoveVolume(w http.ResponseWriter, r *http.Request) { if err := decoder.Decode(&query, r.URL.Query()); err != nil { utils.Error(w, http.StatusInternalServerError, - errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -239,7 +240,7 @@ func RemoveVolume(w http.ResponseWriter, r *http.Request) { if err == nil { // As above, we do not pass `force` from the query parameters here if err := runtime.RemoveVolume(r.Context(), vol, false, query.Timeout); err != nil { - if errors.Cause(err) == define.ErrVolumeBeingUsed { + if errors.Is(err, define.ErrVolumeBeingUsed) { utils.Error(w, http.StatusConflict, err) } else { utils.InternalServerError(w, err) @@ -264,14 +265,14 @@ func PruneVolumes(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime) filterMap, err := util.PrepareFilters(r) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("Decode(): %w", err)) return } f := (url.Values)(*filterMap) filterFuncs, err := filters.GeneratePruneVolumeFilters(f) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to parse filters for %s", f.Encode())) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to parse filters for %s: %w", f.Encode(), err)) return } diff --git a/pkg/api/handlers/libpod/containers.go b/pkg/api/handlers/libpod/containers.go index deddcaf93..5d85d4009 100644 --- a/pkg/api/handlers/libpod/containers.go +++ b/pkg/api/handlers/libpod/containers.go @@ -1,6 +1,7 @@ package libpod import ( + "errors" "fmt" "io/ioutil" "net/http" @@ -16,7 +17,6 @@ import ( "github.com/containers/podman/v4/pkg/domain/infra/abi" "github.com/containers/podman/v4/pkg/util" "github.com/gorilla/schema" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -35,7 +35,7 @@ func ContainerExists(w http.ResponseWriter, r *http.Request) { } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -45,7 +45,7 @@ func ContainerExists(w http.ResponseWriter, r *http.Request) { report, err := containerEngine.ContainerExists(r.Context(), name, options) if err != nil { - if errors.Cause(err) == define.ErrNoSuchCtr { + if errors.Is(err, define.ErrNoSuchCtr) { utils.ContainerNotFound(w, name, err) return } @@ -75,12 +75,12 @@ func ListContainers(w http.ResponseWriter, r *http.Request) { filterMap, err := util.PrepareFilters(r) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to decode filter parameters for %s", r.URL.String())) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to decode filter parameters for %s: %w", r.URL.String(), err)) return } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -127,7 +127,7 @@ func GetContainer(w http.ResponseWriter, r *http.Request) { } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime) @@ -221,7 +221,7 @@ func Checkpoint(w http.ResponseWriter, r *http.Request) { } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -307,7 +307,7 @@ func Restore(w http.ResponseWriter, r *http.Request) { // override any golang type defaults } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -344,11 +344,11 @@ func Restore(w http.ResponseWriter, r *http.Request) { ir := abi.ImageEngine{Libpod: runtime} report, err := ir.Exists(r.Context(), name) if err != nil { - utils.Error(w, http.StatusNotFound, errors.Wrapf(err, "failed to find container or checkpoint image %s", name)) + utils.Error(w, http.StatusNotFound, fmt.Errorf("failed to find container or checkpoint image %s: %w", name, err)) return } if !report.Value { - utils.Error(w, http.StatusNotFound, errors.Errorf("failed to find container or checkpoint image %s", name)) + utils.Error(w, http.StatusNotFound, fmt.Errorf("failed to find container or checkpoint image %s", name)) return } } @@ -380,7 +380,7 @@ func InitContainer(w http.ResponseWriter, r *http.Request) { return } err = ctr.Init(r.Context(), ctr.PodID() != "") - if errors.Cause(err) == define.ErrCtrStateInvalid { + if errors.Is(err, define.ErrCtrStateInvalid) { utils.Error(w, http.StatusNotModified, err) return } @@ -400,7 +400,7 @@ func ShouldRestart(w http.ResponseWriter, r *http.Request) { name := utils.GetName(r) report, err := containerEngine.ShouldRestart(r.Context(), name) if err != nil { - if errors.Cause(err) == define.ErrNoSuchCtr { + if errors.Is(err, define.ErrNoSuchCtr) { utils.ContainerNotFound(w, name, err) return } diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go index b71217efa..ed1c65f8e 100644 --- a/pkg/api/handlers/libpod/images.go +++ b/pkg/api/handlers/libpod/images.go @@ -2,6 +2,7 @@ package libpod import ( "context" + "errors" "fmt" "io" "io/ioutil" @@ -29,7 +30,6 @@ import ( utils2 "github.com/containers/podman/v4/utils" "github.com/containers/storage" "github.com/gorilla/schema" - "github.com/pkg/errors" ) // Commit @@ -50,11 +50,11 @@ func ImageExists(w http.ResponseWriter, r *http.Request) { ir := abi.ImageEngine{Libpod: runtime} report, err := ir.Exists(r.Context(), name) if err != nil { - utils.Error(w, http.StatusNotFound, errors.Wrapf(err, "failed to find image %s", name)) + utils.Error(w, http.StatusNotFound, fmt.Errorf("failed to find image %s: %w", name, err)) return } if !report.Value { - utils.Error(w, http.StatusNotFound, errors.Errorf("failed to find image %s", name)) + utils.Error(w, http.StatusNotFound, fmt.Errorf("failed to find image %s", name)) return } utils.WriteResponse(w, http.StatusNoContent, "") @@ -70,18 +70,18 @@ func ImageTree(w http.ResponseWriter, r *http.Request) { WhatRequires: false, } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } ir := abi.ImageEngine{Libpod: runtime} options := entities.ImageTreeOptions{WhatRequires: query.WhatRequires} report, err := ir.Tree(r.Context(), name, options) if err != nil { - if errors.Cause(err) == storage.ErrImageUnknown { - utils.Error(w, http.StatusNotFound, errors.Wrapf(err, "failed to find image %s", name)) + if errors.Is(err, storage.ErrImageUnknown) { + utils.Error(w, http.StatusNotFound, fmt.Errorf("failed to find image %s: %w", name, err)) return } - utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to generate image tree for %s", name)) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to generate image tree for %s: %w", name, err)) return } utils.WriteResponse(w, http.StatusOK, report) @@ -91,13 +91,13 @@ func GetImage(w http.ResponseWriter, r *http.Request) { name := utils.GetName(r) newImage, err := utils.GetImage(r, name) if err != nil { - utils.Error(w, http.StatusNotFound, errors.Wrapf(err, "failed to find image %s", name)) + utils.Error(w, http.StatusNotFound, fmt.Errorf("failed to find image %s: %w", name, err)) return } options := &libimage.InspectOptions{WithParent: true, WithSize: true} inspect, err := newImage.Inspect(r.Context(), options) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed in inspect image %s", inspect.ID)) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed in inspect image %s: %w", inspect.ID, err)) return } utils.WriteResponse(w, http.StatusOK, inspect) @@ -117,15 +117,13 @@ func PruneImages(w http.ResponseWriter, r *http.Request) { filterMap, err := util.PrepareFilters(r) if err != nil { utils.Error(w, http.StatusInternalServerError, - errors. - Wrapf(err, "failed to decode filter parameters for %s", r.URL.String())) + fmt.Errorf("failed to decode filter parameters for %s: %w", r.URL.String(), err)) return } if err := decoder.Decode(&query, r.URL.Query()); err != nil { utils.Error(w, http.StatusInternalServerError, - errors. - Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -174,7 +172,7 @@ func ExportImage(w http.ResponseWriter, r *http.Request) { if err := decoder.Decode(&query, r.URL.Query()); err != nil { utils.Error(w, http.StatusBadRequest, - errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } name := utils.GetName(r) @@ -188,23 +186,23 @@ func ExportImage(w http.ResponseWriter, r *http.Request) { case define.OCIArchive, define.V2s2Archive: tmpfile, err := ioutil.TempFile("", "api.tar") if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("unable to create tempfile: %w", err)) return } output = tmpfile.Name() if err := tmpfile.Close(); err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to close tempfile")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("unable to close tempfile: %w", err)) return } case define.OCIManifestDir, define.V2s2ManifestDir: tmpdir, err := ioutil.TempDir("", "save") if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to create tempdir")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("unable to create tempdir: %w", err)) return } output = tmpdir default: - utils.Error(w, http.StatusInternalServerError, errors.Errorf("unknown format %q", query.Format)) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("unknown format %q", query.Format)) return } @@ -233,7 +231,7 @@ func ExportImage(w http.ResponseWriter, r *http.Request) { } rdr, err := os.Open(output) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "failed to read the exported tarfile")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to read the exported tarfile: %w", err)) return } defer rdr.Close() @@ -254,20 +252,20 @@ func ExportImages(w http.ResponseWriter, r *http.Request) { } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } // References are mandatory! if len(query.References) == 0 { - utils.Error(w, http.StatusBadRequest, errors.New("No references")) + utils.Error(w, http.StatusBadRequest, errors.New("no references")) return } // Format is mandatory! Currently, we only support multi-image docker // archives. if len(query.References) > 1 && query.Format != define.V2s2Archive { - utils.Error(w, http.StatusInternalServerError, errors.Errorf("multi-image archives must use format of %s", define.V2s2Archive)) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("multi-image archives must use format of %s", define.V2s2Archive)) return } @@ -285,23 +283,23 @@ func ExportImages(w http.ResponseWriter, r *http.Request) { case define.V2s2Archive, define.OCIArchive: tmpfile, err := ioutil.TempFile("", "api.tar") if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("unable to create tempfile: %w", err)) return } output = tmpfile.Name() if err := tmpfile.Close(); err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to close tempfile")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("unable to close tempfile: %w", err)) return } case define.OCIManifestDir, define.V2s2ManifestDir: tmpdir, err := ioutil.TempDir("", "save") if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to create tmpdir")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("unable to create tmpdir: %w", err)) return } output = tmpdir default: - utils.Error(w, http.StatusInternalServerError, errors.Errorf("unsupported format %q", query.Format)) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("unsupported format %q", query.Format)) return } defer os.RemoveAll(output) @@ -323,7 +321,7 @@ func ExportImages(w http.ResponseWriter, r *http.Request) { rdr, err := os.Open(output) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "failed to read the exported tarfile")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to read the exported tarfile: %w", err)) return } defer rdr.Close() @@ -335,7 +333,7 @@ func ImagesLoad(w http.ResponseWriter, r *http.Request) { tmpfile, err := ioutil.TempFile("", "libpod-images-load.tar") if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("unable to create tempfile: %w", err)) return } defer os.Remove(tmpfile.Name()) @@ -344,7 +342,7 @@ func ImagesLoad(w http.ResponseWriter, r *http.Request) { tmpfile.Close() if err != nil && err != io.EOF { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to write archive to temporary file")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("unable to write archive to temporary file: %w", err)) return } @@ -353,7 +351,7 @@ func ImagesLoad(w http.ResponseWriter, r *http.Request) { loadOptions := entities.ImageLoadOptions{Input: tmpfile.Name()} loadReport, err := imageEngine.Load(r.Context(), loadOptions) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to load image")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("unable to load image: %w", err)) return } utils.WriteResponse(w, http.StatusOK, loadReport) @@ -375,7 +373,7 @@ func ImagesImport(w http.ResponseWriter, r *http.Request) { } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -384,14 +382,14 @@ func ImagesImport(w http.ResponseWriter, r *http.Request) { if len(query.URL) == 0 { tmpfile, err := ioutil.TempFile("", "libpod-images-import.tar") if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("unable to create tempfile: %w", err)) return } defer os.Remove(tmpfile.Name()) defer tmpfile.Close() if _, err := io.Copy(tmpfile, r.Body); err != nil && err != io.EOF { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to write archive to temporary file")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("unable to write archive to temporary file: %w", err)) return } @@ -411,7 +409,7 @@ func ImagesImport(w http.ResponseWriter, r *http.Request) { } report, err := imageEngine.Import(r.Context(), importOptions) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to import tarball")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("unable to import tarball: %w", err)) return } @@ -433,7 +431,7 @@ func PushImage(w http.ResponseWriter, r *http.Request) { // This is where you can override the golang default value for one of fields } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -479,7 +477,7 @@ func PushImage(w http.ResponseWriter, r *http.Request) { imageEngine := abi.ImageEngine{Libpod: runtime} if err := imageEngine.Push(context.Background(), source, destination, options); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "error pushing image %q", destination)) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("error pushing image %q: %w", destination, err)) return } @@ -509,12 +507,12 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) { } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } rtc, err := runtime.GetConfig() if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "failed to get runtime config")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to get runtime config: %w", err)) return } sc := runtime.SystemContext() @@ -532,7 +530,7 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) { case "docker": mimeType = manifest.DockerV2Schema2MediaType default: - utils.InternalServerError(w, errors.Errorf("unrecognized image format %q", query.Format)) + utils.InternalServerError(w, fmt.Errorf("unrecognized image format %q", query.Format)) return } options.CommitOptions = buildah.CommitOptions{ @@ -561,7 +559,7 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) { } commitImage, err := ctr.Commit(r.Context(), destImage, options) if err != nil && !strings.Contains(err.Error(), "is not running") { - utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "CommitFailure")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("CommitFailure: %w", err)) return } utils.WriteResponse(w, http.StatusOK, entities.IDResponse{ID: commitImage.ID()}) @@ -600,8 +598,8 @@ func UntagImage(w http.ResponseWriter, r *http.Request) { name := utils.GetName(r) if err := imageEngine.Untag(r.Context(), name, tags, opts); err != nil { - if errors.Cause(err) == storage.ErrImageUnknown { - utils.ImageNotFound(w, name, errors.Wrapf(err, "failed to find image %s", name)) + if errors.Is(err, storage.ErrImageUnknown) { + utils.ImageNotFound(w, name, fmt.Errorf("failed to find image %s: %w", name, err)) } else { utils.Error(w, http.StatusInternalServerError, err) } @@ -623,7 +621,7 @@ func ImagesBatchRemove(w http.ResponseWriter, r *http.Request) { }{} if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -647,7 +645,7 @@ func ImagesRemove(w http.ResponseWriter, r *http.Request) { } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -684,7 +682,7 @@ func ImageScp(w http.ResponseWriter, r *http.Request) { // This is where you can override the golang default value for one of fields } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -697,7 +695,7 @@ func ImageScp(w http.ResponseWriter, r *http.Request) { } if source != nil || dest != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(define.ErrInvalidArg, "cannot use the user transfer function on the remote client")) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("cannot use the user transfer function on the remote client: %w", define.ErrInvalidArg)) return } diff --git a/pkg/api/handlers/libpod/networks.go b/pkg/api/handlers/libpod/networks.go index 16f499d4c..7169a6d44 100644 --- a/pkg/api/handlers/libpod/networks.go +++ b/pkg/api/handlers/libpod/networks.go @@ -2,8 +2,11 @@ package libpod import ( "encoding/json" + "fmt" "net/http" + "errors" + "github.com/containers/common/libnetwork/types" "github.com/containers/podman/v4/libpod" "github.com/containers/podman/v4/libpod/define" @@ -13,7 +16,6 @@ import ( "github.com/containers/podman/v4/pkg/domain/infra/abi" "github.com/containers/podman/v4/pkg/util" "github.com/gorilla/schema" - "github.com/pkg/errors" ) func CreateNetwork(w http.ResponseWriter, r *http.Request) { @@ -25,7 +27,7 @@ func CreateNetwork(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime) network := types.Network{} if err := json.NewDecoder(r.Body).Decode(&network); err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "failed to decode request JSON payload")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to decode request JSON payload: %w", err)) return } @@ -52,7 +54,7 @@ func ListNetworks(w http.ResponseWriter, r *http.Request) { filterMap, err := util.PrepareFilters(r) if err != nil { utils.Error(w, http.StatusInternalServerError, - errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -83,7 +85,7 @@ func RemoveNetwork(w http.ResponseWriter, r *http.Request) { } if err := decoder.Decode(&query, r.URL.Query()); err != nil { utils.Error(w, http.StatusInternalServerError, - errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } name := utils.GetName(r) @@ -99,7 +101,7 @@ func RemoveNetwork(w http.ResponseWriter, r *http.Request) { } if reports[0].Err != nil { // If the network cannot be found, we return a 404. - if errors.Cause(reports[0].Err) == define.ErrNoSuchNetwork { + if errors.Is(reports[0].Err, define.ErrNoSuchNetwork) { utils.Error(w, http.StatusNotFound, reports[0].Err) return } @@ -142,18 +144,18 @@ func Connect(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime) var netConnect entities.NetworkConnectOptions if err := json.NewDecoder(r.Body).Decode(&netConnect); err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "failed to decode request JSON payload")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to decode request JSON payload: %w", err)) return } name := utils.GetName(r) err := runtime.ConnectContainerToNetwork(netConnect.Container, name, netConnect.PerNetworkOptions) if err != nil { - if errors.Cause(err) == define.ErrNoSuchCtr { + if errors.Is(err, define.ErrNoSuchCtr) { utils.ContainerNotFound(w, netConnect.Container, err) return } - if errors.Cause(err) == define.ErrNoSuchNetwork { + if errors.Is(err, define.ErrNoSuchNetwork) { utils.Error(w, http.StatusNotFound, err) return } diff --git a/pkg/api/handlers/libpod/pods.go b/pkg/api/handlers/libpod/pods.go index 5b92358fa..8b1d456ec 100644 --- a/pkg/api/handlers/libpod/pods.go +++ b/pkg/api/handlers/libpod/pods.go @@ -2,6 +2,7 @@ package libpod import ( "encoding/json" + "errors" "fmt" "net/http" "strings" @@ -19,7 +20,6 @@ import ( "github.com/containers/podman/v4/pkg/specgenutil" "github.com/containers/podman/v4/pkg/util" "github.com/gorilla/schema" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -33,11 +33,11 @@ func PodCreate(w http.ResponseWriter, r *http.Request) { ) psg := specgen.PodSpecGenerator{InfraContainerSpec: &specgen.SpecGenerator{}} if err := json.NewDecoder(r.Body).Decode(&psg); err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, failedToDecodeSpecgen)) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("%v: %w", failedToDecodeSpecgen, err)) return } if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, failedToDecodeSpecgen)) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("%v: %w", failedToDecodeSpecgen, err)) return } if !psg.NoInfra { @@ -51,17 +51,17 @@ func PodCreate(w http.ResponseWriter, r *http.Request) { } err = specgenutil.FillOutSpecGen(psg.InfraContainerSpec, &infraOptions, []string{}) // necessary for default values in many cases (userns, idmappings) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error filling out specgen")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("error filling out specgen: %w", err)) return } out, err := json.Marshal(psg) // marshal our spec so the matching options can be unmarshaled into infra if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, failedToDecodeSpecgen)) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("%v: %w", failedToDecodeSpecgen, err)) return } err = json.Unmarshal(out, psg.InfraContainerSpec) // unmarhal matching options if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, failedToDecodeSpecgen)) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("%v: %w", failedToDecodeSpecgen, err)) return } // a few extra that do not have the same json tags @@ -75,10 +75,10 @@ func PodCreate(w http.ResponseWriter, r *http.Request) { pod, err := generate.MakePod(&podSpecComplete, runtime) if err != nil { httpCode := http.StatusInternalServerError - if errors.Cause(err) == define.ErrPodExists { + if errors.Is(err, define.ErrPodExists) { httpCode = http.StatusConflict } - utils.Error(w, httpCode, errors.Wrap(err, "failed to make pod")) + utils.Error(w, httpCode, fmt.Errorf("failed to make pod: %w", err)) return } utils.WriteResponse(w, http.StatusCreated, entities.IDResponse{ID: pod.ID()}) @@ -89,7 +89,7 @@ func Pods(w http.ResponseWriter, r *http.Request) { filterMap, err := util.PrepareFilters(r) if err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -139,7 +139,7 @@ func PodStop(w http.ResponseWriter, r *http.Request) { } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } name := utils.GetName(r) @@ -164,7 +164,7 @@ func PodStop(w http.ResponseWriter, r *http.Request) { } else { responses, stopError = pod.Stop(r.Context(), false) } - if stopError != nil && errors.Cause(stopError) != define.ErrPodPartialFail { + if stopError != nil && !errors.Is(stopError, define.ErrPodPartialFail) { utils.Error(w, http.StatusInternalServerError, err) return } @@ -178,7 +178,7 @@ func PodStop(w http.ResponseWriter, r *http.Request) { report := entities.PodStopReport{Id: pod.ID()} for id, err := range responses { - report.Errs = append(report.Errs, errors.Wrapf(err, "error stopping container %s", id)) + report.Errs = append(report.Errs, fmt.Errorf("error stopping container %s: %w", id, err)) } code := http.StatusOK @@ -207,14 +207,14 @@ func PodStart(w http.ResponseWriter, r *http.Request) { } responses, err := pod.Start(r.Context()) - if err != nil && errors.Cause(err) != define.ErrPodPartialFail { + if err != nil && !errors.Is(err, define.ErrPodPartialFail) { utils.Error(w, http.StatusConflict, err) return } report := entities.PodStartReport{Id: pod.ID()} for id, err := range responses { - report.Errs = append(report.Errs, errors.Wrapf(err, "error starting container "+id)) + report.Errs = append(report.Errs, fmt.Errorf("%v: %w", "error starting container "+id, err)) } code := http.StatusOK @@ -237,7 +237,7 @@ func PodDelete(w http.ResponseWriter, r *http.Request) { } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } name := utils.GetName(r) @@ -263,14 +263,14 @@ func PodRestart(w http.ResponseWriter, r *http.Request) { return } responses, err := pod.Restart(r.Context()) - if err != nil && errors.Cause(err) != define.ErrPodPartialFail { + if err != nil && !errors.Is(err, define.ErrPodPartialFail) { utils.Error(w, http.StatusInternalServerError, err) return } report := entities.PodRestartReport{Id: pod.ID()} for id, err := range responses { - report.Errs = append(report.Errs, errors.Wrapf(err, "error restarting container %s", id)) + report.Errs = append(report.Errs, fmt.Errorf("error restarting container %s: %w", id, err)) } code := http.StatusOK @@ -314,14 +314,14 @@ func PodPause(w http.ResponseWriter, r *http.Request) { return } responses, err := pod.Pause(r.Context()) - if err != nil && errors.Cause(err) != define.ErrPodPartialFail { + if err != nil && !errors.Is(err, define.ErrPodPartialFail) { utils.Error(w, http.StatusInternalServerError, err) return } report := entities.PodPauseReport{Id: pod.ID()} for id, v := range responses { - report.Errs = append(report.Errs, errors.Wrapf(v, "error pausing container %s", id)) + report.Errs = append(report.Errs, fmt.Errorf("error pausing container %s: %w", id, v)) } code := http.StatusOK @@ -340,14 +340,14 @@ func PodUnpause(w http.ResponseWriter, r *http.Request) { return } responses, err := pod.Unpause(r.Context()) - if err != nil && errors.Cause(err) != define.ErrPodPartialFail { + if err != nil && !errors.Is(err, define.ErrPodPartialFail) { utils.Error(w, http.StatusInternalServerError, err) return } report := entities.PodUnpauseReport{Id: pod.ID()} for id, v := range responses { - report.Errs = append(report.Errs, errors.Wrapf(v, "error unpausing container %s", id)) + report.Errs = append(report.Errs, fmt.Errorf("error unpausing container %s: %w", id, v)) } code := http.StatusOK @@ -374,7 +374,7 @@ func PodTop(w http.ResponseWriter, r *http.Request) { PsArgs: psArgs, } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -456,7 +456,7 @@ func PodKill(w http.ResponseWriter, r *http.Request) { // override any golang type defaults } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } if _, found := r.URL.Query()["signal"]; found { @@ -465,7 +465,7 @@ func PodKill(w http.ResponseWriter, r *http.Request) { sig, err := util.ParseSignal(signal) if err != nil { - utils.InternalServerError(w, errors.Wrapf(err, "unable to parse signal value")) + utils.InternalServerError(w, fmt.Errorf("unable to parse signal value: %w", err)) return } name := utils.GetName(r) @@ -488,12 +488,12 @@ func PodKill(w http.ResponseWriter, r *http.Request) { } } if !hasRunning { - utils.Error(w, http.StatusConflict, errors.Errorf("cannot kill a pod with no running containers: %s", pod.ID())) + utils.Error(w, http.StatusConflict, fmt.Errorf("cannot kill a pod with no running containers: %s", pod.ID())) return } responses, err := pod.Kill(r.Context(), uint(sig)) - if err != nil && errors.Cause(err) != define.ErrPodPartialFail { + if err != nil && !errors.Is(err, define.ErrPodPartialFail) { utils.Error(w, http.StatusInternalServerError, err) return } @@ -530,11 +530,15 @@ func PodStats(w http.ResponseWriter, r *http.Request) { query := struct { NamesOrIDs []string `schema:"namesOrIDs"` All bool `schema:"all"` + Stream bool `schema:"stream"` + Delay int `schema:"delay"` }{ // default would go here + Delay: 5, + Stream: false, } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -544,21 +548,49 @@ func PodStats(w http.ResponseWriter, r *http.Request) { utils.InternalServerError(w, err) } + var flush = func() {} + if flusher, ok := w.(http.Flusher); ok { + flush = flusher.Flush + } // Collect the stats and send them over the wire. containerEngine := abi.ContainerEngine{Libpod: runtime} reports, err := containerEngine.PodStats(r.Context(), query.NamesOrIDs, options) // Error checks as documented in swagger. - switch errors.Cause(err) { - case define.ErrNoSuchPod: - utils.Error(w, http.StatusNotFound, err) - return - case nil: - // Nothing to do. - default: + if err != nil { + if errors.Is(err, define.ErrNoSuchPod) { + utils.Error(w, http.StatusNotFound, err) + return + } utils.InternalServerError(w, err) return } - utils.WriteResponse(w, http.StatusOK, reports) + w.Header().Set("Content-Type", "application/json") + coder := json.NewEncoder(w) + coder.SetEscapeHTML(true) + + if err := coder.Encode(reports); err != nil { + logrus.Infof("Error from %s %q : %v", r.Method, r.URL, err) + } + flush() + if query.Stream { + for { + select { + case <-r.Context().Done(): + return + default: + time.Sleep(time.Duration(query.Delay) * time.Second) + reports, err = containerEngine.PodStats(r.Context(), query.NamesOrIDs, options) + if err != nil { + return + } + if err := coder.Encode(reports); err != nil { + logrus.Infof("Error from %s %q : %v", r.Method, r.URL, err) + return + } + flush() + } + } + } } diff --git a/pkg/api/handlers/libpod/volumes.go b/pkg/api/handlers/libpod/volumes.go index e792dea35..5eac76f5b 100644 --- a/pkg/api/handlers/libpod/volumes.go +++ b/pkg/api/handlers/libpod/volumes.go @@ -2,9 +2,12 @@ package libpod import ( "encoding/json" + "fmt" "net/http" "net/url" + "errors" + "github.com/containers/podman/v4/libpod" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/api/handlers/utils" @@ -16,7 +19,6 @@ import ( "github.com/containers/podman/v4/pkg/domain/infra/abi/parse" "github.com/containers/podman/v4/pkg/util" "github.com/gorilla/schema" - "github.com/pkg/errors" ) func CreateVolume(w http.ResponseWriter, r *http.Request) { @@ -30,14 +32,14 @@ func CreateVolume(w http.ResponseWriter, r *http.Request) { } if err := decoder.Decode(&query, r.URL.Query()); err != nil { utils.Error(w, http.StatusInternalServerError, - errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } input := entities.VolumeCreateOptions{} // decode params from body if err := json.NewDecoder(r.Body).Decode(&input); err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("Decode(): %w", err)) return } @@ -108,7 +110,7 @@ func ListVolumes(w http.ResponseWriter, r *http.Request) { filterMap, err := util.PrepareFilters(r) if err != nil { utils.Error(w, http.StatusInternalServerError, - errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -181,7 +183,7 @@ func RemoveVolume(w http.ResponseWriter, r *http.Request) { if err := decoder.Decode(&query, r.URL.Query()); err != nil { utils.Error(w, http.StatusInternalServerError, - errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } name := utils.GetName(r) @@ -191,7 +193,7 @@ func RemoveVolume(w http.ResponseWriter, r *http.Request) { return } if err := runtime.RemoveVolume(r.Context(), vol, query.Force, query.Timeout); err != nil { - if errors.Cause(err) == define.ErrVolumeBeingUsed { + if errors.Is(err, define.ErrVolumeBeingUsed) { utils.Error(w, http.StatusConflict, err) return } diff --git a/pkg/api/handlers/utils/containers.go b/pkg/api/handlers/utils/containers.go index 1795f6ce1..80f8522fd 100644 --- a/pkg/api/handlers/utils/containers.go +++ b/pkg/api/handlers/utils/containers.go @@ -2,6 +2,7 @@ package utils import ( "context" + "errors" "fmt" "net/http" "strconv" @@ -19,7 +20,6 @@ import ( "github.com/containers/podman/v4/libpod" "github.com/gorilla/schema" - "github.com/pkg/errors" ) type waitQueryDocker struct { @@ -39,7 +39,7 @@ func WaitContainerDocker(w http.ResponseWriter, r *http.Request) { decoder := ctx.Value(api.DecoderKey).(*schema.Decoder) if err = decoder.Decode(&query, r.URL.Query()); err != nil { - Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -106,7 +106,7 @@ func WaitContainerLibpod(w http.ResponseWriter, r *http.Request) { decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder) query := waitQueryLibpod{} if err := decoder.Decode(&query, r.URL.Query()); err != nil { - Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -130,7 +130,7 @@ func WaitContainerLibpod(w http.ResponseWriter, r *http.Request) { exitCode, err := waitFn(conditions...) if err != nil { - if errors.Cause(err) == define.ErrNoSuchCtr { + if errors.Is(err, define.ErrNoSuchCtr) { ContainerNotFound(w, name, err) return } @@ -197,7 +197,7 @@ var notRunningStates = []define.ContainerStatus{ func waitRemoved(ctrWait containerWaitFn) (int32, error) { code, err := ctrWait(define.ContainerStateUnknown) - if err != nil && errors.Cause(err) == define.ErrNoSuchCtr { + if err != nil && errors.Is(err, define.ErrNoSuchCtr) { return code, nil } return code, err diff --git a/pkg/api/handlers/utils/errors.go b/pkg/api/handlers/utils/errors.go index bf60b2c84..ab1b6f227 100644 --- a/pkg/api/handlers/utils/errors.go +++ b/pkg/api/handlers/utils/errors.go @@ -1,17 +1,18 @@ package utils import ( + "errors" + "fmt" "net/http" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/errorhandling" "github.com/containers/storage" - "github.com/pkg/errors" log "github.com/sirupsen/logrus" ) var ( - ErrLinkNotSupport = errors.New("Link is not supported") + ErrLinkNotSupport = errors.New("link is not supported") ) // TODO: document the exported functions in this file and make them more @@ -25,7 +26,7 @@ func Error(w http.ResponseWriter, code int, err error) { // Log detailed message of what happened to machine running podman service log.Infof("Request Failed(%s): %s", http.StatusText(code), err.Error()) em := errorhandling.ErrorModel{ - Because: (errors.Cause(err)).Error(), + Because: errorhandling.Cause(err).Error(), Message: err.Error(), ResponseCode: code, } @@ -33,51 +34,50 @@ func Error(w http.ResponseWriter, code int, err error) { } func VolumeNotFound(w http.ResponseWriter, name string, err error) { - if errors.Cause(err) != define.ErrNoSuchVolume { + if !errors.Is(err, define.ErrNoSuchVolume) { InternalServerError(w, err) } Error(w, http.StatusNotFound, err) } func ContainerNotFound(w http.ResponseWriter, name string, err error) { - switch errors.Cause(err) { - case define.ErrNoSuchCtr, define.ErrCtrExists: + if errors.Is(err, define.ErrNoSuchCtr) || errors.Is(err, define.ErrCtrExists) { Error(w, http.StatusNotFound, err) - default: + } else { InternalServerError(w, err) } } func ImageNotFound(w http.ResponseWriter, name string, err error) { - if errors.Cause(err) != storage.ErrImageUnknown { + if !errors.Is(err, storage.ErrImageUnknown) { InternalServerError(w, err) } Error(w, http.StatusNotFound, err) } func NetworkNotFound(w http.ResponseWriter, name string, err error) { - if errors.Cause(err) != define.ErrNoSuchNetwork { + if !errors.Is(err, define.ErrNoSuchNetwork) { InternalServerError(w, err) } Error(w, http.StatusNotFound, err) } func PodNotFound(w http.ResponseWriter, name string, err error) { - if errors.Cause(err) != define.ErrNoSuchPod { + if !errors.Is(err, define.ErrNoSuchPod) { InternalServerError(w, err) } Error(w, http.StatusNotFound, err) } func SessionNotFound(w http.ResponseWriter, name string, err error) { - if errors.Cause(err) != define.ErrNoSuchExecSession { + if !errors.Is(err, define.ErrNoSuchExecSession) { InternalServerError(w, err) } Error(w, http.StatusNotFound, err) } func SecretNotFound(w http.ResponseWriter, nameOrID string, err error) { - if errors.Cause(err).Error() != "no such secret" { + if errorhandling.Cause(err).Error() != "no such secret" { InternalServerError(w, err) } Error(w, http.StatusNotFound, err) @@ -92,7 +92,7 @@ func InternalServerError(w http.ResponseWriter, err error) { } func BadRequest(w http.ResponseWriter, key string, value string, err error) { - e := errors.Wrapf(err, "failed to parse query parameter '%s': %q", key, value) + e := fmt.Errorf("failed to parse query parameter '%s': %q: %w", key, value, err) Error(w, http.StatusBadRequest, e) } diff --git a/pkg/api/handlers/utils/images.go b/pkg/api/handlers/utils/images.go index 77f6dcf1d..357fa2990 100644 --- a/pkg/api/handlers/utils/images.go +++ b/pkg/api/handlers/utils/images.go @@ -1,6 +1,7 @@ package utils import ( + "errors" "fmt" "net/http" "strings" @@ -15,7 +16,6 @@ import ( "github.com/containers/podman/v4/pkg/util" "github.com/containers/storage" "github.com/docker/distribution/reference" - "github.com/pkg/errors" ) // NormalizeToDockerHub normalizes the specified nameOrID to Docker Hub if the @@ -32,7 +32,7 @@ func NormalizeToDockerHub(r *http.Request, nameOrID string) (string, error) { // 'busybox' -> 'registry.com/busybox'. img, candidate, err := runtime.LibimageRuntime().LookupImage(nameOrID, nil) if err != nil { - if errors.Cause(err) != storage.ErrImageUnknown { + if !errors.Is(err, storage.ErrImageUnknown) { return "", fmt.Errorf("normalizing name for compat API: %v", err) } // If the image could not be resolved locally, set the @@ -73,7 +73,7 @@ func IsRegistryReference(name string) error { if imageRef.Transport().Name() == docker.Transport.Name() { return nil } - return errors.Errorf("unsupported transport %s in %q: only docker transport is supported", imageRef.Transport().Name(), name) + return fmt.Errorf("unsupported transport %s in %q: only docker transport is supported", imageRef.Transport().Name(), name) } // ParseStorageReference parses the specified image name to a @@ -83,12 +83,12 @@ func ParseStorageReference(name string) (types.ImageReference, error) { storagePrefix := storageTransport.Transport.Name() imageRef, err := alltransports.ParseImageName(name) if err == nil && imageRef.Transport().Name() != docker.Transport.Name() { - return nil, errors.Errorf("reference %q must be a storage reference", name) + return nil, fmt.Errorf("reference %q must be a storage reference", name) } else if err != nil { origErr := err imageRef, err = alltransports.ParseImageName(fmt.Sprintf("%s:%s", storagePrefix, name)) if err != nil { - return nil, errors.Wrapf(origErr, "reference %q must be a storage reference", name) + return nil, fmt.Errorf("reference %q must be a storage reference: %w", name, origErr) } } return imageRef, nil diff --git a/pkg/bindings/containers/attach.go b/pkg/bindings/containers/attach.go index 303fc65bd..2bfccdd3b 100644 --- a/pkg/bindings/containers/attach.go +++ b/pkg/bindings/containers/attach.go @@ -14,9 +14,9 @@ import ( "strconv" "time" + "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/bindings" - "github.com/containers/podman/v4/utils" "github.com/moby/term" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -159,7 +159,7 @@ func Attach(ctx context.Context, nameOrID string, stdin io.Reader, stdout io.Wri go func() { logrus.Debugf("Copying STDIN to socket") - _, err := utils.CopyDetachable(socket, stdin, detachKeysInBytes) + _, err := util.CopyDetachable(socket, stdin, detachKeysInBytes) if err != nil && err != define.ErrDetach { logrus.Errorf("Failed to write input to service: %v", err) } @@ -497,7 +497,7 @@ func ExecStartAndAttach(ctx context.Context, sessionID string, options *ExecStar if options.GetAttachInput() { go func() { logrus.Debugf("Copying STDIN to socket") - _, err := utils.CopyDetachable(socket, options.InputStream, []byte{}) + _, err := util.CopyDetachable(socket, options.InputStream, []byte{}) if err != nil { logrus.Errorf("Failed to write input to service: %v", err) } @@ -518,7 +518,7 @@ func ExecStartAndAttach(ctx context.Context, sessionID string, options *ExecStar return fmt.Errorf("exec session %s has a terminal and must have STDOUT enabled", sessionID) } // If not multiplex'ed, read from server and write to stdout - _, err := utils.CopyDetachable(options.GetOutputStream(), socket, []byte{}) + _, err := util.CopyDetachable(options.GetOutputStream(), socket, []byte{}) if err != nil { return err } diff --git a/pkg/bindings/manifests/manifests.go b/pkg/bindings/manifests/manifests.go index aaa26d7e1..a68dd5a4e 100644 --- a/pkg/bindings/manifests/manifests.go +++ b/pkg/bindings/manifests/manifests.go @@ -231,7 +231,7 @@ func Modify(ctx context.Context, name string, images []string, options *ModifyOp err = errorhandling.JoinErrors(report.Errors) if err != nil { errModel := errorhandling.ErrorModel{ - Because: (errors.Cause(err)).Error(), + Because: errorhandling.Cause(err).Error(), Message: err.Error(), ResponseCode: response.StatusCode, } diff --git a/pkg/domain/filters/containers.go b/pkg/domain/filters/containers.go index e2ab8d70c..f88a165e7 100644 --- a/pkg/domain/filters/containers.go +++ b/pkg/domain/filters/containers.go @@ -1,6 +1,7 @@ package filters import ( + "errors" "fmt" "strconv" "strings" @@ -10,7 +11,6 @@ import ( "github.com/containers/podman/v4/libpod" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/util" - "github.com/pkg/errors" ) // GenerateContainerFilterFuncs return ContainerFilter functions based of filter. @@ -36,7 +36,7 @@ func GenerateContainerFilterFuncs(filter string, filterValues []string, r *libpo for _, exitCode := range filterValues { ec, err := strconv.ParseInt(exitCode, 10, 32) if err != nil { - return nil, errors.Wrapf(err, "exited code out of range %q", ec) + return nil, fmt.Errorf("exited code out of range %q: %w", ec, err) } exitCodes = append(exitCodes, int32(ec)) } @@ -184,7 +184,7 @@ func GenerateContainerFilterFuncs(filter string, filterValues []string, r *libpo for _, podNameOrID := range filterValues { p, err := r.LookupPod(podNameOrID) if err != nil { - if errors.Cause(err) == define.ErrNoSuchPod { + if errors.Is(err, define.ErrNoSuchPod) { continue } return nil, err @@ -291,7 +291,7 @@ func GenerateContainerFilterFuncs(filter string, filterValues []string, r *libpo return false }, filterValueError } - return nil, errors.Errorf("%s is an invalid filter", filter) + return nil, fmt.Errorf("%s is an invalid filter", filter) } // GeneratePruneContainerFilterFuncs return ContainerFilter functions based of filter for prune operation @@ -304,7 +304,7 @@ func GeneratePruneContainerFilterFuncs(filter string, filterValues []string, r * case "until": return prepareUntilFilterFunc(filterValues) } - return nil, errors.Errorf("%s is an invalid filter", filter) + return nil, fmt.Errorf("%s is an invalid filter", filter) } func prepareUntilFilterFunc(filterValues []string) (func(container *libpod.Container) bool, error) { diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go index 281e448f6..1688be57e 100644 --- a/pkg/domain/infra/abi/containers.go +++ b/pkg/domain/infra/abi/containers.go @@ -2,6 +2,7 @@ package abi import ( "context" + "errors" "fmt" "io/ioutil" "os" @@ -32,7 +33,6 @@ import ( "github.com/containers/podman/v4/pkg/specgenutil" "github.com/containers/podman/v4/pkg/util" "github.com/containers/storage" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -80,7 +80,7 @@ func getContainersByContext(all, latest bool, names []string, runtime *libpod.Ru func (ic *ContainerEngine) ContainerExists(ctx context.Context, nameOrID string, options entities.ContainerExistsOptions) (*entities.BoolReport, error) { _, err := ic.Libpod.LookupContainer(nameOrID) if err != nil { - if errors.Cause(err) != define.ErrNoSuchCtr { + if !errors.Is(err, define.ErrNoSuchCtr) { return nil, err } if options.External { @@ -120,7 +120,7 @@ func (ic *ContainerEngine) ContainerPause(ctx context.Context, namesOrIds []stri report := make([]*entities.PauseUnpauseReport, 0, len(ctrs)) for _, c := range ctrs { err := c.Pause() - if err != nil && options.All && errors.Cause(err) == define.ErrCtrStateInvalid { + if err != nil && options.All && errors.Is(err, define.ErrCtrStateInvalid) { logrus.Debugf("Container %s is not running", c.ID()) continue } @@ -137,7 +137,7 @@ func (ic *ContainerEngine) ContainerUnpause(ctx context.Context, namesOrIds []st report := make([]*entities.PauseUnpauseReport, 0, len(ctrs)) for _, c := range ctrs { err := c.Unpause() - if err != nil && options.All && errors.Cause(err) == define.ErrCtrStateInvalid { + if err != nil && options.All && errors.Is(err, define.ErrCtrStateInvalid) { logrus.Debugf("Container %s is not paused", c.ID()) continue } @@ -148,7 +148,7 @@ func (ic *ContainerEngine) ContainerUnpause(ctx context.Context, namesOrIds []st func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []string, options entities.StopOptions) ([]*entities.StopReport, error) { names := namesOrIds ctrs, rawInputs, err := getContainersAndInputByContext(options.All, options.Latest, names, ic.Libpod) - if err != nil && !(options.Ignore && errors.Cause(err) == define.ErrNoSuchCtr) { + if err != nil && !(options.Ignore && errors.Is(err, define.ErrNoSuchCtr)) { return nil, err } ctrMap := map[string]string{} @@ -166,13 +166,13 @@ func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []strin } if err != nil { switch { - case errors.Cause(err) == define.ErrCtrStopped: + case errors.Is(err, define.ErrCtrStopped): logrus.Debugf("Container %s is already stopped", c.ID()) - case options.All && errors.Cause(err) == define.ErrCtrStateInvalid: + case options.All && errors.Is(err, define.ErrCtrStateInvalid): logrus.Debugf("Container %s is not running, could not stop", c.ID()) // container never created in OCI runtime // docker parity: do nothing just return container id - case errors.Cause(err) == define.ErrCtrStateInvalid: + case errors.Is(err, define.ErrCtrStateInvalid): logrus.Debugf("Container %s is either not created on runtime or is in a invalid state", c.ID()) default: return err @@ -238,7 +238,7 @@ func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []strin reports := make([]*entities.KillReport, 0, len(ctrs)) for _, con := range ctrs { err := con.Kill(uint(sig)) - if options.All && errors.Cause(err) == define.ErrCtrStateInvalid { + if options.All && errors.Is(err, define.ErrCtrStateInvalid) { logrus.Debugf("Container %s is not running", con.ID()) continue } @@ -289,8 +289,7 @@ func (ic *ContainerEngine) removeContainer(ctx context.Context, ctr *libpod.Cont return nil } logrus.Debugf("Failed to remove container %s: %s", ctr.ID(), err.Error()) - switch errors.Cause(err) { - case define.ErrNoSuchCtr: + if errors.Is(err, define.ErrNoSuchCtr) { // Ignore if the container does not exist (anymore) when either // it has been requested by the user of if the container is a // service one. Service containers are removed along with its @@ -301,7 +300,7 @@ func (ic *ContainerEngine) removeContainer(ctx context.Context, ctr *libpod.Cont logrus.Debugf("Ignoring error (--allow-missing): %v", err) return nil } - case define.ErrCtrRemoved: + } else if errors.Is(err, define.ErrCtrRemoved) { return nil } return err @@ -317,15 +316,15 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string, for _, ctr := range names { report := reports.RmReport{Id: ctr} report.Err = ic.Libpod.RemoveStorageContainer(ctr, options.Force) - switch errors.Cause(report.Err) { - case nil: + //nolint:gocritic + if report.Err == nil { // remove container names that we successfully deleted rmReports = append(rmReports, &report) - case define.ErrNoSuchCtr, define.ErrCtrExists: + } else if errors.Is(report.Err, define.ErrNoSuchCtr) || errors.Is(report.Err, define.ErrCtrExists) { // There is still a potential this is a libpod container tmpNames = append(tmpNames, ctr) - default: - if _, err := ic.Libpod.LookupContainer(ctr); errors.Cause(err) == define.ErrNoSuchCtr { + } else { + if _, err := ic.Libpod.LookupContainer(ctr); errors.Is(err, define.ErrNoSuchCtr) { // remove container failed, but not a libpod container rmReports = append(rmReports, &report) continue @@ -337,7 +336,7 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string, names = tmpNames ctrs, err := getContainersByContext(options.All, options.Latest, names, ic.Libpod) - if err != nil && !(options.Ignore && errors.Cause(err) == define.ErrNoSuchCtr) { + if err != nil && !(options.Ignore && errors.Is(err, define.ErrNoSuchCtr)) { // Failed to get containers. If force is specified, get the containers ID // and evict them if !options.Force { @@ -349,7 +348,7 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string, report := reports.RmReport{Id: ctr} _, err := ic.Libpod.EvictContainer(ctx, ctr, options.Volumes) if err != nil { - if options.Ignore && errors.Cause(err) == define.ErrNoSuchCtr { + if options.Ignore && errors.Is(err, define.ErrNoSuchCtr) { logrus.Debugf("Ignoring error (--allow-missing): %v", err) rmReports = append(rmReports, &report) continue @@ -426,7 +425,7 @@ func (ic *ContainerEngine) ContainerInspect(ctx context.Context, namesOrIds []st ctr, err := ic.Libpod.GetLatestContainer() if err != nil { if errors.Is(err, define.ErrNoSuchCtr) { - return nil, []error{errors.Wrapf(err, "no containers to inspect")}, nil + return nil, []error{fmt.Errorf("no containers to inspect: %w", err)}, nil } return nil, nil, err } @@ -452,7 +451,7 @@ func (ic *ContainerEngine) ContainerInspect(ctx context.Context, namesOrIds []st // ErrNoSuchCtr is non-fatal, other errors will be // treated as fatal. if errors.Is(err, define.ErrNoSuchCtr) { - errs = append(errs, errors.Errorf("no such container %s", name)) + errs = append(errs, fmt.Errorf("no such container %s", name)) continue } return nil, nil, err @@ -463,7 +462,7 @@ func (ic *ContainerEngine) ContainerInspect(ctx context.Context, namesOrIds []st // ErrNoSuchCtr is non-fatal, other errors will be // treated as fatal. if errors.Is(err, define.ErrNoSuchCtr) { - errs = append(errs, errors.Errorf("no such container %s", name)) + errs = append(errs, fmt.Errorf("no such container %s", name)) continue } return nil, nil, err @@ -487,7 +486,7 @@ func (ic *ContainerEngine) ContainerTop(ctx context.Context, options entities.To container, err = ic.Libpod.LookupContainer(options.NameOrID) } if err != nil { - return nil, errors.Wrap(err, "unable to look up requested container") + return nil, fmt.Errorf("unable to look up requested container: %w", err) } // Run Top. @@ -512,12 +511,12 @@ func (ic *ContainerEngine) ContainerCommit(ctx context.Context, nameOrID string, case "oci": mimeType = buildah.OCIv1ImageManifest if len(options.Message) > 0 { - return nil, errors.Errorf("messages are only compatible with the docker image format (-f docker)") + return nil, fmt.Errorf("messages are only compatible with the docker image format (-f docker)") } case "docker": mimeType = manifest.DockerV2Schema2MediaType default: - return nil, errors.Errorf("unrecognized image format %q", options.Format) + return nil, fmt.Errorf("unrecognized image format %q", options.Format) } sc := ic.Libpod.SystemContext() @@ -660,7 +659,7 @@ func (ic *ContainerEngine) ContainerRestore(ctx context.Context, namesOrIds []st // CRImportCheckpoint is expected to import exactly one container from checkpoint image checkpointImageImportErrors = append( checkpointImageImportErrors, - errors.Errorf("unable to import checkpoint from image: %q: %v", nameOrID, err), + fmt.Errorf("unable to import checkpoint from image: %q: %v", nameOrID, err), ) } else { containers = append(containers, importedContainers[0]) @@ -720,16 +719,16 @@ func (ic *ContainerEngine) ContainerAttach(ctx context.Context, nameOrID string, ctr := ctrs[0] conState, err := ctr.State() if err != nil { - return errors.Wrapf(err, "unable to determine state of %s", ctr.ID()) + return fmt.Errorf("unable to determine state of %s: %w", ctr.ID(), err) } if conState != define.ContainerStateRunning { - return errors.Errorf("you can only attach to running containers") + return fmt.Errorf("you can only attach to running containers") } // If the container is in a pod, also set to recursively start dependencies err = terminal.StartAttachCtr(ctx, ctr, options.Stdout, options.Stderr, options.Stdin, options.DetachKeys, options.SigProxy, false) - if err != nil && errors.Cause(err) != define.ErrDetach { - return errors.Wrapf(err, "error attaching to container %s", ctr.ID()) + if err != nil && !errors.Is(err, define.ErrDetach) { + return fmt.Errorf("error attaching to container %s: %w", ctr.ID(), err) } os.Stdout.WriteString("\n") return nil @@ -751,12 +750,12 @@ func makeExecConfig(options entities.ExecOptions, rt *libpod.Runtime) (*libpod.E storageConfig := rt.StorageConfig() runtimeConfig, err := rt.GetConfig() if err != nil { - return nil, errors.Wrapf(err, "error retrieving Libpod configuration to build exec exit command") + return nil, fmt.Errorf("error retrieving Libpod configuration to build exec exit command: %w", err) } // TODO: Add some ability to toggle syslog exitCommandArgs, err := specgenutil.CreateExitCommandArgs(storageConfig, runtimeConfig, logrus.IsLevelEnabled(logrus.DebugLevel), false, true) if err != nil { - return nil, errors.Wrapf(err, "error constructing exit command for exec session") + return nil, fmt.Errorf("error constructing exit command for exec session: %w", err) } execConfig.ExitCommand = exitCommandArgs @@ -774,7 +773,7 @@ func checkExecPreserveFDs(options entities.ExecOptions) error { for _, e := range entries { i, err := strconv.Atoi(e.Name()) if err != nil { - return errors.Wrapf(err, "cannot parse %s in /proc/self/fd", e.Name()) + return fmt.Errorf("cannot parse %s in /proc/self/fd: %w", e.Name(), err) } m[i] = true } @@ -891,7 +890,7 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri if options.Attach { err = terminal.StartAttachCtr(ctx, ctr, options.Stdout, options.Stderr, options.Stdin, options.DetachKeys, options.SigProxy, !ctrRunning) - if errors.Cause(err) == define.ErrDetach { + if errors.Is(err, define.ErrDetach) { // User manually detached // Exit cleanly immediately reports = append(reports, &entities.ContainerStartReport{ @@ -903,7 +902,7 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri return reports, nil } - if errors.Cause(err) == define.ErrWillDeadlock { + if errors.Is(err, define.ErrWillDeadlock) { logrus.Debugf("Deadlock error: %v", err) reports = append(reports, &entities.ContainerStartReport{ Id: ctr.ID(), @@ -911,7 +910,7 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri Err: err, ExitCode: define.ExitCode(err), }) - return reports, errors.Errorf("attempting to start container %s would cause a deadlock; please run 'podman system renumber' to resolve", ctr.ID()) + return reports, fmt.Errorf("attempting to start container %s would cause a deadlock; please run 'podman system renumber' to resolve", ctr.ID()) } if ctrRunning { @@ -936,7 +935,7 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri logrus.Errorf("Removing container %s: %v", ctr.ID(), err) } } - return reports, errors.Wrapf(err, "unable to start container %s", ctr.ID()) + return reports, fmt.Errorf("unable to start container %s: %w", ctr.ID(), err) } exitCode = ic.GetContainerExitCode(ctx, ctr) @@ -960,12 +959,12 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri } if err := ctr.Start(ctx, true); err != nil { report.Err = err - if errors.Cause(err) == define.ErrWillDeadlock { - report.Err = errors.Wrapf(err, "please run 'podman system renumber' to resolve deadlocks") + if errors.Is(err, define.ErrWillDeadlock) { + report.Err = fmt.Errorf("please run 'podman system renumber' to resolve deadlocks: %w", err) reports = append(reports, report) continue } - report.Err = errors.Wrapf(err, "unable to start container %q", ctr.ID()) + report.Err = fmt.Errorf("unable to start container %q: %w", ctr.ID(), err) reports = append(reports, report) if ctr.AutoRemove() { if err := ic.removeContainer(ctx, ctr, entities.RmOptions{}); err != nil { @@ -1001,7 +1000,7 @@ func (ic *ContainerEngine) Diff(ctx context.Context, namesOrIDs []string, opts e if opts.Latest { ctnr, err := ic.Libpod.GetLatestContainer() if err != nil { - return nil, errors.Wrap(err, "unable to get latest container") + return nil, fmt.Errorf("unable to get latest container: %w", err) } base = ctnr.ID() } @@ -1064,7 +1063,7 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta // We've manually detached from the container // Do not perform cleanup, or wait for container exit code // Just exit immediately - if errors.Cause(err) == define.ErrDetach { + if errors.Is(err, define.ErrDetach) { report.ExitCode = 0 return &report, nil } @@ -1074,10 +1073,10 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta logrus.Debugf("unable to remove container %s after failing to start and attach to it", ctr.ID()) } } - if errors.Cause(err) == define.ErrWillDeadlock { + if errors.Is(err, define.ErrWillDeadlock) { logrus.Debugf("Deadlock error on %q: %v", ctr.ID(), err) report.ExitCode = define.ExitCode(err) - return &report, errors.Errorf("attempting to start container %s would cause a deadlock; please run 'podman system renumber' to resolve", ctr.ID()) + return &report, fmt.Errorf("attempting to start container %s would cause a deadlock; please run 'podman system renumber' to resolve", ctr.ID()) } report.ExitCode = define.ExitCode(err) return &report, err @@ -1086,8 +1085,8 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta if opts.Rm && !ctr.ShouldRestart(ctx) { var timeout *uint if err := ic.Libpod.RemoveContainer(ctx, ctr, false, true, timeout); err != nil { - if errors.Cause(err) == define.ErrNoSuchCtr || - errors.Cause(err) == define.ErrCtrRemoved { + if errors.Is(err, define.ErrNoSuchCtr) || + errors.Is(err, define.ErrCtrRemoved) { logrus.Infof("Container %s was already removed, skipping --rm", ctr.ID()) } else { logrus.Errorf("Removing container %s: %v", ctr.ID(), err) @@ -1180,12 +1179,12 @@ func (ic *ContainerEngine) ContainerCleanup(ctx context.Context, namesOrIds []st var timeout *uint err = ic.Libpod.RemoveContainer(ctx, ctr, false, true, timeout) if err != nil { - report.RmErr = errors.Wrapf(err, "failed to clean up and remove container %v", ctr.ID()) + report.RmErr = fmt.Errorf("failed to clean up and remove container %v: %w", ctr.ID(), err) } } else { err := ctr.Cleanup(ctx) if err != nil { - report.CleanErr = errors.Wrapf(err, "failed to clean up container %v", ctr.ID()) + report.CleanErr = fmt.Errorf("failed to clean up container %v: %w", ctr.ID(), err) } } @@ -1212,7 +1211,7 @@ func (ic *ContainerEngine) ContainerInit(ctx context.Context, namesOrIds []strin err := ctr.Init(ctx, ctr.PodID() != "") // If we're initializing all containers, ignore invalid state errors - if options.All && errors.Cause(err) == define.ErrCtrStateInvalid { + if options.All && errors.Is(err, define.ErrCtrStateInvalid) { err = nil } report.Err = err @@ -1323,7 +1322,7 @@ func (ic *ContainerEngine) ContainerUnmount(ctx context.Context, nameOrIDs []str if mounted { report := entities.ContainerUnmountReport{Id: sctr.ID} if _, report.Err = ic.Libpod.UnmountStorageContainer(sctr.ID, options.Force); report.Err != nil { - if errors.Cause(report.Err) != define.ErrCtrExists { + if !errors.Is(report.Err, define.ErrCtrExists) { reports = append(reports, &report) } } else { @@ -1357,11 +1356,11 @@ func (ic *ContainerEngine) ContainerUnmount(ctx context.Context, nameOrIDs []str report := entities.ContainerUnmountReport{Id: ctr.ID()} if err := ctr.Unmount(options.Force); err != nil { - if options.All && errors.Cause(err) == storage.ErrLayerNotMounted { + if options.All && errors.Is(err, storage.ErrLayerNotMounted) { logrus.Debugf("Error umounting container %s, storage.ErrLayerNotMounted", ctr.ID()) continue } - report.Err = errors.Wrapf(err, "error unmounting container %s", ctr.ID()) + report.Err = fmt.Errorf("error unmounting container %s: %w", ctr.ID(), err) } reports = append(reports, &report) } @@ -1410,7 +1409,7 @@ func (ic *ContainerEngine) Shutdown(_ context.Context) { func (ic *ContainerEngine) ContainerStats(ctx context.Context, namesOrIds []string, options entities.ContainerStatsOptions) (statsChan chan entities.ContainerStatsReport, err error) { if options.Interval < 1 { - return nil, errors.New("Invalid interval, must be a positive number greater zero") + return nil, errors.New("invalid interval, must be a positive number greater zero") } if rootless.IsRootless() { unified, err := cgroups.IsCgroup2UnifiedMode() @@ -1465,19 +1464,18 @@ func (ic *ContainerEngine) ContainerStats(ctx context.Context, namesOrIds []stri computeStats := func() ([]define.ContainerStats, error) { containers, err = containerFunc() if err != nil { - return nil, errors.Wrapf(err, "unable to get list of containers") + return nil, fmt.Errorf("unable to get list of containers: %w", err) } reportStats := []define.ContainerStats{} for _, ctr := range containers { stats, err := ctr.GetContainerStats(containerStats[ctr.ID()]) if err != nil { - cause := errors.Cause(err) - if queryAll && (cause == define.ErrCtrRemoved || cause == define.ErrNoSuchCtr || cause == define.ErrCtrStateInvalid) { + if queryAll && (errors.Is(err, define.ErrCtrRemoved) || errors.Is(err, define.ErrNoSuchCtr) || errors.Is(err, define.ErrCtrStateInvalid)) { continue } - if cause == cgroups.ErrCgroupV1Rootless { - err = cause + if errors.Is(err, cgroups.ErrCgroupV1Rootless) { + err = cgroups.ErrCgroupV1Rootless } return nil, err } diff --git a/pkg/domain/infra/abi/containers_runlabel.go b/pkg/domain/infra/abi/containers_runlabel.go index fac15f72d..463988c87 100644 --- a/pkg/domain/infra/abi/containers_runlabel.go +++ b/pkg/domain/infra/abi/containers_runlabel.go @@ -2,6 +2,7 @@ package abi import ( "context" + "errors" "fmt" "os" "path/filepath" @@ -14,7 +15,6 @@ import ( envLib "github.com/containers/podman/v4/pkg/env" "github.com/containers/podman/v4/utils" "github.com/google/shlex" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -40,7 +40,7 @@ func (ic *ContainerEngine) ContainerRunlabel(ctx context.Context, label string, } if len(pulledImages) != 1 { - return errors.Errorf("internal error: expected an image to be pulled (or an error)") + return errors.New("internal error: expected an image to be pulled (or an error)") } // Extract the runlabel from the image. @@ -57,7 +57,7 @@ func (ic *ContainerEngine) ContainerRunlabel(ctx context.Context, label string, } } if runlabel == "" { - return errors.Errorf("cannot find the value of label: %s in image: %s", label, imageRef) + return fmt.Errorf("cannot find the value of label: %s in image: %s", label, imageRef) } cmd, env, err := generateRunlabelCommand(runlabel, pulledImages[0], imageRef, args, options) @@ -86,7 +86,7 @@ func (ic *ContainerEngine) ContainerRunlabel(ctx context.Context, label string, name := cmd[i+1] ctr, err := ic.Libpod.LookupContainer(name) if err != nil { - if errors.Cause(err) != define.ErrNoSuchCtr { + if !errors.Is(err, define.ErrNoSuchCtr) { logrus.Debugf("Error occurred searching for container %s: %v", name, err) return err } diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go index 02aa5923d..38008c7b9 100644 --- a/pkg/domain/infra/abi/images.go +++ b/pkg/domain/infra/abi/images.go @@ -2,6 +2,7 @@ package abi import ( "context" + "errors" "fmt" "io/fs" "io/ioutil" @@ -34,7 +35,6 @@ import ( dockerRef "github.com/docker/distribution/reference" "github.com/opencontainers/go-digest" imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -128,14 +128,14 @@ func (ir *ImageEngine) History(ctx context.Context, nameOrID string, opts entiti func (ir *ImageEngine) Mount(ctx context.Context, nameOrIDs []string, opts entities.ImageMountOptions) ([]*entities.ImageMountReport, error) { if opts.All && len(nameOrIDs) > 0 { - return nil, errors.Errorf("cannot mix --all with images") + return nil, errors.New("cannot mix --all with images") } if os.Geteuid() != 0 { if driver := ir.Libpod.StorageConfig().GraphDriverName; driver != "vfs" { // Do not allow to mount a graphdriver that is not vfs if we are creating the userns as part // of the mount command. - return nil, errors.Errorf("cannot mount using driver %s in rootless mode", driver) + return nil, fmt.Errorf("cannot mount using driver %s in rootless mode", driver) } became, ret, err := rootless.BecomeRootInUserNS("") @@ -194,7 +194,7 @@ func (ir *ImageEngine) Mount(ctx context.Context, nameOrIDs []string, opts entit func (ir *ImageEngine) Unmount(ctx context.Context, nameOrIDs []string, options entities.ImageUnmountOptions) ([]*entities.ImageUnmountReport, error) { if options.All && len(nameOrIDs) > 0 { - return nil, errors.Errorf("cannot mix --all with images") + return nil, errors.New("cannot mix --all with images") } listImagesOptions := &libimage.ListImagesOptions{} @@ -292,7 +292,7 @@ func (ir *ImageEngine) Push(ctx context.Context, source string, destination stri case "v2s2", "docker": manifestType = manifest.DockerV2Schema2MediaType default: - return errors.Errorf("unknown format %q. Choose on of the supported formats: 'oci', 'v2s1', or 'v2s2'", options.Format) + return fmt.Errorf("unknown format %q. Choose on of the supported formats: 'oci', 'v2s1', or 'v2s2'", options.Format) } pushOptions := &libimage.PushOptions{} @@ -523,12 +523,12 @@ func removeErrorsToExitCode(rmErrors []error) int { } for _, e := range rmErrors { - switch errors.Cause(e) { - case storage.ErrImageUnknown, storage.ErrLayerUnknown: + //nolint:gocritic + if errors.Is(e, storage.ErrImageUnknown) || errors.Is(e, storage.ErrLayerUnknown) { noSuchImageErrors = true - case storage.ErrImageUsedByContainer: + } else if errors.Is(e, storage.ErrImageUsedByContainer) { inUseErrors = true - default: + } else { otherErrors = true } } @@ -590,11 +590,11 @@ func (ir *ImageEngine) Shutdown(_ context.Context) { func (ir *ImageEngine) Sign(ctx context.Context, names []string, options entities.SignOptions) (*entities.SignReport, error) { mech, err := signature.NewGPGSigningMechanism() if err != nil { - return nil, errors.Wrap(err, "error initializing GPG") + return nil, fmt.Errorf("error initializing GPG: %w", err) } defer mech.Close() if err := mech.SupportsSigning(); err != nil { - return nil, errors.Wrap(err, "signing is not supported") + return nil, fmt.Errorf("signing is not supported: %w", err) } sc := ir.Libpod.SystemContext() sc.DockerCertPath = options.CertDir @@ -604,11 +604,11 @@ func (ir *ImageEngine) Sign(ctx context.Context, names []string, options entitie err = func() error { srcRef, err := alltransports.ParseImageName(signimage) if err != nil { - return errors.Wrapf(err, "error parsing image name") + return fmt.Errorf("error parsing image name: %w", err) } rawSource, err := srcRef.NewImageSource(ctx, sc) if err != nil { - return errors.Wrapf(err, "error getting image source") + return fmt.Errorf("error getting image source: %w", err) } defer func() { if err = rawSource.Close(); err != nil { @@ -617,17 +617,17 @@ func (ir *ImageEngine) Sign(ctx context.Context, names []string, options entitie }() topManifestBlob, manifestType, err := rawSource.GetManifest(ctx, nil) if err != nil { - return errors.Wrapf(err, "error getting manifest blob") + return fmt.Errorf("error getting manifest blob: %w", err) } dockerReference := rawSource.Reference().DockerReference() if dockerReference == nil { - return errors.Errorf("cannot determine canonical Docker reference for destination %s", transports.ImageName(rawSource.Reference())) + return fmt.Errorf("cannot determine canonical Docker reference for destination %s", transports.ImageName(rawSource.Reference())) } var sigStoreDir string if options.Directory != "" { repo := reference.Path(dockerReference) if path.Clean(repo) != repo { // Coverage: This should not be reachable because /./ and /../ components are not valid in docker references - return errors.Errorf("Unexpected path elements in Docker reference %s for signature storage", dockerReference.String()) + return fmt.Errorf("unexpected path elements in Docker reference %s for signature storage", dockerReference.String()) } sigStoreDir = filepath.Join(options.Directory, repo) } else { @@ -647,11 +647,11 @@ func (ir *ImageEngine) Sign(ctx context.Context, names []string, options entitie if options.All { if !manifest.MIMETypeIsMultiImage(manifestType) { - return errors.Errorf("%s is not a multi-architecture image (manifest type %s)", signimage, manifestType) + return fmt.Errorf("%s is not a multi-architecture image (manifest type %s)", signimage, manifestType) } list, err := manifest.ListFromBlob(topManifestBlob, manifestType) if err != nil { - return errors.Wrapf(err, "Error parsing manifest list %q", string(topManifestBlob)) + return fmt.Errorf("error parsing manifest list %q: %w", string(topManifestBlob), err) } instanceDigests := list.Instances() for _, instanceDigest := range instanceDigests { @@ -661,13 +661,13 @@ func (ir *ImageEngine) Sign(ctx context.Context, names []string, options entitie return err } if err = putSignature(man, mech, sigStoreDir, instanceDigest, dockerReference, options); err != nil { - return errors.Wrapf(err, "error storing signature for %s, %v", dockerReference.String(), instanceDigest) + return fmt.Errorf("error storing signature for %s, %v: %w", dockerReference.String(), instanceDigest, err) } } return nil } if err = putSignature(topManifestBlob, mech, sigStoreDir, manifestDigest, dockerReference, options); err != nil { - return errors.Wrapf(err, "error storing signature for %s, %v", dockerReference.String(), manifestDigest) + return fmt.Errorf("error storing signature for %s, %v: %w", dockerReference.String(), manifestDigest, err) } return nil }() @@ -694,7 +694,7 @@ func (ir *ImageEngine) Scp(ctx context.Context, src, dst string, parentFlags []s func Transfer(ctx context.Context, source entities.ImageScpOptions, dest entities.ImageScpOptions, parentFlags []string) error { if source.User == "" { - return errors.Wrapf(define.ErrInvalidArg, "you must define a user when transferring from root to rootless storage") + return fmt.Errorf("you must define a user when transferring from root to rootless storage: %w", define.ErrInvalidArg) } podman, err := os.Executable() if err != nil { @@ -881,7 +881,7 @@ func getSigFilename(sigStoreDirPath string) (string, error) { func localPathFromURI(url *url.URL) (string, error) { if url.Scheme != "file" { - return "", errors.Errorf("writing to %s is not supported. Use a supported scheme", url.String()) + return "", fmt.Errorf("writing to %s is not supported. Use a supported scheme", url.String()) } return url.Path, nil } diff --git a/pkg/domain/infra/abi/manifest.go b/pkg/domain/infra/abi/manifest.go index 8b52c335c..d20744d76 100644 --- a/pkg/domain/infra/abi/manifest.go +++ b/pkg/domain/infra/abi/manifest.go @@ -4,9 +4,12 @@ import ( "bytes" "context" "encoding/json" + "fmt" "os" "strings" + "errors" + "github.com/containers/common/libimage" cp "github.com/containers/image/v5/copy" "github.com/containers/image/v5/manifest" @@ -17,7 +20,6 @@ import ( "github.com/containers/storage" "github.com/opencontainers/go-digest" imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -46,7 +48,7 @@ func (ir *ImageEngine) ManifestCreate(ctx context.Context, name string, images [ func (ir *ImageEngine) ManifestExists(ctx context.Context, name string) (*entities.BoolReport, error) { _, err := ir.Libpod.LibimageRuntime().LookupManifestList(name) if err != nil { - if errors.Cause(err) == storage.ErrImageUnknown { + if errors.Is(err, storage.ErrImageUnknown) { return &entities.BoolReport{Value: false}, nil } return nil, err @@ -63,15 +65,13 @@ func (ir *ImageEngine) ManifestInspect(ctx context.Context, name string) ([]byte manifestList, err := ir.Libpod.LibimageRuntime().LookupManifestList(name) if err != nil { - switch errors.Cause(err) { - // Do a remote inspect if there's no local image or if the - // local image is not a manifest list. - case storage.ErrImageUnknown, libimage.ErrNotAManifestList: + if errors.Is(err, storage.ErrImageUnknown) || errors.Is(err, libimage.ErrNotAManifestList) { + // Do a remote inspect if there's no local image or if the + // local image is not a manifest list. return ir.remoteManifestInspect(ctx, name) - - default: - return nil, err } + + return nil, err } schema2List, err := manifestList.Inspect() @@ -86,7 +86,7 @@ func (ir *ImageEngine) ManifestInspect(ctx context.Context, name string) ([]byte var b bytes.Buffer if err := json.Indent(&b, rawSchema2List, "", " "); err != nil { - return nil, errors.Wrapf(err, "error rendering manifest %s for display", name) + return nil, fmt.Errorf("error rendering manifest %s for display: %w", name, err) } return b.Bytes(), nil } @@ -113,8 +113,7 @@ func (ir *ImageEngine) remoteManifestInspect(ctx context.Context, name string) ( // FIXME should we use multierror package instead? // we want the new line here so ignore the linter - //nolint:revive - latestErr = errors.Wrapf(latestErr, "tried %v\n", e) + latestErr = fmt.Errorf("tried %v\n: %w", e, latestErr) } } @@ -125,14 +124,14 @@ func (ir *ImageEngine) remoteManifestInspect(ctx context.Context, name string) ( } src, err := ref.NewImageSource(ctx, sys) if err != nil { - appendErr(errors.Wrapf(err, "reading image %q", transports.ImageName(ref))) + appendErr(fmt.Errorf("reading image %q: %w", transports.ImageName(ref), err)) continue } defer src.Close() manifestBytes, manifestType, err := src.GetManifest(ctx, nil) if err != nil { - appendErr(errors.Wrapf(err, "loading manifest %q", transports.ImageName(ref))) + appendErr(fmt.Errorf("loading manifest %q: %w", transports.ImageName(ref), err)) continue } @@ -150,7 +149,7 @@ func (ir *ImageEngine) remoteManifestInspect(ctx context.Context, name string) ( logrus.Warnf("The manifest type %s is not a manifest list but a single image.", manType) schema2Manifest, err := manifest.Schema2FromManifest(result) if err != nil { - return nil, errors.Wrapf(err, "error parsing manifest blob %q as a %q", string(result), manType) + return nil, fmt.Errorf("error parsing manifest blob %q as a %q: %w", string(result), manType, err) } if result, err = schema2Manifest.Serialize(); err != nil { return nil, err @@ -158,7 +157,7 @@ func (ir *ImageEngine) remoteManifestInspect(ctx context.Context, name string) ( default: listBlob, err := manifest.ListFromBlob(result, manType) if err != nil { - return nil, errors.Wrapf(err, "error parsing manifest blob %q as a %q", string(result), manType) + return nil, fmt.Errorf("error parsing manifest blob %q as a %q: %w", string(result), manType, err) } list, err := listBlob.ConvertToMIMEType(manifest.DockerV2ListMediaType) if err != nil { @@ -170,7 +169,7 @@ func (ir *ImageEngine) remoteManifestInspect(ctx context.Context, name string) ( } if err = json.Indent(&b, result, "", " "); err != nil { - return nil, errors.Wrapf(err, "error rendering manifest %s for display", name) + return nil, fmt.Errorf("error rendering manifest %s for display: %w", name, err) } return b.Bytes(), nil } @@ -213,7 +212,7 @@ func (ir *ImageEngine) ManifestAdd(ctx context.Context, name string, images []st for _, annotationSpec := range opts.Annotation { spec := strings.SplitN(annotationSpec, "=", 2) if len(spec) != 2 { - return "", errors.Errorf("no value given for annotation %q", spec[0]) + return "", fmt.Errorf("no value given for annotation %q", spec[0]) } annotations[spec[0]] = spec[1] } @@ -231,7 +230,7 @@ func (ir *ImageEngine) ManifestAdd(ctx context.Context, name string, images []st func (ir *ImageEngine) ManifestAnnotate(ctx context.Context, name, image string, opts entities.ManifestAnnotateOptions) (string, error) { instanceDigest, err := digest.Parse(image) if err != nil { - return "", errors.Errorf(`invalid image digest "%s": %v`, image, err) + return "", fmt.Errorf(`invalid image digest "%s": %v`, image, err) } manifestList, err := ir.Libpod.LibimageRuntime().LookupManifestList(name) @@ -251,7 +250,7 @@ func (ir *ImageEngine) ManifestAnnotate(ctx context.Context, name, image string, for _, annotationSpec := range opts.Annotation { spec := strings.SplitN(annotationSpec, "=", 2) if len(spec) != 2 { - return "", errors.Errorf("no value given for annotation %q", spec[0]) + return "", fmt.Errorf("no value given for annotation %q", spec[0]) } annotations[spec[0]] = spec[1] } @@ -269,7 +268,7 @@ func (ir *ImageEngine) ManifestAnnotate(ctx context.Context, name, image string, func (ir *ImageEngine) ManifestRemoveDigest(ctx context.Context, name, image string) (string, error) { instanceDigest, err := digest.Parse(image) if err != nil { - return "", errors.Errorf(`invalid image digest "%s": %v`, image, err) + return "", fmt.Errorf(`invalid image digest "%s": %v`, image, err) } manifestList, err := ir.Libpod.LibimageRuntime().LookupManifestList(name) @@ -293,7 +292,7 @@ func (ir *ImageEngine) ManifestRm(ctx context.Context, names []string) (report * func (ir *ImageEngine) ManifestPush(ctx context.Context, name, destination string, opts entities.ImagePushOptions) (string, error) { manifestList, err := ir.Libpod.LibimageRuntime().LookupManifestList(name) if err != nil { - return "", errors.Wrapf(err, "error retrieving local image from image name %s", name) + return "", fmt.Errorf("error retrieving local image from image name %s: %w", name, err) } var manifestType string @@ -304,7 +303,7 @@ func (ir *ImageEngine) ManifestPush(ctx context.Context, name, destination strin case "v2s2", "docker": manifestType = manifest.DockerV2Schema2MediaType default: - return "", errors.Errorf("unknown format %q. Choose one of the supported formats: 'oci' or 'v2s2'", opts.Format) + return "", fmt.Errorf("unknown format %q. Choose one of the supported formats: 'oci' or 'v2s2'", opts.Format) } } @@ -333,7 +332,7 @@ func (ir *ImageEngine) ManifestPush(ctx context.Context, name, destination strin if opts.Rm { if _, rmErrors := ir.Libpod.LibimageRuntime().RemoveImages(ctx, []string{manifestList.ID()}, nil); len(rmErrors) > 0 { - return "", errors.Wrap(rmErrors[0], "error removing manifest after push") + return "", fmt.Errorf("error removing manifest after push: %w", rmErrors[0]) } } diff --git a/pkg/domain/infra/abi/network.go b/pkg/domain/infra/abi/network.go index 8b95607f4..2428abfe9 100644 --- a/pkg/domain/infra/abi/network.go +++ b/pkg/domain/infra/abi/network.go @@ -2,6 +2,8 @@ package abi import ( "context" + "errors" + "fmt" "strconv" "github.com/containers/common/libnetwork/types" @@ -9,7 +11,6 @@ import ( "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/domain/entities" - "github.com/pkg/errors" ) func (ic *ContainerEngine) NetworkList(ctx context.Context, options entities.NetworkListOptions) ([]types.Network, error) { @@ -20,16 +21,16 @@ func (ic *ContainerEngine) NetworkList(ctx context.Context, options entities.Net if filterDangling { switch len(val) { case 0: - return nil, errors.Errorf("got no values for filter key \"dangling\"") + return nil, fmt.Errorf("got no values for filter key \"dangling\"") case 1: var err error wantDangling, err = strconv.ParseBool(val[0]) if err != nil { - return nil, errors.Errorf("invalid dangling filter value \"%v\"", val[0]) + return nil, fmt.Errorf("invalid dangling filter value \"%v\"", val[0]) } delete(options.Filters, "dangling") default: - return nil, errors.Errorf("got more than one value for filter key \"dangling\"") + return nil, fmt.Errorf("got more than one value for filter key \"dangling\"") } } @@ -56,11 +57,11 @@ func (ic *ContainerEngine) NetworkInspect(ctx context.Context, namesOrIds []stri for _, name := range namesOrIds { net, err := ic.Libpod.Network().NetworkInspect(name) if err != nil { - if errors.Cause(err) == define.ErrNoSuchNetwork { - errs = append(errs, errors.Wrapf(err, "network %s", name)) + if errors.Is(err, define.ErrNoSuchNetwork) { + errs = append(errs, fmt.Errorf("network %s: %w", name, err)) continue } else { - return nil, nil, errors.Wrapf(err, "error inspecting network %s", name) + return nil, nil, fmt.Errorf("error inspecting network %s: %w", name, err) } } networks = append(networks, net) @@ -80,8 +81,8 @@ func (ic *ContainerEngine) NetworkReload(ctx context.Context, names []string, op report.Id = ctr.ID() report.Err = ctr.ReloadNetwork() // ignore errors for invalid ctr state and network mode when --all is used - if options.All && (errors.Cause(report.Err) == define.ErrCtrStateInvalid || - errors.Cause(report.Err) == define.ErrNetworkModeInvalid) { + if options.All && (errors.Is(report.Err, define.ErrCtrStateInvalid) || + errors.Is(report.Err, define.ErrNetworkModeInvalid)) { continue } reports = append(reports, report) @@ -113,7 +114,7 @@ func (ic *ContainerEngine) NetworkRm(ctx context.Context, namesOrIds []string, o // if user passes force, we nuke containers and pods if !options.Force { // Without the force option, we return an error - return reports, errors.Wrapf(define.ErrNetworkInUse, "%q has associated containers with it. Use -f to forcibly delete containers and pods", name) + return reports, fmt.Errorf("%q has associated containers with it. Use -f to forcibly delete containers and pods: %w", name, define.ErrNetworkInUse) } if c.IsInfra() { // if we have a infra container we need to remove the pod @@ -124,7 +125,7 @@ func (ic *ContainerEngine) NetworkRm(ctx context.Context, namesOrIds []string, o if err := ic.Libpod.RemovePod(ctx, pod, true, true, options.Timeout); err != nil { return reports, err } - } else if err := ic.Libpod.RemoveContainer(ctx, c, true, true, options.Timeout); err != nil && errors.Cause(err) != define.ErrNoSuchCtr { + } else if err := ic.Libpod.RemoveContainer(ctx, c, true, true, options.Timeout); err != nil && !errors.Is(err, define.ErrNoSuchCtr) { return reports, err } } @@ -139,7 +140,7 @@ func (ic *ContainerEngine) NetworkRm(ctx context.Context, namesOrIds []string, o func (ic *ContainerEngine) NetworkCreate(ctx context.Context, network types.Network) (*types.Network, error) { if util.StringInSlice(network.Name, []string{"none", "host", "bridge", "private", "slirp4netns", "container", "ns"}) { - return nil, errors.Errorf("cannot create network with name %q because it conflicts with a valid network mode", network.Name) + return nil, fmt.Errorf("cannot create network with name %q because it conflicts with a valid network mode", network.Name) } network, err := ic.Libpod.Network().NetworkCreate(network) if err != nil { diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go index e14a819fa..c913fdb69 100644 --- a/pkg/domain/infra/abi/play.go +++ b/pkg/domain/infra/abi/play.go @@ -3,6 +3,7 @@ package abi import ( "bytes" "context" + "errors" "fmt" "io" "io/ioutil" @@ -29,7 +30,6 @@ import ( "github.com/containers/podman/v4/pkg/util" "github.com/ghodss/yaml" "github.com/opencontainers/go-digest" - "github.com/pkg/errors" "github.com/sirupsen/logrus" yamlv3 "gopkg.in/yaml.v3" ) @@ -114,7 +114,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, options // sort kube kinds documentList, err = sortKubeKinds(documentList) if err != nil { - return nil, errors.Wrap(err, "unable to sort kube kinds") + return nil, fmt.Errorf("unable to sort kube kinds: %w", err) } ipIndex := 0 @@ -126,7 +126,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, options for _, document := range documentList { kind, err := getKubeKind(document) if err != nil { - return nil, errors.Wrap(err, "unable to read kube YAML") + return nil, fmt.Errorf("unable to read kube YAML: %w", err) } // TODO: create constants for the various "kinds" of yaml files. @@ -154,14 +154,14 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, options var podTemplateSpec v1.PodTemplateSpec if err := yaml.Unmarshal(document, &podYAML); err != nil { - return nil, errors.Wrap(err, "unable to read YAML as Kube Pod") + return nil, fmt.Errorf("unable to read YAML as Kube Pod: %w", err) } podTemplateSpec.ObjectMeta = podYAML.ObjectMeta podTemplateSpec.Spec = podYAML.Spec for name, val := range podYAML.Annotations { if len(val) > define.MaxKubeAnnotation { - return nil, errors.Errorf("invalid annotation %q=%q value length exceeds Kubernetetes max %d", name, val, define.MaxKubeAnnotation) + return nil, fmt.Errorf("invalid annotation %q=%q value length exceeds Kubernetetes max %d", name, val, define.MaxKubeAnnotation) } } for name, val := range options.Annotations { @@ -182,7 +182,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, options var deploymentYAML v1apps.Deployment if err := yaml.Unmarshal(document, &deploymentYAML); err != nil { - return nil, errors.Wrap(err, "unable to read YAML as Kube Deployment") + return nil, fmt.Errorf("unable to read YAML as Kube Deployment: %w", err) } r, err := ic.playKubeDeployment(ctx, &deploymentYAML, options, &ipIndex, configMaps, serviceContainer) @@ -196,7 +196,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, options var pvcYAML v1.PersistentVolumeClaim if err := yaml.Unmarshal(document, &pvcYAML); err != nil { - return nil, errors.Wrap(err, "unable to read YAML as Kube PersistentVolumeClaim") + return nil, fmt.Errorf("unable to read YAML as Kube PersistentVolumeClaim: %w", err) } r, err := ic.playKubePVC(ctx, &pvcYAML) @@ -210,7 +210,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, options var configMap v1.ConfigMap if err := yaml.Unmarshal(document, &configMap); err != nil { - return nil, errors.Wrap(err, "unable to read YAML as Kube ConfigMap") + return nil, fmt.Errorf("unable to read YAML as Kube ConfigMap: %w", err) } configMaps = append(configMaps, configMap) default: @@ -240,7 +240,7 @@ func (ic *ContainerEngine) playKubeDeployment(ctx context.Context, deploymentYAM deploymentName = deploymentYAML.ObjectMeta.Name if deploymentName == "" { - return nil, errors.Errorf("Deployment does not have a name") + return nil, errors.New("deployment does not have a name") } numReplicas = 1 if deploymentYAML.Spec.Replicas != nil { @@ -253,7 +253,7 @@ func (ic *ContainerEngine) playKubeDeployment(ctx context.Context, deploymentYAM podName := fmt.Sprintf("%s-pod-%d", deploymentName, i) podReport, err := ic.playKubePod(ctx, podName, &podSpec, options, ipIndex, deploymentYAML.Annotations, configMaps, serviceContainer) if err != nil { - return nil, errors.Wrapf(err, "error encountered while bringing up pod %s", podName) + return nil, fmt.Errorf("error encountered while bringing up pod %s: %w", podName, err) } report.Pods = append(report.Pods, podReport.Pods...) } @@ -275,7 +275,7 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY // Assert the pod has a name if podName == "" { - return nil, errors.Errorf("pod does not have a name") + return nil, fmt.Errorf("pod does not have a name") } podOpt := entities.PodCreateOptions{ @@ -295,7 +295,7 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY } if (ns.IsBridge() && len(networks) == 0) || ns.IsHost() { - return nil, errors.Errorf("invalid value passed to --network: bridge or host networking must be configured in YAML") + return nil, fmt.Errorf("invalid value passed to --network: bridge or host networking must be configured in YAML") } podOpt.Net.Network = ns @@ -316,10 +316,10 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY // FIXME This is very hard to support properly with a good ux if len(options.StaticIPs) > *ipIndex { if !podOpt.Net.Network.IsBridge() { - return nil, errors.Wrap(define.ErrInvalidArg, "static ip addresses can only be set when the network mode is bridge") + return nil, fmt.Errorf("static ip addresses can only be set when the network mode is bridge: %w", define.ErrInvalidArg) } if len(podOpt.Net.Networks) != 1 { - return nil, errors.Wrap(define.ErrInvalidArg, "cannot set static ip addresses for more than network, use netname:ip=<ip> syntax to specify ips for more than network") + return nil, fmt.Errorf("cannot set static ip addresses for more than network, use netname:ip=<ip> syntax to specify ips for more than network: %w", define.ErrInvalidArg) } for name, netOpts := range podOpt.Net.Networks { netOpts.StaticIPs = append(netOpts.StaticIPs, options.StaticIPs[*ipIndex]) @@ -331,10 +331,10 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY } if len(options.StaticMACs) > *ipIndex { if !podOpt.Net.Network.IsBridge() { - return nil, errors.Wrap(define.ErrInvalidArg, "static mac address can only be set when the network mode is bridge") + return nil, fmt.Errorf("static mac address can only be set when the network mode is bridge: %w", define.ErrInvalidArg) } if len(podOpt.Net.Networks) != 1 { - return nil, errors.Wrap(define.ErrInvalidArg, "cannot set static mac address for more than network, use netname:mac=<mac> syntax to specify mac for more than network") + return nil, fmt.Errorf("cannot set static mac address for more than network, use netname:mac=<mac> syntax to specify mac for more than network: %w", define.ErrInvalidArg) } for name, netOpts := range podOpt.Net.Networks { netOpts.StaticMAC = nettypes.HardwareAddr(options.StaticMACs[*ipIndex]) @@ -370,11 +370,11 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY cm, err := readConfigMapFromFile(f) if err != nil { - return nil, errors.Wrapf(err, "%q", p) + return nil, fmt.Errorf("%q: %w", p, err) } if _, present := configMapIndex[cm.Name]; present { - return nil, errors.Errorf("ambiguous configuration: the same config map %s is present in YAML and in --configmaps %s file", cm.Name, p) + return nil, fmt.Errorf("ambiguous configuration: the same config map %s is present in YAML and in --configmaps %s file", cm.Name, p) } configMaps = append(configMaps, cm) @@ -396,22 +396,22 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY // error out instead reuse the current volume. vol, err = ic.Libpod.GetVolume(v.Source) if err != nil { - return nil, errors.Wrapf(err, "cannot re-use local volume for volume from configmap %q", v.Source) + return nil, fmt.Errorf("cannot re-use local volume for volume from configmap %q: %w", v.Source, err) } } else { - return nil, errors.Wrapf(err, "cannot create a local volume for volume from configmap %q", v.Source) + return nil, fmt.Errorf("cannot create a local volume for volume from configmap %q: %w", v.Source, err) } } mountPoint, err := vol.MountPoint() if err != nil || mountPoint == "" { - return nil, errors.Wrapf(err, "unable to get mountpoint of volume %q", vol.Name()) + return nil, fmt.Errorf("unable to get mountpoint of volume %q: %w", vol.Name(), err) } // Create files and add data to the volume mountpoint based on the Items in the volume for k, v := range v.Items { dataPath := filepath.Join(mountPoint, k) f, err := os.Create(dataPath) if err != nil { - return nil, errors.Wrapf(err, "cannot create file %q at volume mountpoint %q", k, mountPoint) + return nil, fmt.Errorf("cannot create file %q at volume mountpoint %q: %w", k, mountPoint, err) } defer f.Close() _, err = f.WriteString(v) @@ -492,12 +492,12 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY for _, initCtr := range podYAML.Spec.InitContainers { // Error out if same name is used for more than one container if _, ok := ctrNames[initCtr.Name]; ok { - return nil, errors.Errorf("the pod %q is invalid; duplicate container name %q detected", podName, initCtr.Name) + return nil, fmt.Errorf("the pod %q is invalid; duplicate container name %q detected", podName, initCtr.Name) } ctrNames[initCtr.Name] = "" // Init containers cannot have either of lifecycle, livenessProbe, readinessProbe, or startupProbe set if initCtr.Lifecycle != nil || initCtr.LivenessProbe != nil || initCtr.ReadinessProbe != nil || initCtr.StartupProbe != nil { - return nil, errors.Errorf("cannot create an init container that has either of lifecycle, livenessProbe, readinessProbe, or startupProbe set") + return nil, fmt.Errorf("cannot create an init container that has either of lifecycle, livenessProbe, readinessProbe, or startupProbe set") } pulledImage, labels, err := ic.getImageAndLabelInfo(ctx, cwd, annotations, writer, initCtr, options) if err != nil { @@ -548,7 +548,7 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY for _, container := range podYAML.Spec.Containers { // Error out if the same name is used for more than one container if _, ok := ctrNames[container.Name]; ok { - return nil, errors.Errorf("the pod %q is invalid; duplicate container name %q detected", podName, container.Name) + return nil, fmt.Errorf("the pod %q is invalid; duplicate container name %q detected", podName, container.Name) } ctrNames[container.Name] = "" pulledImage, labels, err := ic.getImageAndLabelInfo(ctx, cwd, annotations, writer, container, options) @@ -599,11 +599,11 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY if options.Start != types.OptionalBoolFalse { // Start the containers podStartErrors, err := pod.Start(ctx) - if err != nil && errors.Cause(err) != define.ErrPodPartialFail { + if err != nil && !errors.Is(err, define.ErrPodPartialFail) { return nil, err } for id, err := range podStartErrors { - playKubePod.ContainerErrors = append(playKubePod.ContainerErrors, errors.Wrapf(err, "error starting container %s", id).Error()) + playKubePod.ContainerErrors = append(playKubePod.ContainerErrors, fmt.Errorf("error starting container %s: %w", id, err).Error()) fmt.Println(playKubePod.ContainerErrors) } } @@ -735,14 +735,14 @@ func (ic *ContainerEngine) playKubePVC(ctx context.Context, pvcYAML *v1.Persiste case util.VolumeUIDAnnotation: uid, err := strconv.Atoi(v) if err != nil { - return nil, errors.Wrapf(err, "cannot convert uid %s to integer", v) + return nil, fmt.Errorf("cannot convert uid %s to integer: %w", v, err) } volOptions = append(volOptions, libpod.WithVolumeUID(uid)) opts["UID"] = v case util.VolumeGIDAnnotation: gid, err := strconv.Atoi(v) if err != nil { - return nil, errors.Wrapf(err, "cannot convert gid %s to integer", v) + return nil, fmt.Errorf("cannot convert gid %s to integer: %w", v, err) } volOptions = append(volOptions, libpod.WithVolumeGID(gid)) opts["GID"] = v @@ -771,15 +771,15 @@ func readConfigMapFromFile(r io.Reader) (v1.ConfigMap, error) { content, err := ioutil.ReadAll(r) if err != nil { - return cm, errors.Wrapf(err, "unable to read ConfigMap YAML content") + return cm, fmt.Errorf("unable to read ConfigMap YAML content: %w", err) } if err := yaml.Unmarshal(content, &cm); err != nil { - return cm, errors.Wrapf(err, "unable to read YAML as Kube ConfigMap") + return cm, fmt.Errorf("unable to read YAML as Kube ConfigMap: %w", err) } if cm.Kind != "ConfigMap" { - return cm, errors.Errorf("invalid YAML kind: %q. [ConfigMap] is the only supported by --configmap", cm.Kind) + return cm, fmt.Errorf("invalid YAML kind: %q. [ConfigMap] is the only supported by --configmap", cm.Kind) } return cm, nil @@ -799,14 +799,14 @@ func splitMultiDocYAML(yamlContent []byte) ([][]byte, error) { break } if err != nil { - return nil, errors.Wrapf(err, "multi doc yaml could not be split") + return nil, fmt.Errorf("multi doc yaml could not be split: %w", err) } if o != nil { // back to bytes document, err := yamlv3.Marshal(o) if err != nil { - return nil, errors.Wrapf(err, "individual doc yaml could not be marshalled") + return nil, fmt.Errorf("individual doc yaml could not be marshalled: %w", err) } documentList = append(documentList, document) @@ -915,27 +915,27 @@ func (ic *ContainerEngine) PlayKubeDown(ctx context.Context, body io.Reader, _ e // sort kube kinds documentList, err = sortKubeKinds(documentList) if err != nil { - return nil, errors.Wrap(err, "unable to sort kube kinds") + return nil, fmt.Errorf("unable to sort kube kinds: %w", err) } for _, document := range documentList { kind, err := getKubeKind(document) if err != nil { - return nil, errors.Wrap(err, "unable to read as kube YAML") + return nil, fmt.Errorf("unable to read as kube YAML: %w", err) } switch kind { case "Pod": var podYAML v1.Pod if err := yaml.Unmarshal(document, &podYAML); err != nil { - return nil, errors.Wrap(err, "unable to read YAML as Kube Pod") + return nil, fmt.Errorf("unable to read YAML as Kube Pod: %w", err) } podNames = append(podNames, podYAML.ObjectMeta.Name) case "Deployment": var deploymentYAML v1apps.Deployment if err := yaml.Unmarshal(document, &deploymentYAML); err != nil { - return nil, errors.Wrap(err, "unable to read YAML as Kube Deployment") + return nil, fmt.Errorf("unable to read YAML as Kube Deployment: %w", err) } var numReplicas int32 = 1 deploymentName := deploymentYAML.ObjectMeta.Name diff --git a/pkg/domain/infra/abi/pods.go b/pkg/domain/infra/abi/pods.go index 1dca8c580..9a16f7fcd 100644 --- a/pkg/domain/infra/abi/pods.go +++ b/pkg/domain/infra/abi/pods.go @@ -2,6 +2,8 @@ package abi import ( "context" + "errors" + "fmt" "strconv" "strings" @@ -12,7 +14,6 @@ import ( "github.com/containers/podman/v4/pkg/signal" "github.com/containers/podman/v4/pkg/specgen" "github.com/containers/podman/v4/pkg/specgen/generate" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -49,7 +50,7 @@ func getPodsByContext(all, latest bool, pods []string, runtime *libpod.Runtime) func (ic *ContainerEngine) PodExists(ctx context.Context, nameOrID string) (*entities.BoolReport, error) { _, err := ic.Libpod.LookupPod(nameOrID) - if err != nil && errors.Cause(err) != define.ErrNoSuchPod { + if err != nil && !errors.Is(err, define.ErrNoSuchPod) { return nil, err } return &entities.BoolReport{Value: err == nil}, nil @@ -69,14 +70,14 @@ func (ic *ContainerEngine) PodKill(ctx context.Context, namesOrIds []string, opt for _, p := range pods { report := entities.PodKillReport{Id: p.ID()} conErrs, err := p.Kill(ctx, uint(sig)) - if err != nil && errors.Cause(err) != define.ErrPodPartialFail { + if err != nil && !errors.Is(err, define.ErrPodPartialFail) { report.Errs = []error{err} reports = append(reports, &report) continue } if len(conErrs) > 0 { for id, err := range conErrs { - report.Errs = append(report.Errs, errors.Wrapf(err, "error killing container %s", id)) + report.Errs = append(report.Errs, fmt.Errorf("error killing container %s: %w", id, err)) } reports = append(reports, &report) continue @@ -110,7 +111,7 @@ func (ic *ContainerEngine) PodLogs(ctx context.Context, nameOrID string, options } } if !ctrFound { - return errors.Wrapf(define.ErrNoSuchCtr, "container %s is not in pod %s", options.ContainerName, nameOrID) + return fmt.Errorf("container %s is not in pod %s: %w", options.ContainerName, nameOrID, define.ErrNoSuchCtr) } } else { // No container name specified select all containers @@ -135,13 +136,13 @@ func (ic *ContainerEngine) PodPause(ctx context.Context, namesOrIds []string, op for _, p := range pods { report := entities.PodPauseReport{Id: p.ID()} errs, err := p.Pause(ctx) - if err != nil && errors.Cause(err) != define.ErrPodPartialFail { + if err != nil && !errors.Is(err, define.ErrPodPartialFail) { report.Errs = []error{err} continue } if len(errs) > 0 { for id, v := range errs { - report.Errs = append(report.Errs, errors.Wrapf(v, "error pausing container %s", id)) + report.Errs = append(report.Errs, fmt.Errorf("error pausing container %s: %w", id, v)) } reports = append(reports, &report) continue @@ -158,15 +159,23 @@ func (ic *ContainerEngine) PodUnpause(ctx context.Context, namesOrIds []string, return nil, err } for _, p := range pods { + status, err := p.GetPodStatus() + if err != nil { + return nil, err + } + // If the pod is not paused or degraded, there is no need to attempt an unpause on it + if status != define.PodStatePaused && status != define.PodStateDegraded { + continue + } report := entities.PodUnpauseReport{Id: p.ID()} errs, err := p.Unpause(ctx) - if err != nil && errors.Cause(err) != define.ErrPodPartialFail { + if err != nil && !errors.Is(err, define.ErrPodPartialFail) { report.Errs = []error{err} continue } if len(errs) > 0 { for id, v := range errs { - report.Errs = append(report.Errs, errors.Wrapf(v, "error unpausing container %s", id)) + report.Errs = append(report.Errs, fmt.Errorf("error unpausing container %s: %w", id, v)) } reports = append(reports, &report) continue @@ -179,19 +188,19 @@ func (ic *ContainerEngine) PodUnpause(ctx context.Context, namesOrIds []string, func (ic *ContainerEngine) PodStop(ctx context.Context, namesOrIds []string, options entities.PodStopOptions) ([]*entities.PodStopReport, error) { reports := []*entities.PodStopReport{} pods, err := getPodsByContext(options.All, options.Latest, namesOrIds, ic.Libpod) - if err != nil && !(options.Ignore && errors.Cause(err) == define.ErrNoSuchPod) { + if err != nil && !(options.Ignore && errors.Is(err, define.ErrNoSuchPod)) { return nil, err } for _, p := range pods { report := entities.PodStopReport{Id: p.ID()} errs, err := p.StopWithTimeout(ctx, false, options.Timeout) - if err != nil && errors.Cause(err) != define.ErrPodPartialFail { + if err != nil && !errors.Is(err, define.ErrPodPartialFail) { report.Errs = []error{err} continue } if len(errs) > 0 { for id, v := range errs { - report.Errs = append(report.Errs, errors.Wrapf(v, "error stopping container %s", id)) + report.Errs = append(report.Errs, fmt.Errorf("error stopping container %s: %w", id, v)) } reports = append(reports, &report) continue @@ -210,14 +219,14 @@ func (ic *ContainerEngine) PodRestart(ctx context.Context, namesOrIds []string, for _, p := range pods { report := entities.PodRestartReport{Id: p.ID()} errs, err := p.Restart(ctx) - if err != nil && errors.Cause(err) != define.ErrPodPartialFail { + if err != nil && !errors.Is(err, define.ErrPodPartialFail) { report.Errs = []error{err} reports = append(reports, &report) continue } if len(errs) > 0 { for id, v := range errs { - report.Errs = append(report.Errs, errors.Wrapf(v, "error restarting container %s", id)) + report.Errs = append(report.Errs, fmt.Errorf("error restarting container %s: %w", id, v)) } reports = append(reports, &report) continue @@ -237,14 +246,14 @@ func (ic *ContainerEngine) PodStart(ctx context.Context, namesOrIds []string, op for _, p := range pods { report := entities.PodStartReport{Id: p.ID()} errs, err := p.Start(ctx) - if err != nil && errors.Cause(err) != define.ErrPodPartialFail { + if err != nil && !errors.Is(err, define.ErrPodPartialFail) { report.Errs = []error{err} reports = append(reports, &report) continue } if len(errs) > 0 { for id, v := range errs { - report.Errs = append(report.Errs, errors.Wrapf(v, "error starting container %s", id)) + report.Errs = append(report.Errs, fmt.Errorf("error starting container %s: %w", id, v)) } reports = append(reports, &report) continue @@ -256,7 +265,7 @@ func (ic *ContainerEngine) PodStart(ctx context.Context, namesOrIds []string, op func (ic *ContainerEngine) PodRm(ctx context.Context, namesOrIds []string, options entities.PodRmOptions) ([]*entities.PodRmReport, error) { pods, err := getPodsByContext(options.All, options.Latest, namesOrIds, ic.Libpod) - if err != nil && !(options.Ignore && errors.Cause(err) == define.ErrNoSuchPod) { + if err != nil && !(options.Ignore && errors.Is(err, define.ErrNoSuchPod)) { return nil, err } reports := make([]*entities.PodRmReport, 0, len(pods)) @@ -393,7 +402,7 @@ func (ic *ContainerEngine) PodTop(ctx context.Context, options entities.PodTopOp pod, err = ic.Libpod.LookupPod(options.NameOrID) } if err != nil { - return nil, errors.Wrap(err, "unable to look up requested container") + return nil, fmt.Errorf("unable to look up requested container: %w", err) } // Run Top. @@ -505,7 +514,7 @@ func (ic *ContainerEngine) PodInspect(ctx context.Context, options entities.PodI pod, err = ic.Libpod.LookupPod(options.NameOrID) } if err != nil { - return nil, errors.Wrap(err, "unable to look up requested container") + return nil, fmt.Errorf("unable to look up requested container: %w", err) } inspect, err := pod.Inspect() if err != nil { diff --git a/pkg/domain/infra/abi/secrets.go b/pkg/domain/infra/abi/secrets.go index b9380ad73..7321ef715 100644 --- a/pkg/domain/infra/abi/secrets.go +++ b/pkg/domain/infra/abi/secrets.go @@ -2,13 +2,14 @@ package abi import ( "context" + "fmt" "io" "io/ioutil" "path/filepath" + "strings" "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/domain/utils" - "github.com/pkg/errors" ) func (ic *ContainerEngine) SecretCreate(ctx context.Context, name string, reader io.Reader, options entities.SecretCreateOptions) (*entities.SecretCreateReport, error) { @@ -60,11 +61,11 @@ func (ic *ContainerEngine) SecretInspect(ctx context.Context, nameOrIDs []string for _, nameOrID := range nameOrIDs { secret, err := manager.Lookup(nameOrID) if err != nil { - if errors.Cause(err).Error() == "no such secret" { + if strings.Contains(err.Error(), "no such secret") { errs = append(errs, err) continue } else { - return nil, nil, errors.Wrapf(err, "error inspecting secret %s", nameOrID) + return nil, nil, fmt.Errorf("error inspecting secret %s: %w", nameOrID, err) } } report := &entities.SecretInfoReport{ @@ -141,7 +142,7 @@ func (ic *ContainerEngine) SecretRm(ctx context.Context, nameOrIDs []string, opt } for _, nameOrID := range toRemove { deletedID, err := manager.Delete(nameOrID) - if err == nil || errors.Cause(err).Error() == "no such secret" { + if err == nil || strings.Contains(err.Error(), "no such secret") { reports = append(reports, &entities.SecretRmReport{ Err: err, ID: deletedID, diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go index 2bd88ed85..96690afef 100644 --- a/pkg/domain/infra/abi/system.go +++ b/pkg/domain/infra/abi/system.go @@ -2,6 +2,7 @@ package abi import ( "context" + "errors" "fmt" "net/url" "os" @@ -19,7 +20,6 @@ import ( "github.com/containers/podman/v4/utils" "github.com/containers/storage" "github.com/containers/storage/pkg/unshare" - "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/spf13/pflag" ) @@ -99,7 +99,7 @@ func (ic *ContainerEngine) SetupRootless(_ context.Context, noMoveProcess bool) } pausePidPath, err := util.GetRootlessPauseProcessPidPathGivenDir(tmpDir) if err != nil { - return errors.Wrapf(err, "could not get pause process pid file path") + return fmt.Errorf("could not get pause process pid file path: %w", err) } became, ret, err := rootless.TryJoinPauseProcess(pausePidPath) @@ -134,7 +134,7 @@ func (ic *ContainerEngine) SetupRootless(_ context.Context, noMoveProcess bool) } } if err != nil { - logrus.Error(errors.Wrapf(err, "invalid internal status, try resetting the pause process with %q", os.Args[0]+" system migrate")) + logrus.Error(fmt.Errorf("invalid internal status, try resetting the pause process with %q: %w", os.Args[0]+" system migrate", err)) os.Exit(1) } if became { @@ -271,22 +271,22 @@ func (ic *ContainerEngine) SystemDf(ctx context.Context, options entities.System iid, _ := c.Image() state, err := c.State() if err != nil { - return nil, errors.Wrapf(err, "Failed to get state of container %s", c.ID()) + return nil, fmt.Errorf("failed to get state of container %s: %w", c.ID(), err) } conSize, err := c.RootFsSize() if err != nil { - if errors.Cause(err) == storage.ErrContainerUnknown { - logrus.Error(errors.Wrapf(err, "Failed to get root file system size of container %s", c.ID())) + if errors.Is(err, storage.ErrContainerUnknown) { + logrus.Error(fmt.Errorf("failed to get root file system size of container %s: %w", c.ID(), err)) } else { - return nil, errors.Wrapf(err, "Failed to get root file system size of container %s", c.ID()) + return nil, fmt.Errorf("failed to get root file system size of container %s: %w", c.ID(), err) } } rwsize, err := c.RWSize() if err != nil { - if errors.Cause(err) == storage.ErrContainerUnknown { - logrus.Error(errors.Wrapf(err, "Failed to get read/write size of container %s", c.ID())) + if errors.Is(err, storage.ErrContainerUnknown) { + logrus.Error(fmt.Errorf("failed to get read/write size of container %s: %w", c.ID(), err)) } else { - return nil, errors.Wrapf(err, "Failed to get read/write size of container %s", c.ID()) + return nil, fmt.Errorf("failed to get read/write size of container %s: %w", c.ID(), err) } } report := entities.SystemDfContainerReport{ diff --git a/pkg/domain/infra/abi/terminal/sigproxy_linux.go b/pkg/domain/infra/abi/terminal/sigproxy_linux.go index e02c0532c..16d345f06 100644 --- a/pkg/domain/infra/abi/terminal/sigproxy_linux.go +++ b/pkg/domain/infra/abi/terminal/sigproxy_linux.go @@ -1,6 +1,7 @@ package terminal import ( + "errors" "os" "syscall" @@ -8,7 +9,6 @@ import ( "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/libpod/shutdown" "github.com/containers/podman/v4/pkg/signal" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -39,7 +39,7 @@ func ProxySignals(ctr *libpod.Container) { } if err := ctr.Kill(uint(s.(syscall.Signal))); err != nil { - if errors.Cause(err) == define.ErrCtrStateInvalid { + if errors.Is(err, define.ErrCtrStateInvalid) { logrus.Infof("Ceasing signal forwarding to container %s as it has stopped", ctr.ID()) } else { logrus.Errorf("forwarding signal %d to container %s: %v", s, ctr.ID(), err) diff --git a/pkg/domain/infra/abi/terminal/terminal.go b/pkg/domain/infra/abi/terminal/terminal.go index 692f8dcd5..45ebded26 100644 --- a/pkg/domain/infra/abi/terminal/terminal.go +++ b/pkg/domain/infra/abi/terminal/terminal.go @@ -5,7 +5,7 @@ import ( "os" "os/signal" - "github.com/containers/podman/v4/libpod/define" + "github.com/containers/common/pkg/resize" lsignal "github.com/containers/podman/v4/pkg/signal" "github.com/moby/term" "github.com/pkg/errors" @@ -18,20 +18,20 @@ type RawTtyFormatter struct { // getResize returns a TerminalSize command matching stdin's current // size on success, and nil on errors. -func getResize() *define.TerminalSize { +func getResize() *resize.TerminalSize { winsize, err := term.GetWinsize(os.Stdin.Fd()) if err != nil { logrus.Warnf("Could not get terminal size %v", err) return nil } - return &define.TerminalSize{ + return &resize.TerminalSize{ Width: winsize.Width, Height: winsize.Height, } } // Helper for prepareAttach - set up a goroutine to generate terminal resize events -func resizeTty(ctx context.Context, resize chan define.TerminalSize) { +func resizeTty(ctx context.Context, resize chan resize.TerminalSize) { sigchan := make(chan os.Signal, 1) signal.Notify(sigchan, lsignal.SIGWINCH) go func() { @@ -78,7 +78,7 @@ func (f *RawTtyFormatter) Format(entry *logrus.Entry) ([]byte, error) { return bytes, err } -func handleTerminalAttach(ctx context.Context, resize chan define.TerminalSize) (context.CancelFunc, *term.State, error) { +func handleTerminalAttach(ctx context.Context, resize chan resize.TerminalSize) (context.CancelFunc, *term.State, error) { logrus.Debugf("Handling terminal attach") subCtx, cancel := context.WithCancel(ctx) diff --git a/pkg/domain/infra/abi/terminal/terminal_linux.go b/pkg/domain/infra/abi/terminal/terminal_linux.go index 62d36f28d..e8f338418 100644 --- a/pkg/domain/infra/abi/terminal/terminal_linux.go +++ b/pkg/domain/infra/abi/terminal/terminal_linux.go @@ -6,6 +6,7 @@ import ( "fmt" "os" + "github.com/containers/common/pkg/resize" "github.com/containers/podman/v4/libpod" "github.com/containers/podman/v4/libpod/define" "github.com/pkg/errors" @@ -15,14 +16,14 @@ import ( // ExecAttachCtr execs and attaches to a container func ExecAttachCtr(ctx context.Context, ctr *libpod.Container, execConfig *libpod.ExecConfig, streams *define.AttachStreams) (int, error) { - var resize chan define.TerminalSize + var resizechan chan resize.TerminalSize haveTerminal := term.IsTerminal(int(os.Stdin.Fd())) // Check if we are attached to a terminal. If we are, generate resize // events, and set the terminal to raw mode if haveTerminal && execConfig.Terminal { - resize = make(chan define.TerminalSize) - cancel, oldTermState, err := handleTerminalAttach(ctx, resize) + resizechan = make(chan resize.TerminalSize) + cancel, oldTermState, err := handleTerminalAttach(ctx, resizechan) if err != nil { return -1, err } @@ -33,14 +34,14 @@ func ExecAttachCtr(ctx context.Context, ctr *libpod.Container, execConfig *libpo } }() } - return ctr.Exec(execConfig, streams, resize) + return ctr.Exec(execConfig, streams, resizechan) } // StartAttachCtr starts and (if required) attaches to a container // if you change the signature of this function from os.File to io.Writer, it will trigger a downstream // error. we may need to just lint disable this one. func StartAttachCtr(ctx context.Context, ctr *libpod.Container, stdout, stderr, stdin *os.File, detachKeys string, sigProxy bool, startContainer bool) error { //nolint: interfacer - resize := make(chan define.TerminalSize) + resize := make(chan resize.TerminalSize) haveTerminal := term.IsTerminal(int(os.Stdin.Fd())) diff --git a/pkg/domain/infra/abi/volumes.go b/pkg/domain/infra/abi/volumes.go index 1186d8e81..5e95a0551 100644 --- a/pkg/domain/infra/abi/volumes.go +++ b/pkg/domain/infra/abi/volumes.go @@ -2,6 +2,8 @@ package abi import ( "context" + "errors" + "fmt" "github.com/containers/podman/v4/libpod" "github.com/containers/podman/v4/libpod/define" @@ -9,7 +11,6 @@ import ( "github.com/containers/podman/v4/pkg/domain/entities/reports" "github.com/containers/podman/v4/pkg/domain/filters" "github.com/containers/podman/v4/pkg/domain/infra/abi/parse" - "github.com/pkg/errors" ) func (ic *ContainerEngine) VolumeCreate(ctx context.Context, opts entities.VolumeCreateOptions) (*entities.IDOrNameResponse, error) { @@ -91,11 +92,11 @@ func (ic *ContainerEngine) VolumeInspect(ctx context.Context, namesOrIds []strin for _, v := range namesOrIds { vol, err := ic.Libpod.LookupVolume(v) if err != nil { - if errors.Cause(err) == define.ErrNoSuchVolume { - errs = append(errs, errors.Errorf("no such volume %s", v)) + if errors.Is(err, define.ErrNoSuchVolume) { + errs = append(errs, fmt.Errorf("no such volume %s", v)) continue } else { - return nil, nil, errors.Wrapf(err, "error inspecting volume %s", v) + return nil, nil, fmt.Errorf("error inspecting volume %s: %w", v, err) } } vols = append(vols, vol) diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go index fb0be629c..5568ccde8 100644 --- a/pkg/domain/infra/tunnel/containers.go +++ b/pkg/domain/infra/tunnel/containers.go @@ -2,6 +2,7 @@ package tunnel import ( "context" + "errors" "fmt" "io" "os" @@ -23,7 +24,6 @@ import ( "github.com/containers/podman/v4/pkg/specgen" "github.com/containers/podman/v4/pkg/util" "github.com/containers/storage/types" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -64,7 +64,7 @@ func (ic *ContainerEngine) ContainerPause(ctx context.Context, namesOrIds []stri reports := make([]*entities.PauseUnpauseReport, 0, len(ctrs)) for _, c := range ctrs { err := containers.Pause(ic.ClientCtx, c.ID, nil) - if err != nil && options.All && errors.Cause(err).Error() == define.ErrCtrStateInvalid.Error() { + if err != nil && options.All && strings.Contains(err.Error(), define.ErrCtrStateInvalid.Error()) { logrus.Debugf("Container %s is not running", c.ID) continue } @@ -81,7 +81,7 @@ func (ic *ContainerEngine) ContainerUnpause(ctx context.Context, namesOrIds []st } for _, c := range ctrs { err := containers.Unpause(ic.ClientCtx, c.ID, nil) - if err != nil && options.All && errors.Cause(err).Error() == define.ErrCtrStateInvalid.Error() { + if err != nil && options.All && strings.Contains(err.Error(), define.ErrCtrStateInvalid.Error()) { logrus.Debugf("Container %s is not paused", c.ID) continue } @@ -111,11 +111,11 @@ func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []strin } if err = containers.Stop(ic.ClientCtx, c.ID, options); err != nil { // These first two are considered non-fatal under the right conditions - if errors.Cause(err).Error() == define.ErrCtrStopped.Error() { + if strings.Contains(err.Error(), define.ErrCtrStopped.Error()) { logrus.Debugf("Container %s is already stopped", c.ID) reports = append(reports, &report) continue - } else if opts.All && errors.Cause(err).Error() == define.ErrCtrStateInvalid.Error() { + } else if opts.All && strings.Contains(err.Error(), define.ErrCtrStateInvalid.Error()) { logrus.Debugf("Container %s is not running, could not stop", c.ID) reports = append(reports, &report) continue @@ -146,7 +146,7 @@ func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []strin reports := make([]*entities.KillReport, 0, len(ctrs)) for _, c := range ctrs { err := containers.Kill(ic.ClientCtx, c.ID, options) - if err != nil && opts.All && errors.Cause(err).Error() == define.ErrCtrStateInvalid.Error() { + if err != nil && opts.All && strings.Contains(err.Error(), define.ErrCtrStateInvalid.Error()) { logrus.Debugf("Container %s is not running", c.ID) continue } @@ -258,7 +258,7 @@ func (ic *ContainerEngine) ContainerInspect(ctx context.Context, namesOrIds []st return nil, nil, err } if errModel.ResponseCode == 404 { - errs = append(errs, errors.Errorf("no such container %q", name)) + errs = append(errs, fmt.Errorf("no such container %q", name)) continue } return nil, nil, err @@ -291,7 +291,7 @@ func (ic *ContainerEngine) ContainerCommit(ctx context.Context, nameOrID string, if len(opts.ImageName) > 0 { ref, err := reference.Parse(opts.ImageName) if err != nil { - return nil, errors.Wrapf(err, "error parsing reference %q", opts.ImageName) + return nil, fmt.Errorf("error parsing reference %q: %w", opts.ImageName, err) } if t, ok := ref.(reference.Tagged); ok { tag = t.Tag() @@ -300,7 +300,7 @@ func (ic *ContainerEngine) ContainerCommit(ctx context.Context, nameOrID string, repo = r.Name() } if len(repo) < 1 { - return nil, errors.Errorf("invalid image name %q", opts.ImageName) + return nil, fmt.Errorf("invalid image name %q", opts.ImageName) } } options := new(containers.CommitOptions).WithAuthor(opts.Author).WithChanges(opts.Changes).WithComment(opts.Message).WithSquash(opts.Squash) @@ -502,7 +502,7 @@ func (ic *ContainerEngine) ContainerAttach(ctx context.Context, nameOrID string, } ctr := ctrs[0] if ctr.State != define.ContainerStateRunning.String() { - return errors.Errorf("you can only attach to running containers") + return fmt.Errorf("you can only attach to running containers") } options := new(containers.AttachOptions).WithStream(true).WithDetachKeys(opts.DetachKeys) return containers.Attach(ic.ClientCtx, nameOrID, opts.Stdin, opts.Stdout, opts.Stderr, nil, options) @@ -695,7 +695,7 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri report.ExitCode = define.ExitCode(report.Err) report.Err = err reports = append(reports, &report) - return reports, errors.Wrapf(report.Err, "unable to start container %s", name) + return reports, fmt.Errorf("unable to start container %s: %w", name, report.Err) } if ctr.AutoRemove { // Defer the removal, so we can return early if needed and @@ -739,7 +739,7 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri reports, err := containers.Remove(ic.ClientCtx, ctr.ID, rmOptions) logIfRmError(ctr.ID, err, reports) } - report.Err = errors.Wrapf(err, "unable to start container %q", name) + report.Err = fmt.Errorf("unable to start container %q: %w", name, err) report.ExitCode = define.ExitCode(err) reports = append(reports, &report) continue @@ -899,7 +899,7 @@ func (ic *ContainerEngine) ContainerInit(ctx context.Context, namesOrIds []strin err := containers.ContainerInit(ic.ClientCtx, ctr.ID, nil) // When using all, it is NOT considered an error if a container // has already been init'd. - if err != nil && options.All && strings.Contains(errors.Cause(err).Error(), define.ErrCtrStateInvalid.Error()) { + if err != nil && options.All && strings.Contains(err.Error(), define.ErrCtrStateInvalid.Error()) { err = nil } reports = append(reports, &entities.ContainerInitReport{ diff --git a/pkg/domain/infra/tunnel/pods.go b/pkg/domain/infra/tunnel/pods.go index 7b1fa231f..bcbd32d1b 100644 --- a/pkg/domain/infra/tunnel/pods.go +++ b/pkg/domain/infra/tunnel/pods.go @@ -2,12 +2,12 @@ package tunnel import ( "context" + "errors" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/bindings/pods" "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/util" - "github.com/pkg/errors" ) func (ic *ContainerEngine) PodExists(ctx context.Context, nameOrID string) (*entities.BoolReport, error) { @@ -80,6 +80,10 @@ func (ic *ContainerEngine) PodUnpause(ctx context.Context, namesOrIds []string, } reports := make([]*entities.PodUnpauseReport, 0, len(foundPods)) for _, p := range foundPods { + // If the pod is not paused or degraded, there is no need to attempt an unpause on it + if p.Status != define.PodStatePaused && p.Status != define.PodStateDegraded { + continue + } response, err := pods.Unpause(ic.ClientCtx, p.Id, nil) if err != nil { report := entities.PodUnpauseReport{ @@ -97,7 +101,7 @@ func (ic *ContainerEngine) PodUnpause(ctx context.Context, namesOrIds []string, func (ic *ContainerEngine) PodStop(ctx context.Context, namesOrIds []string, opts entities.PodStopOptions) ([]*entities.PodStopReport, error) { timeout := -1 foundPods, err := getPodsByContext(ic.ClientCtx, opts.All, namesOrIds) - if err != nil && !(opts.Ignore && errors.Cause(err) == define.ErrNoSuchPod) { + if err != nil && !(opts.Ignore && errors.Is(err, define.ErrNoSuchPod)) { return nil, err } if opts.Timeout != -1 { @@ -164,7 +168,7 @@ func (ic *ContainerEngine) PodStart(ctx context.Context, namesOrIds []string, op func (ic *ContainerEngine) PodRm(ctx context.Context, namesOrIds []string, opts entities.PodRmOptions) ([]*entities.PodRmReport, error) { foundPods, err := getPodsByContext(ic.ClientCtx, opts.All, namesOrIds) - if err != nil && !(opts.Ignore && errors.Cause(err) == define.ErrNoSuchPod) { + if err != nil && !(opts.Ignore && errors.Is(err, define.ErrNoSuchPod)) { return nil, err } reports := make([]*entities.PodRmReport, 0, len(foundPods)) diff --git a/pkg/errorhandling/errorhandling.go b/pkg/errorhandling/errorhandling.go index fc6772c08..9b456c9c0 100644 --- a/pkg/errorhandling/errorhandling.go +++ b/pkg/errorhandling/errorhandling.go @@ -1,11 +1,11 @@ package errorhandling import ( + "errors" "os" "strings" "github.com/hashicorp/go-multierror" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -121,3 +121,22 @@ func (e PodConflictErrorModel) Error() string { func (e PodConflictErrorModel) Code() int { return 409 } + +// Cause returns the most underlying error for the provided one. There is a +// maximum error depth of 100 to avoid endless loops. An additional error log +// message will be created if this maximum has reached. +func Cause(err error) (cause error) { + cause = err + + const maxDepth = 100 + for i := 0; i <= maxDepth; i++ { + res := errors.Unwrap(cause) + if res == nil { + return cause + } + cause = res + } + + logrus.Errorf("Max error depth of %d reached, cannot unwrap until root cause: %v", maxDepth, err) + return cause +} diff --git a/pkg/errorhandling/errorhandling_test.go b/pkg/errorhandling/errorhandling_test.go new file mode 100644 index 000000000..ec720c5e7 --- /dev/null +++ b/pkg/errorhandling/errorhandling_test.go @@ -0,0 +1,53 @@ +package errorhandling + +import ( + "errors" + "fmt" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestCause(t *testing.T) { + t.Parallel() + + for _, tc := range []struct { + name string + err func() error + expectedErr error + }{ + { + name: "nil error", + err: func() error { return nil }, + expectedErr: nil, + }, + { + name: "equal errors", + err: func() error { return errors.New("foo") }, + expectedErr: errors.New("foo"), + }, + { + name: "wrapped error", + err: func() error { return fmt.Errorf("baz: %w", fmt.Errorf("bar: %w", errors.New("foo"))) }, + expectedErr: errors.New("foo"), + }, + { + name: "max depth reached", + err: func() error { + err := errors.New("error") + for i := 0; i <= 101; i++ { + err = fmt.Errorf("%d: %w", i, err) + } + return err + }, + expectedErr: fmt.Errorf("0: %w", errors.New("error")), + }, + } { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + err := Cause(tc.err()) + assert.Equal(t, tc.expectedErr, err) + }) + } +} diff --git a/pkg/hooks/exec/runtimeconfigfilter_test.go b/pkg/hooks/exec/runtimeconfigfilter_test.go index 5c13a76e1..a4e9b1fdb 100644 --- a/pkg/hooks/exec/runtimeconfigfilter_test.go +++ b/pkg/hooks/exec/runtimeconfigfilter_test.go @@ -3,12 +3,12 @@ package exec import ( "context" "encoding/json" + "errors" "os" "testing" "time" spec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" "github.com/stretchr/testify/assert" ) @@ -18,13 +18,14 @@ func TestRuntimeConfigFilter(t *testing.T) { rootUint32 := uint32(0) binUser := int(1) for _, tt := range []struct { - name string - contextTimeout time.Duration - hooks []spec.Hook - input *spec.Spec - expected *spec.Spec - expectedHookError string - expectedRunError error + name string + contextTimeout time.Duration + hooks []spec.Hook + input *spec.Spec + expected *spec.Spec + expectedHookError string + expectedRunError error + expectedRunErrorString string }{ { name: "no-op", @@ -231,7 +232,8 @@ func TestRuntimeConfigFilter(t *testing.T) { Path: "rootfs", }, }, - expectedRunError: unexpectedEndOfJSONInput, + expectedRunError: unexpectedEndOfJSONInput, + expectedRunErrorString: unexpectedEndOfJSONInput.Error(), }, } { test := tt @@ -243,7 +245,13 @@ func TestRuntimeConfigFilter(t *testing.T) { defer cancel() } hookErr, err := RuntimeConfigFilter(ctx, test.hooks, test.input, DefaultPostKillTimeout) - assert.Equal(t, test.expectedRunError, errors.Cause(err)) + if test.expectedRunError != nil { + if test.expectedRunErrorString != "" { + assert.Contains(t, err.Error(), test.expectedRunErrorString) + } else { + assert.True(t, errors.Is(err, test.expectedRunError)) + } + } if test.expectedHookError == "" { if hookErr != nil { t.Fatal(hookErr) diff --git a/pkg/k8s.io/apimachinery/pkg/api/resource/amount.go b/pkg/k8s.io/apimachinery/pkg/api/resource/amount.go index d05984dac..69613321f 100644 --- a/pkg/k8s.io/apimachinery/pkg/api/resource/amount.go +++ b/pkg/k8s.io/apimachinery/pkg/api/resource/amount.go @@ -48,7 +48,7 @@ const ( var ( Zero = int64Amount{} - // Used by quantity strings - treat as read only + // Used by quantity strings - treat as read-only zeroBytes = []byte("0") ) diff --git a/pkg/k8s.io/apimachinery/pkg/api/resource/math.go b/pkg/k8s.io/apimachinery/pkg/api/resource/math.go index 9d03f5c05..59a4c14de 100644 --- a/pkg/k8s.io/apimachinery/pkg/api/resource/math.go +++ b/pkg/k8s.io/apimachinery/pkg/api/resource/math.go @@ -29,13 +29,13 @@ const ( ) var ( - // Commonly needed big.Int values-- treat as read only! + // Commonly needed big.Int values-- treat as read-only! bigTen = big.NewInt(10) bigZero = big.NewInt(0) bigOne = big.NewInt(1) big1024 = big.NewInt(1024) - // Commonly needed inf.Dec values-- treat as read only! + // Commonly needed inf.Dec values-- treat as read-only! decZero = inf.NewDec(0, 0) decOne = inf.NewDec(1, 0) diff --git a/pkg/kubeutils/LICENSE b/pkg/kubeutils/LICENSE deleted file mode 100644 index 9b259bdfc..000000000 --- a/pkg/kubeutils/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - https://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/pkg/machine/config.go b/pkg/machine/config.go index fcc129338..66fa6ab91 100644 --- a/pkg/machine/config.go +++ b/pkg/machine/config.go @@ -55,6 +55,7 @@ type Provider interface { IsValidVMName(name string) (bool, error) CheckExclusiveActiveVM() (bool, string, error) RemoveAndCleanMachines() error + VMType() string } type RemoteConnectionType string diff --git a/pkg/machine/config_test.go b/pkg/machine/config_test.go index d9fc5425e..ca08660b9 100644 --- a/pkg/machine/config_test.go +++ b/pkg/machine/config_test.go @@ -1,3 +1,6 @@ +//go:build amd64 || arm64 +// +build amd64 arm64 + package machine import ( diff --git a/pkg/machine/e2e/config_info.go b/pkg/machine/e2e/config_info.go new file mode 100644 index 000000000..410c7e518 --- /dev/null +++ b/pkg/machine/e2e/config_info.go @@ -0,0 +1,20 @@ +package e2e + +type infoMachine struct { + format string + cmd []string +} + +func (i *infoMachine) buildCmd(m *machineTestBuilder) []string { + cmd := []string{"machine", "info"} + if len(i.format) > 0 { + cmd = append(cmd, "--format", i.format) + } + i.cmd = cmd + return cmd +} + +func (i *infoMachine) withFormat(format string) *infoMachine { + i.format = format + return i +} diff --git a/pkg/machine/e2e/info_test.go b/pkg/machine/e2e/info_test.go new file mode 100644 index 000000000..eeabb78af --- /dev/null +++ b/pkg/machine/e2e/info_test.go @@ -0,0 +1,58 @@ +package e2e + +import ( + "github.com/containers/podman/v4/cmd/podman/machine" + jsoniter "github.com/json-iterator/go" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + . "github.com/onsi/gomega/gexec" +) + +var _ = Describe("podman machine info", func() { + var ( + mb *machineTestBuilder + testDir string + ) + + BeforeEach(func() { + testDir, mb = setup() + }) + AfterEach(func() { + teardown(originalHomeDir, testDir, mb) + }) + + It("machine info", func() { + info := new(infoMachine) + infoSession, err := mb.setCmd(info).run() + Expect(err).NotTo(HaveOccurred()) + Expect(infoSession).Should(Exit(0)) + + // Verify go template works and check for no running machines + info = new(infoMachine) + infoSession, err = mb.setCmd(info.withFormat("{{.Host.NumberOfMachines}}")).run() + Expect(err).NotTo(HaveOccurred()) + Expect(infoSession).Should(Exit(0)) + Expect(infoSession.outputToString()).To(Equal("0")) + + // Create a machine and check if info has been updated + i := new(initMachine) + initSession, err := mb.setCmd(i.withImagePath(mb.imagePath)).run() + Expect(err).To(BeNil()) + Expect(initSession).To(Exit(0)) + + info = new(infoMachine) + infoSession, err = mb.setCmd(info.withFormat("{{.Host.NumberOfMachines}}")).run() + Expect(err).NotTo(HaveOccurred()) + Expect(infoSession).Should(Exit(0)) + Expect(infoSession.outputToString()).To(Equal("1")) + + // Check if json is in correct format + infoSession, err = mb.setCmd(info.withFormat("json")).run() + Expect(err).NotTo(HaveOccurred()) + Expect(infoSession).Should(Exit(0)) + + infoReport := &machine.Info{} + err = jsoniter.Unmarshal(infoSession.Bytes(), infoReport) + Expect(err).To(BeNil()) + }) +}) diff --git a/pkg/machine/qemu/config_test.go b/pkg/machine/qemu/config_test.go index 4d96ec6e7..72cb3ed90 100644 --- a/pkg/machine/qemu/config_test.go +++ b/pkg/machine/qemu/config_test.go @@ -1,3 +1,6 @@ +//go:build (amd64 && !windows) || (arm64 && !windows) +// +build amd64,!windows arm64,!windows + package qemu import ( diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go index 2fe0230cf..322aa3a15 100644 --- a/pkg/machine/qemu/machine.go +++ b/pkg/machine/qemu/machine.go @@ -8,6 +8,7 @@ import ( "context" "encoding/base64" "encoding/json" + "errors" "fmt" "io/fs" "io/ioutil" @@ -30,7 +31,6 @@ import ( "github.com/containers/storage/pkg/homedir" "github.com/digitalocean/go-qemu/qmp" "github.com/docker/go-units" - "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/sys/unix" ) @@ -318,6 +318,7 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) { source := paths[0] target := source readonly := false + securityModel := "mapped-xattr" if len(paths) > 1 { target = paths[1] } @@ -325,18 +326,20 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) { options := paths[2] volopts := strings.Split(options, ",") for _, o := range volopts { - switch o { - case "rw": + switch { + case o == "rw": readonly = false - case "ro": + case o == "ro": readonly = true + case strings.HasPrefix(o, "security_model="): + securityModel = strings.Split(o, "=")[1] default: fmt.Printf("Unknown option: %s\n", o) } } } if volumeType == VolumeTypeVirtfs { - virtfsOptions := fmt.Sprintf("local,path=%s,mount_tag=%s,security_model=mapped-xattr", source, tag) + virtfsOptions := fmt.Sprintf("local,path=%s,mount_tag=%s,security_model=%s", source, tag, securityModel) if readonly { virtfsOptions += ",readonly" } @@ -434,12 +437,12 @@ func (v *MachineVM) Set(_ string, opts machine.SetOptions) ([]error, error) { if v.Name != machine.DefaultMachineName { suffix = " " + v.Name } - return setErrors, errors.Errorf("cannot change settings while the vm is running, run 'podman machine stop%s' first", suffix) + return setErrors, fmt.Errorf("cannot change settings while the vm is running, run 'podman machine stop%s' first", suffix) } if opts.Rootful != nil && v.Rootful != *opts.Rootful { if err := v.setRootful(*opts.Rootful); err != nil { - setErrors = append(setErrors, errors.Wrapf(err, "failed to set rootful option")) + setErrors = append(setErrors, fmt.Errorf("failed to set rootful option: %w", err)) } else { v.Rootful = *opts.Rootful } @@ -457,7 +460,7 @@ func (v *MachineVM) Set(_ string, opts machine.SetOptions) ([]error, error) { if opts.DiskSize != nil && v.DiskSize != *opts.DiskSize { if err := v.resizeDisk(*opts.DiskSize, v.DiskSize); err != nil { - setErrors = append(setErrors, errors.Wrapf(err, "failed to resize disk")) + setErrors = append(setErrors, fmt.Errorf("failed to resize disk: %w", err)) } else { v.DiskSize = *opts.DiskSize } @@ -514,7 +517,7 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error { forwardSock, forwardState, err := v.startHostNetworking() if err != nil { - return errors.Errorf("unable to start host networking: %q", err) + return fmt.Errorf("unable to start host networking: %q", err) } rtPath, err := getRuntimeDir() @@ -593,7 +596,7 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error { } _, err = os.StartProcess(cmd[0], cmd, attr) if err != nil { - return errors.Wrapf(err, "unable to execute %q", cmd) + return fmt.Errorf("unable to execute %q: %w", cmd, err) } } fmt.Println("Waiting for VM ...") @@ -700,7 +703,7 @@ func (v *MachineVM) checkStatus(monitor *qmp.SocketMonitor) (machine.Status, err } b, err := monitor.Run(input) if err != nil { - if errors.Cause(err) == os.ErrNotExist { + if errors.Is(err, os.ErrNotExist) { return machine.Stopped, nil } return "", err @@ -879,7 +882,7 @@ func (v *MachineVM) Remove(_ string, opts machine.RemoveOptions) (string, func() } if state == machine.Running { if !opts.Force { - return "", nil, errors.Errorf("running vm %q cannot be destroyed", v.Name) + return "", nil, fmt.Errorf("running vm %q cannot be destroyed", v.Name) } err := v.Stop(v.Name, machine.StopOptions{}) if err != nil { @@ -1001,7 +1004,7 @@ func (v *MachineVM) SSH(_ string, opts machine.SSHOptions) error { return err } if state != machine.Running { - return errors.Errorf("vm %q is not running", v.Name) + return fmt.Errorf("vm %q is not running", v.Name) } username := opts.Username @@ -1013,7 +1016,7 @@ func (v *MachineVM) SSH(_ string, opts machine.SSHOptions) error { port := strconv.Itoa(v.Port) args := []string{"-i", v.IdentityPath, "-p", port, sshDestination, "-o", "UserKnownHostsFile=/dev/null", - "-o", "StrictHostKeyChecking=no", "-o", "LogLevel=ERROR"} + "-o", "StrictHostKeyChecking=no", "-o", "LogLevel=ERROR", "-o", "SetEnv=LC_ALL="} if len(opts.Args) > 0 { args = append(args, opts.Args...) } else { @@ -1165,7 +1168,7 @@ func (p *Provider) IsValidVMName(name string) (bool, error) { func (p *Provider) CheckExclusiveActiveVM() (bool, string, error) { vms, err := getVMInfos() if err != nil { - return false, "", errors.Wrap(err, "error checking VM active") + return false, "", fmt.Errorf("error checking VM active: %w", err) } for _, vm := range vms { if vm.Running || vm.Starting { @@ -1217,7 +1220,10 @@ func (v *MachineVM) startHostNetworking() (string, apiForwardingState, error) { fmt.Println(cmd) } _, err = os.StartProcess(cmd[0], cmd, attr) - return forwardSock, state, errors.Wrapf(err, "unable to execute: %q", cmd) + if err != nil { + return "", 0, fmt.Errorf("unable to execute: %q: %w", cmd, err) + } + return forwardSock, state, nil } func (v *MachineVM) setupAPIForwarding(cmd []string) ([]string, string, apiForwardingState) { @@ -1486,7 +1492,7 @@ func (v *MachineVM) update() error { b, err := v.ConfigPath.Read() if err != nil { if errors.Is(err, os.ErrNotExist) { - return errors.Wrap(machine.ErrNoSuchVM, v.Name) + return fmt.Errorf("%v: %w", v.Name, machine.ErrNoSuchVM) } return err } @@ -1562,7 +1568,7 @@ func (v *MachineVM) resizeDisk(diskSize uint64, oldSize uint64) error { // only if the virtualdisk size is less than // the given disk size if diskSize < oldSize { - return errors.Errorf("new disk size must be larger than current disk size: %vGB", oldSize) + return fmt.Errorf("new disk size must be larger than current disk size: %vGB", oldSize) } // Find the qemu executable @@ -1578,7 +1584,7 @@ func (v *MachineVM) resizeDisk(diskSize uint64, oldSize uint64) error { resize.Stdout = os.Stdout resize.Stderr = os.Stderr if err := resize.Run(); err != nil { - return errors.Errorf("resizing image: %q", err) + return fmt.Errorf("resizing image: %q", err) } return nil @@ -1698,6 +1704,9 @@ func isProcessAlive(pid int) bool { if err == nil || err == unix.EPERM { return true } - return false } + +func (p *Provider) VMType() string { + return vmtype +} diff --git a/pkg/machine/qemu/machine_test.go b/pkg/machine/qemu/machine_test.go index 62ca6068a..4c393d0f4 100644 --- a/pkg/machine/qemu/machine_test.go +++ b/pkg/machine/qemu/machine_test.go @@ -1,3 +1,6 @@ +//go:build (amd64 && !windows) || (arm64 && !windows) +// +build amd64,!windows arm64,!windows + package qemu import ( diff --git a/pkg/machine/wsl/machine.go b/pkg/machine/wsl/machine.go index 075f42cb2..492b66659 100644 --- a/pkg/machine/wsl/machine.go +++ b/pkg/machine/wsl/machine.go @@ -18,6 +18,7 @@ import ( "strings" "time" + "github.com/containers/common/pkg/config" "github.com/containers/podman/v4/pkg/machine" "github.com/containers/podman/v4/utils" "github.com/containers/storage/pkg/homedir" @@ -116,6 +117,43 @@ ln -fs /home/[USER]/.config/systemd/[USER]/linger-example.service \ /home/[USER]/.config/systemd/[USER]/default.target.wants/linger-example.service ` +const proxyConfigSetup = `#!/bin/bash + +SYSTEMD_CONF=/etc/systemd/system.conf.d/default-env.conf +ENVD_CONF=/etc/environment.d/default-env.conf +PROFILE_CONF=/etc/profile.d/default-env.sh + +IFS="|" +read proxies + +mkdir -p /etc/profile.d /etc/environment.d /etc/systemd/system.conf.d/ +rm -f $SYSTEMD_CONF +for proxy in $proxies; do + output+="$proxy " +done +echo "[Manager]" >> $SYSTEMD_CONF +echo -ne "DefaultEnvironment=" >> $SYSTEMD_CONF + +echo $output >> $SYSTEMD_CONF +rm -f $ENVD_CONF +for proxy in $proxies; do + echo "$proxy" >> $ENVD_CONF +done +rm -f $PROFILE_CONF +for proxy in $proxies; do + echo "export $proxy" >> $PROFILE_CONF +done +` + +const proxyConfigAttempt = `if [ -f /usr/local/bin/proxyinit ]; \ +then /usr/local/bin/proxyinit; \ +else exit 42; \ +fi` + +const clearProxySettings = `rm -f /etc/systemd/system.conf.d/default-env.conf \ + /etc/environment.d/default-env.conf \ + /etc/profile.d/default-env.sh` + const wslInstallError = `Could not %s. See previous output for any potential failure details. If you can not resolve the issue, and rerunning fails, try the "wsl --install" process outlined in the following article: @@ -300,6 +338,7 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) { return cont, err } + _ = setupWslProxyEnv() homeDir := homedir.Get() sshDir := filepath.Join(homeDir, ".ssh") v.IdentityPath = filepath.Join(sshDir, v.Name) @@ -526,6 +565,40 @@ func configureSystem(v *MachineVM, dist string) error { return nil } +func configureProxy(dist string, useProxy bool) error { + if !useProxy { + _ = runCmdPassThrough("wsl", "-d", dist, "sh", "-c", clearProxySettings) + return nil + } + var content string + for i, key := range config.ProxyEnv { + if value, _ := os.LookupEnv(key); len(value) > 0 { + var suffix string + if i < (len(config.ProxyEnv) - 1) { + suffix = "|" + } + content = fmt.Sprintf("%s%s=\"%s\"%s", content, key, value, suffix) + } + } + + if err := pipeCmdPassThrough("wsl", content, "-d", dist, "sh", "-c", proxyConfigAttempt); err != nil { + const failMessage = "Failure creating proxy configuration" + if exitErr, isExit := err.(*exec.ExitError); isExit && exitErr.ExitCode() != 42 { + return errors.Wrap(err, failMessage) + } + + fmt.Println("Installing proxy support") + _ = pipeCmdPassThrough("wsl", proxyConfigSetup, "-d", dist, "sh", "-c", + "cat > /usr/local/bin/proxyinit; chmod 755 /usr/local/bin/proxyinit") + + if err = pipeCmdPassThrough("wsl", content, "-d", dist, "/usr/local/bin/proxyinit"); err != nil { + return errors.Wrap(err, failMessage) + } + } + + return nil +} + func enableUserLinger(v *MachineVM, dist string) error { lingerCmd := "mkdir -p /var/lib/systemd/linger; touch /var/lib/systemd/linger/" + v.RemoteUsername if err := runCmdPassThrough("wsl", "-d", dist, "sh", "-c", lingerCmd); err != nil { @@ -555,6 +628,11 @@ func installScripts(dist string) error { return errors.Wrap(err, "could not create bootstrap script for guest OS") } + if err := pipeCmdPassThrough("wsl", proxyConfigSetup, "-d", dist, "sh", "-c", + "cat > /usr/local/bin/proxyinit; chmod 755 /usr/local/bin/proxyinit"); err != nil { + return errors.Wrap(err, "could not create proxyinit script for guest OS") + } + return nil } @@ -816,6 +894,26 @@ func pipeCmdPassThrough(name string, input string, arg ...string) error { return cmd.Run() } +func setupWslProxyEnv() (hasProxy bool) { + current, _ := os.LookupEnv("WSLENV") + for _, key := range config.ProxyEnv { + if value, _ := os.LookupEnv(key); len(value) < 1 { + continue + } + + hasProxy = true + delim := "" + if len(current) > 0 { + delim = ":" + } + current = fmt.Sprintf("%s%s%s/u", current, delim, key) + } + if hasProxy { + os.Setenv("WSLENV", current) + } + return +} + func (v *MachineVM) Set(_ string, opts machine.SetOptions) ([]error, error) { // If one setting fails to be applied, the others settings will not fail and still be applied. // The setting(s) that failed to be applied will have its errors returned in setErrors @@ -852,6 +950,10 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error { } dist := toDist(name) + useProxy := setupWslProxyEnv() + if err := configureProxy(dist, useProxy); err != nil { + return err + } err := runCmdPassThrough("wsl", "-d", dist, "/root/bootstrap") if err != nil { @@ -1553,3 +1655,7 @@ func (p *Provider) RemoveAndCleanMachines() error { } return prevErr } + +func (p *Provider) VMType() string { + return vmtype +} diff --git a/pkg/ps/ps.go b/pkg/ps/ps.go index 5fe1b83e2..7fc01de31 100644 --- a/pkg/ps/ps.go +++ b/pkg/ps/ps.go @@ -1,6 +1,8 @@ package ps import ( + "errors" + "fmt" "os" "path/filepath" "regexp" @@ -16,7 +18,6 @@ import ( psdefine "github.com/containers/podman/v4/pkg/ps/define" "github.com/containers/storage" "github.com/containers/storage/types" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -65,7 +66,7 @@ func GetContainerLists(runtime *libpod.Runtime, options entities.ContainerListOp for _, con := range cons { listCon, err := ListContainerBatch(runtime, con, options) switch { - case errors.Cause(err) == define.ErrNoSuchCtr: + case errors.Is(err, define.ErrNoSuchCtr): continue case err != nil: return nil, err @@ -108,7 +109,7 @@ func GetExternalContainerLists(runtime *libpod.Runtime) ([]entities.ListContaine for _, con := range externCons { listCon, err := ListStorageContainer(runtime, con) switch { - case errors.Cause(err) == types.ErrLoadError: + case errors.Is(err, types.ErrLoadError): continue case err != nil: return nil, err @@ -138,19 +139,19 @@ func ListContainerBatch(rt *libpod.Runtime, ctr *libpod.Container, opts entities batchErr := ctr.Batch(func(c *libpod.Container) error { if opts.Sync { if err := c.Sync(); err != nil { - return errors.Wrapf(err, "unable to update container state from OCI runtime") + return fmt.Errorf("unable to update container state from OCI runtime: %w", err) } } conConfig = c.Config() conState, err = c.State() if err != nil { - return errors.Wrapf(err, "unable to obtain container state") + return fmt.Errorf("unable to obtain container state: %w", err) } exitCode, exited, err = c.ExitCode() if err != nil { - return errors.Wrapf(err, "unable to obtain container exit code") + return fmt.Errorf("unable to obtain container exit code: %w", err) } startedTime, err = c.StartedTime() if err != nil { @@ -163,7 +164,7 @@ func ListContainerBatch(rt *libpod.Runtime, ctr *libpod.Container, opts entities pid, err = c.PID() if err != nil { - return errors.Wrapf(err, "unable to obtain container pid") + return fmt.Errorf("unable to obtain container pid: %w", err) } if !opts.Size && !opts.Namespace { @@ -237,8 +238,8 @@ func ListContainerBatch(rt *libpod.Runtime, ctr *libpod.Container, opts entities if opts.Pod && len(conConfig.Pod) > 0 { podName, err := rt.GetName(conConfig.Pod) if err != nil { - if errors.Cause(err) == define.ErrNoSuchCtr { - return entities.ListContainer{}, errors.Wrapf(define.ErrNoSuchPod, "could not find container %s pod (id %s) in state", conConfig.ID, conConfig.Pod) + if errors.Is(err, define.ErrNoSuchCtr) { + return entities.ListContainer{}, fmt.Errorf("could not find container %s pod (id %s) in state: %w", conConfig.ID, conConfig.Pod, define.ErrNoSuchPod) } return entities.ListContainer{}, err } @@ -282,7 +283,7 @@ func ListStorageContainer(rt *libpod.Runtime, ctr storage.Container) (entities.L buildahCtr, err := rt.IsBuildahContainer(ctr.ID) if err != nil { - return ps, errors.Wrapf(err, "error determining buildah container for container %s", ctr.ID) + return ps, fmt.Errorf("error determining buildah container for container %s: %w", ctr.ID, err) } if buildahCtr { @@ -311,7 +312,7 @@ func ListStorageContainer(rt *libpod.Runtime, ctr storage.Container) (entities.L func getNamespaceInfo(path string) (string, error) { val, err := os.Readlink(path) if err != nil { - return "", errors.Wrapf(err, "error getting info from %q", path) + return "", fmt.Errorf("error getting info from %q: %w", path, err) } return getStrFromSquareBrackets(val), nil } diff --git a/pkg/specgen/container_validate.go b/pkg/specgen/container_validate.go index 5616a4511..e09757d1d 100644 --- a/pkg/specgen/container_validate.go +++ b/pkg/specgen/container_validate.go @@ -59,6 +59,7 @@ func (s *SpecGenerator) Validate() error { if s.ContainerBasicConfig.UtsNS.IsPod() { return errors.Wrap(ErrInvalidSpecConfig, "cannot set hostname when joining the pod UTS namespace") } + return errors.Wrap(ErrInvalidSpecConfig, "cannot set hostname when running in the host UTS namespace") } // systemd values must be true, false, or always diff --git a/pkg/specgen/generate/container.go b/pkg/specgen/generate/container.go index 30c759495..8fdd87adf 100644 --- a/pkg/specgen/generate/container.go +++ b/pkg/specgen/generate/container.go @@ -38,10 +38,19 @@ func getImageFromSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGen } // Need to look up image. - image, resolvedName, err := r.LibimageRuntime().LookupImage(s.Image, nil) + lookupOptions := &libimage.LookupImageOptions{ManifestList: true} + image, resolvedName, err := r.LibimageRuntime().LookupImage(s.Image, lookupOptions) if err != nil { return nil, "", nil, err } + manifestList, err := image.ToManifestList() + // only process if manifest list found otherwise expect it to be regular image + if err == nil { + image, err = manifestList.LookupInstance(ctx, s.ImageArch, s.ImageOS, s.ImageVariant) + if err != nil { + return nil, "", nil, err + } + } s.SetImage(image, resolvedName) inspectData, err := image.Inspect(ctx, nil) if err != nil { diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go index 6b2e90b22..f31e46090 100644 --- a/pkg/specgen/generate/container_create.go +++ b/pkg/specgen/generate/container_create.go @@ -133,6 +133,12 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener options = append(options, libpod.WithRootFSFromImage(newImage.ID(), resolvedImageName, s.RawImageName)) } + + _, err = rt.LookupPod(s.Hostname) + if len(s.Hostname) > 0 && !s.UtsNS.IsPrivate() && err == nil { + // ok, we are incorrectly setting the pod as the hostname, lets undo that before validation + s.Hostname = "" + } if err := s.Validate(); err != nil { return nil, nil, nil, errors.Wrap(err, "invalid config provided") } diff --git a/pkg/specgen/generate/kube/kube.go b/pkg/specgen/generate/kube/kube.go index 689c740f0..c254b8192 100644 --- a/pkg/specgen/generate/kube/kube.go +++ b/pkg/specgen/generate/kube/kube.go @@ -511,12 +511,12 @@ func makeHealthCheck(inCmd string, interval int32, retries int32, timeout int32, cmd := []string{} if inCmd == "none" { - cmd = []string{"NONE"} + cmd = []string{define.HealthConfigTestNone} } else { err := json.Unmarshal([]byte(inCmd), &cmd) if err != nil { // ...otherwise pass it to "/bin/sh -c" inside the container - cmd = []string{"CMD-SHELL"} + cmd = []string{define.HealthConfigTestCmdShell} cmd = append(cmd, strings.Split(inCmd, " ")...) } } @@ -810,8 +810,8 @@ func envVarValueResourceFieldRef(env v1.EnvVar, opts *CtrSpecGenOptions) (*strin } // k8s rounds up the result to the nearest integer - intValue := int(math.Ceil(value.AsApproximateFloat64() / divisor.AsApproximateFloat64())) - stringValue := strconv.Itoa(intValue) + intValue := int64(math.Ceil(value.AsApproximateFloat64() / divisor.AsApproximateFloat64())) + stringValue := strconv.FormatInt(intValue, 10) return &stringValue, nil } diff --git a/pkg/specgen/generate/kube/play_test.go b/pkg/specgen/generate/kube/play_test.go index e01d62b08..466dab610 100644 --- a/pkg/specgen/generate/kube/play_test.go +++ b/pkg/specgen/generate/kube/play_test.go @@ -2,7 +2,6 @@ package kube import ( "encoding/json" - "fmt" "math" "runtime" "strconv" @@ -777,8 +776,7 @@ func TestEnvVarValue(t *testing.T) { if test.expected == nilString { assert.Nil(t, result) } else { - fmt.Println(*result, test.expected) - assert.Equal(t, &(test.expected), result) + assert.Equal(t, test.expected, *result) } }) } diff --git a/pkg/specgen/generate/namespaces.go b/pkg/specgen/generate/namespaces.go index 4224d16ce..a3719d58e 100644 --- a/pkg/specgen/generate/namespaces.go +++ b/pkg/specgen/generate/namespaces.go @@ -176,7 +176,14 @@ func namespaceOptions(s *specgen.SpecGenerator, rt *libpod.Runtime, pod *libpod. if pod == nil || infraCtr == nil { return nil, errNoInfra } - toReturn = append(toReturn, libpod.WithUTSNSFrom(infraCtr)) + if pod.NamespaceMode(spec.UTSNamespace) == host { + // adding infra as a nsCtr is not what we want to do when uts == host + // this leads the new ctr to try to add an ns path which is should not in this mode + logrus.Debug("pod has host uts, not adding infra as a nsCtr") + s.UtsNS = specgen.Namespace{NSMode: specgen.Host} + } else { + toReturn = append(toReturn, libpod.WithUTSNSFrom(infraCtr)) + } case specgen.FromContainer: utsCtr, err := rt.LookupContainer(s.UtsNS.Value) if err != nil { diff --git a/pkg/specgen/generate/pod_create.go b/pkg/specgen/generate/pod_create.go index 4ac8a0aa2..59936c7a8 100644 --- a/pkg/specgen/generate/pod_create.go +++ b/pkg/specgen/generate/pod_create.go @@ -60,6 +60,7 @@ func MakePod(p *entities.PodSpec, rt *libpod.Runtime) (*libpod.Pod, error) { if err != nil { return nil, err } + spec.Pod = pod.ID() opts = append(opts, rt.WithPod(pod)) spec.CgroupParent = pod.CgroupParent() diff --git a/pkg/specgen/podspecgen.go b/pkg/specgen/podspecgen.go index 02ba06be1..64a79f4ee 100644 --- a/pkg/specgen/podspecgen.go +++ b/pkg/specgen/podspecgen.go @@ -77,6 +77,8 @@ type PodBasicConfig struct { // Any containers created within the pod will inherit the pod's userns settings. // Optional Userns Namespace `json:"userns,omitempty"` + // UtsNs is used to indicate the UTS mode the pod is in + UtsNs Namespace `json:"utsns,omitempty"` // Devices contains user specified Devices to be added to the Pod Devices []string `json:"pod_devices,omitempty"` // Sysctl sets kernel parameters for the pod diff --git a/pkg/specgen/specgen.go b/pkg/specgen/specgen.go index 79e20667b..42b89ece1 100644 --- a/pkg/specgen/specgen.go +++ b/pkg/specgen/specgen.go @@ -103,6 +103,12 @@ type ContainerBasicConfig struct { // RawImageName is the user-specified and unprocessed input referring // to a local or a remote image. RawImageName string `json:"raw_image_name,omitempty"` + // ImageOS is the user-specified image OS + ImageOS string `json:"image_os,omitempty"` + // ImageArch is the user-specified image architecture + ImageArch string `json:"image_arch,omitempty"` + // ImageVariant is the user-specified image variant + ImageVariant string `json:"image_variant,omitempty"` // RestartPolicy is the container's restart policy - an action which // will be taken when the container exits. // If not given, the default policy, which does nothing, will be used. diff --git a/pkg/specgen/volumes.go b/pkg/specgen/volumes.go index 5e1ea9a78..c9f944abf 100644 --- a/pkg/specgen/volumes.go +++ b/pkg/specgen/volumes.go @@ -37,7 +37,7 @@ type OverlayVolume struct { // ImageVolume is a volume based on a container image. The container image is // first mounted on the host and is then bind-mounted into the container. An -// ImageVolume is always mounted read only. +// ImageVolume is always mounted read-only. type ImageVolume struct { // Source is the source of the image volume. The image can be referred // to by name and by ID. diff --git a/pkg/specgenutil/specgen.go b/pkg/specgenutil/specgen.go index 8ad0a92e7..34350579d 100644 --- a/pkg/specgenutil/specgen.go +++ b/pkg/specgenutil/specgen.go @@ -873,23 +873,23 @@ func makeHealthCheckFromCli(inCmd, interval string, retries uint, timeout, start } var concat string - if cmdArr[0] == "CMD" || cmdArr[0] == "none" { // this is for compat, we are already split properly for most compat cases + if strings.ToUpper(cmdArr[0]) == define.HealthConfigTestCmd || strings.ToUpper(cmdArr[0]) == define.HealthConfigTestNone { // this is for compat, we are already split properly for most compat cases cmdArr = strings.Fields(inCmd) - } else if cmdArr[0] != "CMD-SHELL" { // this is for podman side of things, won't contain the keywords + } else if strings.ToUpper(cmdArr[0]) != define.HealthConfigTestCmdShell { // this is for podman side of things, won't contain the keywords if isArr && len(cmdArr) > 1 { // an array of consecutive commands - cmdArr = append([]string{"CMD"}, cmdArr...) + cmdArr = append([]string{define.HealthConfigTestCmd}, cmdArr...) } else { // one singular command if len(cmdArr) == 1 { concat = cmdArr[0] } else { concat = strings.Join(cmdArr[0:], " ") } - cmdArr = append([]string{"CMD-SHELL"}, concat) + cmdArr = append([]string{define.HealthConfigTestCmdShell}, concat) } } - if cmdArr[0] == "none" { // if specified to remove healtcheck - cmdArr = []string{"NONE"} + if strings.ToUpper(cmdArr[0]) == define.HealthConfigTestNone { // if specified to remove healtcheck + cmdArr = []string{define.HealthConfigTestNone} } // healthcheck is by default an array, so we simply pass the user input diff --git a/pkg/specgenutil/volumes.go b/pkg/specgenutil/volumes.go index 50d745380..016166a20 100644 --- a/pkg/specgenutil/volumes.go +++ b/pkg/specgenutil/volumes.go @@ -605,7 +605,7 @@ func getNamedVolume(args []string) (*specgen.NamedVolume, error) { // Parse the arguments into an image volume. An image volume is a volume based // on a container image. The container image is first mounted on the host and // is then bind-mounted into the container. An ImageVolume is always mounted -// read only. +// read-only. func getImageVolume(args []string) (*specgen.ImageVolume, error) { newVolume := new(specgen.ImageVolume) diff --git a/test/apiv2/40-pods.at b/test/apiv2/40-pods.at index 0a5201213..80724a8d9 100644 --- a/test/apiv2/40-pods.at +++ b/test/apiv2/40-pods.at @@ -134,4 +134,6 @@ t GET libpod/pods/json?filters='{"label":["testl' 400 \ t DELETE libpod/pods/foo 200 t DELETE "libpod/pods/foo (pod has already been deleted)" 404 +t_timeout 5 GET "libpod/pods/stats?stream=true&delay=1" 200 + # vim: filetype=sh diff --git a/test/apiv2/python/rest_api/fixtures/api_testcase.py b/test/apiv2/python/rest_api/fixtures/api_testcase.py index 155e93928..f47136555 100644 --- a/test/apiv2/python/rest_api/fixtures/api_testcase.py +++ b/test/apiv2/python/rest_api/fixtures/api_testcase.py @@ -64,6 +64,10 @@ class APITestCase(unittest.TestCase): def uri(path): return APITestCase.PODMAN_URL + "/v2.0.0/libpod" + path + @staticmethod + def compat_uri(path): + return APITestCase.PODMAN_URL + "/v3.0.0/" + path + def resolve_container(self, path): """Find 'first' container and return 'Id' formatted into given URI path.""" diff --git a/test/apiv2/python/rest_api/test_v2_0_0_container.py b/test/apiv2/python/rest_api/test_v2_0_0_container.py index a44786c0d..a6cd93a1a 100644 --- a/test/apiv2/python/rest_api/test_v2_0_0_container.py +++ b/test/apiv2/python/rest_api/test_v2_0_0_container.py @@ -1,10 +1,12 @@ import multiprocessing import queue import random +import subprocess import threading import unittest import requests +import os import time from dateutil.parser import parse @@ -358,5 +360,50 @@ class ContainerTestCase(APITestCase): self.assertEqual(1000, out["HostConfig"]["Memory"]) + +def execute_process(cmd): + return subprocess.run( + cmd, + shell=True, + check=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + +def create_named_network_ns(network_ns_name): + execute_process(f"ip netns add {network_ns_name}") + execute_process(f"ip netns exec {network_ns_name} ip link add enp2s0 type veth peer name eth0") + execute_process(f"ip netns exec {network_ns_name} ip addr add 10.0.1.0/24 dev eth0") + execute_process(f"ip netns exec {network_ns_name} ip link set eth0 up") + execute_process(f"ip netns exec {network_ns_name} ip link add enp2s1 type veth peer name eth1") + execute_process(f"ip netns exec {network_ns_name} ip addr add 10.0.2.0/24 dev eth1") + execute_process(f"ip netns exec {network_ns_name} ip link set eth1 up") + +def delete_named_network_ns(network_ns_name): + execute_process(f"ip netns delete {network_ns_name}") + +class ContainerCompatibleAPITestCase(APITestCase): + def test_inspect_network(self): + if os.getuid() != 0: + self.skipTest("test needs to be executed as root!") + try: + network_ns_name = "test-compat-api" + create_named_network_ns(network_ns_name) + self.podman.run("rm", "--all", "--force", check=True) + self.podman.run("run", "--net", f"ns:/run/netns/{network_ns_name}", "-d", "alpine", "top", check=True) + + r = requests.post(self.uri(self.resolve_container("/containers/{}/start"))) + self.assertIn(r.status_code, (204, 304), r.text) + + r = requests.get(self.compat_uri(self.resolve_container("/containers/{}/json"))) + self.assertEqual(r.status_code, 200, r.text) + self.assertId(r.content) + out = r.json() + + self.assertEqual("10.0.2.0", out["NetworkSettings"]["SecondaryIPAddresses"][0]["Addr"]) + self.assertEqual(24, out["NetworkSettings"]["SecondaryIPAddresses"][0]["PrefixLen"]) + finally: + delete_named_network_ns(network_ns_name) + if __name__ == "__main__": unittest.main() diff --git a/test/apiv2/test-apiv2 b/test/apiv2/test-apiv2 index 8548d84e5..0fd282854 100755 --- a/test/apiv2/test-apiv2 +++ b/test/apiv2/test-apiv2 @@ -56,6 +56,9 @@ fi # Path to podman binary PODMAN_BIN=${PODMAN:-${CONTAINERS_HELPER_BINARY_DIR}/podman} +# Timeout for streamed responses +CURL_TIMEOUT=0 + # Cleanup handlers clean_up_server() { if [ -n "$service_pid" ]; then @@ -217,6 +220,21 @@ function jsonify() { } ####### +# t_timeout # Timeout wrapper for test helper +####### +function t_timeout() { + CURL_TIMEOUT=$1; shift + local min_runtime=$((CURL_TIMEOUT - 1)) + start=`date +%s` + t $@ + local end=`date +%s` + local runtime=$((end-start)) + if ! [[ "$runtime" -ge "$min_runtime" ]]; then + die "Error: Streaming time should be greater or equal to '$min_runtime'" + fi +} + +####### # t # Main test helper ####### function t() { @@ -226,6 +244,12 @@ function t() { local content_type="application/json" local testname="$method $path" + + if [[ $CURL_TIMEOUT != 0 ]]; then + local c_timeout=$CURL_TIMEOUT + curl_args+=("-m $CURL_TIMEOUT") + CURL_TIMEOUT=0 # 'consume' timeout + fi # POST and PUT requests may be followed by one or more key=value pairs. # Slurp the command line until we see a 3-digit status code. if [[ $method = "POST" || $method == "PUT" ]]; then @@ -291,7 +315,7 @@ function t() { -o $WORKDIR/curl.result.out "$url"); rc=$?; } || : # Any error from curl is instant bad news, from which we can't recover - if [[ $rc -ne 0 ]]; then + if [[ $rc -ne 0 ]] && [[ $c_timeout -eq 0 ]]; then die "curl failure ($rc) on $url - cannot continue" fi diff --git a/test/compose/disable_healthcheck/docker-compose.yml b/test/compose/disable_healthcheck/docker-compose.yml new file mode 100644 index 000000000..1f608c895 --- /dev/null +++ b/test/compose/disable_healthcheck/docker-compose.yml @@ -0,0 +1,10 @@ +version: "3.7" +services: + noHc: + image: alpine + container_name: noHc + ports: + - "4000:80" + restart: unless-stopped + healthcheck: + disable: true diff --git a/test/compose/disable_healthcheck/tests.sh b/test/compose/disable_healthcheck/tests.sh new file mode 100644 index 000000000..2460a687e --- /dev/null +++ b/test/compose/disable_healthcheck/tests.sh @@ -0,0 +1,2 @@ +podman inspect --format='{{.Config.Healthcheck.Test}}' noHc +like $output "[NONE]" "$testname: healthcheck properly disabled" diff --git a/test/compose/update_network_mtu/docker-compose.yml b/test/compose/update_network_mtu/docker-compose.yml new file mode 100644 index 000000000..fabd7b4f2 --- /dev/null +++ b/test/compose/update_network_mtu/docker-compose.yml @@ -0,0 +1,26 @@ +version: '3.7' + +services: + nginx: + image: alpine + ports: + - 8000:5000 + networks: + - default + - macvlan_net + +networks: + default: + driver: bridge + driver_opts: + com.docker.network.bridge.name: docker0 + com.docker.network.driver.mtu: 9000 + macvlan_net: + driver: macvlan + driver_opts: + mode: bridge + ipam: + config: + - + subnet: 192.168.20.0/24 + gateway: 192.168.20.1 diff --git a/test/compose/update_network_mtu/tests.sh b/test/compose/update_network_mtu/tests.sh new file mode 100644 index 000000000..57411eb34 --- /dev/null +++ b/test/compose/update_network_mtu/tests.sh @@ -0,0 +1,10 @@ +# -*- bash -*- + +podman network inspect --format='{{ range . }} {{ .Options.mtu }} {{ end }}' update_network_mtu_default +like "$output" "9000" "$testname : network mtu is set" + +podman network inspect --format='{{ range . }} {{ .NetworkInterface }} {{ end }}' update_network_mtu_default +like "$output" "docker0" "$testname: network interface is set" + +podman network inspect --format='{{ range . }} {{ .Options.mode }} {{ end }}' update_network_mtu_macvlan_net +like "$output" "bridge" "$testname : network mode is set" diff --git a/test/e2e/benchmarks_test.go b/test/e2e/benchmarks_test.go index ef4d51893..fe045b97a 100644 --- a/test/e2e/benchmarks_test.go +++ b/test/e2e/benchmarks_test.go @@ -132,7 +132,7 @@ var _ = Describe("Podman Benchmark Suite", func() { Measure("Podman Benchmark Suite", func(b Benchmarker) { registryOptions := &podmanRegistry.Options{ - Image: "docker-archive:" + imageTarPath(registry), + Image: "docker-archive:" + imageTarPath(REGISTRY_IMAGE), } for i := range allBenchmarks { diff --git a/test/e2e/build/Containerfile.with-platform b/test/e2e/build/Containerfile.with-platform new file mode 100644 index 000000000..3bb585a0a --- /dev/null +++ b/test/e2e/build/Containerfile.with-platform @@ -0,0 +1 @@ +FROM --platform=$TARGETPLATFORM alpine diff --git a/test/e2e/checkpoint_test.go b/test/e2e/checkpoint_test.go index be976207e..5ccafeb37 100644 --- a/test/e2e/checkpoint_test.go +++ b/test/e2e/checkpoint_test.go @@ -339,7 +339,7 @@ var _ = Describe("Podman checkpoint", func() { It("podman checkpoint container with established tcp connections", func() { // Broken on Ubuntu. SkipIfNotFedora() - localRunString := getRunString([]string{redis}) + localRunString := getRunString([]string{REDIS_IMAGE}) session := podmanTest.Podman(localRunString) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) @@ -1052,7 +1052,7 @@ var _ = Describe("Podman checkpoint", func() { It("podman checkpoint and restore container with different port mappings", func() { randomPort, err := utils.GetRandomPort() Expect(err).ShouldNot(HaveOccurred()) - localRunString := getRunString([]string{"-p", fmt.Sprintf("%d:6379", randomPort), "--rm", redis}) + localRunString := getRunString([]string{"-p", fmt.Sprintf("%d:6379", randomPort), "--rm", REDIS_IMAGE}) session := podmanTest.Podman(localRunString) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) @@ -1360,11 +1360,11 @@ var _ = Describe("Podman checkpoint", func() { }) It("podman checkpoint and restore containers with --print-stats", func() { - session1 := podmanTest.Podman(getRunString([]string{redis})) + session1 := podmanTest.Podman(getRunString([]string{REDIS_IMAGE})) session1.WaitWithDefaultTimeout() Expect(session1).Should(Exit(0)) - session2 := podmanTest.Podman(getRunString([]string{redis, "top"})) + session2 := podmanTest.Podman(getRunString([]string{REDIS_IMAGE, "top"})) session2.WaitWithDefaultTimeout() Expect(session2).Should(Exit(0)) diff --git a/test/e2e/commit_test.go b/test/e2e/commit_test.go index c82e5e471..452a378c2 100644 --- a/test/e2e/commit_test.go +++ b/test/e2e/commit_test.go @@ -362,7 +362,7 @@ var _ = Describe("Podman commit", func() { Expect(images[0].Config.ExposedPorts).To(HaveKey("80/tcp")) name = "testcon2" - s = podmanTest.Podman([]string{"run", "--name", name, "-d", nginx}) + s = podmanTest.Podman([]string{"run", "--name", name, "-d", NGINX_IMAGE}) s.WaitWithDefaultTimeout() Expect(s).Should(Exit(0)) diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go index 261db8a9a..43367cf63 100644 --- a/test/e2e/common_test.go +++ b/test/e2e/common_test.go @@ -2,6 +2,7 @@ package integration import ( "bytes" + "errors" "fmt" "io/ioutil" "math/rand" @@ -30,16 +31,15 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" . "github.com/onsi/gomega/gexec" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) var ( //lint:ignore ST1003 - PODMAN_BINARY string //nolint:revive,stylecheck - INTEGRATION_ROOT string //nolint:revive,stylecheck - CGROUP_MANAGER = "systemd" //nolint:revive,stylecheck - RESTORE_IMAGES = []string{ALPINE, BB, nginx} //nolint:revive,stylecheck + PODMAN_BINARY string //nolint:revive,stylecheck + INTEGRATION_ROOT string //nolint:revive,stylecheck + CGROUP_MANAGER = "systemd" //nolint:revive,stylecheck + RESTORE_IMAGES = []string{ALPINE, BB, NGINX_IMAGE} //nolint:revive,stylecheck defaultWaitTimeout = 90 CGROUPSV2, _ = cgroups.IsCgroup2UnifiedMode() ) @@ -115,7 +115,7 @@ var _ = SynchronizedBeforeSuite(func() []byte { podman := PodmanTestSetup("/tmp") // Pull cirros but don't put it into the cache - pullImages := []string{cirros, fedoraToolbox, volumeTest} + pullImages := []string{CIRROS_IMAGE, fedoraToolbox, volumeTest} pullImages = append(pullImages, CACHE_IMAGES...) for _, image := range pullImages { podman.createArtifact(image) @@ -464,7 +464,7 @@ func (p *PodmanTestIntegration) RunNginxWithHealthCheck(name string) (*PodmanSes podmanArgs = append(podmanArgs, "--name", name) } // curl without -f exits 0 even if http code >= 400! - podmanArgs = append(podmanArgs, "-dt", "-P", "--health-cmd", "curl -f http://localhost/", nginx) + podmanArgs = append(podmanArgs, "-dt", "-P", "--health-cmd", "curl -f http://localhost/", NGINX_IMAGE) session := p.Podman(podmanArgs) session.WaitWithDefaultTimeout() return session, session.OutputToString() @@ -618,14 +618,14 @@ func (p *PodmanTestIntegration) RunHealthCheck(cid string) error { restart := p.Podman([]string{"restart", cid}) restart.WaitWithDefaultTimeout() if restart.ExitCode() != 0 { - return errors.Errorf("unable to restart %s", cid) + return fmt.Errorf("unable to restart %s", cid) } } } fmt.Printf("Waiting for %s to pass healthcheck\n", cid) time.Sleep(1 * time.Second) } - return errors.Errorf("unable to detect %s as running", cid) + return fmt.Errorf("unable to detect %s as running", cid) } func (p *PodmanTestIntegration) CreateSeccompJSON(in []byte) (string, error) { @@ -1042,18 +1042,15 @@ var IPRegex = `(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01 // digShort execs into the given container and does a dig lookup with a timeout // backoff. If it gets a response, it ensures that the output is in the correct // format and iterates a string array for match -func digShort(container, lookupName string, matchNames []string, p *PodmanTestIntegration) { +func digShort(container, lookupName, expectedIP string, p *PodmanTestIntegration) { digInterval := time.Millisecond * 250 for i := 0; i < 6; i++ { time.Sleep(digInterval * time.Duration(i)) dig := p.Podman([]string{"exec", container, "dig", "+short", lookupName}) dig.WaitWithDefaultTimeout() - if dig.ExitCode() == 0 { - output := dig.OutputToString() - Expect(output).To(MatchRegexp(IPRegex)) - for _, name := range matchNames { - Expect(output).To(Equal(name)) - } + output := dig.OutputToString() + if dig.ExitCode() == 0 && output != "" { + Expect(output).To(Equal(expectedIP)) // success return } @@ -1064,13 +1061,13 @@ func digShort(container, lookupName string, matchNames []string, p *PodmanTestIn // WaitForFile to be created in defaultWaitTimeout seconds, returns false if file not created func WaitForFile(path string) (err error) { until := time.Now().Add(time.Duration(defaultWaitTimeout) * time.Second) - for i := 1; time.Now().Before(until); i++ { + for time.Now().Before(until) { _, err = os.Stat(path) switch { case err == nil: return nil case errors.Is(err, os.ErrNotExist): - time.Sleep(time.Duration(i) * time.Second) + time.Sleep(10 * time.Millisecond) default: return err } @@ -1078,18 +1075,21 @@ func WaitForFile(path string) (err error) { return err } -// WaitForService blocks, waiting for some service listening on given host:port +// WaitForService blocks for defaultWaitTimeout seconds, waiting for some service listening on given host:port func WaitForService(address url.URL) { // Wait for podman to be ready - var conn net.Conn var err error - for i := 1; i <= 5; i++ { + until := time.Now().Add(time.Duration(defaultWaitTimeout) * time.Second) + for time.Now().Before(until) { + var conn net.Conn conn, err = net.Dial("tcp", address.Host) - if err != nil { - // Podman not available yet... - time.Sleep(time.Duration(i) * time.Second) + if err == nil { + conn.Close() + break } + + // Podman not available yet... + time.Sleep(10 * time.Millisecond) } Expect(err).ShouldNot(HaveOccurred()) - conn.Close() } diff --git a/test/e2e/config.go b/test/e2e/config.go index fbcc9dfff..a8dd6301f 100644 --- a/test/e2e/config.go +++ b/test/e2e/config.go @@ -1,7 +1,7 @@ package integration var ( - redis = "quay.io/libpod/redis:alpine" + REDIS_IMAGE = "quay.io/libpod/redis:alpine" //nolint:revive,stylecheck fedoraMinimal = "registry.fedoraproject.org/fedora-minimal:34" ALPINE = "quay.io/libpod/alpine:latest" ALPINELISTTAG = "quay.io/libpod/alpine:3.10.2" @@ -10,9 +10,9 @@ var ( ALPINEAMD64ID = "961769676411f082461f9ef46626dd7a2d1e2b2a38e6a44364bcbecf51e66dd4" ALPINEARM64DIGEST = "quay.io/libpod/alpine@sha256:f270dcd11e64b85919c3bab66886e59d677cf657528ac0e4805d3c71e458e525" ALPINEARM64ID = "915beeae46751fc564998c79e73a1026542e945ca4f73dc841d09ccc6c2c0672" - infra = "k8s.gcr.io/pause:3.2" + INFRA_IMAGE = "k8s.gcr.io/pause:3.2" //nolint:revive,stylecheck BB = "quay.io/libpod/busybox:latest" - healthcheck = "quay.io/libpod/alpine_healthcheck:latest" + HEALTHCHECK_IMAGE = "quay.io/libpod/alpine_healthcheck:latest" //nolint:revive,stylecheck ImageCacheDir = "/tmp/podman/imagecachedir" fedoraToolbox = "registry.fedoraproject.org/fedora-toolbox:36" volumeTest = "quay.io/libpod/volume-plugin-test-img:20220623" diff --git a/test/e2e/config_amd64.go b/test/e2e/config_amd64.go index c4cb97b2e..f32542df8 100644 --- a/test/e2e/config_amd64.go +++ b/test/e2e/config_amd64.go @@ -1,16 +1,16 @@ package integration var ( - STORAGE_FS = "vfs" //nolint:revive,stylecheck - STORAGE_OPTIONS = "--storage-driver vfs" //nolint:revive,stylecheck - ROOTLESS_STORAGE_FS = "vfs" //nolint:revive,stylecheck - ROOTLESS_STORAGE_OPTIONS = "--storage-driver vfs" //nolint:revive,stylecheck - CACHE_IMAGES = []string{ALPINE, BB, fedoraMinimal, nginx, redis, registry, infra, labels, healthcheck, UBI_INIT, UBI_MINIMAL, fedoraToolbox} //nolint:revive,stylecheck - nginx = "quay.io/libpod/alpine_nginx:latest" - BB_GLIBC = "docker.io/library/busybox:glibc" //nolint:revive,stylecheck - registry = "quay.io/libpod/registry:2.6" - labels = "quay.io/libpod/alpine_labels:latest" - UBI_MINIMAL = "registry.access.redhat.com/ubi8-minimal" //nolint:revive,stylecheck - UBI_INIT = "registry.access.redhat.com/ubi8-init" //nolint:revive,stylecheck - cirros = "quay.io/libpod/cirros:latest" + STORAGE_FS = "vfs" //nolint:revive,stylecheck + STORAGE_OPTIONS = "--storage-driver vfs" //nolint:revive,stylecheck + ROOTLESS_STORAGE_FS = "vfs" //nolint:revive,stylecheck + ROOTLESS_STORAGE_OPTIONS = "--storage-driver vfs" //nolint:revive,stylecheck + CACHE_IMAGES = []string{ALPINE, BB, fedoraMinimal, NGINX_IMAGE, REDIS_IMAGE, REGISTRY_IMAGE, INFRA_IMAGE, LABELS_IMAGE, HEALTHCHECK_IMAGE, UBI_INIT, UBI_MINIMAL, fedoraToolbox} //nolint:revive,stylecheck + NGINX_IMAGE = "quay.io/libpod/alpine_nginx:latest" //nolint:revive,stylecheck + BB_GLIBC = "docker.io/library/busybox:glibc" //nolint:revive,stylecheck + REGISTRY_IMAGE = "quay.io/libpod/registry:2.6" //nolint:revive,stylecheck + LABELS_IMAGE = "quay.io/libpod/alpine_labels:latest" //nolint:revive,stylecheck + UBI_MINIMAL = "registry.access.redhat.com/ubi8-minimal" //nolint:revive,stylecheck + UBI_INIT = "registry.access.redhat.com/ubi8-init" //nolint:revive,stylecheck + CIRROS_IMAGE = "quay.io/libpod/cirros:latest" //nolint:revive,stylecheck ) diff --git a/test/e2e/config_ppc64le.go b/test/e2e/config_ppc64le.go index 569a34efb..a4bec748a 100644 --- a/test/e2e/config_ppc64le.go +++ b/test/e2e/config_ppc64le.go @@ -5,9 +5,9 @@ var ( STORAGE_OPTIONS = "--storage-driver overlay" ROOTLESS_STORAGE_FS = "vfs" ROOTLESS_STORAGE_OPTIONS = "--storage-driver vfs" - CACHE_IMAGES = []string{ALPINE, BB, fedoraMinimal, nginx, redis, infra, labels} - nginx = "quay.io/libpod/alpine_nginx-ppc64le:latest" + CACHE_IMAGES = []string{ALPINE, BB, fedoraMinimal, NGINX_IMAGE, REDIS_IMAGE, INFRA_IMAGE, LABELS_IMAGE} + NGINX_IMAGE = "quay.io/libpod/alpine_nginx-ppc64le:latest" BB_GLIBC = "docker.io/ppc64le/busybox:glibc" - labels = "quay.io/libpod/alpine_labels-ppc64le:latest" - registry string + LABELS_IMAGE = "quay.io/libpod/alpine_labels-ppc64le:latest" + REGISTRY_IMAGE string ) diff --git a/test/e2e/container_inspect_test.go b/test/e2e/container_inspect_test.go index 5aed943da..436c60c05 100644 --- a/test/e2e/container_inspect_test.go +++ b/test/e2e/container_inspect_test.go @@ -58,7 +58,7 @@ var _ = Describe("Podman container inspect", func() { It("podman inspect shows exposed ports on image", func() { name := "testcon" - session := podmanTest.Podman([]string{"run", "-d", "--expose", "8989", "--name", name, nginx}) + session := podmanTest.Podman([]string{"run", "-d", "--expose", "8989", "--name", name, NGINX_IMAGE}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) diff --git a/test/e2e/create_test.go b/test/e2e/create_test.go index 63544d579..9679aad24 100644 --- a/test/e2e/create_test.go +++ b/test/e2e/create_test.go @@ -63,7 +63,7 @@ var _ = Describe("Podman create", func() { lock := GetPortLock("5000") defer lock.Unlock() - session := podmanTest.Podman([]string{"run", "-d", "--name", "registry", "-p", "5000:5000", registry, "/entrypoint.sh", "/etc/docker/registry/config.yml"}) + session := podmanTest.Podman([]string{"run", "-d", "--name", "registry", "-p", "5000:5000", REGISTRY_IMAGE, "/entrypoint.sh", "/etc/docker/registry/config.yml"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) @@ -273,7 +273,7 @@ var _ = Describe("Podman create", func() { It("podman run entrypoint and cmd test", func() { name := "test101" - create := podmanTest.Podman([]string{"create", "--name", name, redis}) + create := podmanTest.Podman([]string{"create", "--name", name, REDIS_IMAGE}) create.WaitWithDefaultTimeout() Expect(create).Should(Exit(0)) @@ -560,7 +560,7 @@ var _ = Describe("Podman create", func() { session = podmanTest.Podman([]string{"create", "--umask", "9999", "--name", "bad", ALPINE}) session.WaitWithDefaultTimeout() Expect(session).To(ExitWithError()) - Expect(session.ErrorToString()).To(ContainSubstring("Invalid umask")) + Expect(session.ErrorToString()).To(ContainSubstring("invalid umask")) }) It("create container in pod with IP should fail", func() { diff --git a/test/e2e/generate_systemd_test.go b/test/e2e/generate_systemd_test.go index 08e8fbc8c..45a2f1f86 100644 --- a/test/e2e/generate_systemd_test.go +++ b/test/e2e/generate_systemd_test.go @@ -111,7 +111,7 @@ var _ = Describe("Podman generate systemd", func() { }) It("podman generate systemd", func() { - n := podmanTest.Podman([]string{"run", "--name", "nginx", "-dt", nginx}) + n := podmanTest.Podman([]string{"run", "--name", "nginx", "-dt", NGINX_IMAGE}) n.WaitWithDefaultTimeout() Expect(n).Should(Exit(0)) @@ -124,7 +124,7 @@ var _ = Describe("Podman generate systemd", func() { }) It("podman generate systemd --files --name", func() { - n := podmanTest.Podman([]string{"run", "--name", "nginx", "-dt", nginx}) + n := podmanTest.Podman([]string{"run", "--name", "nginx", "-dt", NGINX_IMAGE}) n.WaitWithDefaultTimeout() Expect(n).Should(Exit(0)) @@ -139,7 +139,7 @@ var _ = Describe("Podman generate systemd", func() { }) It("podman generate systemd with timeout", func() { - n := podmanTest.Podman([]string{"run", "--name", "nginx", "-dt", nginx}) + n := podmanTest.Podman([]string{"run", "--name", "nginx", "-dt", NGINX_IMAGE}) n.WaitWithDefaultTimeout() Expect(n).Should(Exit(0)) @@ -159,7 +159,7 @@ var _ = Describe("Podman generate systemd", func() { }) It("podman generate systemd with user-defined dependencies", func() { - n := podmanTest.Podman([]string{"run", "--name", "nginx", "-dt", nginx}) + n := podmanTest.Podman([]string{"run", "--name", "nginx", "-dt", NGINX_IMAGE}) n.WaitWithDefaultTimeout() Expect(n).Should(Exit(0)) diff --git a/test/e2e/healthcheck_run_test.go b/test/e2e/healthcheck_run_test.go index add739988..fd4e763f9 100644 --- a/test/e2e/healthcheck_run_test.go +++ b/test/e2e/healthcheck_run_test.go @@ -45,7 +45,7 @@ var _ = Describe("Podman healthcheck run", func() { }) It("podman disable healthcheck with --no-healthcheck on valid container", func() { - session := podmanTest.Podman([]string{"run", "-dt", "--no-healthcheck", "--name", "hc", healthcheck}) + session := podmanTest.Podman([]string{"run", "-dt", "--no-healthcheck", "--name", "hc", HEALTHCHECK_IMAGE}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) hc := podmanTest.Podman([]string{"healthcheck", "run", "hc"}) @@ -54,7 +54,7 @@ var _ = Describe("Podman healthcheck run", func() { }) It("podman disable healthcheck with --no-healthcheck must not show starting on status", func() { - session := podmanTest.Podman([]string{"run", "-dt", "--no-healthcheck", "--name", "hc", healthcheck}) + session := podmanTest.Podman([]string{"run", "-dt", "--no-healthcheck", "--name", "hc", HEALTHCHECK_IMAGE}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) hc := podmanTest.Podman([]string{"container", "inspect", "--format", "{{.State.Health.Status}}", "hc"}) @@ -98,7 +98,7 @@ var _ = Describe("Podman healthcheck run", func() { }) It("podman disable healthcheck with --health-cmd=none on valid container", func() { - session := podmanTest.Podman([]string{"run", "-dt", "--health-cmd", "none", "--name", "hc", healthcheck}) + session := podmanTest.Podman([]string{"run", "-dt", "--health-cmd", "none", "--name", "hc", HEALTHCHECK_IMAGE}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) hc := podmanTest.Podman([]string{"healthcheck", "run", "hc"}) @@ -108,7 +108,7 @@ var _ = Describe("Podman healthcheck run", func() { It("podman healthcheck on valid container", func() { Skip("Extremely consistent flake - re-enable on debugging") - session := podmanTest.Podman([]string{"run", "-dt", "--name", "hc", healthcheck}) + session := podmanTest.Podman([]string{"run", "-dt", "--name", "hc", HEALTHCHECK_IMAGE}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) @@ -143,7 +143,7 @@ var _ = Describe("Podman healthcheck run", func() { }) It("podman healthcheck on stopped container", func() { - session := podmanTest.Podman([]string{"run", "-dt", "--name", "hc", healthcheck, "ls"}) + session := podmanTest.Podman([]string{"run", "-dt", "--name", "hc", HEALTHCHECK_IMAGE, "ls"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) diff --git a/test/e2e/inspect_test.go b/test/e2e/inspect_test.go index 6fe850f0b..1ce2fa93d 100644 --- a/test/e2e/inspect_test.go +++ b/test/e2e/inspect_test.go @@ -182,8 +182,8 @@ var _ = Describe("Podman inspect", func() { }) It("podman inspect shows healthcheck on docker image", func() { - podmanTest.AddImageToRWStore(healthcheck) - session := podmanTest.Podman([]string{"inspect", "--format=json", healthcheck}) + podmanTest.AddImageToRWStore(HEALTHCHECK_IMAGE) + session := podmanTest.Podman([]string{"inspect", "--format=json", HEALTHCHECK_IMAGE}) session.WaitWithDefaultTimeout() imageData := session.InspectImageJSON() Expect(imageData[0].HealthCheck.Timeout).To(BeNumerically("==", 3000000000)) diff --git a/test/e2e/manifest_test.go b/test/e2e/manifest_test.go index 06dbbb539..2f8b47e25 100644 --- a/test/e2e/manifest_test.go +++ b/test/e2e/manifest_test.go @@ -295,7 +295,7 @@ var _ = Describe("Podman manifest", func() { It("authenticated push", func() { registryOptions := &podmanRegistry.Options{ - Image: "docker-archive:" + imageTarPath(registry), + Image: "docker-archive:" + imageTarPath(REGISTRY_IMAGE), } registry, err := podmanRegistry.StartWithOptions(registryOptions) Expect(err).To(BeNil()) diff --git a/test/e2e/network_test.go b/test/e2e/network_test.go index 2fdd62f7e..d4f60d3e4 100644 --- a/test/e2e/network_test.go +++ b/test/e2e/network_test.go @@ -507,14 +507,14 @@ var _ = Describe("Podman network", func() { interval *= 2 } - top := podmanTest.Podman([]string{"run", "-dt", "--name=web", "--network=" + netName, "--network-alias=web1", "--network-alias=web2", nginx}) + top := podmanTest.Podman([]string{"run", "-dt", "--name=web", "--network=" + netName, "--network-alias=web1", "--network-alias=web2", NGINX_IMAGE}) top.WaitWithDefaultTimeout() Expect(top).Should(Exit(0)) interval = 250 * time.Millisecond // Wait for the nginx service to be running for i := 0; i < 6; i++ { // Test curl against the container's name - c1 := podmanTest.Podman([]string{"run", "--dns-search", "dns.podman", "--network=" + netName, nginx, "curl", "web"}) + c1 := podmanTest.Podman([]string{"run", "--dns-search", "dns.podman", "--network=" + netName, NGINX_IMAGE, "curl", "web"}) c1.WaitWithDefaultTimeout() worked = c1.ExitCode() == 0 if worked { @@ -527,12 +527,12 @@ var _ = Describe("Podman network", func() { // Nginx is now running so no need to do a loop // Test against the first alias - c2 := podmanTest.Podman([]string{"run", "--dns-search", "dns.podman", "--network=" + netName, nginx, "curl", "web1"}) + c2 := podmanTest.Podman([]string{"run", "--dns-search", "dns.podman", "--network=" + netName, NGINX_IMAGE, "curl", "web1"}) c2.WaitWithDefaultTimeout() Expect(c2).Should(Exit(0)) // Test against the second alias - c3 := podmanTest.Podman([]string{"run", "--dns-search", "dns.podman", "--network=" + netName, nginx, "curl", "web2"}) + c3 := podmanTest.Podman([]string{"run", "--dns-search", "dns.podman", "--network=" + netName, NGINX_IMAGE, "curl", "web2"}) c3.WaitWithDefaultTimeout() Expect(c3).Should(Exit(0)) }) @@ -558,14 +558,14 @@ var _ = Describe("Podman network", func() { interval *= 2 } - top := podmanTest.Podman([]string{"run", "-dt", "--name=web", "--network=" + netName, "--network-alias=web1", "--network-alias=web2", nginx}) + top := podmanTest.Podman([]string{"run", "-dt", "--name=web", "--network=" + netName, "--network-alias=web1", "--network-alias=web2", NGINX_IMAGE}) top.WaitWithDefaultTimeout() Expect(top).Should(Exit(0)) interval = 250 * time.Millisecond // Wait for the nginx service to be running for i := 0; i < 6; i++ { // Test curl against the container's name - c1 := podmanTest.Podman([]string{"run", "--dns-search", "dns.podman", "--network=" + netName, nginx, "curl", "web"}) + c1 := podmanTest.Podman([]string{"run", "--dns-search", "dns.podman", "--network=" + netName, NGINX_IMAGE, "curl", "web"}) c1.WaitWithDefaultTimeout() worked = c1.ExitCode() == 0 if worked { @@ -578,12 +578,12 @@ var _ = Describe("Podman network", func() { // Nginx is now running so no need to do a loop // Test against the first alias - c2 := podmanTest.Podman([]string{"run", "--dns-search", "dns.podman", "--network=" + netName, nginx, "curl", "web1"}) + c2 := podmanTest.Podman([]string{"run", "--dns-search", "dns.podman", "--network=" + netName, NGINX_IMAGE, "curl", "web1"}) c2.WaitWithDefaultTimeout() Expect(c2).Should(Exit(0)) // Test against the second alias - c3 := podmanTest.Podman([]string{"run", "--dns-search", "dns.podman", "--network=" + netName, nginx, "curl", "web2"}) + c3 := podmanTest.Podman([]string{"run", "--dns-search", "dns.podman", "--network=" + netName, NGINX_IMAGE, "curl", "web2"}) c3.WaitWithDefaultTimeout() Expect(c3).Should(Exit(0)) }) diff --git a/test/e2e/pause_test.go b/test/e2e/pause_test.go index 566aca07e..d677eddb0 100644 --- a/test/e2e/pause_test.go +++ b/test/e2e/pause_test.go @@ -273,7 +273,7 @@ var _ = Describe("Podman pause", func() { It("Pause a bunch of running containers", func() { for i := 0; i < 3; i++ { name := fmt.Sprintf("test%d", i) - run := podmanTest.Podman([]string{"run", "-dt", "--name", name, nginx}) + run := podmanTest.Podman([]string{"run", "-dt", "--name", name, NGINX_IMAGE}) run.WaitWithDefaultTimeout() Expect(run).Should(Exit(0)) @@ -300,7 +300,7 @@ var _ = Describe("Podman pause", func() { It("Unpause a bunch of running containers", func() { for i := 0; i < 3; i++ { name := fmt.Sprintf("test%d", i) - run := podmanTest.Podman([]string{"run", "-dt", "--name", name, nginx}) + run := podmanTest.Podman([]string{"run", "-dt", "--name", name, NGINX_IMAGE}) run.WaitWithDefaultTimeout() Expect(run).Should(Exit(0)) diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go index 61f2b3a1c..457aaebb2 100644 --- a/test/e2e/play_kube_test.go +++ b/test/e2e/play_kube_test.go @@ -1512,7 +1512,7 @@ var _ = Describe("Podman play kube", func() { // If you do not supply command or args for a Container, the defaults defined in the Docker image are used. It("podman play kube test correct args and cmd when not specified", func() { - pod := getPod(withCtr(getCtr(withImage(registry), withCmd(nil), withArg(nil)))) + pod := getPod(withCtr(getCtr(withImage(REGISTRY_IMAGE), withCmd(nil), withArg(nil)))) err := generateKubeYaml("pod", pod, kubeYaml) Expect(err).To(BeNil()) @@ -1536,7 +1536,7 @@ var _ = Describe("Podman play kube", func() { // If you supply a command but no args for a Container, only the supplied command is used. // The default EntryPoint and the default Cmd defined in the Docker image are ignored. It("podman play kube test correct command with only set command in yaml file", func() { - pod := getPod(withCtr(getCtr(withImage(registry), withCmd([]string{"echo", "hello"}), withArg(nil)))) + pod := getPod(withCtr(getCtr(withImage(REGISTRY_IMAGE), withCmd([]string{"echo", "hello"}), withArg(nil)))) err := generateKubeYaml("pod", pod, kubeYaml) Expect(err).To(BeNil()) @@ -1587,7 +1587,7 @@ var _ = Describe("Podman play kube", func() { // If you supply only args for a Container, the default Entrypoint defined in the Docker image is run with the args that you supplied. It("podman play kube test correct command with only set args in yaml file", func() { - pod := getPod(withCtr(getCtr(withImage(registry), withCmd(nil), withArg([]string{"echo", "hello"})))) + pod := getPod(withCtr(getCtr(withImage(REGISTRY_IMAGE), withCmd(nil), withArg([]string{"echo", "hello"})))) err := generateKubeYaml("pod", pod, kubeYaml) Expect(err).To(BeNil()) @@ -1611,7 +1611,7 @@ var _ = Describe("Podman play kube", func() { // the default Entrypoint and the default Cmd defined in the Docker image are ignored. // Your command is run with your args. It("podman play kube test correct command with both set args and cmd in yaml file", func() { - pod := getPod(withCtr(getCtr(withImage(registry), withCmd([]string{"echo"}), withArg([]string{"hello"})))) + pod := getPod(withCtr(getCtr(withImage(REGISTRY_IMAGE), withCmd([]string{"echo"}), withArg([]string{"hello"})))) err := generateKubeYaml("pod", pod, kubeYaml) Expect(err).To(BeNil()) @@ -2507,7 +2507,7 @@ spec: Expect(kube).To(ExitWithError()) }) - It("podman play kube test with read only HostPath volume", func() { + It("podman play kube test with read-only HostPath volume", func() { hostPathLocation := filepath.Join(tempdir, "file") f, err := os.Create(hostPathLocation) Expect(err).To(BeNil()) @@ -3705,7 +3705,7 @@ ENV OPENJ9_JAVA_OPTIONS=%q blockVolume := getHostPathVolume("BlockDevice", devicePath) - pod := getPod(withVolume(blockVolume), withCtr(getCtr(withImage(registry), withCmd(nil), withArg(nil), withVolumeMount(devicePath, false)))) + pod := getPod(withVolume(blockVolume), withCtr(getCtr(withImage(REGISTRY_IMAGE), withCmd(nil), withArg(nil), withVolumeMount(devicePath, false)))) err = generateKubeYaml("pod", pod, kubeYaml) Expect(err).To(BeNil()) @@ -3744,7 +3744,7 @@ ENV OPENJ9_JAVA_OPTIONS=%q charVolume := getHostPathVolume("CharDevice", devicePath) - pod := getPod(withVolume(charVolume), withCtr(getCtr(withImage(registry), withCmd(nil), withArg(nil), withVolumeMount(devicePath, false)))) + pod := getPod(withVolume(charVolume), withCtr(getCtr(withImage(REGISTRY_IMAGE), withCmd(nil), withArg(nil), withVolumeMount(devicePath, false)))) err = generateKubeYaml("pod", pod, kubeYaml) Expect(err).To(BeNil()) @@ -3772,7 +3772,7 @@ ENV OPENJ9_JAVA_OPTIONS=%q blockVolume := getHostPathVolume("BlockDevice", devicePath) - pod := getPod(withVolume(blockVolume), withCtr(getCtr(withImage(registry), withCmd(nil), withArg(nil), withVolumeMount(devicePath, false)))) + pod := getPod(withVolume(blockVolume), withCtr(getCtr(withImage(REGISTRY_IMAGE), withCmd(nil), withArg(nil), withVolumeMount(devicePath, false)))) err = generateKubeYaml("pod", pod, kubeYaml) Expect(err).To(BeNil()) @@ -3798,7 +3798,7 @@ ENV OPENJ9_JAVA_OPTIONS=%q charVolume := getHostPathVolume("BlockDevice", devicePath) - pod := getPod(withVolume(charVolume), withCtr(getCtr(withImage(registry), withCmd(nil), withArg(nil), withVolumeMount(devicePath, false)))) + pod := getPod(withVolume(charVolume), withCtr(getCtr(withImage(REGISTRY_IMAGE), withCmd(nil), withArg(nil), withVolumeMount(devicePath, false)))) err = generateKubeYaml("pod", pod, kubeYaml) Expect(err).To(BeNil()) @@ -3823,7 +3823,7 @@ ENV OPENJ9_JAVA_OPTIONS=%q charVolume := getHostPathVolume("CharDevice", devicePath) - pod := getPod(withVolume(charVolume), withCtr(getCtr(withImage(registry), withCmd(nil), withArg(nil), withVolumeMount(devicePath, false)))) + pod := getPod(withVolume(charVolume), withCtr(getCtr(withImage(REGISTRY_IMAGE), withCmd(nil), withArg(nil), withVolumeMount(devicePath, false)))) err = generateKubeYaml("pod", pod, kubeYaml) Expect(err).To(BeNil()) diff --git a/test/e2e/pod_clone_test.go b/test/e2e/pod_clone_test.go index b90bf10da..9c7abe7a8 100644 --- a/test/e2e/pod_clone_test.go +++ b/test/e2e/pod_clone_test.go @@ -11,9 +11,10 @@ import ( var _ = Describe("Podman pod clone", func() { var ( - tempdir string - err error - podmanTest *PodmanTestIntegration + tempdir string + err error + podmanTest *PodmanTestIntegration + hostname, _ = os.Hostname() ) BeforeEach(func() { @@ -155,4 +156,39 @@ var _ = Describe("Podman pod clone", func() { Expect(strings[0]).Should(ContainSubstring("size=10240k")) }) + It("podman pod clone --uts test", func() { + SkipIfRemote("hostname for the custom NS test is not as expected on the remote client") + + session := podmanTest.Podman([]string{"pod", "create"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + session = podmanTest.Podman([]string{"pod", "clone", "--uts", "host", session.OutputToString()}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + session = podmanTest.Podman([]string{"run", "-it", "--pod", session.OutputToString(), ALPINE, "printenv", "HOSTNAME"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(ContainSubstring(hostname)) + + podName := "utsPod" + ns := "ns:/proc/self/ns/" + + session = podmanTest.Podman([]string{"pod", "create"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + // just share uts with a custom path + podCreate := podmanTest.Podman([]string{"pod", "clone", "--uts", ns, "--name", podName, session.OutputToString()}) + podCreate.WaitWithDefaultTimeout() + Expect(podCreate).Should(Exit(0)) + + podInspect := podmanTest.Podman([]string{"pod", "inspect", podName}) + podInspect.WaitWithDefaultTimeout() + Expect(podInspect).Should(Exit(0)) + podJSON := podInspect.InspectPodToJSON() + Expect(podJSON.InfraConfig).To(HaveField("UtsNS", ns)) + }) + }) diff --git a/test/e2e/pod_create_test.go b/test/e2e/pod_create_test.go index a48193e90..3caae2bd5 100644 --- a/test/e2e/pod_create_test.go +++ b/test/e2e/pod_create_test.go @@ -23,9 +23,10 @@ import ( var _ = Describe("Podman pod create", func() { var ( - tempdir string - err error - podmanTest *PodmanTestIntegration + tempdir string + err error + podmanTest *PodmanTestIntegration + hostname, _ = os.Hostname() ) BeforeEach(func() { @@ -98,7 +99,7 @@ var _ = Describe("Podman pod create", func() { Expect(session).Should(Exit(0)) pod := session.OutputToString() - webserver := podmanTest.Podman([]string{"run", "--pod", pod, "-dt", nginx}) + webserver := podmanTest.Podman([]string{"run", "--pod", pod, "-dt", NGINX_IMAGE}) webserver.WaitWithDefaultTimeout() Expect(webserver).Should(Exit(0)) @@ -114,7 +115,7 @@ var _ = Describe("Podman pod create", func() { Expect(session).Should(Exit(0)) pod := session.OutputToString() - webserver := podmanTest.Podman([]string{"run", "--pod", pod, "-dt", nginx}) + webserver := podmanTest.Podman([]string{"run", "--pod", pod, "-dt", NGINX_IMAGE}) webserver.WaitWithDefaultTimeout() Expect(webserver).Should(Exit(0)) Expect(ncz(port)).To(BeTrue()) @@ -128,7 +129,7 @@ var _ = Describe("Podman pod create", func() { session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - webserver := podmanTest.Podman([]string{"run", "--pod-id-file", file, "-dt", nginx}) + webserver := podmanTest.Podman([]string{"run", "--pod-id-file", file, "-dt", NGINX_IMAGE}) webserver.WaitWithDefaultTimeout() Expect(webserver).Should(Exit(0)) Expect(ncz(port)).To(BeTrue()) @@ -899,27 +900,6 @@ ENTRYPOINT ["sleep","99999"] }) - It("podman pod create --device-read-bps", func() { - SkipIfRootless("Cannot create devices in /dev in rootless mode") - SkipIfRootlessCgroupsV1("Setting device-read-bps not supported on cgroupv1 for rootless users") - - podName := "testPod" - session := podmanTest.Podman([]string{"pod", "create", "--device-read-bps", "/dev/zero:1mb", "--name", podName}) - session.WaitWithDefaultTimeout() - Expect(session).Should(Exit(0)) - - if CGROUPSV2 { - session = podmanTest.Podman([]string{"run", "--rm", "--pod", podName, ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/io.max"}) - } else { - session = podmanTest.Podman([]string{"run", "--rm", "--pod", podName, ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.read_bps_device"}) - } - session.WaitWithDefaultTimeout() - Expect(session).Should(Exit(0)) - if !CGROUPSV2 { - Expect(session.OutputToString()).To(ContainSubstring("1048576")) - } - }) - It("podman pod create --volumes-from", func() { volName := "testVol" volCreate := podmanTest.Podman([]string{"volume", "create", volName}) @@ -1157,4 +1137,28 @@ ENTRYPOINT ["sleep","99999"] Expect(run).ShouldNot(Exit(0)) }) + It("podman pod create --uts test", func() { + session := podmanTest.Podman([]string{"pod", "create", "--uts", "host"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + session = podmanTest.Podman([]string{"run", "-it", "--pod", session.OutputToString(), ALPINE, "printenv", "HOSTNAME"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(ContainSubstring(hostname)) + + podName := "utsPod" + ns := "ns:/proc/self/ns/" + + // just share uts with a custom path + podCreate := podmanTest.Podman([]string{"pod", "create", "--uts", ns, "--name", podName, "--share", "uts"}) + podCreate.WaitWithDefaultTimeout() + Expect(podCreate).Should(Exit(0)) + + podInspect := podmanTest.Podman([]string{"pod", "inspect", podName}) + podInspect.WaitWithDefaultTimeout() + Expect(podInspect).Should(Exit(0)) + podJSON := podInspect.InspectPodToJSON() + Expect(podJSON.InfraConfig).To(HaveField("UtsNS", ns)) + }) }) diff --git a/test/e2e/pod_infra_container_test.go b/test/e2e/pod_infra_container_test.go index 20794a29c..a2e090524 100644 --- a/test/e2e/pod_infra_container_test.go +++ b/test/e2e/pod_infra_container_test.go @@ -114,7 +114,7 @@ var _ = Describe("Podman pod create", func() { session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - session = podmanTest.Podman([]string{"run", "-d", "--pod", podID, nginx}) + session = podmanTest.Podman([]string{"run", "-d", "--pod", podID, NGINX_IMAGE}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) @@ -237,11 +237,11 @@ var _ = Describe("Podman pod create", func() { session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - session = podmanTest.Podman([]string{"run", "-d", "--pod", podID, nginx}) + session = podmanTest.Podman([]string{"run", "-d", "--pod", podID, NGINX_IMAGE}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - session = podmanTest.Podman([]string{"run", "--pod", podID, "--network", "bridge", nginx, "curl", "-f", "localhost"}) + session = podmanTest.Podman([]string{"run", "--pod", podID, "--network", "bridge", NGINX_IMAGE, "curl", "-f", "localhost"}) session.WaitWithDefaultTimeout() Expect(session).To(ExitWithError()) }) diff --git a/test/e2e/pod_pause_test.go b/test/e2e/pod_pause_test.go index d78890347..39e5696fa 100644 --- a/test/e2e/pod_pause_test.go +++ b/test/e2e/pod_pause_test.go @@ -56,7 +56,7 @@ var _ = Describe("Podman pod pause", func() { Expect(result).Should(Exit(0)) }) - It("podman pod pause a running pod by id", func() { + It("pause a running pod by id", func() { _, ec, podid := podmanTest.CreatePod(nil) Expect(ec).To(Equal(0)) @@ -73,11 +73,10 @@ var _ = Describe("Podman pod pause", func() { result = podmanTest.Podman([]string{"pod", "unpause", podid}) result.WaitWithDefaultTimeout() - Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) }) - It("podman unpause a running pod by id", func() { + It("unpause a paused pod by id", func() { _, ec, podid := podmanTest.CreatePod(nil) Expect(ec).To(Equal(0)) @@ -85,14 +84,21 @@ var _ = Describe("Podman pod pause", func() { session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - result := podmanTest.Podman([]string{"pod", "unpause", podid}) + result := podmanTest.Podman([]string{"pod", "pause", podid}) result.WaitWithDefaultTimeout() + Expect(result).Should(Exit(0)) + Expect(result.OutputToStringArray()).Should(HaveLen(1)) + Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) + Expect(podmanTest.GetContainerStatus()).To(Equal(pausedState)) + result = podmanTest.Podman([]string{"pod", "unpause", podid}) + result.WaitWithDefaultTimeout() Expect(result).Should(Exit(0)) + Expect(result.OutputToStringArray()).Should(HaveLen(1)) Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) }) - It("podman pod pause a running pod by name", func() { + It("unpause a paused pod by name", func() { _, ec, _ := podmanTest.CreatePod(map[string][]string{"--name": {"test1"}}) Expect(ec).To(Equal(0)) @@ -102,13 +108,42 @@ var _ = Describe("Podman pod pause", func() { result := podmanTest.Podman([]string{"pod", "pause", "test1"}) result.WaitWithDefaultTimeout() - Expect(result).Should(Exit(0)) + Expect(result.OutputToStringArray()).Should(HaveLen(1)) Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) Expect(podmanTest.GetContainerStatus()).To(Equal(pausedState)) result = podmanTest.Podman([]string{"pod", "unpause", "test1"}) result.WaitWithDefaultTimeout() Expect(result).Should(Exit(0)) + Expect(result.OutputToStringArray()).Should(HaveLen(1)) + Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) + }) + + It("unpause --all", func() { + _, ec, podid1 := podmanTest.CreatePod(nil) + Expect(ec).To(Equal(0)) + _, ec, podid2 := podmanTest.CreatePod(nil) + Expect(ec).To(Equal(0)) + + session := podmanTest.RunTopContainerInPod("", podid1) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + session = podmanTest.RunTopContainerInPod("", podid2) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + result := podmanTest.Podman([]string{"pod", "pause", podid1}) + result.WaitWithDefaultTimeout() + Expect(result).Should(Exit(0)) + Expect(result.OutputToStringArray()).Should(HaveLen(1)) + Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) + Expect(podmanTest.GetContainerStatus()).To(ContainSubstring(pausedState)) + + result = podmanTest.Podman([]string{"pod", "unpause", "--all"}) + result.WaitWithDefaultTimeout() + Expect(result).Should(Exit(0)) + Expect(result.OutputToStringArray()).Should(HaveLen(1)) + Expect(podmanTest.NumberOfContainersRunning()).To(Equal(2)) }) }) diff --git a/test/e2e/pull_test.go b/test/e2e/pull_test.go index 55e8d637b..04b7a280d 100644 --- a/test/e2e/pull_test.go +++ b/test/e2e/pull_test.go @@ -256,7 +256,7 @@ var _ = Describe("Podman pull", func() { It("podman pull from docker-archive", func() { SkipIfRemote("podman-remote does not support pulling from docker-archive") - podmanTest.AddImageToRWStore(cirros) + podmanTest.AddImageToRWStore(CIRROS_IMAGE) tarfn := filepath.Join(podmanTest.TempDir, "cirros.tar") session := podmanTest.Podman([]string{"save", "-o", tarfn, "cirros"}) session.WaitWithDefaultTimeout() @@ -319,7 +319,7 @@ var _ = Describe("Podman pull", func() { It("podman pull from oci-archive", func() { SkipIfRemote("podman-remote does not support pulling from oci-archive") - podmanTest.AddImageToRWStore(cirros) + podmanTest.AddImageToRWStore(CIRROS_IMAGE) tarfn := filepath.Join(podmanTest.TempDir, "oci-cirrus.tar") session := podmanTest.Podman([]string{"save", "--format", "oci-archive", "-o", tarfn, "cirros"}) session.WaitWithDefaultTimeout() @@ -339,7 +339,7 @@ var _ = Describe("Podman pull", func() { It("podman pull from local directory", func() { SkipIfRemote("podman-remote does not support pulling from local directory") - podmanTest.AddImageToRWStore(cirros) + podmanTest.AddImageToRWStore(CIRROS_IMAGE) dirpath := filepath.Join(podmanTest.TempDir, "cirros") err = os.MkdirAll(dirpath, os.ModePerm) Expect(err).ToNot(HaveOccurred()) @@ -363,7 +363,7 @@ var _ = Describe("Podman pull", func() { It("podman pull from local OCI directory", func() { SkipIfRemote("podman-remote does not support pulling from OCI directory") - podmanTest.AddImageToRWStore(cirros) + podmanTest.AddImageToRWStore(CIRROS_IMAGE) dirpath := filepath.Join(podmanTest.TempDir, "cirros") err = os.MkdirAll(dirpath, os.ModePerm) Expect(err).ToNot(HaveOccurred()) diff --git a/test/e2e/push_test.go b/test/e2e/push_test.go index 864278777..97567e40d 100644 --- a/test/e2e/push_test.go +++ b/test/e2e/push_test.go @@ -100,12 +100,12 @@ var _ = Describe("Podman push", func() { Skip("No registry image for ppc64le") } if rootless.IsRootless() { - err := podmanTest.RestoreArtifact(registry) + err := podmanTest.RestoreArtifact(REGISTRY_IMAGE) Expect(err).ToNot(HaveOccurred()) } lock := GetPortLock("5000") defer lock.Unlock() - session := podmanTest.Podman([]string{"run", "-d", "--name", "registry", "-p", "5000:5000", registry, "/entrypoint.sh", "/etc/docker/registry/config.yml"}) + session := podmanTest.Podman([]string{"run", "-d", "--name", "registry", "-p", "5000:5000", REGISTRY_IMAGE, "/entrypoint.sh", "/etc/docker/registry/config.yml"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) @@ -156,7 +156,7 @@ var _ = Describe("Podman push", func() { } lock := GetPortLock("5000") defer lock.Unlock() - session := podmanTest.Podman([]string{"run", "--entrypoint", "htpasswd", registry, "-Bbn", "podmantest", "test"}) + session := podmanTest.Podman([]string{"run", "--entrypoint", "htpasswd", REGISTRY_IMAGE, "-Bbn", "podmantest", "test"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) @@ -173,7 +173,7 @@ var _ = Describe("Podman push", func() { strings.Join([]string{authPath, "/auth"}, ":"), "-e", "REGISTRY_AUTH=htpasswd", "-e", "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm", "-e", "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd", "-v", strings.Join([]string{certPath, "/certs"}, ":"), "-e", "REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt", - "-e", "REGISTRY_HTTP_TLS_KEY=/certs/domain.key", registry}) + "-e", "REGISTRY_HTTP_TLS_KEY=/certs/domain.key", REGISTRY_IMAGE}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) diff --git a/test/e2e/rmi_test.go b/test/e2e/rmi_test.go index cc3cceda5..d1a0cd6f5 100644 --- a/test/e2e/rmi_test.go +++ b/test/e2e/rmi_test.go @@ -50,7 +50,7 @@ var _ = Describe("Podman rmi", func() { }) It("podman rmi with short name", func() { - podmanTest.AddImageToRWStore(cirros) + podmanTest.AddImageToRWStore(CIRROS_IMAGE) session := podmanTest.Podman([]string{"rmi", "cirros"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) @@ -58,7 +58,7 @@ var _ = Describe("Podman rmi", func() { }) It("podman rmi all images", func() { - podmanTest.AddImageToRWStore(nginx) + podmanTest.AddImageToRWStore(NGINX_IMAGE) session := podmanTest.Podman([]string{"rmi", "-a"}) session.WaitWithDefaultTimeout() images := podmanTest.Podman([]string{"images"}) @@ -68,7 +68,7 @@ var _ = Describe("Podman rmi", func() { }) It("podman rmi all images forcibly with short options", func() { - podmanTest.AddImageToRWStore(nginx) + podmanTest.AddImageToRWStore(NGINX_IMAGE) session := podmanTest.Podman([]string{"rmi", "-fa"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) @@ -76,12 +76,12 @@ var _ = Describe("Podman rmi", func() { }) It("podman rmi tagged image", func() { - podmanTest.AddImageToRWStore(cirros) - setup := podmanTest.Podman([]string{"images", "-q", cirros}) + podmanTest.AddImageToRWStore(CIRROS_IMAGE) + setup := podmanTest.Podman([]string{"images", "-q", CIRROS_IMAGE}) setup.WaitWithDefaultTimeout() Expect(setup).Should(Exit(0)) - session := podmanTest.Podman([]string{"tag", cirros, "foo:bar", "foo"}) + session := podmanTest.Podman([]string{"tag", CIRROS_IMAGE, "foo:bar", "foo"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) @@ -93,8 +93,8 @@ var _ = Describe("Podman rmi", func() { }) It("podman rmi image with tags by ID cannot be done without force", func() { - podmanTest.AddImageToRWStore(cirros) - setup := podmanTest.Podman([]string{"images", "-q", cirros}) + podmanTest.AddImageToRWStore(CIRROS_IMAGE) + setup := podmanTest.Podman([]string{"images", "-q", CIRROS_IMAGE}) setup.WaitWithDefaultTimeout() Expect(setup).Should(Exit(0)) cirrosID := setup.OutputToString() @@ -116,8 +116,8 @@ var _ = Describe("Podman rmi", func() { It("podman rmi image that is a parent of another image", func() { Skip("I need help with this one. i don't understand what is going on") - podmanTest.AddImageToRWStore(cirros) - session := podmanTest.Podman([]string{"run", "--name", "c_test", cirros, "true"}) + podmanTest.AddImageToRWStore(CIRROS_IMAGE) + session := podmanTest.Podman([]string{"run", "--name", "c_test", CIRROS_IMAGE, "true"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) @@ -129,7 +129,7 @@ var _ = Describe("Podman rmi", func() { session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - session = podmanTest.Podman([]string{"rmi", cirros}) + session = podmanTest.Podman([]string{"rmi", CIRROS_IMAGE}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) @@ -183,12 +183,12 @@ var _ = Describe("Podman rmi", func() { }) It("podman rmi with cached images", func() { - podmanTest.AddImageToRWStore(cirros) + podmanTest.AddImageToRWStore(CIRROS_IMAGE) dockerfile := fmt.Sprintf(`FROM %s RUN mkdir hello RUN touch test.txt ENV foo=bar - `, cirros) + `, CIRROS_IMAGE) podmanTest.BuildImage(dockerfile, "test", "true") dockerfile = fmt.Sprintf(`FROM %s @@ -196,7 +196,7 @@ var _ = Describe("Podman rmi", func() { RUN touch test.txt RUN mkdir blah ENV foo=bar - `, cirros) + `, CIRROS_IMAGE) podmanTest.BuildImage(dockerfile, "test2", "true") @@ -225,7 +225,7 @@ var _ = Describe("Podman rmi", func() { podmanTest.BuildImage(dockerfile, "test3", "true") - session = podmanTest.Podman([]string{"rmi", cirros}) + session = podmanTest.Podman([]string{"rmi", CIRROS_IMAGE}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) @@ -250,7 +250,7 @@ var _ = Describe("Podman rmi", func() { }) It("podman rmi -a with parent|child images", func() { - podmanTest.AddImageToRWStore(cirros) + podmanTest.AddImageToRWStore(CIRROS_IMAGE) dockerfile := fmt.Sprintf(`FROM %s AS base RUN touch /1 ENV LOCAL=/1 @@ -258,7 +258,7 @@ RUN find $LOCAL FROM base RUN find $LOCAL -`, cirros) +`, CIRROS_IMAGE) podmanTest.BuildImage(dockerfile, "test", "true") session := podmanTest.Podman([]string{"rmi", "-a"}) session.WaitWithDefaultTimeout() @@ -285,7 +285,7 @@ RUN find $LOCAL // a race, we may not hit the condition a 100 percent of times // but ocal reproducers hit it all the time. - podmanTest.AddImageToRWStore(cirros) + podmanTest.AddImageToRWStore(CIRROS_IMAGE) var wg sync.WaitGroup buildAndRemove := func(i int) { @@ -293,7 +293,7 @@ RUN find $LOCAL defer wg.Done() imageName := fmt.Sprintf("rmtest:%d", i) containerfile := fmt.Sprintf(`FROM %s -RUN touch %s`, cirros, imageName) +RUN touch %s`, CIRROS_IMAGE, imageName) podmanTest.BuildImage(containerfile, imageName, "false") session := podmanTest.Podman([]string{"rmi", "-f", imageName}) diff --git a/test/e2e/run_aardvark_test.go b/test/e2e/run_aardvark_test.go index 25eb8b538..2c7dea9f4 100644 --- a/test/e2e/run_aardvark_test.go +++ b/test/e2e/run_aardvark_test.go @@ -42,7 +42,7 @@ var _ = Describe("Podman run networking", func() { defer podmanTest.removeNetwork(netName) Expect(session).Should(Exit(0)) - ctrID := podmanTest.Podman([]string{"run", "-dt", "--name", "aone", "--network", netName, nginx}) + ctrID := podmanTest.Podman([]string{"run", "-dt", "--name", "aone", "--network", netName, NGINX_IMAGE}) ctrID.WaitWithDefaultTimeout() Expect(ctrID).Should(Exit(0)) cid := ctrID.OutputToString() @@ -53,7 +53,7 @@ var _ = Describe("Podman run networking", func() { cip := ctrIP.OutputToString() Expect(cip).To(MatchRegexp(IPRegex)) - digShort(cid, "aone", []string{cip}, podmanTest) + digShort(cid, "aone", cip, podmanTest) reverseLookup := podmanTest.Podman([]string{"exec", cid, "dig", "+short", "-x", cip}) reverseLookup.WaitWithDefaultTimeout() @@ -72,7 +72,7 @@ var _ = Describe("Podman run networking", func() { defer podmanTest.removeNetwork(netName) Expect(session).Should(Exit(0)) - ctr1 := podmanTest.Podman([]string{"run", "-dt", "--name", "aone", "--network", netName, nginx}) + ctr1 := podmanTest.Podman([]string{"run", "-dt", "--name", "aone", "--network", netName, NGINX_IMAGE}) ctr1.WaitWithDefaultTimeout() Expect(ctr1).Should(Exit(0)) cid1 := ctr1.OutputToString() @@ -83,7 +83,7 @@ var _ = Describe("Podman run networking", func() { cip1 := ctrIP1.OutputToString() Expect(cip1).To(MatchRegexp(IPRegex)) - ctr2 := podmanTest.Podman([]string{"run", "-dt", "--name", "atwo", "--network", netName, nginx}) + ctr2 := podmanTest.Podman([]string{"run", "-dt", "--name", "atwo", "--network", netName, NGINX_IMAGE}) ctr2.WaitWithDefaultTimeout() Expect(ctr2).Should(Exit(0)) cid2 := ctr2.OutputToString() @@ -94,9 +94,9 @@ var _ = Describe("Podman run networking", func() { cip2 := ctrIP2.OutputToString() Expect(cip2).To(MatchRegexp(IPRegex)) - digShort("aone", "atwo", []string{cip2}, podmanTest) + digShort("aone", "atwo", cip2, podmanTest) - digShort("atwo", "aone", []string{cip1}, podmanTest) + digShort("atwo", "aone", cip1, podmanTest) reverseLookup12 := podmanTest.Podman([]string{"exec", cid1, "dig", "+short", "-x", cip2}) reverseLookup12.WaitWithDefaultTimeout() @@ -123,7 +123,7 @@ var _ = Describe("Podman run networking", func() { defer podmanTest.removeNetwork(netName) Expect(session).Should(Exit(0)) - ctr1 := podmanTest.Podman([]string{"run", "-dt", "--name", "aone", "--network", netName, "--network-alias", "alias_a1,alias_1a", nginx}) + ctr1 := podmanTest.Podman([]string{"run", "-dt", "--name", "aone", "--network", netName, "--network-alias", "alias_a1,alias_1a", NGINX_IMAGE}) ctr1.WaitWithDefaultTimeout() Expect(ctr1).Should(Exit(0)) @@ -133,7 +133,7 @@ var _ = Describe("Podman run networking", func() { cip1 := ctrIP1.OutputToString() Expect(cip1).To(MatchRegexp(IPRegex)) - ctr2 := podmanTest.Podman([]string{"run", "-dt", "--name", "atwo", "--network", netName, "--network-alias", "alias_a2,alias_2a", nginx}) + ctr2 := podmanTest.Podman([]string{"run", "-dt", "--name", "atwo", "--network", netName, "--network-alias", "alias_a2,alias_2a", NGINX_IMAGE}) ctr2.WaitWithDefaultTimeout() Expect(ctr2).Should(Exit(0)) @@ -143,17 +143,17 @@ var _ = Describe("Podman run networking", func() { cip2 := ctrIP2.OutputToString() Expect(cip2).To(MatchRegexp(IPRegex)) - digShort("aone", "atwo", []string{cip2}, podmanTest) + digShort("aone", "atwo", cip2, podmanTest) - digShort("aone", "alias_a2", []string{cip2}, podmanTest) + digShort("aone", "alias_a2", cip2, podmanTest) - digShort("aone", "alias_2a", []string{cip2}, podmanTest) + digShort("aone", "alias_2a", cip2, podmanTest) - digShort("atwo", "aone", []string{cip1}, podmanTest) + digShort("atwo", "aone", cip1, podmanTest) - digShort("atwo", "alias_a1", []string{cip1}, podmanTest) + digShort("atwo", "alias_a1", cip1, podmanTest) - digShort("atwo", "alias_1a", []string{cip1}, podmanTest) + digShort("atwo", "alias_1a", cip1, podmanTest) }) @@ -170,11 +170,11 @@ var _ = Describe("Podman run networking", func() { defer podmanTest.removeNetwork(netNameB) Expect(sessionB).Should(Exit(0)) - ctrA1 := podmanTest.Podman([]string{"run", "-dt", "--name", "aone", "--network", netNameA, nginx}) + ctrA1 := podmanTest.Podman([]string{"run", "-dt", "--name", "aone", "--network", netNameA, NGINX_IMAGE}) ctrA1.WaitWithDefaultTimeout() cidA1 := ctrA1.OutputToString() - ctrB1 := podmanTest.Podman([]string{"run", "-dt", "--name", "bone", "--network", netNameB, nginx}) + ctrB1 := podmanTest.Podman([]string{"run", "-dt", "--name", "bone", "--network", netNameB, NGINX_IMAGE}) ctrB1.WaitWithDefaultTimeout() cidB1 := ctrB1.OutputToString() @@ -214,7 +214,7 @@ var _ = Describe("Podman run networking", func() { defer podmanTest.removeNetwork(netNameB) Expect(sessionB).Should(Exit(0)) - ctrA1 := podmanTest.Podman([]string{"run", "-dt", "--name", "aone", "--network", netNameA, nginx}) + ctrA1 := podmanTest.Podman([]string{"run", "-dt", "--name", "aone", "--network", netNameA, NGINX_IMAGE}) ctrA1.WaitWithDefaultTimeout() cidA1 := ctrA1.OutputToString() @@ -224,7 +224,7 @@ var _ = Describe("Podman run networking", func() { cipA1 := ctrIPA1.OutputToString() Expect(cipA1).To(MatchRegexp(IPRegex)) - ctrB1 := podmanTest.Podman([]string{"run", "-dt", "--name", "bone", "--network", netNameB, nginx}) + ctrB1 := podmanTest.Podman([]string{"run", "-dt", "--name", "bone", "--network", netNameB, NGINX_IMAGE}) ctrB1.WaitWithDefaultTimeout() cidB1 := ctrB1.OutputToString() @@ -234,7 +234,7 @@ var _ = Describe("Podman run networking", func() { cipB1 := ctrIPB1.OutputToString() Expect(cipB1).To(MatchRegexp(IPRegex)) - ctrA2B2 := podmanTest.Podman([]string{"run", "-dt", "--name", "atwobtwo", "--network", netNameA, "--network", netNameB, nginx}) + ctrA2B2 := podmanTest.Podman([]string{"run", "-dt", "--name", "atwobtwo", "--network", netNameA, "--network", netNameB, NGINX_IMAGE}) ctrA2B2.WaitWithDefaultTimeout() cidA2B2 := ctrA2B2.OutputToString() @@ -250,13 +250,13 @@ var _ = Describe("Podman run networking", func() { cipA2B22 := ctrIPA2B22.OutputToString() Expect(cipA2B22).To(MatchRegexp(IPRegex)) - digShort("aone", "atwobtwo", []string{cipA2B21}, podmanTest) + digShort("aone", "atwobtwo", cipA2B21, podmanTest) - digShort("bone", "atwobtwo", []string{cipA2B22}, podmanTest) + digShort("bone", "atwobtwo", cipA2B22, podmanTest) - digShort("atwobtwo", "aone", []string{cipA1}, podmanTest) + digShort("atwobtwo", "aone", cipA1, podmanTest) - digShort("atwobtwo", "bone", []string{cipB1}, podmanTest) + digShort("atwobtwo", "bone", cipB1, podmanTest) }) It("Aardvark Test 6: Three subnets, first container on 1/2 and second on 2/3, w/ network aliases", func() { @@ -278,11 +278,11 @@ var _ = Describe("Podman run networking", func() { defer podmanTest.removeNetwork(netNameC) Expect(sessionC).Should(Exit(0)) - ctrA := podmanTest.Podman([]string{"run", "-dt", "--name", "aone", "--network", netNameA, nginx}) + ctrA := podmanTest.Podman([]string{"run", "-dt", "--name", "aone", "--network", netNameA, NGINX_IMAGE}) ctrA.WaitWithDefaultTimeout() Expect(ctrA).Should(Exit(0)) - ctrC := podmanTest.Podman([]string{"run", "-dt", "--name", "cone", "--network", netNameC, nginx}) + ctrC := podmanTest.Podman([]string{"run", "-dt", "--name", "cone", "--network", netNameC, NGINX_IMAGE}) ctrC.WaitWithDefaultTimeout() Expect(ctrC).Should(Exit(0)) @@ -304,10 +304,9 @@ var _ = Describe("Podman run networking", func() { Expect(ctrIPCB2).Should(Exit(0)) cipCB2 := ctrIPCB2.OutputToString() - digShort("aone", "testB2_nw", []string{cipCB2}, podmanTest) - - digShort("cone", "testB1_nw", []string{cipAB1}, podmanTest) + digShort("aone", "testB2_nw", cipCB2, podmanTest) + digShort("cone", "testB1_nw", cipAB1, podmanTest) }) }) diff --git a/test/e2e/run_networking_test.go b/test/e2e/run_networking_test.go index 4081ec45b..1ad78c950 100644 --- a/test/e2e/run_networking_test.go +++ b/test/e2e/run_networking_test.go @@ -513,7 +513,7 @@ EXPOSE 2004-2005/tcp`, ALPINE) }) It("podman run network expose ports in image metadata", func() { - session := podmanTest.Podman([]string{"create", "--name", "test", "-t", "-P", nginx}) + session := podmanTest.Podman([]string{"create", "--name", "test", "-t", "-P", NGINX_IMAGE}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) results := podmanTest.Podman([]string{"inspect", "test"}) diff --git a/test/e2e/run_staticip_test.go b/test/e2e/run_staticip_test.go index 09fb4e03c..8207f6d0b 100644 --- a/test/e2e/run_staticip_test.go +++ b/test/e2e/run_staticip_test.go @@ -101,7 +101,7 @@ var _ = Describe("Podman run with --ip flag", func() { It("Podman run two containers with the same IP", func() { ip := GetRandomIPAddress() - result := podmanTest.Podman([]string{"run", "-d", "--name", "nginx", "--ip", ip, nginx}) + result := podmanTest.Podman([]string{"run", "-d", "--name", "nginx", "--ip", ip, NGINX_IMAGE}) result.WaitWithDefaultTimeout() Expect(result).Should(Exit(0)) diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index 828e92170..6edb705a1 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -73,8 +73,30 @@ var _ = Describe("Podman run", func() { Expect(session.OutputToString()).To(ContainSubstring("graphRootMounted=1")) }) + It("podman run from manifest list", func() { + session := podmanTest.Podman([]string{"manifest", "create", "localhost/test:latest"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + session = podmanTest.Podman([]string{"build", "-f", "build/Containerfile.with-platform", "--platform", "linux/amd64,linux/arm64", "--manifest", "localhost/test:latest"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + session = podmanTest.Podman([]string{"run", "--platform", "linux/arm64", "localhost/test", "uname", "-a"}) + session.WaitWithDefaultTimeout() + exitCode := session.ExitCode() + // CI could either support requested platform or not, if it supports then output should contain `aarch64` + // if not run should fail with a very specific error i.e `Exec format error` anything other than this should + // be marked as failure of test. + if exitCode == 0 { + Expect(session.OutputToString()).To(ContainSubstring("aarch64")) + } else { + Expect(session.ErrorToString()).To(ContainSubstring("Exec format error")) + } + }) + It("podman run a container based on a complex local image name", func() { - imageName := strings.TrimPrefix(nginx, "quay.io/") + imageName := strings.TrimPrefix(NGINX_IMAGE, "quay.io/") session := podmanTest.Podman([]string{"run", imageName, "ls"}) session.WaitWithDefaultTimeout() Expect(session.ErrorToString()).ToNot(ContainSubstring("Trying to pull")) @@ -119,10 +141,10 @@ var _ = Describe("Podman run", func() { }) It("podman run a container based on on a short name with localhost", func() { - tag := podmanTest.Podman([]string{"tag", nginx, "localhost/libpod/alpine_nginx:latest"}) + tag := podmanTest.Podman([]string{"tag", NGINX_IMAGE, "localhost/libpod/alpine_nginx:latest"}) tag.WaitWithDefaultTimeout() - rmi := podmanTest.Podman([]string{"rmi", nginx}) + rmi := podmanTest.Podman([]string{"rmi", NGINX_IMAGE}) rmi.WaitWithDefaultTimeout() session := podmanTest.Podman([]string{"run", "libpod/alpine_nginx:latest", "ls"}) @@ -132,10 +154,10 @@ var _ = Describe("Podman run", func() { }) It("podman container run a container based on on a short name with localhost", func() { - tag := podmanTest.Podman([]string{"image", "tag", nginx, "localhost/libpod/alpine_nginx:latest"}) + tag := podmanTest.Podman([]string{"image", "tag", NGINX_IMAGE, "localhost/libpod/alpine_nginx:latest"}) tag.WaitWithDefaultTimeout() - rmi := podmanTest.Podman([]string{"image", "rm", nginx}) + rmi := podmanTest.Podman([]string{"image", "rm", NGINX_IMAGE}) rmi.WaitWithDefaultTimeout() session := podmanTest.Podman([]string{"container", "run", "libpod/alpine_nginx:latest", "ls"}) @@ -176,7 +198,7 @@ var _ = Describe("Podman run", func() { lock := GetPortLock("5000") defer lock.Unlock() - session := podmanTest.Podman([]string{"run", "-d", "--name", "registry", "-p", "5000:5000", registry, "/entrypoint.sh", "/etc/docker/registry/config.yml"}) + session := podmanTest.Podman([]string{"run", "-d", "--name", "registry", "-p", "5000:5000", REGISTRY_IMAGE, "/entrypoint.sh", "/etc/docker/registry/config.yml"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) @@ -1019,7 +1041,7 @@ echo -n %s >%s }) It("podman run with built-in volume image", func() { - session := podmanTest.Podman([]string{"run", "--rm", redis, "ls"}) + session := podmanTest.Podman([]string{"run", "--rm", REDIS_IMAGE, "ls"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) @@ -1084,7 +1106,7 @@ USER mail`, BB) Expect(session).Should(Exit(0)) ctrID := session.OutputToString() - // check that the read only option works + // check that the read-only option works session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID + ":ro", ALPINE, "touch", mountpoint + "abc.txt"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(1)) @@ -1108,13 +1130,13 @@ USER mail`, BB) Expect(session).Should(Exit(125)) Expect(session.ErrorToString()).To(ContainSubstring("cannot set :z more than once in mount options")) - // create new read only volume + // create new read-only volume session = podmanTest.Podman([]string{"create", "--volume", vol + ":" + mountpoint + ":ro", ALPINE, "cat", mountpoint + filename}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) ctrID = session.OutputToString() - // check if the original volume was mounted as read only that --volumes-from also mount it as read only + // check if the original volume was mounted as read-only that --volumes-from also mount it as read-only session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID, ALPINE, "touch", mountpoint + "abc.txt"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(1)) @@ -1122,7 +1144,7 @@ USER mail`, BB) }) It("podman run --volumes-from flag with built-in volumes", func() { - session := podmanTest.Podman([]string{"create", redis, "sh"}) + session := podmanTest.Podman([]string{"create", REDIS_IMAGE, "sh"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) ctrID := session.OutputToString() @@ -1637,7 +1659,7 @@ USER mail`, BB) session = podmanTest.Podman([]string{"run", "--umask", "9999", "--rm", ALPINE, "sh", "-c", "umask"}) session.WaitWithDefaultTimeout() Expect(session).To(ExitWithError()) - Expect(session.ErrorToString()).To(ContainSubstring("Invalid umask")) + Expect(session.ErrorToString()).To(ContainSubstring("invalid umask")) }) It("podman run makes workdir from image", func() { @@ -1679,24 +1701,24 @@ WORKDIR /madethis`, BB) }) It("podman run container with --pull missing and only pull once", func() { - session := podmanTest.Podman([]string{"run", "--pull", "missing", cirros, "ls"}) + session := podmanTest.Podman([]string{"run", "--pull", "missing", CIRROS_IMAGE, "ls"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) Expect(session.ErrorToString()).To(ContainSubstring("Trying to pull")) - session = podmanTest.Podman([]string{"run", "--pull", "missing", cirros, "ls"}) + session = podmanTest.Podman([]string{"run", "--pull", "missing", CIRROS_IMAGE, "ls"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) Expect(session.ErrorToString()).ToNot(ContainSubstring("Trying to pull")) }) It("podman run container with --pull missing should pull image multiple times", func() { - session := podmanTest.Podman([]string{"run", "--pull", "always", cirros, "ls"}) + session := podmanTest.Podman([]string{"run", "--pull", "always", CIRROS_IMAGE, "ls"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) Expect(session.ErrorToString()).To(ContainSubstring("Trying to pull")) - session = podmanTest.Podman([]string{"run", "--pull", "always", cirros, "ls"}) + session = podmanTest.Podman([]string{"run", "--pull", "always", CIRROS_IMAGE, "ls"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) Expect(session.ErrorToString()).To(ContainSubstring("Trying to pull")) diff --git a/test/e2e/run_volume_test.go b/test/e2e/run_volume_test.go index 5fcf340d4..aa8f49176 100644 --- a/test/e2e/run_volume_test.go +++ b/test/e2e/run_volume_test.go @@ -150,7 +150,7 @@ var _ = Describe("Podman run with volumes", func() { }) It("podman run with conflict between image volume and user mount succeeds", func() { - err = podmanTest.RestoreArtifact(redis) + err = podmanTest.RestoreArtifact(REDIS_IMAGE) Expect(err).ToNot(HaveOccurred()) mountPath := filepath.Join(podmanTest.TempDir, "secrets") err := os.Mkdir(mountPath, 0755) @@ -160,7 +160,7 @@ var _ = Describe("Podman run with volumes", func() { Expect(err).To(BeNil(), "os.Create(testfile)") f.Close() Expect(err).To(BeNil()) - session := podmanTest.Podman([]string{"run", "-v", fmt.Sprintf("%s:/data", mountPath), redis, "ls", "/data/test1"}) + session := podmanTest.Podman([]string{"run", "-v", fmt.Sprintf("%s:/data", mountPath), REDIS_IMAGE, "ls", "/data/test1"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) }) @@ -592,7 +592,7 @@ RUN sh -c "cd /etc/apk && ln -s ../../testfile"`, ALPINE) }) It("podman run image volume is not noexec", func() { - session := podmanTest.Podman([]string{"run", "--rm", redis, "grep", "/data", "/proc/self/mountinfo"}) + session := podmanTest.Podman([]string{"run", "--rm", REDIS_IMAGE, "grep", "/data", "/proc/self/mountinfo"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) Expect(session.OutputToString()).To(Not(ContainSubstring("noexec"))) diff --git a/test/e2e/save_test.go b/test/e2e/save_test.go index 7a1fb0fc2..94c363dd4 100644 --- a/test/e2e/save_test.go +++ b/test/e2e/save_test.go @@ -153,7 +153,7 @@ var _ = Describe("Podman save", func() { defer os.Setenv("GNUPGHOME", origGNUPGHOME) port := 5000 - session := podmanTest.Podman([]string{"run", "-d", "--name", "registry", "-p", strings.Join([]string{strconv.Itoa(port), strconv.Itoa(port)}, ":"), "quay.io/libpod/registry:2.6"}) + session := podmanTest.Podman([]string{"run", "-d", "--name", "registry", "-p", strings.Join([]string{strconv.Itoa(port), strconv.Itoa(port)}, ":"), REGISTRY_IMAGE}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) if !WaitContainerReady(podmanTest, "registry", "listening on", 20, 1) { diff --git a/test/e2e/search_test.go b/test/e2e/search_test.go index d37d8fd1a..f8b1bc836 100644 --- a/test/e2e/search_test.go +++ b/test/e2e/search_test.go @@ -206,7 +206,7 @@ registries = ['{{.Host}}:{{.Port}}']` port := GetPort() fakereg := podmanTest.Podman([]string{"run", "-d", "--name", "registry", "-p", fmt.Sprintf("%d:5000", port), - registry, "/entrypoint.sh", "/etc/docker/registry/config.yml"}) + REGISTRY_IMAGE, "/entrypoint.sh", "/etc/docker/registry/config.yml"}) fakereg.WaitWithDefaultTimeout() Expect(fakereg).Should(Exit(0)) @@ -231,7 +231,7 @@ registries = ['{{.Host}}:{{.Port}}']` } port := GetPort() registry := podmanTest.Podman([]string{"run", "-d", "--name", "registry3", - "-p", fmt.Sprintf("%d:5000", port), registry, + "-p", fmt.Sprintf("%d:5000", port), REGISTRY_IMAGE, "/entrypoint.sh", "/etc/docker/registry/config.yml"}) registry.WaitWithDefaultTimeout() Expect(registry).Should(Exit(0)) @@ -268,7 +268,7 @@ registries = ['{{.Host}}:{{.Port}}']` port := GetPort() ep := endpoint{Port: fmt.Sprintf("%d", port), Host: "localhost"} registry := podmanTest.Podman([]string{"run", "-d", "-p", fmt.Sprintf("%d:5000", port), - "--name", "registry4", registry, "/entrypoint.sh", "/etc/docker/registry/config.yml"}) + "--name", "registry4", REGISTRY_IMAGE, "/entrypoint.sh", "/etc/docker/registry/config.yml"}) registry.WaitWithDefaultTimeout() Expect(registry).Should(Exit(0)) @@ -313,7 +313,7 @@ registries = ['{{.Host}}:{{.Port}}']` port := GetPort() ep := endpoint{Port: fmt.Sprintf("%d", port), Host: "localhost"} registry := podmanTest.Podman([]string{"run", "-d", "-p", fmt.Sprintf("%d:5000", port), - "--name", "registry5", registry}) + "--name", "registry5", REGISTRY_IMAGE}) registry.WaitWithDefaultTimeout() Expect(registry).Should(Exit(0)) @@ -353,7 +353,7 @@ registries = ['{{.Host}}:{{.Port}}']` port := GetPort() ep := endpoint{Port: fmt.Sprintf("%d", port), Host: "localhost"} registry := podmanTest.Podman([]string{"run", "-d", "-p", fmt.Sprintf("%d:5000", port), - "--name", "registry6", registry}) + "--name", "registry6", REGISTRY_IMAGE}) registry.WaitWithDefaultTimeout() Expect(registry).Should(Exit(0)) @@ -401,7 +401,7 @@ registries = ['{{.Host}}:{{.Port}}']` ep3 := endpoint{Port: fmt.Sprintf("%d", port3), Host: "localhost"} registryLocal := podmanTest.Podman([]string{"run", "-d", "-p", fmt.Sprintf("%d", port1), - "--name", "registry7", registry}) + "--name", "registry7", REGISTRY_IMAGE}) registryLocal.WaitWithDefaultTimeout() Expect(registryLocal).Should(Exit(0)) @@ -409,7 +409,7 @@ registries = ['{{.Host}}:{{.Port}}']` Fail("Cannot start docker registry on port %s", port1) } - registryLocal = podmanTest.Podman([]string{"run", "-d", "-p", fmt.Sprintf("%d:5000", port2), "--name", "registry8", registry}) + registryLocal = podmanTest.Podman([]string{"run", "-d", "-p", fmt.Sprintf("%d:5000", port2), "--name", "registry8", REGISTRY_IMAGE}) registryLocal.WaitWithDefaultTimeout() Expect(registryLocal).Should(Exit(0)) diff --git a/test/e2e/system_df_test.go b/test/e2e/system_df_test.go index 712d16a6a..998fa8b59 100644 --- a/test/e2e/system_df_test.go +++ b/test/e2e/system_df_test.go @@ -97,4 +97,17 @@ var _ = Describe("podman system df", func() { session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) }) + + It("podman system df --format \"{{ json . }}\"", func() { + session := podmanTest.Podman([]string{"create", ALPINE}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + session = podmanTest.Podman([]string{"system", "df", "--format", "{{ json . }}"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.LineInOutputContains("Size")) + Expect(session.LineInOutputContains("Reclaimable")) + Expect(session.IsJSONOutputValid()) + }) }) diff --git a/test/e2e/systemd_test.go b/test/e2e/systemd_test.go index a1a080904..7b3552cc2 100644 --- a/test/e2e/systemd_test.go +++ b/test/e2e/systemd_test.go @@ -60,7 +60,7 @@ WantedBy=default.target Expect(stop).Should(Exit(0)) }() - create := podmanTest.Podman([]string{"create", "--name", "redis", redis}) + create := podmanTest.Podman([]string{"create", "--name", "redis", REDIS_IMAGE}) create.WaitWithDefaultTimeout() Expect(create).Should(Exit(0)) diff --git a/test/e2e/tree_test.go b/test/e2e/tree_test.go index e1282d2b4..5b552e987 100644 --- a/test/e2e/tree_test.go +++ b/test/e2e/tree_test.go @@ -36,7 +36,7 @@ var _ = Describe("Podman image tree", func() { It("podman image tree", func() { SkipIfRemote("podman-image-tree is not supported for remote clients") - podmanTest.AddImageToRWStore(cirros) + podmanTest.AddImageToRWStore(CIRROS_IMAGE) dockerfile := `FROM quay.io/libpod/cirros:latest RUN mkdir hello RUN touch test.txt diff --git a/test/e2e/untag_test.go b/test/e2e/untag_test.go index 90b0cc95f..b53d654f8 100644 --- a/test/e2e/untag_test.go +++ b/test/e2e/untag_test.go @@ -33,8 +33,8 @@ var _ = Describe("Podman untag", func() { }) It("podman untag all", func() { - podmanTest.AddImageToRWStore(cirros) - tags := []string{cirros, "registry.com/foo:bar", "localhost/foo:bar"} + podmanTest.AddImageToRWStore(CIRROS_IMAGE) + tags := []string{CIRROS_IMAGE, "registry.com/foo:bar", "localhost/foo:bar"} cmd := []string{"tag"} cmd = append(cmd, tags...) @@ -50,7 +50,7 @@ var _ = Describe("Podman untag", func() { } // No arguments -> remove all tags. - session = podmanTest.Podman([]string{"untag", cirros}) + session = podmanTest.Podman([]string{"untag", CIRROS_IMAGE}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) @@ -63,7 +63,7 @@ var _ = Describe("Podman untag", func() { }) It("podman tag/untag - tag normalization", func() { - podmanTest.AddImageToRWStore(cirros) + podmanTest.AddImageToRWStore(CIRROS_IMAGE) tests := []struct { tag, normalized string @@ -77,7 +77,7 @@ var _ = Describe("Podman untag", func() { // Make sure that the user input is normalized correctly for // `podman tag` and `podman untag`. for _, tt := range tests { - session := podmanTest.Podman([]string{"tag", cirros, tt.tag}) + session := podmanTest.Podman([]string{"tag", CIRROS_IMAGE, tt.tag}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) @@ -85,7 +85,7 @@ var _ = Describe("Podman untag", func() { session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - session = podmanTest.Podman([]string{"untag", cirros, tt.tag}) + session = podmanTest.Podman([]string{"untag", CIRROS_IMAGE, tt.tag}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) diff --git a/test/system/060-mount.bats b/test/system/060-mount.bats index 2735d2afd..4498e675f 100644 --- a/test/system/060-mount.bats +++ b/test/system/060-mount.bats @@ -87,7 +87,7 @@ load helpers # Run a container with an image mount run_podman run --rm --mount type=image,src=$IMAGE,dst=/image-mount $IMAGE diff /etc/os-release /image-mount/etc/os-release - # Make sure the mount is read only + # Make sure the mount is read-only run_podman 1 run --rm --mount type=image,src=$IMAGE,dst=/image-mount $IMAGE touch /image-mount/read-only is "$output" "touch: /image-mount/read-only: Read-only file system" diff --git a/test/system/130-kill.bats b/test/system/130-kill.bats index a9456e03c..96b633a42 100644 --- a/test/system/130-kill.bats +++ b/test/system/130-kill.bats @@ -130,4 +130,14 @@ load helpers is "$output" $cname } +@test "podman kill - concurrent stop" { + # 14761 - concurrent kill/stop must record the exit code + random_name=$(random_string 10) + run_podman run -d --replace --name=$random_name alpine sh -c "trap 'echo Received SIGTERM, ignoring' SIGTERM; echo READY; while :; do sleep 0.2; done" + $PODMAN stop -t 1 $random_name & + run_podman kill $random_name + run_podman wait $random_name + run_podman rm -f $random_name +} + # vim: filetype=sh diff --git a/test/system/200-pod.bats b/test/system/200-pod.bats index 92d3966be..0e522b34d 100644 --- a/test/system/200-pod.bats +++ b/test/system/200-pod.bats @@ -479,21 +479,25 @@ spec: fi local name1="resources1" - run_podman --cgroup-manager=systemd pod create --name=$name1 --cpus=5 - run_podman --cgroup-manager=systemd pod start $name1 + run_podman --cgroup-manager=systemd pod create --name=$name1 --cpus=5 --memory=10m + run_podman --cgroup-manager=systemd pod start $name1 run_podman pod inspect --format '{{.CgroupPath}}' $name1 local path1="$output" local actual1=$(< /sys/fs/cgroup/$path1/cpu.max) is "$actual1" "500000 100000" "resource limits set properly" + local actual2=$(< /sys/fs/cgroup/$path1/memory.max) + is "$actual2" "10485760" "resource limits set properly" run_podman pod --cgroup-manager=systemd rm -f $name1 local name2="resources2" - run_podman --cgroup-manager=cgroupfs pod create --cpus=5 --name=$name2 + run_podman --cgroup-manager=cgroupfs pod create --cpus=5 --memory=10m --name=$name2 run_podman --cgroup-manager=cgroupfs pod start $name2 run_podman pod inspect --format '{{.CgroupPath}}' $name2 local path2="$output" local actual2=$(< /sys/fs/cgroup/$path2/cpu.max) is "$actual2" "500000 100000" "resource limits set properly" + local actual2=$(< /sys/fs/cgroup/$path2/memory.max) + is "$actual2" "10485760" "resource limits set properly" run_podman --cgroup-manager=cgroupfs pod rm $name2 } diff --git a/test/system/500-networking.bats b/test/system/500-networking.bats index 0d724985e..50eb15216 100644 --- a/test/system/500-networking.bats +++ b/test/system/500-networking.bats @@ -677,16 +677,20 @@ EOF @test "podman run port forward range" { for netmode in bridge slirp4netns:port_handler=slirp4netns slirp4netns:port_handler=rootlesskit; do local range=$(random_free_port_range 3) - local port="${test%-*}" - local end_port="${test#-*}" + # die() inside $(...) does not actually stop us. + assert "$range" != "" "Could not find free port range" + + local port="${range%-*}" + local end_port="${range#*-}" local random=$(random_string) run_podman run --network $netmode -p "$range:$range" -d $IMAGE sleep inf cid="$output" for port in $(seq $port $end_port); do run_podman exec -d $cid nc -l -p $port -e /bin/cat - # -w 1 adds a 1 second timeout, for some reason ubuntus ncat doesn't close the connection on EOF, - # other options to change this are not portable across distros but -w seems to work + # -w 1 adds a 1 second timeout. For some reason, ubuntu's ncat + # doesn't close the connection on EOF, and other options to + # change this are not portable across distros. -w seems to work. run nc -w 1 127.0.0.1 $port <<<$random is "$output" "$random" "ncat got data back (netmode=$netmode port=$port)" done diff --git a/test/system/helpers.bash b/test/system/helpers.bash index 273e8d2f5..ceac48036 100644 --- a/test/system/helpers.bash +++ b/test/system/helpers.bash @@ -299,15 +299,17 @@ function random_free_port_range() { local maxtries=10 while [[ $maxtries -gt 0 ]]; do local firstport=$(random_free_port) - local all_ports_free=1 - for i in $(seq 2 $size); do - if ! port_is_free $((firstport + $i)); then - all_ports_free= + local lastport= + for i in $(seq 1 $((size - 1))); do + lastport=$((firstport + i)) + if ! port_is_free $lastport; then + echo "# port $lastport is in use; trying another." >&3 + lastport= break fi done - if [[ -n "$all_ports_free" ]]; then - echo "$firstport-$((firstport + $size - 1))" + if [[ -n "$lastport" ]]; then + echo "$firstport-$lastport" return fi diff --git a/test/testvol/main.go b/test/testvol/main.go index 99c6fb694..dd4ba642d 100644 --- a/test/testvol/main.go +++ b/test/testvol/main.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "io/ioutil" "os" "path/filepath" @@ -8,7 +9,6 @@ import ( "time" "github.com/docker/go-plugins-helpers/volume" - "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -80,16 +80,16 @@ func startServer(socketPath string) error { if config.path == "" { path, err := ioutil.TempDir("", "test_volume_plugin") if err != nil { - return errors.Wrapf(err, "error getting directory for plugin") + return fmt.Errorf("error getting directory for plugin: %w", err) } config.path = path } else { pathStat, err := os.Stat(config.path) if err != nil { - return errors.Wrapf(err, "unable to access requested plugin state directory") + return fmt.Errorf("unable to access requested plugin state directory: %w", err) } if !pathStat.IsDir() { - return errors.Errorf("cannot use %v as plugin state dir as it is not a directory", config.path) + return fmt.Errorf("cannot use %v as plugin state dir as it is not a directory", config.path) } } @@ -98,7 +98,7 @@ func startServer(socketPath string) error { server := volume.NewHandler(handle) if err := server.ServeUnix(socketPath, 0); err != nil { - return errors.Wrapf(err, "error starting server") + return fmt.Errorf("error starting server: %w", err) } return nil } @@ -147,7 +147,7 @@ func (d *DirDriver) Create(opts *volume.CreateRequest) error { logrus.Infof("Hit Create() endpoint") if _, exists := d.volumes[opts.Name]; exists { - return errors.Errorf("volume with name %s already exists", opts.Name) + return fmt.Errorf("volume with name %s already exists", opts.Name) } newVol := new(dirVol) @@ -161,7 +161,7 @@ func (d *DirDriver) Create(opts *volume.CreateRequest) error { volPath := filepath.Join(d.volumesPath, opts.Name) if err := os.Mkdir(volPath, 0755); err != nil { - return errors.Wrapf(err, "error making volume directory") + return fmt.Errorf("error making volume directory: %w", err) } newVol.path = volPath @@ -204,7 +204,7 @@ func (d *DirDriver) Get(req *volume.GetRequest) (*volume.GetResponse, error) { vol, exists := d.volumes[req.Name] if !exists { logrus.Debugf("Did not find volume %s", req.Name) - return nil, errors.Errorf("no volume with name %s found", req.Name) + return nil, fmt.Errorf("no volume with name %s found", req.Name) } logrus.Debugf("Found volume %s", req.Name) @@ -228,19 +228,19 @@ func (d *DirDriver) Remove(req *volume.RemoveRequest) error { vol, exists := d.volumes[req.Name] if !exists { logrus.Debugf("Did not find volume %s", req.Name) - return errors.Errorf("no volume with name %s found", req.Name) + return fmt.Errorf("no volume with name %s found", req.Name) } logrus.Debugf("Found volume %s", req.Name) if len(vol.mounts) > 0 { logrus.Debugf("Cannot remove %s, is mounted", req.Name) - return errors.Errorf("volume %s is mounted and cannot be removed", req.Name) + return fmt.Errorf("volume %s is mounted and cannot be removed", req.Name) } delete(d.volumes, req.Name) if err := os.RemoveAll(vol.path); err != nil { - return errors.Wrapf(err, "error removing mountpoint of volume %s", req.Name) + return fmt.Errorf("error removing mountpoint of volume %s: %w", req.Name, err) } logrus.Debugf("Removed volume %s", req.Name) @@ -260,7 +260,7 @@ func (d *DirDriver) Path(req *volume.PathRequest) (*volume.PathResponse, error) vol, exists := d.volumes[req.Name] if !exists { logrus.Debugf("Cannot locate volume %s", req.Name) - return nil, errors.Errorf("no volume with name %s found", req.Name) + return nil, fmt.Errorf("no volume with name %s found", req.Name) } return &volume.PathResponse{ @@ -278,7 +278,7 @@ func (d *DirDriver) Mount(req *volume.MountRequest) (*volume.MountResponse, erro vol, exists := d.volumes[req.Name] if !exists { logrus.Debugf("Cannot locate volume %s", req.Name) - return nil, errors.Errorf("no volume with name %s found", req.Name) + return nil, fmt.Errorf("no volume with name %s found", req.Name) } vol.mounts[req.ID] = true @@ -298,13 +298,13 @@ func (d *DirDriver) Unmount(req *volume.UnmountRequest) error { vol, exists := d.volumes[req.Name] if !exists { logrus.Debugf("Cannot locate volume %s", req.Name) - return errors.Errorf("no volume with name %s found", req.Name) + return fmt.Errorf("no volume with name %s found", req.Name) } mount := vol.mounts[req.ID] if !mount { logrus.Debugf("Volume %s is not mounted by %s", req.Name, req.ID) - return errors.Errorf("volume %s is not mounted by %s", req.Name, req.ID) + return fmt.Errorf("volume %s is not mounted by %s", req.Name, req.ID) } delete(vol.mounts, req.ID) diff --git a/troubleshooting.md b/troubleshooting.md index 05685c906..1fa044fe9 100644 --- a/troubleshooting.md +++ b/troubleshooting.md @@ -663,7 +663,7 @@ $ podman run --rm --rootfs /path/to/rootfs true The command above will create all the missing directories needed to run the container. -After that, it can be used in read only mode, by multiple containers at the same time: +After that, it can be used in read-only mode, by multiple containers at the same time: ```console $ podman run --read-only --rootfs /path/to/rootfs .... @@ -1231,3 +1231,58 @@ While running podman remote commands with the most updated Podman, issues that w When upgrading Podman to a particular version for the required fixes, users often make the mistake of only upgrading the Podman client. However, suppose a setup uses `podman-remote` or uses a client that communicates with the Podman server on a remote machine via the REST API. In that case, it is required to upgrade both the Podman client and the Podman server running on the remote machine. Both the Podman client and server must be upgraded to the same version. Example: If a particular bug was fixed in `v4.1.0` then the Podman client must have version `v4.1.0` as well the Podman server must have version `v4.1.0`. + +### 37) Unexpected carriage returns are outputted on the terminal + +When using the __--tty__ (__-t__) flag, unexpected carriage returns are outputted on the terminal. + +#### Symptom + +The container program prints a newline (`\n`) but the terminal outputs a carriage return and a newline (`\r\n`). + +``` +$ podman run --rm -t fedora echo abc | od -c +0000000 a b c \r \n +0000005 +``` + +When run directly on the host, the result is as expected. + +``` +$ echo abc | od -c +0000000 a b c \n +0000004 +``` + +Extra carriage returns can also shift the prompt to the right. + +``` +$ podman run --rm -t fedora sh -c "echo 1; echo 2; echo 3" | cat -A +1^M$ + 2^M$ + 3^M$ + $ +``` + +#### Solution + +Run Podman without the __--tty__ (__-t__) flag. + +``` +$ podman run --rm fedora echo abc | od -c +0000000 a b c \n +0000004 +``` + +The __--tty__ (__-t__) flag should only be used when the program requires user interaction in the termainal, for instance expecting +the user to type an answer to a question. + +Where does the extra carriage return `\r` come from? + +The extra `\r` is not outputted by Podman but by the terminal. In fact, a reconfiguration of the terminal can make the extra `\r` go away. + +``` +$ podman run --rm -t fedora /bin/sh -c "stty -onlcr && echo abc" | od -c +0000000 a b c \n +0000004 +``` diff --git a/utils/ports.go b/utils/ports.go index 57a6f8275..eea060433 100644 --- a/utils/ports.go +++ b/utils/ports.go @@ -1,26 +1,25 @@ package utils import ( + "fmt" "net" "strconv" - - "github.com/pkg/errors" ) // Find a random, open port on the host. func GetRandomPort() (int, error) { l, err := net.Listen("tcp", ":0") if err != nil { - return 0, errors.Wrapf(err, "unable to get free TCP port") + return 0, fmt.Errorf("unable to get free TCP port: %w", err) } defer l.Close() _, randomPort, err := net.SplitHostPort(l.Addr().String()) if err != nil { - return 0, errors.Wrapf(err, "unable to determine free port") + return 0, fmt.Errorf("unable to determine free port: %w", err) } rp, err := strconv.Atoi(randomPort) if err != nil { - return 0, errors.Wrapf(err, "unable to convert random port to int") + return 0, fmt.Errorf("unable to convert random port to int: %w", err) } return rp, nil } diff --git a/utils/utils.go b/utils/utils.go index 9239cf907..997de150d 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -13,10 +13,8 @@ import ( "sync" "github.com/containers/common/pkg/cgroups" - "github.com/containers/podman/v4/libpod/define" "github.com/containers/storage/pkg/archive" "github.com/godbus/dbus/v5" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -53,57 +51,6 @@ func ExecCmdWithStdStreams(stdin io.Reader, stdout, stderr io.Writer, env []stri return nil } -// ErrDetach is an error indicating that the user manually detached from the -// container. -var ErrDetach = define.ErrDetach - -// CopyDetachable is similar to io.Copy but support a detach key sequence to break out. -func CopyDetachable(dst io.Writer, src io.Reader, keys []byte) (written int64, err error) { - buf := make([]byte, 32*1024) - for { - nr, er := src.Read(buf) - if nr > 0 { - preservBuf := []byte{} - for i, key := range keys { - preservBuf = append(preservBuf, buf[0:nr]...) - if nr != 1 || buf[0] != key { - break - } - if i == len(keys)-1 { - return 0, ErrDetach - } - nr, er = src.Read(buf) - } - var nw int - var ew error - if len(preservBuf) > 0 { - nw, ew = dst.Write(preservBuf) - nr = len(preservBuf) - } else { - nw, ew = dst.Write(buf[0:nr]) - } - if nw > 0 { - written += int64(nw) - } - if ew != nil { - err = ew - break - } - if nr != nw { - err = io.ErrShortWrite - break - } - } - if er != nil { - if er != io.EOF { - err = er - } - break - } - } - return written, err -} - // UntarToFileSystem untars an os.file of a tarball to a destination in the filesystem func UntarToFileSystem(dest string, tarball *os.File, options *archive.TarOptions) error { logrus.Debugf("untarring %s", tarball.Name()) @@ -114,7 +61,7 @@ func UntarToFileSystem(dest string, tarball *os.File, options *archive.TarOption func CreateTarFromSrc(source string, dest string) error { file, err := os.Create(dest) if err != nil { - return errors.Wrapf(err, "Could not create tarball file '%s'", dest) + return fmt.Errorf("could not create tarball file '%s': %w", dest, err) } defer file.Close() return TarToFilesystem(source, file) @@ -154,7 +101,7 @@ func RemoveScientificNotationFromFloat(x float64) (float64, error) { } result, err := strconv.ParseFloat(bigNum, 64) if err != nil { - return x, errors.Wrapf(err, "unable to remove scientific number from calculations") + return x, fmt.Errorf("unable to remove scientific number from calculations: %w", err) } return result, nil } @@ -181,11 +128,11 @@ func moveProcessPIDFileToScope(pidPath, slice, scope string) error { if os.IsNotExist(err) { return nil } - return errors.Wrapf(err, "cannot read pid file %s", pidPath) + return fmt.Errorf("cannot read pid file %s: %w", pidPath, err) } pid, err := strconv.ParseUint(string(data), 10, 0) if err != nil { - return errors.Wrapf(err, "cannot parse pid file %s", pidPath) + return fmt.Errorf("cannot parse pid file %s: %w", pidPath, err) } return moveProcessToScope(int(pid), slice, scope) diff --git a/utils/utils_supported.go b/utils/utils_supported.go index 6378212b6..d7d47b2bc 100644 --- a/utils/utils_supported.go +++ b/utils/utils_supported.go @@ -17,7 +17,6 @@ import ( "github.com/containers/podman/v4/pkg/rootless" systemdDbus "github.com/coreos/go-systemd/v22/dbus" "github.com/godbus/dbus/v5" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -77,7 +76,7 @@ func getCgroupProcess(procFile string, allowRoot bool) (string, error) { line := scanner.Text() parts := strings.SplitN(line, ":", 3) if len(parts) != 3 { - return "", errors.Errorf("cannot parse cgroup line %q", line) + return "", fmt.Errorf("cannot parse cgroup line %q", line) } if strings.HasPrefix(line, "0::") { cgroup = line[3:] @@ -88,7 +87,7 @@ func getCgroupProcess(procFile string, allowRoot bool) (string, error) { } } if len(cgroup) == 0 || (!allowRoot && cgroup == "/") { - return "", errors.Errorf("could not find cgroup mount in %q", procFile) + return "", fmt.Errorf("could not find cgroup mount in %q", procFile) } return cgroup, nil } @@ -133,7 +132,7 @@ func moveUnderCgroup(cgroup, subtree string, processes []uint32) error { line := scanner.Text() parts := strings.SplitN(line, ":", 3) if len(parts) != 3 { - return errors.Errorf("cannot parse cgroup line %q", line) + return fmt.Errorf("cannot parse cgroup line %q", line) } // root cgroup, skip it diff --git a/utils/utils_windows.go b/utils/utils_windows.go index 1d017f5ae..18f232116 100644 --- a/utils/utils_windows.go +++ b/utils/utils_windows.go @@ -3,7 +3,7 @@ package utils -import "github.com/pkg/errors" +import "errors" func RunUnderSystemdScope(pid int, slice string, unitName string) error { return errors.New("not implemented for windows") diff --git a/vendor/github.com/containers/common/pkg/cgroups/systemd_linux.go b/vendor/github.com/containers/common/pkg/cgroups/systemd_linux.go index a45358f9b..ee9f584de 100644 --- a/vendor/github.com/containers/common/pkg/cgroups/systemd_linux.go +++ b/vendor/github.com/containers/common/pkg/cgroups/systemd_linux.go @@ -152,10 +152,10 @@ func resourcesToProps(res *configs.Resources) (map[string]uint64, map[string]str // Mem if res.Memory != 0 { - iMap["MemoryMax"] = res.Memory + uMap["MemoryMax"] = uint64(res.Memory) } if res.MemorySwap != 0 { - iMap["MemorySwapMax"] = res.MemorySwap + uMap["MemorySwapMax"] = uint64(res.MemorySwap) } // Blkio diff --git a/pkg/kubeutils/resize.go b/vendor/github.com/containers/common/pkg/resize/resize.go index a744c66cc..9a2afcf73 100644 --- a/pkg/kubeutils/resize.go +++ b/vendor/github.com/containers/common/pkg/resize/resize.go @@ -14,16 +14,18 @@ See the License for the specific language governing permissions and limitations under the License. */ -package kubeutils +package resize -import ( - "github.com/containers/podman/v4/libpod/define" -) +// TerminalSize represents the width and height of a terminal. +type TerminalSize struct { + Width uint16 + Height uint16 +} // HandleResizing spawns a goroutine that processes the resize channel, calling resizeFunc for each -// remotecommand.TerminalSize received from the channel. The resize channel must be closed elsewhere to stop the +// TerminalSize received from the channel. The resize channel must be closed elsewhere to stop the // goroutine. -func HandleResizing(resize <-chan define.TerminalSize, resizeFunc func(size define.TerminalSize)) { +func HandleResizing(resize <-chan TerminalSize, resizeFunc func(size TerminalSize)) { if resize == nil { return } diff --git a/vendor/github.com/containers/common/pkg/seccomp/default_linux.go b/vendor/github.com/containers/common/pkg/seccomp/default_linux.go index 3712afc71..0db77879c 100644 --- a/vendor/github.com/containers/common/pkg/seccomp/default_linux.go +++ b/vendor/github.com/containers/common/pkg/seccomp/default_linux.go @@ -221,6 +221,9 @@ func DefaultProfile() *Seccomp { "ipc", "keyctl", "kill", + "landlock_add_rule", + "landlock_create_ruleset", + "landlock_restrict_self", "lchown", "lchown32", "lgetxattr", diff --git a/vendor/github.com/containers/common/pkg/seccomp/seccomp.json b/vendor/github.com/containers/common/pkg/seccomp/seccomp.json index 442632e7d..18674db4d 100644 --- a/vendor/github.com/containers/common/pkg/seccomp/seccomp.json +++ b/vendor/github.com/containers/common/pkg/seccomp/seccomp.json @@ -228,6 +228,9 @@ "ipc", "keyctl", "kill", + "landlock_add_rule", + "landlock_create_ruleset", + "landlock_restrict_self", "lchown", "lchown32", "lgetxattr", diff --git a/vendor/github.com/containers/common/pkg/util/copy.go b/vendor/github.com/containers/common/pkg/util/copy.go new file mode 100644 index 000000000..a45b82fc9 --- /dev/null +++ b/vendor/github.com/containers/common/pkg/util/copy.go @@ -0,0 +1,57 @@ +package util + +import ( + "errors" + "io" +) + +// ErrDetach indicates that an attach session was manually detached by +// the user. +var ErrDetach = errors.New("detached from container") + +// CopyDetachable is similar to io.Copy but support a detach key sequence to break out. +func CopyDetachable(dst io.Writer, src io.Reader, keys []byte) (written int64, err error) { + buf := make([]byte, 32*1024) + for { + nr, er := src.Read(buf) + if nr > 0 { + preservBuf := []byte{} + for i, key := range keys { + preservBuf = append(preservBuf, buf[0:nr]...) + if nr != 1 || buf[0] != key { + break + } + if i == len(keys)-1 { + return 0, ErrDetach + } + nr, er = src.Read(buf) + } + var nw int + var ew error + if len(preservBuf) > 0 { + nw, ew = dst.Write(preservBuf) + nr = len(preservBuf) + } else { + nw, ew = dst.Write(buf[0:nr]) + } + if nw > 0 { + written += int64(nw) + } + if ew != nil { + err = ew + break + } + if nr != nw { + err = io.ErrShortWrite + break + } + } + if er != nil { + if er != io.EOF { + err = er + } + break + } + } + return written, err +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 3e8657bc4..fa7a963cd 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -111,7 +111,7 @@ github.com/containers/buildah/pkg/rusage github.com/containers/buildah/pkg/sshagent github.com/containers/buildah/pkg/util github.com/containers/buildah/util -# github.com/containers/common v0.48.1-0.20220628131511-a8336c1613fe +# github.com/containers/common v0.48.1-0.20220705175712-dd1c331887b9 ## explicit github.com/containers/common/libimage github.com/containers/common/libimage/define @@ -142,6 +142,7 @@ github.com/containers/common/pkg/netns github.com/containers/common/pkg/parse github.com/containers/common/pkg/report github.com/containers/common/pkg/report/camelcase +github.com/containers/common/pkg/resize github.com/containers/common/pkg/retry github.com/containers/common/pkg/seccomp github.com/containers/common/pkg/secrets |