API: Handle missing foreign layers gracefully
Context
corrective action for gitlab-com/gl-infra/production#6109 (closed).
Some container images have foreign layers. Foreign layers are those that do not reside in the same container registry where a manifest is pushed to. This is rare and most commonly found in some Windows images.
Problem
We're not handling missing foreign layers gracefully when processing manifest uploads requests through the new code path, registering them on the database.
Right now we're checking for the presence of foreign layers on the blobs
table, but there are no such records for foreign layers, so this fails with an unexpected error.
Specific code: https://gitlab.com/gitlab-org/container-registry/-/blob/86203ff5f6c17b8f36126de5695feeae2a326512/registry/handlers/manifests.go#L978
Solution
The database is intended primarily to track blobs on object storage, so these layers do not need to live in the schema — all of their relevant information is included in the manifest payload. This approach is similar to the one currently taken by the filesystem metadata.
Before associating a layer with a manifest, we should first check if it's a foreign layer before associating it with the manifest on the database. Currently, we call the Layers
method to do this. It's possible that we can update this method to only return layers that would be expected to exist on object storage, this method is currently only used to get layers to associate with the manifest, and to calculate the total size of the manifest. So this change can be localized to the schema 2 and oci image implementations, which would fix #544 (closed) additionally.
Last but not least, we're clearly missing an integration test for this.