Commit af75f51c authored by Arturo Herrero's avatar Arturo Herrero

Find or initialize instance-level services

This is similar to the service templates feature that we are going to
remove: https://gitlab.com/groups/gitlab-org/-/epics/2430 but we don't
need to create the services in the database at this point.

https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25752 implemented
the frontend changes under a feature flag, this implements the backend
changes.

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