Fix regression in parsing capabilities list when a single string is given
Signed-off-by: Antonio Murdaca <runcom@linux.com>
This commit is contained in:
parent
53b897ce9c
commit
10a3061c5f
|
@ -297,8 +297,8 @@ func populateCommand(c *Container, env []string) error {
|
||||||
Resources: resources,
|
Resources: resources,
|
||||||
AllowedDevices: allowedDevices,
|
AllowedDevices: allowedDevices,
|
||||||
AutoCreatedDevices: autoCreatedDevices,
|
AutoCreatedDevices: autoCreatedDevices,
|
||||||
CapAdd: c.hostConfig.CapAdd,
|
CapAdd: c.hostConfig.CapAdd.Slice(),
|
||||||
CapDrop: c.hostConfig.CapDrop,
|
CapDrop: c.hostConfig.CapDrop.Slice(),
|
||||||
ProcessConfig: processConfig,
|
ProcessConfig: processConfig,
|
||||||
ProcessLabel: c.GetProcessLabel(),
|
ProcessLabel: c.GetProcessLabel(),
|
||||||
MountLabel: c.GetMountLabel(),
|
MountLabel: c.GetMountLabel(),
|
||||||
|
|
|
@ -111,8 +111,8 @@ func populateCommand(c *Container, env []string) error {
|
||||||
Network: en,
|
Network: en,
|
||||||
Pid: pid,
|
Pid: pid,
|
||||||
Resources: resources,
|
Resources: resources,
|
||||||
CapAdd: c.hostConfig.CapAdd,
|
CapAdd: c.hostConfig.CapAdd.Slice(),
|
||||||
CapDrop: c.hostConfig.CapDrop,
|
CapDrop: c.hostConfig.CapDrop.Slice(),
|
||||||
ProcessConfig: processConfig,
|
ProcessConfig: processConfig,
|
||||||
ProcessLabel: c.GetProcessLabel(),
|
ProcessLabel: c.GetProcessLabel(),
|
||||||
MountLabel: c.GetMountLabel(),
|
MountLabel: c.GetMountLabel(),
|
||||||
|
|
|
@ -1705,3 +1705,24 @@ func (s *DockerSuite) TestPostContainersCreateWithStringOrSliceCmd(c *check.C) {
|
||||||
out, _ = dockerCmd(c, "start", "-a", "echotest2")
|
out, _ = dockerCmd(c, "start", "-a", "echotest2")
|
||||||
c.Assert(strings.TrimSpace(out), check.Equals, "hello world")
|
c.Assert(strings.TrimSpace(out), check.Equals, "hello world")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// regression #14318
|
||||||
|
func (s *DockerSuite) TestPostContainersCreateWithStringOrSliceCapAddDrop(c *check.C) {
|
||||||
|
config := struct {
|
||||||
|
Image string
|
||||||
|
CapAdd string
|
||||||
|
CapDrop string
|
||||||
|
}{"busybox", "NET_ADMIN", "SYS_ADMIN"}
|
||||||
|
status, _, err := sockRequest("POST", "/containers/create?name=capaddtest0", config)
|
||||||
|
c.Assert(err, check.IsNil)
|
||||||
|
c.Assert(status, check.Equals, http.StatusCreated)
|
||||||
|
|
||||||
|
config2 := struct {
|
||||||
|
Image string
|
||||||
|
CapAdd []string
|
||||||
|
CapDrop []string
|
||||||
|
}{"busybox", []string{"NET_ADMIN", "SYS_ADMIN"}, []string{"SETGID"}}
|
||||||
|
status, _, err = sockRequest("POST", "/containers/create?name=capaddtest1", config2)
|
||||||
|
c.Assert(err, check.IsNil)
|
||||||
|
c.Assert(status, check.Equals, http.StatusCreated)
|
||||||
|
}
|
||||||
|
|
|
@ -173,6 +173,53 @@ func NewLxcConfig(values []KeyValuePair) *LxcConfig {
|
||||||
return &LxcConfig{values}
|
return &LxcConfig{values}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CapList struct {
|
||||||
|
caps []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CapList) MarshalJSON() ([]byte, error) {
|
||||||
|
if c == nil {
|
||||||
|
return []byte{}, nil
|
||||||
|
}
|
||||||
|
return json.Marshal(c.Slice())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CapList) UnmarshalJSON(b []byte) error {
|
||||||
|
if len(b) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var caps []string
|
||||||
|
if err := json.Unmarshal(b, &caps); err != nil {
|
||||||
|
var s string
|
||||||
|
if err := json.Unmarshal(b, &s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
caps = append(caps, s)
|
||||||
|
}
|
||||||
|
c.caps = caps
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CapList) Len() int {
|
||||||
|
if c == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return len(c.caps)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CapList) Slice() []string {
|
||||||
|
if c == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return c.caps
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCapList(caps []string) *CapList {
|
||||||
|
return &CapList{caps}
|
||||||
|
}
|
||||||
|
|
||||||
type HostConfig struct {
|
type HostConfig struct {
|
||||||
Binds []string
|
Binds []string
|
||||||
ContainerIDFile string
|
ContainerIDFile string
|
||||||
|
@ -199,8 +246,8 @@ type HostConfig struct {
|
||||||
IpcMode IpcMode
|
IpcMode IpcMode
|
||||||
PidMode PidMode
|
PidMode PidMode
|
||||||
UTSMode UTSMode
|
UTSMode UTSMode
|
||||||
CapAdd []string
|
CapAdd *CapList
|
||||||
CapDrop []string
|
CapDrop *CapList
|
||||||
RestartPolicy RestartPolicy
|
RestartPolicy RestartPolicy
|
||||||
SecurityOpt []string
|
SecurityOpt []string
|
||||||
ReadonlyRootfs bool
|
ReadonlyRootfs bool
|
||||||
|
|
|
@ -2,6 +2,7 @@ package runconfig
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -254,12 +255,49 @@ func TestDecodeHostConfig(t *testing.T) {
|
||||||
t.Fatalf("Expected 1 bind, found %v\n", c.Binds)
|
t.Fatalf("Expected 1 bind, found %v\n", c.Binds)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(c.CapAdd) != 1 && c.CapAdd[0] != "NET_ADMIN" {
|
if c.CapAdd.Len() != 1 && c.CapAdd.Slice()[0] != "NET_ADMIN" {
|
||||||
t.Fatalf("Expected CapAdd NET_ADMIN, got %v", c.CapAdd)
|
t.Fatalf("Expected CapAdd NET_ADMIN, got %v", c.CapAdd)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(c.CapDrop) != 1 && c.CapDrop[0] != "NET_ADMIN" {
|
if c.CapDrop.Len() != 1 && c.CapDrop.Slice()[0] != "NET_ADMIN" {
|
||||||
t.Fatalf("Expected CapDrop MKNOD, got %v", c.CapDrop)
|
t.Fatalf("Expected CapDrop MKNOD, got %v", c.CapDrop)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCapListUnmarshalSliceAndString(t *testing.T) {
|
||||||
|
var cl *CapList
|
||||||
|
cap0, err := json.Marshal([]string{"CAP_SOMETHING"})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(cap0, &cl); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
slice := cl.Slice()
|
||||||
|
if len(slice) != 1 {
|
||||||
|
t.Fatalf("expected 1 element after unmarshal: %q", slice)
|
||||||
|
}
|
||||||
|
|
||||||
|
if slice[0] != "CAP_SOMETHING" {
|
||||||
|
t.Fatalf("expected `CAP_SOMETHING`, got: %q", slice[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
cap1, err := json.Marshal("CAP_SOMETHING")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(cap1, &cl); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
slice = cl.Slice()
|
||||||
|
if len(slice) != 1 {
|
||||||
|
t.Fatalf("expected 1 element after unmarshal: %q", slice)
|
||||||
|
}
|
||||||
|
|
||||||
|
if slice[0] != "CAP_SOMETHING" {
|
||||||
|
t.Fatalf("expected `CAP_SOMETHING`, got: %q", slice[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -353,8 +353,8 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
|
||||||
PidMode: pidMode,
|
PidMode: pidMode,
|
||||||
UTSMode: utsMode,
|
UTSMode: utsMode,
|
||||||
Devices: deviceMappings,
|
Devices: deviceMappings,
|
||||||
CapAdd: flCapAdd.GetAll(),
|
CapAdd: NewCapList(flCapAdd.GetAll()),
|
||||||
CapDrop: flCapDrop.GetAll(),
|
CapDrop: NewCapList(flCapDrop.GetAll()),
|
||||||
RestartPolicy: restartPolicy,
|
RestartPolicy: restartPolicy,
|
||||||
SecurityOpt: flSecurityOpt.GetAll(),
|
SecurityOpt: flSecurityOpt.GetAll(),
|
||||||
ReadonlyRootfs: *flReadonlyRootfs,
|
ReadonlyRootfs: *flReadonlyRootfs,
|
||||||
|
|
Loading…
Reference in New Issue