Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New flatten buildpacks/builder implementation - Part 2 - Implementing RFC-0123 #1985

Merged
merged 11 commits into from
Jan 22, 2024
Prev Previous commit
Next Next commit
adding more test coverage
Signed-off-by: Juan Bustamante <jbustamante@vmware.com>
  • Loading branch information
jjbustamante committed Jan 20, 2024
commit 4690d2590aaa8c580a7447561fc4b7a6bfacd5bf
4 changes: 4 additions & 0 deletions pkg/buildpack/managed_collection.go
Original file line number Diff line number Diff line change
@@ -58,6 +58,7 @@ type managedCollectionV1 struct {
flattenAll bool
}

// NewManagedCollectionV1 will create a manager instance responsible for flattening Buildpack Packages.
func NewManagedCollectionV1(flattenAll bool) ManagedCollection {
return &managedCollectionV1{
flattenAll: flattenAll,
@@ -84,6 +85,9 @@ func (f *managedCollectionV1) AddModules(main BuildModule, deps ...BuildModule)
}
}

// NewManagedCollectionV2 will create a manager instance responsible for flattening buildpacks inside a Builder.
// The flattened build modules provided are the groups on buildpacks that must be put in a particular layer, the manager
// will take care of keeping them in the correct group (flattened or exploded) once they are added.
func NewManagedCollectionV2(modules FlattenModuleInfos) ManagedCollection {
flattenGroups := 0
if modules != nil {
259 changes: 188 additions & 71 deletions pkg/buildpack/managed_collection_test.go
Original file line number Diff line number Diff line change
@@ -30,15 +30,16 @@ func testModuleManager(t *testing.T, when spec.G, it spec.S) {
* bp31
*/
var (
moduleManager buildpack.ManagedCollection
compositeBP1 buildpack.BuildModule
bp1 buildpack.BuildModule
compositeBP2 buildpack.BuildModule
bp21 buildpack.BuildModule
bp22 buildpack.BuildModule
compositeBP3 buildpack.BuildModule
bp31 buildpack.BuildModule
err error
moduleManager buildpack.ManagedCollection
compositeBP1 buildpack.BuildModule
bp1 buildpack.BuildModule
compositeBP2 buildpack.BuildModule
bp21 buildpack.BuildModule
bp22 buildpack.BuildModule
compositeBP3 buildpack.BuildModule
bp31 buildpack.BuildModule
flattenBuildModules buildpack.FlattenModuleInfos
err error
)

it.Before(func() {
@@ -137,101 +138,217 @@ func testModuleManager(t *testing.T, when spec.G, it spec.S) {
})

when("manager is configured in flatten mode", func() {
when("flatten all", func() {
it.Before(func() {
moduleManager = buildpack.NewManagedCollectionV1(true)
moduleManager.AddModules(compositeBP1, []buildpack.BuildModule{bp1, compositeBP2, bp21, bp22, compositeBP3, bp31}...)
when("V1 is used", func() {
when("flatten all", func() {
it.Before(func() {
moduleManager = buildpack.NewManagedCollectionV1(true)
moduleManager.AddModules(compositeBP1, []buildpack.BuildModule{bp1, compositeBP2, bp21, bp22, compositeBP3, bp31}...)
})

when("#FlattenedModules", func() {
it("returns one flatten module (1 layer)", func() {
modules := moduleManager.FlattenedModules()
h.AssertEq(t, len(modules), 1)
h.AssertEq(t, len(modules[0]), 7)
})
})

when("#ExplodedModules", func() {
it("returns empty", func() {
modules := moduleManager.ExplodedModules()
h.AssertEq(t, len(modules), 0)
})
})

when("#AllModules", func() {
it("returns all explodedModules", func() {
modules := moduleManager.AllModules()
h.AssertEq(t, len(modules), 7)
})
})

when("#ShouldFlatten", func() {
it("returns true for flatten explodedModules", func() {
h.AssertTrue(t, moduleManager.ShouldFlatten(compositeBP1))
h.AssertTrue(t, moduleManager.ShouldFlatten(bp1))
h.AssertTrue(t, moduleManager.ShouldFlatten(compositeBP2))
h.AssertTrue(t, moduleManager.ShouldFlatten(bp21))
h.AssertTrue(t, moduleManager.ShouldFlatten(bp22))
h.AssertTrue(t, moduleManager.ShouldFlatten(compositeBP3))
h.AssertTrue(t, moduleManager.ShouldFlatten(bp31))
})
})
})
})

when("#FlattenedModules", func() {
it("returns one flatten module (1 layer)", func() {
modules := moduleManager.FlattenedModules()
h.AssertEq(t, len(modules), 1)
h.AssertEq(t, len(modules[0]), 7)
when("V2 is used", func() {
when("flattened build modules are provided", func() {
it.Before(func() {
flattenBuildModules, err = buildpack.ParseFlattenBuildModules([]string{"composite-buildpack-3-id@composite-buildpack-3-version,buildpack-31-id@buildpack-31-version", "composite-buildpack-2-id@composite-buildpack-2-version,buildpack-21-id@buildpack-21-version,buildpack-22-id@buildpack-22-version"})
h.AssertNil(t, err)

moduleManager = buildpack.NewManagedCollectionV2(flattenBuildModules)
moduleManager.AddModules(compositeBP1, []buildpack.BuildModule{bp1, compositeBP2, bp21, bp22, compositeBP3, bp31}...)
})

when("#FlattenedModules", func() {
it("returns two flatten module (2 layers)", func() {
modules := moduleManager.FlattenedModules()
h.AssertEq(t, len(modules), 2)
h.AssertTrue(t, len(modules[0]) == 2 || len(modules[0]) == 3)
if len(modules[0]) == 2 {
h.AssertEq(t, len(modules[1]), 3)
} else if len(modules[0]) == 3 {
h.AssertEq(t, len(modules[1]), 2)
}
})
})

when("#ExplodedModules", func() {
it("returns two explodes modules: compositeBP1 and bp1", func() {
modules := moduleManager.ExplodedModules()
h.AssertEq(t, len(modules), 2)
})
})

when("#AllModules", func() {
it("returns all explodedModules", func() {
modules := moduleManager.AllModules()
h.AssertEq(t, len(modules), 7)
})
})

when("#ShouldFlatten", func() {
it("returns true for flatten explodedModules", func() {
// exploded modules
h.AssertFalse(t, moduleManager.ShouldFlatten(compositeBP1))
h.AssertFalse(t, moduleManager.ShouldFlatten(bp1))

// flattened modules
h.AssertTrue(t, moduleManager.ShouldFlatten(compositeBP2))
h.AssertTrue(t, moduleManager.ShouldFlatten(bp21))
h.AssertTrue(t, moduleManager.ShouldFlatten(bp22))
h.AssertTrue(t, moduleManager.ShouldFlatten(compositeBP3))
h.AssertTrue(t, moduleManager.ShouldFlatten(bp31))
})
})
})
})
})

when("manager is not configured in flatten mode", func() {
when("V1 is used", func() {
it.Before(func() {
moduleManager = buildpack.NewManagedCollectionV1(false)
})

when("#ExplodedModules", func() {
it("returns empty", func() {
it("returns nil when no explodedModules are added", func() {
modules := moduleManager.ExplodedModules()
h.AssertEq(t, len(modules), 0)
})

when("explodedModules are added", func() {
it.Before(func() {
moduleManager.AddModules(compositeBP1, []buildpack.BuildModule{bp1, compositeBP2, bp21, bp22, compositeBP3, bp31}...)
})
it("returns all explodedModules added", func() {
modules := moduleManager.ExplodedModules()
h.AssertEq(t, len(modules), 7)
})
})
})

when("#AllModules", func() {
it("returns all explodedModules", func() {
modules := moduleManager.AllModules()
h.AssertEq(t, len(modules), 7)
when("#FlattenedModules", func() {
it("returns nil when no explodedModules are added", func() {
modules := moduleManager.FlattenedModules()
h.AssertEq(t, len(modules), 0)
})

when("explodedModules are added", func() {
it.Before(func() {
moduleManager.AddModules(compositeBP1, []buildpack.BuildModule{bp1, compositeBP2, bp21, bp22, compositeBP3, bp31}...)
})
it("returns nil", func() {
modules := moduleManager.FlattenedModules()
h.AssertEq(t, len(modules), 0)
})
})
})

when("#ShouldFlatten", func() {
it("returns true for flatten explodedModules", func() {
h.AssertTrue(t, moduleManager.ShouldFlatten(compositeBP1))
h.AssertTrue(t, moduleManager.ShouldFlatten(bp1))
h.AssertTrue(t, moduleManager.ShouldFlatten(compositeBP2))
h.AssertTrue(t, moduleManager.ShouldFlatten(bp21))
h.AssertTrue(t, moduleManager.ShouldFlatten(bp22))
h.AssertTrue(t, moduleManager.ShouldFlatten(compositeBP3))
h.AssertTrue(t, moduleManager.ShouldFlatten(bp31))
it("returns false when no explodedModules are added", func() {
h.AssertFalse(t, moduleManager.ShouldFlatten(bp1))
})
})
})
})

when("manager is not configured in flatten mode", func() {
it.Before(func() {
moduleManager = buildpack.NewManagedCollectionV1(false)
when("explodedModules are added", func() {
it.Before(func() {
moduleManager.AddModules(compositeBP1, []buildpack.BuildModule{bp1, compositeBP2, bp21, bp22, compositeBP3, bp31}...)
})
it("returns false", func() {
h.AssertFalse(t, moduleManager.ShouldFlatten(bp1))
h.AssertFalse(t, moduleManager.ShouldFlatten(bp21))
h.AssertFalse(t, moduleManager.ShouldFlatten(bp22))
h.AssertFalse(t, moduleManager.ShouldFlatten(bp31))
})
})
})
})

when("#ExplodedModules", func() {
it("returns nil when no explodedModules are added", func() {
modules := moduleManager.ExplodedModules()
h.AssertEq(t, len(modules), 0)
when("V2 is used", func() {
it.Before(func() {
moduleManager = buildpack.NewManagedCollectionV2(nil)
})

when("explodedModules are added", func() {
it.Before(func() {
moduleManager.AddModules(compositeBP1, []buildpack.BuildModule{bp1, compositeBP2, bp21, bp22, compositeBP3, bp31}...)
})
it("returns all explodedModules added", func() {
when("#ExplodedModules", func() {
it("returns nil when no explodedModules are added", func() {
modules := moduleManager.ExplodedModules()
h.AssertEq(t, len(modules), 7)
h.AssertEq(t, len(modules), 0)
})
})
})

when("#FlattenedModules", func() {
it("returns nil when no explodedModules are added", func() {
modules := moduleManager.FlattenedModules()
h.AssertEq(t, len(modules), 0)
when("explodedModules are added", func() {
it.Before(func() {
moduleManager.AddModules(compositeBP1, []buildpack.BuildModule{bp1, compositeBP2, bp21, bp22, compositeBP3, bp31}...)
})
it("returns all explodedModules added", func() {
modules := moduleManager.ExplodedModules()
h.AssertEq(t, len(modules), 7)
})
})
})

when("explodedModules are added", func() {
it.Before(func() {
moduleManager.AddModules(compositeBP1, []buildpack.BuildModule{bp1, compositeBP2, bp21, bp22, compositeBP3, bp31}...)
})
it("returns nil", func() {
when("#FlattenedModules", func() {
it("returns nil when no explodedModules are added", func() {
modules := moduleManager.FlattenedModules()
h.AssertEq(t, len(modules), 0)
})
})
})

when("#ShouldFlatten", func() {
it("returns false when no explodedModules are added", func() {
h.AssertFalse(t, moduleManager.ShouldFlatten(bp1))
when("explodedModules are added", func() {
it.Before(func() {
moduleManager.AddModules(compositeBP1, []buildpack.BuildModule{bp1, compositeBP2, bp21, bp22, compositeBP3, bp31}...)
})
it("returns nil", func() {
modules := moduleManager.FlattenedModules()
h.AssertEq(t, len(modules), 0)
})
})
})

when("explodedModules are added", func() {
it.Before(func() {
moduleManager.AddModules(compositeBP1, []buildpack.BuildModule{bp1, compositeBP2, bp21, bp22, compositeBP3, bp31}...)
})
it("returns false", func() {
when("#ShouldFlatten", func() {
it("returns false when no explodedModules are added", func() {
h.AssertFalse(t, moduleManager.ShouldFlatten(bp1))
h.AssertFalse(t, moduleManager.ShouldFlatten(bp21))
h.AssertFalse(t, moduleManager.ShouldFlatten(bp22))
h.AssertFalse(t, moduleManager.ShouldFlatten(bp31))
})

when("explodedModules are added", func() {
it.Before(func() {
moduleManager.AddModules(compositeBP1, []buildpack.BuildModule{bp1, compositeBP2, bp21, bp22, compositeBP3, bp31}...)
})
it("returns false", func() {
h.AssertFalse(t, moduleManager.ShouldFlatten(bp1))
h.AssertFalse(t, moduleManager.ShouldFlatten(bp21))
h.AssertFalse(t, moduleManager.ShouldFlatten(bp22))
h.AssertFalse(t, moduleManager.ShouldFlatten(bp31))
})
})
})
})
32 changes: 22 additions & 10 deletions pkg/client/create_builder_test.go
Original file line number Diff line number Diff line change
@@ -997,6 +997,7 @@ func testCreateBuilder(t *testing.T, when spec.G, it spec.S) {
*/
var (
fakeLayerImage *h.FakeAddedLayerImage
err error
)

var successfullyCreateFlattenBuilder = func() {
@@ -1068,7 +1069,7 @@ func testCreateBuilder(t *testing.T, when spec.G, it spec.S) {
})

when("flatten all", func() {
var err error

it("creates 1 layer for all buildpacks", func() {
prepareFetcherWithRunImages()
opts.Flatten, err = buildpack.ParseFlattenBuildModules([]string{"flatten/bp-1@1,flatten/bp-2@2,flatten/bp-4@4,flatten/bp-6@6,flatten/bp-7@7,flatten/bp-3@3,flatten/bp-5@5"})
@@ -1080,18 +1081,29 @@ func testCreateBuilder(t *testing.T, when spec.G, it spec.S) {

h.AssertEq(t, len(layers), 1)
})
})

when("only some modules are flattened", func() {
it("creates 1 layer for buildpacks and 1 layer for buildpack excluded", func() {
prepareFetcherWithRunImages()
opts.Flatten, err = buildpack.ParseFlattenBuildModules([]string{"flatten/bp-1@1,flatten/bp-2@2,flatten/bp-4@4,flatten/bp-6@6,flatten/bp-3@3,flatten/bp-5@5"})
h.AssertNil(t, err)
when("only some modules are flattened", func() {
it("creates 1 layer for buildpacks [1,2,3,4,5,6] and 1 layer for buildpack [7]", func() {
prepareFetcherWithRunImages()
opts.Flatten, err = buildpack.ParseFlattenBuildModules([]string{"flatten/bp-1@1,flatten/bp-2@2,flatten/bp-4@4,flatten/bp-6@6,flatten/bp-3@3,flatten/bp-5@5"})
h.AssertNil(t, err)

successfullyCreateFlattenBuilder()
successfullyCreateFlattenBuilder()

layers := fakeLayerImage.AddedLayersOrder()
h.AssertEq(t, len(layers), 2)
})
layers := fakeLayerImage.AddedLayersOrder()
h.AssertEq(t, len(layers), 2)
})

it("creates 1 layer for buildpacks [1,2,3] and 1 layer for [4,5,6] and 1 layer for [7]", func() {
prepareFetcherWithRunImages()
opts.Flatten, err = buildpack.ParseFlattenBuildModules([]string{"flatten/bp-1@1,flatten/bp-2@2,flatten/bp-3@3", "flatten/bp-4@4,flatten/bp-6@6,flatten/bp-5@5"})
h.AssertNil(t, err)

successfullyCreateFlattenBuilder()

layers := fakeLayerImage.AddedLayersOrder()
h.AssertEq(t, len(layers), 3)
})
})
})
Loading