integration-cli/docker_cli_build_unix_test.go
a9141012
 // +build !windows
 
 package main
 
 import (
851fe00c
 	"bufio"
 	"bytes"
a9141012
 	"encoding/json"
9aad7d20
 	"io/ioutil"
 	"os"
 	"os/exec"
 	"path/filepath"
851fe00c
 	"regexp"
a9141012
 	"strings"
851fe00c
 	"time"
a9141012
 
d7022f2b
 	"github.com/docker/docker/pkg/integration"
f410d7e7
 	"github.com/docker/docker/pkg/integration/checker"
83237aab
 	"github.com/docker/go-units"
a9141012
 	"github.com/go-check/check"
 )
 
 func (s *DockerSuite) TestBuildResourceConstraintsAreUsed(c *check.C) {
6b3c9281
 	testRequires(c, cpuCfsQuota)
a9141012
 	name := "testbuildresourceconstraints"
 
 	ctx, err := fakeContext(`
 	FROM hello-world:frozen
 	RUN ["/hello"]
 	`, map[string]string{})
f410d7e7
 	c.Assert(err, checker.IsNil)
a9141012
 
1b340085
 	_, _, 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, ".")
 	if err != nil {
 		c.Fatal(err)
 	}
a9141012
 
5c295460
 	out, _ := dockerCmd(c, "ps", "-lq")
a9141012
 	cID := strings.TrimSpace(out)
 
 	type hostConfig struct {
 		Memory     int64
 		MemorySwap int64
 		CpusetCpus string
 		CpusetMems string
6b3c9281
 		CPUShares  int64
 		CPUQuota   int64
83237aab
 		Ulimits    []*units.Ulimit
a9141012
 	}
 
62a856e9
 	cfg := inspectFieldJSON(c, cID, "HostConfig")
a9141012
 
 	var c1 hostConfig
f410d7e7
 	err = json.Unmarshal([]byte(cfg), &c1)
 	c.Assert(err, checker.IsNil, check.Commentf(cfg))
 
 	c.Assert(c1.Memory, checker.Equals, int64(64*1024*1024), check.Commentf("resource constraints not set properly for Memory"))
 	c.Assert(c1.MemorySwap, checker.Equals, int64(-1), check.Commentf("resource constraints not set properly for MemorySwap"))
 	c.Assert(c1.CpusetCpus, checker.Equals, "0", check.Commentf("resource constraints not set properly for CpusetCpus"))
 	c.Assert(c1.CpusetMems, checker.Equals, "0", check.Commentf("resource constraints not set properly for CpusetMems"))
 	c.Assert(c1.CPUShares, checker.Equals, int64(100), check.Commentf("resource constraints not set properly for CPUShares"))
 	c.Assert(c1.CPUQuota, checker.Equals, int64(8000), check.Commentf("resource constraints not set properly for CPUQuota"))
 	c.Assert(c1.Ulimits[0].Name, checker.Equals, "nofile", check.Commentf("resource constraints not set properly for Ulimits"))
 	c.Assert(c1.Ulimits[0].Hard, checker.Equals, int64(42), check.Commentf("resource constraints not set properly for Ulimits"))
a9141012
 
 	// Make sure constraints aren't saved to image
5c295460
 	dockerCmd(c, "run", "--name=test", name)
a9141012
 
62a856e9
 	cfg = inspectFieldJSON(c, "test", "HostConfig")
877dbbbd
 
f410d7e7
 	var c2 hostConfig
 	err = json.Unmarshal([]byte(cfg), &c2)
 	c.Assert(err, checker.IsNil, check.Commentf(cfg))
a9141012
 
f410d7e7
 	c.Assert(c2.Memory, check.Not(checker.Equals), int64(64*1024*1024), check.Commentf("resource leaked from build for Memory"))
 	c.Assert(c2.MemorySwap, check.Not(checker.Equals), int64(-1), check.Commentf("resource leaked from build for MemorySwap"))
 	c.Assert(c2.CpusetCpus, check.Not(checker.Equals), "0", check.Commentf("resource leaked from build for CpusetCpus"))
 	c.Assert(c2.CpusetMems, check.Not(checker.Equals), "0", check.Commentf("resource leaked from build for CpusetMems"))
 	c.Assert(c2.CPUShares, check.Not(checker.Equals), int64(100), check.Commentf("resource leaked from build for CPUShares"))
 	c.Assert(c2.CPUQuota, check.Not(checker.Equals), int64(8000), check.Commentf("resource leaked from build for CPUQuota"))
 	c.Assert(c2.Ulimits, checker.IsNil, check.Commentf("resource leaked from build for Ulimits"))
a9141012
 }
9aad7d20
 
 func (s *DockerSuite) TestBuildAddChangeOwnership(c *check.C) {
 	testRequires(c, DaemonIsLinux)
 	name := "testbuildaddown"
 
 	ctx := func() *FakeContext {
 		dockerfile := `
 			FROM busybox
 			ADD foo /bar/
 			RUN [ $(stat -c %U:%G "/bar") = 'root:root' ]
 			RUN [ $(stat -c %U:%G "/bar/foo") = 'root:root' ]
 			`
 		tmpDir, err := ioutil.TempDir("", "fake-context")
 		c.Assert(err, check.IsNil)
 		testFile, err := os.Create(filepath.Join(tmpDir, "foo"))
 		if err != nil {
 			c.Fatalf("failed to create foo file: %v", err)
 		}
 		defer testFile.Close()
 
 		chownCmd := exec.Command("chown", "daemon:daemon", "foo")
 		chownCmd.Dir = tmpDir
 		out, _, err := runCommandWithOutput(chownCmd)
 		if err != nil {
 			c.Fatal(err, out)
 		}
 
 		if err := ioutil.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644); err != nil {
 			c.Fatalf("failed to open destination dockerfile: %v", err)
 		}
 		return fakeContextFromDir(tmpDir)
 	}()
 
 	defer ctx.Close()
 
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
 		c.Fatalf("build failed to complete for TestBuildAddChangeOwnership: %v", err)
 	}
851fe00c
 }
 
 // Test that an infinite sleep during a build is killed if the client disconnects.
 // This test is fairly hairy because there are lots of ways to race.
 // Strategy:
 // * Monitor the output of docker events starting from before
 // * Run a 1-year-long sleep from a docker build.
 // * When docker events sees container start, close the "docker build" command
 // * Wait for docker events to emit a dying event.
 func (s *DockerSuite) TestBuildCancellationKillsSleep(c *check.C) {
 	testRequires(c, DaemonIsLinux)
 	name := "testbuildcancellation"
 
 	observer, err := newEventObserver(c)
 	c.Assert(err, checker.IsNil)
 	err = observer.Start()
 	c.Assert(err, checker.IsNil)
 	defer observer.Stop()
9aad7d20
 
851fe00c
 	// (Note: one year, will never finish)
 	ctx, err := fakeContext("FROM busybox\nRUN sleep 31536000", nil)
 	if err != nil {
 		c.Fatal(err)
 	}
 	defer ctx.Close()
 
 	buildCmd := exec.Command(dockerBinary, "build", "-t", name, ".")
 	buildCmd.Dir = ctx.Dir
 
 	stdoutBuild, err := buildCmd.StdoutPipe()
 	if err := buildCmd.Start(); err != nil {
 		c.Fatalf("failed to run build: %s", err)
 	}
 
 	matchCID := regexp.MustCompile("Running in (.+)")
 	scanner := bufio.NewScanner(stdoutBuild)
 
 	outputBuffer := new(bytes.Buffer)
 	var buildID string
 	for scanner.Scan() {
 		line := scanner.Text()
 		outputBuffer.WriteString(line)
 		outputBuffer.WriteString("\n")
 		if matches := matchCID.FindStringSubmatch(line); len(matches) > 0 {
 			buildID = matches[1]
 			break
 		}
 	}
 
 	if buildID == "" {
 		c.Fatalf("Unable to find build container id in build output:\n%s", outputBuffer.String())
 	}
 
 	testActions := map[string]chan bool{
abbf2aa6
 		"start": make(chan bool, 1),
 		"die":   make(chan bool, 1),
851fe00c
 	}
 
 	matcher := matchEventLine(buildID, "container", testActions)
27b06049
 	processor := processEventMatch(testActions)
 	go observer.Match(matcher, processor)
851fe00c
 
 	select {
 	case <-time.After(10 * time.Second):
 		observer.CheckEventError(c, buildID, "start", matcher)
 	case <-testActions["start"]:
 		// ignore, done
 	}
 
 	// Send a kill to the `docker build` command.
 	// Causes the underlying build to be cancelled due to socket close.
 	if err := buildCmd.Process.Kill(); err != nil {
 		c.Fatalf("error killing build command: %s", err)
 	}
 
 	// Get the exit status of `docker build`, check it exited because killed.
d7022f2b
 	if err := buildCmd.Wait(); err != nil && !integration.IsKilled(err) {
851fe00c
 		c.Fatalf("wait failed during build run: %T %s", err, err)
 	}
 
 	select {
 	case <-time.After(10 * time.Second):
 		observer.CheckEventError(c, buildID, "die", matcher)
 	case <-testActions["die"]:
 		// ignore, done
 	}
9aad7d20
 }