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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
|
# frozen_string_literal: true
# Copies system dashboard definition in .yml file into designated
# .yml file inside `.gitlab/dashboards`
module Metrics
module Dashboard
class CloneDashboardService < ::BaseService
include Stepable
ALLOWED_FILE_TYPE = '.yml'
USER_DASHBOARDS_DIR = ::Metrics::Dashboard::CustomDashboardService::DASHBOARD_ROOT
steps :check_push_authorized,
:check_branch_name,
:check_file_type,
:check_dashboard_template,
:create_file,
:refresh_repository_method_caches
class << self
def allowed_dashboard_templates
@allowed_dashboard_templates ||= Set[::Metrics::Dashboard::SystemDashboardService::DASHBOARD_PATH].freeze
end
def sequences
@sequences ||= {
::Metrics::Dashboard::SystemDashboardService::DASHBOARD_PATH => [::Gitlab::Metrics::Dashboard::Stages::CommonMetricsInserter,
::Gitlab::Metrics::Dashboard::Stages::CustomMetricsInserter,
::Gitlab::Metrics::Dashboard::Stages::Sorter].freeze
}.freeze
end
end
def execute
execute_steps
end
private
def check_push_authorized(result)
return error(_('You are not allowed to push into this branch. Create another branch or open a merge request.'), :forbidden) unless push_authorized?
success(result)
end
def check_branch_name(result)
return error(_('There was an error creating the dashboard, branch name is invalid.'), :bad_request) unless valid_branch_name?
return error(_('There was an error creating the dashboard, branch named: %{branch} already exists.') % { branch: params[:branch] }, :bad_request) unless new_or_default_branch?
success(result)
end
def check_file_type(result)
return error(_('The file name should have a .yml extension'), :bad_request) unless target_file_type_valid?
success(result)
end
def check_dashboard_template(result)
return error(_('Not found.'), :not_found) unless self.class.allowed_dashboard_templates.include?(params[:dashboard])
success(result)
end
def create_file(result)
create_file_response = ::Files::CreateService.new(project, current_user, dashboard_attrs).execute
if create_file_response[:status] == :success
success(result.merge(create_file_response))
else
wrap_error(create_file_response)
end
end
def refresh_repository_method_caches(result)
repository.refresh_method_caches([:metrics_dashboard])
success(result.merge(http_status: :created, dashboard: dashboard_details))
end
def dashboard_attrs
{
commit_message: params[:commit_message],
file_path: new_dashboard_path,
file_content: new_dashboard_content,
encoding: 'text',
branch_name: branch,
start_branch: repository.branch_exists?(branch) ? branch : project.default_branch
}
end
def dashboard_details
{
path: new_dashboard_path,
display_name: ::Metrics::Dashboard::CustomDashboardService.name_for_path(new_dashboard_path),
default: false,
system_dashboard: false
}
end
def push_authorized?
Gitlab::UserAccess.new(current_user, project: project).can_push_to_branch?(branch)
end
def dashboard_template
@dashboard_template ||= params[:dashboard]
end
def branch
@branch ||= params[:branch]
end
def new_or_default_branch?
!repository.branch_exists?(params[:branch]) || project.default_branch == params[:branch]
end
def valid_branch_name?
Gitlab::GitRefValidator.validate(params[:branch])
end
def new_dashboard_path
@new_dashboard_path ||= File.join(USER_DASHBOARDS_DIR, file_name)
end
def file_name
@file_name ||= File.basename(params[:file_name])
end
def target_file_type_valid?
File.extname(params[:file_name]) == ALLOWED_FILE_TYPE
end
def wrap_error(result)
if result[:message] == 'A file with this name already exists'
error(_("A file with '%{file_name}' already exists in %{branch} branch") % { file_name: file_name, branch: branch }, :bad_request)
else
result
end
end
def new_dashboard_content
::Gitlab::Metrics::Dashboard::Processor
.new(project, raw_dashboard, sequence, {})
.process.deep_stringify_keys.to_yaml
end
def repository
@repository ||= project.repository
end
def raw_dashboard
YAML.safe_load(File.read(Rails.root.join(dashboard_template)))
end
def sequence
self.class.sequences[dashboard_template]
end
end
end
end
Metrics::Dashboard::CloneDashboardService.prepend_if_ee('EE::Metrics::Dashboard::CloneDashboardService')
|