summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Bye <8467862+jessebye@users.noreply.github.com>2023-09-21 10:45:11 -0700
committerGitHub <noreply@github.com>2023-09-21 13:45:11 -0400
commit420bd97b57d2d652034f4d1e178ee0568003d7aa (patch)
tree3dbd39ebf6bba26e85cccc715e4b08aac6141897
parent202f6bf966566f8a7f9186dced962e517ceb4a3f (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.go2
-rw-r--r--pkg/registry/client.go136
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