From b0ddbaa07cd780b0ed86aa4e3c24744c6426b1e1 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 18 Apr 2016 08:14:40 -0400 Subject: [PATCH] Added docker registry view --- app/controllers/projects/images_controller.rb | 26 ++++++++++ app/helpers/gitlab_routing_helper.rb | 4 ++ app/helpers/projects_helper.rb | 4 ++ app/models/project.rb | 4 ++ app/models/registry.rb | 42 ++++++++++++++++ app/views/layouts/nav/_project.html.haml | 7 +++ .../projects/images/_header_title.html.haml | 1 + app/views/projects/images/index.html.haml | 48 +++++++++++++++++++ config/initializers/mime_types.rb | 7 +++ config/routes.rb | 2 + lib/gitlab/regex.rb | 4 ++ lib/registry_client.rb | 38 +++++++++++++++ 12 files changed, 187 insertions(+) create mode 100644 app/controllers/projects/images_controller.rb create mode 100644 app/models/registry.rb create mode 100644 app/views/projects/images/_header_title.html.haml create mode 100644 app/views/projects/images/index.html.haml create mode 100644 lib/registry_client.rb diff --git a/app/controllers/projects/images_controller.rb b/app/controllers/projects/images_controller.rb new file mode 100644 index 0000000000..5b10746aa0 --- /dev/null +++ b/app/controllers/projects/images_controller.rb @@ -0,0 +1,26 @@ +class Projects::ImagesController < Projects::ApplicationController + before_action :authorize_read_image! + before_action :authorize_update_image!, only: [:destroy] + before_action :tag, except: [:index] + layout 'project' + + def index + @tags = registry.tags + end + + def destroy + # registry.destroy_tag(tag['fsLayers'].first['blobSum']) + registry.destroy_tag(registry.tag_digest(params[:id])) + redirect_to namespace_project_images_path(project.namespace, project) + end + + private + + def registry + @registry ||= project.registry + end + + def tag + @tag ||= registry.tag(params[:id]) + end +end diff --git a/app/helpers/gitlab_routing_helper.rb b/app/helpers/gitlab_routing_helper.rb index f07eff3fb5..66cb41cc49 100644 --- a/app/helpers/gitlab_routing_helper.rb +++ b/app/helpers/gitlab_routing_helper.rb @@ -33,6 +33,10 @@ module GitlabRoutingHelper namespace_project_builds_path(project.namespace, project, *args) end + def project_images_path(project, *args) + namespace_project_images_path(project.namespace, project, *args) + end + def activity_project_path(project, *args) activity_namespace_project_path(project.namespace, project, *args) end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 3d5e61d2c1..6d1e630a09 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -152,6 +152,10 @@ module ProjectsHelper nav_tabs << :builds end + if can?(current_user, :read_image, project) + nav_tabs << :images + end + if can?(current_user, :admin_project, project) nav_tabs << :settings end diff --git a/app/models/project.rb b/app/models/project.rb index 76265a59ea..496f9f3e34 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -370,6 +370,10 @@ class Project < ActiveRecord::Base @repository ||= Repository.new(path_with_namespace, self) end + def registry + @registry ||= Registry.new(path_with_namespace, self) + end + def registry_repository_url "#{Gitlab.config.registry.host_with_port}/#{path_with_namespace}" if images_enabled? && Gitlab.config.registry.enabled end diff --git a/app/models/registry.rb b/app/models/registry.rb new file mode 100644 index 0000000000..b4ef60a016 --- /dev/null +++ b/app/models/registry.rb @@ -0,0 +1,42 @@ +require 'net/http' + +class Registry + attr_accessor :path_with_namespace, :project + + def initialize(path_with_namespace, project) + @path_with_namespace = path_with_namespace + @project = project + end + + def tags + @tags ||= client.tags(path_with_namespace) + end + + def tag(reference) + return @tag[reference] if defined?(@tag[reference]) + @tag ||= {} + @tag[reference] ||= client.tag(path_with_namespace, reference) + end + + def tag_digest(reference) + return @tag_digest[reference] if defined?(@tag_digest[reference]) + @tag_digest ||= {} + @tag_digest[reference] ||= client.tag_digest(path_with_namespace, reference) + end + + def destroy_tag(reference) + client.delete_tag(path_with_namespace, reference) + end + + def blob_size(blob) + return @blob_size[blob] if defined?(@blob_size[blob]) + @blob_size ||= {} + @blob_size[blob] ||= client.blob_size(path_with_namespace, blob) + end + + private + + def client + @client ||= RegistryClient.new(Gitlab.config.registry.api_url) + end +end diff --git a/app/views/layouts/nav/_project.html.haml b/app/views/layouts/nav/_project.html.haml index 479bde3371..2577afefa9 100644 --- a/app/views/layouts/nav/_project.html.haml +++ b/app/views/layouts/nav/_project.html.haml @@ -46,6 +46,13 @@ Builds %span.count.builds_counter= number_with_delimiter(@project.builds.running_or_pending.count(:all)) + - if project_nav_tab? :images + = nav_link(controller: %w(images)) do + = link_to project_images_path(@project), title: 'Images', class: 'shortcuts-images' do + = icon('image fw') + %span + Images + - if project_nav_tab? :graphs = nav_link(controller: %w(graphs)) do = link_to namespace_project_graph_path(@project.namespace, @project, current_ref), title: 'Graphs', class: 'shortcuts-graphs' do diff --git a/app/views/projects/images/_header_title.html.haml b/app/views/projects/images/_header_title.html.haml new file mode 100644 index 0000000000..648aeeef2d --- /dev/null +++ b/app/views/projects/images/_header_title.html.haml @@ -0,0 +1 @@ +- header_title project_title(@project, "Images", project_images_path(@project)) diff --git a/app/views/projects/images/index.html.haml b/app/views/projects/images/index.html.haml new file mode 100644 index 0000000000..338f3e5662 --- /dev/null +++ b/app/views/projects/images/index.html.haml @@ -0,0 +1,48 @@ +- page_title "Images" += render "header_title" + +.top-area + .nav-controls + +.gray-content-block + A list of Docker Images for this project + +%ul.content-list + - if @tags.blank? + %li + .nothing-here-block No images to show + - else + .table-holder + %table.table.builds + %thead + %tr + %th Name + %th Layers + %th Size + %th Created + %th Docker + %th + + - @tags.sort.each do |tag| + - details = @registry.tag(tag) + - layer = details['history'].first + - if layer && layer['v1Compatibility'] + - layer_data = JSON.parse(layer['v1Compatibility']) + %tr + %td + = link_to namespace_project_image_path(@project.namespace, @project, tag) do + #{details['name']}:#{details['tag']} + %td + = details['fsLayers'].length + %td + = number_to_human_size(details['fsLayers'].inject(0) { |sum, d| sum + @registry.blob_size(d['blobSum']) }.bytes) + %td + - if layer_data + = time_ago_in_words(DateTime.rfc3339(layer_data['created'])) + %td + - if layer_data + = layer_data['docker_version'] + %td.content + .controls.hidden-xs.pull-right + = link_to namespace_project_image_path(@project.namespace, @project, tag), class: 'btn btn-remove has-tooltip', title: "Remove", data: { confirm: "Are you sure?" }, method: :delete do + = icon("trash cred") diff --git a/config/initializers/mime_types.rb b/config/initializers/mime_types.rb index ca58ae92d1..71e3c9d7db 100644 --- a/config/initializers/mime_types.rb +++ b/config/initializers/mime_types.rb @@ -8,3 +8,10 @@ Mime::Type.register_alias "text/plain", :diff Mime::Type.register_alias "text/plain", :patch Mime::Type.register_alias 'text/html', :markdown Mime::Type.register_alias 'text/html', :md +#Mime::Type.unregister :json +Mime::Type.register_alias 'application/vnd.docker.distribution.manifest.v1+prettyjws', :json +#Mime::Type.register 'application/json', :json, %w( text/plain text/x-json application/jsonrequest ) + +ActionDispatch::ParamsParser::DEFAULT_PARSERS[Mime::Type.lookup('application/vnd.docker.distribution.manifest.v1+prettyjws')]=lambda do |body| + JSON.parse(body) +end diff --git a/config/routes.rb b/config/routes.rb index 5b48819dd9..0280898acc 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -690,6 +690,8 @@ Rails.application.routes.draw do end end + resources :images, only: [:index, :destroy], constraints: { id: Gitlab::Regex.image_reference_regex } + resources :milestones, constraints: { id: /\d+/ } do member do put :sort_issues diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb index ace906a6f5..9b8f416ddf 100644 --- a/lib/gitlab/regex.rb +++ b/lib/gitlab/regex.rb @@ -96,5 +96,9 @@ module Gitlab (?