Skip to content

Commit 420bd97

Browse files
authored
fix: Add support for ocischema.DeserializedImageIndex manifest type (#618)
* fix: Add support for ocischema.DeserializedImageIndex manifest type Signed-off-by: Jesse Bye <[email protected]> * more informative error logging Signed-off-by: Jesse Bye <[email protected]> --------- Signed-off-by: Jesse Bye <[email protected]>
1 parent 202f6bf commit 420bd97

File tree

2 files changed

+83
-55
lines changed

2 files changed

+83
-55
lines changed

pkg/argocd/update_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1739,7 +1739,7 @@ func Test_GetGitCreds(t *testing.T) {
17391739
},
17401740
},
17411741
Spec: v1alpha1.ApplicationSpec{
1742-
Source: v1alpha1.ApplicationSource{
1742+
Source: &v1alpha1.ApplicationSource{
17431743
RepoURL: "https://example-helm-repo.com/example",
17441744
TargetRevision: "main",
17451745
},

pkg/registry/client.go

Lines changed: 82 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -244,8 +244,6 @@ func (client *registryClient) TagMetadata(manifest distribution.Manifest, opts *
244244

245245
case *manifestlist.DeserializedManifestList:
246246
var list manifestlist.DeserializedManifestList = *deserialized
247-
var ml []distribution.Descriptor
248-
platforms := []string{}
249247

250248
// List must contain at least one image manifest
251249
if len(list.Manifests) == 0 {
@@ -262,63 +260,27 @@ func (client *registryClient) TagMetadata(manifest distribution.Manifest, opts *
262260

263261
logCtx.Tracef("SHA256 of manifest parent is %v", ti.EncodedDigest())
264262

265-
for _, ref := range list.References() {
266-
platforms = append(platforms, ref.Platform.OS+"/"+ref.Platform.Architecture)
267-
logCtx.Tracef("Found %s", options.PlatformKey(ref.Platform.OS, ref.Platform.Architecture, ref.Platform.Variant))
268-
if !opts.WantsPlatform(ref.Platform.OS, ref.Platform.Architecture, ref.Platform.Variant) {
269-
logCtx.Tracef("Ignoring referenced manifest %v because platform %s does not match any of: %s",
270-
ref.Digest,
271-
options.PlatformKey(ref.Platform.OS, ref.Platform.Architecture, ref.Platform.Variant),
272-
strings.Join(opts.Platforms(), ","))
273-
continue
274-
}
275-
ml = append(ml, ref)
276-
}
263+
return TagInfoFromReferences(client, opts, logCtx, ti, list.References())
277264

278-
// We need at least one reference that matches requested plaforms
279-
if len(ml) == 0 {
280-
logCtx.Debugf("Manifest list did not contain any usable reference. Platforms requested: (%s), platforms included: (%s)",
281-
strings.Join(opts.Platforms(), ","), strings.Join(platforms, ","))
282-
return nil, nil
283-
}
265+
case *ocischema.DeserializedImageIndex:
266+
var index ocischema.DeserializedImageIndex = *deserialized
284267

285-
// For some strategies, we do not need to fetch metadata for further
286-
// processing.
287-
if !opts.WantsMetadata() {
288-
return ti, nil
268+
// Index must contain at least one image manifest
269+
if len(index.Manifests) == 0 {
270+
return nil, fmt.Errorf("empty index not supported")
289271
}
290272

291-
// Loop through all referenced manifests to get their metadata. We only
292-
// consider manifests for platforms we are interested in.
293-
for _, ref := range ml {
294-
logCtx.Tracef("Inspecting metadata of reference: %v", ref.Digest)
295-
296-
man, err := client.ManifestForDigest(ref.Digest)
297-
if err != nil {
298-
return nil, fmt.Errorf("could not fetch manifest %v: %v", ref.Digest, err)
299-
}
300-
301-
cti, err := client.TagMetadata(man, opts)
302-
if err != nil {
303-
return nil, fmt.Errorf("could not fetch metadata for manifest %v: %v", ref.Digest, err)
304-
}
305-
306-
// We save the timestamp of the most recent pushed manifest for any
307-
// given reference, if the metadata for the tag was correctly
308-
// retrieved. This is important for the latest update strategy to
309-
// be able to handle multi-arch images. The latest strategy will
310-
// consider the most recent reference from a manifest list.
311-
if cti != nil {
312-
if cti.CreatedAt.After(ti.CreatedAt) {
313-
ti.CreatedAt = cti.CreatedAt
314-
}
315-
} else {
316-
logCtx.Warnf("returned metadata for manifest %v is nil, this should not happen.", ref.Digest)
317-
continue
318-
}
273+
// We use the SHA from the manifest index to let the container engine
274+
// decide which image to pull, in case of multi-arch clusters.
275+
_, mBytes, err := index.Payload()
276+
if err != nil {
277+
return nil, fmt.Errorf("could not retrieve index payload: %v", err)
319278
}
279+
ti.Digest = sha256.Sum256(mBytes)
320280

321-
return ti, nil
281+
logCtx.Tracef("SHA256 of manifest parent is %v", ti.EncodedDigest())
282+
283+
return TagInfoFromReferences(client, opts, logCtx, ti, index.References())
322284

323285
case *schema2.DeserializedManifest:
324286
var man schema2.Manifest = deserialized.Manifest
@@ -387,8 +349,74 @@ func (client *registryClient) TagMetadata(manifest distribution.Manifest, opts *
387349

388350
return ti, nil
389351
default:
390-
return nil, fmt.Errorf("invalid manifest type")
352+
return nil, fmt.Errorf("invalid manifest type %T", manifest)
353+
}
354+
}
355+
356+
// TagInfoFromReferences is a helper method to retrieve metadata for a given
357+
// list of references. It will return the most recent pushed manifest from the
358+
// list of references.
359+
func TagInfoFromReferences(client *registryClient, opts *options.ManifestOptions, logCtx *log.LogContext, ti *tag.TagInfo, references []distribution.Descriptor) (*tag.TagInfo, error) {
360+
var ml []distribution.Descriptor
361+
platforms := []string{}
362+
363+
for _, ref := range references {
364+
platforms = append(platforms, ref.Platform.OS+"/"+ref.Platform.Architecture)
365+
logCtx.Tracef("Found %s", options.PlatformKey(ref.Platform.OS, ref.Platform.Architecture, ref.Platform.Variant))
366+
if !opts.WantsPlatform(ref.Platform.OS, ref.Platform.Architecture, ref.Platform.Variant) {
367+
logCtx.Tracef("Ignoring referenced manifest %v because platform %s does not match any of: %s",
368+
ref.Digest,
369+
options.PlatformKey(ref.Platform.OS, ref.Platform.Architecture, ref.Platform.Variant),
370+
strings.Join(opts.Platforms(), ","))
371+
continue
372+
}
373+
ml = append(ml, ref)
374+
}
375+
376+
// We need at least one reference that matches requested plaforms
377+
if len(ml) == 0 {
378+
logCtx.Debugf("Manifest list did not contain any usable reference. Platforms requested: (%s), platforms included: (%s)",
379+
strings.Join(opts.Platforms(), ","), strings.Join(platforms, ","))
380+
return nil, nil
381+
}
382+
383+
// For some strategies, we do not need to fetch metadata for further
384+
// processing.
385+
if !opts.WantsMetadata() {
386+
return ti, nil
391387
}
388+
389+
// Loop through all referenced manifests to get their metadata. We only
390+
// consider manifests for platforms we are interested in.
391+
for _, ref := range ml {
392+
logCtx.Tracef("Inspecting metadata of reference: %v", ref.Digest)
393+
394+
man, err := client.ManifestForDigest(ref.Digest)
395+
if err != nil {
396+
return nil, fmt.Errorf("could not fetch manifest %v: %v", ref.Digest, err)
397+
}
398+
399+
cti, err := client.TagMetadata(man, opts)
400+
if err != nil {
401+
return nil, fmt.Errorf("could not fetch metadata for manifest %v: %v", ref.Digest, err)
402+
}
403+
404+
// We save the timestamp of the most recent pushed manifest for any
405+
// given reference, if the metadata for the tag was correctly
406+
// retrieved. This is important for the latest update strategy to
407+
// be able to handle multi-arch images. The latest strategy will
408+
// consider the most recent reference from an image index.
409+
if cti != nil {
410+
if cti.CreatedAt.After(ti.CreatedAt) {
411+
ti.CreatedAt = cti.CreatedAt
412+
}
413+
} else {
414+
logCtx.Warnf("returned metadata for manifest %v is nil, this should not happen.", ref.Digest)
415+
continue
416+
}
417+
}
418+
419+
return ti, nil
392420
}
393421

394422
// Implementation of ping method to intialize the challenge list

0 commit comments

Comments
 (0)