From f64a1a1cc886f9f81673147f4be86f85a750b1e3 Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Wed, 28 Jun 2023 16:37:45 +0200 Subject: [PATCH] rootless: use default_rootless_network_cmd config Make sure we use the config field to know if we should use pasta or slirp4netns as default. While at it fix broken code which sets the default at two different places, also do not set in Validate() as this should not modify the specgen IMO, so set it directly before that. Signed-off-by: Paul Holzinger --- pkg/specgen/container_validate.go | 10 -------- pkg/specgen/generate/container_create.go | 27 +++++++++++++++++++++ pkg/specgen/generate/namespaces.go | 4 --- test/e2e/containers_conf_test.go | 31 ++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 14 deletions(-) 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)) + } + }) })