diff --git a/acceptance/analyzer_test.go b/acceptance/analyzer_test.go index c02fd1d1e..aca6b1af4 100644 --- a/acceptance/analyzer_test.go +++ b/acceptance/analyzer_test.go @@ -102,62 +102,28 @@ func testAnalyzerFunc(platformAPI string) func(t *testing.T, when spec.G, it spe }) }) - when("called with group", func() { - it("errors", func() { - h.SkipIf(t, api.MustParse(platformAPI).LessThan("0.7"), "Platform API < 0.7 accepts a -group flag") - cmd := exec.Command( - "docker", "run", "--rm", - "--env", "CNB_PLATFORM_API="+platformAPI, - analyzeImage, - ctrPath(analyzerPath), - "-group", "group.toml", - "some-image", - ) // #nosec G204 - output, err := cmd.CombinedOutput() - - h.AssertNotNil(t, err) - expected := "flag provided but not defined: -group" - h.AssertStringContains(t, string(output), expected) - }) - }) - when("called with skip layers", func() { - it("errors", func() { - h.SkipIf(t, - api.MustParse(platformAPI).LessThan("0.7") || api.MustParse(platformAPI).AtLeast("0.9"), - "Platform API < 0.7 or Platform API > 0.9 accepts a -skip-layers flag") - cmd := exec.Command( - "docker", "run", "--rm", - "--env", "CNB_PLATFORM_API="+platformAPI, - analyzeImage, - ctrPath(analyzerPath), - "-skip-layers", - "some-image", - ) // #nosec G204 - output, err := cmd.CombinedOutput() - - h.AssertNotNil(t, err) - expected := "flag provided but not defined: -skip-layers" - h.AssertStringContains(t, string(output), expected) - }) - }) - - when("called with cache dir", func() { - it("errors", func() { - h.SkipIf(t, api.MustParse(platformAPI).LessThan("0.7"), "Platform API < 0.7 accepts a -cache-dir flag") - cmd := exec.Command( - "docker", "run", "--rm", - "--env", "CNB_PLATFORM_API="+platformAPI, + it("writes analyzed.toml and does not restore previous image SBOM", func() { + h.SkipIf(t, api.MustParse(platformAPI).LessThan("0.9"), "Platform API < 0.9 does not accept a -skip-layers flag") + output := h.DockerRunAndCopy(t, + containerName, + copyDir, + ctrPath("/layers"), analyzeImage, - ctrPath(analyzerPath), - "-cache-dir", "/cache", - "some-image", - ) // #nosec G204 - output, err := cmd.CombinedOutput() - - h.AssertNotNil(t, err) - expected := "flag provided but not defined: -cache-dir" - h.AssertStringContains(t, string(output), expected) + h.WithFlags(append( + dockerSocketMount, + "--env", "CNB_PLATFORM_API="+platformAPI, + )...), + h.WithArgs( + ctrPath(analyzerPath), + "-daemon", + "-run-image", analyzeRegFixtures.ReadOnlyRunImage, + "-skip-layers", + analyzeDaemonFixtures.AppImage, + ), + ) + assertAnalyzedMetadata(t, filepath.Join(copyDir, "layers", "analyzed.toml")) + h.AssertStringDoesNotContain(t, output, "Restoring data for SBOM from previous image") }) }) @@ -165,10 +131,7 @@ func testAnalyzerFunc(platformAPI string) func(t *testing.T, when spec.G, it spe it("recursively chowns the directory", func() { h.SkipIf(t, runtime.GOOS == "windows", "Not relevant on Windows") - var analyzeFlags []string - if api.MustParse(platformAPI).AtLeast("0.7") { - analyzeFlags = append(analyzeFlags, []string{"-run-image", analyzeRegFixtures.ReadOnlyRunImage}...) - } + analyzeFlags := []string{"-run-image", analyzeRegFixtures.ReadOnlyRunImage} output := h.DockerRun(t, analyzeImage, @@ -190,61 +153,11 @@ func testAnalyzerFunc(platformAPI string) func(t *testing.T, when spec.G, it spe }) }) - when("called with group (on older platforms)", func() { - it("uses the provided group.toml path", func() { - h.SkipIf(t, api.MustParse(platformAPI).AtLeast("0.7"), "Platform API >= 0.7 does not accept a -group flag") - - h.DockerSeedRunAndCopy(t, - containerName, - cacheFixtureDir, ctrPath("/cache"), - copyDir, ctrPath("/layers"), - analyzeImage, - h.WithFlags( - "--env", "CNB_PLATFORM_API="+platformAPI, - ), - h.WithArgs( - ctrPath(analyzerPath), - "-cache-dir", ctrPath("/cache"), - "-group", ctrPath("/layers/other-group.toml"), - "some-image", - ), - ) - - h.AssertPathExists(t, filepath.Join(copyDir, "layers", "some-other-buildpack-id")) - h.AssertPathDoesNotExist(t, filepath.Join(copyDir, "layers", "some-buildpack-id")) - }) - - when("group contains unsupported buildpacks", func() { - it("errors", func() { - h.SkipIf(t, api.MustParse(platformAPI).AtLeast("0.7"), "Platform API >= 0.7 does not accept a -group flag") - - cmd := exec.Command( - "docker", "run", "--rm", - "--env", "CNB_PLATFORM_API="+platformAPI, - analyzeImage, - ctrPath(analyzerPath), - "-group", ctrPath("/layers/unsupported-group.toml"), - "some-image", - ) // #nosec G204 - output, err := cmd.CombinedOutput() - - h.AssertNotNil(t, err) - failErr, ok := err.(*exec.ExitError) - if !ok { - t.Fatalf("expected an error of type exec.ExitError") - } - h.AssertEq(t, failErr.ExitCode(), 12) // platform code for buildpack api incompatibility - expected := "buildpack API version '0.1' is incompatible with the lifecycle" - h.AssertStringContains(t, string(output), expected) - }) - }) - }) - when("called with analyzed", func() { it("uses the provided analyzed.toml path", func() { - analyzeFlags := []string{"-analyzed", ctrPath("/some-dir/some-analyzed.toml")} - if api.MustParse(platformAPI).AtLeast("0.7") { - analyzeFlags = append(analyzeFlags, "-run-image", analyzeRegFixtures.ReadOnlyRunImage) + analyzeFlags := []string{ + "-analyzed", ctrPath("/some-dir/some-analyzed.toml"), + "-run-image", analyzeRegFixtures.ReadOnlyRunImage, } var execArgs []string @@ -292,9 +205,9 @@ func testAnalyzerFunc(platformAPI string) func(t *testing.T, when spec.G, it spe it("drops privileges", func() { h.SkipIf(t, runtime.GOOS == "windows", "Not relevant on Windows") - analyzeArgs := []string{"-analyzed", "/some-dir/some-analyzed.toml"} - if api.MustParse(platformAPI).AtLeast("0.7") { - analyzeArgs = append(analyzeArgs, "-run-image", analyzeRegFixtures.ReadOnlyRunImage) + analyzeArgs := []string{ + "-analyzed", "/some-dir/some-analyzed.toml", + "-run-image", analyzeRegFixtures.ReadOnlyRunImage, } output := h.DockerRun(t, @@ -319,8 +232,6 @@ func testAnalyzerFunc(platformAPI string) func(t *testing.T, when spec.G, it spe when("run image", func() { when("provided", func() { it("is recorded in analyzed.toml", func() { - h.SkipIf(t, api.MustParse(platformAPI).LessThan("0.7"), "Platform API < 0.7 does not accept run image") - h.DockerRunAndCopy(t, containerName, copyDir, @@ -341,8 +252,6 @@ func testAnalyzerFunc(platformAPI string) func(t *testing.T, when spec.G, it spe when("not provided", func() { it("falls back to CNB_RUN_IMAGE", func() { - h.SkipIf(t, api.MustParse(platformAPI).LessThan("0.7"), "Platform API < 0.7 does not accept run image") - h.DockerRunAndCopy(t, containerName, copyDir, @@ -365,9 +274,9 @@ func testAnalyzerFunc(platformAPI string) func(t *testing.T, when spec.G, it spe when("daemon case", func() { it("writes analyzed.toml", func() { - analyzeFlags := []string{"-daemon"} - if api.MustParse(platformAPI).AtLeast("0.7") { - analyzeFlags = append(analyzeFlags, []string{"-run-image", "some-run-image"}...) + analyzeFlags := []string{ + "-daemon", + "-run-image", "some-run-image", } var execArgs []string @@ -391,8 +300,6 @@ func testAnalyzerFunc(platformAPI string) func(t *testing.T, when spec.G, it spe when("app image exists", func() { it("does not restore app metadata to the layers directory", func() { - h.SkipIf(t, api.MustParse(platformAPI).LessThan("0.7"), "Platform API < 0.7 restores app metadata") - analyzeFlags := []string{"-daemon", "-run-image", "some-run-image"} var execArgs []string @@ -413,248 +320,12 @@ func testAnalyzerFunc(platformAPI string) func(t *testing.T, when spec.G, it spe assertNoRestoreOfAppMetadata(t, copyDir, output) }) - - it("restores app metadata to the layers directory (on older platforms)", func() { - h.SkipIf(t, api.MustParse(platformAPI).AtLeast("0.7"), "Platform API >= 0.7 does not restore app metadata") - output := h.DockerRunAndCopy(t, - containerName, - copyDir, - ctrPath("/layers"), - analyzeImage, - h.WithFlags(append( - dockerSocketMount, - "--env", "CNB_PLATFORM_API="+platformAPI, - )...), - h.WithArgs( - ctrPath(analyzerPath), - "-daemon", - analyzeDaemonFixtures.AppImage, - ), - ) - - assertLogsAndRestoresAppMetadata(t, copyDir, output) - }) - - when("skip layers is provided", func() { - it("writes analyzed.toml and does not write buildpack layer metadata", func() { - h.SkipIf(t, api.MustParse(platformAPI).AtLeast("0.7"), "Platform API >= 0.7 does not accept a -skip-layers flag") - output := h.DockerRunAndCopy(t, - containerName, - copyDir, - ctrPath("/layers"), - analyzeImage, - h.WithFlags(append( - dockerSocketMount, - "--env", "CNB_PLATFORM_API="+platformAPI, - )...), - h.WithArgs( - ctrPath(analyzerPath), - "-daemon", - "-skip-layers", - analyzeDaemonFixtures.AppImage, - ), - ) - - assertAnalyzedMetadata(t, filepath.Join(copyDir, "layers", "analyzed.toml")) - assertWritesStoreTomlOnly(t, copyDir, output) - }) - }) - }) - - when("cache is provided (on older platforms)", func() { - when("cache image case", func() { - when("cache image is in a daemon", func() { - it("ignores the cache", func() { - h.SkipIf(t, api.MustParse(platformAPI).AtLeast("0.7"), "Platform API >= 0.7 does not read from the cache") - - h.DockerRunAndCopy(t, - containerName, - copyDir, - ctrPath("/layers"), - analyzeImage, - h.WithFlags(append( - dockerSocketMount, - "--env", "CNB_PLATFORM_API="+platformAPI, - )...), - h.WithArgs( - ctrPath(analyzerPath), - "-daemon", - "-cache-image", analyzeDaemonFixtures.CacheImage, - "some-image", - ), - ) - - h.AssertPathDoesNotExist(t, filepath.Join(copyDir, "layers", "some-buildpack-id", "some-layer.sha")) - h.AssertPathDoesNotExist(t, filepath.Join(copyDir, "layers", "some-buildpack-id", "some-layer.toml")) - }) - }) - - when("cache image is in a registry", func() { - when("auth registry", func() { - when("registry creds are provided in CNB_REGISTRY_AUTH", func() { - it("restores cache metadata", func() { - h.SkipIf(t, api.MustParse(platformAPI).AtLeast("0.7"), "Platform API >= 0.7 does not read from the cache") - output := h.DockerRunAndCopy(t, - containerName, - copyDir, - "/layers", - analyzeImage, - h.WithFlags(append( - dockerSocketMount, - "--env", "CNB_PLATFORM_API="+platformAPI, - "--env", "CNB_REGISTRY_AUTH="+analyzeRegAuthConfig, - "--network", analyzeRegNetwork, - )...), - h.WithArgs( - ctrPath(analyzerPath), - "-daemon", - "-cache-image", analyzeRegFixtures.SomeCacheImage, - analyzeRegFixtures.SomeAppImage, - ), - ) - - assertLogsAndRestoresCacheMetadata(t, copyDir, output) - }) - }) - - when("registry creds are provided in the docker config.json", func() { - it("restores cache metadata", func() { - h.SkipIf(t, api.MustParse(platformAPI).AtLeast("0.7"), "Platform API >= 0.7 does not read from the cache") - output := h.DockerRunAndCopy(t, - containerName, - copyDir, - ctrPath("/layers"), - analyzeImage, - h.WithFlags( - "--env", "CNB_PLATFORM_API="+platformAPI, - "--env", "DOCKER_CONFIG=/docker-config", - "--network", analyzeRegNetwork, - ), - h.WithArgs( - ctrPath(analyzerPath), - "-cache-image", - analyzeRegFixtures.SomeCacheImage, - analyzeRegFixtures.SomeAppImage, - ), - ) - - assertLogsAndRestoresCacheMetadata(t, copyDir, output) - }) - }) - }) - - when("no auth registry", func() { - it("restores cache metadata", func() { - h.SkipIf(t, api.MustParse(platformAPI).AtLeast("0.7"), "Platform API >= 0.7 does not read from the cache") - output := h.DockerRunAndCopy(t, - containerName, - copyDir, - ctrPath("/layers"), - analyzeImage, - h.WithFlags(append( - dockerSocketMount, - "--env", "CNB_PLATFORM_API="+platformAPI, - "--network", analyzeRegNetwork, - )...), - h.WithArgs( - ctrPath(analyzerPath), - "-daemon", - "-cache-image", - analyzeRegFixtures.ReadOnlyCacheImage, - analyzeRegFixtures.ReadOnlyAppImage, - ), - ) - - assertLogsAndRestoresCacheMetadata(t, copyDir, output) - }) - }) - }) - }) - - when("cache directory case", func() { - it("restores cache metadata", func() { - h.SkipIf(t, api.MustParse(platformAPI).AtLeast("0.7"), "Platform API >= 0.7 does not read from the cache") - output := h.DockerSeedRunAndCopy(t, - containerName, - cacheFixtureDir, ctrPath("/cache"), - copyDir, ctrPath("/layers"), - analyzeImage, - h.WithFlags(append( - dockerSocketMount, - "--env", "CNB_PLATFORM_API="+platformAPI, - )...), - h.WithArgs( - ctrPath(analyzerPath), - "-daemon", - "-cache-dir", ctrPath("/cache"), - "some-image", - ), - ) - - assertLogsAndRestoresCacheMetadata(t, copyDir, output) - }) - - when("the provided cache directory isn't writeable by the CNB user's group", func() { - it("recursively chowns the directory", func() { - h.SkipIf(t, api.MustParse(platformAPI).AtLeast("0.7"), "Platform API >= 0.7 does not read from the cache") - h.SkipIf(t, runtime.GOOS == "windows", "Not relevant on Windows") - - cacheVolume := h.SeedDockerVolume(t, cacheFixtureDir) - defer h.DockerVolumeRemove(t, cacheVolume) - - output := h.DockerRun(t, - analyzeImage, - h.WithFlags(append( - dockerSocketMount, - "--env", "CNB_PLATFORM_API="+platformAPI, - "--volume", cacheVolume+":/cache", - )...), - h.WithBash( - fmt.Sprintf("chown -R 9999:9999 /cache; chmod -R 775 /cache; %s -daemon -cache-dir /cache some-image; ls -alR /cache", analyzerPath), - ), - ) - - h.AssertMatch(t, output, "2222 3333 .+ \\.") - h.AssertMatch(t, output, "2222 3333 .+ committed") - h.AssertMatch(t, output, "2222 3333 .+ staging") - }) - }) - - when("the provided cache directory is writeable by the CNB user's group", func() { - it("doesn't chown the directory", func() { - h.SkipIf(t, runtime.GOOS == "windows", "Not relevant on Windows") - h.SkipIf(t, api.MustParse(platformAPI).AtLeast("0.7"), "Platform API >= 0.7 does not read from the cache") - - cacheVolume := h.SeedDockerVolume(t, cacheFixtureDir) - defer h.DockerVolumeRemove(t, cacheVolume) - - output := h.DockerRun(t, - analyzeImage, - h.WithFlags(append( - dockerSocketMount, - "--env", "CNB_PLATFORM_API="+platformAPI, - "--volume", cacheVolume+":/cache", - )...), - h.WithBash( - fmt.Sprintf("chown -R 9999:3333 /cache; chmod -R 775 /cache; %s -daemon -cache-dir /cache some-image; ls -alR /cache", analyzerPath), - ), - ) - - h.AssertMatch(t, output, "9999 3333 .+ \\.") - h.AssertMatch(t, output, "9999 3333 .+ committed") - h.AssertMatch(t, output, "2222 3333 .+ staging") - }) - }) - }) }) }) when("registry case", func() { it("writes analyzed.toml", func() { - var analyzeFlags []string - if api.MustParse(platformAPI).AtLeast("0.7") { - analyzeFlags = append(analyzeFlags, []string{"-run-image", analyzeRegFixtures.ReadOnlyRunImage}...) - } + analyzeFlags := []string{"-run-image", analyzeRegFixtures.ReadOnlyRunImage} var execArgs []string execArgs = append([]string{ctrPath(analyzerPath)}, analyzeFlags...) @@ -676,139 +347,13 @@ func testAnalyzerFunc(platformAPI string) func(t *testing.T, when spec.G, it spe assertAnalyzedMetadata(t, filepath.Join(copyDir, "analyzed.toml")) }) - when("app image exists", func() { - when("auth registry", func() { - when("registry creds are provided in CNB_REGISTRY_AUTH", func() { - it("restores app metadata", func() { - h.SkipIf(t, api.MustParse(platformAPI).AtLeast("0.7"), "Platform API >= 0.7 does not read app layer metadata") - output := h.DockerRunAndCopy(t, - containerName, - copyDir, - ctrPath("/layers"), - analyzeImage, - h.WithFlags( - "--env", "CNB_PLATFORM_API="+platformAPI, - "--env", "CNB_REGISTRY_AUTH="+analyzeRegAuthConfig, - "--network", analyzeRegNetwork, - ), - h.WithArgs( - ctrPath(analyzerPath), - analyzeRegFixtures.SomeAppImage, - ), - ) - - assertLogsAndRestoresAppMetadata(t, copyDir, output) - }) - }) - - when("registry creds are provided in the docker config.json", func() { - it("restores app metadata", func() { - h.SkipIf(t, api.MustParse(platformAPI).AtLeast("0.7"), "Platform API >= 0.7 does not read app layer metadata") - output := h.DockerRunAndCopy(t, - containerName, - copyDir, - ctrPath("/layers"), - analyzeImage, - h.WithFlags( - "--env", "CNB_PLATFORM_API="+platformAPI, - "--env", "DOCKER_CONFIG=/docker-config", - "--network", analyzeRegNetwork, - ), - h.WithArgs( - ctrPath(analyzerPath), - analyzeRegFixtures.SomeAppImage, - ), - ) - - assertLogsAndRestoresAppMetadata(t, copyDir, output) - }) - }) - - when("skip layers is provided", func() { - it("writes analyzed.toml and does not write buildpack layer metadata", func() { - h.SkipIf(t, api.MustParse(platformAPI).AtLeast("0.7"), "Platform API >= 0.7 does not accept a -skip-layers flag") - output := h.DockerRunAndCopy(t, - containerName, - copyDir, - ctrPath("/layers"), - analyzeImage, - h.WithFlags( - "--env", "CNB_PLATFORM_API="+platformAPI, - "--env", "CNB_REGISTRY_AUTH="+analyzeRegAuthConfig, - "--network", analyzeRegNetwork, - ), - h.WithArgs( - ctrPath(analyzerPath), - "-skip-layers", - analyzeRegFixtures.SomeAppImage, - ), - ) - - assertAnalyzedMetadata(t, filepath.Join(copyDir, "layers", "analyzed.toml")) - assertWritesStoreTomlOnly(t, copyDir, output) - }) - }) - }) - - when("no auth registry", func() { - it("restores app metadata", func() { - h.SkipIf(t, api.MustParse(platformAPI).AtLeast("0.7"), "Platform API >= 0.7 does not read app layer metadata") - - output := h.DockerRunAndCopy(t, - containerName, - copyDir, - ctrPath("/layers"), - analyzeImage, - h.WithFlags( - "--env", "CNB_PLATFORM_API="+platformAPI, - "--network", analyzeRegNetwork, - ), - h.WithArgs( - ctrPath(analyzerPath), - analyzeRegFixtures.ReadOnlyAppImage, - ), - ) - - assertLogsAndRestoresAppMetadata(t, copyDir, output) - }) - - when("skip layers is provided", func() { - it("writes analyzed.toml and does not write buildpack layer metadata", func() { - h.SkipIf(t, api.MustParse(platformAPI).AtLeast("0.7"), "Platform API >= 0.7 does not accept a -skip-layers flag") - output := h.DockerRunAndCopy(t, - containerName, - copyDir, - ctrPath("/layers"), - analyzeImage, - h.WithFlags( - "--env", "CNB_PLATFORM_API="+platformAPI, - "--network", analyzeRegNetwork, - ), - h.WithArgs( - ctrPath(analyzerPath), - "-skip-layers", - analyzeRegFixtures.ReadOnlyAppImage, - ), - ) - - assertAnalyzedMetadata(t, filepath.Join(copyDir, "layers", "analyzed.toml")) - assertWritesStoreTomlOnly(t, copyDir, output) - }) - }) - }) - }) - when("called with previous image", func() { - it.Before(func() { - h.SkipIf(t, api.MustParse(platformAPI).LessThan("0.7"), "Platform API < 0.7 does not support -previous-image") - }) - when("auth registry", func() { when("the destination image does not exist", func() { it("writes analyzed.toml with previous image identifier", func() { - analyzeFlags := []string{"-previous-image", analyzeRegFixtures.ReadWriteAppImage} - if api.MustParse(platformAPI).AtLeast("0.7") { - analyzeFlags = append(analyzeFlags, []string{"-run-image", analyzeRegFixtures.ReadOnlyRunImage}...) + analyzeFlags := []string{ + "-previous-image", analyzeRegFixtures.ReadWriteAppImage, + "-run-image", analyzeRegFixtures.ReadOnlyRunImage, } var execArgs []string @@ -834,9 +379,9 @@ func testAnalyzerFunc(platformAPI string) func(t *testing.T, when spec.G, it spe when("the destination image exists", func() { it("writes analyzed.toml with previous image identifier", func() { - analyzeFlags := []string{"-previous-image", analyzeRegFixtures.ReadWriteAppImage} - if api.MustParse(platformAPI).AtLeast("0.7") { - analyzeFlags = append(analyzeFlags, []string{"-run-image", analyzeRegFixtures.ReadOnlyRunImage}...) + analyzeFlags := []string{ + "-previous-image", analyzeRegFixtures.ReadWriteAppImage, + "-run-image", analyzeRegFixtures.ReadOnlyRunImage, } var execArgs []string @@ -863,111 +408,9 @@ func testAnalyzerFunc(platformAPI string) func(t *testing.T, when spec.G, it spe }) }) - when("cache is provided (on older platforms)", func() { - when("cache image case", func() { - when("auth registry", func() { - when("registry creds are provided in CNB_REGISTRY_AUTH", func() { - it("restores cache metadata", func() { - h.SkipIf(t, api.MustParse(platformAPI).AtLeast("0.7"), "Platform API >= 0.7 does not read from the cache") - output := h.DockerRunAndCopy(t, - containerName, - copyDir, - ctrPath("/layers"), - analyzeImage, - h.WithFlags( - "--env", "CNB_PLATFORM_API="+platformAPI, - "--env", "CNB_REGISTRY_AUTH="+analyzeRegAuthConfig, - "--network", analyzeRegNetwork, - ), - h.WithArgs( - ctrPath(analyzerPath), - "-cache-image", analyzeRegFixtures.SomeCacheImage, - "some-image", - ), - ) - - assertLogsAndRestoresCacheMetadata(t, copyDir, output) - }) - }) - - when("registry creds are provided in the docker config.json", func() { - it("restores cache metadata", func() { - h.SkipIf(t, api.MustParse(platformAPI).AtLeast("0.7"), "Platform API >= 0.7 does not read from the cache") - output := h.DockerRunAndCopy(t, - containerName, - copyDir, - ctrPath("/layers"), - analyzeImage, - h.WithFlags( - "--env", "CNB_PLATFORM_API="+platformAPI, - "--env", "DOCKER_CONFIG=/docker-config", - "--network", analyzeRegNetwork, - ), - h.WithArgs( - ctrPath(analyzerPath), - "-cache-image", - analyzeRegFixtures.SomeCacheImage, - analyzeRegFixtures.SomeAppImage, - ), - ) - - assertLogsAndRestoresCacheMetadata(t, copyDir, output) - }) - }) - }) - - when("no auth registry", func() { - it("restores cache metadata", func() { - h.SkipIf(t, api.MustParse(platformAPI).AtLeast("0.7"), "Platform API >= 0.7 does not read from the cache") - - output := h.DockerRunAndCopy(t, - containerName, - copyDir, - ctrPath("/layers"), - analyzeImage, - h.WithFlags( - "--env", "CNB_PLATFORM_API="+platformAPI, - "--network", analyzeRegNetwork, - ), - h.WithArgs( - ctrPath(analyzerPath), - "-cache-image", analyzeRegFixtures.ReadOnlyCacheImage, - analyzeRegFixtures.ReadOnlyAppImage, - ), - ) - - assertLogsAndRestoresCacheMetadata(t, copyDir, output) - }) - }) - }) - - when("cache directory case", func() { - it("restores cache metadata", func() { - h.SkipIf(t, api.MustParse(platformAPI).AtLeast("0.7"), "Platform API >= 0.7 does not read from the cache") - output := h.DockerSeedRunAndCopy(t, - containerName, - cacheFixtureDir, ctrPath("/cache"), - copyDir, ctrPath("/layers"), - analyzeImage, - h.WithFlags( - "--env", "CNB_PLATFORM_API="+platformAPI, - ), - h.WithArgs( - ctrPath(analyzerPath), - "-cache-dir", ctrPath("/cache"), - "some-image", - ), - ) - - assertLogsAndRestoresCacheMetadata(t, copyDir, output) - }) - }) - }) - when("called with tag", func() { when("read/write access to registry", func() { it("passes read/write validation and writes analyzed.toml", func() { - h.SkipIf(t, api.MustParse(platformAPI).LessThan("0.7"), "Platform API < 0.7 does not use tag flag") execArgs := []string{ ctrPath(analyzerPath), "-tag", analyzeRegFixtures.ReadWriteOtherAppImage, @@ -993,7 +436,6 @@ func testAnalyzerFunc(platformAPI string) func(t *testing.T, when spec.G, it spe when("no read/write access to registry", func() { it("throws read/write error accessing destination tag", func() { - h.SkipIf(t, api.MustParse(platformAPI).LessThan("0.7"), "Platform API < 0.7 does not use tag flag") cmd := exec.Command( "docker", "run", "--rm", "--env", "CNB_PLATFORM_API="+platformAPI, @@ -1021,12 +463,11 @@ func testAnalyzerFunc(platformAPI string) func(t *testing.T, when spec.G, it spe it("writes analyzed.toml", func() { h.SkipIf(t, api.MustParse(platformAPI).LessThan("0.12"), "Platform API < 0.12 does not accept a -layout flag") - var analyzeFlags []string - analyzeFlags = append(analyzeFlags, []string{ + analyzeFlags := []string{ "-layout", "-layout-dir", layoutDir, "-run-image", "busybox", - }...) + } var execArgs []string execArgs = append([]string{ctrPath(analyzerPath)}, analyzeFlags...) execArgs = append(execArgs, "my-app") @@ -1086,23 +527,6 @@ func assertAnalyzedMetadata(t *testing.T, path string) *files.Analyzed { return &analyzedMD } -func assertLogsAndRestoresAppMetadata(t *testing.T, dir, output string) { - layerFilenames := []string{ - "launch-layer.sha", - "launch-layer.toml", - "store.toml", - } - for _, filename := range layerFilenames { - h.AssertPathExists(t, filepath.Join(dir, "layers", "some-buildpack-id", filename)) - } - layerNames := []string{ - "launch-layer", - } - for _, layerName := range layerNames { - h.AssertStringContains(t, output, fmt.Sprintf("Restoring metadata for \"some-buildpack-id:%s\"", layerName)) - } -} - func assertNoRestoreOfAppMetadata(t *testing.T, dir, output string) { layerFilenames := []string{ "launch-build-cache-layer.sha", @@ -1118,28 +542,6 @@ func assertNoRestoreOfAppMetadata(t *testing.T, dir, output string) { } } -func assertLogsAndRestoresCacheMetadata(t *testing.T, dir, output string) { - h.AssertPathExists(t, filepath.Join(dir, "layers", "some-buildpack-id", "some-layer.sha")) - h.AssertPathExists(t, filepath.Join(dir, "layers", "some-buildpack-id", "some-layer.toml")) - h.AssertStringContains(t, output, "Restoring metadata for \"some-buildpack-id:some-layer\" from cache") -} - -func assertWritesStoreTomlOnly(t *testing.T, dir, output string) { - h.AssertPathExists(t, filepath.Join(dir, "layers", "some-buildpack-id", "store.toml")) - layerFilenames := []string{ - "launch-build-cache-layer.sha", - "launch-build-cache-layer.toml", - "launch-cache-layer.sha", - "launch-cache-layer.toml", - "launch-layer.sha", - "launch-layer.toml", - } - for _, filename := range layerFilenames { - h.AssertPathDoesNotExist(t, filepath.Join(dir, "layers", "some-buildpack-id", filename)) - } - h.AssertStringContains(t, output, "Skipping buildpack layer analysis") -} - func flatPrint(arr []string) string { return strings.Join(arr, " ") } diff --git a/acceptance/detector_test.go b/acceptance/detector_test.go index 8ab7609cc..0681707d4 100644 --- a/acceptance/detector_test.go +++ b/acceptance/detector_test.go @@ -399,28 +399,4 @@ fail: fail_detect_buildpack@some_version h.AssertEq(t, analyzed.RunImage.Image, "some-run-image-from-extension") }) }) - - when("platform api < 0.6", func() { - when("no buildpack group passed detection", func() { - it("errors and exits with the expected code", func() { - command := exec.Command( - "docker", - "run", - "--rm", - "--env", "CNB_ORDER_PATH=/cnb/orders/empty_order.toml", - "--env", "CNB_PLATFORM_API=0.5", - detectImage, - ) - output, err := command.CombinedOutput() - h.AssertNotNil(t, err) - failErr, ok := err.(*exec.ExitError) - if !ok { - t.Fatalf("expected an error of type exec.ExitError") - } - h.AssertEq(t, failErr.ExitCode(), 100) // platform code for failed detect - expected := "No buildpack groups passed detection." - h.AssertStringContains(t, string(output), expected) - }) - }) - }) } diff --git a/acceptance/exporter_test.go b/acceptance/exporter_test.go index ba57caac8..3b0f84d14 100644 --- a/acceptance/exporter_test.go +++ b/acceptance/exporter_test.go @@ -75,10 +75,6 @@ func testExporterFunc(platformAPI string) func(t *testing.T, when spec.G, it spe when("app", func() { it("is created", func() { exportFlags := []string{"-daemon", "-log-level", "debug"} - if api.MustParse(platformAPI).LessThan("0.7") { - exportFlags = append(exportFlags, []string{"-run-image", exportRegFixtures.ReadOnlyRunImage}...) // though the run image is registry image, it also exists in the daemon with the same tag - } - exportArgs := append([]string{ctrPath(exporterPath)}, exportFlags...) exportedImageName = "some-exported-image-" + h.RandString(10) exportArgs = append(exportArgs, exportedImageName) @@ -202,12 +198,7 @@ func testExporterFunc(platformAPI string) func(t *testing.T, when spec.G, it spe it("Image CreatedAt is set to SOURCE_DATE_EPOCH", func() { h.SkipIf(t, api.MustParse(platformAPI).LessThan("0.9"), "SOURCE_DATE_EPOCH support added in 0.9") expectedTime := time.Date(2022, 1, 5, 5, 5, 5, 0, time.UTC) - exportFlags := []string{"-daemon"} - if api.MustParse(platformAPI).LessThan("0.7") { - exportFlags = append(exportFlags, []string{"-run-image", exportRegFixtures.ReadOnlyRunImage}...) - } - exportArgs := append([]string{ctrPath(exporterPath)}, exportFlags...) exportedImageName = "some-exported-image-" + h.RandString(10) exportArgs = append(exportArgs, exportedImageName) @@ -235,10 +226,6 @@ func testExporterFunc(platformAPI string) func(t *testing.T, when spec.G, it spe when("app", func() { it("is created", func() { var exportFlags []string - if api.MustParse(platformAPI).LessThan("0.7") { - exportFlags = append(exportFlags, []string{"-run-image", exportRegFixtures.ReadOnlyRunImage}...) - } - exportArgs := append([]string{ctrPath(exporterPath)}, exportFlags...) exportedImageName = exportTest.RegRepoName("some-exported-image-" + h.RandString(10)) exportArgs = append(exportArgs, exportedImageName) @@ -265,10 +252,6 @@ func testExporterFunc(platformAPI string) func(t *testing.T, when spec.G, it spe expectedTime := time.Date(2022, 1, 5, 5, 5, 5, 0, time.UTC) var exportFlags []string - if api.MustParse(platformAPI).LessThan("0.7") { - exportFlags = append(exportFlags, []string{"-run-image", exportRegFixtures.ReadOnlyRunImage}...) - } - exportArgs := append([]string{ctrPath(exporterPath)}, exportFlags...) exportedImageName = exportTest.RegRepoName("some-exported-image-" + h.RandString(10)) exportArgs = append(exportArgs, exportedImageName) @@ -295,10 +278,6 @@ func testExporterFunc(platformAPI string) func(t *testing.T, when spec.G, it spe it("is created", func() { cacheImageName := exportTest.RegRepoName("some-cache-image-" + h.RandString(10)) exportFlags := []string{"-cache-image", cacheImageName} - if api.MustParse(platformAPI).LessThan("0.7") { - exportFlags = append(exportFlags, "-run-image", exportRegFixtures.ReadOnlyRunImage) - } - exportArgs := append([]string{ctrPath(exporterPath)}, exportFlags...) exportedImageName = exportTest.RegRepoName("some-exported-image-" + h.RandString(10)) exportArgs = append(exportArgs, exportedImageName) @@ -321,10 +300,6 @@ func testExporterFunc(platformAPI string) func(t *testing.T, when spec.G, it spe it("is created with empty layer", func() { cacheImageName := exportTest.RegRepoName("some-empty-cache-image-" + h.RandString(10)) exportFlags := []string{"-cache-image", cacheImageName, "-layers", "/other_layers"} - if api.MustParse(platformAPI).LessThan("0.7") { - exportFlags = append(exportFlags, "-run-image", exportRegFixtures.ReadOnlyRunImage) - } - exportArgs := append([]string{ctrPath(exporterPath)}, exportFlags...) exportedImageName = exportTest.RegRepoName("some-exported-image-" + h.RandString(10)) exportArgs = append(exportArgs, exportedImageName) diff --git a/acceptance/launcher_test.go b/acceptance/launcher_test.go index f7b08c21d..844183e37 100644 --- a/acceptance/launcher_test.go +++ b/acceptance/launcher_test.go @@ -66,170 +66,79 @@ func testLauncher(t *testing.T, when spec.G, it spec.S) { }) }) - when("Platform API >= 0.4", func() { - when("entrypoint is a process", func() { + when("entrypoint is a process", func() { + it("launches that process", func() { + cmd := exec.Command("docker", "run", "--rm", //nolint + "--entrypoint=web", + "--env=CNB_PLATFORM_API="+latestPlatformAPI, + launchImage) + assertOutput(t, cmd, "Executing web process-type") + }) + + when("process contains a period", func() { it("launches that process", func() { cmd := exec.Command("docker", "run", "--rm", - "--entrypoint=web", + "--entrypoint=process.with.period"+exe, "--env=CNB_PLATFORM_API="+latestPlatformAPI, launchImage) - assertOutput(t, cmd, "Executing web process-type") - }) - - when("process contains a period", func() { - it("launches that process", func() { - cmd := exec.Command("docker", "run", "--rm", - "--entrypoint=process.with.period"+exe, - "--env=CNB_PLATFORM_API="+latestPlatformAPI, - launchImage) - assertOutput(t, cmd, "Executing process.with.period process-type") - }) + assertOutput(t, cmd, "Executing process.with.period process-type") }) + }) - it("appends any args to the process args", func() { - cmd := exec.Command( //nolint - "docker", "run", "--rm", - "--entrypoint=web", - "--env=CNB_PLATFORM_API="+latestPlatformAPI, - launchImage, "with user provided args", - ) - if runtime.GOOS == "windows" { - assertOutput(t, cmd, `Executing web process-type "with user provided args"`) - } else { - assertOutput(t, cmd, "Executing web process-type with user provided args") - } - }) + it("appends any args to the process args", func() { + cmd := exec.Command( //nolint + "docker", "run", "--rm", + "--entrypoint=web", + "--env=CNB_PLATFORM_API="+latestPlatformAPI, + launchImage, "with user provided args", + ) + if runtime.GOOS == "windows" { + assertOutput(t, cmd, `Executing web process-type "with user provided args"`) + } else { + assertOutput(t, cmd, "Executing web process-type with user provided args") + } }) + }) - when("entrypoint is a not a process", func() { - it("builds a process from the arguments", func() { - cmd := exec.Command( //nolint + when("entrypoint is a not a process", func() { + it("builds a process from the arguments", func() { + cmd := exec.Command( //nolint + "docker", "run", "--rm", + "--entrypoint=launcher", + "--env=CNB_PLATFORM_API="+latestPlatformAPI, + launchImage, "--", + "env", + ) + if runtime.GOOS == "windows" { + cmd = exec.Command( //nolint "docker", "run", "--rm", - "--entrypoint=launcher", - "--env=CNB_PLATFORM_API="+latestPlatformAPI, + `--entrypoint=launcher`, + "--env=CNB_PLATFORM_API=0.7", launchImage, "--", - "env", - ) - if runtime.GOOS == "windows" { - cmd = exec.Command( //nolint - "docker", "run", "--rm", - `--entrypoint=launcher`, - "--env=CNB_PLATFORM_API=0.4", - launchImage, "--", - "cmd", "/c", "set", - ) - } - - assertOutput(t, cmd, - "SOME_VAR=some-bp-val", - "OTHER_VAR=other-bp-val", + "cmd", "/c", "set", ) - }) - }) + } - when("CNB_PROCESS_TYPE is set", func() { - it("should warn", func() { - cmd := exec.Command("docker", "run", "--rm", - "--env=CNB_PROCESS_TYPE=direct-process", - "--env=CNB_PLATFORM_API="+latestPlatformAPI, - "--env=CNB_NO_COLOR=true", - launchImage, - ) - out, err := cmd.CombinedOutput() - h.AssertNotNil(t, err) - h.AssertStringContains(t, string(out), "Warning: CNB_PROCESS_TYPE is not supported in Platform API "+latestPlatformAPI) - h.AssertStringContains(t, string(out), `Warning: Run with ENTRYPOINT 'direct-process' to invoke the 'direct-process' process type`) - h.AssertStringContains(t, string(out), "ERROR: failed to launch: determine start command: when there is no default process a command is required") - }) + assertOutput(t, cmd, + "SOME_VAR=some-bp-val", + "OTHER_VAR=other-bp-val", + ) }) }) - when("Platform API < 0.4", func() { - when("there is no CMD provided", func() { - when("CNB_PROCESS_TYPE is NOT set", func() { - it("web is the default process-type", func() { - cmd := exec.Command("docker", "run", "--rm", "--env=CNB_PLATFORM_API=0.3", launchImage) - assertOutput(t, cmd, "Executing web process-type") - }) - }) - - when("CNB_PROCESS_TYPE is set", func() { - it("should run the specified CNB_PROCESS_TYPE", func() { - cmd := exec.Command("docker", "run", "--rm", "--env=CNB_PLATFORM_API=0.3", "--env=CNB_PROCESS_TYPE=direct-process", launchImage) - if runtime.GOOS == "windows" { - assertOutput(t, cmd, "Usage: ping") - } else { - assertOutput(t, cmd, "Executing direct-process process-type") - } - }) - }) - }) - - when("process-type provided in CMD", func() { - it("launches that process-type", func() { - cmd := exec.Command("docker", "run", "--rm", "--env=CNB_PLATFORM_API=0.3", launchImage, "direct-process") - expected := "Executing direct-process process-type" - if runtime.GOOS == "windows" { - expected = "Usage: ping" - } - assertOutput(t, cmd, expected) - }) - - it("sets env vars from process specific directories", func() { - cmd := exec.Command("docker", "run", "--rm", "--env=CNB_PLATFORM_API=0.3", launchImage, "worker") - expected := "worker-process-val" - assertOutput(t, cmd, expected) - }) - }) - - when("process is direct=false", func() { - when("the process type has no args", func() { - it("runs command as script", func() { - h.SkipIf(t, runtime.GOOS == "windows", "scripts are unsupported on windows") - cmd := exec.Command("docker", "run", "--rm", - "--env=CNB_PLATFORM_API=0.3", - "--env", "VAR1=val1", - "--env", "VAR2=val with space", - launchImage, "indirect-process-with-script", - ) - assertOutput(t, cmd, "'val1' 'val with space'") - }) - }) - - when("the process type has args", func() { - // buildpack API is determined by looking up the API of the process buildpack in metadata.toml - - it("command and args become shell-parsed tokens in a script", func() { - var val2 string - if runtime.GOOS == "windows" { - val2 = `"val with space"` // windows values with spaces must contain quotes - } else { - val2 = "val with space" - } - cmd := exec.Command("docker", "run", "--rm", - "--env=CNB_PLATFORM_API=0.3", - "--env", "VAR1=val1", - "--env", "VAR2="+val2, - launchImage, "indirect-process-with-args", - ) // #nosec G204 - assertOutput(t, cmd, "'val1' 'val with space'") - }) - }) - - it("sources scripts from process specific directories", func() { - cmd := exec.Command("docker", "run", "--rm", "--env=CNB_PLATFORM_API=0.3", launchImage, "profile-checker") - expected := "sourced bp profile\nsourced bp profile-checker profile\nsourced app profile\nval-from-profile" - assertOutput(t, cmd, expected) - }) - }) - - it("respects CNB_APP_DIR and CNB_LAYERS_DIR environment variables", func() { + when("CNB_PROCESS_TYPE is set", func() { + it("should warn", func() { cmd := exec.Command("docker", "run", "--rm", - "--env=CNB_PLATFORM_API=0.3", - "--env", "CNB_APP_DIR="+ctrPath("/other-app"), - "--env", "CNB_LAYERS_DIR=/other-layers", - launchImage) // #nosec G204 - assertOutput(t, cmd, "sourced other app profile\nExecuting other-layers web process-type") + "--env=CNB_PROCESS_TYPE=direct-process", + "--env=CNB_PLATFORM_API="+latestPlatformAPI, + "--env=CNB_NO_COLOR=true", + launchImage, + ) + out, err := cmd.CombinedOutput() + h.AssertNotNil(t, err) + h.AssertStringContains(t, string(out), "Warning: CNB_PROCESS_TYPE is not supported in Platform API "+latestPlatformAPI) + h.AssertStringContains(t, string(out), `Warning: Run with ENTRYPOINT 'direct-process' to invoke the 'direct-process' process type`) + h.AssertStringContains(t, string(out), "ERROR: failed to launch: determine start command: when there is no default process a command is required") }) }) diff --git a/acceptance/restorer_test.go b/acceptance/restorer_test.go index df4471858..a356967ef 100644 --- a/acceptance/restorer_test.go +++ b/acceptance/restorer_test.go @@ -80,28 +80,6 @@ func testRestorerFunc(platformAPI string) func(t *testing.T, when spec.G, it spe }) }) - when("called with -analyzed (on older platforms)", func() { - it("errors", func() { - h.SkipIf(t, api.MustParse(platformAPI).AtLeast("0.7"), "Platform API >= 0.7 supports -analyzed flag") - command := exec.Command("docker", "run", "--rm", "--env", "CNB_PLATFORM_API="+platformAPI, restoreImage, "-analyzed some-file-location") - output, err := command.CombinedOutput() - h.AssertNotNil(t, err) - expected := "flag provided but not defined: -analyzed" - h.AssertStringContains(t, string(output), expected) - }) - }) - - when("called with -skip-layers (on older platforms)", func() { - it("errors", func() { - h.SkipIf(t, api.MustParse(platformAPI).AtLeast("0.7"), "Platform API >= 0.7 supports -skip-layers flag") - command := exec.Command("docker", "run", "--rm", "--env", "CNB_PLATFORM_API="+platformAPI, restoreImage, "-skip-layers true") - output, err := command.CombinedOutput() - h.AssertNotNil(t, err) - expected := "flag provided but not defined: -skip-layers" - h.AssertStringContains(t, string(output), expected) - }) - }) - when("called without any cache flag", func() { it("outputs it will not restore cache layer data", func() { command := exec.Command("docker", "run", "--rm", "--env", "CNB_PLATFORM_API="+platformAPI, restoreImage) @@ -114,7 +92,6 @@ func testRestorerFunc(platformAPI string) func(t *testing.T, when spec.G, it spe when("analyzed.toml exists with app metadata", func() { it("restores app metadata", func() { - h.SkipIf(t, api.MustParse(platformAPI).LessThan("0.7"), "Platform API < 0.7 does not restore app metadata") output := h.DockerRunAndCopy(t, containerName, copyDir, @@ -252,7 +229,6 @@ func testRestorerFunc(platformAPI string) func(t *testing.T, when spec.G, it spe when("target data", func() { it("updates run image reference in analyzed.toml to include digest and target data on newer platforms", func() { - h.SkipIf(t, api.MustParse(platformAPI).LessThan("0.7"), "Platform API < 0.7 does not support -analyzed flag") h.DockerRunAndCopy(t, containerName, copyDir, diff --git a/analyzer.go b/analyzer.go index 0f09e85da..16f43fbb4 100644 --- a/analyzer.go +++ b/analyzer.go @@ -5,7 +5,6 @@ import ( "github.com/pkg/errors" "github.com/buildpacks/lifecycle/api" - "github.com/buildpacks/lifecycle/buildpack" "github.com/buildpacks/lifecycle/cache" "github.com/buildpacks/lifecycle/image" "github.com/buildpacks/lifecycle/internal/fsutil" @@ -48,48 +47,18 @@ type Analyzer struct { Logger log.Logger SBOMRestorer layer.SBOMRestorer PlatformAPI *api.Version - - // Platform API < 0.7 - Buildpacks []buildpack.GroupElement - Cache Cache - LayerMetadataRestorer layer.MetadataRestorer - RestoresLayerMetadata bool } -func (f *AnalyzerFactory) NewAnalyzer( - additionalTags []string, - cacheImageRef string, - launchCacheDir string, - layersDir string, - legacyCacheDir string, - legacyGroup buildpack.Group, - legacyGroupPath string, - outputImageRef string, - previousImageRef string, - runImageRef string, - skipLayers bool, - logger log.Logger, -) (*Analyzer, error) { +// NewAnalyzer configures a new Analyzer according to the provided Platform API version. +func (f *AnalyzerFactory) NewAnalyzer(additionalTags []string, cacheImageRef string, launchCacheDir string, layersDir string, outputImageRef string, previousImageRef string, runImageRef string, skipLayers bool, logger log.Logger) (*Analyzer, error) { analyzer := &Analyzer{ - LayerMetadataRestorer: &layer.NopMetadataRestorer{}, - Logger: logger, - SBOMRestorer: &layer.NopSBOMRestorer{}, - PlatformAPI: f.platformAPI, + Logger: logger, + SBOMRestorer: &layer.NopSBOMRestorer{}, + PlatformAPI: f.platformAPI, } - if f.platformAPI.AtLeast("0.7") { - if err := f.ensureRegistryAccess(additionalTags, cacheImageRef, outputImageRef, runImageRef, previousImageRef); err != nil { - return nil, err - } - } else { - if err := f.setBuildpacks(analyzer, legacyGroup, legacyGroupPath, logger); err != nil { - return nil, err - } - if err := f.setCache(analyzer, cacheImageRef, legacyCacheDir); err != nil { - return nil, err - } - analyzer.LayerMetadataRestorer = layer.NewDefaultMetadataRestorer(layersDir, skipLayers, logger) - analyzer.RestoresLayerMetadata = true + if err := f.ensureRegistryAccess(additionalTags, cacheImageRef, outputImageRef, runImageRef, previousImageRef); err != nil { + return nil, err } if f.platformAPI.AtLeast("0.8") && !skipLayers { @@ -132,29 +101,6 @@ func (f *AnalyzerFactory) ensureRegistryAccess( return nil } -func (f *AnalyzerFactory) setBuildpacks(analyzer *Analyzer, group buildpack.Group, path string, logger log.Logger) error { - if len(group.Group) > 0 { - analyzer.Buildpacks = group.Group - return nil - } - var err error - if analyzer.Buildpacks, _, err = f.configHandler.ReadGroup(path); err != nil { - return err - } - for _, bp := range analyzer.Buildpacks { - if err := f.apiVerifier.VerifyBuildpackAPI(buildpack.KindBuildpack, bp.String(), bp.API, logger); err != nil { - return err - } - } - return nil -} - -func (f *AnalyzerFactory) setCache(analyzer *Analyzer, imageRef string, dir string) error { - var err error - analyzer.Cache, err = f.cacheHandler.InitCache(imageRef, dir, f.platformAPI.LessThan("0.13")) - return err -} - func (f *AnalyzerFactory) setPrevious(analyzer *Analyzer, imageRef string, launchCacheDir string) error { if imageRef == "" { return nil @@ -194,7 +140,6 @@ func (a *Analyzer) Analyze() (files.Analyzed, error) { var ( err error appMeta files.LayersMetadata - cacheMeta platform.CacheMetadata previousImageRef string runImageRef string ) @@ -230,18 +175,6 @@ func (a *Analyzer) Analyze() (files.Analyzed, error) { } } - if a.RestoresLayerMetadata { - cacheMeta, err = retrieveCacheMetadata(a.Cache, a.Logger) - if err != nil { - return files.Analyzed{}, err - } - - useShaFiles := true - if err := a.LayerMetadataRestorer.Restore(a.Buildpacks, appMeta, cacheMeta, layer.NewSHAStore(useShaFiles)); err != nil { - return files.Analyzed{}, err - } - } - return files.Analyzed{ PreviousImage: &files.ImageIdentifier{ Reference: previousImageRef, @@ -275,27 +208,8 @@ func bomSHA(appMeta files.LayersMetadata) string { return appMeta.BOM.SHA } -func retrieveCacheMetadata(fromCache Cache, logger log.Logger) (platform.CacheMetadata, error) { - // Create empty cache metadata in case a usable cache is not provided. - var cacheMeta platform.CacheMetadata - if fromCache != nil { - var err error - if !fromCache.Exists() { - logger.Info("Layer cache not found") - } - cacheMeta, err = fromCache.RetrieveMetadata() - if err != nil { - return cacheMeta, errors.Wrap(err, "retrieving cache metadata") - } - } else { - logger.Debug("Usable cache not provided, using empty cache metadata") - } - - return cacheMeta, nil -} - func (a *Analyzer) retrieveAppMetadata() (files.LayersMetadata, string, error) { - if a.PreviousImage == nil { // Previous image is optional in Platform API >= 0.7 + if a.PreviousImage == nil { return files.LayersMetadata{}, "", nil } previousImageRef, err := a.getImageIdentifier(a.PreviousImage) diff --git a/analyzer_test.go b/analyzer_test.go index 12193ead5..0c6ba9aa8 100644 --- a/analyzer_test.go +++ b/analyzer_test.go @@ -20,7 +20,6 @@ import ( "github.com/buildpacks/lifecycle" "github.com/buildpacks/lifecycle/api" - "github.com/buildpacks/lifecycle/buildpack" "github.com/buildpacks/lifecycle/cache" "github.com/buildpacks/lifecycle/cmd" "github.com/buildpacks/lifecycle/internal/layer" @@ -100,20 +99,7 @@ func testAnalyzerFactory(t *testing.T, when spec.G, it spec.S) { t.Log("processes run image") fakeImageHandler.EXPECT().InitImage("some-run-image-ref").Return(runImage, nil) - analyzer, err := analyzerFactory.NewAnalyzer( - []string{"some-additional-tag"}, - "some-cache-image-ref", - "some-launch-cache-dir", - "some-layers-dir", - "some-legacy-cache-dir", - buildpack.Group{}, - "some-legacy-group-path", - "some-output-image-ref", - "some-previous-image-ref", - "some-run-image-ref", - false, - logger, - ) + analyzer, err := analyzerFactory.NewAnalyzer([]string{"some-additional-tag"}, "some-cache-image-ref", "some-launch-cache-dir", "some-layers-dir", "some-output-image-ref", "some-previous-image-ref", "some-run-image-ref", false, logger) h.AssertNil(t, err) h.AssertEq(t, analyzer.PreviousImage.Name(), previousImage.Name()) h.AssertEq(t, analyzer.RunImage.Name(), runImage.Name()) @@ -124,10 +110,6 @@ func testAnalyzerFactory(t *testing.T, when spec.G, it spec.S) { h.AssertEq(t, sbomRestorer.LayersDir, "some-layers-dir") h.AssertEq(t, sbomRestorer.Logger, logger) - t.Log("does not restore layer metadata") - _, ok = analyzer.LayerMetadataRestorer.(*layer.NopMetadataRestorer) - h.AssertEq(t, ok, true) - t.Log("sets logger") h.AssertEq(t, analyzer.Logger, logger) }) @@ -150,20 +132,7 @@ func testAnalyzerFactory(t *testing.T, when spec.G, it spec.S) { t.Log("processes run image") fakeImageHandler.EXPECT().InitImage("some-run-image-ref").Return(runImage, nil) - analyzer, err := analyzerFactory.NewAnalyzer( - []string{"some-additional-tag"}, - "some-cache-image-ref", - "some-launch-cache-dir", - "some-layers-dir", - "some-legacy-cache-dir", - buildpack.Group{}, - "some-legacy-group-path", - "some-output-image-ref", - "some-previous-image-ref", - "some-run-image-ref", - false, - logger, - ) + analyzer, err := analyzerFactory.NewAnalyzer([]string{"some-additional-tag"}, "some-cache-image-ref", "some-launch-cache-dir", "some-layers-dir", "some-output-image-ref", "some-previous-image-ref", "some-run-image-ref", false, logger) h.AssertNil(t, err) h.AssertEq(t, analyzer.PreviousImage.Name(), previousImage.Name()) h.AssertEq(t, analyzer.RunImage.Name(), runImage.Name()) @@ -175,10 +144,6 @@ func testAnalyzerFactory(t *testing.T, when spec.G, it spec.S) { h.AssertEq(t, sbomRestorer.Logger, logger) h.AssertEq(t, analyzer.PlatformAPI, api.Platform.Latest()) - t.Log("does not restore layer metadata") - _, ok = analyzer.LayerMetadataRestorer.(*layer.NopMetadataRestorer) - h.AssertEq(t, ok, true) - t.Log("sets logger") h.AssertEq(t, analyzer.Logger, logger) }) @@ -201,20 +166,7 @@ func testAnalyzerFactory(t *testing.T, when spec.G, it spec.S) { launchCacheDir := filepath.Join(tempDir, "some-launch-cache-dir") h.AssertNil(t, os.MkdirAll(launchCacheDir, 0777)) - analyzer, err := analyzerFactory.NewAnalyzer( - []string{"some-additional-tag"}, - "some-cache-image-ref", - launchCacheDir, - "some-layers-dir", - "some-legacy-cache-dir", - buildpack.Group{}, - "some-legacy-group-path", - "some-output-image-ref", - "some-previous-image-ref", - "some-run-image-ref", - false, - logger, - ) + analyzer, err := analyzerFactory.NewAnalyzer([]string{"some-additional-tag"}, "some-cache-image-ref", launchCacheDir, "some-layers-dir", "some-output-image-ref", "some-previous-image-ref", "some-run-image-ref", false, logger) h.AssertNil(t, err) h.AssertEq(t, analyzer.PreviousImage.Name(), previousImage.Name()) h.AssertEq(t, analyzer.RunImage.Name(), runImage.Name()) @@ -235,19 +187,7 @@ func testAnalyzerFactory(t *testing.T, when spec.G, it spec.S) { fakeImageHandler.EXPECT().InitImage(gomock.Any()) fakeImageHandler.EXPECT().InitImage(gomock.Any()) - analyzer, err := analyzerFactory.NewAnalyzer( - []string{"some-additional-tag"}, - "some-cache-image-ref", - "some-launch-cache-dir", - "some-layers-dir", - "some-legacy-cache-dir", buildpack.Group{}, - "some-legacy-group-path", - "some-output-image-ref", - "some-previous-image-ref", - "some-run-image-ref", - true, - logger, - ) + analyzer, err := analyzerFactory.NewAnalyzer([]string{"some-additional-tag"}, "some-cache-image-ref", "some-launch-cache-dir", "some-layers-dir", "some-output-image-ref", "some-previous-image-ref", "some-run-image-ref", true, logger) h.AssertNil(t, err) _, ok := analyzer.SBOMRestorer.(*layer.NopSBOMRestorer) @@ -283,20 +223,7 @@ func testAnalyzerFactory(t *testing.T, when spec.G, it spec.S) { t.Log("processes run image") fakeImageHandler.EXPECT().InitImage("some-run-image-ref").Return(runImage, nil) - analyzer, err := analyzerFactory.NewAnalyzer( - []string{"some-additional-tag"}, - "some-cache-image-ref", - "some-launch-cache-dir", - "some-layers-dir", - "some-legacy-cache-dir", - buildpack.Group{}, - "some-legacy-group-path", - "some-output-image-ref", - "some-previous-image-ref", - "some-run-image-ref", - false, - logger, - ) + analyzer, err := analyzerFactory.NewAnalyzer([]string{"some-additional-tag"}, "some-cache-image-ref", "some-launch-cache-dir", "some-layers-dir", "some-output-image-ref", "some-previous-image-ref", "some-run-image-ref", false, logger) h.AssertNil(t, err) h.AssertEq(t, analyzer.PreviousImage.Name(), previousImage.Name()) h.AssertEq(t, analyzer.RunImage.Name(), runImage.Name()) @@ -305,10 +232,6 @@ func testAnalyzerFactory(t *testing.T, when spec.G, it spec.S) { _, ok := analyzer.SBOMRestorer.(*layer.NopSBOMRestorer) h.AssertEq(t, ok, true) - t.Log("does not restore layer metadata") - _, ok = analyzer.LayerMetadataRestorer.(*layer.NopMetadataRestorer) - h.AssertEq(t, ok, true) - t.Log("sets logger") h.AssertEq(t, analyzer.Logger, logger) }) @@ -331,158 +254,27 @@ func testAnalyzerFactory(t *testing.T, when spec.G, it spec.S) { launchCacheDir := filepath.Join(tempDir, "some-launch-cache-dir") h.AssertNil(t, os.MkdirAll(launchCacheDir, 0777)) - analyzer, err := analyzerFactory.NewAnalyzer( - []string{"some-additional-tag"}, - "some-cache-image-ref", launchCacheDir, - "some-layers-dir", - "some-legacy-cache-dir", buildpack.Group{}, - "some-legacy-group-path", - "some-output-image-ref", - "some-previous-image-ref", - "some-run-image-ref", - false, - logger, - ) + analyzer, err := analyzerFactory.NewAnalyzer([]string{"some-additional-tag"}, "some-cache-image-ref", launchCacheDir, "some-layers-dir", "some-output-image-ref", "some-previous-image-ref", "some-run-image-ref", false, logger) h.AssertNil(t, err) h.AssertEq(t, analyzer.PreviousImage.Name(), previousImage.Name()) h.AssertEq(t, analyzer.RunImage.Name(), runImage.Name()) }) }) }) - - when("platform api < 0.7", func() { - it.Before(func() { - analyzerFactory = lifecycle.NewAnalyzerFactory(api.MustParse("0.6"), fakeAPIVerifier, fakeCacheHandler, fakeConfigHandler, fakeImageHandler, fakeRegistryHandler) - }) - - it("configures the analyzer", func() { - previousImage := fakes.NewImage("some-previous-image-ref", "", nil) - runImage := fakes.NewImage("some-run-image-ref", "", nil) - - t.Log("does not ensure registry access") - - t.Log("processes group") - group := []buildpack.GroupElement{{ID: "some-buildpack-id", Version: "some-buildpack-version", API: "0.2"}} - fakeConfigHandler.EXPECT().ReadGroup("some-legacy-group-path").Return(group, []buildpack.GroupElement{}, nil) - fakeAPIVerifier.EXPECT().VerifyBuildpackAPI(buildpack.KindBuildpack, "some-buildpack-id@some-buildpack-version", "0.2", logger) - - t.Log("processes cache") - fakeCacheHandler.EXPECT().InitCache("some-cache-image-ref", "some-legacy-cache-dir", true) - - t.Log("processes previous image") - fakeImageHandler.EXPECT().InitImage("some-previous-image-ref").Return(previousImage, nil) - fakeImageHandler.EXPECT().Kind().Return(image.RemoteKind) - - t.Log("processes run image") - fakeImageHandler.EXPECT().InitImage("some-run-image-ref").Return(runImage, nil) - - analyzer, err := analyzerFactory.NewAnalyzer([]string{"some-additional-tag"}, - "some-cache-image-ref", - "some-launch-cache-dir", - "some-layers-dir", - "some-legacy-cache-dir", - buildpack.Group{}, - "some-legacy-group-path", - "some-output-image-ref", - "some-previous-image-ref", - "some-run-image-ref", - false, - logger, - ) - h.AssertNil(t, err) - h.AssertEq(t, analyzer.PreviousImage.Name(), previousImage.Name()) - h.AssertEq(t, analyzer.RunImage.Name(), runImage.Name()) - - t.Log("does not restore sbom data") - _, ok := analyzer.SBOMRestorer.(*layer.NopSBOMRestorer) - h.AssertEq(t, ok, true) - - t.Log("restores layer metadata") - metadataRestorer, ok := analyzer.LayerMetadataRestorer.(*layer.DefaultMetadataRestorer) - h.AssertEq(t, ok, true) - h.AssertEq(t, metadataRestorer.LayersDir, "some-layers-dir") - h.AssertEq(t, metadataRestorer.Logger, logger) - h.AssertEq(t, metadataRestorer.SkipLayers, false) - - t.Log("sets logger") - h.AssertEq(t, analyzer.Logger, logger) - }) - - when("daemon case", func() { - it("configures the analyzer", func() { - previousImage := fakes.NewImage("some-previous-image-ref", "", nil) - runImage := fakes.NewImage("some-run-image-ref", "", nil) - - t.Log("does not ensure registry access") - - t.Log("processes group") - group := []buildpack.GroupElement{{ID: "some-buildpack-id", Version: "some-buildpack-version", API: "0.2"}} - fakeConfigHandler.EXPECT().ReadGroup("some-legacy-group-path").Return(group, []buildpack.GroupElement{}, nil) - fakeAPIVerifier.EXPECT().VerifyBuildpackAPI(buildpack.KindBuildpack, "some-buildpack-id@some-buildpack-version", "0.2", logger) - - t.Log("processes cache") - fakeCacheHandler.EXPECT().InitCache("some-cache-image-ref", "some-legacy-cache-dir", true) - - t.Log("processes previous image") - fakeImageHandler.EXPECT().InitImage("some-previous-image-ref").Return(previousImage, nil) - fakeImageHandler.EXPECT().Kind().Return(image.LocalKind) - - t.Log("processes run image") - fakeImageHandler.EXPECT().InitImage("some-run-image-ref").Return(runImage, nil) - - launchCacheDir := filepath.Join(tempDir, "some-launch-cache-dir") - h.AssertNil(t, os.MkdirAll(launchCacheDir, 0777)) - analyzer, err := analyzerFactory.NewAnalyzer( - []string{"some-additional-tag"}, - "some-cache-image-ref", - launchCacheDir, - "some-layers-dir", - "some-legacy-cache-dir", - buildpack.Group{}, - "some-legacy-group-path", - "some-output-image-ref", - "some-previous-image-ref", - "some-run-image-ref", - false, - logger, - ) - h.AssertNil(t, err) - h.AssertEq(t, analyzer.PreviousImage.Name(), previousImage.Name()) - h.AssertEq(t, analyzer.RunImage.Name(), runImage.Name()) - }) - }) - - when("buildpack group is provided", func() { - it("uses the provided group", func() { - fakeCacheHandler.EXPECT().InitCache(gomock.Any(), gomock.Any(), gomock.Any()) - fakeImageHandler.EXPECT().InitImage(gomock.Any()) - fakeImageHandler.EXPECT().Kind().Return(image.RemoteKind) - fakeImageHandler.EXPECT().InitImage(gomock.Any()) - - providedGroup := buildpack.Group{Group: []buildpack.GroupElement{{ID: "some-buildpack-id"}}} - - analyzer, err := analyzerFactory.NewAnalyzer([]string{"some-additional-tag"}, "some-cache-image-ref", "some-launch-cache-dir", "some-layers-dir", "some-legacy-cache-dir", providedGroup, "some-legacy-group-path", "some-output-image-ref", "some-previous-image-ref", "some-run-image-ref", false, nil) - h.AssertNil(t, err) - - h.AssertEq(t, analyzer.Buildpacks, providedGroup.Group) - }) - }) - }) }) } func testAnalyzer(platformAPI string) func(t *testing.T, when spec.G, it spec.S) { return func(t *testing.T, when spec.G, it spec.S) { var ( - cacheDir string - layersDir string - tmpDir string - analyzer *lifecycle.Analyzer - image *fakes.Image - metadataRestorer *testmock.MockMetadataRestorer - mockCtrl *gomock.Controller - sbomRestorer *testmock.MockSBOMRestorer - testCache lifecycle.Cache + cacheDir string + layersDir string + tmpDir string + analyzer *lifecycle.Analyzer + image *fakes.Image + mockCtrl *gomock.Controller + sbomRestorer *testmock.MockSBOMRestorer + testCache lifecycle.Cache ) it.Before(func() { @@ -507,7 +299,6 @@ func testAnalyzer(platformAPI string) func(t *testing.T, when spec.G, it spec.S) discardLogger := log.Logger{Handler: &discard.Handler{}} mockCtrl = gomock.NewController(t) - metadataRestorer = testmock.NewMockMetadataRestorer(mockCtrl) sbomRestorer = testmock.NewMockSBOMRestorer(mockCtrl) @@ -516,15 +307,7 @@ func testAnalyzer(platformAPI string) func(t *testing.T, when spec.G, it spec.S) PreviousImage: image, Logger: &discardLogger, SBOMRestorer: sbomRestorer, - Buildpacks: []buildpack.GroupElement{ - {ID: "metadata.buildpack", API: api.Buildpack.Latest().String()}, - {ID: "no.cache.buildpack", API: api.Buildpack.Latest().String()}, - {ID: "no.metadata.buildpack", API: api.Buildpack.Latest().String()}, - }, - Cache: testCache, - LayerMetadataRestorer: metadataRestorer, - RestoresLayerMetadata: api.MustParse(platformAPI).LessThan("0.7"), - PlatformAPI: api.MustParse(platformAPI), + PlatformAPI: api.MustParse(platformAPI), } if testing.Verbose() { @@ -548,14 +331,6 @@ func testAnalyzer(platformAPI string) func(t *testing.T, when spec.G, it spec.S) ref *testmock.MockReference ) - expectRestoresLayerMetadataIfSupported := func() { - if api.MustParse(platformAPI).LessThan("0.7") { - useShaFiles := true - layerSHAStore := layer.NewSHAStore(useShaFiles) - metadataRestorer.EXPECT().Restore(analyzer.Buildpacks, expectedAppMetadata, expectedCacheMetadata, layerSHAStore) - } - } - it.Before(func() { ref = testmock.NewMockReference(mockCtrl) ref.EXPECT().Name().AnyTimes() @@ -569,8 +344,6 @@ func testAnalyzer(platformAPI string) func(t *testing.T, when spec.G, it spec.S) }) it("returns the analyzed metadata", func() { - expectRestoresLayerMetadataIfSupported() - md, err := analyzer.Analyze() h.AssertNil(t, err) @@ -584,9 +357,6 @@ func testAnalyzer(platformAPI string) func(t *testing.T, when spec.G, it spec.S) h.AssertNil(t, json.Unmarshal(metadata, &expectedCacheMetadata)) h.AssertNil(t, testCache.SetMetadata(expectedCacheMetadata)) h.AssertNil(t, testCache.Commit()) - - analyzer.Buildpacks = append(analyzer.Buildpacks, buildpack.GroupElement{ID: "escaped/buildpack/id", API: api.Buildpack.Latest().String()}) - expectRestoresLayerMetadataIfSupported() }) it("returns the analyzed metadata", func() { @@ -601,7 +371,6 @@ func testAnalyzer(platformAPI string) func(t *testing.T, when spec.G, it spec.S) when("previous image not found", func() { it.Before(func() { h.AssertNil(t, image.Delete()) - expectRestoresLayerMetadataIfSupported() }) it("returns a nil image in the analyzed metadata", func() { @@ -616,7 +385,6 @@ func testAnalyzer(platformAPI string) func(t *testing.T, when spec.G, it spec.S) when("previous image does not have metadata label", func() { it.Before(func() { h.AssertNil(t, image.SetLabel("io.buildpacks.lifecycle.metadata", "")) - expectRestoresLayerMetadataIfSupported() }) it("returns empty analyzed metadata", func() { @@ -629,7 +397,6 @@ func testAnalyzer(platformAPI string) func(t *testing.T, when spec.G, it spec.S) when("previous image has incompatible metadata", func() { it.Before(func() { h.AssertNil(t, image.SetLabel("io.buildpacks.lifecycle.metadata", `{["bad", "metadata"]}`)) - expectRestoresLayerMetadataIfSupported() }) it("returns empty analyzed metadata", func() { @@ -644,7 +411,6 @@ func testAnalyzer(platformAPI string) func(t *testing.T, when spec.G, it spec.S) metadata := fmt.Sprintf(`{"sbom": {"sha":"%s"}}`, "some-digest") h.AssertNil(t, image.SetLabel("io.buildpacks.lifecycle.metadata", metadata)) h.AssertNil(t, json.Unmarshal([]byte(metadata), &expectedAppMetadata)) - expectRestoresLayerMetadataIfSupported() }) it("calls the SBOM restorer with the SBOM layer digest", func() { @@ -657,7 +423,6 @@ func testAnalyzer(platformAPI string) func(t *testing.T, when spec.G, it spec.S) when("run image is provided", func() { it.Before(func() { analyzer.RunImage = image - expectRestoresLayerMetadataIfSupported() }) it("returns the run image digest in the analyzed metadata", func() { diff --git a/api/apis.go b/api/apis.go index 81a9966fc..58f6d6785 100644 --- a/api/apis.go +++ b/api/apis.go @@ -11,7 +11,7 @@ var ( // Platform is a pair of lists of Platform API versions: // 1. All supported versions (including deprecated versions) // 2. The versions that are deprecated - Platform = newApisMustParse([]string{"0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9", "0.10", "0.11", "0.12"}, []string{"0.3", "0.4", "0.5", "0.6"}) + Platform = newApisMustParse([]string{"0.7", "0.8", "0.9", "0.10", "0.11", "0.12"}, []string{}) // Buildpack is a pair of lists of Buildpack API versions: // 1. All supported versions (including deprecated versions) // 2. The versions that are deprecated diff --git a/builder_test.go b/builder_test.go index 190e6f692..00971bc3b 100644 --- a/builder_test.go +++ b/builder_test.go @@ -952,56 +952,6 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) { }) }) - when("platform api < 0.6", func() { - it.Before(func() { - builder.PlatformAPI = api.MustParse("0.5") - }) - - when("there is a web process", func() { - it.Before(func() { - builder.Group.Group = []buildpack.GroupElement{ - {ID: "A", Version: "v1", API: api.Buildpack.Latest().String()}, - } - }) - - it("does not set it as a default process", func() { - bpA := &buildpack.BpDescriptor{Buildpack: buildpack.BpInfo{BaseInfo: buildpack.BaseInfo{ID: "A", Version: "v1"}}} - dirStore.EXPECT().LookupBp("A", "v1").Return(bpA, nil) - executor.EXPECT().Build(*bpA, gomock.Any(), gomock.Any()).Return(buildpack.BuildOutputs{ - Processes: []launch.Process{ - { - Type: "web", - Command: launch.NewRawCommand([]string{"web-cmd"}), - Args: []string{"web-arg"}, - Direct: false, - BuildpackID: "A", - Default: false, - }, - }, - }, nil) - - metadata, err := builder.Build() - h.AssertNil(t, err) - - if s := cmp.Diff(metadata.Processes, []launch.Process{ - { - Type: "web", - Command: launch.NewRawCommand([]string{"web-cmd"}). - WithPlatformAPI(builder.PlatformAPI), - Args: []string{"web-arg"}, - Direct: false, - BuildpackID: "A", - Default: false, - PlatformAPI: builder.PlatformAPI, - }, - }); s != "" { - t.Fatalf("Unexpected:\n%s\n", s) - } - h.AssertEq(t, metadata.BuildpackDefaultProcessType, "") - }) - }) - }) - when("platform api < 0.9", func() { it.Before(func() { builder.PlatformAPI = api.MustParse("0.8") diff --git a/cmd/launcher/cli/launcher.go b/cmd/launcher/cli/launcher.go index ae48727f3..82e09e02e 100644 --- a/cmd/launcher/cli/launcher.go +++ b/cmd/launcher/cli/launcher.go @@ -67,9 +67,6 @@ func boolEnv(k string) bool { } func defaultProcessType(platformAPI *api.Version, launchMD launch.Metadata) string { - if platformAPI.LessThan("0.4") { - return cmd.EnvOrDefault(platform.EnvProcessType, platform.DefaultProcessType) - } if pType := os.Getenv(platform.EnvProcessType); pType != "" { cmd.DefaultLogger.Warnf("CNB_PROCESS_TYPE is not supported in Platform API %s", platformAPI) cmd.DefaultLogger.Warnf("Run with ENTRYPOINT '%s' to invoke the '%s' process type", pType, pType) diff --git a/cmd/lifecycle/analyzer.go b/cmd/lifecycle/analyzer.go index adba0b7ee..e8ff5e8b1 100644 --- a/cmd/lifecycle/analyzer.go +++ b/cmd/lifecycle/analyzer.go @@ -11,7 +11,6 @@ import ( "github.com/buildpacks/lifecycle" "github.com/buildpacks/lifecycle/auth" - "github.com/buildpacks/lifecycle/buildpack" "github.com/buildpacks/lifecycle/cmd" "github.com/buildpacks/lifecycle/cmd/lifecycle/cli" "github.com/buildpacks/lifecycle/platform" @@ -27,14 +26,9 @@ type analyzeCmd struct { // DefineFlags defines the flags that are considered valid and reads their values (if provided). func (a *analyzeCmd) DefineFlags() { - if a.PlatformAPI.LessThan("0.12") && a.PlatformAPI.AtLeast("0.7") { + if a.PlatformAPI.LessThan("0.12") { cli.FlagStackPath(&a.StackPath) } - if a.PlatformAPI.LessThan("0.7") { - cli.FlagCacheDir(&a.CacheDir) - cli.FlagGroupPath(&a.GroupPath) - cli.FlagSkipLayers(&a.SkipLayers) - } switch { case a.PlatformAPI.AtLeast("0.12"): cli.FlagLayoutDir(&a.LayoutDir) @@ -45,16 +39,14 @@ func (a *analyzeCmd) DefineFlags() { cli.FlagLaunchCacheDir(&a.LaunchCacheDir) cli.FlagSkipLayers(&a.SkipLayers) fallthrough - case a.PlatformAPI.AtLeast("0.7"): - cli.FlagPreviousImage(&a.PreviousImageRef) - cli.FlagRunImage(&a.RunImageRef) - cli.FlagTags(&a.AdditionalTags) - fallthrough default: cli.FlagAnalyzedPath(&a.AnalyzedPath) cli.FlagCacheImage(&a.CacheImageRef) cli.FlagGID(&a.GID) cli.FlagLayersDir(&a.LayersDir) + cli.FlagPreviousImage(&a.PreviousImageRef) + cli.FlagRunImage(&a.RunImageRef) + cli.FlagTags(&a.AdditionalTags) cli.FlagUID(&a.UID) cli.FlagUseDaemon(&a.UseDaemon) } @@ -110,20 +102,7 @@ func (a *analyzeCmd) Exec() error { image.NewHandler(a.docker, a.keychain, a.LayoutDir, a.UseLayout), NewRegistryHandler(a.keychain), ) - analyzer, err := factory.NewAnalyzer( - a.AdditionalTags, - a.CacheImageRef, - a.LaunchCacheDir, - a.LayersDir, - a.CacheDir, - buildpack.Group{}, - a.GroupPath, - a.OutputImageRef, - a.PreviousImageRef, - a.RunImageRef, - a.SkipLayers, - cmd.DefaultLogger, - ) + analyzer, err := factory.NewAnalyzer(a.AdditionalTags, a.CacheImageRef, a.LaunchCacheDir, a.LayersDir, a.OutputImageRef, a.PreviousImageRef, a.RunImageRef, a.SkipLayers, cmd.DefaultLogger) if err != nil { return unwrapErrorFailWithMessage(err, "initialize analyzer") } diff --git a/cmd/lifecycle/creator.go b/cmd/lifecycle/creator.go index 708525131..e67cb334e 100644 --- a/cmd/lifecycle/creator.go +++ b/cmd/lifecycle/creator.go @@ -112,106 +112,45 @@ func (c *createCmd) Exec() error { return err } - // Analyze, Detect + // Analyze var ( analyzedMD files.Analyzed group buildpack.Group plan files.Plan ) - if c.PlatformAPI.AtLeast("0.7") { - cmd.DefaultLogger.Phase("ANALYZING") - analyzerFactory := lifecycle.NewAnalyzerFactory( - c.PlatformAPI, - &cmd.BuildpackAPIVerifier{}, - NewCacheHandler(c.keychain), - lifecycle.NewConfigHandler(), - image.NewHandler(c.docker, c.keychain, c.LayoutDir, c.UseLayout), - NewRegistryHandler(c.keychain), - ) - analyzer, err := analyzerFactory.NewAnalyzer( - c.AdditionalTags, - c.CacheImageRef, - c.LaunchCacheDir, - c.LayersDir, - "", - buildpack.Group{}, - "", - c.OutputImageRef, - c.PreviousImageRef, - c.RunImageRef, - c.SkipLayers, - cmd.DefaultLogger, - ) - if err != nil { - return unwrapErrorFailWithMessage(err, "initialize analyzer") - } - analyzedMD, err = analyzer.Analyze() - if err != nil { - return err - } - - cmd.DefaultLogger.Phase("DETECTING") - detectorFactory := lifecycle.NewDetectorFactory( - c.PlatformAPI, - &cmd.BuildpackAPIVerifier{}, - lifecycle.NewConfigHandler(), - dirStore, - ) - detector, err := detectorFactory.NewDetector(analyzedMD, c.AppDir, c.BuildConfigDir, c.OrderPath, c.PlatformDir, cmd.DefaultLogger) - if err != nil { - return unwrapErrorFailWithMessage(err, "initialize detector") - } - group, plan, err = doDetect(detector, c.Platform) - if err != nil { - return err // pass through error - } - } else { - cmd.DefaultLogger.Phase("DETECTING") - detectorFactory := lifecycle.NewDetectorFactory( - c.PlatformAPI, - &cmd.BuildpackAPIVerifier{}, - lifecycle.NewConfigHandler(), - dirStore, - ) - detector, err := detectorFactory.NewDetector(files.Analyzed{}, c.AppDir, c.BuildConfigDir, c.OrderPath, c.PlatformDir, cmd.DefaultLogger) - if err != nil { - return unwrapErrorFailWithMessage(err, "initialize detector") - } - group, plan, err = doDetect(detector, c.Platform) - if err != nil { - return err // pass through error - } + cmd.DefaultLogger.Phase("ANALYZING") + analyzerFactory := lifecycle.NewAnalyzerFactory( + c.PlatformAPI, + &cmd.BuildpackAPIVerifier{}, + NewCacheHandler(c.keychain), + lifecycle.NewConfigHandler(), + image.NewHandler(c.docker, c.keychain, c.LayoutDir, c.UseLayout), + NewRegistryHandler(c.keychain), + ) + analyzer, err := analyzerFactory.NewAnalyzer(c.AdditionalTags, c.CacheImageRef, c.LaunchCacheDir, c.LayersDir, c.OutputImageRef, c.PreviousImageRef, c.RunImageRef, c.SkipLayers, cmd.DefaultLogger) + if err != nil { + return unwrapErrorFailWithMessage(err, "initialize analyzer") + } + analyzedMD, err = analyzer.Analyze() + if err != nil { + return err + } - cmd.DefaultLogger.Phase("ANALYZING") - analyzerFactory := lifecycle.NewAnalyzerFactory( - c.PlatformAPI, - &cmd.BuildpackAPIVerifier{}, - NewCacheHandler(c.keychain), - lifecycle.NewConfigHandler(), - image.NewHandler(c.docker, c.keychain, c.LayoutDir, c.UseLayout), - NewRegistryHandler(c.keychain), - ) - analyzer, err := analyzerFactory.NewAnalyzer( - c.AdditionalTags, - c.CacheImageRef, - c.LaunchCacheDir, - c.LayersDir, - c.CacheDir, - group, - "", - c.OutputImageRef, - c.PreviousImageRef, - c.RunImageRef, - c.SkipLayers, - cmd.DefaultLogger, - ) - if err != nil { - return unwrapErrorFailWithMessage(err, "initialize analyzer") - } - analyzedMD, err = analyzer.Analyze() - if err != nil { - return err - } + // Detect + cmd.DefaultLogger.Phase("DETECTING") + detectorFactory := lifecycle.NewDetectorFactory( + c.PlatformAPI, + &cmd.BuildpackAPIVerifier{}, + lifecycle.NewConfigHandler(), + dirStore, + ) + detector, err := detectorFactory.NewDetector(analyzedMD, c.AppDir, c.BuildConfigDir, c.OrderPath, c.PlatformDir, cmd.DefaultLogger) + if err != nil { + return unwrapErrorFailWithMessage(err, "initialize detector") + } + group, plan, err = doDetect(detector, c.Platform) + if err != nil { + return err // pass through error } // Restore diff --git a/cmd/lifecycle/restorer.go b/cmd/lifecycle/restorer.go index dc17c2e5c..dde3604fc 100644 --- a/cmd/lifecycle/restorer.go +++ b/cmd/lifecycle/restorer.go @@ -46,15 +46,13 @@ func (r *restoreCmd) DefineFlags() { if r.PlatformAPI.AtLeast("0.10") { cli.FlagBuildImage(&r.BuildImageRef) } - if r.PlatformAPI.AtLeast("0.7") { - cli.FlagAnalyzedPath(&r.AnalyzedPath) - cli.FlagSkipLayers(&r.SkipLayers) - } + cli.FlagAnalyzedPath(&r.AnalyzedPath) cli.FlagCacheDir(&r.CacheDir) cli.FlagCacheImage(&r.CacheImageRef) cli.FlagGID(&r.GID) cli.FlagGroupPath(&r.GroupPath) cli.FlagLayersDir(&r.LayersDir) + cli.FlagSkipLayers(&r.SkipLayers) cli.FlagUID(&r.UID) } @@ -158,12 +156,7 @@ func (r *restoreCmd) Exec() error { return err } - var appMeta files.LayersMetadata - if r.restoresLayerMetadata() { - appMeta = analyzedMD.LayersMetadata - } - - return r.restore(appMeta, group, cacheStore) + return r.restore(analyzedMD.LayersMetadata, group, cacheStore) } func updateAnalyzedMD(analyzedMD *files.Analyzed, remoteRunImage imgutil.Image) error { @@ -260,10 +253,6 @@ func (r *restoreCmd) pullSparse(imageRef string) (imgutil.Image, error) { return remoteImage, nil } -func (r *restoreCmd) restoresLayerMetadata() bool { - return r.PlatformAPI.AtLeast("0.7") -} - func (r *restoreCmd) restore(layerMetadata files.LayersMetadata, group buildpack.Group, cacheStore lifecycle.Cache) error { restorer := &lifecycle.Restorer{ LayersDir: r.LayersDir, diff --git a/exporter.go b/exporter.go index e18148e2d..992907b1a 100644 --- a/exporter.go +++ b/exporter.go @@ -155,15 +155,13 @@ func (e *Exporter) Export(opts ExportOptions) (files.Report, error) { return files.Report{}, err } - if err := e.setEnv(opts, buildMD.ToLaunchMD()); err != nil { + if err := e.setEnv(opts); err != nil { return files.Report{}, err } - if e.PlatformAPI.AtLeast("0.6") { - e.Logger.Debugf("Setting WORKDIR: '%s'", opts.AppDir) - if err := e.setWorkingDir(opts); err != nil { - return files.Report{}, errors.Wrap(err, "setting workdir") - } + e.Logger.Debugf("Setting WORKDIR: '%s'", opts.AppDir) + if err := e.setWorkingDir(opts); err != nil { + return files.Report{}, errors.Wrap(err, "setting workdir") } entrypoint, err := e.entrypoint(buildMD.ToLaunchMD(), opts.DefaultProcessType, buildMD.BuildpackDefaultProcessType) @@ -188,11 +186,6 @@ func (e *Exporter) Export(opts ExportOptions) (files.Report, error) { if err != nil { return files.Report{}, err } - if !e.supportsManifestSize() { - // unset manifest size in report.toml for old platform API versions - report.Image.ManifestSize = 0 - } - return report, nil } @@ -562,7 +555,7 @@ func (e *Exporter) setLabels(opts ExportOptions, meta files.LayersMetadata, buil return nil } -func (e *Exporter) setEnv(opts ExportOptions, launchMD launch.Metadata) error { +func (e *Exporter) setEnv(opts ExportOptions) error { e.Logger.Debugf("Setting %s=%s", platform.EnvLayersDir, opts.LayersDir) if err := opts.WorkingImage.SetEnv(platform.EnvLayersDir, opts.LayersDir); err != nil { return errors.Wrapf(err, "set app image env %s", platform.EnvLayersDir) @@ -583,24 +576,14 @@ func (e *Exporter) setEnv(opts ExportOptions, launchMD launch.Metadata) error { return errors.Wrapf(err, "set app image env %s", platform.EnvAppDir) } - if e.supportsMulticallLauncher() { - path, err := opts.WorkingImage.Env("PATH") - if err != nil { - return errors.Wrap(err, "failed to get PATH from app image") - } - path = strings.Join([]string{launch.ProcessDir, launch.LifecycleDir, path}, string(os.PathListSeparator)) - e.Logger.Debugf("Prepending %s and %s to PATH", launch.ProcessDir, launch.LifecycleDir) - if err := opts.WorkingImage.SetEnv("PATH", path); err != nil { - return errors.Wrap(err, "set app image env PATH") - } - } else if opts.DefaultProcessType != "" { - if _, ok := launchMD.FindProcessType(opts.DefaultProcessType); !ok { - return processTypeError(launchMD, opts.DefaultProcessType) - } - e.Logger.Debugf("Setting %s=%s", platform.EnvProcessType, opts.DefaultProcessType) - if err := opts.WorkingImage.SetEnv(platform.EnvProcessType, opts.DefaultProcessType); err != nil { - return errors.Wrapf(err, "set app image env %s", platform.EnvProcessType) - } + path, err := opts.WorkingImage.Env("PATH") + if err != nil { + return errors.Wrap(err, "failed to get PATH from app image") + } + path = strings.Join([]string{launch.ProcessDir, launch.LifecycleDir, path}, string(os.PathListSeparator)) + e.Logger.Debugf("Prepending %s and %s to PATH", launch.ProcessDir, launch.LifecycleDir) + if err := opts.WorkingImage.SetEnv("PATH", path); err != nil { + return errors.Wrap(err, "set app image env PATH") } return nil } @@ -610,23 +593,9 @@ func (e *Exporter) setWorkingDir(opts ExportOptions) error { } func (e *Exporter) entrypoint(launchMD launch.Metadata, userDefaultProcessType, buildpackDefaultProcessType string) (string, error) { - if !e.supportsMulticallLauncher() { - return launch.LauncherPath, nil - } - - if userDefaultProcessType == "" && e.PlatformAPI.LessThan("0.6") && len(launchMD.Processes) == 1 { - // if there is only one process, we set it to the default for platform API < 0.6 - e.Logger.Infof("Setting default process type '%s'", launchMD.Processes[0].Type) - return launch.ProcessPath(launchMD.Processes[0].Type), nil - } - if userDefaultProcessType != "" { defaultProcess, ok := launchMD.FindProcessType(userDefaultProcessType) if !ok { - if e.PlatformAPI.LessThan("0.6") { - e.Logger.Warn(processTypeWarning(launchMD, userDefaultProcessType)) - return launch.LauncherPath, nil - } return "", fmt.Errorf("tried to set %s to default but it doesn't exist", userDefaultProcessType) } e.Logger.Infof("Setting default process type '%s'", defaultProcess.Type) @@ -641,44 +610,22 @@ func (e *Exporter) entrypoint(launchMD launch.Metadata, userDefaultProcessType, } func (e *Exporter) launcherConfig(opts ExportOptions, buildMD *files.BuildMetadata, meta *files.LayersMetadata) error { - if e.supportsMulticallLauncher() { - launchMD := launch.Metadata{ - Processes: buildMD.Processes, + launchMD := launch.Metadata{ + Processes: buildMD.Processes, + } + if len(buildMD.Processes) > 0 { + processTypesLayer, err := e.LayerFactory.ProcessTypesLayer(launchMD) + if err != nil { + return errors.Wrapf(err, "creating layer '%s'", processTypesLayer.ID) } - if len(buildMD.Processes) > 0 { - processTypesLayer, err := e.LayerFactory.ProcessTypesLayer(launchMD) - if err != nil { - return errors.Wrapf(err, "creating layer '%s'", processTypesLayer.ID) - } - meta.ProcessTypes.SHA, err = e.addOrReuseBuildpackLayer(opts.WorkingImage, processTypesLayer, opts.OrigMetadata.ProcessTypes.SHA, layers.ProcessTypesLayerName) - if err != nil { - return errors.Wrapf(err, "exporting layer '%s'", processTypesLayer.ID) - } + meta.ProcessTypes.SHA, err = e.addOrReuseBuildpackLayer(opts.WorkingImage, processTypesLayer, opts.OrigMetadata.ProcessTypes.SHA, layers.ProcessTypesLayerName) + if err != nil { + return errors.Wrapf(err, "exporting layer '%s'", processTypesLayer.ID) } } return nil } -func (e *Exporter) supportsMulticallLauncher() bool { - return e.PlatformAPI.AtLeast("0.4") -} - -func (e *Exporter) supportsManifestSize() bool { - return e.PlatformAPI.AtLeast("0.6") -} - -func processTypeError(launchMD launch.Metadata, defaultProcessType string) error { - return fmt.Errorf(processTypeWarning(launchMD, defaultProcessType)) -} - -func processTypeWarning(launchMD launch.Metadata, defaultProcessType string) string { - var typeList []string - for _, p := range launchMD.Processes { - typeList = append(typeList, p.Type) - } - return fmt.Sprintf("default process type '%s' not present in list %+v", defaultProcessType, typeList) -} - func (e *Exporter) addOrReuseBuildpackLayer(image imgutil.Image, layer layers.Layer, previousSHA, createdBy string) (string, error) { layer, err := e.LayerFactory.DirLayer(layer.ID, layer.TarPath, createdBy) if err != nil { @@ -713,7 +660,7 @@ func (e *Exporter) addOrReuseExtensionLayer(image imgutil.Image, layer layers.La } func (e *Exporter) makeBuildReport(layersDir string) (files.BuildReport, error) { - if e.PlatformAPI.LessThan("0.5") || e.PlatformAPI.AtLeast("0.9") { + if e.PlatformAPI.AtLeast("0.9") { return files.BuildReport{}, nil } var out []buildpack.BOMEntry diff --git a/exporter_test.go b/exporter_test.go index c0f34f175..f1e3ec23b 100644 --- a/exporter_test.go +++ b/exporter_test.go @@ -702,61 +702,27 @@ version = "4.5.6" h.AssertNil(t, fakeAppImage.SetEnv("PATH", "some-path")) }) - when("platform API >= 0.4", func() { - it("prepends the process and lifecycle dirs to PATH", func() { - _, err := exporter.Export(opts) - h.AssertNil(t, err) - - val, err := opts.WorkingImage.Env("PATH") - h.AssertNil(t, err) - if runtime.GOOS == "windows" { - h.AssertEq(t, val, `c:\cnb\process;c:\cnb\lifecycle;some-path`) - } else { - h.AssertEq(t, val, `/cnb/process:/cnb/lifecycle:some-path`) - } - }) - }) - - when("platform API < 0.4", func() { - it.Before(func() { - exporter.PlatformAPI = api.MustParse("0.3") - }) - - it("doesn't prepend the process dir", func() { - _, err := exporter.Export(opts) - h.AssertNil(t, err) + it("prepends the process and lifecycle dirs to PATH", func() { + _, err := exporter.Export(opts) + h.AssertNil(t, err) - val, err := opts.WorkingImage.Env("PATH") - h.AssertNil(t, err) - h.AssertEq(t, val, "some-path") - }) + val, err := opts.WorkingImage.Env("PATH") + h.AssertNil(t, err) + if runtime.GOOS == "windows" { + h.AssertEq(t, val, `c:\cnb\process;c:\cnb\lifecycle;some-path`) + } else { + h.AssertEq(t, val, `/cnb/process:/cnb/lifecycle:some-path`) + } }) }) - when("working directory", func() { - when("platform API > 0.5", func() { - it("sets WorkingDir", func() { - _, err := exporter.Export(opts) - h.AssertNil(t, err) - - val, err := fakeAppImage.WorkingDir() - h.AssertNil(t, err) - h.AssertEq(t, val, opts.AppDir) - }) - }) - - when("platform API <= 0.5", func() { - platformAPI = api.MustParse("0.5") - - it("doesn't set WorkingDir", func() { - _, err := exporter.Export(opts) - h.AssertNil(t, err) + it("sets WorkingDir", func() { + _, err := exporter.Export(opts) + h.AssertNil(t, err) - val, err := fakeAppImage.WorkingDir() - h.AssertNil(t, err) - h.AssertEq(t, val, "") - }) - }) + val, err := fakeAppImage.WorkingDir() + h.AssertNil(t, err) + h.AssertEq(t, val, opts.AppDir) }) it("sets empty CMD", func() { @@ -959,24 +925,12 @@ version = "4.5.6" assertAddLayerLog(t, logHandler, "launcher") }) - when("platform API >= 0.4", func() { - it("creates process-types layer", func() { - _, err := exporter.Export(opts) - h.AssertNil(t, err) + it("creates process-types layer", func() { + _, err := exporter.Export(opts) + h.AssertNil(t, err) - assertHasLayer(t, fakeAppImage, "process-types") - assertAddLayerLog(t, logHandler, "process-types") - }) - }) - - when("platform API < 0.4", func() { - it("doesn't create process-types layer", func() { - exporter.PlatformAPI = api.MustParse("0.3") - _, err := exporter.Export(opts) - h.AssertNil(t, err) - - assertDoesNotHaveLayer(t, fakeAppImage, "process-types") - }) + assertHasLayer(t, fakeAppImage, "process-types") + assertAddLayerLog(t, logHandler, "process-types") }) it("adds launch layers", func() { @@ -1211,129 +1165,47 @@ version = "4.5.6" }) }) }) + }) - when("platform API < 0.6", func() { - platformAPI = api.MustParse("0.5") - - it.Before(func() { - h.RecursiveCopy(t, filepath.Join("testdata", "exporter", "default-process", "metadata-with-no-default", "layers"), opts.LayersDir) - }) - - when("-process-type is set to a process type that doesn't exist", func() { - it.Before(func() { - opts.DefaultProcessType = "some-non-existing-process-type" - }) - it("warns the process type doesn't exist, and sets the ENTRYPOINT to the launcher", func() { - _, err := exporter.Export(opts) - h.AssertNil(t, err) - assertLogEntry(t, logHandler, "default process type 'some-non-existing-process-type' not present in list [some-process-type]") - assertHasEntrypoint(t, fakeAppImage, filepath.Join(path.RootDir, "cnb", "lifecycle", "launcher"+path.ExecExt)) - }) - }) - - when("-process-type is not set and there is exactly one process", func() { - it("sets the ENTRYPOINT to the only process", func() { - _, err := exporter.Export(opts) - h.AssertNil(t, err) - assertHasEntrypoint(t, fakeAppImage, filepath.Join(path.RootDir, "cnb", "process", "some-process-type"+path.ExecExt)) - }) - }) - }) - - when("platform API < 0.4", func() { + when("report.toml", func() { + when("manifest size", func() { + var fakeRemoteManifestSize int64 it.Before(func() { - exporter.PlatformAPI = api.MustParse("0.3") - h.RecursiveCopy(t, filepath.Join("testdata", "exporter", "default-process", "metadata-with-no-default", "layers"), opts.LayersDir) + opts.LayersDir = filepath.Join("testdata", "exporter", "empty-metadata", "layers") }) - when("-process-type is set to an existing process type", func() { + when("image has a manifest", func() { it.Before(func() { - opts.DefaultProcessType = "some-process-type" + fakeRemoteManifestSize = 12345 + fakeAppImage.SetManifestSize(fakeRemoteManifestSize) }) - it("sets CNB_PROCESS_TYPE", func() { + it("outputs the manifest size", func() { _, err := exporter.Export(opts) h.AssertNil(t, err) - val, err := fakeAppImage.Env("CNB_PROCESS_TYPE") - h.AssertNil(t, err) - h.AssertEq(t, val, "some-process-type") + assertLogEntry(t, logHandler, fmt.Sprintf("*** Manifest Size: %d", fakeRemoteManifestSize)) }) - }) - when("-process-type is not set", func() { - it("doesn't set CNB_PROCESS_TYPE", func() { - _, err := exporter.Export(opts) + it("add the manifest size to the report", func() { + report, err := exporter.Export(opts) h.AssertNil(t, err) - val, err := fakeAppImage.Env("CNB_PROCESS_TYPE") - h.AssertNil(t, err) - h.AssertEq(t, val, "") + h.AssertEq(t, report.Image.ManifestSize, fakeRemoteManifestSize) }) }) - }) - }) - when("report.toml", func() { - when("manifest size", func() { - var fakeRemoteManifestSize int64 - it.Before(func() { - opts.LayersDir = filepath.Join("testdata", "exporter", "empty-metadata", "layers") - }) - - when("platform API is < 0.6", func() { + when("image doesn't have a manifest", func() { it.Before(func() { - exporter.PlatformAPI = api.MustParse("0.5") + fakeRemoteManifestSize = 0 + fakeAppImage.SetManifestSize(fakeRemoteManifestSize) }) - when("image has a manifest", func() { - it.Before(func() { - fakeRemoteManifestSize = 12345 - fakeAppImage.SetManifestSize(fakeRemoteManifestSize) - }) - - it("doesn't set the manifest size in the report.toml", func() { - report, err := exporter.Export(opts) - h.AssertNil(t, err) - - h.AssertEq(t, report.Image.ManifestSize, int64(0)) - }) - }) - }) - - when("platform API is >= 0.6", func() { - when("image has a manifest", func() { - it.Before(func() { - fakeRemoteManifestSize = 12345 - fakeAppImage.SetManifestSize(fakeRemoteManifestSize) - }) - - it("outputs the manifest size", func() { - _, err := exporter.Export(opts) - h.AssertNil(t, err) - - assertLogEntry(t, logHandler, fmt.Sprintf("*** Manifest Size: %d", fakeRemoteManifestSize)) - }) - - it("add the manifest size to the report", func() { - report, err := exporter.Export(opts) - h.AssertNil(t, err) - h.AssertEq(t, report.Image.ManifestSize, fakeRemoteManifestSize) - }) - }) - - when("image doesn't have a manifest", func() { - it.Before(func() { - fakeRemoteManifestSize = 0 - fakeAppImage.SetManifestSize(fakeRemoteManifestSize) - }) - - it("doesn't set the manifest size in the report.toml", func() { - report, err := exporter.Export(opts) - h.AssertNil(t, err) + it("doesn't set the manifest size in the report.toml", func() { + report, err := exporter.Export(opts) + h.AssertNil(t, err) - h.AssertEq(t, report.Image.ManifestSize, int64(0)) - }) + h.AssertEq(t, report.Image.ManifestSize, int64(0)) }) }) }) diff --git a/internal/layer/metadata_restorer.go b/internal/layer/metadata_restorer.go index 88d39db3f..831ff1e81 100644 --- a/internal/layer/metadata_restorer.go +++ b/internal/layer/metadata_restorer.go @@ -142,27 +142,11 @@ type SHAStore interface { Get(buildpackID string, layer buildpack.Layer) (string, error) } -func NewSHAStore(useShaFiles bool) SHAStore { - if useShaFiles { - return &fileStore{} - } +// NewSHAStore returns a new SHAStore for mapping buildpack IDs to layer names and their SHAs. +func NewSHAStore() SHAStore { return &memoryStore{make(map[string]layerToSha)} } -type fileStore struct{} - -func (fs *fileStore) add(_, sha string, layer *buildpack.Layer) error { - return layer.WriteSha(sha) -} - -func (fs *fileStore) Get(_ string, layer buildpack.Layer) (string, error) { - data, err := layer.Read() - if err != nil { - return "", errors.Wrapf(err, "reading layer") - } - return data.SHA, nil -} - type memoryStore struct { buildpacksToLayersShaMap map[string]layerToSha } diff --git a/internal/layer/metadata_restorer_test.go b/internal/layer/metadata_restorer_test.go index fdd5a13ae..aec91d373 100644 --- a/internal/layer/metadata_restorer_test.go +++ b/internal/layer/metadata_restorer_test.go @@ -33,7 +33,6 @@ func testLayerMetadataRestorer(t *testing.T, when spec.G, it spec.S) { cacheMetadata platform.CacheMetadata buildpacks []buildpack.GroupElement skipLayers bool - useShaFiles bool logger log.Logger ) @@ -42,10 +41,9 @@ func testLayerMetadataRestorer(t *testing.T, when spec.G, it spec.S) { layerDir, err = os.MkdirTemp("", "lifecycle-layer-dir") h.AssertNil(t, err) - useShaFiles = true // notice - the default for platform API >= 0.7 is false (it's set to false in some of the tests) logger = log.Logger{Handler: &discard.Handler{}} layerMetadataRestorer = layer.NewDefaultMetadataRestorer(layerDir, skipLayers, &logger) - layerSHAStore = layer.NewSHAStore(useShaFiles) + layerSHAStore = layer.NewSHAStore() }) it.After(func() { @@ -165,42 +163,6 @@ func testLayerMetadataRestorer(t *testing.T, when spec.G, it spec.S) { } }) - when("restoring sha files is not needed", func() { - it.Before(func() { - useShaFiles = false - layerMetadataRestorer = layer.NewDefaultMetadataRestorer(layerDir, skipLayers, &logger) - layerSHAStore = layer.NewSHAStore(useShaFiles) - }) - - it("does not restore sha files", func() { - err := layerMetadataRestorer.Restore(buildpacks, layersMetadata, cacheMetadata, layerSHAStore) - h.AssertNil(t, err) - - h.AssertPathDoesNotExist(t, filepath.Join(layerDir, "metadata.buildpack/launch.sha", "launch-sha")) - h.AssertPathDoesNotExist(t, filepath.Join(layerDir, "metadata.buildpack/launch-build-cache.sha", "launch-build-cache-sha")) - h.AssertPathDoesNotExist(t, filepath.Join(layerDir, "metadata.buildpack/launch-cache.sha", "launch-cache-sha")) - h.AssertPathDoesNotExist(t, filepath.Join(layerDir, "no.cache.buildpack/some-layer.sha", "some-layer-sha")) - h.AssertPathDoesNotExist(t, filepath.Join(layerDir, "metadata.buildpack", "launch-cache-not-in-app.sha")) - }) - }) - - it("restores app and cache layer sha files, prefers app sha", func() { - err := layerMetadataRestorer.Restore(buildpacks, layersMetadata, cacheMetadata, layerSHAStore) - h.AssertNil(t, err) - - for _, data := range []struct{ name, want string }{ - {"metadata.buildpack/launch.sha", "launch-sha"}, - {"metadata.buildpack/launch-build-cache.sha", "launch-build-cache-sha"}, - {"metadata.buildpack/launch-cache.sha", "launch-cache-sha"}, - {"no.cache.buildpack/some-layer.sha", "some-layer-sha"}, - // Cache-image-only layers. - {"metadata.buildpack/cache.sha", "cache-sha"}, - } { - got := h.MustReadFile(t, filepath.Join(layerDir, data.name)) - h.AssertStringContains(t, string(got), data.want) - } - }) - it("does not overwrite metadata from app image", func() { err := layerMetadataRestorer.Restore(buildpacks, layersMetadata, cacheMetadata, layerSHAStore) h.AssertNil(t, err) @@ -217,22 +179,6 @@ func testLayerMetadataRestorer(t *testing.T, when spec.G, it spec.S) { } }) - it("does not overwrite sha from app image", func() { - err := layerMetadataRestorer.Restore(buildpacks, layersMetadata, cacheMetadata, layerSHAStore) - h.AssertNil(t, err) - - for _, name := range []string{ - "metadata.buildpack/launch-build-cache.sha", - "metadata.buildpack/launch-cache.sha", - } { - got := h.MustReadFile(t, filepath.Join(layerDir, name)) - avoid := "old-sha" - if strings.Contains(string(got), avoid) { - t.Errorf("Expected %q to not contain %q, got %q", name, avoid, got) - } - } - }) - it("does not restore cache=true layers for non-selected groups", func() { err := layerMetadataRestorer.Restore(buildpacks, layersMetadata, cacheMetadata, layerSHAStore) h.AssertNil(t, err) diff --git a/launch/process.go b/launch/process.go index 7237a687d..323be9c5b 100644 --- a/launch/process.go +++ b/launch/process.go @@ -19,10 +19,6 @@ import ( // * it constructs a new process from cmd // * If the first element in cmd is `cmd` the process shall be direct func (l *Launcher) ProcessFor(cmd []string) (Process, error) { - if l.PlatformAPI.LessThan("0.4") { - return l.processForLegacy(cmd) - } - if l.DefaultProcessType == "" { process, err := l.userProvidedProcess(cmd) if err != nil { diff --git a/launch/process_test.go b/launch/process_test.go index 4c6648053..e08897fbd 100644 --- a/launch/process_test.go +++ b/launch/process_test.go @@ -270,124 +270,5 @@ func testProcess(t *testing.T, when spec.G, it spec.S) { }) }) }) - - when("Platform API < 0.4", func() { - it.Before(func() { - launcher.PlatformAPI = api.MustParse("0.3") - }) - - when("DefaultProcessType", func() { - when("is unset", func() { - when("cmd is empty", func() { - it("errors", func() { - _, err := launcher.ProcessFor([]string{}) - h.AssertNotNil(t, err) - }) - }) - - when("cmd contains a only a process type", func() { - it("returns the process type", func() { - proc, err := launcher.ProcessFor([]string{"other-type"}) - h.AssertNil(t, err) - h.AssertEq(t, proc, launch.Process{ - Type: "other-type", - Command: launch.NewRawCommand([]string{"other-command"}), - Args: []string{"other-arg1", "other-arg2"}, - BuildpackID: "some-buildpack", - }, processCmpOpts...) - }) - }) - - when("cmd starts with --", func() { - it("creates a new direct process from cmd", func() { - proc, err := launcher.ProcessFor([]string{"--", "user-command", "user-arg1", "user-arg2"}) - h.AssertNil(t, err) - h.AssertEq(t, proc, launch.Process{ - Command: launch.NewRawCommand([]string{"user-command"}), - Args: []string{"user-arg1", "user-arg2"}, - Direct: true, - }, processCmpOpts...) - }) - }) - - when("cmd contains more than one arg and does not start with --", func() { - it("creates a new shell process from cmd", func() { - proc, err := launcher.ProcessFor([]string{"user-command", "user-arg1", "user-arg2"}) - h.AssertNil(t, err) - h.AssertEq(t, proc, launch.Process{ - Command: launch.NewRawCommand([]string{"user-command"}), - Args: []string{"user-arg1", "user-arg2"}, - }, processCmpOpts...) - }) - }) - }) - - when("exists", func() { - it.Before(func() { - launcher.DefaultProcessType = "some-type" - }) - - when("cmd is empty", func() { - it("returns the default process type", func() { - proc, err := launcher.ProcessFor([]string{}) - h.AssertNil(t, err) - h.AssertEq(t, proc, launch.Process{ - Type: "some-type", - Command: launch.NewRawCommand([]string{"some-command"}), - Args: []string{"some-arg1", "some-arg2"}, - BuildpackID: "some-buildpack", - }, processCmpOpts...) - }) - }) - - when("cmd contains a only a process type", func() { - it("returns the process type", func() { - proc, err := launcher.ProcessFor([]string{"other-type"}) - h.AssertNil(t, err) - h.AssertEq(t, proc, launch.Process{ - Type: "other-type", - Command: launch.NewRawCommand([]string{"other-command"}), - Args: []string{"other-arg1", "other-arg2"}, - BuildpackID: "some-buildpack", - }, processCmpOpts...) - }) - }) - - when("cmd contains more than one arg and starts with --", func() { - it("creates a new direct process from cmd", func() { - proc, err := launcher.ProcessFor([]string{"--", "user-command", "user-arg1", "user-arg2"}) - h.AssertNil(t, err) - h.AssertEq(t, proc, launch.Process{ - Command: launch.NewRawCommand([]string{"user-command"}), - Args: []string{"user-arg1", "user-arg2"}, - Direct: true, - }, processCmpOpts...) - }) - }) - - when("cmd contains more than one arg and does not start with --", func() { - it("creates a new shell process from cmd", func() { - proc, err := launcher.ProcessFor([]string{"user-command", "user-arg1", "user-arg2"}) - h.AssertNil(t, err) - h.AssertEq(t, proc, launch.Process{ - Command: launch.NewRawCommand([]string{"user-command"}), - Args: []string{"user-arg1", "user-arg2"}, - }, processCmpOpts...) - }) - }) - }) - - when("doesn't exist", func() { - it.Before(func() { - launcher.DefaultProcessType = "missing-type" - }) - - it("errors when cmd is empty", func() { - _, err := launcher.ProcessFor([]string{}) - h.AssertNotNil(t, err) - }) - }) - }) - }) }) } diff --git a/lifecycle.toml b/lifecycle.toml index f23871592..f98af64fd 100644 --- a/lifecycle.toml +++ b/lifecycle.toml @@ -9,7 +9,7 @@ # For backwards compatibility the minimum supported APIs are provided in RFC-0011 format # https://github.com/buildpacks/rfcs/blob/main/text/0011-lifecycle-descriptor.md [api] - platform = "0.3" + platform = "0.7" buildpack = "0.7" [lifecycle] diff --git a/platform/exit.go b/platform/exit.go index 4d2391d39..b6333cbc0 100644 --- a/platform/exit.go +++ b/platform/exit.go @@ -26,13 +26,9 @@ type Exiter interface { CodeFor(errType LifecycleExitError) int } -func NewExiter(platformAPI string) Exiter { - switch platformAPI { - case "0.3", "0.4", "0.5": - return &LegacyExiter{} - default: - return &DefaultExiter{} - } +// NewExiter configures a new Exiter according to the provided Platform API version. +func NewExiter(_ string) Exiter { + return &DefaultExiter{} } type DefaultExiter struct{} @@ -74,45 +70,6 @@ func (e *DefaultExiter) CodeFor(errType LifecycleExitError) int { return codeFor(errType, defaultExitCodes) } -type LegacyExiter struct{} - -var legacyExitCodes = map[LifecycleExitError]int{ - // detect phase errors: 100-199 - FailedDetect: 100, // FailedDetect indicates that no buildpacks detected - FailedDetectWithErrors: 101, // FailedDetectWithErrors indicated that no buildpacks detected and at least one errored - DetectError: 102, // DetectError indicates generic detect error - - // analyze phase errors: 200-299 - AnalyzeError: 202, // AnalyzeError indicates generic analyze error - - // restore phase errors: 300-399 - RestoreError: 302, // RestoreError indicates generic restore error - - // build phase errors: 400-499 - FailedBuildWithErrors: 401, // FailedBuildWithErrors indicates buildpack error during /bin/build - BuildError: 402, // BuildError indicates generic build error - - // export phase errors: 500-599 - ExportError: 502, // ExportError indicates generic export error - - // rebase phase errors: 600-699 - RebaseError: 602, // RebaseError indicates generic rebase error - - // launch phase errors: 700-799 - LaunchError: 702, // LaunchError indicates generic launch error - - // generate phase is unsupported on older platforms and shouldn't be reached - FailedGenerateWithErrors: CodeForFailed, - GenerateError: CodeForFailed, - - // extend phase is unsupported on older platforms and shouldn't be reached - ExtendError: CodeForFailed, -} - -func (e *LegacyExiter) CodeFor(errType LifecycleExitError) int { - return codeFor(errType, legacyExitCodes) -} - func codeFor(errType LifecycleExitError, exitCodes map[LifecycleExitError]int) int { if code, ok := exitCodes[errType]; ok { return code diff --git a/platform/launch/exit.go b/platform/launch/exit.go index b4cc82041..85e10269c 100644 --- a/platform/launch/exit.go +++ b/platform/launch/exit.go @@ -12,13 +12,9 @@ type Exiter interface { CodeFor(errType LifecycleExitError) int } -func NewExiter(platformAPI string) Exiter { - switch platformAPI { - case "0.3", "0.4", "0.5": - return &LegacyExiter{} - default: - return &DefaultExiter{} - } +// NewExiter configures a new Exiter according to the provided Platform API version. +func NewExiter(_ string) Exiter { + return &DefaultExiter{} } type DefaultExiter struct{} @@ -32,17 +28,6 @@ func (e *DefaultExiter) CodeFor(errType LifecycleExitError) int { return codeFor(errType, defaultExitCodes) } -type LegacyExiter struct{} - -var legacyExitCodes = map[LifecycleExitError]int{ - // launch phase errors: 700-799 - LaunchError: 702, // LaunchError indicates generic launch error -} - -func (e *LegacyExiter) CodeFor(errType LifecycleExitError) int { - return codeFor(errType, legacyExitCodes) -} - func codeFor(errType LifecycleExitError, exitCodes map[LifecycleExitError]int) int { if code, ok := exitCodes[errType]; ok { return code diff --git a/platform/launch/platform_test.go b/platform/launch/platform_test.go index 0f78be07c..6e172764e 100644 --- a/platform/launch/platform_test.go +++ b/platform/launch/platform_test.go @@ -20,38 +20,15 @@ func TestPlatform(t *testing.T) { func testPlatform(platformAPI *api.Version) func(t *testing.T, when spec.G, it spec.S) { return func(t *testing.T, when spec.G, it spec.S) { when("#NewPlatform", func() { - when("Platform API >= 0.6", func() { - it.Before(func() { - h.SkipIf(t, platformAPI.LessThan("0.6"), "") - }) + it("configures the platform", func() { + foundPlatform := platform.NewPlatform(platformAPI.String()) - it("configures the platform", func() { - foundPlatform := platform.NewPlatform(platformAPI.String()) + t.Log("with a default exiter") + _, ok := foundPlatform.Exiter.(*platform.DefaultExiter) + h.AssertEq(t, ok, true) - t.Log("with a default exiter") - _, ok := foundPlatform.Exiter.(*platform.DefaultExiter) - h.AssertEq(t, ok, true) - - t.Log("with an api") - h.AssertEq(t, foundPlatform.API(), platformAPI) - }) - }) - - when("Platform API < 0.6", func() { - it.Before(func() { - h.SkipIf(t, platformAPI.AtLeast("0.6"), "") - }) - - it("configures the platform", func() { - foundPlatform := platform.NewPlatform(platformAPI.String()) - - t.Log("with a legacy exiter") - _, ok := foundPlatform.Exiter.(*platform.LegacyExiter) - h.AssertEq(t, ok, true) - - t.Log("with an api") - h.AssertEq(t, foundPlatform.API(), platformAPI) - }) + t.Log("with an api") + h.AssertEq(t, foundPlatform.API(), platformAPI) }) }) } diff --git a/platform/lifecycle_inputs.go b/platform/lifecycle_inputs.go index e7cbde28e..81c8e4409 100644 --- a/platform/lifecycle_inputs.go +++ b/platform/lifecycle_inputs.go @@ -150,20 +150,6 @@ func NewLifecycleInputs(platformAPI *api.Version) *LifecycleInputs { ForceRebase: boolEnv(EnvForceRebase), } - if platformAPI.LessThan("0.6") { - // The default location for order.toml is /cnb/order.toml - inputs.OrderPath = envOrDefault(EnvOrderPath, CNBOrderPath) - } - - if platformAPI.LessThan("0.5") { - inputs.AnalyzedPath = envOrDefault(EnvAnalyzedPath, DefaultAnalyzedFile) - inputs.GeneratedDir = envOrDefault(EnvGeneratedDir, DefaultGeneratedDir) - inputs.GroupPath = envOrDefault(EnvGroupPath, DefaultGroupFile) - inputs.PlanPath = envOrDefault(EnvPlanPath, DefaultPlanFile) - inputs.ProjectMetadataPath = envOrDefault(EnvProjectMetadataPath, DefaultProjectMetadataFile) - inputs.ReportPath = envOrDefault(EnvReportPath, DefaultReportFile) - } - return inputs } diff --git a/platform/lifecycle_inputs_test.go b/platform/lifecycle_inputs_test.go index 6e5248538..f857c5827 100644 --- a/platform/lifecycle_inputs_test.go +++ b/platform/lifecycle_inputs_test.go @@ -186,45 +186,6 @@ func testLifecycleInputs(t *testing.T, when spec.G, it spec.S) { h.AssertEq(t, inputs.ProjectMetadataPath, filepath.Join("", "project-metadata.toml")) h.AssertEq(t, inputs.ReportPath, filepath.Join("", "report.toml")) }) - - when("Platform API = 0.5", func() { - platformAPI = api.MustParse("0.5") - - it("expects and writes files in the layers directory", func() { - inputs = platform.NewLifecycleInputs(platformAPI) - - h.AssertEq(t, inputs.AnalyzedPath, filepath.Join("", "analyzed.toml")) - h.AssertEq(t, inputs.GroupPath, filepath.Join("", "group.toml")) - h.AssertEq(t, inputs.PlanPath, filepath.Join("", "plan.toml")) - h.AssertEq(t, inputs.ProjectMetadataPath, filepath.Join("", "project-metadata.toml")) - h.AssertEq(t, inputs.ReportPath, filepath.Join("", "report.toml")) - }) - - it("expects order.toml in the /cnb directory", func() { - inputs = platform.NewLifecycleInputs(platformAPI) - - h.AssertEq(t, inputs.OrderPath, platform.CNBOrderPath) - }) - }) - - when("Platform API < 0.5", func() { - platformAPI = api.MustParse("0.4") - - it("expects and writes files in the working directory", func() { - inputs = platform.NewLifecycleInputs(platformAPI) - - h.AssertEq(t, inputs.AnalyzedPath, "analyzed.toml") - h.AssertEq(t, inputs.GroupPath, "group.toml") - h.AssertEq(t, inputs.PlanPath, "plan.toml") - h.AssertEq(t, inputs.ProjectMetadataPath, "project-metadata.toml") - h.AssertEq(t, inputs.ReportPath, "report.toml") - }) - - it("expects order.toml in the /cnb directory", func() { - inputs = platform.NewLifecycleInputs(platformAPI) - h.AssertEq(t, inputs.OrderPath, platform.CNBOrderPath) - }) - }) }) when("#UpdatePlaceholderPaths", func() { diff --git a/platform/platform_test.go b/platform/platform_test.go index 6ba13c737..02e852282 100644 --- a/platform/platform_test.go +++ b/platform/platform_test.go @@ -20,38 +20,15 @@ func TestPlatform(t *testing.T) { func testPlatform(platformAPI *api.Version) func(t *testing.T, when spec.G, it spec.S) { return func(t *testing.T, when spec.G, it spec.S) { when("#NewPlatformFor", func() { - when("Platform API >= 0.6", func() { - it.Before(func() { - h.SkipIf(t, platformAPI.LessThan("0.6"), "") - }) + it("configures the platform", func() { + foundPlatform := platform.NewPlatformFor(platformAPI.String()) - it("configures the platform", func() { - foundPlatform := platform.NewPlatformFor(platformAPI.String()) + t.Log("with a default exiter") + _, ok := foundPlatform.Exiter.(*platform.DefaultExiter) + h.AssertEq(t, ok, true) - t.Log("with a default exiter") - _, ok := foundPlatform.Exiter.(*platform.DefaultExiter) - h.AssertEq(t, ok, true) - - t.Log("with an api") - h.AssertEq(t, foundPlatform.API(), platformAPI) - }) - }) - - when("Platform API < 0.6", func() { - it.Before(func() { - h.SkipIf(t, platformAPI.AtLeast("0.6"), "") - }) - - it("configures the platform", func() { - foundPlatform := platform.NewPlatformFor(platformAPI.String()) - - t.Log("with a legacy exiter") - _, ok := foundPlatform.Exiter.(*platform.LegacyExiter) - h.AssertEq(t, ok, true) - - t.Log("with an api") - h.AssertEq(t, foundPlatform.API(), platformAPI) - }) + t.Log("with an api") + h.AssertEq(t, foundPlatform.API(), platformAPI) }) }) } diff --git a/platform/resolve_analyze_inputs_test.go b/platform/resolve_analyze_inputs_test.go index a9dc2e729..4f4b560fb 100644 --- a/platform/resolve_analyze_inputs_test.go +++ b/platform/resolve_analyze_inputs_test.go @@ -83,7 +83,6 @@ func testResolveAnalyzeInputs(platformAPI string) func(t *testing.T, when spec.G when("Platform API 0.7 to 0.11", func() { it.Before(func() { - h.SkipIf(t, api.MustParse(platformAPI).LessThan("0.7"), "") h.SkipIf(t, api.MustParse(platformAPI).AtLeast("0.12"), "") inputs.RunImageRef = "some-run-image" // satisfy validation }) @@ -121,54 +120,22 @@ func testResolveAnalyzeInputs(platformAPI string) func(t *testing.T, when spec.G }) }) - when("Platform API >= 0.7", func() { + when("provided destination tags are on different registries", func() { it.Before(func() { - h.SkipIf(t, api.MustParse(platformAPI).LessThan("0.7"), "") inputs.RunImageRef = "some-run-image" // satisfy validation - inputs.UseDaemon = false + inputs.UseDaemon = false // force this particular validation }) - when("provided destination tags are on different registries", func() { - it("errors", func() { - inputs.AdditionalTags = str.Slice{ - "some-registry.io/some-namespace/some-image:tag", - "some-other-registry.io/some-namespace/some-image", - } - inputs.OutputImageRef = "some-registry.io/some-namespace/some-image" - err := platform.ResolveInputs(platform.Analyze, inputs, logger) - h.AssertNotNil(t, err) - expected := "writing to multiple registries is unsupported" - h.AssertStringContains(t, err.Error(), expected) - }) - }) - }) - - when("Platform API < 0.7", func() { - it.Before(func() { - h.SkipIf(t, api.MustParse(platformAPI).AtLeast("0.7"), "") - }) - - when("cache image tag and cache directory are both blank", func() { - it("warns", func() { - inputs.CacheImageRef = "" - inputs.CacheDir = "" - err := platform.ResolveInputs(platform.Analyze, inputs, logger) - h.AssertNil(t, err) - expected := "No cached data will be used, no cache specified." - h.AssertLogEntry(t, logHandler, expected) - }) - }) - - when("run image", func() { - when("not provided", func() { - it("does not warn", func() { - inputs.StackPath = "not-exist-stack.toml" - err := platform.ResolveInputs(platform.Analyze, inputs, logger) - h.AssertNil(t, err) - h.AssertNoLogEntry(t, logHandler, `no stack metadata found at path ''`) - h.AssertNoLogEntry(t, logHandler, `Previous image with name "" not found`) - }) - }) + it("errors", func() { + inputs.AdditionalTags = str.Slice{ + "some-registry.io/some-namespace/some-image:tag", + "some-other-registry.io/some-namespace/some-image", + } + inputs.OutputImageRef = "some-registry.io/some-namespace/some-image" + err := platform.ResolveInputs(platform.Analyze, inputs, logger) + h.AssertNotNil(t, err) + expected := "writing to multiple registries is unsupported" + h.AssertStringContains(t, err.Error(), expected) }) }) } diff --git a/platform/resolve_create_inputs_test.go b/platform/resolve_create_inputs_test.go index 2466ebeea..51d8fbc0e 100644 --- a/platform/resolve_create_inputs_test.go +++ b/platform/resolve_create_inputs_test.go @@ -83,7 +83,6 @@ func testResolveCreateInputs(platformAPI string) func(t *testing.T, when spec.G, when("Platform API 0.7 to 0.11", func() { it.Before(func() { - h.SkipIf(t, api.MustParse(platformAPI).LessThan("0.7"), "") h.SkipIf(t, api.MustParse(platformAPI).AtLeast("0.12"), "") }) @@ -120,9 +119,8 @@ func testResolveCreateInputs(platformAPI string) func(t *testing.T, when spec.G, }) }) - when("Platform API >= 0.7", func() { + when("using a registry", func() { it.Before(func() { - h.SkipIf(t, api.MustParse(platformAPI).LessThan("0.7"), "") inputs.UseDaemon = false }) @@ -140,34 +138,5 @@ func testResolveCreateInputs(platformAPI string) func(t *testing.T, when spec.G, }) }) }) - - when("Platform API < 0.7", func() { - it.Before(func() { - h.SkipIf(t, api.MustParse(platformAPI).AtLeast("0.7"), "") - }) - - when("cache image tag and cache directory are both blank", func() { - it("warns", func() { - inputs.CacheImageRef = "" - inputs.CacheDir = "" - err := platform.ResolveInputs(platform.Create, inputs, logger) - h.AssertNil(t, err) - expected := "No cached data will be used, no cache specified." - h.AssertLogEntry(t, logHandler, expected) - }) - }) - - when("run image", func() { - when("not provided", func() { - it("does not warn", func() { - inputs.StackPath = "not-exist-stack.toml" - err := platform.ResolveInputs(platform.Create, inputs, logger) - h.AssertNil(t, err) - h.AssertNoLogEntry(t, logHandler, `no stack metadata found at path ''`) - h.AssertNoLogEntry(t, logHandler, `Previous image with name "" not found`) - }) - }) - }) - }) } } diff --git a/platform/resolve_inputs.go b/platform/resolve_inputs.go index 45f735b2e..743784ee5 100644 --- a/platform/resolve_inputs.go +++ b/platform/resolve_inputs.go @@ -25,9 +25,6 @@ func ResolveInputs(phase LifecyclePhase, i *LifecycleInputs, logger log.Logger) ops := []LifecycleInputsOperation{UpdatePlaceholderPaths, ResolveAbsoluteDirPaths} switch phase { case Analyze: - if i.PlatformAPI.LessThan("0.7") { - ops = append(ops, CheckCache) - } ops = append(ops, FillAnalyzeImages, ValidateOutputImageProvided, @@ -101,9 +98,6 @@ func FillAnalyzeImages(i *LifecycleInputs, logger log.Logger) error { if i.PreviousImageRef == "" { i.PreviousImageRef = i.OutputImageRef } - if i.PlatformAPI.LessThan("0.7") { - return nil - } if i.PlatformAPI.LessThan("0.12") { return fillRunImageFromStackTOMLIfNeeded(i, logger) } @@ -128,36 +122,21 @@ func FillCreateImages(i *LifecycleInputs, logger log.Logger) error { } func FillExportRunImage(i *LifecycleInputs, logger log.Logger) error { - supportsRunImageFlag := i.PlatformAPI.LessThan("0.7") - if supportsRunImageFlag { - switch { - case i.DeprecatedRunImageRef != "" && i.RunImageRef != os.Getenv(EnvRunImage): - return errors.New(ErrSupplyOnlyOneRunImage) - case i.RunImageRef != "": - return nil - case i.DeprecatedRunImageRef != "": - i.RunImageRef = i.DeprecatedRunImageRef - return nil - default: - return fillRunImageFromStackTOMLIfNeeded(i, logger) + switch { + case i.RunImageRef != "" && i.RunImageRef != os.Getenv(EnvRunImage): + return errors.New(ErrRunImageUnsupported) + case i.DeprecatedRunImageRef != "": + return errors.New(ErrImageUnsupported) + default: + analyzedMD, err := files.ReadAnalyzed(i.AnalyzedPath, logger) + if err != nil { + return err } - } else { - switch { - case i.RunImageRef != "" && i.RunImageRef != os.Getenv(EnvRunImage): - return errors.New(ErrRunImageUnsupported) - case i.DeprecatedRunImageRef != "": - return errors.New(ErrImageUnsupported) - default: - analyzedMD, err := files.ReadAnalyzed(i.AnalyzedPath, logger) - if err != nil { - return err - } - if analyzedMD.RunImage.Reference == "" { - return errors.New("run image not found in analyzed metadata") - } - i.RunImageRef = analyzedMD.RunImage.Reference - return nil + if analyzedMD.RunImage.Reference == "" { + return errors.New("run image not found in analyzed metadata") } + i.RunImageRef = analyzedMD.RunImage.Reference + return nil } } diff --git a/rebaser.go b/rebaser.go index adf52fe1e..76a70f186 100644 --- a/rebaser.go +++ b/rebaser.go @@ -135,11 +135,6 @@ func (r *Rebaser) Rebase(workingImage imgutil.Image, newBaseImage imgutil.Image, if err != nil { return RebaseReport{}, err } - if !r.supportsManifestSize() { - // unset manifest size in report.toml for old platform API versions - report.Image.ManifestSize = 0 - } - return report, err } @@ -243,7 +238,3 @@ func (r *Rebaser) validateTarget(appImg imgutil.Image, newBaseImg imgutil.Image) } return nil } - -func (r *Rebaser) supportsManifestSize() bool { - return r.PlatformAPI.AtLeast("0.6") -} diff --git a/rebaser_test.go b/rebaser_test.go index 32b41cfb7..3337dce95 100644 --- a/rebaser_test.go +++ b/rebaser_test.go @@ -418,53 +418,31 @@ func testRebaser(t *testing.T, when spec.G, it spec.S) { when("checking the image manifest", func() { var fakeRemoteManifestSize int64 - when("platform API < 0.6", func() { + when("image has a manifest", func() { it.Before(func() { - rebaser.PlatformAPI = api.MustParse("0.5") + fakeRemoteManifestSize = 12345 + fakeAppImage.SetManifestSize(fakeRemoteManifestSize) }) - when("image has a manifest", func() { - it.Before(func() { - fakeRemoteManifestSize = 12345 - fakeAppImage.SetManifestSize(fakeRemoteManifestSize) - }) - - it("doesn't set the manifest size in the report.toml", func() { - report, err := rebaser.Rebase(fakeAppImage, fakeNewBaseImage, fakeAppImage.Name(), additionalNames) - h.AssertNil(t, err) + it("add the manifest size to the report", func() { + report, err := rebaser.Rebase(fakeAppImage, fakeNewBaseImage, fakeAppImage.Name(), additionalNames) + h.AssertNil(t, err) - h.AssertEq(t, report.Image.ManifestSize, int64(0)) - }) + h.AssertEq(t, report.Image.ManifestSize, fakeRemoteManifestSize) }) }) - when("platform API >= 0.6", func() { - when("image has a manifest", func() { - it.Before(func() { - fakeRemoteManifestSize = 12345 - fakeAppImage.SetManifestSize(fakeRemoteManifestSize) - }) - - it("add the manifest size to the report", func() { - report, err := rebaser.Rebase(fakeAppImage, fakeNewBaseImage, fakeAppImage.Name(), additionalNames) - h.AssertNil(t, err) - - h.AssertEq(t, report.Image.ManifestSize, fakeRemoteManifestSize) - }) + when("image doesn't have a manifest", func() { + it.Before(func() { + fakeRemoteManifestSize = 0 + fakeAppImage.SetManifestSize(fakeRemoteManifestSize) }) - when("image doesn't have a manifest", func() { - it.Before(func() { - fakeRemoteManifestSize = 0 - fakeAppImage.SetManifestSize(fakeRemoteManifestSize) - }) - - it("doesn't set the manifest size in the report.toml", func() { - report, err := rebaser.Rebase(fakeAppImage, fakeNewBaseImage, fakeAppImage.Name(), additionalNames) - h.AssertNil(t, err) + it("doesn't set the manifest size in the report.toml", func() { + report, err := rebaser.Rebase(fakeAppImage, fakeNewBaseImage, fakeAppImage.Name(), additionalNames) + h.AssertNil(t, err) - h.AssertEq(t, report.Image.ManifestSize, int64(0)) - }) + h.AssertEq(t, report.Image.ManifestSize, int64(0)) }) }) }) diff --git a/restorer.go b/restorer.go index 13064f03d..4bf29c60c 100644 --- a/restorer.go +++ b/restorer.go @@ -11,6 +11,7 @@ import ( "github.com/buildpacks/lifecycle/internal/layer" "github.com/buildpacks/lifecycle/layers" "github.com/buildpacks/lifecycle/log" + "github.com/buildpacks/lifecycle/platform" "github.com/buildpacks/lifecycle/platform/files" ) @@ -19,8 +20,8 @@ type Restorer struct { Logger log.Logger Buildpacks []buildpack.GroupElement - LayerMetadataRestorer layer.MetadataRestorer // Platform API >= 0.7 - LayersMetadata files.LayersMetadata // Platform API >= 0.7 + LayerMetadataRestorer layer.MetadataRestorer + LayersMetadata files.LayersMetadata PlatformAPI *api.Version SBOMRestorer layer.SBOMRestorer } @@ -34,13 +35,10 @@ func (r *Restorer) Restore(cache Cache) error { return err } - useShaFiles := !r.restoresLayerMetadata() - layerSHAStore := layer.NewSHAStore(useShaFiles) - if r.restoresLayerMetadata() { - r.Logger.Debug("Restoring Layer Metadata") - if err := r.LayerMetadataRestorer.Restore(r.Buildpacks, r.LayersMetadata, cacheMeta, layerSHAStore); err != nil { - return err - } + layerSHAStore := layer.NewSHAStore() + r.Logger.Debug("Restoring Layer Metadata") + if err := r.LayerMetadataRestorer.Restore(r.Buildpacks, r.LayersMetadata, cacheMeta, layerSHAStore); err != nil { + return err } var g errgroup.Group @@ -113,10 +111,6 @@ func (r *Restorer) Restore(cache Cache) error { return nil } -func (r *Restorer) restoresLayerMetadata() bool { - return r.PlatformAPI.AtLeast("0.7") -} - func (r *Restorer) restoreCacheLayer(cache Cache, sha string) error { // Sanity check to prevent panic. if cache == nil { @@ -131,3 +125,22 @@ func (r *Restorer) restoreCacheLayer(cache Cache, sha string) error { return layers.Extract(rc, "") } + +func retrieveCacheMetadata(fromCache Cache, logger log.Logger) (platform.CacheMetadata, error) { + // Create empty cache metadata in case a usable cache is not provided. + var cacheMeta platform.CacheMetadata + if fromCache != nil { + var err error + if !fromCache.Exists() { + logger.Info("Layer cache not found") + } + cacheMeta, err = fromCache.RetrieveMetadata() + if err != nil { + return cacheMeta, errors.Wrap(err, "retrieving cache metadata") + } + } else { + logger.Debug("Usable cache not provided, using empty cache metadata") + } + + return cacheMeta, nil +} diff --git a/restorer_test.go b/restorer_test.go index 441f88431..0cef4b599 100644 --- a/restorer_test.go +++ b/restorer_test.go @@ -97,9 +97,6 @@ func testRestorer(buildpackAPI, platformAPI string) func(t *testing.T, when spec when("there is a cache=true layer", func() { it.Before(func() { var meta, sha string - if api.MustParse(platformAPI).LessThan("0.7") { - sha = "cache-only-layer-sha" - } h.AssertNil(t, writeLayer(layersDir, "buildpack.id", "cache-true", meta, sha)) h.AssertNil(t, restorer.Restore(nil)) }) @@ -112,9 +109,6 @@ func testRestorer(buildpackAPI, platformAPI string) func(t *testing.T, when spec when("there is a cache=false layer", func() { it.Before(func() { var meta, sha string - if api.MustParse(platformAPI).LessThan("0.7") { - sha = "cache-false-layer-sha" - } h.AssertNil(t, writeLayer(layersDir, "buildpack.id", "cache-false", meta, sha)) h.AssertNil(t, restorer.Restore(testCache)) }) @@ -123,11 +117,6 @@ func testRestorer(buildpackAPI, platformAPI string) func(t *testing.T, when spec h.AssertPathExists(t, filepath.Join(layersDir, "buildpack.id", "cache-false.toml")) }) - it("keeps sha file", func() { - h.SkipIf(t, api.MustParse(platformAPI).AtLeast("0.7"), "sha file isn't created") - h.AssertPathExists(t, filepath.Join(layersDir, "buildpack.id", "cache-false.sha")) - }) - it("does not restore layer data", func() { h.AssertPathDoesNotExist(t, filepath.Join(layersDir, "buildpack.id", "cache-false")) }) @@ -138,9 +127,6 @@ func testRestorer(buildpackAPI, platformAPI string) func(t *testing.T, when spec when("there is a cache=true layer", func() { it.Before(func() { var meta, sha string - if api.MustParse(platformAPI).LessThan("0.7") { - sha = "cache-only-layer-sha" - } h.AssertNil(t, writeLayer(layersDir, "buildpack.id", "cache-true", meta, sha)) h.AssertNil(t, restorer.Restore(testCache)) }) @@ -153,9 +139,6 @@ func testRestorer(buildpackAPI, platformAPI string) func(t *testing.T, when spec when("there is a cache=false layer", func() { it.Before(func() { var meta, sha string - if api.MustParse(platformAPI).LessThan("0.7") { - sha = "cache-false-layer-sha" - } h.AssertNil(t, writeLayer(layersDir, "buildpack.id", "cache-false", meta, sha)) h.AssertNil(t, restorer.Restore(testCache)) }) @@ -164,11 +147,6 @@ func testRestorer(buildpackAPI, platformAPI string) func(t *testing.T, when spec h.AssertPathExists(t, filepath.Join(layersDir, "buildpack.id", "cache-false.toml")) }) - it("keeps sha file", func() { - h.SkipIf(t, api.MustParse(platformAPI).AtLeast("0.7"), "sha file isn't created") - h.AssertPathExists(t, filepath.Join(layersDir, "buildpack.id", "cache-false.sha")) - }) - it("does not restore layer data", func() { h.AssertPathDoesNotExist(t, filepath.Join(layersDir, "buildpack.id", "cache-false")) }) @@ -291,9 +269,6 @@ func testRestorer(buildpackAPI, platformAPI string) func(t *testing.T, when spec it.Before(func() { meta += "[metadata]\n cache-only-key = \"cache-only-val\"\n" var sha string - if api.MustParse(platformAPI).LessThan("0.7") { - sha = cacheOnlyLayerSHA - } h.AssertNil(t, writeLayer(layersDir, "buildpack.id", "cache-only", meta, sha)) h.AssertNil(t, restorer.Restore(testCache)) }) @@ -303,12 +278,6 @@ func testRestorer(buildpackAPI, platformAPI string) func(t *testing.T, when spec h.AssertEq(t, string(got), meta) }) - it("keeps layer sha", func() { - h.SkipIf(t, api.MustParse(platformAPI).AtLeast("0.7"), "sha file isn't created") - got := h.MustReadFile(t, filepath.Join(layersDir, "buildpack.id", "cache-only.sha")) - h.AssertEq(t, string(got), cacheOnlyLayerSHA) - }) - it("restores data", func() { got := h.MustReadFile(t, filepath.Join(layersDir, "buildpack.id", "cache-only", "file-from-cache-only-layer")) want := "echo text from cache-only layer\n" @@ -321,9 +290,6 @@ func testRestorer(buildpackAPI, platformAPI string) func(t *testing.T, when spec it.Before(func() { meta = "[metadata]\n cache-false-key = \"cache-false-val\"" var sha string - if api.MustParse(platformAPI).LessThan("0.7") { - sha = cacheFalseLayerSHA - } h.AssertNil(t, writeLayer(layersDir, "buildpack.id", "cache-false", meta, sha)) h.AssertNil(t, restorer.Restore(testCache)) }) @@ -333,12 +299,6 @@ func testRestorer(buildpackAPI, platformAPI string) func(t *testing.T, when spec h.AssertEq(t, string(got), meta) }) - it("keeps layer sha", func() { - h.SkipIf(t, api.MustParse(platformAPI).AtLeast("0.7"), "sha file isn't created") - got := h.MustReadFile(t, filepath.Join(layersDir, "buildpack.id", "cache-false.sha")) - h.AssertEq(t, string(got), cacheFalseLayerSHA) - }) - it("does not restore data", func() { h.AssertPathDoesNotExist(t, filepath.Join(layersDir, "buildpack.id", "cache-false")) }) @@ -349,9 +309,6 @@ func testRestorer(buildpackAPI, platformAPI string) func(t *testing.T, when spec it.Before(func() { otherSHA = "some-made-up-sha" var meta, layerSha string - if api.MustParse(platformAPI).LessThan("0.7") { - layerSha = otherSHA - } h.AssertNil(t, writeLayer(layersDir, "buildpack.id", "cache-launch", meta, layerSha)) appMetaContents := []byte(fmt.Sprintf(`{ @@ -382,11 +339,6 @@ func testRestorer(buildpackAPI, platformAPI string) func(t *testing.T, when spec h.AssertPathDoesNotExist(t, filepath.Join(layersDir, "buildpack.id", "cache-launch.toml")) }) - it("removes sha file", func() { - h.SkipIf(t, api.MustParse(platformAPI).AtLeast("0.7"), "sha file isn't created") - h.AssertPathDoesNotExist(t, filepath.Join(layersDir, "buildpack.id", "cache-launch.sha")) - }) - it("does not restore layer data", func() { h.AssertPathDoesNotExist(t, filepath.Join(layersDir, "buildpack.id", "cache-launch")) expected := "Removing \"buildpack.id:cache-launch\", wrong sha" @@ -399,9 +351,6 @@ func testRestorer(buildpackAPI, platformAPI string) func(t *testing.T, when spec when("there is a cache=true layer not in cache", func() { it.Before(func() { var meta, sha string - if api.MustParse(platformAPI).LessThan("0.7") { - sha = "some-made-up-sha" - } h.AssertNil(t, writeLayer(layersDir, "buildpack.id", "cache-layer-not-in-cache", meta, sha)) h.AssertNil(t, restorer.Restore(testCache)) }) @@ -416,9 +365,6 @@ func testRestorer(buildpackAPI, platformAPI string) func(t *testing.T, when spec it.Before(func() { meta += "[metadata]\n escaped-bp-key = \"escaped-bp-val\"\n" var sha string - if api.MustParse(platformAPI).LessThan("0.7") { - sha = escapedLayerSHA - } h.AssertNil(t, writeLayer(layersDir, "escaped_buildpack_id", "escaped-bp-layer", meta, sha)) h.AssertNil(t, restorer.Restore(testCache)) }) @@ -428,12 +374,6 @@ func testRestorer(buildpackAPI, platformAPI string) func(t *testing.T, when spec h.AssertEq(t, string(got), meta) }) - it("keeps layer sha", func() { - h.SkipIf(t, api.MustParse(platformAPI).AtLeast("0.7"), "sha file isn't created") - got := h.MustReadFile(t, filepath.Join(layersDir, "escaped_buildpack_id", "escaped-bp-layer.sha")) - h.AssertEq(t, string(got), escapedLayerSHA) - }) - it("restores data", func() { got := h.MustReadFile(t, filepath.Join(layersDir, "escaped_buildpack_id", "escaped-bp-layer", "file-from-escaped-bp")) want := "echo text from escaped bp layer\n" @@ -444,9 +384,6 @@ func testRestorer(buildpackAPI, platformAPI string) func(t *testing.T, when spec when("there is a cache=true layer in cache but not in group", func() { it.Before(func() { var meta, sha string - if api.MustParse(platformAPI).LessThan("0.7") { - sha = noGroupLayerSHA - } h.AssertNil(t, writeLayer(layersDir, "nogroup.buildpack.id", "some-layer", meta, sha)) h.AssertNil(t, restorer.Restore(testCache)) }) @@ -465,11 +402,6 @@ func testRestorer(buildpackAPI, platformAPI string) func(t *testing.T, when spec h.AssertPathExists(t, filepath.Join(layersDir, "nogroup.buildpack.id", "some-layer.toml")) }) - it("keeps sha file", func() { - h.SkipIf(t, api.MustParse(platformAPI).AtLeast("0.7"), "sha file isn't created") - h.AssertPathExists(t, filepath.Join(layersDir, "nogroup.buildpack.id", "some-layer.sha")) - }) - it("restores data", func() { got := h.MustReadFile(t, filepath.Join(layersDir, "nogroup.buildpack.id", "some-layer", "file-from-some-layer")) want := "echo text from some layer\n" @@ -484,12 +416,6 @@ func testRestorer(buildpackAPI, platformAPI string) func(t *testing.T, when spec it.Before(func() { var typesMeta, cacheOnlySha, cacheLaunchSha, escapedSha string - if api.MustParse(platformAPI).LessThan("0.7") { - cacheOnlySha = cacheOnlyLayerSHA - cacheLaunchSha = cacheLaunchLayerSHA - escapedSha = escapedLayerSHA - } - cacheOnlyMeta = typesMeta + "[metadata]\n cache-only-key = \"cache-only-val\"\n" h.AssertNil(t, writeLayer(layersDir, "buildpack.id", "cache-only", cacheOnlyMeta, cacheOnlySha)) @@ -532,16 +458,6 @@ func testRestorer(buildpackAPI, platformAPI string) func(t *testing.T, when spec h.AssertEq(t, string(got), escapedMeta) }) - it("keeps layer sha for all layers", func() { - h.SkipIf(t, api.MustParse(platformAPI).AtLeast("0.7"), "sha file isn't created") - got := h.MustReadFile(t, filepath.Join(layersDir, "buildpack.id", "cache-only.sha")) - h.AssertEq(t, string(got), cacheOnlyLayerSHA) - got = h.MustReadFile(t, filepath.Join(layersDir, "buildpack.id", "cache-launch.sha")) - h.AssertEq(t, string(got), cacheLaunchLayerSHA) - got = h.MustReadFile(t, filepath.Join(layersDir, "escaped_buildpack_id", "escaped-bp-layer.sha")) - h.AssertEq(t, string(got), escapedLayerSHA) - }) - it("restores data for all layers", func() { got := h.MustReadFile(t, filepath.Join(layersDir, "buildpack.id", "cache-only", "file-from-cache-only-layer")) want := "echo text from cache-only layer\n"