Skip to content

Conversation

@JianLi-RH
Copy link
Contributor

@JianLi-RH JianLi-RH commented Oct 22, 2025

In this PR, I finished 2 things:

  1. MustGetKubeClient() function helps us create an Clientset instance which can be used to connect to cluster.
  2. Update the README.md file, we can follow it to create our e2e test cases.

/cc @wking @DavidHurta @PratikMahajan @hongkailiu @jhou1 @dis016 @jiajliu

@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 Oct 22, 2025
@JianLi-RH JianLi-RH force-pushed the implement_client_oc branch 4 times, most recently from a6a8ada to 37caff4 Compare October 23, 2025 07:39
@JianLi-RH JianLi-RH changed the title [WIP] Create packages for connecting to a cluster [WIP] OTA-1605 Create e2e test in CVO repo Oct 23, 2025
@JianLi-RH JianLi-RH force-pushed the implement_client_oc branch 4 times, most recently from a79646a to d944000 Compare October 23, 2025 09:32
@DavidHurta
Copy link
Contributor

Please note that @petr-muller is no longer an active reviewer or approver in the CVO repository. You can refrain from directly pinging him on usual PRs where the expertise of the active folks should be sufficient. He is an "emeritus" approver.

What's an emeritus approver?

GitHub usernames listed under the emeritus_approvers key can no longer approve code (use the /approve command) and will be ignored by prow for assignment. However, it can still be referenced by a person looking at the OWNERS file for a possible second or more informed opinion.

@JianLi-RH JianLi-RH force-pushed the implement_client_oc branch from d944000 to 067cd4b Compare October 24, 2025 07:45
@JianLi-RH JianLi-RH changed the title [WIP] OTA-1605 Create e2e test in CVO repo [WIP] NO-ISSUE: OTA-1605 Create e2e test in CVO repo Oct 24, 2025
@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Oct 24, 2025
@openshift-ci-robot
Copy link
Contributor

@JianLi-RH: This pull request explicitly references no jira issue.

In response to this:

In this PR, finished first e2e test case. Related case can be found in: https://polarion.engineering.redhat.com/polarion/#/project/OSE/workitem?id=OCP-42543

Tested it locally:

[jianl@jianl-thinkpadt14gen4 cvo]$ ginkgo --label-filter="42543"
Running Suite: CVO Suite - /home/jianl/1_code/cluster-version-operator/test/cvo
===============================================================================
Random Seed: 1761205561

Will run 1 of 1 specs
•

Ran 1 of 1 Specs in 1.585 seconds
SUCCESS! -- 1 Passed | 0 Failed | 0 Pending | 0 Skipped
PASS

Ginkgo ran 1 suite in 3.310067262s
Test Suite Passed
[jianl@jianl-thinkpadt14gen4 cvo]$ 

Here is the old case in openshift-tests-private: https://github.com/openshift/openshift-tests-private/blob/f1f32ff1e9eeef4cb2cb4ae6549daa9306c6616a/test/extended/ota/cvo/cvo.go#L716-L759

There is a disadvantage here when I use client-go, it seems client-go does not support all Openshift features, for example it could not extract all manifest and it although support methods to get all resource types but it could not use these types to get resources. So in these PR I don't check all manifests but check some special objects.

Another work we need to do is improve the make update command to let it can embed all tests into binary.

/cc @petr-muller @DavidHurta @hongkailiu @wking @jhou1 @dis016 @jiajliu

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 openshift-eng/jira-lifecycle-plugin repository.

@JianLi-RH
Copy link
Contributor Author

Tested on my local machine:

[jianl@jianl-thinkpadt14gen4 cluster-version-operator]$ make update
hack/build-go.sh
Using version from git...
Building binaries into _output/linux/amd64
Building github.com/openshift/cluster-version-operator cluster-version-operator-tests binary (v1.0.0-1482-gd9440005-dirty)
Compressing the cluster-version-operator-tests binary
Building github.com/openshift/cluster-version-operator cluster-version-operator binary (v1.0.0-1482-gd9440005-dirty)
hack/update-test-metadata.sh
Using version from git...
successfully updated metadata
[jianl@jianl-thinkpadt14gen4 cluster-version-operator]$ _output/linux/amd64/cluster-version-operator-tests list
[
  {
    "name": "[Jira:Cluster Version Operator] cluster-version-operator-tests Author:jianl-High-42543-the removed resources are not created in a fresh installed cluster",
    "labels": {
      "42543": {},
      "High": {},
      "cvo": {}
    },
    "resources": {
      "isolation": {}
    },
    "source": "openshift:payload:cluster-version-operator",
    "lifecycle": "blocking",
    "environmentSelector": {}
  }
]
[jianl@jianl-thinkpadt14gen4 cluster-version-operator]$

Run the case:

[jianl@jianl-thinkpadt14gen4 cluster-version-operator]$ _output/linux/amd64/cluster-version-operator-tests list | jq '.[] | select(.name | contains("42543")) | .name' | xargs _output/linux/amd64/cluster-version-operator-tests run-test
  Running Suite:  - /home/jianl/1_code/cluster-version-operator
  =============================================================
  Random Seed: 1761292866 - will randomize all specs

  Will run 1 of 1 specs
  ------------------------------
  [Jira:Cluster Version Operator] cluster-version-operator-tests Author:jianl-High-42543-the removed resources are not created in a fresh installed cluster [cvo, High, 42543]
  /home/jianl/1_code/cluster-version-operator/test/cvo/cvo.go:22
    STEP: Validate resource with 'release.openshift.io/delete: "true"' annotation is not installed @ 10/24/25 16:01:06.862
  • [1.428 seconds]
  ------------------------------

  Ran 1 of 1 Specs in 1.428 seconds
  SUCCESS! -- 1 Passed | 0 Failed | 0 Pending | 0 Skipped
[
  {
    "name": "[Jira:Cluster Version Operator] cluster-version-operator-tests Author:jianl-High-42543-the removed resources are not created in a fresh installed cluster",
    "lifecycle": "blocking",
    "duration": 1428,
    "startTime": "2025-10-24 08:01:06.858981 UTC",
    "endTime": "2025-10-24 08:01:08.287644 UTC",
    "result": "passed",
    "output": "  STEP: Validate resource with 'release.openshift.io/delete: \"true\"' annotation is not installed @ 10/24/25 16:01:06.862\n"
  }
]
[jianl@jianl-thinkpadt14gen4 cluster-version-operator]$ 

@JianLi-RH JianLi-RH changed the title [WIP] NO-ISSUE: OTA-1605 Create e2e test in CVO repo NO-ISSUE: OTA-1605 Create e2e test in CVO repo Oct 24, 2025
@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 Oct 24, 2025
@JianLi-RH JianLi-RH force-pushed the implement_client_oc branch from 067cd4b to bac7793 Compare October 27, 2025 03:16
@DavidHurta
Copy link
Contributor

/cc

@openshift-ci openshift-ci bot requested a review from DavidHurta October 27, 2025 11:41
@hongkailiu
Copy link
Member

/cc

@openshift-ci openshift-ci bot requested a review from hongkailiu October 27, 2025 13:04
@JianLi-RH JianLi-RH force-pushed the implement_client_oc branch from bac7793 to 51facb3 Compare October 29, 2025 04:06
@JianLi-RH
Copy link
Contributor Author

After modification, the case is still valid:

[jianl@jianl-thinkpadt14gen4 cluster-version-operator]$ _output/linux/amd64/cluster-version-operator-tests run-test "[Jira:Cluster Version Operator] The cluster version operator the removed resources are not created in a fresh installed cluster"
  Running Suite:  - /home/jianl/1_code/cluster-version-operator
  =============================================================
  Random Seed: 1761710868 - will randomize all specs

  Will run 1 of 1 specs
  ------------------------------
  [Jira:Cluster Version Operator] The cluster version operator the removed resources are not created in a fresh installed cluster [cvo, High, 42543]
  /home/jianl/1_code/cluster-version-operator/test/cvo/cvo.go:24
    STEP: Service controller-manager-service should not be installed @ 10/29/25 12:07:48.862
    STEP: ClusterRoleBindings default-account-openshift-machine-config-operator should not be installed @ 10/29/25 12:07:49.759
    STEP: CronJobs machine-config-nodes-crd-cleanup should not be installed @ 10/29/25 12:07:50.024
  • [1.428 seconds]
  ------------------------------

  Ran 1 of 1 Specs in 1.429 seconds
  SUCCESS! -- 1 Passed | 0 Failed | 0 Pending | 0 Skipped
[
  {
    "name": "[Jira:Cluster Version Operator] The cluster version operator the removed resources are not created in a fresh installed cluster",
    "lifecycle": "blocking",
    "duration": 1429,
    "startTime": "2025-10-29 04:07:48.858522 UTC",
    "endTime": "2025-10-29 04:07:50.287978 UTC",
    "result": "passed",
    "output": "  STEP: Service controller-manager-service should not be installed @ 10/29/25 12:07:48.862\n  STEP: ClusterRoleBindings default-account-openshift-machine-config-operator should not be installed @ 10/29/25 12:07:49.759\n  STEP: CronJobs machine-config-nodes-crd-cleanup should not be installed @ 10/29/25 12:07:50.024\n"
  }
]
[jianl@jianl-thinkpadt14gen4 cluster-version-operator]$ 

@JianLi-RH JianLi-RH force-pushed the implement_client_oc branch from 51facb3 to 8e9da36 Compare October 30, 2025 01:44
@JianLi-RH JianLi-RH force-pushed the implement_client_oc branch 2 times, most recently from 72354d1 to 3a8631b Compare November 4, 2025 01:46
@JianLi-RH
Copy link
Contributor Author

@hongkailiu @DavidHurta I just removed the case, right now the PR only finished one thing: MustGetKubeClient().
Then we can start creating test cases in new PRs.

@JianLi-RH JianLi-RH changed the title NO-ISSUE: OTA-1605 Create e2e test in CVO repo NO-ISSUE: OTA-1605 Create MustGetKubeClient function for e2e test Nov 11, 2025
@JianLi-RH
Copy link
Contributor Author

/retest

@JianLi-RH
Copy link
Contributor Author

/hold

I want to investigate more about client-go.

@DavidHurta
Copy link
Contributor

/hold
I want to investigate more about client-go.

@JianLi-RH, in case the investigation is not done by the end of the day, you want simply more time to explore or are simply busy, I would like to ask you whether it would be fine for me to rename the sanity test in a separate PR. That specific change is blocking my openshift/origin#30316 PR. I am happy to rename the test personally in a separate PR to unblock my PR while we are working on this one.

@JianLi-RH
Copy link
Contributor Author

@DavidHurta of course, go ahead, please. I am not sure when I can finish the investigation.

@JianLi-RH JianLi-RH force-pushed the implement_client_oc branch 6 times, most recently from d2300d9 to f98e03c Compare November 13, 2025 09:10
@JianLi-RH
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 Nov 13, 2025
Clientset instance can be used to connect to cluster, manage resources.
With clientset instance we can evaluate the posibility of moving other tests to OTE.

The reference to OTE framework:
https://docs.google.com/document/d/1cFZj9QdzW8hbHc3H0Nce-2xrJMtpDJrwAse9H7hLiWk/edit?tab=t.0#heading=h.8cf3f4eii1q8
@JianLi-RH JianLi-RH force-pushed the implement_client_oc branch 4 times, most recently from 878cbc8 to 1102f9c Compare November 17, 2025 04:26
@JianLi-RH
Copy link
Contributor Author

@hongkailiu @DavidHurta Just added back the case, please help review it. Here is the output:

$ ginkgo ./test/...
Running Suite: CVO Suite - /home/jianl/1_code/cluster-version-operator/test/cvo
===============================================================================
Random Seed: 1763353592

Will run 2 of 2 specs
•Test Authentication...
namespace: default
        - Test services...
        - Test RoleBinding...
        - Test CronJob...
success
namespace: kube-node-lease
        - Test services...
        - Test RoleBinding...
        - Test CronJob...
success
namespace: kube-public
        - Test services...
        - Test RoleBinding...
        - Test CronJob...
.....................
namespace: openshift-vsphere-infra
        - Test services...
        - Test RoleBinding...
        - Test CronJob...
success


Ran 2 of 2 Specs in 82.840 seconds
SUCCESS! -- 2 Passed | 0 Failed | 0 Pending | 0 Skipped
PASS

Ginkgo ran 1 suite in 1m24.112444203s
Test Suite Passed

If there is resource installed unexpected, it will fail as below:

$ ginkgo ./test/...
Running Suite: CVO Suite - /home/jianl/1_code/cluster-version-operator/test/cvo
===============================================================================
Random Seed: 1763353871

Will run 2 of 2 specs
•Test Authentication...

------------------------------
• [FAILED] [1.522 seconds]
[Jira:"Cluster Version Operator"] cluster-version-operator-tests [It] should not install resources annotated with release.openshift.io/delete=true [cvo, Conformance, High, 42543]
/home/jianl/1_code/cluster-version-operator/test/cvo/cvo.go:20

  [FAILED] Unexpectedly installed authentication cluster which has release.openshift.io/delete annotation
  Expected
      <bool>: true
  not to be true
  In [It] at: /home/jianl/1_code/cluster-version-operator/test/cvo/cvo.go:30 @ 11/17/25 12:31:14.175
------------------------------

Summarizing 1 Failure:
  [FAIL] [Jira:"Cluster Version Operator"] cluster-version-operator-tests [It] should not install resources annotated with release.openshift.io/delete=true [cvo, Conformance, High, 42543]
  /home/jianl/1_code/cluster-version-operator/test/cvo/cvo.go:30

Ran 2 of 2 Specs in 1.522 seconds
FAIL! -- 1 Passed | 1 Failed | 0 Pending | 0 Skipped
--- FAIL: TestGinkgo (1.52s)
FAIL

Ginkgo ran 1 suite in 2.725034617s

Test Suite Failed

@JianLi-RH JianLi-RH changed the title NO-ISSUE: OTA-1605 Create MustGetKubeClient function for e2e test NO-ISSUE: OTA-1605 Create first e2e test OCP-42543 Nov 17, 2025
…ient-go

openshift/client-go gives us more efficient functions to access cluster
After adding new OTE test cases, we need to update test metadata
@coderabbitai
Copy link

coderabbitai bot commented Nov 24, 2025

Walkthrough

This PR adds a test case verifying that cluster version operator does not install resources annotated with release.openshift.io/delete=true. It introduces utility functions for creating Kubernetes clients and rewrites the CVO test suite using Ginkgo v2 to implement comprehensive resource validation across namespaces.

Changes

Cohort / File(s) Summary
Test Utilities
test/utilities/connection.go
New file adding helper functions to create Kubernetes and ConfigV1 clients from KUBECONFIG environment variable, with public must-have wrappers that panic on failure.
CVO Test Suite
test/cvo/cvo.go
Rewrites test file with Ginkgo v2 structure using ordered test blocks. Adds comprehensive test validating that Authentications, Services, RoleBindings, and CronJobs across all namespaces do not carry the release.openshift.io/delete=true annotation, with explicit error handling.
Test Configuration
.openshift-tests-extension/openshift_payload_cluster-version-operator.json
Adds new test case entry for cluster version operator resource deletion annotation validation with labels and conformance marking.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20–30 minutes

  • test/cvo/cvo.go: Requires careful review of the multi-namespace iteration logic, resource type validation across Services, RoleBindings, CronJobs, and Authentications, and error handling for NotFound scenarios.
  • test/utilities/connection.go: Verify proper environment variable handling for KUBECONFIG and context propagation in client creation functions.
  • Ginkgo v2 patterns: Confirm the test structure and assertion patterns follow expected idioms for ordered test blocks and labeled test cases.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between df1ec55 and 946876f.

📒 Files selected for processing (3)
  • .openshift-tests-extension/openshift_payload_cluster-version-operator.json (1 hunks)
  • test/cvo/cvo.go (1 hunks)
  • test/utilities/connection.go (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**

⚙️ CodeRabbit configuration file

-Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity.

Files:

  • test/utilities/connection.go
  • test/cvo/cvo.go
🧬 Code graph analysis (1)
test/cvo/cvo.go (1)
test/utilities/connection.go (2)
  • MustGetV1Client (65-71)
  • MustGetKubeClient (56-62)
🔇 Additional comments (3)
.openshift-tests-extension/openshift_payload_cluster-version-operator.json (1)

13-25: New test metadata entry looks consistent and well-formed

The added metadata object matches the existing structure (name, labels, resources, source, lifecycle, environmentSelector) and aligns with the new CVO test and label conventions (42543, Conformance, High, cvo). No issues from a structure/maintainability perspective.

test/utilities/connection.go (1)

1-71: Client helper utilities are correct and suitable for test usage

KUBECONFIG handling, config construction, clientset creation, and error wrapping all look correct. The MustGet* helpers are appropriate for tests where a missing/invalid config should hard-fail immediately. No blocking issues here.

test/cvo/cvo.go (1)

17-21: Sanity test Describe block is fine

The lightweight [Jira:"Cluster Version Operator"] cluster-version-operator-tests sanity spec is simple and effective as an integration signal. No issues.

Comment on lines +23 to +82
var _ = g.Describe("[Jira:Cluster Version Operator] The cluster version operator", g.Ordered, g.Label("cvo"), func() {
defer g.GinkgoRecover()
var client *v1.ConfigV1Client
var kubeclient *kubernetes.Clientset

g.BeforeAll(func() {
client = utilities.MustGetV1Client()
kubeclient = utilities.MustGetKubeClient()
})

g.It(`should not install resources annotated with release.openshift.io/delete=true`, g.Label("Conformance", "High", "42543"), func() {
annotation := "release.openshift.io/delete"

auths, err := client.Authentications().List(context.TODO(), metav1.ListOptions{})
o.Expect(kerrors.IsNotFound(err)).To(o.BeFalse(), "The NotFound error should occur when listing authentications")

g.By(fmt.Sprintf("checking if authentication with %s annotation exists", annotation))
for _, auth := range auths.Items {
if _, ok := auth.Annotations[annotation]; ok {
o.Expect(ok).NotTo(o.BeTrue(), fmt.Sprintf("Unexpectedly installed authentication %s which has '%s' annotation", auth.Name, annotation))
}
}

namespaces, err := kubeclient.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{})
o.Expect(kerrors.IsNotFound(err)).To(o.BeFalse(), "The NotFound error should occur when listing namespaces")

g.By(fmt.Sprintf("checking if special resources with %s annotation exist in all namespaces", annotation))
for _, ns := range namespaces.Items {
namespace := ns.Name
fmt.Printf("namespace: %s\n", namespace)

fmt.Println(" - Test services...")
services, err := kubeclient.CoreV1().Services(namespace).List(context.TODO(), metav1.ListOptions{})
o.Expect(kerrors.IsNotFound(err)).To(o.BeFalse(), "The NotFound error should occur when listing services")
for _, service := range services.Items {
if _, ok := service.Annotations[annotation]; ok {
o.Expect(ok).NotTo(o.BeTrue(), fmt.Sprintf("Unexpectedly installed service %s which has '%s' annotation", service.Name, annotation))
}
}

fmt.Println(" - Test RoleBinding...")
rolebindings, err := kubeclient.RbacV1().RoleBindings(namespace).List(context.TODO(), metav1.ListOptions{})
o.Expect(kerrors.IsNotFound(err)).To(o.BeFalse(), "The NotFound error should occur when listing rolebindings")
for _, rb := range rolebindings.Items {
if _, ok := rb.Annotations[annotation]; ok {
o.Expect(ok).NotTo(o.BeTrue(), fmt.Sprintf("Unexpectedly installed RoleBinding %s which has '%s' annotation", rb.Name, annotation))
}
}

fmt.Println(" - Test CronJob...")
cronjobs, err := kubeclient.BatchV1().CronJobs(namespace).List(context.TODO(), metav1.ListOptions{})
o.Expect(kerrors.IsNotFound(err)).To(o.BeFalse(), "The NotFound error should occur when listing cronjobs")
for _, cj := range cronjobs.Items {
if _, ok := cj.Annotations[annotation]; ok {
o.Expect(ok).NotTo(o.BeTrue(), fmt.Sprintf("Unexpectedly installed CronJob %s which has %s annotation", cj.Name, annotation))
}
}

fmt.Println("success")
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

Fix List error handling to fail on real API errors, not just NotFound

All the List calls currently do:

auths, err := client.Authentications().List(...)
o.Expect(kerrors.IsNotFound(err)).To(o.BeFalse(), "The NotFound error should occur when listing ...")

This has two problems:

  1. False positives on failures

    • Any non-NotFound error (e.g., auth, RBAC, networking, API server issues) makes kerrors.IsNotFound(err) return false, so the expectation passes.
    • The test then proceeds, typically iterating over an empty/zero-valued list, and can still pass even though the underlying List failed.
    • That means the test can report success while not actually verifying the cluster state.
  2. Misleading messages

    • The description says “The NotFound error should occur when listing …” while the matcher asserts BeFalse(), which is contradictory.

You want the test to fail on any error from those List calls. A more robust pattern is to assert on err directly, for each List:

-		auths, err := client.Authentications().List(context.TODO(), metav1.ListOptions{})
-		o.Expect(kerrors.IsNotFound(err)).To(o.BeFalse(), "The NotFound error should occur when listing authentications")
+		auths, err := client.Authentications().List(context.TODO(), metav1.ListOptions{})
+		o.Expect(err).NotTo(o.HaveOccurred(), "failed to list authentications")

-		namespaces, err := kubeclient.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{})
-		o.Expect(kerrors.IsNotFound(err)).To(o.BeFalse(), "The NotFound error should occur when listing namespaces")
+		namespaces, err := kubeclient.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{})
+		o.Expect(err).NotTo(o.HaveOccurred(), "failed to list namespaces")

-			services, err := kubeclient.CoreV1().Services(namespace).List(context.TODO(), metav1.ListOptions{})
-			o.Expect(kerrors.IsNotFound(err)).To(o.BeFalse(), "The NotFound error should occur when listing services")
+			services, err := kubeclient.CoreV1().Services(namespace).List(context.TODO(), metav1.ListOptions{})
+			o.Expect(err).NotTo(o.HaveOccurred(), "failed to list services")

-			rolebindings, err := kubeclient.RbacV1().RoleBindings(namespace).List(context.TODO(), metav1.ListOptions{})
-			o.Expect(kerrors.IsNotFound(err)).To(o.BeFalse(), "The NotFound error should occur when listing rolebindings")
+			rolebindings, err := kubeclient.RbacV1().RoleBindings(namespace).List(context.TODO(), metav1.ListOptions{})
+			o.Expect(err).NotTo(o.HaveOccurred(), "failed to list rolebindings")

-			cronjobs, err := kubeclient.BatchV1().CronJobs(namespace).List(context.TODO(), metav1.ListOptions{})
-			o.Expect(kerrors.IsNotFound(err)).To(o.BeFalse(), "The NotFound error should occur when listing cronjobs")
+			cronjobs, err := kubeclient.BatchV1().CronJobs(namespace).List(context.TODO(), metav1.ListOptions{})
+			o.Expect(err).NotTo(o.HaveOccurred(), "failed to list cronjobs")

This way, any failure to talk to the API (including NotFound on the resource type) will correctly fail the spec instead of silently passing.

If you want to double‑check semantics, please confirm in the Kubernetes/client-go docs (or local experiments) that List should normally return an empty list with err == nil when no items exist, and that kerrors.IsNotFound is intended for handling Get/Delete style operations rather than normal successful Lists.


🌐 Web query:

How does the Kubernetes client-go List API signal errors vs. an empty result, and when is k8s.io/apimachinery/pkg/api/errors.IsNotFound typically used?

💡 Result:

Short answer: List returns an empty list with err == nil (the returned List object's Items slice is just empty). IsNotFound is not used for a successful List — it's used when an operation asking for a specific named resource (e.g., Get or Delete by name) returns HTTP 404; k8s.io/apimachinery/pkg/api/errors.IsNotFound(err) detects that 404 StatusError. Use IsNotFound when you expect a single resource might not exist and you want to handle "resource missing" specially.

References: k8s error helpers (IsNotFound). [1] Client List/Get semantics (List returns list object; Reader/List returns error only on failure). [2] REST practice: collection endpoints return 200 + empty array when no items. [3]

Sources:
[1] k8s.io/apimachinery/pkg/api/errors (IsNotFound description).
[2] sigs.k8s.io/controller-runtime/pkg/client (Client.List / Reader semantics).
[3] RESTful API design discussion (return 200 with empty array for empty collections).


Replace error assertions with proper nil checks for all List calls

The web search confirms your analysis: Kubernetes List operations return an empty list with err == nil on success. The IsNotFound check is not intended for List operations—it detects HTTP 404 on named-resource operations (Get/Delete), not on collection endpoints.

This means the current code has a critical flaw:

o.Expect(kerrors.IsNotFound(err)).To(o.BeFalse(), "The NotFound error should occur when listing ...")

—will pass whenever IsNotFound(err) == false, which includes:

  • Normal success with no items ✓
  • Network/auth/RBAC failures ✗ (silent pass when should fail)

Your proposed fix is correct. Replace all five List error checks in test/cvo/cvo.go (lines 26–27, 41–42, 51–52, 60–61, 68–69) with:

-o.Expect(kerrors.IsNotFound(err)).To(o.BeFalse(), "The NotFound error should occur when listing ...")
+o.Expect(err).NotTo(o.HaveOccurred(), "failed to list ...")

This ensures any API failure is caught, not silently suppressed.

🤖 Prompt for AI Agents
In test/cvo/cvo.go around lines 23 to 82, the List() error checks use
kerrors.IsNotFound(err) which is inappropriate for collection endpoints and can
silently ignore real API errors; replace each usage at lines ~26–27, ~41–42,
~51–52, ~60–61, and ~68–69 with a direct nil-check assertion (i.e., assert err
is nil) so any List failure causes the test to fail; keep the existing
descriptive messages but change the assertion to ensure err == nil.

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Nov 24, 2025

@JianLi-RH: all tests passed!

Full PR test history. Your PR dashboard.

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. I understand the commands that are listed here.

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. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants