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

Makes OLMVariableSource responsible for fetching #245

Merged
merged 1 commit into from
Jun 8, 2023

Conversation

m1kola
Copy link
Member

@m1kola m1kola commented Jun 1, 2023

Description

OLMVariableSource now contains the client and makes requests to get available operators.

Doing this:

  • Makes OperatorResolver wrapper around deppy solver unnecessary: we can use solver.DeppySolver directly in the controller. I kept it for now, but I think we can remove it as a follow up and replaced by solver.DeppySolver directly.
  • Makes it easier to implement Dependency Library + CLI #206 since OperatorResolver no longer contains logic (it does not instantiate variable sources and underlying solver in the Resolve method). But further refactoring still required in order to achieve the above task (e.g. need to get rid of this)

Reviewer Checklist

  • API Go Documentation
  • Tests: Unit Tests (and E2E Tests, if appropriate)
  • Comprehensive Commit Messages
  • Links to related GitHub Issue(s)

@@ -109,15 +130,17 @@ var _ = Describe("OLMVariableSource", func() {
out = append(out, variable.BundleEntity().Entity)
}
return out
}, Equal([]*input.Entity{
}, ConsistOf([]*input.Entity{
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 believe the order of variables returned from olmVariableSource.GetVariables is not important here.
Since it is now using a client to fetch operators - order is different now and tests were relying on order.

Copy link
Member

Choose a reason for hiding this comment

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

This sounds like an important question to resolve at the public-facing level - if the order is not guaranteed, it should be noted in the API docs. If it is, a simple sort-in-place can be added.

Copy link
Member Author

Choose a reason for hiding this comment

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

This sounds like an important question to resolve at the public-facing level - if the order is not guaranteed, it should be noted in the API docs.

We are not defining an API here - we are implementing a contract/interface required by Deppy. Solver will be calling GetVariables and as far as I see it doesn't require variable s to be sorted in a specific way.

https://github.com/operator-framework/deppy/blob/9a7655cd364b3900d394f81a752731200e2d01a4/pkg/deppy/input/variable_source.go#L9-L12

IMO nether sorting variables nor documenting ordering on the operator-controller side is necessary.

Copy link
Member Author

Choose a reason for hiding this comment

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

Solver will be calling GetVariables and as far as I see it doesn't require variable s to be sorted in a specific way.

Want to clarify: there are some places where the order is very important for the resolution process. For example, we want to select latest possible version for the solution.

But I think here it is not important. However thinking about debuggability - it still might be a good idea to have some stable order.

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 think I was partially wrong here:

olmVariableSource.GetVariables now returns in different order. This is mostly due to a fake client: sigs.k8s.io/controller-runtime/pkg/client/fake doesn't guarantee stable order.

I looked into this a bit more. It looks like the fake client does not guarantee order (at least I do not see anything about this in docs), but de facto it does sorting (we hit this code eventually).

So in the test we add prometheus and then packageA into the fake, but when GetVariables calls the client - it returns packageA first and prometheus because the result list gets sorted.

Our options here:

  • Change ordering of the expected results taking undocumented sorting of fake client into account. This will make the diff minimal. But I think this is not ideal - it will lead to a hard to understand failure, if underlying implementation of the fake client changes.
  • Do sorting in GetVariables after calling the client. This is only required for making the test simplier. I think it is not right to introduce sorting in the code which we test just to make the test code a little bit simplier.
  • Change tests (what we currently have in this PR) to make sure that we do not rely on order provided by the fake client. I think this is the best approach given that we do not need to guarantee order from GetVariables.
  • Create a fake client which maintains order of objects provided in the constructor when returning a List result. Not sure this has any benefit: we will have to introduce extra testing code to avoid changing existing testing code (assertions).

However thinking about debuggability - it still might be a good idea to have some stable order.

Since we now know that fake client returns in deterministic order (not documented, but still) - I think there is little to no benefit in sorting.

Copy link
Member

Choose a reason for hiding this comment

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

If sort order is immaterial except for testing, I agree that your third option is the best.

Copy link
Member

@stevekuznetsov stevekuznetsov left a comment

Choose a reason for hiding this comment

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

I'm not super-familiar with all the internals here but the purpose of this refactor looks great!

internal/controllers/operator_controller_test.go Outdated Show resolved Hide resolved
internal/resolution/resolver.go Outdated Show resolved Hide resolved
internal/resolution/resolver.go Outdated Show resolved Hide resolved
internal/resolution/resolver_test.go Outdated Show resolved Hide resolved
@@ -109,15 +130,17 @@ var _ = Describe("OLMVariableSource", func() {
out = append(out, variable.BundleEntity().Entity)
}
return out
}, Equal([]*input.Entity{
}, ConsistOf([]*input.Entity{
Copy link
Member

Choose a reason for hiding this comment

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

This sounds like an important question to resolve at the public-facing level - if the order is not guaranteed, it should be noted in the API docs. If it is, a simple sort-in-place can be added.

@m1kola m1kola mentioned this pull request Jun 1, 2023
4 tasks
@openshift-merge-robot openshift-merge-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jun 2, 2023
@openshift-merge-robot openshift-merge-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jun 2, 2023
`OLMVariableSource` now contains the client and makes requests
to get available operators.

Signed-off-by: Mikalai Radchuk <mradchuk@redhat.com>
Copy link
Member

@varshaprasad96 varshaprasad96 left a comment

Choose a reason for hiding this comment

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

/lgtm

The changes look good to me. But I'm curious about the extensibility of variable source. Previously, since we had a wrapper around Deppy's Resolver, we could technically pass multiple entity sources for the resolution. Ie, in here, the OperatorResolver struct could contain multiple entity Sources, and the resolve method could accordingly transform them into variableSources. Now looking at it, I realize that we are restricting the resolver to fetch just one variable and entity source.

The other aspect which seems evident now, is the need for entitySource [issue]. EntitySource seems to be getting transformed to variable source with GetVariables in Resolve. This means there is technically no need for both of them to be passed. This has been discussed before but with this change it seems more evident :)

@openshift-ci openshift-ci bot added the lgtm Indicates that a PR is ready to be merged. label Jun 8, 2023
@m1kola
Copy link
Member Author

m1kola commented Jun 8, 2023

@varshaprasad96 I think a lot of this will change soon-ish. We need to agree on the method of building problem for the solver. @perdasilva presented an RFC on this topic during the recent community meeting.

For now I'm trying to work with what we have today. For example in #246 I created a couple of composite variable sources to be able to combine variable sources (see internal/resolution/variable_sources/olm/composite.go here and internal/resolution/variable_sources/olm/olm.go here for how it used). But I expect this to be replaced eventually with different method of building the resolution problem.

@m1kola m1kola merged commit b418973 into operator-framework:main Jun 8, 2023
5 checks passed
@m1kola m1kola deleted the variable_source_cleanup branch June 8, 2023 15:08
@varshaprasad96
Copy link
Member

varshaprasad96 commented Jun 8, 2023

@m1kola that's fair. The accumulator perspective which I was thinking is similar to as you mentioned here. Which is why I was curious on whether it would make sense to move it to top level and extend the possibility of having multiple variable sources directly. But agreed, since this is a changing API with new architectures, most of this thought might look differently in future.

@ankitathomas ankitathomas mentioned this pull request Jun 15, 2023
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
lgtm Indicates that a PR is ready to be merged.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants