Skip to content

CNTRLPLANE-3234: health reporter writer#2318

Open
ibihim wants to merge 6 commits into
openshift:masterfrom
ibihim:CNTRLPLANE-3234-health-reporter-writer
Open

CNTRLPLANE-3234: health reporter writer#2318
ibihim wants to merge 6 commits into
openshift:masterfrom
ibihim:CNTRLPLANE-3234-health-reporter-writer

Conversation

@ibihim

@ibihim ibihim commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

What

Add health report status writer.

Why

We need to write the status into the status of each individual (aggregated) apiserver's operator status for access to KMSv2 controllers.

Notes

Check usage pattern at openshift/cluster-authentication-operator#929.

Summary by CodeRabbit

  • New Features

    • KMS health checks now publish encryption status updates instead of only logging probe results.
    • Health reporting now works consistently across the supported control plane status views.
  • Bug Fixes

    • Improved status mapping so unexpected health values are reported safely as errors.
    • Added clearer handling for missing or empty report details to avoid invalid status updates.
  • Tests

    • Added coverage for end-to-end health report generation and status publishing behavior.

@openshift-ci-robot

openshift-ci-robot commented Jun 19, 2026

Copy link
Copy Markdown

@ibihim: This pull request references CNTRLPLANE-3234 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the task to target the "5.0.0" version, but no target version was set.

Details

In response to this:

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-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Jun 19, 2026
@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

KMS health probe results are now converted into KMSEncryptionStatus apply configurations and published through injected status writers. The command wiring builds a per-node writer, and new writers target Authentication, KubeAPIServer, and OpenShiftAPIServer status subresources.

Changes

KMS health status publishing

Layer / File(s) Summary
Status shape and mapping
pkg/operator/encryption/kms/health/writer.go, pkg/operator/encryption/kms/health/writer_test.go
pluginHealthReport values are converted into KMSEncryptionStatus apply configurations, with tests covering conditional KEK/detail fields and health-status enum mapping.
Status writer constructors
pkg/operator/encryption/kms/health/writers/writers.go
Shared apply options are added, and writer constructors apply KMSEncryptionStatus to Authentication, KubeAPIServer, and OpenShiftAPIServer status subresources.
Command wiring
pkg/operator/encryption/kms/health/cmd.go
NewCommand and Config now accept a writer factory and create a per-node writeStatus callback during setup.
Publish loop
pkg/operator/encryption/kms/health/cmd.go, pkg/operator/encryption/kms/health/cmd_test.go
Config.Run now builds and publishes encryption status from probe reports, and the new test verifies one probe-and-publish cycle.

Sequence Diagram(s)

sequenceDiagram
  participant "Config.Run" as ConfigRun
  participant prober
  participant buildEncryptionStatus
  participant writeStatus
  participant "KubeAPIServer.status.encryptionStatus" as KubeAPIServerStatus

  ConfigRun->>prober: probe KMSv2 plugins
  prober-->>ConfigRun: pluginHealthReport entries
  ConfigRun->>buildEncryptionStatus: build KMSEncryptionStatus
  buildEncryptionStatus-->>ConfigRun: KMSEncryptionStatusApplyConfiguration
  ConfigRun->>writeStatus: publish status
  writeStatus->>KubeAPIServerStatus: apply status
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • p0lyn0mial

Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
No-Sensitive-Data-In-Logs ❌ Error klog.InfoS logs the whole options struct at startup, including NodeName and Kubeconfig; NodeName may be an internal hostname. Avoid logging the full options struct; log only non-sensitive fields or redact NodeName/Kubeconfig before emitting InfoS.
Docstring Coverage ⚠️ Warning Docstring coverage is 63.64% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (13 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and directly reflects the main change: adding a health reporter writer for KMS health reporting.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Stable And Deterministic Test Names ✅ Passed No Ginkgo titles were added; the new tests use static Go test names and only static t.Run cases, with no dynamic data in titles.
Test Structure And Quality ✅ Passed These are focused unit tests, not Ginkgo; they use fakes/table cases, no cluster resources or waits, and match nearby repo test patterns.
Microshift Test Compatibility ✅ Passed No new Ginkgo/e2e tests were added; the changes are plain unit tests using testing and mocks, so MicroShift compatibility is not implicated.
Single Node Openshift (Sno) Test Compatibility ✅ Passed The PR adds only unit tests; no Ginkgo/e2e tests or multi-node/SNO assumptions were introduced.
Topology-Aware Scheduling Compatibility ✅ Passed No new scheduling constraints were added; the PR only wires KMS health reporting/writing logic and tests, with no node selectors, affinity, spread constraints, or replica changes.
Ote Binary Stdout Contract ✅ Passed No main/init/TestMain/suite hooks or fmt.Print stdout writes were added; the new klog usage is runtime-only and klog defaults to stderr.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed No new Ginkgo/e2e tests were added; the changed tests are unit tests and contain no IPv4-only or external connectivity assumptions.
No-Weak-Crypto ✅ Passed Touched files only add KMS status-writer plumbing and tests; no MD5/SHA1/DES/RC4/3DES/Blowfish/ECB, custom crypto, or secret comparisons found.
Container-Privileges ✅ Passed PR only changes Go health-reporter code/tests; no manifests or privileged settings (privileged, hostNetwork, hostPID, hostIPC, SYS_ADMIN, allowPrivilegeEscalation) were added.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@openshift-ci openshift-ci Bot requested review from ardaguclu and bertinatto June 19, 2026 09:00
@ibihim ibihim changed the title CNTRLPLANE-3234: health reporter writer [WIP] CNTRLPLANE-3234: health reporter writer Jun 19, 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 Jun 19, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@go.mod`:
- Around line 144-145: Remove the replace directive that maps
github.com/openshift/client-go to the local filesystem path
/home/ibihim/go/src/github.com/openshift/client-go-worktrees/health-reporter-regen-api,
as this absolute path will not exist on other machines or CI/CD runners and will
cause build failures. If the regenerated client-go types are not yet available
in a published version, first push those types to the upstream
openshift/client-go repository, then update the github.com/openshift/client-go
version constraint in go.mod to reference the published version instead of the
local path.
- Line 21: The github.com/openshift/api dependency is using a pseudo-version
(v0.0.0-20260618083218-a3c8dea7f8bc) which is an unreleased development commit
and violates supply chain security guidelines. Replace this pseudo-version with
a stable released version of openshift/api that includes the
KMSPluginHealthStatus enum used in writer.go. If a released version is not yet
available, document and justify why the unreleased pseudo-version is necessary
as an exception to the security policy.

In `@pkg/operator/encryption/kms/health/cmd_test.go`:
- Around line 131-151: Replace the context.WithCancel call at the beginning of
the test with context.WithTimeout to add a timeout bound. Instead of relying
solely on the writeStatus callback to cancel the context, use a timeout-bound
context (such as a reasonable test timeout like 5 seconds) so that if
writeStatus is never reached and cancel() is never called, the test will fail
fast due to context timeout rather than hanging indefinitely.

In `@pkg/operator/encryption/kms/health/cmd.go`:
- Around line 135-139: Add a length validation check in the validate() method to
ensure the reporterID does not exceed Kubernetes' 128-character fieldManager
limit. The reporterID is constructed by concatenating "kms-health-reporter-" (20
characters) with o.NodeName, so add a check after the existing NodeName empty
validation that ensures o.NodeName is not longer than 108 characters (128 minus
20). Return an appropriate error if this validation fails to prevent repeated
write failures at runtime when the fieldManager length exceeds the Kubernetes
API limit.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 4ffa0f75-70ab-4860-83e2-6fffefb9f4fc

📥 Commits

Reviewing files that changed from the base of the PR and between b0f5231 and cb0904f.

⛔ Files ignored due to path filters (65)
  • go.sum is excluded by !**/*.sum
  • vendor/github.com/openshift/api/.ci-operator.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/Dockerfile.ocp is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/Makefile is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/types_authentication.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/types_tlssecurityprofile.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.deepcopy.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/config/v1/zz_generated.featuregated-crd-manifests.yaml is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/config/v1/zz_generated.swagger_doc_generated.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/config/v1alpha1/types_cluster_monitoring.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1alpha1/zz_generated.deepcopy.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/config/v1alpha1/zz_generated.swagger_doc_generated.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/features.md is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/features/features.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/features/legacyfeaturegates.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/types_authentication.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/types_etcd.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/types_ingresscontroller.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/types_kmsencryption.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/types_kubeapiserver.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/types_openshiftapiserver.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.deepcopy.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/operator/v1/zz_generated.featuregated-crd-manifests.yaml is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/operator/v1/zz_generated.swagger_doc_generated.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/route/v1/generated.proto is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/route/v1/types.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/route/v1/zz_generated.featuregated-crd-manifests.yaml is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/clientcredentialconfig.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/clientsecretsecretreference.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/customtlsprofile.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/externalclaimssource.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/externalsourceauthentication.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/externalsourcecertificateauthorityconfigmapreference.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/externalsourcepredicate.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/externalsourcetls.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/networkobservabilityspec.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/networkspec.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/oidcprovider.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/sourcedclaimmapping.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/sourceurl.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/tlsprofilespec.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/tlssecurityprofile.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/vaultapproleauthentication.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/vaultkmspluginconfig.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/vaulttlsconfig.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1alpha1/alertmanagercustomconfig.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1alpha1/clustermonitoringspec.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1alpha1/kubestatemetricsconfig.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1alpha1/kubestatemetricsresourcelabels.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1alpha1/nodeexporterconfig.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1alpha1/prometheusconfig.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1alpha1/retention.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1alpha1/thanosquerierconfig.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1alpha1/thanosquerierrequestloggingconfig.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/internal/internal.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/utils.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/operator/applyconfigurations/internal/internal.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/operator/applyconfigurations/operator/v1/etcdspec.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/operator/applyconfigurations/operator/v1/kmsencryptionstatus.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/operator/applyconfigurations/operator/v1/kmspluginhealthreport.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/operator/applyconfigurations/operator/v1/kubeapiserverstatus.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/operator/applyconfigurations/operator/v1/oauthapiserverstatus.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/operator/applyconfigurations/operator/v1/openshiftapiserverstatus.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/operator/applyconfigurations/utils.go is excluded by !**/vendor/**, !vendor/**
  • vendor/modules.txt is excluded by !**/vendor/**, !vendor/**
📒 Files selected for processing (6)
  • go.mod
  • pkg/operator/encryption/kms/health/cmd.go
  • pkg/operator/encryption/kms/health/cmd_test.go
  • pkg/operator/encryption/kms/health/prober.go
  • pkg/operator/encryption/kms/health/writer.go
  • pkg/operator/encryption/kms/health/writer_test.go

Comment thread go.mod Outdated
Comment thread go.mod Outdated
Comment thread pkg/operator/encryption/kms/health/cmd_test.go Outdated
Comment thread pkg/operator/encryption/kms/health/cmd.go Outdated
@ibihim ibihim changed the title [WIP] CNTRLPLANE-3234: health reporter writer CNTRLPLANE-3234: health reporter writer Jun 19, 2026
@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 Jun 19, 2026
Comment thread pkg/operator/encryption/kms/health/cmd.go Outdated
@ibihim ibihim force-pushed the CNTRLPLANE-3234-health-reporter-writer branch from cb0904f to 38f7db2 Compare June 19, 2026 14:34
@ibihim ibihim changed the title CNTRLPLANE-3234: health reporter writer [WIP] CNTRLPLANE-3234: health reporter writer Jun 19, 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 Jun 19, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@go.mod`:
- Around line 21-23: The three github.com/openshift dependencies (api,
build-machinery-go, and client-go) on lines 21-23 are currently pinned to
pseudo-versions (v0.0.0-YYYYMMDD format) which represent development commits
rather than stable releases, violating supply-chain security guidelines. To fix
this, either upgrade each of these three dependencies to their latest stable
released versions by updating the version strings in go.mod to actual release
versions (e.g., v1.x.y), or add a clear comment in the pull request description
explaining the justification for keeping pseudo-versions (such as awaiting an
upstream stable release or requiring an unreleased bug fix).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 00c0f63a-8803-4e7e-81a2-687c392838a8

📥 Commits

Reviewing files that changed from the base of the PR and between cb0904f and 38f7db2.

⛔ Files ignored due to path filters (65)
  • go.sum is excluded by !**/*.sum
  • vendor/github.com/openshift/api/.ci-operator.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/Dockerfile.ocp is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/Makefile is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/types_authentication.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/types_tlssecurityprofile.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.deepcopy.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/config/v1/zz_generated.featuregated-crd-manifests.yaml is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/config/v1/zz_generated.swagger_doc_generated.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/config/v1alpha1/types_cluster_monitoring.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1alpha1/zz_generated.deepcopy.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/config/v1alpha1/zz_generated.swagger_doc_generated.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/features.md is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/features/features.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/features/legacyfeaturegates.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/types_authentication.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/types_etcd.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/types_ingresscontroller.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/types_kmsencryption.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/types_kubeapiserver.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/types_openshiftapiserver.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.deepcopy.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/operator/v1/zz_generated.featuregated-crd-manifests.yaml is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/operator/v1/zz_generated.swagger_doc_generated.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/route/v1/generated.proto is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/route/v1/types.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/route/v1/zz_generated.featuregated-crd-manifests.yaml is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/clientcredentialconfig.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/clientsecretsecretreference.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/customtlsprofile.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/externalclaimssource.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/externalsourceauthentication.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/externalsourcecertificateauthorityconfigmapreference.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/externalsourcepredicate.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/externalsourcetls.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/networkobservabilityspec.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/networkspec.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/oidcprovider.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/sourcedclaimmapping.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/sourceurl.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/tlsprofilespec.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/tlssecurityprofile.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/vaultapproleauthentication.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/vaultkmspluginconfig.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/vaulttlsconfig.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1alpha1/alertmanagercustomconfig.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1alpha1/clustermonitoringspec.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1alpha1/kubestatemetricsconfig.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1alpha1/kubestatemetricsresourcelabels.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1alpha1/nodeexporterconfig.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1alpha1/prometheusconfig.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1alpha1/retention.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1alpha1/thanosquerierconfig.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1alpha1/thanosquerierrequestloggingconfig.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/internal/internal.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/config/applyconfigurations/utils.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/operator/applyconfigurations/internal/internal.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/operator/applyconfigurations/operator/v1/etcdspec.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/operator/applyconfigurations/operator/v1/kmsencryptionstatus.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/operator/applyconfigurations/operator/v1/kmspluginhealthreport.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/operator/applyconfigurations/operator/v1/kubeapiserverstatus.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/operator/applyconfigurations/operator/v1/oauthapiserverstatus.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/operator/applyconfigurations/operator/v1/openshiftapiserverstatus.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/client-go/operator/applyconfigurations/utils.go is excluded by !**/vendor/**, !vendor/**
  • vendor/modules.txt is excluded by !**/vendor/**, !vendor/**
📒 Files selected for processing (6)
  • go.mod
  • pkg/operator/encryption/kms/health/cmd.go
  • pkg/operator/encryption/kms/health/cmd_test.go
  • pkg/operator/encryption/kms/health/prober.go
  • pkg/operator/encryption/kms/health/writer.go
  • pkg/operator/encryption/kms/health/writer_test.go
🚧 Files skipped from review as they are similar to previous changes (5)
  • pkg/operator/encryption/kms/health/cmd_test.go
  • pkg/operator/encryption/kms/health/writer.go
  • pkg/operator/encryption/kms/health/prober.go
  • pkg/operator/encryption/kms/health/writer_test.go
  • pkg/operator/encryption/kms/health/cmd.go

Comment thread go.mod Outdated
@ibihim ibihim force-pushed the CNTRLPLANE-3234-health-reporter-writer branch from 38f7db2 to 1d303cb Compare June 23, 2026 09:49
@ibihim ibihim changed the title [WIP] CNTRLPLANE-3234: health reporter writer CNTRLPLANE-3234: health reporter writer Jun 24, 2026
@openshift-ci openshift-ci Bot added needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. and removed do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. labels Jun 24, 2026
ibihim added 2 commits June 25, 2026 10:47
Adds a health report writer. The construction is a bit awkward, but the
lib knows how to create the healthreport-to-be-applied-config and the
individual operator knows where to apply it.
@ibihim ibihim force-pushed the CNTRLPLANE-3234-health-reporter-writer branch from 496f469 to ca23cdf Compare June 25, 2026 08:48
@openshift-ci openshift-ci Bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jun 25, 2026
)

// applyOpts ensures that we are the dominant fieldManager.
func applyOpts(fieldManager string) metav1.ApplyOptions {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we really need this just for Force?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

no, we could remove it.

@ardaguclu ardaguclu left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Overall looks good to me

return fmt.Errorf("--node-name is required")
}
if fieldManager := fieldManagerPrefix + o.NodeName; len(fieldManager) > metav1validation.FieldManagerMaxLength {
return fmt.Errorf("--node-name too long: reporter identity %q is %d chars, exceeds the %d-char fieldManager limit", fieldManager, len(fieldManager), metav1validation.FieldManagerMaxLength)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can we really hit this error?.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

how would you even get out of this situation as an admin? rename your nodes?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

with the prefix we have like 100 characters left, I think it's OK. We can also make the prefix a bit shorter?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Maybe we can just continue as is and allow kube-apiserver errors out?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think he has a case with this, but we probably need a different solution here

checkout the max length we can have per node:
https://github.com/kubernetes/apimachinery/blob/master/pkg/api/validate/content/dns.go#L56-L57

@ardaguclu ardaguclu Jun 26, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I agree with Thomas. If it is possible, maybe we can use something else (uuid, hash, etc.) to remove that check. I think, other than this thread, this PR is ready to merge.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

we can do that as a follow-up. This is probably a bit bigger because we have to rename the cmdline and add this in the lifecycle

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What about cutting the static length from node name, if it exceeds?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

you'd have to cut the unique bits from the back and hope they don't have a subdomain per node, as Krzys says

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

That makes sense. Thank you

// Unique name per plugin so the gRPC client's KMS operation metrics
// don't merge both plugins into one series.
service, err := k8senvelopekmsv2.NewGRPCService(ctx, socket, Subcommand+"-"+keyID, timeout)
service, err := k8senvelopekmsv2.NewGRPCService(ctx, socket, fieldManagerPrefix+keyID, timeout)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
service, err := k8senvelopekmsv2.NewGRPCService(ctx, socket, fieldManagerPrefix+keyID, timeout)
service, err := k8senvelopekmsv2.NewGRPCService(ctx, socket, fmt.Sprintf("%s-%s", Subcommand, keyID), timeout)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

you can probably even leave this empty, nobody is going to look at the metric this string generates

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

OR just use the Subcommand on its own, I guess the metrics can then be sliced by node/podip or so which you get for free by prometheus scraper

// NewAuthenticationWriter writes into Authentication/cluster at
// .status.oauthAPIServer.encryptionStatus. The auth operator manages the
// oauth-apiserver. There is an extra hop the other two operators don't have.
func NewAuthenticationWriter(restConfig *rest.Config, fieldManager string) (health.EncryptionStatusWriter, error) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I really like this mechanism

require.Equal(t, want, have)
}

func TestMapStatus(t *testing.T) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we need this test?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I can remove it.


func TestBuildEncryptionStatus(t *testing.T) {
// Fixed UTC time dodges Go's monotonic clock and timezone drift.
checked := time.Unix(0, 0).UTC()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

There is a fakeclock, or something like this. Maybe we can use it


operatorClient, err := o.newOperatorClient(restCfg)
// fieldManager is the per-node ownership identity.
fieldManager := fieldManagerPrefix + o.NodeName

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

In another place we use fieldManagerPrefix + keyID but here we use fieldManagerPrefix + o.NodeName. Isn't this a discrepancy?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

+ o.NodeName distinguishes the 3 health reporters in the KAS setup. So this will be unique per writer.

+ keyID is to distinguish individual sockets within a node. This was the case in creating the service, but I dropped it to just the Subcommand according to #2318 (comment).

WithStatus(mapStatus(r.Status)).
WithLastCheckedTime(metav1.NewTime(r.LastChecked))

// kekId/detail have MinLength=1; setting "" would fail validation.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

for kekId I think the behavior is correct, because we want to retain the existing value, even when we transiently can't connect to the plugin.

The Detail, I'm not so sure. What do you think?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

AFAIU this is an alternating logic...

KekID would be empty on an error.
Detail would be empty without an error.


// mapStatus defaults to Error so an unknown value never becomes an empty,
// invalid enum.
func mapStatus(s string) operatorv1.KMSPluginHealthStatus {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

any reason not to directly return the operator constant from pluginHealthReport?

as in, you probably can just avoid that switch and put it directly into the prober logic

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

lol. This code goes through its third iteration at this point... I seem to have lost the eye for detail.

@ibihim ibihim Jun 25, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Do we need the "pluginHealthReport" struct at all, we could use the API directly, no?

Drop intermediate struct and go immediately for the SSA read config.
Address some other comments.
// EncryptionStatusWriter is capable of applying the
// KMSEncryptionStatusApplyConfiguration at the correct place in the operator's
// status.
type EncryptionStatusWriter func(ctx context.Context, status *applyoperatorv1.KMSEncryptionStatusApplyConfiguration) error

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Add this point, we could move this to cmd.go. It is small enough.

If cmd.go is considered too big, we could move out the options logic into its own file.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just an idea; Maybe we can move functions under writers/writers.go to here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I liked the idea to have them as something distinct, like they would be "already on the operator side". But if you like I could move them here.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not needed. That works for me. Thank you

@ardaguclu

Copy link
Copy Markdown
Member

@ibihim the task that wiring of health reporter to the operators has been finished. Now you can test this PR on operators via fake bump. So that we can verify that changes here work.

@ardaguclu

Copy link
Copy Markdown
Member

CI Job in fake PR proves that health of kms plugins are reported;

$ omc get authentications.operator.openshift.io cluster -oyaml
apiVersion: operator.openshift.io/v1
kind: Authentication
metadata:
  annotations:
    include.release.openshift.io/self-managed-high-availability: "true"
    include.release.openshift.io/single-node-developer: "true"
    release.openshift.io/create-only: "true"
  creationTimestamp: "2026-06-29T16:02:49Z"
  generation: 11
  name: cluster
....
oauthAPIServer:
    encryptionStatus:
      healthReports:
      - kekId: CgQKAnYxGjwKJgoFYWRtaW4aHQobaHR0cHM6Ly8xNzIuMzAuMjM4LjE2Nzo4MjAwGgd0cmFuc2l0IgdrbXMta2V5KA
        keyId: "6"
        lastCheckedTime: "2026-06-29T17:49:06Z"
        nodeName: ip-10-0-42-231.ec2.internal
        status: Healthy
      - kekId: CgQKAnYxGjwKJgoFYWRtaW4aHQobaHR0cHM6Ly8xNzIuMzAuMjM4LjE2Nzo4MjAwGgd0cmFuc2l0IgdrbXMta2V5KA
        keyId: "6"
        lastCheckedTime: "2026-06-29T17:49:09Z"
        nodeName: ip-10-0-20-198.ec2.internal
        status: Healthy
      - kekId: CgQKAnYxGjwKJgoFYWRtaW4aHQobaHR0cHM6Ly8xNzIuMzAuMjM4LjE2Nzo4MjAwGgd0cmFuc2l0IgdrbXMta2V5KA
        keyId: "6"
        lastCheckedTime: "2026-06-29T17:49:04Z"
        nodeName: ip-10-0-2-175.ec2.internal
        status: Healthy

return fmt.Errorf("--node-name is required")
}
if fieldManager := fmt.Sprintf("%s-%s", Subcommand, o.NodeName); len(fieldManager) > metav1validation.FieldManagerMaxLength {
return fmt.Errorf("--node-name too long: reporter identity %q is %d chars, exceeds the %d-char fieldManager limit", fieldManager, len(fieldManager), metav1validation.FieldManagerMaxLength)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This one is probably the only part that requires a change.

@ibihim ibihim force-pushed the CNTRLPLANE-3234-health-reporter-writer branch 2 times, most recently from dcfc42c to df08a04 Compare July 1, 2026 06:53

// NewKubeAPIServerWriter writes into KubeAPIServer/cluster at
// .status.encryptionStatus.
func NewKubeAPIServerWriter(restConfig *rest.Config, nodeName string) (health.EncryptionStatusWriter, error) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

In the previous version, writers were consistent. They just accept the field manager and set it accordingly. Now we leak the field manager extraction into the writer and this makes them inconsistent (some hardcodes, some send request to API Server). In my opinion, it would be better to return back to previous version by passing field manager.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Honestly, I thought this is my master piece :D The operators themselves know best what to put in there, but based on the discussion in the other comment, we can keep it as is.

// The writer owns its fieldManager: it turns the node name into whatever
// ownership identity its status needs (a per-node UID for the kube-apiserver,
// a constant for the single-reporter operators).
writeStatus, err := o.newWriter(restCfg, o.NodeName)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can't we get UID here and pass it as field manager to newWriter?. Why shouldn't we use UID for aggregated apiservers?.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

what if we do a simpler step and just set the --node-name argument as the node.UUID instead of the node.Name from the lifecycle.

We can rename the argument later. I don't really think we should be querying node objects from here just to resolve the name.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah, I must admit, that querying node-objects is not optimal, but I didn't want to offload it to somewhere else, but we can do so. Maybe the lifecycle has it at hand already.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I can drop the comment and we "interpret" the node-name flag creatively as something unique within bounds like an UID?

I might adjust the description for the flag, but not sure if it is worth changing the flag itself, maybe? Because of tests? WDYT?

@ibihim ibihim force-pushed the CNTRLPLANE-3234-health-reporter-writer branch from df08a04 to 6f33b49 Compare July 2, 2026 12:55
@tjungblu

tjungblu commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

/retest

@tjungblu

tjungblu commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

/approve
/lgtm

I have a bit of time at my hands to figure out the nodename hashing

@openshift-ci openshift-ci Bot added the lgtm Indicates that a PR is ready to be merged. label Jul 2, 2026
@openshift-ci

openshift-ci Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: ibihim, tjungblu
Once this PR has been reviewed and has the lgtm label, please assign dgrisonnet 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

@openshift-ci

openshift-ci Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

@ibihim: all tests passed!

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

jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. lgtm Indicates that a PR is ready to be merged.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants