gitlab-ce/spec/services/groups/update_shared_runners_servi...

263 lines
11 KiB
Ruby

# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Groups::UpdateSharedRunnersService, '#execute', :sidekiq_inline, feature_category: :groups_and_projects do
include ReloadHelpers
let(:params) { {} }
let(:service) { described_class.new(group, user, params) }
subject(:execute) { service.execute }
context 'when current_user is not the group owner' do
let_it_be(:user) { create(:user) }
let(:group) { create(:group, maintainers: user) }
let(:params) { { shared_runners_setting: 'enabled' } }
it 'returns error' do
is_expected.to match(a_hash_including(
status: :error,
message: 'Operation not allowed',
http_status: 403))
end
end
context 'when current_user is the group owner' do
let_it_be(:user) { create(:user) }
before do
group.add_owner(user)
end
context 'enable shared Runners' do
let(:params) { { shared_runners_setting: 'enabled' } }
context 'when ancestor disable shared runners' do
let(:parent) { create(:group, :shared_runners_disabled) }
let(:group) { create(:group, :shared_runners_disabled, parent: parent) }
let!(:project) { create(:project, shared_runners_enabled: false, group: group) }
it 'returns an error and does not enable shared runners' do
expect do
expect(execute).to match(a_hash_including(
status: :error,
message:
'Validation failed: Shared runners enabled cannot be enabled because parent group ' \
'has shared Runners disabled'))
reload_models(parent, group, project)
end.to not_change { parent.shared_runners_enabled }
.and not_change { group.shared_runners_enabled }
.and not_change { project.shared_runners_enabled }
end
end
context 'when updating root group' do
let(:group) { create(:group, :shared_runners_disabled) }
let(:sub_group) { create(:group, :shared_runners_disabled, parent: group) }
let!(:project) { create(:project, shared_runners_enabled: false, group: sub_group) }
it 'enables shared Runners for itself and descendants' do
expect do
expect(execute[:status]).to eq(:success)
reload_models(group, sub_group, project)
end.to change { group.shared_runners_enabled }.from(false).to(true)
.and change { sub_group.shared_runners_enabled }.from(false).to(true)
.and change { project.shared_runners_enabled }.from(false).to(true)
end
context 'when already allowing descendants to override' do
let(:group) { create(:group, :shared_runners_disabled_and_overridable) }
it 'enables shared Runners for itself and descendants' do
expect do
expect(execute[:status]).to eq(:success)
reload_models(group, sub_group, project)
end.to change { group.shared_runners_enabled }.from(false).to(true)
.and change { group.allow_descendants_override_disabled_shared_runners }.from(true).to(false)
.and change { sub_group.shared_runners_enabled }.from(false).to(true)
.and change { project.shared_runners_enabled }.from(false).to(true)
end
end
end
context 'when group has pending builds', :aggregate_failures do
let_it_be(:group) { create(:group, :shared_runners_disabled) }
let_it_be(:sub_group) { create(:group, :shared_runners_disabled, parent: group) }
let_it_be(:project) { create(:project, namespace: group, shared_runners_enabled: false) }
let_it_be(:project2) { create(:project, namespace: sub_group, shared_runners_enabled: false) }
let_it_be(:pending_build_1) { create(:ci_pending_build, project: project, instance_runners_enabled: false) }
let_it_be(:pending_build_2) { create(:ci_pending_build, project: project, instance_runners_enabled: false) }
let_it_be(:pending_build_3) { create(:ci_pending_build, project: project2, instance_runners_enabled: false) }
it 'updates pending builds for the group and descendants' do
expect(::Ci::PendingBuilds::UpdateGroupWorker).to receive(:perform_async)
.with(group.id, { 'instance_runners_enabled' => true })
.and_call_original
execute
expect(pending_build_1.reload.instance_runners_enabled).to be_truthy
expect(pending_build_2.reload.instance_runners_enabled).to be_truthy
expect(pending_build_3.reload.instance_runners_enabled).to be_truthy
end
context 'when shared runners is not toggled' do
let(:params) { { shared_runners_setting: 'invalid_enabled' } }
it 'does not update pending builds for the group' do
expect(::Ci::PendingBuilds::UpdateGroupWorker).not_to receive(:new)
execute
expect(pending_build_1.reload.instance_runners_enabled).to be_falsey
expect(pending_build_2.reload.instance_runners_enabled).to be_falsey
end
end
end
end
context 'disable shared Runners' do
let!(:group) { create(:group) }
let!(:sub_group) { create(:group, :shared_runners_disabled_and_overridable, parent: group) }
let!(:sub_group2) { create(:group, parent: group) }
let!(:project) { create(:project, group: group, shared_runners_enabled: true) }
let!(:project2) { create(:project, group: sub_group2, shared_runners_enabled: true) }
let(:params) { { shared_runners_setting: Namespace::SR_DISABLED_AND_UNOVERRIDABLE } }
it 'disables shared Runners for all descendant groups and projects' do
expect do
expect(execute[:status]).to eq(:success)
reload_models(group, sub_group, sub_group2, project, project2)
end.to change { group.shared_runners_enabled }.from(true).to(false)
.and not_change { group.allow_descendants_override_disabled_shared_runners }
.and not_change { sub_group.shared_runners_enabled }
.and change { sub_group.allow_descendants_override_disabled_shared_runners }.from(true).to(false)
.and change { sub_group2.shared_runners_enabled }.from(true).to(false)
.and not_change { sub_group2.allow_descendants_override_disabled_shared_runners }
.and change { project.shared_runners_enabled }.from(true).to(false)
.and change { project2.shared_runners_enabled }.from(true).to(false)
end
context 'with override on self' do
let(:group) { create(:group, :shared_runners_disabled_and_overridable) }
it 'disables it' do
expect do
expect(execute[:status]).to eq(:success)
group.reload
end
.to not_change { group.shared_runners_enabled }
.and change { group.allow_descendants_override_disabled_shared_runners }.from(true).to(false)
end
end
context 'when group has pending builds', :aggregate_failures do
let!(:pending_build_1) { create(:ci_pending_build, project: project, instance_runners_enabled: true) }
let!(:pending_build_2) { create(:ci_pending_build, project: project, instance_runners_enabled: true) }
it 'updates pending builds for the group and descendants' do
expect(::Ci::PendingBuilds::UpdateGroupWorker).to receive(:perform_async)
.with(group.id, { 'instance_runners_enabled' => false })
.and_call_original
execute
expect(pending_build_1.reload.instance_runners_enabled).to be_falsey
expect(pending_build_2.reload.instance_runners_enabled).to be_falsey
end
end
end
shared_examples 'allow descendants to override' do
context 'top level group' do
let!(:group) { create(:group, :shared_runners_disabled) }
let!(:sub_group) { create(:group, :shared_runners_disabled, parent: group) }
let!(:project) { create(:project, shared_runners_enabled: false, group: sub_group) }
it 'enables allow descendants to override only for itself' do
expect do
expect(execute[:status]).to eq(:success)
reload_models(group, sub_group, project)
end.to change { group.allow_descendants_override_disabled_shared_runners }.from(false).to(true)
.and not_change { group.shared_runners_enabled }
.and not_change { sub_group.allow_descendants_override_disabled_shared_runners }
.and not_change { sub_group.shared_runners_enabled }
.and not_change { project.shared_runners_enabled }
end
end
context 'when ancestor disables shared Runners but allows to override' do
let!(:parent) { create(:group, :shared_runners_disabled_and_overridable) }
let!(:group) { create(:group, :shared_runners_disabled, parent: parent) }
let!(:project) { create(:project, shared_runners_enabled: false, group: group) }
it 'enables allow descendants to override' do
expect do
expect(execute[:status]).to eq(:success)
reload_models(parent, group, project)
end
.to not_change { parent.allow_descendants_override_disabled_shared_runners }
.and not_change { parent.shared_runners_enabled }
.and change { group.allow_descendants_override_disabled_shared_runners }.from(false).to(true)
.and not_change { group.shared_runners_enabled }
.and not_change { project.shared_runners_enabled }
end
end
context 'when ancestor disables shared runners' do
let(:parent) { create(:group, :shared_runners_disabled) }
let(:group) { create(:group, :shared_runners_disabled, parent: parent) }
let!(:project) { create(:project, shared_runners_enabled: false, group: group) }
it 'returns an error and does not enable shared runners' do
expect do
expect(execute).to match(a_hash_including(
status: :error,
message:
'Validation failed: Allow descendants override disabled shared runners cannot be enabled ' \
'because parent group does not allow it'))
reload_models(parent, group, project)
end.to not_change { parent.shared_runners_enabled }
.and not_change { group.shared_runners_enabled }
.and not_change { project.shared_runners_enabled }
end
end
context 'top level group that has shared Runners enabled' do
let!(:group) { create(:group, shared_runners_enabled: true) }
let!(:sub_group) { create(:group, shared_runners_enabled: true, parent: group) }
let!(:project) { create(:project, shared_runners_enabled: true, group: sub_group) }
it 'enables allow descendants to override & disables shared runners everywhere' do
expect do
expect(execute[:status]).to eq(:success)
reload_models(group, sub_group, project)
end
.to change { group.shared_runners_enabled }.from(true).to(false)
.and change { group.allow_descendants_override_disabled_shared_runners }.from(false).to(true)
.and change { sub_group.shared_runners_enabled }.from(true).to(false)
.and change { project.shared_runners_enabled }.from(true).to(false)
end
end
end
context "when using SR_DISABLED_AND_OVERRIDABLE" do
let(:params) { { shared_runners_setting: Namespace::SR_DISABLED_AND_OVERRIDABLE } }
include_examples 'allow descendants to override'
end
end
end