-
Notifications
You must be signed in to change notification settings - Fork 897
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
Fixup polymorphic issues with MiqReport + Rbac #19804
Conversation
top_level_rels.uniq.each do |assoc| | ||
reflection = db_klass.reflect_on_association(assoc) | ||
polymorphic_rels << assoc if reflection && reflection.polymorphic? | ||
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.
Note: This is basically a reworking of the code that was removed here:
2fa1e6c
to
91ff9a6
Compare
91ff9a6
to
6f23bdc
Compare
b545018
to
98af3e7
Compare
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.
98af3e7
to
7a94f10
Compare
We have removed support for filtering includes/references by polymorphic relations: ManageIQ@8cc2277b So it is up to the callers to determine the best way to handle this. Raising a custom error will make it more obvious what needs to be done.
This changes what is passed to Rbac from MiqReport::Generator to avoid passing keys for includes/references that are polymorphic in nature. This means that there might be a bit of a performance degradation on some reports, but for now stability is being favored over performance. Follow up: For the keys that are skipped, a MiqPreload should probably be called to avoid N+1 calls, but unsure where the best for this would be.
7a94f10
to
66c9ec8
Compare
Checked commits NickLaMuro/manageiq@1a4de9c~...66c9ec8 with ruby 2.5.5, rubocop 0.69.0, haml-lint 0.20.0, and yamllint 1.10.0 app/models/miq_report/generator.rb
|
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 is a great solution. Solves our issue and isn't going backwards.
At a future date I may see about getting away from references and going towards left_joins
/preload
:include_for_find => @include | ||
described_class.search :class => "MetricRollup", | ||
:include_for_find => @include, | ||
:references => @include |
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's unclear what's not supported here^: polymorphic reflection in includes OR references OR both. Also, does it make sense to put the @include[:resource] = {}
here, so it's more clear what isn't supported. Is that change in the before
needed for other tests or specific to this test? If the latter, I'd prefer it be here.
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.
may make sense to trim down this includes.
:includes_for_find => %w[v_derived_storage_used resource],
:references => %w[v_derived_storage_used]
The current problem is having a polymorphic in the includes()
and anything in the references()
.
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.
Right, I was commenting that it was unclear what exactly is causing the error to be raised. It sounds like a polymorphic in an includes with anything in references so @kbrock's example would make that clearer to me. That can be done as a followup.
|
||
expect do | ||
described_class.search :class => "MetricRollup", | ||
:include_for_find => @include |
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.
Again, it's unclear if this is raising because the polymorphic is in includes or references or both.
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.
yea, this problem is that no references
is passed and it fell back to legacy support (when we didn't pass references, we used includes_for_find
for both)
|
||
expect do | ||
described_class.search :class => "MetricRollup", | ||
:include_for_find => @include, |
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 helps clarify it but is passing just the polymorphic in the references also supported?
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.
To avoid a 📖 explaining the Rails internals, the short answer is that .references
does not work without .includes
, per the docs:
https://api.rubyonrails.org/v5.1.7/classes/ActiveRecord/QueryMethods.html#method-i-references
So doing a test by itself would be pointless.
ActiveRecord::Base.includes
, on the otherhand, under the hood will internally do a polymorphic check and decides whether or not to do one or multiple queries (the "one query" will do some joins as a result):
MetricRollup.inclMetricRollup.includes(:time_profile => {})
# MetricRollup Load (2.2ms) SELECT "metric_rollups".* FROM "metric_rollups"
# MetricRollup Inst Including Associations (0.1ms - 1rows)
# TimeProfile Load (0.3ms) SELECT "time_profiles".* FROM "time_profiles" WHERE "time_profiles"."id" = 22000000000118
# TimeProfile Inst Including Associations (0.2ms - 1rows)
MetricRollup.includes(:time_profile => {}).references(:time_profiles)
# SQL (2.3ms) SELECT "metric_rollups"."id" AS t0_r0,
# "metric_rollups"."timestamp" AS t0_r1,
# "metric_rollups"."capture_interval" AS t0_r2,
# "metric_rollups"."resource_type" AS t0_r3,
# ...
# "time_profiles"."id" AS t1_r0,
# "time_profiles"."description" AS t1_r1,
# "time_profiles"."profile_type" AS t1_r2,
# "time_profiles"."profile_key" AS t1_r3,
# LEFT OUTER JOIN "time_profiles" ON "time_profiles"."id" = "metric_rollups"."time_profile_id"
# MetricRollup Inst Including Associations (0.2ms - 1rows)
Guess this is a book...
But if you want a book, you can read the commit where I added this spec in the first place: NickLaMuro@03284cf
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.
lol. yup 📖 says you need all references() values in the
includes()`. ;)
:db => "VimPerformanceDaily", | ||
:col_order => %w[timestamp cpu_usagemhz_rate_average max_derived_cpu_available | ||
resource.derived_memory_used_low_over_time_period] | ||
) |
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.
Are we testing that it runs without raising? Should we be doing that or checking the results of generate_table?
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 didn't write this spec... @kbrock ?
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.
yea, this is testing that it doesn't puke.
@@ -319,6 +321,8 @@ def search(options = {}) | |||
attrs[:auth_count] = auth_count unless options[:skip_counts] | |||
|
|||
return targets, attrs | |||
rescue ActiveRecord::EagerLoadPolymorphicError | |||
raise Rbac::PolymorphicError |
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.
Does the exception message include the polymorphic that attempted to be eagerly loaded?
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 is just a nice to have... hopefully if it blows up, it will tell you which polymorphic is at fault.
LGTM, I just had a few questions above. |
Removed comment in description implying this is WIP. |
YAY! |
Alternative to #19778
Takes an "alternative" approach to the above by not trying to fix the issue in Rbac, but instead assume the
Rbac
implementation is as intended, and callers need to work around it.In this specific case, change the caller of
MiqReport::Generator
so we aren't passing in arguments toRbac
that are polymorphic.Links