diff --git a/platforms/compare.go b/platforms/compare.go index 22a86a8a2..c7657e186 100644 --- a/platforms/compare.go +++ b/platforms/compare.go @@ -85,6 +85,18 @@ func Only(platform specs.Platform) MatchComparer { return Ordered(platformVector(Normalize(platform))...) } +// OnlyStrict returns a match comparer for a single platform. +// +// Unlike Only, OnlyStrict does not match sub platforms. +// So, "arm/vN" will not match "arm/vM" where M < N, +// and "amd64" will not also match "386". +// +// OnlyStrict matches non-canonical forms. +// So, "arm64" matches "arm/64/v8". +func OnlyStrict(platform specs.Platform) MatchComparer { + return Ordered(Normalize(platform)) +} + // Ordered returns a platform MatchComparer which matches any of the platforms // but orders them in order they are provided. func Ordered(platforms ...specs.Platform) MatchComparer { diff --git a/platforms/compare_test.go b/platforms/compare_test.go index 9f6623a81..b734c2afe 100644 --- a/platforms/compare_test.go +++ b/platforms/compare_test.go @@ -206,3 +206,190 @@ func TestOnly(t *testing.T) { }) } } + +func TestOnlyStrict(t *testing.T) { + for _, tc := range []struct { + platform string + matches map[bool][]string + }{ + { + platform: "linux/amd64", + matches: map[bool][]string{ + true: { + "linux/amd64", + }, + false: { + "linux/386", + "linux/arm/v7", + "linux/arm64", + "windows/amd64", + "windows/arm", + }, + }, + }, + { + platform: "linux/386", + matches: map[bool][]string{ + true: { + "linux/386", + }, + false: { + "linux/amd64", + "linux/arm/v7", + "linux/arm64", + "windows/amd64", + "windows/arm", + }, + }, + }, + { + platform: "windows/amd64", + matches: map[bool][]string{ + true: {"windows/amd64"}, + false: { + "linux/amd64", + "linux/arm/v7", + "linux/arm64", + "windows/arm", + }, + }, + }, + { + platform: "linux/arm/v8", + matches: map[bool][]string{ + true: { + "linux/arm/v8", + }, + false: { + "linux/arm", + "linux/arm/v5", + "linux/arm/v6", + "linux/arm/v7", + "linux/amd64", + "linux/arm/v4", + "linux/arm64", + "windows/amd64", + "windows/arm", + }, + }, + }, + { + platform: "linux/arm/v7", + matches: map[bool][]string{ + true: { + "linux/arm", + "linux/arm/v7", + }, + false: { + "linux/arm/v5", + "linux/arm/v6", + "linux/amd64", + "linux/arm/v4", + "linux/arm/v8", + "linux/arm64", + "windows/amd64", + "windows/arm", + }, + }, + }, + { + platform: "linux/arm/v6", + matches: map[bool][]string{ + true: { + "linux/arm/v6", + }, + false: { + "linux/arm/v5", + "linux/amd64", + "linux/arm", + "linux/arm/v4", + "linux/arm/v7", + "linux/arm/v8", + "linux/arm64", + "windows/amd64", + "windows/arm", + }, + }, + }, + { + platform: "linux/arm/v5", + matches: map[bool][]string{ + true: { + "linux/arm/v5", + }, + false: { + "linux/amd64", + "linux/arm", + "linux/arm/v4", + "linux/arm/v6", + "linux/arm/v7", + "linux/arm/v8", + "linux/arm64", + "windows/amd64", + "windows/arm", + }, + }, + }, + { + platform: "linux/arm/v4", + matches: map[bool][]string{ + true: { + "linux/arm/v4", + }, + false: { + "linux/amd64", + "linux/arm", + "linux/arm/v5", + "linux/arm/v6", + "linux/arm/v7", + "linux/arm/v8", + "linux/arm64", + "windows/amd64", + "windows/arm", + }, + }, + }, + { + platform: "linux/arm64", + matches: map[bool][]string{ + true: { + "linux/arm64", + "linux/arm64/v8", + }, + false: { + "linux/arm", + "linux/arm/v5", + "linux/arm/v6", + "linux/arm/v7", + "linux/arm/v8", + "linux/amd64", + "linux/arm/v4", + "linux/arm/v9", + "linux/arm64/v9", + "windows/amd64", + "windows/arm", + }, + }, + }, + } { + testcase := tc + t.Run(testcase.platform, func(t *testing.T) { + p, err := Parse(testcase.platform) + if err != nil { + t.Fatal(err) + } + m := OnlyStrict(p) + for shouldMatch, platforms := range testcase.matches { + for _, matchPlatform := range platforms { + mp, err := Parse(matchPlatform) + if err != nil { + t.Fatal(err) + } + if match := m.Match(mp); shouldMatch != match { + t.Errorf("OnlyStrict(%q).Match(%q) should return %v, but returns %v", testcase.platform, matchPlatform, shouldMatch, match) + } + } + } + }) + } +} diff --git a/platforms/defaults.go b/platforms/defaults.go index 076f29f82..cb77fbc9f 100644 --- a/platforms/defaults.go +++ b/platforms/defaults.go @@ -36,3 +36,8 @@ func DefaultSpec() specs.Platform { Variant: cpuVariant(), } } + +// DefaultStrict returns strict form of Default. +func DefaultStrict() MatchComparer { + return OnlyStrict(DefaultSpec()) +}