diff --git a/pkg/specgen/container_validate.go b/pkg/specgen/container_validate.go index 37bb5c0147..d4311a91c9 100644 --- a/pkg/specgen/container_validate.go +++ b/pkg/specgen/container_validate.go @@ -7,7 +7,6 @@ import ( "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/libpod/define" - "github.com/containers/podman/v4/pkg/rootless" ) var ( @@ -150,15 +149,6 @@ func (s *SpecGenerator) Validate() error { return err } - // Set defaults if network info is not provided - // when we are rootless we default to slirp4netns - if s.NetNS.IsPrivate() || s.NetNS.IsDefault() { - if rootless.IsRootless() { - s.NetNS.NSMode = Slirp - } else { - s.NetNS.NSMode = Bridge - } - } if err := validateNetNS(&s.NetNS); err != nil { return err } diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go index 65143ca641..648dd17c35 100644 --- a/pkg/specgen/generate/container_create.go +++ b/pkg/specgen/generate/container_create.go @@ -11,9 +11,12 @@ import ( cdi "github.com/container-orchestrated-devices/container-device-interface/pkg/cdi" "github.com/containers/common/libimage" + "github.com/containers/common/libnetwork/pasta" + "github.com/containers/common/libnetwork/slirp4netns" "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/specgenutil" "github.com/containers/podman/v4/pkg/util" @@ -184,6 +187,30 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener // ok, we are incorrectly setting the pod as the hostname, let's undo that before validation s.Hostname = "" } + + // Set defaults if network info is not provided + if s.NetNS.IsPrivate() || s.NetNS.IsDefault() { + if rootless.IsRootless() { + // when we are rootless we default to default_rootless_network_cmd from containers.conf + conf, err := rt.GetConfigNoCopy() + if err != nil { + return nil, nil, nil, err + } + switch conf.Network.DefaultRootlessNetworkCmd { + case slirp4netns.BinaryName, "": + s.NetNS.NSMode = specgen.Slirp + case pasta.BinaryName: + s.NetNS.NSMode = specgen.Pasta + default: + return nil, nil, nil, fmt.Errorf("invalid default_rootless_network_cmd option %q", + conf.Network.DefaultRootlessNetworkCmd) + } + } else { + // as root default to bridge + s.NetNS.NSMode = specgen.Bridge + } + } + if err := s.Validate(); err != nil { return nil, nil, nil, fmt.Errorf("invalid config provided: %w", err) } diff --git a/pkg/specgen/generate/namespaces.go b/pkg/specgen/generate/namespaces.go index 4a3d451b94..390aa2364b 100644 --- a/pkg/specgen/generate/namespaces.go +++ b/pkg/specgen/generate/namespaces.go @@ -294,10 +294,6 @@ func namespaceOptions(s *specgen.SpecGenerator, rt *libpod.Runtime, pod *libpod. } 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: diff --git a/test/e2e/containers_conf_test.go b/test/e2e/containers_conf_test.go index 86f3ec1ce0..0eed5efe87 100644 --- a/test/e2e/containers_conf_test.go +++ b/test/e2e/containers_conf_test.go @@ -657,4 +657,35 @@ var _ = Describe("Verify podman containers.conf usage", func() { Expect(result).Should(Exit(0)) Expect(result.OutputToString()).To(ContainSubstring("Path to the OCI-compatible binary used to run containers. (default \"testruntime\")")) }) + + It("podman default_rootless_network_cmd", func() { + SkipIfNotRootless("default_rootless_network_cmd is only used rootless") + + for _, mode := range []string{"pasta", "slirp4netns", "invalid"} { + conffile := filepath.Join(podmanTest.TempDir, "container.conf") + content := "[network]\ndefault_rootless_network_cmd=\"" + mode + "\"\n" + err := os.WriteFile(conffile, []byte(content), 0755) + Expect(err).ToNot(HaveOccurred()) + + os.Setenv("CONTAINERS_CONF_OVERRIDE", conffile) + if IsRemote() { + podmanTest.RestartRemoteService() + } + + podman := podmanTest.Podman([]string{"create", "--name", mode, ALPINE, "ip", "addr"}) + podman.WaitWithDefaultTimeout() + + if mode == "invalid" { + Expect(podman).Should(Exit(125)) + Expect(podman.ErrorToString()).Should(ContainSubstring("invalid default_rootless_network_cmd option \"invalid\"")) + continue + } + Expect(podman).Should(Exit(0)) + + inspect := podmanTest.Podman([]string{"inspect", "--format", "{{.HostConfig.NetworkMode}}", mode}) + inspect.WaitWithDefaultTimeout() + Expect(inspect).Should(Exit(0)) + Expect(inspect.OutputToString()).Should(Equal(mode)) + } + }) })