Commit 537bbde3 authored by Robert Speicher's avatar Robert Speicher

Merge branch '196525-instance-level-services' into 'master'

Find or initialize instance-level services

See merge request gitlab-org/gitlab!28033
parents 4629e944 af75f51c
......@@ -8,7 +8,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
# ApplicationSetting model uses Gitlab::ThreadMemoryCache for caching and the
# cache might be stale immediately after an update.
# https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30233
before_action :set_application_setting
before_action :set_application_setting, except: :integrations
before_action :whitelist_query_limiting, only: [:usage_data]
......@@ -29,13 +29,12 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
def integrations
if Feature.enabled?(:instance_level_integrations)
# TODO: Update this with actual integrations
# To be fixed with https://gitlab.com/gitlab-org/gitlab/-/issues/199388
@integrations = []
end
@integrations = Service.find_or_initialize_instances.sort_by(&:title)
else
set_application_setting
perform_update if submitted?
end
end
def update
perform_update
......
......@@ -6,7 +6,7 @@ class Admin::ServicesController < Admin::ApplicationController
before_action :service, only: [:edit, :update]
def index
@services = Service.find_or_create_templates
@services = Service.find_or_create_templates.sort_by(&:title)
end
def edit
......
......@@ -47,6 +47,7 @@ class Service < ApplicationRecord
scope :without_defaults, -> { where(default: false) }
scope :by_type, -> (type) { where(type: type) }
scope :templates, -> { where(template: true, type: available_services_types) }
scope :instances, -> { where(instance: true, type: available_services_types) }
scope :push_hooks, -> { where(push_events: true, active: true) }
scope :tag_push_hooks, -> { where(tag_push_events: true, active: true) }
......@@ -260,17 +261,16 @@ class Service < ApplicationRecord
self.category == :issue_tracker
end
# Find all service templates; if some of them do not exist, create them
# within a transaction to perform the lowest possible SQL queries.
def self.find_or_create_templates
create_nonexistent_templates
templates
end
private_class_method def self.create_nonexistent_templates
nonexistent_services = available_services_types - templates.map(&:type)
nonexistent_services = list_nonexistent_services_for(templates)
return if nonexistent_services.empty?
# Create within a transaction to perform the lowest possible SQL queries.
transaction do
nonexistent_services.each do |service_type|
service_type.constantize.create(template: true)
......@@ -278,6 +278,20 @@ class Service < ApplicationRecord
end
end
def self.find_or_initialize_instances
instances + build_nonexistent_instances
end
private_class_method def self.build_nonexistent_instances
list_nonexistent_services_for(instances).map do |service_type|
service_type.constantize.new
end
end
private_class_method def self.list_nonexistent_services_for(scope)
available_services_types - scope.map(&:type)
end
def self.available_services_names
service_names = %w[
alerts
......
......@@ -10,7 +10,7 @@
%th Service
%th Description
%th Last edit
- @services.sort_by(&:title).each do |service|
- @services.each do |service|
%tr
%td
= boolean_to_icon service.activated?
......
......@@ -12,7 +12,7 @@
%th{ role: 'columnheader', scope: 'col', 'aria-colindex': 4 }= _('Last updated')
%tbody{ role: 'rowgroup' }
- @integrations&.each do |integration|
- @integrations.each do |integration|
%tr{ role: 'row' }
%td{ role: 'cell', 'aria-colindex': 1 }
= boolean_to_icon integration.activated?
......
......@@ -6,6 +6,7 @@ describe 'Admin updates EE-only settings' do
include StubENV
before do
stub_feature_flags(instance_level_integrations: false)
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
sign_in(create(:admin))
allow(License).to receive(:feature_available?).and_return(true)
......@@ -57,7 +58,7 @@ describe 'Admin updates EE-only settings' do
context 'Elasticsearch settings' do
before do
visit general_admin_application_settings_path
visit integrations_admin_application_settings_path
page.within('.as-elasticsearch') do
click_button 'Expand'
end
......@@ -137,7 +138,7 @@ describe 'Admin updates EE-only settings' do
namespace = create(:elasticsearch_indexed_namespace).namespace
project = create(:elasticsearch_indexed_project).project
visit general_admin_application_settings_path
visit integrations_admin_application_settings_path
expect(ElasticsearchIndexedNamespace.count).to be > 0
expect(ElasticsearchIndexedProject.count).to be > 0
......@@ -167,7 +168,7 @@ describe 'Admin updates EE-only settings' do
it 'Enable Slack application' do
allow(Gitlab).to receive(:com?).and_return(true)
visit general_admin_application_settings_path
visit integrations_admin_application_settings_path
page.within('.as-slack') do
check 'Enable Slack application'
......
......@@ -127,6 +127,10 @@ describe Admin::ApplicationSettingsController do
end
describe 'verify panel actions' do
before do
stub_feature_flags(instance_level_integrations: false)
end
Admin::ApplicationSettingsController::VALID_SETTING_PANELS.each do |valid_action|
it_behaves_like 'renders correct panels' do
let(:action) { valid_action }
......
......@@ -194,6 +194,13 @@ describe 'Admin updates settings', :clean_gitlab_redis_shared_state, :do_not_moc
expect(page).to have_content "Application settings saved successfully"
expect(current_settings.terminal_max_session_time).to eq(15)
end
end
context 'Integrations page' do
before do
stub_feature_flags(instance_level_integrations: false)
visit integrations_admin_application_settings_path
end
it 'Enable hiding third party offers' do
page.within('.as-third-party-offers') do
......
......@@ -205,10 +205,11 @@ describe 'Gcp Cluster', :js, :do_not_mock_admin_mode do
let(:admin) { create(:admin) }
before do
stub_feature_flags(instance_level_integrations: false)
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
sign_in(admin)
gitlab_enable_admin_mode_sign_in(admin)
visit general_admin_application_settings_path
visit integrations_admin_application_settings_path
end
it 'user does not see the offer' do
......
......@@ -149,6 +149,47 @@ describe Service do
end
end
describe '.find_or_initialize_instances' do
shared_examples 'service instances' do
it 'returns the available service instances' do
expect(Service.find_or_initialize_instances.pluck(:type)).to match_array(Service.available_services_types)
end
it 'does not create service instances' do
expect { Service.find_or_initialize_instances }.not_to change { Service.count }
end
end
it_behaves_like 'service instances'
context 'with all existing instances' do
before do
Service.insert_all(
Service.available_services_types.map { |type| { instance: true, type: type } }
)
end
it_behaves_like 'service instances'
context 'with a previous existing service (Previous) and a new service (Asana)' do
before do
Service.insert(type: 'PreviousService', instance: true)
Service.delete_by(type: 'AsanaService', instance: true)
end
it_behaves_like 'service instances'
end
end
context 'with a few existing instances' do
before do
create(:jira_service, :instance)
end
it_behaves_like 'service instances'
end
end
describe 'template' do
let(:project) { create(:project) }
......@@ -173,7 +214,7 @@ describe Service do
end
it 'does not create service templates' do
expect { Service.find_or_create_templates }.to change { Service.count }.by(0)
expect { Service.find_or_create_templates }.not_to change { Service.count }
end
it_behaves_like 'retrieves service templates'
......
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