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  }