github.com/jiasir/docker@v1.3.3-0.20170609024000-252e610103e7/integration-cli/docker_cli_build_unix_test.go (about) 1 // +build !windows 2 3 package main 4 5 import ( 6 "bufio" 7 "bytes" 8 "encoding/json" 9 "io/ioutil" 10 "os" 11 "os/exec" 12 "path/filepath" 13 "regexp" 14 "strings" 15 "time" 16 17 "github.com/docker/docker/integration-cli/checker" 18 "github.com/docker/docker/integration-cli/cli" 19 "github.com/docker/docker/integration-cli/cli/build" 20 "github.com/docker/docker/integration-cli/cli/build/fakecontext" 21 "github.com/docker/docker/pkg/testutil" 22 icmd "github.com/docker/docker/pkg/testutil/cmd" 23 "github.com/docker/go-units" 24 "github.com/go-check/check" 25 ) 26 27 func (s *DockerSuite) TestBuildResourceConstraintsAreUsed(c *check.C) { 28 testRequires(c, cpuCfsQuota) 29 name := "testbuildresourceconstraints" 30 31 ctx := fakecontext.New(c, "", fakecontext.WithDockerfile(` 32 FROM hello-world:frozen 33 RUN ["/hello"] 34 `)) 35 cli.Docker( 36 cli.Args("build", "--no-cache", "--rm=false", "--memory=64m", "--memory-swap=-1", "--cpuset-cpus=0", "--cpuset-mems=0", "--cpu-shares=100", "--cpu-quota=8000", "--ulimit", "nofile=42", "-t", name, "."), 37 cli.InDir(ctx.Dir), 38 ).Assert(c, icmd.Success) 39 40 out := cli.DockerCmd(c, "ps", "-lq").Combined() 41 cID := strings.TrimSpace(out) 42 43 type hostConfig struct { 44 Memory int64 45 MemorySwap int64 46 CpusetCpus string 47 CpusetMems string 48 CPUShares int64 49 CPUQuota int64 50 Ulimits []*units.Ulimit 51 } 52 53 cfg := inspectFieldJSON(c, cID, "HostConfig") 54 55 var c1 hostConfig 56 err := json.Unmarshal([]byte(cfg), &c1) 57 c.Assert(err, checker.IsNil, check.Commentf(cfg)) 58 59 c.Assert(c1.Memory, checker.Equals, int64(64*1024*1024), check.Commentf("resource constraints not set properly for Memory")) 60 c.Assert(c1.MemorySwap, checker.Equals, int64(-1), check.Commentf("resource constraints not set properly for MemorySwap")) 61 c.Assert(c1.CpusetCpus, checker.Equals, "0", check.Commentf("resource constraints not set properly for CpusetCpus")) 62 c.Assert(c1.CpusetMems, checker.Equals, "0", check.Commentf("resource constraints not set properly for CpusetMems")) 63 c.Assert(c1.CPUShares, checker.Equals, int64(100), check.Commentf("resource constraints not set properly for CPUShares")) 64 c.Assert(c1.CPUQuota, checker.Equals, int64(8000), check.Commentf("resource constraints not set properly for CPUQuota")) 65 c.Assert(c1.Ulimits[0].Name, checker.Equals, "nofile", check.Commentf("resource constraints not set properly for Ulimits")) 66 c.Assert(c1.Ulimits[0].Hard, checker.Equals, int64(42), check.Commentf("resource constraints not set properly for Ulimits")) 67 68 // Make sure constraints aren't saved to image 69 cli.DockerCmd(c, "run", "--name=test", name) 70 71 cfg = inspectFieldJSON(c, "test", "HostConfig") 72 73 var c2 hostConfig 74 err = json.Unmarshal([]byte(cfg), &c2) 75 c.Assert(err, checker.IsNil, check.Commentf(cfg)) 76 77 c.Assert(c2.Memory, check.Not(checker.Equals), int64(64*1024*1024), check.Commentf("resource leaked from build for Memory")) 78 c.Assert(c2.MemorySwap, check.Not(checker.Equals), int64(-1), check.Commentf("resource leaked from build for MemorySwap")) 79 c.Assert(c2.CpusetCpus, check.Not(checker.Equals), "0", check.Commentf("resource leaked from build for CpusetCpus")) 80 c.Assert(c2.CpusetMems, check.Not(checker.Equals), "0", check.Commentf("resource leaked from build for CpusetMems")) 81 c.Assert(c2.CPUShares, check.Not(checker.Equals), int64(100), check.Commentf("resource leaked from build for CPUShares")) 82 c.Assert(c2.CPUQuota, check.Not(checker.Equals), int64(8000), check.Commentf("resource leaked from build for CPUQuota")) 83 c.Assert(c2.Ulimits, checker.IsNil, check.Commentf("resource leaked from build for Ulimits")) 84 } 85 86 func (s *DockerSuite) TestBuildAddChangeOwnership(c *check.C) { 87 testRequires(c, DaemonIsLinux) 88 name := "testbuildaddown" 89 90 ctx := func() *fakecontext.Fake { 91 dockerfile := ` 92 FROM busybox 93 ADD foo /bar/ 94 RUN [ $(stat -c %U:%G "/bar") = 'root:root' ] 95 RUN [ $(stat -c %U:%G "/bar/foo") = 'root:root' ] 96 ` 97 tmpDir, err := ioutil.TempDir("", "fake-context") 98 c.Assert(err, check.IsNil) 99 testFile, err := os.Create(filepath.Join(tmpDir, "foo")) 100 if err != nil { 101 c.Fatalf("failed to create foo file: %v", err) 102 } 103 defer testFile.Close() 104 105 icmd.RunCmd(icmd.Cmd{ 106 Command: []string{"chown", "daemon:daemon", "foo"}, 107 Dir: tmpDir, 108 }).Assert(c, icmd.Success) 109 110 if err := ioutil.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644); err != nil { 111 c.Fatalf("failed to open destination dockerfile: %v", err) 112 } 113 return fakecontext.New(c, tmpDir) 114 }() 115 116 defer ctx.Close() 117 118 buildImageSuccessfully(c, name, build.WithExternalBuildContext(ctx)) 119 } 120 121 // Test that an infinite sleep during a build is killed if the client disconnects. 122 // This test is fairly hairy because there are lots of ways to race. 123 // Strategy: 124 // * Monitor the output of docker events starting from before 125 // * Run a 1-year-long sleep from a docker build. 126 // * When docker events sees container start, close the "docker build" command 127 // * Wait for docker events to emit a dying event. 128 func (s *DockerSuite) TestBuildCancellationKillsSleep(c *check.C) { 129 testRequires(c, DaemonIsLinux) 130 name := "testbuildcancellation" 131 132 observer, err := newEventObserver(c) 133 c.Assert(err, checker.IsNil) 134 err = observer.Start() 135 c.Assert(err, checker.IsNil) 136 defer observer.Stop() 137 138 // (Note: one year, will never finish) 139 ctx := fakecontext.New(c, "", fakecontext.WithDockerfile("FROM busybox\nRUN sleep 31536000")) 140 defer ctx.Close() 141 142 buildCmd := exec.Command(dockerBinary, "build", "-t", name, ".") 143 buildCmd.Dir = ctx.Dir 144 145 stdoutBuild, err := buildCmd.StdoutPipe() 146 c.Assert(err, checker.IsNil) 147 148 if err := buildCmd.Start(); err != nil { 149 c.Fatalf("failed to run build: %s", err) 150 } 151 152 matchCID := regexp.MustCompile("Running in (.+)") 153 scanner := bufio.NewScanner(stdoutBuild) 154 155 outputBuffer := new(bytes.Buffer) 156 var buildID string 157 for scanner.Scan() { 158 line := scanner.Text() 159 outputBuffer.WriteString(line) 160 outputBuffer.WriteString("\n") 161 if matches := matchCID.FindStringSubmatch(line); len(matches) > 0 { 162 buildID = matches[1] 163 break 164 } 165 } 166 167 if buildID == "" { 168 c.Fatalf("Unable to find build container id in build output:\n%s", outputBuffer.String()) 169 } 170 171 testActions := map[string]chan bool{ 172 "start": make(chan bool, 1), 173 "die": make(chan bool, 1), 174 } 175 176 matcher := matchEventLine(buildID, "container", testActions) 177 processor := processEventMatch(testActions) 178 go observer.Match(matcher, processor) 179 180 select { 181 case <-time.After(10 * time.Second): 182 observer.CheckEventError(c, buildID, "start", matcher) 183 case <-testActions["start"]: 184 // ignore, done 185 } 186 187 // Send a kill to the `docker build` command. 188 // Causes the underlying build to be cancelled due to socket close. 189 if err := buildCmd.Process.Kill(); err != nil { 190 c.Fatalf("error killing build command: %s", err) 191 } 192 193 // Get the exit status of `docker build`, check it exited because killed. 194 if err := buildCmd.Wait(); err != nil && !testutil.IsKilled(err) { 195 c.Fatalf("wait failed during build run: %T %s", err, err) 196 } 197 198 select { 199 case <-time.After(10 * time.Second): 200 observer.CheckEventError(c, buildID, "die", matcher) 201 case <-testActions["die"]: 202 // ignore, done 203 } 204 }