@@ -20,6 +20,7 @@ package mdutil
20
20
import (
21
21
"context"
22
22
"fmt"
23
+ "reflect"
23
24
"sort"
24
25
"strconv"
25
26
"strings"
@@ -38,7 +39,6 @@ import (
38
39
ctrl "sigs.k8s.io/controller-runtime"
39
40
40
41
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
41
- "sigs.k8s.io/cluster-api/internal/util/compare"
42
42
"sigs.k8s.io/cluster-api/util/conversion"
43
43
)
44
44
@@ -371,13 +371,50 @@ func getMachineSetFraction(ms clusterv1.MachineSet, md clusterv1.MachineDeployme
371
371
return integer .RoundToInt32 (newMSsize ) - * (ms .Spec .Replicas )
372
372
}
373
373
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 )
379
379
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
381
418
}
382
419
383
420
// MachineTemplateDeepCopyRolloutFields copies a MachineTemplateSpec
@@ -386,6 +423,9 @@ func EqualMachineTemplate(template1, template2 *clusterv1.MachineTemplateSpec) (
386
423
func MachineTemplateDeepCopyRolloutFields (template * clusterv1.MachineTemplateSpec ) * clusterv1.MachineTemplateSpec {
387
424
templateCopy := template .DeepCopy ()
388
425
426
+ // Moving MD from one cluster to another is not supported.
427
+ templateCopy .Spec .ClusterName = ""
428
+
389
429
// Drop labels and annotations
390
430
templateCopy .Labels = nil
391
431
templateCopy .Annotations = nil
@@ -413,7 +453,7 @@ func MachineTemplateDeepCopyRolloutFields(template *clusterv1.MachineTemplateSpe
413
453
// NOTE: If we find a matching MachineSet which only differs in in-place mutable fields we can use it to
414
454
// fulfill the intent of the MachineDeployment by just updating the MachineSet to propagate in-place mutable fields.
415
455
// 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"
417
457
// using the old logic then a new machineset will definitely exist using the new logic. The new logic is looser. Therefore, we will
418
458
// 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.
419
459
// 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
432
472
var matchingMachineSets []* clusterv1.MachineSet
433
473
var diffs []string
434
474
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 {
440
477
matchingMachineSets = append (matchingMachineSets , ms )
441
478
} 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 , ", " ) ))
443
480
}
444
481
}
445
482
446
483
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
448
485
}
449
486
450
487
// If RolloutAfter is not set, pick the first matching MachineSet.
0 commit comments