summaryrefslogtreecommitdiff
path: root/pkg/specgen/generate
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/specgen/generate')
-rw-r--r--pkg/specgen/generate/config_linux.go150
-rw-r--r--pkg/specgen/generate/config_linux_cgo.go11
-rw-r--r--pkg/specgen/generate/container.go38
-rw-r--r--pkg/specgen/generate/container_create.go51
-rw-r--r--pkg/specgen/generate/kube/kube.go67
-rw-r--r--pkg/specgen/generate/kube/play_test.go4
-rw-r--r--pkg/specgen/generate/kube/seccomp.go6
-rw-r--r--pkg/specgen/generate/kube/volume.go31
-rw-r--r--pkg/specgen/generate/namespaces.go94
-rw-r--r--pkg/specgen/generate/oci.go43
-rw-r--r--pkg/specgen/generate/pod_create.go107
-rw-r--r--pkg/specgen/generate/ports.go27
-rw-r--r--pkg/specgen/generate/security.go27
-rw-r--r--pkg/specgen/generate/storage.go38
-rw-r--r--pkg/specgen/generate/validate.go24
15 files changed, 368 insertions, 350 deletions
diff --git a/pkg/specgen/generate/config_linux.go b/pkg/specgen/generate/config_linux.go
index ed2e5408d..a46966161 100644
--- a/pkg/specgen/generate/config_linux.go
+++ b/pkg/specgen/generate/config_linux.go
@@ -3,7 +3,6 @@ package generate
import (
"fmt"
"io/fs"
- "io/ioutil"
"os"
"path"
"path/filepath"
@@ -11,63 +10,13 @@ import (
"github.com/containers/podman/v4/libpod/define"
"github.com/containers/podman/v4/pkg/rootless"
+ "github.com/containers/podman/v4/pkg/util"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-tools/generate"
- "github.com/pkg/errors"
"github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
)
-var (
- errNotADevice = errors.New("not a device node")
-)
-
-func addPrivilegedDevices(g *generate.Generator) error {
- hostDevices, err := getDevices("/dev")
- if err != nil {
- return err
- }
- g.ClearLinuxDevices()
-
- if rootless.IsRootless() {
- mounts := make(map[string]interface{})
- for _, m := range g.Mounts() {
- mounts[m.Destination] = true
- }
- newMounts := []spec.Mount{}
- for _, d := range hostDevices {
- devMnt := spec.Mount{
- Destination: d.Path,
- Type: define.TypeBind,
- Source: d.Path,
- Options: []string{"slave", "nosuid", "noexec", "rw", "rbind"},
- }
- if d.Path == "/dev/ptmx" || strings.HasPrefix(d.Path, "/dev/tty") {
- continue
- }
- if _, found := mounts[d.Path]; found {
- continue
- }
- newMounts = append(newMounts, devMnt)
- }
- g.Config.Mounts = append(newMounts, g.Config.Mounts...)
- if g.Config.Linux.Resources != nil {
- g.Config.Linux.Resources.Devices = nil
- }
- } else {
- for _, d := range hostDevices {
- g.AddDevice(d)
- }
- // Add resources device - need to clear the existing one first.
- if g.Config.Linux.Resources != nil {
- g.Config.Linux.Resources.Devices = nil
- }
- g.AddLinuxResourcesDevice(true, "", nil, nil, "rwm")
- }
-
- return nil
-}
-
// DevicesFromPath computes a list of devices
func DevicesFromPath(g *generate.Generator, devicePath string) error {
devs := strings.Split(devicePath, ":")
@@ -96,7 +45,7 @@ func DevicesFromPath(g *generate.Generator, devicePath string) error {
}
if len(devs) > 2 {
if devmode != "" {
- return errors.Wrapf(unix.EINVAL, "invalid device specification %s", devicePath)
+ return fmt.Errorf("invalid device specification %s: %w", devicePath, unix.EINVAL)
}
devmode = devs[2]
}
@@ -110,7 +59,7 @@ func DevicesFromPath(g *generate.Generator, devicePath string) error {
device = fmt.Sprintf("%s:%s", device, devmode)
}
if err := addDevice(g, device); err != nil {
- return errors.Wrapf(err, "failed to add %s device", dpath)
+ return fmt.Errorf("failed to add %s device: %w", dpath, err)
}
}
return nil
@@ -118,7 +67,7 @@ func DevicesFromPath(g *generate.Generator, devicePath string) error {
return err
}
if !found {
- return errors.Wrapf(unix.EINVAL, "no devices found in %s", devicePath)
+ return fmt.Errorf("no devices found in %s: %w", devicePath, unix.EINVAL)
}
return nil
}
@@ -174,62 +123,14 @@ func BlockAccessToKernelFilesystems(privileged, pidModeIsHost bool, mask, unmask
}
}
-// based on getDevices from runc (libcontainer/devices/devices.go)
-func getDevices(path string) ([]spec.LinuxDevice, error) {
- files, err := ioutil.ReadDir(path)
- if err != nil {
- if rootless.IsRootless() && os.IsPermission(err) {
- return nil, nil
- }
- return nil, err
- }
- out := []spec.LinuxDevice{}
- for _, f := range files {
- switch {
- case f.IsDir():
- switch f.Name() {
- // ".lxc" & ".lxd-mounts" added to address https://github.com/lxc/lxd/issues/2825
- case "pts", "shm", "fd", "mqueue", ".lxc", ".lxd-mounts":
- continue
- default:
- sub, err := getDevices(filepath.Join(path, f.Name()))
- if err != nil {
- return nil, err
- }
- if sub != nil {
- out = append(out, sub...)
- }
- continue
- }
- case f.Name() == "console":
- continue
- case f.Mode()&os.ModeSymlink != 0:
- continue
- }
-
- device, err := deviceFromPath(filepath.Join(path, f.Name()))
- if err != nil {
- if err == errNotADevice {
- continue
- }
- if os.IsNotExist(err) {
- continue
- }
- return nil, err
- }
- out = append(out, *device)
- }
- return out, nil
-}
-
func addDevice(g *generate.Generator, device string) error {
src, dst, permissions, err := ParseDevice(device)
if err != nil {
return err
}
- dev, err := deviceFromPath(src)
+ dev, err := util.DeviceFromPath(src)
if err != nil {
- return errors.Wrapf(err, "%s is not a valid device", src)
+ return fmt.Errorf("%s is not a valid device: %w", src, err)
}
if rootless.IsRootless() {
if _, err := os.Stat(src); err != nil {
@@ -262,7 +163,7 @@ func addDevice(g *generate.Generator, device string) error {
}
// ParseDevice parses device mapping string to a src, dest & permissions string
-func ParseDevice(device string) (string, string, string, error) { //nolint
+func ParseDevice(device string) (string, string, string, error) {
var src string
var dst string
permissions := "rwm"
@@ -316,43 +217,6 @@ func IsValidDeviceMode(mode string) bool {
return true
}
-// Copied from github.com/opencontainers/runc/libcontainer/devices
-// Given the path to a device look up the information about a linux device
-func deviceFromPath(path string) (*spec.LinuxDevice, error) {
- var stat unix.Stat_t
- err := unix.Lstat(path, &stat)
- if err != nil {
- return nil, err
- }
- var (
- devType string
- mode = stat.Mode
- devNumber = uint64(stat.Rdev) // nolint: unconvert
- m = os.FileMode(mode)
- )
-
- switch {
- case mode&unix.S_IFBLK == unix.S_IFBLK:
- devType = "b"
- case mode&unix.S_IFCHR == unix.S_IFCHR:
- devType = "c"
- case mode&unix.S_IFIFO == unix.S_IFIFO:
- devType = "p"
- default:
- return nil, errNotADevice
- }
-
- return &spec.LinuxDevice{
- Type: devType,
- Path: path,
- FileMode: &m,
- UID: &stat.Uid,
- GID: &stat.Gid,
- Major: int64(unix.Major(devNumber)),
- Minor: int64(unix.Minor(devNumber)),
- }, nil
-}
-
func supportAmbientCapabilities() bool {
err := unix.Prctl(unix.PR_CAP_AMBIENT, unix.PR_CAP_AMBIENT_IS_SET, 0, 0, 0)
return err == nil
diff --git a/pkg/specgen/generate/config_linux_cgo.go b/pkg/specgen/generate/config_linux_cgo.go
index efab6679a..74ba4aeeb 100644
--- a/pkg/specgen/generate/config_linux_cgo.go
+++ b/pkg/specgen/generate/config_linux_cgo.go
@@ -5,6 +5,8 @@ package generate
import (
"context"
+ "errors"
+ "fmt"
"io/ioutil"
"github.com/containers/common/libimage"
@@ -12,7 +14,6 @@ import (
"github.com/containers/podman/v4/pkg/seccomp"
"github.com/containers/podman/v4/pkg/specgen"
spec "github.com/opencontainers/runtime-spec/specs-go"
- "github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -39,7 +40,7 @@ func getSeccompConfig(s *specgen.SpecGenerator, configSpec *spec.Spec, img *libi
logrus.Debug("Loading seccomp profile from the security config")
seccompConfig, err = goSeccomp.LoadProfile(imagePolicy, configSpec)
if err != nil {
- return nil, errors.Wrap(err, "loading seccomp profile failed")
+ return nil, fmt.Errorf("loading seccomp profile failed: %w", err)
}
return seccompConfig, nil
}
@@ -48,17 +49,17 @@ func getSeccompConfig(s *specgen.SpecGenerator, configSpec *spec.Spec, img *libi
logrus.Debugf("Loading seccomp profile from %q", s.SeccompProfilePath)
seccompProfile, err := ioutil.ReadFile(s.SeccompProfilePath)
if err != nil {
- return nil, errors.Wrap(err, "opening seccomp profile failed")
+ return nil, fmt.Errorf("opening seccomp profile failed: %w", err)
}
seccompConfig, err = goSeccomp.LoadProfile(string(seccompProfile), configSpec)
if err != nil {
- return nil, errors.Wrapf(err, "loading seccomp profile (%s) failed", s.SeccompProfilePath)
+ return nil, fmt.Errorf("loading seccomp profile (%s) failed: %w", s.SeccompProfilePath, err)
}
} else {
logrus.Debug("Loading default seccomp profile")
seccompConfig, err = goSeccomp.GetDefaultProfile(configSpec)
if err != nil {
- return nil, errors.Wrapf(err, "loading seccomp profile (%s) failed", s.SeccompProfilePath)
+ return nil, fmt.Errorf("loading seccomp profile (%s) failed: %w", s.SeccompProfilePath, err)
}
}
diff --git a/pkg/specgen/generate/container.go b/pkg/specgen/generate/container.go
index cc376125f..2248c9235 100644
--- a/pkg/specgen/generate/container.go
+++ b/pkg/specgen/generate/container.go
@@ -3,6 +3,7 @@ package generate
import (
"context"
"encoding/json"
+ "errors"
"fmt"
"os"
"strings"
@@ -17,7 +18,6 @@ import (
"github.com/containers/podman/v4/pkg/signal"
"github.com/containers/podman/v4/pkg/specgen"
spec "github.com/opencontainers/runtime-spec/specs-go"
- "github.com/pkg/errors"
"github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
)
@@ -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 {
@@ -106,7 +115,7 @@ func CompleteSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerat
// Get Default Environment from containers.conf
defaultEnvs, err := envLib.ParseSlice(rtc.GetDefaultEnvEx(s.EnvHost, s.HTTPProxy))
if err != nil {
- return nil, errors.Wrap(err, "error parsing fields in containers.conf")
+ return nil, fmt.Errorf("error parsing fields in containers.conf: %w", err)
}
var envs map[string]string
@@ -116,7 +125,7 @@ func CompleteSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerat
// already, overriding the default environments
envs, err = envLib.ParseSlice(inspectData.Config.Env)
if err != nil {
- return nil, errors.Wrap(err, "Env fields from image failed to parse")
+ return nil, fmt.Errorf("env fields from image failed to parse: %w", err)
}
defaultEnvs = envLib.Join(envLib.DefaultEnvVariables(), envLib.Join(defaultEnvs, envs))
}
@@ -132,7 +141,7 @@ func CompleteSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerat
// any case.
osEnv, err := envLib.ParseSlice(os.Environ())
if err != nil {
- return nil, errors.Wrap(err, "error parsing host environment variables")
+ return nil, fmt.Errorf("error parsing host environment variables: %w", err)
}
// Caller Specified defaults
if s.EnvHost {
@@ -303,8 +312,8 @@ func FinishThrottleDevices(s *specgen.SpecGenerator) error {
if err := unix.Stat(k, &statT); err != nil {
return err
}
- v.Major = (int64(unix.Major(uint64(statT.Rdev)))) // nolint: unconvert
- v.Minor = (int64(unix.Minor(uint64(statT.Rdev)))) // nolint: unconvert
+ v.Major = (int64(unix.Major(uint64(statT.Rdev)))) //nolint: unconvert
+ v.Minor = (int64(unix.Minor(uint64(statT.Rdev)))) //nolint: unconvert
if s.ResourceLimits.BlockIO == nil {
s.ResourceLimits.BlockIO = new(spec.LinuxBlockIO)
}
@@ -317,8 +326,8 @@ func FinishThrottleDevices(s *specgen.SpecGenerator) error {
if err := unix.Stat(k, &statT); err != nil {
return err
}
- v.Major = (int64(unix.Major(uint64(statT.Rdev)))) // nolint: unconvert
- v.Minor = (int64(unix.Minor(uint64(statT.Rdev)))) // nolint: unconvert
+ v.Major = (int64(unix.Major(uint64(statT.Rdev)))) //nolint: unconvert
+ v.Minor = (int64(unix.Minor(uint64(statT.Rdev)))) //nolint: unconvert
s.ResourceLimits.BlockIO.ThrottleWriteBpsDevice = append(s.ResourceLimits.BlockIO.ThrottleWriteBpsDevice, v)
}
}
@@ -328,8 +337,8 @@ func FinishThrottleDevices(s *specgen.SpecGenerator) error {
if err := unix.Stat(k, &statT); err != nil {
return err
}
- v.Major = (int64(unix.Major(uint64(statT.Rdev)))) // nolint: unconvert
- v.Minor = (int64(unix.Minor(uint64(statT.Rdev)))) // nolint: unconvert
+ v.Major = (int64(unix.Major(uint64(statT.Rdev)))) //nolint: unconvert
+ v.Minor = (int64(unix.Minor(uint64(statT.Rdev)))) //nolint: unconvert
s.ResourceLimits.BlockIO.ThrottleReadIOPSDevice = append(s.ResourceLimits.BlockIO.ThrottleReadIOPSDevice, v)
}
}
@@ -339,8 +348,8 @@ func FinishThrottleDevices(s *specgen.SpecGenerator) error {
if err := unix.Stat(k, &statT); err != nil {
return err
}
- v.Major = (int64(unix.Major(uint64(statT.Rdev)))) // nolint: unconvert
- v.Minor = (int64(unix.Minor(uint64(statT.Rdev)))) // nolint: unconvert
+ v.Major = (int64(unix.Major(uint64(statT.Rdev)))) //nolint: unconvert
+ v.Minor = (int64(unix.Minor(uint64(statT.Rdev)))) //nolint: unconvert
s.ResourceLimits.BlockIO.ThrottleWriteIOPSDevice = append(s.ResourceLimits.BlockIO.ThrottleWriteIOPSDevice, v)
}
}
@@ -450,7 +459,7 @@ func ConfigToSpec(rt *libpod.Runtime, specg *specgen.SpecGenerator, contaierID s
specg.IpcNS = specgen.Namespace{NSMode: specgen.Default} // default
}
case "uts":
- specg.UtsNS = specgen.Namespace{NSMode: specgen.Default} // default
+ specg.UtsNS = specgen.Namespace{NSMode: specgen.Private} // default
case "user":
if conf.AddCurrentUserPasswdEntry {
specg.UserNS = specgen.Namespace{NSMode: specgen.KeepID}
@@ -506,6 +515,7 @@ func ConfigToSpec(rt *libpod.Runtime, specg *specgen.SpecGenerator, contaierID s
specg.Mounts = mounts
specg.HostDeviceList = conf.DeviceHostSrc
specg.Networks = conf.Networks
+ specg.ShmSize = &conf.ShmSize
mapSecurityConfig(conf, specg)
diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go
index 04e24d625..51d290bb4 100644
--- a/pkg/specgen/generate/container_create.go
+++ b/pkg/specgen/generate/container_create.go
@@ -3,6 +3,8 @@ package generate
import (
"context"
"encoding/json"
+ "errors"
+ "fmt"
"path/filepath"
"strings"
@@ -15,7 +17,6 @@ import (
"github.com/containers/podman/v4/pkg/util"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/selinux/go-selinux/label"
- "github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -34,7 +35,7 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
if s.Pod != "" {
pod, err = rt.LookupPod(s.Pod)
if err != nil {
- return nil, nil, nil, errors.Wrapf(err, "error retrieving pod %s", s.Pod)
+ return nil, nil, nil, fmt.Errorf("error retrieving pod %s: %w", s.Pod, err)
}
if pod.HasInfraContainer() {
infra, err = pod.InfraContainer()
@@ -133,8 +134,14 @@ 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")
+ return nil, nil, nil, fmt.Errorf("invalid config provided: %w", err)
}
finalMounts, finalVolumes, finalOverlays, err := finalizeMounts(ctx, s, rt, rtc, newImage)
@@ -180,10 +187,23 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
if err != nil {
return nil, nil, nil, err
}
+ resources := runtimeSpec.Linux.Resources
+
+ // resources get overwrritten similarly to pod inheritance, manually assign here if there is a new value
+ marshalRes, err := json.Marshal(resources)
+ if err != nil {
+ return nil, nil, nil, err
+ }
+
err = json.Unmarshal(out, runtimeSpec.Linux)
if err != nil {
return nil, nil, nil, err
}
+
+ err = json.Unmarshal(marshalRes, runtimeSpec.Linux.Resources)
+ if err != nil {
+ return nil, nil, nil, err
+ }
}
if s.ResourceLimits != nil {
switch {
@@ -278,6 +298,10 @@ func createContainerOptions(rt *libpod.Runtime, s *specgen.SpecGenerator, pod *l
options = append(options, libpod.WithPasswdEntry(s.PasswdEntry))
}
+ if s.Privileged {
+ options = append(options, libpod.WithMountAllDevices())
+ }
+
useSystemd := false
switch s.Systemd {
case "always":
@@ -309,7 +333,7 @@ func createContainerOptions(rt *libpod.Runtime, s *specgen.SpecGenerator, pod *l
}
}
default:
- return nil, errors.Wrapf(err, "invalid value %q systemd option requires 'true, false, always'", s.Systemd)
+ return nil, fmt.Errorf("invalid value %q systemd option requires 'true, false, always': %w", s.Systemd, err)
}
logrus.Debugf("using systemd mode: %t", useSystemd)
if useSystemd {
@@ -318,7 +342,7 @@ func createContainerOptions(rt *libpod.Runtime, s *specgen.SpecGenerator, pod *l
if s.StopSignal == nil {
stopSignal, err := util.ParseSignal("RTMIN+3")
if err != nil {
- return nil, errors.Wrapf(err, "error parsing systemd signal")
+ return nil, fmt.Errorf("error parsing systemd signal: %w", err)
}
s.StopSignal = &stopSignal
}
@@ -513,7 +537,7 @@ func createContainerOptions(rt *libpod.Runtime, s *specgen.SpecGenerator, pod *l
for _, ctr := range s.DependencyContainers {
depCtr, err := rt.LookupContainer(ctr)
if err != nil {
- return nil, errors.Wrapf(err, "%q is not a valid container, cannot be used as a dependency", ctr)
+ return nil, fmt.Errorf("%q is not a valid container, cannot be used as a dependency: %w", ctr, err)
}
deps = append(deps, depCtr)
}
@@ -542,6 +566,16 @@ func Inherit(infra libpod.Container, s *specgen.SpecGenerator, rt *libpod.Runtim
infraConf := infra.Config()
infraSpec := infraConf.Spec
+ // need to set compatOptions to the currently filled specgenOptions so we do not overwrite
+ compatibleOptions.CapAdd = append(compatibleOptions.CapAdd, s.CapAdd...)
+ compatibleOptions.CapDrop = append(compatibleOptions.CapDrop, s.CapDrop...)
+ compatibleOptions.HostDeviceList = append(compatibleOptions.HostDeviceList, s.HostDeviceList...)
+ compatibleOptions.ImageVolumes = append(compatibleOptions.ImageVolumes, s.ImageVolumes...)
+ compatibleOptions.Mounts = append(compatibleOptions.Mounts, s.Mounts...)
+ compatibleOptions.OverlayVolumes = append(compatibleOptions.OverlayVolumes, s.OverlayVolumes...)
+ compatibleOptions.SelinuxOpts = append(compatibleOptions.SelinuxOpts, s.SelinuxOpts...)
+ compatibleOptions.Volumes = append(compatibleOptions.Volumes, s.Volumes...)
+
compatByte, err := json.Marshal(compatibleOptions)
if err != nil {
return nil, nil, nil, err
@@ -550,5 +584,10 @@ func Inherit(infra libpod.Container, s *specgen.SpecGenerator, rt *libpod.Runtim
if err != nil {
return nil, nil, nil, err
}
+
+ // this causes errors when shmSize is the default value, it will still get passed down unless we manually override.
+ if s.IpcNS.NSMode == specgen.Host && (compatibleOptions.ShmSize != nil && compatibleOptions.IsDefaultShmSize()) {
+ s.ShmSize = nil
+ }
return options, infraSpec, compatibleOptions, nil
}
diff --git a/pkg/specgen/generate/kube/kube.go b/pkg/specgen/generate/kube/kube.go
index f37d79798..454a1e1d0 100644
--- a/pkg/specgen/generate/kube/kube.go
+++ b/pkg/specgen/generate/kube/kube.go
@@ -3,6 +3,7 @@ package kube
import (
"context"
"encoding/json"
+ "errors"
"fmt"
"math"
"net"
@@ -16,6 +17,7 @@ import (
"github.com/containers/common/libnetwork/types"
"github.com/containers/common/pkg/parse"
"github.com/containers/common/pkg/secrets"
+ cutil "github.com/containers/common/pkg/util"
"github.com/containers/image/v5/manifest"
"github.com/containers/podman/v4/libpod/define"
ann "github.com/containers/podman/v4/pkg/annotations"
@@ -28,7 +30,6 @@ import (
"github.com/docker/docker/pkg/system"
"github.com/docker/go-units"
spec "github.com/opencontainers/runtime-spec/specs-go"
- "github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -145,7 +146,7 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
// pod name should be non-empty for Deployment objects to be able to create
// multiple pods having containers with unique names
if len(opts.PodName) < 1 {
- return nil, errors.Errorf("got empty pod name on container creation when playing kube")
+ return nil, errors.New("got empty pod name on container creation when playing kube")
}
s.Name = fmt.Sprintf("%s-%s", opts.PodName, opts.Container.Name)
@@ -162,7 +163,7 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
for _, o := range opts.LogOptions {
split := strings.SplitN(o, "=", 2)
if len(split) < 2 {
- return nil, errors.Errorf("invalid log option %q", o)
+ return nil, fmt.Errorf("invalid log option %q", o)
}
switch strings.ToLower(split[0]) {
case "driver":
@@ -178,7 +179,7 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
default:
switch len(split[1]) {
case 0:
- return nil, errors.Wrapf(define.ErrInvalidArg, "invalid log option")
+ return nil, fmt.Errorf("invalid log option: %w", define.ErrInvalidArg)
default:
// tags for journald only
if s.LogConfiguration.Driver == "" || s.LogConfiguration.Driver == define.JournaldLogging {
@@ -195,7 +196,7 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
setupSecurityContext(s, opts.Container.SecurityContext, opts.PodSecurityContext)
err := setupLivenessProbe(s, opts.Container, opts.RestartPolicy)
if err != nil {
- return nil, errors.Wrap(err, "Failed to configure livenessProbe")
+ return nil, fmt.Errorf("failed to configure livenessProbe: %w", err)
}
// Since we prefix the container name with pod name to work-around the uniqueness requirement,
@@ -206,7 +207,7 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
s.ResourceLimits = &spec.LinuxResources{}
milliCPU, err := quantityToInt64(opts.Container.Resources.Limits.Cpu())
if err != nil {
- return nil, errors.Wrap(err, "Failed to set CPU quota")
+ return nil, fmt.Errorf("failed to set CPU quota: %w", err)
}
if milliCPU > 0 {
period, quota := util.CoresToPeriodAndQuota(float64(milliCPU))
@@ -218,12 +219,12 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
limit, err := quantityToInt64(opts.Container.Resources.Limits.Memory())
if err != nil {
- return nil, errors.Wrap(err, "Failed to set memory limit")
+ return nil, fmt.Errorf("failed to set memory limit: %w", err)
}
memoryRes, err := quantityToInt64(opts.Container.Resources.Requests.Memory())
if err != nil {
- return nil, errors.Wrap(err, "Failed to set memory reservation")
+ return nil, fmt.Errorf("failed to set memory reservation: %w", err)
}
if limit > 0 || memoryRes > 0 {
@@ -336,7 +337,7 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
for _, volume := range opts.Container.VolumeMounts {
volumeSource, exists := opts.Volumes[volume.Name]
if !exists {
- return nil, errors.Errorf("Volume mount %s specified for container but not configured in volumes", volume.Name)
+ return nil, fmt.Errorf("volume mount %s specified for container but not configured in volumes", volume.Name)
}
// Skip if the volume is optional. This means that a configmap for a configmap volume was not found but it was
// optional so we can move on without throwing an error
@@ -356,7 +357,7 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
// a selinux mount option exists for it
for k, v := range opts.Annotations {
// Make sure the z/Z option is not already there (from editing the YAML)
- if strings.Replace(k, define.BindMountPrefix, "", 1) == volumeSource.Source && !util.StringInSlice("z", options) && !util.StringInSlice("Z", options) {
+ if strings.Replace(k, define.BindMountPrefix, "", 1) == volumeSource.Source && !cutil.StringInSlice("z", options) && !cutil.StringInSlice("Z", options) {
options = append(options, v)
}
}
@@ -398,7 +399,7 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
}
s.Devices = append(s.Devices, device)
default:
- return nil, errors.Errorf("Unsupported volume source type")
+ return nil, errors.New("unsupported volume source type")
}
}
@@ -431,21 +432,21 @@ func parseMountPath(mountPath string, readOnly bool, propagationMode *v1.MountPr
options := []string{}
splitVol := strings.Split(mountPath, ":")
if len(splitVol) > 2 {
- return "", options, errors.Errorf("%q incorrect volume format, should be ctr-dir[:option]", mountPath)
+ return "", options, fmt.Errorf("%q incorrect volume format, should be ctr-dir[:option]", mountPath)
}
dest := splitVol[0]
if len(splitVol) > 1 {
options = strings.Split(splitVol[1], ",")
}
if err := parse.ValidateVolumeCtrDir(dest); err != nil {
- return "", options, errors.Wrapf(err, "parsing MountPath")
+ return "", options, fmt.Errorf("parsing MountPath: %w", err)
}
if readOnly {
options = append(options, "ro")
}
opts, err := parse.ValidateVolumeOpts(options)
if err != nil {
- return "", opts, errors.Wrapf(err, "parsing MountOptions")
+ return "", opts, fmt.Errorf("parsing MountOptions: %w", err)
}
if propagationMode != nil {
switch *propagationMode {
@@ -456,7 +457,7 @@ func parseMountPath(mountPath string, readOnly bool, propagationMode *v1.MountPr
case v1.MountPropagationBidirectional:
opts = append(opts, "rshared")
default:
- return "", opts, errors.Errorf("unknown propagation mode %q", *propagationMode)
+ return "", opts, fmt.Errorf("unknown propagation mode %q", *propagationMode)
}
}
return dest, opts, nil
@@ -503,19 +504,19 @@ func setupLivenessProbe(s *specgen.SpecGenerator, containerYAML v1.Container, re
func makeHealthCheck(inCmd string, interval int32, retries int32, timeout int32, startPeriod int32) (*manifest.Schema2HealthConfig, error) {
// Every healthcheck requires a command
if len(inCmd) == 0 {
- return nil, errors.New("Must define a healthcheck command for all healthchecks")
+ return nil, errors.New("must define a healthcheck command for all healthchecks")
}
// first try to parse option value as JSON array of strings...
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, " ")...)
}
}
@@ -629,7 +630,7 @@ func quantityToInt64(quantity *resource.Quantity) (int64, error) {
return i, nil
}
- return 0, errors.Errorf("Quantity cannot be represented as int64: %v", quantity)
+ return 0, fmt.Errorf("quantity cannot be represented as int64: %v", quantity)
}
// read a k8s secret in JSON format from the secret manager
@@ -641,7 +642,7 @@ func k8sSecretFromSecretManager(name string, secretsManager *secrets.SecretsMana
var secrets map[string][]byte
if err := json.Unmarshal(jsonSecret, &secrets); err != nil {
- return nil, errors.Errorf("Secret %v is not valid JSON: %v", name, err)
+ return nil, fmt.Errorf("secret %v is not valid JSON: %v", name, err)
}
return secrets, nil
}
@@ -652,7 +653,7 @@ func envVarsFrom(envFrom v1.EnvFromSource, opts *CtrSpecGenOptions) (map[string]
if envFrom.ConfigMapRef != nil {
cmRef := envFrom.ConfigMapRef
- err := errors.Errorf("Configmap %v not found", cmRef.Name)
+ err := fmt.Errorf("configmap %v not found", cmRef.Name)
for _, c := range opts.ConfigMaps {
if cmRef.Name == c.Name {
@@ -688,14 +689,14 @@ func envVarValue(env v1.EnvVar, opts *CtrSpecGenOptions) (*string, error) {
if env.ValueFrom != nil {
if env.ValueFrom.ConfigMapKeyRef != nil {
cmKeyRef := env.ValueFrom.ConfigMapKeyRef
- err := errors.Errorf("Cannot set env %v: configmap %v not found", env.Name, cmKeyRef.Name)
+ err := fmt.Errorf("cannot set env %v: configmap %v not found", env.Name, cmKeyRef.Name)
for _, c := range opts.ConfigMaps {
if cmKeyRef.Name == c.Name {
if value, ok := c.Data[cmKeyRef.Key]; ok {
return &value, nil
}
- err = errors.Errorf("Cannot set env %v: key %s not found in configmap %v", env.Name, cmKeyRef.Key, cmKeyRef.Name)
+ err = fmt.Errorf("cannot set env %v: key %s not found in configmap %v", env.Name, cmKeyRef.Key, cmKeyRef.Name)
break
}
}
@@ -713,10 +714,10 @@ func envVarValue(env v1.EnvVar, opts *CtrSpecGenOptions) (*string, error) {
value := string(val)
return &value, nil
}
- err = errors.Errorf("Secret %v has not %v key", secKeyRef.Name, secKeyRef.Key)
+ err = fmt.Errorf("secret %v has not %v key", secKeyRef.Name, secKeyRef.Key)
}
if secKeyRef.Optional == nil || !*secKeyRef.Optional {
- return nil, errors.Errorf("Cannot set env %v: %v", env.Name, err)
+ return nil, fmt.Errorf("cannot set env %v: %v", env.Name, err)
}
return nil, nil
}
@@ -760,8 +761,8 @@ func envVarValueFieldRef(env v1.EnvVar, opts *CtrSpecGenOptions) (*string, error
return &annotationValue, nil
}
- return nil, errors.Errorf(
- "Can not set env %v. Reason: fieldPath %v is either not valid or not supported",
+ return nil, fmt.Errorf(
+ "can not set env %v. Reason: fieldPath %v is either not valid or not supported",
env.Name, fieldPath,
)
}
@@ -795,22 +796,22 @@ func envVarValueResourceFieldRef(env v1.EnvVar, opts *CtrSpecGenOptions) (*strin
value = resources.Requests.Cpu()
isValidDivisor = isCPUDivisor(divisor)
default:
- return nil, errors.Errorf(
- "Can not set env %v. Reason: resource %v is either not valid or not supported",
+ return nil, fmt.Errorf(
+ "can not set env %v. Reason: resource %v is either not valid or not supported",
env.Name, resourceName,
)
}
if !isValidDivisor {
- return nil, errors.Errorf(
- "Can not set env %s. Reason: divisor value %s is not valid",
+ return nil, fmt.Errorf(
+ "can not set env %s. Reason: divisor value %s is not valid",
env.Name, divisor.String(),
)
}
// 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/kube/seccomp.go b/pkg/specgen/generate/kube/seccomp.go
index 8f93b34ff..6e3accd8b 100644
--- a/pkg/specgen/generate/kube/seccomp.go
+++ b/pkg/specgen/generate/kube/seccomp.go
@@ -1,12 +1,12 @@
package kube
import (
+ "fmt"
"path/filepath"
"strings"
"github.com/containers/podman/v4/libpod"
v1 "github.com/containers/podman/v4/pkg/k8s.io/api/core/v1"
- "github.com/pkg/errors"
)
// KubeSeccompPaths holds information about a pod YAML's seccomp configuration
@@ -42,7 +42,7 @@ func InitializeSeccompPaths(annotations map[string]string, profileRoot string) (
// this could be caused by a user inputting either of
// container.seccomp.security.alpha.kubernetes.io{,/}
// both of which are invalid
- return nil, errors.Errorf("Invalid seccomp path: %s", prefixAndCtr[0])
+ return nil, fmt.Errorf("invalid seccomp path: %s", prefixAndCtr[0])
}
path, err := verifySeccompPath(seccomp, profileRoot)
@@ -80,6 +80,6 @@ func verifySeccompPath(path string, profileRoot string) (string, error) {
if parts[0] == "localhost" {
return filepath.Join(profileRoot, parts[1]), nil
}
- return "", errors.Errorf("invalid seccomp path: %s", path)
+ return "", fmt.Errorf("invalid seccomp path: %s", path)
}
}
diff --git a/pkg/specgen/generate/kube/volume.go b/pkg/specgen/generate/kube/volume.go
index 1d6d49b9d..f5c0c241d 100644
--- a/pkg/specgen/generate/kube/volume.go
+++ b/pkg/specgen/generate/kube/volume.go
@@ -1,12 +1,13 @@
package kube
import (
+ "errors"
+ "fmt"
"os"
"github.com/containers/common/pkg/parse"
"github.com/containers/podman/v4/libpod"
v1 "github.com/containers/podman/v4/pkg/k8s.io/api/core/v1"
- "github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -56,13 +57,13 @@ func VolumeFromHostPath(hostPath *v1.HostPathVolumeSource) (*KubeVolume, error)
}
// Label a newly created volume
if err := libpod.LabelVolumePath(hostPath.Path); err != nil {
- return nil, errors.Wrapf(err, "error giving %s a label", hostPath.Path)
+ return nil, fmt.Errorf("error giving %s a label: %w", hostPath.Path, err)
}
case v1.HostPathFileOrCreate:
if _, err := os.Stat(hostPath.Path); os.IsNotExist(err) {
f, err := os.OpenFile(hostPath.Path, os.O_RDONLY|os.O_CREATE, kubeFilePermission)
if err != nil {
- return nil, errors.Wrap(err, "error creating HostPath")
+ return nil, fmt.Errorf("error creating HostPath: %w", err)
}
if err := f.Close(); err != nil {
logrus.Warnf("Error in closing newly created HostPath file: %v", err)
@@ -70,23 +71,23 @@ func VolumeFromHostPath(hostPath *v1.HostPathVolumeSource) (*KubeVolume, error)
}
// unconditionally label a newly created volume
if err := libpod.LabelVolumePath(hostPath.Path); err != nil {
- return nil, errors.Wrapf(err, "error giving %s a label", hostPath.Path)
+ return nil, fmt.Errorf("error giving %s a label: %w", hostPath.Path, err)
}
case v1.HostPathSocket:
st, err := os.Stat(hostPath.Path)
if err != nil {
- return nil, errors.Wrap(err, "error checking HostPathSocket")
+ return nil, fmt.Errorf("error checking HostPathSocket: %w", err)
}
if st.Mode()&os.ModeSocket != os.ModeSocket {
- return nil, errors.Errorf("checking HostPathSocket: path %s is not a socket", hostPath.Path)
+ return nil, fmt.Errorf("checking HostPathSocket: path %s is not a socket", hostPath.Path)
}
case v1.HostPathBlockDev:
dev, err := os.Stat(hostPath.Path)
if err != nil {
- return nil, errors.Wrap(err, "error checking HostPathBlockDevice")
+ return nil, fmt.Errorf("error checking HostPathBlockDevice: %w", err)
}
if dev.Mode()&os.ModeCharDevice == os.ModeCharDevice {
- return nil, errors.Errorf("checking HostPathDevice: path %s is not a block device", hostPath.Path)
+ return nil, fmt.Errorf("checking HostPathDevice: path %s is not a block device", hostPath.Path)
}
return &KubeVolume{
Type: KubeVolumeTypeBlockDevice,
@@ -95,10 +96,10 @@ func VolumeFromHostPath(hostPath *v1.HostPathVolumeSource) (*KubeVolume, error)
case v1.HostPathCharDev:
dev, err := os.Stat(hostPath.Path)
if err != nil {
- return nil, errors.Wrap(err, "error checking HostPathCharDevice")
+ return nil, fmt.Errorf("error checking HostPathCharDevice: %w", err)
}
if dev.Mode()&os.ModeCharDevice != os.ModeCharDevice {
- return nil, errors.Errorf("checking HostPathCharDevice: path %s is not a character device", hostPath.Path)
+ return nil, fmt.Errorf("checking HostPathCharDevice: path %s is not a character device", hostPath.Path)
}
return &KubeVolume{
Type: KubeVolumeTypeCharDevice,
@@ -110,12 +111,12 @@ func VolumeFromHostPath(hostPath *v1.HostPathVolumeSource) (*KubeVolume, error)
// do nothing here because we will verify the path exists in validateVolumeHostDir
break
default:
- return nil, errors.Errorf("Invalid HostPath type %v", hostPath.Type)
+ return nil, fmt.Errorf("invalid HostPath type %v", hostPath.Type)
}
}
if err := parse.ValidateVolumeHostDir(hostPath.Path); err != nil {
- return nil, errors.Wrapf(err, "error in parsing HostPath in YAML")
+ return nil, fmt.Errorf("error in parsing HostPath in YAML: %w", err)
}
return &KubeVolume{
@@ -152,7 +153,7 @@ func VolumeFromConfigMap(configMapVolumeSource *v1.ConfigMapVolumeSource, config
kv.Optional = *configMapVolumeSource.Optional
return kv, nil
}
- return nil, errors.Errorf("no such ConfigMap %q", configMapVolumeSource.Name)
+ return nil, fmt.Errorf("no such ConfigMap %q", configMapVolumeSource.Name)
}
// If there are Items specified in the volumeSource, that overwrites the Data from the configmap
@@ -180,7 +181,7 @@ func VolumeFromSource(volumeSource v1.VolumeSource, configMaps []v1.ConfigMap) (
case volumeSource.ConfigMap != nil:
return VolumeFromConfigMap(volumeSource.ConfigMap, configMaps)
default:
- return nil, errors.Errorf("HostPath, ConfigMap, and PersistentVolumeClaim are currently the only supported VolumeSource")
+ return nil, errors.New("HostPath, ConfigMap, and PersistentVolumeClaim are currently the only supported VolumeSource")
}
}
@@ -191,7 +192,7 @@ func InitializeVolumes(specVolumes []v1.Volume, configMaps []v1.ConfigMap) (map[
for _, specVolume := range specVolumes {
volume, err := VolumeFromSource(specVolume.VolumeSource, configMaps)
if err != nil {
- return nil, errors.Wrapf(err, "failed to create volume %q", specVolume.Name)
+ return nil, fmt.Errorf("failed to create volume %q: %w", specVolume.Name, err)
}
volumes[specVolume.Name] = volume
diff --git a/pkg/specgen/generate/namespaces.go b/pkg/specgen/generate/namespaces.go
index 37d561ec2..f0d4e9153 100644
--- a/pkg/specgen/generate/namespaces.go
+++ b/pkg/specgen/generate/namespaces.go
@@ -1,6 +1,7 @@
package generate
import (
+ "errors"
"fmt"
"os"
"strings"
@@ -15,10 +16,11 @@ import (
"github.com/containers/podman/v4/pkg/util"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-tools/generate"
- "github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
+const host = "host"
+
// Get the default namespace mode for any given namespace type.
func GetDefaultNamespaceMode(nsType string, cfg *config.Config, pod *libpod.Pod) (specgen.Namespace, error) {
// The default for most is private
@@ -33,16 +35,38 @@ func GetDefaultNamespaceMode(nsType string, cfg *config.Config, pod *libpod.Pod)
podMode := false
switch {
case nsType == "pid" && pod.SharesPID():
+ if pod.NamespaceMode(spec.PIDNamespace) == host {
+ toReturn.NSMode = specgen.Host
+ return toReturn, nil
+ }
podMode = true
case nsType == "ipc" && pod.SharesIPC():
+ if pod.NamespaceMode(spec.IPCNamespace) == host {
+ toReturn.NSMode = specgen.Host
+ return toReturn, nil
+ }
podMode = true
case nsType == "uts" && pod.SharesUTS():
+ if pod.NamespaceMode(spec.UTSNamespace) == host {
+ toReturn.NSMode = specgen.Host
+ return toReturn, nil
+ }
podMode = true
case nsType == "user" && pod.SharesUser():
+ // user does not need a special check for host, this is already validated on pod creation
+ // if --userns=host then pod.SharesUser == false
podMode = true
case nsType == "net" && pod.SharesNet():
+ if pod.NetworkMode() == host {
+ toReturn.NSMode = specgen.Host
+ return toReturn, nil
+ }
podMode = true
case nsType == "cgroup" && pod.SharesCgroup():
+ if pod.NamespaceMode(spec.CgroupNamespace) == host {
+ toReturn.NSMode = specgen.Host
+ return toReturn, nil
+ }
podMode = true
}
if podMode {
@@ -70,7 +94,7 @@ func GetDefaultNamespaceMode(nsType string, cfg *config.Config, pod *libpod.Pod)
return ns, err
}
- return toReturn, errors.Wrapf(define.ErrInvalidArg, "invalid namespace type %q passed", nsType)
+ return toReturn, fmt.Errorf("invalid namespace type %q passed: %w", nsType, define.ErrInvalidArg)
}
// namespaceOptions generates container creation options for all
@@ -89,18 +113,18 @@ func namespaceOptions(s *specgen.SpecGenerator, rt *libpod.Runtime, pod *libpod.
if err != nil {
// This is likely to be of the fatal kind (pod was
// removed) so hard fail
- return nil, errors.Wrapf(err, "error looking up pod %s infra container", pod.ID())
+ return nil, fmt.Errorf("error looking up pod %s infra container: %w", pod.ID(), err)
}
if infraID != "" {
ctr, err := rt.GetContainer(infraID)
if err != nil {
- return nil, errors.Wrapf(err, "error retrieving pod %s infra container %s", pod.ID(), infraID)
+ return nil, fmt.Errorf("error retrieving pod %s infra container %s: %w", pod.ID(), infraID, err)
}
infraCtr = ctr
}
}
- errNoInfra := errors.Wrapf(define.ErrInvalidArg, "cannot use pod namespace as container is not joining a pod or pod has no infra container")
+ errNoInfra := fmt.Errorf("cannot use pod namespace as container is not joining a pod or pod has no infra container: %w", define.ErrInvalidArg)
// PID
switch s.PidNS.NSMode {
@@ -112,7 +136,7 @@ func namespaceOptions(s *specgen.SpecGenerator, rt *libpod.Runtime, pod *libpod.
case specgen.FromContainer:
pidCtr, err := rt.LookupContainer(s.PidNS.Value)
if err != nil {
- return nil, errors.Wrapf(err, "error looking up container to share pid namespace with")
+ return nil, fmt.Errorf("error looking up container to share pid namespace with: %w", err)
}
toReturn = append(toReturn, libpod.WithPIDNSFrom(pidCtr))
}
@@ -131,10 +155,10 @@ func namespaceOptions(s *specgen.SpecGenerator, rt *libpod.Runtime, pod *libpod.
case specgen.FromContainer:
ipcCtr, err := rt.LookupContainer(s.IpcNS.Value)
if err != nil {
- return nil, errors.Wrapf(err, "error looking up container to share ipc namespace with")
+ return nil, fmt.Errorf("error looking up container to share ipc namespace with: %w", err)
}
if ipcCtr.ConfigNoCopy().NoShmShare {
- return nil, errors.Errorf("joining IPC of container %s is not allowed: non-shareable IPC (hint: use IpcMode:shareable for the donor container)", ipcCtr.ID())
+ return nil, fmt.Errorf("joining IPC of container %s is not allowed: non-shareable IPC (hint: use IpcMode:shareable for the donor container)", ipcCtr.ID())
}
toReturn = append(toReturn, libpod.WithIPCNSFrom(ipcCtr))
if !ipcCtr.ConfigNoCopy().NoShm {
@@ -152,11 +176,18 @@ 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 {
- return nil, errors.Wrapf(err, "error looking up container to share uts namespace with")
+ return nil, fmt.Errorf("error looking up container to share uts namespace with: %w", err)
}
toReturn = append(toReturn, libpod.WithUTSNSFrom(utsCtr))
}
@@ -191,7 +222,7 @@ func namespaceOptions(s *specgen.SpecGenerator, rt *libpod.Runtime, pod *libpod.
case specgen.FromContainer:
userCtr, err := rt.LookupContainer(s.UserNS.Value)
if err != nil {
- return nil, errors.Wrapf(err, "error looking up container to share user namespace with")
+ return nil, fmt.Errorf("error looking up container to share user namespace with: %w", err)
}
toReturn = append(toReturn, libpod.WithUserNSFrom(userCtr))
}
@@ -203,7 +234,7 @@ func namespaceOptions(s *specgen.SpecGenerator, rt *libpod.Runtime, pod *libpod.
if pod == nil {
toReturn = append(toReturn, libpod.WithIDMappings(*s.IDMappings))
} else if pod.HasInfraContainer() && (len(s.IDMappings.UIDMap) > 0 || len(s.IDMappings.GIDMap) > 0) {
- return nil, errors.Wrapf(define.ErrInvalidArg, "cannot specify a new uid/gid map when entering a pod with an infra container")
+ return nil, fmt.Errorf("cannot specify a new uid/gid map when entering a pod with an infra container: %w", define.ErrInvalidArg)
}
}
if s.User != "" {
@@ -223,7 +254,7 @@ func namespaceOptions(s *specgen.SpecGenerator, rt *libpod.Runtime, pod *libpod.
case specgen.FromContainer:
cgroupCtr, err := rt.LookupContainer(s.CgroupNS.Value)
if err != nil {
- return nil, errors.Wrapf(err, "error looking up container to share cgroup namespace with")
+ return nil, fmt.Errorf("error looking up container to share cgroup namespace with: %w", err)
}
toReturn = append(toReturn, libpod.WithCgroupNSFrom(cgroupCtr))
}
@@ -236,10 +267,12 @@ func namespaceOptions(s *specgen.SpecGenerator, rt *libpod.Runtime, pod *libpod.
toReturn = append(toReturn, libpod.WithCgroupsMode(s.CgroupsMode))
}
- // Net
- // TODO validate CNINetworks, StaticIP, StaticIPv6 are only set if we
- // are in bridge mode.
postConfigureNetNS := !s.UserNS.IsHost()
+ // when we are rootless we default to slirp4netns
+ if rootless.IsRootless() && (s.NetNS.IsPrivate() || s.NetNS.IsDefault()) {
+ s.NetNS.NSMode = specgen.Slirp
+ }
+
switch s.NetNS.NSMode {
case specgen.FromPod:
if pod == nil || infraCtr == nil {
@@ -249,7 +282,7 @@ func namespaceOptions(s *specgen.SpecGenerator, rt *libpod.Runtime, pod *libpod.
case specgen.FromContainer:
netCtr, err := rt.LookupContainer(s.NetNS.Value)
if err != nil {
- return nil, errors.Wrapf(err, "error looking up container to share net namespace with")
+ return nil, fmt.Errorf("error looking up container to share net namespace with: %w", err)
}
toReturn = append(toReturn, libpod.WithNetNSFrom(netCtr))
case specgen.Slirp:
@@ -262,9 +295,7 @@ func namespaceOptions(s *specgen.SpecGenerator, rt *libpod.Runtime, pod *libpod.
val = fmt.Sprintf("slirp4netns:%s", s.NetNS.Value)
}
toReturn = append(toReturn, libpod.WithNetNS(portMappings, expose, postConfigureNetNS, val, nil))
- case specgen.Private:
- fallthrough
- case specgen.Bridge:
+ case specgen.Bridge, specgen.Private, specgen.Default:
portMappings, expose, err := createPortMappings(s, imageData)
if err != nil {
return nil, err
@@ -331,7 +362,7 @@ func specConfigureNamespaces(s *specgen.SpecGenerator, g *generate.Generator, rt
switch s.PidNS.NSMode {
case specgen.Path:
if _, err := os.Stat(s.PidNS.Value); err != nil {
- return errors.Wrap(err, "cannot find specified PID namespace path")
+ return fmt.Errorf("cannot find specified PID namespace path: %w", err)
}
if err := g.AddOrReplaceLinuxNamespace(string(spec.PIDNamespace), s.PidNS.Value); err != nil {
return err
@@ -350,7 +381,7 @@ func specConfigureNamespaces(s *specgen.SpecGenerator, g *generate.Generator, rt
switch s.IpcNS.NSMode {
case specgen.Path:
if _, err := os.Stat(s.IpcNS.Value); err != nil {
- return errors.Wrap(err, "cannot find specified IPC namespace path")
+ return fmt.Errorf("cannot find specified IPC namespace path: %w", err)
}
if err := g.AddOrReplaceLinuxNamespace(string(spec.IPCNamespace), s.IpcNS.Value); err != nil {
return err
@@ -369,7 +400,7 @@ func specConfigureNamespaces(s *specgen.SpecGenerator, g *generate.Generator, rt
switch s.UtsNS.NSMode {
case specgen.Path:
if _, err := os.Stat(s.UtsNS.Value); err != nil {
- return errors.Wrap(err, "cannot find specified UTS namespace path")
+ return fmt.Errorf("cannot find specified UTS namespace path: %w", err)
}
if err := g.AddOrReplaceLinuxNamespace(string(spec.UTSNamespace), s.UtsNS.Value); err != nil {
return err
@@ -392,13 +423,13 @@ func specConfigureNamespaces(s *specgen.SpecGenerator, g *generate.Generator, rt
case s.UtsNS.NSMode == specgen.FromContainer:
utsCtr, err := rt.LookupContainer(s.UtsNS.Value)
if err != nil {
- return errors.Wrapf(err, "error looking up container to share uts namespace with")
+ return fmt.Errorf("error looking up container to share uts namespace with: %w", err)
}
hostname = utsCtr.Hostname()
case (s.NetNS.NSMode == specgen.Host && hostname == "") || s.UtsNS.NSMode == specgen.Host:
tmpHostname, err := os.Hostname()
if err != nil {
- return errors.Wrap(err, "unable to retrieve hostname of the host")
+ return fmt.Errorf("unable to retrieve hostname of the host: %w", err)
}
hostname = tmpHostname
default:
@@ -427,7 +458,7 @@ func specConfigureNamespaces(s *specgen.SpecGenerator, g *generate.Generator, rt
switch s.CgroupNS.NSMode {
case specgen.Path:
if _, err := os.Stat(s.CgroupNS.Value); err != nil {
- return errors.Wrap(err, "cannot find specified cgroup namespace path")
+ return fmt.Errorf("cannot find specified cgroup namespace path: %w", err)
}
if err := g.AddOrReplaceLinuxNamespace(string(spec.CgroupNamespace), s.CgroupNS.Value); err != nil {
return err
@@ -446,7 +477,7 @@ func specConfigureNamespaces(s *specgen.SpecGenerator, g *generate.Generator, rt
switch s.NetNS.NSMode {
case specgen.Path:
if _, err := os.Stat(s.NetNS.Value); err != nil {
- return errors.Wrap(err, "cannot find specified network namespace path")
+ return fmt.Errorf("cannot find specified network namespace path: %w", err)
}
if err := g.AddOrReplaceLinuxNamespace(string(spec.NetworkNamespace), s.NetNS.Value); err != nil {
return err
@@ -488,12 +519,9 @@ func GetNamespaceOptions(ns []string, netnsIsHost bool) ([]libpod.PodCreateOptio
case "cgroup":
options = append(options, libpod.WithPodCgroup())
case "net":
- // share the netns setting with other containers in the pod only when it is not set to host
- if !netnsIsHost {
- options = append(options, libpod.WithPodNet())
- }
+ options = append(options, libpod.WithPodNet())
case "mnt":
- return erroredOptions, errors.Errorf("Mount sharing functionality not supported on pod level")
+ return erroredOptions, fmt.Errorf("mount sharing functionality not supported on pod level")
case "pid":
options = append(options, libpod.WithPodPID())
case "user":
@@ -506,7 +534,7 @@ func GetNamespaceOptions(ns []string, netnsIsHost bool) ([]libpod.PodCreateOptio
case "none":
return erroredOptions, nil
default:
- return erroredOptions, errors.Errorf("Invalid kernel namespace to share: %s. Options are: cgroup, ipc, net, pid, uts or none", toShare)
+ return erroredOptions, fmt.Errorf("invalid kernel namespace to share: %s. Options are: cgroup, ipc, net, pid, uts or none", toShare)
}
}
return options, nil
diff --git a/pkg/specgen/generate/oci.go b/pkg/specgen/generate/oci.go
index dda2de6e4..bb5f2d0ec 100644
--- a/pkg/specgen/generate/oci.go
+++ b/pkg/specgen/generate/oci.go
@@ -3,6 +3,7 @@ package generate
import (
"context"
"encoding/json"
+ "fmt"
"path"
"strings"
@@ -15,7 +16,6 @@ import (
"github.com/containers/podman/v4/pkg/specgen"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-tools/generate"
- "github.com/pkg/errors"
"github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
)
@@ -117,7 +117,7 @@ func makeCommand(s *specgen.SpecGenerator, imageData *libimage.ImageData, rtc *c
finalCommand = append(finalCommand, command...)
if len(finalCommand) == 0 {
- return nil, errors.Errorf("no command or entrypoint provided, and no CMD or ENTRYPOINT from image")
+ return nil, fmt.Errorf("no command or entrypoint provided, and no CMD or ENTRYPOINT from image")
}
if s.Init {
@@ -126,7 +126,7 @@ func makeCommand(s *specgen.SpecGenerator, imageData *libimage.ImageData, rtc *c
initPath = rtc.Engine.InitPath
}
if initPath == "" {
- return nil, errors.Errorf("no path to init binary found but container requested an init")
+ return nil, fmt.Errorf("no path to init binary found but container requested an init")
}
finalCommand = append([]string{define.ContainerInitPath, "--"}, finalCommand...)
}
@@ -298,8 +298,7 @@ func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runt
g.AddAnnotation(key, val)
}
- switch {
- case compatibleOptions.InfraResources == nil && s.ResourceLimits != nil:
+ if s.ResourceLimits != nil {
out, err := json.Marshal(s.ResourceLimits)
if err != nil {
return nil, err
@@ -308,43 +307,17 @@ func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runt
if err != nil {
return nil, err
}
- case s.ResourceLimits != nil: // if we have predefined resource limits we need to make sure we keep the infra and container limits
- originalResources, err := json.Marshal(s.ResourceLimits)
- if err != nil {
- return nil, err
- }
- infraResources, err := json.Marshal(compatibleOptions.InfraResources)
- if err != nil {
- return nil, err
- }
- err = json.Unmarshal(infraResources, s.ResourceLimits) // put infra's resource limits in the container
- if err != nil {
- return nil, err
- }
- err = json.Unmarshal(originalResources, s.ResourceLimits) // make sure we did not override anything
- if err != nil {
- return nil, err
- }
g.Config.Linux.Resources = s.ResourceLimits
- default:
- g.Config.Linux.Resources = compatibleOptions.InfraResources
}
// Devices
-
// set the default rule at the beginning of device configuration
if !inUserNS && !s.Privileged {
g.AddLinuxResourcesDevice(false, "", nil, nil, "rwm")
}
var userDevices []spec.LinuxDevice
- if s.Privileged {
- // If privileged, we need to add all the host devices to the
- // spec. We do not add the user provided ones because we are
- // already adding them all.
- if err := addPrivilegedDevices(&g); err != nil {
- return nil, err
- }
- } else {
+
+ if !s.Privileged {
// add default devices from containers.conf
for _, device := range rtc.Containers.Devices {
if err = DevicesFromPath(&g, device); err != nil {
@@ -375,9 +348,9 @@ func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runt
for k, v := range s.WeightDevice {
statT := unix.Stat_t{}
if err := unix.Stat(k, &statT); err != nil {
- return nil, errors.Wrapf(err, "failed to inspect '%s' in --blkio-weight-device", k)
+ return nil, fmt.Errorf("failed to inspect '%s' in --blkio-weight-device: %w", k, err)
}
- g.AddLinuxResourcesBlockIOWeightDevice((int64(unix.Major(uint64(statT.Rdev)))), (int64(unix.Minor(uint64(statT.Rdev)))), *v.Weight) // nolint: unconvert
+ g.AddLinuxResourcesBlockIOWeightDevice((int64(unix.Major(uint64(statT.Rdev)))), (int64(unix.Minor(uint64(statT.Rdev)))), *v.Weight) //nolint: unconvert
}
BlockAccessToKernelFilesystems(s.Privileged, s.PidNS.IsHost(), s.Mask, s.Unmask, &g)
diff --git a/pkg/specgen/generate/pod_create.go b/pkg/specgen/generate/pod_create.go
index 5b7bb2b57..212d613fe 100644
--- a/pkg/specgen/generate/pod_create.go
+++ b/pkg/specgen/generate/pod_create.go
@@ -2,13 +2,17 @@ package generate
import (
"context"
+ "fmt"
"net"
+ "os"
+ "strconv"
+ "strings"
"github.com/containers/podman/v4/libpod"
"github.com/containers/podman/v4/libpod/define"
"github.com/containers/podman/v4/pkg/domain/entities"
"github.com/containers/podman/v4/pkg/specgen"
- "github.com/pkg/errors"
+ "github.com/containers/podman/v4/pkg/specgenutil"
"github.com/sirupsen/logrus"
)
@@ -55,6 +59,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()
@@ -141,30 +146,33 @@ func MapSpec(p *specgen.PodSpecGenerator) (*specgen.SpecGenerator, error) {
case specgen.Bridge:
p.InfraContainerSpec.NetNS.NSMode = specgen.Bridge
logrus.Debugf("Pod using bridge network mode")
+ case specgen.Private:
+ p.InfraContainerSpec.NetNS.NSMode = specgen.Private
+ logrus.Debugf("Pod will use default network mode")
case specgen.Host:
logrus.Debugf("Pod will use host networking")
if len(p.InfraContainerSpec.PortMappings) > 0 ||
len(p.InfraContainerSpec.Networks) > 0 ||
p.InfraContainerSpec.NetNS.NSMode == specgen.NoNetwork {
- return nil, errors.Wrapf(define.ErrInvalidArg, "cannot set host network if network-related configuration is specified")
+ return nil, fmt.Errorf("cannot set host network if network-related configuration is specified: %w", define.ErrInvalidArg)
}
p.InfraContainerSpec.NetNS.NSMode = specgen.Host
case specgen.Slirp:
logrus.Debugf("Pod will use slirp4netns")
- if p.InfraContainerSpec.NetNS.NSMode != "host" {
+ if p.InfraContainerSpec.NetNS.NSMode != specgen.Host {
p.InfraContainerSpec.NetworkOptions = p.NetworkOptions
- p.InfraContainerSpec.NetNS.NSMode = specgen.NamespaceMode("slirp4netns")
+ p.InfraContainerSpec.NetNS.NSMode = specgen.Slirp
}
case specgen.NoNetwork:
logrus.Debugf("Pod will not use networking")
if len(p.InfraContainerSpec.PortMappings) > 0 ||
len(p.InfraContainerSpec.Networks) > 0 ||
- p.InfraContainerSpec.NetNS.NSMode == "host" {
- return nil, errors.Wrapf(define.ErrInvalidArg, "cannot disable pod network if network-related configuration is specified")
+ p.InfraContainerSpec.NetNS.NSMode == specgen.Host {
+ return nil, fmt.Errorf("cannot disable pod network if network-related configuration is specified: %w", define.ErrInvalidArg)
}
p.InfraContainerSpec.NetNS.NSMode = specgen.NoNetwork
default:
- return nil, errors.Errorf("pods presently do not support network mode %s", p.NetNS.NSMode)
+ return nil, fmt.Errorf("pods presently do not support network mode %s", p.NetNS.NSMode)
}
if len(p.InfraCommand) > 0 {
@@ -207,3 +215,88 @@ func MapSpec(p *specgen.PodSpecGenerator) (*specgen.SpecGenerator, error) {
p.InfraContainerSpec.Image = p.InfraImage
return p.InfraContainerSpec, nil
}
+
+func PodConfigToSpec(rt *libpod.Runtime, spec *specgen.PodSpecGenerator, infraOptions *entities.ContainerCreateOptions, id string) (p *libpod.Pod, err error) {
+ pod, err := rt.LookupPod(id)
+ if err != nil {
+ return nil, err
+ }
+
+ infraSpec := &specgen.SpecGenerator{}
+ if pod.HasInfraContainer() {
+ infraID, err := pod.InfraContainerID()
+ if err != nil {
+ return nil, err
+ }
+ _, _, err = ConfigToSpec(rt, infraSpec, infraID)
+ if err != nil {
+ return nil, err
+ }
+
+ infraSpec.Hostname = ""
+ infraSpec.CgroupParent = ""
+ infraSpec.Pod = "" // remove old pod...
+ infraOptions.IsClone = true
+ infraOptions.IsInfra = true
+
+ n := infraSpec.Name
+ _, err = rt.LookupContainer(n + "-clone")
+ if err == nil { // if we found a ctr with this name, set it so the below switch can tell
+ n += "-clone"
+ }
+
+ switch {
+ case strings.Contains(n, "-clone"):
+ ind := strings.Index(n, "-clone") + 6
+ num, err := strconv.Atoi(n[ind:])
+ if num == 0 && err != nil { // clone1 is hard to get with this logic, just check for it here.
+ _, err = rt.LookupContainer(n + "1")
+ if err != nil {
+ infraSpec.Name = n + "1"
+ break
+ }
+ } else {
+ n = n[0:ind]
+ }
+ err = nil
+ count := num
+ for err == nil {
+ count++
+ tempN := n + strconv.Itoa(count)
+ _, err = rt.LookupContainer(tempN)
+ }
+ n += strconv.Itoa(count)
+ infraSpec.Name = n
+ default:
+ infraSpec.Name = n + "-clone"
+ }
+
+ err = specgenutil.FillOutSpecGen(infraSpec, infraOptions, []string{})
+ if err != nil {
+ return nil, err
+ }
+
+ out, err := CompleteSpec(context.Background(), rt, infraSpec)
+ if err != nil {
+ return nil, err
+ }
+
+ // Print warnings
+ if len(out) > 0 {
+ for _, w := range out {
+ fmt.Println("Could not properly complete the spec as expected:")
+ fmt.Fprintf(os.Stderr, "%s\n", w)
+ }
+ }
+
+ spec.InfraContainerSpec = infraSpec
+ }
+
+ // need to reset hostname, name etc of both pod and infra
+ spec.Hostname = ""
+
+ if len(spec.InfraContainerSpec.Image) > 0 {
+ spec.InfraImage = spec.InfraContainerSpec.Image
+ }
+ return pod, nil
+}
diff --git a/pkg/specgen/generate/ports.go b/pkg/specgen/generate/ports.go
index bec548d3b..572f256c1 100644
--- a/pkg/specgen/generate/ports.go
+++ b/pkg/specgen/generate/ports.go
@@ -10,10 +10,9 @@ import (
"github.com/containers/common/libnetwork/types"
"github.com/containers/podman/v4/utils"
+ "github.com/containers/common/pkg/util"
"github.com/containers/podman/v4/pkg/specgen"
"github.com/containers/podman/v4/pkg/specgenutil"
- "github.com/containers/podman/v4/pkg/util"
- "github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -46,7 +45,7 @@ func joinTwoPortsToRangePortIfPossible(ports *[]types.PortMapping, allHostPorts,
// if both host port ranges overlap and the container port range did not match
// we have to error because we cannot assign the same host port to more than one container port
if previousPort.HostPort+previousPort.Range-1 > port.HostPort {
- return nil, errors.Errorf("conflicting port mappings for host port %d (protocol %s)", port.HostPort, port.Protocol)
+ return nil, fmt.Errorf("conflicting port mappings for host port %d (protocol %s)", port.HostPort, port.Protocol)
}
}
// we could not join the ports so we append the old one to the list
@@ -127,7 +126,7 @@ outer:
rangePort = fmt.Sprintf("with range %d ", port.Range)
}
- return port, errors.Errorf("failed to find an open port to expose container port %d %son the host", port.ContainerPort, rangePort)
+ return port, fmt.Errorf("failed to find an open port to expose container port %d %son the host", port.ContainerPort, rangePort)
}
// Parse port maps to port mappings.
@@ -163,7 +162,7 @@ func ParsePortMapping(portMappings []types.PortMapping, exposePorts map[uint16][
}
if port.HostIP != "" {
if ip := net.ParseIP(port.HostIP); ip == nil {
- return nil, errors.Errorf("invalid IP address %q in port mapping", port.HostIP)
+ return nil, fmt.Errorf("invalid IP address %q in port mapping", port.HostIP)
}
}
@@ -174,14 +173,14 @@ func ParsePortMapping(portMappings []types.PortMapping, exposePorts map[uint16][
}
containerPort := port.ContainerPort
if containerPort == 0 {
- return nil, errors.Errorf("container port number must be non-0")
+ return nil, fmt.Errorf("container port number must be non-0")
}
hostPort := port.HostPort
if uint32(portRange-1)+uint32(containerPort) > 65535 {
- return nil, errors.Errorf("container port range exceeds maximum allowable port number")
+ return nil, fmt.Errorf("container port range exceeds maximum allowable port number")
}
if uint32(portRange-1)+uint32(hostPort) > 65535 {
- return nil, errors.Errorf("host port range exceeds maximum allowable port number")
+ return nil, fmt.Errorf("host port range exceeds maximum allowable port number")
}
hostProtoMap, ok := portMap[port.HostIP]
@@ -351,11 +350,11 @@ func createPortMappings(s *specgen.SpecGenerator, imageData *libimage.ImageData)
for _, expose := range []map[uint16]string{expose, s.Expose} {
for port, proto := range expose {
if port == 0 {
- return nil, nil, errors.Errorf("cannot expose 0 as it is not a valid port number")
+ return nil, nil, fmt.Errorf("cannot expose 0 as it is not a valid port number")
}
protocols, err := checkProtocol(proto, false)
if err != nil {
- return nil, nil, errors.Wrapf(err, "error validating protocols for exposed port %d", port)
+ return nil, nil, fmt.Errorf("error validating protocols for exposed port %d: %w", port, err)
}
toExpose[port] = appendProtocolsNoDuplicates(toExpose[port], protocols)
}
@@ -387,11 +386,11 @@ func checkProtocol(protocol string, allowSCTP bool) ([]string, error) {
protocols[protoUDP] = struct{}{}
case protoSCTP:
if !allowSCTP {
- return nil, errors.Errorf("protocol SCTP is not allowed for exposed ports")
+ return nil, fmt.Errorf("protocol SCTP is not allowed for exposed ports")
}
protocols[protoSCTP] = struct{}{}
default:
- return nil, errors.Errorf("unrecognized protocol %q in port mapping", p)
+ return nil, fmt.Errorf("unrecognized protocol %q in port mapping", p)
}
}
@@ -402,7 +401,7 @@ func checkProtocol(protocol string, allowSCTP bool) ([]string, error) {
// This shouldn't be possible, but check anyways
if len(finalProto) == 0 {
- return nil, errors.Errorf("no valid protocols specified for port mapping")
+ return nil, fmt.Errorf("no valid protocols specified for port mapping")
}
return finalProto, nil
@@ -415,7 +414,7 @@ func GenExposedPorts(exposedPorts map[string]struct{}) (map[uint16]string, error
}
toReturn, err := specgenutil.CreateExpose(expose)
if err != nil {
- return nil, errors.Wrapf(err, "unable to convert image EXPOSE")
+ return nil, fmt.Errorf("unable to convert image EXPOSE: %w", err)
}
return toReturn, nil
}
diff --git a/pkg/specgen/generate/security.go b/pkg/specgen/generate/security.go
index ec52164ab..aacefcbac 100644
--- a/pkg/specgen/generate/security.go
+++ b/pkg/specgen/generate/security.go
@@ -1,19 +1,20 @@
package generate
import (
+ "fmt"
"strings"
"github.com/containers/common/libimage"
"github.com/containers/common/pkg/apparmor"
"github.com/containers/common/pkg/capabilities"
"github.com/containers/common/pkg/config"
+ cutil "github.com/containers/common/pkg/util"
"github.com/containers/podman/v4/libpod"
"github.com/containers/podman/v4/libpod/define"
"github.com/containers/podman/v4/pkg/specgen"
"github.com/containers/podman/v4/pkg/util"
"github.com/opencontainers/runtime-tools/generate"
"github.com/opencontainers/selinux/go-selinux/label"
- "github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -31,11 +32,11 @@ func setLabelOpts(s *specgen.SpecGenerator, runtime *libpod.Runtime, pidConfig s
} else if pidConfig.IsContainer() {
ctr, err := runtime.LookupContainer(pidConfig.Value)
if err != nil {
- return errors.Wrapf(err, "container %q not found", pidConfig.Value)
+ return fmt.Errorf("container %q not found: %w", pidConfig.Value, err)
}
secopts, err := label.DupSecOpt(ctr.ProcessLabel())
if err != nil {
- return errors.Wrapf(err, "failed to duplicate label %q ", ctr.ProcessLabel())
+ return fmt.Errorf("failed to duplicate label %q : %w", ctr.ProcessLabel(), err)
}
labelOpts = append(labelOpts, secopts...)
}
@@ -45,11 +46,11 @@ func setLabelOpts(s *specgen.SpecGenerator, runtime *libpod.Runtime, pidConfig s
} else if ipcConfig.IsContainer() {
ctr, err := runtime.LookupContainer(ipcConfig.Value)
if err != nil {
- return errors.Wrapf(err, "container %q not found", ipcConfig.Value)
+ return fmt.Errorf("container %q not found: %w", ipcConfig.Value, err)
}
secopts, err := label.DupSecOpt(ctr.ProcessLabel())
if err != nil {
- return errors.Wrapf(err, "failed to duplicate label %q ", ctr.ProcessLabel())
+ return fmt.Errorf("failed to duplicate label %q : %w", ctr.ProcessLabel(), err)
}
labelOpts = append(labelOpts, secopts...)
}
@@ -62,7 +63,7 @@ func setupApparmor(s *specgen.SpecGenerator, rtc *config.Config, g *generate.Gen
hasProfile := len(s.ApparmorProfile) > 0
if !apparmor.IsEnabled() {
if hasProfile && s.ApparmorProfile != "unconfined" {
- return errors.Errorf("Apparmor profile %q specified, but Apparmor is not enabled on this system", s.ApparmorProfile)
+ return fmt.Errorf("apparmor profile %q specified, but Apparmor is not enabled on this system", s.ApparmorProfile)
}
return nil
}
@@ -120,7 +121,7 @@ func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator,
// capabilities, required to run the container.
var capsRequiredRequested []string
for key, val := range s.Labels {
- if util.StringInSlice(key, capabilities.ContainerImageLabels) {
+ if cutil.StringInSlice(key, capabilities.ContainerImageLabels) {
capsRequiredRequested = strings.Split(val, ",")
}
}
@@ -128,11 +129,11 @@ func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator,
// Pass capRequiredRequested in CapAdd field to normalize capabilities names
capsRequired, err := capabilities.MergeCapabilities(nil, capsRequiredRequested, nil)
if err != nil {
- return errors.Wrapf(err, "capabilities requested by user or image are not valid: %q", strings.Join(capsRequired, ","))
+ return fmt.Errorf("capabilities requested by user or image are not valid: %q: %w", strings.Join(capsRequired, ","), err)
}
// Verify all capRequired are in the capList
for _, cap := range capsRequired {
- if !util.StringInSlice(cap, caplist) {
+ if !cutil.StringInSlice(cap, caplist) {
privCapsRequired = append(privCapsRequired, cap)
}
}
@@ -160,7 +161,7 @@ func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator,
} else {
mergedCaps, err := capabilities.MergeCapabilities(nil, s.CapAdd, nil)
if err != nil {
- return errors.Wrapf(err, "capabilities requested by user are not valid: %q", strings.Join(s.CapAdd, ","))
+ return fmt.Errorf("capabilities requested by user are not valid: %q: %w", strings.Join(s.CapAdd, ","), err)
}
boundingSet, err := capabilities.BoundingSet()
if err != nil {
@@ -244,17 +245,17 @@ func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator,
for sysctlKey, sysctlVal := range s.Sysctl {
if s.IpcNS.IsHost() && strings.HasPrefix(sysctlKey, "fs.mqueue.") {
- return errors.Wrapf(define.ErrInvalidArg, "sysctl %s=%s can't be set since IPC Namespace set to host", sysctlKey, sysctlVal)
+ return fmt.Errorf("sysctl %s=%s can't be set since IPC Namespace set to host: %w", sysctlKey, sysctlVal, define.ErrInvalidArg)
}
// Ignore net sysctls if --net=host
if s.NetNS.IsHost() && strings.HasPrefix(sysctlKey, "net.") {
- return errors.Wrapf(define.ErrInvalidArg, "sysctl %s=%s can't be set since Network Namespace set to host", sysctlKey, sysctlVal)
+ return fmt.Errorf("sysctl %s=%s can't be set since Network Namespace set to host: %w", sysctlKey, sysctlVal, define.ErrInvalidArg)
}
// Ignore uts sysctls if --uts=host
if s.UtsNS.IsHost() && (strings.HasPrefix(sysctlKey, "kernel.domainname") || strings.HasPrefix(sysctlKey, "kernel.hostname")) {
- return errors.Wrapf(define.ErrInvalidArg, "sysctl %s=%s can't be set since UTS Namespace set to host", sysctlKey, sysctlVal)
+ return fmt.Errorf("sysctl %s=%s can't be set since UTS Namespace set to host: %w", sysctlKey, sysctlVal, define.ErrInvalidArg)
}
g.AddLinuxSysctl(sysctlKey, sysctlVal)
diff --git a/pkg/specgen/generate/storage.go b/pkg/specgen/generate/storage.go
index 0a4d03780..867bb4b79 100644
--- a/pkg/specgen/generate/storage.go
+++ b/pkg/specgen/generate/storage.go
@@ -2,6 +2,7 @@ package generate
import (
"context"
+ "errors"
"fmt"
"os"
"path"
@@ -16,11 +17,10 @@ import (
"github.com/containers/podman/v4/pkg/specgen"
"github.com/containers/podman/v4/pkg/util"
spec "github.com/opencontainers/runtime-spec/specs-go"
- "github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
-var errDuplicateDest = errors.Errorf("duplicate mount destination")
+var errDuplicateDest = errors.New("duplicate mount destination")
// Produce final mounts and named volumes for a container
func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runtime, rtc *config.Config, img *libimage.Image) ([]spec.Mount, []*specgen.NamedVolume, []*specgen.OverlayVolume, error) {
@@ -63,7 +63,7 @@ func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Ru
}
cleanDestination := filepath.Clean(m.Destination)
if _, ok := unifiedMounts[cleanDestination]; ok {
- return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict in specified mounts - multiple mounts at %q", cleanDestination)
+ return nil, nil, nil, fmt.Errorf("conflict in specified mounts - multiple mounts at %q: %w", cleanDestination, errDuplicateDest)
}
unifiedMounts[cleanDestination] = m
}
@@ -84,7 +84,7 @@ func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Ru
}
cleanDestination := filepath.Clean(v.Dest)
if _, ok := unifiedVolumes[cleanDestination]; ok {
- return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict in specified volumes - multiple volumes at %q", cleanDestination)
+ return nil, nil, nil, fmt.Errorf("conflict in specified volumes - multiple volumes at %q: %w", cleanDestination, errDuplicateDest)
}
unifiedVolumes[cleanDestination] = v
}
@@ -105,7 +105,7 @@ func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Ru
}
cleanDestination := filepath.Clean(v.Destination)
if _, ok := unifiedOverlays[cleanDestination]; ok {
- return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict in specified volumes - multiple volumes at %q", cleanDestination)
+ return nil, nil, nil, fmt.Errorf("conflict in specified volumes - multiple volumes at %q: %w", cleanDestination, errDuplicateDest)
}
unifiedOverlays[cleanDestination] = v
}
@@ -131,7 +131,7 @@ func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Ru
return nil, nil, nil, err
}
if _, ok := unifiedMounts[initMount.Destination]; ok {
- return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict with mount added by --init to %q", initMount.Destination)
+ return nil, nil, nil, fmt.Errorf("conflict with mount added by --init to %q: %w", initMount.Destination, errDuplicateDest)
}
unifiedMounts[initMount.Destination] = initMount
}
@@ -161,12 +161,12 @@ func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Ru
// Check for conflicts between named volumes and mounts
for dest := range baseMounts {
if _, ok := baseVolumes[dest]; ok {
- return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict at mount destination %v", dest)
+ return nil, nil, nil, fmt.Errorf("conflict at mount destination %v: %w", dest, errDuplicateDest)
}
}
for dest := range baseVolumes {
if _, ok := baseMounts[dest]; ok {
- return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict at mount destination %v", dest)
+ return nil, nil, nil, fmt.Errorf("conflict at mount destination %v: %w", dest, errDuplicateDest)
}
}
// Final step: maps to arrays
@@ -175,7 +175,7 @@ func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Ru
if mount.Type == define.TypeBind {
absSrc, err := filepath.Abs(mount.Source)
if err != nil {
- return nil, nil, nil, errors.Wrapf(err, "error getting absolute path of %s", mount.Source)
+ return nil, nil, nil, fmt.Errorf("error getting absolute path of %s: %w", mount.Source, err)
}
mount.Source = absSrc
}
@@ -208,7 +208,7 @@ func getImageVolumes(ctx context.Context, img *libimage.Image, s *specgen.SpecGe
inspect, err := img.Inspect(ctx, nil)
if err != nil {
- return nil, nil, errors.Wrapf(err, "error inspecting image to get image volumes")
+ return nil, nil, fmt.Errorf("error inspecting image to get image volumes: %w", err)
}
for volume := range inspect.Config.Volumes {
logrus.Debugf("Image has volume at %q", volume)
@@ -252,16 +252,16 @@ func getVolumesFrom(volumesFrom []string, runtime *libpod.Runtime) (map[string]s
switch opt {
case "z":
if setZ {
- return nil, nil, errors.Errorf("cannot set :z more than once in mount options")
+ return nil, nil, errors.New("cannot set :z more than once in mount options")
}
setZ = true
case "ro", "rw":
if setRORW {
- return nil, nil, errors.Errorf("cannot set ro or rw options more than once")
+ return nil, nil, errors.New("cannot set ro or rw options more than once")
}
setRORW = true
default:
- return nil, nil, errors.Errorf("invalid option %q specified - volumes from another container can only use z,ro,rw options", opt)
+ return nil, nil, fmt.Errorf("invalid option %q specified - volumes from another container can only use z,ro,rw options", opt)
}
}
options = splitOpts
@@ -269,7 +269,7 @@ func getVolumesFrom(volumesFrom []string, runtime *libpod.Runtime) (map[string]s
ctr, err := runtime.LookupContainer(splitVol[0])
if err != nil {
- return nil, nil, errors.Wrapf(err, "error looking up container %q for volumes-from", splitVol[0])
+ return nil, nil, fmt.Errorf("error looking up container %q for volumes-from: %w", splitVol[0], err)
}
logrus.Debugf("Adding volumes from container %s", ctr.ID())
@@ -290,7 +290,7 @@ func getVolumesFrom(volumesFrom []string, runtime *libpod.Runtime) (map[string]s
// and append them in if we can find them.
spec := ctr.Spec()
if spec == nil {
- return nil, nil, errors.Errorf("retrieving container %s spec for volumes-from", ctr.ID())
+ return nil, nil, fmt.Errorf("retrieving container %s spec for volumes-from", ctr.ID())
}
for _, mnt := range spec.Mounts {
if mnt.Type != define.TypeBind {
@@ -364,16 +364,16 @@ func addContainerInitBinary(s *specgen.SpecGenerator, path string) (spec.Mount,
}
if path == "" {
- return mount, fmt.Errorf("please specify a path to the container-init binary")
+ return mount, errors.New("please specify a path to the container-init binary")
}
if !s.PidNS.IsPrivate() {
- return mount, fmt.Errorf("cannot add init binary as PID 1 (PID namespace isn't private)")
+ return mount, errors.New("cannot add init binary as PID 1 (PID namespace isn't private)")
}
if s.Systemd == "always" {
- return mount, fmt.Errorf("cannot use container-init binary with systemd=always")
+ return mount, errors.New("cannot use container-init binary with systemd=always")
}
if _, err := os.Stat(path); os.IsNotExist(err) {
- return mount, errors.Wrap(err, "container-init binary not found on the host")
+ return mount, fmt.Errorf("container-init binary not found on the host: %w", err)
}
return mount, nil
}
diff --git a/pkg/specgen/generate/validate.go b/pkg/specgen/generate/validate.go
index 44c7818e7..9c933d747 100644
--- a/pkg/specgen/generate/validate.go
+++ b/pkg/specgen/generate/validate.go
@@ -1,6 +1,9 @@
package generate
import (
+ "errors"
+ "fmt"
+ "io/ioutil"
"os"
"path/filepath"
@@ -8,7 +11,6 @@ import (
"github.com/containers/common/pkg/sysinfo"
"github.com/containers/podman/v4/pkg/specgen"
"github.com/containers/podman/v4/utils"
- "github.com/pkg/errors"
)
// Verify resource limits are sanely set when running on cgroup v1.
@@ -22,7 +24,7 @@ func verifyContainerResourcesCgroupV1(s *specgen.SpecGenerator) ([]string, error
}
if s.ResourceLimits.Unified != nil {
- return nil, errors.New("Cannot use --cgroup-conf without cgroup v2")
+ return nil, errors.New("cannot use --cgroup-conf without cgroup v2")
}
// Memory checks
@@ -48,7 +50,7 @@ func verifyContainerResourcesCgroupV1(s *specgen.SpecGenerator) ([]string, error
warnings = append(warnings, "Your kernel does not support memory swappiness capabilities, or the cgroup is not mounted. Memory swappiness discarded.")
memory.Swappiness = nil
} else if *memory.Swappiness > 100 {
- return warnings, errors.Errorf("invalid value: %v, valid memory swappiness range is 0-100", *memory.Swappiness)
+ return warnings, fmt.Errorf("invalid value: %v, valid memory swappiness range is 0-100", *memory.Swappiness)
}
}
if memory.Reservation != nil && !sysInfo.MemoryReservation {
@@ -103,18 +105,18 @@ func verifyContainerResourcesCgroupV1(s *specgen.SpecGenerator) ([]string, error
cpusAvailable, err := sysInfo.IsCpusetCpusAvailable(cpu.Cpus)
if err != nil {
- return warnings, errors.Errorf("invalid value %s for cpuset cpus", cpu.Cpus)
+ return warnings, fmt.Errorf("invalid value %s for cpuset cpus", cpu.Cpus)
}
if !cpusAvailable {
- return warnings, errors.Errorf("requested CPUs are not available - requested %s, available: %s", cpu.Cpus, sysInfo.Cpus)
+ return warnings, fmt.Errorf("requested CPUs are not available - requested %s, available: %s", cpu.Cpus, sysInfo.Cpus)
}
memsAvailable, err := sysInfo.IsCpusetMemsAvailable(cpu.Mems)
if err != nil {
- return warnings, errors.Errorf("invalid value %s for cpuset mems", cpu.Mems)
+ return warnings, fmt.Errorf("invalid value %s for cpuset mems", cpu.Mems)
}
if !memsAvailable {
- return warnings, errors.Errorf("requested memory nodes are not available - requested %s, available: %s", cpu.Mems, sysInfo.Mems)
+ return warnings, fmt.Errorf("requested memory nodes are not available - requested %s, available: %s", cpu.Mems, sysInfo.Mems)
}
}
@@ -166,6 +168,14 @@ func verifyContainerResourcesCgroupV2(s *specgen.SpecGenerator) ([]string, error
if err != nil {
return warnings, err
}
+
+ if own == "/" {
+ // If running under the root cgroup try to create or reuse a "probe" cgroup to read memory values
+ own = "podman_probe"
+ _ = os.MkdirAll(filepath.Join("/sys/fs/cgroup", own), 0o755)
+ _ = ioutil.WriteFile("/sys/fs/cgroup/cgroup.subtree_control", []byte("+memory"), 0o644)
+ }
+
memoryMax := filepath.Join("/sys/fs/cgroup", own, "memory.max")
memorySwapMax := filepath.Join("/sys/fs/cgroup", own, "memory.swap.max")
_, errMemoryMax := os.Stat(memoryMax)