Read about our upcoming Code of Conduct on this issue

Commit e4fa80f3 authored by Andre Guedes's avatar Andre Guedes
Browse files

Fixes broken and missing tests

parent 2ebd456d3092
...@@ -3,14 +3,14 @@ ...@@ -3,14 +3,14 @@
*/ */
.container-image { .container-image {
border-bottom: 1px solid #f0f0f0; border-bottom: 1px solid $white-normal;
} }
.container-image-head { .container-image-head {
padding: 0px 16px; padding: 0 16px;
line-height: 4; line-height: 4;
} }
.table.tags { .table.tags {
margin-bottom: 0px; margin-bottom: 0;
} }
...@@ -20,7 +20,6 @@ def destroy ...@@ -20,7 +20,6 @@ def destroy
redirect_to url, alert: 'Failed to remove image' redirect_to url, alert: 'Failed to remove image'
end end
end end
end end
private private
......
...@@ -22,7 +22,7 @@ def path ...@@ -22,7 +22,7 @@ def path
end end
def name_with_namespace def name_with_namespace
[container_registry_path_with_namespace, name].compact.join('/') [container_registry_path_with_namespace, name].reject(&:blank?).join('/')
end end
def tag(tag) def tag(tag)
...@@ -55,6 +55,8 @@ def delete_tags ...@@ -55,6 +55,8 @@ def delete_tags
end end
end end
# rubocop:disable RedundantReturn
def self.split_namespace(full_path) def self.split_namespace(full_path)
image_name = full_path.split('/').last image_name = full_path.split('/').last
namespace = full_path.gsub(/(.*)(#{Regexp.escape('/' + image_name)})/, '\1') namespace = full_path.gsub(/(.*)(#{Regexp.escape('/' + image_name)})/, '\1')
......
...@@ -118,8 +118,8 @@ def human_name ...@@ -118,8 +118,8 @@ def human_name
end end
def move_dir def move_dir
if any_project_has_container_registry_tags? if any_project_has_container_registry_images?
raise Gitlab::UpdatePathError.new('Namespace cannot be moved, because at least one project has tags in container registry') raise Gitlab::UpdatePathError.new('Namespace cannot be moved, because at least one project has images in container registry')
end end
# Move the namespace directory in all storages paths used by member projects # Move the namespace directory in all storages paths used by member projects
...@@ -154,8 +154,8 @@ def move_dir ...@@ -154,8 +154,8 @@ def move_dir
end end
end end
def any_project_has_container_registry_tags? def any_project_has_container_registry_images?
projects.any?(&:has_container_registry_tags?) projects.any? { |project| project.container_images.present? }
end end
def send_update_instructions def send_update_instructions
......
...@@ -421,18 +421,12 @@ def container_registry ...@@ -421,18 +421,12 @@ def container_registry
end end
end end
def container_registry_repository_url def container_registry_url
if Gitlab.config.registry.enabled if Gitlab.config.registry.enabled
"#{Gitlab.config.registry.host_port}/#{container_registry_path_with_namespace}" "#{Gitlab.config.registry.host_port}/#{container_registry_path_with_namespace}"
end end
end end
def has_container_registry_tags?
return unless container_images
container_images.first.tags.any?
end
def commit(ref = 'HEAD') def commit(ref = 'HEAD')
repository.commit(ref) repository.commit(ref)
end end
...@@ -913,11 +907,11 @@ def rename_repo ...@@ -913,11 +907,11 @@ def rename_repo
expire_caches_before_rename(old_path_with_namespace) expire_caches_before_rename(old_path_with_namespace)
if has_container_registry_tags? if container_images.present?
Rails.logger.error "Project #{old_path_with_namespace} cannot be renamed because container registry tags are present" Rails.logger.error "Project #{old_path_with_namespace} cannot be renamed because container registry images are present"
# we currently doesn't support renaming repository if it contains tags in container registry # we currently doesn't support renaming repository if it contains images in container registry
raise StandardError.new('Project cannot be renamed, because tags are present in its container registry') raise StandardError.new('Project cannot be renamed, because images are present in its container registry')
end end
if gitlab_shell.mv_repository(repository_storage_path, old_path_with_namespace, new_path_with_namespace) if gitlab_shell.mv_repository(repository_storage_path, old_path_with_namespace, new_path_with_namespace)
...@@ -1264,7 +1258,7 @@ def container_registry_variables ...@@ -1264,7 +1258,7 @@ def container_registry_variables
] ]
if container_registry_enabled? if container_registry_enabled?
variables << { key: 'CI_REGISTRY_IMAGE', value: container_registry_repository_url, public: true } variables << { key: 'CI_REGISTRY_IMAGE', value: container_registry_url, public: true }
end end
variables variables
......
...@@ -16,7 +16,8 @@ def execute(authentication_abilities:) ...@@ -16,7 +16,8 @@ def execute(authentication_abilities:)
{ token: authorized_token(scope).encoded } { token: authorized_token(scope).encoded }
end end
def self.full_access_token(names) def self.full_access_token(*names)
names = names.flatten
registry = Gitlab.config.registry registry = Gitlab.config.registry
token = JSONWebToken::RSAToken.new(registry.key) token = JSONWebToken::RSAToken.new(registry.key)
token.issuer = registry.issuer token.issuer = registry.issuer
......
module ContainerImages module ContainerImages
class DestroyService < BaseService class DestroyService < BaseService
class DestroyError < StandardError; end class DestroyError < StandardError; end
def execute(container_image) def execute(container_image)
......
...@@ -36,9 +36,9 @@ def transfer(project, new_namespace) ...@@ -36,9 +36,9 @@ def transfer(project, new_namespace)
raise TransferError.new("Project with same path in target namespace already exists") raise TransferError.new("Project with same path in target namespace already exists")
end end
if project.has_container_registry_tags? unless project.container_images.empty?
# we currently doesn't support renaming repository if it contains tags in container registry # we currently doesn't support renaming repository if it contains images in container registry
raise TransferError.new('Project cannot be transferred, because tags are present in its container registry') raise TransferError.new('Project cannot be transferred, because images are present in its container registry')
end end
project.expire_caches_before_rename(old_path) project.expire_caches_before_rename(old_path)
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
= escape_once(image.name) = escape_once(image.name)
= clipboard_button(clipboard_text: "docker pull #{image.path}") = clipboard_button(clipboard_text: "docker pull #{image.path}")
.controls.hidden-xs.pull-right .controls.hidden-xs.pull-right
= link_to namespace_project_container_registry_path(@project.namespace, @project, image.id), class: 'btn btn-remove has-tooltip', title: "Remove", data: { confirm: "Are you sure?" }, method: :delete do = link_to namespace_project_container_registry_path(@project.namespace, @project, image.id), class: 'btn btn-remove has-tooltip', title: "Remove image", data: { confirm: "Are you sure?" }, method: :delete do
= icon("trash cred") = icon("trash cred")
......
...@@ -25,5 +25,5 @@ ...@@ -25,5 +25,5 @@
- if can?(current_user, :update_container_image, @project) - if can?(current_user, :update_container_image, @project)
%td.content %td.content
.controls.hidden-xs.pull-right .controls.hidden-xs.pull-right
= link_to namespace_project_container_registry_path(@project.namespace, @project, { id: tag.repository.id, tag: tag.name} ), class: 'btn btn-remove has-tooltip', title: "Remove", data: { confirm: "Are you sure?" }, method: :delete do = link_to namespace_project_container_registry_path(@project.namespace, @project, { id: tag.repository.id, tag: tag.name} ), class: 'btn btn-remove has-tooltip', title: "Remove tag", data: { confirm: "Are you sure?" }, method: :delete do
= icon("trash cred") = icon("trash cred")
...@@ -15,9 +15,9 @@ ...@@ -15,9 +15,9 @@
%br %br
Then you are free to create and upload a container image with build and push commands: Then you are free to create and upload a container image with build and push commands:
%pre %pre
docker build -t #{escape_once(@project.container_registry_repository_url)} . docker build -t #{escape_once(@project.container_registry_url)} .
%br %br
docker push #{escape_once(@project.container_registry_repository_url)} docker push #{escape_once(@project.container_registry_url)}
- if @images.blank? - if @images.blank?
.nothing-here-block No container images in Container Registry for this project. .nothing-here-block No container images in Container Registry for this project.
......
...@@ -109,6 +109,7 @@ ...@@ -109,6 +109,7 @@
t.boolean "html_emails_enabled", default: true t.boolean "html_emails_enabled", default: true
t.string "plantuml_url" t.string "plantuml_url"
t.boolean "plantuml_enabled" t.boolean "plantuml_enabled"
t.string "container_registry_access_token"
t.integer "max_pages_size", default: 100, null: false t.integer "max_pages_size", default: 100, null: false
t.integer "terminal_max_session_time", default: 0, null: false t.integer "terminal_max_session_time", default: 0, null: false
end end
...@@ -392,6 +393,11 @@ ...@@ -392,6 +393,11 @@
add_index "ci_variables", ["gl_project_id"], name: "index_ci_variables_on_gl_project_id", using: :btree add_index "ci_variables", ["gl_project_id"], name: "index_ci_variables_on_gl_project_id", using: :btree
create_table "container_images", force: :cascade do |t|
t.integer "project_id"
t.string "name"
end
create_table "deploy_keys_projects", force: :cascade do |t| create_table "deploy_keys_projects", force: :cascade do |t|
t.integer "deploy_key_id", null: false t.integer "deploy_key_id", null: false
t.integer "project_id", null: false t.integer "project_id", null: false
......
...@@ -46,9 +46,7 @@ class RegistryEvents < Grape::API ...@@ -46,9 +46,7 @@ class RegistryEvents < Grape::API
if project if project
container_image = project.container_images.find_or_create_by(name: container_image_name) container_image = project.container_images.find_or_create_by(name: container_image_name)
if container_image.valid? unless container_image.valid?
puts('Valid!')
else
render_api_error!({ error: "Failed to create container image!" }, 400) render_api_error!({ error: "Failed to create container image!" }, 400)
end end
else else
......
...@@ -38,11 +38,11 @@ def short_revision ...@@ -38,11 +38,11 @@ def short_revision
end end
def delete def delete
client.delete_blob(repository.name, digest) client.delete_blob(repository.name_with_namespace, digest)
end end
def data def data
@data ||= client.blob(repository.name, digest, type) @data ||= client.blob(repository.name_with_namespace, digest, type)
end end
end end
end end
...@@ -8,10 +8,6 @@ def initialize(uri, options = {}) ...@@ -8,10 +8,6 @@ def initialize(uri, options = {})
@client = ContainerRegistry::Client.new(uri, options) @client = ContainerRegistry::Client.new(uri, options)
end end
def repository(name)
ContainerRegistry::Repository.new(self, name)
end
private private
def default_path def default_path
......
module ContainerRegistry
class Repository
attr_reader :registry, :name
delegate :client, to: :registry
def initialize(registry, name)
@registry, @name = registry, name
end
def path
[registry.path, name].compact.join('/')
end
def tag(tag)
ContainerRegistry::Tag.new(self, tag)
end
def manifest
return @manifest if defined?(@manifest)
@manifest = client.repository_tags(name)
end
def valid?
manifest.present?
end
def tags
return @tags if defined?(@tags)
return [] unless manifest && manifest['tags']
@tags = manifest['tags'].map do |tag|
ContainerRegistry::Tag.new(self, tag)
end
end
def blob(config)
ContainerRegistry::Blob.new(self, config)
end
def delete_tags
return unless tags
tags.all?(&:delete)
end
end
end
FactoryGirl.define do
factory :container_image do
name "test_container_image"
project
transient do
tags ['tag']
stubbed true
end
after(:build) do |image, evaluator|
if evaluator.stubbed
allow(Gitlab.config.registry).to receive(:enabled).and_return(true)
allow(image.client).to receive(:repository_tags).and_return({
name: image.name_with_namespace,
tags: evaluator.tags
})
end
end
end
end
...@@ -2,15 +2,18 @@ ...@@ -2,15 +2,18 @@
describe "Container Registry" do describe "Container Registry" do
let(:project) { create(:empty_project) } let(:project) { create(:empty_project) }
let(:repository) { project.container_registry_repository } let(:registry) { project.container_registry }
let(:tag_name) { 'latest' } let(:tag_name) { 'latest' }
let(:tags) { [tag_name] } let(:tags) { [tag_name] }
let(:container_image) { create(:container_image) }
let(:image_name) { container_image.name }
before do before do
login_as(:user) login_as(:user)
project.team << [@user, :developer] project.team << [@user, :developer]
stub_container_registry_tags(*tags)
stub_container_registry_config(enabled: true) stub_container_registry_config(enabled: true)
stub_container_registry_tags(*tags)
project.container_images << container_image unless container_image.nil?
allow(Auth::ContainerRegistryAuthenticationService).to receive(:full_access_token).and_return('token') allow(Auth::ContainerRegistryAuthenticationService).to receive(:full_access_token).and_return('token')
end end
...@@ -19,15 +22,26 @@ ...@@ -19,15 +22,26 @@
visit namespace_project_container_registry_index_path(project.namespace, project) visit namespace_project_container_registry_index_path(project.namespace, project)
end end
context 'when no tags' do context 'when no images' do
let(:tags) { [] } let(:container_image) { }
it { expect(page).to have_content('No container images in Container Registry for this project') }
end
it { expect(page).to have_content('No images in Container Registry for this project') } context 'when there are images' do
it { expect(page).to have_content(image_name) }
end end
end
describe 'DELETE /:project/container_registry/:image_id' do
before do
visit namespace_project_container_registry_index_path(project.namespace, project)
end
it do
expect_any_instance_of(ContainerImage).to receive(:delete_tags).and_return(true)
context 'when there are tags' do click_on 'Remove image'
it { expect(page).to have_content(tag_name) }
it { expect(page).to have_content('d7a513a66') }
end end
end end
...@@ -39,7 +53,7 @@ ...@@ -39,7 +53,7 @@
it do it do
expect_any_instance_of(::ContainerRegistry::Tag).to receive(:delete).and_return(true) expect_any_instance_of(::ContainerRegistry::Tag).to receive(:delete).and_return(true)
click_on 'Remove' click_on 'Remove tag'
end end
end end
end end
...@@ -429,9 +429,12 @@ ...@@ -429,9 +429,12 @@
end end
describe "GET /:project_path/container_registry" do describe "GET /:project_path/container_registry" do
let(:container_image) { create(:container_image) }
before do before do
stub_container_registry_tags('latest') stub_container_registry_tags('latest')
stub_container_registry_config(enabled: true) stub_container_registry_config(enabled: true)
project.container_images << container_image
end end
subject { namespace_project_container_registry_index_path(project.namespace, project) } subject { namespace_project_container_registry_index_path(project.namespace, project) }
......
...@@ -418,9 +418,12 @@ ...@@ -418,9 +418,12 @@
end end
describe "GET /:project_path/container_registry" do describe "GET /:project_path/container_registry" do
let(:container_image) { create(:container_image) }
before do before do
stub_container_registry_tags('latest') stub_container_registry_tags('latest')
stub_container_registry_config(enabled: true) stub_container_registry_config(enabled: true)
project.container_images << container_image
end end
subject { namespace_project_container_registry_index_path(project.namespace, project) } subject { namespace_project_container_registry_index_path(project.namespace, project) }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment