Skip to content

Commit 4e6c8f3

Browse files
authored
Merge pull request #12813 from sbueringer/pr-filter-refactoring
🌱 Simplify KCP matchesKubeadmConfig
2 parents a0bb17c + a7d9e68 commit 4e6c8f3

File tree

2 files changed

+442
-637
lines changed

2 files changed

+442
-637
lines changed

controlplane/kubeadm/internal/filters.go

Lines changed: 42 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)