Skip to content

✨ Add ServiceAccount validation to ClusterExtension reconciliation#2488

Open
perdasilva wants to merge 1 commit intooperator-framework:mainfrom
perdasilva:validation-stage
Open

✨ Add ServiceAccount validation to ClusterExtension reconciliation#2488
perdasilva wants to merge 1 commit intooperator-framework:mainfrom
perdasilva:validation-stage

Conversation

@perdasilva
Copy link
Contributor

@perdasilva perdasilva commented Feb 5, 2026

Summary

Introduces an extensible validation framework for ClusterExtension reconciliation that validates configuration before attempting bundle installation. The first validator ensures the specified ServiceAccount exists.

Problem

Previously, ServiceAccount validation happened during revision state retrieval, which meant:

  • Configuration errors were discovered late in the reconciliation process
  • Error handling was mixed with business logic
  • No way to validate multiple aspects and report all errors at once

Solution

New Validation Framework

ValidateClusterExtension(validators ...ClusterExtensionValidator)

  • Orchestrates multiple validators in a single reconcile step
  • Executes ALL validators even if some fail (collects all errors)
  • Sets appropriate status conditions on failure:
    • Installed: Unknown
    • Progressing: True (Reason: Retrying)
  • Returns aggregated errors with clear user-facing messages

ServiceAccountValidator(saClient)

  • Validates ServiceAccount existence via direct CoreV1 API Get call
  • Returns friendly error: service account "name" not found in namespace "ns"

Integration Points

Added as a reconcile step (after finalizer handling, before revision state retrieval) in both:

  • Boxcutter runtime configuration
  • Helm runtime configuration

RBAC Changes

  • Added get permission for serviceaccounts resources to the operator-controller manager ClusterRole
  • Regenerated all deployment manifests (standard, experimental, e2e variants)

Cleanup

  • Removed ServiceAccount-specific error handling from RetrieveRevisionStates since validation now happens earlier in the pipeline
  • Removed authentication.ServiceAccountNotFoundError dependency from reconcile steps and tests

Testing

Unit Tests (clusterextension_controller_test.go)

TestValidateClusterExtension - 7 table-driven scenarios:

  • All validators pass
  • Single validator fails
  • Multiple validators collect all failures
  • Multiple validators all pass
  • Mixed pass/fail validators
  • ServiceAccount not found
  • ServiceAccount found

E2E Tests (test/e2e/features/install.feature)

  • New scenario: "Report validation error when ServiceAccount does not exist"

Files Changed

  • cmd/operator-controller/main.go - Added validation step with ServiceAccountValidator to both boxcutter and helm reconciler configurations
  • internal/operator-controller/controllers/clusterextension_reconcile_steps.go - New validation framework (ClusterExtensionValidator type, ValidateClusterExtension, ServiceAccountValidator), removed SA error handling from RetrieveRevisionStates
  • internal/operator-controller/controllers/clusterextension_controller_test.go - Replaced TestClusterExtensionServiceAccountNotFound with comprehensive TestValidateClusterExtension table-driven tests (7 scenarios)
  • internal/operator-controller/controllers/suite_test.go - Added Validators field to test deps and included ValidateClusterExtension in default reconcile steps
  • helm/olmv1/templates/rbac/clusterrole-operator-controller-manager-role.yml - Added get permission for serviceaccounts
  • manifests/*.yaml - Regenerated manifests reflecting RBAC changes
  • test/e2e/features/install.feature - E2E validation scenario for missing ServiceAccount

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings February 5, 2026 14:19
@netlify
Copy link

netlify bot commented Feb 5, 2026

Deploy Preview for olmv1 ready!

Name Link
🔨 Latest commit 7cd5abe
🔍 Latest deploy log https://app.netlify.com/projects/olmv1/deploys/69972be1337d17000821fb61
😎 Deploy Preview https://deploy-preview-2488--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.

@openshift-ci openshift-ci bot requested review from anik120 and grokspawn February 5, 2026 14:19
@openshift-ci
Copy link

openshift-ci bot commented Feb 5, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign oceanc80 for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found 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

@perdasilva perdasilva changed the title feat: Add ServiceAccount validation to ClusterExtension reconciliation ✨ Add ServiceAccount validation to ClusterExtension reconciliation Feb 5, 2026
@perdasilva perdasilva marked this pull request as draft February 5, 2026 14:20
@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 Feb 5, 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

This PR adds ServiceAccount validation to the ClusterExtension reconciliation pipeline. The validation checks whether the ServiceAccount specified in .spec.serviceAccount exists on the cluster before proceeding with bundle installation, moving this check from RetrieveRevisionStates to an earlier validation stage.

Changes:

  • Introduces a new validation framework with ValidateClusterExtension orchestrator and ServiceAccountValidator implementation
  • Moves ServiceAccount existence checks earlier in the reconciliation pipeline (after finalizer handling)
  • Updates both Boxcutter and Helm reconciler configurations to include the validation step

Reviewed changes

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

Show a summary per file
File Description
internal/operator-controller/controllers/clusterextension_reconcile_steps.go Adds validation framework (ValidateClusterExtension, ClusterExtensionValidator, ServiceAccountValidator) and removes ServiceAccount error handling from RetrieveRevisionStates
internal/operator-controller/controllers/clusterextension_reconcile_steps_test.go Adds comprehensive unit tests for validator functions (10 test cases total)
internal/operator-controller/controllers/clusterextension_controller_test.go Updates existing ServiceAccount test to use new validation approach with mock TokenGetter
cmd/operator-controller/main.go Integrates validation step into both Boxcutter and Helm reconciler configurations
test/e2e/features/install.feature Adds E2E Gherkin scenario for ServiceAccount validation error case

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

@codecov
Copy link

codecov bot commented Feb 5, 2026

Codecov Report

❌ Patch coverage is 96.42857% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 73.13%. Comparing base (553e210) to head (7cd5abe).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
...er/controllers/clusterextension_reconcile_steps.go 95.45% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2488      +/-   ##
==========================================
- Coverage   73.21%   73.13%   -0.09%     
==========================================
  Files         102      103       +1     
  Lines        8505     8539      +34     
==========================================
+ Hits         6227     6245      +18     
- Misses       1799     1813      +14     
- Partials      479      481       +2     
Flag Coverage Δ
e2e 45.73% <85.71%> (+0.14%) ⬆️
experimental-e2e 53.60% <85.71%> (-0.01%) ⬇️
unit 57.94% <75.00%> (+0.05%) ⬆️

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.

Copilot AI review requested due to automatic review settings February 5, 2026 16:54
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 5 out of 5 changed files in this pull request and generated 4 comments.


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

revisionStates, err := r.GetRevisionStates(ctx, ext)
if err != nil {
setInstallStatus(ext, nil)
var saerr *authentication.ServiceAccountNotFoundError
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 got split between the service account validator and the cluster extension validator

Copilot AI review requested due to automatic review settings February 9, 2026 09:31
@perdasilva perdasilva marked this pull request as ready for review February 9, 2026 09:33
@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 Feb 9, 2026
@openshift-ci openshift-ci bot requested a review from pedjak February 9, 2026 09:33
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 5 out of 5 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 February 9, 2026 14:09
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 5 out of 5 changed files in this pull request and generated 1 comment.


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

Copilot AI review requested due to automatic review settings February 18, 2026 16:39
@perdasilva perdasilva force-pushed the validation-stage branch 2 times, most recently from 18ede8a to 6bad46a Compare February 18, 2026 16:42
require.NoError(t, cl.DeleteAllOf(ctx, &ocv1.ClusterExtension{}))
}

func TestClusterExtensionServiceAccountNotFound(t *testing.T) {
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 moved this use-case into a more general test against validation

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 5 out of 5 changed files in this pull request and generated no new comments.


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

// validators sequentially. All validators are executed even if some fail,
// and all errors are collected and returned as a joined error.
// This provides complete validation feedback in a single reconciliation cycle.
func ValidateClusterExtension(validators ...ClusterExtensionValidator) ReconcileStepFunc {
Copy link
Contributor

Choose a reason for hiding this comment

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

it would be nice to add some unit tests for the new reconcile step.

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 think I've covered those here, no?

Copilot AI review requested due to automatic review settings February 19, 2026 11:47
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 5 out of 5 changed files in this pull request and generated 2 comments.


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

…erExtension

Introduces an extensible validation framework that runs early in the
ClusterExtension reconciliation pipeline (after finalizer handling,
before revision state retrieval) to catch configuration errors before
expensive operations begin.

Key changes:
- New ClusterExtensionValidator type and ValidateClusterExtension
  reconcile step that executes all validators and collects all errors
  (no fail-fast behavior)
- ServiceAccountValidator checks SA existence via direct CoreV1 API
  Get call, providing clear "not found" feedback
- Sets Installed=Unknown and Progressing=Retrying conditions on
  validation failure
- Removed SA-specific error handling from RetrieveRevisionStates,
  since validation now catches these errors earlier
- Added RBAC permission (get serviceaccounts) to the operator-controller
  manager ClusterRole and regenerated manifests

Testing:
- Table-driven unit tests covering 7 scenarios (all pass, single
  fail, multiple fail, mixed, SA not found, SA found)
- E2E scenario for missing ServiceAccount validation error

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Signed-off-by: Per Goncalves da Silva <pegoncal@redhat.com>
Signed-off-by: Per G. da Silva <pegoncal@redhat.com>
Copilot AI review requested due to automatic review settings February 19, 2026 15:27
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 10 out of 10 changed files in this pull request and generated 2 comments.


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

return nil, nil
}

// Set status condition with the validation error for other validation failures
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

The comment "Set status condition with the validation error for other validation failures" is misleading. The word "other" suggests there are different types of validation failures handled differently, but this code path handles all validation failures uniformly. Consider changing to "Set status conditions with the validation errors" for clarity.

Suggested change
// Set status condition with the validation error for other validation failures
// Set status conditions with the validation errors

Copilot uses AI. Check for mistakes.
Comment on lines +858 to +860
serviceAccountValidatorWithFakeClient(&corev1.ServiceAccount{
ObjectMeta: metav1.ObjectMeta{
Name: "missing-sa",
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

The test setup is confusing because it creates a ServiceAccount named "missing-sa" in the fake client, but the test name "service account not found" and the expected error message suggest we're testing for "test-sa" not being found. While the test logic is correct (it verifies that when "test-sa" doesn't exist, we get the expected error), the setup could be clearer. Consider either: (1) Renaming the ServiceAccount to clarify it's a decoy (e.g., "other-sa"), (2) Adding a comment explaining that this creates a different SA to ensure "test-sa" is not found, or (3) Passing nil to serviceAccountValidatorWithFakeClient to make it explicit that no SA exists.

Suggested change
serviceAccountValidatorWithFakeClient(&corev1.ServiceAccount{
ObjectMeta: metav1.ObjectMeta{
Name: "missing-sa",
// Create a different ServiceAccount to ensure "test-sa" is not found.
serviceAccountValidatorWithFakeClient(&corev1.ServiceAccount{
ObjectMeta: metav1.ObjectMeta{
Name: "other-sa",

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

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments