diff --git a/build.go b/build.go index 4ce43c8..fe54b3e 100644 --- a/build.go +++ b/build.go @@ -57,6 +57,12 @@ type BuildContext struct { // Deprecated: StackID is the ID of the stack. StackID string + + // TargetInfo contains info of the target (os, arch, ...). + TargetInfo TargetInfo + + // TargetDistro is the target distribution (name, version). + TargetDistro TargetDistro } // BuildResult contains the results of detection. @@ -231,6 +237,19 @@ func Build(build BuildFunc, config Config) { config.logger.Debugf("Stack: %s", ctx.StackID) } + if API.GreaterThan(semver.MustParse("0.9")) { + ctx.TargetInfo = TargetInfo{} + ctx.TargetInfo.OS, _ = os.LookupEnv(EnvTargetOS) + ctx.TargetInfo.Arch, _ = os.LookupEnv(EnvTargetArch) + ctx.TargetInfo.Variant, _ = os.LookupEnv(EnvTargetArchVariant) + config.logger.Debugf("System: %+v", ctx.TargetInfo) + + ctx.TargetDistro = TargetDistro{} + ctx.TargetDistro.Name, _ = os.LookupEnv(EnvTargetDistroName) + ctx.TargetDistro.Version, _ = os.LookupEnv(EnvTargetDistroVersion) + config.logger.Debugf("Distro: %+v", ctx.TargetDistro) + } + result, err := build(ctx) if err != nil { config.exitHandler.Error(err) diff --git a/build_test.go b/build_test.go index 18ff429..730ca5e 100644 --- a/build_test.go +++ b/build_test.go @@ -165,6 +165,12 @@ test-key = "test-value" Expect(os.Setenv("CNB_PLATFORM_DIR", platformPath)).To(Succeed()) Expect(os.Setenv("CNB_BP_PLAN_PATH", buildpackPlanPath)).To(Succeed()) + Expect(os.Setenv("CNB_TARGET_OS", "linux")).To(Succeed()) + Expect(os.Setenv("CNB_TARGET_ARCH", "arm")).To(Succeed()) + Expect(os.Setenv("CNB_TARGET_ARCH_VARIANT", "v6")).To(Succeed()) + Expect(os.Setenv("CNB_TARGET_DISTRO_NAME", "ubuntu")).To(Succeed()) + Expect(os.Setenv("CNB_TARGET_DISTRO_VERSION", "24.04")).To(Succeed()) + workingDir, err = os.Getwd() Expect(err).NotTo(HaveOccurred()) Expect(os.Chdir(applicationPath)).To(Succeed()) @@ -178,6 +184,12 @@ test-key = "test-value" Expect(os.Unsetenv("CNB_BP_PLAN_PATH")).To(Succeed()) Expect(os.Unsetenv("CNB_LAYERS_DIR")).To(Succeed()) + Expect(os.Unsetenv("CNB_TARGET_OS")) + Expect(os.Unsetenv("CNB_TARGET_ARCH")) + Expect(os.Unsetenv("CNB_TARGET_ARCH_VARIANT")) + Expect(os.Unsetenv("CNB_TARGET_DISTRO_NAME")) + Expect(os.Unsetenv("CNB_TARGET_DISTRO_VERSION")) + Expect(os.RemoveAll(applicationPath)).To(Succeed()) Expect(os.RemoveAll(buildpackPath)).To(Succeed()) Expect(os.RemoveAll(buildpackPlanPath)).To(Succeed()) @@ -360,7 +372,9 @@ version = "1.1.1" it("provides target information", func() { libcnb.Build(buildFunc, libcnb.NewConfig( - libcnb.WithArguments([]string{commandPath})), + libcnb.WithArguments([]string{commandPath}), + libcnb.WithLogger(log.New(os.Stdout)), + ), ) Expect(ctx.Buildpack.Targets).To(HaveLen(2)) @@ -372,6 +386,12 @@ version = "1.1.1" Expect(ctx.Buildpack.Targets[0].Distros[1].Name).To(Equal("debian")) Expect(ctx.Buildpack.Targets[1].Variant).To(Equal("v6")) + + Expect(ctx.TargetInfo.OS).To(Equal("linux")) + Expect(ctx.TargetInfo.Arch).To(Equal("arm")) + Expect(ctx.TargetInfo.Variant).To(Equal("v6")) + Expect(ctx.TargetDistro.Name).To(Equal("ubuntu")) + Expect(ctx.TargetDistro.Version).To(Equal("24.04")) }) }) diff --git a/buildpack.go b/buildpack.go index bc1f73f..d6195d9 100644 --- a/buildpack.go +++ b/buildpack.go @@ -85,8 +85,8 @@ type BuildpackStack struct { Mixins []string `toml:"mixins"` } -// BuildpackTargetDistro is the supported target distro -type BuildpackTargetDistro struct { +// TargetDistro is the supported target distro +type TargetDistro struct { // Name is the name of the supported distro. Name string `toml:"name"` @@ -94,8 +94,8 @@ type BuildpackTargetDistro struct { Version string `toml:"version"` } -// BuildpackTarget is a target supported by the buildpack. -type BuildpackTarget struct { +// TargetInfo is the supported target +type TargetInfo struct { // OS is the supported os. OS string `toml:"os"` @@ -104,9 +104,14 @@ type BuildpackTarget struct { // Variant is the supported variant of the architecture. Variant string `toml:"variant"` +} + +// Target is a target supported by the buildpack. +type Target struct { + TargetInfo // Distros is the collection of distros associated with the target. - Distros []BuildpackTargetDistro `toml:"distros"` + Distros []TargetDistro `toml:"distros"` } // Buildpack is the contents of the buildpack.toml file. @@ -124,7 +129,7 @@ type Buildpack struct { Stacks []BuildpackStack `toml:"stacks"` // Targets is the collection of targets supported by the buildpack. - Targets []BuildpackTarget `toml:"targets"` + Targets []Target `toml:"targets"` // Metadata is arbitrary metadata attached to the buildpack. Metadata map[string]interface{} `toml:"metadata"` diff --git a/extension.go b/extension.go index 763ede1..d100799 100644 --- a/extension.go +++ b/extension.go @@ -51,6 +51,9 @@ type Extension struct { // Path is the path to the extension. Path string `toml:"-"` + // Targets is the collection of targets supported by the buildpack. + Targets []Target `toml:"targets"` + // Metadata is arbitrary metadata attached to the extension. Metadata map[string]interface{} `toml:"metadata"` } diff --git a/generate.go b/generate.go index 407a554..635373e 100644 --- a/generate.go +++ b/generate.go @@ -50,6 +50,12 @@ type GenerateContext struct { // Platform is the contents of the platform. Platform Platform + // TargetInfo contains info of the target (os, arch, ...). + TargetInfo TargetInfo + + // TargetDistro is the target distribution (name, version). + TargetDistro TargetDistro + // Deprecated: StackID is the ID of the stack. StackID string } @@ -184,6 +190,19 @@ func Generate(generate GenerateFunc, config Config) { config.logger.Debugf("Stack: %s", ctx.StackID) } + if API.GreaterThan(semver.MustParse("0.9")) { + ctx.TargetInfo = TargetInfo{} + ctx.TargetInfo.OS, _ = os.LookupEnv(EnvTargetOS) + ctx.TargetInfo.Arch, _ = os.LookupEnv(EnvTargetArch) + ctx.TargetInfo.Variant, _ = os.LookupEnv(EnvTargetArchVariant) + config.logger.Debugf("System: %+v", ctx.TargetInfo) + + ctx.TargetDistro = TargetDistro{} + ctx.TargetDistro.Name, _ = os.LookupEnv(EnvTargetDistroName) + ctx.TargetDistro.Version, _ = os.LookupEnv(EnvTargetDistroVersion) + config.logger.Debugf("Distro: %+v", ctx.TargetDistro) + } + result, err := generate(ctx) if err != nil { config.exitHandler.Error(err) diff --git a/generate_test.go b/generate_test.go index 54a77d2..1ec6403 100644 --- a/generate_test.go +++ b/generate_test.go @@ -76,8 +76,8 @@ api = "{{.APIVersion}}" id = "test-id" name = "test-name" version = "1.1.1" -description = "A test buildpack" -keywords = ["test", "buildpack"] +description = "A test extension" +keywords = ["test", "extension"] [[extension.licenses]] type = "Apache-2.0" @@ -147,6 +147,12 @@ test-key = "test-value" Expect(os.Setenv("CNB_PLATFORM_DIR", platformPath)).To(Succeed()) Expect(os.Setenv("CNB_BP_PLAN_PATH", buildpackPlanPath)).To(Succeed()) + Expect(os.Setenv("CNB_TARGET_OS", "linux")).To(Succeed()) + Expect(os.Setenv("CNB_TARGET_ARCH", "arm")).To(Succeed()) + Expect(os.Setenv("CNB_TARGET_ARCH_VARIANT", "v6")).To(Succeed()) + Expect(os.Setenv("CNB_TARGET_DISTRO_NAME", "ubuntu")).To(Succeed()) + Expect(os.Setenv("CNB_TARGET_DISTRO_VERSION", "24.04")).To(Succeed()) + workingDir, err = os.Getwd() Expect(err).NotTo(HaveOccurred()) Expect(os.Chdir(applicationPath)).To(Succeed()) @@ -160,6 +166,12 @@ test-key = "test-value" Expect(os.Unsetenv("CNB_BP_PLAN_PATH")).To(Succeed()) Expect(os.Unsetenv("CNB_OUTPUT_DIR")).To(Succeed()) + Expect(os.Unsetenv("CNB_TARGET_OS")) + Expect(os.Unsetenv("CNB_TARGET_ARCH")) + Expect(os.Unsetenv("CNB_TARGET_ARCH_VARIANT")) + Expect(os.Unsetenv("CNB_TARGET_DISTRO_NAME")) + Expect(os.Unsetenv("CNB_TARGET_DISTRO_VERSION")) + Expect(os.RemoveAll(applicationPath)).To(Succeed()) Expect(os.RemoveAll(extensionPath)).To(Succeed()) Expect(os.RemoveAll(buildpackPlanPath)).To(Succeed()) @@ -300,6 +312,69 @@ version = "1.1.1" }) }) + context("has a build environment specifying target metadata", func() { + var ctx libcnb.GenerateContext + + it.Before(func() { + Expect(os.WriteFile(filepath.Join(extensionPath, "extension.toml"), + []byte(` + api = "0.10" + + [extension] + id = "test-id" + name = "test-name" + version = "1.1.1" + + [[targets]] + os = "linux" + arch = "amd64" + + [[targets.distros]] + name = "ubuntu" + version = "18.04" + + [[targets.distros]] + name = "debian" + + [[targets]] + os = "linux" + arch = "arm" + variant = "v6" + `), 0600), + ).To(Succeed()) + + generateFunc = func(context libcnb.GenerateContext) (libcnb.GenerateResult, error) { + ctx = context + return libcnb.NewGenerateResult(), nil + } + }) + + it("provides target information", func() { + libcnb.Generate(generateFunc, + libcnb.NewConfig( + libcnb.WithArguments([]string{commandPath}), + libcnb.WithLogger(log.New(os.Stdout)), + ), + ) + + Expect(ctx.Extension.Targets).To(HaveLen(2)) + Expect(ctx.Extension.Targets[0].OS).To(Equal("linux")) + Expect(ctx.Extension.Targets[0].Arch).To(Equal("amd64")) + Expect(ctx.Extension.Targets[0].Distros).To(HaveLen(2)) + Expect(ctx.Extension.Targets[0].Distros[0].Name).To(Equal("ubuntu")) + Expect(ctx.Extension.Targets[0].Distros[0].Version).To(Equal("18.04")) + Expect(ctx.Extension.Targets[0].Distros[1].Name).To(Equal("debian")) + + Expect(ctx.Extension.Targets[1].Variant).To(Equal("v6")) + + Expect(ctx.TargetInfo.OS).To(Equal("linux")) + Expect(ctx.TargetInfo.Arch).To(Equal("arm")) + Expect(ctx.TargetInfo.Variant).To(Equal("v6")) + Expect(ctx.TargetDistro.Name).To(Equal("ubuntu")) + Expect(ctx.TargetDistro.Version).To(Equal("24.04")) + }) + }) + it("fails if CNB_EXTENSION_DIR is not set", func() { Expect(os.Unsetenv("CNB_EXTENSION_DIR")).To(Succeed()) diff --git a/platform.go b/platform.go index e2ebf4f..e38d45b 100644 --- a/platform.go +++ b/platform.go @@ -68,6 +68,21 @@ const ( // Deprecated: EnvStackID is the name of the environment variable that contains the stack id EnvStackID = "CNB_STACK_ID" + // EnvTargetOS contains the name of the os + EnvTargetOS = "CNB_TARGET_OS" + + // EnvTargetArch contains the architecture + EnvTargetArch = "CNB_TARGET_ARCH" + + // EnvTargetOS contains the variant of the architecture + EnvTargetArchVariant = "CNB_TARGET_ARCH_VARIANT" + + // EnvTargetDistroName contains the name of the ditro + EnvTargetDistroName = "CNB_TARGET_DISTRO_NAME" + + // EnvTargetDistroVersion contains the version of the distro + EnvTargetDistroVersion = "CNB_TARGET_DISTRO_VERSION" + // DefaultPlatformBindingsLocation is the typical location for bindings, which exists under the platform directory // // Not guaranteed to exist, but often does. This should only be used as a fallback if EnvServiceBindings and EnvPlatformDirectory are not set