aboutsummaryrefslogtreecommitdiff
path: root/pkg/specgen/generate
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/specgen/generate')
-rw-r--r--pkg/specgen/generate/container.go164
-rw-r--r--pkg/specgen/generate/container_create.go24
-rw-r--r--pkg/specgen/generate/kube/kube.go31
-rw-r--r--pkg/specgen/generate/kube/play_test.go6
-rw-r--r--pkg/specgen/generate/kube/volume.go28
-rw-r--r--pkg/specgen/generate/namespaces.go176
-rw-r--r--pkg/specgen/generate/namespaces_freebsd.go51
-rw-r--r--pkg/specgen/generate/namespaces_linux.go160
-rw-r--r--pkg/specgen/generate/namespaces_unsupported.go16
-rw-r--r--pkg/specgen/generate/oci.go345
-rw-r--r--pkg/specgen/generate/oci_freebsd.go96
-rw-r--r--pkg/specgen/generate/oci_linux.go331
-rw-r--r--pkg/specgen/generate/oci_unsupported.go24
-rw-r--r--pkg/specgen/generate/pod_create.go26
-rw-r--r--pkg/specgen/generate/ports.go2
-rw-r--r--pkg/specgen/generate/rlimit_int64.go6
-rw-r--r--pkg/specgen/generate/rlimit_uint64.go6
-rw-r--r--pkg/specgen/generate/security_freebsd.go19
-rw-r--r--pkg/specgen/generate/security_linux.go (renamed from pkg/specgen/generate/security.go)0
-rw-r--r--pkg/specgen/generate/security_unsupported.go24
-rw-r--r--pkg/specgen/generate/storage.go6
-rw-r--r--pkg/specgen/generate/validate.go22
22 files changed, 945 insertions, 618 deletions
diff --git a/pkg/specgen/generate/container.go b/pkg/specgen/generate/container.go
index 8cfac924b..c18b5654a 100644
--- a/pkg/specgen/generate/container.go
+++ b/pkg/specgen/generate/container.go
@@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"os"
+ "strconv"
"strings"
"time"
@@ -17,9 +18,8 @@ import (
envLib "github.com/containers/podman/v4/pkg/env"
"github.com/containers/podman/v4/pkg/signal"
"github.com/containers/podman/v4/pkg/specgen"
- spec "github.com/opencontainers/runtime-spec/specs-go"
+ "github.com/openshift/imagebuilder"
"github.com/sirupsen/logrus"
- "golang.org/x/sys/unix"
)
func getImageFromSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerator) (*libimage.Image, string, *libimage.ImageData, error) {
@@ -115,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, fmt.Errorf("error parsing fields in containers.conf: %w", err)
+ return nil, fmt.Errorf("parsing fields in containers.conf: %w", err)
}
var envs map[string]string
@@ -130,6 +130,17 @@ func CompleteSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerat
defaultEnvs = envLib.Join(envLib.DefaultEnvVariables(), envLib.Join(defaultEnvs, envs))
}
+ for _, e := range s.EnvMerge {
+ processedWord, err := imagebuilder.ProcessWord(e, envLib.Slice(defaultEnvs))
+ if err != nil {
+ return nil, fmt.Errorf("unable to process variables for --env-merge %s: %w", e, err)
+ }
+ splitWord := strings.Split(processedWord, "=")
+ if _, ok := defaultEnvs[splitWord[0]]; ok {
+ defaultEnvs[splitWord[0]] = splitWord[1]
+ }
+ }
+
for _, e := range s.UnsetEnv {
delete(defaultEnvs, e)
}
@@ -139,10 +150,8 @@ func CompleteSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerat
}
// First transform the os env into a map. We need it for the labels later in
// any case.
- osEnv, err := envLib.ParseSlice(os.Environ())
- if err != nil {
- return nil, fmt.Errorf("error parsing host environment variables: %w", err)
- }
+ osEnv := envLib.Map(os.Environ())
+
// Caller Specified defaults
if s.EnvHost {
defaultEnvs = envLib.Join(defaultEnvs, osEnv)
@@ -191,16 +200,24 @@ func CompleteSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerat
// - "container" denotes the container should join the VM of the SandboxID
// (the infra container)
if len(s.Pod) > 0 {
- annotations[ann.SandboxID] = s.Pod
+ p, err := r.LookupPod(s.Pod)
+ if err != nil {
+ return nil, err
+ }
+ sandboxID := p.ID()
+ if p.HasInfraContainer() {
+ infra, err := p.InfraContainer()
+ if err != nil {
+ return nil, err
+ }
+ sandboxID = infra.ID()
+ }
+ annotations[ann.SandboxID] = sandboxID
annotations[ann.ContainerType] = ann.ContainerTypeContainer
// Check if this is an init-ctr and if so, check if
// the pod is running. we do not want to add init-ctrs to
// a running pod because it creates confusion for us.
if len(s.InitContainerType) > 0 {
- p, err := r.LookupPod(s.Pod)
- if err != nil {
- return nil, err
- }
containerStatuses, err := p.Status()
if err != nil {
return nil, err
@@ -254,19 +271,7 @@ func CompleteSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerat
}
// If caller did not specify Pids Limits load default
- if s.ResourceLimits == nil || s.ResourceLimits.Pids == nil {
- if s.CgroupsMode != "disabled" {
- limit := rtc.PidsLimit()
- if limit != 0 {
- if s.ResourceLimits == nil {
- s.ResourceLimits = &spec.LinuxResources{}
- }
- s.ResourceLimits.Pids = &spec.LinuxPids{
- Limit: limit,
- }
- }
- }
- }
+ s.InitResourceLimits(rtc)
if s.LogConfiguration == nil {
s.LogConfiguration = &specgen.LogConfig{}
@@ -338,9 +343,21 @@ func ConfigToSpec(rt *libpod.Runtime, specg *specgen.SpecGenerator, contaierID s
conf.Systemd = tmpSystemd
conf.Mounts = tmpMounts
- if conf.Spec != nil && conf.Spec.Linux != nil && conf.Spec.Linux.Resources != nil {
- if specg.ResourceLimits == nil {
- specg.ResourceLimits = conf.Spec.Linux.Resources
+ if conf.Spec != nil {
+ if conf.Spec.Linux != nil && conf.Spec.Linux.Resources != nil {
+ if specg.ResourceLimits == nil {
+ specg.ResourceLimits = conf.Spec.Linux.Resources
+ }
+ }
+ if conf.Spec.Process != nil && conf.Spec.Process.Env != nil {
+ env := make(map[string]string)
+ for _, entry := range conf.Spec.Process.Env {
+ split := strings.Split(entry, "=")
+ if len(split) == 2 {
+ env[split[0]] = split[1]
+ }
+ }
+ specg.Env = env
}
}
@@ -487,71 +504,40 @@ func mapSecurityConfig(c *libpod.ContainerConfig, s *specgen.SpecGenerator) {
s.HostUsers = c.HostUsers
}
-// FinishThrottleDevices takes the temporary representation of the throttle
-// devices in the specgen and looks up the major and major minors. it then
-// sets the throttle devices proper in the specgen
-func FinishThrottleDevices(s *specgen.SpecGenerator) error {
- if s.ResourceLimits == nil {
- s.ResourceLimits = &spec.LinuxResources{}
- }
- if bps := s.ThrottleReadBpsDevice; len(bps) > 0 {
- if s.ResourceLimits.BlockIO == nil {
- s.ResourceLimits.BlockIO = &spec.LinuxBlockIO{}
- }
- for k, v := range bps {
- statT := unix.Stat_t{}
- if err := unix.Stat(k, &statT); err != nil {
- return fmt.Errorf("could not parse throttle device at %s: %w", k, err)
- }
- 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)
+// Check name looks for existing containers/pods with the same name, and modifies the given string until a new name is found
+func CheckName(rt *libpod.Runtime, n string, kind bool) string {
+ 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.
+ if kind {
+ _, err = rt.LookupContainer(n + "1")
+ } else {
+ _, err = rt.LookupPod(n + "1")
}
- s.ResourceLimits.BlockIO.ThrottleReadBpsDevice = append(s.ResourceLimits.BlockIO.ThrottleReadBpsDevice, v)
- }
- }
- if bps := s.ThrottleWriteBpsDevice; len(bps) > 0 {
- if s.ResourceLimits.BlockIO == nil {
- s.ResourceLimits.BlockIO = &spec.LinuxBlockIO{}
- }
- for k, v := range bps {
- statT := unix.Stat_t{}
- if err := unix.Stat(k, &statT); err != nil {
- return fmt.Errorf("could not parse throttle device at %s: %w", k, err)
- }
- 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)
- }
- }
- if iops := s.ThrottleReadIOPSDevice; len(iops) > 0 {
- if s.ResourceLimits.BlockIO == nil {
- s.ResourceLimits.BlockIO = &spec.LinuxBlockIO{}
- }
- for k, v := range iops {
- statT := unix.Stat_t{}
- if err := unix.Stat(k, &statT); err != nil {
- return fmt.Errorf("could not parse throttle device at %s: %w", k, err)
+
+ if err != nil {
+ n += "1"
+ break
}
- 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)
- }
- }
- if iops := s.ThrottleWriteIOPSDevice; len(iops) > 0 {
- if s.ResourceLimits.BlockIO == nil {
- s.ResourceLimits.BlockIO = &spec.LinuxBlockIO{}
+ } else {
+ n = n[0:ind]
}
- for k, v := range iops {
- statT := unix.Stat_t{}
- if err := unix.Stat(k, &statT); err != nil {
- return fmt.Errorf("could not parse throttle device at %s: %w", k, err)
+ err = nil
+ count := num
+ for err == nil {
+ count++
+ tempN := n + strconv.Itoa(count)
+ if kind {
+ _, err = rt.LookupContainer(tempN)
+ } else {
+ _, err = rt.LookupPod(tempN)
}
- 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)
}
+ n += strconv.Itoa(count)
+ default:
+ n += "-clone"
}
- return nil
+ return n
}
diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go
index 8334d386f..6ef5ca79c 100644
--- a/pkg/specgen/generate/container_create.go
+++ b/pkg/specgen/generate/container_create.go
@@ -5,6 +5,7 @@ import (
"encoding/json"
"errors"
"fmt"
+ "os"
"path/filepath"
"strings"
@@ -35,7 +36,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, fmt.Errorf("error retrieving pod %s: %w", s.Pod, err)
+ return nil, nil, nil, fmt.Errorf("retrieving pod %s: %w", s.Pod, err)
}
if pod.HasInfraContainer() {
infra, err = pod.InfraContainer()
@@ -55,7 +56,7 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
}
}
- if err := FinishThrottleDevices(s); err != nil {
+ if err := specgen.FinishThrottleDevices(s); err != nil {
return nil, nil, nil, err
}
@@ -343,7 +344,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, fmt.Errorf("error parsing systemd signal: %w", err)
+ return nil, fmt.Errorf("parsing systemd signal: %w", err)
}
s.StopSignal = &stopSignal
}
@@ -352,7 +353,13 @@ func createContainerOptions(rt *libpod.Runtime, s *specgen.SpecGenerator, pod *l
}
if len(s.SdNotifyMode) > 0 {
options = append(options, libpod.WithSdNotifyMode(s.SdNotifyMode))
+ if s.SdNotifyMode != define.SdNotifyModeIgnore {
+ if notify, ok := os.LookupEnv("NOTIFY_SOCKET"); ok {
+ options = append(options, libpod.WithSdNotifySocket(notify))
+ }
+ }
}
+
if pod != nil {
logrus.Debugf("adding container to pod %s", pod.Name())
options = append(options, rt.WithPod(pod))
@@ -380,9 +387,10 @@ func createContainerOptions(rt *libpod.Runtime, s *specgen.SpecGenerator, pod *l
var vols []*libpod.ContainerNamedVolume
for _, v := range volumes {
vols = append(vols, &libpod.ContainerNamedVolume{
- Name: v.Name,
- Dest: v.Dest,
- Options: v.Options,
+ Name: v.Name,
+ Dest: v.Dest,
+ Options: v.Options,
+ IsAnonymous: v.IsAnonymous,
})
}
options = append(options, libpod.WithNamedVolumes(vols))
@@ -507,6 +515,10 @@ func createContainerOptions(rt *libpod.Runtime, s *specgen.SpecGenerator, pod *l
logrus.Debugf("New container has a health check")
}
+ if s.ContainerHealthCheckConfig.HealthCheckOnFailureAction != define.HealthCheckOnFailureActionNone {
+ options = append(options, libpod.WithHealthCheckOnFailureAction(s.ContainerHealthCheckConfig.HealthCheckOnFailureAction))
+ }
+
if len(s.Secrets) != 0 {
manager, err := rt.SecretsManager()
if err != nil {
diff --git a/pkg/specgen/generate/kube/kube.go b/pkg/specgen/generate/kube/kube.go
index e9abf419b..7d85fd2f3 100644
--- a/pkg/specgen/generate/kube/kube.go
+++ b/pkg/specgen/generate/kube/kube.go
@@ -7,6 +7,7 @@ import (
"fmt"
"math"
"net"
+ "os"
"regexp"
"runtime"
"strconv"
@@ -26,6 +27,7 @@ import (
"github.com/containers/podman/v4/pkg/k8s.io/apimachinery/pkg/api/resource"
"github.com/containers/podman/v4/pkg/specgen"
"github.com/containers/podman/v4/pkg/specgen/generate"
+ systemdDefine "github.com/containers/podman/v4/pkg/systemd/define"
"github.com/containers/podman/v4/pkg/util"
"github.com/docker/docker/pkg/system"
"github.com/docker/go-units"
@@ -205,12 +207,9 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
s.SeccompProfilePath = opts.SeccompPaths.FindForContainer(opts.Container.Name)
s.ResourceLimits = &spec.LinuxResources{}
- milliCPU, err := quantityToInt64(opts.Container.Resources.Limits.Cpu())
- if err != nil {
- return nil, fmt.Errorf("failed to set CPU quota: %w", err)
- }
+ milliCPU := opts.Container.Resources.Limits.Cpu().MilliValue()
if milliCPU > 0 {
- period, quota := util.CoresToPeriodAndQuota(float64(milliCPU))
+ period, quota := util.CoresToPeriodAndQuota(float64(milliCPU) / 1000)
s.ResourceLimits.CPU = &spec.LinuxCPU{
Quota: &quota,
Period: &period,
@@ -357,8 +356,11 @@ 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 && !cutil.StringInSlice("z", options) && !cutil.StringInSlice("Z", options) {
- options = append(options, v)
+ if k == define.BindMountPrefix {
+ lastIndex := strings.LastIndex(v, ":")
+ if v[:lastIndex] == volumeSource.Source && !cutil.StringInSlice("z", options) && !cutil.StringInSlice("Z", options) {
+ options = append(options, v[lastIndex+1:])
+ }
}
}
mount := spec.Mount{
@@ -406,8 +408,15 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
Name: volumeSource.Source,
Options: options,
}
-
s.Volumes = append(s.Volumes, &secretVolume)
+ case KubeVolumeTypeEmptyDir:
+ emptyDirVolume := specgen.NamedVolume{
+ Dest: volume.MountPath,
+ Name: volumeSource.Source,
+ Options: options,
+ IsAnonymous: true,
+ }
+ s.Volumes = append(s.Volumes, &emptyDirVolume)
default:
return nil, errors.New("unsupported volume source type")
}
@@ -435,6 +444,12 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
}
}
+ // Make sure the container runs in a systemd unit which is
+ // stored as a label at container creation.
+ if unit := os.Getenv(systemdDefine.EnvVariable); unit != "" {
+ s.Labels[systemdDefine.EnvVariable] = unit
+ }
+
return s, nil
}
diff --git a/pkg/specgen/generate/kube/play_test.go b/pkg/specgen/generate/kube/play_test.go
index 470c0c39c..ec0dc4bcd 100644
--- a/pkg/specgen/generate/kube/play_test.go
+++ b/pkg/specgen/generate/kube/play_test.go
@@ -24,11 +24,15 @@ func createSecrets(t *testing.T, d string) *secrets.SecretsManager {
"path": d,
}
+ storeOpts := secrets.StoreOptions{
+ DriverOpts: driverOpts,
+ }
+
for _, s := range k8sSecrets {
data, err := json.Marshal(s.Data)
assert.NoError(t, err)
- _, err = secretsManager.Store(s.ObjectMeta.Name, data, driver, driverOpts, nil)
+ _, err = secretsManager.Store(s.ObjectMeta.Name, data, driver, storeOpts)
assert.NoError(t, err)
}
diff --git a/pkg/specgen/generate/kube/volume.go b/pkg/specgen/generate/kube/volume.go
index c12adadd8..2d8085020 100644
--- a/pkg/specgen/generate/kube/volume.go
+++ b/pkg/specgen/generate/kube/volume.go
@@ -32,6 +32,7 @@ const (
KubeVolumeTypeBlockDevice
KubeVolumeTypeCharDevice
KubeVolumeTypeSecret
+ KubeVolumeTypeEmptyDir
)
//nolint:revive
@@ -62,13 +63,13 @@ func VolumeFromHostPath(hostPath *v1.HostPathVolumeSource) (*KubeVolume, error)
}
// Label a newly created volume
if err := libpod.LabelVolumePath(hostPath.Path); err != nil {
- return nil, fmt.Errorf("error giving %s a label: %w", hostPath.Path, err)
+ return nil, fmt.Errorf("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, fmt.Errorf("error creating HostPath: %w", err)
+ return nil, fmt.Errorf("creating HostPath: %w", err)
}
if err := f.Close(); err != nil {
logrus.Warnf("Error in closing newly created HostPath file: %v", err)
@@ -76,12 +77,12 @@ func VolumeFromHostPath(hostPath *v1.HostPathVolumeSource) (*KubeVolume, error)
}
// unconditionally label a newly created volume
if err := libpod.LabelVolumePath(hostPath.Path); err != nil {
- return nil, fmt.Errorf("error giving %s a label: %w", hostPath.Path, err)
+ return nil, fmt.Errorf("giving %s a label: %w", hostPath.Path, err)
}
case v1.HostPathSocket:
st, err := os.Stat(hostPath.Path)
if err != nil {
- return nil, fmt.Errorf("error checking HostPathSocket: %w", err)
+ return nil, fmt.Errorf("checking HostPathSocket: %w", err)
}
if st.Mode()&os.ModeSocket != os.ModeSocket {
return nil, fmt.Errorf("checking HostPathSocket: path %s is not a socket", hostPath.Path)
@@ -89,7 +90,7 @@ func VolumeFromHostPath(hostPath *v1.HostPathVolumeSource) (*KubeVolume, error)
case v1.HostPathBlockDev:
dev, err := os.Stat(hostPath.Path)
if err != nil {
- return nil, fmt.Errorf("error checking HostPathBlockDevice: %w", err)
+ return nil, fmt.Errorf("checking HostPathBlockDevice: %w", err)
}
if dev.Mode()&os.ModeCharDevice == os.ModeCharDevice {
return nil, fmt.Errorf("checking HostPathDevice: path %s is not a block device", hostPath.Path)
@@ -101,7 +102,7 @@ func VolumeFromHostPath(hostPath *v1.HostPathVolumeSource) (*KubeVolume, error)
case v1.HostPathCharDev:
dev, err := os.Stat(hostPath.Path)
if err != nil {
- return nil, fmt.Errorf("error checking HostPathCharDevice: %w", err)
+ return nil, fmt.Errorf("checking HostPathCharDevice: %w", err)
}
if dev.Mode()&os.ModeCharDevice != os.ModeCharDevice {
return nil, fmt.Errorf("checking HostPathCharDevice: path %s is not a character device", hostPath.Path)
@@ -121,7 +122,7 @@ func VolumeFromHostPath(hostPath *v1.HostPathVolumeSource) (*KubeVolume, error)
}
if err := parse.ValidateVolumeHostDir(hostPath.Path); err != nil {
- return nil, fmt.Errorf("error in parsing HostPath in YAML: %w", err)
+ return nil, fmt.Errorf("in parsing HostPath in YAML: %w", err)
}
return &KubeVolume{
@@ -219,8 +220,13 @@ func VolumeFromConfigMap(configMapVolumeSource *v1.ConfigMapVolumeSource, config
return kv, nil
}
+// Create a kubeVolume for an emptyDir volume
+func VolumeFromEmptyDir(emptyDirVolumeSource *v1.EmptyDirVolumeSource, name string) (*KubeVolume, error) {
+ return &KubeVolume{Type: KubeVolumeTypeEmptyDir, Source: name}, nil
+}
+
// Create a KubeVolume from one of the supported VolumeSource
-func VolumeFromSource(volumeSource v1.VolumeSource, configMaps []v1.ConfigMap, secretsManager *secrets.SecretsManager) (*KubeVolume, error) {
+func VolumeFromSource(volumeSource v1.VolumeSource, configMaps []v1.ConfigMap, secretsManager *secrets.SecretsManager, volName string) (*KubeVolume, error) {
switch {
case volumeSource.HostPath != nil:
return VolumeFromHostPath(volumeSource.HostPath)
@@ -230,8 +236,10 @@ func VolumeFromSource(volumeSource v1.VolumeSource, configMaps []v1.ConfigMap, s
return VolumeFromConfigMap(volumeSource.ConfigMap, configMaps)
case volumeSource.Secret != nil:
return VolumeFromSecret(volumeSource.Secret, secretsManager)
+ case volumeSource.EmptyDir != nil:
+ return VolumeFromEmptyDir(volumeSource.EmptyDir, volName)
default:
- return nil, errors.New("HostPath, ConfigMap, and PersistentVolumeClaim are currently the only supported VolumeSource")
+ return nil, errors.New("HostPath, ConfigMap, EmptyDir, and PersistentVolumeClaim are currently the only supported VolumeSource")
}
}
@@ -240,7 +248,7 @@ func InitializeVolumes(specVolumes []v1.Volume, configMaps []v1.ConfigMap, secre
volumes := make(map[string]*KubeVolume)
for _, specVolume := range specVolumes {
- volume, err := VolumeFromSource(specVolume.VolumeSource, configMaps, secretsManager)
+ volume, err := VolumeFromSource(specVolume.VolumeSource, configMaps, secretsManager, specVolume.Name)
if err != nil {
return nil, fmt.Errorf("failed to create volume %q: %w", specVolume.Name, err)
}
diff --git a/pkg/specgen/generate/namespaces.go b/pkg/specgen/generate/namespaces.go
index f0d4e9153..9497894f3 100644
--- a/pkg/specgen/generate/namespaces.go
+++ b/pkg/specgen/generate/namespaces.go
@@ -3,7 +3,6 @@ package generate
import (
"errors"
"fmt"
- "os"
"strings"
"github.com/containers/common/libimage"
@@ -11,11 +10,11 @@ import (
"github.com/containers/common/pkg/config"
"github.com/containers/podman/v4/libpod"
"github.com/containers/podman/v4/libpod/define"
+ "github.com/containers/podman/v4/pkg/namespaces"
"github.com/containers/podman/v4/pkg/rootless"
"github.com/containers/podman/v4/pkg/specgen"
"github.com/containers/podman/v4/pkg/util"
spec "github.com/opencontainers/runtime-spec/specs-go"
- "github.com/opencontainers/runtime-tools/generate"
"github.com/sirupsen/logrus"
)
@@ -113,12 +112,12 @@ 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, fmt.Errorf("error looking up pod %s infra container: %w", pod.ID(), err)
+ return nil, fmt.Errorf("looking up pod %s infra container: %w", pod.ID(), err)
}
if infraID != "" {
ctr, err := rt.GetContainer(infraID)
if err != nil {
- return nil, fmt.Errorf("error retrieving pod %s infra container %s: %w", pod.ID(), infraID, err)
+ return nil, fmt.Errorf("retrieving pod %s infra container %s: %w", pod.ID(), infraID, err)
}
infraCtr = ctr
}
@@ -136,7 +135,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, fmt.Errorf("error looking up container to share pid namespace with: %w", err)
+ return nil, fmt.Errorf("looking up container to share pid namespace with: %w", err)
}
toReturn = append(toReturn, libpod.WithPIDNSFrom(pidCtr))
}
@@ -155,7 +154,7 @@ 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, fmt.Errorf("error looking up container to share ipc namespace with: %w", err)
+ return nil, fmt.Errorf("looking up container to share ipc namespace with: %w", err)
}
if ipcCtr.ConfigNoCopy().NoShmShare {
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())
@@ -187,7 +186,7 @@ func namespaceOptions(s *specgen.SpecGenerator, rt *libpod.Runtime, pod *libpod.
case specgen.FromContainer:
utsCtr, err := rt.LookupContainer(s.UtsNS.Value)
if err != nil {
- return nil, fmt.Errorf("error looking up container to share uts namespace with: %w", err)
+ return nil, fmt.Errorf("looking up container to share uts namespace with: %w", err)
}
toReturn = append(toReturn, libpod.WithUTSNSFrom(utsCtr))
}
@@ -198,12 +197,18 @@ func namespaceOptions(s *specgen.SpecGenerator, rt *libpod.Runtime, pod *libpod.
if !rootless.IsRootless() {
return nil, errors.New("keep-id is only supported in rootless mode")
}
- toReturn = append(toReturn, libpod.WithAddCurrentUserPasswdEntry())
+ opts, err := namespaces.UsernsMode(s.UserNS.String()).GetKeepIDOptions()
+ if err != nil {
+ return nil, err
+ }
+ if opts.UID == nil && opts.GID == nil {
+ toReturn = append(toReturn, libpod.WithAddCurrentUserPasswdEntry())
+ }
// If user is not overridden, set user in the container
// to user running Podman.
if s.User == "" {
- _, uid, gid, err := util.GetKeepIDMapping()
+ _, uid, gid, err := util.GetKeepIDMapping(opts)
if err != nil {
return nil, err
}
@@ -222,7 +227,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, fmt.Errorf("error looking up container to share user namespace with: %w", err)
+ return nil, fmt.Errorf("looking up container to share user namespace with: %w", err)
}
toReturn = append(toReturn, libpod.WithUserNSFrom(userCtr))
}
@@ -254,7 +259,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, fmt.Errorf("error looking up container to share cgroup namespace with: %w", err)
+ return nil, fmt.Errorf("looking up container to share cgroup namespace with: %w", err)
}
toReturn = append(toReturn, libpod.WithCgroupNSFrom(cgroupCtr))
}
@@ -282,7 +287,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, fmt.Errorf("error looking up container to share net namespace with: %w", err)
+ return nil, fmt.Errorf("looking up container to share net namespace with: %w", err)
}
toReturn = append(toReturn, libpod.WithNetNSFrom(netCtr))
case specgen.Slirp:
@@ -357,153 +362,6 @@ func namespaceOptions(s *specgen.SpecGenerator, rt *libpod.Runtime, pod *libpod.
return toReturn, nil
}
-func specConfigureNamespaces(s *specgen.SpecGenerator, g *generate.Generator, rt *libpod.Runtime, pod *libpod.Pod) error {
- // PID
- switch s.PidNS.NSMode {
- case specgen.Path:
- if _, err := os.Stat(s.PidNS.Value); err != nil {
- 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
- }
- case specgen.Host:
- if err := g.RemoveLinuxNamespace(string(spec.PIDNamespace)); err != nil {
- return err
- }
- case specgen.Private:
- if err := g.AddOrReplaceLinuxNamespace(string(spec.PIDNamespace), ""); err != nil {
- return err
- }
- }
-
- // IPC
- switch s.IpcNS.NSMode {
- case specgen.Path:
- if _, err := os.Stat(s.IpcNS.Value); err != nil {
- 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
- }
- case specgen.Host:
- if err := g.RemoveLinuxNamespace(string(spec.IPCNamespace)); err != nil {
- return err
- }
- case specgen.Private:
- if err := g.AddOrReplaceLinuxNamespace(string(spec.IPCNamespace), ""); err != nil {
- return err
- }
- }
-
- // UTS
- switch s.UtsNS.NSMode {
- case specgen.Path:
- if _, err := os.Stat(s.UtsNS.Value); err != nil {
- 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
- }
- case specgen.Host:
- if err := g.RemoveLinuxNamespace(string(spec.UTSNamespace)); err != nil {
- return err
- }
- case specgen.Private:
- if err := g.AddOrReplaceLinuxNamespace(string(spec.UTSNamespace), ""); err != nil {
- return err
- }
- }
-
- hostname := s.Hostname
- if hostname == "" {
- switch {
- case s.UtsNS.NSMode == specgen.FromPod:
- hostname = pod.Hostname()
- case s.UtsNS.NSMode == specgen.FromContainer:
- utsCtr, err := rt.LookupContainer(s.UtsNS.Value)
- if err != nil {
- 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 fmt.Errorf("unable to retrieve hostname of the host: %w", err)
- }
- hostname = tmpHostname
- default:
- logrus.Debug("No hostname set; container's hostname will default to runtime default")
- }
- }
-
- g.RemoveHostname()
- if s.Hostname != "" || s.UtsNS.NSMode != specgen.Host {
- // Set the hostname in the OCI configuration only if specified by
- // the user or if we are creating a new UTS namespace.
- // TODO: Should we be doing this for pod or container shared
- // namespaces?
- g.SetHostname(hostname)
- }
- if _, ok := s.Env["HOSTNAME"]; !ok && s.Hostname != "" {
- g.AddProcessEnv("HOSTNAME", hostname)
- }
-
- // User
- if _, err := specgen.SetupUserNS(s.IDMappings, s.UserNS, g); err != nil {
- return err
- }
-
- // Cgroup
- switch s.CgroupNS.NSMode {
- case specgen.Path:
- if _, err := os.Stat(s.CgroupNS.Value); err != nil {
- 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
- }
- case specgen.Host:
- if err := g.RemoveLinuxNamespace(string(spec.CgroupNamespace)); err != nil {
- return err
- }
- case specgen.Private:
- if err := g.AddOrReplaceLinuxNamespace(string(spec.CgroupNamespace), ""); err != nil {
- return err
- }
- }
-
- // Net
- switch s.NetNS.NSMode {
- case specgen.Path:
- if _, err := os.Stat(s.NetNS.Value); err != nil {
- 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
- }
- case specgen.Host:
- if err := g.RemoveLinuxNamespace(string(spec.NetworkNamespace)); err != nil {
- return err
- }
- case specgen.Private, specgen.NoNetwork:
- if err := g.AddOrReplaceLinuxNamespace(string(spec.NetworkNamespace), ""); err != nil {
- return err
- }
- }
-
- if g.Config.Annotations == nil {
- g.Config.Annotations = make(map[string]string)
- }
- if s.PublishExposedPorts {
- g.Config.Annotations[define.InspectAnnotationPublishAll] = define.InspectResponseTrue
- } else {
- g.Config.Annotations[define.InspectAnnotationPublishAll] = define.InspectResponseFalse
- }
-
- return nil
-}
-
// GetNamespaceOptions transforms a slice of kernel namespaces
// into a slice of pod create options. Currently, not all
// kernel namespaces are supported, and they will be returned in an error
diff --git a/pkg/specgen/generate/namespaces_freebsd.go b/pkg/specgen/generate/namespaces_freebsd.go
new file mode 100644
index 000000000..f4246de34
--- /dev/null
+++ b/pkg/specgen/generate/namespaces_freebsd.go
@@ -0,0 +1,51 @@
+package generate
+
+import (
+ "fmt"
+ "os"
+
+ "github.com/containers/podman/v4/libpod"
+ "github.com/containers/podman/v4/pkg/specgen"
+ "github.com/opencontainers/runtime-tools/generate"
+ "github.com/sirupsen/logrus"
+)
+
+func specConfigureNamespaces(s *specgen.SpecGenerator, g *generate.Generator, rt *libpod.Runtime, pod *libpod.Pod) error {
+ // UTS
+
+ hostname := s.Hostname
+ if hostname == "" {
+ switch {
+ case s.UtsNS.NSMode == specgen.FromPod:
+ hostname = pod.Hostname()
+ case s.UtsNS.NSMode == specgen.FromContainer:
+ utsCtr, err := rt.LookupContainer(s.UtsNS.Value)
+ if err != nil {
+ return fmt.Errorf("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 fmt.Errorf("unable to retrieve hostname of the host: %w", err)
+ }
+ hostname = tmpHostname
+ default:
+ logrus.Debug("No hostname set; container's hostname will default to runtime default")
+ }
+ }
+
+ g.RemoveHostname()
+ if s.Hostname != "" || s.UtsNS.NSMode != specgen.Host {
+ // Set the hostname in the OCI configuration only if specified by
+ // the user or if we are creating a new UTS namespace.
+ // TODO: Should we be doing this for pod or container shared
+ // namespaces?
+ g.SetHostname(hostname)
+ }
+ if _, ok := s.Env["HOSTNAME"]; !ok && s.Hostname != "" {
+ g.AddProcessEnv("HOSTNAME", hostname)
+ }
+
+ return nil
+}
diff --git a/pkg/specgen/generate/namespaces_linux.go b/pkg/specgen/generate/namespaces_linux.go
new file mode 100644
index 000000000..9fda000f9
--- /dev/null
+++ b/pkg/specgen/generate/namespaces_linux.go
@@ -0,0 +1,160 @@
+package generate
+
+import (
+ "fmt"
+ "os"
+
+ "github.com/containers/podman/v4/libpod"
+ "github.com/containers/podman/v4/libpod/define"
+ "github.com/containers/podman/v4/pkg/specgen"
+ spec "github.com/opencontainers/runtime-spec/specs-go"
+ "github.com/opencontainers/runtime-tools/generate"
+ "github.com/sirupsen/logrus"
+)
+
+func specConfigureNamespaces(s *specgen.SpecGenerator, g *generate.Generator, rt *libpod.Runtime, pod *libpod.Pod) error {
+ // PID
+ switch s.PidNS.NSMode {
+ case specgen.Path:
+ if _, err := os.Stat(s.PidNS.Value); err != nil {
+ 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
+ }
+ case specgen.Host:
+ if err := g.RemoveLinuxNamespace(string(spec.PIDNamespace)); err != nil {
+ return err
+ }
+ case specgen.Private:
+ if err := g.AddOrReplaceLinuxNamespace(string(spec.PIDNamespace), ""); err != nil {
+ return err
+ }
+ }
+
+ // IPC
+ switch s.IpcNS.NSMode {
+ case specgen.Path:
+ if _, err := os.Stat(s.IpcNS.Value); err != nil {
+ 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
+ }
+ case specgen.Host:
+ if err := g.RemoveLinuxNamespace(string(spec.IPCNamespace)); err != nil {
+ return err
+ }
+ case specgen.Private:
+ if err := g.AddOrReplaceLinuxNamespace(string(spec.IPCNamespace), ""); err != nil {
+ return err
+ }
+ }
+
+ // UTS
+ switch s.UtsNS.NSMode {
+ case specgen.Path:
+ if _, err := os.Stat(s.UtsNS.Value); err != nil {
+ 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
+ }
+ case specgen.Host:
+ if err := g.RemoveLinuxNamespace(string(spec.UTSNamespace)); err != nil {
+ return err
+ }
+ case specgen.Private:
+ if err := g.AddOrReplaceLinuxNamespace(string(spec.UTSNamespace), ""); err != nil {
+ return err
+ }
+ }
+
+ hostname := s.Hostname
+ if hostname == "" {
+ switch {
+ case s.UtsNS.NSMode == specgen.FromPod:
+ hostname = pod.Hostname()
+ case s.UtsNS.NSMode == specgen.FromContainer:
+ utsCtr, err := rt.LookupContainer(s.UtsNS.Value)
+ if err != nil {
+ return fmt.Errorf("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 fmt.Errorf("unable to retrieve hostname of the host: %w", err)
+ }
+ hostname = tmpHostname
+ default:
+ logrus.Debug("No hostname set; container's hostname will default to runtime default")
+ }
+ }
+
+ g.RemoveHostname()
+ if s.Hostname != "" || s.UtsNS.NSMode != specgen.Host {
+ // Set the hostname in the OCI configuration only if specified by
+ // the user or if we are creating a new UTS namespace.
+ // TODO: Should we be doing this for pod or container shared
+ // namespaces?
+ g.SetHostname(hostname)
+ }
+ if _, ok := s.Env["HOSTNAME"]; !ok && s.Hostname != "" {
+ g.AddProcessEnv("HOSTNAME", hostname)
+ }
+
+ // User
+ if _, err := specgen.SetupUserNS(s.IDMappings, s.UserNS, g); err != nil {
+ return err
+ }
+
+ // Cgroup
+ switch s.CgroupNS.NSMode {
+ case specgen.Path:
+ if _, err := os.Stat(s.CgroupNS.Value); err != nil {
+ 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
+ }
+ case specgen.Host:
+ if err := g.RemoveLinuxNamespace(string(spec.CgroupNamespace)); err != nil {
+ return err
+ }
+ case specgen.Private:
+ if err := g.AddOrReplaceLinuxNamespace(string(spec.CgroupNamespace), ""); err != nil {
+ return err
+ }
+ }
+
+ // Net
+ switch s.NetNS.NSMode {
+ case specgen.Path:
+ if _, err := os.Stat(s.NetNS.Value); err != nil {
+ 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
+ }
+ case specgen.Host:
+ if err := g.RemoveLinuxNamespace(string(spec.NetworkNamespace)); err != nil {
+ return err
+ }
+ case specgen.Private, specgen.NoNetwork:
+ if err := g.AddOrReplaceLinuxNamespace(string(spec.NetworkNamespace), ""); err != nil {
+ return err
+ }
+ }
+
+ if g.Config.Annotations == nil {
+ g.Config.Annotations = make(map[string]string)
+ }
+ if s.PublishExposedPorts {
+ g.Config.Annotations[define.InspectAnnotationPublishAll] = define.InspectResponseTrue
+ } else {
+ g.Config.Annotations[define.InspectAnnotationPublishAll] = define.InspectResponseFalse
+ }
+
+ return nil
+}
diff --git a/pkg/specgen/generate/namespaces_unsupported.go b/pkg/specgen/generate/namespaces_unsupported.go
new file mode 100644
index 000000000..c4a9c22d8
--- /dev/null
+++ b/pkg/specgen/generate/namespaces_unsupported.go
@@ -0,0 +1,16 @@
+//go:build !linux && !freebsd
+// +build !linux,!freebsd
+
+package generate
+
+import (
+ "errors"
+
+ "github.com/containers/podman/v4/libpod"
+ "github.com/containers/podman/v4/pkg/specgen"
+ "github.com/opencontainers/runtime-tools/generate"
+)
+
+func specConfigureNamespaces(s *specgen.SpecGenerator, g *generate.Generator, rt *libpod.Runtime, pod *libpod.Pod) error {
+ return errors.New("unsupported specConfigureNamespaces")
+}
diff --git a/pkg/specgen/generate/oci.go b/pkg/specgen/generate/oci.go
index f59fe1011..3ac1a9b3f 100644
--- a/pkg/specgen/generate/oci.go
+++ b/pkg/specgen/generate/oci.go
@@ -1,37 +1,19 @@
package generate
import (
- "context"
- "encoding/json"
"fmt"
- "path"
"strings"
"github.com/containers/common/libimage"
- "github.com/containers/common/pkg/cgroups"
"github.com/containers/common/pkg/config"
- "github.com/containers/podman/v4/libpod"
"github.com/containers/podman/v4/libpod/define"
"github.com/containers/podman/v4/pkg/rootless"
"github.com/containers/podman/v4/pkg/specgen"
- spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-tools/generate"
"github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
)
-func setProcOpts(s *specgen.SpecGenerator, g *generate.Generator) {
- if s.ProcOpts == nil {
- return
- }
- for i := range g.Config.Mounts {
- if g.Config.Mounts[i].Destination == "/proc" {
- g.Config.Mounts[i].Options = s.ProcOpts
- return
- }
- }
-}
-
func addRlimits(s *specgen.SpecGenerator, g *generate.Generator) {
var (
isRootless = rootless.IsRootless()
@@ -58,38 +40,38 @@ func addRlimits(s *specgen.SpecGenerator, g *generate.Generator) {
// files and number of processes to the maximum they can be set to
// (without overriding a sysctl)
if !nofileSet {
- max := define.RLimitDefaultValue
- current := define.RLimitDefaultValue
+ max := rlimT(define.RLimitDefaultValue)
+ current := rlimT(define.RLimitDefaultValue)
if isRootless {
var rlimit unix.Rlimit
if err := unix.Getrlimit(unix.RLIMIT_NOFILE, &rlimit); err != nil {
logrus.Warnf("Failed to return RLIMIT_NOFILE ulimit %q", err)
}
- if rlimit.Cur < current {
- current = rlimit.Cur
+ if rlimT(rlimit.Cur) < current {
+ current = rlimT(rlimit.Cur)
}
- if rlimit.Max < max {
- max = rlimit.Max
+ if rlimT(rlimit.Max) < max {
+ max = rlimT(rlimit.Max)
}
}
- g.AddProcessRlimits("RLIMIT_NOFILE", max, current)
+ g.AddProcessRlimits("RLIMIT_NOFILE", uint64(max), uint64(current))
}
if !nprocSet {
- max := define.RLimitDefaultValue
- current := define.RLimitDefaultValue
+ max := rlimT(define.RLimitDefaultValue)
+ current := rlimT(define.RLimitDefaultValue)
if isRootless {
var rlimit unix.Rlimit
if err := unix.Getrlimit(unix.RLIMIT_NPROC, &rlimit); err != nil {
logrus.Warnf("Failed to return RLIMIT_NPROC ulimit %q", err)
}
- if rlimit.Cur < current {
- current = rlimit.Cur
+ if rlimT(rlimit.Cur) < current {
+ current = rlimT(rlimit.Cur)
}
- if rlimit.Max < max {
- max = rlimit.Max
+ if rlimT(rlimit.Max) < max {
+ max = rlimT(rlimit.Max)
}
}
- g.AddProcessRlimits("RLIMIT_NPROC", max, current)
+ g.AddProcessRlimits("RLIMIT_NPROC", uint64(max), uint64(current))
}
}
@@ -133,302 +115,3 @@ func makeCommand(s *specgen.SpecGenerator, imageData *libimage.ImageData, rtc *c
return finalCommand, nil
}
-
-// canMountSys is a best-effort heuristic to detect whether mounting a new sysfs is permitted in the container
-func canMountSys(isRootless, isNewUserns bool, s *specgen.SpecGenerator) bool {
- if s.NetNS.IsHost() && (isRootless || isNewUserns) {
- return false
- }
- if isNewUserns {
- switch s.NetNS.NSMode {
- case specgen.Slirp, specgen.Private, specgen.NoNetwork, specgen.Bridge:
- return true
- default:
- return false
- }
- }
- return true
-}
-
-func getCgroupPermissons(unmask []string) string {
- ro := "ro"
- rw := "rw"
- cgroup := "/sys/fs/cgroup"
-
- cgroupv2, _ := cgroups.IsCgroup2UnifiedMode()
- if !cgroupv2 {
- return ro
- }
-
- if unmask != nil && unmask[0] == "ALL" {
- return rw
- }
-
- for _, p := range unmask {
- if path.Clean(p) == cgroup {
- return rw
- }
- }
- return ro
-}
-
-// SpecGenToOCI returns the base configuration for the container.
-func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runtime, rtc *config.Config, newImage *libimage.Image, mounts []spec.Mount, pod *libpod.Pod, finalCmd []string, compatibleOptions *libpod.InfraInherit) (*spec.Spec, error) {
- cgroupPerm := getCgroupPermissons(s.Unmask)
-
- g, err := generate.New("linux")
- if err != nil {
- return nil, err
- }
- // Remove the default /dev/shm mount to ensure we overwrite it
- g.RemoveMount("/dev/shm")
- g.HostSpecific = true
- addCgroup := true
-
- isRootless := rootless.IsRootless()
- isNewUserns := s.UserNS.IsContainer() || s.UserNS.IsPath() || s.UserNS.IsPrivate()
-
- canMountSys := canMountSys(isRootless, isNewUserns, s)
-
- if s.Privileged && canMountSys {
- cgroupPerm = "rw"
- g.RemoveMount("/sys")
- sysMnt := spec.Mount{
- Destination: "/sys",
- Type: "sysfs",
- Source: "sysfs",
- Options: []string{"rprivate", "nosuid", "noexec", "nodev", "rw"},
- }
- g.AddMount(sysMnt)
- }
- if !canMountSys {
- addCgroup = false
- g.RemoveMount("/sys")
- r := "ro"
- if s.Privileged {
- r = "rw"
- }
- sysMnt := spec.Mount{
- Destination: "/sys",
- Type: "bind", // should we use a constant for this, like createconfig?
- Source: "/sys",
- Options: []string{"rprivate", "nosuid", "noexec", "nodev", r, "rbind"},
- }
- g.AddMount(sysMnt)
- if !s.Privileged && isRootless {
- g.AddLinuxMaskedPaths("/sys/kernel")
- }
- }
- gid5Available := true
- if isRootless {
- nGids, err := rootless.GetAvailableGids()
- if err != nil {
- return nil, err
- }
- gid5Available = nGids >= 5
- }
- // When using a different user namespace, check that the GID 5 is mapped inside
- // the container.
- if gid5Available && (s.IDMappings != nil && len(s.IDMappings.GIDMap) > 0) {
- mappingFound := false
- for _, r := range s.IDMappings.GIDMap {
- if r.ContainerID <= 5 && 5 < r.ContainerID+r.Size {
- mappingFound = true
- break
- }
- }
- if !mappingFound {
- gid5Available = false
- }
- }
- if !gid5Available {
- // If we have no GID mappings, the gid=5 default option would fail, so drop it.
- g.RemoveMount("/dev/pts")
- devPts := spec.Mount{
- Destination: "/dev/pts",
- Type: "devpts",
- Source: "devpts",
- Options: []string{"rprivate", "nosuid", "noexec", "newinstance", "ptmxmode=0666", "mode=0620"},
- }
- g.AddMount(devPts)
- }
-
- inUserNS := isRootless || isNewUserns
-
- if inUserNS && s.IpcNS.IsHost() {
- g.RemoveMount("/dev/mqueue")
- devMqueue := spec.Mount{
- Destination: "/dev/mqueue",
- Type: "bind", // constant ?
- Source: "/dev/mqueue",
- Options: []string{"bind", "nosuid", "noexec", "nodev"},
- }
- g.AddMount(devMqueue)
- }
- if inUserNS && s.PidNS.IsHost() {
- g.RemoveMount("/proc")
- procMount := spec.Mount{
- Destination: "/proc",
- Type: define.TypeBind,
- Source: "/proc",
- Options: []string{"rbind", "nosuid", "noexec", "nodev"},
- }
- g.AddMount(procMount)
- }
-
- if addCgroup {
- cgroupMnt := spec.Mount{
- Destination: "/sys/fs/cgroup",
- Type: "cgroup",
- Source: "cgroup",
- Options: []string{"rprivate", "nosuid", "noexec", "nodev", "relatime", cgroupPerm},
- }
- g.AddMount(cgroupMnt)
- }
-
- g.Config.Linux.Personality = s.Personality
-
- g.SetProcessCwd(s.WorkDir)
-
- g.SetProcessArgs(finalCmd)
-
- g.SetProcessTerminal(s.Terminal)
-
- for key, val := range s.Annotations {
- g.AddAnnotation(key, val)
- }
-
- if s.ResourceLimits != nil {
- out, err := json.Marshal(s.ResourceLimits)
- if err != nil {
- return nil, err
- }
- err = json.Unmarshal(out, g.Config.Linux.Resources)
- if err != nil {
- return nil, err
- }
- g.Config.Linux.Resources = s.ResourceLimits
- }
-
- weightDevices, err := WeightDevices(s.WeightDevice)
- if err != nil {
- return nil, err
- }
- if len(weightDevices) > 0 {
- for _, dev := range weightDevices {
- g.AddLinuxResourcesBlockIOWeightDevice(dev.Major, dev.Minor, *dev.Weight)
- }
- }
-
- // 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 {
- // add default devices from containers.conf
- for _, device := range rtc.Containers.Devices {
- if err = DevicesFromPath(&g, device); err != nil {
- return nil, err
- }
- }
- if len(compatibleOptions.HostDeviceList) > 0 && len(s.Devices) == 0 {
- userDevices = compatibleOptions.HostDeviceList
- } else {
- userDevices = s.Devices
- }
- // add default devices specified by caller
- for _, device := range userDevices {
- if err = DevicesFromPath(&g, device.Path); err != nil {
- return nil, err
- }
- }
- }
- s.HostDeviceList = userDevices
-
- // set the devices cgroup when not running in a user namespace
- if !inUserNS && !s.Privileged {
- for _, dev := range s.DeviceCgroupRule {
- g.AddLinuxResourcesDevice(true, dev.Type, dev.Major, dev.Minor, dev.Access)
- }
- }
-
- BlockAccessToKernelFilesystems(s.Privileged, s.PidNS.IsHost(), s.Mask, s.Unmask, &g)
-
- g.ClearProcessEnv()
- for name, val := range s.Env {
- g.AddProcessEnv(name, val)
- }
-
- addRlimits(s, &g)
-
- // NAMESPACES
- if err := specConfigureNamespaces(s, &g, rt, pod); err != nil {
- return nil, err
- }
- configSpec := g.Config
-
- if err := securityConfigureGenerator(s, &g, newImage, rtc); err != nil {
- return nil, err
- }
-
- // BIND MOUNTS
- configSpec.Mounts = SupersedeUserMounts(mounts, configSpec.Mounts)
- // Process mounts to ensure correct options
- if err := InitFSMounts(configSpec.Mounts); err != nil {
- return nil, err
- }
-
- // Add annotations
- if configSpec.Annotations == nil {
- configSpec.Annotations = make(map[string]string)
- }
-
- if s.Remove {
- configSpec.Annotations[define.InspectAnnotationAutoremove] = define.InspectResponseTrue
- } else {
- configSpec.Annotations[define.InspectAnnotationAutoremove] = define.InspectResponseFalse
- }
-
- if len(s.VolumesFrom) > 0 {
- configSpec.Annotations[define.InspectAnnotationVolumesFrom] = strings.Join(s.VolumesFrom, ",")
- }
-
- if s.Privileged {
- configSpec.Annotations[define.InspectAnnotationPrivileged] = define.InspectResponseTrue
- } else {
- configSpec.Annotations[define.InspectAnnotationPrivileged] = define.InspectResponseFalse
- }
-
- if s.Init {
- configSpec.Annotations[define.InspectAnnotationInit] = define.InspectResponseTrue
- } else {
- configSpec.Annotations[define.InspectAnnotationInit] = define.InspectResponseFalse
- }
-
- if s.OOMScoreAdj != nil {
- g.SetProcessOOMScoreAdj(*s.OOMScoreAdj)
- }
- setProcOpts(s, &g)
-
- return configSpec, nil
-}
-
-func WeightDevices(wtDevices map[string]spec.LinuxWeightDevice) ([]spec.LinuxWeightDevice, error) {
- devs := []spec.LinuxWeightDevice{}
- for k, v := range wtDevices {
- statT := unix.Stat_t{}
- if err := unix.Stat(k, &statT); err != nil {
- return nil, fmt.Errorf("failed to inspect '%s' in --blkio-weight-device: %w", k, err)
- }
- dev := new(spec.LinuxWeightDevice)
- dev.Major = (int64(unix.Major(uint64(statT.Rdev)))) //nolint: unconvert
- dev.Minor = (int64(unix.Minor(uint64(statT.Rdev)))) //nolint: unconvert
- dev.Weight = v.Weight
- devs = append(devs, *dev)
- }
- return devs, nil
-}
diff --git a/pkg/specgen/generate/oci_freebsd.go b/pkg/specgen/generate/oci_freebsd.go
new file mode 100644
index 000000000..71c926fd2
--- /dev/null
+++ b/pkg/specgen/generate/oci_freebsd.go
@@ -0,0 +1,96 @@
+//go:build freebsd
+
+package generate
+
+import (
+ "context"
+ "strings"
+
+ "github.com/containers/common/libimage"
+ "github.com/containers/common/pkg/config"
+ "github.com/containers/podman/v4/libpod"
+ "github.com/containers/podman/v4/libpod/define"
+ "github.com/containers/podman/v4/pkg/specgen"
+ spec "github.com/opencontainers/runtime-spec/specs-go"
+ "github.com/opencontainers/runtime-tools/generate"
+)
+
+// SpecGenToOCI returns the base configuration for the container.
+func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runtime, rtc *config.Config, newImage *libimage.Image, mounts []spec.Mount, pod *libpod.Pod, finalCmd []string, compatibleOptions *libpod.InfraInherit) (*spec.Spec, error) {
+ g, err := generate.New("freebsd")
+ if err != nil {
+ return nil, err
+ }
+
+ g.SetProcessCwd(s.WorkDir)
+
+ g.SetProcessArgs(finalCmd)
+
+ g.SetProcessTerminal(s.Terminal)
+
+ for key, val := range s.Annotations {
+ g.AddAnnotation(key, val)
+ }
+
+ g.ClearProcessEnv()
+ for name, val := range s.Env {
+ g.AddProcessEnv(name, val)
+ }
+
+ addRlimits(s, &g)
+
+ // NAMESPACES
+ if err := specConfigureNamespaces(s, &g, rt, pod); err != nil {
+ return nil, err
+ }
+ configSpec := g.Config
+
+ if err := securityConfigureGenerator(s, &g, newImage, rtc); err != nil {
+ return nil, err
+ }
+
+ // BIND MOUNTS
+ configSpec.Mounts = SupersedeUserMounts(mounts, configSpec.Mounts)
+ // Process mounts to ensure correct options
+ if err := InitFSMounts(configSpec.Mounts); err != nil {
+ return nil, err
+ }
+
+ // Add annotations
+ if configSpec.Annotations == nil {
+ configSpec.Annotations = make(map[string]string)
+ }
+
+ if s.Remove {
+ configSpec.Annotations[define.InspectAnnotationAutoremove] = define.InspectResponseTrue
+ } else {
+ configSpec.Annotations[define.InspectAnnotationAutoremove] = define.InspectResponseFalse
+ }
+
+ if len(s.VolumesFrom) > 0 {
+ configSpec.Annotations[define.InspectAnnotationVolumesFrom] = strings.Join(s.VolumesFrom, ",")
+ }
+
+ if s.Privileged {
+ configSpec.Annotations[define.InspectAnnotationPrivileged] = define.InspectResponseTrue
+ } else {
+ configSpec.Annotations[define.InspectAnnotationPrivileged] = define.InspectResponseFalse
+ }
+
+ if s.Init {
+ configSpec.Annotations[define.InspectAnnotationInit] = define.InspectResponseTrue
+ } else {
+ configSpec.Annotations[define.InspectAnnotationInit] = define.InspectResponseFalse
+ }
+
+ if s.OOMScoreAdj != nil {
+ g.SetProcessOOMScoreAdj(*s.OOMScoreAdj)
+ }
+
+ return configSpec, nil
+}
+
+func WeightDevices(wtDevices map[string]spec.LinuxWeightDevice) ([]spec.LinuxWeightDevice, error) {
+ devs := []spec.LinuxWeightDevice{}
+ return devs, nil
+}
diff --git a/pkg/specgen/generate/oci_linux.go b/pkg/specgen/generate/oci_linux.go
new file mode 100644
index 000000000..341853de5
--- /dev/null
+++ b/pkg/specgen/generate/oci_linux.go
@@ -0,0 +1,331 @@
+package generate
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "path"
+ "strings"
+
+ "github.com/containers/common/libimage"
+ "github.com/containers/common/pkg/cgroups"
+ "github.com/containers/common/pkg/config"
+ "github.com/containers/podman/v4/libpod"
+ "github.com/containers/podman/v4/libpod/define"
+ "github.com/containers/podman/v4/pkg/rootless"
+ "github.com/containers/podman/v4/pkg/specgen"
+ spec "github.com/opencontainers/runtime-spec/specs-go"
+ "github.com/opencontainers/runtime-tools/generate"
+ "golang.org/x/sys/unix"
+)
+
+func setProcOpts(s *specgen.SpecGenerator, g *generate.Generator) {
+ if s.ProcOpts == nil {
+ return
+ }
+ for i := range g.Config.Mounts {
+ if g.Config.Mounts[i].Destination == "/proc" {
+ g.Config.Mounts[i].Options = s.ProcOpts
+ return
+ }
+ }
+}
+
+// canMountSys is a best-effort heuristic to detect whether mounting a new sysfs is permitted in the container
+func canMountSys(isRootless, isNewUserns bool, s *specgen.SpecGenerator) bool {
+ if s.NetNS.IsHost() && (isRootless || isNewUserns) {
+ return false
+ }
+ if isNewUserns {
+ switch s.NetNS.NSMode {
+ case specgen.Slirp, specgen.Private, specgen.NoNetwork, specgen.Bridge:
+ return true
+ default:
+ return false
+ }
+ }
+ return true
+}
+
+func getCgroupPermissons(unmask []string) string {
+ ro := "ro"
+ rw := "rw"
+ cgroup := "/sys/fs/cgroup"
+
+ cgroupv2, _ := cgroups.IsCgroup2UnifiedMode()
+ if !cgroupv2 {
+ return ro
+ }
+
+ if unmask != nil && unmask[0] == "ALL" {
+ return rw
+ }
+
+ for _, p := range unmask {
+ if path.Clean(p) == cgroup {
+ return rw
+ }
+ }
+ return ro
+}
+
+// SpecGenToOCI returns the base configuration for the container.
+func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runtime, rtc *config.Config, newImage *libimage.Image, mounts []spec.Mount, pod *libpod.Pod, finalCmd []string, compatibleOptions *libpod.InfraInherit) (*spec.Spec, error) {
+ cgroupPerm := getCgroupPermissons(s.Unmask)
+
+ g, err := generate.New("linux")
+ if err != nil {
+ return nil, err
+ }
+ // Remove the default /dev/shm mount to ensure we overwrite it
+ g.RemoveMount("/dev/shm")
+ g.HostSpecific = true
+ addCgroup := true
+
+ isRootless := rootless.IsRootless()
+ isNewUserns := s.UserNS.IsContainer() || s.UserNS.IsPath() || s.UserNS.IsPrivate()
+
+ canMountSys := canMountSys(isRootless, isNewUserns, s)
+
+ if s.Privileged && canMountSys {
+ cgroupPerm = "rw"
+ g.RemoveMount("/sys")
+ sysMnt := spec.Mount{
+ Destination: "/sys",
+ Type: "sysfs",
+ Source: "sysfs",
+ Options: []string{"rprivate", "nosuid", "noexec", "nodev", "rw"},
+ }
+ g.AddMount(sysMnt)
+ }
+ if !canMountSys {
+ addCgroup = false
+ g.RemoveMount("/sys")
+ r := "ro"
+ if s.Privileged {
+ r = "rw"
+ }
+ sysMnt := spec.Mount{
+ Destination: "/sys",
+ Type: "bind", // should we use a constant for this, like createconfig?
+ Source: "/sys",
+ Options: []string{"rprivate", "nosuid", "noexec", "nodev", r, "rbind"},
+ }
+ g.AddMount(sysMnt)
+ if !s.Privileged && isRootless {
+ g.AddLinuxMaskedPaths("/sys/kernel")
+ }
+ }
+ gid5Available := true
+ if isRootless {
+ nGids, err := rootless.GetAvailableGids()
+ if err != nil {
+ return nil, err
+ }
+ gid5Available = nGids >= 5
+ }
+ // When using a different user namespace, check that the GID 5 is mapped inside
+ // the container.
+ if gid5Available && (s.IDMappings != nil && len(s.IDMappings.GIDMap) > 0) {
+ mappingFound := false
+ for _, r := range s.IDMappings.GIDMap {
+ if r.ContainerID <= 5 && 5 < r.ContainerID+r.Size {
+ mappingFound = true
+ break
+ }
+ }
+ if !mappingFound {
+ gid5Available = false
+ }
+ }
+ if !gid5Available {
+ // If we have no GID mappings, the gid=5 default option would fail, so drop it.
+ g.RemoveMount("/dev/pts")
+ devPts := spec.Mount{
+ Destination: "/dev/pts",
+ Type: "devpts",
+ Source: "devpts",
+ Options: []string{"rprivate", "nosuid", "noexec", "newinstance", "ptmxmode=0666", "mode=0620"},
+ }
+ g.AddMount(devPts)
+ }
+
+ inUserNS := isRootless || isNewUserns
+
+ if inUserNS && s.IpcNS.IsHost() {
+ g.RemoveMount("/dev/mqueue")
+ devMqueue := spec.Mount{
+ Destination: "/dev/mqueue",
+ Type: "bind", // constant ?
+ Source: "/dev/mqueue",
+ Options: []string{"bind", "nosuid", "noexec", "nodev"},
+ }
+ g.AddMount(devMqueue)
+ }
+ if inUserNS && s.PidNS.IsHost() {
+ g.RemoveMount("/proc")
+ procMount := spec.Mount{
+ Destination: "/proc",
+ Type: define.TypeBind,
+ Source: "/proc",
+ Options: []string{"rbind", "nosuid", "noexec", "nodev"},
+ }
+ g.AddMount(procMount)
+ }
+
+ if addCgroup {
+ cgroupMnt := spec.Mount{
+ Destination: "/sys/fs/cgroup",
+ Type: "cgroup",
+ Source: "cgroup",
+ Options: []string{"rprivate", "nosuid", "noexec", "nodev", "relatime", cgroupPerm},
+ }
+ g.AddMount(cgroupMnt)
+ }
+
+ g.Config.Linux.Personality = s.Personality
+
+ g.SetProcessCwd(s.WorkDir)
+
+ g.SetProcessArgs(finalCmd)
+
+ g.SetProcessTerminal(s.Terminal)
+
+ for key, val := range s.Annotations {
+ g.AddAnnotation(key, val)
+ }
+
+ if s.ResourceLimits != nil {
+ out, err := json.Marshal(s.ResourceLimits)
+ if err != nil {
+ return nil, err
+ }
+ err = json.Unmarshal(out, g.Config.Linux.Resources)
+ if err != nil {
+ return nil, err
+ }
+ g.Config.Linux.Resources = s.ResourceLimits
+ }
+
+ weightDevices, err := WeightDevices(s.WeightDevice)
+ if err != nil {
+ return nil, err
+ }
+ if len(weightDevices) > 0 {
+ for _, dev := range weightDevices {
+ g.AddLinuxResourcesBlockIOWeightDevice(dev.Major, dev.Minor, *dev.Weight)
+ }
+ }
+
+ // 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 {
+ // add default devices from containers.conf
+ for _, device := range rtc.Containers.Devices {
+ if err = DevicesFromPath(&g, device); err != nil {
+ return nil, err
+ }
+ }
+ if len(compatibleOptions.HostDeviceList) > 0 && len(s.Devices) == 0 {
+ userDevices = compatibleOptions.HostDeviceList
+ } else {
+ userDevices = s.Devices
+ }
+ // add default devices specified by caller
+ for _, device := range userDevices {
+ if err = DevicesFromPath(&g, device.Path); err != nil {
+ return nil, err
+ }
+ }
+ }
+ s.HostDeviceList = userDevices
+
+ // set the devices cgroup when not running in a user namespace
+ if !inUserNS && !s.Privileged {
+ for _, dev := range s.DeviceCgroupRule {
+ g.AddLinuxResourcesDevice(true, dev.Type, dev.Major, dev.Minor, dev.Access)
+ }
+ }
+
+ BlockAccessToKernelFilesystems(s.Privileged, s.PidNS.IsHost(), s.Mask, s.Unmask, &g)
+
+ g.ClearProcessEnv()
+ for name, val := range s.Env {
+ g.AddProcessEnv(name, val)
+ }
+
+ addRlimits(s, &g)
+
+ // NAMESPACES
+ if err := specConfigureNamespaces(s, &g, rt, pod); err != nil {
+ return nil, err
+ }
+ configSpec := g.Config
+
+ if err := securityConfigureGenerator(s, &g, newImage, rtc); err != nil {
+ return nil, err
+ }
+
+ // BIND MOUNTS
+ configSpec.Mounts = SupersedeUserMounts(mounts, configSpec.Mounts)
+ // Process mounts to ensure correct options
+ if err := InitFSMounts(configSpec.Mounts); err != nil {
+ return nil, err
+ }
+
+ // Add annotations
+ if configSpec.Annotations == nil {
+ configSpec.Annotations = make(map[string]string)
+ }
+
+ if s.Remove {
+ configSpec.Annotations[define.InspectAnnotationAutoremove] = define.InspectResponseTrue
+ } else {
+ configSpec.Annotations[define.InspectAnnotationAutoremove] = define.InspectResponseFalse
+ }
+
+ if len(s.VolumesFrom) > 0 {
+ configSpec.Annotations[define.InspectAnnotationVolumesFrom] = strings.Join(s.VolumesFrom, ",")
+ }
+
+ if s.Privileged {
+ configSpec.Annotations[define.InspectAnnotationPrivileged] = define.InspectResponseTrue
+ } else {
+ configSpec.Annotations[define.InspectAnnotationPrivileged] = define.InspectResponseFalse
+ }
+
+ if s.Init {
+ configSpec.Annotations[define.InspectAnnotationInit] = define.InspectResponseTrue
+ } else {
+ configSpec.Annotations[define.InspectAnnotationInit] = define.InspectResponseFalse
+ }
+
+ if s.OOMScoreAdj != nil {
+ g.SetProcessOOMScoreAdj(*s.OOMScoreAdj)
+ }
+ setProcOpts(s, &g)
+
+ return configSpec, nil
+}
+
+func WeightDevices(wtDevices map[string]spec.LinuxWeightDevice) ([]spec.LinuxWeightDevice, error) {
+ devs := []spec.LinuxWeightDevice{}
+ for k, v := range wtDevices {
+ statT := unix.Stat_t{}
+ if err := unix.Stat(k, &statT); err != nil {
+ return nil, fmt.Errorf("failed to inspect '%s' in --blkio-weight-device: %w", k, err)
+ }
+ dev := new(spec.LinuxWeightDevice)
+ dev.Major = (int64(unix.Major(uint64(statT.Rdev)))) //nolint: unconvert
+ dev.Minor = (int64(unix.Minor(uint64(statT.Rdev)))) //nolint: unconvert
+ dev.Weight = v.Weight
+ devs = append(devs, *dev)
+ }
+ return devs, nil
+}
diff --git a/pkg/specgen/generate/oci_unsupported.go b/pkg/specgen/generate/oci_unsupported.go
new file mode 100644
index 000000000..7e1b8c42c
--- /dev/null
+++ b/pkg/specgen/generate/oci_unsupported.go
@@ -0,0 +1,24 @@
+//go:build !linux && !freebsd
+// +build !linux,!freebsd
+
+package generate
+
+import (
+ "context"
+ "errors"
+
+ "github.com/containers/common/libimage"
+ "github.com/containers/common/pkg/config"
+ "github.com/containers/podman/v4/libpod"
+ "github.com/containers/podman/v4/pkg/specgen"
+ spec "github.com/opencontainers/runtime-spec/specs-go"
+)
+
+// SpecGenToOCI returns the base configuration for the container.
+func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runtime, rtc *config.Config, newImage *libimage.Image, mounts []spec.Mount, pod *libpod.Pod, finalCmd []string, compatibleOptions *libpod.InfraInherit) (*spec.Spec, error) {
+ return nil, errors.New("unsupported SpecGenToOCI")
+}
+
+func WeightDevices(wtDevices map[string]spec.LinuxWeightDevice) ([]spec.LinuxWeightDevice, error) {
+ return []spec.LinuxWeightDevice{}, errors.New("unsupported WeightDevices")
+}
diff --git a/pkg/specgen/generate/pod_create.go b/pkg/specgen/generate/pod_create.go
index 4e6362c9b..14d390e49 100644
--- a/pkg/specgen/generate/pod_create.go
+++ b/pkg/specgen/generate/pod_create.go
@@ -2,6 +2,7 @@ package generate
import (
"context"
+ "encoding/json"
"fmt"
"net"
"os"
@@ -44,7 +45,7 @@ func MakePod(p *entities.PodSpec, rt *libpod.Runtime) (*libpod.Pod, error) {
}
if !p.PodSpecGen.NoInfra {
- err := FinishThrottleDevices(p.PodSpecGen.InfraContainerSpec)
+ err := specgen.FinishThrottleDevices(p.PodSpecGen.InfraContainerSpec)
if err != nil {
return nil, err
}
@@ -52,17 +53,11 @@ func MakePod(p *entities.PodSpec, rt *libpod.Runtime) (*libpod.Pod, error) {
p.PodSpecGen.ResourceLimits.BlockIO = p.PodSpecGen.InfraContainerSpec.ResourceLimits.BlockIO
}
- weightDevices, err := WeightDevices(p.PodSpecGen.InfraContainerSpec.WeightDevice)
+ err = specgen.WeightDevices(p.PodSpecGen.InfraContainerSpec)
if err != nil {
return nil, err
}
-
- if p.PodSpecGen.ResourceLimits != nil && len(weightDevices) > 0 {
- if p.PodSpecGen.ResourceLimits.BlockIO == nil {
- p.PodSpecGen.ResourceLimits.BlockIO = &specs.LinuxBlockIO{}
- }
- p.PodSpecGen.ResourceLimits.BlockIO.WeightDevice = weightDevices
- }
+ p.PodSpecGen.ResourceLimits = p.PodSpecGen.InfraContainerSpec.ResourceLimits
}
options, err := createPodOptions(&p.PodSpecGen)
@@ -327,6 +322,19 @@ func PodConfigToSpec(rt *libpod.Runtime, spec *specgen.PodSpecGenerator, infraOp
}
spec.InfraContainerSpec = infraSpec
+ matching, err := json.Marshal(infraSpec)
+ if err != nil {
+ return nil, err
+ }
+
+ // track name before unmarshal so we do not overwrite w/ infra
+ name := spec.Name
+ err = json.Unmarshal(matching, spec)
+ if err != nil {
+ return nil, err
+ }
+
+ spec.Name = name
}
// need to reset hostname, name etc of both pod and infra
diff --git a/pkg/specgen/generate/ports.go b/pkg/specgen/generate/ports.go
index 572f256c1..8ad249409 100644
--- a/pkg/specgen/generate/ports.go
+++ b/pkg/specgen/generate/ports.go
@@ -354,7 +354,7 @@ func createPortMappings(s *specgen.SpecGenerator, imageData *libimage.ImageData)
}
protocols, err := checkProtocol(proto, false)
if err != nil {
- return nil, nil, fmt.Errorf("error validating protocols for exposed port %d: %w", port, err)
+ return nil, nil, fmt.Errorf("validating protocols for exposed port %d: %w", port, err)
}
toExpose[port] = appendProtocolsNoDuplicates(toExpose[port], protocols)
}
diff --git a/pkg/specgen/generate/rlimit_int64.go b/pkg/specgen/generate/rlimit_int64.go
new file mode 100644
index 000000000..b4cce3453
--- /dev/null
+++ b/pkg/specgen/generate/rlimit_int64.go
@@ -0,0 +1,6 @@
+//go:build freebsd
+// +build freebsd
+
+package generate
+
+type rlimT int64
diff --git a/pkg/specgen/generate/rlimit_uint64.go b/pkg/specgen/generate/rlimit_uint64.go
new file mode 100644
index 000000000..d85f8dd2c
--- /dev/null
+++ b/pkg/specgen/generate/rlimit_uint64.go
@@ -0,0 +1,6 @@
+//go:build linux || darwin
+// +build linux darwin
+
+package generate
+
+type rlimT uint64
diff --git a/pkg/specgen/generate/security_freebsd.go b/pkg/specgen/generate/security_freebsd.go
new file mode 100644
index 000000000..5fd66c769
--- /dev/null
+++ b/pkg/specgen/generate/security_freebsd.go
@@ -0,0 +1,19 @@
+package generate
+
+import (
+ "github.com/containers/common/libimage"
+ "github.com/containers/common/pkg/config"
+ "github.com/containers/podman/v4/libpod"
+ "github.com/containers/podman/v4/pkg/specgen"
+ "github.com/opencontainers/runtime-tools/generate"
+)
+
+// setLabelOpts sets the label options of the SecurityConfig according to the
+// input.
+func setLabelOpts(s *specgen.SpecGenerator, runtime *libpod.Runtime, pidConfig specgen.Namespace, ipcConfig specgen.Namespace) error {
+ return nil
+}
+
+func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator, newImage *libimage.Image, rtc *config.Config) error {
+ return nil
+}
diff --git a/pkg/specgen/generate/security.go b/pkg/specgen/generate/security_linux.go
index aacefcbac..aacefcbac 100644
--- a/pkg/specgen/generate/security.go
+++ b/pkg/specgen/generate/security_linux.go
diff --git a/pkg/specgen/generate/security_unsupported.go b/pkg/specgen/generate/security_unsupported.go
new file mode 100644
index 000000000..d0f937e44
--- /dev/null
+++ b/pkg/specgen/generate/security_unsupported.go
@@ -0,0 +1,24 @@
+//go:build !linux && !freebsd
+// +build !linux,!freebsd
+
+package generate
+
+import (
+ "errors"
+
+ "github.com/containers/common/libimage"
+ "github.com/containers/common/pkg/config"
+ "github.com/containers/podman/v4/libpod"
+ "github.com/containers/podman/v4/pkg/specgen"
+ "github.com/opencontainers/runtime-tools/generate"
+)
+
+// setLabelOpts sets the label options of the SecurityConfig according to the
+// input.
+func setLabelOpts(s *specgen.SpecGenerator, runtime *libpod.Runtime, pidConfig specgen.Namespace, ipcConfig specgen.Namespace) error {
+ return errors.New("unsupported setLabelOpts")
+}
+
+func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator, newImage *libimage.Image, rtc *config.Config) error {
+ return errors.New("unsupported securityConfigureGenerator")
+}
diff --git a/pkg/specgen/generate/storage.go b/pkg/specgen/generate/storage.go
index 867bb4b79..c3cd61b36 100644
--- a/pkg/specgen/generate/storage.go
+++ b/pkg/specgen/generate/storage.go
@@ -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, fmt.Errorf("error getting absolute path of %s: %w", mount.Source, err)
+ return nil, nil, nil, fmt.Errorf("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, fmt.Errorf("error inspecting image to get image volumes: %w", err)
+ return nil, nil, fmt.Errorf("inspecting image to get image volumes: %w", err)
}
for volume := range inspect.Config.Volumes {
logrus.Debugf("Image has volume at %q", volume)
@@ -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, fmt.Errorf("error looking up container %q for volumes-from: %w", splitVol[0], err)
+ return nil, nil, fmt.Errorf("looking up container %q for volumes-from: %w", splitVol[0], err)
}
logrus.Debugf("Adding volumes from container %s", ctr.ID())
diff --git a/pkg/specgen/generate/validate.go b/pkg/specgen/generate/validate.go
index 9c933d747..e9ebdfce3 100644
--- a/pkg/specgen/generate/validate.go
+++ b/pkg/specgen/generate/validate.go
@@ -9,6 +9,7 @@ import (
"github.com/containers/common/pkg/cgroups"
"github.com/containers/common/pkg/sysinfo"
+ "github.com/containers/podman/v4/pkg/rootless"
"github.com/containers/podman/v4/pkg/specgen"
"github.com/containers/podman/v4/utils"
)
@@ -19,6 +20,11 @@ func verifyContainerResourcesCgroupV1(s *specgen.SpecGenerator) ([]string, error
sysInfo := sysinfo.New(true)
+ if s.ResourceLimits != nil && rootless.IsRootless() {
+ s.ResourceLimits = nil
+ warnings = append(warnings, "Resource limits are not supported and ignored on cgroups V1 rootless systems")
+ }
+
if s.ResourceLimits == nil {
return warnings, nil
}
@@ -76,7 +82,7 @@ func verifyContainerResourcesCgroupV1(s *specgen.SpecGenerator) ([]string, error
}
}
- // CPU Checks
+ // CPU checks
if s.ResourceLimits.CPU != nil {
cpu := s.ResourceLimits.CPU
if cpu.Shares != nil && !sysInfo.CPUShares {
@@ -163,6 +169,7 @@ func verifyContainerResourcesCgroupV2(s *specgen.SpecGenerator) ([]string, error
return warnings, nil
}
+ // Memory checks
if s.ResourceLimits.Memory != nil && s.ResourceLimits.Memory.Swap != nil {
own, err := utils.GetOwnCgroup()
if err != nil {
@@ -192,6 +199,19 @@ func verifyContainerResourcesCgroupV2(s *specgen.SpecGenerator) ([]string, error
s.ResourceLimits.Memory.Swap = nil
}
}
+
+ // CPU checks
+ if s.ResourceLimits.CPU != nil {
+ cpu := s.ResourceLimits.CPU
+ if cpu.RealtimePeriod != nil {
+ warnings = append(warnings, "Realtime period not supported on cgroups V2 systems")
+ cpu.RealtimePeriod = nil
+ }
+ if cpu.RealtimeRuntime != nil {
+ warnings = append(warnings, "Realtime runtime not supported on cgroups V2 systems")
+ cpu.RealtimeRuntime = nil
+ }
+ }
return warnings, nil
}