Skip to content

Commit

Permalink
Merge pull request #17167 from cben/quota-purging
Browse files Browse the repository at this point in the history
Purging of ContainerQuota & ContainerQuotaItem
(cherry picked from commit 388f266)

https://bugzilla.redhat.com/show_bug.cgi?id=1559544
  • Loading branch information
kbrock authored and simaishi committed Mar 26, 2018
1 parent 796dc34 commit d583069
Show file tree
Hide file tree
Showing 8 changed files with 183 additions and 0 deletions.
1 change: 1 addition & 0 deletions app/models/container_quota.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class ContainerQuota < ApplicationRecord
# - ContainerQuotaItems can be added/deleted/changed, and we use archiving to
# record changes too!
include ArchivedMixin
include_concern 'Purging'

belongs_to :ext_management_system, :foreign_key => "ems_id"
belongs_to :container_project
Expand Down
25 changes: 25 additions & 0 deletions app/models/container_quota/purging.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
class ContainerQuota < ApplicationRecord
module Purging
extend ActiveSupport::Concern
include PurgingMixin

module ClassMethods
def purge_date
::Settings.container_entities.history.keep_archived_quotas.to_i_with_method.seconds.ago.utc
end

def purge_window_size
::Settings.container_entities.history.purge_window_size
end

def purge_scope(older_than)
where(arel_table[:deleted_on].lteq(older_than))
end

def purge_associated_records(ids)
ContainerQuotaScope.where(:container_quota_id => ids).delete_all
ContainerQuotaItem.where(:container_quota_id => ids).delete_all
end
end
end
end
1 change: 1 addition & 0 deletions app/models/container_quota_item.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ class ContainerQuotaItem < ApplicationRecord
# This model is unusual in using archiving not only to record deletions but also changes in quota_desired, quota_enforced, quota_observed.
# Instead of updating in-place, we archive the old record and create a new one.
include ArchivedMixin
include_concern 'Purging'

belongs_to :container_quota
has_many :container_quota_scopes, :through => :container_quota
Expand Down
20 changes: 20 additions & 0 deletions app/models/container_quota_item/purging.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
class ContainerQuotaItem < ApplicationRecord
module Purging
extend ActiveSupport::Concern
include PurgingMixin

module ClassMethods
def purge_date
::Settings.container_entities.history.keep_archived_quotas.to_i_with_method.seconds.ago.utc
end

def purge_window_size
::Settings.container_entities.history.purge_window_size
end

def purge_scope(older_than)
where(arel_table[:deleted_on].lteq(older_than))
end
end
end
end
2 changes: 2 additions & 0 deletions app/models/miq_schedule_worker/jobs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ def archived_entities_purge_timer
queue_work(:class_name => "ContainerGroup", :method_name => "purge_timer", :zone => nil)
queue_work(:class_name => "ContainerImage", :method_name => "purge_timer", :zone => nil)
queue_work(:class_name => "ContainerProject", :method_name => "purge_timer", :zone => nil)
queue_work(:class_name => "ContainerQuota", :method_name => "purge_timer", :zone => nil)
queue_work(:class_name => "ContainerQuotaItem", :method_name => "purge_timer", :zone => nil)
end

def miq_schedule_queue_scheduled_work(schedule_id, rufus_job)
Expand Down
1 change: 1 addition & 0 deletions config/settings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -963,6 +963,7 @@
:container_entities:
:history:
:keep_archived_entities: 6.months
:keep_archived_quotas: 6.months
:purge_window_size: 1000
:product:
:maindb: ExtManagementSystem
Expand Down
63 changes: 63 additions & 0 deletions spec/models/container_quota/purging_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
describe ContainerQuota do
context "::Purging" do
context ".purge_queue" do
before do
EvmSpecHelper.create_guid_miq_server_zone
end
let(:purge_time) { (Time.zone.now + 10).round }

it "submits to the queue" do
expect(described_class).to receive(:purge_date).and_return(purge_time)
described_class.purge_timer

q = MiqQueue.all
expect(q.length).to eq(1)
expect(q.first).to have_attributes(
:class_name => described_class.name,
:method_name => "purge_by_date",
:args => [purge_time]
)
end
end

context ".purge" do
let(:deleted_date) { 6.months.ago }

before do
@old_quota = FactoryGirl.create(:container_quota, :deleted_on => deleted_date - 1.day)
@old_quota_scope = FactoryGirl.create(:container_quota_scope, :container_quota => @old_quota)
@old_quota_old_item = FactoryGirl.create(:container_quota_item, :container_quota => @old_quota,
:deleted_on => deleted_date - 1.day)
@old_quota_active_item = FactoryGirl.create(:container_quota_item, :container_quota => @old_quota,
:deleted_on => nil)

@purge_date_quota = FactoryGirl.create(:container_quota, :deleted_on => deleted_date)

@new_quota = FactoryGirl.create(:container_quota, :deleted_on => deleted_date + 1.day)
@new_quota_scope = FactoryGirl.create(:container_quota_scope, :container_quota => @new_quota)
@new_quota_old_item = FactoryGirl.create(:container_quota_item, :container_quota => @new_quota,
:deleted_on => deleted_date - 1.day)
end

def assert_unpurged_ids(model, unpurged_ids)
expect(model.order(:id).pluck(:id)).to eq(Array(unpurged_ids).sort)
end

it "purge_date and older" do
described_class.purge(deleted_date)
assert_unpurged_ids(ContainerQuota, @new_quota.id)
assert_unpurged_ids(ContainerQuotaScope, @new_quota_scope.id)
# This quota item is itself due for purging, but not as part of ContainerQuota::Purging.
assert_unpurged_ids(ContainerQuotaItem, @new_quota_old_item.id)
end

it "with a window" do
described_class.purge(deleted_date, 1)
assert_unpurged_ids(ContainerQuota, @new_quota.id)
assert_unpurged_ids(ContainerQuotaScope, @new_quota_scope.id)
# This quota item is itself due for purging, but not as part of ContainerQuota::Purging.
assert_unpurged_ids(ContainerQuotaItem, @new_quota_old_item.id)
end
end
end
end
70 changes: 70 additions & 0 deletions spec/models/container_quota_item/purging_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
describe ContainerQuotaItem do
context "::Purging" do
context ".purge_queue" do
before do
EvmSpecHelper.create_guid_miq_server_zone
end
let(:purge_time) { (Time.zone.now + 10).round }

it "submits to the queue" do
expect(described_class).to receive(:purge_date).and_return(purge_time)
described_class.purge_timer

q = MiqQueue.all
expect(q.length).to eq(1)
expect(q.first).to have_attributes(
:class_name => described_class.name,
:method_name => "purge_by_date",
:args => [purge_time]
)
end
end

context ".purge" do
let(:deleted_date) { 6.months.ago }

before do
@old_quota = FactoryGirl.create(:container_quota, :deleted_on => deleted_date - 1.day)
@old_quota_scope = FactoryGirl.create(:container_quota_scope, :container_quota => @old_quota)
@old_quota_old_item = FactoryGirl.create(:container_quota_item, :container_quota => @old_quota,
:deleted_on => deleted_date - 1.day)
@old_quota_purge_date_item = FactoryGirl.create(:container_quota_item, :container_quota => @old_quota,
:deleted_on => deleted_date)
@old_quota_new_item = FactoryGirl.create(:container_quota_item, :container_quota => @old_quota,
:deleted_on => deleted_date + 1.day)

# Quota items may get archived as result of quota edits, while parent quota remains active.
@active_quota = FactoryGirl.create(:container_quota, :deleted_on => nil)
@active_quota_scope = FactoryGirl.create(:container_quota_scope, :container_quota => @active_quota)
@active_quota_old_item = FactoryGirl.create(:container_quota_item, :container_quota => @active_quota,
:deleted_on => deleted_date - 1.day)
@active_quota_purge_date_item = FactoryGirl.create(:container_quota_item, :container_quota => @active_quota,
:deleted_on => deleted_date)
@active_quota_new_item = FactoryGirl.create(:container_quota_item, :container_quota => @active_quota,
:deleted_on => deleted_date + 1.day)
@active_quota_active_item = FactoryGirl.create(:container_quota_item, :container_quota => @active_quota,
:deleted_on => nil)
end

def assert_unpurged_ids(model, unpurged_ids)
expect(model.order(:id).pluck(:id)).to eq(Array(unpurged_ids).sort)
end

it "purge_date and older" do
described_class.purge(deleted_date)
# @old_quota is itself due for purging, but not as part of ContainerQuotaItem::Purging.
assert_unpurged_ids(ContainerQuota, [@old_quota.id, @active_quota.id])
assert_unpurged_ids(ContainerQuotaScope, [@old_quota_scope.id, @active_quota_scope.id])
assert_unpurged_ids(ContainerQuotaItem, [@old_quota_new_item.id, @active_quota_new_item.id, @active_quota_active_item.id])
end

it "with a window" do
described_class.purge(deleted_date, 1)
# @old_quota is itself due for purging, but not as part of ContainerQuotaItem::Purging.
assert_unpurged_ids(ContainerQuota, [@old_quota.id, @active_quota.id])
assert_unpurged_ids(ContainerQuotaScope, [@old_quota_scope.id, @active_quota_scope.id])
assert_unpurged_ids(ContainerQuotaItem, [@old_quota_new_item.id, @active_quota_new_item.id, @active_quota_active_item.id])
end
end
end
end

0 comments on commit d583069

Please sign in to comment.