Skip to content
Open
Show file tree
Hide file tree
Changes from 9 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
15 changes: 15 additions & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,21 @@ linters:
# to enforce specific condition types are always present.
path: etcd/v1/types_pacemakercluster.go
text: "conditions: Conditions field in (PacemakerClusterStatus|PacemakerClusterNodeStatus|PacemakerClusterFencingAgentStatus|PacemakerClusterResourceStatus) is missing the following markers: optional"
- linters:
- kubeapilinter
# Empty lists are meaningful: no available transitions, or no completed evaluation condition yet.
path: config/v1/types_infrastructure_transitions.go
text: 'minlength: field TopologyTransitionStatus\.(AvailableTransitions|Conditions) must have a minimum items'
- linters:
- kubeapilinter
# Keep the pointer so nil means no topology transition has started; omitempty omits nil.
path: config/v1/types_infrastructure_transitions.go
text: 'optionalfields: field TopologyTransitionStatus\.CurrentTransition'
- linters:
- kubeapilinter
# Keep an evaluated empty list serialized as [] rather than omitting this required field.
path: config/v1/types_infrastructure_transitions.go
text: 'requiredfields: field TopologyTransitionStatus\.AvailableTransitions should have the omitempty tag'
- linters:
- kubeapilinter
path: features|payload-command/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,29 @@ tests:
type: UserManaged
type: BareMetal
expectedStatusError: 'status.platformStatus.baremetal.loadBalancer.type: Invalid value: "string": type is immutable once set'
- name: Should prune topologyTransitionStatus when MutableTopology is disabled
initial: |
apiVersion: config.openshift.io/v1
kind: Infrastructure
spec: {}
status:
controlPlaneTopology: SingleReplica
updated: |
apiVersion: config.openshift.io/v1
kind: Infrastructure
spec: {}
status:
controlPlaneTopology: SingleReplica
topologyTransitionStatus:
availableTransitions: []
expected: |
apiVersion: config.openshift.io/v1
kind: Infrastructure
spec: {}
status:
controlPlaneTopology: SingleReplica
infrastructureTopology: HighlyAvailable
cpuPartitioning: None
- name: Should not allow changing the immutable OpenStack load balancer type field
initial: |
apiVersion: config.openshift.io/v1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,3 +259,227 @@ tests:
spec:
controlPlaneTopology: InvalidValue
expectedError: 'spec.controlPlaneTopology: Unsupported value: "InvalidValue": supported values: "HighlyAvailable", "SingleReplica"'
- name: Should allow updating Infrastructure status without topologyTransitionStatus
initial: |
apiVersion: config.openshift.io/v1
kind: Infrastructure
spec: {}
status:
controlPlaneTopology: SingleReplica
updated: |
apiVersion: config.openshift.io/v1
kind: Infrastructure
spec: {}
status:
controlPlaneTopology: SingleReplica
infrastructureTopology: HighlyAvailable
expected: |
apiVersion: config.openshift.io/v1
kind: Infrastructure
spec: {}
status:
controlPlaneTopology: SingleReplica
infrastructureTopology: HighlyAvailable
cpuPartitioning: None
- name: Should allow an empty availableTransitions list after successful evaluation
initial: |
apiVersion: config.openshift.io/v1
kind: Infrastructure
spec: {}
status:
controlPlaneTopology: SingleReplica
updated: |
apiVersion: config.openshift.io/v1
kind: Infrastructure
spec: {}
status:
controlPlaneTopology: SingleReplica
topologyTransitionStatus:
availableTransitions: []
conditions:
- type: TopologyTransitionsEvaluated
status: "True"
lastTransitionTime: "2025-01-01T00:00:00Z"
reason: EvaluationComplete
message: No transitions are available
expected: |
apiVersion: config.openshift.io/v1
kind: Infrastructure
spec: {}
status:
controlPlaneTopology: SingleReplica
infrastructureTopology: HighlyAvailable
cpuPartitioning: None
topologyTransitionStatus:
availableTransitions: []
conditions:
- type: TopologyTransitionsEvaluated
status: "True"
lastTransitionTime: "2025-01-01T00:00:00Z"
reason: EvaluationComplete
message: No transitions are available
- name: Should allow reporting current transition progress
initial: |
apiVersion: config.openshift.io/v1
kind: Infrastructure
spec: {}
status:
controlPlaneTopology: SingleReplica
infrastructureTopology: SingleReplica
updated: |
apiVersion: config.openshift.io/v1
kind: Infrastructure
spec: {}
status:
controlPlaneTopology: SingleReplica
infrastructureTopology: SingleReplica
topologyTransitionStatus:
availableTransitions:
- source:
controlPlaneTopology: SingleReplica
infrastructureTopology: SingleReplica
target:
controlPlaneTopology: HighlyAvailable
infrastructureTopology: HighlyAvailable
reason: PreflightCheckFailed
currentTransition:
status: Partial
reason: TransitionInProgress
message: Applying topology changes
startedTime: "2025-01-01T00:00:00Z"
expected: |
apiVersion: config.openshift.io/v1
kind: Infrastructure
spec: {}
status:
controlPlaneTopology: SingleReplica
infrastructureTopology: SingleReplica
cpuPartitioning: None
topologyTransitionStatus:
availableTransitions:
- source:
controlPlaneTopology: SingleReplica
infrastructureTopology: SingleReplica
target:
controlPlaneTopology: HighlyAvailable
infrastructureTopology: HighlyAvailable
reason: PreflightCheckFailed
currentTransition:
status: Partial
reason: TransitionInProgress
message: Applying topology changes
startedTime: "2025-01-01T00:00:00Z"
- name: Should reject a topology transition reason that is not CamelCase
initial: |
apiVersion: config.openshift.io/v1
kind: Infrastructure
spec: {}
status:
controlPlaneTopology: SingleReplica
infrastructureTopology: SingleReplica
updated: |
apiVersion: config.openshift.io/v1
kind: Infrastructure
spec: {}
status:
controlPlaneTopology: SingleReplica
infrastructureTopology: SingleReplica
topologyTransitionStatus:
availableTransitions:
- source:
controlPlaneTopology: SingleReplica
infrastructureTopology: SingleReplica
target:
controlPlaneTopology: HighlyAvailable
infrastructureTopology: HighlyAvailable
reason: preflightCheckFailed
expectedStatusError: "reason must be CamelCase, matching ^[A-Z][A-Za-z0-9]*$"
- name: Should reject an available transition whose source does not match status topology
initial: |
apiVersion: config.openshift.io/v1
kind: Infrastructure
spec: {}
status:
controlPlaneTopology: SingleReplica
infrastructureTopology: SingleReplica
updated: |
apiVersion: config.openshift.io/v1
kind: Infrastructure
spec: {}
status:
controlPlaneTopology: SingleReplica
infrastructureTopology: SingleReplica
topologyTransitionStatus:
availableTransitions:
- source:
controlPlaneTopology: HighlyAvailable
infrastructureTopology: HighlyAvailable
target:
controlPlaneTopology: SingleReplica
infrastructureTopology: SingleReplica
expectedStatusError: "transition sources must match the current status topology"
- name: Should enforce the supported maximum available transition count
initial: |
apiVersion: config.openshift.io/v1
kind: Infrastructure
spec: {}
status:
controlPlaneTopology: SingleReplica
infrastructureTopology: SingleReplica
updated: |
apiVersion: config.openshift.io/v1
kind: Infrastructure
spec: {}
status:
controlPlaneTopology: SingleReplica
infrastructureTopology: SingleReplica
topologyTransitionStatus:
availableTransitions:
- source:
controlPlaneTopology: SingleReplica
infrastructureTopology: SingleReplica
target:
controlPlaneTopology: HighlyAvailable
infrastructureTopology: HighlyAvailable
- source:
controlPlaneTopology: SingleReplica
infrastructureTopology: SingleReplica
target:
controlPlaneTopology: HighlyAvailable
infrastructureTopology: HighlyAvailable
expectedStatusError: "Too many: 2: must have at most 1 items"
- name: Should require availableTransitions when topologyTransitionStatus is set
initial: |
apiVersion: config.openshift.io/v1
kind: Infrastructure
spec: {}
status:
controlPlaneTopology: SingleReplica
updated: |
apiVersion: config.openshift.io/v1
kind: Infrastructure
spec: {}
status:
controlPlaneTopology: SingleReplica
topologyTransitionStatus:
conditions: []
expectedStatusError: "Required value"
- name: Should require status on currentTransition
initial: |
apiVersion: config.openshift.io/v1
kind: Infrastructure
spec: {}
status:
controlPlaneTopology: SingleReplica
updated: |
apiVersion: config.openshift.io/v1
kind: Infrastructure
spec: {}
status:
controlPlaneTopology: SingleReplica
topologyTransitionStatus:
availableTransitions: []
currentTransition:
reason: TransitionInProgress
message: Applying topology changes
expectedStatusError: "Required value"
7 changes: 7 additions & 0 deletions config/v1/types_infrastructure.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
// +kubebuilder:subresource:status
// +kubebuilder:metadata:annotations=release.openshift.io/bootstrap-required=true
// +openshift:validation:FeatureGateAwareXValidation:featureGate=MutableTopology,rule="!has(self.spec.controlPlaneTopology) || (has(oldSelf.spec.controlPlaneTopology) && self.spec.controlPlaneTopology == oldSelf.spec.controlPlaneTopology) || (has(self.status.controlPlaneTopology) && self.spec.controlPlaneTopology == self.status.controlPlaneTopology) || (has(self.status.controlPlaneTopology) && self.status.controlPlaneTopology == 'SingleReplica' && self.spec.controlPlaneTopology == 'HighlyAvailable')",message="spec.controlPlaneTopology must match status.controlPlaneTopology or be set to HighlyAvailable when status.controlPlaneTopology is SingleReplica"
// +openshift:validation:FeatureGateAwareXValidation:featureGate=MutableTopology,rule="!has(self.status) || !has(self.status.topologyTransitionStatus) || self.status.topologyTransitionStatus.availableTransitions.all(t, has(self.status.controlPlaneTopology) && has(self.status.infrastructureTopology) && t.source.controlPlaneTopology == self.status.controlPlaneTopology && t.source.infrastructureTopology == self.status.infrastructureTopology)",message="transition sources must match the current status topology"
type Infrastructure struct {
metav1.TypeMeta `json:",inline"`

Expand Down Expand Up @@ -138,6 +139,12 @@ type InfrastructureStatus struct {
// +optional
InfrastructureTopology TopologyMode `json:"infrastructureTopology,omitempty"`

// topologyTransitionStatus reports available topology transitions and current progress, if any.
// It is omitted until the topology controller evaluates transitions.
// +openshift:enable:FeatureGate=MutableTopology
// +optional
TopologyTransitionStatus *TopologyTransitionStatus `json:"topologyTransitionStatus,omitempty"`

// cpuPartitioning expresses if CPU partitioning is a currently enabled feature in the cluster.
// CPU Partitioning means that this cluster can support partitioning workloads to specific CPU Sets.
// Valid values are "None" and "AllNodes". When omitted, the default value is "None".
Expand Down
Loading