summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRémy Coutable <remy@rymai.me>2016-06-15 15:07:39 +0000
committerRémy Coutable <remy@rymai.me>2016-06-15 15:07:39 +0000
commita8b46301907abeeedab4010a966bbd8efc8d370c (patch)
treea24d4121c2912b55e9b38689859afd971ac81463
parente27de52607369a11ee3cec7fbdd2ffa5cb6e0061 (diff)
parent3213023dd657ba6c5c6d690fae2ca44a409b16fd (diff)
downloadgitlab-ce-a8b46301907abeeedab4010a966bbd8efc8d370c.tar.gz
Merge branch 'docker-registry-manifest-v1' into 'master'
Add support for Docker Registry manifest v1 ## What does this MR do? Adds support for Manifest V1 generated by older versions of Docker (before 1.10). ## What are the relevant issue numbers? Fixes https://gitlab.com/gitlab-org/gitlab-ce/issues/18609 See merge request !4669
-rw-r--r--CHANGELOG1
-rw-r--r--app/views/projects/container_registry/_tag.html.haml16
-rw-r--r--lib/container_registry/blob.rb2
-rw-r--r--lib/container_registry/client.rb4
-rw-r--r--lib/container_registry/tag.rb14
-rw-r--r--spec/fixtures/container_registry/tag_manifest_1.json32
-rw-r--r--spec/lib/container_registry/tag_spec.rb89
7 files changed, 125 insertions, 33 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 6f4de643fb2..a215d794670 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -31,6 +31,7 @@ v 8.9.0 (unreleased)
- Add Environments and Deployments
- Redesign account and email confirmation emails
- Don't fail builds for projects that are deleted
+ - Support Docker Registry manifest v1
- `git clone https://host/namespace/project` now works, in addition to using the `.git` suffix
- Bump nokogiri to 1.6.8
- Use gitlab-shell v3.0.0
diff --git a/app/views/projects/container_registry/_tag.html.haml b/app/views/projects/container_registry/_tag.html.haml
index 4e9f936539b..f35faa6afb5 100644
--- a/app/views/projects/container_registry/_tag.html.haml
+++ b/app/views/projects/container_registry/_tag.html.haml
@@ -9,11 +9,19 @@
- else
\-
%td
- = number_to_human_size(tag.total_size)
- &middot;
- = pluralize(tag.layers.size, "layer")
+ - if tag.total_size
+ = number_to_human_size(tag.total_size)
+ &middot;
+ = pluralize(tag.layers.size, "layer")
+ - else
+ .light
+ \-
%td
- = time_ago_in_words(tag.created_at)
+ - if tag.created_at
+ = time_ago_in_words(tag.created_at)
+ - else
+ .light
+ \-
- if can?(current_user, :update_container_image, @project)
%td.content
.controls.hidden-xs.pull-right
diff --git a/lib/container_registry/blob.rb b/lib/container_registry/blob.rb
index 4e20dc4f875..eb5a2596177 100644
--- a/lib/container_registry/blob.rb
+++ b/lib/container_registry/blob.rb
@@ -18,7 +18,7 @@ module ContainerRegistry
end
def digest
- config['digest']
+ config['digest'] || config['blobSum']
end
def type
diff --git a/lib/container_registry/client.rb b/lib/container_registry/client.rb
index 4d726692f45..e0b3f14d384 100644
--- a/lib/container_registry/client.rb
+++ b/lib/container_registry/client.rb
@@ -47,7 +47,9 @@ module ContainerRegistry
conn.request :json
conn.headers['Accept'] = MANIFEST_VERSION
- conn.response :json, content_type: /\bjson$/
+ 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'
if options[:user] && options[:password]
conn.request(:basic_auth, options[:user].to_s, options[:password].to_s)
diff --git a/lib/container_registry/tag.rb b/lib/container_registry/tag.rb
index 43f8d6dc8c2..7a0929d774e 100644
--- a/lib/container_registry/tag.rb
+++ b/lib/container_registry/tag.rb
@@ -12,6 +12,14 @@ module ContainerRegistry
manifest.present?
end
+ def v1?
+ manifest && manifest['schemaVersion'] == 1
+ end
+
+ def v2?
+ manifest && manifest['schemaVersion'] == 2
+ end
+
def manifest
return @manifest if defined?(@manifest)
@@ -57,7 +65,9 @@ module ContainerRegistry
return @layers if defined?(@layers)
return unless manifest
- @layers = manifest['layers'].map do |layer|
+ layers = manifest['layers'] || manifest['fsLayers']
+
+ @layers = layers.map do |layer|
repository.blob(layer)
end
end
@@ -65,7 +75,7 @@ module ContainerRegistry
def total_size
return unless layers
- layers.map(&:size).sum
+ layers.map(&:size).sum if v2?
end
def delete
diff --git a/spec/fixtures/container_registry/tag_manifest_1.json b/spec/fixtures/container_registry/tag_manifest_1.json
new file mode 100644
index 00000000000..d09ede5bea7
--- /dev/null
+++ b/spec/fixtures/container_registry/tag_manifest_1.json
@@ -0,0 +1,32 @@
+{
+ "schemaVersion": 1,
+ "name": "library/alpine",
+ "tag": "2.6",
+ "architecture": "amd64",
+ "fsLayers": [
+ {
+ "blobSum": "sha256:2a3ebcb7fbcc29bf40c4f62863008bb573acdea963454834d9483b3e5300c45d"
+ }
+ ],
+ "history": [
+ {
+ "v1Compatibility": "{\"id\":\"dd807873c9a21bcc82e30317c283e6601d7e19f5cf7867eec34cdd1aeb3f099e\",\"created\":\"2016-01-18T18:32:39.162138276Z\",\"container\":\"556a728876db7b0e621adc029c87c649d32520804f8f15defd67bb070dc1a88d\",\"container_config\":{\"Hostname\":\"556a728876db\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) ADD file:7dee8a455bcc39013aa168d27ece9227aad155adbaacbd153d94ca60113f59fc in /\"],\"Image\":\"\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":null},\"docker_version\":\"1.8.3\",\"config\":{\"Hostname\":\"556a728876db\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":null,\"Image\":\"\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":null},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":4501436}"
+ }
+ ],
+ "signatures": [
+ {
+ "header": {
+ "jwk": {
+ "crv": "P-256",
+ "kid": "4MZL:Z5ZP:2RPA:Q3TD:QOHA:743L:EM2G:QY6Q:ZJCX:BSD7:CRYC:LQ6T",
+ "kty": "EC",
+ "x": "qmWOaxPUk7QsE5iTPdeG1e9yNE-wranvQEnWzz9FhWM",
+ "y": "WeeBpjTOYnTNrfCIxtFY5qMrJNNk9C1vc5ryxbbMD_M"
+ },
+ "alg": "ES256"
+ },
+ "signature": "0zmjTJ4m21yVwAeteLc3SsQ0miScViCDktFPR67W-ozGjjI3iBjlDjwOl6o2sds5ZI9U6bSIKOeLDinGOhHoOQ",
+ "protected": "eyJmb3JtYXRMZW5ndGgiOjEzNzIsImZvcm1hdFRhaWwiOiJDbjAiLCJ0aW1lIjoiMjAxNi0wNi0xNVQxMDo0NDoxNFoifQ"
+ }
+ ]
+}
diff --git a/spec/lib/container_registry/tag_spec.rb b/spec/lib/container_registry/tag_spec.rb
index 858cb0bb134..c7324c2bf77 100644
--- a/spec/lib/container_registry/tag_spec.rb
+++ b/spec/lib/container_registry/tag_spec.rb
@@ -17,46 +17,85 @@ describe ContainerRegistry::Tag do
end
context 'manifest processing' do
- before do
- stub_request(:get, 'http://example.com/v2/group/test/manifests/tag').
- with(headers: headers).
- to_return(
- status: 200,
- body: File.read(Rails.root + 'spec/fixtures/container_registry/tag_manifest.json'),
- headers: { 'Content-Type' => 'application/vnd.docker.distribution.manifest.v2+json' })
- end
+ context 'schema v1' do
+ before do
+ stub_request(:get, 'http://example.com/v2/group/test/manifests/tag').
+ with(headers: headers).
+ to_return(
+ status: 200,
+ body: File.read(Rails.root + 'spec/fixtures/container_registry/tag_manifest_1.json'),
+ headers: { 'Content-Type' => 'application/vnd.docker.distribution.manifest.v1+prettyjws' })
+ end
- context '#layers' do
- subject { tag.layers }
+ context '#layers' do
+ subject { tag.layers }
- it { expect(subject.length).to eq(1) }
- end
+ it { expect(subject.length).to eq(1) }
+ end
+
+ context '#total_size' do
+ subject { tag.total_size }
- context '#total_size' do
- subject { tag.total_size }
+ it { is_expected.to be_nil }
+ end
- it { is_expected.to eq(2319870) }
+ context 'config processing' do
+ context '#config' do
+ subject { tag.config }
+
+ it { is_expected.to be_nil }
+ end
+
+ context '#created_at' do
+ subject { tag.created_at }
+
+ it { is_expected.to be_nil }
+ end
+ end
end
- context 'config processing' do
+ context 'schema v2' do
before do
- stub_request(:get, 'http://example.com/v2/group/test/blobs/sha256:d7a513a663c1a6dcdba9ed832ca53c02ac2af0c333322cd6ca92936d1d9917ac').
- with(headers: { 'Accept' => 'application/octet-stream' }).
+ stub_request(:get, 'http://example.com/v2/group/test/manifests/tag').
+ with(headers: headers).
to_return(
status: 200,
- body: File.read(Rails.root + 'spec/fixtures/container_registry/config_blob.json'))
+ body: File.read(Rails.root + 'spec/fixtures/container_registry/tag_manifest.json'),
+ headers: { 'Content-Type' => 'application/vnd.docker.distribution.manifest.v2+json' })
end
- context '#config' do
- subject { tag.config }
+ context '#layers' do
+ subject { tag.layers }
- it { is_expected.not_to be_nil }
+ it { expect(subject.length).to eq(1) }
end
- context '#created_at' do
- subject { tag.created_at }
+ context '#total_size' do
+ subject { tag.total_size }
+
+ it { is_expected.to eq(2319870) }
+ end
+
+ context 'config processing' do
+ before do
+ stub_request(:get, 'http://example.com/v2/group/test/blobs/sha256:d7a513a663c1a6dcdba9ed832ca53c02ac2af0c333322cd6ca92936d1d9917ac').
+ with(headers: { 'Accept' => 'application/octet-stream' }).
+ to_return(
+ status: 200,
+ body: File.read(Rails.root + 'spec/fixtures/container_registry/config_blob.json'))
+ end
+
+ context '#config' do
+ subject { tag.config }
+
+ it { is_expected.not_to be_nil }
+ end
+
+ context '#created_at' do
+ subject { tag.created_at }
- it { is_expected.not_to be_nil }
+ it { is_expected.not_to be_nil }
+ end
end
end
end