Skip to content

Commit

Permalink
Adds -run as an input to the analyzer & creator (#1005)
Browse files Browse the repository at this point in the history
- Also adds unit tests for create inputs

Signed-off-by: Natalie Arellano <[email protected]>
  • Loading branch information
natalieparellano authored Feb 13, 2023
1 parent 5382f32 commit 014cceb
Show file tree
Hide file tree
Showing 18 changed files with 462 additions and 79 deletions.
37 changes: 29 additions & 8 deletions acceptance/analyzer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,8 @@ func testAnalyzerFunc(platformAPI string) func(t *testing.T, when spec.G, it spe
})
})

when("group path is provided", func() {
it("uses the provided group path", func() {
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,
Expand Down Expand Up @@ -228,8 +228,8 @@ func testAnalyzerFunc(platformAPI string) func(t *testing.T, when spec.G, it spe
})
})

when("analyzed path is provided", func() {
it("uses the provided analyzed path", func() {
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)
Expand All @@ -256,6 +256,27 @@ func testAnalyzerFunc(platformAPI string) func(t *testing.T, when spec.G, it spe
})
})

when("called with run", func() {
it("uses the provided run.toml path", func() {
h.SkipIf(t, api.MustParse(platformAPI).LessThan("0.12"), "Platform API < 0.12 does not accept -run")
cmd := exec.Command(
"docker", "run", "--rm",
"--env", "CNB_PLATFORM_API="+platformAPI,
"--env", "CNB_REGISTRY_AUTH="+analyzeRegAuthConfig,
"--network", analyzeRegNetwork,
analyzeImage,
ctrPath(analyzerPath),
"-run", "/cnb/run.toml",
analyzeRegFixtures.SomeAppImage,
) // #nosec G204
output, err := cmd.CombinedOutput()

h.AssertNotNil(t, err)
expected := "ensure registry read access to some-run-image-from-run-toml"
h.AssertStringContains(t, string(output), expected)
})
})

it("drops privileges", func() {
h.SkipIf(t, runtime.GOOS == "windows", "Not relevant on Windows")

Expand Down Expand Up @@ -357,7 +378,7 @@ func testAnalyzerFunc(platformAPI string) func(t *testing.T, when spec.G, it spe
})

when("app image exists", func() {
it("does not restore app metadata", 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"}
Expand All @@ -381,7 +402,7 @@ func testAnalyzerFunc(platformAPI string) func(t *testing.T, when spec.G, it spe
assertNoRestoreOfAppMetadata(t, copyDir, output)
})

it("restores app metadata", func() {
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,
Expand Down Expand Up @@ -428,7 +449,7 @@ func testAnalyzerFunc(platformAPI string) func(t *testing.T, when spec.G, it spe
})
})

when("cache is provided", func() {
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() {
Expand Down Expand Up @@ -830,7 +851,7 @@ func testAnalyzerFunc(platformAPI string) func(t *testing.T, when spec.G, it spe
})
})

when("cache is provided", func() {
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() {
Expand Down
21 changes: 21 additions & 0 deletions acceptance/creator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,27 @@ func testCreatorFunc(platformAPI string) func(t *testing.T, when spec.G, it spec
return func(t *testing.T, when spec.G, it spec.S) {
var createdImageName string

when("called with run", func() {
it("uses the provided run.toml path", func() {
h.SkipIf(t, api.MustParse(platformAPI).LessThan("0.12"), "Platform API < 0.12 does not accept -run")
cmd := exec.Command(
"docker", "run", "--rm",
"--env", "CNB_PLATFORM_API="+platformAPI,
"--env", "CNB_REGISTRY_AUTH="+createRegAuthConfig,
"--network", createRegNetwork,
createImage,
ctrPath(creatorPath),
"-run", "/cnb/run.toml",
createRegFixtures.SomeAppImage,
) // #nosec G204
output, err := cmd.CombinedOutput()

h.AssertNotNil(t, err)
expected := "ensure registry read access to some-run-image-from-run-toml"
h.AssertStringContains(t, string(output), expected)
})
})

when("daemon case", func() {
it.After(func() {
h.DockerImageRemove(t, createdImageName)
Expand Down
5 changes: 5 additions & 0 deletions acceptance/testdata/analyzer/container/cnb/run.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[[image]]
image = "some-run-image-from-run-toml"

[[image]]
image = "some-other-run-image"
5 changes: 5 additions & 0 deletions acceptance/testdata/creator/container/cnb/run.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[[image]]
image = "some-run-image-from-run-toml"

[[image]]
image = "some-other-run-image"
2 changes: 1 addition & 1 deletion api/apis.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
)

var (
Platform = newApisMustParse([]string{"0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9", "0.10", "0.11"}, []string{"0.3", "0.4", "0.5", "0.6"})
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"})
Buildpack = newApisMustParse([]string{"0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9"}, []string{"0.2", "0.3", "0.4", "0.5", "0.6"})
)

Expand Down
18 changes: 6 additions & 12 deletions cmd/lifecycle/analyzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,14 @@ type analyzeCmd struct {

// DefineFlags defines the flags that are considered valid and reads their values (if provided).
func (a *analyzeCmd) DefineFlags() {
switch {
case a.PlatformAPI.AtLeast("0.9"):
cli.FlagAnalyzedPath(&a.AnalyzedPath)
cli.FlagCacheImage(&a.CacheImageRef)
cli.FlagGID(&a.GID)
if a.PlatformAPI.AtLeast("0.12") {
cli.FlagRunPath(&a.RunPath)
}
if a.PlatformAPI.AtLeast("0.9") {
cli.FlagLaunchCacheDir(&a.LaunchCacheDir)
cli.FlagLayersDir(&a.LayersDir)
cli.FlagPreviousImage(&a.PreviousImageRef)
cli.FlagRunImage(&a.RunImageRef)
cli.FlagSkipLayers(&a.SkipLayers)
cli.FlagStackPath(&a.StackPath)
cli.FlagTags(&a.AdditionalTags)
cli.FlagUID(&a.UID)
cli.FlagUseDaemon(&a.UseDaemon)
}
switch {
case a.PlatformAPI.AtLeast("0.7"):
cli.FlagAnalyzedPath(&a.AnalyzedPath)
cli.FlagCacheImage(&a.CacheImageRef)
Expand Down
4 changes: 4 additions & 0 deletions cmd/lifecycle/cli/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ func FlagRunImage(runImage *string) {
flagSet.StringVar(runImage, "run-image", *runImage, "reference to run image")
}

func FlagRunPath(runPath *string) {
flagSet.StringVar(runPath, "run", *runPath, "path to run.toml")
}

func FlagSkipLayers(skipLayers *bool) {
flagSet.BoolVar(skipLayers, "skip-layers", *skipLayers, "do not provide layer metadata to buildpacks")
}
Expand Down
3 changes: 3 additions & 0 deletions cmd/lifecycle/creator.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ type createCmd struct {

// DefineFlags defines the flags that are considered valid and reads their values (if provided).
func (c *createCmd) DefineFlags() {
if c.PlatformAPI.AtLeast("0.12") {
cli.FlagRunPath(&c.RunPath)
}
if c.PlatformAPI.AtLeast("0.11") {
cli.FlagBuildConfigDir(&c.BuildConfigDir)
cli.FlagLauncherSBOMDir(&c.LauncherSBOMDir)
Expand Down
2 changes: 1 addition & 1 deletion exporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ func testExporter(t *testing.T, when spec.G, it spec.S) {

it("saves run image metadata to the resulting image", func() {
opts.Stack = platform.StackMetadata{
RunImage: platform.StackRunImageMetadata{
RunImage: platform.RunImageMetadata{
Image: "some/run",
Mirrors: []string{"registry.example.com/some/run", "other.example.com/some/run"},
},
Expand Down
21 changes: 16 additions & 5 deletions platform/analyze_inputs.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ import (
func DefaultAnalyzeInputs(platformAPI *api.Version) LifecycleInputs {
var inputs LifecycleInputs
switch {
case platformAPI.AtLeast("0.9"):
case platformAPI.AtLeast("0.12"):
inputs = defaultAnalyzeInputs()
case platformAPI.AtLeast("0.9"):
inputs = defaultAnalyzeInputs09To011()
case platformAPI.AtLeast("0.7"):
inputs = defaultAnalyzeInputs07()
inputs = defaultAnalyzeInputs07To08()
case platformAPI.AtLeast("0.5"):
inputs = defaultAnalyzeInputs05To06()
default:
Expand All @@ -27,12 +29,18 @@ func DefaultAnalyzeInputs(platformAPI *api.Version) LifecycleInputs {
}

func defaultAnalyzeInputs() LifecycleInputs {
ai := defaultAnalyzeInputs07()
ai := defaultAnalyzeInputs09To011()
ai.RunPath = envOrDefault(EnvRunPath, DefaultRunPath)
return ai
}

func defaultAnalyzeInputs09To011() LifecycleInputs {
ai := defaultAnalyzeInputs07To08()
ai.LaunchCacheDir = os.Getenv(EnvLaunchCacheDir)
return ai
}

func defaultAnalyzeInputs07() LifecycleInputs {
func defaultAnalyzeInputs07To08() LifecycleInputs {
ai := defaultAnalyzeInputs05To06()
ai.AdditionalTags = str.Slice{}
ai.CacheDir = "" // removed
Expand Down Expand Up @@ -72,5 +80,8 @@ func FillAnalyzeImages(i *LifecycleInputs, logger log.Logger) error {
if i.PlatformAPI.LessThan("0.7") {
return nil
}
return fillRunImageFromStackTOMLIfNeeded(i, logger)
if i.PlatformAPI.LessThan("0.12") {
return fillRunImageFromStackTOMLIfNeeded(i, logger)
}
return fillRunImageFromRunTOMLIfNeeded(i, logger)
}
96 changes: 73 additions & 23 deletions platform/analyze_inputs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/sclevine/spec/report"

"github.com/buildpacks/lifecycle/api"
"github.com/buildpacks/lifecycle/internal/path"
"github.com/buildpacks/lifecycle/internal/str"
llog "github.com/buildpacks/lifecycle/log"
"github.com/buildpacks/lifecycle/platform"
Expand Down Expand Up @@ -38,8 +39,51 @@ func testAnalyzeInputs(platformAPI string) func(t *testing.T, when spec.G, it sp
})

when("latest Platform API(s)", func() {
it.Before(func() {
h.SkipIf(t, api.MustParse(platformAPI).LessThan("0.12"), "")
inputs.RunImageRef = "some-run-image" // satisfy validation
})

when("run image", func() {
when("not provided", func() {
it.Before(func() {
inputs.RunImageRef = ""
})

it("falls back to run.toml", func() {
inputs.RunPath = filepath.Join("testdata", "cnb", "run.toml")
err := platform.ResolveInputs(platform.Analyze, &inputs, logger)
h.AssertNil(t, err)
h.AssertEq(t, inputs.RunImageRef, "some-run-image")
})

when("run.toml", func() {
when("not provided", func() {
it("defaults to /cnb/run.toml", func() {
_ = platform.ResolveInputs(platform.Analyze, &inputs, logger)
h.AssertEq(t, inputs.RunPath, filepath.Join(path.RootDir, "cnb", "run.toml"))
})
})

when("not exists", func() {
it("errors", func() {
inputs.RunImageRef = ""
inputs.RunPath = "not-exist-run.toml"
err := platform.ResolveInputs(platform.Analyze, &inputs, logger)
h.AssertNotNil(t, err)
expected := "-run-image is required when there is no run metadata available"
h.AssertStringContains(t, err.Error(), expected)
})
})
})
})
})
})

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
})

Expand All @@ -53,18 +97,34 @@ func testAnalyzeInputs(platformAPI string) func(t *testing.T, when spec.G, it sp
h.AssertEq(t, inputs.RunImageRef, "some-run-image")
})

when("stack.toml not present", func() {
it("errors", func() {
inputs.RunImageRef = ""
inputs.StackPath = "not-exist-stack.toml"
err := platform.ResolveInputs(platform.Analyze, &inputs, logger)
h.AssertNotNil(t, err)
expected := "-run-image is required when there is no stack metadata available"
h.AssertStringContains(t, err.Error(), expected)
when("stack.toml", func() {
when("not provided", func() {
it("defaults to /cnb/stack.toml", func() {
_ = platform.ResolveInputs(platform.Analyze, &inputs, logger)
h.AssertEq(t, inputs.StackPath, filepath.Join(path.RootDir, "cnb", "stack.toml"))
})
})

when("not exists", func() {
it("errors", func() {
inputs.RunImageRef = ""
inputs.StackPath = "not-exist-stack.toml"
err := platform.ResolveInputs(platform.Analyze, &inputs, logger)
h.AssertNotNil(t, err)
expected := "-run-image is required when there is no stack metadata available"
h.AssertStringContains(t, err.Error(), expected)
})
})
})
})
})
})

when("Platform API >= 0.7", func() {
it.Before(func() {
h.SkipIf(t, api.MustParse(platformAPI).LessThan("0.7"), "")
inputs.RunImageRef = "some-run-image" // satisfy validation
})

when("provided destination tags are on different registries", func() {
it("errors", func() {
Expand All @@ -79,15 +139,6 @@ func testAnalyzeInputs(platformAPI string) func(t *testing.T, when spec.G, it sp
h.AssertStringContains(t, err.Error(), expected)
})
})

when("layers directory is provided", func() {
it("writes analyzed.toml at the layers directory", func() {
inputs.LayersDir = "some-layers-dir"
err := platform.ResolveInputs(platform.Analyze, &inputs, logger)
h.AssertNil(t, err)
h.AssertEq(t, inputs.AnalyzedPath, filepath.Join("some-layers-dir", "analyzed.toml"))
})
})
})

when("Platform API < 0.7", func() {
Expand Down Expand Up @@ -119,13 +170,12 @@ func testAnalyzeInputs(platformAPI string) func(t *testing.T, when spec.G, it sp
})
})

when("Platform API 0.5 to 0.6", func() {
when("Platform API >= 0.5", func() {
it.Before(func() {
h.SkipIf(
t,
!(api.MustParse(platformAPI).Equal(api.MustParse("0.5")) || api.MustParse(platformAPI).Equal(api.MustParse("0.6"))),
"",
)
h.SkipIf(t, api.MustParse(platformAPI).LessThan("0.5"), "")
if api.MustParse(platformAPI).AtLeast("0.7") {
inputs.RunImageRef = "some-run-image" // satisfy validation
}
})

when("layers directory is provided", func() {
Expand Down
Loading

0 comments on commit 014cceb

Please sign in to comment.