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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
|
# frozen_string_literal: true
module Gitlab
module DatabaseImporters
module SelfMonitoring
module Project
class CreateService < ::BaseService
include Stepable
STEPS_ALLOWED_TO_FAIL = [
:validate_application_settings, :validate_project_created, :validate_admins
].freeze
VISIBILITY_LEVEL = Gitlab::VisibilityLevel::INTERNAL
PROJECT_NAME = 'GitLab Instance Administration'
steps :validate_application_settings,
:validate_project_created,
:validate_admins,
:create_group,
:create_project,
:save_project_id,
:add_group_members,
:add_prometheus_manual_configuration
def initialize
super(nil)
end
def execute!
result = execute_steps
if result[:status] == :success
result
elsif STEPS_ALLOWED_TO_FAIL.include?(result[:last_step])
success
else
raise StandardError, result[:message]
end
end
private
def validate_application_settings(_result)
return success if application_settings
log_error('No application_settings found')
error(_('No application_settings found'))
end
def validate_project_created(result)
return success(result) unless project_created?
log_error('Project already created')
error(_('Project already created'))
end
def validate_admins(result)
unless instance_admins.any?
log_error('No active admin user found')
return error(_('No active admin user found'))
end
success(result)
end
def create_group(result)
if project_created?
log_info(_('Instance administrators group already exists'))
result[:group] = application_settings.instance_administration_project.owner
return success(result)
end
result[:group] = ::Groups::CreateService.new(group_owner, create_group_params).execute
if result[:group].persisted?
success(result)
else
error(_('Could not create group'))
end
end
def create_project(result)
if project_created?
log_info('Instance administration project already exists')
result[:project] = application_settings.instance_administration_project
return success(result)
end
result[:project] = ::Projects::CreateService.new(group_owner, create_project_params(result[:group])).execute
if result[:project].persisted?
success(result)
else
log_error("Could not create instance administration project. Errors: %{errors}" % { errors: result[:project].errors.full_messages })
error(_('Could not create project'))
end
end
def save_project_id(result)
return success if project_created?
response = application_settings.update(
instance_administration_project_id: result[:project].id
)
if response
success(result)
else
log_error("Could not save instance administration project ID, errors: %{errors}" % { errors: application_settings.errors.full_messages })
error(_('Could not save project ID'))
end
end
def add_group_members(result)
group = result[:group]
members = group.add_users(members_to_add(group), Gitlab::Access::MAINTAINER)
errors = members.flat_map { |member| member.errors.full_messages }
if errors.any?
log_error('Could not add admins as members to self-monitoring project. Errors: %{errors}' % { errors: errors })
error(_('Could not add admins as members'))
else
success(result)
end
end
def add_prometheus_manual_configuration(result)
return success(result) unless prometheus_enabled?
return success(result) unless prometheus_listen_address.present?
service = result[:project].find_or_initialize_service('prometheus')
unless service.update(prometheus_service_attributes)
log_error('Could not save prometheus manual configuration for self-monitoring project. Errors: %{errors}' % { errors: service.errors.full_messages })
return error(_('Could not save prometheus manual configuration'))
end
success(result)
end
def application_settings
@application_settings ||= ApplicationSetting.current_without_cache
end
def project_created?
application_settings.instance_administration_project.present?
end
def parse_url(uri_string)
Addressable::URI.parse(uri_string)
rescue Addressable::URI::InvalidURIError, TypeError
end
def prometheus_enabled?
::Gitlab::Prometheus::Internal.prometheus_enabled?
end
def prometheus_listen_address
::Gitlab::Prometheus::Internal.listen_address
end
def instance_admins
@instance_admins ||= User.admins.active
end
def group_owner
instance_admins.first
end
def members_to_add(group)
# Exclude admins who are already members of group because
# `group.add_users(users)` returns an error if the users parameter contains
# users who are already members of the group.
instance_admins - group.members.collect(&:user)
end
def create_group_params
{
name: 'GitLab Instance Administrators',
path: "gitlab-instance-administrators-#{SecureRandom.hex(4)}",
visibility_level: VISIBILITY_LEVEL
}
end
def docs_path
Rails.application.routes.url_helpers.help_page_path(
'administration/monitoring/gitlab_instance_administration_project/index'
)
end
def create_project_params(group)
{
initialize_with_readme: true,
visibility_level: VISIBILITY_LEVEL,
name: PROJECT_NAME,
description: "This project is automatically generated and will be used to help monitor this GitLab instance. [More information](#{docs_path})",
namespace_id: group.id
}
end
def internal_prometheus_listen_address_uri
::Gitlab::Prometheus::Internal.uri
end
def prometheus_service_attributes
{
api_url: internal_prometheus_listen_address_uri,
manual_configuration: true,
active: true
}
end
end
end
end
end
end
|