Skip to content

Commit e1cc998

Browse files
authored
fix: allow the specific image platform os/arch/variant to meet the requirement for a broader image platform os/arch (#858)
Signed-off-by: Cheng Fang <[email protected]>
1 parent 40f260a commit e1cc998

File tree

4 files changed

+55
-16
lines changed

4 files changed

+55
-16
lines changed

pkg/image/options_test.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"regexp"
66
"runtime"
7+
"strings"
78
"testing"
89

910
"github.com/stretchr/testify/assert"
@@ -380,8 +381,17 @@ func Test_GetPlatformOptions(t *testing.T) {
380381
opts := img.GetPlatformOptions(annotations, false)
381382
os := runtime.GOOS
382383
arch := runtime.GOARCH
383-
assert.True(t, opts.WantsPlatform(os, arch, ""))
384-
assert.False(t, opts.WantsPlatform(os, arch, "invalid"))
384+
platform := opts.Platforms()[0]
385+
slashCount := strings.Count(platform, "/")
386+
if slashCount == 1 {
387+
assert.True(t, opts.WantsPlatform(os, arch, ""))
388+
assert.True(t, opts.WantsPlatform(os, arch, "invalid"))
389+
} else if slashCount == 2 {
390+
assert.False(t, opts.WantsPlatform(os, arch, ""))
391+
assert.False(t, opts.WantsPlatform(os, arch, "invalid"))
392+
} else {
393+
t.Fatal("invalid platform options ", platform)
394+
}
385395
})
386396
t.Run("Empty platform options without restriction", func(t *testing.T) {
387397
annotations := map[string]string{}
@@ -396,7 +406,7 @@ func Test_GetPlatformOptions(t *testing.T) {
396406
t.Run("Single platform without variant requested", func(t *testing.T) {
397407
os := "linux"
398408
arch := "arm64"
399-
variant := ""
409+
variant := "v8"
400410
annotations := map[string]string{
401411
fmt.Sprintf(common.PlatformsAnnotation, "dummy"): options.PlatformKey(os, arch, variant),
402412
}
@@ -431,7 +441,7 @@ func Test_GetPlatformOptions(t *testing.T) {
431441
assert.True(t, opts.WantsPlatform(os, arch, variant))
432442
assert.True(t, opts.WantsPlatform(runtime.GOOS, runtime.GOARCH, ""))
433443
assert.False(t, opts.WantsPlatform(os, arch, ""))
434-
assert.False(t, opts.WantsPlatform(runtime.GOOS, runtime.GOARCH, variant))
444+
assert.True(t, opts.WantsPlatform(runtime.GOOS, runtime.GOARCH, variant))
435445
})
436446
t.Run("Invalid platform requested", func(t *testing.T) {
437447
os := "linux"

pkg/options/options.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,25 @@ func PlatformKey(os string, arch string, variant string) string {
3232
return key
3333
}
3434

35-
// MatchesPlatform returns true if given OS name matches the OS set in options
35+
// WantsPlatform returns true if given platform matches the platform set in options
3636
func (o *ManifestOptions) WantsPlatform(os string, arch string, variant string) bool {
3737
o.mutex.RLock()
3838
defer o.mutex.RUnlock()
3939
if len(o.platforms) == 0 {
4040
return true
4141
}
4242
_, ok := o.platforms[PlatformKey(os, arch, variant)]
43-
return ok
43+
if ok {
44+
return true
45+
}
46+
47+
// if no exact match, and the passed platform has variant, it may be a more
48+
// specific variant of the platform specified in options. So compare os/arch only
49+
if variant != "" {
50+
_, ok = o.platforms[PlatformKey(os, arch, "")]
51+
return ok
52+
}
53+
return false
4454
}
4555

4656
// WithPlatform sets a platform filter for options o

pkg/options/options_test.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,28 @@ func Test_WantsPlatform(t *testing.T) {
2626
opts = opts.WithPlatform("linux", "arm", "v7")
2727
assert.True(t, opts.WantsPlatform("linux", "arm", "v7"))
2828
})
29-
t.Run("Platform appended", func(t *testing.T) {
29+
t.Run("Platform appended and non-match", func(t *testing.T) {
3030
opts = opts.WithPlatform("linux", "arm", "v8")
3131
assert.True(t, opts.WantsPlatform("linux", "arm", "v7"))
3232
assert.True(t, opts.WantsPlatform("linux", "arm", "v8"))
33+
34+
assert.False(t, opts.WantsPlatform("linux", "arm", "v6"))
35+
assert.False(t, opts.WantsPlatform("linux", "arm", ""))
36+
assert.False(t, opts.WantsPlatform("linux", "", ""))
37+
38+
assert.False(t, opts.WantsPlatform("linux", "amd64", "v7"))
39+
assert.False(t, opts.WantsPlatform("linux", "amd64", ""))
40+
41+
assert.False(t, opts.WantsPlatform("darwin", "arm", "v7"))
42+
assert.False(t, opts.WantsPlatform("darwin", "arm", ""))
43+
})
44+
t.Run("Platform lenient match", func(t *testing.T) {
45+
opts := &ManifestOptions{}
46+
opts = opts.WithPlatform("linux", "arm", "")
47+
opts = opts.WithPlatform("linux", "arm", "v7")
48+
assert.True(t, opts.WantsPlatform("linux", "arm", "v8"))
49+
assert.True(t, opts.WantsPlatform("linux", "arm", "v7"))
50+
assert.True(t, opts.WantsPlatform("linux", "arm", ""))
3351
})
3452
t.Run("Uninitialized options", func(t *testing.T) {
3553
opts := &ManifestOptions{}

pkg/registry/client.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ type registryClient struct {
6464
}
6565

6666
// credentials is an implementation of distribution/V3/session struct
67-
// to mangage registry credentials and token
67+
// to manage registry credentials and token
6868
type credentials struct {
6969
username string
7070
password string
@@ -306,8 +306,8 @@ func (client *registryClient) TagMetadata(manifest distribution.Manifest, opts *
306306
}
307307

308308
if !opts.WantsPlatform(info.OS, info.Arch, info.Variant) {
309-
logCtx.Debugf("ignoring v2 manifest %v. Manifest platform: %s/%s, requested: %s",
310-
ti.EncodedDigest(), info.OS, info.Arch, strings.Join(opts.Platforms(), ","))
309+
logCtx.Debugf("ignoring v2 manifest %v. Manifest platform: %s, requested: %s",
310+
ti.EncodedDigest(), options.PlatformKey(info.OS, info.Arch, info.Variant), strings.Join(opts.Platforms(), ","))
311311
return nil, nil
312312
}
313313

@@ -338,8 +338,8 @@ func (client *registryClient) TagMetadata(manifest distribution.Manifest, opts *
338338
}
339339

340340
if !opts.WantsPlatform(info.OS, info.Arch, info.Variant) {
341-
logCtx.Debugf("ignoring OCI manifest %v. Manifest platform: %s/%s, requested: %s",
342-
ti.EncodedDigest(), info.OS, info.Arch, strings.Join(opts.Platforms(), ","))
341+
logCtx.Debugf("ignoring OCI manifest %v. Manifest platform: %s, requested: %s",
342+
ti.EncodedDigest(), options.PlatformKey(info.OS, info.Arch, info.Variant), strings.Join(opts.Platforms(), ","))
343343
return nil, nil
344344
}
345345

@@ -367,19 +367,20 @@ func TagInfoFromReferences(client *registryClient, opts *options.ManifestOptions
367367
refArch = ref.Platform.Architecture
368368
refVariant = ref.Platform.Variant
369369
}
370-
platforms = append(platforms, refOS+"/"+refArch)
371-
logCtx.Tracef("Found %s", options.PlatformKey(refOS, refArch, refVariant))
370+
platform1 := options.PlatformKey(refOS, refArch, refVariant)
371+
platforms = append(platforms, platform1)
372+
logCtx.Tracef("Found %s", platform1)
372373
if !opts.WantsPlatform(refOS, refArch, refVariant) {
373374
logCtx.Tracef("Ignoring referenced manifest %v because platform %s does not match any of: %s",
374375
ref.Digest,
375-
options.PlatformKey(refOS, refArch, refVariant),
376+
platform1,
376377
strings.Join(opts.Platforms(), ","))
377378
continue
378379
}
379380
ml = append(ml, ref)
380381
}
381382

382-
// We need at least one reference that matches requested plaforms
383+
// We need at least one reference that matches requested platforms
383384
if len(ml) == 0 {
384385
logCtx.Debugf("Manifest list did not contain any usable reference. Platforms requested: (%s), platforms included: (%s)",
385386
strings.Join(opts.Platforms(), ","), strings.Join(platforms, ","))

0 commit comments

Comments
 (0)