Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
apiVersion: apiextensions.k8s.io/v1 # Hack because controller-gen complains if we don't have this
name: "Infrastructure"
crdName: infrastructures.config.openshift.io
featureGates:
- AdaptableTopology
tests:
onCreate:
- name: Should be able to create a minimal Infrastructure
initial: |
apiVersion: config.openshift.io/v1
kind: Infrastructure
spec: {} # No spec is required for a Infrastructure
expected: |
apiVersion: config.openshift.io/v1
kind: Infrastructure
spec: {}
onUpdate:
- name: status should allow controlPlaneTopology value for `Adaptable` on platform None
initial: |
apiVersion: config.openshift.io/v1
kind: Infrastructure
spec:
platformSpec:
type: None
updated: |
apiVersion: config.openshift.io/v1
kind: Infrastructure
spec:
platformSpec:
type: None
status:
controlPlaneTopology: Adaptable
infrastructureTopology: HighlyAvailable
platform: None
platformStatus:
type: None
expected: |
apiVersion: config.openshift.io/v1
kind: Infrastructure
spec:
platformSpec:
type: None
status:
controlPlaneTopology: Adaptable
cpuPartitioning: None
infrastructureTopology: HighlyAvailable
platform: None
platformStatus:
type: None
- name: status should allow infrastructureTopology value for `Adaptable` on platform None
initial: |
apiVersion: config.openshift.io/v1
kind: Infrastructure
spec:
platformSpec:
type: None
updated: |
apiVersion: config.openshift.io/v1
kind: Infrastructure
spec:
platformSpec:
type: None
status:
controlPlaneTopology: HighlyAvailable
infrastructureTopology: Adaptable
platform: None
platformStatus:
type: None
expected: |
apiVersion: config.openshift.io/v1
kind: Infrastructure
spec:
platformSpec:
type: None
status:
controlPlaneTopology: HighlyAvailable
cpuPartitioning: None
infrastructureTopology: Adaptable
platform: None
platformStatus:
type: None
6 changes: 6 additions & 0 deletions config/v1/types_infrastructure.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ type InfrastructureStatus struct {
// +kubebuilder:default=HighlyAvailable
// +openshift:validation:FeatureGateAwareEnum:featureGate="",enum=HighlyAvailable;HighlyAvailableArbiter;SingleReplica;External
// +openshift:validation:FeatureGateAwareEnum:featureGate=DualReplica,enum=HighlyAvailable;HighlyAvailableArbiter;SingleReplica;DualReplica;External
// +openshift:validation:FeatureGateAwareEnum:featureGate=AdaptableTopology,enum=HighlyAvailable;HighlyAvailableArbiter;SingleReplica;DualReplica;Adaptable;External
// +optional
ControlPlaneTopology TopologyMode `json:"controlPlaneTopology"`
Comment on lines 108 to 112
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot Apr 24, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check whether a compound AdaptableTopology+DualReplica marker exists anywhere
# in the repo, and inspect all FeatureGateAwareEnum markers on controlPlaneTopology.
echo "=== Compound marker search (any compound) ==="
rg -nP 'FeatureGateAwareEnum:featureGate=[A-Za-z0-9]+\+[A-Za-z0-9]+'

echo
echo "=== All FeatureGateAwareEnum markers in types_infrastructure.go ==="
rg -nP 'FeatureGateAwareEnum' config/v1/types_infrastructure.go

echo
echo "=== Generated CRDs: check Adaptable presence under DevPreview / CustomNoUpgrade ==="
fd -t f 'infrastructures.*DevPreview.*\.yaml|infrastructures.*CustomNoUpgrade.*\.yaml' \
  | xargs -I{} sh -c 'echo "--- {} ---"; rg -n "Adaptable|DualReplica" "{}" | head -40'

echo
echo "=== Integration test profiles exercised by AdaptableTopology.yaml ==="
fd -t f 'AdaptableTopology.yaml' | xargs -I{} sh -c 'echo "--- {} ---"; cat "{}"'

Repository: openshift/api

Length of output: 3994


Missing compound AdaptableTopology+DualReplica marker for controlPlaneTopology causes Adaptable to be absent from generated CRD under dual-gate profiles.

The PR description states a compound FeatureGateAwareEnum:featureGate=AdaptableTopology+DualReplica marker should be added for controlPlaneTopology. However, the code at lines 108–110 shows only three markers (baseline, DualReplica, AdaptableTopology), with no compound marker present anywhere in the repository.

This is a functional bug: under Server-Side Apply with Force=true, single-gate overlays apply in sort order and each fully replaces the previous enum. Because the DualReplica overlay (line 109) does not include Adaptable, it overwrites the AdaptableTopology overlay's enum when both DevPreview gates are enabled (e.g., in CustomNoUpgrade or DevPreviewNoUpgrade profiles). Generated CRDs for these profiles confirm that Adaptable is missing from controlPlaneTopology's enum. The integration test only exercises the AdaptableTopology gate alone, not the "both gates enabled" case, so this regression is not caught.

Add the compound marker:

Diff
 	// +openshift:validation:FeatureGateAwareEnum:featureGate=DualReplica,enum=HighlyAvailable;HighlyAvailableArbiter;SingleReplica;DualReplica;External
 	// +openshift:validation:FeatureGateAwareEnum:featureGate=AdaptableTopology,enum=HighlyAvailable;HighlyAvailableArbiter;SingleReplica;DualReplica;Adaptable;External
+	// +openshift:validation:FeatureGateAwareEnum:featureGate=AdaptableTopology+DualReplica,enum=HighlyAvailable;HighlyAvailableArbiter;SingleReplica;DualReplica;Adaptable;External
 	// +optional
 	ControlPlaneTopology TopologyMode `json:"controlPlaneTopology"`
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// +openshift:validation:FeatureGateAwareEnum:featureGate="",enum=HighlyAvailable;HighlyAvailableArbiter;SingleReplica;External
// +openshift:validation:FeatureGateAwareEnum:featureGate=DualReplica,enum=HighlyAvailable;HighlyAvailableArbiter;SingleReplica;DualReplica;External
// +openshift:validation:FeatureGateAwareEnum:featureGate=AdaptableTopology,enum=HighlyAvailable;HighlyAvailableArbiter;SingleReplica;DualReplica;Adaptable;External
// +optional
ControlPlaneTopology TopologyMode `json:"controlPlaneTopology"`
// +openshift:validation:FeatureGateAwareEnum:featureGate="",enum=HighlyAvailable;HighlyAvailableArbiter;SingleReplica;External
// +openshift:validation:FeatureGateAwareEnum:featureGate=DualReplica,enum=HighlyAvailable;HighlyAvailableArbiter;SingleReplica;DualReplica;External
// +openshift:validation:FeatureGateAwareEnum:featureGate=AdaptableTopology,enum=HighlyAvailable;HighlyAvailableArbiter;SingleReplica;DualReplica;Adaptable;External
// +openshift:validation:FeatureGateAwareEnum:featureGate=AdaptableTopology+DualReplica,enum=HighlyAvailable;HighlyAvailableArbiter;SingleReplica;DualReplica;Adaptable;External
// +optional
ControlPlaneTopology TopologyMode `json:"controlPlaneTopology"`
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@config/v1/types_infrastructure.go` around lines 108 - 112, Add the missing
compound FeatureGateAwareEnum marker so the ControlPlaneTopology enum preserves
"Adaptable" when both gates are enabled: update the feature-gate annotations on
ControlPlaneTopology (TopologyMode) to include a compound marker with
featureGate=AdaptableTopology+DualReplica and enum that includes
HighlyAvailable;HighlyAvailableArbiter;SingleReplica;DualReplica;Adaptable;External
(matching the AdaptableTopology overlay), ensuring the compound marker is
present alongside the existing single-gate markers so overlays applied in sort
order do not drop Adaptable under dual-gate profiles.

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.

@jeff-roche There is a consequence of how things get generated which means we need to add an extra annotation for situations like this where two FeatureGates exist for the same value.

This is what's missing, but the suggestion is wrong, you'll want to add this annotation under adaptable you added, this will generate a DualReplica+AdaptableTopology DevPreview file, which you'll want to add the tests for both DualReplica and AdaptableTopology.

+openshift:validation:FeatureGateAwareEnum:featureGate=AdaptableTopology,enum=HighlyAvailable;HighlyAvailableArbiter;SingleReplica;DualReplica;Adaptable;External
+openshift:validation:FeatureGateAwareEnum:requiredFeatureGate=DualReplica;AdaptableTopology,enum=HighlyAvailable;SingleReplica;DualReplica;Adaptable;External

Feel free to peruse this PR where we originally added Arbiter and DualReplica.

Locally you can run make integration to validate the unit tests won't fail.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!


Expand All @@ -119,6 +120,7 @@ type InfrastructureStatus struct {
// NOTE: External topology mode is not applicable for this field.
// +kubebuilder:default=HighlyAvailable
// +kubebuilder:validation:Enum=HighlyAvailable;SingleReplica
// +openshift:validation:FeatureGateAwareEnum:featureGate=AdaptableTopology,enum=HighlyAvailable;SingleReplica;Adaptable
// +optional
InfrastructureTopology TopologyMode `json:"infrastructureTopology,omitempty"`

Expand Down Expand Up @@ -159,6 +161,10 @@ const (
// that any of the control plane components such as kubernetes API server or etcd are visible within
// the cluster.
ExternalTopologyMode TopologyMode = "External"

// "Adaptable" is for clusters that dynamically adjust control-plane and
// infrastructure behavior based on current node count.
AdaptableTopologyMode TopologyMode = "Adaptable"
)

// CPUPartitioningMode defines the mode for CPU partitioning
Expand Down
1 change: 1 addition & 0 deletions config/v1/zz_generated.featuregated-crd-manifests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,7 @@ infrastructures.config.openshift.io:
FeatureGates:
- AWSClusterHostedDNSInstall
- AWSDualStackInstall
- AdaptableTopology
- AzureClusterHostedDNSInstall
- AzureDualStackInstall
- DualReplica
Expand Down
1 change: 1 addition & 0 deletions features.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
| MachineAPIOperatorDisableMachineHealthCheckController| | | | | | | | |
| MultiArchInstallAzure| | | | | | | | |
| ShortCertRotation| | | | | | | | |
| AdaptableTopology| | | | <span style="background-color: #519450">Enabled</span> | | | | |
| ClusterAPIComputeInstall| | | <span style="background-color: #519450">Enabled</span> | <span style="background-color: #519450">Enabled</span> | | | | |
| ClusterAPIControlPlaneInstall| | | <span style="background-color: #519450">Enabled</span> | <span style="background-color: #519450">Enabled</span> | | | | |
| ClusterUpdatePreflight| | | <span style="background-color: #519450">Enabled</span> | <span style="background-color: #519450">Enabled</span> | | | | |
Expand Down
8 changes: 8 additions & 0 deletions features/features.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,14 @@ var (
enable(inDefault(), inOKD(), inTechPreviewNoUpgrade(), inDevPreviewNoUpgrade()).
mustRegister()

FeatureGateAdaptableTopology = newFeatureGate("AdaptableTopology").
reportProblemsToJiraComponent("Adaptable Topology").
contactPerson("jaypoulz").
productScope(ocpSpecific).
enhancementPR("https://github.com/openshift/enhancements/pull/1905").
enable(inClusterProfile(SelfManaged), inDevPreviewNoUpgrade()).
mustRegister()

FeatureGateAzureWorkloadIdentity = newFeatureGate("AzureWorkloadIdentity").
reportProblemsToJiraComponent("cloud-credential-operator").
contactPerson("abutcher").
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ controllerconfigs.machineconfiguration.openshift.io:
- AWSClusterHostedDNSInstall
- AWSDualStackInstall
- AWSEuropeanSovereignCloudInstall
- AdaptableTopology
- AzureClusterHostedDNSInstall
- AzureDualStackInstall
- DualReplica
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
{
"name": "AWSServiceLBNetworkSecurityGroup"
},
{
"name": "AdaptableTopology"
},
{
"name": "AdditionalStorageConfig"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
"featureGates": [
{
"disabled": [
{
"name": "AdaptableTopology"
},
{
"name": "ClientsAllowCBOR"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
{
"name": "AWSServiceLBNetworkSecurityGroup"
},
{
"name": "AdaptableTopology"
},
{
"name": "AdditionalStorageConfig"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
"featureGates": [
{
"disabled": [
{
"name": "AdaptableTopology"
},
{
"name": "ClientsAllowCBOR"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
{
"name": "AWSEuropeanSovereignCloudInstall"
},
{
"name": "AdaptableTopology"
},
{
"name": "AdditionalStorageConfig"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@
{
"name": "AWSServiceLBNetworkSecurityGroup"
},
{
"name": "AdaptableTopology"
},
{
"name": "AdditionalStorageConfig"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
{
"name": "AWSEuropeanSovereignCloudInstall"
},
{
"name": "AdaptableTopology"
},
{
"name": "AdditionalStorageConfig"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
"featureGates": [
{
"disabled": [
{
"name": "AdaptableTopology"
},
{
"name": "ClientsAllowCBOR"
},
Expand Down