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