-
Notifications
You must be signed in to change notification settings - Fork 125
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Migrations for suspending provider #222
Conversation
69d2243
to
2085d39
Compare
Cc @Fryguy |
2085d39
to
5099394
Compare
@@ -0,0 +1,5 @@ | |||
class AddVisibleToZone < ActiveRecord::Migration[5.0] | |||
def change | |||
add_column :zones, :visible, :boolean, :default => true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefer default_value_for
at the model level over a database-level default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That being said, you will need a data migration to update all existing zones to visible => true.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Fryguy exactly, so why is preferred more difficult solution? database-level default, at least for boolean, was standard for every project I seen before.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought about it, what about compromise solution? keep :default => true
as better alternative to data migration and add default_value_for
to keep your code standards
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
...ok, I disagree with your approach, but we need to finish this RFE, so as you wish
@@ -0,0 +1,5 @@ | |||
class AddBackupZoneIdToExtManagementSystem < ActiveRecord::Migration[5.0] | |||
def change | |||
add_reference :ext_management_systems, :backup_zone, :type => :bigint, :index => true, :after => :zone_id |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove the :after
bit...it's not necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it makes db structure more clear, if you group logical related columns together
Zone.where(:name => 'maintenance').where(:visible => false).destroy_all | ||
end | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This entire migration is unnecessary, because this can be handled in Zone.seed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Fryguy - are you sure that Zone.seed
is called after migrations in all existing installations?
f85d7e2
to
c8b53f3
Compare
class MakeMaintenanceZoneRecord < ActiveRecord::Migration[5.0] | ||
class Zone < ActiveRecord::Base | ||
validates_presence_of :name | ||
validates_uniqueness_of :name |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These must be removed. In a global region, since zones are transferred from other regions, there are multiple "default" zones, for example. As such, this migration will fail to migrate a global database.
|
||
def up | ||
say_with_time("Creating Maintenance Zone") do | ||
zone = Zone.where(:name => Zone::MAINTENANCE_ZONE_NAME).first |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It just occurred to me that this is not region aware. Please change this to Zone.in_my_region.where(...)
, to allow migrating a global database. You can also create a spec showing this, but will need to give each zone an id within a region. There should be other migrations that have examples showing how to do that.
1c19691
to
6c36a15
Compare
@Fryguy I'm not sure, how exactly migrations work on global database so please look if |
|
||
migration_context :up do | ||
before(:each) do | ||
zone_stub.delete_all |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure why you need this...the database should be empty.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is not cleaned between specs in migration_context
when I use zone_stub.create!
. I don't know if it is some bad local settings, but specs are failing without this line.
zone.save | ||
end | ||
|
||
Zone.create_with(:description => "Maintenance Zone", :visible => false).find_or_create_by!(:name => Zone::MAINTENANCE_ZONE_NAME) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We typically don't create seed data in migrations, instead doing that in the .seed method. Typically a migrated empty database should still be empty in the end.
What I recommend here is to keep the bit where we rename any existing __maintenance__
zone, but get rid of the part that actually creates the maintenance zone, instead moving that to .seed in the core.
|
||
migration_context :up do | ||
before(:each) do | ||
zone_stub.delete_all |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Fryguy my respose was hidden after commit...
I think it should be cleared, but it's not, create!
in spec below is creating more and more records when running repeatedly and spec doesn't work then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hm, this should not happen, something must be off, because it should all just a transaction that gets rolled back
Delete like this will not work if the specs will run in parallel. So we need to find a way to to properly fix this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Ladas probably some bad before :all
in the past in my local db so it work without it normally.
e2f4ce1
to
e4b3ab6
Compare
@carbonin 👍 works for me |
@carbonin I'm not sure what you mean by it - what does it mean "just fail the migration"? And creating of zone in migration doesn't want @Fryguy, so it seems to me that we are in loop :) |
@slemrmartin Just leave the rename as is but add an exception handler that prints a message like "Failed to rename maintenance, check for zone conflicts" and re-raise the exception. It will fail the upgrade and the customer will have to remediate it. |
class Zone < ActiveRecord::Base | ||
include ActiveRecord::IdRegions | ||
|
||
validates_presence_of :name |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it is, it need to be multi-region aware.
|
||
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The where
s can be merged
Doesn't seem acceptable to me. If it was only developers I could be okay with it, but not for customers. I know it's an edge case, but they're not going to know what went wrong or how to fix it and it's going to lead to an unnecessary support call on a weekend (since that's when they do upgrades). Maybe we could talk about something like #222 (comment) instead? |
@bdunne they should know exactly what to do to fix it if we include the remediation steps in the failure message. It should be straight forward enough. |
Okay, so @carbonin and I were just discussing this some more... I think renaming an existing zone in a migration is just out of the question. Too many things don't use real relations and point to zones by name (mistakes were made), that's why there is a uniqueness validation on Zone#name. That said, it really doesn't matter what the name of our maintenance zone is as long as we can find it when we want to use it. I think we should generate a random zone name and create that as our maintenance zone (and if it conflicts with an existing one, generate a new one until it doesn't conflict). Then we can put a reference to that zone on MiqRegion so that we can find it in the future. Is there any case where we would want multiple maintenance zones? |
@bdunne good point Answer is: No, we don't want multiple maintenance zones - that's another reason why it isn't identified by some boolean flag. I consider your solution as more robust, but it requires new migration to MiqRegion - I hope for choosing any solution, it was customer request (urgent, I suppose) 3 months ago, I think ;)) |
Reading back, I'm on the fence about renaming maintenance zone. On one hand, having a hard-coded name is nice because that's what we have for the default zone. However the difference is that the default zone is seeded way before a customer gets a chance to create their own zone. Additionally, as @bdunne mentioned, the data migration would also have to rename every column where we store zone as a name, such as in MiqQueue, and in the worst case some deep yaml options column (I really hope this isn't a thing, but you never know).
It does matter if we have to show it somewhere. We can probably easily hide it from the Zone configuration page, but my concern is there's going to some random locations in the UI we haven't considered and the user is going to see
I don't think we want multiple zones for any particular purpose, but there will be multiple maintenance zones upon replication. For the default zone we deal with this just fine, but the default zone isn't "special"; it's just a normal zone we seed. For maintenance, if we need to "hide" it, then you get into having to hide multiple zones in the UI. |
@Fryguy For what it's worth, we don't show the region accordion for anything other than the current region. So we don't really display the zone anywhere in the UI. But while thinking about this, I'm realizing that the provider (and its relation to its zone) would be replicated. That makes me think that the global will need the information about which zone is is the maintenance zone for each of the remote regions to display the provider correctly (as suspended). |
I would prefer to keep identification by name If we need to rename existing |
Also backup zone column for ems https://bugzilla.redhat.com/show_bug.cgi?id=1455145
If previously created by user
Due to global region
For global database https://bugzilla.redhat.com/show_bug.cgi?id=1455145
Present also in Zone.seed
e4b3ab6
to
0adca06
Compare
Like Job,MiqTask,MiqQueue + raises error when renaming existing zone to another existing.
0adca06
to
87bbb6a
Compare
Checked commits slemrmartin/manageiq-schema@8767c08~...87bbb6a with ruby 2.3.3, rubocop 0.52.1, haml-lint 0.20.0, and yamllint 1.10.0 db/migrate/20180618084054_init_zones_visibility.rb
|
say_with_time("Renaming user-defined Maintenance Zone") do | ||
zone = Zone.in_my_region.find_by(:name => Zone::MAINTENANCE_ZONE_NAME) | ||
if zone.present? | ||
# STEP 1 - rename zone |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still think this is the wrong approach
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bdunne you were worried about string associations
- possibility that user has
__maintenance__
as name is almost zero - if so, zone and associations are renamed to name with possibility of duplication zero^2.
could you be more specific? When this fails (with significant probability).
Is it not acceptable for @Fryguy, @agrare, @carbonin too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- possibility that user has maintenance as name is almost zero
I agree, but while unlikely, not impossible
- if so, zone and associations are renamed to name with possibility of duplication zero^2.
Right now you're only updating Job
and MiqQueue
. The following models have a zone
column:
=> ["MiqQueue", "Job", "MiqTask", "ManageIQ::Providers::Kubernetes::ContainerManager::Scanning::Job", "ManageIQ::Providers::EmbeddedAnsible::AutomationManager::PlaybookRunner", "ManageIQ::Providers::EmsRefreshWorkflow", "ManageIQ::Providers::AnsibleRunnerWorkflow", "VmScan", "ManageIQ::Providers::NativeOperationWorkflow", "Service::LinkingWorkflow"]
I also believe it's in Settings and who knows how many other places it's buried in a serialized column. I just don't think it's practical to try renaming a zone
I prepared alternative PR with region association: |
Closing in favor of #275 now that it is merged |
BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1455145
Issue: ManageIQ/manageiq#17489
Adds Zone visibility and EMS's backup zone relation