Skip to content

Commit

Permalink
Inspect builder logs stack, run images, buildpacks, and detection ord…
Browse files Browse the repository at this point in the history
…er groups

- Write buildpack and group metadata during create builder on the
  metadata label

[buildpacks/roadmap#22]

Signed-off-by: Danny Joyce <[email protected]>
  • Loading branch information
Danny Joyce committed Mar 15, 2019
1 parent 9489860 commit 157efb8
Show file tree
Hide file tree
Showing 10 changed files with 415 additions and 94 deletions.
27 changes: 9 additions & 18 deletions acceptance/acceptance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -741,37 +741,28 @@ func testAcceptance(t *testing.T, when spec.G, it spec.S) {
builderImageName := h.CreateImageOnRemote(t, dockerCli, registryConfig, "some/builder",
fmt.Sprintf(`
FROM scratch
LABEL %s="{\"runImage\": { \"image\": \"some/run1\", \"mirrors\": [\"gcr.io/some/run1\"]}}"
LABEL %s="{\"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
`, pack.BuilderMetadataLabel))

h.CreateImageOnLocal(t, dockerCli, builderImageName,
fmt.Sprintf(`
FROM scratch
LABEL %s="{\"runImage\": { \"image\": \"some/run1\", \"mirrors\": [\"gcr.io/some/run2\"]}}"
LABEL %s="{\"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
`, pack.BuilderMetadataLabel))
println(builderImageName)

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

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

h.AssertEq(t, output, `Remote
------
Run Image: some/run1
Run Image Mirrors:
some-registry.com/some/run1 (user-configured)
gcr.io/some/run1
Local
-----
Run Image: some/run1
Run Image Mirrors:
some-registry.com/some/run1 (user-configured)
gcr.io/some/run2
`)
expected, err := ioutil.ReadFile(filepath.Join("testdata", "inspect_builder_output.txt"))
h.AssertNil(t, err)

h.AssertEq(t, output, fmt.Sprintf(string(expected), builderImageName))
})
})
}
Expand Down
45 changes: 45 additions & 0 deletions acceptance/testdata/inspect_builder_output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
Inspecting builder: %s

Remote
------

Stack: some.test.stack

Run Images:
some-registry.com/some/run1 (user-configured)
some/run1
gcr.io/some/run1

Buildpacks:
ID VERSION LATEST
test.bp.one 0.0.1 false
test.bp.two 0.0.2 true

Detection Order:
Group #1:
[email protected]
[email protected]
Group #2:
[email protected]

Local
-----

Stack: some.test.stack

Run Images:
some-registry.com/some/run1 (user-configured)
some/run1
gcr.io/some/run2

Buildpacks:
ID VERSION LATEST
test.bp.one 0.0.1 false
test.bp.two 0.0.2 true

Detection Order:
Group #1:
[email protected]
[email protected]
Group #2:
[email protected]
19 changes: 16 additions & 3 deletions builder_factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ func (f *BuilderFactory) Create(config BuilderConfig) error {
return fmt.Errorf(`failed append order.toml layer to image: %s`, err)
}

buildpacksMetadata := make([]BuilderBuildpacksMetadata, 0, len(config.Buildpacks))
buildpacksMetadata := make([]BuilderBuildpackMetadata, 0, len(config.Buildpacks))
for _, buildpack := range config.Buildpacks {
tarFile, err := f.buildpackLayer(tmpDir, &buildpack, config.BuilderDir)
if err != nil {
Expand All @@ -210,7 +210,7 @@ func (f *BuilderFactory) Create(config BuilderConfig) error {
if err := config.Repo.AddLayer(tarFile); err != nil {
return fmt.Errorf(`failed append buildpack layer to image: %s`, err)
}
buildpacksMetadata = append(buildpacksMetadata, BuilderBuildpacksMetadata{ID: buildpack.ID, Version: buildpack.Version})
buildpacksMetadata = append(buildpacksMetadata, BuilderBuildpackMetadata{ID: buildpack.ID, Version: buildpack.Version, Latest: buildpack.Latest})
}

tarFile, err := f.latestLayer(config.Buildpacks, tmpDir, config.BuilderDir)
Expand All @@ -221,19 +221,32 @@ func (f *BuilderFactory) Create(config BuilderConfig) error {
return fmt.Errorf(`failed append latest link layer to image: %s`, err)
}

groupsMetadata := make([]BuilderGroupMetadata, 0, len(config.Groups))
for _, group := range config.Groups {
groupBuildpacks := make([]BuilderBuildpackMetadata, 0, len(group.Buildpacks))
for _, buildpack := range group.Buildpacks {
groupBuildpacks = append(groupBuildpacks, BuilderBuildpackMetadata{ID: buildpack.ID, Version: buildpack.Version})
}
groupsMetadata = append(groupsMetadata, BuilderGroupMetadata{Buildpacks: groupBuildpacks})
}

jsonBytes, err := json.Marshal(&BuilderImageMetadata{
RunImage: BuilderRunImageMetadata{Image: config.RunImage, Mirrors: config.RunImageMirrors},
Buildpacks: buildpacksMetadata,
Groups: groupsMetadata,
})
if err != nil {
return fmt.Errorf(`failed marshal builder image metadata: %s`, err)
}

config.Repo.SetLabel(BuilderMetadataLabel, string(jsonBytes))
if err := config.Repo.SetLabel(BuilderMetadataLabel, string(jsonBytes)); err != nil {
return fmt.Errorf("failed to set metadata label: %s", err)
}

if _, err := config.Repo.Save(); err != nil {
return err
}

return nil
}

Expand Down
42 changes: 28 additions & 14 deletions builder_factory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ run-image = "some/run"
builderConfig = pack.BuilderConfig{
Repo: mockImage,
Buildpacks: []pack.Buildpack{},
Groups: []lifecycle.BuildpackGroup{{Buildpacks: []*lifecycle.Buildpack{{ID: "bpId"}}}},
Groups: []lifecycle.BuildpackGroup{},
BuilderDir: "",
RunImage: "myorg/run",
RunImageMirrors: []string{"gcr.io/myorg/run"},
Expand All @@ -447,32 +447,46 @@ run-image = "some/run"
h.AssertNil(t, factory.Create(builderConfig))
h.AssertEq(t,
labels["io.buildpacks.builder.metadata"],
`{"runImage":{"image":"myorg/run","mirrors":["gcr.io/myorg/run"]},"buildpacks":[]}`,
`{"runImage":{"image":"myorg/run","mirrors":["gcr.io/myorg/run"]},"buildpacks":[],"groups":[]}`,
)
})

it("should write a 'order.toml' that lists buildpack groups", func() {
h.AssertNil(t, factory.Create(builderConfig))
buf, exists := savedLayers["order.tar"]
h.AssertEq(t, exists, true)

contents, err := h.UntarSingleFile(buf, "/buildpacks/order.toml")
h.AssertNil(t, err)
h.AssertContains(t, string(contents), `id = "bpId"`)
})

when("builder config contains buildpacks", func() {
it.Before(func() {
builderConfig.Buildpacks = []pack.Buildpack{
{ID: "some-buildpack-id", Version: "some-buildpack-version", Dir: "testdata/used-to-test-various-uri-schemes/buildpack"},
{ID: "some-buildpack-id", Version: "some-buildpack-version", Dir: "testdata/used-to-test-various-uri-schemes/buildpack", Latest: true},
}
})

it("stores metadata about the buildpacks in the builder label", func() {
h.AssertNil(t, factory.Create(builderConfig))
h.AssertEq(t,
labels["io.buildpacks.builder.metadata"],
`{"runImage":{"image":"myorg/run","mirrors":["gcr.io/myorg/run"]},"buildpacks":[{"id":"some-buildpack-id","version":"some-buildpack-version"}]}`,
`{"runImage":{"image":"myorg/run","mirrors":["gcr.io/myorg/run"]},"buildpacks":[{"id":"some-buildpack-id","version":"some-buildpack-version","latest":true}],"groups":[]}`,
)
})
})

when("builder config contains groups", func() {
it.Before(func() {
builderConfig.Groups = []lifecycle.BuildpackGroup{{Buildpacks: []*lifecycle.Buildpack{{ID: "bpId", Version: "bpVersion"}}}}
})

it("should write a 'order.toml' that lists buildpack groups", func() {
h.AssertNil(t, factory.Create(builderConfig))
buf, exists := savedLayers["order.tar"]
h.AssertEq(t, exists, true)

contents, err := h.UntarSingleFile(buf, "/buildpacks/order.toml")
h.AssertNil(t, err)
h.AssertContains(t, string(contents), `id = "bpId"`)
})

it("stores metadata about the groups in the builder label", func() {
h.AssertNil(t, factory.Create(builderConfig))
h.AssertEq(t,
labels["io.buildpacks.builder.metadata"],
`{"runImage":{"image":"myorg/run","mirrors":["gcr.io/myorg/run"]},"buildpacks":[],"groups":[{"buildpacks":[{"id":"bpId","version":"bpVersion","latest":false}]}]}`,
)
})
})
Expand Down
30 changes: 17 additions & 13 deletions builder_inspector.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ type Builder struct {
RunImage string
LocalRunImageMirrors []string
RunImageMirrors []string
Buildpacks []BuilderBuildpackMetadata
Groups []BuilderGroupMetadata
}

func DefaultBuilderInspect() (*BuilderInspect, error) {
Expand All @@ -35,17 +37,18 @@ func DefaultBuilderInspect() (*BuilderInspect, error) {
}

func (b *BuilderInspect) Inspect(builderImage image.Image) (Builder, error) {
defaultRunImage, err := b.getRunImageMirrors(builderImage)
builderMetadata, err := b.getBuilderMetadata(builderImage)
if err != nil {
return Builder{}, err
}

builderName := builderImage.Name()
return Builder{
Image: builderName,
RunImage: defaultRunImage.Image,
LocalRunImageMirrors: b.getLocalRunImageMirrors(defaultRunImage.Image),
RunImageMirrors: defaultRunImage.Mirrors,
Image: builderImage.Name(),
RunImage: builderMetadata.RunImage.Image,
LocalRunImageMirrors: b.getLocalRunImageMirrors(builderMetadata.RunImage.Image),
RunImageMirrors: builderMetadata.RunImage.Mirrors,
Buildpacks: builderMetadata.Buildpacks,
Groups: builderMetadata.Groups,
}, nil
}

Expand All @@ -56,19 +59,20 @@ func (b *BuilderInspect) getLocalRunImageMirrors(imageName string) []string {
return nil
}

func (b *BuilderInspect) getRunImageMirrors(builderImage image.Image) (*BuilderRunImageMetadata, error) {
var metadata BuilderImageMetadata

func (b *BuilderInspect) getBuilderMetadata(builderImage image.Image) (BuilderImageMetadata, error) {
label, err := builderImage.Label(BuilderMetadataLabel)
if err != nil {
return nil, errors.Wrapf(err, "failed to find run images for builder %s", style.Symbol(builderImage.Name()))
return BuilderImageMetadata{}, errors.Wrapf(err, "failed to find run images for builder %s", style.Symbol(builderImage.Name()))
}

if label == "" {
return nil, fmt.Errorf("invalid builder image %s: missing required label %s -- try recreating builder", style.Symbol(builderImage.Name()), style.Symbol(BuilderMetadataLabel))
return BuilderImageMetadata{}, fmt.Errorf("invalid builder image %s: missing required label %s -- try recreating builder", style.Symbol(builderImage.Name()), style.Symbol(BuilderMetadataLabel))
}

var metadata BuilderImageMetadata
if err := json.Unmarshal([]byte(label), &metadata); err != nil {
return nil, errors.Wrapf(err, "failed to parse run images for builder %s", style.Symbol(builderImage.Name()))
return BuilderImageMetadata{}, errors.Wrapf(err, "failed to parse run images for builder %s", style.Symbol(builderImage.Name()))
}

return &metadata.RunImage, nil
return metadata, nil
}
40 changes: 39 additions & 1 deletion builder_inspector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,33 @@ func testInspectBuilder(t *testing.T, when spec.G, it spec.S) {
when("#Inspect", func() {
when("builder has valid metadata label", func() {
it.Before(func() {
mockBuilderImage.EXPECT().Label("io.buildpacks.builder.metadata").Return(`{"runImage": {"image": "some/default", "mirrors": ["gcr.io/some/default"]}}`, nil)
mockBuilderImage.EXPECT().Label("io.buildpacks.builder.metadata").
Return(`{
"runImage": {
"image": "some/default",
"mirrors": [
"gcr.io/some/default"
]
},
"buildpacks": [
{
"id": "test.bp.one",
"version": "1.0.0",
"latest": true
}
],
"groups": [
{
"buildpacks": [
{
"id": "test.bp.one",
"version": "1.0.0",
"latest": true
}
]
}
]
}`, nil)
})

when("builder exists in config", func() {
Expand Down Expand Up @@ -79,6 +105,18 @@ func testInspectBuilder(t *testing.T, when spec.G, it spec.S) {
h.AssertNil(t, err)
h.AssertEq(t, builder.RunImageMirrors, []string{"gcr.io/some/default"})
})

it("sets the buildpacks", func() {
builder, err := inspector.Inspect(mockBuilderImage)
h.AssertNil(t, err)
h.AssertEq(t, builder.Buildpacks, []pack.BuilderBuildpackMetadata{{ID: "test.bp.one", Version: "1.0.0", Latest: true}})
})

it("sets the groups", func() {
builder, err := inspector.Inspect(mockBuilderImage)
h.AssertNil(t, err)
h.AssertEq(t, builder.Groups, []pack.BuilderGroupMetadata{{Buildpacks: []pack.BuilderBuildpackMetadata{{ID: "test.bp.one", Version: "1.0.0", Latest: true}}}})
})
})

when("builder does not exist in config", func() {
Expand Down
13 changes: 12 additions & 1 deletion cmd/pack/main.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"github.com/buildpack/pack/config"
"os"

"github.com/buildpack/lifecycle/image"
Expand All @@ -17,6 +18,7 @@ var (
Version = "0.0.0"
timestamps, quiet bool
logger logging.Logger
cfg config.Config
inspect pack.BuilderInspect
imageFetcher pack.ImageFetcher
)
Expand All @@ -27,6 +29,7 @@ func main() {
Use: "pack",
PersistentPreRun: func(cmd *cobra.Command, args []string) {
logger = *logging.NewLogger(os.Stdout, os.Stderr, !quiet, timestamps)
cfg = initConfig(logger)
inspect = initInspect(logger)
imageFetcher = initImageFetcher(logger)
},
Expand All @@ -42,7 +45,7 @@ func main() {

rootCmd.AddCommand(commands.CreateBuilder(&logger, &imageFetcher))
rootCmd.AddCommand(commands.SetRunImagesMirrors(&logger))
rootCmd.AddCommand(commands.InspectBuilder(&logger, &inspect, &imageFetcher))
rootCmd.AddCommand(commands.InspectBuilder(&logger, &cfg, &inspect, &imageFetcher))
rootCmd.AddCommand(commands.SetDefaultBuilder(&logger))

rootCmd.AddCommand(commands.Version(&logger, Version))
Expand All @@ -52,6 +55,14 @@ func main() {
}
}

func initConfig(logger logging.Logger) config.Config {
cfg, err := config.NewDefault()
if err != nil {
exitError(logger, err)
}
return *cfg
}

func initInspect(logger logging.Logger) pack.BuilderInspect {
inspect, err := pack.DefaultBuilderInspect()
if err != nil {
Expand Down
Loading

0 comments on commit 157efb8

Please sign in to comment.