diff --git a/integration-cli/docker_api_containers_test.go b/integration-cli/docker_api_containers_test.go index fcef221061..668ecab70d 100644 --- a/integration-cli/docker_api_containers_test.go +++ b/integration-cli/docker_api_containers_test.go @@ -1636,3 +1636,48 @@ func (s *DockerSuite) TestPostContainerStop(c *check.C) { c.Fatal(err) } } + +// #14170 +func (s *DockerSuite) TestPostContainersCreateWithStringOrSliceEntrypoint(c *check.C) { + config := struct { + Image string + Entrypoint string + Cmd []string + }{"busybox", "echo", []string{"hello", "world"}} + _, _, err := sockRequest("POST", "/containers/create?name=echotest", config) + c.Assert(err, check.IsNil) + out, _ := dockerCmd(c, "start", "-a", "echotest") + c.Assert(strings.TrimSpace(out), check.Equals, "hello world") + + config2 := struct { + Image string + Entrypoint []string + Cmd []string + }{"busybox", []string{"echo"}, []string{"hello", "world"}} + _, _, err = sockRequest("POST", "/containers/create?name=echotest2", config2) + c.Assert(err, check.IsNil) + out, _ = dockerCmd(c, "start", "-a", "echotest2") + c.Assert(strings.TrimSpace(out), check.Equals, "hello world") +} + +// #14170 +func (s *DockerSuite) TestPostContainersCreateWithStringOrSliceCmd(c *check.C) { + config := struct { + Image string + Entrypoint string + Cmd string + }{"busybox", "echo", "hello world"} + _, _, err := sockRequest("POST", "/containers/create?name=echotest", config) + c.Assert(err, check.IsNil) + out, _ := dockerCmd(c, "start", "-a", "echotest") + c.Assert(strings.TrimSpace(out), check.Equals, "hello world") + + config2 := struct { + Image string + Cmd []string + }{"busybox", []string{"echo", "hello", "world"}} + _, _, err = sockRequest("POST", "/containers/create?name=echotest2", config2) + c.Assert(err, check.IsNil) + out, _ = dockerCmd(c, "start", "-a", "echotest2") + c.Assert(strings.TrimSpace(out), check.Equals, "hello world") +} diff --git a/runconfig/config.go b/runconfig/config.go index 786b075618..2a7f289f26 100644 --- a/runconfig/config.go +++ b/runconfig/config.go @@ -32,7 +32,11 @@ func (e *Entrypoint) UnmarshalJSON(b []byte) error { p := make([]string, 0, 1) if err := json.Unmarshal(b, &p); err != nil { - p = append(p, string(b)) + var s string + if err := json.Unmarshal(b, &s); err != nil { + return err + } + p = append(p, s) } e.parts = p return nil @@ -79,7 +83,11 @@ func (e *Command) UnmarshalJSON(b []byte) error { p := make([]string, 0, 1) if err := json.Unmarshal(b, &p); err != nil { - p = append(p, string(b)) + var s string + if err := json.Unmarshal(b, &s); err != nil { + return err + } + p = append(p, s) } e.parts = p return nil diff --git a/runconfig/config_test.go b/runconfig/config_test.go index a0687df3a6..6be68b6cc8 100644 --- a/runconfig/config_test.go +++ b/runconfig/config_test.go @@ -2,6 +2,7 @@ package runconfig import ( "bytes" + "encoding/json" "fmt" "io/ioutil" "strings" @@ -310,3 +311,83 @@ func TestDecodeContainerConfig(t *testing.T) { } } } + +func TestEntrypointUnmarshalString(t *testing.T) { + var e *Entrypoint + echo, err := json.Marshal("echo") + if err != nil { + t.Fatal(err) + } + if err := json.Unmarshal(echo, &e); err != nil { + t.Fatal(err) + } + + slice := e.Slice() + if len(slice) != 1 { + t.Fatalf("expected 1 element after unmarshal: %q", slice) + } + + if slice[0] != "echo" { + t.Fatalf("expected `echo`, got: %q", slice[0]) + } +} + +func TestEntrypointUnmarshalSlice(t *testing.T) { + var e *Entrypoint + echo, err := json.Marshal([]string{"echo"}) + if err != nil { + t.Fatal(err) + } + if err := json.Unmarshal(echo, &e); err != nil { + t.Fatal(err) + } + + slice := e.Slice() + if len(slice) != 1 { + t.Fatalf("expected 1 element after unmarshal: %q", slice) + } + + if slice[0] != "echo" { + t.Fatalf("expected `echo`, got: %q", slice[0]) + } +} + +func TestCommandUnmarshalSlice(t *testing.T) { + var e *Command + echo, err := json.Marshal([]string{"echo"}) + if err != nil { + t.Fatal(err) + } + if err := json.Unmarshal(echo, &e); err != nil { + t.Fatal(err) + } + + slice := e.Slice() + if len(slice) != 1 { + t.Fatalf("expected 1 element after unmarshal: %q", slice) + } + + if slice[0] != "echo" { + t.Fatalf("expected `echo`, got: %q", slice[0]) + } +} + +func TestCommandUnmarshalString(t *testing.T) { + var e *Command + echo, err := json.Marshal("echo") + if err != nil { + t.Fatal(err) + } + if err := json.Unmarshal(echo, &e); err != nil { + t.Fatal(err) + } + + slice := e.Slice() + if len(slice) != 1 { + t.Fatalf("expected 1 element after unmarshal: %q", slice) + } + + if slice[0] != "echo" { + t.Fatalf("expected `echo`, got: %q", slice[0]) + } +}