@@ -163,109 +163,88 @@ func matchesKubeadmConfig(kubeadmConfigs map[string]*bootstrapv1.KubeadmConfig,
163163 return "" , true , nil
164164 }
165165
166- // Check if KCP and machine ClusterConfiguration matches, if not return
167- match , diff , err := matchClusterConfiguration (currentKubeadmConfig , kcp )
166+ // takes the KubeadmConfigSpec from KCP and applies the transformations required
167+ // to allow a comparison with the KubeadmConfig referenced from the machine.
168+ desiredKubeadmConfig := getAdjustedKcpConfig (kcp , currentKubeadmConfig )
169+
170+ desiredKubeadmConfigForDiff , currentKubeadmConfigForDiff , err := PrepareKubeadmConfigsForDiff (desiredKubeadmConfig , currentKubeadmConfig , kcp )
168171 if err != nil {
169172 return "" , false , errors .Wrapf (err , "failed to match KubeadmConfig" )
170173 }
171- if ! match {
172- return fmt .Sprintf ("Machine KubeadmConfig ClusterConfiguration is outdated: diff: %s" , diff ), false , nil
173- }
174174
175- // Check if KCP and machine InitConfiguration or JoinConfiguration matches
175+ // Check if current and desired KubeadmConfigs match.
176176 // NOTE: only one between init configuration and join configuration is set on a machine, depending
177177 // on the fact that the machine was the initial control plane node or a joining control plane node.
178- match , diff , err = matchInitOrJoinConfiguration ( currentKubeadmConfig , kcp )
178+ match , diff , err := compare . Diff ( & currentKubeadmConfigForDiff . Spec , & desiredKubeadmConfigForDiff . Spec )
179179 if err != nil {
180180 return "" , false , errors .Wrapf (err , "failed to match KubeadmConfig" )
181181 }
182182 if ! match {
183- return fmt .Sprintf ("Machine KubeadmConfig InitConfiguration or JoinConfiguration are outdated: diff: %s" , diff ), false , nil
183+ return fmt .Sprintf ("Machine KubeadmConfig is outdated: diff: %s" , diff ), false , nil
184184 }
185185
186186 return "" , true , nil
187187}
188188
189- // matchClusterConfiguration verifies if KCP and machine ClusterConfiguration matches.
190- func matchClusterConfiguration (machineConfig * bootstrapv1.KubeadmConfig , kcp * controlplanev1.KubeadmControlPlane ) (bool , string , error ) {
191- if machineConfig == nil {
192- // Return true here because failing to get KubeadmConfig should not be considered as unmatching.
193- // This is a safety precaution to avoid rolling out machines if the client or the api-server is misbehaving.
194- return true , "" , nil
195- }
196- machineConfig = machineConfig .DeepCopy ()
197-
198- kcpLocalKubeadmConfig := kcp .Spec .KubeadmConfigSpec .DeepCopy ()
199- if kcpLocalKubeadmConfig == nil {
200- kcpLocalKubeadmConfig = & bootstrapv1.KubeadmConfigSpec {}
201- }
189+ // PrepareKubeadmConfigsForDiff cleans up all fields that are not relevant for the comparison.
190+ func PrepareKubeadmConfigsForDiff (desiredKubeadmConfig , currentKubeadmConfig * bootstrapv1.KubeadmConfig , kcp * controlplanev1.KubeadmControlPlane ) (desired * bootstrapv1.KubeadmConfig , current * bootstrapv1.KubeadmConfig , _ error ) {
191+ // DeepCopy to ensure the passed in KubeadmConfigs are not modified.
192+ // This has to be done because we eventually want to be able to apply the desiredKubeadmConfig
193+ // (without the modifications that we make here).
194+ desiredKubeadmConfig = desiredKubeadmConfig .DeepCopy ()
195+ currentKubeadmConfig = currentKubeadmConfig .DeepCopy ()
202196
203197 // Default feature gates like in initializeControlPlane / scaleUpControlPlane.
204198 // Note: Changes in feature gates can still trigger rollouts.
205199 // TODO(in-place) refactor this area so the desired KubeadmConfig is not computed in multiple places independently.
206200 parsedVersion , err := semver .ParseTolerant (kcp .Spec .Version )
207201 if err != nil {
208- return false , "" , errors .Wrapf (err , "failed to parse Kubernetes version %q" , kcp .Spec .Version )
202+ return nil , nil , errors .Wrapf (err , "failed to parse Kubernetes version %q" , kcp .Spec .Version )
209203 }
210- DefaultFeatureGates (kcpLocalKubeadmConfig , parsedVersion )
204+ DefaultFeatureGates (& desiredKubeadmConfig . Spec , parsedVersion )
211205
212206 // Ignore ControlPlaneEndpoint which is added on the Machine KubeadmConfig by CABPK.
213207 // Note: ControlPlaneEndpoint should also never change for a Cluster, so no reason to trigger a rollout because of that.
214- machineConfig .Spec .ClusterConfiguration .ControlPlaneEndpoint = kcpLocalKubeadmConfig .ClusterConfiguration .ControlPlaneEndpoint
208+ currentKubeadmConfig .Spec .ClusterConfiguration .ControlPlaneEndpoint = desiredKubeadmConfig . Spec .ClusterConfiguration .ControlPlaneEndpoint
215209
216210 // Skip checking DNS fields because we can update the configuration of the working cluster in place.
217- machineConfig .Spec .ClusterConfiguration .DNS = kcpLocalKubeadmConfig .ClusterConfiguration .DNS
218-
219- // Drop differences that do not lead to changes to Machines, but that might exist due
220- // to changes in how we serialize objects or how webhooks work.
221- dropOmittableFields (kcpLocalKubeadmConfig )
222- dropOmittableFields (& machineConfig .Spec )
223-
224- // Compare and return.
225- match , diff , err := compare .Diff (machineConfig .Spec .ClusterConfiguration , kcpLocalKubeadmConfig .ClusterConfiguration )
226- if err != nil {
227- return false , "" , errors .Wrapf (err , "failed to match ClusterConfiguration" )
228- }
229- return match , diff , nil
230- }
231-
232- // matchInitOrJoinConfiguration verifies if KCP and machine InitConfiguration or JoinConfiguration matches.
233- // NOTE: By extension this method takes care of detecting changes in other fields of the KubeadmConfig configuration (e.g. Files, Mounts etc.)
234- func matchInitOrJoinConfiguration (machineConfig * bootstrapv1.KubeadmConfig , kcp * controlplanev1.KubeadmControlPlane ) (bool , string , error ) {
235- if machineConfig == nil {
236- // Return true here because failing to get KubeadmConfig should not be considered as unmatching.
237- // This is a safety precaution to avoid rolling out machines if the client or the api-server is misbehaving.
238- return true , "" , nil
239- }
240- machineConfig = machineConfig .DeepCopy ()
241-
242- // takes the KubeadmConfigSpec from KCP and applies the transformations required
243- // to allow a comparison with the KubeadmConfig referenced from the machine.
244- kcpConfig := getAdjustedKcpConfig (kcp , machineConfig )
211+ currentKubeadmConfig .Spec .ClusterConfiguration .DNS = desiredKubeadmConfig .Spec .ClusterConfiguration .DNS
245212
246213 // Default both KubeadmConfigSpecs before comparison.
247214 // *Note* This assumes that newly added default values never
248215 // introduce a semantic difference to the unset value.
249216 // But that is something that is ensured by our API guarantees.
250- defaulting .ApplyPreviousKubeadmConfigDefaults (kcpConfig )
251- defaulting .ApplyPreviousKubeadmConfigDefaults (& machineConfig .Spec )
217+ defaulting .ApplyPreviousKubeadmConfigDefaults (& desiredKubeadmConfig . Spec )
218+ defaulting .ApplyPreviousKubeadmConfigDefaults (& currentKubeadmConfig .Spec )
252219
253- // Cleanup all fields that are not relevant for the comparison.
254- cleanupConfigFields (kcpConfig , machineConfig )
220+ // Cleanup JoinConfiguration.Discovery from desiredKubeadmConfig and currentKubeadmConfig, because those info are relevant only for
221+ // the join process and not for comparing the configuration of the machine.
222+ // Note: Changes to Discovery will apply for the next join, but they will not lead to a rollout.
223+ // Note: We should also not send Discovery.BootstrapToken.Token to a RuntimeExtension for security reasons.
224+ desiredKubeadmConfig .Spec .JoinConfiguration .Discovery = bootstrapv1.Discovery {}
225+ currentKubeadmConfig .Spec .JoinConfiguration .Discovery = bootstrapv1.Discovery {}
255226
256- // Compare and return.
257- match , diff , err := compare .Diff (& machineConfig .Spec , kcpConfig )
258- if err != nil {
259- return false , "" , errors .Wrapf (err , "failed to match InitConfiguration or JoinConfiguration" )
227+ // If KCP JoinConfiguration.ControlPlane is nil and the Machine JoinConfiguration.ControlPlane is empty,
228+ // set Machine JoinConfiguration.ControlPlane to nil.
229+ // NOTE: This is required because CABPK applies an empty JoinConfiguration.ControlPlane in case it is nil.
230+ if desiredKubeadmConfig .Spec .JoinConfiguration .ControlPlane == nil &&
231+ reflect .DeepEqual (currentKubeadmConfig .Spec .JoinConfiguration .ControlPlane , & bootstrapv1.JoinControlPlane {}) {
232+ currentKubeadmConfig .Spec .JoinConfiguration .ControlPlane = nil
260233 }
261- return match , diff , nil
234+
235+ // Drop differences that do not lead to changes to Machines, but that might exist due
236+ // to changes in how we serialize objects or how webhooks work.
237+ dropOmittableFields (& desiredKubeadmConfig .Spec )
238+ dropOmittableFields (& currentKubeadmConfig .Spec )
239+
240+ return desiredKubeadmConfig , currentKubeadmConfig , nil
262241}
263242
264243// getAdjustedKcpConfig takes the KubeadmConfigSpec from KCP and applies the transformations required
265244// to allow a comparison with the KubeadmConfig referenced from the machine.
266245// NOTE: The KCP controller applies a set of transformations when creating a KubeadmConfig referenced from the machine;
267246// those transformations are implemented in ControlPlane.InitialControlPlaneConfig() and ControlPlane.JoinControlPlaneConfig().
268- func getAdjustedKcpConfig (kcp * controlplanev1.KubeadmControlPlane , machineConfig * bootstrapv1.KubeadmConfig ) * bootstrapv1.KubeadmConfigSpec {
247+ func getAdjustedKcpConfig (kcp * controlplanev1.KubeadmControlPlane , machineConfig * bootstrapv1.KubeadmConfig ) * bootstrapv1.KubeadmConfig {
269248 kcpConfig := kcp .Spec .KubeadmConfigSpec .DeepCopy ()
270249
271250 // if Machine's JoinConfiguration is set, this is a joining control plane machine, so empty out the InitConfiguration;
@@ -278,36 +257,7 @@ func getAdjustedKcpConfig(kcp *controlplanev1.KubeadmControlPlane, machineConfig
278257 kcpConfig .JoinConfiguration = bootstrapv1.JoinConfiguration {}
279258 }
280259
281- return kcpConfig
282- }
283-
284- // cleanupConfigFields cleanups all the fields that are not relevant for the comparison.
285- // Note: This function assumes that old defaults have been applied to kcpConfig and machineConfig
286- // as a consequence we can assume JoinConfiguration and JoinConfiguration.NodeRegistration are always defined.
287- func cleanupConfigFields (kcpConfig * bootstrapv1.KubeadmConfigSpec , machineConfig * bootstrapv1.KubeadmConfig ) {
288- // KCP ClusterConfiguration will be compared in `matchClusterConfiguration` so we are cleaning it up here
289- // so it doesn't lead to a duplicate diff in `matchInitOrJoinConfiguration`.
290- kcpConfig .ClusterConfiguration = bootstrapv1.ClusterConfiguration {}
291- machineConfig .Spec .ClusterConfiguration = bootstrapv1.ClusterConfiguration {}
292-
293- // Cleanup JoinConfiguration.Discovery from kcpConfig and machineConfig, because those info are relevant only for
294- // the join process and not for comparing the configuration of the machine.
295- // Note: Changes to Discovery will apply for the next join, but they will not lead to a rollout.
296- kcpConfig .JoinConfiguration .Discovery = bootstrapv1.Discovery {}
297- machineConfig .Spec .JoinConfiguration .Discovery = bootstrapv1.Discovery {}
298-
299- // If KCP JoinConfiguration.ControlPlane is nil and the Machine JoinConfiguration.ControlPlane is empty,
300- // set Machine JoinConfiguration.ControlPlane to nil.
301- // NOTE: This is required because CABPK applies an empty JoinConfiguration.ControlPlane in case it is nil.
302- if kcpConfig .JoinConfiguration .ControlPlane == nil &&
303- reflect .DeepEqual (machineConfig .Spec .JoinConfiguration .ControlPlane , & bootstrapv1.JoinControlPlane {}) {
304- machineConfig .Spec .JoinConfiguration .ControlPlane = nil
305- }
306-
307- // Drop differences that do not lead to changes to Machines, but that might exist due
308- // to changes in how we serialize objects or how webhooks work.
309- dropOmittableFields (kcpConfig )
310- dropOmittableFields (& machineConfig .Spec )
260+ return & bootstrapv1.KubeadmConfig {Spec : * kcpConfig }
311261}
312262
313263// dropOmittableFields makes the comparison tolerant to omittable fields being set in the go struct. It applies to:
0 commit comments