Skip to content

Commit

Permalink
Add support for ARM64 support in DependencyResolver
Browse files Browse the repository at this point in the history
This commit adds support to DependencyResolver.Resolve to pick a Dependency and consider the architecture. It looks at either `BP_ARCH` (if set) or `runtime.GOARCH` otherwise. It then compares this to the `arch=` value that is set in PURL. We are using the PURL because it exists already and already contains the arch info. This is opposed to adding a new property to the dependency metadata. We *may* end up doing that still, but this just gets things working more quickly now and we can change this in the future.

Signed-off-by: Daniel Mikusa <[email protected]>
  • Loading branch information
dmikusa committed Oct 29, 2023
1 parent 5f6aab3 commit 763ed5b
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 2 deletions.
38 changes: 38 additions & 0 deletions buildpack.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ package libpak

import (
"fmt"
"net/url"
"os"
"reflect"
"runtime"
"sort"
"strconv"
"strings"
Expand Down Expand Up @@ -506,6 +508,15 @@ func (d *DependencyResolver) Resolve(id string, version string) (BuildpackDepend
return BuildpackDependency{}, fmt.Errorf("unable to parse version %s\n%w", c.Version, err)
}

// filter out deps that do not match the current running architecture
arch, err := archFromPURL(c.PURL)
if err != nil {
return BuildpackDependency{}, fmt.Errorf("unable to compare arch\n%w", err)
}
if arch != archFromSystem() {
continue
}

if c.ID == id && vc.Check(v) && d.contains(c.Stacks, d.StackID) {
candidates = append(candidates, c)
}
Expand Down Expand Up @@ -534,6 +545,33 @@ func (d *DependencyResolver) Resolve(id string, version string) (BuildpackDepend
return candidate, nil
}

func archFromPURL(rawPURL string) (string, error) {
if len(strings.TrimSpace(rawPURL)) == 0 {
return "amd64", nil
}

purl, err := url.Parse(rawPURL)
if err != nil {
return "", fmt.Errorf("unable to parse PURL\n%w", err)
}

queryParams := purl.Query()
if arch, ok := queryParams["arch"]; ok {
return arch[0], nil
}

return "amd64", nil
}

func archFromSystem() string {
archFromEnv, ok := os.LookupEnv("BP_ARCH")
if !ok {
archFromEnv = runtime.GOARCH
}

return archFromEnv
}

func (DependencyResolver) contains(candidates []string, value string) bool {
if len(candidates) == 0 {
return true
Expand Down
40 changes: 40 additions & 0 deletions buildpack_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,10 @@ func testBuildpack(t *testing.T, context spec.G, it spec.S) {
resolver libpak.DependencyResolver
)

it.Before(func() {
t.Setenv("BP_ARCH", "amd64") // force for test consistency
})

context("Resolve", func() {

it("filters by id", func() {
Expand Down Expand Up @@ -315,6 +319,42 @@ func testBuildpack(t *testing.T, context spec.G, it spec.S) {
}))
})

it("filters by arch", func() {
resolver.Dependencies = []libpak.BuildpackDependency{
{
ID: "test-id-1",
Name: "test-name",
Version: "1.0",
URI: "test-uri-amd64",
SHA256: "test-sha256",
Stacks: []string{"test-stack-1", "test-stack-2"},
PURL: "pkg:generic/[email protected]?arch=amd64",
},
{
ID: "test-id-1",
Name: "test-name",
Version: "1.0",
URI: "test-uri-arm64",
SHA256: "test-sha256",
Stacks: []string{"test-stack-1", "test-stack-2"},
PURL: "pkg:generic/[email protected]?arch=arm64",
},
}
resolver.StackID = "test-stack-1"

t.Setenv("BP_ARCH", "arm64")

Expect(resolver.Resolve("test-id-1", "1.0")).To(Equal(libpak.BuildpackDependency{
ID: "test-id-1",
Name: "test-name",
Version: "1.0",
URI: "test-uri-arm64",
SHA256: "test-sha256",
Stacks: []string{"test-stack-1", "test-stack-2"},
PURL: "pkg:generic/[email protected]?arch=arm64",
}))
})

it("filters by version constraint", func() {
resolver.Dependencies = []libpak.BuildpackDependency{
{
Expand Down
4 changes: 2 additions & 2 deletions carton/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func (p Package) Create(options ...Option) {
config.exitHandler.Error(fmt.Errorf("unable to decode buildpack %s\n%w", file, err))
return
}
logger.Debug("Buildpack: %+v", buildpack)
logger.Debugf("Buildpack: %+v", buildpack)

metadata, err := libpak.NewBuildpackMetadata(buildpack.Metadata)
if err != nil {
Expand All @@ -102,7 +102,7 @@ func (p Package) Create(options ...Option) {
for _, i := range metadata.IncludeFiles {
entries[i] = filepath.Join(p.Source, i)
}
logger.Debug("Include files: %+v", entries)
logger.Debugf("Include files: %+v", entries)

if p.Version != "" {
buildpack.Info.Version = p.Version
Expand Down

0 comments on commit 763ed5b

Please sign in to comment.