Skip to content

✨ Make install hubaddons by helm chart more general#533

Open
qiujian16 wants to merge 1 commit intoopen-cluster-management-io:mainfrom
qiujian16:install-addon-by-helm
Open

✨ Make install hubaddons by helm chart more general#533
qiujian16 wants to merge 1 commit intoopen-cluster-management-io:mainfrom
qiujian16:install-addon-by-helm

Conversation

@qiujian16
Copy link
Member

@qiujian16 qiujian16 commented Jan 30, 2026

Summary

Related issue(s)

Fixes #

Summary by CodeRabbit

  • Refactor

    • Improved add-on installation and configuration with generalized chart handling and consistent namespace behavior
    • Centralized Policy Framework install/uninstall path for cleaner deployments and unified messaging
    • Simplified uninstall flow for add-ons
  • Chores

    • Removed HubAddons field from configuration—update your add-on setup accordingly

@openshift-ci openshift-ci bot requested review from gparvin and mikeshng January 30, 2026 09:51
@qiujian16
Copy link
Member Author

/hold

@coderabbitai
Copy link

coderabbitai bot commented Jan 30, 2026

Warning

Rate limit exceeded

@qiujian16 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 4 minutes and 4 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

Walkthrough

Replaces hard-coded addon identifiers with a public AddonChart map and exported addon name constants; introduces installPolicyAddon/uninstallPolicy flows; removes Values.HubAddons; aggregates install validation errors; adapts Helm client flows to use AddonCharts; updates tests to the new policy-addon-focused workflow.

Changes

Cohort / File(s) Summary
Install logic & public API
pkg/cmd/install/hubaddon/exec.go
Adds AddonChart type and AddonCharts map; exports addon name constants; introduces installPolicyAddon() and refactors install flows to use AddonCharts and aggregated errors; adapts Helm and resource-apply paths.
Install tests
pkg/cmd/install/hubaddon/exec_test.go
Updates tests to remove HubAddons-driven table tests, switch to Namespace/BundleVersion-based Values, and assert per-deployment readiness via Eventually.
Scenario values
pkg/cmd/install/hubaddon/scenario/resources.go
Removes exported field HubAddons []string from Values struct (public API change).
Uninstall logic
pkg/cmd/uninstall/hubaddon/exec.go
Replaces per-addon handling with set-based iteration; adds uninstallPolicy flow; uses AddonCharts for Helm uninstall lookups and simplifies resource deletion and output messaging.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • gparvin
  • mikeshng
  • JustinKuli
🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description contains only the repository template with empty Summary and Related issue(s) sections; no actual implementation details, rationale, or context about the changes are provided. Fill in the Summary section with details about the changes, their purpose, and any breaking changes; include the Related issue(s) link if applicable.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed Title uses a specific feature indicator (✨) and references the main change—generalizing Helm chart installation for hub addons. However, 'more general' is somewhat vague about the specific improvements.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pkg/cmd/install/hubaddon/exec_test.go (1)

42-50: ⚠️ Potential issue | 🟡 Minor

Test may be passing for the wrong reason.

The test description states it validates "not a valid add-on name", but the validate() function in exec.go no longer validates addon names—it only checks that names is non-empty and that the version bundle is valid. This test likely passes because bundleVersion is empty (not set in the Options), causing GetVersionBundle to fail, not because of the invalid addon name.

Consider either:

  1. Updating the test description to accurately reflect what it's testing
  2. Or, if addon name validation is desired, implementing it in validate() using the addonCharts map or scenario.AddonDeploymentFiles
🤖 Fix all issues with AI agents
In `@pkg/cmd/install/hubaddon/exec.go`:
- Line 126: The printed status "Installing built-in %s add-on..."
(fmt.Fprintf(o.Streams.Out, ... , policyFrameworkAddonName)) is emitted after
CRDs/configs/deployments are applied, which is misleading; move that fmt.Fprintf
call to execute before the sequence of Apply calls that apply CRDs, configs, and
deployments (the Apply.../apply functions in this file) so the message appears
when installation begins rather than after completion.
🧹 Nitpick comments (3)
pkg/cmd/install/hubaddon/exec.go (2)

33-51: Unused version field in addonChart struct.

The version field defined on line 37 is never used anywhere in the code. If this is intended for future use, consider adding a comment or TODO. Otherwise, remove it to avoid confusion.

♻️ Proposed fix to remove unused field
 type addonChart struct {
 	chartName   string
 	releaseName string
 	namespace   string
-	version     string
 }

168-176: Fallback chart configuration uses addon name directly.

The fallback for unknown addons (lines 171-175) assumes the chart name and release name match the addon name exactly. This may not always be true for all Helm charts in the OCM repository.

Consider adding a warning or debug log when using the fallback to help users diagnose issues if their addon installation fails due to chart naming mismatches.

♻️ Proposed improvement
 	addonChartToInstall, ok := addonCharts[addon]
 	if !ok {
+		klog.V(2).InfoS("No explicit chart configuration found, using addon name as defaults", "addon", addon)
 		addonChartToInstall = addonChart{
 			chartName:   addon,
 			releaseName: addon,
 			namespace:   o.values.Namespace,
 		}
 	}
pkg/cmd/install/hubaddon/exec_test.go (1)

72-72: Missing In stream in IOStreams.

The Streams field is initialized with Out and ErrOut but not In. While likely not needed for this test, it's good practice to initialize all fields of IOStreams for completeness, especially if the code under test ever reads from stdin.

♻️ Proposed fix
-				Streams: genericiooptions.IOStreams{Out: os.Stdout, ErrOut: os.Stderr},
+				Streams: genericiooptions.IOStreams{In: os.Stdin, Out: os.Stdout, ErrOut: os.Stderr},

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

User-facing message printed after installation completes.

The "Installing built-in..." message is printed after CRDs, configs, and deployments have already been applied (lines 113-124). This is misleading since it suggests the installation is starting when it has already finished. Move this message before the Apply calls for accurate progress feedback.

🛠️ Proposed fix
 func (o *Options) installPolicyAddon() error {
 	if o.values.CreateNamespace {
 		if err := o.createNamespace(); err != nil {
 			return err
 		}
 	}

+	fmt.Fprintf(o.Streams.Out, "Installing built-in %s add-on to the Hub cluster...\n", policyFrameworkAddonName)
+
 	r := reader.NewResourceReader(o.ClusteradmFlags.KubectlFactory, o.ClusteradmFlags.DryRun, o.Streams)
 	files, ok := scenario.AddonDeploymentFiles[policyFrameworkAddonName]
 	if !ok {
 		return fmt.Errorf("no policy framework addon")
 	}
 	err := r.Apply(scenario.Files, o.values, files.CRDFiles...)
 	if err != nil {
 		return fmt.Errorf("Error deploying %s CRDs: %w", policyFrameworkAddonName, err)
 	}
 	err = r.Apply(scenario.Files, o.values, files.ConfigFiles...)
 	if err != nil {
 		return fmt.Errorf("Error deploying %s dependencies: %w", policyFrameworkAddonName, err)
 	}
 	err = r.Apply(scenario.Files, o.values, files.DeploymentFiles...)
 	if err != nil {
 		return fmt.Errorf("Error deploying %s deployments: %w", policyFrameworkAddonName, err)
 	}

-	fmt.Fprintf(o.Streams.Out, "Installing built-in %s add-on to the Hub cluster...\n", policyFrameworkAddonName)
-
 	if len(o.outputFile) > 0 {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fmt.Fprintf(o.Streams.Out, "Installing built-in %s add-on to the Hub cluster...\n", policyFrameworkAddonName)
func (o *Options) installPolicyAddon() error {
if o.values.CreateNamespace {
if err := o.createNamespace(); err != nil {
return err
}
}
fmt.Fprintf(o.Streams.Out, "Installing built-in %s add-on to the Hub cluster...\n", policyFrameworkAddonName)
r := reader.NewResourceReader(o.ClusteradmFlags.KubectlFactory, o.ClusteradmFlags.DryRun, o.Streams)
files, ok := scenario.AddonDeploymentFiles[policyFrameworkAddonName]
if !ok {
return fmt.Errorf("no policy framework addon")
}
err := r.Apply(scenario.Files, o.values, files.CRDFiles...)
if err != nil {
return fmt.Errorf("Error deploying %s CRDs: %w", policyFrameworkAddonName, err)
}
err = r.Apply(scenario.Files, o.values, files.ConfigFiles...)
if err != nil {
return fmt.Errorf("Error deploying %s dependencies: %w", policyFrameworkAddonName, err)
}
err = r.Apply(scenario.Files, o.values, files.DeploymentFiles...)
if err != nil {
return fmt.Errorf("Error deploying %s deployments: %w", policyFrameworkAddonName, err)
}
if len(o.outputFile) > 0 {
🤖 Prompt for AI Agents
In `@pkg/cmd/install/hubaddon/exec.go` at line 126, The printed status "Installing
built-in %s add-on..." (fmt.Fprintf(o.Streams.Out, ... ,
policyFrameworkAddonName)) is emitted after CRDs/configs/deployments are
applied, which is misleading; move that fmt.Fprintf call to execute before the
sequence of Apply calls that apply CRDs, configs, and deployments (the
Apply.../apply functions in this file) so the message appears when installation
begins rather than after completion.

@qiujian16 qiujian16 mentioned this pull request Jan 31, 2026
@qiujian16 qiujian16 force-pushed the install-addon-by-helm branch from cb11547 to 69f464b Compare February 4, 2026 09:01
Signed-off-by: Jian Qiu <jqiu@redhat.com>
@qiujian16 qiujian16 force-pushed the install-addon-by-helm branch from 69f464b to 8b7bda1 Compare February 4, 2026 09:08
@openshift-ci
Copy link

openshift-ci bot commented Feb 4, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: qiujian16

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pkg/cmd/uninstall/hubaddon/exec.go (1)

4-49: ⚠️ Potential issue | 🟠 Major

Only the first addon is uninstalled (set order is nondeterministic).

The loop returns on the first element, so additional addons are skipped and the selection depends on set iteration order. Iterate all addons and aggregate errors (similar to install).

🛠️ Proposed fix
 import (
 	"fmt"
+	utilerrors "k8s.io/apimachinery/pkg/util/errors"
 	"k8s.io/apimachinery/pkg/util/sets"
 	"strings"
@@
 func (o *Options) run() error {
 	addons := sets.New[string](strings.Split(o.names, ",")...)
 	if len(addons) == 0 {
 		return nil
 	}
-	for a := range addons {
-		if a == clusteradmhubaddoninstall.PolicyFrameworkAddonName {
-			return o.uninstallPolicy()
-		}
-		return o.runWithHelmClient(a)
-	}
-
-	return o.uninstallPolicy()
+	var errs []error
+	for a := range addons {
+		if a == clusteradmhubaddoninstall.PolicyFrameworkAddonName {
+			if err := o.uninstallPolicy(); err != nil {
+				errs = append(errs, err)
+			}
+			continue
+		}
+		if err := o.runWithHelmClient(a); err != nil {
+			errs = append(errs, err)
+		}
+	}
+	return utilerrors.NewAggregate(errs)
 }
🤖 Fix all issues with AI agents
In `@pkg/cmd/install/hubaddon/exec_test.go`:
- Line 23: The test is expecting validate() to reject invalidAddon
("no-such-addon") but Options.validate now only checks non-empty names and
bundle version parsing; either update the test to match the new behavior by
removing the expectation of an error for invalidAddon (or asserting that
validate() succeeds for that input), or reintroduce addon-name validation inside
Options.validate (or a helper it calls) to explicitly check the name against the
canonical AddonCharts list and any policy rules before returning; locate the
test's use of invalidAddon in exec_test.go and the Options.validate
implementation to apply the corresponding change so the test and validate()
behavior stay consistent.
- Around line 78-88: The readiness check currently compares
appDeployment.Status.AvailableReplicas to appDeployment.Status.Replicas which
can be lower than the desired replica count; update the gomega.Eventually
closure that iterates policyAddonDeployments (the
kubeClient.AppsV1().Deployments(...).Get call) to use the desired replica count
from appDeployment.Spec.Replicas (treat nil as default 1 or 0 per your
convention) as the expected value instead of Status.Replicas so the test only
passes when AvailableReplicas equals the intended Spec.Replicas.

In `@pkg/cmd/uninstall/hubaddon/exec.go`:
- Around line 61-63: The code currently ignores errors from
version.GetVersionBundle when setting o.values.BundleVersion; instead call
version.GetVersionBundle("default", "") and check the returned error, returning
it (or wrapping it) from the enclosing function rather than discarding it so
uninstall does not proceed with an invalid BundleVersion; update the logic
around o.values.BundleVersion assignment in exec.go to handle and propagate the
error from GetVersionBundle.
- Around line 81-90: The uninstall always sets Helm namespace to
o.values.Namespace causing releases in addon-specific namespaces to be missed;
update the code around addonChart lookup (AddonCharts and addonChart) to choose
the namespace: use addonChart.Namespace when it is non-empty, otherwise fall
back to o.values.Namespace, then call o.Helm.WithNamespace(chosenNamespace)
before o.Helm.UninstallRelease(addonChart.ReleaseName); ensure any default
AddonChart created also allows its Namespace to be empty so the fallback works.

Comment on lines +78 to +88
for _, deployment := range policyAddonDeployments {
gomega.Eventually(func() (bool, error) {
appDeployment, err := kubeClient.AppsV1().Deployments(ocmNamespace).Get(context.Background(), deployment, metav1.GetOptions{})
if err != nil {
return false, err
}

availableReplicas := appDeployment.Status.AvailableReplicas
expectedReplicas := appDeployment.Status.Replicas
return availableReplicas == expectedReplicas, nil
}, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue(), deployment+" deployment should be ready")
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Readiness check can pass before desired replicas are reached.

Status.Replicas can be less than desired; using it can yield a false positive when AvailableReplicas == Status.Replicas but Spec.Replicas is higher. Use Spec.Replicas (with nil default) as the expected count.

🛠️ Proposed fix
-					expectedReplicas := appDeployment.Status.Replicas
-					return availableReplicas == expectedReplicas, nil
+					expectedReplicas := int32(1)
+					if appDeployment.Spec.Replicas != nil {
+						expectedReplicas = *appDeployment.Spec.Replicas
+					}
+					return availableReplicas == expectedReplicas, nil
🤖 Prompt for AI Agents
In `@pkg/cmd/install/hubaddon/exec_test.go` around lines 78 - 88, The readiness
check currently compares appDeployment.Status.AvailableReplicas to
appDeployment.Status.Replicas which can be lower than the desired replica count;
update the gomega.Eventually closure that iterates policyAddonDeployments (the
kubeClient.AppsV1().Deployments(...).Get call) to use the desired replica count
from appDeployment.Spec.Replicas (treat nil as default 1 or 0 per your
convention) as the expected value instead of Status.Replicas so the test only
passes when AvailableReplicas equals the intended Spec.Replicas.

Comment on lines +61 to +63
// this needs to be set to render the manifests, but the version value
// does not matter.
o.values.BundleVersion, _ = version.GetVersionBundle("default", "")
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Don’t ignore GetVersionBundle errors.

If the default bundle cannot be resolved, uninstall proceeds with an invalid BundleVersion. Return the error instead.

🛠️ Proposed fix
-	o.values.BundleVersion, _ = version.GetVersionBundle("default", "")
+	bundle, err := version.GetVersionBundle("default", "")
+	if err != nil {
+		return err
+	}
+	o.values.BundleVersion = bundle
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// this needs to be set to render the manifests, but the version value
// does not matter.
o.values.BundleVersion, _ = version.GetVersionBundle("default", "")
// this needs to be set to render the manifests, but the version value
// does not matter.
bundle, err := version.GetVersionBundle("default", "")
if err != nil {
return err
}
o.values.BundleVersion = bundle
🤖 Prompt for AI Agents
In `@pkg/cmd/uninstall/hubaddon/exec.go` around lines 61 - 63, The code currently
ignores errors from version.GetVersionBundle when setting
o.values.BundleVersion; instead call version.GetVersionBundle("default", "") and
check the returned error, returning it (or wrapping it) from the enclosing
function rather than discarding it so uninstall does not proceed with an invalid
BundleVersion; update the logic around o.values.BundleVersion assignment in
exec.go to handle and propagate the error from GetVersionBundle.

Copy link
Member

@mikeshng mikeshng left a comment

Choose a reason for hiding this comment

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

The Argo CD related changes look good to me.
I will leave the lgtm to the policy experts.

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.

2 participants

Comments