-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Attempt to retrieve manifest from local repo for manifest requests to proxy #21123
Conversation
c301366
to
dd9af57
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #21123 +/- ##
===========================================
+ Coverage 45.36% 66.10% +20.73%
===========================================
Files 244 1049 +805
Lines 13333 114679 +101346
Branches 2719 2867 +148
===========================================
+ Hits 6049 75804 +69755
- Misses 6983 34733 +27750
- Partials 301 4142 +3841
Flags with carried forward coverage won't be shown. Click here to find out more.
|
… proxy Signed-off-by: Raphael Zöllner <raphael.zoellner@regiocom.com>
dd9af57
to
0a326e6
Compare
@@ -175,35 +213,64 @@ func (c *controller) UseLocalManifest(ctx context.Context, art lib.ArtifactInfo, | |||
return false, nil, errors.NotFoundError(fmt.Errorf("repo %v, tag %v not found", art.Repository, art.Tag)) | |||
} | |||
|
|||
// Use digest to retrieve manifest, digest is more stable than tag, because tag could be updated |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what you changed in this part is already covered previous line 202
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previous line 202 is the return of a manifest list if it could be fetched from the cache.
harbor/src/controller/proxy/controller.go
Line 202 in 62d1d93
return true, &ManifestList{content, string(desc.Digest), contentType}, nil |
But since manifests are not cached (in redis) this logs a not found error
in previous line 190 for GET .../manifests/{tag} requests referencing a tag.
harbor/src/controller/proxy/controller.go
Line 190 in 62d1d93
log.Debugf("Digest is not found in manifest list cache, key=cache:%v", manifestListKey(art.Repository, art)) |
and returns false (when
a
is nil, because the artifact with the matching digest in the local repository must not have an associated tag) and without a manifest in line 194.harbor/src/controller/proxy/controller.go
Line 194 in 62d1d93
return a != nil && string(desc.Digest) == a.Digest, nil, nil |
This then leads to the manifest not being served from the local repository
harbor/src/server/middleware/repoproxy/proxy.go
Lines 186 to 210 in 62d1d93
if useLocal { | |
if man != nil { | |
w.Header().Set(contentLength, fmt.Sprintf("%v", len(man.Content))) | |
w.Header().Set(contentType, man.ContentType) | |
w.Header().Set(dockerContentDigest, man.Digest) | |
w.Header().Set(etag, man.Digest) | |
if r.Method == http.MethodGet { | |
_, err = w.Write(man.Content) | |
if err != nil { | |
return err | |
} | |
} | |
return nil | |
} | |
next.ServeHTTP(w, r) | |
return nil | |
} | |
log.Debugf("the tag is %v, digest is %v", art.Tag, art.Digest) | |
if r.Method == http.MethodHead { | |
err = proxyManifestHead(ctx, w, proxyCtl, p, art, remote) | |
} else if r.Method == http.MethodGet { | |
log.Warningf("Artifact: %v:%v, digest:%v is not found in proxy cache, fetch it from remote repo", art.Repository, art.Tag, art.Digest) | |
err = proxyManifestGet(ctx, w, proxyCtl, p, art, remote) | |
} |
My intention with this part in new lines 223-234 was to check prior to the manifest list cache if a manifest with the digest already exists in the local repository and if found return it.
Wouldn't this extend the current behavior for that case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I'm new to harbor and I think my proposed implementation would skip other middlewares, which might be a problem.
harbor/src/server/registry/route.go
Lines 51 to 67 in 62d1d93
// manifest | |
root.NewRoute(). | |
Method(http.MethodGet). | |
Path("/*/manifests/:reference"). | |
Middleware(metric.InjectOpIDMiddleware(metric.ManifestOperationID)). | |
Middleware(repoproxy.ManifestMiddleware()). | |
Middleware(contenttrust.ContentTrust()). | |
Middleware(vulnerable.Middleware()). | |
HandlerFunc(getManifest) | |
root.NewRoute(). | |
Method(http.MethodHead). | |
Path("/*/manifests/:reference"). | |
Middleware(metric.InjectOpIDMiddleware(metric.ManifestOperationID)). | |
Middleware(repoproxy.ManifestMiddleware()). | |
Middleware(contenttrust.ContentTrust()). | |
Middleware(vulnerable.Middleware()). | |
HandlerFunc(getManifest) |
I will close this PR.
I think to solve this one would need to make sure that the initally proxied and cached artifact in the local repository will be referenced by the tag.
src/controller/proxy/controller.go
Outdated
} | ||
|
||
func manifestListKey(repo string, art lib.ArtifactInfo) string { | ||
// actual redis key format is cache:manifestlist:<repo name>:<tag> or cache:manifestlist:<repo name>:sha256:xxxx | ||
// actual redis key format is cache:manifest:<repo name>:<tag> or cache:manifest:<repo name>:sha256:xxxx |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The manifestListKey is only cache the manfest List, not used to cache a normal manifest
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, updating this comment was a mistake. I will revert it.
Signed-off-by: Raphael Zöllner <raphael.zoellner@regiocom.com>
Signed-off-by: Raphael Zöllner <raphael.zoellner@regiocom.com>
ae91368
to
dc4b936
Compare
Comprehensive Summary of your change
Harbor Proxies will serve manifests located in the local repository if the digest of the local manifest matches the digest of the remote manifest.
Issue being fixed
Fixes #21122
Please indicate you've done the following: