diff --git a/pkg/v1/match/match.go b/pkg/v1/match/match.go index 39fae5e6d..0f886667a 100644 --- a/pkg/v1/match/match.go +++ b/pkg/v1/match/match.go @@ -44,19 +44,24 @@ func Annotation(key, value string) Matcher { } } -// Platform returns a match.Matcher that matches on the provided platform. +// Platforms returns a match.Matcher that matches on any one of the provided platforms. // Ignores any descriptors that do not have a platform. -func Platform(platform v1.Platform) Matcher { +func Platforms(platforms ...v1.Platform) Matcher { return func(desc v1.Descriptor) bool { if desc.Platform == nil { return false } - return desc.Platform.Equals(platform) + for _, platform := range platforms { + if desc.Platform.Equals(platform) { + return true + } + } + return false } } // MediaTypes returns a match.Matcher that matches at least one of the provided media types. -func MediaTypes(mediaTypes []string) Matcher { +func MediaTypes(mediaTypes ...string) Matcher { mts := map[string]bool{} for _, media := range mediaTypes { mts[media] = true @@ -71,3 +76,15 @@ func MediaTypes(mediaTypes []string) Matcher { return false } } + +// Digests returns a match.Matcher that matches at least one of the provided Digests +func Digests(digests ...v1.Hash) Matcher { + digs := map[v1.Hash]bool{} + for _, digest := range digests { + digs[digest] = true + } + return func(desc v1.Descriptor) bool { + _, ok := digs[desc.Digest] + return ok + } +} diff --git a/pkg/v1/match/match_test.go b/pkg/v1/match/match_test.go index cbdee93d5..c54319d81 100644 --- a/pkg/v1/match/match_test.go +++ b/pkg/v1/match/match_test.go @@ -64,23 +64,23 @@ func TestAnnotation(t *testing.T) { } } -func TestPlatform(t *testing.T) { +func TestPlatforms(t *testing.T) { tests := []struct { - desc v1.Descriptor - platform v1.Platform - match bool + desc v1.Descriptor + platforms []v1.Platform + match bool }{ - {v1.Descriptor{Platform: &v1.Platform{Architecture: "amd64", OS: "linux"}}, v1.Platform{Architecture: "amd64", OS: "linux"}, true}, - {v1.Descriptor{Platform: &v1.Platform{Architecture: "amd64", OS: "linux"}}, v1.Platform{Architecture: "arm64", OS: "linux"}, false}, - {v1.Descriptor{Platform: &v1.Platform{OS: "linux"}}, v1.Platform{Architecture: "arm64", OS: "linux"}, false}, - {v1.Descriptor{Platform: &v1.Platform{}}, v1.Platform{Architecture: "arm64", OS: "linux"}, false}, - {v1.Descriptor{Platform: nil}, v1.Platform{Architecture: "arm64", OS: "linux"}, false}, - {v1.Descriptor{}, v1.Platform{Architecture: "arm64", OS: "linux"}, false}, + {v1.Descriptor{Platform: &v1.Platform{Architecture: "amd64", OS: "linux"}}, []v1.Platform{{Architecture: "amd64", OS: "darwin"}, {Architecture: "amd64", OS: "linux"}}, true}, + {v1.Descriptor{Platform: &v1.Platform{Architecture: "amd64", OS: "linux"}}, []v1.Platform{{Architecture: "arm64", OS: "linux"}, {Architecture: "s390x", OS: "linux"}}, false}, + {v1.Descriptor{Platform: &v1.Platform{OS: "linux"}}, []v1.Platform{{Architecture: "arm64", OS: "linux"}}, false}, + {v1.Descriptor{Platform: &v1.Platform{}}, []v1.Platform{{Architecture: "arm64", OS: "linux"}}, false}, + {v1.Descriptor{Platform: nil}, []v1.Platform{{Architecture: "arm64", OS: "linux"}}, false}, + {v1.Descriptor{}, []v1.Platform{{Architecture: "arm64", OS: "linux"}}, false}, } for i, tt := range tests { - f := match.Platform(tt.platform) + f := match.Platforms(tt.platforms...) if match := f(tt.desc); match != tt.match { - t.Errorf("%d: mismatched, got %v expected %v for desc %#v platform %#v", i, match, tt.match, tt.desc, tt.platform) + t.Errorf("%d: mismatched, got %v expected %v for desc %#v platform %#v", i, match, tt.match, tt.desc, tt.platforms) } } } @@ -98,9 +98,34 @@ func TestMediaTypes(t *testing.T) { {v1.Descriptor{}, []string{string(types.OCIManifestSchema1), string(types.OCIImageIndex)}, false}, } for i, tt := range tests { - f := match.MediaTypes(tt.mediaTypes) + f := match.MediaTypes(tt.mediaTypes...) if match := f(tt.desc); match != tt.match { t.Errorf("%d: mismatched, got %v expected %v for desc %#v mediaTypes %#v", i, match, tt.match, tt.desc, tt.mediaTypes) } } } + +func TestDigests(t *testing.T) { + hashes := []string{ + "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef", + "abcde1111111222f0123456789abcdef0123456789abcdef0123456789abcdef", + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", + } + algo := "sha256" + + tests := []struct { + desc v1.Descriptor + digests []v1.Hash + match bool + }{ + {v1.Descriptor{Digest: v1.Hash{Algorithm: algo, Hex: hashes[0]}}, []v1.Hash{{Algorithm: algo, Hex: hashes[0]}, {Algorithm: algo, Hex: hashes[1]}}, true}, + {v1.Descriptor{Digest: v1.Hash{Algorithm: algo, Hex: hashes[1]}}, []v1.Hash{{Algorithm: algo, Hex: hashes[0]}, {Algorithm: algo, Hex: hashes[1]}}, true}, + {v1.Descriptor{Digest: v1.Hash{Algorithm: algo, Hex: hashes[2]}}, []v1.Hash{{Algorithm: algo, Hex: hashes[0]}, {Algorithm: algo, Hex: hashes[1]}}, false}, + } + for i, tt := range tests { + f := match.Digests(tt.digests...) + if match := f(tt.desc); match != tt.match { + t.Errorf("%d: mismatched, got %v expected %v for desc %#v digests %#v", i, match, tt.match, tt.desc, tt.digests) + } + } +}