Commit 523c619f authored by Mayra Cabrera's avatar Mayra Cabrera

Merge branch '56883-migration' into 'master'

Add migration to execute SelfMonitoring::Project::CreateService

See merge request gitlab-org/gitlab-ce!31389
parents a93612aa 2515c0cd
# 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
---
title: Create a project for self-monitoring the GitLab instance
merge_request: 31389
author:
type: added
# frozen_string_literal: true
class AddGitlabInstanceAdministrationProject < ActiveRecord::Migration[5.2]
DOWNTIME = false
def up
Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService.new.execute!
end
def down
ApplicationSetting.current_without_cache
&.instance_administration_project
&.owner
&.destroy!
end
end
# frozen_string_literal: true
class SetSelfMonitoringProjectAlertingToken < ActiveRecord::Migration[5.2]
DOWNTIME = false
module Migratable
module Alerting
class ProjectAlertingSetting < ApplicationRecord
self.table_name = 'project_alerting_settings'
belongs_to :project
validates :token, presence: true
attr_encrypted :token,
mode: :per_attribute_iv,
key: Settings.attr_encrypted_db_key_base_truncated,
algorithm: 'aes-256-gcm'
before_validation :ensure_token
private
def ensure_token
self.token ||= generate_token
end
def generate_token
SecureRandom.hex
end
end
end
class Project < ApplicationRecord
has_one :alerting_setting, inverse_of: :project, class_name: 'Alerting::ProjectAlertingSetting'
end
class ApplicationSetting < ApplicationRecord
self.table_name = 'application_settings'
belongs_to :instance_administration_project, class_name: 'Project'
def self.current_without_cache
last
end
end
end
def setup_alertmanager_token(project)
return unless License.feature_available?(:prometheus_alerts)
project.create_alerting_setting!
end
def up
Gitlab.ee do
project = Migratable::ApplicationSetting.current_without_cache&.instance_administration_project
if project
setup_alertmanager_token(project)
end
end
end
def down
Gitlab.ee do
Migratable::ApplicationSetting.current_without_cache
&.instance_administration_project
&.alerting_setting
&.destroy!
end
end
end
# frozen_string_literal: true
module Gitlab
module DatabaseImporters
module SelfMonitoring
module Project
include Stepable
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_to_whitelist,
: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[:failed_step])
success
else
raise StandardError, result[:message]
end
end
private
def validate_application_settings
return success if application_settings
log_error(_('No application_settings found'))
error(_('No application_settings found'))
end
def validate_project_created
return success unless project_created?
log_error(_('Project already created'))
error(_('Project already created'))
end
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
@group = ::Groups::CreateService.new(group_owner, 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
@project = ::Projects::CreateService.new(group_owner, 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 = application_settings.update(instance_administration_project_id: @project.id)
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(members_to_add, 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
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
application_settings.add_to_outbound_local_requests_whitelist([uri.normalized_host])
result = application_settings.save
if result
# Expire the Gitlab::CurrentSettings cache after updating the whitelist.
# This happens automatically in an after_commit hook, but in migrations,
# the after_commit hook only runs at the end of the migration.
Gitlab::CurrentSettings.expire_current_application_settings
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: %{errors}') % { errors: service.errors.full_messages })
return error(_('Could not save prometheus manual configuration'))
end
success
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.config.prometheus.enable
rescue Settingslogic::MissingSetting
log_error(_('prometheus.enable is not present in gitlab.yml'))
false
end
def prometheus_listen_address
Gitlab.config.prometheus.listen_address
rescue Settingslogic::MissingSetting
log_error(_('prometheus.listen_address is not present in gitlab.yml'))
nil
end
def instance_admins
@instance_admins ||= User.admins.active
end
def group_owner
instance_admins.first
end
def members_to_add
# 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
{
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
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
end
end
...@@ -3353,6 +3353,12 @@ msgstr "" ...@@ -3353,6 +3353,12 @@ msgstr ""
msgid "Copy token to clipboard" msgid "Copy token to clipboard"
msgstr "" msgstr ""
msgid "Could not add admins as members"
msgstr ""
msgid "Could not add admins as members to self-monitoring project. Errors: %{errors}"
msgstr ""
msgid "Could not add prometheus URL to whitelist" msgid "Could not add prometheus URL to whitelist"
msgstr "" msgstr ""
...@@ -3371,6 +3377,9 @@ msgstr "" ...@@ -3371,6 +3377,9 @@ msgstr ""
msgid "Could not create Wiki Repository at this time. Please try again later." msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr "" msgstr ""
msgid "Could not create group"
msgstr ""
msgid "Could not create instance administration project. Errors: %{errors}" msgid "Could not create instance administration project. Errors: %{errors}"
msgstr "" msgstr ""
...@@ -3398,6 +3407,12 @@ msgstr "" ...@@ -3398,6 +3407,12 @@ msgstr ""
msgid "Could not save project ID" msgid "Could not save project ID"
msgstr "" msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
msgid "Could not save prometheus manual configuration for self-monitoring project. Errors: %{errors}"
msgstr ""
msgid "Coverage" msgid "Coverage"
msgstr "" msgstr ""
...@@ -7400,9 +7415,15 @@ msgstr "" ...@@ -7400,9 +7415,15 @@ msgstr ""
msgid "No Tag" msgid "No Tag"
msgstr "" msgstr ""
msgid "No active admin user found"
msgstr ""
msgid "No activities found" msgid "No activities found"
msgstr "" msgstr ""
msgid "No application_settings found"
msgstr ""
msgid "No available namespaces to fork the project." msgid "No available namespaces to fork the project."
msgstr "" msgstr ""
...@@ -8746,6 +8767,9 @@ msgstr "" ...@@ -8746,6 +8767,9 @@ msgstr ""
msgid "Project access must be granted explicitly to each user." msgid "Project access must be granted explicitly to each user."
msgstr "" msgstr ""
msgid "Project already created"
msgstr ""
msgid "Project and wiki repositories" msgid "Project and wiki repositories"
msgstr "" msgstr ""
...@@ -13961,6 +13985,12 @@ msgstr "" ...@@ -13961,6 +13985,12 @@ msgstr ""
msgid "project avatar" msgid "project avatar"
msgstr "" msgstr ""
msgid "prometheus.enable is not present in gitlab.yml"
msgstr ""
msgid "prometheus.listen_address is not present in gitlab.yml"
msgstr ""
msgid "quick actions" msgid "quick actions"
msgstr "" msgstr ""
......
...@@ -2,29 +2,48 @@ ...@@ -2,29 +2,48 @@
require 'spec_helper' require 'spec_helper'
describe SelfMonitoring::Project::CreateService do describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService do
describe '#execute' do describe '#execute' do
let(:result) { subject.execute } let(:result) { subject.execute! }
let(:prometheus_settings) do let(:prometheus_settings) do
OpenStruct.new( {
enable: true, enable: true,
listen_address: 'localhost:9090' listen_address: 'localhost:9090'
) }
end end
before do before do
allow(Gitlab.config).to receive(:prometheus).and_return(prometheus_settings) stub_config(prometheus: prometheus_settings)
end
context 'without application_settings' do
it 'does not fail' do
expect(subject).to receive(:log_error).and_call_original
expect(result).to eq(
status: :success
)
expect(Project.count).to eq(0)
expect(Group.count).to eq(0)
end
end end
context 'without admin users' do context 'without admin users' do
it 'returns error' do let(:application_setting) { Gitlab::CurrentSettings.current_application_settings }
before do
allow(ApplicationSetting).to receive(:current_without_cache) { application_setting }
end
it 'does not fail' do
expect(subject).to receive(:log_error).and_call_original expect(subject).to receive(:log_error).and_call_original
expect(result).to eq( expect(result).to eq(
status: :error, status: :success
message: 'No active admin user found',
failed_step: :validate_admins
) )
expect(Project.count).to eq(0)
expect(Group.count).to eq(0)
end end
end end
...@@ -36,6 +55,7 @@ describe SelfMonitoring::Project::CreateService do ...@@ -36,6 +55,7 @@ describe SelfMonitoring::Project::CreateService do
let!(:user) { create(:user, :admin) } let!(:user) { create(:user, :admin) }
before do before do
allow(ApplicationSetting).to receive(:current_without_cache) { application_setting }
application_setting.allow_local_requests_from_web_hooks_and_services = true application_setting.allow_local_requests_from_web_hooks_and_services = true
end end
...@@ -56,8 +76,8 @@ describe SelfMonitoring::Project::CreateService do ...@@ -56,8 +76,8 @@ describe SelfMonitoring::Project::CreateService do
it 'creates group' do it 'creates group' do
expect(result[:status]).to eq(:success) expect(result[:status]).to eq(:success)
expect(group).to be_persisted expect(group).to be_persisted
expect(group.name).to eq(described_class::GROUP_NAME) expect(group.name).to eq('GitLab Instance Administrators')
expect(group.path).to start_with(described_class::GROUP_PATH) expect(group.path).to start_with('gitlab-instance-administrators')
expect(group.path.split('-').last.length).to eq(8) expect(group.path.split('-').last.length).to eq(8)
expect(group.visibility_level).to eq(described_class::VISIBILITY_LEVEL) expect(group.visibility_level).to eq(described_class::VISIBILITY_LEVEL)
end end
...@@ -77,9 +97,16 @@ describe SelfMonitoring::Project::CreateService do ...@@ -77,9 +97,16 @@ describe SelfMonitoring::Project::CreateService do
end end
it 'creates project with correct name and description' do it 'creates project with correct name and description' do
path = 'administration/monitoring/gitlab_instance_administration_project/index'
docs_path = Rails.application.routes.url_helpers.help_page_path(path)
expect(result[:status]).to eq(:success) expect(result[:status]).to eq(:success)
expect(project.name).to eq(described_class::PROJECT_NAME) expect(project.name).to eq(described_class::PROJECT_NAME)
expect(project.description).to eq(described_class::PROJECT_DESCRIPTION) expect(project.description).to eq(
'This project is automatically generated and will be used to help monitor this GitLab instance. ' \
"[More information](#{docs_path})"
)
expect(File).to exist("doc/#{path}.md")
end end
it 'adds all admins as maintainers' do it 'adds all admins as maintainers' do
...@@ -105,19 +132,30 @@ describe SelfMonitoring::Project::CreateService do ...@@ -105,19 +132,30 @@ describe SelfMonitoring::Project::CreateService do
it 'returns error when saving project ID fails' do it 'returns error when saving project ID fails' do
allow(application_setting).to receive(:update) { false } allow(application_setting).to receive(:update) { false }
expect(result[:status]).to eq(:error) expect { result }.to raise_error(StandardError, 'Could not save project ID')
expect(result[:failed_step]).to eq(:save_project_id)
expect(result[:message]).to eq('Could not save project ID')
end end
it 'does not fail when a project already exists' do context 'when project already exists' do
expect(result[:status]).to eq(:success) let(:existing_group) { create(:group) }
let(:existing_project) { create(:project, namespace: existing_group) }
second_result = subject.execute before do
admin1 = create(:user, :admin)
admin2 = create(:user, :admin)
existing_group.add_owner(user)
existing_group.add_users([admin1, admin2], Gitlab::Access::MAINTAINER)
expect(second_result[:status]).to eq(:success) application_setting.instance_administration_project_id = existing_project.id
expect(second_result[:project]).to eq(project) end
expect(second_result[:group]).to eq(group)
it 'does not fail' do
expect(subject).to receive(:log_error).and_call_original
expect(result[:status]).to eq(:success)
expect(Project.count).to eq(1)
expect(Group.count).to eq(1)
end
end end
context 'when local requests from hooks and services are not allowed' do context 'when local requests from hooks and services are not allowed' do
...@@ -138,8 +176,11 @@ describe SelfMonitoring::Project::CreateService do ...@@ -138,8 +176,11 @@ describe SelfMonitoring::Project::CreateService do
end end
context 'with non default prometheus address' do context 'with non default prometheus address' do
before do let(:prometheus_settings) do
prometheus_settings.listen_address = 'https://localhost:9090' {
enable: true,
listen_address: 'https://localhost:9090'
}
end end
it_behaves_like 'has prometheus service', 'https://localhost:9090' it_behaves_like 'has prometheus service', 'https://localhost:9090'
...@@ -157,8 +198,11 @@ describe SelfMonitoring::Project::CreateService do ...@@ -157,8 +198,11 @@ describe SelfMonitoring::Project::CreateService do
end end
context 'when prometheus setting is disabled in gitlab.yml' do context 'when prometheus setting is disabled in gitlab.yml' do
before do let(:prometheus_settings) do
prometheus_settings.enable = false {
enable: false,
listen_address: 'http://localhost:9090'
}
end end
it 'does not configure prometheus' do it 'does not configure prometheus' do
...@@ -168,9 +212,7 @@ describe SelfMonitoring::Project::CreateService do ...@@ -168,9 +212,7 @@ describe SelfMonitoring::Project::CreateService do
end end
context 'when prometheus listen address is blank in gitlab.yml' do context 'when prometheus listen address is blank in gitlab.yml' do
before do let(:prometheus_settings) { { enable: true, listen_address: '' } }
prometheus_settings.listen_address = ''
end
it 'does not configure prometheus' do it 'does not configure prometheus' do
expect(result).to include(status: :success) expect(result).to include(status: :success)
...@@ -192,11 +234,7 @@ describe SelfMonitoring::Project::CreateService do ...@@ -192,11 +234,7 @@ describe SelfMonitoring::Project::CreateService do
it 'returns error' do it 'returns error' do
expect(subject).to receive(:log_error).and_call_original expect(subject).to receive(:log_error).and_call_original
expect(result).to eq({ expect { result }.to raise_error(StandardError, 'Could not create project')
status: :error,
message: 'Could not create project',
failed_step: :create_project
})
end end
end end
...@@ -207,26 +245,21 @@ describe SelfMonitoring::Project::CreateService do ...@@ -207,26 +245,21 @@ describe SelfMonitoring::Project::CreateService do
it 'returns error' do it 'returns error' do
expect(subject).to receive(:log_error).and_call_original expect(subject).to receive(:log_error).and_call_original
expect(result).to eq({ expect { result }.to raise_error(StandardError, 'Could not add admins as members')
status: :error,
message: 'Could not add admins as members',
failed_step: :add_group_members
})
end end
end end
context 'when prometheus manual configuration cannot be saved' do context 'when prometheus manual configuration cannot be saved' do
before do let(:prometheus_settings) do
prometheus_settings.listen_address = 'httpinvalid://localhost:9090' {
enable: true,
listen_address: 'httpinvalid://localhost:9090'
}
end end
it 'returns error' do it 'returns error' do
expect(subject).to receive(:log_error).and_call_original expect(subject).to receive(:log_error).and_call_original
expect(result).to eq( expect { result }.to raise_error(StandardError, 'Could not save prometheus manual configuration')
status: :error,
message: 'Could not save prometheus manual configuration',
failed_step: :add_prometheus_manual_configuration
)
end end
end end
end end
......
# frozen_string_literal: true
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20190801072937_add_gitlab_instance_administration_project.rb')
describe AddGitlabInstanceAdministrationProject, :migration do
let(:application_settings) { table(:application_settings) }
let(:users) { table(:users) }
let(:projects) { table(:projects) }
let(:namespaces) { table(:namespaces) }
let(:members) { table(:members) }
let(:service_class) do
Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService
end
let(:prometheus_settings) do
{
enable: true,
listen_address: 'localhost:9090'
}
end
before do
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
stub_config(prometheus: prometheus_settings)
end
describe 'down' do
let!(:application_setting) { application_settings.create! }
let!(:user) { users.create!(admin: true, email: 'admin1@example.com', projects_limit: 10, state: :active) }
it 'deletes group and project' do
migrate!
expect(Project.count).to eq(1)
expect(Group.count).to eq(1)
schema_migrate_down!
expect(Project.count).to eq(0)
expect(Group.count).to eq(0)
end
end
describe 'up' do
context 'without application_settings' do
it 'does not fail' do
migrate!
expect(Project.count).to eq(0)
end
end
context 'without admin users' do
let!(:application_setting) { application_settings.create! }
it 'does not fail' do
migrate!
expect(Project.count).to eq(0)
end
end
context 'with admin users' do
let(:project) { Project.last }
let(:group) { Group.last }
let!(:application_setting) { application_settings.create! }
let!(:user) { users.create!(admin: true, email: 'admin1@example.com', projects_limit: 10, state: :active) }
before do
stub_application_setting(allow_local_requests_from_web_hooks_and_services: true)
end
shared_examples 'has prometheus service' do |listen_address|
it do
migrate!
prometheus = project.prometheus_service
expect(prometheus).to be_persisted
expect(prometheus).not_to eq(nil)
expect(prometheus.api_url).to eq(listen_address)
expect(prometheus.active).to eq(true)
expect(prometheus.manual_configuration).to eq(true)
end
end
it_behaves_like 'has prometheus service', 'http://localhost:9090'
it 'creates GitLab Instance Administrator group' do
migrate!
expect(group).to be_persisted
expect(group.name).to eq('GitLab Instance Administrators')
expect(group.path).to start_with('gitlab-instance-administrators')
expect(group.path.split('-').last.length).to eq(8)
expect(group.visibility_level).to eq(service_class::VISIBILITY_LEVEL)
end
it 'creates project with internal visibility' do
migrate!
expect(project.visibility_level).to eq(Gitlab::VisibilityLevel::INTERNAL)
expect(project).to be_persisted
end
it 'creates project with correct name and description' do
migrate!
path = 'administration/monitoring/gitlab_instance_administration_project/index'
docs_path = Rails.application.routes.url_helpers.help_page_path(path)
expect(project.name).to eq(service_class::PROJECT_NAME)
expect(project.description).to eq(
'This project is automatically generated and will be used to help monitor this GitLab instance. ' \
"[More information](#{docs_path})"
)
expect(File).to exist("doc/#{path}.md")
end
it 'adds all admins as maintainers' do
admin1 = users.create!(admin: true, email: 'admin2@example.com', projects_limit: 10, state: :active)
admin2 = users.create!(admin: true, email: 'admin3@example.com', projects_limit: 10, state: :active)
users.create!(email: 'nonadmin1@example.com', projects_limit: 10, state: :active)
migrate!
expect(project.owner).to eq(group)
expect(group.members.collect(&:user).collect(&:id)).to contain_exactly(user.id, admin1.id, admin2.id)
expect(group.members.collect(&:access_level)).to contain_exactly(
Gitlab::Access::OWNER,
Gitlab::Access::MAINTAINER,
Gitlab::Access::MAINTAINER
)
end
it 'saves the project id' do
migrate!
application_setting.reload
expect(application_setting.instance_administration_project_id).to eq(project.id)
end
it 'does not fail when a project already exists' do
group = namespaces.create!(
path: 'gitlab-instance-administrators',
name: 'GitLab Instance Administrators',
type: 'Group'
)
project = projects.create!(
namespace_id: group.id,
name: 'GitLab Instance Administration'
)
admin1 = users.create!(admin: true, email: 'admin4@example.com', projects_limit: 10, state: :active)
admin2 = users.create!(admin: true, email: 'admin5@example.com', projects_limit: 10, state: :active)
members.create!(
user_id: admin1.id,
source_id: group.id,
source_type: 'Namespace',
type: 'GroupMember',
access_level: GroupMember::MAINTAINER,
notification_level: NotificationSetting.levels[:global]
)
members.create!(
user_id: admin2.id,
source_id: group.id,
source_type: 'Namespace',
type: 'GroupMember',
access_level: GroupMember::MAINTAINER,
notification_level: NotificationSetting.levels[:global]
)
stub_application_setting(instance_administration_project: project)
migrate!
expect(Project.last.id).to eq(project.id)
expect(Group.last.id).to eq(group.id)
end
context 'when local requests from hooks and services are not allowed' do
before do
stub_application_setting(allow_local_requests_from_web_hooks_and_services: false)
end
it_behaves_like 'has prometheus service', 'http://localhost:9090'
it 'does not overwrite the existing whitelist' do
application_setting.update!(outbound_local_requests_whitelist: ['example.com'])
migrate!
application_setting.reload
expect(application_setting.outbound_local_requests_whitelist).to contain_exactly(
'example.com', 'localhost'
)
end
end
context 'with non default prometheus address' do
let(:prometheus_settings) do
{
enable: true,
listen_address: 'https://localhost:9090'
}
end
it_behaves_like 'has prometheus service', 'https://localhost:9090'
end
context 'when prometheus setting is not present in gitlab.yml' do
before do
allow(Gitlab.config).to receive(:prometheus).and_raise(Settingslogic::MissingSetting)
end
it 'does not fail' do
migrate!
expect(project.prometheus_service).to be_nil
end
end
context 'when prometheus setting is disabled in gitlab.yml' do
let(:prometheus_settings) do
{
enable: false,
listen_address: 'localhost:9090'
}
end
it 'does not configure prometheus' do
migrate!
expect(project.prometheus_service).to be_nil
end
end
context 'when prometheus listen address is blank in gitlab.yml' do
let(:prometheus_settings) { { enable: true, listen_address: '' } }
it 'does not configure prometheus' do
migrate!
expect(project.prometheus_service).to be_nil
end
end
end
end
end
...@@ -30,6 +30,10 @@ module StubConfiguration ...@@ -30,6 +30,10 @@ module StubConfiguration
allow(Gitlab.config.gitlab).to receive_messages(to_settings(messages)) allow(Gitlab.config.gitlab).to receive_messages(to_settings(messages))
end end
def stub_config(messages)
allow(Gitlab.config).to receive_messages(to_settings(messages))
end
def stub_default_url_options(host: "localhost", protocol: "http") def stub_default_url_options(host: "localhost", protocol: "http")
url_options = { host: host, protocol: protocol } url_options = { host: host, protocol: protocol }
allow(Rails.application.routes).to receive(:default_url_options).and_return(url_options) allow(Rails.application.routes).to receive(:default_url_options).and_return(url_options)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment