Skip to content
Open
Show file tree
Hide file tree
Changes from 7 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

Large diffs are not rendered by default.

112 changes: 112 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.topologyTransitions) || self.status.topologyTransitions.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"
Comment thread
jeff-roche marked this conversation as resolved.
Outdated
type Infrastructure struct {
metav1.TypeMeta `json:",inline"`

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

// topologyTransitions reports, as controller-computed observed state, the
// topology transitions that originate at the current status.controlPlaneTopology
// and status.infrastructureTopology and whether each can currently be initiated. It is
// advisory: the cluster may change between a status read and a spec write, so the
// cluster-config-operator revalidates any requested transition; consumers such as
// the CLI must not treat Available as an admission guarantee. Transitions are
// requested via spec.controlPlaneTopology, not through this field. When omitted,
// the controller has not yet completed its first evaluation; an empty list is also
// valid and intentionally carries the same meaning as omitted, since this field does
// not currently distinguish "not yet evaluated" from "evaluated with no applicable
// transitions". The only supported transition is from a state where both topology
// values are SingleReplica to a state where both are HighlyAvailable. When the
// current topology does not match the supported source state, this field is expected
// to remain omitted or empty. At most 1 entry is permitted because only one
// transition direction is currently supported.
// +openshift:enable:FeatureGate=MutableTopology
// +listType=atomic
// +kubebuilder:validation:MinItems=0
Comment thread
jeff-roche marked this conversation as resolved.
Outdated
// +kubebuilder:validation:MaxItems=1
// +kubebuilder:validation:XValidation:rule="self.all(t, t.source.controlPlaneTopology == 'SingleReplica' && t.source.infrastructureTopology == 'SingleReplica' && t.target.controlPlaneTopology == 'HighlyAvailable' && t.target.infrastructureTopology == 'HighlyAvailable')",message="only SingleReplica to HighlyAvailable topology transitions are supported"
// +optional
TopologyTransitions []TopologyTransition `json:"topologyTransitions,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 Expand Up @@ -177,6 +201,94 @@ const (
ExternalTopologyMode TopologyMode = "External"
)

// TopologyTransition describes one topology transition available from the
// cluster's current topology and whether it can currently be initiated. source
// and target must differ. reason must be set whenever availability is
// Unavailable or Unknown; both constraints are enforced by validation rules on
// the entry as a whole.
// +kubebuilder:validation:XValidation:rule="self.source.controlPlaneTopology != self.target.controlPlaneTopology || self.source.infrastructureTopology != self.target.infrastructureTopology",message="source and target must differ"
// +kubebuilder:validation:XValidation:rule="self.availability == 'Available' || has(self.reason)",message="reason is required when availability is not Available"
type TopologyTransition struct {
// source is the control-plane and infrastructure topology this transition starts
// from. It must equal the current topology in the corresponding status fields.
// source is required.
// +required
Source TopologyState `json:"source,omitempty,omitzero"`

// target is the control-plane and infrastructure topology this transition would
// move to. target is required.
// +required
Target TopologyState `json:"target,omitempty,omitzero"`

// availability indicates whether this transition can currently be initiated.
// Valid values are Available, Unavailable, and Unknown. Available means the
// controller evaluated the transition and its preconditions pass. Unavailable
// means the transition is defined but cannot be initiated now; see reason and
// message. Unknown means the controller has not completed evaluation.
// +required
Availability TransitionAvailability `json:"availability,omitempty"`

// reason is a CamelCase machine-readable explanation of the availability, e.g.
// PreflightCheckFailed or SourceTopologyMismatch. It is required when
// availability is Unavailable or Unknown and is normally omitted when Available.
// The set of reasons is diagnostic and not exhaustive. Must start with an
// uppercase letter and contain only alphanumeric characters, and must be
// between 1 and 128 characters long.
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=128
// +kubebuilder:validation:XValidation:rule=`self.matches('^[A-Z][A-Za-z0-9]*$')`,message="reason must be CamelCase, matching ^[A-Z][A-Za-z0-9]*$"
// +optional
Reason string `json:"reason,omitempty"`

// message is a human-readable explanation, primarily for Unavailable
// transitions (e.g. a concise summary of the failing preconditions). It is for
// humans only and must not be parsed. It may be truncated by the controller.
// When omitted, no human-readable explanation is available for the transition.
// When set, it must be between 1 and 2048 characters long.
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=2048
// +optional
Message string `json:"message,omitempty"`
}

// TopologyState describes the control-plane and infrastructure topology at one
// end of a topology transition.
type TopologyState struct {
// controlPlaneTopology is the topology of the control-plane nodes. Valid values
// are SingleReplica and HighlyAvailable. When set to SingleReplica, operators
// avoid spending resources for high availability. When set to HighlyAvailable,
// operators configure high availability as much as possible.
// controlPlaneTopology is required.
// +kubebuilder:validation:Enum=SingleReplica;HighlyAvailable
// +required
ControlPlaneTopology TopologyMode `json:"controlPlaneTopology,omitempty"`

// infrastructureTopology is the topology of infrastructure services. Valid
// values are SingleReplica and HighlyAvailable. When set to SingleReplica,
// operators avoid spending resources for high availability. When set to
// HighlyAvailable, operators configure high availability as much as possible.
// infrastructureTopology is required.
// +kubebuilder:validation:Enum=SingleReplica;HighlyAvailable
// +required
InfrastructureTopology TopologyMode `json:"infrastructureTopology,omitempty"`
}

// TransitionAvailability indicates whether a topology transition can currently be
// initiated.
// +kubebuilder:validation:Enum=Available;Unavailable;Unknown
type TransitionAvailability string

const (
// TransitionAvailable means the transition can be initiated now.
TransitionAvailable TransitionAvailability = "Available"

// TransitionUnavailable means the transition is defined but cannot be initiated now.
TransitionUnavailable TransitionAvailability = "Unavailable"

// TransitionUnknown means the controller has not completed evaluation.
TransitionUnknown TransitionAvailability = "Unknown"
)

// CPUPartitioningMode defines the mode for CPU partitioning
type CPUPartitioningMode string

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2843,6 +2843,151 @@ spec:
rule: '!has(self.dnsRecordsType) || self.dnsRecordsType == ''Internal''
|| (has(self.loadBalancer) && self.loadBalancer.type == ''UserManaged'')'
type: object
topologyTransitions:
description: |-
topologyTransitions reports, as controller-computed observed state, the
topology transitions that originate at the current status.controlPlaneTopology
and status.infrastructureTopology and whether each can currently be initiated. It is
advisory: the cluster may change between a status read and a spec write, so the
cluster-config-operator revalidates any requested transition; consumers such as
the CLI must not treat Available as an admission guarantee. Transitions are
requested via spec.controlPlaneTopology, not through this field. When omitted,
the controller has not yet completed its first evaluation; an empty list is also
valid and intentionally carries the same meaning as omitted, since this field does
not currently distinguish "not yet evaluated" from "evaluated with no applicable
transitions". The only supported transition is from a state where both topology
values are SingleReplica to a state where both are HighlyAvailable. When the
current topology does not match the supported source state, this field is expected
to remain omitted or empty. At most 1 entry is permitted because only one
transition direction is currently supported.
items:
description: |-
TopologyTransition describes one topology transition available from the
cluster's current topology and whether it can currently be initiated. source
and target must differ. reason must be set whenever availability is
Unavailable or Unknown; both constraints are enforced by validation rules on
the entry as a whole.
properties:
availability:
description: |-
availability indicates whether this transition can currently be initiated.
Valid values are Available, Unavailable, and Unknown. Available means the
controller evaluated the transition and its preconditions pass. Unavailable
means the transition is defined but cannot be initiated now; see reason and
message. Unknown means the controller has not completed evaluation.
enum:
- Available
- Unavailable
- Unknown
type: string
message:
description: |-
message is a human-readable explanation, primarily for Unavailable
transitions (e.g. a concise summary of the failing preconditions). It is for
humans only and must not be parsed. It may be truncated by the controller.
When omitted, no human-readable explanation is available for the transition.
When set, it must be between 1 and 2048 characters long.
maxLength: 2048
minLength: 1
type: string
reason:
description: |-
reason is a CamelCase machine-readable explanation of the availability, e.g.
PreflightCheckFailed or SourceTopologyMismatch. It is required when
availability is Unavailable or Unknown and is normally omitted when Available.
The set of reasons is diagnostic and not exhaustive. Must start with an
uppercase letter and contain only alphanumeric characters, and must be
between 1 and 128 characters long.
maxLength: 128
minLength: 1
type: string
x-kubernetes-validations:
- message: reason must be CamelCase, matching ^[A-Z][A-Za-z0-9]*$
rule: self.matches('^[A-Z][A-Za-z0-9]*$')
source:
description: |-
source is the control-plane and infrastructure topology this transition starts
from. It must equal the current topology in the corresponding status fields.
source is required.
properties:
controlPlaneTopology:
description: |-
controlPlaneTopology is the topology of the control-plane nodes. Valid values
are SingleReplica and HighlyAvailable. When set to SingleReplica, operators
avoid spending resources for high availability. When set to HighlyAvailable,
operators configure high availability as much as possible.
controlPlaneTopology is required.
enum:
- SingleReplica
- HighlyAvailable
type: string
infrastructureTopology:
description: |-
infrastructureTopology is the topology of infrastructure services. Valid
values are SingleReplica and HighlyAvailable. When set to SingleReplica,
operators avoid spending resources for high availability. When set to
HighlyAvailable, operators configure high availability as much as possible.
infrastructureTopology is required.
enum:
- SingleReplica
- HighlyAvailable
type: string
required:
- controlPlaneTopology
- infrastructureTopology
type: object
target:
description: |-
target is the control-plane and infrastructure topology this transition would
move to. target is required.
properties:
controlPlaneTopology:
description: |-
controlPlaneTopology is the topology of the control-plane nodes. Valid values
are SingleReplica and HighlyAvailable. When set to SingleReplica, operators
avoid spending resources for high availability. When set to HighlyAvailable,
operators configure high availability as much as possible.
controlPlaneTopology is required.
enum:
- SingleReplica
- HighlyAvailable
type: string
infrastructureTopology:
description: |-
infrastructureTopology is the topology of infrastructure services. Valid
values are SingleReplica and HighlyAvailable. When set to SingleReplica,
operators avoid spending resources for high availability. When set to
HighlyAvailable, operators configure high availability as much as possible.
infrastructureTopology is required.
enum:
- SingleReplica
- HighlyAvailable
type: string
required:
- controlPlaneTopology
- infrastructureTopology
type: object
required:
- availability
- source
- target
type: object
x-kubernetes-validations:
- message: source and target must differ
rule: self.source.controlPlaneTopology != self.target.controlPlaneTopology
|| self.source.infrastructureTopology != self.target.infrastructureTopology
- message: reason is required when availability is not Available
rule: self.availability == 'Available' || has(self.reason)
maxItems: 1
minItems: 0
type: array
x-kubernetes-list-type: atomic
x-kubernetes-validations:
- message: only SingleReplica to HighlyAvailable topology transitions
are supported
rule: self.all(t, t.source.controlPlaneTopology == 'SingleReplica'
&& t.source.infrastructureTopology == 'SingleReplica' && t.target.controlPlaneTopology
== 'HighlyAvailable' && t.target.infrastructureTopology == 'HighlyAvailable')
type: object
required:
- spec
Expand All @@ -2856,6 +3001,11 @@ spec:
== self.status.controlPlaneTopology) || (has(self.status.controlPlaneTopology)
&& self.status.controlPlaneTopology == ''SingleReplica'' && self.spec.controlPlaneTopology
== ''HighlyAvailable'')'
- message: transition sources must match the current status topology
rule: '!has(self.status) || !has(self.status.topologyTransitions) || self.status.topologyTransitions.all(t,
has(self.status.controlPlaneTopology) && has(self.status.infrastructureTopology)
&& t.source.controlPlaneTopology == self.status.controlPlaneTopology &&
t.source.infrastructureTopology == self.status.infrastructureTopology)'
served: true
storage: true
subresources:
Expand Down
Loading