Пример #1
0
func TestBuilderEnsureContainer(t *testing.T) {
	t.Skip()

	// we will need docker client to cleanup and do some cross-checks
	client, err := dockerclient.New()
	if err != nil {
		t.Fatal(err)
	}

	builder := &Builder{
		OutStream: util.PrefixPipe("[TEST] ", os.Stdout),
		Docker:    client,
		Auth:      &docker.AuthConfiguration{},
	}

	containerConfig := &docker.Config{
		Image: "grammarly/rsync-static:1",
	}
	containerName := "rocker_TestBuilderEnsureContainer"

	defer func() {
		if err := client.RemoveContainer(docker.RemoveContainerOptions{ID: containerName, Force: true}); err != nil {
			t.Fatal(err)
		}
	}()

	if _, err := builder.ensureContainer(containerName, containerConfig, "testing"); err != nil {
		t.Fatal(err)
	}

	assert.Equal(t, "", "")
}
Пример #2
0
func TestBuilderBuildInclude(t *testing.T) {

	tempDir, err := ioutil.TempDir("/tmp", "rocker_TestBuilderBuildInclude_")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tempDir)

	err = test.MakeFiles(tempDir, map[string]string{
		"/nodejs": `
RUN touch /test/bin/nodejs
RUN touch /test/bin/npm
`,
		"/java": `
RUN touch /test/bin/java
RUN touch /test/bin/gradle
`,
		"/Rockerfile": `
FROM busybox:buildroot-2013.08.1
RUN mkdir -p /test/bin
INCLUDE nodejs
INCLUDE java
CMD ["ls", "/test/bin"]
`,
	})

	// we will need docker client to cleanup and do some cross-checks
	client, err := dockerclient.New()
	if err != nil {
		t.Fatal(err)
	}

	builder := &Builder{
		Rockerfile: tempDir + "/Rockerfile",
		OutStream:  util.PrefixPipe("[TEST] ", os.Stdout),
		Docker:     client,
	}

	imageID, err := builder.Build()
	if err != nil {
		t.Fatal(err)
	}
	t.Logf("Got imageID: %s", imageID)

	defer func() {
		if err := client.RemoveImageExtended(imageID, docker.RemoveImageOptions{Force: true}); err != nil {
			t.Log(err)
		}
	}()

	result, err := runContainer(t, client, &docker.Config{
		Image: imageID,
	}, nil)

	t.Logf("Got result: %q", result)

	assert.Equal(t, "gradle\njava\nnodejs\nnpm\n", result, "expected result (ls) to contain included files")
}
Пример #3
0
func TestBuilderBuildRequire(t *testing.T) {

	tempDir, err := ioutil.TempDir("/tmp", "rocker_TestBuilderBuildRequire_")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tempDir)

	err = test.MakeFiles(tempDir, map[string]string{
		"/Rockerfile": `FROM busybox:buildroot-2013.08.1
REQUIRE version
RUN echo "$version" > /testing
CMD cat /testing`,
	})

	// we will need docker client to cleanup and do some cross-checks
	client, err := dockerclient.New()
	if err != nil {
		t.Fatal(err)
	}

	run := func(vars []string) (string, error) {
		tlpVars, err := template.VarsFromStrings(vars)
		if err != nil {
			return "", err
		}

		builder := &Builder{
			Rockerfile: tempDir + "/Rockerfile",
			OutStream:  util.PrefixPipe("[TEST] ", os.Stdout),
			Docker:     client,
			Vars:       tlpVars,
		}

		imageID, err := builder.Build()
		if err != nil {
			return "", err
		}
		t.Logf("Got imageID: %s", imageID)

		defer func() {
			if err := client.RemoveImageExtended(imageID, docker.RemoveImageOptions{Force: true}); err != nil {
				t.Log(err)
			}
		}()

		return runContainer(t, client, &docker.Config{
			Image: imageID,
		}, nil)
	}

	_, err1 := run([]string{})
	result, err2 := run([]string{"version=123"})

	assert.Equal(t, "Var $version is required but not set", err1.Error())
	assert.Nil(t, err2, "expected second run to not give error")
	assert.Equal(t, "123\n", result)
}
Пример #4
0
func TestBuilderBuildVars(t *testing.T) {

	tempDir, err := ioutil.TempDir("/tmp", "rocker_TestBuilderBuildVars_")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tempDir)

	err = test.MakeFiles(tempDir, map[string]string{
		"/Rockerfile": `FROM busybox:buildroot-2013.08.1
RUN echo "version:$version" > /version`,
	})

	// we will need docker client to cleanup and do some cross-checks
	client, err := dockerclient.New()
	if err != nil {
		t.Fatal(err)
	}

	vars, err := template.VarsFromStrings([]string{"version=125"})
	if err != nil {
		t.Fatal(err)
	}

	builder := &Builder{
		Rockerfile: tempDir + "/Rockerfile",
		OutStream:  util.PrefixPipe("[TEST] ", os.Stdout),
		Vars:       vars,
		// Push:       true,
		Docker: client,
	}

	imageID, err := builder.Build()
	if err != nil {
		t.Fatal(err)
	}
	t.Logf("Got imageID: %s", imageID)

	defer func() {
		if err := client.RemoveImageExtended(imageID, docker.RemoveImageOptions{Force: true}); err != nil {
			t.Log(err)
		}
	}()

	result, err := runContainer(t, client, &docker.Config{
		Image: imageID,
		Cmd:   []string{"cat", "/version"},
	}, nil)

	assert.Equal(t, "version:125\n", result, "failed")
}
Пример #5
0
func TestBuilderMountFromHost(t *testing.T) {

	wd, err := os.Getwd()
	if err != nil {
		t.Fatal(err)
	}

	// Use current working directroy as a temp dir to make MOUNT work in boot2docker
	tempDir, err := ioutil.TempDir(wd, "rocker_TestBuilderMountFromHost_")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tempDir)

	err = test.MakeFiles(tempDir, map[string]string{
		"/Rockerfile": `FROM busybox:buildroot-2013.08.1
MOUNT .:/src
RUN echo "hello" > /src/test`,
	})

	// we will need docker client to cleanup and do some cross-checks
	client, err := dockerclient.New()
	if err != nil {
		t.Fatal(err)
	}

	builder := &Builder{
		Rockerfile: tempDir + "/Rockerfile",
		OutStream:  util.PrefixPipe("[TEST] ", os.Stdout),
		Docker:     client,
	}

	imageID, err := builder.Build()
	if err != nil {
		t.Fatal(err)
	}
	t.Logf("Got imageID: %s", imageID)

	defer func() {
		if err := client.RemoveImageExtended(imageID, docker.RemoveImageOptions{Force: true}); err != nil {
			t.Log(err)
		}
	}()

	content, err := ioutil.ReadFile(tempDir + "/test")
	if err != nil {
		t.Fatal(err)
	}

	assert.Equal(t, "hello\n", string(content))
}
Пример #6
0
func TestBuilderBuildTag(t *testing.T) {

	tempDir, err := ioutil.TempDir("/tmp", "rocker_TestBuilderBuildTag_")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tempDir)

	err = test.MakeFiles(tempDir, map[string]string{
		"/Rockerfile": `FROM busybox:buildroot-2013.08.1
TAG testing
RUN touch /testing
PUSH quay.io/testing_project`,
	})

	// we will need docker client to cleanup and do some cross-checks
	client, err := dockerclient.New()
	if err != nil {
		t.Fatal(err)
	}

	builder := &Builder{
		Rockerfile: tempDir + "/Rockerfile",
		OutStream:  util.PrefixPipe("[TEST] ", os.Stdout),
		Docker:     client,
	}

	imageID, err := builder.Build()
	if err != nil {
		t.Fatal(err)
	}
	t.Logf("Got imageID: %s", imageID)

	defer func() {
		if err := client.RemoveImageExtended(imageID, docker.RemoveImageOptions{Force: true}); err != nil {
			t.Log(err)
		}
	}()

	result, err := runContainer(t, client, &docker.Config{
		Image: imageID,
		Cmd:   []string{"ls", "/"},
	}, nil)

	t.Logf("Got result: %s", result)

	assert.Equal(t, "true", "true", "failed")
}
Пример #7
0
func TestBuilderBuildGitWarning(t *testing.T) {
	t.Skip()

	tempDir, err := ioutil.TempDir("/tmp", "rocker_TestBuilderBuildGitWarning_")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tempDir)

	err = test.MakeFiles(tempDir, map[string]string{
		"/.git/HEAD": "hello",
		"/testing":   "hello2",
		"/Rockerfile": `FROM busybox:buildroot-2013.08.1
ADD . /`,
	})

	// we will need docker client to cleanup and do some cross-checks
	client, err := dockerclient.New()
	if err != nil {
		t.Fatal(err)
	}

	builder := &Builder{
		Rockerfile: tempDir + "/Rockerfile",
		OutStream:  util.PrefixPipe("[TEST] ", os.Stdout),
		Docker:     client,
	}

	imageID, err := builder.Build()
	if err != nil {
		t.Fatal(err)
	}
	t.Logf("Got imageID: %s", imageID)

	defer func() {
		if err := client.RemoveImageExtended(imageID, docker.RemoveImageOptions{Force: true}); err != nil {
			t.Log(err)
		}
	}()

	result, err := runContainer(t, client, &docker.Config{
		Image: imageID,
	}, nil)

	t.Logf("Got result: %q", result)

	assert.Contains(t, result, "testing", "expected result (ls) to contain testing file")
}
Пример #8
0
func TestBuilderBuildSemverTag(t *testing.T) {

	tempDir, err := ioutil.TempDir("/tmp", "rocker_TestBuilderBuildSemverTag_")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tempDir)

	err = test.MakeFiles(tempDir, map[string]string{
		"/Rockerfile": `FROM scratch
TAG --semver testing:1.2.3-build123`,
	})

	// we will need docker client to cleanup and do some cross-checks
	client, err := dockerclient.New()
	if err != nil {
		t.Fatal(err)
	}

	builder := &Builder{
		Rockerfile: tempDir + "/Rockerfile",
		OutStream:  util.PrefixPipe("[TEST] ", os.Stdout),
		Docker:     client,
		// Vars:       VarsFromStrings([]string{"branch=master", "commit=314ad"}),
	}

	imageID, err := builder.Build()
	if err != nil {
		t.Fatal(err)
	}
	t.Logf("Got imageID: %s", imageID)

	defer func() {
		if err := client.RemoveImageExtended(imageID, docker.RemoveImageOptions{Force: true}); err != nil {
			t.Log(err)
		}
	}()

	result, err := runContainer(t, client, &docker.Config{
		Image: imageID,
		Cmd:   []string{"ls", "/"},
	}, nil)

	t.Logf("Got result: %s", result)

	assert.Equal(t, "true", "true", "failed")
}
Пример #9
0
func TestBuilderBuildAttach(t *testing.T) {
	t.Skip()

	tempDir, err := ioutil.TempDir("/tmp", "rocker_TestBuilderBuildAttach_")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tempDir)

	err = test.MakeFiles(tempDir, map[string]string{
		"/Rockerfile": `FROM busybox:buildroot-2013.08.1
CMD ["/bin/sh"]
ATTACH --name=test-attach ["ls", "-la"]`,
	})

	// we will need docker client to cleanup and do some cross-checks
	client, err := dockerclient.New()
	if err != nil {
		t.Fatal(err)
	}

	builder := &Builder{
		Rockerfile: tempDir + "/Rockerfile",
		InStream:   os.Stdin,
		OutStream:  util.PrefixPipe("[TEST] ", os.Stdout),
		Docker:     client,
		Attach:     true,
	}

	imageID, err := builder.Build()
	if err != nil {
		t.Fatal(err)
	}
	t.Logf("Got imageID: %s", imageID)

	defer func() {
		if err := client.RemoveImageExtended(imageID, docker.RemoveImageOptions{Force: true}); err != nil {
			t.Log(err)
		}
	}()
}
Пример #10
0
func TestBuilderEnsureImage(t *testing.T) {
	t.Skip()

	// we will need docker client to cleanup and do some cross-checks
	client, err := dockerclient.New()
	if err != nil {
		t.Fatal(err)
	}

	builder := &Builder{
		OutStream: util.PrefixPipe("[TEST] ", os.Stdout),
		Docker:    client,
		Auth:      &docker.AuthConfiguration{},
	}

	image := "busybox:buildroot-2013.08.1"

	if err := builder.ensureImage(image, "testing"); err != nil {
		t.Fatal(err)
	}

	assert.Equal(t, "", "")
}
Пример #11
0
func TestBuilderBuildVar(t *testing.T) {

	tempDir, err := ioutil.TempDir("/tmp", "rocker_TestBuilderBuildVar_")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tempDir)

	err = test.MakeFiles(tempDir, map[string]string{
		"/Rockerfile": `FROM busybox:buildroot-2013.08.1
VAR test=true
RUN touch /testing
RUN if [ "$test" == "true" ] ; then echo "done test" > /testing; fi
CMD cat /testing`,
	})

	// we will need docker client to cleanup and do some cross-checks
	client, err := dockerclient.New()
	if err != nil {
		t.Fatal(err)
	}

	run := func(vars []string) (string, error) {
		tplVars, err := template.VarsFromStrings(vars)
		if err != nil {
			return "", err
		}

		builder := &Builder{
			Rockerfile: tempDir + "/Rockerfile",
			OutStream:  util.PrefixPipe("[TEST] ", os.Stdout),
			Docker:     client,
			Vars:       tplVars,
		}

		imageID, err := builder.Build()
		if err != nil {
			return "", err
		}
		t.Logf("Got imageID: %s", imageID)

		defer func() {
			if err := client.RemoveImageExtended(imageID, docker.RemoveImageOptions{Force: true}); err != nil {
				t.Log(err)
			}
		}()

		return runContainer(t, client, &docker.Config{
			Image: imageID,
		}, nil)
	}

	result1, err := run([]string{})
	if err != nil {
		t.Fatal(err)
	}

	result2, err := run([]string{"test=false"})
	if err != nil {
		t.Fatal(err)
	}

	assert.Equal(t, "done test\n", result1)
	assert.Equal(t, "", result2)
}
Пример #12
0
func TestBuilderImportFromScratch(t *testing.T) {

	tempDir, err := ioutil.TempDir("/tmp", "rocker_TestBuilderImportFromScratch_")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tempDir)

	err = test.MakeFiles(tempDir, map[string]string{
		"/Rockerfile": `
FROM busybox:buildroot-2013.08.1
RUN mkdir -p /zzz && echo "hi" > /zzz/lalala
EXPORT zzz /

FROM scratch
IMPORT zzz /
CMD ["true"]
`,
	})

	// we will need docker client to cleanup and do some cross-checks
	client, err := dockerclient.New()
	if err != nil {
		t.Fatal(err)
	}

	builder := &Builder{
		Rockerfile: tempDir + "/Rockerfile",
		OutStream:  util.PrefixPipe("[TEST] ", os.Stdout),
		Docker:     client,
	}

	imageID, err := builder.Build()
	if err != nil {
		t.Fatal(err)
	}
	t.Logf("Got imageID: %s", imageID)

	defer func() {
		if err := client.RemoveImageExtended(imageID, docker.RemoveImageOptions{Force: true}); err != nil {
			t.Log(err)
		}
	}()

	// Create data volume container with scratch image
	c, err := client.CreateContainer(docker.CreateContainerOptions{
		Config: &docker.Config{
			Image: imageID,
			Volumes: map[string]struct{}{
				"/zzz": struct{}{},
			},
		},
	})
	if err != nil {
		t.Fatal(err)
	}
	defer func() {
		if err := client.RemoveContainer(docker.RemoveContainerOptions{ID: c.ID, RemoveVolumes: true, Force: true}); err != nil {
			t.Log(err)
		}
	}()

	result, err := runContainer(t, client, &docker.Config{
		Image: "busybox:buildroot-2013.08.1",
		Cmd:   []string{"/bin/sh", "-c", "cat /zzz/lalala"},
	}, &docker.HostConfig{
		VolumesFrom: []string{c.ID},
	})

	t.Logf("Got result: %q", result)

	assert.Equal(t, "hi\n", result)
}
Пример #13
0
func TestBuilderBuildContainerVolume(t *testing.T) {

	tempDir, err := ioutil.TempDir("/tmp", "rocker_TestBuilderBuildContainerVolume_")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tempDir)

	err = test.MakeFiles(tempDir, map[string]string{
		"/Rockerfile": `FROM busybox:buildroot-2013.08.1
MOUNT /cache
RUN echo "hello" >> /cache/output.log
RUN cp /cache/output.log /result_cache.log
CMD cat /result_cache.log`,
	})

	// we will need docker client to cleanup and do some cross-checks
	client, err := dockerclient.New()
	if err != nil {
		t.Fatal(err)
	}

	// Step 1

	runUtilizeCache := func(utilizeCache bool) (result string, err error) {
		builder := &Builder{
			Rockerfile:   tempDir + "/Rockerfile",
			OutStream:    util.PrefixPipe("[TEST] ", os.Stdout),
			UtilizeCache: utilizeCache,
			Docker:       client,
		}

		imageID, err := builder.Build()
		if err != nil {
			return "", err
		}
		t.Logf("Got imageID: %s", imageID)

		// Cleanup mount containers
		defer func() {
			for _, mountContainerID := range builder.getAllMountContainerIds() {
				if err := client.RemoveContainer(docker.RemoveContainerOptions{
					ID:            mountContainerID,
					RemoveVolumes: true,
					Force:         true,
				}); err != nil {
					t.Log(err)
				}
			}
		}()

		defer func() {
			if err := client.RemoveImageExtended(imageID, docker.RemoveImageOptions{Force: true}); err != nil {
				t.Log(err)
			}
		}()

		// Step 2

		builder2 := &Builder{
			Rockerfile:   tempDir + "/Rockerfile",
			OutStream:    util.PrefixPipe("[TEST] ", os.Stdout),
			UtilizeCache: utilizeCache,
			Docker:       client,
		}

		imageID2, err := builder2.Build()
		if err != nil {
			return "", err
		}
		t.Logf("Got imageID2: %s", imageID2)

		defer func() {
			if err := client.RemoveImageExtended(imageID2, docker.RemoveImageOptions{Force: true}); err != nil {
				t.Log(err)
			}
		}()

		return runContainer(t, client, &docker.Config{
			Image: imageID2,
		}, nil)
	}

	result1, err := runUtilizeCache(true)
	if err != nil {
		t.Fatal(err)
	}
	assert.Equal(t, "hello\n", result1, "failed")

	result2, err := runUtilizeCache(false)
	if err != nil {
		t.Fatal(err)
	}
	assert.Equal(t, "hello\nhello\n", result2, "failed")
}
Пример #14
0
func TestBuilderBuildMultiple(t *testing.T) {

	tempDir, err := ioutil.TempDir("/tmp", "rocker_TestBuilderBuildMultiple_")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tempDir)

	err = test.MakeFiles(tempDir, map[string]string{
		"/index.js":    "console.log('hello')",
		"/data/README": "hello",
		"/Rockerfile": `
FROM busybox:buildroot-2013.08.1
ADD . /app
MOUNT /app/node_modules
RUN echo "hehe" > /app/node_modules/some_module && \
		cd /app/node_modules && \
		ln -sf some_module link_to_some_module
EXPORT /app
FROM busybox:buildroot-2013.08.1
IMPORT /app
		`,
	})
	if err != nil {
		t.Fatal(err)
	}

	imageIDs := make(map[string]struct{})
	mounts := make(map[string]struct{})

	// we will need docker client to cleanup and do some cross-checks
	client, err := dockerclient.New()
	if err != nil {
		t.Fatal(err)
	}

	run := func() (imageID string, err error) {

		builder := &Builder{
			Rockerfile:   tempDir + "/Rockerfile",
			UtilizeCache: true,
			OutStream:    util.PrefixPipe("[TEST] ", os.Stdout),
			Docker:       client,
		}

		defer func() {
			for _, mountContainerID := range builder.getAllMountContainerIds() {
				if mountContainerID != "" {
					mounts[mountContainerID] = struct{}{}
				}
			}
		}()

		imageID, err = builder.Build()
		if err != nil {
			return "", err
		}
		t.Logf("Got imageID: %s", imageID)

		imageIDs[imageID] = struct{}{}

		for _, imageID := range builder.intermediateImages {
			imageIDs[imageID] = struct{}{}
		}

		return imageID, nil
	}

	defer func() {
		for imageID := range imageIDs {
			if err := client.RemoveImageExtended(imageID, docker.RemoveImageOptions{Force: true}); err != nil {
				t.Log(err)
			}
		}
	}()

	// Cleanup mount containers
	defer func() {
		for mountContainerID := range mounts {
			if err := client.RemoveContainer(docker.RemoveContainerOptions{
				ID:            mountContainerID,
				RemoveVolumes: true,
				Force:         true,
			}); err != nil {
				t.Log(err)
			}
		}
	}()

	imageID1, err := run()
	if err != nil {
		t.Fatal(err)
	}

	fmt.Println("============================================================")

	imageID2, err := run()
	if err != nil {
		t.Fatal(err)
	}

	assert.Equal(t, imageID1, imageID2, "expected images to be equal (valid caching behavior)")
}
Пример #15
0
func TestBuilderBuildMounts(t *testing.T) {

	tempDir, err := ioutil.TempDir("/tmp", "rocker_TestBuilderBuildTag_")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tempDir)

	err = test.MakeFiles(tempDir, map[string]string{
		"/Rockerfile": `FROM busybox:buildroot-2013.08.1
MOUNT /app/node_modules /app/bower_components
RUN ls /app > /out
CMD cat /out`,
	})

	// we will need docker client to cleanup and do some cross-checks
	client, err := dockerclient.New()
	if err != nil {
		t.Fatal(err)
	}

	builder := &Builder{
		Rockerfile: tempDir + "/Rockerfile",
		OutStream:  util.PrefixPipe("[TEST] ", os.Stdout),
		Docker:     client,
	}

	imageID, err := builder.Build()
	if err != nil {
		t.Fatal(err)
	}
	t.Logf("Got imageID: %s", imageID)

	defer func() {
		if err := client.RemoveImageExtended(imageID, docker.RemoveImageOptions{Force: true}); err != nil {
			t.Log(err)
		}
	}()

	// Cleanup mount containers
	defer func() {
		for _, mountContainerID := range builder.getAllMountContainerIds() {
			if err := client.RemoveContainer(docker.RemoveContainerOptions{
				ID:            mountContainerID,
				RemoveVolumes: true,
				Force:         true,
			}); err != nil {
				t.Log(err)
			}
		}
	}()

	result, err := runContainer(t, client, &docker.Config{
		Image: imageID,
	}, nil)

	t.Logf("Got result: %s", result)

	assert.Equal(t, "bower_components\nnode_modules\n", result, "expected both volumes to be mounted")
	assert.Equal(t, 1, len(builder.getMountContainerIds()), "expected only one volume container to be created")
}
Пример #16
0
func TestBuilderBuildTagLabels(t *testing.T) {

	tempDir, err := ioutil.TempDir("/tmp", "rocker_TestBuilderBuildTagLabels_")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tempDir)

	rockerfileContent := `FROM busybox:buildroot-2013.08.1
TAG testing
RUN touch /testing
LABEL foo=bar
PUSH quay.io/testing_project`

	err = test.MakeFiles(tempDir, map[string]string{
		"/Rockerfile": rockerfileContent,
	})

	// we will need docker client to cleanup and do some cross-checks
	client, err := dockerclient.New()
	if err != nil {
		t.Fatal(err)
	}

	vars, err := template.VarsFromStrings([]string{"asd=qwe"})
	if err != nil {
		t.Fatal(err)
	}

	builder := &Builder{
		Rockerfile: tempDir + "/Rockerfile",
		OutStream:  util.PrefixPipe("[TEST] ", os.Stdout),
		CliVars:    vars,
		Docker:     client,
		AddMeta:    true,
	}

	imageID, err := builder.Build()
	if err != nil {
		t.Fatal(err)
	}
	t.Logf("Got imageID: %s", imageID)

	defer func() {
		if err := client.RemoveImageExtended(imageID, docker.RemoveImageOptions{Force: true}); err != nil {
			t.Log(err)
		}
	}()

	inspect, err := client.InspectImage(imageID)
	if err != nil {
		t.Fatal(err)
	}

	// test inherited labels
	assert.Equal(t, "bar", inspect.Config.Labels["foo"])

	// test rockerfile content
	data := &RockerImageData{}
	if err := json.Unmarshal([]byte(inspect.Config.Labels["rocker-data"]), data); err != nil {
		t.Fatal(err)
	}
	assert.Equal(t, rockerfileContent, data.Rockerfile)

	// test vars
	assert.Equal(t, vars, data.Vars)
}
Пример #17
0
func TestBuilderBuildAddCache(t *testing.T) {

	tempDir, err := ioutil.TempDir("/tmp", "rocker_TestBuilderBuildAddCache_")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tempDir)

	err = test.MakeFiles(tempDir, map[string]string{
		"/data/README": "hello",
		"/Rockerfile": `
FROM busybox:buildroot-2013.08.1
ADD . /src
RUN ls -la /src
`,
	})
	if err != nil {
		t.Fatal(err)
	}

	var imageIDs []string

	// we will need docker client to cleanup and do some cross-checks
	client, err := dockerclient.New()
	if err != nil {
		t.Fatal(err)
	}

	run := func() (imageID string, err error) {

		builder := &Builder{
			Rockerfile:   tempDir + "/Rockerfile",
			UtilizeCache: true,
			OutStream:    util.PrefixPipe("[TEST] ", os.Stdout),
			Docker:       client,
		}

		imageID, err = builder.Build()
		if err != nil {
			return "", err
		}
		t.Logf("Got imageID: %s", imageID)

		imageIDs = append(imageIDs, imageID)

		return imageID, nil
	}

	defer func() {
		for _, imageID := range imageIDs {
			if err := client.RemoveImageExtended(imageID, docker.RemoveImageOptions{Force: true}); err != nil {
				t.Log(err)
			}
		}
	}()

	imageID1, err := run()
	if err != nil {
		t.Fatal(err)
	}

	time.Sleep(time.Second)

	imageID2, err := run()
	if err != nil {
		t.Fatal(err)
	}

	assert.Equal(t, imageID1, imageID2, "expected images to be equal (valid caching behavior)")
}
Пример #18
0
func (builder *Builder) runContainerAttachStdin(containerID string, attachStdin bool) error {
	success := make(chan struct{})

	attachOpts := docker.AttachToContainerOptions{
		Container:    containerID,
		OutputStream: util.PrefixPipe("[Docker] ", builder.OutStream),
		ErrorStream:  util.PrefixPipe("[Docker] ", builder.OutStream),
		Stdout:       true,
		Stderr:       true,
		Stream:       true,
		Success:      success,
	}

	if attachStdin {
		if !builder.isTerminalIn {
			return fmt.Errorf("Cannot attach to a container on non tty input")
		}
		oldState, err := term.SetRawTerminal(builder.fdIn)
		if err != nil {
			return err
		}
		defer term.RestoreTerminal(builder.fdIn, oldState)

		attachOpts.InputStream = readerVoidCloser{builder.InStream}
		attachOpts.OutputStream = builder.OutStream
		attachOpts.ErrorStream = builder.OutStream
		attachOpts.Stdin = true
		attachOpts.RawTerminal = true
	}

	finished := make(chan struct{}, 1)

	go func() {
		if err := builder.Docker.AttachToContainer(attachOpts); err != nil {
			select {
			case <-finished:
				// Ignore any attach errors when we have finished already.
				// It may happen if we attach stdin, then container exit, but then there is other input from stdin continues.
				// This is the case when multiple ATTACH command are used in a single Rockerfile.
				// The problem though is that we cannot close stdin, to have it available for the subsequent ATTACH;
				// therefore, hijack goroutine from the previous ATTACH will hang until the input received and then
				// it will fire an error.
				// It's ok for `rocker` since it is not a daemon, but rather a one-off command.
				//
				// Also, there is still a problem that `rocker` loses second character from the Stdin in a second ATTACH.
				// But let's consider it a corner case.
			default:
				// Print the error. We cannot return it because the main routine is handing on WaitContaienr
				fmt.Fprintf(builder.OutStream, "Got error while attaching to container %s: %s\n", containerID, err)
			}
		}
	}()

	success <- <-success

	if err := builder.Docker.StartContainer(containerID, &docker.HostConfig{}); err != nil {
		return err
	}

	if attachStdin {
		if err := builder.monitorTtySize(containerID); err != nil {
			return fmt.Errorf("Failed to monitor TTY size for container %s, error: %s", containerID, err)
		}
	}

	sigch := make(chan os.Signal, 1)
	signal.Notify(sigch, os.Interrupt)

	errch := make(chan error)

	go func() {
		statusCode, err := builder.Docker.WaitContainer(containerID)
		if err != nil {
			errch <- err
		} else if statusCode != 0 {
			errch <- fmt.Errorf("Failed to run container, exit with code %d", statusCode)
		}
		errch <- nil
		return
	}()

	select {
	case err := <-errch:
		// indicate 'finished' so the `attach` goroutine will not give any errors
		finished <- struct{}{}
		if err != nil {
			return err
		}
	case <-sigch:
		fmt.Fprintf(builder.OutStream, "[Rocker] Received SIGINT, remove current container...\n")
		if err := builder.removeContainer(containerID); err != nil {
			fmt.Fprintf(builder.OutStream, "[Rocker] Failed to remove container: %s\n", err)
		}
		// TODO: send signal to builder.Build() and have a proper cleanup
		os.Exit(2)
	}

	return nil
}