Skip to content

Commit

Permalink
run,create: add support for --env-merge for preprocessing vars
Browse files Browse the repository at this point in the history
Allow end users to preprocess default environment variables before
injecting them into container using `--env-merge`

Usage
```
podman run -it --rm --env-merge some=${some}-edit --env-merge
some2=${some2}-edit2 myimage sh
```

Closes: containers#15288

Signed-off-by: Aditya R <arajan@redhat.com>
  • Loading branch information
flouthoc committed Aug 24, 2022
1 parent 2538bea commit db465c7
Show file tree
Hide file tree
Showing 13 changed files with 51 additions and 0 deletions.
8 changes: 8 additions & 0 deletions cmd/podman/common/create.go
Expand Up @@ -124,6 +124,14 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
"This is a Docker specific option and is a NOOP",
)

envMergeFlagName := "env-merge"
createFlags.StringArrayVar(
&cf.EnvMerge,
envMergeFlagName, []string{},
"Preprocess environment variables from image before injecting them into the container",
)
_ = cmd.RegisterFlagCompletionFunc(envMergeFlagName, completion.AutocompleteNone)

envFlagName := "env"
createFlags.StringArrayP(
envFlagName, "e", Env(),
Expand Down
5 changes: 5 additions & 0 deletions docs/source/markdown/options/env-merge.md
@@ -0,0 +1,5 @@
#### **--env-merge**=*env*

Preprocess default environment variables for the containers. For example
if image contains environment variable `hello=world` user can preprocess
it using `--env-merge hello=${hello}-some` so new value will be `hello=world-some`.
2 changes: 2 additions & 0 deletions docs/source/markdown/podman-create.1.md.in
Expand Up @@ -208,6 +208,8 @@ Read in a line delimited file of environment variables. See **Environment** note

@@option env-host

@@option env-merge

@@option expose

#### **--gidmap**=*container_gid:host_gid:amount*
Expand Down
2 changes: 2 additions & 0 deletions docs/source/markdown/podman-run.1.md.in
Expand Up @@ -243,6 +243,8 @@ Read in a line delimited file of environment variables. See **Environment** note

@@option env-host

@@option env-merge

@@option expose

#### **--gidmap**=*container_gid:host_gid:amount*
Expand Down
1 change: 1 addition & 0 deletions go.mod
Expand Up @@ -49,6 +49,7 @@ require (
github.com/opencontainers/runtime-spec v1.0.3-0.20211214071223-8958f93039ab
github.com/opencontainers/runtime-tools v0.9.1-0.20220714195903-17b3287fafb7
github.com/opencontainers/selinux v1.10.1
github.com/openshift/imagebuilder v1.2.4-0.20220711175835-4151e43600df
github.com/rootless-containers/rootlesskit v1.0.1
github.com/sirupsen/logrus v1.9.0
github.com/spf13/cobra v1.5.0
Expand Down
1 change: 1 addition & 0 deletions pkg/api/handlers/compat/containers_create.go
Expand Up @@ -408,6 +408,7 @@ func cliOpts(cc handlers.CreateContainerConfig, rtc *config.Config) (*entities.C
Systemd: "true", // podman default
TmpFS: parsedTmp,
TTY: cc.Config.Tty,
EnvMerge: cc.EnvMerge,
UnsetEnv: cc.UnsetEnv,
UnsetEnvAll: cc.UnsetEnvAll,
User: cc.Config.User,
Expand Down
1 change: 1 addition & 0 deletions pkg/api/handlers/types.go
Expand Up @@ -127,6 +127,7 @@ type CreateContainerConfig struct {
dockerContainer.Config // desired container configuration
HostConfig dockerContainer.HostConfig // host dependent configuration for container
NetworkingConfig dockerNetwork.NetworkingConfig // network configuration for container
EnvMerge []string // preprocess env variables from image before injecting into containers
UnsetEnv []string // unset specified default environment variables
UnsetEnvAll bool // unset all default environment variables
}
Expand Down
1 change: 1 addition & 0 deletions pkg/domain/entities/pods.go
Expand Up @@ -263,6 +263,7 @@ type ContainerCreateOptions struct {
TTY bool
Timezone string
Umask string
EnvMerge []string
UnsetEnv []string
UnsetEnvAll bool
UIDMap []string
Expand Down
12 changes: 12 additions & 0 deletions pkg/specgen/generate/container.go
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/containers/podman/v4/pkg/signal"
"github.com/containers/podman/v4/pkg/specgen"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/openshift/imagebuilder"
"github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
)
Expand Down Expand Up @@ -131,6 +132,17 @@ func CompleteSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerat
defaultEnvs = envLib.Join(envLib.DefaultEnvVariables(), envLib.Join(defaultEnvs, envs))
}

for _, e := range s.EnvMerge {
processedWord, err := imagebuilder.ProcessWord(e, envLib.Slice(defaultEnvs))
if err != nil {
return nil, fmt.Errorf("unable to process variables for --env-merge %s: %w", e, err)
}
splitWord := strings.Split(processedWord, "=")
if _, ok := defaultEnvs[splitWord[0]]; ok {
defaultEnvs[splitWord[0]] = splitWord[1]
}
}

for _, e := range s.UnsetEnv {
delete(defaultEnvs, e)
}
Expand Down
3 changes: 3 additions & 0 deletions pkg/specgen/specgen.go
Expand Up @@ -204,6 +204,9 @@ type ContainerBasicConfig struct {
// The execution domain system allows Linux to provide limited support
// for binaries compiled under other UNIX-like operating systems.
Personality *spec.LinuxPersonality `json:"personality,omitempty"`
// EnvMerge takes the specified environment variables from image and preprocess them before injecting them into the
// container.
EnvMerge []string `json:"envmerge,omitempty"`
// UnsetEnv unsets the specified default environment variables from the image or from buildin or containers.conf
// Optional.
UnsetEnv []string `json:"unsetenv,omitempty"`
Expand Down
3 changes: 3 additions & 0 deletions pkg/specgenutil/specgen.go
Expand Up @@ -839,6 +839,9 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions
if !s.Volatile {
s.Volatile = c.Rm
}
if len(s.EnvMerge) == 0 || len(c.EnvMerge) != 0 {
s.EnvMerge = c.EnvMerge
}
if len(s.UnsetEnv) == 0 || len(c.UnsetEnv) != 0 {
s.UnsetEnv = c.UnsetEnv
}
Expand Down
11 changes: 11 additions & 0 deletions test/e2e/run_env_test.go
Expand Up @@ -82,6 +82,17 @@ var _ = Describe("Podman run", func() {
Expect(session.OutputToString()).To(ContainSubstring("HOSTNAME"))
})

It("podman run with --env-merge", func() {
dockerfile := `FROM quay.io/libpod/alpine:latest
ENV hello=world
`
podmanTest.BuildImage(dockerfile, "test", "false")
session := podmanTest.Podman([]string{"run", "--rm", "--env-merge", "hello=${hello}-earth", "test", "echo $hello"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(session.OutputToString()).To(ContainSubstring("world-earth"))
})

It("podman run --env-host environment test", func() {
env := append(os.Environ(), "FOO=BAR")
session := podmanTest.PodmanAsUser([]string{"run", "--rm", "--env-host", ALPINE, "/bin/printenv", "FOO"}, 0, 0, "", env)
Expand Down
1 change: 1 addition & 0 deletions vendor/modules.txt
Expand Up @@ -620,6 +620,7 @@ github.com/opencontainers/selinux/go-selinux/label
github.com/opencontainers/selinux/pkg/pwalk
github.com/opencontainers/selinux/pkg/pwalkdir
# github.com/openshift/imagebuilder v1.2.4-0.20220711175835-4151e43600df
## explicit
github.com/openshift/imagebuilder
github.com/openshift/imagebuilder/dockerfile/command
github.com/openshift/imagebuilder/dockerfile/parser
Expand Down

0 comments on commit db465c7

Please sign in to comment.