@@ -44,7 +44,6 @@ import (
44
44
"sigs.k8s.io/controller-runtime/pkg/log"
45
45
"sigs.k8s.io/controller-runtime/pkg/source"
46
46
47
- "github.com/rancher/cluster-api-provider-rke2/controlplane/internal/util/ssa"
48
47
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
49
48
"sigs.k8s.io/cluster-api/controllers/clustercache"
50
49
"sigs.k8s.io/cluster-api/controllers/remote"
@@ -57,6 +56,8 @@ import (
57
56
"sigs.k8s.io/cluster-api/util/patch"
58
57
59
58
controlplanev1 "github.com/rancher/cluster-api-provider-rke2/controlplane/api/v1beta1"
59
+ "github.com/rancher/cluster-api-provider-rke2/controlplane/internal/contract"
60
+ "github.com/rancher/cluster-api-provider-rke2/controlplane/internal/util/ssa"
60
61
"github.com/rancher/cluster-api-provider-rke2/pkg/kubeconfig"
61
62
"github.com/rancher/cluster-api-provider-rke2/pkg/registration"
62
63
"github.com/rancher/cluster-api-provider-rke2/pkg/rke2"
@@ -65,8 +66,10 @@ import (
65
66
)
66
67
67
68
const (
69
+ // rke2ManagerName is the name of the RKE2 manager deployment.
68
70
rke2ManagerName = "rke2controlplane"
69
71
72
+ // rke2ControlPlaneKind is the kind of the RKE2 control plane.
70
73
rke2ControlPlaneKind = "RKE2ControlPlane"
71
74
72
75
// dependentCertRequeueAfter is how long to wait before checking again to see if
@@ -500,6 +503,10 @@ func (r *RKE2ControlPlaneReconciler) reconcileNormal(
500
503
return result , err
501
504
}
502
505
506
+ if err := r .syncMachines (ctx , rke2.ControlPlane {}); err != nil {
507
+ return ctrl.Result {}, errors .Wrap (err , "failed to sync Machines" )
508
+ }
509
+
503
510
controlPlaneMachines , err := r .managementClusterUncached .GetMachinesForCluster (
504
511
ctx ,
505
512
util .ObjectKey (cluster ),
@@ -1098,3 +1105,86 @@ func (r *RKE2ControlPlaneReconciler) getWorkloadCluster(ctx context.Context, clu
1098
1105
1099
1106
return workloadCluster , nil
1100
1107
}
1108
+
1109
+ // syncMachines updates Machines, InfrastructureMachines and Rke2Configs to propagate in-place mutable fields from KCP.
1110
+ // Note: It also cleans up managed fields of all Machines so that Machines that were
1111
+ // created/patched before (< v1.4.0)“ the controller adopted Server-Side-Apply (SSA) can also work with SSA.
1112
+ // Note: For InfrastructureMachines and Rke2Configs it also drops ownership of "metadata.labels" and
1113
+ // "metadata.annotations" from "manager" so that "rke2controlplane" can own these fields and can work with SSA.
1114
+ // Otherwise, fields would be co-owned by our "old" "manager" and "rke2controlplane" and then we would not be
1115
+ // able to e.g. drop labels and annotations.
1116
+ func (r * RKE2ControlPlaneReconciler ) syncMachines (ctx context.Context , controlPlane rke2.ControlPlane ) error {
1117
+ patchHelpers := map [string ]* patch.Helper {}
1118
+
1119
+ for machineName := range controlPlane .Machines {
1120
+ m := controlPlane .Machines [machineName ]
1121
+ // If the machine is already being deleted, we don't need to update it.
1122
+ if ! m .DeletionTimestamp .IsZero () {
1123
+ continue
1124
+ }
1125
+
1126
+ // Cleanup managed fields of all Machines.
1127
+ // We do this so that Machines that were created/patched before the controller adopted Server-Side-Apply (SSA)
1128
+ // (< v1.4.0) can also work with SSA. Otherwise, fields would be co-owned by our "old" "manager" and
1129
+ // "rke2controlplane" and then we would not be able to e.g. drop labels and annotations.
1130
+ if err := ssa .CleanUpManagedFieldsForSSAAdoption (ctx , r .Client , m , rke2ManagerName ); err != nil {
1131
+ return errors .Wrapf (err , "failed to update Machine: failed to adjust the managedFields of the Machine %s" , klog .KObj (m ))
1132
+ }
1133
+ // Update Machine to propagate in-place mutable fields from RCP.
1134
+ updatedMachine , err := r .UpdateMachine (ctx , m , controlPlane .RCP , controlPlane .Cluster )
1135
+ if err != nil {
1136
+ return errors .Wrapf (err , "failed to update Machine: %s" , klog .KObj (m ))
1137
+ }
1138
+
1139
+ controlPlane .Machines [machineName ] = updatedMachine
1140
+ // Since the machine is updated, re-create the patch helper so that any subsequent
1141
+ // Patch calls use the correct base machine object to calculate the diffs.
1142
+ // Example: reconcileControlPlaneConditions patches the machine objects in a subsequent call
1143
+ // and, it should use the updated machine to calculate the diff.
1144
+ // Note: If the patchHelpers are not re-computed based on the new updated machines, subsequent
1145
+ // Patch calls will fail because the patch will be calculated based on an outdated machine and will error
1146
+ // because of outdated resourceVersion.
1147
+ patchHelper , err := patch .NewHelper (updatedMachine , r .Client )
1148
+ if err != nil {
1149
+ return errors .Wrapf (err , "failed to create patch helper for Machine %s" , klog .KObj (updatedMachine ))
1150
+ }
1151
+
1152
+ patchHelpers [machineName ] = patchHelper
1153
+
1154
+ labelsAndAnnotationsManagedFieldPaths := []contract.Path {
1155
+ {"f:metadata" , "f:annotations" },
1156
+ {"f:metadata" , "f:labels" },
1157
+ }
1158
+ infraMachine := controlPlane .InfraResources [machineName ]
1159
+ // Cleanup managed fields of all InfrastructureMachines to drop ownership of labels and annotations
1160
+ // from "manager". We do this so that InfrastructureMachines that are created using the Create method
1161
+ // can also work with SSA. Otherwise, labels and annotations would be co-owned by our "old" "manager"
1162
+ // and "rke2-kubeadmcontrolplane" and then we would not be able to e.g. drop labels and annotations.
1163
+ if err := ssa .DropManagedFields (ctx , r .Client , infraMachine , rke2ManagerName , labelsAndAnnotationsManagedFieldPaths ); err != nil {
1164
+ return errors .Wrapf (err , "failed to clean up managedFields of InfrastructureMachine %s" , klog .KObj (infraMachine ))
1165
+ }
1166
+ // Update in-place mutating fields on InfrastructureMachine.
1167
+ if err := r .UpdateExternalObject (ctx , infraMachine , controlPlane .RCP , controlPlane .Cluster ); err != nil {
1168
+ return errors .Wrapf (err , "failed to update InfrastructureMachine %s" , klog .KObj (infraMachine ))
1169
+ }
1170
+
1171
+ rke2Config := controlPlane .Rke2Configs [machineName ]
1172
+ // Note: Set the GroupVersionKind because updateExternalObject depends on it.
1173
+ rke2Config .SetGroupVersionKind (m .Spec .Bootstrap .ConfigRef .GroupVersionKind ())
1174
+ // Cleanup managed fields of all Rke2Configs to drop ownership of labels and annotations
1175
+ // from "manager". We do this so that Rke2Configs that are created using the Create method
1176
+ // can also work with SSA. Otherwise, labels and annotations would be co-owned by our "old" "manager"
1177
+ // and "rke2controlplane" and then we would not be able to e.g. drop labels and annotations.
1178
+ if err := ssa .DropManagedFields (ctx , r .Client , rke2Config , rke2ManagerName , labelsAndAnnotationsManagedFieldPaths ); err != nil {
1179
+ return errors .Wrapf (err , "failed to clean up managedFields of KubeadmConfig %s" , klog .KObj (rke2Config ))
1180
+ }
1181
+ // Update in-place mutating fields on BootstrapConfig.
1182
+ if err := r .UpdateExternalObject (ctx , rke2Config , controlPlane .RCP , controlPlane .Cluster ); err != nil {
1183
+ return errors .Wrapf (err , "failed to update Rke2Config %s" , klog .KObj (rke2Config ))
1184
+ }
1185
+ }
1186
+ // Update the patch helpers.
1187
+ controlPlane .SetPatchHelpers (patchHelpers )
1188
+
1189
+ return nil
1190
+ }
0 commit comments