Skip to content

Commit

Permalink
Builder struct can now create new builder images
Browse files Browse the repository at this point in the history
- Add create builder to client
- Create builder uses the refactored builder to construct a new builder image
- Inspect builder uses the refactored builder to get builder info

Signed-off-by: Danny Joyce <djoyce@pivotal.io>
Signed-off-by: Emily Casey <ecasey@pivotal.io>
  • Loading branch information
Danny Joyce authored and ekcasey committed Apr 17, 2019
1 parent cb45dab commit 9ae32db
Show file tree
Hide file tree
Showing 55 changed files with 1,644 additions and 1,260 deletions.
11 changes: 7 additions & 4 deletions acceptance/acceptance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,15 @@ import (
"testing"
"time"

"github.com/buildpack/pack/archive"

"github.com/buildpack/lifecycle"
"github.com/buildpack/lifecycle/metadata"
dockertypes "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/client"
"github.com/docker/go-connections/nat"
"github.com/sclevine/spec"
"github.com/sclevine/spec/report"

"github.com/buildpack/pack/archive"
"github.com/buildpack/pack/cache"
h "github.com/buildpack/pack/testhelpers"
)
Expand Down Expand Up @@ -163,7 +162,7 @@ func testAcceptance(t *testing.T, when spec.G, it spec.S) {
assertHasBase(t, repoName, "packs/run:"+lifecycleVersion)

t.Log("sets the run image metadata")
runImageLabel := imageLabel(t, dockerCli, repoName, lifecycle.MetadataLabel)
runImageLabel := imageLabel(t, dockerCli, repoName, metadata.AppMetadataLabel)
h.AssertContains(t, runImageLabel, fmt.Sprintf(`"stack":{"runImage":{"image":"%s","mirrors":["%s"]}}}`, runImage, runImageMirror))

t.Log("registry is empty")
Expand Down Expand Up @@ -673,13 +672,17 @@ func testAcceptance(t *testing.T, when spec.G, it spec.S) {
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"))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
[buildpack]
id = "noop.buildpack"
version = "noop.buildpack.version"
name = "NOOP Buildpack"
id = "noop.buildpack"
version = "noop.buildpack.version"
name = "NOOP Buildpack"

[[stacks]]
id = "pack.test.stack"
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
[buildpack]
id = "local/bp"
version = "local-bp-version"
name = "Not in Builder Buildpack"
id = "local/bp"
version = "local-bp-version"
name = "Not in Builder Buildpack"

[[stacks]]
id = "pack.test.stack"
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
[buildpack]
id = "read/env"
version = "read-env-version"
name = "Buildpack Reads Env"
id = "read/env"
version = "read-env-version"
name = "Buildpack Reads Env"

[[stacks]]
id = "pack.test.stack"
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
[buildpack]
id = "simple/layers"
version = "simple-layers-version"
name = "Simple Layers Buildpack"
id = "simple/layers"
version = "simple-layers-version"
name = "Simple Layers Buildpack"

[[stacks]]
id = "pack.test.stack"
6 changes: 3 additions & 3 deletions app/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ import (
h "github.com/buildpack/pack/testhelpers"
)

func TestRun(t *testing.T) {
func TestApp(t *testing.T) {
h.RequireDocker(t)
color.NoColor = true
rand.Seed(time.Now().UTC().UnixNano())
spec.Run(t, "run", testRun, spec.Sequential(), spec.Report(report.Terminal{}))
spec.Run(t, "app", testApp, spec.Sequential(), spec.Report(report.Terminal{}))
}

func testRun(t *testing.T, when spec.G, it spec.S) {
func testApp(t *testing.T, when spec.G, it spec.S) {
when("#Run", func() {
var (
subject *app.Image
Expand Down
25 changes: 17 additions & 8 deletions archive/tar.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ import (
"bytes"
"compress/gzip"
"fmt"
"github.com/pkg/errors"
"io"
"os"
"path/filepath"
"runtime"
"strings"
"time"

"github.com/pkg/errors"
)

var NormalizedDateTime time.Time
Expand All @@ -20,22 +21,33 @@ func init() {
NormalizedDateTime = time.Date(1980, time.January, 1, 0, 0, 1, 0, time.UTC)
}

func WriteDirToTar(tw *tar.Writer, srcDir, tarDir string, uid, gid int) error {
return writeTarArchive(tw, srcDir, tarDir, uid, gid)
}

func CreateTar(tarFile, srcDir, tarDir string, uid, gid int) error {
fh, err := os.Create(tarFile)
if err != nil {
return fmt.Errorf("create file for tar: %s", err)
}
defer fh.Close()
return writeTarArchive(fh, srcDir, tarDir, uid, gid)

tw := tar.NewWriter(fh)
defer tw.Close()

return writeTarArchive(tw, srcDir, tarDir, uid, gid)
}

func CreateTarReader(srcDir, tarDir string, uid, gid int) (io.Reader, chan error) {
r, w := io.Pipe()
errChan := make(chan error, 1)
go func() {
defer w.Close()
err := writeTarArchive(w, srcDir, tarDir, uid, gid)
w.Close()

tw := tar.NewWriter(w)
defer tw.Close()

err := writeTarArchive(tw, srcDir, tarDir, uid, gid)
errChan <- err
}()
return r, errChan
Expand Down Expand Up @@ -163,10 +175,7 @@ func isNotRootDir(parent string) bool {
return parent != "/"
}

func writeTarArchive(w io.Writer, srcDir, tarDir string, uid, gid int) error {
tw := tar.NewWriter(w)
defer tw.Close()

func writeTarArchive(tw *tar.Writer, srcDir, tarDir string, uid, gid int) error {
err := writeParentDirectoryHeaders(tarDir, tw, uid, gid)
if err != nil {
return err
Expand Down
14 changes: 12 additions & 2 deletions build.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,13 +169,23 @@ func (bf *BuildFactory) BuildConfigFromFlags(ctx context.Context, f *BuildFlags)
if err != nil {
return nil, err
}
builderImage = builder.NewBuilder(bimg, bf.Config)

builderImage, err = builder.GetBuilder(bimg)
if err != nil {
return nil, err
}

if f.RunImage != "" {
bf.Logger.Verbose("Using user-provided run image %s", style.Symbol(f.RunImage))
b.RunImage = f.RunImage
} else {
b.RunImage, err = builderImage.GetRunImageByRepoName(f.RepoName)
stack := builderImage.GetStackInfo()

var localMirrors []string
if runImageConfig := bf.Config.GetRunImage(stack.RunImage.Image); runImageConfig != nil {
localMirrors = runImageConfig.Mirrors
}
b.RunImage, err = stack.GetBestMirror(f.RepoName, localMirrors)
if err != nil {
return nil, err
}
Expand Down
25 changes: 9 additions & 16 deletions build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ func testBuildFactory(t *testing.T, when spec.G, it spec.S) {
factory *pack.BuildFactory
mockCache *mocks.MockCache
MockImageFetcher *mocks.MockImageFetcher
mockBuilderImage *mocks.MockImage
)

it.Before(func() {
Expand All @@ -59,14 +60,18 @@ func testBuildFactory(t *testing.T, when spec.G, it spec.S) {
}

mockCache.EXPECT().Image().AnyTimes()
mockBuilderImage = mocks.NewMockImage(mockController)
mockBuilderImage.EXPECT().Env("CNB_USER_ID").Return("1111", nil).AnyTimes()
mockBuilderImage.EXPECT().Env("CNB_GROUP_ID").Return("2222", nil).AnyTimes()
mockBuilderImage.EXPECT().Label("io.buildpacks.stack.id").Return(`some.stack.id`, nil).AnyTimes()
mockBuilderImage.EXPECT().Name().Return("some/builder").AnyTimes()
})

it.After(func() {
mockController.Finish()
})

it("defaults to daemon, default-builder, pulls builder and run images, selects run-image from builder", func() {
mockBuilderImage := mocks.NewMockImage(mockController)
mockBuilderImage.EXPECT().Label("io.buildpacks.builder.metadata").Return(`{"stack":{"runImage": {"image": "some/run"}}}`, nil).AnyTimes()
MockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/builder", true, true).Return(mockBuilderImage, nil)

Expand All @@ -83,7 +88,6 @@ func testBuildFactory(t *testing.T, when spec.G, it spec.S) {
})

it("respects builder from flags", func() {
mockBuilderImage := mocks.NewMockImage(mockController)
mockBuilderImage.EXPECT().Label("io.buildpacks.builder.metadata").Return(`{"stack":{"runImage": {"image": "some/run"}}}`, nil).AnyTimes()
MockImageFetcher.EXPECT().Fetch(gomock.Any(), "custom/builder", true, true).Return(mockBuilderImage, nil)

Expand All @@ -100,7 +104,6 @@ func testBuildFactory(t *testing.T, when spec.G, it spec.S) {
})

it("doesn't pull builder or run images when --no-pull is passed", func() {
mockBuilderImage := mocks.NewMockImage(mockController)
mockBuilderImage.EXPECT().Label("io.buildpacks.builder.metadata").Return(`{"stack":{"runImage": {"image": "some/run"}}}`, nil).AnyTimes()
MockImageFetcher.EXPECT().Fetch(gomock.Any(), "custom/builder", true, false).Return(mockBuilderImage, nil)

Expand All @@ -118,7 +121,6 @@ func testBuildFactory(t *testing.T, when spec.G, it spec.S) {
})

it("selects run images with matching registry", func() {
mockBuilderImage := mocks.NewMockImage(mockController)
mockBuilderImage.EXPECT().Label("io.buildpacks.builder.metadata").
Return(`{"stack":{"runImage": {"image": "some/run", "mirrors": ["registry.com/some/run"]}}}`, nil).AnyTimes()
MockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/builder", true, true).Return(mockBuilderImage, nil)
Expand Down Expand Up @@ -146,7 +148,6 @@ func testBuildFactory(t *testing.T, when spec.G, it spec.S) {
},
}

mockBuilderImage := mocks.NewMockImage(mockController)
mockBuilderImage.EXPECT().Label("io.buildpacks.builder.metadata").
Return(`{"stack":{"runImage": {"image": "default/run", "mirrors": ["registry.com/default/run"]}}}`, nil).AnyTimes()
MockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/builder", true, true).Return(mockBuilderImage, nil)
Expand Down Expand Up @@ -180,7 +181,6 @@ func testBuildFactory(t *testing.T, when spec.G, it spec.S) {
})

it("uses a remote run image when --publish is passed", func() {
mockBuilderImage := mocks.NewMockImage(mockController)
mockBuilderImage.EXPECT().Label("io.buildpacks.builder.metadata").Return(`{"stack":{"runImage": {"image": "some/run"}}}`, nil).AnyTimes()
MockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/builder", true, true).Return(mockBuilderImage, nil)

Expand All @@ -198,7 +198,7 @@ func testBuildFactory(t *testing.T, when spec.G, it spec.S) {
})

it("allows run-image from flags if the stacks match", func() {
mockBuilderImage := mocks.NewMockImage(mockController)
mockBuilderImage.EXPECT().Label("io.buildpacks.builder.metadata").Return(`{"stack":{"runImage": {"image": "some/run"}}}`, nil).AnyTimes()
MockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/builder", true, true).Return(mockBuilderImage, nil)

mockRunImage := mocks.NewMockImage(mockController)
Expand All @@ -216,7 +216,6 @@ func testBuildFactory(t *testing.T, when spec.G, it spec.S) {
})

it("uses working dir if appDir is set to placeholder value", func() {
mockBuilderImage := mocks.NewMockImage(mockController)
mockBuilderImage.EXPECT().Label("io.buildpacks.builder.metadata").Return(`{"stack":{"runImage": {"image": "some/run"}}}`, nil).AnyTimes()
MockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/builder", true, true).Return(mockBuilderImage, nil)

Expand All @@ -236,8 +235,6 @@ func testBuildFactory(t *testing.T, when spec.G, it spec.S) {
})

it("returns an error when the builder metadata label is missing", func() {
mockBuilderImage := mocks.NewMockImage(mockController)
mockBuilderImage.EXPECT().Name().Return("some/builder")
mockBuilderImage.EXPECT().Label("io.buildpacks.builder.metadata").Return("", nil)
MockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/builder", true, true).Return(mockBuilderImage, nil)

Expand All @@ -249,8 +246,6 @@ func testBuildFactory(t *testing.T, when spec.G, it spec.S) {
})

it("returns an error when the builder metadata label is unparsable", func() {
mockBuilderImage := mocks.NewMockImage(mockController)
mockBuilderImage.EXPECT().Name().Return("some/builder")
mockBuilderImage.EXPECT().Label("io.buildpacks.builder.metadata").Return("junk", nil)
MockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/builder", true, true).Return(mockBuilderImage, nil)

Expand All @@ -262,7 +257,8 @@ func testBuildFactory(t *testing.T, when spec.G, it spec.S) {
})

it("returns an error if fetching run-image returns an error", func() {
mockBuilderImage := mocks.NewMockImage(mockController)
mockBuilderImage.EXPECT().Label("io.buildpacks.builder.metadata").Return(`{"stack":{"runImage": {"image": "some/run"}}}`, nil).AnyTimes()

MockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/builder", true, true).Return(mockBuilderImage, nil)
MockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/run", false, false).Return(nil, errors.New("some-error"))

Expand All @@ -276,7 +272,6 @@ func testBuildFactory(t *testing.T, when spec.G, it spec.S) {
})

it("sets Env", func() {
mockBuilderImage := mocks.NewMockImage(mockController)
mockBuilderImage.EXPECT().Label("io.buildpacks.builder.metadata").Return(`{"stack":{"runImage": {"image": "some/run"}}}`, nil).AnyTimes()
MockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/builder", true, true).Return(mockBuilderImage, nil)

Expand All @@ -302,7 +297,6 @@ func testBuildFactory(t *testing.T, when spec.G, it spec.S) {
})

it("sets EnvFile", func() {
mockBuilderImage := mocks.NewMockImage(mockController)
mockBuilderImage.EXPECT().Label("io.buildpacks.builder.metadata").Return(`{"stack":{"runImage": {"image": "some/run"}}}`, nil).AnyTimes()
MockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/builder", true, true).Return(mockBuilderImage, nil)

Expand Down Expand Up @@ -336,7 +330,6 @@ PATH
})

it("sets EnvFile with Env overrides", func() {
mockBuilderImage := mocks.NewMockImage(mockController)
mockBuilderImage.EXPECT().Label("io.buildpacks.builder.metadata").Return(`{"stack":{"runImage": {"image": "some/run"}}}`, nil).AnyTimes()
MockImageFetcher.EXPECT().Fetch(gomock.Any(), "some/builder", true, true).Return(mockBuilderImage, nil)

Expand Down
Loading

0 comments on commit 9ae32db

Please sign in to comment.