Add support for Docker Registry manifest v1
This commit is contained in:
parent
3a857e0e6c
commit
f30d1fdf94
7 changed files with 130 additions and 38 deletions
|
@ -29,6 +29,7 @@ v 8.9.0 (unreleased)
|
|||
- Fix groups API to list only user's accessible projects
|
||||
- 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
|
||||
|
|
|
@ -9,11 +9,19 @@
|
|||
- else
|
||||
\-
|
||||
%td
|
||||
= number_to_human_size(tag.total_size)
|
||||
·
|
||||
= pluralize(tag.layers.size, "layer")
|
||||
- if tag.total_size
|
||||
= number_to_human_size(tag.total_size)
|
||||
·
|
||||
= pluralize(tag.layers.size, "layer")
|
||||
- else
|
||||
.light
|
||||
\-
|
||||
%td
|
||||
- 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
|
||||
|
|
|
@ -18,7 +18,7 @@ module ContainerRegistry
|
|||
end
|
||||
|
||||
def digest
|
||||
config['digest']
|
||||
config['digest'] || config['blobSum']
|
||||
end
|
||||
|
||||
def type
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
32
spec/fixtures/container_registry/tag_manifest_1.json
vendored
Normal file
32
spec/fixtures/container_registry/tag_manifest_1.json
vendored
Normal file
|
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -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 '#layers' do
|
||||
subject { tag.layers }
|
||||
|
||||
it { expect(subject.length).to eq(1) }
|
||||
end
|
||||
|
||||
context '#total_size' do
|
||||
subject { tag.total_size }
|
||||
|
||||
it { is_expected.to eq(2319870) }
|
||||
end
|
||||
|
||||
context 'config processing' do
|
||||
context 'schema v1' 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_1.json'),
|
||||
headers: { 'Content-Type' => 'application/vnd.docker.distribution.manifest.v1+prettyjws' })
|
||||
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.not_to be_nil }
|
||||
it { is_expected.to be_nil }
|
||||
end
|
||||
|
||||
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 'schema v2' 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 '#layers' do
|
||||
subject { tag.layers }
|
||||
|
||||
it { expect(subject.length).to eq(1) }
|
||||
end
|
||||
|
||||
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 }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue