Skip to content

Commit

Permalink
Add lifecycle binaries to builder during create-builder
Browse files Browse the repository at this point in the history
* Add Downloader for generic artifact downloads
* Add lifecycle fetcher

Signed-off-by: Andrew Meyer <ameyer@pivotal.io>
Signed-off-by: Danny Joyce <djoyce@pivotal.io>
Signed-off-by: Emily Casey <ecasey@pivotal.io>
  • Loading branch information
ameyer-pivotal authored and Danny Joyce committed May 2, 2019
1 parent e03fb14 commit 6ed36d1
Show file tree
Hide file tree
Showing 59 changed files with 1,010 additions and 447 deletions.
99 changes: 49 additions & 50 deletions acceptance/acceptance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,19 @@ import (

"github.com/buildpack/pack/archive"
"github.com/buildpack/pack/cache"
"github.com/buildpack/pack/lifecycle"
h "github.com/buildpack/pack/testhelpers"
)

var (
packPath string
dockerCli *client.Client
registryConfig *h.TestRegistryConfig
lifecycleVersion = "0.1.0"
runImage = "pack-test/run"
buildImage = "pack-test/build"
runImageMirror string
packHome string
builder string
lifecycleVersion = lifecycle.DefaultLifecycleVersion
)

func TestAcceptance(t *testing.T) {
Expand All @@ -64,15 +64,11 @@ func TestAcceptance(t *testing.T) {
}
defer os.RemoveAll(packTmpDir)
}

var err error
dockerCli, err = client.NewClientWithOpts(client.FromEnv, client.WithVersion("1.38"))
h.AssertNil(t, err)
registryConfig = h.RunRegistry(t, false)
defer registryConfig.StopRegistry(t)
if version, ok := os.LookupEnv("LIFECYCLE_VERSION"); ok {
lifecycleVersion = version
}
runImageMirror = registryConfig.RepoName(runImage)
createStack(t, dockerCli)
builder = createBuilder(t, runImageMirror)
Expand Down Expand Up @@ -134,7 +130,7 @@ func testAcceptance(t *testing.T, when spec.G, it spec.S) {
dockerCli.ContainerKill(context.TODO(), containerName, "SIGKILL")
dockerCli.ContainerRemove(context.TODO(), containerName, dockertypes.ContainerRemoveOptions{Force: true})
dockerCli.ImageRemove(context.TODO(), repoName, dockertypes.ImageRemoveOptions{Force: true, PruneChildren: true})
ref, err := name.ParseReference(repoName, name.WeakValidation)
ref, err := name.ParseReference(repoName, name.WeakValidation)
h.AssertNil(t, err)
cacheImage := cache.New(ref, dockerCli)
cacheImage.Clear(context.TODO())
Expand All @@ -161,7 +157,7 @@ func testAcceptance(t *testing.T, when spec.G, it spec.S) {
assertMockAppRunsWithOutput(t, repoName, "Launch Dep Contents", "Cached Dep Contents")

t.Log("it uses the default run image as a base image")
assertHasBase(t, repoName, "packs/run:"+lifecycleVersion)
assertHasBase(t, repoName, runImage)

t.Log("sets the run image metadata")
runImageLabel := imageLabel(t, dockerCli, repoName, metadata.AppMetadataLabel)
Expand Down Expand Up @@ -190,8 +186,8 @@ func testAcceptance(t *testing.T, when spec.G, it spec.S) {
h.AssertContainsMatch(t, output, `\[analyzer] using cached launch layer 'simple/layers:cached-launch-layer'`)

t.Log("exporter and cacher reuse unchanged layers")
h.AssertContainsMatch(t, output, `\[exporter] reusing layer 'simple/layers:cached-launch-layer'`)
h.AssertContainsMatch(t, output, `\[cacher] reusing layer 'simple/layers:cached-launch-layer'`)
h.AssertContainsMatch(t, output, `(?i)\[exporter] reusing layer 'simple/layers:cached-launch-layer'`)
h.AssertContainsMatch(t, output, `(?i)\[cacher] reusing layer 'simple/layers:cached-launch-layer'`)

t.Log("rebuild with --clear-cache")
cmd = packCmd("build", repoName, "-p", "testdata/mock_app/.", "--clear-cache")
Expand All @@ -205,10 +201,14 @@ func testAcceptance(t *testing.T, when spec.G, it spec.S) {
h.AssertContains(t, output, "Skipping 'analyze' due to clearing cache")

t.Log("exporter reuses unchanged layers")
h.AssertContainsMatch(t, output, `\[exporter] reusing layer 'simple/layers:cached-launch-layer'`)
h.AssertContainsMatch(t, output, `(?i)\[exporter] reusing layer 'simple/layers:cached-launch-layer'`)

t.Log("cacher adds layers")
h.AssertContainsMatch(t, output, `\[cacher] adding layer 'simple/layers:cached-launch-layer'`)
if lifecycleVersion == "0.1.0" {
h.AssertContainsMatch(t, output, `\[cacher] adding layer 'simple/layers:cached-launch-layer'`)
} else {
h.AssertContainsMatch(t, output, `\[cacher] Caching layer 'simple/layers:cached-launch-layer'`)
}
})

when("--buildpack", func() {
Expand Down Expand Up @@ -677,38 +677,18 @@ func testAcceptance(t *testing.T, when spec.G, it spec.S) {

when("pack inspect-builder", func() {
it("displays configuration for a builder (local and remote)", func() {
configuredRunImage := "some-registry.com/some/run1"

builderImageName := h.CreateImageOnRemote(t, dockerCli, registryConfig, "some/builder",
fmt.Sprintf(`
FROM scratch
ENV CNB_USER_ID=1234
ENV CNB_GROUP_ID=4321
LABEL %s="{\"stack\":{\"runImage\":{\"image\":\"some/run1\",\"mirrors\":[\"gcr.io/some/run1\"]}},\"buildpacks\":[{\"id\":\"test.bp.one\",\"version\":\"0.0.1\",\"latest\":false},{\"id\":\"test.bp.two\",\"version\":\"0.0.2\",\"latest\":true}],\"groups\":[{\"buildpacks\":[{\"id\":\"test.bp.one\",\"version\":\"0.0.1\"},{\"id\":\"test.bp.two\",\"version\":\"0.0.2\"}]},{\"buildpacks\":[{\"id\":\"test.bp.one\",\"version\":\"0.0.1\"}]}]}"
LABEL io.buildpacks.stack.id=some.test.stack
`, "io.buildpacks.builder.metadata"))

h.CreateImageOnLocal(t, dockerCli, builderImageName,
fmt.Sprintf(`
FROM scratch
ENV CNB_USER_ID=1234
ENV CNB_GROUP_ID=4321
LABEL %s="{\"stack\":{\"runImage\":{\"image\":\"some/run1\",\"mirrors\":[\"gcr.io/some/run2\"]}},\"buildpacks\":[{\"id\":\"test.bp.one\",\"version\":\"0.0.1\",\"latest\":false},{\"id\":\"test.bp.two\",\"version\":\"0.0.2\",\"latest\":true}],\"groups\":[{\"buildpacks\":[{\"id\":\"test.bp.one\",\"version\":\"0.0.1\"},{\"id\":\"test.bp.two\",\"version\":\"0.0.2\"}]},{\"buildpacks\":[{\"id\":\"test.bp.one\",\"version\":\"0.0.1\"}]}]}"
LABEL io.buildpacks.stack.id=some.test.stack
`, "io.buildpacks.builder.metadata"))
defer h.DockerRmi(dockerCli, builderImageName)

cmd := packCmd("set-run-image-mirrors", "some/run1", "--mirror", configuredRunImage)
configuredRunImage := "some-registry.com/pack-test/run1"
cmd := packCmd("set-run-image-mirrors", "pack-test/run", "--mirror", configuredRunImage)
output := h.Run(t, cmd)
h.AssertEq(t, output, "Run Image 'some/run1' configured with mirror 'some-registry.com/some/run1'\n")
h.AssertEq(t, output, "Run Image 'pack-test/run' configured with mirror 'some-registry.com/pack-test/run1'\n")

cmd = packCmd("inspect-builder", builderImageName)
cmd = packCmd("inspect-builder", builder)
output = h.Run(t, cmd)

expected, err := ioutil.ReadFile(filepath.Join("testdata", "inspect_builder_output.txt"))
h.AssertNil(t, err)

h.AssertEq(t, output, fmt.Sprintf(string(expected), builderImageName))
h.AssertEq(t, output, fmt.Sprintf(string(expected), builder, lifecycleVersion, runImageMirror, lifecycleVersion, runImageMirror))
})
})
}
Expand All @@ -720,29 +700,48 @@ func createBuilder(t *testing.T, runImageMirror string) string {
tmpDir, err := ioutil.TempDir("", "create-test-builder")
h.AssertNil(t, err)
defer os.RemoveAll(tmpDir)

h.RecursiveCopy(t, filepath.Join("testdata", "mock_buildpacks"), tmpDir)

builderConfigFile, err := os.OpenFile(filepath.Join(tmpDir, "builder.toml"), os.O_RDWR|os.O_APPEND, 0666)
h.AssertNil(t, err)
_, err = builderConfigFile.Write([]byte(
fmt.Sprintf(`run-image-mirrors = ["%s"]`, runImageMirror)))

_, err = builderConfigFile.Write([]byte(fmt.Sprintf("run-image-mirrors = [\"%s\"]\n", runImageMirror)))
h.AssertNil(t, err)

_, err = builderConfigFile.Write([]byte("[lifecycle]\n"))
h.AssertNil(t, err)
if lifecyclePath, ok := os.LookupEnv("LIFECYCLE_PATH"); ok {
lifecycleVersion = "Unknown"
if !filepath.IsAbs(lifecyclePath) {
t.Fatal("LIFECYCLE_PATH must be an absolute path")
}
_, err = builderConfigFile.Write([]byte(fmt.Sprintf("uri = \"%s\"\n", lifecyclePath)))
h.AssertNil(t, err)
}
if lcver, ok := os.LookupEnv("LIFECYCLE_VERSION"); ok {
lifecycleVersion = lcver
_, err = builderConfigFile.Write([]byte(fmt.Sprintf("version = \"%s\"\n", lifecycleVersion)))
h.AssertNil(t, err)
}

builderConfigFile.Close()

builder := "some-org/" + h.RandString(10)
builder := registryConfig.RepoName("some-org/" + h.RandString(10))

cmd := exec.Command(packPath, "create-builder", "--no-color", builder, "-b", filepath.Join(tmpDir, "builder.toml"))
output := h.Run(t, cmd)

h.AssertContains(t, output, fmt.Sprintf("Successfully created builder image '%s'", builder))
h.AssertNil(t, h.PushImage(dockerCli, builder, registryConfig))

return builder
}

func createStack(t *testing.T, dockerCli *client.Client) {
t.Log("create stack images")
createStackImage(t, dockerCli, runImage, filepath.Join("testdata", "mock_stack", "run"))
createStackImage(t, dockerCli, buildImage, filepath.Join("testdata", "mock_stack", "build"))
err := dockerCli.ImageTag(context.Background(), runImage, runImageMirror)
h.AssertNil(t, err)
createStackImage(t, dockerCli, runImage, filepath.Join("testdata", "mock_stack"))
h.AssertNil(t, dockerCli.ImageTag(context.Background(), runImage, buildImage))
h.AssertNil(t, dockerCli.ImageTag(context.Background(), runImage, runImageMirror))
h.AssertNil(t, h.PushImage(dockerCli, runImageMirror, registryConfig))
}

Expand All @@ -754,7 +753,6 @@ func createStackImage(t *testing.T, dockerCli *client.Client, repoName string, d
Tags: []string{repoName},
Remove: true,
ForceRemove: true,
BuildArgs: map[string]*string{"lifecycleVersion": &lifecycleVersion},
})
h.AssertNil(t, err)

Expand Down Expand Up @@ -807,7 +805,7 @@ func fetchHostPort(t *testing.T, dockerID string) string {
func imgSHAFromOutput(txt, repoName string) (string, error) {
for _, m := range regexp.MustCompile(`\*\*\* Image: (.+)@(.+)`).FindAllStringSubmatch(txt, -1) {
// remove the :latest tag check once we fix tag + sha output error in lifecycle
if m[1] == repoName || m[1] == repoName + ":latest" {
if m[1] == repoName || m[1] == repoName+":latest" {
return m[2], nil
}
}
Expand All @@ -819,9 +817,10 @@ func runDockerImageExposePort(t *testing.T, containerName, repoName string) stri
ctx := context.Background()

ctr, err := dockerCli.ContainerCreate(ctx, &container.Config{
Image: repoName,
Env: []string{"PORT=8080"},
Healthcheck: nil,
Image: repoName,
Env: []string{"PORT=8080"},
ExposedPorts: map[nat.Port]struct{}{"8080/tcp": {}},
Healthcheck: nil,
}, &container.HostConfig{
PortBindings: nat.PortMap{
"8080/tcp": []nat.PortBinding{{}},
Expand Down
46 changes: 24 additions & 22 deletions acceptance/testdata/inspect_builder_output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,43 +3,45 @@ Inspecting builder: '%s'
Remote
------

Stack: some.test.stack
Stack: pack.test.stack

Lifecycle Version: %s

Run Images:
some-registry.com/some/run1 (user-configured)
some/run1
gcr.io/some/run1
some-registry.com/pack-test/run1 (user-configured)
pack-test/run
%s

Buildpacks:
ID VERSION LATEST
test.bp.one 0.0.1 false
test.bp.two 0.0.2 true
ID VERSION LATEST
simple/layers simple-layers-version false
read/env read-env-version false
noop.buildpack noop.buildpack.version true

Detection Order:
Group #1:
test.bp.one@0.0.1
test.bp.two@0.0.2
Group #2:
test.bp.one@0.0.1
simple/layers@simple-layers-version
read/env@read-env-version

Local
-----

Stack: some.test.stack
Stack: pack.test.stack

Lifecycle Version: %s

Run Images:
some-registry.com/some/run1 (user-configured)
some/run1
gcr.io/some/run2
some-registry.com/pack-test/run1 (user-configured)
pack-test/run
%s

Buildpacks:
ID VERSION LATEST
test.bp.one 0.0.1 false
test.bp.two 0.0.2 true
ID VERSION LATEST
simple/layers simple-layers-version false
read/env read-env-version false
noop.buildpack noop.buildpack.version true

Detection Order:
Group #1:
test.bp.one@0.0.1
test.bp.two@0.0.2
Group #2:
test.bp.one@0.0.1
simple/layers@simple-layers-version
read/env@read-env-version
2 changes: 1 addition & 1 deletion acceptance/testdata/mock_buildpacks/builder.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@
build-image = "pack-test/build"
run-image = "pack-test/run"

# run-image-mirror is append by accpetance tests
# run-image-mirror and lifecycle are appended by accpetance tests
18 changes: 18 additions & 0 deletions acceptance/testdata/mock_stack/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
FROM ubuntu:bionic

ENV CNB_USER_ID=2222
ENV CNB_GROUP_ID=3333

RUN \
groupadd pack --gid 3333 && \
useradd --uid 2222 --gid 3333 -m -s /bin/bash pack

RUN apt-get update && apt-get -yq install netcat
LABEL io.buildpacks.stack.id=pack.test.stack

RUN mkdir /layers && chown pack:pack /layers

USER pack
WORKDIR /layers


5 changes: 0 additions & 5 deletions acceptance/testdata/mock_stack/build/Dockerfile

This file was deleted.

4 changes: 2 additions & 2 deletions acceptance/testdata/mock_stack/create-stack.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@

dir="$(cd $(dirname $0) && pwd)"

docker build --tag pack-test/build "$dir/build"
docker build --tag pack-test/run "$dir/run"
docker build --tag pack-test/build "$dir"
docker tag pack-test/build pack-test/run
9 changes: 0 additions & 9 deletions acceptance/testdata/mock_stack/run/Dockerfile

This file was deleted.

6 changes: 6 additions & 0 deletions build/lifecycle.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ func (l *Lifecycle) Execute(ctx context.Context, opts LifecycleOptions) error {
l.Setup(opts.AppDir, opts.Builder)
defer l.Cleanup()

if lifecycleVersion := l.Builder.GetLifecycleVersion(); lifecycleVersion == "" {
l.logger.Verbose("Warning: lifecycle version unknown")
}else {
l.logger.Verbose("Executing lifecycle version %s", style.Symbol(lifecycleVersion))
}

l.logger.Verbose(style.Step("DETECTING"))
if err := l.Detect(ctx); err != nil {
return err
Expand Down
2 changes: 1 addition & 1 deletion build/testdata/fake-lifecycle/phase.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func testRegistryAccess(repoName string) {
}
_, err = v1remote.Image(ref, v1remote.WithAuth(auth))
if err != nil {
fmt.Println("failed to access image")
fmt.Println("failed to access image:", err)
os.Exit(6)
}
}
Expand Down
3 changes: 2 additions & 1 deletion build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,9 @@ func testBuild(t *testing.T, when spec.G, it spec.S) {
clientConfig,
logging.NewLogger(logOut, logErr, true, false),
fakeImageFetcher,
buildpack.NewFetcher(NewDownloader(logging.NewLogger(logOut, logErr, true, false), tmpDir)),
nil,
fakeLifecycle,
buildpack.NewFetcher(logging.NewLogger(logOut, logErr, true, false), tmpDir),
docker,
)
})
Expand Down
Loading

0 comments on commit 6ed36d1

Please sign in to comment.