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
|
# frozen_string_literal: true
module Gitlab
module DatabaseImporters
module SelfMonitoring
module Project
class CreateService < ::BaseService
include Stepable
include SelfMonitoring::Helpers
VISIBILITY_LEVEL = Gitlab::VisibilityLevel::INTERNAL
PROJECT_NAME = 'Monitoring'
steps :validate_application_settings,
:create_group,
:create_project,
:save_project_id,
:create_environment,
:add_prometheus_manual_configuration,
:track_event
def initialize
super(nil)
end
def execute
execute_steps
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 create_group(result)
create_group_response =
Gitlab::DatabaseImporters::InstanceAdministrators::CreateGroup.new.execute
if create_group_response[:status] == :success
success(result.merge(create_group_response))
else
error(create_group_response[:message])
end
end
def create_project(result)
if project_created?
log_info('Instance administration project already exists')
result[:project] = self_monitoring_project
return success(result)
end
owner = result[:group].owners.first
result[:project] = ::Projects::CreateService.new(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(result) if project_created?
response = application_settings.update(
self_monitoring_project_id: result[:project].id
)
if response
# In the add_prometheus_manual_configuration method, the Prometheus
# listen_address config is saved as an api_url in the PrometheusService
# model. There are validates hooks in the PrometheusService model that
# check if the project associated with the PrometheusService is the
# self_monitoring project. It checks
# Gitlab::CurrentSettings.self_monitoring_project_id, which is why the
# Gitlab::CurrentSettings cache needs to be expired here, so that
# PrometheusService sees the latest self_monitoring_project_id.
Gitlab::CurrentSettings.expire_current_application_settings
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 create_environment(result)
return success(result) if result[:project].environments.exists?
environment = ::Environment.new(project_id: result[:project].id, name: 'production')
if environment.save
success(result)
else
log_error("Could not create environment for the Self monitoring project. Errors: %{errors}" % { errors: environment.errors.full_messages })
error(_('Could not create environment'))
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 track_event(result)
::Gitlab::Tracking.event("self_monitoring", "project_created")
success(result)
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 docs_path
Rails.application.routes.url_helpers.help_page_path(
'administration/monitoring/gitlab_self_monitoring_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 helps monitor this GitLab instance. [Learn more](#{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
|