Skip to content

Commit c54a51b

Browse files
authored
Merge pull request #11393 from fabriziopandini/add-machine-upToDate-condition-to-MachineSet
✨ Add machine UpToDate condition to MachineSet
2 parents 9b37a3b + 769af58 commit c54a51b

File tree

4 files changed

+445
-323
lines changed

4 files changed

+445
-323
lines changed

internal/controllers/machinedeployment/mdutil/util.go

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ package mdutil
2020
import (
2121
"context"
2222
"fmt"
23+
"reflect"
2324
"sort"
2425
"strconv"
2526
"strings"
@@ -38,7 +39,6 @@ import (
3839
ctrl "sigs.k8s.io/controller-runtime"
3940

4041
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
41-
"sigs.k8s.io/cluster-api/internal/util/compare"
4242
"sigs.k8s.io/cluster-api/util/conversion"
4343
)
4444

@@ -371,13 +371,50 @@ func getMachineSetFraction(ms clusterv1.MachineSet, md clusterv1.MachineDeployme
371371
return integer.RoundToInt32(newMSsize) - *(ms.Spec.Replicas)
372372
}
373373

374-
// EqualMachineTemplate returns true if two given machineTemplateSpec are equal,
375-
// ignoring all the in-place propagated fields, and the version from external references.
376-
func EqualMachineTemplate(template1, template2 *clusterv1.MachineTemplateSpec) (equal bool, diff string, err error) {
377-
t1Copy := MachineTemplateDeepCopyRolloutFields(template1)
378-
t2Copy := MachineTemplateDeepCopyRolloutFields(template2)
374+
// MachineTemplateUpToDate returns true if the current MachineTemplateSpec is up-to-date with a corresponding desired MachineTemplateSpec.
375+
// Note: The comparison does not consider any in-place propagated fields, as well as the version from external references.
376+
func MachineTemplateUpToDate(current, desired *clusterv1.MachineTemplateSpec) (upToDate bool, logMessages, conditionMessages []string) {
377+
currentCopy := MachineTemplateDeepCopyRolloutFields(current)
378+
desiredCopy := MachineTemplateDeepCopyRolloutFields(desired)
379379

380-
return compare.Diff(t1Copy, t2Copy)
380+
if !reflect.DeepEqual(currentCopy.Spec.Version, desiredCopy.Spec.Version) {
381+
logMessages = append(logMessages, fmt.Sprintf("spec.version %s, %s required", ptr.Deref(currentCopy.Spec.Version, "nil"), ptr.Deref(desiredCopy.Spec.Version, "nil")))
382+
conditionMessages = append(conditionMessages, fmt.Sprintf("Version %s, %s required", ptr.Deref(currentCopy.Spec.Version, "nil"), ptr.Deref(desiredCopy.Spec.Version, "nil")))
383+
}
384+
385+
// Note: we return a message based on desired.bootstrap.ConfigRef != nil, but we always compare the entire bootstrap
386+
// struct to catch cases when either configRef or dataSecretName is set in current vs desired (usually MachineTemplates
387+
// have ConfigRef != nil, might be in some edge case dataSecret are used, but switching from one to another is not a
388+
// common operation so it is acceptable to handle it in this way).
389+
if currentCopy.Spec.Bootstrap.ConfigRef != nil {
390+
if !reflect.DeepEqual(currentCopy.Spec.Bootstrap, desiredCopy.Spec.Bootstrap) {
391+
logMessages = append(logMessages, fmt.Sprintf("spec.bootstrap.configRef %s %s, %s %s required", currentCopy.Spec.Bootstrap.ConfigRef.Kind, currentCopy.Spec.Bootstrap.ConfigRef.Name, ptr.Deref(desiredCopy.Spec.Bootstrap.ConfigRef, corev1.ObjectReference{}).Kind, ptr.Deref(desiredCopy.Spec.Bootstrap.ConfigRef, corev1.ObjectReference{}).Name))
392+
// Note: dropping "Template" suffix because conditions message will surface on machine.
393+
conditionMessages = append(conditionMessages, fmt.Sprintf("%s is not up-to-date", strings.TrimSuffix(currentCopy.Spec.Bootstrap.ConfigRef.Kind, clusterv1.TemplateSuffix)))
394+
}
395+
} else {
396+
if !reflect.DeepEqual(currentCopy.Spec.Bootstrap, desiredCopy.Spec.Bootstrap) {
397+
logMessages = append(logMessages, fmt.Sprintf("spec.bootstrap.dataSecretName %s, %s required", ptr.Deref(currentCopy.Spec.Bootstrap.DataSecretName, "nil"), ptr.Deref(desiredCopy.Spec.Bootstrap.DataSecretName, "nil")))
398+
conditionMessages = append(conditionMessages, fmt.Sprintf("spec.bootstrap.dataSecretName %s, %s required", ptr.Deref(currentCopy.Spec.Bootstrap.DataSecretName, "nil"), ptr.Deref(desiredCopy.Spec.Bootstrap.DataSecretName, "nil")))
399+
}
400+
}
401+
402+
if !reflect.DeepEqual(currentCopy.Spec.InfrastructureRef, desiredCopy.Spec.InfrastructureRef) {
403+
logMessages = append(logMessages, fmt.Sprintf("spec.infrastructureRef %s %s, %s %s required", currentCopy.Spec.InfrastructureRef.Kind, currentCopy.Spec.InfrastructureRef.Name, desiredCopy.Spec.InfrastructureRef.Kind, desiredCopy.Spec.InfrastructureRef.Name))
404+
// Note: dropping "Template" suffix because conditions message will surface on machine.
405+
conditionMessages = append(conditionMessages, fmt.Sprintf("%s is not up-to-date", strings.TrimSuffix(currentCopy.Spec.InfrastructureRef.Kind, clusterv1.TemplateSuffix)))
406+
}
407+
408+
if !reflect.DeepEqual(currentCopy.Spec.FailureDomain, desiredCopy.Spec.FailureDomain) {
409+
logMessages = append(logMessages, fmt.Sprintf("spec.failureDomain %s, %s required", ptr.Deref(currentCopy.Spec.FailureDomain, "nil"), ptr.Deref(desiredCopy.Spec.FailureDomain, "nil")))
410+
conditionMessages = append(conditionMessages, fmt.Sprintf("Failure domain %s, %s required", ptr.Deref(currentCopy.Spec.FailureDomain, "nil"), ptr.Deref(desiredCopy.Spec.FailureDomain, "nil")))
411+
}
412+
413+
if len(logMessages) > 0 || len(conditionMessages) > 0 {
414+
return false, logMessages, conditionMessages
415+
}
416+
417+
return true, nil, nil
381418
}
382419

383420
// MachineTemplateDeepCopyRolloutFields copies a MachineTemplateSpec
@@ -386,6 +423,9 @@ func EqualMachineTemplate(template1, template2 *clusterv1.MachineTemplateSpec) (
386423
func MachineTemplateDeepCopyRolloutFields(template *clusterv1.MachineTemplateSpec) *clusterv1.MachineTemplateSpec {
387424
templateCopy := template.DeepCopy()
388425

426+
// Moving MD from one cluster to another is not supported.
427+
templateCopy.Spec.ClusterName = ""
428+
389429
// Drop labels and annotations
390430
templateCopy.Labels = nil
391431
templateCopy.Annotations = nil
@@ -413,7 +453,7 @@ func MachineTemplateDeepCopyRolloutFields(template *clusterv1.MachineTemplateSpe
413453
// NOTE: If we find a matching MachineSet which only differs in in-place mutable fields we can use it to
414454
// fulfill the intent of the MachineDeployment by just updating the MachineSet to propagate in-place mutable fields.
415455
// Thus we don't have to create a new MachineSet and we can avoid an unnecessary rollout.
416-
// NOTE: Even after we changed EqualMachineTemplate to ignore fields that are propagated in-place we can guarantee that if there exists a "new machineset"
456+
// NOTE: Even after we changed MachineTemplateUpToDate to ignore fields that are propagated in-place we can guarantee that if there exists a "new machineset"
417457
// using the old logic then a new machineset will definitely exist using the new logic. The new logic is looser. Therefore, we will
418458
// not face a case where there exists a machine set matching the old logic but there does not exist a machineset matching the new logic.
419459
// In fact previously not matching MS can now start matching the target. Since there could be multiple matches, lets choose the
@@ -432,19 +472,16 @@ func FindNewMachineSet(deployment *clusterv1.MachineDeployment, msList []*cluste
432472
var matchingMachineSets []*clusterv1.MachineSet
433473
var diffs []string
434474
for _, ms := range msList {
435-
equal, diff, err := EqualMachineTemplate(&ms.Spec.Template, &deployment.Spec.Template)
436-
if err != nil {
437-
return nil, "", errors.Wrapf(err, "failed to compare MachineDeployment spec template with MachineSet %s", ms.Name)
438-
}
439-
if equal {
475+
upToDate, logMessages, _ := MachineTemplateUpToDate(&ms.Spec.Template, &deployment.Spec.Template)
476+
if upToDate {
440477
matchingMachineSets = append(matchingMachineSets, ms)
441478
} else {
442-
diffs = append(diffs, fmt.Sprintf("MachineSet %s: diff: %s", ms.Name, diff))
479+
diffs = append(diffs, fmt.Sprintf("MachineSet %s: diff: %s", ms.Name, strings.Join(logMessages, ", ")))
443480
}
444481
}
445482

446483
if len(matchingMachineSets) == 0 {
447-
return nil, fmt.Sprintf("couldn't find MachineSet matching MachineDeployment spec template: %s", strings.Join(diffs, ",")), nil
484+
return nil, fmt.Sprintf("couldn't find MachineSet matching MachineDeployment spec template: %s", strings.Join(diffs, "; ")), nil
448485
}
449486

450487
// If RolloutAfter is not set, pick the first matching MachineSet.

0 commit comments

Comments
 (0)