Introduce `hostPlatformSpec` as a replacement, so we can decouple from
containerd platforms logic and override for tests.
Default image-store operations should share the same host platform
preference as pulls, otherwise list, identity cache, and classic-builder
selection can still rank plain linux/amd64 ahead of compatible amd64
variants.
Route those unspecified-platform paths through the ImageService host
matcher so amd64 variant fallback stays consistent.
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
| ... | ... |
@@ -200,7 +200,7 @@ func newROLayerForImage(ctx context.Context, imgDesc *ocispec.Descriptor, i *Ima |
| 200 | 200 |
return nil, errors.New("can't make an RO layer for a nil image :'(")
|
| 201 | 201 |
} |
| 202 | 202 |
|
| 203 |
- platMatcher := platforms.Default() |
|
| 203 |
+ platMatcher := i.hostPlatformMatcher() |
|
| 204 | 204 |
if platform != nil {
|
| 205 | 205 |
platMatcher = platforms.Only(*platform) |
| 206 | 206 |
} |
| ... | ... |
@@ -449,7 +449,7 @@ func (i *ImageService) CreateImage(ctx context.Context, config []byte, parent st |
| 449 | 449 |
if err != nil {
|
| 450 | 450 |
return nil, err |
| 451 | 451 |
} |
| 452 |
- parentImageManifest, err := c8dimages.Manifest(ctx, i.content, parentDesc, platforms.Default()) |
|
| 452 |
+ parentImageManifest, err := c8dimages.Manifest(ctx, i.content, parentDesc, i.hostPlatformMatcher()) |
|
| 453 | 453 |
if err != nil {
|
| 454 | 454 |
return nil, err |
| 455 | 455 |
} |
| ... | ... |
@@ -424,7 +424,7 @@ func (i *ImageService) refreshImageIdentityCacheKey(ctx context.Context, cacheKe |
| 424 | 424 |
return nil |
| 425 | 425 |
} |
| 426 | 426 |
|
| 427 |
- platformMatcher, err := imageIdentityPlatformMatcher(bestPlatform) |
|
| 427 |
+ platformMatcher, err := i.imageIdentityPlatformMatcher(bestPlatform) |
|
| 428 | 428 |
if err != nil {
|
| 429 | 429 |
return err |
| 430 | 430 |
} |
| ... | ... |
@@ -448,9 +448,9 @@ func (i *ImageService) refreshImageIdentityCacheKey(ctx context.Context, cacheKe |
| 448 | 448 |
return nil |
| 449 | 449 |
} |
| 450 | 450 |
|
| 451 |
-func imageIdentityPlatformMatcher(platform string) (platforms.MatchComparer, error) {
|
|
| 451 |
+func (i *ImageService) imageIdentityPlatformMatcher(platform string) (platforms.MatchComparer, error) {
|
|
| 452 | 452 |
if platform == "" {
|
| 453 |
- return matchAnyWithPreference(platforms.Default(), nil), nil |
|
| 453 |
+ return matchAnyWithPreference(i.hostPlatformMatcher(), nil), nil |
|
| 454 | 454 |
} |
| 455 | 455 |
parsed, err := platforms.Parse(platform) |
| 456 | 456 |
if err != nil {
|
| ... | ... |
@@ -541,7 +541,7 @@ func (i *ImageService) warmImageIdentityCache(ctx context.Context, img c8dimages |
| 541 | 541 |
go func() {
|
| 542 | 542 |
warmCtx, cancel := context.WithTimeout(context.WithoutCancel(ctx), imageIdentityWarmupTimeout) |
| 543 | 543 |
defer cancel() |
| 544 |
- multi, err := i.multiPlatformSummary(warmCtx, img, matchAnyWithPreference(platforms.Default(), nil)) |
|
| 544 |
+ multi, err := i.multiPlatformSummary(warmCtx, img, matchAnyWithPreference(i.hostPlatformMatcher(), nil)) |
|
| 545 | 545 |
if err != nil {
|
| 546 | 546 |
log.G(warmCtx).WithError(err).WithField("image", img.Name).Debug("failed to build image identity cache in background")
|
| 547 | 547 |
return |
| ... | ... |
@@ -107,7 +107,7 @@ func (i *ImageService) Images(ctx context.Context, opts imagebackend.ListOptions |
| 107 | 107 |
} |
| 108 | 108 |
|
| 109 | 109 |
// TODO: Allow platform override? |
| 110 |
- platformMatcher := matchAnyWithPreference(platforms.Default(), nil) |
|
| 110 |
+ platformMatcher := matchAnyWithPreference(i.hostPlatformMatcher(), nil) |
|
| 111 | 111 |
|
| 112 | 112 |
for _, img := range imgs {
|
| 113 | 113 |
isDangling := isDanglingImage(img) |
| ... | ... |
@@ -138,7 +138,7 @@ func (i *ImageService) pullTag(ctx context.Context, ref reference.Named, platfor |
| 138 | 138 |
}() |
| 139 | 139 |
} |
| 140 | 140 |
|
| 141 |
- p := platforms.Default() |
|
| 141 |
+ p := i.hostPlatformMatcher() |
|
| 142 | 142 |
if platform != nil {
|
| 143 | 143 |
p = platforms.Only(*platform) |
| 144 | 144 |
} |
| ... | ... |
@@ -252,7 +252,7 @@ func (i *ImageService) pullTag(ctx context.Context, ref reference.Named, platfor |
| 252 | 252 |
// the same message as the graphdrivers backend. |
| 253 | 253 |
// The one returned by containerd doesn't contain the platform and is much less informative. |
| 254 | 254 |
if strings.Contains(err.Error(), "platform") {
|
| 255 |
- platformStr := platforms.DefaultString() |
|
| 255 |
+ platformStr := platforms.FormatAll(i.hostPlatformSpec()) |
|
| 256 | 256 |
if platform != nil {
|
| 257 | 257 |
platformStr = platforms.FormatAll(*platform) |
| 258 | 258 |
} |
| ... | ... |
@@ -65,9 +65,14 @@ func (i *ImageService) matchRequestedOrDefault( |
| 65 | 65 |
|
| 66 | 66 |
// hostPlatformMatcher returns a platform match comparer that matches the host platform. |
| 67 | 67 |
func (i *ImageService) hostPlatformMatcher() platforms.MatchComparer {
|
| 68 |
- // Allow to override the host platform for testing purposes. |
|
| 68 |
+ return platforms.Only(i.hostPlatformSpec()) |
|
| 69 |
+} |
|
| 70 |
+ |
|
| 71 |
+// hostPlatformSpec returns the host platform specification. |
|
| 72 |
+func (i *ImageService) hostPlatformSpec() ocispec.Platform {
|
|
| 73 |
+ // Allow tests to override the host platform before constructing matchers. |
|
| 69 | 74 |
if i.defaultPlatformOverride != nil {
|
| 70 |
- return platforms.Only(*i.defaultPlatformOverride) |
|
| 75 |
+ return *i.defaultPlatformOverride |
|
| 71 | 76 |
} |
| 72 |
- return platforms.Default() |
|
| 77 |
+ return platforms.DefaultSpec() |
|
| 73 | 78 |
} |