diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go index d01b95700e..5964607fa1 100644 --- a/pkg/specgen/generate/container_create.go +++ b/pkg/specgen/generate/container_create.go @@ -17,7 +17,7 @@ import ( "github.com/containers/podman/v4/pkg/specgen" "github.com/containers/podman/v4/pkg/specgenutil" "github.com/containers/podman/v4/pkg/util" - spec "github.com/opencontainers/runtime-spec/specs-go" + "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/selinux/go-selinux/label" "github.com/sirupsen/logrus" ) @@ -25,7 +25,7 @@ import ( // MakeContainer creates a container based on the SpecGenerator. // Returns the created, container and any warnings resulting from creating the // container, or an error. -func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGenerator, clone bool, c *libpod.Container) (*spec.Spec, *specgen.SpecGenerator, []libpod.CtrCreateOption, error) { +func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGenerator, clone bool, c *libpod.Container) (*specs.Spec, *specgen.SpecGenerator, []libpod.CtrCreateOption, error) { rtc, err := rt.GetConfigNoCopy() if err != nil { return nil, nil, nil, err @@ -41,6 +41,24 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener s.OOMScoreAdj = rtc.Containers.OOMScoreAdj } + if len(rtc.Containers.CgroupConf) > 0 { + if s.ResourceLimits == nil { + s.ResourceLimits = &specs.LinuxResources{} + } + if s.ResourceLimits.Unified == nil { + s.ResourceLimits.Unified = make(map[string]string) + } + for _, cgroupConf := range rtc.Containers.CgroupConf { + cgr := strings.SplitN(cgroupConf, "=", 2) + if len(cgr) != 2 { + return nil, nil, nil, fmt.Errorf("CgroupConf %q from containers.conf invalid, must be name=value", cgr) + } + if _, ok := s.ResourceLimits.Unified[cgr[0]]; !ok { + s.ResourceLimits.Unified[cgr[0]] = cgr[1] + } + } + } + // If joining a pod, retrieve the pod for use, and its infra container var pod *libpod.Pod var infra *libpod.Container @@ -59,7 +77,7 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener options := []libpod.CtrCreateOption{} compatibleOptions := &libpod.InfraInherit{} - var infraSpec *spec.Spec + var infraSpec *specs.Spec if infra != nil { options, infraSpec, compatibleOptions, err = Inherit(*infra, s, rt) if err != nil { @@ -261,7 +279,7 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener } return runtimeSpec, s, options, err } -func ExecuteCreate(ctx context.Context, rt *libpod.Runtime, runtimeSpec *spec.Spec, s *specgen.SpecGenerator, infra bool, options ...libpod.CtrCreateOption) (*libpod.Container, error) { +func ExecuteCreate(ctx context.Context, rt *libpod.Runtime, runtimeSpec *specs.Spec, s *specgen.SpecGenerator, infra bool, options ...libpod.CtrCreateOption) (*libpod.Container, error) { ctr, err := rt.NewContainer(ctx, runtimeSpec, s, infra, options...) if err != nil { return ctr, err @@ -274,7 +292,7 @@ func ExecuteCreate(ctx context.Context, rt *libpod.Runtime, runtimeSpec *spec.Sp // The CDI devices are added to the list of CtrCreateOptions. // Note that this may modify the device list associated with the spec, which should then only contain non-CDI devices. func ExtractCDIDevices(s *specgen.SpecGenerator) []libpod.CtrCreateOption { - devs := make([]spec.LinuxDevice, 0, len(s.Devices)) + devs := make([]specs.LinuxDevice, 0, len(s.Devices)) var cdiDevs []string var options []libpod.CtrCreateOption @@ -606,7 +624,7 @@ func createContainerOptions(rt *libpod.Runtime, s *specgen.SpecGenerator, pod *l return options, nil } -func Inherit(infra libpod.Container, s *specgen.SpecGenerator, rt *libpod.Runtime) (opts []libpod.CtrCreateOption, infraS *spec.Spec, compat *libpod.InfraInherit, err error) { +func Inherit(infra libpod.Container, s *specgen.SpecGenerator, rt *libpod.Runtime) (opts []libpod.CtrCreateOption, infraS *specs.Spec, compat *libpod.InfraInherit, err error) { inheritSpec := &specgen.SpecGenerator{} _, compatibleOptions, err := ConfigToSpec(rt, inheritSpec, infra.ID()) if err != nil { diff --git a/test/e2e/containers_conf_test.go b/test/e2e/containers_conf_test.go index 9359f21808..b45e78d0a9 100644 --- a/test/e2e/containers_conf_test.go +++ b/test/e2e/containers_conf_test.go @@ -41,6 +41,7 @@ var _ = Describe("Verify podman containers.conf usage", func() { f := CurrentGinkgoTestDescription() processTestResult(f) os.Unsetenv("CONTAINERS_CONF") + os.Unsetenv("CONTAINERS_CONF_OVERRIDE") }) It("limits test", func() { @@ -102,6 +103,36 @@ var _ = Describe("Verify podman containers.conf usage", func() { }) + It("cgroup_conf in containers.conf", func() { + if isCgroupsV1() { + Skip("Setting cgroup_confs not supported on cgroupv1") + } + // FIXME: Needs crun-1.8.2-2 to allow this with --cgroup-manager=cgroupfs, once this is available remove the skip below. + SkipIfRootless("--cgroup-manager=cgoupfs and --cgroup-conf not supported in rootless mode with crun") + conffile := filepath.Join(podmanTest.TempDir, "container.conf") + tempdir, err = CreateTempDirInTempDir() + Expect(err).ToNot(HaveOccurred()) + + err := os.WriteFile(conffile, []byte("[containers]\ncgroup_conf = [\"pids.max=1234\",]\n"), 0755) + Expect(err).ToNot(HaveOccurred()) + + os.Setenv("CONTAINERS_CONF_OVERRIDE", conffile) + if IsRemote() { + podmanTest.RestartRemoteService() + } + + // containers.conf is set to "pids.max=1234" + session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "cat", "/sys/fs/cgroup/pids.max"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(Equal("1234")) + + session = podmanTest.Podman([]string{"run", "--rm", "--cgroup-conf", "pids.max=400", ALPINE, "cat", "/sys/fs/cgroup/pids.max"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(Equal("400")) + }) + It("having additional env", func() { // containers.conf default env includes foo session := podmanTest.Podman([]string{"run", ALPINE, "printenv"})