Skip to content

⚠️ Change .status.replicas fields to pointer + omitempty #12250

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 21, 2025
Merged
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
10 changes: 10 additions & 0 deletions api/v1beta1/conversion_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,11 @@ func hubMachineSetStatus(in *clusterv1.MachineSetStatus, c fuzz.Continue) {
if in.Deprecated.V1Beta1 == nil {
in.Deprecated.V1Beta1 = &clusterv1.MachineSetV1Beta1DeprecatedStatus{}
}
// nil becomes &0 after hub => spoke => hub conversion
// This is acceptable as usually Replicas is set and controllers using older apiVersions are not writing MachineSet status.
if in.Replicas == nil {
in.Replicas = ptr.To(int32(0))
}
}

func spokeMachineSetStatus(in *MachineSetStatus, c fuzz.Continue) {
Expand Down Expand Up @@ -304,6 +309,11 @@ func hubMachineDeploymentStatus(in *clusterv1.MachineDeploymentStatus, c fuzz.Co
if in.Deprecated.V1Beta1 == nil {
in.Deprecated.V1Beta1 = &clusterv1.MachineDeploymentV1Beta1DeprecatedStatus{}
}
// nil becomes &0 after hub => spoke => hub conversion
// This is acceptable as usually Replicas is set and controllers using older apiVersions are not writing MachineSet status.
if in.Replicas == nil {
in.Replicas = ptr.To(int32(0))
}
}

func spokeMachineDeploymentSpec(in *MachineDeploymentSpec, c fuzz.Continue) {
Expand Down
16 changes: 12 additions & 4 deletions api/v1beta1/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion api/v1beta2/machinedeployment_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ type MachineDeploymentStatus struct {
// replicas is the total number of non-terminated machines targeted by this deployment
// (their labels match the selector).
// +optional
Replicas int32 `json:"replicas"`
Replicas *int32 `json:"replicas,omitempty"`

// readyReplicas is the number of ready replicas for this MachineDeployment. A machine is considered ready when Machine's Ready condition is true.
// +optional
Expand Down
2 changes: 1 addition & 1 deletion api/v1beta2/machineset_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ type MachineSetStatus struct {

// replicas is the most recently observed number of replicas.
// +optional
Replicas int32 `json:"replicas"`
Replicas *int32 `json:"replicas,omitempty"`

// readyReplicas is the number of ready replicas for this MachineSet. A machine is considered ready when Machine's Ready condition is true.
// +optional
Expand Down
10 changes: 10 additions & 0 deletions api/v1beta2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions api/v1beta2/zz_generated.openapi.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions controlplane/kubeadm/api/v1beta1/conversion_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
fuzz "github.com/google/gofuzz"
"k8s.io/apimachinery/pkg/api/apitesting/fuzzer"
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/utils/ptr"

bootstrapv1beta1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1beta1"
controlplanev1 "sigs.k8s.io/cluster-api/controlplane/kubeadm/api/v1beta2"
Expand Down Expand Up @@ -70,6 +71,12 @@ func hubKubeadmControlPlaneStatus(in *controlplanev1.KubeadmControlPlaneStatus,
in.Initialization = nil
}
}

// nil becomes &0 after hub => spoke => hub conversion
// This is acceptable as usually Replicas is set and controllers using older apiVersions are not writing MachineSet status.
if in.Replicas == nil {
in.Replicas = ptr.To(int32(0))
}
}

func spokeKubeadmControlPlaneStatus(in *KubeadmControlPlaneStatus, c fuzz.Continue) {
Expand Down
8 changes: 6 additions & 2 deletions controlplane/kubeadm/api/v1beta1/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -650,7 +650,7 @@ type KubeadmControlPlaneStatus struct {
// replicas is the total number of non-terminated machines targeted by this control plane
// (their labels match the selector).
// +optional
Replicas int32 `json:"replicas"`
Replicas *int32 `json:"replicas,omitempty"`

// readyReplicas is the number of ready replicas for this KubeadmControlPlane. A machine is considered ready when Machine's Ready condition is true.
// +optional
Expand Down
5 changes: 5 additions & 0 deletions controlplane/kubeadm/api/v1beta2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions controlplane/kubeadm/internal/controllers/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1385,7 +1385,7 @@ kubernetesVersion: metav1.16.1
g.Expect(kcp.Finalizers).To(ContainElement(controlplanev1.KubeadmControlPlaneFinalizer))

g.Expect(kcp.Status.Selector).NotTo(BeEmpty())
g.Expect(kcp.Status.Replicas).To(BeEquivalentTo(1))
g.Expect(kcp.Status.Replicas).To(HaveValue(BeEquivalentTo(1)))
g.Expect(v1beta1conditions.IsFalse(kcp, controlplanev1.AvailableV1Beta1Condition)).To(BeTrue())
g.Expect(conditions.IsFalse(kcp, controlplanev1.KubeadmControlPlaneInitializedCondition)).To(BeTrue())

Expand Down Expand Up @@ -1626,7 +1626,7 @@ kubernetesVersion: metav1.16.1`,
g.Expect(kcp.Finalizers).To(ContainElement(controlplanev1.KubeadmControlPlaneFinalizer))

g.Expect(kcp.Status.Selector).NotTo(BeEmpty())
g.Expect(kcp.Status.Replicas).To(BeEquivalentTo(1))
g.Expect(kcp.Status.Replicas).To(HaveValue(BeEquivalentTo(1)))
g.Expect(v1beta1conditions.IsFalse(kcp, controlplanev1.AvailableV1Beta1Condition)).To(BeTrue())

// Verify that the kubeconfig is using the custom CA
Expand Down
2 changes: 1 addition & 1 deletion controlplane/kubeadm/internal/controllers/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ func setReplicas(_ context.Context, kcp *controlplanev1.KubeadmControlPlane, mac
}
}

kcp.Status.Replicas = int32(len(machines))
kcp.Status.Replicas = ptr.To(int32(len(machines)))
kcp.Status.ReadyReplicas = ptr.To(readyReplicas)
kcp.Status.AvailableReplicas = ptr.To(availableReplicas)
kcp.Status.UpToDateReplicas = ptr.To(upToDateReplicas)
Expand Down
27 changes: 14 additions & 13 deletions controlplane/kubeadm/internal/controllers/status_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ func TestSetReplicas(t *testing.T) {
setReplicas(ctx, c.KCP, c.Machines)

g.Expect(kcp.Status).ToNot(BeNil())
g.Expect(kcp.Status.Replicas).To(Equal(int32(6)))
g.Expect(kcp.Status.Replicas).ToNot(BeNil())
g.Expect(*kcp.Status.Replicas).To(Equal(int32(6)))
g.Expect(kcp.Status.ReadyReplicas).ToNot(BeNil())
g.Expect(*kcp.Status.ReadyReplicas).To(Equal(int32(3)))
g.Expect(kcp.Status.AvailableReplicas).ToNot(BeNil())
Expand Down Expand Up @@ -304,7 +305,7 @@ func Test_setScalingUpCondition(t *testing.T) {
controlPlane: &internal.ControlPlane{
KCP: &controlplanev1.KubeadmControlPlane{
Spec: controlplanev1.KubeadmControlPlaneSpec{Replicas: ptr.To(int32(3))},
Status: controlplanev1.KubeadmControlPlaneStatus{Replicas: 3},
Status: controlplanev1.KubeadmControlPlaneStatus{Replicas: ptr.To(int32(3))},
},
Machines: collections.FromMachines(
&clusterv1.Machine{ObjectMeta: metav1.ObjectMeta{Name: "m1"}},
Expand All @@ -323,7 +324,7 @@ func Test_setScalingUpCondition(t *testing.T) {
controlPlane: &internal.ControlPlane{
KCP: &controlplanev1.KubeadmControlPlane{
Spec: controlplanev1.KubeadmControlPlaneSpec{Replicas: ptr.To(int32(3)), MachineTemplate: controlplanev1.KubeadmControlPlaneMachineTemplate{InfrastructureRef: corev1.ObjectReference{Kind: "AWSTemplate"}}},
Status: controlplanev1.KubeadmControlPlaneStatus{Replicas: 3},
Status: controlplanev1.KubeadmControlPlaneStatus{Replicas: ptr.To(int32(3))},
},
Machines: collections.FromMachines(
&clusterv1.Machine{ObjectMeta: metav1.ObjectMeta{Name: "m1"}},
Expand All @@ -344,7 +345,7 @@ func Test_setScalingUpCondition(t *testing.T) {
controlPlane: &internal.ControlPlane{
KCP: &controlplanev1.KubeadmControlPlane{
Spec: controlplanev1.KubeadmControlPlaneSpec{Replicas: ptr.To(int32(5))},
Status: controlplanev1.KubeadmControlPlaneStatus{Replicas: 3},
Status: controlplanev1.KubeadmControlPlaneStatus{Replicas: ptr.To(int32(3))},
},
Machines: collections.FromMachines(
&clusterv1.Machine{ObjectMeta: metav1.ObjectMeta{Name: "m1"}},
Expand All @@ -365,7 +366,7 @@ func Test_setScalingUpCondition(t *testing.T) {
KCP: &controlplanev1.KubeadmControlPlane{
ObjectMeta: metav1.ObjectMeta{DeletionTimestamp: ptr.To(metav1.Time{Time: time.Now()})},
Spec: controlplanev1.KubeadmControlPlaneSpec{Replicas: ptr.To(int32(5))},
Status: controlplanev1.KubeadmControlPlaneStatus{Replicas: 3},
Status: controlplanev1.KubeadmControlPlaneStatus{Replicas: ptr.To(int32(3))},
},
Machines: collections.FromMachines(
&clusterv1.Machine{ObjectMeta: metav1.ObjectMeta{Name: "m1"}},
Expand All @@ -384,7 +385,7 @@ func Test_setScalingUpCondition(t *testing.T) {
controlPlane: &internal.ControlPlane{
KCP: &controlplanev1.KubeadmControlPlane{
Spec: controlplanev1.KubeadmControlPlaneSpec{Replicas: ptr.To(int32(5)), MachineTemplate: controlplanev1.KubeadmControlPlaneMachineTemplate{InfrastructureRef: corev1.ObjectReference{Kind: "AWSTemplate"}}},
Status: controlplanev1.KubeadmControlPlaneStatus{Replicas: 3},
Status: controlplanev1.KubeadmControlPlaneStatus{Replicas: ptr.To(int32(3))},
},
Machines: collections.FromMachines(
&clusterv1.Machine{ObjectMeta: metav1.ObjectMeta{Name: "m1"}},
Expand Down Expand Up @@ -413,7 +414,7 @@ func Test_setScalingUpCondition(t *testing.T) {
},
KCP: &controlplanev1.KubeadmControlPlane{
Spec: controlplanev1.KubeadmControlPlaneSpec{Replicas: ptr.To(int32(5))},
Status: controlplanev1.KubeadmControlPlaneStatus{Replicas: 3},
Status: controlplanev1.KubeadmControlPlaneStatus{Replicas: ptr.To(int32(3))},
},
Machines: collections.FromMachines(
&clusterv1.Machine{ObjectMeta: metav1.ObjectMeta{Name: "m1"}},
Expand Down Expand Up @@ -475,7 +476,7 @@ func Test_setScalingDownCondition(t *testing.T) {
controlPlane: &internal.ControlPlane{
KCP: &controlplanev1.KubeadmControlPlane{
Spec: controlplanev1.KubeadmControlPlaneSpec{Replicas: ptr.To(int32(3))},
Status: controlplanev1.KubeadmControlPlaneStatus{Replicas: 3},
Status: controlplanev1.KubeadmControlPlaneStatus{Replicas: ptr.To(int32(3))},
},
Machines: collections.FromMachines(
&clusterv1.Machine{ObjectMeta: metav1.ObjectMeta{Name: "m1"}},
Expand All @@ -494,7 +495,7 @@ func Test_setScalingDownCondition(t *testing.T) {
controlPlane: &internal.ControlPlane{
KCP: &controlplanev1.KubeadmControlPlane{
Spec: controlplanev1.KubeadmControlPlaneSpec{Replicas: ptr.To(int32(3))},
Status: controlplanev1.KubeadmControlPlaneStatus{Replicas: 5},
Status: controlplanev1.KubeadmControlPlaneStatus{Replicas: ptr.To(int32(5))},
},
Machines: collections.FromMachines(
&clusterv1.Machine{ObjectMeta: metav1.ObjectMeta{Name: "m1"}},
Expand All @@ -517,7 +518,7 @@ func Test_setScalingDownCondition(t *testing.T) {
KCP: &controlplanev1.KubeadmControlPlane{
ObjectMeta: metav1.ObjectMeta{DeletionTimestamp: ptr.To(metav1.Time{Time: time.Now()})},
Spec: controlplanev1.KubeadmControlPlaneSpec{Replicas: ptr.To(int32(3))},
Status: controlplanev1.KubeadmControlPlaneStatus{Replicas: 5},
Status: controlplanev1.KubeadmControlPlaneStatus{Replicas: ptr.To(int32(5))},
},
Machines: collections.FromMachines(
&clusterv1.Machine{ObjectMeta: metav1.ObjectMeta{Name: "m1"}},
Expand All @@ -539,7 +540,7 @@ func Test_setScalingDownCondition(t *testing.T) {
controlPlane: &internal.ControlPlane{
KCP: &controlplanev1.KubeadmControlPlane{
Spec: controlplanev1.KubeadmControlPlaneSpec{Replicas: ptr.To(int32(1))},
Status: controlplanev1.KubeadmControlPlaneStatus{Replicas: 3},
Status: controlplanev1.KubeadmControlPlaneStatus{Replicas: ptr.To(int32(3))},
},
Machines: collections.FromMachines(
&clusterv1.Machine{ObjectMeta: metav1.ObjectMeta{Name: "m1", DeletionTimestamp: ptr.To(metav1.Time{Time: time.Now().Add(-1 * time.Hour)})},
Expand Down Expand Up @@ -579,7 +580,7 @@ After above Pods have been removed from the Node, the following Pods will be evi
controlPlane: &internal.ControlPlane{
KCP: &controlplanev1.KubeadmControlPlane{
Spec: controlplanev1.KubeadmControlPlaneSpec{Replicas: ptr.To(int32(1))},
Status: controlplanev1.KubeadmControlPlaneStatus{Replicas: 3},
Status: controlplanev1.KubeadmControlPlaneStatus{Replicas: ptr.To(int32(3))},
},
Machines: collections.FromMachines(
&clusterv1.Machine{ObjectMeta: metav1.ObjectMeta{Name: "m1", DeletionTimestamp: ptr.To(metav1.Time{Time: time.Now().Add(-1 * time.Hour)})}},
Expand Down Expand Up @@ -607,7 +608,7 @@ After above Pods have been removed from the Node, the following Pods will be evi
},
KCP: &controlplanev1.KubeadmControlPlane{
Spec: controlplanev1.KubeadmControlPlaneSpec{Replicas: ptr.To(int32(1))},
Status: controlplanev1.KubeadmControlPlaneStatus{Replicas: 3},
Status: controlplanev1.KubeadmControlPlaneStatus{Replicas: ptr.To(int32(3))},
},
Machines: collections.FromMachines(
&clusterv1.Machine{ObjectMeta: metav1.ObjectMeta{Name: "m1"}},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ proposal because most of the changes described below are a consequence of the wo
- See changes that apply to [all CRDs](#all-crds)
- The `spec.progressDeadlineSeconds` field (deprecated since CAPI v1.9) has been removed
- Replica counters are now consistent with replica counters from other resources
- `status.replicas` was made a pointer and omitempty was added
- `status.readyReplicas` has now a new semantic based on machine's `Ready` condition
- `status.availableReplicas` has now a new semantic based on machine's `Available` condition
- `status.upToDateReplicas` has now a new semantic (and name) based on machine's `UpToDate` condition
Expand All @@ -111,6 +112,7 @@ proposal because most of the changes described below are a consequence of the wo

- See changes that apply to [all CRDs](#all-crds)
- Replica counters fields are now consistent with replica counters from other resources
- `status.replicas` was made a pointer and omitempty was added
- `status.readyReplicas` has now a new semantic based on machine's `Ready` condition
- `status.availableReplicas` has now a new semantic based on machine's `Available` condition
- `status.upToDateReplicas` has now a new semantic (and name) based on machine's `UpToDate` condition
Expand All @@ -121,6 +123,7 @@ proposal because most of the changes described below are a consequence of the wo
### MachinePool

- See changes that apply to [all CRDs](#all-crds)
- `status.replicas` was made a pointer and omitempty was added
- Support for terminal errors has been dropped.
- `status.failureReason` and `status.failureMessage` will continue to exist temporarily under `status.deprecated.v1beta1`.
- The const values for `Failed` phase has been deprecated in the enum type for `status.phase` (controllers are not setting this value anymore)
Expand Down Expand Up @@ -165,6 +168,7 @@ proposal because most of the changes described below are a consequence of the wo
- KubeadmControlPlane (and the entire KCP provider) now implements the v1beta2 Cluster API contract.
- See changes that apply to [all CRDs](#all-crds)
- Replica counters fields are now consistent with replica counters from other resources.
- `status.replicas` was made a pointer and omitempty was added
- `status.readyReplicas` has now a new semantic based on machine's `Ready` condition
- `status.availableReplicas` has now a new semantic based on machine's `Available` condition
- `status.upToDateReplicas` has now a new semantic (and name) based on machine's `UpToDate` condition
Expand Down
7 changes: 7 additions & 0 deletions exp/api/v1beta1/conversion_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
fuzz "github.com/google/gofuzz"
"k8s.io/apimachinery/pkg/api/apitesting/fuzzer"
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/utils/ptr"

expv1 "sigs.k8s.io/cluster-api/exp/api/v1beta2"
utilconversion "sigs.k8s.io/cluster-api/util/conversion"
Expand Down Expand Up @@ -63,6 +64,12 @@ func hubMachinePoolStatus(in *expv1.MachinePoolStatus, c fuzz.Continue) {
in.Initialization = nil
}
}

// nil becomes &0 after hub => spoke => hub conversion
// This is acceptable as usually Replicas is set and controllers using older apiVersions are not writing MachineSet status.
if in.Replicas == nil {
in.Replicas = ptr.To(int32(0))
}
}

func spokeMachinePoolStatus(in *MachinePoolStatus, c fuzz.Continue) {
Expand Down
Loading
Loading