diff options
author | Stan Hu <stanhu@gmail.com> | 2019-07-24 21:44:07 -0700 |
---|---|---|
committer | Stan Hu <stanhu@gmail.com> | 2019-07-25 04:11:38 -0700 |
commit | a40116065e2a761f6fa8dc7d569cb3e39025f6d3 (patch) | |
tree | 64d0d2ba3cfdc8f1cbc57c4fa7bc21ae7044a01b | |
parent | a5eaefc9027696fc65b7d51251902e013c14d161 (diff) | |
download | gitlab-ce-a40116065e2a761f6fa8dc7d569cb3e39025f6d3.tar.gz |
Support Docker OCI imagessh-support-docker-oci-images
Docker Distribution v2.7.0 shipped with OCI support, but our container
registry client was not updated to handle the manifest format in the
HTTP `Accept` header. As a result, API calls to retrieve a manifest
would return with an error, "OCI manifest found, but accept header does
not support OCI manifests". This would result in blank fields in the
container registry page and prevent tags from being deleted.
To fix this, we just need to add
`application/vnd.oci.image.manifest.v1+json` to the `Accept` header and
configure Faraday to parse the response as JSON. The response structure
is the same as the standard Docker Distribution V2 manifest.
Closes https://gitlab.com/gitlab-org/gitlab-ce/issues/58685
Closes https://gitlab.com/gitlab-org/gitlab-ee/issues/12877
-rw-r--r-- | changelogs/unreleased/sh-support-docker-oci-images.yml | 5 | ||||
-rw-r--r-- | lib/container_registry/client.rb | 9 | ||||
-rw-r--r-- | spec/lib/container_registry/client_spec.rb | 36 | ||||
-rw-r--r-- | spec/lib/container_registry/tag_spec.rb | 2 | ||||
-rw-r--r-- | spec/models/container_repository_spec.rb | 2 |
5 files changed, 49 insertions, 5 deletions
diff --git a/changelogs/unreleased/sh-support-docker-oci-images.yml b/changelogs/unreleased/sh-support-docker-oci-images.yml new file mode 100644 index 00000000000..2dcf980fa50 --- /dev/null +++ b/changelogs/unreleased/sh-support-docker-oci-images.yml @@ -0,0 +1,5 @@ +--- +title: Support Docker OCI images +merge_request: 31127 +author: +type: fixed diff --git a/lib/container_registry/client.rb b/lib/container_registry/client.rb index c80f49f5ae0..c3a19af7a94 100644 --- a/lib/container_registry/client.rb +++ b/lib/container_registry/client.rb @@ -7,7 +7,9 @@ module ContainerRegistry class Client attr_accessor :uri - MANIFEST_VERSION = 'application/vnd.docker.distribution.manifest.v2+json'.freeze + DOCKER_DISTRIBUTION_MANIFEST_V2_TYPE = 'application/vnd.docker.distribution.manifest.v2+json' + OCI_MANIFEST_V1_TYPE = 'application/vnd.oci.image.manifest.v1+json' + ACCEPTED_TYPES = [DOCKER_DISTRIBUTION_MANIFEST_V2_TYPE, OCI_MANIFEST_V1_TYPE].freeze # Taken from: FaradayMiddleware::FollowRedirects REDIRECT_CODES = Set.new [301, 302, 303, 307] @@ -60,12 +62,13 @@ module ContainerRegistry end def accept_manifest(conn) - conn.headers['Accept'] = MANIFEST_VERSION + conn.headers['Accept'] = ACCEPTED_TYPES conn.response :json, content_type: 'application/json' conn.response :json, content_type: 'application/vnd.docker.distribution.manifest.v1+prettyjws' conn.response :json, content_type: 'application/vnd.docker.distribution.manifest.v1+json' - conn.response :json, content_type: 'application/vnd.docker.distribution.manifest.v2+json' + conn.response :json, content_type: DOCKER_DISTRIBUTION_MANIFEST_V2_TYPE + conn.response :json, content_type: OCI_MANIFEST_V1_TYPE end def response_body(response, allow_redirect: false) diff --git a/spec/lib/container_registry/client_spec.rb b/spec/lib/container_registry/client_spec.rb index 3df33f48adb..ce06377bbbf 100644 --- a/spec/lib/container_registry/client_spec.rb +++ b/spec/lib/container_registry/client_spec.rb @@ -6,6 +6,42 @@ describe ContainerRegistry::Client do let(:options) { { token: token } } let(:client) { described_class.new("http://container-registry", options) } + shared_examples '#repository_manifest' do |manifest_type| + let(:manifest) do + { + "schemaVersion" => 2, + "config" => { + "mediaType" => manifest_type, + "digest" => + "sha256:4a3ef0786dd241be6000311e1503869b320be433b9cba84cfafeb512d1720c95", + "size" => 6608 + }, + "layers" => [ + { + "mediaType" => manifest_type, + "digest" => + "sha256:83ef92b73cf4595aa7fe214ec6747228283d585f373d8f6bc08d66bebab531b7", + "size" => 2828661 + } + ] + } + end + + it 'GET /v2/:name/manifests/mytag' do + stub_request(:get, "http://container-registry/v2/group/test/manifests/mytag") + .with(headers: { + 'Accept' => described_class::ACCEPTED_TYPES.join(', '), + 'Authorization' => "bearer #{token}" + }) + .to_return(status: 200, body: manifest.to_json, headers: { content_type: manifest_type }) + + expect(client.repository_manifest('group/test', 'mytag')).to eq(manifest) + end + end + + it_behaves_like '#repository_manifest', described_class::DOCKER_DISTRIBUTION_MANIFEST_V2_TYPE + it_behaves_like '#repository_manifest', described_class::OCI_MANIFEST_V1_TYPE + describe '#blob' do it 'GET /v2/:name/blobs/:digest' do stub_request(:get, "http://container-registry/v2/group/test/blobs/sha256:0123456789012345") diff --git a/spec/lib/container_registry/tag_spec.rb b/spec/lib/container_registry/tag_spec.rb index cb4ae3be525..65090f32f66 100644 --- a/spec/lib/container_registry/tag_spec.rb +++ b/spec/lib/container_registry/tag_spec.rb @@ -9,7 +9,7 @@ describe ContainerRegistry::Tag do end let(:headers) do - { 'Accept' => 'application/vnd.docker.distribution.manifest.v2+json' } + { 'Accept' => ContainerRegistry::Client::ACCEPTED_TYPES.join(', ') } end let(:tag) { described_class.new(repository, 'tag') } diff --git a/spec/models/container_repository_spec.rb b/spec/models/container_repository_spec.rb index 013112d1d51..935838ce294 100644 --- a/spec/models/container_repository_spec.rb +++ b/spec/models/container_repository_spec.rb @@ -16,7 +16,7 @@ describe ContainerRepository do host_port: 'registry.gitlab') stub_request(:get, 'http://registry.gitlab/v2/group/test/my_image/tags/list') - .with(headers: { 'Accept' => 'application/vnd.docker.distribution.manifest.v2+json' }) + .with(headers: { 'Accept' => ContainerRegistry::Client::ACCEPTED_TYPES.join(', ') }) .to_return( status: 200, body: JSON.dump(tags: ['test_tag']), |