github.com/kinvolk/docker@v1.13.1/integration-cli/docker_cli_update_unix_test.go (about)

     1  // +build !windows
     2  
     3  package main
     4  
     5  import (
     6  	"encoding/json"
     7  	"fmt"
     8  	"github.com/kr/pty"
     9  	"os/exec"
    10  	"strings"
    11  	"time"
    12  
    13  	"github.com/docker/docker/api/types"
    14  	"github.com/docker/docker/pkg/integration/checker"
    15  	"github.com/docker/docker/pkg/parsers/kernel"
    16  	"github.com/go-check/check"
    17  )
    18  
    19  func (s *DockerSuite) TestUpdateRunningContainer(c *check.C) {
    20  	testRequires(c, DaemonIsLinux)
    21  	testRequires(c, memoryLimitSupport)
    22  
    23  	name := "test-update-container"
    24  	dockerCmd(c, "run", "-d", "--name", name, "-m", "300M", "busybox", "top")
    25  	dockerCmd(c, "update", "-m", "500M", name)
    26  
    27  	c.Assert(inspectField(c, name, "HostConfig.Memory"), checker.Equals, "524288000")
    28  
    29  	file := "/sys/fs/cgroup/memory/memory.limit_in_bytes"
    30  	out, _ := dockerCmd(c, "exec", name, "cat", file)
    31  	c.Assert(strings.TrimSpace(out), checker.Equals, "524288000")
    32  }
    33  
    34  func (s *DockerSuite) TestUpdateRunningContainerWithRestart(c *check.C) {
    35  	testRequires(c, DaemonIsLinux)
    36  	testRequires(c, memoryLimitSupport)
    37  
    38  	name := "test-update-container"
    39  	dockerCmd(c, "run", "-d", "--name", name, "-m", "300M", "busybox", "top")
    40  	dockerCmd(c, "update", "-m", "500M", name)
    41  	dockerCmd(c, "restart", name)
    42  
    43  	c.Assert(inspectField(c, name, "HostConfig.Memory"), checker.Equals, "524288000")
    44  
    45  	file := "/sys/fs/cgroup/memory/memory.limit_in_bytes"
    46  	out, _ := dockerCmd(c, "exec", name, "cat", file)
    47  	c.Assert(strings.TrimSpace(out), checker.Equals, "524288000")
    48  }
    49  
    50  func (s *DockerSuite) TestUpdateStoppedContainer(c *check.C) {
    51  	testRequires(c, DaemonIsLinux)
    52  	testRequires(c, memoryLimitSupport)
    53  
    54  	name := "test-update-container"
    55  	file := "/sys/fs/cgroup/memory/memory.limit_in_bytes"
    56  	dockerCmd(c, "run", "--name", name, "-m", "300M", "busybox", "cat", file)
    57  	dockerCmd(c, "update", "-m", "500M", name)
    58  
    59  	c.Assert(inspectField(c, name, "HostConfig.Memory"), checker.Equals, "524288000")
    60  
    61  	out, _ := dockerCmd(c, "start", "-a", name)
    62  	c.Assert(strings.TrimSpace(out), checker.Equals, "524288000")
    63  }
    64  
    65  func (s *DockerSuite) TestUpdatePausedContainer(c *check.C) {
    66  	testRequires(c, DaemonIsLinux)
    67  	testRequires(c, cpuShare)
    68  
    69  	name := "test-update-container"
    70  	dockerCmd(c, "run", "-d", "--name", name, "--cpu-shares", "1000", "busybox", "top")
    71  	dockerCmd(c, "pause", name)
    72  	dockerCmd(c, "update", "--cpu-shares", "500", name)
    73  
    74  	c.Assert(inspectField(c, name, "HostConfig.CPUShares"), checker.Equals, "500")
    75  
    76  	dockerCmd(c, "unpause", name)
    77  	file := "/sys/fs/cgroup/cpu/cpu.shares"
    78  	out, _ := dockerCmd(c, "exec", name, "cat", file)
    79  	c.Assert(strings.TrimSpace(out), checker.Equals, "500")
    80  }
    81  
    82  func (s *DockerSuite) TestUpdateWithUntouchedFields(c *check.C) {
    83  	testRequires(c, DaemonIsLinux)
    84  	testRequires(c, memoryLimitSupport)
    85  	testRequires(c, cpuShare)
    86  
    87  	name := "test-update-container"
    88  	dockerCmd(c, "run", "-d", "--name", name, "-m", "300M", "--cpu-shares", "800", "busybox", "top")
    89  	dockerCmd(c, "update", "-m", "500M", name)
    90  
    91  	// Update memory and not touch cpus, `cpuset.cpus` should still have the old value
    92  	out := inspectField(c, name, "HostConfig.CPUShares")
    93  	c.Assert(out, check.Equals, "800")
    94  
    95  	file := "/sys/fs/cgroup/cpu/cpu.shares"
    96  	out, _ = dockerCmd(c, "exec", name, "cat", file)
    97  	c.Assert(strings.TrimSpace(out), checker.Equals, "800")
    98  }
    99  
   100  func (s *DockerSuite) TestUpdateContainerInvalidValue(c *check.C) {
   101  	testRequires(c, DaemonIsLinux)
   102  	testRequires(c, memoryLimitSupport)
   103  
   104  	name := "test-update-container"
   105  	dockerCmd(c, "run", "-d", "--name", name, "-m", "300M", "busybox", "true")
   106  	out, _, err := dockerCmdWithError("update", "-m", "2M", name)
   107  	c.Assert(err, check.NotNil)
   108  	expected := "Minimum memory limit allowed is 4MB"
   109  	c.Assert(out, checker.Contains, expected)
   110  }
   111  
   112  func (s *DockerSuite) TestUpdateContainerWithoutFlags(c *check.C) {
   113  	testRequires(c, DaemonIsLinux)
   114  	testRequires(c, memoryLimitSupport)
   115  
   116  	name := "test-update-container"
   117  	dockerCmd(c, "run", "-d", "--name", name, "-m", "300M", "busybox", "true")
   118  	_, _, err := dockerCmdWithError("update", name)
   119  	c.Assert(err, check.NotNil)
   120  }
   121  
   122  func (s *DockerSuite) TestUpdateKernelMemory(c *check.C) {
   123  	testRequires(c, DaemonIsLinux, kernelMemorySupport)
   124  
   125  	name := "test-update-container"
   126  	dockerCmd(c, "run", "-d", "--name", name, "--kernel-memory", "50M", "busybox", "top")
   127  	dockerCmd(c, "update", "--kernel-memory", "100M", name)
   128  
   129  	c.Assert(inspectField(c, name, "HostConfig.KernelMemory"), checker.Equals, "104857600")
   130  
   131  	file := "/sys/fs/cgroup/memory/memory.kmem.limit_in_bytes"
   132  	out, _ := dockerCmd(c, "exec", name, "cat", file)
   133  	c.Assert(strings.TrimSpace(out), checker.Equals, "104857600")
   134  }
   135  
   136  func (s *DockerSuite) TestUpdateKernelMemoryUninitialized(c *check.C) {
   137  	testRequires(c, DaemonIsLinux, kernelMemorySupport)
   138  
   139  	isNewKernel := kernel.CheckKernelVersion(4, 6, 0)
   140  	name := "test-update-container"
   141  	dockerCmd(c, "run", "-d", "--name", name, "busybox", "top")
   142  	_, _, err := dockerCmdWithError("update", "--kernel-memory", "100M", name)
   143  	// Update kernel memory to a running container without kernel memory initialized
   144  	// is not allowed before kernel version 4.6.
   145  	if !isNewKernel {
   146  		c.Assert(err, check.NotNil)
   147  	} else {
   148  		c.Assert(err, check.IsNil)
   149  	}
   150  
   151  	dockerCmd(c, "pause", name)
   152  	_, _, err = dockerCmdWithError("update", "--kernel-memory", "200M", name)
   153  	if !isNewKernel {
   154  		c.Assert(err, check.NotNil)
   155  	} else {
   156  		c.Assert(err, check.IsNil)
   157  	}
   158  	dockerCmd(c, "unpause", name)
   159  
   160  	dockerCmd(c, "stop", name)
   161  	dockerCmd(c, "update", "--kernel-memory", "300M", name)
   162  	dockerCmd(c, "start", name)
   163  
   164  	c.Assert(inspectField(c, name, "HostConfig.KernelMemory"), checker.Equals, "314572800")
   165  
   166  	file := "/sys/fs/cgroup/memory/memory.kmem.limit_in_bytes"
   167  	out, _ := dockerCmd(c, "exec", name, "cat", file)
   168  	c.Assert(strings.TrimSpace(out), checker.Equals, "314572800")
   169  }
   170  
   171  func (s *DockerSuite) TestUpdateSwapMemoryOnly(c *check.C) {
   172  	testRequires(c, DaemonIsLinux)
   173  	testRequires(c, memoryLimitSupport)
   174  	testRequires(c, swapMemorySupport)
   175  
   176  	name := "test-update-container"
   177  	dockerCmd(c, "run", "-d", "--name", name, "--memory", "300M", "--memory-swap", "500M", "busybox", "top")
   178  	dockerCmd(c, "update", "--memory-swap", "600M", name)
   179  
   180  	c.Assert(inspectField(c, name, "HostConfig.MemorySwap"), checker.Equals, "629145600")
   181  
   182  	file := "/sys/fs/cgroup/memory/memory.memsw.limit_in_bytes"
   183  	out, _ := dockerCmd(c, "exec", name, "cat", file)
   184  	c.Assert(strings.TrimSpace(out), checker.Equals, "629145600")
   185  }
   186  
   187  func (s *DockerSuite) TestUpdateInvalidSwapMemory(c *check.C) {
   188  	testRequires(c, DaemonIsLinux)
   189  	testRequires(c, memoryLimitSupport)
   190  	testRequires(c, swapMemorySupport)
   191  
   192  	name := "test-update-container"
   193  	dockerCmd(c, "run", "-d", "--name", name, "--memory", "300M", "--memory-swap", "500M", "busybox", "top")
   194  	_, _, err := dockerCmdWithError("update", "--memory-swap", "200M", name)
   195  	// Update invalid swap memory should fail.
   196  	// This will pass docker config validation, but failed at kernel validation
   197  	c.Assert(err, check.NotNil)
   198  
   199  	// Update invalid swap memory with failure should not change HostConfig
   200  	c.Assert(inspectField(c, name, "HostConfig.Memory"), checker.Equals, "314572800")
   201  	c.Assert(inspectField(c, name, "HostConfig.MemorySwap"), checker.Equals, "524288000")
   202  
   203  	dockerCmd(c, "update", "--memory-swap", "600M", name)
   204  
   205  	c.Assert(inspectField(c, name, "HostConfig.MemorySwap"), checker.Equals, "629145600")
   206  
   207  	file := "/sys/fs/cgroup/memory/memory.memsw.limit_in_bytes"
   208  	out, _ := dockerCmd(c, "exec", name, "cat", file)
   209  	c.Assert(strings.TrimSpace(out), checker.Equals, "629145600")
   210  }
   211  
   212  func (s *DockerSuite) TestUpdateStats(c *check.C) {
   213  	testRequires(c, DaemonIsLinux)
   214  	testRequires(c, memoryLimitSupport)
   215  	testRequires(c, cpuCfsQuota)
   216  	name := "foo"
   217  	dockerCmd(c, "run", "-d", "-ti", "--name", name, "-m", "500m", "busybox")
   218  
   219  	c.Assert(waitRun(name), checker.IsNil)
   220  
   221  	getMemLimit := func(id string) uint64 {
   222  		resp, body, err := sockRequestRaw("GET", fmt.Sprintf("/containers/%s/stats?stream=false", id), nil, "")
   223  		c.Assert(err, checker.IsNil)
   224  		c.Assert(resp.Header.Get("Content-Type"), checker.Equals, "application/json")
   225  
   226  		var v *types.Stats
   227  		err = json.NewDecoder(body).Decode(&v)
   228  		c.Assert(err, checker.IsNil)
   229  		body.Close()
   230  
   231  		return v.MemoryStats.Limit
   232  	}
   233  	preMemLimit := getMemLimit(name)
   234  
   235  	dockerCmd(c, "update", "--cpu-quota", "2000", name)
   236  
   237  	curMemLimit := getMemLimit(name)
   238  
   239  	c.Assert(preMemLimit, checker.Equals, curMemLimit)
   240  
   241  }
   242  
   243  func (s *DockerSuite) TestUpdateMemoryWithSwapMemory(c *check.C) {
   244  	testRequires(c, DaemonIsLinux)
   245  	testRequires(c, memoryLimitSupport)
   246  	testRequires(c, swapMemorySupport)
   247  
   248  	name := "test-update-container"
   249  	dockerCmd(c, "run", "-d", "--name", name, "--memory", "300M", "busybox", "top")
   250  	out, _, err := dockerCmdWithError("update", "--memory", "800M", name)
   251  	c.Assert(err, checker.NotNil)
   252  	c.Assert(out, checker.Contains, "Memory limit should be smaller than already set memoryswap limit")
   253  
   254  	dockerCmd(c, "update", "--memory", "800M", "--memory-swap", "1000M", name)
   255  }
   256  
   257  func (s *DockerSuite) TestUpdateNotAffectMonitorRestartPolicy(c *check.C) {
   258  	testRequires(c, DaemonIsLinux, cpuShare)
   259  
   260  	out, _ := dockerCmd(c, "run", "-tid", "--restart=always", "busybox", "sh")
   261  	id := strings.TrimSpace(string(out))
   262  	dockerCmd(c, "update", "--cpu-shares", "512", id)
   263  
   264  	cpty, tty, err := pty.Open()
   265  	c.Assert(err, checker.IsNil)
   266  	defer cpty.Close()
   267  
   268  	cmd := exec.Command(dockerBinary, "attach", id)
   269  	cmd.Stdin = tty
   270  
   271  	c.Assert(cmd.Start(), checker.IsNil)
   272  	defer cmd.Process.Kill()
   273  
   274  	_, err = cpty.Write([]byte("exit\n"))
   275  	c.Assert(err, checker.IsNil)
   276  
   277  	c.Assert(cmd.Wait(), checker.IsNil)
   278  
   279  	// container should restart again and keep running
   280  	err = waitInspect(id, "{{.RestartCount}}", "1", 30*time.Second)
   281  	c.Assert(err, checker.IsNil)
   282  	c.Assert(waitRun(id), checker.IsNil)
   283  }