2020-01-11 10:07:49 -05:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2020-02-19 13:09:10 -05:00
|
|
|
class ContainerExpirationPolicyWorker # rubocop:disable Scalability/IdempotentWorker
|
2020-01-11 10:07:49 -05:00
|
|
|
include ApplicationWorker
|
2021-04-30 14:10:09 -04:00
|
|
|
|
|
|
|
sidekiq_options retry: 3
|
2020-02-11 10:08:44 -05:00
|
|
|
include CronjobQueue
|
2020-10-26 14:08:27 -04:00
|
|
|
include ExclusiveLeaseGuard
|
2020-01-11 10:07:49 -05:00
|
|
|
|
|
|
|
feature_category :container_registry
|
|
|
|
|
2020-10-26 14:08:27 -04:00
|
|
|
InvalidPolicyError = Class.new(StandardError)
|
|
|
|
|
2021-03-25 23:09:21 -04:00
|
|
|
BATCH_SIZE = 1000
|
2020-10-26 14:08:27 -04:00
|
|
|
|
2020-01-11 10:07:49 -05:00
|
|
|
def perform
|
2021-05-20 11:10:13 -04:00
|
|
|
process_stale_ongoing_cleanups
|
2021-06-16 14:10:35 -04:00
|
|
|
disable_policies_without_container_repositories
|
2020-10-26 14:08:27 -04:00
|
|
|
throttling_enabled? ? perform_throttled : perform_unthrottled
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
2021-06-16 14:10:35 -04:00
|
|
|
def disable_policies_without_container_repositories
|
|
|
|
ContainerExpirationPolicy.active.each_batch(of: BATCH_SIZE) do |policies|
|
|
|
|
policies.without_container_repositories
|
|
|
|
.update_all(enabled: false)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-05-20 11:10:13 -04:00
|
|
|
def process_stale_ongoing_cleanups
|
|
|
|
threshold = delete_tags_service_timeout.seconds + 30.minutes
|
|
|
|
ContainerRepository.with_stale_ongoing_cleanup(threshold.ago)
|
|
|
|
.update_all(expiration_policy_cleanup_status: :cleanup_unfinished)
|
|
|
|
end
|
|
|
|
|
2020-10-26 14:08:27 -04:00
|
|
|
def perform_unthrottled
|
|
|
|
with_runnable_policy(preloaded: true) do |policy|
|
|
|
|
with_context(project: policy.project,
|
|
|
|
user: policy.project.owner) do |project:, user:|
|
|
|
|
ContainerExpirationPolicyService.new(project, user)
|
|
|
|
.execute(policy)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def perform_throttled
|
|
|
|
try_obtain_lease do
|
|
|
|
ContainerExpirationPolicies::CleanupContainerRepositoryWorker.perform_with_capacity
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# TODO : remove the preload option when cleaning FF container_registry_expiration_policies_throttling
|
|
|
|
def with_runnable_policy(preloaded: false)
|
|
|
|
ContainerExpirationPolicy.runnable_schedules.each_batch(of: BATCH_SIZE) do |policies|
|
|
|
|
# rubocop: disable CodeReuse/ActiveRecord
|
|
|
|
cte = Gitlab::SQL::CTE.new(:batched_policies, policies.limit(BATCH_SIZE))
|
|
|
|
# rubocop: enable CodeReuse/ActiveRecord
|
|
|
|
scope = cte.apply_to(ContainerExpirationPolicy.all).with_container_repositories
|
|
|
|
|
|
|
|
scope = scope.preloaded if preloaded
|
|
|
|
|
|
|
|
scope.each do |policy|
|
|
|
|
if policy.valid?
|
2020-10-27 17:08:45 -04:00
|
|
|
yield policy
|
2020-10-26 14:08:27 -04:00
|
|
|
else
|
|
|
|
disable_invalid_policy!(policy)
|
2020-10-19 14:08:54 -04:00
|
|
|
end
|
2020-02-11 10:08:44 -05:00
|
|
|
end
|
2020-01-11 10:07:49 -05:00
|
|
|
end
|
|
|
|
end
|
2020-10-26 14:08:27 -04:00
|
|
|
|
|
|
|
def disable_invalid_policy!(policy)
|
|
|
|
policy.disable!
|
|
|
|
Gitlab::ErrorTracking.log_exception(
|
|
|
|
::ContainerExpirationPolicyWorker::InvalidPolicyError.new,
|
|
|
|
container_expiration_policy_id: policy.id
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
def throttling_enabled?
|
|
|
|
Feature.enabled?(:container_registry_expiration_policies_throttling)
|
|
|
|
end
|
|
|
|
|
|
|
|
def lease_timeout
|
|
|
|
5.hours
|
|
|
|
end
|
2021-05-20 11:10:13 -04:00
|
|
|
|
|
|
|
def delete_tags_service_timeout
|
|
|
|
::Gitlab::CurrentSettings.current_application_settings.container_registry_delete_tags_service_timeout || 0
|
|
|
|
end
|
2020-01-11 10:07:49 -05:00
|
|
|
end
|