summaryrefslogtreecommitdiff
path: root/app/controllers/concerns/metrics_dashboard.rb
blob: 7a84c597424add3de49aa0dd82e92b83c98c2601 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# frozen_string_literal: true

# Provides an action which fetches a metrics dashboard according
# to the parameters specified by the controller.
module MetricsDashboard
  include RenderServiceResults
  include ChecksCollaboration
  include EnvironmentsHelper

  extend ActiveSupport::Concern

  def metrics_dashboard
    return not_found if Feature.enabled?(:remove_monitor_metrics)

    result = dashboard_finder.find(
      project_for_dashboard,
      current_user,
      decoded_params
    )

    if result
      result[:all_dashboards] = all_dashboards if include_all_dashboards?
      result[:metrics_data] = metrics_data(project_for_dashboard, environment_for_dashboard)
    end

    respond_to do |format|
      if result.nil?
        format.json { continue_polling_response }
      elsif result[:status] == :success
        format.json { render dashboard_success_response(result) }
      else
        format.json { render dashboard_error_response(result) }
      end
    end
  end

  private

  def all_dashboards
    dashboard_finder
      .find_all_paths(project_for_dashboard)
      .map { |dashboard| amend_dashboard(dashboard) }
  end

  def amend_dashboard(dashboard)
    project_dashboard = project_for_dashboard && !dashboard[:out_of_the_box_dashboard]

    dashboard[:can_edit] = project_dashboard ? can_edit?(dashboard) : false
    dashboard[:project_blob_path] = project_dashboard ? dashboard_project_blob_path(dashboard) : nil
    dashboard[:starred] = starred_dashboards.include?(dashboard[:path])
    dashboard[:user_starred_path] = project_for_dashboard ? user_starred_path(project_for_dashboard, dashboard[:path]) : nil

    dashboard
  end

  def user_starred_path(project, path)
    expose_path(api_v4_projects_metrics_user_starred_dashboards_path(id: project.id, params: { dashboard_path: path }))
  end

  def dashboard_project_blob_path(dashboard)
    project_blob_path(project_for_dashboard, File.join(project_for_dashboard.default_branch, dashboard.fetch(:path, "")))
  end

  def can_edit?(dashboard)
    can_collaborate_with_project?(project_for_dashboard, ref: project_for_dashboard.default_branch)
  end

  # Override in class to provide arguments to the finder.
  def metrics_dashboard_params
    {}
  end

  # Override in class if response requires complete list of
  # dashboards in addition to requested dashboard body.
  def include_all_dashboards?
    false
  end

  def dashboard_finder
    ::Gitlab::Metrics::Dashboard::Finder
  end

  def starred_dashboards
    @starred_dashboards ||=
      if project_for_dashboard.present?
        ::Metrics::UsersStarredDashboardsFinder
          .new(user: current_user, project: project_for_dashboard)
          .execute
          .map(&:dashboard_path)
          .to_set
      else
        Set.new
      end
  end

  # Project is not defined for group and admin level clusters.
  def project_for_dashboard
    defined?(project) ? project : nil
  end

  def environment_for_dashboard
    defined?(environment) ? environment : nil
  end

  def dashboard_success_response(result)
    {
      status: :ok,
      json: result.slice(:all_dashboards, :dashboard, :status, :metrics_data)
    }
  end

  def dashboard_error_response(result)
    {
      status: result[:http_status] || :bad_request,
      json: result.slice(:all_dashboards, :message, :status)
    }
  end

  def decoded_params
    params = metrics_dashboard_params

    params[:dashboard_path] = CGI.unescape(params[:dashboard_path]) if params[:dashboard_path]

    params
  end
end