Fix ulimits in `docker inspect` when daemon default exists

This fix tries to fix 26326 where `docker inspect` will not show
ulimit even when daemon default ulimit has been set.

This fix merge the HostConfig's ulimit with daemon default in
`docker inspect`, so that when daemon is started with `default-ulimit`
and HostConfig's ulimit is not set, `docker inspect` will output
the daemon default.

An integration test has been added to cover the changes.

This fix fixes 26326.

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
This commit is contained in:
Yong Tang 2016-09-07 21:23:56 -07:00
parent 5be6ccc433
commit 7d705a7355
5 changed files with 60 additions and 13 deletions

View File

@ -110,6 +110,9 @@ func (daemon *Daemon) getInspectData(container *container.Container, size bool)
hostConfig.Links = append(hostConfig.Links, fmt.Sprintf("%s:%s", child.Name, linkAlias)) hostConfig.Links = append(hostConfig.Links, fmt.Sprintf("%s:%s", child.Name, linkAlias))
} }
// We merge the Ulimits from hostConfig with daemon default
daemon.mergeUlimits(&hostConfig)
var containerHealth *types.Health var containerHealth *types.Health
if container.State.Health != nil { if container.State.Health != nil {
containerHealth = &types.Health{ containerHealth = &types.Health{

View File

@ -115,19 +115,11 @@ func setDevices(s *specs.Spec, c *container.Container) error {
func setRlimits(daemon *Daemon, s *specs.Spec, c *container.Container) error { func setRlimits(daemon *Daemon, s *specs.Spec, c *container.Container) error {
var rlimits []specs.Rlimit var rlimits []specs.Rlimit
ulimits := c.HostConfig.Ulimits // We want to leave the original HostConfig alone so make a copy here
// Merge ulimits with daemon defaults hostConfig := *c.HostConfig
ulIdx := make(map[string]struct{}) // Merge with the daemon defaults
for _, ul := range ulimits { daemon.mergeUlimits(&hostConfig)
ulIdx[ul.Name] = struct{}{} for _, ul := range hostConfig.Ulimits {
}
for name, ul := range daemon.configStore.Ulimits {
if _, exists := ulIdx[name]; !exists {
ulimits = append(ulimits, ul)
}
}
for _, ul := range ulimits {
rlimits = append(rlimits, specs.Rlimit{ rlimits = append(rlimits, specs.Rlimit{
Type: "RLIMIT_" + strings.ToUpper(ul.Name), Type: "RLIMIT_" + strings.ToUpper(ul.Name),
Soft: uint64(ul.Soft), Soft: uint64(ul.Soft),
@ -709,3 +701,19 @@ func clearReadOnly(m *specs.Mount) {
} }
m.Options = opt m.Options = opt
} }
// mergeUlimits merge the Ulimits from HostConfig with daemon defaults, and update HostConfig
func (daemon *Daemon) mergeUlimits(c *containertypes.HostConfig) {
ulimits := c.Ulimits
// Merge ulimits with daemon defaults
ulIdx := make(map[string]struct{})
for _, ul := range ulimits {
ulIdx[ul.Name] = struct{}{}
}
for name, ul := range daemon.configStore.Ulimits {
if _, exists := ulIdx[name]; !exists {
ulimits = append(ulimits, ul)
}
}
c.Ulimits = ulimits
}

View File

@ -1,6 +1,7 @@
package daemon package daemon
import ( import (
containertypes "github.com/docker/docker/api/types/container"
"github.com/docker/docker/container" "github.com/docker/docker/container"
"github.com/docker/docker/libcontainerd" "github.com/docker/docker/libcontainerd"
"github.com/docker/docker/oci" "github.com/docker/docker/oci"
@ -10,3 +11,9 @@ func (daemon *Daemon) createSpec(c *container.Container) (*libcontainerd.Spec, e
s := oci.DefaultSpec() s := oci.DefaultSpec()
return (*libcontainerd.Spec)(&s), nil return (*libcontainerd.Spec)(&s), nil
} }
// mergeUlimits merge the Ulimits from HostConfig with daemon defaults, and update HostConfig
// It will do nothing on non-Linux platform
func (daemon *Daemon) mergeUlimits(c *containertypes.HostConfig) {
return
}

View File

@ -7,6 +7,7 @@ import (
"path/filepath" "path/filepath"
"syscall" "syscall"
containertypes "github.com/docker/docker/api/types/container"
"github.com/docker/docker/container" "github.com/docker/docker/container"
"github.com/docker/docker/image" "github.com/docker/docker/image"
"github.com/docker/docker/layer" "github.com/docker/docker/layer"
@ -192,3 +193,9 @@ func escapeArgs(args []string) []string {
} }
return escapedArgs return escapedArgs
} }
// mergeUlimits merge the Ulimits from HostConfig with daemon defaults, and update HostConfig
// It will do nothing on non-Linux platform
func (daemon *Daemon) mergeUlimits(c *containertypes.HostConfig) {
return
}

View File

@ -4518,3 +4518,25 @@ exec "$@"`,
c.Assert(err, check.NotNil) c.Assert(err, check.NotNil)
c.Assert(err.Error(), checker.Contains, "No command specified") c.Assert(err.Error(), checker.Contains, "No command specified")
} }
func (s *DockerDaemonSuite) TestRunWithUlimitAndDaemonDefault(c *check.C) {
c.Assert(s.d.StartWithBusybox("--debug", "--default-ulimit=nofile=65535"), checker.IsNil)
name := "test-A"
_, err := s.d.Cmd("run", "--name", name, "-d", "busybox", "top")
c.Assert(err, checker.IsNil)
c.Assert(s.d.waitRun(name), check.IsNil)
out, err := s.d.Cmd("inspect", "--format", "{{.HostConfig.Ulimits}}", name)
c.Assert(err, checker.IsNil)
c.Assert(out, checker.Contains, "[nofile=65535:65535]")
name = "test-B"
_, err = s.d.Cmd("run", "--name", name, "--ulimit=nofile=42", "-d", "busybox", "top")
c.Assert(err, checker.IsNil)
c.Assert(s.d.waitRun(name), check.IsNil)
out, err = s.d.Cmd("inspect", "--format", "{{.HostConfig.Ulimits}}", name)
c.Assert(err, checker.IsNil)
c.Assert(out, checker.Contains, "[nofile=42:42]")
}