summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/assets/stylesheets/pages/container_registry.scss16
-rw-r--r--app/controllers/projects/container_registry_controller.rb28
-rw-r--r--app/models/container_image.rb20
-rw-r--r--app/models/container_images_repository.rb26
-rw-r--r--app/models/project.rb20
-rw-r--r--app/services/container_images/destroy_service.rb32
-rw-r--r--app/services/container_images_repositories/container_images/create_service.rb16
-rw-r--r--app/services/container_images_repositories/container_images/destroy_service.rb11
-rw-r--r--app/services/container_images_repositories/container_images/push_service.rb26
-rw-r--r--app/services/container_images_repositories/create_service.rb7
-rw-r--r--app/services/projects/destroy_service.rb10
-rw-r--r--app/views/projects/container_registry/_image.html.haml35
-rw-r--r--app/views/projects/container_registry/_tag.html.haml2
-rw-r--r--app/views/projects/container_registry/index.html.haml20
-rw-r--r--db/migrate/20161029153736_create_container_images_repository.rb31
-rw-r--r--db/migrate/20161031013926_create_container_image.rb2
-rw-r--r--lib/api/registry_events.rb16
17 files changed, 149 insertions, 169 deletions
diff --git a/app/assets/stylesheets/pages/container_registry.scss b/app/assets/stylesheets/pages/container_registry.scss
new file mode 100644
index 00000000000..7d68eae3c97
--- /dev/null
+++ b/app/assets/stylesheets/pages/container_registry.scss
@@ -0,0 +1,16 @@
+/**
+ * Container Registry
+ */
+
+.container-image {
+ border-bottom: 1px solid #f0f0f0;
+}
+
+.container-image-head {
+ padding: 0px 16px;
+ line-height: 4;
+}
+
+.table.tags {
+ margin-bottom: 0px;
+}
diff --git a/app/controllers/projects/container_registry_controller.rb b/app/controllers/projects/container_registry_controller.rb
index d1f46497207..54bcb5f504a 100644
--- a/app/controllers/projects/container_registry_controller.rb
+++ b/app/controllers/projects/container_registry_controller.rb
@@ -5,17 +5,22 @@ class Projects::ContainerRegistryController < Projects::ApplicationController
layout 'project'
def index
- @tags = container_registry_repository.tags
+ @images = project.container_images
end
def destroy
url = namespace_project_container_registry_index_path(project.namespace, project)
- if tag.delete
- redirect_to url
+ if tag
+ delete_tag(url)
else
- redirect_to url, alert: 'Failed to remove tag'
+ if image.destroy
+ redirect_to url
+ else
+ redirect_to url, alert: 'Failed to remove image'
+ end
end
+
end
private
@@ -24,11 +29,20 @@ class Projects::ContainerRegistryController < Projects::ApplicationController
render_404 unless Gitlab.config.registry.enabled
end
- def container_registry_repository
- @container_registry_repository ||= project.container_registry_repository
+ def delete_tag(url)
+ if tag.delete
+ image.destroy if image.tags.empty?
+ redirect_to url
+ else
+ redirect_to url, alert: 'Failed to remove tag'
+ end
+ end
+
+ def image
+ @image ||= project.container_images.find_by(id: params[:id])
end
def tag
- @tag ||= container_registry_repository.tag(params[:id])
+ @tag ||= image.tag(params[:tag]) if params[:tag].present?
end
end
diff --git a/app/models/container_image.rb b/app/models/container_image.rb
index dcc4a7af629..7721c53a6fc 100644
--- a/app/models/container_image.rb
+++ b/app/models/container_image.rb
@@ -1,23 +1,28 @@
class ContainerImage < ActiveRecord::Base
- belongs_to :container_images_repository
+ belongs_to :project
- delegate :registry, :registry_path_with_namespace, :client, to: :container_images_repository
+ delegate :container_registry, :container_registry_allowed_paths,
+ :container_registry_path_with_namespace, to: :project
+
+ delegate :client, to: :container_registry
validates :manifest, presence: true
+ before_destroy :delete_tags
+
before_validation :update_token, on: :create
def update_token
- paths = container_images_repository.allowed_paths << name_with_namespace
+ paths = container_registry_allowed_paths << name_with_namespace
token = Auth::ContainerRegistryAuthenticationService.full_access_token(paths)
client.update_token(token)
end
def path
- [registry.path, name_with_namespace].compact.join('/')
+ [container_registry.path, name_with_namespace].compact.join('/')
end
def name_with_namespace
- [registry_path_with_namespace, name].compact.join('/')
+ [container_registry_path_with_namespace, name].compact.join('/')
end
def tag(tag)
@@ -44,7 +49,10 @@ class ContainerImage < ActiveRecord::Base
def delete_tags
return unless tags
- tags.all?(&:delete)
+ digests = tags.map {|tag| tag.digest }.to_set
+ digests.all? do |digest|
+ client.delete_repository_tag(name_with_namespace, digest)
+ end
end
def self.split_namespace(full_path)
diff --git a/app/models/container_images_repository.rb b/app/models/container_images_repository.rb
deleted file mode 100644
index 99e94d2a6d0..00000000000
--- a/app/models/container_images_repository.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-class ContainerImagesRepository < ActiveRecord::Base
-
- belongs_to :project
-
- has_many :container_images, dependent: :destroy
-
- delegate :client, to: :registry
-
- def registry_path_with_namespace
- project.path_with_namespace.downcase
- end
-
- def allowed_paths
- @allowed_paths ||= [registry_path_with_namespace] +
- container_images.map { |i| i.name_with_namespace }
- end
-
- def registry
- @registry ||= begin
- token = Auth::ContainerRegistryAuthenticationService.full_access_token(allowed_paths)
- url = Gitlab.config.registry.api_url
- host_port = Gitlab.config.registry.host_port
- ContainerRegistry::Registry.new(url, token: token, path: host_port)
- end
- end
-end
diff --git a/app/models/project.rb b/app/models/project.rb
index 703e24eb79a..afaf2095a4c 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -157,7 +157,7 @@ class Project < ActiveRecord::Base
has_one :import_data, dependent: :destroy, class_name: "ProjectImportData"
has_one :project_feature, dependent: :destroy
has_one :statistics, class_name: 'ProjectStatistics', dependent: :delete
- has_one :container_images_repository, dependent: :destroy
+ has_many :container_images, dependent: :destroy
has_many :commit_statuses, dependent: :destroy, foreign_key: :gl_project_id
has_many :pipelines, dependent: :destroy, class_name: 'Ci::Pipeline', foreign_key: :gl_project_id
@@ -405,15 +405,19 @@ class Project < ActiveRecord::Base
path_with_namespace.downcase
end
- def container_registry_repository
+ def container_registry_allowed_paths
+ @container_registry_allowed_paths ||= [container_registry_path_with_namespace] +
+ container_images.map { |i| i.name_with_namespace }
+ end
+
+ def container_registry
return unless Gitlab.config.registry.enabled
- @container_registry_repository ||= begin
- token = Auth::ContainerRegistryAuthenticationService.full_access_token(container_registry_path_with_namespace)
+ @container_registry ||= begin
+ token = Auth::ContainerRegistryAuthenticationService.full_access_token(container_registry_allowed_paths)
url = Gitlab.config.registry.api_url
host_port = Gitlab.config.registry.host_port
- registry = ContainerRegistry::Registry.new(url, token: token, path: host_port)
- registry.repository(container_registry_path_with_namespace)
+ ContainerRegistry::Registry.new(url, token: token, path: host_port)
end
end
@@ -424,9 +428,9 @@ class Project < ActiveRecord::Base
end
def has_container_registry_tags?
- return unless container_registry_repository
+ return unless container_images
- container_registry_repository.tags.any?
+ container_images.first.tags.any?
end
def commit(ref = 'HEAD')
diff --git a/app/services/container_images/destroy_service.rb b/app/services/container_images/destroy_service.rb
new file mode 100644
index 00000000000..bc5b53fd055
--- /dev/null
+++ b/app/services/container_images/destroy_service.rb
@@ -0,0 +1,32 @@
+module ContainerImages
+ class DestroyService < BaseService
+
+ class DestroyError < StandardError; end
+
+ def execute(container_image)
+ @container_image = container_image
+
+ return false unless can?(current_user, :remove_project, project)
+
+ ContainerImage.transaction do
+ container_image.destroy!
+
+ unless remove_container_image_tags
+ raise_error('Failed to remove container image tags. Please try again or contact administrator')
+ end
+ end
+
+ true
+ end
+
+ private
+
+ def raise_error(message)
+ raise DestroyError.new(message)
+ end
+
+ def remove_container_image_tags
+ container_image.delete_tags
+ end
+ end
+end
diff --git a/app/services/container_images_repositories/container_images/create_service.rb b/app/services/container_images_repositories/container_images/create_service.rb
deleted file mode 100644
index 0c2c69d5183..00000000000
--- a/app/services/container_images_repositories/container_images/create_service.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-module ContainerImagesRepositories
- module ContainerImages
- class CreateService < BaseService
- def execute
- @container_image = container_images_repository.container_images.create(params)
- @container_image if @container_image.valid?
- end
-
- private
-
- def container_images_repository
- @container_images_repository ||= project.container_images_repository
- end
- end
- end
-end
diff --git a/app/services/container_images_repositories/container_images/destroy_service.rb b/app/services/container_images_repositories/container_images/destroy_service.rb
deleted file mode 100644
index 91b8cfeea47..00000000000
--- a/app/services/container_images_repositories/container_images/destroy_service.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-module ContainerImagesRepositories
- module ContainerImages
- class DestroyService < BaseService
- def execute(container_image)
- return false unless container_image
-
- container_image.destroy
- end
- end
- end
-end
diff --git a/app/services/container_images_repositories/container_images/push_service.rb b/app/services/container_images_repositories/container_images/push_service.rb
deleted file mode 100644
index 2731cf1d52e..00000000000
--- a/app/services/container_images_repositories/container_images/push_service.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-module ContainerImagesRepositories
- module ContainerImages
- class PushService < BaseService
- def execute(container_image_name, event)
- find_or_create_container_image(container_image_name).valid?
- end
-
- private
-
- def find_or_create_container_image(container_image_name)
- options = {name: container_image_name}
- container_images.find_by(options) ||
- ::ContainerImagesRepositories::ContainerImages::CreateService.new(project,
- current_user, options).execute
- end
-
- def container_images_repository
- @container_images_repository ||= project.container_images_repository
- end
-
- def container_images
- @container_images ||= container_images_repository.container_images
- end
- end
- end
-end
diff --git a/app/services/container_images_repositories/create_service.rb b/app/services/container_images_repositories/create_service.rb
deleted file mode 100644
index 7e9dd3abe5f..00000000000
--- a/app/services/container_images_repositories/create_service.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-module ContainerImagesRepositories
- class CreateService < BaseService
- def execute
- project.container_images_repository || ::ContainerImagesRepository.create(project: project)
- end
- end
-end
diff --git a/app/services/projects/destroy_service.rb b/app/services/projects/destroy_service.rb
index 9716a1780a9..ba410b79e8c 100644
--- a/app/services/projects/destroy_service.rb
+++ b/app/services/projects/destroy_service.rb
@@ -31,10 +31,6 @@ module Projects
project.team.truncate
project.destroy!
- unless remove_registry_tags
- raise_error('Failed to remove project container registry. Please try again or contact administrator')
- end
-
unless remove_repository(repo_path)
raise_error('Failed to remove project repository. Please try again or contact administrator')
end
@@ -68,12 +64,6 @@ module Projects
end
end
- def remove_registry_tags
- return true unless Gitlab.config.registry.enabled
-
- project.container_registry_repository.delete_tags
- end
-
def raise_error(message)
raise DestroyError.new(message)
end
diff --git a/app/views/projects/container_registry/_image.html.haml b/app/views/projects/container_registry/_image.html.haml
new file mode 100644
index 00000000000..b1d62e34a97
--- /dev/null
+++ b/app/views/projects/container_registry/_image.html.haml
@@ -0,0 +1,35 @@
+- expanded = false
+.container-image.js-toggle-container
+ .container-image-head
+ = link_to "#", class: "js-toggle-button" do
+ - if expanded
+ = icon("chevron-up")
+ - else
+ = icon("chevron-down")
+
+ = escape_once(image.name)
+ = clipboard_button(clipboard_text: "docker pull #{image.path}")
+ .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
+ = icon("trash cred")
+
+
+ .container-image-tags.js-toggle-content{ class: ("hide" unless expanded) }
+ - if image.tags.blank?
+ %li
+ .nothing-here-block No tags in Container Registry for this container image.
+
+ - else
+ .table-holder
+ %table.table.tags
+ %thead
+ %tr
+ %th Name
+ %th Image ID
+ %th Size
+ %th Created
+ - if can?(current_user, :update_container_image, @project)
+ %th
+
+ - image.tags.each do |tag|
+ = render 'tag', tag: tag
diff --git a/app/views/projects/container_registry/_tag.html.haml b/app/views/projects/container_registry/_tag.html.haml
index 10822b6184c..00345ec26de 100644
--- a/app/views/projects/container_registry/_tag.html.haml
+++ b/app/views/projects/container_registry/_tag.html.haml
@@ -25,5 +25,5 @@
- if can?(current_user, :update_container_image, @project)
%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
+ = 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
= icon("trash cred")
diff --git a/app/views/projects/container_registry/index.html.haml b/app/views/projects/container_registry/index.html.haml
index 993da27310f..f074ce6be6d 100644
--- a/app/views/projects/container_registry/index.html.haml
+++ b/app/views/projects/container_registry/index.html.haml
@@ -19,21 +19,9 @@
%br
docker push #{escape_once(@project.container_registry_repository_url)}
- - if @tags.blank?
- %li
- .nothing-here-block No images in Container Registry for this project.
+ - if @images.blank?
+ .nothing-here-block No container images in Container Registry for this project.
- else
- .table-holder
- %table.table.tags
- %thead
- %tr
- %th Name
- %th Image ID
- %th Size
- %th Created
- - if can?(current_user, :update_container_image, @project)
- %th
-
- - @tags.each do |tag|
- = render 'tag', tag: tag
+ - @images.each do |image|
+ = render 'image', image: image
diff --git a/db/migrate/20161029153736_create_container_images_repository.rb b/db/migrate/20161029153736_create_container_images_repository.rb
deleted file mode 100644
index d93180b1674..00000000000
--- a/db/migrate/20161029153736_create_container_images_repository.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# See http://doc.gitlab.com/ce/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
-class CreateContainerImagesRepository < ActiveRecord::Migration
- include Gitlab::Database::MigrationHelpers
-
- # Set this constant to true if this migration requires downtime.
- DOWNTIME = false
-
- # When a migration requires downtime you **must** uncomment the following
- # constant and define a short and easy to understand explanation as to why the
- # migration requires downtime.
- # DOWNTIME_REASON = ''
-
- # When using the methods "add_concurrent_index" or "add_column_with_default"
- # you must disable the use of transactions as these methods can not run in an
- # existing transaction. When using "add_concurrent_index" make sure that this
- # method is the _only_ method called in the migration, any other changes
- # should go in a separate migration. This ensures that upon failure _only_ the
- # index creation fails and can be retried or reverted easily.
- #
- # To disable transactions uncomment the following line and remove these
- # comments:
- # disable_ddl_transaction!
-
- def change
- create_table :container_images_repositories do |t|
- t.integer :project_id, null: false
- end
- end
-end
diff --git a/db/migrate/20161031013926_create_container_image.rb b/db/migrate/20161031013926_create_container_image.rb
index 94feae280a6..85c0913b8f3 100644
--- a/db/migrate/20161031013926_create_container_image.rb
+++ b/db/migrate/20161031013926_create_container_image.rb
@@ -25,7 +25,7 @@ class CreateContainerImage < ActiveRecord::Migration
def change
create_table :container_images do |t|
- t.integer :container_images_repository_id
+ t.integer :project_id
t.string :name
end
end
diff --git a/lib/api/registry_events.rb b/lib/api/registry_events.rb
index c0473051424..dc7279d2b75 100644
--- a/lib/api/registry_events.rb
+++ b/lib/api/registry_events.rb
@@ -41,9 +41,19 @@ module API
if event['action'] == 'push' and !!event['target']['tag']
namespace, container_image_name = ContainerImage::split_namespace(repository)
- ::ContainerImagesRepositories::ContainerImages::PushService.new(
- Project::find_with_namespace(namespace), current_user
- ).execute(container_image_name, event)
+ project = Project::find_with_namespace(namespace)
+
+ if project
+ container_image = project.container_images.find_or_create_by(name: container_image_name)
+
+ if container_image.valid?
+ puts('Valid!')
+ else
+ render_api_error!({ error: "Failed to create container image!" }, 400)
+ end
+ else
+ not_found!('Project')
+ end
end
end
end