From 352acebf24775b7e4d903ab20790e54ad2de71b5 Mon Sep 17 00:00:00 2001 From: Ryan Moran Date: Tue, 26 Oct 2021 10:27:15 -0700 Subject: [PATCH] Moves layer types to table --- build.go | 2 +- build_test.go | 47 +++++++++++++++++++++++++++++++++++++++++++++++ layer.go | 49 +++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 87 insertions(+), 11 deletions(-) diff --git a/build.go b/build.go index 64a537df..b497be42 100644 --- a/build.go +++ b/build.go @@ -189,7 +189,7 @@ func Build(f BuildFunc, options ...Option) { } for _, layer := range result.Layers { - err = config.tomlWriter.Write(filepath.Join(layersPath, fmt.Sprintf("%s.toml", layer.Name)), layer) + err = config.tomlWriter.Write(filepath.Join(layersPath, fmt.Sprintf("%s.toml", layer.Name)), formattedLayer{layer, apiVersion}) if err != nil { config.exitHandler.Error(err) return diff --git a/build_test.go b/build_test.go index 30ac0132..927e8581 100644 --- a/build_test.go +++ b/build_test.go @@ -230,6 +230,52 @@ api = "0.4" Expect(err).NotTo(HaveOccurred()) Expect(string(contents)).To(MatchTOML(` +[types] + launch = true + build = true + cache = true + +[metadata] + some-key = "some-value" +`)) + }) + + context("when the buildpack api version is less than 0.6", func() { + it.Before(func() { + bpTOML := []byte(` +api = "0.5" +[buildpack] + id = "some-id" + name = "some-name" + version = "some-version" +`) + Expect(os.WriteFile(filepath.Join(cnbDir, "buildpack.toml"), bpTOML, 0600)).To(Succeed()) + }) + it("persists layer metadata", func() { + packit.Build(func(ctx packit.BuildContext) (packit.BuildResult, error) { + layerPath := filepath.Join(ctx.Layers.Path, "some-layer") + Expect(os.MkdirAll(layerPath, os.ModePerm)).To(Succeed()) + + return packit.BuildResult{ + Layers: []packit.Layer{ + packit.Layer{ + Path: layerPath, + Name: "some-layer", + Build: true, + Launch: true, + Cache: true, + Metadata: map[string]interface{}{ + "some-key": "some-value", + }, + }, + }, + }, nil + }, packit.WithArgs([]string{binaryPath, layersDir, platformDir, planPath})) + + contents, err := os.ReadFile(filepath.Join(layersDir, "some-layer.toml")) + Expect(err).NotTo(HaveOccurred()) + + Expect(string(contents)).To(MatchTOML(` launch = true build = true cache = true @@ -237,6 +283,7 @@ cache = true [metadata] some-key = "some-value" `)) + }) }) context("when there are existing layer.toml files", func() { diff --git a/layer.go b/layer.go index 06335d4d..cb722f8a 100644 --- a/layer.go +++ b/layer.go @@ -3,6 +3,9 @@ package packit import ( "fmt" "os" + + "github.com/Masterminds/semver/v3" + "github.com/pelletier/go-toml" ) // Layer provides a representation of a layer managed by a buildpack as @@ -10,48 +13,48 @@ import ( // https://github.com/buildpacks/spec/blob/main/buildpack.md#layers. type Layer struct { // Path is the absolute location of the layer on disk. - Path string `toml:"-"` + Path string // Name is the descriptive name of the layer. - Name string `toml:"-"` + Name string // Build indicates whether the layer is available to subsequent buildpacks // during their build phase according to the specification: // https://github.com/buildpacks/spec/blob/main/buildpack.md#build-layers. - Build bool `toml:"build"` + Build bool // Launch indicates whether the layer is exported into the application image // and made available during the launch phase according to the specification: // https://github.com/buildpacks/spec/blob/main/buildpack.md#launch-layers. - Launch bool `toml:"launch"` + Launch bool // Cache indicates whether the layer is persisted and made available to // subsequent builds of the same application according to the specification: // https://github.com/buildpacks/spec/blob/main/buildpack.md#launch-layers // and // https://github.com/buildpacks/spec/blob/main/buildpack.md#build-layers. - Cache bool `toml:"cache"` + Cache bool // SharedEnv is the set of environment variables attached to the layer and // made available during both the build and launch phases according to the // specification: // https://github.com/buildpacks/spec/blob/main/buildpack.md#provided-by-the-buildpacks. - SharedEnv Environment `toml:"-"` + SharedEnv Environment // BuildEnv is the set of environment variables attached to the layer and // made available during the build phase according to the specification: // https://github.com/buildpacks/spec/blob/main/buildpack.md#provided-by-the-buildpacks. - BuildEnv Environment `toml:"-"` + BuildEnv Environment // LaunchEnv is the set of environment variables attached to the layer and // made available during the launch phase according to the specification: // https://github.com/buildpacks/spec/blob/main/buildpack.md#provided-by-the-buildpacks. - LaunchEnv Environment `toml:"-"` + LaunchEnv Environment // ProcessLaunchEnv is a map of environment variables attached to the layer and // made available to specified proccesses in the launch phase accoring to the specification: // https://github.com/buildpacks/spec/blob/main/buildpack.md#provided-by-the-buildpacks - ProcessLaunchEnv map[string]Environment `toml:"-"` + ProcessLaunchEnv map[string]Environment // Metadata is an unspecified field allowing buildpacks to communicate extra // details about the layer. Examples of this type of metadata might include @@ -60,7 +63,7 @@ type Layer struct { // layer if suitable. The Metadata field ultimately fills the metadata field // of the Layer Content Metadata TOML file according to the specification: // https://github.com/buildpacks/spec/blob/main/buildpack.md#layer-content-metadata-toml. - Metadata map[string]interface{} `toml:"metadata"` + Metadata map[string]interface{} } // Reset clears the state of a layer such that the layer can be replaced with @@ -89,3 +92,29 @@ func (l Layer) Reset() (Layer, error) { return l, nil } + +type formattedLayer struct { + layer Layer + api *semver.Version +} + +func (l formattedLayer) MarshalTOML() ([]byte, error) { + layer := map[string]interface{}{ + "metadata": l.layer.Metadata, + } + + apiV06, _ := semver.NewVersion("0.6") + if l.api.LessThan(apiV06) { + layer["build"] = l.layer.Build + layer["launch"] = l.layer.Launch + layer["cache"] = l.layer.Cache + } else { + layer["types"] = map[string]bool{ + "build": l.layer.Build, + "launch": l.layer.Launch, + "cache": l.layer.Cache, + } + } + + return toml.Marshal(layer) +}