Skip to content

✨ Refactor rukpak convert (now with testing!) - #1893

Merged
perdasilva merged 1 commit into
operator-framework:mainfrom
perdasilva:add-render-framework
Apr 28, 2025
Merged

✨ Refactor rukpak convert (now with testing!)#1893
perdasilva merged 1 commit into
operator-framework:mainfrom
perdasilva:add-render-framework

Conversation

@perdasilva

@perdasilvaperdasilva commented Apr 2, 2025

Copy link
Copy Markdown
Contributor

Description

The Convert function in the rukpak/convert package is very simplistic, hard to extend and lacking in testing. This PR adds a bundle rendering framework composed:

  • ResourceGenerator: a function that takes a bundle and produces one or more kubernetes resources
  • BundleRenderer: a struct that orchestrates generators to produce the rendered bundle resources

ResourceGenerators added:

  • BundleDeploymentGenerator: produces appsv1.Deployments from the bundle CSV
  • BundlePermissionsGenerator: produces Roles and RoleBindings from the permissions in the CSV
  • BundleClusterPermissionsGenerator: produces ClusterRoles and ClusterRoleBindings from the clusterPermissions in the CSV
  • BundleServiceAccountGenerator: produces corev1.ServiceAccount resources from the permissions and clusterPermissions in the CSV
  • BundleCRDGenerator: produces CRDs based on the bundle CRDs
  • BundleResourceGenerator: produces the resources included in the bundle that are not the CSV

Reviewer Checklist

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

@openshift-ciopenshift-ciBot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Apr 2, 2025
@netlify

netlifyBot commented Apr 2, 2025

Copy link
Copy Markdown

Deploy Preview for olmv1 ready!

NameLink
🔨 Latest commitf36e306
🔍 Latest deploy loghttps://app.netlify.com/sites/olmv1/deploys/680f6b247c605200082b4f04
😎 Deploy Previewhttps://deploy-preview-1893--olmv1.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
"csv": "annotation",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I always have to refresh my memory on this question: CSV annotations are copied into the pod annotations, but not the deployment annotations? That may very well be the case, it's just that it never obvious if there is anything that motivates this.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I had the same questions in my mind. This is probably a game of telephone, but I just wanted to make sure we had what we currently have in the convert function. I don't know the motivation behind this =S

@perdasilva
perdasilvaforce-pushed the add-render-framework branch 2 times, most recently from 688bd22 to 7aaadf9CompareApril 3, 2025 13:12
@perdasilva
perdasilva marked this pull request as ready for review April 3, 2025 13:14
@perdasilva
perdasilva requested a review from a team as a code ownerApril 3, 2025 13:14
@perdasilvaperdasilva changed the title [WIP] ✨ add render package[WIP] ✨ Add rukpak/convert/render packageApr 3, 2025
@perdasilvaperdasilva changed the title [WIP] ✨ Add rukpak/convert/render package✨ Add rukpak/convert/render packageApr 3, 2025
@openshift-ciopenshift-ciBot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Apr 3, 2025
@codecov

codecovBot commented Apr 3, 2025

Copy link
Copy Markdown

Codecov Report

Attention: Patch coverage is 92.43697% with 27 lines in your changes missing coverage. Please review.

Project coverage is 66.37%. Comparing base (a7ab445) to head (f36e306).
Report is 1 commits behind head on main.

Files with missing linesPatch %Lines
...-controller/rukpak/render/generators/generators.go93.38%6 Missing and 3 partials ⚠️
...r-controller/rukpak/render/generators/resources.go93.49%8 Missing ⚠️
...ternal/operator-controller/rukpak/render/render.go87.50%4 Missing and 2 partials ⚠️
...nternal/operator-controller/rukpak/util/testing.go88.57%4 Missing ⚠️
Additional details and impacted files
@@ Coverage Diff @@## main #1893 +/- ##
==========================================
+ Coverage 65.87% 66.37% +0.50% 
==========================================
Files 71 75 +4 Lines 6189 6326 +137 ==========================================
+ Hits 4077 4199 +122 - Misses 1850 1864 +14 - Partials 262 263 +1 
FlagCoverage Δ
e2e45.25% <61.34%> (+0.13%)⬆️
unit55.91% <91.03%> (+0.60%)⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment threadinternal/operator-controller/rukpak/convert/render/generate.go Outdated
Comment threadinternal/operator-controller/rukpak/convert/render/generate.go Outdated
@perdasilva
perdasilvaforce-pushed the add-render-framework branch from 7aaadf9 to 0589b6cCompareApril 4, 2025 10:08
@perdasilvaperdasilva changed the title ✨ Add rukpak/convert/render package✨ Refactor rukpak convert into a renderer (with testing!)Apr 4, 2025
@perdasilvaperdasilva changed the title ✨ Refactor rukpak convert into a renderer (with testing!)✨ Refactor rukpak convert (now with testing!)Apr 4, 2025
@perdasilva
perdasilvaforce-pushed the add-render-framework branch 3 times, most recently from 3ac6014 to 7b25a77CompareApril 4, 2025 15:16
@openshift-merge-robotopenshift-merge-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Apr 6, 2025
@perdasilva
perdasilvaforce-pushed the add-render-framework branch from 7b25a77 to 3adc8ddCompareApril 7, 2025 06:28
@openshift-merge-robotopenshift-merge-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Apr 7, 2025

@anik120anik120 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The test cases are chef's kiss

Comment threadinternal/operator-controller/rukpak/convert/generate.go Outdated
@openshift-merge-robotopenshift-merge-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Apr 8, 2025
@perdasilva
perdasilvaforce-pushed the add-render-framework branch from 3adc8dd to d6858e6CompareApril 8, 2025 09:33
@openshift-merge-robotopenshift-merge-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Apr 8, 2025
@perdasilva
perdasilvaforce-pushed the add-render-framework branch 4 times, most recently from eea8fba to 9585806CompareApril 8, 2025 12:18
@perdasilva
perdasilvaforce-pushed the add-render-framework branch 4 times, most recently from f63c8e6 to 744a674CompareApril 9, 2025 14:00

@anik120anik120 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I realized that while testing is being added to test the convert functionalities, the testing is exclusively on the new components (ResourceGenerators, BundleRenders etc).

Maybe a way to break this PR would have to be add tests in the first PR that tests the conversion exhaustively.

Then the new PR would refractor and add the new components, with minimal changes to the tests, while the pieces being called would obviously need to change, the behavior would not change in the existing tests.

That way we can be sure that we're not regressing on any functionality while refactoring and introducing the new components.

Comment on lines +215 to 230
var PlainConverter = Converter{
BundleRenderer: render.BundleRenderer{
BundleValidator: validators.RegistryV1BundleValidator,
ResourceGenerators: []render.ResourceGenerator{
generators.BundleCSVRBACResourceGenerator.ResourceGenerator(),
generators.BundleCRDGenerator,
generators.BundleAdditionalResourcesGenerator,
generators.BundleCSVDeploymentGenerator,
},
},
}

type Converter struct {
BundleValidator BundleValidator
render.BundleRenderer
}

@anik120anik120Apr 9, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This feels a bit weird to me. I get the feeling that these changes are incorporating something new, to something existing. But do we have to keep the existing layout?

What are your thoughts on the following:

var PlainConverter = render.BundleRenderer func (r BundleRenderer) Convert(rv1 RegistryV1, installNamespace string, targetNamespaces []string) (*Plain, error) {
.
.
}
PlainConverter.Convert(...)

And then take that one step further:

var RegistryV1ToPlainBundleRenderer = render.BundleRenderer RegistryV1ToPlainBundleRenderer.Convert(...)
func (r BundleRenderer) Convert(rv1 RegistryV1, installNamespace string, targetNamespaces []string) (*Plain, error) {
.
.
}

ie get rid of Converter totally, with the Convert function defined in the render package as a BundleRenderer component.

Isn't the PR essentially replacing Converter with Renderer?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Eventually I'd like to do away with the convert package all together in favor of the renderer. I just didn't want to also carry over all the logic checking the install and target namespaces, and validating install modes, and conversion support, etc. to the renderer (yet). In hindsight, I wish I had hidden everything inside the Convert() function for now to also reduce touch points with other parts of the code (leaving that for later).

I don't quite get the code suggesting. Seems its to rename PlainConverter to RegistryV1ToPlainBundleRenderer?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Eventually I'd like to do away with the convert package all together in favor of the renderer.

I was talking about this - getting rid of the Converter in favor of using render.BundleRenderer directly, instead of wrapping renderer.BundleRender inside a Converter and then using Converter. That'd mean

package render type BundleRenderer struct{
.
.
}
func (r BundleRenderer) Convert (rv1 RegistryV1, installNamespace string, targetNamespaces []string) (*Plain, error)}
.
.
}

would have to be defined.

But that would also mean

carry over all the logic checking the install and target namespaces, and validating install modes, and conversion support, etc. to the renderer (yet)

has to be done. It didn't look like this'd be too much of a heavy lift to me, but maybe I'm missing something

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

it's not about the effort, it's just about the scope of the change in the PR - and I'd also like to consider what to do with the Helm converter as part of this, and that will definitely influence everything up from that. I'd also like to think over whether that logic should live in the renderer itself or outside of it, or just in the Plain renderer, etc. It might have made things tidier, but I don't think it's necessary for this PR (though I do think its necessary).

@perdasilva

Copy link
Copy Markdown
ContributorAuthor

I realized that while testing is being added to test the convert functionalities, the testing is exclusively on the new components (ResourceGenerators, BundleRenders etc).

Maybe a way to break this PR would have to be add tests in the first PR that tests the conversion exhaustively.

Then the new PR would refractor and add the new components, with minimal changes to the tests, while the pieces being called would obviously need to change, the behavior would not change in the existing tests.

That way we can be sure that we're not regressing on any functionality while refactoring and introducing the new components.

I started with that. But, because the convert function was so monolithic it meant each test would need to set itself up in a way that it can get through to the logic it wants to test, e.g. the csv would need to support AllNamespaces (which is not super important when you want to check that strategy deployment spec is properly converted to a deployment resource, etc. It also meant that, for the permissions tests, the resulting resource names would carry the hash (which is also not so important when you want to check that spec.permissions -> rbav1.Role and rbacv1.RoleBinding). Also, the convert function returns all generated resources, which means we need to try and find the expected ones in the pile. Not the end of the world, but adds complexity to write and in case of failure. So, I pivoted away towards adding the regression tests (#1895) , which, tbf might not be as thorough as unit testing, I thought it still gave me enough of an indication that everything would be ok after refactor. Having said all that, the generator unit tests were portable enough that I brought them over to the current rukpak/convert package (#1912). Maybe as we move through, their short livedness will outweigh their drawbacks and give us extra security. Wdyt?

@anik120

Copy link
Copy Markdown
Member

I started with that. But, because the convert function was so monolithic it meant each test would need to set itself up in a way that it can get through to the logic it wants to test..... So, I pivoted away towards adding the regression tests (#1895) , which, tbf might not be as thorough as unit testing, I thought it still gave me enough of an indication that everything would be ok after refactor. Having said all that, the generator unit tests were portable enough that I brought them over to the current rukpak/convert package (#1912). Maybe as we move through, their short livedness will outweigh their drawbacks and give us extra security. Wdyt?

That makes a lot of sense thank you for the context!! #1895 being present basically addresses the concern I was brining up, albeit in a different form - which makes sense given the challenges you described 👍🏽

// WithSubjects applies rbac subjects to ClusterRoleBinding and RoleBinding resources
func WithSubjects(subjects ...rbacv1.Subject) func(client.Object) {
return func(obj client.Object) {
switch o := obj.(type) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Add a default case to panic if the type doesn't support setting a subject?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Same question for the other With* funcs.

joelanford
joelanford previously approved these changes Apr 25, 2025

@joelanfordjoelanford left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks great! One nit is all.

@perdasilva
perdasilvaforce-pushed the add-render-framework branch from ea23274 to 30ad5f6CompareApril 28, 2025 11:43
Signed-off-by: Per Goncalves da Silva <pegoncal@redhat.com>
@perdasilva
perdasilva added this pull request to the merge queue Apr 28, 2025
Merged via the queue into operator-framework:main with commit 8b6d7acApr 28, 2025
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@perdasilva@anik120@joelanford@thetechnick@openshift-merge-robot