Skip to content

Commit

Permalink
Added package support to build
Browse files Browse the repository at this point in the history
- Interprets package from --buildpack flag

Signed-off-by: Andrew Meyer <ameyer@pivotal.io>
Signed-off-by: Javier Romero <jromero@pivotal.io>
Signed-off-by: Micah Young <myoung@pivotal.io>
  • Loading branch information
ameyer-pivotal authored and Javier Romero and Andrew Meyer committed Feb 12, 2020
1 parent 9a93698 commit 919ef0d
Show file tree
Hide file tree
Showing 6 changed files with 203 additions and 15 deletions.
12 changes: 10 additions & 2 deletions build.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ func (c *Client) Build(ctx context.Context, opts BuildOptions) error {
return err
}

fetchedBPs, order, err := c.processBuildpacks(ctx, bldr.Buildpacks(), bldr.Order(), opts.Buildpacks)
fetchedBPs, order, err := c.processBuildpacks(ctx, bldr.Buildpacks(), bldr.Order(), opts.Buildpacks, opts.NoPull, opts.Publish)
if err != nil {
return err
}
Expand Down Expand Up @@ -381,7 +381,7 @@ func (c *Client) processProxyConfig(config *ProxyConfig) ProxyConfig {
// ----------
// - group:
// - A
func (c *Client) processBuildpacks(ctx context.Context, builderBPs []dist.BuildpackInfo, builderOrder dist.Order, declaredBPs []string) (fetchedBPs []dist.Buildpack, order dist.Order, err error) {
func (c *Client) processBuildpacks(ctx context.Context, builderBPs []dist.BuildpackInfo, builderOrder dist.Order, declaredBPs []string, noPull bool, publish bool) (fetchedBPs []dist.Buildpack, order dist.Order, err error) {
order = dist.Order{{Group: []dist.BuildpackRef{}}}
for _, bp := range declaredBPs {
locatorType, err := buildpack.GetLocatorType(bp, builderBPs)
Expand Down Expand Up @@ -431,6 +431,14 @@ func (c *Client) processBuildpacks(ctx context.Context, builderBPs []dist.Buildp

fetchedBPs = append(fetchedBPs, fetchedBP)
order = appendBuildpackToOrder(order, fetchedBP.Descriptor().Info)
case buildpack.PackageLocator:
mainBP, depBPs, err := extractPackagedBuildpacks(ctx, bp, c.imageFetcher, publish, noPull)
if err != nil {
return fetchedBPs, order, errors.Wrapf(err, "creating from buildpackage %s", style.Symbol(bp))
}

fetchedBPs = append(append(fetchedBPs, mainBP), depBPs...)
order = appendBuildpackToOrder(order, mainBP.Descriptor().Info)
default:
return nil, nil, fmt.Errorf("invalid buildpack string %s", style.Symbol(bp))
}
Expand Down
165 changes: 165 additions & 0 deletions build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"archive/tar"
"bytes"
"context"
"crypto/sha256"
"encoding/hex"
"fmt"
"io"
"io/ioutil"
Expand All @@ -26,6 +28,7 @@ import (
"github.com/buildpacks/pack/internal/api"
"github.com/buildpacks/pack/internal/blob"
"github.com/buildpacks/pack/internal/builder"
"github.com/buildpacks/pack/internal/buildpackage"
"github.com/buildpacks/pack/internal/dist"
ifakes "github.com/buildpacks/pack/internal/fakes"
ilogging "github.com/buildpacks/pack/internal/logging"
Expand Down Expand Up @@ -881,6 +884,157 @@ func testBuild(t *testing.T, when spec.G, it spec.S) {
})
})

when("buildpackage image is used", func() {
var fakePackage *fakes.Image

it.Before(func() {
metaBuildpackTar := createBuildpackTar(t, tmpDir, dist.BuildpackDescriptor{
API: api.MustParse("0.3"),
Info: dist.BuildpackInfo{
ID: "meta.buildpack.id",
Version: "meta.buildpack.version",
},
Stacks: nil,
Order: dist.Order{{
Group: []dist.BuildpackRef{{
BuildpackInfo: dist.BuildpackInfo{
ID: "child.buildpack.id",
Version: "child.buildpack.version",
},
Optional: false,
}},
}},
})

childBuildpackTar := createBuildpackTar(t, tmpDir, dist.BuildpackDescriptor{
API: api.MustParse("0.3"),
Info: dist.BuildpackInfo{
ID: "child.buildpack.id",
Version: "child.buildpack.version",
},
Stacks: []dist.Stack{
{ID: defaultBuilderStackID},
},
})

bpLayers := dist.BuildpackLayers{
"meta.buildpack.id": {
"meta.buildpack.version": {
API: api.MustParse("0.3"),
Order: dist.Order{{
Group: []dist.BuildpackRef{{
BuildpackInfo: dist.BuildpackInfo{
ID: "child.buildpack.id",
Version: "child.buildpack.version",
},
Optional: false,
}},
}},
LayerDiffID: diffIDForFile(t, metaBuildpackTar),
},
},
"child.buildpack.id": {
"child.buildpack.version": {
API: api.MustParse("0.3"),
Stacks: []dist.Stack{
{ID: defaultBuilderStackID},
},
LayerDiffID: diffIDForFile(t, childBuildpackTar),
},
},
}

md := buildpackage.Metadata{
BuildpackInfo: dist.BuildpackInfo{
ID: "meta.buildpack.id",
Version: "meta.buildpack.version",
},
Stacks: []dist.Stack{
{ID: defaultBuilderStackID},
},
}

fakePackage = fakes.NewImage("example.com/some/package", "", nil)
h.AssertNil(t, dist.SetLabel(fakePackage, "io.buildpacks.buildpack.layers", bpLayers))
h.AssertNil(t, dist.SetLabel(fakePackage, "io.buildpacks.buildpackage.metadata", md))

h.AssertNil(t, fakePackage.AddLayer(metaBuildpackTar))
h.AssertNil(t, fakePackage.AddLayer(childBuildpackTar))

fakeImageFetcher.LocalImages[fakePackage.Name()] = fakePackage
})

it("all buildpacks are added to ephemeral builder", func() {
err := subject.Build(context.TODO(), BuildOptions{
Image: "some/app",
Builder: builderName,
ClearCache: true,
Buildpacks: []string{
"example.com/some/package",
},
})

h.AssertNil(t, err)
h.AssertEq(t, fakeLifecycle.Opts.Builder.Name(), defaultBuilderImage.Name())
bldr, err := builder.FromImage(defaultBuilderImage)
h.AssertNil(t, err)
h.AssertEq(t, bldr.Order(), dist.Order{
{Group: []dist.BuildpackRef{
{BuildpackInfo: dist.BuildpackInfo{ID: "meta.buildpack.id", Version: "meta.buildpack.version"}},
}},
// Child buildpacks should not be added to order
})
h.AssertEq(t, bldr.Buildpacks(), []dist.BuildpackInfo{
{
ID: "buildpack.1.id",
Version: "buildpack.1.version",
},
{
ID: "buildpack.2.id",
Version: "buildpack.2.version",
},
{
ID: "meta.buildpack.id",
Version: "meta.buildpack.version",
},
{
ID: "child.buildpack.id",
Version: "child.buildpack.version",
},
})
})

it("fails when no metadata label on package", func() {
h.AssertNil(t, fakePackage.SetLabel("io.buildpacks.buildpackage.metadata", ""))

err := subject.Build(context.TODO(), BuildOptions{
Image: "some/app",
Builder: builderName,
ClearCache: true,
Buildpacks: []string{
"example.com/some/package",
},
})

h.AssertError(t, err, "could not find label 'io.buildpacks.buildpackage.metadata' on image 'example.com/some/package'")
})

it("fails when no bp layers label is on package", func() {
h.AssertNil(t, fakePackage.SetLabel("io.buildpacks.buildpack.layers", ""))

err := subject.Build(context.TODO(), BuildOptions{
Image: "some/app",
Builder: builderName,
ClearCache: true,
Buildpacks: []string{
"example.com/some/package",
},
})

h.AssertError(t, err, "could not find label 'io.buildpacks.buildpack.layers' on image 'example.com/some/package'")
})
})

it("ensures buildpacks exist on builder", func() {
h.AssertError(t, subject.Build(context.TODO(), BuildOptions{
Image: "some/app",
Expand Down Expand Up @@ -1402,3 +1556,14 @@ func createBuildpackTar(t *testing.T, tmpDir string, descriptor dist.BuildpackDe

return tempFile.Name()
}

func diffIDForFile(t *testing.T, path string) string {
file, err := os.Open(path)
h.AssertNil(t, err)

hasher := sha256.New()
_, err = io.Copy(hasher, file)
h.AssertNil(t, err)

return "sha256:" + hex.EncodeToString(hasher.Sum(make([]byte, 0, hasher.Size())))
}
4 changes: 2 additions & 2 deletions create_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,12 @@ func (c *Client) CreateBuilder(ctx context.Context, opts CreateBuilderOptions) e
}

for _, pkg := range opts.Config.Packages {
bps, err := extractPackagedBuildpacks(ctx, pkg.Image, c.imageFetcher, opts.Publish, opts.NoPull)
mainBP, depBPs, err := extractPackagedBuildpacks(ctx, pkg.Image, c.imageFetcher, opts.Publish, opts.NoPull)
if err != nil {
return err
}

for _, bp := range bps {
for _, bp := range append([]dist.Buildpack{mainBP}, depBPs...) {
bldr.AddBuildpack(bp)
}
}
Expand Down
4 changes: 2 additions & 2 deletions create_buildpackage.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ func (c *Client) CreatePackage(ctx context.Context, opts CreatePackageOptions) e

packageBuilder.AddDependency(depBP)
} else if dep.ImageName != "" {
bps, err := extractPackagedBuildpacks(ctx, dep.ImageName, c.imageFetcher, opts.Publish, opts.NoPull)
mainBP, depBPs, err := extractPackagedBuildpacks(ctx, dep.ImageName, c.imageFetcher, opts.Publish, opts.NoPull)
if err != nil {
return err
}

for _, depBP := range bps {
for _, depBP := range append([]dist.Buildpack{mainBP}, depBPs...) {
packageBuilder.AddDependency(depBP)
}
}
Expand Down
32 changes: 24 additions & 8 deletions pack.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,42 @@ import (

"github.com/pkg/errors"

"github.com/buildpacks/pack/internal/buildpackage"
"github.com/buildpacks/pack/internal/dist"
"github.com/buildpacks/pack/internal/style"
)

func extractPackagedBuildpacks(ctx context.Context, pkgImageRef string, fetcher ImageFetcher, publish, noPull bool) ([]dist.Buildpack, error) {
func extractPackagedBuildpacks(ctx context.Context, pkgImageRef string, fetcher ImageFetcher, publish, noPull bool) (mainBP dist.Buildpack, depBPs []dist.Buildpack, err error) {
pkgImage, err := fetcher.Fetch(ctx, pkgImageRef, !publish, !noPull)
if err != nil {
return nil, errors.Wrapf(err, "fetching image %s", style.Symbol(pkgImageRef))
return nil, nil, errors.Wrapf(err, "fetching image %s", style.Symbol(pkgImageRef))
}

md := &buildpackage.Metadata{}
if found, err := dist.GetLabel(pkgImage, buildpackage.MetadataLabel, md); err != nil {
return nil, nil, err
} else if !found {
return nil, nil, errors.Errorf(
"could not find label %s on image %s",
style.Symbol(buildpackage.MetadataLabel),
style.Symbol(pkgImageRef),
)
}

bpLayers := dist.BuildpackLayers{}
ok, err := dist.GetLabel(pkgImage, dist.BuildpackLayersLabel, &bpLayers)
if err != nil {
return nil, err
return nil, nil, err
}

if !ok {
return nil, errors.Errorf(
"label %s not present on package %s",
return nil, nil, errors.Errorf(
"could not find label %s on image %s",
style.Symbol(dist.BuildpackLayersLabel),
style.Symbol(pkgImageRef),
)
}

var bps []dist.Buildpack
for bpID, v := range bpLayers {
for bpVersion, bpInfo := range v {
desc := dist.BuildpackDescriptor{
Expand Down Expand Up @@ -59,10 +70,15 @@ func extractPackagedBuildpacks(ctx context.Context, pkgImageRef string, fetcher
},
}

bps = append(bps, dist.BuildpackFromTarBlob(desc, b))
if desc.Info == md.BuildpackInfo {
mainBP = dist.BuildpackFromTarBlob(desc, b)
} else {
depBPs = append(depBPs, dist.BuildpackFromTarBlob(desc, b))
}
}
}
return bps, nil

return mainBP, depBPs, nil
}

type openerBlob struct {
Expand Down
1 change: 0 additions & 1 deletion testhelpers/archive.go

This file was deleted.

0 comments on commit 919ef0d

Please sign in to comment.