Skip to content

Commit 9072b09

Browse files
committed
Refactor platforms.Only with a "platformVector" helper
This improves the hard-coded list of ARM fallbacks in the `platform.Only` implementation (by doing a descending loop over variant numbers instead, which is all the hard-coded list was doing). Making this a separate function can then more easily be recursive later for handling an `arm64`->`arm` fallback (or similar), but I think it makes the code a lot more clear too (so we're calculating a vector of platforms separately from building a matcher object). This also makes a minor adjustment in `TestImagePullWithDistSourceLabel` which had an implicit assumption that `platforms.Only` would only ever result in a single suitable manifest, which isn't strictly true (and is likely failing as-is when run on any 32bit `arm` system that's `v6` or higher, which this fixes 😅). Signed-off-by: Tianon Gravi <[email protected]>
1 parent 7a2720f commit 9072b09

2 files changed

Lines changed: 34 additions & 103 deletions

File tree

image_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ func TestImagePullWithDistSourceLabel(t *testing.T) {
113113
key := fmt.Sprintf("containerd.io/distribution.source.%s", source)
114114

115115
// only check the target platform
116-
childrenHandler := images.FilterPlatforms(images.ChildrenHandler(cs), pMatcher)
116+
childrenHandler := images.LimitManifests(images.ChildrenHandler(cs), pMatcher, 1)
117117

118118
checkLabelHandler := func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
119119
children, err := childrenHandler(ctx, desc)

platforms/compare.go

Lines changed: 33 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,12 @@
1616

1717
package platforms
1818

19-
import specs "github.com/opencontainers/image-spec/specs-go/v1"
19+
import (
20+
"strconv"
21+
"strings"
22+
23+
specs "github.com/opencontainers/image-spec/specs-go/v1"
24+
)
2025

2126
// MatchComparer is able to match and compare platforms to
2227
// filter and sort platforms.
@@ -26,103 +31,37 @@ type MatchComparer interface {
2631
Less(specs.Platform, specs.Platform) bool
2732
}
2833

29-
// Only returns a match comparer for a single platform
30-
// using default resolution logic for the platform.
31-
//
32-
// For ARMv8, will also match ARMv7, ARMv6 and ARMv5 (for 32bit runtimes)
33-
// For ARMv7, will also match ARMv6 and ARMv5
34-
// For ARMv6, will also match ARMv5
35-
func Only(platform specs.Platform) MatchComparer {
36-
platform = Normalize(platform)
37-
if platform.Architecture == "arm" {
38-
if platform.Variant == "v8" {
39-
return orderedPlatformComparer{
40-
matchers: []Matcher{
41-
&matcher{
42-
Platform: platform,
43-
},
44-
&matcher{
45-
Platform: specs.Platform{
46-
Architecture: platform.Architecture,
47-
OS: platform.OS,
48-
OSVersion: platform.OSVersion,
49-
OSFeatures: platform.OSFeatures,
50-
Variant: "v7",
51-
},
52-
},
53-
&matcher{
54-
Platform: specs.Platform{
55-
Architecture: platform.Architecture,
56-
OS: platform.OS,
57-
OSVersion: platform.OSVersion,
58-
OSFeatures: platform.OSFeatures,
59-
Variant: "v6",
60-
},
61-
},
62-
&matcher{
63-
Platform: specs.Platform{
64-
Architecture: platform.Architecture,
65-
OS: platform.OS,
66-
OSVersion: platform.OSVersion,
67-
OSFeatures: platform.OSFeatures,
68-
Variant: "v5",
69-
},
70-
},
71-
},
72-
}
73-
}
74-
if platform.Variant == "v7" {
75-
return orderedPlatformComparer{
76-
matchers: []Matcher{
77-
&matcher{
78-
Platform: platform,
79-
},
80-
&matcher{
81-
Platform: specs.Platform{
82-
Architecture: platform.Architecture,
83-
OS: platform.OS,
84-
OSVersion: platform.OSVersion,
85-
OSFeatures: platform.OSFeatures,
86-
Variant: "v6",
87-
},
88-
},
89-
&matcher{
90-
Platform: specs.Platform{
91-
Architecture: platform.Architecture,
92-
OS: platform.OS,
93-
OSVersion: platform.OSVersion,
94-
OSFeatures: platform.OSFeatures,
95-
Variant: "v5",
96-
},
97-
},
98-
},
99-
}
100-
}
101-
if platform.Variant == "v6" {
102-
return orderedPlatformComparer{
103-
matchers: []Matcher{
104-
&matcher{
105-
Platform: platform,
106-
},
107-
&matcher{
108-
Platform: specs.Platform{
109-
Architecture: platform.Architecture,
110-
OS: platform.OS,
111-
OSVersion: platform.OSVersion,
112-
OSFeatures: platform.OSFeatures,
113-
Variant: "v5",
114-
},
115-
},
116-
},
34+
// platformVector returns an (ordered) vector of appropriate specs.Platform
35+
// objects to try matching for the given platform object (see platforms.Only).
36+
func platformVector(platform specs.Platform) []specs.Platform {
37+
vector := []specs.Platform{platform}
38+
39+
switch platform.Architecture {
40+
case "arm":
41+
if armVersion, err := strconv.Atoi(strings.TrimPrefix(platform.Variant, "v")); err == nil && armVersion > 5 {
42+
for armVersion--; armVersion >= 5; armVersion-- {
43+
vector = append(vector, specs.Platform{
44+
Architecture: platform.Architecture,
45+
OS: platform.OS,
46+
OSVersion: platform.OSVersion,
47+
OSFeatures: platform.OSFeatures,
48+
Variant: "v" + strconv.Itoa(armVersion),
49+
})
11750
}
11851
}
11952
}
12053

121-
return singlePlatformComparer{
122-
Matcher: &matcher{
123-
Platform: platform,
124-
},
125-
}
54+
return vector
55+
}
56+
57+
// Only returns a match comparer for a single platform
58+
// using default resolution logic for the platform.
59+
//
60+
// For arm/v8, will also match arm/v7, arm/v6 and arm/v5
61+
// For arm/v7, will also match arm/v6 and arm/v5
62+
// For arm/v6, will also match arm/v5
63+
func Only(platform specs.Platform) MatchComparer {
64+
return Ordered(platformVector(Normalize(platform))...)
12665
}
12766

12867
// Ordered returns a platform MatchComparer which matches any of the platforms
@@ -153,14 +92,6 @@ func Any(platforms ...specs.Platform) MatchComparer {
15392
// with preference for ordering.
15493
var All MatchComparer = allPlatformComparer{}
15594

156-
type singlePlatformComparer struct {
157-
Matcher
158-
}
159-
160-
func (c singlePlatformComparer) Less(p1, p2 specs.Platform) bool {
161-
return c.Match(p1) && !c.Match(p2)
162-
}
163-
16495
type orderedPlatformComparer struct {
16596
matchers []Matcher
16697
}

0 commit comments

Comments
 (0)