Skip to content

Commit 63d1965

Browse files
camilamacedo86ci-robot
authored andcommitted
UPSTREAM: <carry>: [Default Catalog Consistency Test] (feat) add check to validate multi-arch support
1 parent 5e6f946 commit 63d1965

File tree

2 files changed

+84
-16
lines changed

2 files changed

+84
-16
lines changed

openshift/default-catalog-consistency/pkg/check/image.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ import (
88
"sort"
99
"strings"
1010

11+
"github.com/containers/image/v5/docker"
1112
"github.com/containers/image/v5/manifest"
13+
"github.com/containers/image/v5/types"
1214
specsgov1 "github.com/opencontainers/image-spec/specs-go/v1"
1315
"oras.land/oras-go/v2"
1416
)
@@ -112,6 +114,67 @@ func ImageHasLabels(expectedLabels map[string]string) ImageCheck {
112114
}
113115
}
114116

117+
// RequiredPlatforms is a list of platforms that are required for the image to be considered valid.
118+
var RequiredPlatforms = []specsgov1.Platform{
119+
{OS: "linux", Architecture: "amd64"},
120+
{OS: "linux", Architecture: "arm64"},
121+
{OS: "linux", Architecture: "ppc64le"},
122+
{OS: "linux", Architecture: "s390x"},
123+
}
124+
125+
// ImageSupportsMultiArch verifies multi-arch support by inspecting the remote image manifest
126+
// list directly. We don’t use extract.UnpackImage and the check interfaces here because it picks
127+
// one platform based on OSChoice. On macOS, this fails if the image doesn’t support darwin/arm64
128+
// or darwin/amd64 and to make easier develop and test on macOS we keep the check independent of
129+
// the unpacking logic where we set OSChoice = "linux" to avoid OS mismatch errors.
130+
func ImageSupportsMultiArch(imageRef string, expected []specsgov1.Platform, sysCtx *types.SystemContext) ImageCheck {
131+
return ImageCheck{
132+
Name: "ImageSupportsMultiArch",
133+
// Do not use the unpacked image, but pull the manifest list directly from the remote.
134+
Fn: func(ctx context.Context, _ specsgov1.Descriptor, _ oras.ReadOnlyTarget) error {
135+
ref, err := docker.ParseReference("//" + imageRef)
136+
if err != nil {
137+
return fmt.Errorf("parse image ref: %w", err)
138+
}
139+
140+
src, err := ref.NewImageSource(ctx, sysCtx)
141+
if err != nil {
142+
return fmt.Errorf("new image source: %w", err)
143+
}
144+
defer src.Close()
145+
146+
manifestBytes, _, err := src.GetManifest(ctx, nil)
147+
if err != nil {
148+
return fmt.Errorf("get manifest: %w", err)
149+
}
150+
151+
mf, err := manifest.Schema2ListFromManifest(manifestBytes)
152+
if err != nil {
153+
return fmt.Errorf("parse multiarch list: %w", err)
154+
}
155+
156+
found := map[string]struct{}{}
157+
for _, desc := range mf.Manifests {
158+
key := fmt.Sprintf("%s/%s", desc.Platform.OS, desc.Platform.Architecture)
159+
found[key] = struct{}{}
160+
}
161+
162+
var missing []string
163+
for _, p := range expected {
164+
key := fmt.Sprintf("%s/%s", p.OS, p.Architecture)
165+
if _, ok := found[key]; !ok {
166+
missing = append(missing, key)
167+
}
168+
}
169+
170+
if len(missing) > 0 {
171+
return fmt.Errorf("missing required platforms: %v", missing)
172+
}
173+
return nil
174+
},
175+
}
176+
}
177+
115178
func isValidMediaType(m specsgov1.Manifest) error {
116179
switch m.MediaType {
117180
case specsgov1.MediaTypeImageManifest, manifest.DockerV2Schema2MediaType:

openshift/default-catalog-consistency/test/validate/suite_test.go

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
. "github.com/onsi/gomega"
1111

1212
"github.com/containers/image/v5/types"
13+
specsgov1 "github.com/opencontainers/image-spec/specs-go/v1"
1314

1415
"github/operator-framework-operator-controller/openshift/default-catalog-consistency/pkg/check"
1516
"github/operator-framework-operator-controller/openshift/default-catalog-consistency/pkg/extract"
@@ -28,32 +29,36 @@ var _ = Describe("Check Catalog Consistency", func() {
2829
Expect(images).ToNot(BeEmpty(), "no images found")
2930
authPath := os.Getenv("REGISTRY_AUTH_FILE")
3031

31-
// Force image resolution to Linux to avoid OS mismatch errors on macOS,
32-
// like: "no image found for architecture 'arm64', OS 'darwin'".
33-
//
34-
// Setting OSChoice = "linux" ensures we always get a Linux image,
35-
// even when running on macOS.
36-
//
37-
// This skips the full multi-arch index and gives us just one manifest.
38-
// To check all supported architectures (e.g., amd64, arm64, ppc64le, s390x),
39-
// we’d need to avoid setting OSChoice and inspect the full index manually.
40-
//
41-
// TODO: Update this to support checking all architectures.
42-
// See: https://issues.redhat.com/browse/OPRUN-3793
43-
sysCtx := &types.SystemContext{
44-
OSChoice: "linux",
45-
}
32+
sysCtx := &types.SystemContext{}
4633
if authPath != "" {
4734
fmt.Println("Using registry auth file:", authPath)
4835
sysCtx.AuthFilePath = authPath
4936
}
5037

5138
for _, url := range images {
5239
name := utils.ImageNameFromRef(url)
40+
ctx := context.Background()
41+
42+
It(fmt.Sprintf("validates multiarch support for image: %s", name), func() {
43+
By(fmt.Sprintf("Validating image: %s", url))
44+
err := check.ImageSupportsMultiArch(
45+
url,
46+
check.RequiredPlatforms,
47+
sysCtx,
48+
).Fn(ctx, specsgov1.Descriptor{}, nil)
49+
Expect(err).ToNot(HaveOccurred())
50+
})
5351

5452
It(fmt.Sprintf("validates image: %s", name), func() {
55-
ctx := context.Background()
5653
By(fmt.Sprintf("Validating image: %s", url))
54+
// Force image resolution to Linux to avoid OS mismatch errors on macOS,
55+
// like: "no image found for architecture 'arm64', OS 'darwin'".
56+
//
57+
// Setting OSChoice = "linux" ensures we always get a Linux image,
58+
// even when running on macOS.
59+
//
60+
// This skips the full multi-arch index and gives us just one manifest.
61+
sysCtx.OSChoice = "linux"
5762

5863
extractedImage, err := extract.UnpackImage(ctx, url, name, sysCtx)
5964
Expect(err).ToNot(HaveOccurred())

0 commit comments

Comments
 (0)