219 lines
6.3 KiB
Ruby
219 lines
6.3 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module SelfMonitoring
|
|
module Project
|
|
class CreateService < ::BaseService
|
|
include Stepable
|
|
include Gitlab::Utils::StrongMemoize
|
|
|
|
VISIBILITY_LEVEL = Gitlab::VisibilityLevel::INTERNAL
|
|
PROJECT_NAME = 'GitLab Instance Administration'
|
|
PROJECT_DESCRIPTION = <<~HEREDOC
|
|
This project is automatically generated and will be used to help monitor this GitLab instance.
|
|
HEREDOC
|
|
|
|
GROUP_NAME = 'GitLab Instance Administrators'
|
|
GROUP_PATH = 'gitlab-instance-administrators'
|
|
|
|
steps :validate_admins,
|
|
:create_group,
|
|
:create_project,
|
|
:save_project_id,
|
|
:add_group_members,
|
|
:add_to_whitelist,
|
|
:add_prometheus_manual_configuration
|
|
|
|
def initialize
|
|
super(nil)
|
|
end
|
|
|
|
def execute
|
|
execute_steps
|
|
end
|
|
|
|
private
|
|
|
|
def validate_admins
|
|
unless instance_admins.any?
|
|
log_error('No active admin user found')
|
|
return error('No active admin user found')
|
|
end
|
|
|
|
success
|
|
end
|
|
|
|
def create_group
|
|
if project_created?
|
|
log_info(_('Instance administrators group already exists'))
|
|
@group = application_settings.instance_administration_project.owner
|
|
return success(group: @group)
|
|
end
|
|
|
|
admin_user = group_owner
|
|
@group = ::Groups::CreateService.new(admin_user, create_group_params).execute
|
|
|
|
if @group.persisted?
|
|
success(group: @group)
|
|
else
|
|
error('Could not create group')
|
|
end
|
|
end
|
|
|
|
def create_project
|
|
if project_created?
|
|
log_info(_('Instance administration project already exists'))
|
|
@project = application_settings.instance_administration_project
|
|
return success(project: project)
|
|
end
|
|
|
|
admin_user = group_owner
|
|
@project = ::Projects::CreateService.new(admin_user, create_project_params).execute
|
|
|
|
if project.persisted?
|
|
success(project: project)
|
|
else
|
|
log_error(_("Could not create instance administration project. Errors: %{errors}") % { errors: project.errors.full_messages })
|
|
error(_('Could not create project'))
|
|
end
|
|
end
|
|
|
|
def save_project_id
|
|
return success if project_created?
|
|
|
|
result = ApplicationSettings::UpdateService.new(
|
|
application_settings,
|
|
group_owner,
|
|
{ instance_administration_project_id: @project.id }
|
|
).execute
|
|
|
|
if result
|
|
success
|
|
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
|
|
members = @group.add_users(group_maintainers, 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}")
|
|
error('Could not add admins as members')
|
|
else
|
|
success
|
|
end
|
|
end
|
|
|
|
def add_to_whitelist
|
|
return success unless prometheus_enabled?
|
|
return success unless prometheus_listen_address.present?
|
|
|
|
uri = parse_url(internal_prometheus_listen_address_uri)
|
|
return error(_('Prometheus listen_address is not a valid URI')) unless uri
|
|
|
|
result = ApplicationSettings::UpdateService.new(
|
|
application_settings,
|
|
group_owner,
|
|
add_to_outbound_local_requests_whitelist: [uri.normalized_host]
|
|
).execute
|
|
|
|
if result
|
|
success
|
|
else
|
|
log_error(_("Could not add prometheus URL to whitelist, errors: %{errors}") % { errors: application_settings.errors.full_messages })
|
|
error(_('Could not add prometheus URL to whitelist'))
|
|
end
|
|
end
|
|
|
|
def add_prometheus_manual_configuration
|
|
return success unless prometheus_enabled?
|
|
return success unless prometheus_listen_address.present?
|
|
|
|
service = 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: #{service.errors.full_messages}")
|
|
return error('Could not save prometheus manual configuration')
|
|
end
|
|
|
|
success
|
|
end
|
|
|
|
def application_settings
|
|
strong_memoize(:application_settings) do
|
|
Gitlab::CurrentSettings.expire_current_application_settings
|
|
Gitlab::CurrentSettings.current_application_settings
|
|
end
|
|
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.config.prometheus.enable
|
|
rescue Settingslogic::MissingSetting
|
|
false
|
|
end
|
|
|
|
def prometheus_listen_address
|
|
Gitlab.config.prometheus.listen_address
|
|
rescue Settingslogic::MissingSetting
|
|
end
|
|
|
|
def instance_admins
|
|
@instance_admins ||= User.admins.active
|
|
end
|
|
|
|
def group_owner
|
|
instance_admins.first
|
|
end
|
|
|
|
def group_maintainers
|
|
# Exclude the first so that the group_owner is not added again as a member.
|
|
instance_admins - [group_owner]
|
|
end
|
|
|
|
def create_group_params
|
|
{
|
|
name: GROUP_NAME,
|
|
path: "#{GROUP_PATH}-#{SecureRandom.hex(4)}",
|
|
visibility_level: VISIBILITY_LEVEL
|
|
}
|
|
end
|
|
|
|
def create_project_params
|
|
{
|
|
initialize_with_readme: true,
|
|
visibility_level: VISIBILITY_LEVEL,
|
|
name: PROJECT_NAME,
|
|
description: PROJECT_DESCRIPTION,
|
|
namespace_id: @group.id
|
|
}
|
|
end
|
|
|
|
def internal_prometheus_listen_address_uri
|
|
if prometheus_listen_address.starts_with?('http')
|
|
prometheus_listen_address
|
|
else
|
|
'http://' + prometheus_listen_address
|
|
end
|
|
end
|
|
|
|
def prometheus_service_attributes
|
|
{
|
|
api_url: internal_prometheus_listen_address_uri,
|
|
manual_configuration: true,
|
|
active: true
|
|
}
|
|
end
|
|
end
|
|
end
|
|
end
|