mirror of
https://github.com/containers/podman.git
synced 2025-05-23 10:07:33 +08:00
podman: split env variables in env and overrides
There are three different priorities for applying env variables: 1) environment/config file environment variables 2) image's config 3) user overrides (--env) The third kind are known to the client, while the default config and image's config is handled by the backend. Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com> Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:

committed by
Daniel J Walsh

parent
1d3cdf9a46
commit
99bdafba99
@ -156,8 +156,7 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet {
|
|||||||
createFlags.String("entrypoint", "",
|
createFlags.String("entrypoint", "",
|
||||||
"Overwrite the default ENTRYPOINT of the image",
|
"Overwrite the default ENTRYPOINT of the image",
|
||||||
)
|
)
|
||||||
createFlags.StringArrayVarP(
|
createFlags.StringArrayP(
|
||||||
&cf.env,
|
|
||||||
"env", "e", containerConfig.Env(),
|
"env", "e", containerConfig.Env(),
|
||||||
"Set environment variables in container",
|
"Set environment variables in container",
|
||||||
)
|
)
|
||||||
|
@ -32,7 +32,7 @@ type ContainerCLIOpts struct {
|
|||||||
DeviceWriteBPs []string
|
DeviceWriteBPs []string
|
||||||
DeviceWriteIOPs []string
|
DeviceWriteIOPs []string
|
||||||
Entrypoint *string
|
Entrypoint *string
|
||||||
env []string
|
Env []string
|
||||||
EnvHost bool
|
EnvHost bool
|
||||||
EnvFile []string
|
EnvFile []string
|
||||||
Expose []string
|
Expose []string
|
||||||
|
@ -335,15 +335,12 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string
|
|||||||
env = envLib.Join(env, fileEnv)
|
env = envLib.Join(env, fileEnv)
|
||||||
}
|
}
|
||||||
|
|
||||||
// env overrides any previous variables
|
parsedEnv, err := envLib.ParseSlice(c.Env)
|
||||||
if cmdLineEnv := c.env; len(cmdLineEnv) > 0 {
|
if err != nil {
|
||||||
parsedEnv, err := envLib.ParseSlice(cmdLineEnv)
|
return err
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
env = envLib.Join(env, parsedEnv)
|
|
||||||
}
|
}
|
||||||
s.Env = env
|
|
||||||
|
s.Env = envLib.Join(env, parsedEnv)
|
||||||
|
|
||||||
// LABEL VARIABLES
|
// LABEL VARIABLES
|
||||||
labels, err := parse.GetAllLabels(c.LabelFile, c.Label)
|
labels, err := parse.GetAllLabels(c.LabelFile, c.Label)
|
||||||
|
@ -55,6 +55,11 @@ func createFlags(flags *pflag.FlagSet) {
|
|||||||
flags.AddFlagSet(common.GetCreateFlags(&cliVals))
|
flags.AddFlagSet(common.GetCreateFlags(&cliVals))
|
||||||
flags.AddFlagSet(common.GetNetFlags())
|
flags.AddFlagSet(common.GetNetFlags())
|
||||||
flags.SetNormalizeFunc(common.AliasFlags)
|
flags.SetNormalizeFunc(common.AliasFlags)
|
||||||
|
if registry.IsRemote() {
|
||||||
|
_ = flags.MarkHidden("authfile")
|
||||||
|
_ = flags.MarkHidden("env-host")
|
||||||
|
_ = flags.MarkHidden("http-proxy")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -170,6 +175,13 @@ func createInit(c *cobra.Command) error {
|
|||||||
val := c.Flag("entrypoint").Value.String()
|
val := c.Flag("entrypoint").Value.String()
|
||||||
cliVals.Entrypoint = &val
|
cliVals.Entrypoint = &val
|
||||||
}
|
}
|
||||||
|
if c.Flags().Changed("env") {
|
||||||
|
env, err := c.Flags().GetStringArray("env")
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "retrieve env flag")
|
||||||
|
}
|
||||||
|
cliVals.Env = env
|
||||||
|
}
|
||||||
|
|
||||||
// Docker-compatibility: the "-h" flag for run/create is reserved for
|
// Docker-compatibility: the "-h" flag for run/create is reserved for
|
||||||
// the hostname (see https://github.com/containers/libpod/issues/1367).
|
// the hostname (see https://github.com/containers/libpod/issues/1367).
|
||||||
|
@ -60,6 +60,8 @@ func runFlags(flags *pflag.FlagSet) {
|
|||||||
flags.BoolVar(&runRmi, "rmi", false, "Remove container image unless used by other containers")
|
flags.BoolVar(&runRmi, "rmi", false, "Remove container image unless used by other containers")
|
||||||
if registry.IsRemote() {
|
if registry.IsRemote() {
|
||||||
_ = flags.MarkHidden("authfile")
|
_ = flags.MarkHidden("authfile")
|
||||||
|
_ = flags.MarkHidden("env-host")
|
||||||
|
_ = flags.MarkHidden("http-proxy")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -278,7 +278,7 @@ See [**Environment**](#environment) note below for precedence and examples.
|
|||||||
|
|
||||||
**--env-host**=*true|false*
|
**--env-host**=*true|false*
|
||||||
|
|
||||||
Use host environment inside of the container. See **Environment** note below for precedence.
|
Use host environment inside of the container. See **Environment** note below for precedence. (Not available for remote commands)
|
||||||
|
|
||||||
**--env-file**=*file*
|
**--env-file**=*file*
|
||||||
|
|
||||||
@ -347,7 +347,7 @@ the container should not use any proxy. Proxy environment variables specified
|
|||||||
for the container in any other way will override the values that would have
|
for the container in any other way will override the values that would have
|
||||||
been passed through from the host. (Other ways to specify the proxy for the
|
been passed through from the host. (Other ways to specify the proxy for the
|
||||||
container include passing the values with the `--env` flag, or hard coding the
|
container include passing the values with the `--env` flag, or hard coding the
|
||||||
proxy environment at container build time.)
|
proxy environment at container build time.) (Not available for remote commands)
|
||||||
|
|
||||||
For example, to disable passing these environment variables from host to
|
For example, to disable passing these environment variables from host to
|
||||||
container:
|
container:
|
||||||
|
@ -294,7 +294,7 @@ See [**Environment**](#environment) note below for precedence and examples.
|
|||||||
|
|
||||||
**--env-host**=**true**|**false**
|
**--env-host**=**true**|**false**
|
||||||
|
|
||||||
Use host environment inside of the container. See **Environment** note below for precedence.
|
Use host environment inside of the container. See **Environment** note below for precedence. (Not available for remote commands)
|
||||||
|
|
||||||
**--env-file**=*file*
|
**--env-file**=*file*
|
||||||
|
|
||||||
@ -363,7 +363,7 @@ the container should not use any proxy. Proxy environment variables specified
|
|||||||
for the container in any other way will override the values that would have
|
for the container in any other way will override the values that would have
|
||||||
been passed through from the host. (Other ways to specify the proxy for the
|
been passed through from the host. (Other ways to specify the proxy for the
|
||||||
container include passing the values with the **--env** flag, or hard coding the
|
container include passing the values with the **--env** flag, or hard coding the
|
||||||
proxy environment at container build time.)
|
proxy environment at container build time.) (Not available for remote commands)
|
||||||
|
|
||||||
Defaults to **true**.
|
Defaults to **true**.
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
envLib "github.com/containers/libpod/pkg/env"
|
envLib "github.com/containers/libpod/pkg/env"
|
||||||
"github.com/containers/libpod/pkg/signal"
|
"github.com/containers/libpod/pkg/signal"
|
||||||
"github.com/containers/libpod/pkg/specgen"
|
"github.com/containers/libpod/pkg/specgen"
|
||||||
|
"github.com/pkg/errors"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -48,24 +49,28 @@ func CompleteSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerat
|
|||||||
s.StopSignal = &sig
|
s.StopSignal = &sig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rtc, err := r.GetConfig()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Get Default Environment
|
||||||
|
defaultEnvs, err := envLib.ParseSlice(rtc.Containers.Env)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "Env fields in containers.conf failed to parse")
|
||||||
|
}
|
||||||
|
|
||||||
// Image envs from the image if they don't exist
|
// Image envs from the image if they don't exist
|
||||||
// already
|
// already, overriding the default environments
|
||||||
env, err := newImage.Env(ctx)
|
imageEnvs, err := newImage.Env(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(env) > 0 {
|
envs, err := envLib.ParseSlice(imageEnvs)
|
||||||
envs, err := envLib.ParseSlice(env)
|
if err != nil {
|
||||||
if err != nil {
|
return errors.Wrap(err, "Env fields from image failed to parse")
|
||||||
return err
|
|
||||||
}
|
|
||||||
for k, v := range envs {
|
|
||||||
if _, exists := s.Env[k]; !exists {
|
|
||||||
s.Env[v] = k
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
s.Env = envLib.Join(envLib.Join(defaultEnvs, envs), s.Env)
|
||||||
|
|
||||||
labels, err := newImage.Labels(ctx)
|
labels, err := newImage.Labels(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -47,6 +47,7 @@ type ContainerBasicConfig struct {
|
|||||||
// Optional.
|
// Optional.
|
||||||
Env map[string]string `json:"env,omitempty"`
|
Env map[string]string `json:"env,omitempty"`
|
||||||
// Terminal is whether the container will create a PTY.
|
// Terminal is whether the container will create a PTY.
|
||||||
|
// Optional.
|
||||||
Terminal bool `json:"terminal,omitempty"`
|
Terminal bool `json:"terminal,omitempty"`
|
||||||
// Stdin is whether the container will keep its STDIN open.
|
// Stdin is whether the container will keep its STDIN open.
|
||||||
Stdin bool `json:"stdin,omitempty"`
|
Stdin bool `json:"stdin,omitempty"`
|
||||||
|
@ -177,7 +177,6 @@ var _ = Describe("Podman build", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("podman Test PATH in built image", func() {
|
It("podman Test PATH in built image", func() {
|
||||||
Skip(v2fail) // Run error - we don't set data from the image (i.e., PATH) yet
|
|
||||||
path := "/tmp:/bin:/usr/bin:/usr/sbin"
|
path := "/tmp:/bin:/usr/bin:/usr/sbin"
|
||||||
session := podmanTest.PodmanNoCache([]string{
|
session := podmanTest.PodmanNoCache([]string{
|
||||||
"build", "-f", "build/basicalpine/Containerfile.path", "-t", "test-path",
|
"build", "-f", "build/basicalpine/Containerfile.path", "-t", "test-path",
|
||||||
|
@ -91,7 +91,8 @@ var _ = Describe("Podman run", func() {
|
|||||||
Expect(match).Should(BeTrue())
|
Expect(match).Should(BeTrue())
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman run --host-env environment test", func() {
|
It("podman run --env-host environment test", func() {
|
||||||
|
SkipIfRemote()
|
||||||
env := append(os.Environ(), "FOO=BAR")
|
env := append(os.Environ(), "FOO=BAR")
|
||||||
session := podmanTest.PodmanAsUser([]string{"run", "--rm", "--env-host", ALPINE, "/bin/printenv", "FOO"}, 0, 0, "", env)
|
session := podmanTest.PodmanAsUser([]string{"run", "--rm", "--env-host", ALPINE, "/bin/printenv", "FOO"}, 0, 0, "", env)
|
||||||
|
|
||||||
@ -109,6 +110,7 @@ var _ = Describe("Podman run", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("podman run --http-proxy test", func() {
|
It("podman run --http-proxy test", func() {
|
||||||
|
SkipIfRemote()
|
||||||
os.Setenv("http_proxy", "1.2.3.4")
|
os.Setenv("http_proxy", "1.2.3.4")
|
||||||
session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "printenv", "http_proxy"})
|
session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "printenv", "http_proxy"})
|
||||||
session.WaitWithDefaultTimeout()
|
session.WaitWithDefaultTimeout()
|
||||||
|
Reference in New Issue
Block a user