Commit e419699c authored by Bob Van Landuyt's avatar Bob Van Landuyt

Merge branch 'check-for-plans-in-update-all-mirrors-worker' into 'master'

Check for plans in update all mirrors worker

See merge request gitlab-org/gitlab!27796
parents 50f7d343 df780560
...@@ -102,6 +102,22 @@ class UpdateAllMirrorsWorker # rubocop:disable Scalability/IdempotentWorker ...@@ -102,6 +102,22 @@ class UpdateAllMirrorsWorker # rubocop:disable Scalability/IdempotentWorker
relation = relation.where('import_state.next_execution_timestamp > ?', offset_at) if offset_at relation = relation.where('import_state.next_execution_timestamp > ?', offset_at) if offset_at
if check_mirror_plans_in_query?
root_namespaces_sql = Gitlab::ObjectHierarchy
.new(Namespace.where('id = projects.namespace_id'))
.roots
.select(:id)
.to_sql
root_namespaces_join = "INNER JOIN namespaces AS root_namespaces ON root_namespaces.id = (#{root_namespaces_sql})"
relation = relation
.joins(root_namespaces_join)
.joins('LEFT JOIN gitlab_subscriptions ON gitlab_subscriptions.namespace_id = root_namespaces.id')
.joins('LEFT JOIN plans ON plans.id = gitlab_subscriptions.hosted_plan_id')
.where(['plans.name IN (?) OR projects.visibility_level = ?', ::Plan::ALL_HOSTED_PLANS, ::Gitlab::VisibilityLevel::PUBLIC])
end
relation relation
end end
# rubocop: enable CodeReuse/ActiveRecord # rubocop: enable CodeReuse/ActiveRecord
...@@ -113,4 +129,9 @@ class UpdateAllMirrorsWorker # rubocop:disable Scalability/IdempotentWorker ...@@ -113,4 +129,9 @@ class UpdateAllMirrorsWorker # rubocop:disable Scalability/IdempotentWorker
context_proc: -> (project) { { project: project } } context_proc: -> (project) { { project: project } }
) )
end end
def check_mirror_plans_in_query?
::Gitlab::CurrentSettings.should_check_namespace_plan? &&
!::Feature.enabled?(:free_period_for_pull_mirroring, default_enabled: true)
end
end end
...@@ -126,7 +126,7 @@ describe UpdateAllMirrorsWorker do ...@@ -126,7 +126,7 @@ describe UpdateAllMirrorsWorker do
projects.each { |project| expect_import_status(project, 'none') } projects.each { |project| expect_import_status(project, 'none') }
end end
context 'unlicensed' do context 'when the instance is unlicensed' do
it 'does not schedule when project does not have repository mirrors available' do it 'does not schedule when project does not have repository mirrors available' do
project = create(:project, :mirror) project = create(:project, :mirror)
...@@ -138,40 +138,93 @@ describe UpdateAllMirrorsWorker do ...@@ -138,40 +138,93 @@ describe UpdateAllMirrorsWorker do
end end
end end
context 'licensed' do context 'when the instance is licensed' do
def scheduled_mirror(at:, licensed:) def scheduled_mirror(at:)
namespace = create(:group, :public) project = create(:project, :mirror)
project.import_state.update!(next_execution_timestamp: at)
project
end
before do
stub_feature_flags(free_period_for_pull_mirroring: false)
end
let_it_be(:project1) { scheduled_mirror(at: 8.weeks.ago) }
let_it_be(:project2) { scheduled_mirror(at: 7.weeks.ago) }
context 'when capacity is in excess' do
it 'schedules all available mirrors' do
schedule_mirrors!(capacity: 3)
expect_import_scheduled(project1, project2)
end
end
end
context 'when the instance checks namespace plans' do
def scheduled_mirror(at:, licensed:, public: false, subgroup: nil)
group_args = [:group, :public, subgroup && :nested].compact
namespace = create(*group_args)
project = create(:project, :public, :mirror, namespace: namespace) project = create(:project, :public, :mirror, namespace: namespace)
create(:gitlab_subscription, (licensed ? :bronze : :free), namespace: namespace) create(:gitlab_subscription, (licensed ? :bronze : :free), namespace: namespace.root_ancestor)
project.import_state.update!(next_execution_timestamp: at) project.import_state.update!(next_execution_timestamp: at)
project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE) project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE) unless public
project project
end end
before do before do
stub_licensed_features(repository_mirrors: true)
stub_application_setting(check_namespace_plan: true) stub_application_setting(check_namespace_plan: true)
allow(Gitlab).to receive_messages(com?: true)
stub_const('License::ANY_PLAN_FEATURES', [])
end end
let!(:unlicensed_project1) { scheduled_mirror(at: 8.weeks.ago, licensed: false) } let_it_be(:unlicensed_project1) { scheduled_mirror(at: 8.weeks.ago, licensed: false) }
let!(:unlicensed_project2) { scheduled_mirror(at: 7.weeks.ago, licensed: false) } let_it_be(:unlicensed_project2) { scheduled_mirror(at: 7.weeks.ago, licensed: false) }
let!(:licensed_project1) { scheduled_mirror(at: 6.weeks.ago, licensed: true) } let_it_be(:licensed_project1) { scheduled_mirror(at: 6.weeks.ago, licensed: true, subgroup: true) }
let!(:unlicensed_project3) { scheduled_mirror(at: 5.weeks.ago, licensed: false) } let_it_be(:unlicensed_project3) { scheduled_mirror(at: 5.weeks.ago, licensed: false) }
let!(:licensed_project2) { scheduled_mirror(at: 4.weeks.ago, licensed: true) } let_it_be(:licensed_project2) { scheduled_mirror(at: 4.weeks.ago, licensed: true) }
let!(:unlicensed_project4) { scheduled_mirror(at: 3.weeks.ago, licensed: false) } let_it_be(:unlicensed_project4) { scheduled_mirror(at: 3.weeks.ago, licensed: false) }
let!(:licensed_project3) { scheduled_mirror(at: 1.week.ago, licensed: true) } let_it_be(:public_project) { scheduled_mirror(at: 1.week.ago, licensed: false, public: true) }
let(:unlicensed_projects) { [unlicensed_project1, unlicensed_project2, unlicensed_project3, unlicensed_project4] } let(:unlicensed_projects) { [unlicensed_project1, unlicensed_project2, unlicensed_project3, unlicensed_project4] }
context 'after the free period for pull mirroring' do
before do
stub_feature_flags(free_period_for_pull_mirroring: false)
end
context 'when capacity is in excess' do
it 'schedules all available mirrors' do
schedule_mirrors!(capacity: 4)
expect_import_scheduled(licensed_project1, licensed_project2, public_project)
expect_import_not_scheduled(*unlicensed_projects)
end
end
context 'when capacity is exactly sufficient' do
it 'does not include unlicensed non-public projects in batches' do
# We expect that all three eligible projects will be
# included in the first batch because the query will only
# return eligible projects.
expect(subject).to receive(:pull_mirrors_batch).with(hash_including(batch_size: 6)).and_call_original.once
schedule_mirrors!(capacity: 3)
end
end
end
context 'when checking licenses on each record individually' do
before do
stub_feature_flags(free_period_for_pull_mirroring: true)
stub_const('License::ANY_PLAN_FEATURES', [])
end
context 'when capacity is in excess' do context 'when capacity is in excess' do
it "schedules all available mirrors" do it "schedules all available mirrors" do
schedule_mirrors!(capacity: 4) schedule_mirrors!(capacity: 4)
expect_import_scheduled(licensed_project1, licensed_project2, licensed_project3) expect_import_scheduled(licensed_project1, licensed_project2, public_project)
expect_import_not_scheduled(*unlicensed_projects) expect_import_not_scheduled(*unlicensed_projects)
end end
...@@ -188,7 +241,7 @@ describe UpdateAllMirrorsWorker do ...@@ -188,7 +241,7 @@ describe UpdateAllMirrorsWorker do
schedule_mirrors!(capacity: 4) schedule_mirrors!(capacity: 4)
expect_import_scheduled(licensed_project2, licensed_project3) expect_import_scheduled(licensed_project2, public_project)
expect_import_not_scheduled(licensed_project1) expect_import_not_scheduled(licensed_project1)
expect_import_not_scheduled(*unlicensed_projects) expect_import_not_scheduled(*unlicensed_projects)
end end
...@@ -198,7 +251,7 @@ describe UpdateAllMirrorsWorker do ...@@ -198,7 +251,7 @@ describe UpdateAllMirrorsWorker do
it "schedules all available mirrors" do it "schedules all available mirrors" do
schedule_mirrors!(capacity: 3) schedule_mirrors!(capacity: 3)
expect_import_scheduled(licensed_project1, licensed_project2, licensed_project3) expect_import_scheduled(licensed_project1, licensed_project2, public_project)
expect_import_not_scheduled(*unlicensed_projects) expect_import_not_scheduled(*unlicensed_projects)
end end
...@@ -216,7 +269,7 @@ describe UpdateAllMirrorsWorker do ...@@ -216,7 +269,7 @@ describe UpdateAllMirrorsWorker do
schedule_mirrors!(capacity: 2) schedule_mirrors!(capacity: 2)
expect_import_scheduled(licensed_project1, licensed_project2) expect_import_scheduled(licensed_project1, licensed_project2)
expect_import_not_scheduled(*unlicensed_projects, licensed_project3) expect_import_not_scheduled(*unlicensed_projects, public_project)
end end
it 'requests as many batches as necessary' do it 'requests as many batches as necessary' do
...@@ -233,7 +286,7 @@ describe UpdateAllMirrorsWorker do ...@@ -233,7 +286,7 @@ describe UpdateAllMirrorsWorker do
schedule_mirrors!(capacity: 1) schedule_mirrors!(capacity: 1)
expect_import_scheduled(licensed_project1) expect_import_scheduled(licensed_project1)
expect_import_not_scheduled(*unlicensed_projects, licensed_project2, licensed_project3) expect_import_not_scheduled(*unlicensed_projects, licensed_project2, public_project)
end end
it 'requests as many batches as necessary' do it 'requests as many batches as necessary' do
...@@ -246,4 +299,5 @@ describe UpdateAllMirrorsWorker do ...@@ -246,4 +299,5 @@ describe UpdateAllMirrorsWorker do
end end
end end
end end
end
end end
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