ソースを参照

Merge pull request #4102 from shykes/separate-mkbuildclient

Refactor utility `MkBuildContext` to the more generic `archive.Generate`
Michael Crosby 11 年 前
コミット
4bc966f302
4 ファイル変更76 行追加41 行削除
  1. 59 0
      archive/wrap.go
  2. 1 27
      commands.go
  3. 15 13
      integration/buildfile_test.go
  4. 1 1
      server.go

+ 59 - 0
archive/wrap.go

@@ -0,0 +1,59 @@
+package archive
+
+import (
+	"archive/tar"
+	"bytes"
+	"io/ioutil"
+)
+
+// Generate generates a new archive from the content provided
+// as input.
+//
+// `files` is a sequence of path/content pairs. A new file is
+// added to the archive for each pair.
+// If the last pair is incomplete, the file is created with an
+// empty content. For example:
+//
+// Generate("foo.txt", "hello world", "emptyfile")
+//
+// The above call will return an archive with 2 files:
+//  * ./foo.txt with content "hello world"
+//  * ./empty with empty content
+//
+// FIXME: stream content instead of buffering
+// FIXME: specify permissions and other archive metadata
+func Generate(input ...string) (Archive, error) {
+	files := parseStringPairs(input...)
+	buf := new(bytes.Buffer)
+	tw := tar.NewWriter(buf)
+	for _, file := range files {
+		name, content := file[0], file[1]
+		hdr := &tar.Header{
+			Name: name,
+			Size: int64(len(content)),
+		}
+		if err := tw.WriteHeader(hdr); err != nil {
+			return nil, err
+		}
+		if _, err := tw.Write([]byte(content)); err != nil {
+			return nil, err
+		}
+	}
+	if err := tw.Close(); err != nil {
+		return nil, err
+	}
+	return ioutil.NopCloser(buf), nil
+}
+
+func parseStringPairs(input ...string) (output [][2]string) {
+	output = make([][2]string, 0, len(input)/2+1)
+	for i := 0; i < len(input); i += 2 {
+		var pair [2]string
+		pair[0] = input[i]
+		if i+1 < len(input) {
+			pair[1] = input[i+1]
+		}
+		output = append(output, pair)
+	}
+	return
+}

+ 1 - 27
commands.go

@@ -1,7 +1,6 @@
 package docker
 
 import (
-	"archive/tar"
 	"bufio"
 	"bytes"
 	"encoding/base64"
@@ -136,31 +135,6 @@ func (cli *DockerCli) CmdInsert(args ...string) error {
 	return cli.stream("POST", "/images/"+cmd.Arg(0)+"/insert?"+v.Encode(), nil, cli.out, nil)
 }
 
-// mkBuildContext returns an archive of an empty context with the contents
-// of `dockerfile` at the path ./Dockerfile
-func MkBuildContext(dockerfile string, files [][2]string) (archive.Archive, error) {
-	buf := new(bytes.Buffer)
-	tw := tar.NewWriter(buf)
-	files = append(files, [2]string{"Dockerfile", dockerfile})
-	for _, file := range files {
-		name, content := file[0], file[1]
-		hdr := &tar.Header{
-			Name: name,
-			Size: int64(len(content)),
-		}
-		if err := tw.WriteHeader(hdr); err != nil {
-			return nil, err
-		}
-		if _, err := tw.Write([]byte(content)); err != nil {
-			return nil, err
-		}
-	}
-	if err := tw.Close(); err != nil {
-		return nil, err
-	}
-	return ioutil.NopCloser(buf), nil
-}
-
 func (cli *DockerCli) CmdBuild(args ...string) error {
 	cmd := cli.Subcmd("build", "[OPTIONS] PATH | URL | -", "Build a new container image from the source code at PATH")
 	tag := cmd.String([]string{"t", "-tag"}, "", "Repository name (and optionally a tag) to be applied to the resulting image in case of success")
@@ -188,7 +162,7 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
 		if err != nil {
 			return err
 		}
-		context, err = MkBuildContext(string(dockerfile), nil)
+		context, err = archive.Generate("Dockerfile", string(dockerfile))
 	} else if utils.IsURL(cmd.Arg(0)) || utils.IsGIT(cmd.Arg(0)) {
 		isRemote = true
 	} else {

+ 15 - 13
integration/buildfile_test.go

@@ -14,16 +14,6 @@ import (
 	"testing"
 )
 
-// mkTestContext generates a build context from the contents of the provided dockerfile.
-// This context is suitable for use as an argument to BuildFile.Build()
-func mkTestContext(dockerfile string, files [][2]string, t *testing.T) archive.Archive {
-	context, err := docker.MkBuildContext(dockerfile, files)
-	if err != nil {
-		t.Fatal(err)
-	}
-	return context
-}
-
 // A testContextTemplate describes a build context and how to test it
 type testContextTemplate struct {
 	// Contents of the Dockerfile
@@ -34,6 +24,18 @@ type testContextTemplate struct {
 	remoteFiles [][2]string
 }
 
+func (context testContextTemplate) Archive(dockerfile string, t *testing.T) archive.Archive {
+	input := []string{"Dockerfile", dockerfile}
+	for _, pair := range context.files {
+		input = append(input, pair[0], pair[1])
+	}
+	a, err := archive.Generate(input...)
+	if err != nil {
+		t.Fatal(err)
+	}
+	return a
+}
+
 // A table of all the contexts to build and test.
 // A new docker runtime will be created and torn down for each context.
 var testContexts = []testContextTemplate{
@@ -381,7 +383,7 @@ func buildImage(context testContextTemplate, t *testing.T, eng *engine.Engine, u
 	dockerfile := constructDockerfile(context.dockerfile, ip, port)
 
 	buildfile := docker.NewBuildFile(srv, ioutil.Discard, ioutil.Discard, false, useCache, false, ioutil.Discard, utils.NewStreamFormatter(false), nil, nil)
-	id, err := buildfile.Build(mkTestContext(dockerfile, context.files, t))
+	id, err := buildfile.Build(context.Archive(dockerfile, t))
 	if err != nil {
 		return nil, err
 	}
@@ -785,7 +787,7 @@ func TestForbiddenContextPath(t *testing.T) {
 	dockerfile := constructDockerfile(context.dockerfile, ip, port)
 
 	buildfile := docker.NewBuildFile(srv, ioutil.Discard, ioutil.Discard, false, true, false, ioutil.Discard, utils.NewStreamFormatter(false), nil, nil)
-	_, err = buildfile.Build(mkTestContext(dockerfile, context.files, t))
+	_, err = buildfile.Build(context.Archive(dockerfile, t))
 
 	if err == nil {
 		t.Log("Error should not be nil")
@@ -831,7 +833,7 @@ func TestBuildADDFileNotFound(t *testing.T) {
 	dockerfile := constructDockerfile(context.dockerfile, ip, port)
 
 	buildfile := docker.NewBuildFile(mkServerFromEngine(eng, t), ioutil.Discard, ioutil.Discard, false, true, false, ioutil.Discard, utils.NewStreamFormatter(false), nil, nil)
-	_, err = buildfile.Build(mkTestContext(dockerfile, context.files, t))
+	_, err = buildfile.Build(context.Archive(dockerfile, t))
 
 	if err == nil {
 		t.Log("Error should not be nil")

+ 1 - 1
server.go

@@ -476,7 +476,7 @@ func (srv *Server) Build(job *engine.Job) engine.Status {
 		if err != nil {
 			return job.Error(err)
 		}
-		c, err := MkBuildContext(string(dockerFile), nil)
+		c, err := archive.Generate("Dockerfile", string(dockerFile))
 		if err != nil {
 			return job.Error(err)
 		}