From ce4cf85ba85e15f69130106e37321ee94da702d8 Mon Sep 17 00:00:00 2001 From: Ricardo Branco Date: Thu, 3 Nov 2022 20:47:07 +0100 Subject: [PATCH 1/2] Calculate digest if missing --- registry/digest.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/registry/digest.go b/registry/digest.go index 361ae4748..7a635ddb4 100644 --- a/registry/digest.go +++ b/registry/digest.go @@ -2,6 +2,7 @@ package registry import ( "context" + _ "crypto/sha256" "fmt" "net/http" @@ -36,5 +37,16 @@ func (r *Registry) Digest(ctx context.Context, image Image) (digest.Digest, erro return "", fmt.Errorf("got status code: %d", resp.StatusCode) } - return digest.Parse(resp.Header.Get("Docker-Content-Digest")) + d := resp.Header.Get("Docker-Content-Digest") + if d == "" { + // Get the v2 manifest. + m, err := r.Manifest(ctx, image.Path, image.Reference()) + if err != nil { + return "", err + } + _, p, _ := m.Payload() + return digest.FromBytes(p), nil + } + + return digest.Parse(d) } From c30f09c61c753605d4285a9fb42909b980db0d99 Mon Sep 17 00:00:00 2001 From: Ricardo Branco Date: Wed, 9 Nov 2022 21:11:43 +0100 Subject: [PATCH 2/2] Some registries return a digest only with the HEAD method --- registry/digest.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/registry/digest.go b/registry/digest.go index 7a635ddb4..b9f5da4a1 100644 --- a/registry/digest.go +++ b/registry/digest.go @@ -10,6 +10,8 @@ import ( digest "github.com/opencontainers/go-digest" ) +var useHead bool = true + // Digest returns the digest for an image. func (r *Registry) Digest(ctx context.Context, image Image) (digest.Digest, error) { if len(image.Digest) > 1 { @@ -38,6 +40,28 @@ func (r *Registry) Digest(ctx context.Context, image Image) (digest.Digest, erro } d := resp.Header.Get("Docker-Content-Digest") + if d == "" { + req, err := http.NewRequest("HEAD", url, nil) + if err != nil { + return "", err + } + + req.Header.Add("Accept", schema2.MediaTypeManifest) + resp, err := r.Client.Do(req.WithContext(ctx)) + if err != nil { + return "", err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusNotFound { + return "", fmt.Errorf("got status code: %d", resp.StatusCode) + } + + d = resp.Header.Get("Docker-Content-Digest") + if d == "" { + useHead = false + } + } if d == "" { // Get the v2 manifest. m, err := r.Manifest(ctx, image.Path, image.Reference())