diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-10-10 15:06:19 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-10-10 15:06:19 +0300 |
commit | 69849c280c5525d132ebaddb1200c390a42ecc06 (patch) | |
tree | 2c6ffc6fd6dc4fa719305f25b475391730389747 /app | |
parent | c157f963db87a40a3ba7b94b339530ee83194bc8 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r-- | app/controllers/concerns/render_service_results.rb | 29 | ||||
-rw-r--r-- | app/controllers/projects/environments/prometheus_api_controller.rb | 21 | ||||
-rw-r--r-- | app/controllers/projects/grafana_api_controller.rb | 25 | ||||
-rw-r--r-- | app/controllers/projects/merge_requests/diffs_controller.rb | 7 | ||||
-rw-r--r-- | app/helpers/diff_helper.rb | 4 | ||||
-rw-r--r-- | app/models/grafana_integration.rb | 4 | ||||
-rw-r--r-- | app/models/repository_language.rb | 2 | ||||
-rw-r--r-- | app/serializers/diff_file_metadata_entity.rb | 10 | ||||
-rw-r--r-- | app/serializers/diffs_entity.rb | 2 | ||||
-rw-r--r-- | app/serializers/diffs_metadata_entity.rb | 6 | ||||
-rw-r--r-- | app/serializers/diffs_metadata_serializer.rb | 5 | ||||
-rw-r--r-- | app/services/grafana/proxy_service.rb | 83 | ||||
-rw-r--r-- | app/views/projects/diffs/_diffs.html.haml | 2 |
13 files changed, 179 insertions, 21 deletions
diff --git a/app/controllers/concerns/render_service_results.rb b/app/controllers/concerns/render_service_results.rb new file mode 100644 index 00000000000..0149a71d9f5 --- /dev/null +++ b/app/controllers/concerns/render_service_results.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +module RenderServiceResults + extend ActiveSupport::Concern + + def success_response(result) + render({ + status: result[:http_status], + json: result[:body] + }) + end + + def continue_polling_response + render({ + status: :no_content, + json: { + status: _('processing'), + message: _('Not ready yet. Try again later.') + } + }) + end + + def error_response(result) + render({ + status: result[:http_status] || :bad_request, + json: { status: result[:status], message: result[:message] } + }) + end +end diff --git a/app/controllers/projects/environments/prometheus_api_controller.rb b/app/controllers/projects/environments/prometheus_api_controller.rb index 9c6c6513a78..e902d218c75 100644 --- a/app/controllers/projects/environments/prometheus_api_controller.rb +++ b/app/controllers/projects/environments/prometheus_api_controller.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class Projects::Environments::PrometheusApiController < Projects::ApplicationController + include RenderServiceResults + before_action :authorize_read_prometheus! before_action :environment @@ -12,21 +14,10 @@ class Projects::Environments::PrometheusApiController < Projects::ApplicationCon proxy_params ).execute - if result.nil? - return render status: :no_content, json: { - status: _('processing'), - message: _('Not ready yet. Try again later.') - } - end - - if result[:status] == :success - render status: result[:http_status], json: result[:body] - else - render( - status: result[:http_status] || :bad_request, - json: { status: result[:status], message: result[:message] } - ) - end + return continue_polling_response if result.nil? + return error_response(result) if result[:status] == :error + + success_response(result) end private diff --git a/app/controllers/projects/grafana_api_controller.rb b/app/controllers/projects/grafana_api_controller.rb new file mode 100644 index 00000000000..4bdf4c12cac --- /dev/null +++ b/app/controllers/projects/grafana_api_controller.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +class Projects::GrafanaApiController < Projects::ApplicationController + include RenderServiceResults + + def proxy + result = ::Grafana::ProxyService.new( + project, + params[:datasource_id], + params[:proxy_path], + query_params.to_h + ).execute + + return continue_polling_response if result.nil? + return error_response(result) if result[:status] == :error + + success_response(result) + end + + private + + def query_params + params.permit(:query, :start, :end, :step) + end +end diff --git a/app/controllers/projects/merge_requests/diffs_controller.rb b/app/controllers/projects/merge_requests/diffs_controller.rb index 7b694dcdd77..1913d7cd580 100644 --- a/app/controllers/projects/merge_requests/diffs_controller.rb +++ b/app/controllers/projects/merge_requests/diffs_controller.rb @@ -7,7 +7,7 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic before_action :apply_diff_view_cookie! before_action :commit, except: :diffs_batch before_action :define_diff_vars, except: :diffs_batch - before_action :define_diff_comment_vars, except: :diffs_batch + before_action :define_diff_comment_vars, except: [:diffs_batch, :diffs_metadata] def show render_diffs @@ -37,6 +37,11 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic render json: PaginatedDiffSerializer.new(current_user: current_user).represent(diffs, options) end + def diffs_metadata + render json: DiffsMetadataSerializer.new(project: @merge_request.project) + .represent(@diffs, additional_attributes) + end + private def preloadable_mr_relations diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb index 6aafd856423..52ec2eadf5e 100644 --- a/app/helpers/diff_helper.rb +++ b/app/helpers/diff_helper.rb @@ -203,8 +203,8 @@ module DiffHelper link_to "#{hide_whitespace? ? 'Show' : 'Hide'} whitespace changes", url, class: options[:class] end - def render_overflow_warning?(diff_files) - diffs = @merge_request_diff.presence || diff_files + def render_overflow_warning?(diffs_collection) + diffs = @merge_request_diff.presence || diffs_collection.diff_files diffs.overflow? end diff --git a/app/models/grafana_integration.rb b/app/models/grafana_integration.rb index 668b9dafd7d..51cc398394d 100644 --- a/app/models/grafana_integration.rb +++ b/app/models/grafana_integration.rb @@ -13,4 +13,8 @@ class GrafanaIntegration < ApplicationRecord addressable_url: { enforce_sanitization: true, ascii_only: true } validates :token, :project, presence: true + + def client + @client ||= ::Grafana::Client.new(api_url: grafana_url.chomp('/'), token: token) + end end diff --git a/app/models/repository_language.rb b/app/models/repository_language.rb index e6867f905e2..e468d716239 100644 --- a/app/models/repository_language.rb +++ b/app/models/repository_language.rb @@ -7,7 +7,7 @@ class RepositoryLanguage < ApplicationRecord default_scope { includes(:programming_language) } validates :project, presence: true - validates :share, inclusion: { in: 0..100, message: "The share of a lanuage is between 0 and 100" } + validates :share, inclusion: { in: 0..100, message: "The share of a language is between 0 and 100" } validates :programming_language, uniqueness: { scope: :project_id } delegate :name, :color, to: :programming_language diff --git a/app/serializers/diff_file_metadata_entity.rb b/app/serializers/diff_file_metadata_entity.rb new file mode 100644 index 00000000000..500a844b170 --- /dev/null +++ b/app/serializers/diff_file_metadata_entity.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +class DiffFileMetadataEntity < Grape::Entity + expose :added_lines + expose :removed_lines + expose :new_path + expose :old_path + expose :new_file?, as: :new_file + expose :deleted_file?, as: :deleted_file +end diff --git a/app/serializers/diffs_entity.rb b/app/serializers/diffs_entity.rb index 1763fe5b6ab..19875a1287c 100644 --- a/app/serializers/diffs_entity.rb +++ b/app/serializers/diffs_entity.rb @@ -53,7 +53,7 @@ class DiffsEntity < Grape::Entity # rubocop: enable CodeReuse/ActiveRecord expose :render_overflow_warning do |diffs| - render_overflow_warning?(diffs.diff_files) + render_overflow_warning?(diffs) end expose :email_patch_path, if: -> (*) { merge_request } do |diffs| diff --git a/app/serializers/diffs_metadata_entity.rb b/app/serializers/diffs_metadata_entity.rb new file mode 100644 index 00000000000..c82c686e8ef --- /dev/null +++ b/app/serializers/diffs_metadata_entity.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +class DiffsMetadataEntity < DiffsEntity + unexpose :diff_files + expose :diff_files, using: DiffFileMetadataEntity +end diff --git a/app/serializers/diffs_metadata_serializer.rb b/app/serializers/diffs_metadata_serializer.rb new file mode 100644 index 00000000000..9f3ba7b778d --- /dev/null +++ b/app/serializers/diffs_metadata_serializer.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +class DiffsMetadataSerializer < BaseSerializer + entity DiffsMetadataEntity +end diff --git a/app/services/grafana/proxy_service.rb b/app/services/grafana/proxy_service.rb new file mode 100644 index 00000000000..74fcdc750b0 --- /dev/null +++ b/app/services/grafana/proxy_service.rb @@ -0,0 +1,83 @@ +# frozen_string_literal: true + +# Proxies calls to a Grafana-integrated Prometheus instance +# through the Grafana proxy API + +# This allows us to fetch and render metrics in GitLab from a Prometheus +# instance for which dashboards are configured in Grafana +module Grafana + class ProxyService < BaseService + include ReactiveCaching + + self.reactive_cache_key = ->(service) { service.cache_key } + self.reactive_cache_lease_timeout = 30.seconds + self.reactive_cache_refresh_interval = 30.seconds + self.reactive_cache_worker_finder = ->(_id, *args) { from_cache(*args) } + + attr_accessor :project, :datasource_id, :proxy_path, :query_params + + # @param project_id [Integer] Project id for which grafana is configured. + # + # See #initialize for other parameters. + def self.from_cache(project_id, datasource_id, proxy_path, query_params) + project = Project.find(project_id) + + new(project, datasource_id, proxy_path, query_params) + end + + # @param project [Project] Project for which grafana is configured. + # @param datasource_id [String] Grafana datasource id for Prometheus instance + # @param proxy_path [String] Path to Prometheus endpoint; EX) 'api/v1/query_range' + # @param query_params [Hash<String, String>] Supported params: [query, start, end, step] + def initialize(project, datasource_id, proxy_path, query_params) + @project = project + @datasource_id = datasource_id + @proxy_path = proxy_path + @query_params = query_params + end + + def execute + return cannot_proxy_response unless client + + with_reactive_cache(*cache_key) { |result| result } + end + + def calculate_reactive_cache(*) + return cannot_proxy_response unless client + + response = client.proxy_datasource( + datasource_id: datasource_id, + proxy_path: proxy_path, + query: query_params + ) + + success(http_status: response.code, body: response.body) + rescue ::Grafana::Client::Error => error + service_unavailable_response(error) + end + + # Required for ReactiveCaching; Usage overridden by + # self.reactive_cache_worker_finder + def id + nil + end + + def cache_key + [project.id, datasource_id, proxy_path, query_params] + end + + private + + def client + project.grafana_integration&.client + end + + def service_unavailable_response(exception) + error(exception.message, :service_unavailable) + end + + def cannot_proxy_response + error('Proxy support for this API is not available currently') + end + end +end diff --git a/app/views/projects/diffs/_diffs.html.haml b/app/views/projects/diffs/_diffs.html.haml index 2dba3fcd664..cf7fe36af9d 100644 --- a/app/views/projects/diffs/_diffs.html.haml +++ b/app/views/projects/diffs/_diffs.html.haml @@ -21,7 +21,7 @@ = parallel_diff_btn = render 'projects/diffs/stats', diff_files: diff_files -- if render_overflow_warning?(diff_files) +- if render_overflow_warning?(diffs) = render 'projects/diffs/warning', diff_files: diffs .files{ data: { can_create_note: can_create_note } } |