From 88b440c1e91010d42874956cff756eff54b85bfc Mon Sep 17 00:00:00 2001 From: Vikas Goel Date: Fri, 19 Jan 2024 23:24:24 -0800 Subject: [PATCH] New global option interface_name in containers.conf Add a new containers.conf attribute to define how to set interface name inside containers. Relates to: containers/podman#21313 Signed-off-by: Vikas Goel --- docs/containers.conf.5.md | 7 ++++ pkg/config/config.go | 11 +++++ pkg/config/config_local.go | 8 ++++ pkg/config/config_local_test.go | 45 +++++++++++++++++++++ pkg/config/config_remote.go | 4 ++ pkg/config/config_test.go | 1 + pkg/config/containers.conf | 7 ++++ pkg/config/testdata/containers_comment.conf | 3 ++ pkg/config/testdata/containers_default.conf | 3 ++ 9 files changed, 89 insertions(+) diff --git a/docs/containers.conf.5.md b/docs/containers.conf.5.md index 589ea7a57..43a424420 100644 --- a/docs/containers.conf.5.md +++ b/docs/containers.conf.5.md @@ -227,6 +227,13 @@ Path to the container-init binary, which forwards signals and reaps processes within containers. Note that the container-init binary will only be used when the `--init` for podman-create and podman-run is set. +**interface_name**="" + +Default way to set interface names inside containers. Defaults to legacy pattern +of ethX, where X is an integer, when left undefined. +Options are: + `device` Uses the network_interface name from the network config as interface name. Falls back to the ethX pattern if the network_interface is not set. + **ipcns**="shareable" Default way to to create a IPC namespace for the container. diff --git a/pkg/config/config.go b/pkg/config/config.go index 2e352db44..f1f5e51ff 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -154,6 +154,13 @@ type ContainersConfig struct { // Deprecated: Do not use this field directly use conf.FindInitBinary() instead. InitPath string `toml:"init_path,omitempty"` + // InterfaceName tells container runtimes how to set interface names + // inside containers. + // The only valid value at the moment is "device" that indicates the + // interface name should be set as the network_interface name from + // the network config. + InterfaceName string `toml:"interface_name,omitempty"` + // IPCNS way to create a ipc namespace for the container IPCNS string `toml:"ipcns,omitempty"` @@ -814,6 +821,10 @@ func (c *ContainersConfig) Validate() error { return err } + if err := c.validateInterfaceName(); err != nil { + return err + } + if err := c.validateTZ(); err != nil { return err } diff --git a/pkg/config/config_local.go b/pkg/config/config_local.go index aac90b299..e9826d62c 100644 --- a/pkg/config/config_local.go +++ b/pkg/config/config_local.go @@ -42,6 +42,14 @@ func (c *ContainersConfig) validateDevices() error { return nil } +func (c *ContainersConfig) validateInterfaceName() error { + if c.InterfaceName == "device" || c.InterfaceName == "" { + return nil + } + + return fmt.Errorf("invalid interface_name option %s", c.InterfaceName) +} + func (c *ContainersConfig) validateUlimits() error { for _, u := range c.DefaultUlimits.Get() { ul, err := units.ParseUlimit(u) diff --git a/pkg/config/config_local_test.go b/pkg/config/config_local_test.go index 4da9a1f4f..efc007c21 100644 --- a/pkg/config/config_local_test.go +++ b/pkg/config/config_local_test.go @@ -234,6 +234,51 @@ var _ = Describe("Config Local", func() { gomega.Expect(err).NotTo(gomega.BeNil()) }) + It("should fail on invalid interface_name", func() { + defConf, err := defaultConfig() + gomega.Expect(err).To(gomega.BeNil()) + gomega.Expect(defConf).NotTo(gomega.BeNil()) + + // Given + defConf.Containers.InterfaceName = "random" + + // When + err = defConf.Containers.Validate() + + // Then + gomega.Expect(err).NotTo(gomega.BeNil()) + }) + + It("should succeed on good interface_name", func() { + defConf, err := defaultConfig() + gomega.Expect(err).To(gomega.BeNil()) + gomega.Expect(defConf).NotTo(gomega.BeNil()) + + // Given + defConf.Containers.InterfaceName = "device" + + // When + err = defConf.Containers.Validate() + + // Then + gomega.Expect(err).To(gomega.BeNil()) + }) + + It("should succeed on default interface_name", func() { + defConf, err := defaultConfig() + gomega.Expect(err).To(gomega.BeNil()) + gomega.Expect(defConf).NotTo(gomega.BeNil()) + + // Given + defConf.Containers.InterfaceName = "" + + // When + err = defConf.Containers.Validate() + + // Then + gomega.Expect(err).To(gomega.BeNil()) + }) + It("should fail on bad timezone", func() { defConf, err := defaultConfig() gomega.Expect(err).To(gomega.BeNil()) diff --git a/pkg/config/config_remote.go b/pkg/config/config_remote.go index 7ad7bc233..f7b3d1a02 100644 --- a/pkg/config/config_remote.go +++ b/pkg/config/config_remote.go @@ -20,6 +20,10 @@ func (c *ContainersConfig) validateDevices() error { return nil } +func (c *ContainersConfig) validateInterfaceName() error { + return nil +} + func (c *ContainersConfig) validateUlimits() error { return nil } diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index 756910e3f..05cfcd399 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -28,6 +28,7 @@ var _ = Describe("Config", func() { gomega.Expect(err).To(gomega.BeNil()) gomega.Expect(defaultConfig.Containers.ApparmorProfile).To(gomega.Equal(apparmor.Profile)) gomega.Expect(defaultConfig.Containers.BaseHostsFile).To(gomega.Equal("")) + gomega.Expect(defaultConfig.Containers.InterfaceName).To(gomega.Equal("")) gomega.Expect(defaultConfig.Containers.PidsLimit).To(gomega.BeEquivalentTo(2048)) gomega.Expect(defaultConfig.Containers.Privileged).To(gomega.BeFalse()) gomega.Expect(defaultConfig.Containers.ReadOnly).To(gomega.BeFalse()) diff --git a/pkg/config/containers.conf b/pkg/config/containers.conf index 7a21f69ff..73337012c 100644 --- a/pkg/config/containers.conf +++ b/pkg/config/containers.conf @@ -164,6 +164,13 @@ default_sysctls = [ # #ipcns = "shareable" +# Default way to set an interface name inside container. Defaults to legacy +# pattern of ethX, where X is a integer, when left undefined. +# Options are: +# "device" Uses the network_interface name from the network config as interface name. +# Falls back to the ethX pattern if the network_interface is not set. +#interface_name = "" + # keyring tells the container engine whether to create # a kernel keyring for use within the container. # diff --git a/pkg/config/testdata/containers_comment.conf b/pkg/config/testdata/containers_comment.conf index 3433dedca..d4c4f3c35 100644 --- a/pkg/config/testdata/containers_comment.conf +++ b/pkg/config/testdata/containers_comment.conf @@ -86,6 +86,9 @@ # Run an init inside the container that forwards signals and reaps processes. # init = false +# Pattern of interface name inside container. +# interface_name = "" + # The network table containers settings pertaining to the management of # CNI plugins. diff --git a/pkg/config/testdata/containers_default.conf b/pkg/config/testdata/containers_default.conf index 8b3cc1e58..464377211 100644 --- a/pkg/config/testdata/containers_default.conf +++ b/pkg/config/testdata/containers_default.conf @@ -66,6 +66,9 @@ env = [ # Run an init inside the container that forwards signals and reaps processes. init = false +# Set interface name inside container in legacy way, ethX. +interface_name = "" + host_containers_internal_ip = "1.2.3.4" # proxy environment variables are passed into the container