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