Skip to content

Commit

Permalink
Validate io.buildpacks.rebasable label on rebase
Browse files Browse the repository at this point in the history
For platforms >= 0.12 - the rebaser will now fail if the io.buildpacks.rebasable label is set to false when the force flag is not set.

Signed-off-by: Jesse Brown <jabrown85@gmail.com>
  • Loading branch information
jabrown85 committed Mar 9, 2023
1 parent 47c6203 commit bfd3344
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 1 deletion.
1 change: 1 addition & 0 deletions cmd/lifecycle/rebaser.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ func (r *rebaseCmd) Exec() error {
rebaser := &lifecycle.Rebaser{
Logger: cmd.DefaultLogger,
PlatformAPI: r.PlatformAPI,
Force: r.ForceRebase,
}
report, err := rebaser.Rebase(r.appImage, newBaseImage, r.OutputImageRef, r.AdditionalTags)
if err != nil {
Expand Down
3 changes: 2 additions & 1 deletion platform/labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ package platform
const (
BuildMetadataLabel = "io.buildpacks.build.metadata"
LayerMetadataLabel = "io.buildpacks.lifecycle.metadata"
MixinsLabel = "io.buildpacks.stack.mixins"
ProjectMetadataLabel = "io.buildpacks.project.metadata"
RebaseableLabel = "io.buildpacks.rebasable"
StackIDLabel = "io.buildpacks.stack.id"
MixinsLabel = "io.buildpacks.stack.mixins"
)
18 changes: 18 additions & 0 deletions rebaser.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
type Rebaser struct {
Logger log.Logger
PlatformAPI *api.Version
Force bool
}

type RebaseReport struct {
Expand Down Expand Up @@ -53,6 +54,10 @@ func (r *Rebaser) Rebase(workingImage imgutil.Image, newBaseImage imgutil.Image,
return RebaseReport{}, fmt.Errorf("incompatible stack: '%s' is not compatible with '%s'", newBaseStackID, appStackID)
}

if err := r.validateRebaseable(workingImage); err != nil {
return RebaseReport{}, err
}

if err := validateMixins(workingImage, newBaseImage); err != nil {
return RebaseReport{}, err
}
Expand Down Expand Up @@ -123,6 +128,19 @@ func validateMixins(appImg, newBaseImg imgutil.Image) error {
return nil
}

func (r *Rebaser) validateRebaseable(appImg imgutil.Image) error {
if r.PlatformAPI.AtLeast("0.12") {
rebaseable, err := appImg.Label(platform.RebaseableLabel)
if err != nil {
return errors.Wrap(err, "get app image rebaseable label")
}
if !r.Force && rebaseable == "false" {
return fmt.Errorf("app image is not marked as rebaseable")
}
}
return nil
}

func (r *Rebaser) supportsManifestSize() bool {
return r.PlatformAPI.AtLeast("0.6")
}
50 changes: 50 additions & 0 deletions rebaser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,56 @@ func testRebaser(t *testing.T, when spec.G, it spec.S) {
})
})

when("platform API is >= 0.12", func() {
it.Before(func() {
rebaser.PlatformAPI = api.MustParse("0.12")
})

when("validating rebasable", func() {
when("rebaseable label is false", func() {
it.Before(func() {
h.AssertNil(t, fakeAppImage.SetLabel(platform.RebaseableLabel, "false"))
})

it("returns an error", func() {
_, err := rebaser.Rebase(fakeAppImage, fakeNewBaseImage, fakeAppImage.Name(), additionalNames)
h.AssertError(t, err, "app image is not marked as rebaseable")
})

when("force is true", func() {
it("allows rebase", func() {
rebaser.Force = true
_, err := rebaser.Rebase(fakeAppImage, fakeNewBaseImage, fakeAppImage.Name(), additionalNames)
h.AssertNil(t, err)
})
})
})

when("rebaseable label is not false", func() {
it.Before(func() {
h.AssertNil(t, fakeAppImage.SetLabel(platform.RebaseableLabel, "true"))
})

it("allows rebase", func() {
_, err := rebaser.Rebase(fakeAppImage, fakeNewBaseImage, fakeAppImage.Name(), additionalNames)
h.AssertNil(t, err)
})
})

when("rebaseable label is empty", func() {

This comment has been minimized.

Copy link
@natalieparellano

natalieparellano Mar 9, 2023

Member

What about when the label is missing? My sense is that we should treat it as safe to rebase, but maybe I'm wrong.

This comment has been minimized.

Copy link
@jabrown85

jabrown85 Mar 9, 2023

Author Contributor

ImgUtil treats labels that aren't there as "" - so they are treated the same and allowed.

it.Before(func() {
h.AssertNil(t, fakeAppImage.SetLabel(platform.RebaseableLabel, ""))
})

it("allows rebase", func() {
_, err := rebaser.Rebase(fakeAppImage, fakeNewBaseImage, fakeAppImage.Name(), additionalNames)
h.AssertNil(t, err)
})
})
})

})

when("validating mixins", func() {
when("there are no mixin labels", func() {
it("allows rebase", func() {
Expand Down

0 comments on commit bfd3344

Please sign in to comment.