Skip to content

Commit

Permalink
Copy host env to container for env/envfile option
Browse files Browse the repository at this point in the history
Add a function to process env/envfile specified by users
and set value for env with no value has been set.

Fixes: containerd#1487

Signed-off-by: bin liu <liubin0329@gmail.com>
  • Loading branch information
liubin committed Nov 21, 2022
1 parent 2ae985b commit 38f4bcb
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 5 deletions.
41 changes: 38 additions & 3 deletions cmd/nerdctl/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -456,21 +456,28 @@ func createContainer(cmd *cobra.Command, ctx context.Context, client *containerd
if err != nil {
return nil, nil, err
}

var envs []string

if envFiles := strutil.DedupeStrSlice(envFile); len(envFiles) > 0 {
env, err := parseEnvVars(envFiles)
envs, err = parseEnvVars(envFiles)
if err != nil {
return nil, nil, err
}
opts = append(opts, oci.WithEnv(env))
}

env, err := cmd.Flags().GetStringArray("env")
if err != nil {
return nil, nil, err
}
if env := strutil.DedupeStrSlice(env); len(env) > 0 {
opts = append(opts, oci.WithEnv(env))
envs = append(envs, env...)
}

if envs, err = withOSEnv(envs); err != nil {
return nil, nil, err
}
opts = append(opts, oci.WithEnv(envs))

if flagI {
if flagD {
Expand Down Expand Up @@ -1145,6 +1152,34 @@ func parseEnvVars(paths []string) ([]string, error) {
return vars, nil
}

func withOSEnv(envs []string) ([]string, error) {
newEnvs := make([]string, len(envs))

// from /~https://github.com/docker/cli/blob/v22.06.0-beta.0/opts/env.go#L18
getEnv := func(val string) (string, error) {
arr := strings.SplitN(val, "=", 2)
if arr[0] == "" {
return "", errors.New("invalid environment variable: " + val)
}
if len(arr) > 1 {
return val, nil
}
if envVal, ok := os.LookupEnv(arr[0]); ok {
return arr[0] + "=" + envVal, nil
}
return val, nil
}
for i := range envs {
env, err := getEnv(envs[i])
if err != nil {
return nil, err
}
newEnvs[i] = env
}

return newEnvs, nil
}

func generateSharingPIDOpts(ctx context.Context, targetCon containerd.Container) ([]oci.SpecOpts, error) {
opts := make([]oci.SpecOpts, 0)

Expand Down
25 changes: 23 additions & 2 deletions cmd/nerdctl/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ func TestRunCIDFile(t *testing.T) {
func TestRunEnvFile(t *testing.T) {
t.Parallel()
base := testutil.NewBase(t)
base.Env = append(os.Environ(), "HOST_ENV=ENV-IN-HOST")

tID := testutil.Identifier(t)
file1, err := os.CreateTemp("", tID)
Expand All @@ -165,23 +166,30 @@ func TestRunEnvFile(t *testing.T) {
path2 := file2.Name()
defer file2.Close()
defer os.Remove(path2)
err = os.WriteFile(path2, []byte("# this is a comment line\nTESTKEY2=TESTVAL2"), 0666)
err = os.WriteFile(path2, []byte("# this is a comment line\nTESTKEY2=TESTVAL2\nHOST_ENV"), 0666)
assert.NilError(base.T, err)

base.Cmd("run", "--rm", "--env-file", path1, "--env-file", path2, testutil.CommonImage, "sh", "-c", "echo -n $TESTKEY1").AssertOutExactly("TESTVAL1")
base.Cmd("run", "--rm", "--env-file", path1, "--env-file", path2, testutil.CommonImage, "sh", "-c", "echo -n $TESTKEY2").AssertOutExactly("TESTVAL2")
base.Cmd("run", "--rm", "--env-file", path1, "--env-file", path2, testutil.CommonImage, "sh", "-c", "echo -n $HOST_ENV").AssertOutExactly("ENV-IN-HOST")
}

func TestRunEnv(t *testing.T) {
t.Parallel()
base := testutil.NewBase(t)
base.Env = append(os.Environ(), "CORGE=corge-value-in-host", "GARPLY=garply-value-in-host")
base.Cmd("run", "--rm",
"--env", "FOO=foo1,foo2",
"--env", "BAR=bar1 bar2",
"--env", "BAZ=",
"--env", "QUX",
"--env", "QUX", // not exported in OS
"--env", "QUUX=quux1",
"--env", "QUUX=quux2",
"--env", "CORGE", // OS exported
"--env", "GRAULT=grault_key=grault_value", // value contains `=` char
"--env", "GARPLY=", // OS exported
"--env", "WALDO=", // not exported in OS

testutil.CommonImage, "env").AssertOutWithFunc(func(stdout string) error {
if !strings.Contains(stdout, "\nFOO=foo1,foo2\n") {
return errors.New("got bad FOO")
Expand All @@ -198,6 +206,19 @@ func TestRunEnv(t *testing.T) {
if !strings.Contains(stdout, "\nQUUX=quux2\n") {
return errors.New("got bad QUUX")
}
if !strings.Contains(stdout, "\nCORGE=corge-value-in-host\n") {
return errors.New("got bad CORGE")
}
if !strings.Contains(stdout, "\nGRAULT=grault_key=grault_value\n") {
return errors.New("got bad GRAULT")
}
if !strings.Contains(stdout, "\nGARPLY=\n") && runtime.GOOS != "windows" {
return errors.New("got bad GARPLY")
}
if !strings.Contains(stdout, "\nWALDO=\n") && runtime.GOOS != "windows" {
return errors.New("got bad WALDO")
}

return nil
})
}
Expand Down

0 comments on commit 38f4bcb

Please sign in to comment.