Skip to content

Conversation

@perdasilva
Copy link
Contributor

@perdasilva perdasilva commented Jan 20, 2026

Description

Adds initial uninstall feature e2e tests:

  • cluster extension deletion removes bundle resources from the cluster
  • cluster extension deletion after service account deletion removed bundle resources from the cluster

Note: this PR also does some low level variable name refactoring to improve readability

Reviewer Checklist

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

Copilot AI review requested due to automatic review settings January 20, 2026 17:16
@openshift-ci openshift-ci bot requested review from bentito and pedjak January 20, 2026 17:16
@netlify
Copy link

netlify bot commented Jan 20, 2026

Deploy Preview for olmv1 ready!

Name Link
🔨 Latest commit babfc30
🔍 Latest deploy log https://app.netlify.com/projects/olmv1/deploys/6977bb52f21e8b00086be232
😎 Deploy Preview https://deploy-preview-2453--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 project configuration.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds an end-to-end test for verifying that bundle resources are properly removed when a ClusterExtension is uninstalled. The test uses the Gherkin BDD format to define the uninstall scenario.

Changes:

  • Added new uninstall.feature file with a test scenario that verifies resource cleanup after ClusterExtension deletion

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@codecov
Copy link

codecov bot commented Jan 20, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 69.50%. Comparing base (8167ff8) to head (876fc6b).
⚠️ Report is 4 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff            @@
##             main    #2453    +/-   ##
========================================
  Coverage   69.49%   69.50%            
========================================
  Files         101      101            
  Lines        7754     7891   +137     
========================================
+ Hits         5389     5485    +96     
- Misses       1930     1968    +38     
- Partials      435      438     +3     
Flag Coverage Δ
e2e 46.94% <ø> (+0.83%) ⬆️
experimental-e2e 13.71% <ø> (+0.25%) ⬆️
unit 57.07% <ø> (-0.11%) ⬇️

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.

@perdasilva perdasilva marked this pull request as draft January 20, 2026 18:27
@openshift-ci openshift-ci bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jan 20, 2026
@perdasilva perdasilva marked this pull request as ready for review January 21, 2026 07:28
Copilot AI review requested due to automatic review settings January 21, 2026 07:28
@openshift-ci openshift-ci bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jan 21, 2026
@openshift-ci openshift-ci bot requested review from grokspawn and trgeiger January 21, 2026 07:28
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@perdasilva perdasilva changed the title 🌱 Add unintall feature test 🌱 Add uninstall feature test Jan 21, 2026
Copy link
Contributor

@camilamacedo86 camilamacedo86 left a comment

Choose a reason for hiding this comment

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

Just I nit otherwise
/approved

@perdasilva
Copy link
Contributor Author

/hold to add another test

@openshift-ci openshift-ci bot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Jan 21, 2026
Copilot AI review requested due to automatic review settings January 21, 2026 14:08
@perdasilva
Copy link
Contributor Author

/unhold

@openshift-ci openshift-ci bot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Jan 21, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

And resource "clusterrole/testoperator.v1.2.-37mym6pni2xxmai9n7fmhtbn9i348lx7o619rmf3ypio" is eventually not found
And resource "clusterrole/testoperator.v1.2.0-t88i5epjh8oxp4klplhjyrsekwcp92b27w03ayr1ku5" is eventually not found
And resource "clusterrolebinding/testoperator.v1.2.-37mym6pni2xxmai9n7fmhtbn9i348lx7o619rmf3ypio" is eventually not found
And resource "clusterrolebinding/testoperator.v1.2.0-t88i5epjh8oxp4klplhjyrsekwcp92b27w03ayr1ku5" is eventually not found No newline at end of file
Copy link
Contributor

@camilamacedo86 camilamacedo86 Jan 21, 2026

Choose a reason for hiding this comment

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

I do not think we can have those fixed. Can we not improve that and search by label something like that?

/approved cancel (due new additionals)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can't see a way around it. If we use a label, all we assert is that there are no clusterroles owned by the ClusterExtension. But, they could still exist on the cluster =/

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This brought up something I hadn't thought about: if the names change, then we'll get a false positive. I've updated the Background to ensure the resources exist with those names.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yep—I don’t think we can do that.

Also, my understanding is that e2e tests should reflect what an end user expects. As a user, I’d expect all owned files to be deleted, while keeping the CRDs to avoid data loss.

Since this is all managed by OLM, do we have any label/annotation we can rely on to identify everything OLM manages for a given CE?

Copilot AI review requested due to automatic review settings January 21, 2026 15:52
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@perdasilva perdasilva force-pushed the uninstall-e2e-test branch 2 times, most recently from 34df40f to 20cf71d Compare January 21, 2026 16:19
Copilot AI review requested due to automatic review settings January 21, 2026 16:19
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copilot AI review requested due to automatic review settings January 21, 2026 16:37
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@@ -0,0 +1,66 @@
Feature: Uninstall ClusterExtension

As an OLM user I would like to uninstall a cluster extension.
Copy link
Contributor

Choose a reason for hiding this comment

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

perhaps we should extend description, stating what is the expected outcome of such operation?

Suggested change
As an OLM user I would like to uninstall a cluster extension.
As an OLM user I would like to uninstall a cluster extension, removing all resources previously installed/updated through the extension

Comment on lines 27 to 33
And bundle "test-operator.1.2.0" is installed in version "1.2.0"
# Ensure the bundle resources exist before initiating the deletion process and checking
# that they no longer exist to avoid false positives (i.e. if they never existed, checking that they don't exist
# will succeed)
And resource "networkpolicy/test-operator-network-policy" exists
And resource "configmap/test-configmap" exists
And resource "deployment/test-operator" exists
Copy link
Contributor

Choose a reason for hiding this comment

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

for better readability and maintainability, I would suggest to:

  • extend ClusterExtension is rolled out step implementation to check if all resources that are listed as a part of extension really exist on the cluster.
  • Instead of listing explicitly we can find it out programmatically by (1) listing all objects stated in revision phases, or (2) listing manifests in Helm release secret (by using helm cli)
  • these resources (GVK + name) can be stored in the test context.

With all these changes, we can collapse above steps and replace them with ClusterExtension is rolled out. It makes the test more readable, because is not in focus of this test.

edit: the comment applies to all lines until the line 40.

And resource "clusterrolebinding/testoperator.v1.2.0-t88i5epjh8oxp4klplhjyrsekwcp92b27w03ayr1ku5" exists

Scenario: Uninstall ClusterExtension
When resource "clusterextension/${NAME}" is removed
Copy link
Contributor

Choose a reason for hiding this comment

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

Reads better if we introduce step ClusterExtension is removed.

And resource "clusterrolebinding/testoperator.v1.2.-37mym6pni2xxmai9n7fmhtbn9i348lx7o619rmf3ypio" exists
And resource "clusterrolebinding/testoperator.v1.2.0-t88i5epjh8oxp4klplhjyrsekwcp92b27w03ayr1ku5" exists

Scenario: Uninstall ClusterExtension
Copy link
Contributor

Choose a reason for hiding this comment

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

Be more verbose, e.g. "Removing ClusterExtension triggers the extension uninstall, removing all installed resources eventually.

Comment on lines 44 to 50
Then resource "networkpolicy/test-operator-network-policy" is eventually not found
And resource "configmap/test-configmap" is eventually not found
And resource "deployment/test-operator" is eventually not found
And resource "clusterrole/testoperator.v1.2.-37mym6pni2xxmai9n7fmhtbn9i348lx7o619rmf3ypio" is eventually not found
And resource "clusterrole/testoperator.v1.2.0-t88i5epjh8oxp4klplhjyrsekwcp92b27w03ayr1ku5" is eventually not found
And resource "clusterrolebinding/testoperator.v1.2.-37mym6pni2xxmai9n7fmhtbn9i348lx7o619rmf3ypio" is eventually not found
And resource "clusterrolebinding/testoperator.v1.2.0-t88i5epjh8oxp4klplhjyrsekwcp92b27w03ayr1ku5" is eventually not found
Copy link
Contributor

Choose a reason for hiding this comment

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

See comments above. We can now introduce a step that reads like:

All resources owned by extension are removed.

Step implementation is going to fetch from the test context all resources (GVK, name) pairs and iterate over them, asserting that they cannot be found in the cluster.

@tmshort
Copy link
Contributor

tmshort commented Jan 23, 2026

/approve

Once @pedjak comments are addressed.

@openshift-ci
Copy link

openshift-ci bot commented Jan 23, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: tmshort

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

@openshift-ci openshift-ci bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jan 23, 2026
Signed-off-by: Per Goncalves da Silva <pegoncal@redhat.com>
Copilot AI review requested due to automatic review settings January 26, 2026 19:06
@openshift-merge-robot openshift-merge-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jan 26, 2026
@openshift-merge-robot
Copy link

PR needs rebase.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


require.Eventually(godog.T(ctx), func() bool {
obj, err := k8sClient("get", kind, name, "-n", sc.namespace, "--ignore-not-found", "-o", "yaml")
return err == nil && obj == ""
Copy link

Copilot AI Jan 26, 2026

Choose a reason for hiding this comment

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

ResourceEventuallyNotFound checks obj == "", but kubectl get ... --ignore-not-found -o yaml can still return whitespace/newlines (or other benign output) on stdout. This can make the step flaky; compare against strings.TrimSpace(obj) == "" instead of a raw empty string check.

Suggested change
return err == nil && obj == ""
return err == nil && strings.TrimSpace(obj) == ""

Copilot uses AI. Check for mistakes.
Comment on lines +941 to +947
out, err := k8sClient("get", "secrets", "-n", "olmv1-system", "-l", fmt.Sprintf("name=%s", extName), "--field-selector", "type=operatorframework.io/index.v1", "-o", "json")
if err != nil {
return nil, err
}
if strings.TrimSpace(out) == "" {
return nil, err
}
Copy link

Copilot AI Jan 26, 2026

Choose a reason for hiding this comment

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

When kubectl get secrets ... returns an empty string, this function returns (nil, err) where err is nil. That propagates a nil Secret to callers and can cause a panic later. Return a non-nil error when no matching release Secret is found.

Copilot uses AI. Check for mistakes.
Comment on lines +949 to +956
var secretList corev1.SecretList
if err = json.Unmarshal([]byte(out), &secretList); err != nil {
return nil, err
}
if len(secretList.Items) != 1 {
return nil, err
}
return &secretList.Items[0], nil
Copy link

Copilot AI Jan 26, 2026

Choose a reason for hiding this comment

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

This assumes exactly one Secret matches the selector, but Helm release storage typically keeps multiple Secrets (history / revisions). As written, len(secretList.Items) != 1 returns (nil, err) where err is nil, and also makes the lookup fail in normal cases. Select the latest deployed revision (e.g., by Helm labels like version) or otherwise disambiguate, and return a real error if the result set is empty/ambiguous.

Copilot uses AI. Check for mistakes.
Comment on lines +961 to +966
func helmReleaseFromSecret(secret *corev1.Secret) (*release.Release, error) {
gzReader, err := gzip.NewReader(strings.NewReader(string(secret.Data["chunk"])))
if err != nil {
return nil, err
}
defer gzReader.Close()
Copy link

Copilot AI Jan 26, 2026

Choose a reason for hiding this comment

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

helmReleaseFromSecret assumes a gzipped JSON-encoded Helm release is stored in secret.Data["chunk"] and reads it via string(...) + strings.NewReader. This is very unlikely to match Helm’s standard release Secret encoding (and will panic if secret is nil). Consider using Helm’s storage/driver decoding logic (or the helm-operator-plugins action client) and validate the expected data key/format; at minimum, guard against secret == nil and missing data keys with a clear error.

Copilot uses AI. Check for mistakes.
Comment on lines +983 to +984
menifests := strings.Split(rel.Manifest, "\n")
for _, manifest := range menifests {
Copy link

Copilot AI Jan 26, 2026

Choose a reason for hiding this comment

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

Typo in variable name: menifests should be manifests.

Suggested change
menifests := strings.Split(rel.Manifest, "\n")
for _, manifest := range menifests {
manifests := strings.Split(rel.Manifest, "\n")
for _, manifest := range manifests {

Copilot uses AI. Check for mistakes.
Comment on lines +981 to +991
func collectHelmReleaseObjects(rel *release.Release) ([]client.Object, error) {
objs := []client.Object{}
menifests := strings.Split(rel.Manifest, "\n")
for _, manifest := range menifests {
if manifest == "" {
continue
}
u := &unstructured.Unstructured{}
if err := yaml.Unmarshal([]byte(manifest), u); err != nil {
return nil, fmt.Errorf("failed to unmarshal manifest: %w", err)
}
Copy link

Copilot AI Jan 26, 2026

Choose a reason for hiding this comment

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

collectHelmReleaseObjects splits rel.Manifest by newline and unmarshals each line independently. This will fail if the manifest contains standard multi-line YAML documents (or if objects aren’t newline-delimited). Prefer using the same manifest parsing approach used elsewhere in the codebase (e.g., internal/operator-controller/rukpak/util.ManifestObjects over the full manifest string), or otherwise split on YAML document boundaries and trim whitespace.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants