Skip to content

Conversation

@wangke19
Copy link
Contributor

@wangke19 wangke19 commented Jan 16, 2026

Summary

Migrates the refresh-CA test to the OTE (OpenShift Test Extended) Ginkgo framework while maintaining dual-compatibility with traditional Go tests.

This PR continues the systematic migration of e2e tests to support OTE test discovery, following the pattern established in previous PRs (#297-#305).

Critical Fix: Added g.Ordered for Test Execution Order

Problem: OTE's BuildExtensionTestSpecsFromOpenShiftGinkgoSuite() does not preserve g.Ordered or g.Serial decorators. Without g.Ordered, Ginkgo randomizes test execution order by default, even with Parallelism: 1 in the suite configuration.

Impact: Tests with state dependencies fail in OTE CI because they run in random order instead of the intended sequential order.

Solution: Added g.Ordered decorator to the Describe block to guarantee tests execute in declaration order, matching the execution sequence in traditional Go tests.

Changes

test/e2e/e2e.go

  • Add g.Ordered decorator to enforce sequential test execution
  • Fix test context order: Move headless-stateful-serving-cert-secret-delete-data to correct position (set .travis.yml golang to 1.9 #5, after serving-cert-secret-delete-data)
  • Add Ginkgo test context for OTE test discovery:
    • refresh-CA - Tests CA regeneration when deleted and recreated
  • Extract test logic into shared function with testing.TB interface:
    • testRefreshCA() - Verifies serving certs and configmaps update when CA secret is deleted and recreated
  • Add helper functions:
    • pollForCABundleInjectionConfigMapWithReturn() - Polls for CA bundle injection configmap
    • pollForCARecreation() - Polls for CA secret recreation after deletion

test/e2e/e2e_test.go

  • Replace inline test code (74 lines) with test runner calling shared function
  • Remove duplicate helper functions:
    • pollForCABundleInjectionConfigMapWithReturn()
    • pollForCARecreation()
  • Remove unused imports

Test Execution Order (Guaranteed by g.Ordered)

1. serving-cert-annotation
2. serving-cert-secret-modify-bad-tlsCert
3. serving-cert-secret-add-data
4. serving-cert-secret-delete-data
5. headless-stateful-serving-cert-secret-delete-data  ✅ Fixed position
6. ca-bundle-injection-configmap
7. ca-bundle-injection-configmap-update
8. vulnerable-legacy-ca-bundle-injection-configmap
9. metrics
10. refresh-CA  ✅ This test

This order matches the execution sequence in e2e_test.go and ensures state dependencies are preserved.

Testing

Both test frameworks work correctly:

  • ✅ Standard Go test: go test -run "^TestE2E$/^refresh-CA$"
  • ✅ OTE: service-ca-operator-tests-ext run-test "refresh-CA"

Technical Details

Why g.Ordered is Required:

  • Ginkgo v2 randomizes test order by default (to detect test interdependencies)
  • Parallelism: 1 only means "run one test at a time", NOT "run in declaration order"
  • OTE's spec transformation doesn't preserve ordering semantics
  • Our tests have intentional state dependencies (CA creation, rotation, deletion)
  • g.Ordered explicitly enforces declaration order for all nested Context/It blocks

Related

Migrates the refresh-CA test to the OTE (Openshift Test Extended)
Ginkgo framework while maintaining dual-compatibility with traditional
Go tests.

Changes:
- Add Ginkgo test context in e2e.go for OTE test discovery:
  * refresh-CA - Tests CA regeneration when deleted and recreated
- Extract test logic into shared function with testing.TB interface:
  * testRefreshCA() - Verifies serving certs and configmaps update
    when CA secret is deleted and recreated
- Add helper functions in e2e.go:
  * pollForCABundleInjectionConfigMapWithReturn() - Polls for configmap
  * pollForCARecreation() - Polls for CA secret recreation
- Keep test runner in e2e_test.go that calls shared function
- Remove duplicate helper functions from e2e_test.go

Net change: +30 lines (132 added - 102 removed)

Both test frameworks continue to work:
- Standard Go test: go test -run "^TestE2E$/^refresh-CA$"
- OTE: Ginkgo test discovery via service-ca-operator-tests-ext
@coderabbitai
Copy link

coderabbitai bot commented Jan 16, 2026

Important

Review skipped

Auto reviews are limited based on label configuration.

🚫 Excluded labels (none allowed) (1)
  • do-not-merge/work-in-progress

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

The pull request refactors the e2e CA refresh test by moving helper functions and test logic from e2e_test.go to e2e.go. A new testRefreshCA function with supporting polling helpers is introduced to verify that deleting and recreating the CA secret triggers updates to serving certificates and ConfigMaps. The inline test code is consolidated into a single reusable function.

Changes

Cohort / File(s) Summary
E2E Test Refactoring
test/e2e/e2e.go, test/e2e/e2e_test.go
Moves CA refresh test logic and polling helpers (pollForCABundleInjectionConfigMapWithReturn, pollForCARecreation) from e2e_test.go to e2e.go. Introduces testRefreshCA function to verify CA secret deletion and recreation triggers updates to serving certs and ConfigMaps. Replaces inline test code with consolidated function call.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes


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

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Jan 16, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: wangke19

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 16, 2026
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

🤖 Fix all issues with AI agents
In `@test/e2e/e2e.go`:
- Around line 1230-1317: The test captures configmapCopy before verifying the
injected CA data and calls pollForSecretChangeGinkgo for the headless secret
with no keys (which returns immediately); fix by moving the configmapCopy =
configmap.DeepCopy() to after checkConfigMapCABundleInjectionData(adminClient,
testConfigMapName, ns.Name) so the baseline includes injected data, and call
pollForSecretChangeGinkgo(t, adminClient, headlessSecretCopy, v1.TLSCertKey,
v1.TLSPrivateKeyKey) (same keys used for the regular secret) so the headless
secret change is actually validated; locate symbols
pollForServiceServingSecretWithReturn, configmapCopy,
checkConfigMapCABundleInjectionData, pollForConfigMapChange, headlessSecretCopy,
and pollForSecretChangeGinkgo to make the edits.
📜 Review details

Configuration used: Organization 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 503e4f5 and 952a380.

📒 Files selected for processing (2)
  • test/e2e/e2e.go
  • test/e2e/e2e_test.go
🧰 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/e2e/e2e.go
  • test/e2e/e2e_test.go
🧬 Code graph analysis (1)
test/e2e/e2e.go (1)
pkg/controller/api/api.go (1)
  • InjectionDataKey (29-29)
🔇 Additional comments (3)
test/e2e/e2e_test.go (1)

697-703: Clean delegation to shared refresh-CA test.

Nice consolidation to the shared testRefreshCA path for OTE compatibility.

test/e2e/e2e.go (2)

106-111: refresh-CA Ginkgo context integration looks good.

Clear test discovery wiring for OTE.


1319-1349: Polling helpers are straightforward and consistent.

Timeout usage and error handling align with the other poll helpers.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment on lines +1230 to +1317
// testRefreshCA verifies that when the CA secret is deleted and recreated,
// all serving certs and configmaps get updated with the new CA.
//
// This test uses testing.TB interface for dual-compatibility with both
// standard Go tests and Ginkgo tests.
//
// This situation is temporary until we test the new e2e jobs with OTE.
// Eventually all tests will be run only as part of the OTE framework.
func testRefreshCA(t testing.TB) {
adminClient, err := getKubeClient()
if err != nil {
t.Fatalf("error getting kube client: %v", err)
}

ns, cleanup, err := createTestNamespace(t, adminClient, "test-"+randSeq(5))
if err != nil {
t.Fatalf("could not create test namespace: %v", err)
}
defer cleanup()

// create secrets
testServiceName := "test-service-" + randSeq(5)
testSecretName := "test-secret-" + randSeq(5)
testHeadlessServiceName := "test-headless-service-" + randSeq(5)
testHeadlessSecretName := "test-headless-secret-" + randSeq(5)

err = createServingCertAnnotatedService(adminClient, testSecretName, testServiceName, ns.Name, false)
if err != nil {
t.Fatalf("error creating annotated service: %v", err)
}
if err = createServingCertAnnotatedService(adminClient, testHeadlessSecretName, testHeadlessServiceName, ns.Name, true); err != nil {
t.Fatalf("error creating annotated headless service: %v", err)
}

secret, err := pollForServiceServingSecretWithReturn(adminClient, testSecretName, ns.Name)
if err != nil {
t.Fatalf("error fetching created serving cert secret: %v", err)
}
secretCopy := secret.DeepCopy()
headlessSecret, err := pollForServiceServingSecretWithReturn(adminClient, testHeadlessSecretName, ns.Name)
if err != nil {
t.Fatalf("error fetching created serving cert secret: %v", err)
}
headlessSecretCopy := headlessSecret.DeepCopy()

// create configmap
testConfigMapName := "test-configmap-" + randSeq(5)

err = createAnnotatedCABundleInjectionConfigMap(adminClient, testConfigMapName, ns.Name)
if err != nil {
t.Fatalf("error creating annotated configmap: %v", err)
}

configmap, err := pollForCABundleInjectionConfigMapWithReturn(adminClient, testConfigMapName, ns.Name)
if err != nil {
t.Fatalf("error fetching ca bundle injection configmap: %v", err)
}
configmapCopy := configmap.DeepCopy()
err = checkConfigMapCABundleInjectionData(adminClient, testConfigMapName, ns.Name)
if err != nil {
t.Fatalf("error when checking ca bundle injection configmap: %v", err)
}

// delete ca secret
err = adminClient.CoreV1().Secrets("openshift-service-ca").Delete(context.TODO(), "signing-key", metav1.DeleteOptions{})
if err != nil {
t.Fatalf("error deleting signing key: %v", err)
}

// make sure it's recreated
err = pollForCARecreation(adminClient)
if err != nil {
t.Fatalf("signing key was not recreated: %v", err)
}

err = pollForConfigMapChange(t, adminClient, configmapCopy, api.InjectionDataKey)
if err != nil {
t.Fatalf("configmap bundle did not change: %v", err)
}

err = pollForSecretChangeGinkgo(t, adminClient, secretCopy, v1.TLSCertKey, v1.TLSPrivateKeyKey)
if err != nil {
t.Fatalf("secret cert did not change: %v", err)
}
if err := pollForSecretChangeGinkgo(t, adminClient, headlessSecretCopy); err != nil {
t.Fatalf("headless secret cert did not change: %v", err)
}
}
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

Fix false-positive checks for configmap and headless secret changes.

configmapCopy is captured before ensuring injected data exists, so the post-rotation check can succeed even if the bundle didn’t change. Also, pollForSecretChangeGinkgo is called with no keys for the headless secret, which makes it return immediately. Both weaken the test’s assertion.

Proposed fix
 	configmap, err := pollForCABundleInjectionConfigMapWithReturn(adminClient, testConfigMapName, ns.Name)
 	if err != nil {
 		t.Fatalf("error fetching ca bundle injection configmap: %v", err)
 	}
-	configmapCopy := configmap.DeepCopy()
 	err = checkConfigMapCABundleInjectionData(adminClient, testConfigMapName, ns.Name)
 	if err != nil {
 		t.Fatalf("error when checking ca bundle injection configmap: %v", err)
 	}
+	configmap, err = adminClient.CoreV1().ConfigMaps(ns.Name).Get(context.TODO(), testConfigMapName, metav1.GetOptions{})
+	if err != nil {
+		t.Fatalf("error fetching ca bundle injection configmap: %v", err)
+	}
+	configmapCopy := configmap.DeepCopy()
@@
-	if err := pollForSecretChangeGinkgo(t, adminClient, headlessSecretCopy); err != nil {
+	if err := pollForSecretChangeGinkgo(t, adminClient, headlessSecretCopy, v1.TLSCertKey, v1.TLSPrivateKeyKey); err != nil {
 		t.Fatalf("headless secret cert did not change: %v", err)
 	}
🤖 Prompt for AI Agents
In `@test/e2e/e2e.go` around lines 1230 - 1317, The test captures configmapCopy
before verifying the injected CA data and calls pollForSecretChangeGinkgo for
the headless secret with no keys (which returns immediately); fix by moving the
configmapCopy = configmap.DeepCopy() to after
checkConfigMapCABundleInjectionData(adminClient, testConfigMapName, ns.Name) so
the baseline includes injected data, and call pollForSecretChangeGinkgo(t,
adminClient, headlessSecretCopy, v1.TLSCertKey, v1.TLSPrivateKeyKey) (same keys
used for the regular secret) so the headless secret change is actually
validated; locate symbols pollForServiceServingSecretWithReturn, configmapCopy,
checkConfigMapCABundleInjectionData, pollForConfigMapChange, headlessSecretCopy,
and pollForSecretChangeGinkgo to make the edits.

@wangke19 wangke19 changed the title test/e2e: migrate refresh-CA test for OTE compatibility CNTRLPLANE-2549:test/e2e: migrate refresh-CA test for OTE compatibility Jan 16, 2026
@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Jan 16, 2026
@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Jan 16, 2026

@wangke19: This pull request references CNTRLPLANE-2549 which is a valid jira issue.

Details

In response to this:

Summary

Migrates the refresh-CA test to the OTE (OpenShift Test Extended) Ginkgo framework while maintaining dual-compatibility with traditional Go tests.

This PR continues the systematic migration of e2e tests to support OTE test discovery, following the pattern established in previous PRs (#297-#305).

Changes

test/e2e/e2e.go (+127 lines)

  • Add Ginkgo test context for OTE test discovery:
  • refresh-CA - Tests CA regeneration when deleted and recreated
  • Extract test logic into shared function with testing.TB interface:
  • testRefreshCA() - Verifies serving certs and configmaps update when CA secret is deleted and recreated
  • Add helper functions:
  • pollForCABundleInjectionConfigMapWithReturn() - Polls for CA bundle injection configmap
  • pollForCARecreation() - Polls for CA secret recreation after deletion

test/e2e/e2e_test.go (-102 lines)

  • Replace inline test code (74 lines) with test runner calling shared function
  • Remove duplicate helper functions:
  • pollForCABundleInjectionConfigMapWithReturn()
  • pollForCARecreation()

Net change: +30 lines (132 added - 102 removed)

The net +30 lines consist of:

  1. Ginkgo Context wrapper (~6 lines) - OTE test discovery
  2. Comments and documentation (~7 lines) - Better documentation
  3. Two helper functions (~17 lines) - Now reusable from both files

The migration moved 95 lines from e2e_test.go → e2e.go and added 30 lines of new infrastructure (Ginkgo wrapper + better organization).

Test Verification

Traditional Go Test

$ go test -v -run "^TestE2E$/^refresh-CA$" ./test/e2e/ -timeout 15m
=== RUN   TestE2E
=== RUN   TestE2E/refresh-CA
--- PASS: TestE2E (76.51s)
   --- PASS: TestE2E/refresh-CA (74.79s)
PASS
ok      github.com/openshift/service-ca-operator/test/e2e      76.549s

OTE Binary

$ go build -o /tmp/service-ca-operator-tests-ext ./test/e2e/
# Binary compiles successfully (ready for OTE test discovery)

Dual Compatibility

Both test frameworks continue to work:

  • Standard Go test: go test -run "^TestE2E$/^refresh-CA$"
  • OTE: Ginkgo test discovery via service-ca-operator-tests-ext

Related PRs

Part of the OTE migration effort:

Next Steps

After this PR, remaining tests to migrate:

  • time-based-ca-rotation
  • forced-ca-rotation
  • apiservice-ca-bundle-injection
  • crd-ca-bundle-injection
  • mutatingwebhook-ca-bundle-injection
  • validatingwebhook-ca-bundle-injection

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.

@wangke19 wangke19 changed the title CNTRLPLANE-2549:test/e2e: migrate refresh-CA test for OTE compatibility [WIP]CNTRLPLANE-2549:test/e2e: migrate refresh-CA test for OTE compatibility Jan 16, 2026
@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 16, 2026
@wangke19
Copy link
Contributor Author

/test e2e-aws-operator-serial-ote

2 similar comments
@wangke19
Copy link
Contributor Author

/test e2e-aws-operator-serial-ote

@wangke19
Copy link
Contributor Author

/test e2e-aws-operator-serial-ote

Move headless-stateful-serving-cert-secret-delete-data context to correct position.
It should run after serving-cert-secret-delete-data and before ca-bundle tests.

This fixes the test execution sequence to match e2e_test.go order:
1. serving-cert-secret-delete-data
2. headless-stateful-serving-cert-secret-delete-data
3. ca-bundle-injection-configmap
4. ca-bundle-injection-configmap-update
5. vulnerable-legacy-ca-bundle-injection-configmap
6. metrics
7. refresh-CA
Add g.Ordered decorator to Ginkgo Describe block to guarantee tests
run in declaration order.

Without g.Ordered, Ginkgo randomizes test execution order by default,
even with Parallelism: 1. This causes OTE tests to fail because the
tests have state dependencies and must run in the exact order defined
in e2e_test.go.

The g.Ordered decorator ensures tests execute in this sequence:
1. serving-cert-annotation
2. serving-cert-secret-modify-bad-tlsCert
3. serving-cert-secret-add-data
4. serving-cert-secret-delete-data
5. headless-stateful-serving-cert-secret-delete-data
6. ca-bundle-injection-configmap
7. ca-bundle-injection-configmap-update
8. vulnerable-legacy-ca-bundle-injection-configmap
9. metrics
10. refresh-CA

This matches the execution order in traditional Go tests.
@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Jan 20, 2026

@wangke19: This pull request references CNTRLPLANE-2549 which is a valid jira issue.

Details

In response to this:

Summary

Migrates the refresh-CA test to the OTE (OpenShift Test Extended) Ginkgo framework while maintaining dual-compatibility with traditional Go tests.

This PR continues the systematic migration of e2e tests to support OTE test discovery, following the pattern established in previous PRs (#297-#305).

Critical Fix: Added g.Ordered for Test Execution Order

Problem: OTE's BuildExtensionTestSpecsFromOpenShiftGinkgoSuite() does not preserve g.Ordered or g.Serial decorators. Without g.Ordered, Ginkgo randomizes test execution order by default, even with Parallelism: 1 in the suite configuration.

Impact: Tests with state dependencies fail in OTE CI because they run in random order instead of the intended sequential order.

Solution: Added g.Ordered decorator to the Describe block to guarantee tests execute in declaration order, matching the execution sequence in traditional Go tests.

Changes

test/e2e/e2e.go

  • Add g.Ordered decorator to enforce sequential test execution
  • Fix test context order: Move headless-stateful-serving-cert-secret-delete-data to correct position (set .travis.yml golang to 1.9 #5, after serving-cert-secret-delete-data)
  • Add Ginkgo test context for OTE test discovery:
  • refresh-CA - Tests CA regeneration when deleted and recreated
  • Extract test logic into shared function with testing.TB interface:
  • testRefreshCA() - Verifies serving certs and configmaps update when CA secret is deleted and recreated
  • Add helper functions:
  • pollForCABundleInjectionConfigMapWithReturn() - Polls for CA bundle injection configmap
  • pollForCARecreation() - Polls for CA secret recreation after deletion

test/e2e/e2e_test.go

  • Replace inline test code (74 lines) with test runner calling shared function
  • Remove duplicate helper functions:
  • pollForCABundleInjectionConfigMapWithReturn()
  • pollForCARecreation()
  • Remove unused imports

Test Execution Order (Guaranteed by g.Ordered)

1. serving-cert-annotation
2. serving-cert-secret-modify-bad-tlsCert
3. serving-cert-secret-add-data
4. serving-cert-secret-delete-data
5. headless-stateful-serving-cert-secret-delete-data  ✅ Fixed position
6. ca-bundle-injection-configmap
7. ca-bundle-injection-configmap-update
8. vulnerable-legacy-ca-bundle-injection-configmap
9. metrics
10. refresh-CA  ✅ This test

This order matches the execution sequence in e2e_test.go and ensures state dependencies are preserved.

Testing

Both test frameworks work correctly:

  • ✅ Standard Go test: go test -run "^TestE2E$/^refresh-CA$"
  • ✅ OTE: service-ca-operator-tests-ext run-test "refresh-CA"

Technical Details

Why g.Ordered is Required:

  • Ginkgo v2 randomizes test order by default (to detect test interdependencies)
  • Parallelism: 1 only means "run one test at a time", NOT "run in declaration order"
  • OTE's spec transformation doesn't preserve ordering semantics
  • Our tests have intentional state dependencies (CA creation, rotation, deletion)
  • g.Ordered explicitly enforces declaration order for all nested Context/It blocks

Related

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.

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Jan 20, 2026

@wangke19: The following tests failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/e2e-aws-operator-serial-ote a2e7875 link false /test e2e-aws-operator-serial-ote
ci/prow/e2e-aws a2e7875 link true /test e2e-aws

Full PR test history. Your PR dashboard.

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. 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. do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. 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.

2 participants