Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix CNB_TARGET_* env vars on older Platform API #1374

Merged
merged 4 commits into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions phase/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,6 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) {
executor.EXPECT().Build(*bpA, gomock.Any(), gomock.Any()).DoAndReturn(
func(_ buildpack.BpDescriptor, inputs buildpack.BuildInputs, logger llog.Logger) (buildpack.BuildOutputs, error) {
h.AssertContains(t, inputs.TargetEnv, "CNB_TARGET_ARCH=amd64")
h.AssertContains(t, inputs.TargetEnv, "CNB_TARGET_ARCH_VARIANT=")
h.AssertContains(t, inputs.TargetEnv, "CNB_TARGET_OS=linux")
return buildpack.BuildOutputs{}, nil
},
Expand All @@ -201,7 +200,6 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) {
executor.EXPECT().Build(*bpB, gomock.Any(), gomock.Any()).Do(
func(_ buildpack.BpDescriptor, inputs buildpack.BuildInputs, _ llog.Logger) (buildpack.BuildOutputs, error) {
h.AssertContains(t, inputs.TargetEnv, "CNB_TARGET_ARCH=amd64")
h.AssertContains(t, inputs.TargetEnv, "CNB_TARGET_ARCH_VARIANT=")
h.AssertContains(t, inputs.TargetEnv, "CNB_TARGET_OS=linux")
return buildpack.BuildOutputs{}, nil
})
Expand Down
1 change: 0 additions & 1 deletion phase/detector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,6 @@ func testDetector(t *testing.T, when spec.G, it spec.S) {
executor.EXPECT().Detect(bpA1, gomock.Any(), gomock.Any()).Do(
func(_ buildpack.Descriptor, inputs buildpack.DetectInputs, _ log.Logger) buildpack.DetectOutputs {
h.AssertContains(t, inputs.TargetEnv, "CNB_TARGET_ARCH=amd64")
h.AssertContains(t, inputs.TargetEnv, "CNB_TARGET_ARCH_VARIANT=")
h.AssertContains(t, inputs.TargetEnv, "CNB_TARGET_OS=linux")
return buildpack.DetectOutputs{}
})
Expand Down
2 changes: 0 additions & 2 deletions phase/generator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,6 @@ func testGenerator(t *testing.T, when spec.G, it spec.S) {
func(d buildpack.ExtDescriptor, inputs buildpack.GenerateInputs, _ *log.Logger) (buildpack.GenerateOutputs, error) {
h.AssertContains(t, inputs.TargetEnv,
"CNB_TARGET_ARCH=amd64",
"CNB_TARGET_ARCH_VARIANT=",
"CNB_TARGET_OS=linux",
)
return buildpack.GenerateOutputs{Dockerfiles: []buildpack.DockerfileInfo{{ExtensionID: d.Extension.ID,
Expand All @@ -293,7 +292,6 @@ func testGenerator(t *testing.T, when spec.G, it spec.S) {
func(d buildpack.ExtDescriptor, inputs buildpack.GenerateInputs, _ *log.Logger) (buildpack.GenerateOutputs, error) {
h.AssertContains(t, inputs.TargetEnv,
"CNB_TARGET_ARCH=amd64",
"CNB_TARGET_ARCH_VARIANT=",
"CNB_TARGET_OS=linux",
)
return buildpack.GenerateOutputs{Dockerfiles: []buildpack.DockerfileInfo{{ExtensionID: d.Extension.ID,
Expand Down
28 changes: 23 additions & 5 deletions platform/target_data.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package platform

import (
"fmt"
"runtime"

"github.com/buildpacks/imgutil"

"github.com/buildpacks/lifecycle/buildpack"
Expand Down Expand Up @@ -87,10 +90,16 @@ func matches(target1, target2 string) bool {
return target1 == target2
}

// GetTargetOSFromFileSystem populates the target metadata you pass in if the information is available
// returns a boolean indicating whether it populated any data.
// GetTargetOSFromFileSystem populates the provided target metadata with information from /etc/os-release
// if it is available.
func GetTargetOSFromFileSystem(d fsutil.Detector, tm *files.TargetMetadata, logger log.Logger) {
if d.HasSystemdFile() {
if tm.OS == "" {
tm.OS = "linux"
}
if tm.Arch == "" {
tm.Arch = runtime.GOARCH // in a future world where we support cross platform builds, this should be removed
}
contents, err := d.ReadSystemdFile()
if err != nil {
logger.Warnf("Encountered error trying to read /etc/os-release file: %s", err.Error())
Expand All @@ -112,21 +121,30 @@ func EnvVarsFor(d fsutil.Detector, tm files.TargetMetadata, logger log.Logger) [
logger.Info("target distro name/version labels not found, reading /etc/os-release file")
GetTargetOSFromFileSystem(d, &tm, logger)
}
// required
ret := []string{
"CNB_TARGET_OS=" + tm.OS,
"CNB_TARGET_ARCH=" + tm.Arch,
"CNB_TARGET_ARCH_VARIANT=" + tm.ArchVariant,
}
// optional
var distName, distVersion string
if tm.Distro != nil {
distName = tm.Distro.Name
distVersion = tm.Distro.Version
}
ret = append(ret, "CNB_TARGET_DISTRO_NAME="+distName)
ret = append(ret, "CNB_TARGET_DISTRO_VERSION="+distVersion)
ret = appendIfNotEmpty(ret, "CNB_TARGET_ARCH_VARIANT", tm.ArchVariant)
ret = appendIfNotEmpty(ret, "CNB_TARGET_DISTRO_NAME", distName)
ret = appendIfNotEmpty(ret, "CNB_TARGET_DISTRO_VERSION", distVersion)
return ret
}

func appendIfNotEmpty(env []string, key, val string) []string {
if val == "" {
return env
}
return append(env, fmt.Sprintf("%s=%s", key, val))
}

// TargetSatisfiedForRebase treats optional fields (ArchVariant and Distribution fields) as wildcards if empty, returns true if all populated fields match
func TargetSatisfiedForRebase(t files.TargetMetadata, appTargetMetadata files.TargetMetadata) bool {
if t.OS != appTargetMetadata.OS || t.Arch != appTargetMetadata.Arch {
Expand Down
31 changes: 25 additions & 6 deletions platform/target_data_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package platform_test

import (
"fmt"
"runtime"
"testing"

"github.com/apex/log"
Expand Down Expand Up @@ -129,6 +130,8 @@ func testTargetData(t *testing.T, when spec.G, it spec.S) {
t: t,
HasFile: true}
platform.GetTargetOSFromFileSystem(&d, &tm, logr)
h.AssertEq(t, "linux", tm.OS)
h.AssertEq(t, runtime.GOARCH, tm.Arch)
h.AssertEq(t, "opensesame", tm.Distro.Name)
h.AssertEq(t, "3.14", tm.Distro.Version)
})
Expand Down Expand Up @@ -199,12 +202,28 @@ func testTargetData(t *testing.T, when spec.G, it spec.S) {
observed := platform.EnvVarsFor(d, tm, &log.Logger{Handler: memory.New()})
h.AssertContains(t, observed, "CNB_TARGET_ARCH="+tm.Arch)
h.AssertContains(t, observed, "CNB_TARGET_OS="+tm.OS)
// note: per the spec only the ID field is optional, so I guess the others should always be set: https://github.com/buildpacks/rfcs/blob/main/text/0096-remove-stacks-mixins.md#runtime-metadata
// the empty ones:
h.AssertContains(t, observed, "CNB_TARGET_ARCH_VARIANT=")
h.AssertContains(t, observed, "CNB_TARGET_DISTRO_NAME=")
h.AssertContains(t, observed, "CNB_TARGET_DISTRO_VERSION=")
h.AssertEq(t, len(observed), 5)
h.AssertEq(t, len(observed), 2)
})

when("optional vars are empty", func() {
it("omits them", func() {
tm := files.TargetMetadata{
// required
OS: "linux",
Arch: "pentium",
// optional
ArchVariant: "",
Distro: &files.OSDistro{Name: "nix", Version: ""},
ID: "",
}
d := &mockDetector{
contents: "this is just test contents really",
t: t,
HasFile: false,
}
observed := platform.EnvVarsFor(d, tm, &log.Logger{Handler: memory.New()})
h.AssertEq(t, len(observed), 3)
})
})
})

Expand Down
Loading