|
4 | 4 | "crypto/sha256"
|
5 | 5 | "fmt"
|
6 | 6 | "io"
|
| 7 | + "runtime" |
7 | 8 |
|
8 | 9 | imageManifest "github.com/containers/image/v5/manifest"
|
9 | 10 | "github.com/docker/distribution"
|
@@ -153,6 +154,34 @@ func renderDigest(manifest payloadGetter) (digest.Digest, error) {
|
153 | 154 | return dig, nil
|
154 | 155 | }
|
155 | 156 |
|
| 157 | +func handleManifestLists(reg types.Registry, remote, ref string, manifests []manifestlist.ManifestDescriptor) (digest.Digest, []string, error) { |
| 158 | + if len(manifests) == 0 { |
| 159 | + return "", nil, errors.Errorf("no valid manifests found for %s:%s", remote, ref) |
| 160 | + } |
| 161 | + if len(manifests) == 1 { |
| 162 | + return handleManifest(reg, manifests[0].MediaType, remote, manifests[0].Digest.String()) |
| 163 | + } |
| 164 | + var amdManifest manifestlist.ManifestDescriptor |
| 165 | + var foundAMD bool |
| 166 | + for _, m := range manifests { |
| 167 | + if m.Platform.OS != "linux" { |
| 168 | + continue |
| 169 | + } |
| 170 | + // Matching platform for GOARCH takes priority so return immediately |
| 171 | + if m.Platform.Architecture == runtime.GOARCH { |
| 172 | + return handleManifest(reg, m.MediaType, remote, m.Digest.String()) |
| 173 | + } |
| 174 | + if m.Platform.Architecture == "amd64" { |
| 175 | + foundAMD = true |
| 176 | + amdManifest = m |
| 177 | + } |
| 178 | + } |
| 179 | + if foundAMD { |
| 180 | + return handleManifest(reg, amdManifest.MediaType, remote, amdManifest.Digest.String()) |
| 181 | + } |
| 182 | + return "", nil, errors.Errorf("no manifest in list matched linux and amd64 or %s architectures: %s:%s", runtime.GOARCH, remote, ref) |
| 183 | +} |
| 184 | + |
156 | 185 | func handleManifest(reg types.Registry, manifestType, remote, ref string) (digest.Digest, []string, error) {
|
157 | 186 | switch manifestType {
|
158 | 187 | case manifestV1.MediaTypeManifest:
|
@@ -203,25 +232,13 @@ func handleManifest(reg types.Registry, manifestType, remote, ref string) (diges
|
203 | 232 | if err != nil {
|
204 | 233 | return "", nil, err
|
205 | 234 | }
|
206 |
| - for _, manifest := range manifestList.Manifests { |
207 |
| - // TODO(ROX-13284): Support multi-arch images. |
208 |
| - if manifest.Platform.OS == "linux" && manifest.Platform.Architecture == "amd64" { |
209 |
| - return handleManifest(reg, manifest.MediaType, remote, manifest.Digest.String()) |
210 |
| - } |
211 |
| - } |
212 |
| - return "", nil, errors.New("No corresponding manifest found from Docker manifest list object") |
| 235 | + return handleManifestLists(reg, remote, ref, manifestList.Manifests) |
213 | 236 | case registry.MediaTypeImageIndex:
|
214 | 237 | imageIndex, err := reg.ImageIndex(remote, ref)
|
215 | 238 | if err != nil {
|
216 | 239 | return "", nil, err
|
217 | 240 | }
|
218 |
| - for _, manifest := range imageIndex.Manifests { |
219 |
| - // TODO(ROX-13284): Support multi-arch images. |
220 |
| - if manifest.Platform.OS == "linux" && manifest.Platform.Architecture == "amd64" { |
221 |
| - return handleManifest(reg, manifest.MediaType, remote, manifest.Digest.String()) |
222 |
| - } |
223 |
| - } |
224 |
| - return "", nil, errors.New("No corresponding manifest found from OCI image index object") |
| 241 | + return handleManifestLists(reg, remote, ref, imageIndex.Manifests) |
225 | 242 | default:
|
226 | 243 | return "", nil, fmt.Errorf("Could not parse manifest type %q", manifestType)
|
227 | 244 | }
|
|
0 commit comments