Skip to content

Commit acbd243

Browse files
authored
Merge pull request #1111 from buildpacks/fix/1081-1108-buildpack-duplicates
Fix duplicate detection and content collision Signed-off-by: David Freilich <[email protected]>
2 parents b364ad3 + f5856d6 commit acbd243

File tree

17 files changed

+479
-47
lines changed

17 files changed

+479
-47
lines changed

acceptance/acceptance_test.go

+61-1
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,53 @@ func testAcceptance(
704704
builderName = value
705705
})
706706

707+
when("complex builder", func() {
708+
it.Before(func() {
709+
// create our nested builder
710+
h.SkipIf(t, imageManager.HostOS() == "windows", "These tests are not yet compatible with Windows-based containers")
711+
h.SkipIf(t, !createBuilderPack.SupportsFeature(invoke.BuilderNoDuplicateLayers), "bug fixed in 0.18.0")
712+
713+
// create a task, handled by a 'task manager' which executes our pack commands during tests.
714+
// looks like this is used to de-dup tasks
715+
key := taskKey(
716+
"create-complex-builder",
717+
append(
718+
[]string{runImageMirror, createBuilderPackConfig.Path(), lifecycle.Identifier()},
719+
createBuilderPackConfig.FixturePaths()...,
720+
)...,
721+
)
722+
723+
value, err := suiteManager.RunTaskOnceString(key, func() (string, error) {
724+
return createComplexBuilder(
725+
t,
726+
assert,
727+
createBuilderPack,
728+
lifecycle,
729+
buildpackManager,
730+
runImageMirror,
731+
)
732+
})
733+
assert.Nil(err)
734+
735+
// register task to be run to 'clean up' a task
736+
suiteManager.RegisterCleanUp("clean-"+key, func() error {
737+
imageManager.CleanupImages(value)
738+
return nil
739+
})
740+
builderName = value
741+
742+
output := pack.RunSuccessfully(
743+
"config", "run-image-mirrors", "add", "pack-test/run", "--mirror", "some-registry.com/pack-test/run1")
744+
assertOutput := assertions.NewOutputAssertionManager(t, output)
745+
assertOutput.ReportsSuccesfulRunImageMirrorsAdd("pack-test/run", "some-registry.com/pack-test/run1")
746+
})
747+
when("builder has duplicate buildpacks", func() {
748+
it("buildpack layers have no duplication", func() {
749+
assertImage.DoesNotHaveDuplicateLayers(builderName)
750+
})
751+
})
752+
})
753+
707754
when("builder.toml is invalid", func() {
708755
it("displays an error", func() {
709756
builderConfigPath := createBuilderPack.FixtureManager().FixtureLocation("invalid_builder.toml")
@@ -1941,6 +1988,7 @@ include = [ "*.jar", "media/mountain.jpg", "/media/person.png", ]
19411988
it.Before(func() {
19421989
// create our nested builder
19431990
h.SkipIf(t, imageManager.HostOS() == "windows", "These tests are not yet compatible with Windows-based containers")
1991+
h.SkipIf(t, !pack.SupportsFeature(invoke.BuilderNoDuplicateLayers), "bug fixed in 0.18.0")
19441992

19451993
// create a task, handled by a 'task manager' which executes our pack commands during tests.
19461994
// looks like this is used to de-dup tasks
@@ -2457,12 +2505,14 @@ func createComplexBuilder(t *testing.T,
24572505
packageImageName := registryConfig.RepoName("nested-level-1-buildpack-" + h.RandString(8))
24582506
nestedLevelTwoBuildpackName := registryConfig.RepoName("nested-level-2-buildpack-" + h.RandString(8))
24592507
simpleLayersBuildpackName := registryConfig.RepoName("simple-layers-buildpack-" + h.RandString(8))
2508+
simpleLayersBuildpackDifferentShaName := registryConfig.RepoName("simple-layers-buildpack-different-name-" + h.RandString(8))
24602509

24612510
templateMapping["package_id"] = "simple/nested-level-1"
24622511
templateMapping["package_image_name"] = packageImageName
24632512
templateMapping["nested_level_1_buildpack"] = packageImageName
24642513
templateMapping["nested_level_2_buildpack"] = nestedLevelTwoBuildpackName
24652514
templateMapping["simple_layers_buildpack"] = simpleLayersBuildpackName
2515+
templateMapping["simple_layers_buildpack_different_sha"] = simpleLayersBuildpackDifferentShaName
24662516

24672517
fixtureManager := pack.FixtureManager()
24682518

@@ -2483,6 +2533,7 @@ func createComplexBuilder(t *testing.T,
24832533
nestedLevelTwoConfigFile,
24842534
templateMapping,
24852535
)
2536+
24862537
err = nestedLevelTwoConfigFile.Close()
24872538
assert.Nil(err)
24882539

@@ -2512,11 +2563,20 @@ func createComplexBuilder(t *testing.T,
25122563
),
25132564
)
25142565

2515-
defer imageManager.CleanupImages(packageImageName, nestedLevelTwoBuildpackName, simpleLayersBuildpackName)
2566+
simpleLayersDifferentShaBuildpack := buildpacks.NewPackageImage(
2567+
t,
2568+
pack,
2569+
simpleLayersBuildpackDifferentShaName,
2570+
fixtureManager.FixtureLocation("simple-layers-buildpack-different-sha_package.toml"),
2571+
buildpacks.WithRequiredBuildpacks(buildpacks.SimpleLayersDifferentSha),
2572+
)
2573+
2574+
defer imageManager.CleanupImages(packageImageName, nestedLevelTwoBuildpackName, simpleLayersBuildpackName, simpleLayersBuildpackDifferentShaName)
25162575

25172576
builderBuildpacks = append(
25182577
builderBuildpacks,
25192578
packageImageBuildpack,
2579+
simpleLayersDifferentShaBuildpack,
25202580
)
25212581

25222582
buildpackManager.PrepareBuildpacks(tmpDir, builderBuildpacks...)

acceptance/assertions/image.go

+16
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,19 @@ func (a ImageAssertionManager) NotExistsInRegistry(name string) {
100100
"Didn't expect to see image %s in the registry",
101101
)
102102
}
103+
104+
func (a ImageAssertionManager) DoesNotHaveDuplicateLayers(name string) {
105+
a.testObject.Helper()
106+
107+
out, err := a.imageManager.InspectLocal(name)
108+
a.assert.Nil(err)
109+
110+
layerSet := map[string]interface{}{}
111+
for _, layer := range out.RootFS.Layers {
112+
_, ok := layerSet[layer]
113+
if ok {
114+
a.testObject.Fatalf("duplicate layer found in builder %s", layer)
115+
}
116+
layerSet[layer] = true
117+
}
118+
}

acceptance/buildpacks/archive_buildpack.go

+13-12
Original file line numberDiff line numberDiff line change
@@ -84,16 +84,17 @@ func (a archiveBuildpack) createTgz(sourceDir string) (string, error) {
8484
}
8585

8686
var (
87-
SimpleLayersParent = &archiveBuildpack{name: "simple-layers-parent-buildpack"}
88-
SimpleLayers = &archiveBuildpack{name: "simple-layers-buildpack"}
89-
InternetCapable = &archiveBuildpack{name: "internet-capable-buildpack"}
90-
ReadVolume = &archiveBuildpack{name: "read-volume-buildpack"}
91-
ReadWriteVolume = &archiveBuildpack{name: "read-write-volume-buildpack"}
92-
ArchiveNotInBuilder = &archiveBuildpack{name: "not-in-builder-buildpack"}
93-
Noop = &archiveBuildpack{name: "noop-buildpack"}
94-
Noop2 = &archiveBuildpack{name: "noop-buildpack-2"}
95-
OtherStack = &archiveBuildpack{name: "other-stack-buildpack"}
96-
ReadEnv = &archiveBuildpack{name: "read-env-buildpack"}
97-
NestedLevelOne = &archiveBuildpack{name: "nested-level-1-buildpack"}
98-
NestedLevelTwo = &archiveBuildpack{name: "nested-level-2-buildpack"}
87+
SimpleLayersParent = &archiveBuildpack{name: "simple-layers-parent-buildpack"}
88+
SimpleLayers = &archiveBuildpack{name: "simple-layers-buildpack"}
89+
SimpleLayersDifferentSha = &archiveBuildpack{name: "simple-layers-buildpack-different-sha"}
90+
InternetCapable = &archiveBuildpack{name: "internet-capable-buildpack"}
91+
ReadVolume = &archiveBuildpack{name: "read-volume-buildpack"}
92+
ReadWriteVolume = &archiveBuildpack{name: "read-write-volume-buildpack"}
93+
ArchiveNotInBuilder = &archiveBuildpack{name: "not-in-builder-buildpack"}
94+
Noop = &archiveBuildpack{name: "noop-buildpack"}
95+
Noop2 = &archiveBuildpack{name: "noop-buildpack-2"}
96+
OtherStack = &archiveBuildpack{name: "other-stack-buildpack"}
97+
ReadEnv = &archiveBuildpack{name: "read-env-buildpack"}
98+
NestedLevelOne = &archiveBuildpack{name: "nested-level-1-buildpack"}
99+
NestedLevelTwo = &archiveBuildpack{name: "nested-level-2-buildpack"}
99100
)

acceptance/buildpacks/package_image_buildpack.go

+1
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ func (p PackageImage) Prepare(sourceDir, _ string) error {
8383
packArgs = append(packArgs, "--publish")
8484
}
8585

86+
p.testObject.Log("packaging image: ", p.name)
8687
output := p.pack.RunSuccessfully("buildpack", append([]string{"package"}, packArgs...)...)
8788
assertOutput := assertions.NewOutputAssertionManager(p.testObject, output)
8889
if p.publish {

acceptance/invoke/pack.go

+4
Original file line numberDiff line numberDiff line change
@@ -219,12 +219,16 @@ type Feature int
219219

220220
const (
221221
InspectRemoteImage = iota
222+
BuilderNoDuplicateLayers
222223
)
223224

224225
var featureTests = map[Feature]func(i *PackInvoker) bool{
225226
InspectRemoteImage: func(i *PackInvoker) bool {
226227
return i.laterThan("0.17.0")
227228
},
229+
BuilderNoDuplicateLayers: func(i *PackInvoker) bool {
230+
return i.laterThan("0.18.0")
231+
},
228232
}
229233

230234
func (i *PackInvoker) SupportsFeature(f Feature) bool {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#!/usr/bin/env bash
2+
3+
echo "---> Build: Simple Layers Different Sha Buildpack"
4+
5+
set -o errexit
6+
set -o nounset
7+
set -o pipefail
8+
9+
launch_dir=$1
10+
11+
## makes a launch layer
12+
echo "making launch layer"
13+
14+
# Add color line, to test for --no-color
15+
echo "Color: Styled"
16+
17+
mkdir "$launch_dir/launch-layer"
18+
echo "Launch Dep Contents" > "$launch_dir/launch-layer/launch-dep"
19+
ln -snf "$launch_dir/launch-layer" launch-deps
20+
echo "launch = true" > "$launch_dir/launch-layer.toml"
21+
22+
## makes a cached launch layer
23+
if [[ ! -f "$launch_dir/cached-launch-layer.toml" ]]; then
24+
echo "making cached launch layer"
25+
mkdir "$launch_dir/cached-launch-layer"
26+
echo "Cached Dep Contents" > "$launch_dir/cached-launch-layer/cached-dep"
27+
ln -snf "$launch_dir/cached-launch-layer" cached-deps
28+
echo "launch = true" > "$launch_dir/cached-launch-layer.toml"
29+
echo "cache = true" >> "$launch_dir/cached-launch-layer.toml"
30+
else
31+
echo "reusing cached launch layer"
32+
ln -snf "$launch_dir/cached-launch-layer" cached-deps
33+
fi
34+
35+
## adds a process
36+
cat <<EOF > "$launch_dir/launch.toml"
37+
[[processes]]
38+
type = "web"
39+
command = "./run"
40+
args = ["8080"]
41+
42+
[[processes]]
43+
type = "hello"
44+
command = "echo"
45+
args = ["hello", "world"]
46+
direct = true
47+
EOF
48+
49+
echo "---> Done"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
@echo off
2+
echo --- Build: Simple Layers Different Sha Buildpack
3+
4+
set launch_dir=%1
5+
6+
:: makes a launch layer
7+
echo making launch layer %launch_dir%\launch-layer
8+
mkdir %launch_dir%\launch-layer
9+
echo Launch Dep Contents > "%launch_dir%\launch-layer\launch-dep
10+
mklink /j launch-deps %launch_dir%\launch-layer
11+
echo launch = true > %launch_dir%\launch-layer.toml
12+
13+
:: makes a cached launch layer
14+
if not exist %launch_dir%\cached-launch-layer.toml (
15+
echo making cached launch layer %launch_dir%\cached-launch-layer
16+
mkdir %launch_dir%\cached-launch-layer
17+
echo Cached Dep Contents > %launch_dir%\cached-launch-layer\cached-dep
18+
mklink /j cached-deps %launch_dir%\cached-launch-layer
19+
echo launch = true > %launch_dir%\cached-launch-layer.toml
20+
echo cache = true >> %launch_dir%\cached-launch-layer.toml
21+
) else (
22+
echo reusing cached launch layer %launch_dir%\cached-launch-layer
23+
mklink /j cached-deps %launch_dir%\cached-launch-layer
24+
)
25+
26+
:: adds a process
27+
(
28+
echo [[processes]]
29+
echo type = "web"
30+
echo command = '.\run'
31+
echo args = ["8080"]
32+
echo.
33+
echo [[processes]]
34+
echo type = "hello"
35+
echo command = "cmd"
36+
echo args = ["/c", "echo hello world"]
37+
echo direct = true
38+
) > %launch_dir%\launch.toml
39+
40+
echo --- Done
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/usr/bin/env bash
2+
3+
## always detect
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
@echo off
2+
:: always detect
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Just some extra content to change the sha256 of this buildpack :)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
api = "0.2"
2+
3+
[buildpack]
4+
id = "simple/layers"
5+
version = "simple-layers-version"
6+
name = "Simple Layers Buildpack"
7+
8+
[[stacks]]
9+
id = "pack.test.stack"

acceptance/testdata/pack_fixtures/nested_builder.toml

+2-3
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,9 @@
1111
# noop-buildpack-2 has the same id but a different version compared to noop-buildpack
1212
uri = "noop-buildpack-2.tgz"
1313

14-
15-
{{- if .simple_layers_buildpack}}
14+
{{- if .simple_layers_buildpack_different_sha}}
1615
[[buildpacks]]
17-
image = "{{.simple_layers_buildpack}}"
16+
image = "{{.simple_layers_buildpack_different_sha}}"
1817
version = "simple-layers-version"
1918
{{- end}}
2019

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[buildpack]
2+
uri = "simple-layers-buildpack-different-sha.tgz"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[buildpack]
2+
uri = "simple-layers-buildpack-different-sha.tgz"

0 commit comments

Comments
 (0)