github.com/endocode/docker@v1.4.2-0.20160113120958-46eb4700391e/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  }