Skip to content

Commit aff7177

Browse files
authored
Merge pull request #47337 from vvoland/cache-fix-older-windows-25
[25.0 backport] image/cache: Ignore Build and Revision on Windows
2 parents df96d8d + 0227d95 commit aff7177

File tree

3 files changed

+109
-2
lines changed

3 files changed

+109
-2
lines changed

image/cache/cache.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"reflect"
88
"strings"
99

10-
"github.com/containerd/containerd/platforms"
1110
"github.com/containerd/log"
1211
containertypes "github.com/docker/docker/api/types/container"
1312
"github.com/docker/docker/dockerversion"
@@ -250,11 +249,12 @@ func getLocalCachedImage(imageStore image.Store, imgID image.ID, config *contain
250249
}
251250

252251
imgPlatform := img.Platform()
252+
253253
// Discard old linux/amd64 images with empty platform.
254254
if imgPlatform.OS == "" && imgPlatform.Architecture == "" {
255255
continue
256256
}
257-
if !platforms.OnlyStrict(platform).Match(imgPlatform) {
257+
if !comparePlatform(platform, imgPlatform) {
258258
continue
259259
}
260260

image/cache/compare.go

+27
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
package cache // import "github.com/docker/docker/image/cache"
22

33
import (
4+
"strings"
5+
6+
"github.com/containerd/containerd/platforms"
47
"github.com/docker/docker/api/types/container"
8+
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
59
)
610

711
// TODO: Remove once containerd image service directly uses the ImageCache and
@@ -10,6 +14,29 @@ func CompareConfig(a, b *container.Config) bool {
1014
return compare(a, b)
1115
}
1216

17+
func comparePlatform(builderPlatform, imagePlatform ocispec.Platform) bool {
18+
// On Windows, only check the Major and Minor versions.
19+
// The Build and Revision compatibility depends on whether `process` or
20+
// `hyperv` isolation used.
21+
//
22+
// Fixes https://github.com/moby/moby/issues/47307
23+
if builderPlatform.OS == "windows" && imagePlatform.OS == builderPlatform.OS {
24+
// OSVersion format is:
25+
// Major.Minor.Build.Revision
26+
builderParts := strings.Split(builderPlatform.OSVersion, ".")
27+
imageParts := strings.Split(imagePlatform.OSVersion, ".")
28+
29+
if len(builderParts) >= 3 && len(imageParts) >= 3 {
30+
// Keep only Major & Minor.
31+
builderParts[0] = imageParts[0]
32+
builderParts[1] = imageParts[1]
33+
imagePlatform.OSVersion = strings.Join(builderParts, ".")
34+
}
35+
}
36+
37+
return platforms.Only(builderPlatform).Match(imagePlatform)
38+
}
39+
1340
// compare two Config struct. Do not container-specific fields:
1441
// - Image
1542
// - Hostname

image/cache/compare_test.go

+80
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
package cache // import "github.com/docker/docker/image/cache"
22

33
import (
4+
"runtime"
45
"testing"
56

67
"github.com/docker/docker/api/types/container"
78
"github.com/docker/docker/api/types/strslice"
89
"github.com/docker/go-connections/nat"
10+
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
11+
"gotest.tools/v3/assert"
12+
is "gotest.tools/v3/assert/cmp"
913
)
1014

1115
// Just to make life easier
@@ -124,3 +128,79 @@ func TestCompare(t *testing.T) {
124128
}
125129
}
126130
}
131+
132+
func TestPlatformCompare(t *testing.T) {
133+
for _, tc := range []struct {
134+
name string
135+
builder ocispec.Platform
136+
image ocispec.Platform
137+
expected bool
138+
}{
139+
{
140+
name: "same os and arch",
141+
builder: ocispec.Platform{Architecture: "amd64", OS: runtime.GOOS},
142+
image: ocispec.Platform{Architecture: "amd64", OS: runtime.GOOS},
143+
expected: true,
144+
},
145+
{
146+
name: "same os different arch",
147+
builder: ocispec.Platform{Architecture: "amd64", OS: runtime.GOOS},
148+
image: ocispec.Platform{Architecture: "arm64", OS: runtime.GOOS},
149+
expected: false,
150+
},
151+
{
152+
name: "same os smaller host variant",
153+
builder: ocispec.Platform{Variant: "v7", Architecture: "arm", OS: runtime.GOOS},
154+
image: ocispec.Platform{Variant: "v8", Architecture: "arm", OS: runtime.GOOS},
155+
expected: false,
156+
},
157+
{
158+
name: "same os higher host variant",
159+
builder: ocispec.Platform{Variant: "v8", Architecture: "arm", OS: runtime.GOOS},
160+
image: ocispec.Platform{Variant: "v7", Architecture: "arm", OS: runtime.GOOS},
161+
expected: true,
162+
},
163+
{
164+
// Test for https://github.com/moby/moby/issues/47307
165+
name: "different build and revision",
166+
builder: ocispec.Platform{Architecture: "amd64", OS: "windows", OSVersion: "10.0.22621"},
167+
image: ocispec.Platform{Architecture: "amd64", OS: "windows", OSVersion: "10.0.17763.5329"},
168+
expected: true,
169+
},
170+
{
171+
name: "different revision",
172+
builder: ocispec.Platform{Architecture: "amd64", OS: "windows", OSVersion: "10.0.17763.1234"},
173+
image: ocispec.Platform{Architecture: "amd64", OS: "windows", OSVersion: "10.0.17763.5329"},
174+
expected: true,
175+
},
176+
{
177+
name: "different major",
178+
builder: ocispec.Platform{Architecture: "amd64", OS: "windows", OSVersion: "11.0.17763.5329"},
179+
image: ocispec.Platform{Architecture: "amd64", OS: "windows", OSVersion: "10.0.17763.5329"},
180+
expected: false,
181+
},
182+
{
183+
name: "different minor same osver",
184+
builder: ocispec.Platform{Architecture: "amd64", OS: "windows", OSVersion: "10.0.17763.5329"},
185+
image: ocispec.Platform{Architecture: "amd64", OS: "windows", OSVersion: "10.1.17763.5329"},
186+
expected: false,
187+
},
188+
{
189+
name: "different arch same osver",
190+
builder: ocispec.Platform{Architecture: "arm64", OS: "windows", OSVersion: "10.0.17763.5329"},
191+
image: ocispec.Platform{Architecture: "amd64", OS: "windows", OSVersion: "10.0.17763.5329"},
192+
expected: false,
193+
},
194+
} {
195+
tc := tc
196+
// OSVersion comparison is only performed by containerd platform
197+
// matcher if built on Windows.
198+
if (tc.image.OSVersion != "" || tc.builder.OSVersion != "") && runtime.GOOS != "windows" {
199+
continue
200+
}
201+
202+
t.Run(tc.name, func(t *testing.T) {
203+
assert.Check(t, is.Equal(comparePlatform(tc.builder, tc.image), tc.expected))
204+
})
205+
}
206+
}

0 commit comments

Comments
 (0)