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