Merge pull request #2414 from dmcgowan/platform-arm-normalization

Fix arm platform matching
This commit is contained in:
Derek McGowan 2018-06-22 13:15:23 -07:00 committed by GitHub
commit 47a128d455
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 128 additions and 10 deletions

View File

@ -89,18 +89,21 @@ func normalizeArch(arch, variant string) (string, string) {
case "x86_64", "x86-64": case "x86_64", "x86-64":
arch = "amd64" arch = "amd64"
variant = "" variant = ""
case "aarch64": case "aarch64", "arm64":
arch = "arm64" arch = "arm64"
variant = "" // v8 is implied switch variant {
case "", "8":
variant = "v8"
}
case "armhf": case "armhf":
arch = "arm" arch = "arm"
variant = "" variant = "v7"
case "armel": case "armel":
arch = "arm" arch = "arm"
variant = "v6" variant = "v6"
case "arm": case "arm":
switch variant { switch variant {
case "v7", "7": case "", "7":
variant = "v7" variant = "v7"
case "5", "6", "8": case "5", "6", "8":
variant = "v" + variant variant = "v" + variant
@ -109,3 +112,15 @@ func normalizeArch(arch, variant string) (string, string) {
return arch, variant return arch, variant
} }
// defaultVariant detects default variants on normalized arch/variant
func defaultVariant(arch, variant string) bool {
switch arch {
case "arm64":
return variant == "v8"
case "arm":
return variant == "v7"
default:
return true
}
}

View File

@ -135,7 +135,7 @@ type Matcher interface {
// Applications should opt to use `Match` over directly parsing specifiers. // Applications should opt to use `Match` over directly parsing specifiers.
func NewMatcher(platform specs.Platform) Matcher { func NewMatcher(platform specs.Platform) Matcher {
return &matcher{ return &matcher{
Platform: platform, Platform: Normalize(platform),
} }
} }
@ -197,6 +197,9 @@ func Parse(specifier string) (specs.Platform, error) {
} }
p.Architecture, p.Variant = normalizeArch(parts[0], "") p.Architecture, p.Variant = normalizeArch(parts[0], "")
if defaultVariant(p.Architecture, p.Variant) {
p.Variant = ""
}
if isKnownArch(p.Architecture) { if isKnownArch(p.Architecture) {
p.OS = runtime.GOOS p.OS = runtime.GOOS
return p, nil return p, nil
@ -208,6 +211,9 @@ func Parse(specifier string) (specs.Platform, error) {
// about whether or not we know of the platform. // about whether or not we know of the platform.
p.OS = normalizeOS(parts[0]) p.OS = normalizeOS(parts[0])
p.Architecture, p.Variant = normalizeArch(parts[1], "") p.Architecture, p.Variant = normalizeArch(parts[1], "")
if defaultVariant(p.Architecture, p.Variant) {
p.Variant = ""
}
return p, nil return p, nil
case 3: case 3:

View File

@ -17,7 +17,6 @@
package platforms package platforms
import ( import (
"fmt"
"reflect" "reflect"
"runtime" "runtime"
"testing" "testing"
@ -35,6 +34,7 @@ func TestParseSelector(t *testing.T) {
skip bool skip bool
input string input string
expected specs.Platform expected specs.Platform
matches []specs.Platform
formatted string formatted string
}{ }{
// While wildcards are a valid use case for platform selection, // While wildcards are a valid use case for platform selection,
@ -66,8 +66,72 @@ func TestParseSelector(t *testing.T) {
OS: "*", OS: "*",
Architecture: "arm64", Architecture: "arm64",
}, },
matches: []specs.Platform{
{
OS: "*",
Architecture: "aarch64",
},
{
OS: "*",
Architecture: "aarch64",
Variant: "v8",
},
{
OS: "*",
Architecture: "arm64",
Variant: "v8",
},
},
formatted: "*/arm64", formatted: "*/arm64",
}, },
{
input: "linux/arm64",
expected: specs.Platform{
OS: "linux",
Architecture: "arm64",
},
matches: []specs.Platform{
{
OS: "linux",
Architecture: "aarch64",
},
{
OS: "linux",
Architecture: "aarch64",
Variant: "v8",
},
{
OS: "linux",
Architecture: "arm64",
Variant: "v8",
},
},
formatted: "linux/arm64",
},
{
input: "linux/arm64/v8",
expected: specs.Platform{
OS: "linux",
Architecture: "arm64",
Variant: "v8",
},
matches: []specs.Platform{
{
OS: "linux",
Architecture: "aarch64",
},
{
OS: "linux",
Architecture: "aarch64",
Variant: "v8",
},
{
OS: "linux",
Architecture: "arm64",
},
},
formatted: "linux/arm64/v8",
},
{ {
// NOTE(stevvooe): In this case, the consumer can assume this is v7 // NOTE(stevvooe): In this case, the consumer can assume this is v7
// but we leave the variant blank. This will represent the vast // but we leave the variant blank. This will represent the vast
@ -77,6 +141,22 @@ func TestParseSelector(t *testing.T) {
OS: "linux", OS: "linux",
Architecture: "arm", Architecture: "arm",
}, },
matches: []specs.Platform{
{
OS: "linux",
Architecture: "arm",
Variant: "v7",
},
{
OS: "linux",
Architecture: "armhf",
},
{
OS: "linux",
Architecture: "arm",
Variant: "7",
},
},
formatted: "linux/arm", formatted: "linux/arm",
}, },
{ {
@ -86,6 +166,12 @@ func TestParseSelector(t *testing.T) {
Architecture: "arm", Architecture: "arm",
Variant: "v6", Variant: "v6",
}, },
matches: []specs.Platform{
{
OS: "linux",
Architecture: "armel",
},
},
formatted: "linux/arm/v6", formatted: "linux/arm/v6",
}, },
{ {
@ -95,6 +181,16 @@ func TestParseSelector(t *testing.T) {
Architecture: "arm", Architecture: "arm",
Variant: "v7", Variant: "v7",
}, },
matches: []specs.Platform{
{
OS: "linux",
Architecture: "arm",
},
{
OS: "linux",
Architecture: "armhf",
},
},
formatted: "linux/arm/v7", formatted: "linux/arm/v7",
}, },
{ {
@ -204,11 +300,12 @@ func TestParseSelector(t *testing.T) {
// ensure that match works on the input to the output. // ensure that match works on the input to the output.
if ok := m.Match(testcase.expected); !ok { if ok := m.Match(testcase.expected); !ok {
t.Fatalf("expected specifier %q matches %v", testcase.input, testcase.expected) t.Fatalf("expected specifier %q matches %#v", testcase.input, testcase.expected)
} }
for _, mc := range testcase.matches {
if fmt.Sprint(m) != testcase.formatted { if ok := m.Match(mc); !ok {
t.Fatalf("unexpected matcher string: %q != %q", fmt.Sprint(m), testcase.formatted) t.Fatalf("expected specifier %q matches %#v", testcase.input, mc)
}
} }
formatted := Format(p) formatted := Format(p)