-
Notifications
You must be signed in to change notification settings - Fork 898
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
Rbac virtual attributes #18543
Rbac virtual attributes #18543
Conversation
d54d98e
to
a0090a5
Compare
WIP status: this works. I put in a kludge to enable this for every page possible. In the short term, I would like us to test this across as many pages as possible, just to find issues. then when we are ready to merge, I'll remove the hack and enable on specific pages |
a0090a5
to
6c3bfd1
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.
Not all of these require a change (some are just comments/rants), but would at least like a few answers/discussion before giving a signoff.
a8aebf4
to
5065ebb
Compare
@NickLaMuro just fixed cops. All good with you now? |
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.
***BIG ASTERISK next to the "Request changes" status for this review***. PLEASE READ:
First off, the main theme of this review is "do we need this now", not "this is bad".
Besides this being a high touch point part of the app, making this extremely risky, I am also wondering if it makes sense to undo what caused this issue in the first place, which was a PR that I wrote three years ago:
But, undoing that is MUCH more invasive, so that would also be something we would do later. And I don't say that to rule out possibility of going with the original plan of sticking with this approach either, just that the reason we aren't doing that refactoring effort now is the same reason we aren't gutting what I wrote.
What I want to get to is the MVP amount of changes to make this work (and only work) for Service.yaml
, and if there are any use cases that aren't described in the PR that some of the lines of code are addressing (add_joins
for example), then we should document those in this PR and/or in specs.
If we can remove code (for now) or at least add missing documentation/explanations, I am fine with this for the most part.
lib/rbac/filterer.rb
Outdated
limit && extra_cols && | ||
!klass.table_name&.include?(".") && scope.respond_to?(:includes_values) | ||
inner_scope = scope.except(:select, :includes, :references) | ||
scope.includes_values.each { |hash| inner_scope = add_joins(klass, inner_scope, hash) } |
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.
Can you describe where this is needed for the BZ in question (aka: Service.yaml
)?
I am not trying to argue "we don't need this", but am unsure if "we need this now". Would prefer some clarification in the PR description, a response here, or a comment in the code as to what this is fixing.
Note: If we don't need this line for backports, then that also means the two methods add_joins
and table_include?
don't need to be backported either, and we can add them back in a follow up.
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, the “I know you said to in-line this but it will bread under these conditions” block may be too cautious.
The if block reads: if this is enabled, and it would benifit us, and it would not blowup, then...
And the inline view reads: convert this to just select from the primary table without the extra tables (but do left join to tables so we can use the where clause)
And the main scope no longer needs the where and limit, since those are already applied in the inline view.
I thought this was getting pretty minimal. I agree that the conversion from requires to joins is not optimal, but that is the only complexity there.
Taking a step back, is the applying of the join your main gripe?
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.
In the perfect scenario, the inline view is simple:
FROM (select * from services limit 20) as services
When the references stay there, it throws wrenches into the mix. So many different ways. Converting to joins ended up being simpler than handling all the edge cases.
That was the reason I had the select(“*”) in there before. But it broke too easily with different rbac filters.
So while not optimal, this was the simplest way I could get it consistently working without thinking a different type of rbac filter would break things. And it gave me the most confidence.
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.
Taking a step back, is the applying of the join your main gripe?
Yes, but only in the context of a backport. Goes back to what I was saying in the "review description", but from the info I have provided from you, I can't see where this is needed to fix the BZ.
I definitely can see why this is needed a broader fix outside the scope of Service.yaml
, but I haven't been presented with any case within that scope where doing the add_joins
is necessary to specifically fix the BZ. The only reason I have been able determine you added the add_joins
was to fix specs and use cases when options[:use_sql_view]
was always enabled, but again, I think that falls outside the scope of a "targeted bugfix".
So I would like to drop it for this PR (if possible), but my gripe is only that it "adds risk/complexity" that isn't needed now (please correct me if I am wrong on this), not that "it is bad, never do this".
That said, we should add this as part of the follow up PR we talked about if it turns out we don't require it here, and I will have next to no problem with that there. And in regards to my suggestion previously:
I am also wondering if it makes sense to undo what caused this issue in the first place, which was a PR that I wrote three years ago: #11502
Is probably much more work and haven't fully vetted, just something I thought as a potential alternative.
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.
When the references stay there, it throws wrenches into the mix. So many different ways. Converting to joins ended up being simpler than handling all the edge cases.
That was the reason I had the select(“*”) in there before. But it broke too easily with different rbac filters.
So these were the edge cases I was curious about when I said:
... and if there are any use cases that aren't described in the PR that some of the lines of code are addressing (
add_joins
for example), then we should document those in this PR and/or in specs.
If it broke when using filters on Service.yaml
, you basically can ignore any gripes I had with this. However, I would like some examples (specs, documentation, and/or PR description update), since I am still unclear if those Rbac filters are use cases relevant to Service.yaml
.
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 think it is necessary for Service.yaml
BUT I need to create a spec to prove it.
I don't know all the parameters necessary to really tweak out rbac. It is possible that the gook I'm trying to avoid is not present for Service
Thanks for keeping me honest here. I really appreciate it.
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, it wasn't that hard to reproduce the problem here. Turns out a simple miq_expression forced the error.
16147bd
to
5a9f8f9
Compare
un WIP: I was able to condense the change in Determining if we "should" optimize the query can be further simplified to just checking Converting the I needed to use |
Trivia: turns out So I changed the code to read We definitely have some duplicate code in the code that handles targets/klass/scope/array/... |
@kbrock is this for hammer? I think so, but want to make sure. Please add the labels if so. This change looks good overall. Do you know what will be opt-ing in via |
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.
Well, I wouldn't say it is "less code"...
it is a lot smaller. and it doesn't feel like a kludge
- @kbrock 2019
But, I think it now proves that the code is as small as we can make it. Ran the specs locally with and without the add_joins
for my own sanity, and I does what I expected.
Thanks for all the work on this!
5a9f8f9
to
610ffe7
Compare
fixed cops |
For queries with virtual_attributes, it can be slow to embed the attributes in the primary query because it runs the attribute's sub query for every row in the base table. So even though you are using limit(20), it runs the virtual attribute subquery for every row in the base table (think 6k times) This is only really an issue on the services page, but other larger tables like vms can benefit from this optimization. This option embeds the table query in an inline view think `select * from (select * from table) as inline_view` This is opt-in behavior, and only the Services pages will use this optimization for now.
610ffe7
to
652260b
Compare
Checked commit kbrock@652260b with ruby 2.3.3, rubocop 0.52.1, haml-lint 0.20.0, and yamllint 1.10.0 |
@Fryguy Are you good with this now? |
Rbac virtual attributes (cherry picked from commit 3dfb0b0) Fixes https://bugzilla.redhat.com/show_bug.cgi?id=1688937
Hammer backport details:
|
@kbrock Please take a look at Travis failure in
|
Overview
When running queries, we are putting more and more virtual attributes into the main query. This transitions us from running N+1 queries from ruby to only running 1. Just running them as subqueries.
Running them as sub queries still runs each of the queries, but it lets us avoid downloading a ton of data to then do a
COUNT
,SUM
, orFIRST
. So if you look at theEXPLAIN
plans, the queries are still happening, but in a much more controlled manner.addresses
Problem
This is a PR/BZ after all. There is a problem.
We are running these sub queries once for every row in the database (6k), not for every row returned (20). Typically, this is a lot faster and still less work than downloading all that data to ruby.
Well it is faster until the number of rows in the base table is sufficiently large, and the virtual attribute subquery is sufficiently slow.
And yes, we found that edge case for the
Service
explorer page.Solution
The solution is to run the subquery once for every row on the screen rather than every row in the base table. To get this, we run the query with the
WHERE
andLIMIT
as an inline view (subquery in theFROM
clause). So the database is running for "every row in the base table", we just pretended like the 20 rows in the result set were "every row in the table."Active record has the
from()
method to allow us to do this pretty easily.Numbers
I was not able to compare the timing of the original query. I needed to pair back to only 1 virtual attribute.
comments
before-7 attrs
after-7 attrs
comments
before-1 attr
after-1 attr
Code
for those following at home, this is how I reproduced it.