diff options
| author | Jesse Bye <8467862+jessebye@users.noreply.github.com> | 2023-09-21 10:45:11 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-09-21 13:45:11 -0400 |
| commit | 420bd97b57d2d652034f4d1e178ee0568003d7aa (patch) | |
| tree | 3dbd39ebf6bba26e85cccc715e4b08aac6141897 | |
| parent | 202f6bf966566f8a7f9186dced962e517ceb4a3f (diff) | |
fix: Add support for ocischema.DeserializedImageIndex manifest type (#618)
* fix: Add support for ocischema.DeserializedImageIndex manifest type
Signed-off-by: Jesse Bye <8467862+jessebye@users.noreply.github.com>
* more informative error logging
Signed-off-by: Jesse Bye <8467862+jessebye@users.noreply.github.com>
---------
Signed-off-by: Jesse Bye <8467862+jessebye@users.noreply.github.com>
| -rw-r--r-- | pkg/argocd/update_test.go | 2 | ||||
| -rw-r--r-- | pkg/registry/client.go | 136 |
2 files changed, 83 insertions, 55 deletions
diff --git a/pkg/argocd/update_test.go b/pkg/argocd/update_test.go index 1d26dd5..6517025 100644 --- a/pkg/argocd/update_test.go +++ b/pkg/argocd/update_test.go @@ -1739,7 +1739,7 @@ func Test_GetGitCreds(t *testing.T) { }, }, Spec: v1alpha1.ApplicationSpec{ - Source: v1alpha1.ApplicationSource{ + Source: &v1alpha1.ApplicationSource{ RepoURL: "https://example-helm-repo.com/example", TargetRevision: "main", }, diff --git a/pkg/registry/client.go b/pkg/registry/client.go index 8673752..b92b291 100644 --- a/pkg/registry/client.go +++ b/pkg/registry/client.go @@ -244,8 +244,6 @@ func (client *registryClient) TagMetadata(manifest distribution.Manifest, opts * case *manifestlist.DeserializedManifestList: var list manifestlist.DeserializedManifestList = *deserialized - var ml []distribution.Descriptor - platforms := []string{} // List must contain at least one image manifest if len(list.Manifests) == 0 { @@ -262,63 +260,27 @@ func (client *registryClient) TagMetadata(manifest distribution.Manifest, opts * logCtx.Tracef("SHA256 of manifest parent is %v", ti.EncodedDigest()) - for _, ref := range list.References() { - platforms = append(platforms, ref.Platform.OS+"/"+ref.Platform.Architecture) - logCtx.Tracef("Found %s", options.PlatformKey(ref.Platform.OS, ref.Platform.Architecture, ref.Platform.Variant)) - if !opts.WantsPlatform(ref.Platform.OS, ref.Platform.Architecture, ref.Platform.Variant) { - logCtx.Tracef("Ignoring referenced manifest %v because platform %s does not match any of: %s", - ref.Digest, - options.PlatformKey(ref.Platform.OS, ref.Platform.Architecture, ref.Platform.Variant), - strings.Join(opts.Platforms(), ",")) - continue - } - ml = append(ml, ref) - } + return TagInfoFromReferences(client, opts, logCtx, ti, list.References()) - // We need at least one reference that matches requested plaforms - if len(ml) == 0 { - logCtx.Debugf("Manifest list did not contain any usable reference. Platforms requested: (%s), platforms included: (%s)", - strings.Join(opts.Platforms(), ","), strings.Join(platforms, ",")) - return nil, nil - } + case *ocischema.DeserializedImageIndex: + var index ocischema.DeserializedImageIndex = *deserialized - // For some strategies, we do not need to fetch metadata for further - // processing. - if !opts.WantsMetadata() { - return ti, nil + // Index must contain at least one image manifest + if len(index.Manifests) == 0 { + return nil, fmt.Errorf("empty index not supported") } - // Loop through all referenced manifests to get their metadata. We only - // consider manifests for platforms we are interested in. - for _, ref := range ml { - logCtx.Tracef("Inspecting metadata of reference: %v", ref.Digest) - - man, err := client.ManifestForDigest(ref.Digest) - if err != nil { - return nil, fmt.Errorf("could not fetch manifest %v: %v", ref.Digest, err) - } - - cti, err := client.TagMetadata(man, opts) - if err != nil { - return nil, fmt.Errorf("could not fetch metadata for manifest %v: %v", ref.Digest, err) - } - - // We save the timestamp of the most recent pushed manifest for any - // given reference, if the metadata for the tag was correctly - // retrieved. This is important for the latest update strategy to - // be able to handle multi-arch images. The latest strategy will - // consider the most recent reference from a manifest list. - if cti != nil { - if cti.CreatedAt.After(ti.CreatedAt) { - ti.CreatedAt = cti.CreatedAt - } - } else { - logCtx.Warnf("returned metadata for manifest %v is nil, this should not happen.", ref.Digest) - continue - } + // We use the SHA from the manifest index to let the container engine + // decide which image to pull, in case of multi-arch clusters. + _, mBytes, err := index.Payload() + if err != nil { + return nil, fmt.Errorf("could not retrieve index payload: %v", err) } + ti.Digest = sha256.Sum256(mBytes) - return ti, nil + logCtx.Tracef("SHA256 of manifest parent is %v", ti.EncodedDigest()) + + return TagInfoFromReferences(client, opts, logCtx, ti, index.References()) case *schema2.DeserializedManifest: var man schema2.Manifest = deserialized.Manifest @@ -387,8 +349,74 @@ func (client *registryClient) TagMetadata(manifest distribution.Manifest, opts * return ti, nil default: - return nil, fmt.Errorf("invalid manifest type") + return nil, fmt.Errorf("invalid manifest type %T", manifest) + } +} + +// TagInfoFromReferences is a helper method to retrieve metadata for a given +// list of references. It will return the most recent pushed manifest from the +// list of references. +func TagInfoFromReferences(client *registryClient, opts *options.ManifestOptions, logCtx *log.LogContext, ti *tag.TagInfo, references []distribution.Descriptor) (*tag.TagInfo, error) { + var ml []distribution.Descriptor + platforms := []string{} + + for _, ref := range references { + platforms = append(platforms, ref.Platform.OS+"/"+ref.Platform.Architecture) + logCtx.Tracef("Found %s", options.PlatformKey(ref.Platform.OS, ref.Platform.Architecture, ref.Platform.Variant)) + if !opts.WantsPlatform(ref.Platform.OS, ref.Platform.Architecture, ref.Platform.Variant) { + logCtx.Tracef("Ignoring referenced manifest %v because platform %s does not match any of: %s", + ref.Digest, + options.PlatformKey(ref.Platform.OS, ref.Platform.Architecture, ref.Platform.Variant), + strings.Join(opts.Platforms(), ",")) + continue + } + ml = append(ml, ref) + } + + // We need at least one reference that matches requested plaforms + if len(ml) == 0 { + logCtx.Debugf("Manifest list did not contain any usable reference. Platforms requested: (%s), platforms included: (%s)", + strings.Join(opts.Platforms(), ","), strings.Join(platforms, ",")) + return nil, nil + } + + // For some strategies, we do not need to fetch metadata for further + // processing. + if !opts.WantsMetadata() { + return ti, nil } + + // Loop through all referenced manifests to get their metadata. We only + // consider manifests for platforms we are interested in. + for _, ref := range ml { + logCtx.Tracef("Inspecting metadata of reference: %v", ref.Digest) + + man, err := client.ManifestForDigest(ref.Digest) + if err != nil { + return nil, fmt.Errorf("could not fetch manifest %v: %v", ref.Digest, err) + } + + cti, err := client.TagMetadata(man, opts) + if err != nil { + return nil, fmt.Errorf("could not fetch metadata for manifest %v: %v", ref.Digest, err) + } + + // We save the timestamp of the most recent pushed manifest for any + // given reference, if the metadata for the tag was correctly + // retrieved. This is important for the latest update strategy to + // be able to handle multi-arch images. The latest strategy will + // consider the most recent reference from an image index. + if cti != nil { + if cti.CreatedAt.After(ti.CreatedAt) { + ti.CreatedAt = cti.CreatedAt + } + } else { + logCtx.Warnf("returned metadata for manifest %v is nil, this should not happen.", ref.Digest) + continue + } + } + + return ti, nil } // Implementation of ping method to intialize the challenge list |
