Skip to content

STOR-2859: Add APIs for disabling force detach in KCM operator - #2668

Open
dobsonj wants to merge 1 commit into
openshift:masterfrom
dobsonj:STOR-2859
Open

dobsonj wants to merge 1 commit into
openshift:masterfrom
dobsonj:STOR-2859

Conversation

@dobsonj

@dobsonj dobsonj commented Jan 24, 2026 •

Copy link
Copy Markdown
Member

User description

https://issues.redhat.com/browse/STOR-2859

This PR introduces an API to disable force detach in kube-controller-manager. The design is based on this slack discussion (internal only). There is already a KubeControllerManager operator type to configure cluster-kube-controller-manager-operator, and this PR introduces a ControllerManager config type to configure kube-controller-manager. This is approach is consistent with other workload components like KubeAPIServer / APIServer and KubeScheduler / Scheduler.

controllerManager.spec.forceDetachOnTimeout will be used to enable or disable force detach in KCM.

/cc @openshift/storage


PR Type

Enhancement


Description

  • Add ControllerManager API for cluster-wide Kubernetes controller manager configuration

  • Introduce ForceDetachOnTimeoutPolicy to control volume force detach behavior

  • Generate deepcopy, swagger documentation, and OpenAPI schema definitions

  • Create CustomResourceDefinition manifest for controllermanagers resource


Diagram Walkthrough

flowchart LR
  A["ControllerManager API Type"] --> B["ForceDetachOnTimeoutPolicy"]
  A --> C["ControllerManagerSpec"]
  C --> E["forceDetachOnTimeout Field"]
  E --> F["Enabled/Disabled/Omitted"]
  A --> G["Generated Code"]
  G --> H["DeepCopy Functions"]
  G --> I["Swagger Documentation"]
  G --> J["OpenAPI Schemas"]
  A --> K["CRD Manifest"]
Loading

File Walkthrough

Relevant files
Enhancement
types_controllermanager.go
Define ControllerManager API types and policy                       

config/v1alpha1/types_controllermanager.go

  • Define new ControllerManager struct with metadata and spec
    fields
  • Create ControllerManagerSpec with ForceDetachOnTimeoutPolicy field
  • Define ForceDetachOnTimeoutPolicy type with Enabled and Disabled
    constants
  • Create ControllerManagerList struct for list operations
+72/-0   
Code generation
zz_generated.deepcopy.go
Generate deepcopy functions for ControllerManager types   

config/v1alpha1/zz_generated.deepcopy.go

  • Generate DeepCopyInto, DeepCopy, and DeepCopyObject methods for
    ControllerManager
  • Generate deepcopy methods for ControllerManagerList
  • Generate deepcopy methods for ControllerManagerSpec
+93/-0   
zz_generated.swagger_doc_generated.go
Generate swagger documentation for ControllerManager         

config/v1alpha1/zz_generated.swagger_doc_generated.go

  • Add swagger documentation map for ControllerManager type
  • Add swagger documentation map for ControllerManagerList type
  • Add swagger documentation map for ControllerManagerSpec type
  • Document field descriptions and compatibility level
+28/-0   
zz_generated.openapi.go
Generate OpenAPI schema definitions for ControllerManager

openapi/generated_openapi/zz_generated.openapi.go

  • Register OpenAPI schema definitions for ControllerManager,
    ControllerManagerList, and ControllerManagerSpec
  • Generate schema_openshift_api_config_v1_ControllerManager function
    with properties and dependencies
  • Generate schema_openshift_api_config_v1_ControllerManagerList function
    with items array
  • Generate schema_openshift_api_config_v1_ControllerManagerSpec schema functions
+135/-0 
Configuration
0000_10_config-operator_01_controllermanagers.crd.yaml
Create ControllerManager CustomResourceDefinition manifest

config/v1alpha1/zz_generated.crd-manifests/0000_10_config-operator_01_controllermanagers.crd.yaml

  • Create CustomResourceDefinition manifest for
    controllermanagers.config.openshift.io
  • Define spec with forceDetachOnTimeout property supporting Enabled,
    Disabled, and empty string values
  • Configure cluster-scoped resource
  • Include API approval reference
+73/-0   
zz_generated.featuregated-crd-manifests.yaml
Register ControllerManager in featuregated manifests         

config/v1alpha1/zz_generated.featuregated-crd-manifests.yaml

  • Add controllermanagers.config.openshift.io entry to featuregated CRD
    manifests
  • Register metadata including operator name, run level, and scope
    information
+22/-0   
AAA_ungated.yaml
Create ungated ControllerManager CRD manifest                       

config/v1alpha1/zz_generated.featuregated-crd-manifests/controllermanagers.config.openshift.io/AAA_ungated.yaml

  • Create ungated CustomResourceDefinition manifest for
    controllermanagers resource
  • Define identical schema to main CRD manifest with feature-gate
    annotations
  • Configure cluster scope resource
+74/-0   

@openshift-ci-robot

Copy link
Copy Markdown

Pipeline controller notification
This repo is configured to use the pipeline controller. Second-stage tests will be triggered either automatically or after lgtm label is added, depending on the repository configuration. The pipeline controller will automatically detect which contexts are required and will utilize /test Prow commands to trigger the second stage.

For optional jobs, comment /test ? to see a list of all defined jobs. To trigger manually all jobs from second stage use /pipeline required command.

This repository is configured in: LGTM mode

@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 24, 2026
@openshift-ci-robot

openshift-ci-robot commented Jan 24, 2026 •

Copy link
Copy Markdown

@dobsonj: This pull request references STOR-2859 which is a valid jira issue.

Details

In response to this:

https://issues.redhat.com/browse/STOR-2859

/cc @openshift/storage

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 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 24, 2026
@openshift-ci

openshift-ci Bot commented Jan 24, 2026

Copy link
Copy Markdown
Contributor

Hello @dobsonj! Some important instructions when contributing to openshift/api:
API design plays an important part in the user experience of OpenShift and as such API PRs are subject to a high level of scrutiny to ensure they follow our best practices. If you haven't already done so, please review the OpenShift API Conventions and ensure that your proposed changes are compliant. Following these conventions will help expedite the api review process for your PR.

@openshift-ci

openshift-ci Bot commented Jan 24, 2026 •

Copy link
Copy Markdown
Contributor

@dobsonj: GitHub didn't allow me to request PR reviews from the following users: openshift/storage.

Note that only openshift members and repo collaborators can review this PR, and authors cannot review their own PRs.

Details

In response to this:

https://issues.redhat.com/browse/STOR-2859

/cc @openshift/storage

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.

@coderabbitai

coderabbitai Bot commented Jan 24, 2026 •

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: a527c695-bec4-4b04-b282-3b7e640fa399

📥 Commits

Reviewing files that changed from the base of the PR and between 0ab90fb and 3518de8.

⛔ Files ignored due to path filters (9)
  • config/v1alpha1/zz_generated.crd-manifests/0000_10_config-operator_01_controllermanagers.crd.yaml is excluded by !**/zz_generated.crd-manifests/*
  • config/v1alpha1/zz_generated.deepcopy.go is excluded by !**/zz_generated*
  • config/v1alpha1/zz_generated.featuregated-crd-manifests.yaml is excluded by !**/zz_generated*
  • config/v1alpha1/zz_generated.featuregated-crd-manifests/controllermanagers.config.openshift.io/ControllerManagerConfig.yaml is excluded by !**/zz_generated.featuregated-crd-manifests/**
  • config/v1alpha1/zz_generated.featuregated-crd-manifests/controllermanagers.config.openshift.io/DisableForceDetachOnTimeout.yaml is excluded by !**/zz_generated.featuregated-crd-manifests/**
  • config/v1alpha1/zz_generated.model_name.go is excluded by !**/zz_generated*
  • config/v1alpha1/zz_generated.swagger_doc_generated.go is excluded by !**/zz_generated*
  • openapi/generated_openapi/zz_generated.openapi.go is excluded by !openapi/**, !**/zz_generated*
  • openapi/openapi.json is excluded by !openapi/**
📒 Files selected for processing (3)
  • features/features.go
  • payload-manifests/featuregates/featureGate-4-10-Hypershift-DevPreviewNoUpgrade.yaml
  • payload-manifests/featuregates/featureGate-4-10-SelfManagedHA-DevPreviewNoUpgrade.yaml

Included review availability: Your plan provides up to 12 included reviews per hour; 11 remain after this review.


📝 Walkthrough

Walkthrough

This change adds the cluster-scoped ControllerManager v1alpha1 API and registers its resource types. It defines the forceDetachOnTimeout policy and validates singleton naming and supported values. It adds the CRD, generated API metadata, OpenAPI definitions, and deepcopy methods. It adds paired feature gates, CRD validation tests, payload feature-gate settings, and CRD payload synchronization.

Suggested reviewers: saschagrunert

Priority: ➖ Normal

Merge Risk: ⚪ Minimal · up to 3518d

This adds the ControllerManager API and feature-gated configuration without any remaining concrete merge-blocking risk identified in the supplied evidence.

🚥 Pre-merge checks | ✅ 14 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 8 functions across 5 files. (2 skipped: 2… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (14 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely identifies the main change: adding APIs to disable force detach in kube-controller-manager.
Description check ✅ Passed The description directly explains the new ControllerManager API, force-detach configuration, generated artifacts, feature gates, and CRD manifests. It is related to the changeset.
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 The PR adds five declarative test titles in two YAML suites. Each title is a fixed descriptive string. No title contains a generated name, timestamp, UUID, node name, namespace, IP address, or other r…
Test Structure And Quality ✅ Passed The pull request adds only declarative YAML CRD test fixtures under config/v1alpha1/tests/...; it adds no Ginkgo or Go test files. The fixtures use onCreate and onUpdate cases with expected obje…
Microshift Test Compatibility ✅ Passed PASS: The pull-request diff adds no Ginkgo e2e tests. The two added files under config/v1alpha1/tests/... are declarative YAML API test configurations, not It, Describe, Context, or When tes…
Single Node Openshift (Sno) Test Compatibility ✅ Passed The pull request adds no Ginkgo e2e tests. The two added YAML files are API/CRD test configurations and contain no It(), Describe(), Context(), When(), or related Ginkgo constructs. Therefore, the SNO…
Topology-Aware Scheduling Compatibility ✅ Passed The pull request adds API types, CRD manifests, generated schemas, tests, and feature-gate entries. The authoritative diff adds no Deployments, DaemonSets, StatefulSets, controllers, operator scheduli…
Ote Binary Stdout Contract ✅ Passed The pull request adds API types, scheme/generated code, feature gates, CRD manifests, and YAML configuration tests. The authoritative diff adds no fmt/log/klog stdout writes, process entry point…
Ipv6 And Disconnected Network Test Compatibility ✅ Passed PASS — The pull request adds CRD validation test configuration in YAML, not Ginkgo e2e tests. The added tests only create and update ControllerManager objects and validate names and enum values. No …
No-Weak-Crypto ✅ Passed No weak cryptography was introduced. The authoritative PR diff adds API types, generated deepcopy/OpenAPI/Swagger code, CRD manifests, tests, and feature-gate entries. The new Go API source imports on…
Container-Privileges ✅ Passed The PR adds CRD, FeatureGate, API, and CRD test files only. The reviewed diff contains no Pod or controller workload manifests and no privileged, hostPID, hostNetwork, hostIPC, SYS_ADMIN, `a…
No-Sensitive-Data-In-Logs ✅ Passed The pull-request diff adds API types, generated schemas, CRD manifests, feature gates, and validation tests. It adds no logging calls, logger imports, or output writes. The added test and schema conte…
Full details: Docstring Coverage

Explanation

Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 8 functions across 5 files. (2 skipped: 2 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Create a new PR

Warning

Some tools did not complete. Review the errors below.

🔧 golangci-lint (2.13.2)

Error: build linters: unable to load custom analyzer "kubeapilinter": tools/_output/bin/kube-api-linter.so, plugin: not implemented
The command is terminated due to an error: build linters: unable to load custom analyzer "kubeapilinter": tools/_output/bin/kube-api-linter.so, plugin: not implemented


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

@openshift-ci openshift-ci Bot added the size/L Denotes a PR that changes 100-499 lines, ignoring generated files. label Jan 24, 2026
@openshift-ci-robot

openshift-ci-robot commented Jan 24, 2026 •

Copy link
Copy Markdown

@dobsonj: This pull request references STOR-2859 which is a valid jira issue.

Details

In response to this:

User description

https://issues.redhat.com/browse/STOR-2859

/cc @openshift/storage


PR Type

Enhancement


Description

  • Add ControllerManager API for cluster-wide Kubernetes controller manager configuration

  • Introduce ForceDetachOnTimeoutPolicy to control volume force detach behavior

  • Generate deepcopy, swagger documentation, and OpenAPI schema definitions

  • Create CustomResourceDefinition manifest for controllermanagers resource


Diagram Walkthrough

flowchart LR
 A["ControllerManager API Type"] --> B["ForceDetachOnTimeoutPolicy"]
 A --> C["ControllerManagerSpec"]
 A --> D["ControllerManagerStatus"]
 C --> E["forceDetachOnTimeout Field"]
 E --> F["Enabled/Disabled/Omitted"]
 A --> G["Generated Code"]
 G --> H["DeepCopy Functions"]
 G --> I["Swagger Documentation"]
 G --> J["OpenAPI Schemas"]
 A --> K["CRD Manifest"]
Loading

File Walkthrough

Relevant files
Enhancement
types_controllermanager.go
Define ControllerManager API types and policy                       

config/v1/types_controllermanager.go

  • Define new ControllerManager struct with metadata, spec, and status
    fields
  • Create ControllerManagerSpec with ForceDetachOnTimeoutPolicy field
  • Define ForceDetachOnTimeoutPolicy type with Enabled and Disabled
    constants
  • Create ControllerManagerList struct for list operations
+72/-0   
Code generation
zz_generated.deepcopy.go
Generate deepcopy functions for ControllerManager types   

config/v1/zz_generated.deepcopy.go

  • Generate DeepCopyInto, DeepCopy, and DeepCopyObject methods for
    ControllerManager
  • Generate deepcopy methods for ControllerManagerList
  • Generate deepcopy methods for ControllerManagerSpec
  • Generate deepcopy methods for ControllerManagerStatus
+93/-0   
zz_generated.swagger_doc_generated.go
Generate swagger documentation for ControllerManager         

config/v1/zz_generated.swagger_doc_generated.go

  • Add swagger documentation map for ControllerManager type
  • Add swagger documentation map for ControllerManagerList type
  • Add swagger documentation map for ControllerManagerSpec type
  • Document field descriptions and compatibility level
+28/-0   
zz_generated.openapi.go
Generate OpenAPI schema definitions for ControllerManager

openapi/generated_openapi/zz_generated.openapi.go

  • Register OpenAPI schema definitions for ControllerManager,
    ControllerManagerList, ControllerManagerSpec, and
    ControllerManagerStatus
  • Generate schema_openshift_api_config_v1_ControllerManager function
    with properties and dependencies
  • Generate schema_openshift_api_config_v1_ControllerManagerList function
    with items array
  • Generate schema_openshift_api_config_v1_ControllerManagerSpec and
    ControllerManagerStatus schema functions
+135/-0 
Configuration
0000_10_config-operator_01_controllermanagers.crd.yaml
Create ControllerManager CustomResourceDefinition manifest

config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_controllermanagers.crd.yaml

  • Create CustomResourceDefinition manifest for
    controllermanagers.config.openshift.io
  • Define spec with forceDetachOnTimeout property supporting Enabled,
    Disabled, and empty string values
  • Configure cluster-scoped resource with status subresource
  • Include bootstrap-required annotation and API approval reference
+73/-0   
zz_generated.featuregated-crd-manifests.yaml
Register ControllerManager in featuregated manifests         

config/v1/zz_generated.featuregated-crd-manifests.yaml

  • Add controllermanagers.config.openshift.io entry to featuregated CRD
    manifests
  • Register metadata including operator name, run level, and scope
    information
  • Mark as bootstrap-required and ungated feature
+22/-0   
AAA_ungated.yaml
Create ungated ControllerManager CRD manifest                       

config/v1/zz_generated.featuregated-crd-manifests/controllermanagers.config.openshift.io/AAA_ungated.yaml

  • Create ungated CustomResourceDefinition manifest for
    controllermanagers resource
  • Define identical schema to main CRD manifest with feature-gate
    annotations
  • Configure cluster scope with status subresource and bootstrap
    requirement
+74/-0   

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.

1 similar comment
@openshift-ci-robot

openshift-ci-robot commented Jan 24, 2026 •

Copy link
Copy Markdown

@dobsonj: This pull request references STOR-2859 which is a valid jira issue.

Details

In response to this:

User description

https://issues.redhat.com/browse/STOR-2859

/cc @openshift/storage


PR Type

Enhancement


Description

  • Add ControllerManager API for cluster-wide Kubernetes controller manager configuration

  • Introduce ForceDetachOnTimeoutPolicy to control volume force detach behavior

  • Generate deepcopy, swagger documentation, and OpenAPI schema definitions

  • Create CustomResourceDefinition manifest for controllermanagers resource


Diagram Walkthrough

flowchart LR
 A["ControllerManager API Type"] --> B["ForceDetachOnTimeoutPolicy"]
 A --> C["ControllerManagerSpec"]
 A --> D["ControllerManagerStatus"]
 C --> E["forceDetachOnTimeout Field"]
 E --> F["Enabled/Disabled/Omitted"]
 A --> G["Generated Code"]
 G --> H["DeepCopy Functions"]
 G --> I["Swagger Documentation"]
 G --> J["OpenAPI Schemas"]
 A --> K["CRD Manifest"]
Loading

File Walkthrough

Relevant files
Enhancement
types_controllermanager.go
Define ControllerManager API types and policy                       

config/v1/types_controllermanager.go

  • Define new ControllerManager struct with metadata, spec, and status
    fields
  • Create ControllerManagerSpec with ForceDetachOnTimeoutPolicy field
  • Define ForceDetachOnTimeoutPolicy type with Enabled and Disabled
    constants
  • Create ControllerManagerList struct for list operations
+72/-0   
Code generation
zz_generated.deepcopy.go
Generate deepcopy functions for ControllerManager types   

config/v1/zz_generated.deepcopy.go

  • Generate DeepCopyInto, DeepCopy, and DeepCopyObject methods for
    ControllerManager
  • Generate deepcopy methods for ControllerManagerList
  • Generate deepcopy methods for ControllerManagerSpec
  • Generate deepcopy methods for ControllerManagerStatus
+93/-0   
zz_generated.swagger_doc_generated.go
Generate swagger documentation for ControllerManager         

config/v1/zz_generated.swagger_doc_generated.go

  • Add swagger documentation map for ControllerManager type
  • Add swagger documentation map for ControllerManagerList type
  • Add swagger documentation map for ControllerManagerSpec type
  • Document field descriptions and compatibility level
+28/-0   
zz_generated.openapi.go
Generate OpenAPI schema definitions for ControllerManager

openapi/generated_openapi/zz_generated.openapi.go

  • Register OpenAPI schema definitions for ControllerManager,
    ControllerManagerList, ControllerManagerSpec, and
    ControllerManagerStatus
  • Generate schema_openshift_api_config_v1_ControllerManager function
    with properties and dependencies
  • Generate schema_openshift_api_config_v1_ControllerManagerList function
    with items array
  • Generate schema_openshift_api_config_v1_ControllerManagerSpec and
    ControllerManagerStatus schema functions
+135/-0 
Configuration
0000_10_config-operator_01_controllermanagers.crd.yaml
Create ControllerManager CustomResourceDefinition manifest

config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_controllermanagers.crd.yaml

  • Create CustomResourceDefinition manifest for
    controllermanagers.config.openshift.io
  • Define spec with forceDetachOnTimeout property supporting Enabled,
    Disabled, and empty string values
  • Configure cluster-scoped resource with status subresource
  • Include bootstrap-required annotation and API approval reference
+73/-0   
zz_generated.featuregated-crd-manifests.yaml
Register ControllerManager in featuregated manifests         

config/v1/zz_generated.featuregated-crd-manifests.yaml

  • Add controllermanagers.config.openshift.io entry to featuregated CRD
    manifests
  • Register metadata including operator name, run level, and scope
    information
  • Mark as bootstrap-required and ungated feature
+22/-0   
AAA_ungated.yaml
Create ungated ControllerManager CRD manifest                       

config/v1/zz_generated.featuregated-crd-manifests/controllermanagers.config.openshift.io/AAA_ungated.yaml

  • Create ungated CustomResourceDefinition manifest for
    controllermanagers resource
  • Define identical schema to main CRD manifest with feature-gate
    annotations
  • Configure cluster scope with status subresource and bootstrap
    requirement
+74/-0   

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.

@qodo-code-review

qodo-code-review Bot commented Jan 24, 2026 •

Copy link
Copy Markdown

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
🟢
No security concerns identified No security vulnerabilities detected by AI analysis. Human verification advised for critical code.
Ticket Compliance
⚪
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
⚪
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

🔴
Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status:
Optional field not omittable: ForceDetachOnTimeout is documented as optional/omittable but is a non-pointer field
without omitempty, so it will serialize as "" and cannot reliably represent
“omitted/no opinion.”

Referred Code
type ControllerManagerSpec struct {
	// ForceDetachOnTimeout allows the admin to enable or disable
	// force detaching volumes based on a timeout.
	// Valid values are Enabled, Disabled and omitted.
	// Omitted means no opinion and the platform is left to choose
	// a reasonable default, which is subject to change over time.
	// The current default is Enabled.
	// +optional
	ForceDetachOnTimeout ForceDetachOnTimeoutPolicy `json:"forceDetachOnTimeout"`
}

Learn more about managing compliance generic rules or creating your own custom rules

  • Update
Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@openshift-ci

openshift-ci Bot commented Jan 24, 2026

Copy link
Copy Markdown
Contributor

[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 everettraven 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

@qodo-code-review

qodo-code-review Bot commented Jan 24, 2026 •

Copy link
Copy Markdown

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
High-level
✅ Consider if a new CRD is justified
Suggestion Impact:The newly introduced ControllerManager CRD/types were removed entirely (types_controllermanager.go deleted), aligning with the suggestion to avoid creating a new CRD for a single field.

code diff:

# File: config/v1/types_controllermanager.go
@@ -1,76 +1 @@
-package v1
 
-import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-
-// +genclient
-// +genclient:nonNamespaced
-// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
-
-// ControllerManager holds cluster-wide config information to run the Kubernetes controller manager
-// and influence its placement decisions. The canonical name for this config is `cluster`.
-//
-// Compatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer).
-// +openshift:compatibility-gen:level=1
-// +openshift:api-approved.openshift.io=https://github.com/openshift/api/pull/2668
-// +openshift:file-pattern=cvoRunLevel=0000_10,operatorName=config-operator,operatorOrdering=01
-// +kubebuilder:object:root=true
-// +kubebuilder:resource:path=controllermanagers,scope=Cluster
-// +kubebuilder:subresource:status
-// +kubebuilder:metadata:annotations=release.openshift.io/bootstrap-required=true
-type ControllerManager struct {
-	metav1.TypeMeta `json:",inline"`
-
-	// metadata is the standard object's metadata.
-	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
-	// +optional
-	metav1.ObjectMeta `json:"metadata,omitzero"`
-	// spec holds user settable values for configuration
-	// +required
-	Spec ControllerManagerSpec `json:"spec,omitzero"`
-	// status holds observed values from the cluster. They may not be overridden.
-	// +optional
-	Status ControllerManagerStatus `json:"status,omitzero"`
-}
-
-// ControllerManagerSpec defines the desired state of the Kubernetes controller manager
-// +kubebuilder:validation:MinProperties=1
-type ControllerManagerSpec struct {
-	// forceDetachOnTimeout expresses whether to allow kube-controller-manager
-	// to force detach volumes when unmount takes longer than the timeout.
-	// Valid values are Enabled and Disabled. If omitted, the default is Enabled.
-	// +default="Enabled"
-	// +optional
-	ForceDetachOnTimeout ForceDetachOnTimeoutPolicy `json:"forceDetachOnTimeout,omitempty"`
-}
-
-// +kubebuilder:validation:Enum=Enabled;Disabled
-type ForceDetachOnTimeoutPolicy string
-
-const (
-	// ForceDetachOnTimeoutEnabled will allow kube-controller-manager to
-	// force detach volumes based on maximum unmount time and node status.
-	ForceDetachOnTimeoutEnabled  ForceDetachOnTimeoutPolicy = "Enabled"
-	// ForceDetachOnTimeoutDisabled will prevent kube-controller-manager
-	// from force detaching volumes.
-	ForceDetachOnTimeoutDisabled ForceDetachOnTimeoutPolicy = "Disabled"
-)
-
-// ControllerManagerStatus defines the observed state of the Kubernetes controller manager
-// +kubebuilder:validation:MinProperties=1
-type ControllerManagerStatus struct {
-}
-
-// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
-
-// Compatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer).
-// +openshift:compatibility-gen:level=1
-type ControllerManagerList struct {
-	metav1.TypeMeta `json:",inline"`
-
-	// metadata is the standard list's metadata.
-	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
-	metav1.ListMeta `json:"metadata"`
-
-	Items []ControllerManager `json:"items"`
-}

The suggestion questions the creation of a new ControllerManager CRD for just a
single configuration field. It asks for justification, such as plans for future
additions, to validate introducing a new top-level API.

Examples:

config/v1/types_controllermanager.go [20-43]
type ControllerManager struct {
	metav1.TypeMeta `json:",inline"`

	// metadata is the standard object's metadata.
	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
	metav1.ObjectMeta `json:"metadata,omitempty"`
	// spec holds user settable values for configuration
	// +required
	Spec ControllerManagerSpec `json:"spec"`
	// status holds observed values from the cluster. They may not be overridden.

 ... (clipped 14 lines)

Solution Walkthrough:

Before:

// File: config/v1/types_controllermanager.go

// A new CRD is introduced
type ControllerManager struct {
  metav1.TypeMeta   `json:",inline"`
  metav1.ObjectMeta `json:"metadata,omitempty"`
  Spec ControllerManagerSpec `json:"spec"`
  Status ControllerManagerStatus `json:"status"`
}

// The spec for the new CRD contains only one field
type ControllerManagerSpec struct {
  ForceDetachOnTimeout ForceDetachOnTimeoutPolicy `json:"forceDetachOnTimeout"`
}

type ControllerManagerStatus struct {}

After:

// The suggestion implies that instead of a new CRD,
// the new field could be added to an existing, related CRD.
// For example (conceptual):

// File: config/v1/types_some_existing_crd.go

type SomeExistingCRDSpec struct {
  // ... existing fields ...

  // The new field is added here, avoiding a new CRD
  ControllerManager ControllerManagerConfig `json:"controllerManager,omitempty"`
}

type ControllerManagerConfig struct {
    ForceDetachOnTimeout ForceDetachOnTimeoutPolicy `json:"forceDetachOnTimeout,omitempty"`
}
Suggestion importance[1-10]: 8

__

Why: The suggestion raises a critical API design question about the justification for creating an entirely new CRD for a single configuration field, which has long-term implications for the API surface and maintainability.

Medium
General
Add conditions field to status

Add a Conditions field of type []metav1.Condition to the ControllerManagerStatus
struct to align with Kubernetes API best practices for status reporting.

config/v1/types_controllermanager.go [57-58]

 type ControllerManagerStatus struct {
+	// conditions provide details on the status of the controller manager configuration.
+	// +optional
+	Conditions []metav1.Condition `json:"conditions,omitempty"`
 }
  • Apply / Chat
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly recommends adding a standard conditions field to the status struct, which is a Kubernetes API best practice that improves extensibility and observability.

Medium
Possible issue
✅ Omit empty JSON field
Suggestion Impact:The commit updated the `ForceDetachOnTimeout` field JSON tag from `json:"forceDetachOnTimeout"` to `json:"forceDetachOnTimeout,omitempty"`, omitting the field when empty.

code diff:

-	// ForceDetachOnTimeout allows the admin to enable or disable
-	// force detaching volumes based on a timeout.
-	// Valid values are Enabled, Disabled and omitted.
-	// Omitted means no opinion and the platform is left to choose
-	// a reasonable default, which is subject to change over time.
-	// The current default is Enabled.
+	// forceDetachOnTimeout expresses whether to allow kube-controller-manager
+	// to force detach volumes when unmount takes longer than the timeout.
+	// Valid values are Enabled and Disabled. If omitted, the default is Enabled.
+	// +default=Enabled
 	// +optional
-	ForceDetachOnTimeout ForceDetachOnTimeoutPolicy `json:"forceDetachOnTimeout"`
+	ForceDetachOnTimeout ForceDetachOnTimeoutPolicy `json:"forceDetachOnTimeout,omitempty"`
 }

Add omitempty to the json tag of the forceDetachOnTimeout field.

config/v1/types_controllermanager.go [41-42]

 // +optional
-ForceDetachOnTimeout ForceDetachOnTimeoutPolicy `json:"forceDetachOnTimeout"`
+ForceDetachOnTimeout ForceDetachOnTimeoutPolicy `json:"forceDetachOnTimeout,omitempty"`

[Suggestion processed]

Suggestion importance[1-10]: 6

__

Why: The suggestion correctly identifies that an optional field is missing omitempty in its JSON tag, and adding it aligns with Kubernetes API best practices for cleaner resource definitions.

Low
  • Update

@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: 2

🤖 Fix all issues with AI agents
In `@config/v1/types_controllermanager.go`:
- Around line 12-15: The +openshift:api-approved annotation in the header
comment of types_controllermanager.go still uses the placeholder URL
"https://github.com/openshift/api/pull/XYZ"; update that annotation to the
actual API approval PR URL (the real pull request number) so it passes API
approval checks—locate the comment block containing
"+openshift:api-approved.openshift.io" and replace the placeholder with the real
PR link.

In `@config/v1/zz_generated.featuregated-crd-manifests.yaml`:
- Around line 199-203: Update the placeholder ApprovedPRNumber value for the CRD
entry with CRDName controllermanagers.config.openshift.io: replace
"https://github.com/openshift/api/pull/XYZ" with the real approval PR URL (or
the correct PR number path) so the ApprovedPRNumber field references the actual
merged/approved PR; ensure the URL is valid and points to the final PR in the
openshift/api repo.
🧹 Nitpick comments (1)
config/v1/types_controllermanager.go (1)

34-42: Add omitempty to the optional enum field for consistency.

ForceDetachOnTimeout is marked optional and should use omitempty in its JSON tag, consistent with other optional enum fields throughout the config/v1 API group (e.g., Platform, CgroupMode, WorkerLatencyProfile). This keeps manifests clean by omitting the field when unset.

♻️ Proposed change
-	ForceDetachOnTimeout ForceDetachOnTimeoutPolicy `json:"forceDetachOnTimeout"`
+	ForceDetachOnTimeout ForceDetachOnTimeoutPolicy `json:"forceDetachOnTimeout,omitempty"`

Comment thread config/v1/types_controllermanager.go Outdated
Comment thread config/v1/zz_generated.featuregated-crd-manifests.yaml Outdated

@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

🤖 Fix all issues with AI agents
In
`@payload-manifests/crds/0000_10_config-operator_01_controllermanagers.crd.yaml`:
- Line 5: The api approval annotation api-approved.openshift.io currently
contains a placeholder URL ending with "XYZ"; replace that placeholder with the
actual GitHub PR URL for the OpenShift API approval (the final merged/approved
PR number), e.g. https://github.com/openshift/api/pull/<PR_NUMBER>, ensuring the
annotation value is a valid URL and kept as a single string on the
api-approved.openshift.io line in the CRD manifest so gating will recognize it.

Comment thread payload-manifests/crds/0000_10_config-operator_01_controllermanagers.crd.yaml Outdated
@openshift-merge-robot openshift-merge-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jan 28, 2026
@openshift-merge-robot openshift-merge-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jan 28, 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

🤖 Fix all issues with AI agents
In `@config/v1/types_controllermanager.go`:
- Around line 58-61: The struct ControllerManagerStatus is empty but annotated
with +kubebuilder:validation:MinProperties=1 which makes an empty status
invalid; remove the +kubebuilder:validation:MinProperties=1 annotation from the
ControllerManagerStatus definition in types_controllermanager.go (or
alternatively add actual status fields to ControllerManagerStatus if you intend
to require properties) so that writing an empty {} status is valid.

Comment thread config/v1alpha1/types_controllermanager.go Outdated

@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

🤖 Fix all issues with AI agents
In `@config/v1/types_controllermanager.go`:
- Around line 35-44: The kubebuilder markers on ControllerManagerSpec are not
being picked up by controller-gen: move/ensure the
`+kubebuilder:validation:MinProperties=1` marker is placed immediately above the
`type ControllerManagerSpec struct {` line (no blank comment gap) and replace
the incorrect `+default="Enabled"` with the kubebuilder form
`+kubebuilder:default=Enabled` (attach it immediately above the
`ForceDetachOnTimeout ForceDetachOnTimeoutPolicy` field or the field definition)
so controller-gen will emit the spec.minProperties and the default for
`ForceDetachOnTimeout`; then re-run the CRD generation to verify the generated
CRD includes `minProperties` and the `default` value.
🧹 Nitpick comments (2)
config/v1/types_controllermanager.go (2)

29-32: Minor: JSON tag inconsistencies.

  • Line 29: Spec is marked +required but uses omitzero, which could omit the spec from serialized output if it's a zero value. Consider using omitempty for consistency with typical Kubernetes API patterns, or verify this is the intended behavior.
  • Line 32: omitempty,omitzero is redundant—omitzero (Go 1.24+) subsumes omitempty for struct types.

49-56: Use const instead of var for policy constants.

These are immutable enum-like values that should not be modifiable at runtime. Declaring them as const is idiomatic Go and provides compile-time immutability guarantees.

♻️ Proposed fix
-var (
+const (
 	// ForceDetachOnTimeoutEnabled will allow kube-controller-manager to
 	// force detach volumes based on maximum unmount time and node status.
-	ForceDetachOnTimeoutEnabled  ForceDetachOnTimeoutPolicy = "Enabled"
+	ForceDetachOnTimeoutEnabled ForceDetachOnTimeoutPolicy = "Enabled"
 	// ForceDetachOnTimeoutDisabled will prevent kube-controller-manager
 	// from force detaching volumes.
 	ForceDetachOnTimeoutDisabled ForceDetachOnTimeoutPolicy = "Disabled"
 )

Comment thread config/v1alpha1/types_controllermanager.go Outdated

@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: 2

🤖 Fix all issues with AI agents
In `@openapi/generated_openapi/zz_generated.openapi.go`:
- Around line 12445-12452: The generated OpenAPI schema for the field
forceDetachOnTimeout is missing the Enum constraint; regenerate the OpenAPI
output so the SchemaProps for forceDetachOnTimeout includes the Enum values
["Enabled","Disabled"] (the source type has
+kubebuilder:validation:Enum=Enabled;Disabled in types_controllermanager.go).
Re-run the project's OpenAPI generation task (the generator that produces
zz_generated.openapi.go), verify the SchemaProps.Enum for forceDetachOnTimeout
is populated with the two enum strings, and commit the updated
zz_generated.openapi.go so the generated schema matches the source annotation.

In
`@payload-manifests/crds/0000_10_config-operator_01_controllermanagers.crd.yaml`:
- Around line 61-65: The CRD's schema for the status subresource currently sets
"minProperties: 1" on the "status" object but no status properties are declared,
which will prune and reject updates; remove the "minProperties: 1" constraint
from the "status" schema (or alternatively declare the intended status fields
under "status" if you want to enforce at least one field) so status updates are
not rejected; locate the "status:" object in the controllermanagers CRD
definition and delete the "minProperties: 1" line (or add explicit status
property definitions) to fix the issue.

Comment thread openapi/generated_openapi/zz_generated.openapi.go Outdated

@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

🤖 Fix all issues with AI agents
In
`@payload-manifests/crds/0000_10_config-operator_01_controllermanagers.crd.yaml`:
- Around line 46-60: Remove the minProperties: 1 constraint from the spec object
so the CRD no longer requires at least one property; specifically edit the spec
block that contains forceDetachOnTimeout (remove the minProperties: 1 line) to
make spec optional and consistent with other config-operator CRDs while leaving
the forceDetachOnTimeout property, its default, enum and description intact.

@openshift-ci-robot

openshift-ci-robot commented Jan 28, 2026 •

Copy link
Copy Markdown

@dobsonj: This pull request references STOR-2859 which is a valid jira issue.

Details

In response to this:

User description

https://issues.redhat.com/browse/STOR-2859

This PR introduces an API to disable force detach in kube-controller-manager. The design is based on this slack discussion (internal only). There is already a KubeControllerManager operator type to configure cluster-kube-controller-manager-operator, and this PR introduces a ControllerManager config type to configure kube-controller-manager. This is approach is consistent with other workload components like KubeAPIServer / APIServer and KubeScheduler / Scheduler.

controllerManager.spec.forceDetachOnTimeout will be used to enable or disable force detach in KCM.

/cc @openshift/storage


PR Type

Enhancement


Description

  • Add ControllerManager API for cluster-wide Kubernetes controller manager configuration

  • Introduce ForceDetachOnTimeoutPolicy to control volume force detach behavior

  • Generate deepcopy, swagger documentation, and OpenAPI schema definitions

  • Create CustomResourceDefinition manifest for controllermanagers resource


Diagram Walkthrough

flowchart LR
 A["ControllerManager API Type"] --> B["ForceDetachOnTimeoutPolicy"]
 A --> C["ControllerManagerSpec"]
 A --> D["ControllerManagerStatus"]
 C --> E["forceDetachOnTimeout Field"]
 E --> F["Enabled/Disabled/Omitted"]
 A --> G["Generated Code"]
 G --> H["DeepCopy Functions"]
 G --> I["Swagger Documentation"]
 G --> J["OpenAPI Schemas"]
 A --> K["CRD Manifest"]
Loading

File Walkthrough

Relevant files
Enhancement
types_controllermanager.go
Define ControllerManager API types and policy                       

config/v1/types_controllermanager.go

  • Define new ControllerManager struct with metadata, spec, and status
    fields
  • Create ControllerManagerSpec with ForceDetachOnTimeoutPolicy field
  • Define ForceDetachOnTimeoutPolicy type with Enabled and Disabled
    constants
  • Create ControllerManagerList struct for list operations
+72/-0   
Code generation
zz_generated.deepcopy.go
Generate deepcopy functions for ControllerManager types   

config/v1/zz_generated.deepcopy.go

  • Generate DeepCopyInto, DeepCopy, and DeepCopyObject methods for
    ControllerManager
  • Generate deepcopy methods for ControllerManagerList
  • Generate deepcopy methods for ControllerManagerSpec
  • Generate deepcopy methods for ControllerManagerStatus
+93/-0   
zz_generated.swagger_doc_generated.go
Generate swagger documentation for ControllerManager         

config/v1/zz_generated.swagger_doc_generated.go

  • Add swagger documentation map for ControllerManager type
  • Add swagger documentation map for ControllerManagerList type
  • Add swagger documentation map for ControllerManagerSpec type
  • Document field descriptions and compatibility level
+28/-0   
zz_generated.openapi.go
Generate OpenAPI schema definitions for ControllerManager

openapi/generated_openapi/zz_generated.openapi.go

  • Register OpenAPI schema definitions for ControllerManager,
    ControllerManagerList, ControllerManagerSpec, and
    ControllerManagerStatus
  • Generate schema_openshift_api_config_v1_ControllerManager function
    with properties and dependencies
  • Generate schema_openshift_api_config_v1_ControllerManagerList function
    with items array
  • Generate schema_openshift_api_config_v1_ControllerManagerSpec and
    ControllerManagerStatus schema functions
+135/-0 
Configuration
0000_10_config-operator_01_controllermanagers.crd.yaml
Create ControllerManager CustomResourceDefinition manifest

config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_controllermanagers.crd.yaml

  • Create CustomResourceDefinition manifest for
    controllermanagers.config.openshift.io
  • Define spec with forceDetachOnTimeout property supporting Enabled,
    Disabled, and empty string values
  • Configure cluster-scoped resource with status subresource
  • Include bootstrap-required annotation and API approval reference
+73/-0   
zz_generated.featuregated-crd-manifests.yaml
Register ControllerManager in featuregated manifests         

config/v1/zz_generated.featuregated-crd-manifests.yaml

  • Add controllermanagers.config.openshift.io entry to featuregated CRD
    manifests
  • Register metadata including operator name, run level, and scope
    information
  • Mark as bootstrap-required and ungated feature
+22/-0   
AAA_ungated.yaml
Create ungated ControllerManager CRD manifest                       

config/v1/zz_generated.featuregated-crd-manifests/controllermanagers.config.openshift.io/AAA_ungated.yaml

  • Create ungated CustomResourceDefinition manifest for
    controllermanagers resource
  • Define identical schema to main CRD manifest with feature-gate
    annotations
  • Configure cluster scope with status subresource and bootstrap
    requirement
+74/-0   

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.

@dobsonj dobsonj changed the title [WIP] STOR-2859: Add APIs for disabling force detach in KCM operator STOR-2859: Add APIs for disabling force detach in KCM operator Jan 28, 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 Jan 28, 2026
@dobsonj

dobsonj commented Jan 29, 2026

Copy link
Copy Markdown
Member Author

/cc @gnufied @ingvagabund
for reviews

@openshift-ci openshift-ci Bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Sep 15, 2026
@dobsonj

dobsonj commented Sep 15, 2026

Copy link
Copy Markdown
Member Author

/label tide/merge-method-squash

@openshift-ci openshift-ci Bot added tide/merge-method-squash Denotes a PR that should be squashed by tide when it merges. and removed needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. labels Sep 15, 2026

@saschagrunert saschagrunert 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.

Another pass over the current state. The earlier round looks addressed: scheme registration, payload CRD glob, +enum, singleton rule and the status contract are all right now.

Verified locally on 9547e69: make lint clean, ControllerManager integration tests pass, payload manifest byte-identical to the generated one with bootstrap-required gone. I also ran throwaway suites against envtest to confirm what the MinProperties / MinItems markers actually reject; details inline.

Two things not inline:

  1. @lance5890's question about the type name is still open. config.openshift.io/APIServer deliberately covers both apiservers, so a ControllerManager that only ever configures KCM is a name that will read wrong if openshift-controller-manager config ever needs a home. v1alpha1 is the point to settle it, so the thread deserves an explicit answer either way.
  2. openshift/enhancements#2095 has no acks yet. The API reviewers guide expects an initial ack before a gate merges into DevPreviewNoUpgrade, so that is the gating item here. The PR description is also stale (still config/v1, status without conditions) and feeds the squashed commit message.

Comment thread config/v1alpha1/types_controllermanager.go Outdated
Comment thread config/v1alpha1/types_controllermanager.go Outdated
Comment thread config/v1alpha1/types_controllermanager.go Outdated
Comment thread config/v1alpha1/types_controllermanager.go Outdated
Comment thread config/v1alpha1/types_controllermanager.go Outdated
Comment thread features/features.go Outdated
@openshift-ci openshift-ci Bot added size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. and removed size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Sep 17, 2026
Comment thread config/v1alpha1/types_controllermanager.go Outdated
@openshift-ci openshift-ci Bot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. and removed size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels Sep 17, 2026

@saschagrunert saschagrunert 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.

Another pass over 4edbf3b1. The status removal, the gate split, scheme registration, the payload glob and the singleton rule all look right now. Verified locally: make lint clean, make verify-codegen-crds clean, payload manifest byte-identical to the generated one, ControllerManager integration tests green.

Inline comments cover what is left in the code. Three things that do not anchor to a line:

  1. openshift/enhancements#2095 has no ack. Every review on it is COMMENTED, there is no lgtm, and the bot still reports NOT APPROVED. The API reviewers guide expects an initial ack before a gate merges into DevPreviewNoUpgrade, so this is the gating item here, not anything in the API itself.

  2. The EP no longer matches the API. #2095 still documents .status.conditions with a Progressing type (lines 63 and 82-83 of its diff), which 4edbf3b1 removed. I agree with your conclusion that rollout progress belongs on kubecontrollermanagers.operator.openshift.io status, so the EP wants the same edit. It also only names DisableForceDetachOnTimeout while both gates point readers at it, so ControllerManagerConfig should be described there too.

  3. The PR description is stale. It still refers to config/v1, config/v1/types_controllermanager.go and ControllerManagerStatus. With tide/merge-method-squash that text becomes the commit message.

@JoelSpeed for what it is worth, the three things you asked for in January (an EP, a feature gate, and starting at v1alpha1) are all in place now.

Comment thread config/v1alpha1/types_controllermanager.go
Comment thread config/v1alpha1/types_controllermanager.go
@openshift-ci-robot

openshift-ci-robot commented Sep 18, 2026 •

Copy link
Copy Markdown

@dobsonj: This pull request references STOR-2859 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 story to target the "5.1.0" version, but no target version was set.

Details

In response to this:

User description

https://issues.redhat.com/browse/STOR-2859

This PR introduces an API to disable force detach in kube-controller-manager. The design is based on this slack discussion (internal only). There is already a KubeControllerManager operator type to configure cluster-kube-controller-manager-operator, and this PR introduces a ControllerManager config type to configure kube-controller-manager. This is approach is consistent with other workload components like KubeAPIServer / APIServer and KubeScheduler / Scheduler.

controllerManager.spec.forceDetachOnTimeout will be used to enable or disable force detach in KCM.

/cc @openshift/storage


PR Type

Enhancement


Description

  • Add ControllerManager API for cluster-wide Kubernetes controller manager configuration

  • Introduce ForceDetachOnTimeoutPolicy to control volume force detach behavior

  • Generate deepcopy, swagger documentation, and OpenAPI schema definitions

  • Create CustomResourceDefinition manifest for controllermanagers resource


Diagram Walkthrough

flowchart LR
 A["ControllerManager API Type"] --> B["ForceDetachOnTimeoutPolicy"]
 A --> C["ControllerManagerSpec"]
 A --> D["ControllerManagerStatus"]
 C --> E["forceDetachOnTimeout Field"]
 E --> F["Enabled/Disabled/Omitted"]
 A --> G["Generated Code"]
 G --> H["DeepCopy Functions"]
 G --> I["Swagger Documentation"]
 G --> J["OpenAPI Schemas"]
 A --> K["CRD Manifest"]
Loading

File Walkthrough

Relevant files
Enhancement
types_controllermanager.go
Define ControllerManager API types and policy                       

config/v1alpha1/types_controllermanager.go

  • Define new ControllerManager struct with metadata, spec, and status
    fields
  • Create ControllerManagerSpec with ForceDetachOnTimeoutPolicy field
  • Define ForceDetachOnTimeoutPolicy type with Enabled and Disabled
    constants
  • Create ControllerManagerList struct for list operations
+72/-0   
Code generation
zz_generated.deepcopy.go
Generate deepcopy functions for ControllerManager types   

config/v1alpha1/zz_generated.deepcopy.go

  • Generate DeepCopyInto, DeepCopy, and DeepCopyObject methods for
    ControllerManager
  • Generate deepcopy methods for ControllerManagerList
  • Generate deepcopy methods for ControllerManagerSpec
  • Generate deepcopy methods for ControllerManagerStatus
+93/-0   
zz_generated.swagger_doc_generated.go
Generate swagger documentation for ControllerManager         

config/v1alpha1/zz_generated.swagger_doc_generated.go

  • Add swagger documentation map for ControllerManager type
  • Add swagger documentation map for ControllerManagerList type
  • Add swagger documentation map for ControllerManagerSpec type
  • Document field descriptions and compatibility level
+28/-0   
zz_generated.openapi.go
Generate OpenAPI schema definitions for ControllerManager

openapi/generated_openapi/zz_generated.openapi.go

  • Register OpenAPI schema definitions for ControllerManager,
    ControllerManagerList, ControllerManagerSpec, and
    ControllerManagerStatus
  • Generate schema_openshift_api_config_v1_ControllerManager function
    with properties and dependencies
  • Generate schema_openshift_api_config_v1_ControllerManagerList function
    with items array
  • Generate schema_openshift_api_config_v1_ControllerManagerSpec and
    ControllerManagerStatus schema functions
+135/-0 
Configuration
0000_10_config-operator_01_controllermanagers.crd.yaml
Create ControllerManager CustomResourceDefinition manifest

config/v1alpha1/zz_generated.crd-manifests/0000_10_config-operator_01_controllermanagers.crd.yaml

  • Create CustomResourceDefinition manifest for
    controllermanagers.config.openshift.io
  • Define spec with forceDetachOnTimeout property supporting Enabled,
    Disabled, and empty string values
  • Configure cluster-scoped resource with status subresource
  • Include bootstrap-required annotation and API approval reference
+73/-0   
zz_generated.featuregated-crd-manifests.yaml
Register ControllerManager in featuregated manifests         

config/v1alpha1/zz_generated.featuregated-crd-manifests.yaml

  • Add controllermanagers.config.openshift.io entry to featuregated CRD
    manifests
  • Register metadata including operator name, run level, and scope
    information
  • Mark as bootstrap-required and ungated feature
+22/-0   
AAA_ungated.yaml
Create ungated ControllerManager CRD manifest                       

config/v1alpha1/zz_generated.featuregated-crd-manifests/controllermanagers.config.openshift.io/AAA_ungated.yaml

  • Create ungated CustomResourceDefinition manifest for
    controllermanagers resource
  • Define identical schema to main CRD manifest with feature-gate
    annotations
  • Configure cluster scope with status subresource and bootstrap
    requirement
+74/-0   

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.

@dobsonj

dobsonj commented Sep 18, 2026

Copy link
Copy Markdown
Member Author

/test verify-client-go
/test verify-crdify

@dobsonj

dobsonj commented Sep 18, 2026

Copy link
Copy Markdown
Member Author

Thanks @saschagrunert for all your help with this.

openshift/enhancements#2095 has no ack. Every review on it is COMMENTED, there is no lgtm, and the bot still reports NOT APPROVED. The API reviewers guide expects an initial ack before a gate merges into DevPreviewNoUpgrade, so this is the gating item here, not anything in the API itself.

Understood, I'll chase approvals on the enhancement and then report back once it has merged.

The EP no longer matches the API. #2095 still documents .status.conditions with a Progressing type (lines 63 and 82-83 of its diff), which 4edbf3b removed. I agree with your conclusion that rollout progress belongs on kubecontrollermanagers.operator.openshift.io status, so the EP wants the same edit. It also only names DisableForceDetachOnTimeout while both gates point readers at it, so ControllerManagerConfig should be described there too.

I pushed an update to the EP to drop the condition, and to mention both feature gates in the API section.

The PR description is stale. It still refers to config/v1, config/v1/types_controllermanager.go and ControllerManagerStatus. With tide/merge-method-squash that text becomes the commit message.

I updated the PR description. Everything from "PR Type" down was generated by one of the bots, but I made manual edits. Maybe there's a way to get it regenerated based on current state. Note though that tide/merge-method-squash only includes the PR title and the individual commit messages. It won't include the lengthy PR description in the commit message.

I just came across Joel's comment though that we shouldn't use tide squash on this repo, so I'll plan on doing a final squash of all these commits before merge.

@dobsonj

dobsonj commented Sep 18, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai resume

@coderabbitai

coderabbitai Bot commented Sep 18, 2026 •

Copy link
Copy Markdown
✅ Action performed

Reviews resumed and review finished.

@dobsonj

dobsonj commented Sep 18, 2026

Copy link
Copy Markdown
Member Author

/test minor-images

1 similar comment
@dobsonj

dobsonj commented Sep 18, 2026

Copy link
Copy Markdown
Member Author

/test minor-images

Comment thread config/v1alpha1/types_controllermanager.go Outdated
Comment thread config/v1alpha1/types_controllermanager.go Outdated
Comment thread config/v1alpha1/types_controllermanager.go
@dobsonj

dobsonj commented Sep 21, 2026

Copy link
Copy Markdown
Member Author

/retest

Introduce ControllerManager config v1alpha1 API with a forceDetachOnTimeout
option to control whether kube-controller-manager force detaches volumes from
a node that is not healthy once the volumes have not been unmounted within
the maximum unmount time (6 minutes).

Co-authored-by: Sascha Grunert <sgrunert@redhat.com>
@dobsonj

dobsonj commented Sep 22, 2026

Copy link
Copy Markdown
Member Author

/remove-label tide/merge-method-squash
I squashed the commits in the last push.

@openshift-ci openshift-ci Bot removed the tide/merge-method-squash Denotes a PR that should be squashed by tide when it merges. label Sep 22, 2026
@dobsonj

dobsonj commented Sep 22, 2026

Copy link
Copy Markdown
Member Author

/retest

@dobsonj

dobsonj commented Sep 22, 2026

Copy link
Copy Markdown
Member Author

The enhancement PR openshift/enhancements#2095 has merged, I've addressed the remaining feedback on this PR, and squashed the commits. So I think this is ready for approvals unless anyone has new feedback to discuss.

@openshift-ci

openshift-ci Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

@dobsonj: 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. Review effort 2/5 size/XL Denotes a PR that changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants