diff options
-rw-r--r-- | app/controllers/jwt_controller.rb | 2 | ||||
-rw-r--r-- | app/services/jwt/container_registry_authentication_service.rb | 6 | ||||
-rw-r--r-- | app/services/projects/destroy_service.rb | 2 | ||||
-rw-r--r-- | app/views/projects/container_registry/_tag.html.haml | 20 | ||||
-rw-r--r-- | app/views/projects/container_registry/index.html.haml | 23 | ||||
-rw-r--r-- | lib/container_registry/client.rb | 4 | ||||
-rw-r--r-- | spec/features/container_registry_spec.rb | 43 | ||||
-rw-r--r-- | spec/fixtures/container_registry/config_blob.json | 1 | ||||
-rw-r--r-- | spec/fixtures/container_registry/tag_manifest.json | 1 | ||||
-rw-r--r-- | spec/support/stub_gitlab_calls.rb | 12 |
10 files changed, 87 insertions, 27 deletions
diff --git a/app/controllers/jwt_controller.rb b/app/controllers/jwt_controller.rb index 0048a1a31ea..07a842970b8 100644 --- a/app/controllers/jwt_controller.rb +++ b/app/controllers/jwt_controller.rb @@ -3,7 +3,7 @@ class JwtController < ApplicationController skip_before_action :verify_authenticity_token SERVICES = { - 'container_registry' => Jwt::ContainerRegistryAuthenticationService, + Jwt::ContainerRegistryAuthenticationService::AUDIENCE => Jwt::ContainerRegistryAuthenticationService, } def auth diff --git a/app/services/jwt/container_registry_authentication_service.rb b/app/services/jwt/container_registry_authentication_service.rb index 88af4f8361b..2edee1f0ab0 100644 --- a/app/services/jwt/container_registry_authentication_service.rb +++ b/app/services/jwt/container_registry_authentication_service.rb @@ -1,5 +1,7 @@ module Jwt class ContainerRegistryAuthenticationService < BaseService + AUDIENCE = 'container_registry' + def execute if params[:offline_token] return error('forbidden', 403) unless current_user @@ -14,7 +16,7 @@ module Jwt registry = Gitlab.config.registry token = ::Jwt::RSAToken.new(registry.key) token.issuer = registry.issuer - token.audience = 'docker' + token.audience = AUDIENCE token[:access] = names.map do |name| { type: 'repository', name: name, actions: %w(pull push) } end @@ -26,7 +28,7 @@ module Jwt def authorized_token(access) token = ::Jwt::RSAToken.new(registry.key) token.issuer = registry.issuer - token.audience = params[:service] + token.audience = AUDIENCE token.subject = current_user.try(:username) token[:access] = access token diff --git a/app/services/projects/destroy_service.rb b/app/services/projects/destroy_service.rb index a8b31f95c4c..8e2e46346ca 100644 --- a/app/services/projects/destroy_service.rb +++ b/app/services/projects/destroy_service.rb @@ -27,7 +27,7 @@ module Projects project.destroy! unless remove_registry_tags - raise_error('Failed to remove project image registry. Please try again or contact administrator') + raise_error('Failed to remove project container registry. Please try again or contact administrator') end unless remove_repository(repo_path) diff --git a/app/views/projects/container_registry/_tag.html.haml b/app/views/projects/container_registry/_tag.html.haml new file mode 100644 index 00000000000..f97988d20cf --- /dev/null +++ b/app/views/projects/container_registry/_tag.html.haml @@ -0,0 +1,20 @@ +%tr.tag + %td + = escape_once(tag.name) + = clipboard_button(clipboard_text: "docker pull #{tag.path}") + %td + - if layer = tag.layers.first + %span.has-tooltip(title="#{layer.revision}") + = layer.short_revision + - else + \- + %td + = number_to_human_size(tag.total_size) + · + = pluralize(tag.layers.size, "layer") + %td + = time_ago_in_words(tag.created_at) + %td.content + .controls.hidden-xs.pull-right + = link_to namespace_project_container_registry_path(@project.namespace, @project, tag.name), class: 'btn btn-remove has-tooltip', title: "Remove", data: { confirm: "Are you sure?" }, method: :delete do + = icon("trash cred") diff --git a/app/views/projects/container_registry/index.html.haml b/app/views/projects/container_registry/index.html.haml index 5b7dd27ace6..701f1a86b56 100644 --- a/app/views/projects/container_registry/index.html.haml +++ b/app/views/projects/container_registry/index.html.haml @@ -26,7 +26,7 @@ - else .table-holder - %table.table.builds + %table.table.tags %thead %tr %th Name @@ -36,23 +36,4 @@ %th - @tags.each do |tag| - %tr - %td - = escape_once(tag.name) - = clipboard_button(clipboard_text: "docker pull #{tag.path}") - %td - - if layer = tag.layers.first - %span.has-tooltip(title="#{layer.revision}") - = layer.short_revision - - else - \- - %td - = number_to_human_size(tag.total_size) - · - = pluralize(tag.layers.size, "layer") - %td - = time_ago_in_words(tag.created_at) - %td.content - .controls.hidden-xs.pull-right - = link_to namespace_project_container_registry_path(@project.namespace, @project, tag.name), class: 'btn btn-remove has-tooltip', title: "Remove", data: { confirm: "Are you sure?" }, method: :delete do - = icon("trash cred") + = render 'tag', tag: tag
\ No newline at end of file diff --git a/lib/container_registry/client.rb b/lib/container_registry/client.rb index 41d9cb46ae9..0bfb6baffd4 100644 --- a/lib/container_registry/client.rb +++ b/lib/container_registry/client.rb @@ -10,7 +10,7 @@ module ContainerRegistry def initialize(base_uri, options = {}) @base_uri = base_uri @faraday = Faraday.new(@base_uri) do |conn| - initialize_connection(conn) + initialize_connection(conn, options) end end @@ -51,7 +51,7 @@ module ContainerRegistry private - def initialize_connection(conn) + def initialize_connection(conn, options) conn.request :json conn.headers['Accept'] = MANIFEST_VERSION diff --git a/spec/features/container_registry_spec.rb b/spec/features/container_registry_spec.rb new file mode 100644 index 00000000000..7bef7a2ee81 --- /dev/null +++ b/spec/features/container_registry_spec.rb @@ -0,0 +1,43 @@ +require 'spec_helper' + +describe "Container Registry" do + let(:project) { create(:empty_project) } + let(:repository) { project.container_registry_repository } + let(:tag_name) { 'latest' } + let(:tags) { [tag_name] } + + before do + end + + before do + login_as(:user) + project.team << [@user, :developer] + stub_container_registry(*tags) + end + + describe 'GET /:project/container_registry' do + before do + visit namespace_project_container_registry_index_path(project.namespace, project) + end + + context 'when no tags' do + let(:tags) { [] } + it { expect(page).to have_content('No images in Container Registry for this project') } + end + + context 'when there are tags' do + it { expect(page).to have_content(tag_name)} + end + end + + describe 'DELETE /:project/container_registry/tag' do + before do + visit namespace_project_container_registry_index_path(project.namespace, project) + end + + it do + expect_any_instance_of(::ContainerRegistry::Tag).to receive(:delete).and_return(true) + click_on 'Remove' + end + end +end
\ No newline at end of file diff --git a/spec/fixtures/container_registry/config_blob.json b/spec/fixtures/container_registry/config_blob.json new file mode 100644 index 00000000000..1028c994a24 --- /dev/null +++ b/spec/fixtures/container_registry/config_blob.json @@ -0,0 +1 @@ +{"architecture":"amd64","config":{"Hostname":"b14cd8298755","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},"container":"b14cd82987550b01af9a666a2f4c996280a6152e66873134fae5a0f223dc5976","container_config":{"Hostname":"b14cd8298755","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":null,"Cmd":["/bin/sh","-c","#(nop) ADD file:033ab063740d9ff4dcfb1c69eccf25f91d88729f57cd5a73050e014e3e094aa0 in /"],"Image":"","Volumes":null,"WorkingDir":"","Entrypoint":null,"OnBuild":null,"Labels":null},"created":"2016-04-01T20:53:00.160300546Z","docker_version":"1.9.1","history":[{"created":"2016-04-01T20:53:00.160300546Z","created_by":"/bin/sh -c #(nop) ADD file:033ab063740d9ff4dcfb1c69eccf25f91d88729f57cd5a73050e014e3e094aa0 in /"}],"os":"linux","rootfs":{"type":"layers","diff_ids":["sha256:c56b7dabbc7aa730eeab07668bdcbd7e3d40855047ca9a0cc1bfed23a2486111"]}} diff --git a/spec/fixtures/container_registry/tag_manifest.json b/spec/fixtures/container_registry/tag_manifest.json new file mode 100644 index 00000000000..1b6008e2872 --- /dev/null +++ b/spec/fixtures/container_registry/tag_manifest.json @@ -0,0 +1 @@ +{"schemaVersion":2,"mediaType":"application/vnd.docker.distribution.manifest.v2+json","config":{"mediaType":"application/octet-stream","size":1145,"digest":"sha256:d7a513a663c1a6dcdba9ed832ca53c02ac2af0c333322cd6ca92936d1d9917ac"},"layers":[{"mediaType":"application/vnd.docker.image.rootfs.diff.tar.gzip","size":2319870,"digest":"sha256:420890c9e918b6668faaedd9000e220190f2493b0693ee563ebd7b4cc754a57d"}]} diff --git a/spec/support/stub_gitlab_calls.rb b/spec/support/stub_gitlab_calls.rb index eec2e681117..6b3a4010063 100644 --- a/spec/support/stub_gitlab_calls.rb +++ b/spec/support/stub_gitlab_calls.rb @@ -25,6 +25,18 @@ module StubGitlabCalls allow_any_instance_of(Project).to receive(:builds_enabled?).and_return(false) end + def stub_container_registry(*tags) + allow_any_instance_of(ContainerRegistry::Client).to receive(:repository_tags).and_return( + { "tags" => tags } + ) + allow_any_instance_of(ContainerRegistry::Client).to receive(:repository_manifest).and_return( + JSON.load(File.read(Rails.root + 'spec/fixtures/container_registry/tag_manifest.json')) + ) + allow_any_instance_of(ContainerRegistry::Client).to receive(:blob).and_return( + File.read(Rails.root + 'spec/fixtures/container_registry/config_blob.json') + ) + end + private def gitlab_url |