github.com/boynux/docker@v1.11.0-rc4/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 := 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  		chownCmd := exec.Command("chown", "daemon:daemon", "foo")
   103  		chownCmd.Dir = tmpDir
   104  		out, _, err := runCommandWithOutput(chownCmd)
   105  		if err != nil {
   106  			c.Fatal(err, out)
   107  		}
   108  
   109  		if err := ioutil.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644); err != nil {
   110  			c.Fatalf("failed to open destination dockerfile: %v", err)
   111  		}
   112  		return fakeContextFromDir(tmpDir)
   113  	}()
   114  
   115  	defer ctx.Close()
   116  
   117  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
   118  		c.Fatalf("build failed to complete for TestBuildAddChangeOwnership: %v", err)
   119  	}
   120  }
   121  
   122  // Test that an infinite sleep during a build is killed if the client disconnects.
   123  // This test is fairly hairy because there are lots of ways to race.
   124  // Strategy:
   125  // * Monitor the output of docker events starting from before
   126  // * Run a 1-year-long sleep from a docker build.
   127  // * When docker events sees container start, close the "docker build" command
   128  // * Wait for docker events to emit a dying event.
   129  func (s *DockerSuite) TestBuildCancellationKillsSleep(c *check.C) {
   130  	testRequires(c, DaemonIsLinux)
   131  	name := "testbuildcancellation"
   132  
   133  	observer, err := newEventObserver(c)
   134  	c.Assert(err, checker.IsNil)
   135  	err = observer.Start()
   136  	c.Assert(err, checker.IsNil)
   137  	defer observer.Stop()
   138  
   139  	// (Note: one year, will never finish)
   140  	ctx, err := fakeContext("FROM busybox\nRUN sleep 31536000", nil)
   141  	if err != nil {
   142  		c.Fatal(err)
   143  	}
   144  	defer ctx.Close()
   145  
   146  	buildCmd := exec.Command(dockerBinary, "build", "-t", name, ".")
   147  	buildCmd.Dir = ctx.Dir
   148  
   149  	stdoutBuild, err := buildCmd.StdoutPipe()
   150  	if err := buildCmd.Start(); err != nil {
   151  		c.Fatalf("failed to run build: %s", err)
   152  	}
   153  
   154  	matchCID := regexp.MustCompile("Running in (.+)")
   155  	scanner := bufio.NewScanner(stdoutBuild)
   156  
   157  	outputBuffer := new(bytes.Buffer)
   158  	var buildID string
   159  	for scanner.Scan() {
   160  		line := scanner.Text()
   161  		outputBuffer.WriteString(line)
   162  		outputBuffer.WriteString("\n")
   163  		if matches := matchCID.FindStringSubmatch(line); len(matches) > 0 {
   164  			buildID = matches[1]
   165  			break
   166  		}
   167  	}
   168  
   169  	if buildID == "" {
   170  		c.Fatalf("Unable to find build container id in build output:\n%s", outputBuffer.String())
   171  	}
   172  
   173  	testActions := map[string]chan bool{
   174  		"start": make(chan bool, 1),
   175  		"die":   make(chan bool, 1),
   176  	}
   177  
   178  	matcher := matchEventLine(buildID, "container", testActions)
   179  	processor := processEventMatch(testActions)
   180  	go observer.Match(matcher, processor)
   181  
   182  	select {
   183  	case <-time.After(10 * time.Second):
   184  		observer.CheckEventError(c, buildID, "start", matcher)
   185  	case <-testActions["start"]:
   186  		// ignore, done
   187  	}
   188  
   189  	// Send a kill to the `docker build` command.
   190  	// Causes the underlying build to be cancelled due to socket close.
   191  	if err := buildCmd.Process.Kill(); err != nil {
   192  		c.Fatalf("error killing build command: %s", err)
   193  	}
   194  
   195  	// Get the exit status of `docker build`, check it exited because killed.
   196  	if err := buildCmd.Wait(); err != nil && !isKilled(err) {
   197  		c.Fatalf("wait failed during build run: %T %s", err, err)
   198  	}
   199  
   200  	select {
   201  	case <-time.After(10 * time.Second):
   202  		observer.CheckEventError(c, buildID, "die", matcher)
   203  	case <-testActions["die"]:
   204  		// ignore, done
   205  	}
   206  }