Fix HEAD on cached container virtual registry manifests
What does this MR do and why?
Fixes cached manifest HEAD responses in the container virtual registry. containerd rejects them, so the first pull works and every later pull fails.
On a cache hit, HEAD returned Content-Length: 0 and no Docker-Content-Digest. containerd fails with "reports content size of zero". Two customers are blocked, and one is a POC. A cache miss works because we proxy the upstream response.
Cause
- No real Content-Length: on
HEAD, the controller still calledsend_uploadfor the cached file. The body was stripped, so the response had no realContent-Length. It also had aContent-Dispositionheader. - Missing digest: we built
Docker-Content-Digestfrom the upstream ETag. Upstreams like quay.io send no ETag, or send one that is not the digest. We dropped the header.
Fix
- Controller: on
HEADfor a cached file, setContent-Lengthfrom the stored size. SetContent-TypeandDocker-Content-Digest. Returnhead :okand do not send the file. The digest comes from the storeddigest, then falls back toupstream_etag. - Cache entry service: when we cache a manifest, store
sha256:<file sha256>as the digest. A manifest digest is the sha256 of its bytes. Workhorse already computes this on upload. The order is: digest from path, then manifest content digest, then ETag digest. - File request service: pass
digestandsizein the download payload.
There is no migration. The digest column already exists and has no uniqueness constraint.
Existing cache entries
- Old entries get the right
Content-Lengthat once. - They get a digest after we re-fetch them from upstream. That happens after the cache validity period, which is 24 hours by default.
- Upstreams with cache validity 0 never re-fetch. Their old entries need a cache clear.
Not yet tested
I have not validated this end to end in GDK with Workhorse in front and a real quay.io upstream. Request specs cover the controller behavior. Reviewers, please note this when you review.
References
- Fixes #618754 (closed)
Screenshots or screen recordings
Not applicable. This MR has no UI change.
How to set up and validate locally
- Create a container virtual registry with upstream
https://quay.ioin a top-level group. - Pull an image by tag through it once. This is a cache miss.
- Run
curl -Iwith a bearer token against/v2/virtual_registries/container/<registry_id>/<image>/manifests/<tag>twice. Check that the second response has a non-zeroContent-Lengthand aDocker-Content-Digest. - Pull by digest with containerd twice, for example with
crictl pullornerdctl pull. Confirm both pulls succeed.
Run the specs:
bin/rspec ee/spec/requests/virtual_registries/container_controller_spec.rb ee/spec/services/virtual_registries/container/cache/entries/create_or_update_service_spec.rb ee/spec/services/virtual_registries/container/handle_file_request_service_spec.rbMR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.