Skip to content
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

Merged
merged 4 commits into from
Feb 7, 2020

Conversation

NickLaMuro
Copy link
Member

@NickLaMuro NickLaMuro commented Feb 4, 2020

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 to Rbac that are polymorphic.

Links

top_level_rels.uniq.each do |assoc|
reflection = db_klass.reflect_on_association(assoc)
polymorphic_rels << assoc if reflection && reflection.polymorphic?
end
Copy link
Member Author

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:

@miq-bot miq-bot added the wip label Feb 4, 2020
@NickLaMuro NickLaMuro force-pushed the fix_issue_19664_v2 branch 2 times, most recently from 2fa1e6c to 91ff9a6 Compare February 4, 2020 19:50
app/models/miq_report/generator.rb Outdated Show resolved Hide resolved
app/models/miq_report/generator.rb Outdated Show resolved Hide resolved
app/models/miq_report/generator.rb Outdated Show resolved Hide resolved
app/models/miq_report/generator.rb Show resolved Hide resolved
spec/models/miq_report/generator_spec.rb Show resolved Hide resolved
spec/lib/rbac/filterer_spec.rb Outdated Show resolved Hide resolved
spec/lib/rbac/filterer_spec.rb Show resolved Hide resolved
@NickLaMuro NickLaMuro force-pushed the fix_issue_19664_v2 branch 2 times, most recently from b545018 to 98af3e7 Compare February 5, 2020 23:09
Copy link
Member

@skateman skateman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Seal of Approval
This fixes my issue with the generation of Utilization charts

@NickLaMuro NickLaMuro changed the title [WIP] Fixup polymorphic issues with MiqReport + Rbac Fixup polymorphic issues with MiqReport + Rbac Feb 6, 2020
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.
@miq-bot
Copy link
Member

miq-bot commented Feb 6, 2020

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
5 files checked, 3 offenses detected

app/models/miq_report/generator.rb

Copy link
Member

@kbrock kbrock left a 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
Copy link
Member

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.

Copy link
Member

@kbrock kbrock Feb 7, 2020

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().

Copy link
Member

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
Copy link
Member

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.

Copy link
Member

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,
Copy link
Member

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?

Copy link
Member Author

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

Copy link
Member

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]
)
Copy link
Member

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?

Copy link
Member Author

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 ?

Copy link
Member

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
Copy link
Member

@jrafanie jrafanie Feb 7, 2020

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?

Copy link
Member

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.

@jrafanie
Copy link
Member

jrafanie commented Feb 7, 2020

LGTM, I just had a few questions above.

@jrafanie
Copy link
Member

jrafanie commented Feb 7, 2020

Removed comment in description implying this is WIP.

@jrafanie jrafanie merged commit c6a25c0 into ManageIQ:master Feb 7, 2020
@jrafanie jrafanie self-assigned this Feb 7, 2020
@jrafanie jrafanie added this to the Sprint 130 Ending Feb 17, 2020 milestone Feb 7, 2020
@skateman
Copy link
Member

skateman commented Feb 7, 2020

YAY!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants