diff --git a/common/docs/containers.conf.5.md b/common/docs/containers.conf.5.md index 52308be2b0..57dbf3969f 100644 --- a/common/docs/containers.conf.5.md +++ b/common/docs/containers.conf.5.md @@ -226,6 +226,14 @@ overwriting values specified on the command line when the container was created. Pass all host environment variables into the container. +**env_merge**=[] + +Preprocess default environment variables for the container. +Works the same as the **--env-merge** command line option. +The value of existing variables in the image will be used for substitution. + +Example: `env_merge=["PATH=${PATH}:/custom/bin"]` + **host_containers_internal_ip**="" Set the IP address the container should expect to connect to the host. The IP diff --git a/common/pkg/config/config.go b/common/pkg/config/config.go index e53dcce63b..cf79cec7f4 100644 --- a/common/pkg/config/config.go +++ b/common/pkg/config/config.go @@ -142,6 +142,9 @@ type ContainersConfig struct { // EnvHost Pass all host environment variables into the container. EnvHost bool `toml:"env_host,omitempty"` + // EnvMerge preprocess the environment variables list for the container. + EnvMerge configfile.Slice `toml:"env_merge,omitempty"` + // HostContainersInternalIP is used to set a specific host.containers.internal ip. HostContainersInternalIP string `toml:"host_containers_internal_ip,omitempty"` diff --git a/common/pkg/config/config_local_test.go b/common/pkg/config/config_local_test.go index 833a1b60de..a031fd8d2f 100644 --- a/common/pkg/config/config_local_test.go +++ b/common/pkg/config/config_local_test.go @@ -664,4 +664,15 @@ var _ = Describe("Config Local", func() { // Then gomega.Expect(err).To(gomega.HaveOccurred()) }) + It("should parse env_merge from config file", func() { + // Given + config, err := newLocked(&Options{}, testConfigPath("")) + gomega.Expect(err).ToNot(gomega.HaveOccurred()) + gomega.Expect(config.Containers.EnvMerge.Get()).To(gomega.BeEmpty()) + // When + config2, err := newLocked(&Options{}, testConfigPath("testdata/containers_default.conf")) + // Then + gomega.Expect(err).ToNot(gomega.HaveOccurred()) + gomega.Expect(config2.Containers.EnvMerge.Get()).To(gomega.Equal([]string{"FOO=bar"})) + }) }) diff --git a/common/pkg/config/containers.conf b/common/pkg/config/containers.conf index 1725909fc7..03949a1594 100644 --- a/common/pkg/config/containers.conf +++ b/common/pkg/config/containers.conf @@ -137,6 +137,10 @@ default_sysctls = [ # #env_host = false +# Preprocess default environment variables for the container. +# +#env_merge = [] + # Set the IP address the container should expect to connect to the host. The IP # address is used by Podman to automatically add the `host.containers.internal` # and `host.docker.internal` hostnames to the container's `/etc/hosts` file. It diff --git a/common/pkg/config/default.go b/common/pkg/config/default.go index 1fd30e21cf..453c3068ba 100644 --- a/common/pkg/config/default.go +++ b/common/pkg/config/default.go @@ -223,6 +223,7 @@ func defaultConfig() (*Config, error) { EnableLabeling: selinux.GetEnabled(), Env: configfile.NewSlice(defaultContainerEnv), EnvHost: false, + EnvMerge: configfile.Slice{}, HTTPProxy: true, IPCNS: "shareable", Init: false, diff --git a/common/pkg/config/modules_test.go b/common/pkg/config/modules_test.go index 866cbff6bb..33cc7a5d5a 100644 --- a/common/pkg/config/modules_test.go +++ b/common/pkg/config/modules_test.go @@ -57,6 +57,11 @@ var _ = Describe("Config Modules", func() { gomega.Expect(err).ToNot(gomega.HaveOccurred()) gomega.Expect(c.Containers.InitPath).To(gomega.Equal("etc four")) gomega.Expect(c.Containers.Env.Get()).To(gomega.Equal([]string{"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "usr share only"})) + gomega.Expect(c.Containers.EnvMerge.Get()).To(gomega.Equal([]string{ + "PATH=/base/bin:${PATH}", + "PATH=/usr/local/share/bin:${PATH}", + "etc only env_merge conf", + })) gomega.Expect(c.Network.DefaultNetwork).To(gomega.Equal("etc only conf")) gomega.Expect(c.LoadedModules()).To(gomega.HaveLen(3)) // 3 modules are getting loaded! diff --git a/common/pkg/config/testdata/containers_default.conf b/common/pkg/config/testdata/containers_default.conf index b888740308..dd7ca9e9d3 100644 --- a/common/pkg/config/testdata/containers_default.conf +++ b/common/pkg/config/testdata/containers_default.conf @@ -65,6 +65,8 @@ env = [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", ] +env_merge = ["FOO=bar"] + # Run an init inside the container that forwards signals and reaps processes. init = false diff --git a/common/pkg/config/testdata/modules/etc/containers/containers.conf.modules/sub/etc-only.conf b/common/pkg/config/testdata/modules/etc/containers/containers.conf.modules/sub/etc-only.conf index b2e15478a3..c60ccb66a8 100644 --- a/common/pkg/config/testdata/modules/etc/containers/containers.conf.modules/sub/etc-only.conf +++ b/common/pkg/config/testdata/modules/etc/containers/containers.conf.modules/sub/etc-only.conf @@ -1,2 +1,5 @@ [network] default_network="etc only conf" + +[containers] +env_merge=["PATH=/usr/local/share/bin:${PATH}", "etc only env_merge conf", {append=true}] diff --git a/common/pkg/config/testdata/modules/usr/share/containers/containers.conf.modules/sub/share-only.conf b/common/pkg/config/testdata/modules/usr/share/containers/containers.conf.modules/sub/share-only.conf index 6f203a8378..124a443428 100644 --- a/common/pkg/config/testdata/modules/usr/share/containers/containers.conf.modules/sub/share-only.conf +++ b/common/pkg/config/testdata/modules/usr/share/containers/containers.conf.modules/sub/share-only.conf @@ -1,2 +1,3 @@ [containers] env=["usr share only", {append=true}] +env_merge=["PATH=/base/bin:${PATH}"]