Skip to content

Commit

Permalink
Merge pull request #1364 from HusterWan/zr/update-env
Browse files Browse the repository at this point in the history
feature: support update and delete env
  • Loading branch information
Wei Fu authored May 21, 2018
2 parents 1e75a11 + 2e5dd73 commit 0d0d697
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 2 deletions.
27 changes: 27 additions & 0 deletions apis/opts/env.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package opts

import (
"fmt"
"strings"
)

// ParseEnv parses the env param of container.
func ParseEnv(env []string) (map[string]string, error) {
results := make(map[string]string)
for _, e := range env {
fields := strings.SplitN(e, "=", 2)
if len(fields) != 2 {
return nil, fmt.Errorf("invalid env %s: env must be in format of key=value", e)
}
results[fields[0]] = fields[1]
}

return results, nil
}

// ValidateEnv verifies the correct of env
func ValidateEnv(map[string]string) error {
// TODO

return nil
}
34 changes: 34 additions & 0 deletions apis/opts/env_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package opts

import (
"reflect"
"testing"
)

func TestParseEnv(t *testing.T) {
type args struct {
env []string
}
tests := []struct {
name string
args args
want map[string]string
wantErr bool
}{
// TODO: Add test cases.
{name: "test1", args: args{env: []string{"foo=bar"}}, want: map[string]string{"foo": "bar"}, wantErr: false},
{name: "test2", args: args{env: []string{"ErrorInfo"}}, want: nil, wantErr: true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := ParseEnv(tt.args.env)
if (err != nil) != tt.wantErr {
t.Errorf("ParseEnv() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("ParseEnv() = %v, want %v", got, tt.want)
}
})
}
}
38 changes: 36 additions & 2 deletions daemon/mgr/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -799,8 +799,42 @@ func (mgr *ContainerManager) Update(ctx context.Context, name string, config *ty
}
}

for _, v := range config.Env {
c.Config.Env = append(c.Config.Env, v)
// Update Env
if len(config.Env) > 0 {
newEnvMap, err := opts.ParseEnv(config.Env)
if err != nil {
return errors.Wrapf(err, "failed to parse new env")
}

oldEnvMap, err := opts.ParseEnv(c.Config.Env)
if err != nil {
return errors.Wrapf(err, "failed to parse old env")
}

for k, v := range newEnvMap {
// key should not be empty
if k == "" {
continue
}

// add or change an env
if v != "" {
oldEnvMap[k] = v
continue
}

// value is empty, we need delete the env
if _, exists := oldEnvMap[k]; exists {
delete(oldEnvMap, k)
}
}

newEnvSlice := []string{}
for k, v := range oldEnvMap {
newEnvSlice = append(newEnvSlice, fmt.Sprintf("%s=%s", k, v))
}

c.Config.Env = newEnvSlice
}

// If container is not running, update container metadata struct is enough,
Expand Down
56 changes: 56 additions & 0 deletions test/cli_update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,3 +292,59 @@ func (suite *PouchUpdateSuite) TestUpdateContainerLabel(c *check.C) {
c.Errorf("expect 'foo=bar' in Labels, got: %v", result[0].Config.Labels)
}
}

// TestUpdateContainerEnvValue is to verify the correctness of updating env's value of container.
func (suite *PouchUpdateSuite) TestUpdateContainerEnvValue(c *check.C) {
name := "update-container-env-value"

res := command.PouchRun("run", "-d", "--env", "foo=bar", "--name", name, busyboxImage, "top")
defer DelContainerForceMultyTime(c, name)
res.Assert(c, icmd.Success)

command.PouchRun("update", "--env", "foo=bar1", name).Assert(c, icmd.Success)

output := command.PouchRun("inspect", name).Stdout()
result := []types.ContainerJSON{}
if err := json.Unmarshal([]byte(output), &result); err != nil {
c.Errorf("failed to decode inspect output: %v", err)
}

if !utils.StringInSlice(result[0].Config.Env, "foo=bar1") {
c.Errorf("expect 'foo=bar' in container env, but got: %v", result[0].Config.Env)
}

if utils.StringInSlice(result[0].Config.Env, "foo=bar") {
c.Errorf("expect change 'foo=bar' to 'foo=bar1', but got: %v", result[0].Config.Env)
}

output = command.PouchRun("exec", name, "env").Stdout()
if !strings.Contains(output, "foo=bar1") {
c.Fatalf("Update running container env not worked")
}
}

// TestUpdateContainerDeleteEnv is to verify the correctness of delete env by update interface
func (suite *PouchUpdateSuite) TestUpdateContainerDeleteEnv(c *check.C) {
name := "update-container-delete-env"

res := command.PouchRun("run", "-d", "--env", "foo=bar", "--name", name, busyboxImage, "top")
defer DelContainerForceMultyTime(c, name)
res.Assert(c, icmd.Success)

command.PouchRun("update", "--env", "foo=", name).Assert(c, icmd.Success)

output := command.PouchRun("inspect", name).Stdout()
result := []types.ContainerJSON{}
if err := json.Unmarshal([]byte(output), &result); err != nil {
c.Errorf("failed to decode inspect output: %v", err)
}

if utils.StringInSlice(result[0].Config.Env, "foo=bar") {
c.Errorf("expect 'foo=bar' env being deleted, but not")
}

output = command.PouchRun("exec", name, "env").Stdout()
if strings.Contains(output, "foo=bar") {
c.Errorf("foo=bar env should be deleted from container's env")
}
}

0 comments on commit 0d0d697

Please sign in to comment.