@@ -22,12 +22,14 @@ import (
22
22
"fmt"
23
23
"time"
24
24
25
+ "github.com/blang/semver/v4"
25
26
"github.com/google/go-cmp/cmp"
26
27
"github.com/google/go-cmp/cmp/cmpopts"
27
28
"github.com/pkg/errors"
28
29
corev1 "k8s.io/api/core/v1"
29
30
apierrors "k8s.io/apimachinery/pkg/api/errors"
30
31
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
32
+ "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
31
33
"k8s.io/apimachinery/pkg/runtime/schema"
32
34
"k8s.io/client-go/tools/record"
33
35
"k8s.io/klog/v2"
@@ -305,6 +307,16 @@ func (r *AWSMachinePoolReconciler) reconcileNormal(ctx context.Context, machineP
305
307
// But we want to update the LaunchTemplate because an error in the LaunchTemplate may be blocking the ASG creation.
306
308
return true , nil
307
309
}
310
+
311
+ canProceed , err := r .isMachinePoolAllowedToUpgradeDueToControlPlaneVersionSkew (clusterScope , machinePoolScope )
312
+ if err != nil {
313
+ return true , err
314
+ }
315
+ if ! canProceed {
316
+ machinePoolScope .Info ("blocking the Launch Template update due to control plane k8s version skew" )
317
+ return false , nil
318
+ }
319
+
308
320
return asgsvc .CanStartASGInstanceRefresh (machinePoolScope )
309
321
}
310
322
runPostLaunchTemplateUpdateOperation := func () error {
@@ -442,6 +454,35 @@ func (r *AWSMachinePoolReconciler) reconcileNormal(ctx context.Context, machineP
442
454
return ctrl.Result {}, nil
443
455
}
444
456
457
+ // isMachinePoolAllowedToUpgradeDueToControlPlaneVersionSkew checks if the control plane is being upgraded, in which case we shouldn't update the launch template.
458
+ func (r * AWSMachinePoolReconciler ) isMachinePoolAllowedToUpgradeDueToControlPlaneVersionSkew (clusterScope cloud.ClusterScoper , machinePoolScope * scope.MachinePoolScope ) (bool , error ) {
459
+ if machinePoolScope .Cluster .Spec .ControlPlaneRef == nil {
460
+ return true , nil
461
+ }
462
+
463
+ controlPlane , err := clusterScope .UnstructuredControlPlane ()
464
+ if err != nil {
465
+ return true , errors .Wrap (err , "failed to get ControlPlane" )
466
+ }
467
+
468
+ cpVersion , found , err := unstructured .NestedString (controlPlane .Object , "status" , "version" )
469
+ if ! found || err != nil {
470
+ return true , errors .Wrapf (err , "failed to get version of ControlPlane %s" , machinePoolScope .Cluster .Spec .ControlPlaneRef .Name )
471
+ }
472
+
473
+ controlPlaneCurrentK8sVersion , err := semver .ParseTolerant (cpVersion )
474
+ if err != nil {
475
+ return true , errors .Wrapf (err , "failed to parse version of ControlPlane %s" , machinePoolScope .Cluster .Spec .ControlPlaneRef .Name )
476
+ }
477
+
478
+ machinePoolDesiredK8sVersion , err := semver .ParseTolerant (* machinePoolScope .MachinePool .Spec .Template .Spec .Version )
479
+ if err != nil {
480
+ return true , errors .Wrap (err , "failed to parse version of MachinePool" )
481
+ }
482
+
483
+ return controlPlaneCurrentK8sVersion .GE (machinePoolDesiredK8sVersion ), nil
484
+ }
485
+
445
486
func (r * AWSMachinePoolReconciler ) reconcileDelete (ctx context.Context , machinePoolScope * scope.MachinePoolScope , clusterScope cloud.ClusterScoper , ec2Scope scope.EC2Scope ) error {
446
487
clusterScope .Info ("Handling deleted AWSMachinePool" )
447
488
0 commit comments