Skip to content

Commit

Permalink
Renaming maintenance zone's string associations.
Browse files Browse the repository at this point in the history
Like Job,MiqTask,MiqQueue + raises error when renaming existing zone to another existing.
  • Loading branch information
slemrmartin committed Sep 10, 2018
1 parent 59b1e78 commit 0adca06
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 11 deletions.
79 changes: 72 additions & 7 deletions db/migrate/20180626125655_rename_user_maintenance_zone_record.rb
Original file line number Diff line number Diff line change
@@ -1,18 +1,62 @@
class RenameUserMaintenanceZoneRecord < ActiveRecord::Migration[5.0]
class UniqueWithinRegionValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
return if value.nil?
match_case = options.key?(:match_case) ? options[:match_case] : true
record_base_class = record.class.base_class
field_matches =
if match_case
record_base_class.where(attribute => value)
else
record_base_class.where(record_base_class.arel_attribute(attribute).lower.eq(value.downcase))
end
unless field_matches.in_region(record.region_id).where.not(:id => record.id).empty?
record.errors.add(attribute, "is not unique within region #{record.region_id}")
end
end
end

class Zone < ActiveRecord::Base
include ActiveRecord::IdRegions

validates_presence_of :name
validates :name, "rename_user_maintenance_zone_record/unique_within_region" => true

MAINTENANCE_ZONE_NAME = "__maintenance__".freeze
end

class Job < ActiveRecord::Base
self.inheritance_column = :_type_disabled

belongs_to :miq_task, :dependent => :delete
after_update_commit :update_linked_task

def update_linked_task
miq_task&.update_attributes!(:zone => zone)
end
end

class MiqTask < ActiveRecord::Base
has_one :job, :dependent => :destroy
has_one :miq_queue
end

class MiqQueue < ActiveRecord::Base
belongs_to :miq_task
end

def up
say_with_time("Renaming user-defined Maintenance Zone") do
zone = Zone.in_my_region.where(:name => Zone::MAINTENANCE_ZONE_NAME).first
zone = Zone.in_my_region.find_by(:name => Zone::MAINTENANCE_ZONE_NAME)
if zone.present?
zone.name = "#{zone.name}_0"
zone.save
# STEP 1 - rename zone
zone.name = "#{zone.name}_#{Zone.my_region_number}"
if zone.save
# STEP 2 - rename string associations
rename_string_associations(Zone::MAINTENANCE_ZONE_NAME, zone.name)
else
raise "Zone '#{Zone::MAINTENANCE_ZONE_NAME}' cannot be renamed to #{zone.name}. Reason: #{zone.errors.messages.inspect}"
end
end
end
end
Expand All @@ -21,11 +65,32 @@ def down
say_with_time("Renaming user-defined Maintenance Zone") do
Zone.in_my_region.where(:name => Zone::MAINTENANCE_ZONE_NAME).where(:visible => false).destroy_all

orig = Zone.in_my_region.where(:name => "#{Zone::MAINTENANCE_ZONE_NAME}_0").first
user_zone_name = "#{Zone::MAINTENANCE_ZONE_NAME}_#{Zone.my_region_number}"
orig = Zone.in_my_region.find_by(:name => user_zone_name)
if orig.present?
orig.name = orig.name[0..orig.name.size - 3]
orig.save
# STEP 1 - rename user's zone back
orig.name = Zone::MAINTENANCE_ZONE_NAME
if orig.save
# STEP 2 - rename string associations
rename_string_associations(user_zone_name, Zone::MAINTENANCE_ZONE_NAME)
else
raise "Zone '#{user_zone_name}' cannot be renamed to #{Zone::MAINTENANCE_ZONE_NAME}. Reason: #{orig.errors.messages.inspect}"
end
end
end
end

private

def rename_string_associations(old_zone_name, new_zone_name)
[Job, MiqQueue].each do |klass|
klass.where(:zone => old_zone_name).each do |record|
record.zone = new_zone_name
unless record.save
# This is not critical, migrations can continue
say("WARN: #{klass.name}'s (id: #{record.id}) zone not renamed. Reason: #{record.errors.messages.inspect}")
end
end
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

describe RenameUserMaintenanceZoneRecord do
let(:zone_stub) { migration_stub(:Zone) }
let(:job_stub) { migration_stub(:Job) }
let(:miq_task_stub) { migration_stub(:MiqTask) }
let(:miq_queue_stub) { migration_stub(:MiqQueue) }

let(:remote_region_start) do
anonymous_class_with_id_regions.rails_sequence_start +
Expand All @@ -15,7 +18,7 @@
migrate
orig.reload

expect(orig.name).to eq("#{zone_stub::MAINTENANCE_ZONE_NAME}_0")
expect(orig.name).to eq("#{zone_stub::MAINTENANCE_ZONE_NAME}_#{zone_stub.my_region_number}")
end

it "does not rename zone from remote regions" do
Expand All @@ -29,6 +32,47 @@

expect(user_zone.name).to eq(zone_stub::MAINTENANCE_ZONE_NAME)
end

it "renames string associations belonging to former maintenance zone" do
orig = zone_stub.create!(:name => zone_stub::MAINTENANCE_ZONE_NAME)
assoc = {}
assoc[:miq_task] = miq_task_stub.create!(:zone => orig.name)
assoc[:job] = job_stub.create!(:zone => orig.name, :miq_task => assoc[:miq_task])
assoc[:miq_queue] = miq_queue_stub.create!(:zone => orig.name, :miq_task => assoc[:miq_task])

migrate
orig.reload
assoc.each_value do |record|
record.reload
expect(record.zone).to eq(orig.name)
end
end

it "does not rename unrelated jobs, tasks and queues" do
orig = zone_stub.create!(:name => zone_stub::MAINTENANCE_ZONE_NAME)
other_zone_name = "Some other zone"
other = zone_stub.create!(:name => other_zone_name)

assoc = {}
assoc[:miq_task] = miq_task_stub.create!(:zone => other.name)
assoc[:job] = job_stub.create!(:zone => other.name, :miq_task => assoc[:miq_task])
assoc[:miq_queue] = miq_queue_stub.create!(:zone => other.name, :miq_task => assoc[:miq_task])

migrate
orig.reload
other.reload
expect(other.name).to eq(other_zone_name)
assoc.each_value do |record|
record.reload
expect(record.zone).to eq(other_zone_name)
end
end

it "raises error when original zone renamed to existing one" do
zone_stub.create!(:name => zone_stub::MAINTENANCE_ZONE_NAME)
zone_stub.create!(:name => "#{zone_stub::MAINTENANCE_ZONE_NAME}_#{zone_stub.my_region_number}")
expect { migrate }.to raise_error(/is not unique within region/)
end
end

migration_context :down do
Expand All @@ -43,7 +87,7 @@
end

it "renames original maintenance zone back" do
orig = zone_stub.create!(:name => "#{zone_stub::MAINTENANCE_ZONE_NAME}_0")
orig = zone_stub.create!(:name => "#{zone_stub::MAINTENANCE_ZONE_NAME}_#{zone_stub.my_region_number}")

migrate
orig.reload
Expand All @@ -55,12 +99,27 @@
id = remote_region_start

user_zone = zone_stub.create!(:id => id,
:name => "#{zone_stub::MAINTENANCE_ZONE_NAME}_0")
:name => "#{zone_stub::MAINTENANCE_ZONE_NAME}_#{zone_stub.my_region_number}")

migrate
user_zone.reload

expect(user_zone.name).to eq("#{zone_stub::MAINTENANCE_ZONE_NAME}_0")
expect(user_zone.name).to eq("#{zone_stub::MAINTENANCE_ZONE_NAME}_#{zone_stub.my_region_number}")
end

it "renames string associations belonging to original maintenance zone back" do
orig = zone_stub.create!(:name => "#{zone_stub::MAINTENANCE_ZONE_NAME}_#{zone_stub.my_region_number}")
assoc = {}
assoc[:miq_task] = miq_task_stub.create!(:zone => orig.name)
assoc[:job] = job_stub.create!(:zone => orig.name, :miq_task => assoc[:miq_task])
assoc[:miq_queue] = miq_queue_stub.create!(:zone => orig.name, :miq_task => assoc[:miq_task])

migrate
orig.reload
assoc.each_value do |record|
record.reload
expect(record.zone).to eq(orig.name)
end
end
end
end

0 comments on commit 0adca06

Please sign in to comment.